|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 package javax.microedition.lcdui; |
|
18 |
|
19 import javax.microedition.lcdui.EventDispatcher.LCDUIEvent; |
|
20 import javax.microedition.midlet.MIDlet; |
|
21 import org.eclipse.ercp.swt.mobile.MobileDevice; |
|
22 import org.eclipse.ercp.swt.mobile.Screen; |
|
23 import org.eclipse.swt.SWT; |
|
24 import org.eclipse.swt.graphics.RGB; |
|
25 import org.eclipse.swt.internal.extension.DisplayExtension; |
|
26 import org.eclipse.swt.widgets.Event; |
|
27 |
|
28 /** |
|
29 * Display - represents device's display. |
|
30 */ |
|
31 public class Display |
|
32 { |
|
33 |
|
34 /** |
|
35 * Type of image for List element. |
|
36 * |
|
37 * @value for LIST_ELEMENT is 1. |
|
38 */ |
|
39 public static final int LIST_ELEMENT = 1; |
|
40 |
|
41 /** |
|
42 * Type of image for ChoiceGroup element. |
|
43 * |
|
44 * @value for CHOICE_GROUP_ELEMENT is 2. |
|
45 */ |
|
46 public static final int CHOICE_GROUP_ELEMENT = 2; |
|
47 |
|
48 /** |
|
49 * Type of image for Alert. |
|
50 * |
|
51 * @value for ALERT is 3. |
|
52 */ |
|
53 public static final int ALERT = 3; |
|
54 |
|
55 /** |
|
56 * A color constant for usage in getColor(). COLOR_BACKGROUND defines |
|
57 * background color of the screen. It is always in contrast with |
|
58 * COLOR_FOREGROUND. |
|
59 * |
|
60 * @value for COLOR_BACKGROUND is 0. |
|
61 */ |
|
62 public static final int COLOR_BACKGROUND = 0; |
|
63 |
|
64 /** |
|
65 * A color constant for usage in getColor(). COLOR_BACKGROUND defines |
|
66 * foreground color of the screen. It is always in contrast with |
|
67 * COLOR_BACKGROUND. |
|
68 * |
|
69 * @value for COLOR_FOREGROUND is 1. |
|
70 */ |
|
71 public static final int COLOR_FOREGROUND = 1; |
|
72 |
|
73 /** |
|
74 * A color constant for usage in getColor(). COLOR_HIGHLIGHTED_BACKGROUND |
|
75 * defines background color for focused or highlighted items. It is always |
|
76 * in contrast with COLOR_HIGHLIGHTED_FOREGROUND. |
|
77 * |
|
78 * @value for COLOR_HIGHLIGHTED_BACKGROUND is 2. |
|
79 */ |
|
80 public static final int COLOR_HIGHLIGHTED_BACKGROUND = 2; |
|
81 |
|
82 /** |
|
83 * A color constant for usage in getColor(). COLOR_HIGHLIGHTED_FOREGROUND |
|
84 * defines foreground color for focused or highlighted items. |
|
85 * |
|
86 * @value for COLOR_HIGHLIGHTED_FOREGROUND is 3. |
|
87 */ |
|
88 public static final int COLOR_HIGHLIGHTED_FOREGROUND = 3; |
|
89 |
|
90 /** |
|
91 * A color constant for usage in getColor(). COLOR_BORDER defines color of |
|
92 * border of items in Display. |
|
93 * |
|
94 * @value for COLOR_BORDER is 4. |
|
95 */ |
|
96 public static final int COLOR_BORDER = 4; |
|
97 |
|
98 /** |
|
99 * A color constant for usage in getColor(). COLOR_HIGHLIGHTED_BORDER |
|
100 * defines color of border of highlighted or focused items in Display. |
|
101 * |
|
102 * @value for COLOR_HIGHLIGHTED_BORDER is 5. |
|
103 */ |
|
104 public static final int COLOR_HIGHLIGHTED_BORDER = 5; |
|
105 |
|
106 private static Display instance = new Display(); |
|
107 // private static Form emptyForm; |
|
108 |
|
109 private Displayable currentDisplayable; |
|
110 private Displayable getcurrent; |
|
111 private int numColors; |
|
112 private RGB eswtTempRgb; |
|
113 |
|
114 /** |
|
115 * Constructor. |
|
116 */ |
|
117 private Display() |
|
118 { |
|
119 } |
|
120 |
|
121 /** |
|
122 * Returns the Display unique for specific midlet. |
|
123 * |
|
124 * @param midlet - MIDlet |
|
125 * @return display - unique display used by the midlet. note: current |
|
126 * implementation supports 1 Display. |
|
127 */ |
|
128 public static Display getDisplay(MIDlet midlet) |
|
129 { |
|
130 if(midlet == null) |
|
131 { |
|
132 throw new NullPointerException( |
|
133 MsgRepository.DISPLAY_EXCEPTION_MIDLET_IS_NULL); |
|
134 } |
|
135 // following code was removed to improve performance |
|
136 /*if (emptyForm == null) { |
|
137 emptyForm = new Form(midlet.getAppProperty("MIDlet-Name")); |
|
138 ESWTUIThreadRunner.syncExec(new Runnable() { |
|
139 public void run() { |
|
140 emptyForm.eswtHandleShowCurrentEvent(); |
|
141 emptyForm.eswtHandleHideCurrentEvent(); |
|
142 emptyForm.getContentComp().getVerticalBar().setVisible( |
|
143 false); |
|
144 } |
|
145 }); |
|
146 }*/ |
|
147 return instance; |
|
148 } |
|
149 |
|
150 /** |
|
151 * Returns the Display instance. |
|
152 */ |
|
153 static Display getDisplay() |
|
154 { |
|
155 return instance; |
|
156 } |
|
157 |
|
158 /** |
|
159 * Propagate event to current displayable. |
|
160 */ |
|
161 void eswtHandleEvent(Event e) |
|
162 { |
|
163 if(currentDisplayable != null) |
|
164 { |
|
165 currentDisplayable.eswtHandleEvent(e); |
|
166 } |
|
167 } |
|
168 |
|
169 /** |
|
170 * Detect support for colors. |
|
171 * |
|
172 * @return true if Display supports colors. false if black and white only |
|
173 * supported. |
|
174 */ |
|
175 public boolean isColor() |
|
176 { |
|
177 return true; |
|
178 } |
|
179 |
|
180 /** |
|
181 * Get number of colors supported by device. |
|
182 * |
|
183 * @return number of Colors supported by device. |
|
184 */ |
|
185 public int numColors() |
|
186 { |
|
187 ESWTUIThreadRunner.syncExec(new Runnable() |
|
188 { |
|
189 public void run() |
|
190 { |
|
191 numColors = eswtNumColors(); |
|
192 } |
|
193 }); |
|
194 return numColors; |
|
195 } |
|
196 |
|
197 /** |
|
198 * eSWT specific call to implement Display.numColors() functionality. |
|
199 * |
|
200 * @return numColors supported by device. |
|
201 */ |
|
202 public int eswtNumColors() |
|
203 { |
|
204 final int MAX_SHIFT = 24; |
|
205 |
|
206 Screen[] screens = MobileDevice.getMobileDevice().getScreens(); |
|
207 Screen activeScreen = null; |
|
208 int depth = 0; |
|
209 |
|
210 if(screens != null) |
|
211 { |
|
212 for(int i = 0; i < screens.length; i++) |
|
213 { |
|
214 if(screens[i].isActive()) |
|
215 { |
|
216 activeScreen = screens[i]; |
|
217 } |
|
218 } |
|
219 |
|
220 depth = activeScreen.getColorDepth(); |
|
221 |
|
222 if(depth >= MAX_SHIFT) |
|
223 { |
|
224 // For 16 Million Colors |
|
225 numColors = (1 << 24); |
|
226 } |
|
227 else |
|
228 { |
|
229 numColors = (1 << depth); |
|
230 } |
|
231 } |
|
232 |
|
233 return numColors; |
|
234 } |
|
235 |
|
236 /** |
|
237 * Returns current Displayable for Display. |
|
238 * |
|
239 * @return current Displayable |
|
240 */ |
|
241 public Displayable getCurrent() |
|
242 { |
|
243 ESWTUIThreadRunner.syncExec(new Runnable() |
|
244 { |
|
245 public void run() |
|
246 { |
|
247 getcurrent = eswtGetCurrent(); |
|
248 } |
|
249 }); |
|
250 return getcurrent; |
|
251 } |
|
252 |
|
253 /** |
|
254 * eSWT specific call to implement Display.getCurrent() functionality |
|
255 * |
|
256 * @return current Displayable object which is active for Display |
|
257 */ |
|
258 Displayable eswtGetCurrent() |
|
259 { |
|
260 if(ESWTUIThreadRunner.getInstance().getDisplay().getActiveShell() |
|
261 != null) |
|
262 { |
|
263 return currentDisplayable; |
|
264 } |
|
265 return null; |
|
266 } |
|
267 |
|
268 /** |
|
269 * Set the currentDisplayable to be active in the midlet. |
|
270 * |
|
271 * @param displayable new Displayable to be set active in midlet |
|
272 */ |
|
273 public void setCurrent(Displayable displayable) |
|
274 { |
|
275 if(displayable != null) |
|
276 { |
|
277 if(displayable instanceof Alert) |
|
278 { |
|
279 Alert alert = (Alert) displayable; |
|
280 if(currentDisplayable == null) |
|
281 { |
|
282 // if Alert is the first Displayable |
|
283 alert.setNextDisplayable(null); |
|
284 doSetCurrent(alert); |
|
285 } |
|
286 else |
|
287 { |
|
288 setCurrent(alert, currentDisplayable); |
|
289 } |
|
290 } |
|
291 else |
|
292 { |
|
293 doSetCurrent(displayable); |
|
294 } |
|
295 } |
|
296 else |
|
297 { |
|
298 /* |
|
299 * If parameter is null, nothing is required to happen, optionally |
|
300 * bringing Midlet to background/foreground. |
|
301 */ |
|
302 |
|
303 if(currentDisplayable != null && currentDisplayable instanceof Alert) |
|
304 { |
|
305 // Restarts Alert timer if any |
|
306 Alert alert = (Alert) currentDisplayable; |
|
307 alert.resetTimerTask(true); |
|
308 } |
|
309 } |
|
310 } |
|
311 |
|
312 /** |
|
313 * Set an Alarm to be active in the midlet. |
|
314 * |
|
315 * @param alert Alert to be set active in midlet |
|
316 * @param nextDisplayable next Displayable to be set active after Alert |
|
317 * |
|
318 * @throws NullPointerException if aAlert or aNextDisplayable is null |
|
319 * @throws IllegalArgumentException if aNextDisplayable is an Alert |
|
320 */ |
|
321 public void setCurrent(Alert alert, Displayable nextDisplayable) |
|
322 { |
|
323 if(alert == null) |
|
324 { |
|
325 throw new NullPointerException( |
|
326 MsgRepository.DISPLAY_EXCEPTION_ALERT_IS_NULL); |
|
327 } |
|
328 else if(nextDisplayable == null) |
|
329 { |
|
330 throw new NullPointerException( |
|
331 MsgRepository.DISPLAY_EXCEPTION_NEXTDISP_IS_NULL); |
|
332 } |
|
333 else if(nextDisplayable instanceof Alert) |
|
334 { |
|
335 throw new IllegalArgumentException( |
|
336 MsgRepository.DISPLAY_EXCEPTION_NEXTDISP_IS_ALERT); |
|
337 } |
|
338 alert.setNextDisplayable(nextDisplayable); |
|
339 doSetCurrent(alert); |
|
340 } |
|
341 |
|
342 /** |
|
343 * Sets Displayable which contains specified item to be current and scrolls |
|
344 * Displayable so that the item is visible. In addition of that, if item is |
|
345 * focusable the focus is set to the item. |
|
346 * |
|
347 * @param item Item to be displayed. |
|
348 * @throws IllegalStateException If Item is not owned by a container. |
|
349 * @throws IllegalStateException If The Item is owned by an Alert. |
|
350 * @throws NullPointerException If the Item is null. |
|
351 */ |
|
352 public void setCurrentItem(Item item) |
|
353 { |
|
354 if(item == null) |
|
355 { |
|
356 throw new NullPointerException( |
|
357 MsgRepository.DISPLAY_EXCEPTION_ITEM_IS_NULL); |
|
358 } |
|
359 if(item.isContainedInAlert()) |
|
360 { |
|
361 throw new IllegalStateException( |
|
362 MsgRepository.ITEM_EXCEPTION_OWNED_BY_ALERT); |
|
363 } |
|
364 if(item.getParent() == null) |
|
365 { |
|
366 throw new IllegalStateException( |
|
367 MsgRepository.DISPLAY_EXCEPTION_ITEM_HAS_NO_PARENT); |
|
368 } |
|
369 Logger.method(this, "setCurrentItem", item); |
|
370 ((Form) item.getParent()).setCurrentItem(item); |
|
371 setCurrent((item.getParent())); |
|
372 } |
|
373 |
|
374 /** |
|
375 * Changes the current Displayable |
|
376 * |
|
377 * @param displayable the Displayable to be set active |
|
378 */ |
|
379 private void doSetCurrent(final Displayable displayable) |
|
380 { |
|
381 if(currentDisplayable != displayable) |
|
382 { |
|
383 ESWTUIThreadRunner.syncExec(new Runnable() |
|
384 { |
|
385 public void run() |
|
386 { |
|
387 eswtDoSetCurrent(displayable); |
|
388 } |
|
389 }); |
|
390 } |
|
391 } |
|
392 |
|
393 /** |
|
394 * eSWT callback for doSetCurrent |
|
395 */ |
|
396 private void eswtDoSetCurrent(Displayable displayable) |
|
397 { |
|
398 Logger.info("Display :: " + currentDisplayable + " -> " + displayable); |
|
399 // hide old Displayable |
|
400 if(currentDisplayable != null) |
|
401 { |
|
402 currentDisplayable.eswtHandleHideCurrentEvent(); |
|
403 } |
|
404 // change the current reference |
|
405 currentDisplayable = displayable; |
|
406 // show new Displayable |
|
407 if(currentDisplayable != null) |
|
408 { |
|
409 currentDisplayable.eswtHandleShowCurrentEvent(); |
|
410 } |
|
411 } |
|
412 |
|
413 /** |
|
414 * Calls Run of Runnable parameter synchronized with event thread. |
|
415 * |
|
416 * @param runnable to serialize. |
|
417 */ |
|
418 public void callSerially(Runnable runnable) |
|
419 { |
|
420 eswtCallSerially(runnable); |
|
421 } |
|
422 |
|
423 /** |
|
424 * eSWT specific calls to implement callSerially(Runnable runnable). |
|
425 * |
|
426 * @param runnable to serialize. |
|
427 */ |
|
428 void eswtCallSerially(Runnable runnable) |
|
429 { |
|
430 EventDispatcher eventDispatcher = EventDispatcher.instance(); |
|
431 LCDUIEvent event = eventDispatcher.newEvent(LCDUIEvent.RUNNABLE_CALLSERIALLY, this); |
|
432 event.runnable = runnable; |
|
433 eventDispatcher.postEvent(event); |
|
434 } |
|
435 |
|
436 /** |
|
437 * Flashes devices backlight. |
|
438 * |
|
439 * @param duration Duration in milliseconds. |
|
440 * @return false if no flashing happened because MIDlet was in background or |
|
441 * feature is not supported. |
|
442 * @throws IllegalArgumentException if duration is negative. |
|
443 */ |
|
444 public boolean flashBacklight(int duration) |
|
445 { |
|
446 if(duration < 0) |
|
447 { |
|
448 throw new IllegalArgumentException( |
|
449 MsgRepository.DISPLAY_EXCEPTION_NEGATIVE_DURATION); |
|
450 } |
|
451 return DisplayExtension.flashLights(duration); |
|
452 } |
|
453 |
|
454 /** |
|
455 * Vibrates device. |
|
456 * |
|
457 * @param duration Duration in milliseconds. |
|
458 * @return false if no vibration happened because MIDlet was in background |
|
459 * or feature is not supported. |
|
460 * @throws IllegalArgumentException if duration is negative. |
|
461 */ |
|
462 public boolean vibrate(int duration) |
|
463 { |
|
464 if(duration < 0) |
|
465 { |
|
466 throw new IllegalArgumentException( |
|
467 MsgRepository.DISPLAY_EXCEPTION_NEGATIVE_DURATION); |
|
468 } |
|
469 return DisplayExtension.startVibra(duration); |
|
470 } |
|
471 |
|
472 /** |
|
473 * Defines color in RGB based on specifier. |
|
474 * |
|
475 * @param specifier one of the defined color specifiers. |
|
476 * @return color in RGB. currently only 2 constants supported: |
|
477 * COLOR_BACKGROUND and COLOR_FOREGROUND |
|
478 */ |
|
479 public int getColor(int specifier) |
|
480 { |
|
481 // TODO: eSWT support required - for other color constants in LCDUI |
|
482 int constant = 0; |
|
483 switch(specifier) |
|
484 { |
|
485 case COLOR_BACKGROUND: |
|
486 constant = SWT.COLOR_WIDGET_BACKGROUND; |
|
487 break; |
|
488 case COLOR_FOREGROUND: |
|
489 constant = SWT.COLOR_WIDGET_FOREGROUND; |
|
490 break; |
|
491 case COLOR_HIGHLIGHTED_BACKGROUND: |
|
492 break; |
|
493 case COLOR_HIGHLIGHTED_FOREGROUND: |
|
494 break; |
|
495 case COLOR_BORDER: |
|
496 break; |
|
497 case COLOR_HIGHLIGHTED_BORDER: |
|
498 break; |
|
499 default: |
|
500 throw new IllegalArgumentException( |
|
501 MsgRepository.DISPLAY_EXCEPTION_INVALID_COLOR_IDENTIFIER); |
|
502 } |
|
503 |
|
504 final int finalConstant = constant; |
|
505 ESWTUIThreadRunner.syncExec(new Runnable() |
|
506 { |
|
507 public void run() |
|
508 { |
|
509 eswtTempRgb = ESWTUIThreadRunner.getInstance().getDisplay() |
|
510 .getSystemColor(finalConstant).getRGB(); |
|
511 } |
|
512 }); |
|
513 |
|
514 int color = eswtTempRgb.red; |
|
515 color <<= Config.DISPLAY_BITS_PER_PIXEL; |
|
516 color += eswtTempRgb.green; |
|
517 color <<= Config.DISPLAY_BITS_PER_PIXEL; |
|
518 color += eswtTempRgb.blue; |
|
519 return color; |
|
520 } |
|
521 |
|
522 /** |
|
523 * Returns border style of a UI component. |
|
524 * |
|
525 * @param isHighlighted true if component is highlighted |
|
526 * @return Border style of a UI component. |
|
527 */ |
|
528 public int getBorderStyle(boolean isHighlighted) |
|
529 { |
|
530 return Graphics.SOLID; |
|
531 } |
|
532 |
|
533 /** |
|
534 * Get number of alpha levels supported. |
|
535 * |
|
536 * @return number of supported alpha levels |
|
537 */ |
|
538 public int numAlphaLevels() |
|
539 { |
|
540 // Number of alpha levels is always 256, this implementation does |
|
541 // not support monochrome or 2-bit transparency. |
|
542 return 256; |
|
543 } |
|
544 |
|
545 /** |
|
546 * Get best image width. |
|
547 * |
|
548 * @param imgType Image type. |
|
549 * @return Best image width in pixels. |
|
550 */ |
|
551 public int getBestImageWidth(int imgType) |
|
552 { |
|
553 if ((imgType < LIST_ELEMENT) || (imgType > ALERT)) |
|
554 throw new IllegalArgumentException(); |
|
555 |
|
556 return DisplayExtension.getBestImageWidth(imgType); |
|
557 } |
|
558 |
|
559 /** |
|
560 * Get best image height. |
|
561 * |
|
562 * @param imgType Image type. |
|
563 * @return Best image height in pixels. |
|
564 */ |
|
565 public int getBestImageHeight(int imgType) |
|
566 { |
|
567 if ((imgType < LIST_ELEMENT) || (imgType > ALERT)) |
|
568 throw new IllegalArgumentException(); |
|
569 |
|
570 return DisplayExtension.getBestImageHeight(imgType); |
|
571 } |
|
572 |
|
573 /* |
|
574 * Dispatcher thread calls. |
|
575 */ |
|
576 void doCallback(LCDUIEvent event) |
|
577 { |
|
578 switch(event.type) |
|
579 { |
|
580 case LCDUIEvent.RUNNABLE_CALLSERIALLY: |
|
581 event.runnable.run(); |
|
582 break; |
|
583 } |
|
584 } |
|
585 } |