View Javadoc

1   /*
2    *  MicroEmulator
3    *  Copyright (C) 2001-2003 Bartek Teodorczyk <barteo@barteo.net>
4    *
5    *  This library is free software; you can redistribute it and/or
6    *  modify it under the terms of the GNU Lesser General Public
7    *  License as published by the Free Software Foundation; either
8    *  version 2.1 of the License, or (at your option) any later version.
9    *
10   *  This library is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   *  Lesser General Public License for more details.
14   *
15   *  You should have received a copy of the GNU Lesser General Public
16   *  License along with this library; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.microemu.app.ui.swt;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.Enumeration;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  
28  import javax.microedition.lcdui.Command;
29  
30  import org.eclipse.swt.SWT;
31  import org.eclipse.swt.SWTException;
32  import org.eclipse.swt.events.KeyEvent;
33  import org.eclipse.swt.events.KeyListener;
34  import org.eclipse.swt.events.MouseAdapter;
35  import org.eclipse.swt.events.MouseEvent;
36  import org.eclipse.swt.events.MouseMoveListener;
37  import org.eclipse.swt.events.PaintEvent;
38  import org.eclipse.swt.events.PaintListener;
39  import org.eclipse.swt.graphics.Color;
40  import org.eclipse.swt.graphics.Font;
41  import org.eclipse.swt.graphics.FontMetrics;
42  import org.eclipse.swt.graphics.GC;
43  import org.eclipse.swt.graphics.Image;
44  import org.eclipse.swt.graphics.ImageData;
45  import org.eclipse.swt.graphics.Point;
46  import org.eclipse.swt.graphics.RGB;
47  import org.eclipse.swt.widgets.Canvas;
48  import org.eclipse.swt.widgets.Composite;
49  import org.eclipse.swt.widgets.Event;
50  import org.microemu.CommandManager;
51  import org.microemu.DisplayComponent;
52  import org.microemu.MIDletBridge;
53  import org.microemu.device.Device;
54  import org.microemu.device.DeviceFactory;
55  import org.microemu.device.impl.Rectangle;
56  import org.microemu.device.impl.SoftButton;
57  import org.microemu.device.swt.SwtButton;
58  import org.microemu.device.swt.SwtDeviceDisplay;
59  import org.microemu.device.swt.SwtImmutableImage;
60  import org.microemu.device.swt.SwtInputMethod;
61  
62  
63  
64  public class SwtDeviceComponent extends Canvas
65  {
66  	private static SwtDeviceComponent instance;
67  	private static HashMap colors = new HashMap();
68  
69  	private SwtDisplayComponent dc;
70  	
71  	private Image fBuffer = null;
72  
73  	private SwtButton prevOverButton;
74  	private SwtButton overButton;
75  	private SwtButton pressedButton;
76  	
77  	private SoftButton initialPressedSoftButton;
78  
79  	private boolean mousePressed;
80    
81    KeyListener keyListener = new KeyListener()
82    {
83  		public void keyPressed(KeyEvent ev)
84  		{
85  	    	if (MIDletBridge.getCurrentMIDlet() == null) {
86  	    		return;
87  	    	}
88  
89  	    	Device device = DeviceFactory.getDevice();
90  	    	
91  			for (Iterator it = device.getButtons().iterator(); it.hasNext(); ) {
92  				SwtButton button = (SwtButton) it.next();
93  				if (ev.keyCode == button.getKeyboardKey()) {
94  					ev.keyCode = button.getKeyCode();
95  					break;
96  				}
97  			}
98  	    		    	
99  	    	((SwtInputMethod) device.getInputMethod()).keyPressed(ev);
100 			
101 			pressedButton = ((SwtInputMethod) device.getInputMethod()).getButton(ev);
102 			if (pressedButton != null) {
103 				org.microemu.device.impl.Shape shape = pressedButton.getShape();
104 				if (shape != null) {
105 					Rectangle r = shape.getBounds();
106 		  			redraw(r.x, r.y, r.width, r.height, true);
107 				}
108 			} else {
109 				redraw();
110 			}
111 		}   
112 	  
113 		public void keyReleased(KeyEvent ev)
114 		{
115 	    	if (MIDletBridge.getCurrentMIDlet() == null) {
116 	    		return;
117 	    	}
118 
119 	    	Device device = DeviceFactory.getDevice();
120 	    	
121 			for (Iterator it = device.getButtons().iterator(); it.hasNext(); ) {
122 				SwtButton button = (SwtButton) it.next();
123 				if (ev.keyCode == button.getKeyboardKey()) {
124 					ev.keyCode = button.getKeyCode();
125 					break;
126 				}
127 			}
128 
129 			((SwtInputMethod) device.getInputMethod()).keyReleased(ev);
130 			
131 			prevOverButton = pressedButton;
132 			pressedButton = null;
133 			if (prevOverButton != null) {
134 				org.microemu.device.impl.Shape shape = prevOverButton.getShape();
135 				if (shape != null) {
136 					Rectangle r = shape.getBounds();
137 		  			redraw(r.x, r.y, r.width, r.height, true);
138 				}
139 			} else {
140 				redraw();
141 			}
142 		}   
143   };
144   
145 	MouseAdapter mouseListener = new MouseAdapter() 
146 	{    
147 		public void mouseDown(MouseEvent e) 
148 		{
149 	    	if (MIDletBridge.getCurrentMIDlet() == null) {
150 	    		return;
151 	    	}
152 	    	
153 			Device device = DeviceFactory.getDevice();
154 			org.microemu.device.impl.Rectangle rect = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayRectangle();
155 			SwtInputMethod inputMethod = (SwtInputMethod) device.getInputMethod();
156 			// if the displayable is in full screen mode, we should not
157 			// invoke any associated commands, but send the raw key codes
158 			// instead
159 			boolean fullScreenMode = device.getDeviceDisplay().isFullScreenMode();
160 
161 			if (rect.x <= e.x && (rect.x + rect.width) > e.x
162 					&& rect.y <= e.y && (rect.y + rect.height) > e.y) {
163 				if (device.hasPointerEvents()) {
164 					if (!fullScreenMode) {
165 						Iterator it = device.getSoftButtons().iterator();
166 						while (it.hasNext()) {
167 							SoftButton button = (SoftButton) it.next();
168 							if (button.isVisible()) {
169 								org.microemu.device.impl.Rectangle pb = button.getPaintable();
170 								if (pb != null && pb.contains(e.x - rect.x, e.y - rect.y)) {
171 									initialPressedSoftButton = button;
172 									button.setPressed(true);
173 									dc.repaintRequest(pb.x, pb.y, pb.width, pb.height);
174 									break;
175 								}
176 							}
177 						}
178 					}
179 					if (fullScreenMode) {
180 						inputMethod.pointerPressed(e.x - rect.x, e.y - rect.y);
181 					} else {
182 						org.microemu.device.impl.Rectangle pb = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayPaintable();
183 						inputMethod.pointerPressed(e.x - rect.x - pb.x, e.y - rect.y - pb.y);
184 					}
185 				}
186 			} else {
187 		    	pressedButton = getButton(e.x, e.y);	
188 				if (pressedButton != null) {
189 					if (pressedButton instanceof SoftButton && !fullScreenMode) {
190 						Command cmd = ((SoftButton) pressedButton).getCommand();
191 						if (cmd != null) {
192 							CommandManager.getInstance().commandAction(cmd);
193 						}
194 					} else {
195 						Event event = new Event();
196 						event.widget = e.widget;
197 						KeyEvent ev = new KeyEvent(event);
198 						ev.keyCode = pressedButton.getKeyCode();
199 						inputMethod.mousePressed(ev);
200 					}
201 					// optimize for some video cards.
202 					Rectangle r = pressedButton.getShape().getBounds();
203 					redraw(r.x, r.y, r.width, r.height, true);
204 				}
205 			}
206 			
207 			mousePressed = true;
208 		}
209 
210 		public void mouseUp(MouseEvent e) 
211 		{
212 	    	if (MIDletBridge.getCurrentMIDlet() == null) {
213 	    		return;
214 	    	}
215 
216 			Device device = DeviceFactory.getDevice();
217 			org.microemu.device.impl.Rectangle rect = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayRectangle();
218 			SwtInputMethod inputMethod = (SwtInputMethod) device.getInputMethod();
219 			boolean fullScreenMode = device.getDeviceDisplay().isFullScreenMode();
220 			if (rect.x <= e.x && (rect.x + rect.width) > e.x
221 					&& rect.y <= e.y && (rect.y + rect.height) > e.y) {
222 				if (device.hasPointerEvents()) {
223 					if (!fullScreenMode) {
224 						if (initialPressedSoftButton != null && initialPressedSoftButton.isPressed()) {
225 							initialPressedSoftButton.setPressed(false);
226 							org.microemu.device.impl.Rectangle pb = initialPressedSoftButton.getPaintable();
227 							if (pb != null) {
228 								dc.repaintRequest(pb.x, pb.y, pb.width, pb.height);
229 								if (pb.contains(e.x - rect.x, e.y - rect.y)) {
230 									Command cmd = initialPressedSoftButton.getCommand();
231 									if (cmd != null) {
232 										CommandManager.getInstance().commandAction(cmd);
233 									}
234 								}
235 							}
236 						}
237 						initialPressedSoftButton = null;
238 					}
239 					if (fullScreenMode) {
240 						inputMethod.pointerReleased(e.x - rect.x, e.y - rect.y);
241 					} else {
242 						org.microemu.device.impl.Rectangle pb = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayPaintable();
243 						inputMethod.pointerReleased(e.x - rect.x - pb.x, e.y - rect.y - pb.y);
244 					}
245 				}
246 			} else {
247 		    	SwtButton prevOverButton = getButton(e.x, e.y);
248 				if (prevOverButton != null) {
249 					inputMethod.mouseReleased(prevOverButton.getKeyCode());
250 				}
251 				pressedButton = null;
252 				//	optimize for some video cards.
253 				if (prevOverButton != null) {
254 					Rectangle r = prevOverButton.getShape().getBounds();
255 					redraw(r.x, r.y, r.width, r.height, true);
256 				} else {
257 					redraw();
258 				}
259 			}
260 			
261 			mousePressed = false;
262 		}
263 	};
264   
265 
266 	MouseMoveListener mouseMoveListener = new MouseMoveListener() 
267 	{
268 		public void mouseMove(MouseEvent e)
269 		{
270 			prevOverButton = overButton;
271 			overButton = getButton(e.x, e.y);
272 			if (overButton != prevOverButton) {
273 	      		// optimize for some video cards.
274 	      		if (prevOverButton != null) {
275 	      			Rectangle r = prevOverButton.getShape().getBounds();
276 	      			redraw(r.x, r.y, r.width, r.height, true);
277 	      		}
278 	      		if (overButton != null) {
279 	      			Rectangle r = overButton.getShape().getBounds();
280 	      			redraw(r.x, r.y, r.width, r.height, true);
281 	      		}
282 			}
283 			
284 			if (mousePressed) {
285 				Device device = DeviceFactory.getDevice();
286 				org.microemu.device.impl.Rectangle rect = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayRectangle();
287 				SwtInputMethod inputMethod = (SwtInputMethod) device.getInputMethod();
288 				boolean fullScreenMode = device.getDeviceDisplay().isFullScreenMode();
289 				if (rect.x <= e.x && (rect.x + rect.width) > e.x
290 						&& rect.y <= e.y && (rect.y + rect.height) > e.y) {
291 					if (device.hasPointerMotionEvents()) {
292 						if (!fullScreenMode) {
293 							if (initialPressedSoftButton != null) {
294 								org.microemu.device.impl.Rectangle pb = initialPressedSoftButton.getPaintable();
295 								if (pb != null) {
296 									if (pb.contains(e.x - rect.x, e.y - rect.y)) {
297 										if (!initialPressedSoftButton.isPressed()) {
298 											initialPressedSoftButton.setPressed(true);
299 											dc.repaintRequest(pb.x, pb.y, pb.width, pb.height);
300 										}
301 									} else {
302 										if (initialPressedSoftButton.isPressed()) {
303 											initialPressedSoftButton.setPressed(false);
304 											dc.repaintRequest(pb.x, pb.y, pb.width, pb.height);
305 										}
306 									}
307 								}
308 							}
309 						}
310 						if (fullScreenMode) {
311 							inputMethod.pointerDragged(e.x - rect.x, e.y - rect.y);
312 						} else {
313 							org.microemu.device.impl.Rectangle pb = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayPaintable();
314 							inputMethod.pointerDragged(e.x - rect.x - pb.x, e.y - rect.y - pb.y);
315 						}
316 					}
317 				}
318 			}
319 		}    
320 	};
321   
322   
323 	public SwtDeviceComponent(Composite parent) 
324 	{
325 		super(parent, SWT.NO_BACKGROUND);
326 		instance = this;
327 		mousePressed = false;
328     
329 		dc = new SwtDisplayComponent(this);    
330     
331 	    this.initialPressedSoftButton = null;
332 
333 	    addKeyListener(keyListener);
334 		addMouseListener(mouseListener);
335 		addMouseMoveListener(mouseMoveListener);
336 		addPaintListener(new PaintListener() 
337 		{
338 			public void paintControl(PaintEvent e) 
339 			{
340 				SwtDeviceComponent.this.paintControl(e);
341 			}
342 		});
343 	}
344   
345   
346 	public DisplayComponent getDisplayComponent()
347 	{
348 		return dc;
349 	}
350   
351   
352 	public Point computeSize(int wHint, int hHint, boolean changed)
353 	{
354 		javax.microedition.lcdui.Image tmp = DeviceFactory.getDevice().getNormalImage();
355 
356 		return new Point(tmp.getWidth(), tmp.getHeight());		
357 	}
358 							 
359   
360 	public void paintControl(PaintEvent pe) 
361 	{
362 		Point size= getSize();
363 
364 		if (size.x <= 0 || size.y <= 0)
365 		 return;
366 
367 		if (fBuffer != null) {
368 			org.eclipse.swt.graphics.Rectangle r= fBuffer.getBounds();
369 			if (r.width != size.x || r.height != size.y) {
370 			fBuffer.dispose();
371 			fBuffer= null;
372 			}
373 		}
374 		if (fBuffer == null) {
375 			fBuffer= new Image(getDisplay(), size.x, size.y);
376 		}
377 
378 		SwtGraphics gc = new SwtGraphics(new GC(fBuffer));
379 		try {
380 			Device device = DeviceFactory.getDevice();
381 			
382 			gc.drawImage(((SwtImmutableImage) device.getNormalImage()).getImage()
383 			        , 0, 0);
384     
385 			org.microemu.device.impl.Rectangle displayRectangle = 
386 					((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayRectangle();
387 			gc.translate(displayRectangle.x, displayRectangle.y);
388 			dc.paint(gc);
389 			gc.translate(-displayRectangle.x, -displayRectangle.y);
390 
391 	    	if (prevOverButton != null) {
392 				org.microemu.device.impl.Shape shape = prevOverButton.getShape();
393 				if (shape != null) {
394 					drawImageInShape(
395 							gc, 
396 							((SwtImmutableImage) device.getNormalImage()).getImage(), 
397 							shape);
398 				}
399 				prevOverButton = null;
400 			}
401 			if (overButton != null) {
402 				org.microemu.device.impl.Shape shape = overButton.getShape();
403 				if (shape != null) {
404 					drawImageInShape(
405 							gc, 
406 							((SwtImmutableImage) device.getOverImage()).getImage(), 
407 							shape);
408 				}
409 			}
410 			if (pressedButton != null) {
411 				org.microemu.device.impl.Shape shape = pressedButton.getShape();
412 				if (shape != null) {
413 					drawImageInShape(
414 							gc, 
415 							((SwtImmutableImage) device.getPressedImage()).getImage(), 
416 							shape);
417 				}
418 			}
419 
420 			org.microemu.device.impl.Rectangle rect;
421 			if (prevOverButton != null ) {				
422 				rect = prevOverButton.getShape().getBounds();
423 				if (rect != null) {
424 					gc.drawImage(((SwtImmutableImage) DeviceFactory.getDevice().getNormalImage()).getImage(), 
425 							rect.x, rect.y, rect.width, rect.height,
426 							rect.x, rect.y, rect.width, rect.height);
427 				}
428 				prevOverButton = null;
429 			}
430 			if (overButton != null) {
431 				rect = overButton.getShape().getBounds();
432 				if (rect != null) {
433 					gc.drawImage(((SwtImmutableImage) DeviceFactory.getDevice().getOverImage()).getImage(), 
434 							rect.x, rect.y, rect.width, rect.height,
435 							rect.x, rect.y, rect.width, rect.height);
436 				}
437 			}
438 			if (pressedButton != null) {
439 				rect = pressedButton.getShape().getBounds();
440 				if (rect != null) {
441 					gc.drawImage(((SwtImmutableImage) DeviceFactory.getDevice().getPressedImage()).getImage(), 
442 							rect.x, rect.y, rect.width, rect.height,
443 							rect.x, rect.y, rect.width, rect.height);
444 				}
445 			}
446 		} finally {
447 			gc.dispose();
448 		}
449 		
450 		pe.gc.drawImage(fBuffer, 0, 0);
451 	}
452 
453 
454   	private void drawImageInShape(SwtGraphics g, Image image, org.microemu.device.impl.Shape shape) {
455   		org.eclipse.swt.graphics.Rectangle clipSave = g.getClipping();
456 		if (shape instanceof org.microemu.device.impl.Polygon) {
457 			// TODO not implemented yet
458 //			g.setCliping(region);
459 		}
460 		org.microemu.device.impl.Rectangle r = shape.getBounds();
461 		g.drawImage(image, 
462 				r.x, r.y, r.width, r.height,
463 				r.x, r.y, r.width, r.height);
464 		g.setClipping(clipSave);
465 	}
466   	
467   	
468 	private SwtButton getButton(int x, int y)
469 	{
470 		for (Enumeration e = DeviceFactory.getDevice().getButtons().elements(); e.hasMoreElements(); ) {
471 			SwtButton button = (SwtButton) e.nextElement();
472 			if (button.getShape() != null) {
473 				try {
474 					org.microemu.device.impl.Shape tmp = (org.microemu.device.impl.Shape) button.getShape().clone();
475 				      if (tmp.contains(x, y)) {
476 				    	  return button;
477 				      }
478 				} catch (CloneNotSupportedException ex) {
479 					ex.printStackTrace();
480 				}
481 			}
482 		}        
483 		return null;
484 	}
485 
486   
487 	private class CreateImageRunnable implements Runnable
488 	{
489 		private ImageData data;
490 		private Image image;
491 		
492 		CreateImageRunnable(ImageData data)
493 		{
494 			this.data = data;
495 		}
496 		
497 		Image getImage()
498 		{
499 			return image;
500 		}
501 			
502 		public void run() 
503 		{
504 			image = new Image(instance.getParent().getDisplay(), data);
505 		}		
506 	}
507 	
508 	
509 	public static Image createImage(int width, int height)
510 	{
511 		return new Image(instance.getDisplay(), width, height);
512 	}
513 
514 
515 	public static Image createImage(Image image)
516 	{
517 		return new Image(instance.getDisplay(), image, SWT.IMAGE_COPY);
518 	}
519 	
520 	
521 	public static Image createImage(ImageData data)
522 	{
523 		CreateImageRunnable createImageRunnable = instance.new CreateImageRunnable(data);		
524 		instance.getDisplay().syncExec(createImageRunnable); 
525 		
526 		return createImageRunnable.getImage(); 
527 	}
528 
529 	
530 	public static Image createImage(InputStream is) 
531 	{
532 		ImageData data = new ImageData(is);
533 			
534 		CreateImageRunnable createImageRunnable = instance.new CreateImageRunnable(data);		
535 		instance.getDisplay().syncExec(createImageRunnable); 
536 		
537 		return createImageRunnable.getImage(); 
538 	}
539 	
540 	
541 	public static Image createImage(InputStream is, ImageFilter filter)
542 			throws IOException
543 	{
544 		try {
545 			ImageData data = new ImageData(is);
546 		
547 			RGB[] rgbs = data.getRGBs();
548 			if (rgbs != null) {	
549 				for (int i = 0; i < rgbs.length; i++) {
550 					rgbs[i] = filter.filterRGB(0, 0, rgbs[i]);
551 				}
552 			} else {
553 				RGB rgb;
554 				int pixel;
555 				for (int y = 0; y < data.height; y++) {
556 					for (int x = 0; x < data.width; x++) {
557 						pixel = data.getPixel(x, y);
558 						rgb = new RGB((pixel >> 16) & 255, (pixel >> 8) & 255, pixel & 255);
559 						rgb = filter.filterRGB(x, y, rgb);					
560 						data.setPixel(x, y, (rgb.red << 16) + (rgb.green << 8) + rgb.blue);
561 					}
562 				}
563 			}		
564 				
565 			CreateImageRunnable createImageRunnable = instance.new CreateImageRunnable(data);		
566 			instance.getDisplay().syncExec(createImageRunnable); 
567 			
568 			return createImageRunnable.getImage(); 
569 		} catch (SWTException ex) {
570 			throw new IOException(ex.toString());
571 		}
572 	}
573 	
574 	
575 	private class CreateColorRunnable implements Runnable
576 	{
577 		private RGB rgb;
578 		private Color color;
579 		
580 		CreateColorRunnable(RGB rgb)
581 		{
582 			this.rgb = rgb;
583 		}
584 		
585 		Color getColor()
586 		{
587 			return color;
588 		}
589 			
590 		public void run() 
591 		{
592 			color = new Color(instance.getParent().getDisplay(), rgb);
593 		}		
594 	}
595 
596 
597 	public static Color getColor(RGB rgb) 
598 	{
599 		Color result = (Color) colors.get(rgb);
600 		
601 		if (result == null) {
602 			CreateColorRunnable createColorRunnable = instance.new CreateColorRunnable(rgb);		
603 			instance.getDisplay().syncExec(createColorRunnable); 		
604 			result = createColorRunnable.getColor();
605 			colors.put(rgb, result);
606 		}
607 		
608 		return result;
609 	}
610 
611 
612 	private class GetFontMetricsRunnable implements Runnable
613 	{
614 		private Font font;
615 		private FontMetrics fontMetrics;
616 		
617 		GetFontMetricsRunnable(Font font)
618 		{
619 			this.font = font;
620 		}
621 		
622 		FontMetrics getFontMetrics()
623 		{
624 			return fontMetrics;
625 		}
626 			
627 		public void run() 
628 		{
629 			SwtGraphics gc = new SwtGraphics(instance.getParent().getDisplay());
630 			gc.setFont(font);
631 			fontMetrics = gc.getFontMetrics();
632 			gc.dispose();
633 		}		
634 	}
635 
636 
637 	private class GetFontRunnable implements Runnable
638 	{
639 		private String name;
640 		private int size;
641 		private int style;
642 		private boolean antialiasing;
643 		private Font font;
644 		
645 		GetFontRunnable(String name, int size, int style, boolean antialiasing)
646 		{
647 			this.name = name;
648 			this.size = size;
649 			this.style = style;
650 		}
651 		
652 		Font getFont()
653 		{
654 			return font;
655 		}
656 			
657 		public void run() 
658 		{
659 			SwtGraphics gc = new SwtGraphics(instance.getParent().getDisplay());
660 			gc.setAntialias(antialiasing);
661 			gc.setFont(new Font(instance.getParent().getDisplay(), name, size, style));
662 			font = gc.getFont();
663 			gc.dispose();
664 		}		
665 	}
666 
667 
668 	private class StringWidthRunnable implements Runnable
669 	{
670 		private Font font;
671 		private String str;
672 		private int stringWidth;
673 		
674 		StringWidthRunnable(Font font, String str)
675 		{
676 			this.font = font;
677 			this.str = str;
678 		}
679 		
680 		int stringWidth()
681 		{
682 			return stringWidth;
683 		}
684 			
685 		public void run() 
686 		{
687 			SwtGraphics gc = new SwtGraphics(instance.getParent().getDisplay());
688 			gc.setFont(font);
689 			stringWidth = gc.stringWidth(str);
690 			gc.dispose();
691 		}		
692 	}
693 
694 
695 	public static Font getFont(String name, int size, int style, boolean antialiasing) 
696 	{
697 		GetFontRunnable getFontRunnable = instance.new GetFontRunnable(name, size, style, antialiasing);
698 		
699 		instance.getDisplay().syncExec(getFontRunnable); 
700 		
701 		return getFontRunnable.getFont(); 
702 	}
703 
704 
705 	public static FontMetrics getFontMetrics(Font font) 
706 	{
707 		GetFontMetricsRunnable getFontMetricsRunnable = instance.new GetFontMetricsRunnable(font);
708 		
709 		instance.getDisplay().syncExec(getFontMetricsRunnable); 
710 		
711 		return getFontMetricsRunnable.getFontMetrics(); 
712 	}
713 	
714 	
715 	public static int stringWidth(Font font, String str)
716 	{
717 		StringWidthRunnable stringWidthRunnable = instance.new StringWidthRunnable(font, str);
718 		
719 		instance.getDisplay().syncExec(stringWidthRunnable); 
720 
721 		return stringWidthRunnable.stringWidth(); 
722 	}
723   
724 }