1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
157
158
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
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
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
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
458
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 }