|
1 /* |
|
2 * Copyright (c) 2009, 2010 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 java.util.Enumeration; |
|
20 import java.util.Vector; |
|
21 |
|
22 import javax.microedition.lcdui.EventDispatcher.LCDUIEvent; |
|
23 |
|
24 import org.eclipse.swt.SWT; |
|
25 import org.eclipse.swt.events.*; |
|
26 import org.eclipse.swt.graphics.Rectangle; |
|
27 import org.eclipse.swt.internal.extension.CompositeExtension; |
|
28 import org.eclipse.swt.internal.extension.MobileShellExtension; |
|
29 import org.eclipse.swt.widgets.*; |
|
30 import com.nokia.mj.impl.rt.support.ApplicationUtils; |
|
31 |
|
32 /** |
|
33 * Implementation of LCDUI <code>Displayable</code> class. |
|
34 */ |
|
35 public abstract class Displayable |
|
36 { |
|
37 |
|
38 private EswtCommandListener eswtCommandListener = new EswtCommandListener(); |
|
39 |
|
40 private EswtShellListener eswtShellListener = new EswtShellListener(); |
|
41 |
|
42 private EswtControlListener eswtControlListener = new EswtControlListener(); |
|
43 |
|
44 private EswtDisposeListener eswtDisposeListener = new EswtDisposeListener(); |
|
45 |
|
46 /** |
|
47 * Are the commands enabled or not. |
|
48 */ |
|
49 private boolean isEnabledCmds = true; |
|
50 |
|
51 /** |
|
52 * Shell is activated/de-activated. Called by shell listener. |
|
53 */ |
|
54 private boolean isShellActive = true; |
|
55 |
|
56 /** |
|
57 * Visible from OpenLCDUI's point of view. Called by Display.setCurrent(). |
|
58 */ |
|
59 private boolean isLcduiVisible; |
|
60 |
|
61 /** |
|
62 * Owned mobile shell. |
|
63 */ |
|
64 private Shell shell; |
|
65 |
|
66 /** |
|
67 * Content composite. |
|
68 */ |
|
69 private Composite contentComp; |
|
70 |
|
71 private Rectangle contentArea; |
|
72 |
|
73 private boolean initialized; |
|
74 |
|
75 private boolean isShownReturnValue; |
|
76 |
|
77 private com.nokia.mj.impl.rt.support.Finalizer finalizer; |
|
78 |
|
79 private String title; |
|
80 |
|
81 private Vector commands = new Vector(); |
|
82 |
|
83 private CommandListener iCommandListener; |
|
84 |
|
85 private Ticker ticker; |
|
86 |
|
87 /** |
|
88 * eSWT Label which is used to display the Ticker. This is stored in |
|
89 * displayable because same Ticker may exists in many displayables but eSWT |
|
90 * Controls are always associated with only one Displayable. |
|
91 */ |
|
92 private Label tickerLabel; |
|
93 |
|
94 /** |
|
95 * Default Constructor. |
|
96 */ |
|
97 Displayable(String title) |
|
98 { |
|
99 this.title = title; |
|
100 finalizer = ((finalizer != null) ? finalizer |
|
101 : new com.nokia.mj.impl.rt.support.Finalizer() |
|
102 { |
|
103 public void finalizeImpl() |
|
104 { |
|
105 if(finalizer != null) |
|
106 { |
|
107 finalizer = null; |
|
108 if(!ESWTUIThreadRunner.isDisposed()) |
|
109 { |
|
110 dispose(); |
|
111 } |
|
112 } |
|
113 } |
|
114 }); |
|
115 ESWTUIThreadRunner.update(getClass().getName(), 1); |
|
116 } |
|
117 |
|
118 /** |
|
119 * Performs eSWT construction of shell and content composite. <br> |
|
120 * Should be called from child level constructors. |
|
121 */ |
|
122 final void construct() |
|
123 { |
|
124 ESWTUIThreadRunner.safeSyncExec(new Runnable() |
|
125 { |
|
126 public void run() |
|
127 { |
|
128 shell = eswtConstructShell(SWT.SHELL_TRIM | SWT.PRIMARY_MODAL); |
|
129 eswtSetTitle(); |
|
130 contentComp = eswtConstructContent(SWT.NONE); |
|
131 contentArea = eswtLayoutShellContent(); |
|
132 eswtInitGraphics(); |
|
133 } |
|
134 }); |
|
135 } |
|
136 |
|
137 /** |
|
138 * Dispose Displayable. |
|
139 */ |
|
140 void dispose() |
|
141 { |
|
142 if(ticker != null) |
|
143 { |
|
144 ticker.removeLabel(tickerLabel); |
|
145 } |
|
146 ESWTUIThreadRunner.update(getClass().getName(), -1); |
|
147 ESWTUIThreadRunner.safeSyncExec(new Runnable() |
|
148 { |
|
149 public void run() |
|
150 { |
|
151 if(shell != null) |
|
152 { |
|
153 shell.dispose(); |
|
154 } |
|
155 } |
|
156 }); |
|
157 } |
|
158 |
|
159 /** |
|
160 * Constructs default eSWT Shell.<br> |
|
161 * Default SWT shell style is SWT.SYSTEM_MODAL |
|
162 * |
|
163 * @param style eSWT style |
|
164 * |
|
165 * @return eSWT shell |
|
166 */ |
|
167 Shell eswtConstructShell(int style) |
|
168 { |
|
169 return new MobileShellExtension(ESWTUIThreadRunner.getInstance().getDisplay(), style); |
|
170 } |
|
171 |
|
172 /** |
|
173 * Creates content Composite. this Composite is placed inside of |
|
174 * shell and contains the actual displayable's content (excluding ticker). |
|
175 * |
|
176 * Child classes may override this is if for example scrollbar is needed. |
|
177 * |
|
178 * @return Composite where the content is placed. |
|
179 */ |
|
180 Composite eswtConstructContent(int style) |
|
181 { |
|
182 Composite comp = new CompositeExtension(shell, style); |
|
183 return comp; |
|
184 } |
|
185 |
|
186 /** |
|
187 * Initializes the Displayable for Graphics drawing. |
|
188 */ |
|
189 void eswtInitGraphics() { |
|
190 |
|
191 } |
|
192 |
|
193 /** |
|
194 * Called by Display when Displayable should become visible. |
|
195 */ |
|
196 void eswtHandleShowCurrentEvent() |
|
197 { |
|
198 if(!shell.isDisposed()) |
|
199 { |
|
200 eswtUpdateSizes(); |
|
201 if(ticker != null) |
|
202 { |
|
203 ticker.start(); |
|
204 } |
|
205 shell.addShellListener(eswtShellListener); |
|
206 shell.addDisposeListener(eswtDisposeListener); |
|
207 shell.addControlListener(eswtControlListener); |
|
208 eswtAddSelectionListenerForCommands(); |
|
209 // calling open() causes a resize event to be sent |
|
210 shell.open(); |
|
211 isLcduiVisible = true; |
|
212 // shell.setVisible(true); |
|
213 // TODO: needed because of eSWT focus bug |
|
214 /*if (!isDialogShell()) { |
|
215 Shell[] shells = shell.getDisplay().getShells(); |
|
216 for (int i = 0; i < shells.length; i++) { |
|
217 if (shells[i] != shell && shells[i].isVisible()) { |
|
218 shells[i].setVisible(false); |
|
219 } |
|
220 } |
|
221 }*/ |
|
222 } |
|
223 } |
|
224 |
|
225 /** |
|
226 * Called by Display when Displayable should become hidden. |
|
227 */ |
|
228 void eswtHandleHideCurrentEvent() |
|
229 { |
|
230 isLcduiVisible = false; |
|
231 if(!shell.isDisposed()) |
|
232 { |
|
233 shell.removeShellListener(eswtShellListener); |
|
234 shell.removeDisposeListener(eswtDisposeListener); |
|
235 shell.removeControlListener(eswtControlListener); |
|
236 eswtRemoveSelectionListenerForCommands(); |
|
237 } |
|
238 } |
|
239 |
|
240 /** |
|
241 * Handle event. |
|
242 * |
|
243 * @param e eSWT event |
|
244 */ |
|
245 void eswtHandleEvent(Event e) |
|
246 { |
|
247 // implementation in child classes |
|
248 // Logger.method(this, "eswtHandleEvent", e); |
|
249 } |
|
250 |
|
251 /** |
|
252 * Called by ShellListener when shell gets activated. |
|
253 */ |
|
254 void handleShellActivatedEvent() |
|
255 { |
|
256 // Implementation in child-classes |
|
257 // Logger.method(this, "handleShellActivatedEvent"); |
|
258 if(ESWTUIThreadRunner.getInstance().getDisplay().getActiveShell() |
|
259 != null) |
|
260 { |
|
261 if(JadAttributeUtil.isValue(JadAttributeUtil.ATTRIB_NOKIA_MIDLET_BACKGROUND_EVENT, |
|
262 JadAttributeUtil.VALUE_PAUSE)) |
|
263 { |
|
264 ApplicationUtils.getInstance().resumeApplication(); |
|
265 } |
|
266 isShellActive = true; |
|
267 } |
|
268 } |
|
269 |
|
270 /** |
|
271 * Called by ShellListener when shell gets de-activated. |
|
272 */ |
|
273 void handleShellDeActivatedEvent() |
|
274 { |
|
275 // Implementation in child-classes |
|
276 // Logger.method(this, "handleShellDeActivatedEvent"); |
|
277 if(isShellActive) |
|
278 { |
|
279 if(ESWTUIThreadRunner.getInstance().getDisplay().getActiveShell() |
|
280 == null) |
|
281 { |
|
282 if(JadAttributeUtil.isValue(JadAttributeUtil.ATTRIB_NOKIA_MIDLET_BACKGROUND_EVENT, |
|
283 JadAttributeUtil.VALUE_PAUSE)) |
|
284 { |
|
285 ApplicationUtils.getInstance().pauseApplication(); |
|
286 isShellActive = false; |
|
287 } |
|
288 } |
|
289 } |
|
290 } |
|
291 |
|
292 /** |
|
293 * This is called if resolution or orientation was changed. This should be |
|
294 * overwritten by sub-classes to get notifications about size changes. |
|
295 * |
|
296 * @param width new width of Displayable. |
|
297 * @param height new height of Displayable. |
|
298 */ |
|
299 void eswtHandleResizeEvent(int width, int height) |
|
300 { |
|
301 Logger.method(this, "eswtHandleResizeEvent", |
|
302 String.valueOf(width), String.valueOf(height)); |
|
303 LCDUIEvent event = EventDispatcher.instance().newEvent(LCDUIEvent.DISPLAYABLE_SIZECHANGED, this); |
|
304 event.width = width; |
|
305 event.height = height; |
|
306 EventDispatcher.instance().postEvent(event); |
|
307 } |
|
308 |
|
309 /** |
|
310 * Returns if the shell is Dialog styled. |
|
311 */ |
|
312 private boolean isDialogShell() |
|
313 { |
|
314 return (shell.getStyle() & SWT.DIALOG_TRIM) == SWT.DIALOG_TRIM; |
|
315 } |
|
316 |
|
317 /** |
|
318 * Set content size. |
|
319 * |
|
320 * @param aWidth required width or -1 to ignore |
|
321 * @param aHeight required height or -1 to ignore |
|
322 */ |
|
323 void eswtSetPreferredContentSize(int aWidth, int aHeight) |
|
324 { |
|
325 if(isDialogShell()) |
|
326 { |
|
327 // aHeight += Config.DISPLAYABLE_DIALOGSHELL_HEIGHT_DISPLACEMENT; |
|
328 |
|
329 Logger.method(this, "eswtSetPreferredContentSize", |
|
330 String.valueOf(aWidth), String.valueOf(aHeight)); |
|
331 |
|
332 Rectangle contentBounds = contentComp.getBounds(); |
|
333 int newWidth = (aWidth > 0 ? aWidth : contentBounds.width); |
|
334 int newHeight = (aHeight > 0 ? aHeight : contentBounds.height); |
|
335 |
|
336 if(tickerLabel != null) |
|
337 { |
|
338 newHeight += tickerLabel.getBounds().height; |
|
339 } |
|
340 |
|
341 Rectangle shellBounds = shell.getBounds(); |
|
342 // compute the trimmed shell size |
|
343 Rectangle newSize = shell.computeTrim(0, 0, newWidth, newHeight); |
|
344 // set the new size |
|
345 shell.setSize(newSize.width, newSize.height); |
|
346 // set the location - attached to the bottom growing upwards |
|
347 shell.setLocation(shellBounds.x, (shellBounds.y + shellBounds.height) - newSize.height); |
|
348 } |
|
349 } |
|
350 |
|
351 Rectangle eswtLayoutShellContent() |
|
352 { |
|
353 Rectangle shellArea = shell.getClientArea(); |
|
354 if(tickerLabel != null) |
|
355 { |
|
356 int tickerHeight = tickerLabel.getBounds().height; |
|
357 |
|
358 contentComp.setBounds(0, tickerHeight, |
|
359 shellArea.width, shellArea.height - tickerHeight); |
|
360 } |
|
361 else |
|
362 { |
|
363 contentComp.setBounds(0, 0, shellArea.width, shellArea.height); |
|
364 } |
|
365 return contentComp.getClientArea(); |
|
366 } |
|
367 |
|
368 /** |
|
369 * Update internal size of Displayable. |
|
370 */ |
|
371 void eswtUpdateSizes() |
|
372 { |
|
373 Rectangle newArea = eswtLayoutShellContent(); |
|
374 // if the content size has changed or its not initialized |
|
375 if(!initialized |
|
376 || newArea.width != contentArea.width |
|
377 || newArea.height != contentArea.height) |
|
378 { |
|
379 contentArea = newArea; |
|
380 initialized = true; |
|
381 if(ticker != null) |
|
382 { |
|
383 ticker.updateSpeed(); |
|
384 } |
|
385 eswtHandleResizeEvent(contentArea.width, contentArea.height); |
|
386 } |
|
387 } |
|
388 |
|
389 /** |
|
390 * Tells is this Displayable visible. |
|
391 * |
|
392 * @return true if this Displayable is currently visible. |
|
393 */ |
|
394 public synchronized boolean isShown() |
|
395 { |
|
396 ESWTUIThreadRunner.syncExec(new Runnable() |
|
397 { |
|
398 public void run() |
|
399 { |
|
400 isShownReturnValue = eswtIsShown(); |
|
401 } |
|
402 }); |
|
403 return isShownReturnValue; |
|
404 } |
|
405 |
|
406 /** |
|
407 * eSWT call-back that verifies that the Displayable is shown. |
|
408 */ |
|
409 boolean eswtIsShown() |
|
410 { |
|
411 if(!isLcduiVisible || !isShellActive) |
|
412 { |
|
413 // shell.isVisible() doesn't return false if MIDlet |
|
414 // is in background. That's why isVisible-variable is |
|
415 // used instead. |
|
416 return false; |
|
417 } |
|
418 if(shell.isDisposed() || !shell.isEnabled()) |
|
419 { |
|
420 return false; |
|
421 } |
|
422 return true; |
|
423 } |
|
424 |
|
425 /** |
|
426 * Validates a Command. |
|
427 * |
|
428 * @param command a Command |
|
429 */ |
|
430 void validateCommand(Command command) |
|
431 { |
|
432 if(command == null) |
|
433 { |
|
434 throw new NullPointerException( |
|
435 MsgRepository.DISPLAYABLE_EXCEPTION_NULL_PARAMETER); |
|
436 } |
|
437 } |
|
438 |
|
439 /** |
|
440 * Set commands visibility. |
|
441 * |
|
442 * @param enableCmds visibility switch |
|
443 */ |
|
444 void setCommandsVisibility(boolean enableCmds) |
|
445 { |
|
446 if(enableCmds != isEnabledCmds) |
|
447 { |
|
448 isEnabledCmds = enableCmds; |
|
449 ESWTUIThreadRunner.syncExec(new Runnable() |
|
450 { |
|
451 public void run() |
|
452 { |
|
453 int numCmd = getNumCommands(); |
|
454 for(int i = 0; i < numCmd; i++) |
|
455 { |
|
456 if(isEnabledCmds) |
|
457 { |
|
458 eswtAddCommand(getCommand(i)); |
|
459 } |
|
460 else |
|
461 { |
|
462 eswtRemoveCommand(getCommand(i)); |
|
463 } |
|
464 } |
|
465 } |
|
466 }); |
|
467 } |
|
468 } |
|
469 |
|
470 /** |
|
471 * Adds a command to this Displayable. |
|
472 * |
|
473 * @param command The Command to be added. If the Command already is added |
|
474 * to this Displayable, nothing happens. |
|
475 * @throws NullPointerException If parameter is null. |
|
476 */ |
|
477 public void addCommand(Command command) |
|
478 { |
|
479 validateCommand(command); |
|
480 if(!commands.contains(command)) |
|
481 { |
|
482 commands.addElement(command); |
|
483 // Command is not yet added to this Displayable. |
|
484 if(isEnabledCmds) |
|
485 { |
|
486 final Command finalCommand = command; |
|
487 ESWTUIThreadRunner.syncExec(new Runnable() |
|
488 { |
|
489 public void run() |
|
490 { |
|
491 eswtAddCommand(finalCommand); |
|
492 } |
|
493 }); |
|
494 } |
|
495 } |
|
496 } |
|
497 |
|
498 /** |
|
499 * eSWT callback to add a Command. |
|
500 */ |
|
501 void eswtAddCommand(Command cmd) |
|
502 { |
|
503 cmd.eswtAddESWTCommand(shell, false); |
|
504 if(eswtIsShown()) |
|
505 { |
|
506 cmd.eswtAddCommandSelectionListener(shell, eswtCommandListener); |
|
507 } |
|
508 } |
|
509 |
|
510 /** |
|
511 * Removes command from the Displayable. |
|
512 * |
|
513 * @param command Command to be removed. If parameter is null or Command |
|
514 * isn't added to Displayable, nothing happens. |
|
515 */ |
|
516 public void removeCommand(Command command) |
|
517 { |
|
518 if(command != null && commands.contains(command)) |
|
519 { |
|
520 // Remove command from iCommands-vector |
|
521 commands.removeElement(command); |
|
522 if(isEnabledCmds) |
|
523 { |
|
524 final Command finalCommand = command; |
|
525 ESWTUIThreadRunner.syncExec(new Runnable() |
|
526 { |
|
527 public void run() |
|
528 { |
|
529 eswtRemoveCommand(finalCommand); |
|
530 } |
|
531 }); |
|
532 } |
|
533 } |
|
534 } |
|
535 |
|
536 /** |
|
537 * eSWT callback to remove a Command. |
|
538 */ |
|
539 void eswtRemoveCommand(Command cmd) |
|
540 { |
|
541 if(eswtIsShown()) |
|
542 { |
|
543 cmd.eswtRemoveCommandSelectionListener(shell, eswtCommandListener); |
|
544 } |
|
545 cmd.eswtRemoveESWTCommand(shell); |
|
546 } |
|
547 |
|
548 /** |
|
549 * Sets CommandListener. If CommandListener already exists, it is replaced |
|
550 * with the new one. |
|
551 * |
|
552 * @param commandListener New CommandListener. If null, existing |
|
553 * CommandListener is removed. If null and no CommandListener |
|
554 * exists, nothing happens. |
|
555 */ |
|
556 public void setCommandListener(CommandListener commandListener) |
|
557 { |
|
558 this.iCommandListener = commandListener; |
|
559 } |
|
560 |
|
561 public boolean hasCommandListener() |
|
562 { |
|
563 if(this.iCommandListener != null) |
|
564 { |
|
565 return true; |
|
566 } |
|
567 return false; |
|
568 } |
|
569 |
|
570 |
|
571 /** |
|
572 * Add command listener for all Commands added to this Displayable. |
|
573 */ |
|
574 void eswtAddSelectionListenerForCommands() |
|
575 { |
|
576 Command cmd = null; |
|
577 for(Enumeration e = commands.elements(); e.hasMoreElements();) |
|
578 { |
|
579 cmd = (Command) e.nextElement(); |
|
580 cmd.eswtAddCommandSelectionListener(shell, eswtCommandListener); |
|
581 } |
|
582 } |
|
583 |
|
584 /** |
|
585 * Remove command listener from Commands added to this Displayable. |
|
586 */ |
|
587 void eswtRemoveSelectionListenerForCommands() |
|
588 { |
|
589 Command cmd = null; |
|
590 for(Enumeration e = commands.elements(); e.hasMoreElements();) |
|
591 { |
|
592 cmd = (Command) e.nextElement(); |
|
593 cmd.eswtRemoveCommandSelectionListener(shell, eswtCommandListener); |
|
594 } |
|
595 } |
|
596 |
|
597 /** |
|
598 * Calls the command action on the current command listener. |
|
599 * |
|
600 * @param command the Command |
|
601 */ |
|
602 final void callCommandAction(Command command) |
|
603 { |
|
604 if(iCommandListener != null && command != null) |
|
605 { |
|
606 LCDUIEvent event = EventDispatcher.instance().newEvent(LCDUIEvent.DISPLAYABLE_COMMANDACTION, this); |
|
607 event.command = command; |
|
608 event.commandListener = iCommandListener; |
|
609 EventDispatcher.instance().postEvent(event); |
|
610 } |
|
611 } |
|
612 |
|
613 /** |
|
614 * Gets the number of commands. |
|
615 * |
|
616 * @return the number of commands in this Displayable |
|
617 */ |
|
618 final int getNumCommands() |
|
619 { |
|
620 return commands.size(); |
|
621 } |
|
622 |
|
623 /** |
|
624 * Gets a command in the command array. |
|
625 * |
|
626 * @param index index of command |
|
627 * @return the command |
|
628 */ |
|
629 final Command getCommand(int index) |
|
630 { |
|
631 return (Command) commands.elementAt(index); |
|
632 } |
|
633 |
|
634 /** |
|
635 * Gets the commands array. |
|
636 * |
|
637 * @return the commands |
|
638 */ |
|
639 Vector getCommands() |
|
640 { |
|
641 return commands; |
|
642 } |
|
643 |
|
644 /** |
|
645 * Gets the command listener. |
|
646 * |
|
647 * @return the eswt command listener. |
|
648 */ |
|
649 final EswtCommandListener getCommandListener() |
|
650 { |
|
651 return eswtCommandListener; |
|
652 } |
|
653 |
|
654 /** |
|
655 * Gets width. |
|
656 * |
|
657 * @return Width of the Displayable in pixels. |
|
658 */ |
|
659 public int getWidth() |
|
660 { |
|
661 return contentArea.width; |
|
662 } |
|
663 |
|
664 /** |
|
665 * Gets height. |
|
666 * |
|
667 * @return Height of the Displayable in pixels. |
|
668 */ |
|
669 public int getHeight() |
|
670 { |
|
671 return contentArea.height; |
|
672 } |
|
673 |
|
674 /** |
|
675 * Sets ticker. If ticker is added already to other displayable(s), |
|
676 * it continues running from position where it was. Otherwise |
|
677 * it will start running from beginning when this method returns. |
|
678 * |
|
679 * @param newTicker New ticker. If null, current ticker is removed. |
|
680 */ |
|
681 public void setTicker(Ticker newTicker) |
|
682 { |
|
683 if(ticker == newTicker) |
|
684 { |
|
685 return; |
|
686 } |
|
687 if(ticker != null) |
|
688 { |
|
689 // Ticker exists, removing it: |
|
690 ticker.removeLabel(getTickerLabel()); |
|
691 } |
|
692 ticker = newTicker; |
|
693 if(ticker != null) |
|
694 { |
|
695 ticker.addLabel(getTickerLabel()); |
|
696 } |
|
697 |
|
698 final Ticker finalTicker = ticker; |
|
699 ESWTUIThreadRunner.syncExec(new Runnable() |
|
700 { |
|
701 public void run() |
|
702 { |
|
703 if(finalTicker != null) |
|
704 { |
|
705 // Setting ticker: |
|
706 tickerLabel.setText(finalTicker.getFormattedString()); |
|
707 tickerLabel.pack(); |
|
708 // Avoid ticker flashing by setting it out of the |
|
709 // screen first: |
|
710 tickerLabel.setBounds(Integer.MIN_VALUE, 0, |
|
711 tickerLabel.getBounds().width, |
|
712 tickerLabel.getBounds().height); |
|
713 } |
|
714 else |
|
715 { |
|
716 // Removing ticker: |
|
717 tickerLabel.setText(""); |
|
718 tickerLabel.setBounds(Integer.MIN_VALUE, 0, 0, 0); |
|
719 } |
|
720 eswtUpdateSizes(); |
|
721 } |
|
722 }); |
|
723 if(ticker != null) |
|
724 { |
|
725 if(isLcduiVisible) |
|
726 { |
|
727 // Start to scroll the ticker. Ticker may be already running |
|
728 // if it exists in some other displayable already, but |
|
729 // calling this again wont do any harm: |
|
730 ticker.start(); |
|
731 } |
|
732 } |
|
733 } |
|
734 |
|
735 /** |
|
736 * Gets current ticker. |
|
737 * |
|
738 * @return Current ticker or null if no ticker set. |
|
739 */ |
|
740 public Ticker getTicker() |
|
741 { |
|
742 return ticker; |
|
743 } |
|
744 |
|
745 /** |
|
746 * Gets the current title. |
|
747 * |
|
748 * @return The title of the Displayable, or null if no title set. |
|
749 */ |
|
750 public String getTitle() |
|
751 { |
|
752 return title; |
|
753 } |
|
754 |
|
755 /** |
|
756 * Sets the title of this Displayable. |
|
757 * |
|
758 * @param newTitle new title or null for no title. |
|
759 */ |
|
760 public void setTitle(String newTitle) |
|
761 { |
|
762 this.title = newTitle; |
|
763 ESWTUIThreadRunner.syncExec(new Runnable() |
|
764 { |
|
765 public void run() |
|
766 { |
|
767 eswtSetTitle(); |
|
768 } |
|
769 }); |
|
770 } |
|
771 |
|
772 /** |
|
773 * Sets shell's title. Nulls are not allowed. |
|
774 */ |
|
775 void eswtSetTitle() |
|
776 { |
|
777 // eSWT Shell doesn't take null value as title |
|
778 shell.setText((title != null ? title : "")); |
|
779 } |
|
780 |
|
781 /** |
|
782 * Creates singleton Label instance used by Ticker. |
|
783 */ |
|
784 Label getTickerLabel() |
|
785 { |
|
786 if(tickerLabel == null) |
|
787 { |
|
788 ESWTUIThreadRunner.syncExec(new Runnable() |
|
789 { |
|
790 public void run() |
|
791 { |
|
792 tickerLabel = new Label(shell, |
|
793 SWT.SHADOW_NONE | SWT.HORIZONTAL | SWT.CENTER); |
|
794 } |
|
795 }); |
|
796 } |
|
797 return tickerLabel; |
|
798 } |
|
799 |
|
800 /** |
|
801 * Called by underlying system when the size of the Displayable changes. |
|
802 * This might be overwritten by user-side classes. |
|
803 * |
|
804 * @param width new width of Displayable. |
|
805 * @param height new height of Displayable. |
|
806 */ |
|
807 protected void sizeChanged(int width, int height) |
|
808 { |
|
809 } |
|
810 |
|
811 /** |
|
812 * eSWT callback to get the Shell of the Displayable. |
|
813 */ |
|
814 final Shell getShell() |
|
815 { |
|
816 return this.shell; |
|
817 } |
|
818 |
|
819 /** |
|
820 * Gets composite that contains displayable's content. |
|
821 * |
|
822 * @return Composite. |
|
823 */ |
|
824 Composite getContentComp() |
|
825 { |
|
826 return contentComp; |
|
827 } |
|
828 |
|
829 /* |
|
830 * The client area. It's ensured that after the construction this is always |
|
831 * set. |
|
832 */ |
|
833 final Rectangle getContentArea() |
|
834 { |
|
835 return contentArea; |
|
836 } |
|
837 |
|
838 /* |
|
839 * Dispatcher thread calls. |
|
840 */ |
|
841 void doCallback(LCDUIEvent event) |
|
842 { |
|
843 switch(event.type) |
|
844 { |
|
845 case LCDUIEvent.DISPLAYABLE_SIZECHANGED: |
|
846 sizeChanged(event.width, event.height); |
|
847 break; |
|
848 case LCDUIEvent.DISPLAYABLE_COMMANDACTION: |
|
849 event.commandListener.commandAction(event.command, this); |
|
850 break; |
|
851 } |
|
852 } |
|
853 |
|
854 /** |
|
855 * Inner class which receives SelectionEvents from eSWT and convert and |
|
856 * forwards those events to LCDUI's CommandListener. |
|
857 */ |
|
858 class EswtCommandListener implements SelectionListener |
|
859 { |
|
860 |
|
861 public void widgetDefaultSelected(SelectionEvent e) |
|
862 { |
|
863 } |
|
864 |
|
865 /** |
|
866 * Executed by eSWT when event occurs. This method will then call |
|
867 * Displayable's CommandListener if event source matches with the |
|
868 * Commands added to the Displayable. |
|
869 */ |
|
870 public void widgetSelected(SelectionEvent event) |
|
871 { |
|
872 // Go through all Commands added to this Displayable: |
|
873 for(Enumeration e = commands.elements(); e.hasMoreElements();) |
|
874 { |
|
875 Command cmd = (Command) e.nextElement(); |
|
876 // Select eSWT Command from Command which is connected to |
|
877 // this Displayable and compare it to the widget which |
|
878 // launched the event: |
|
879 if(cmd.getESWTCommand(shell) == event.widget) |
|
880 { |
|
881 callCommandAction(cmd); |
|
882 break; |
|
883 } |
|
884 } |
|
885 } |
|
886 } |
|
887 |
|
888 /** |
|
889 * Every Displayable must listen shell events to be able to tell is the |
|
890 * MIDlet sent to background. |
|
891 */ |
|
892 class EswtShellListener implements ShellListener |
|
893 { |
|
894 |
|
895 public void shellActivated(ShellEvent e) |
|
896 { |
|
897 ESWTUIThreadRunner.getInstance().getDisplay() |
|
898 .asyncExec(new Runnable() |
|
899 { |
|
900 public void run() |
|
901 { |
|
902 handleShellActivatedEvent(); |
|
903 } |
|
904 }); |
|
905 } |
|
906 |
|
907 public void shellDeactivated(ShellEvent e) |
|
908 { |
|
909 ESWTUIThreadRunner.getInstance().getDisplay() |
|
910 .asyncExec(new Runnable() |
|
911 { |
|
912 public void run() |
|
913 { |
|
914 handleShellDeActivatedEvent(); |
|
915 } |
|
916 }); |
|
917 |
|
918 } |
|
919 |
|
920 public void shellClosed(ShellEvent e) |
|
921 { |
|
922 } |
|
923 |
|
924 public void shellIconified(ShellEvent e) |
|
925 { |
|
926 } |
|
927 |
|
928 public void shellDeiconified(ShellEvent e) |
|
929 { |
|
930 } |
|
931 |
|
932 } |
|
933 |
|
934 class EswtDisposeListener implements DisposeListener |
|
935 { |
|
936 |
|
937 public void widgetDisposed(DisposeEvent e) |
|
938 { |
|
939 isShellActive = false; |
|
940 } |
|
941 } |
|
942 |
|
943 /** |
|
944 * Displayable must listen resize-events to be able to call |
|
945 * sizeChanged()-method at the right time. |
|
946 */ |
|
947 class EswtControlListener implements ControlListener |
|
948 { |
|
949 |
|
950 public void controlResized(ControlEvent e) |
|
951 { |
|
952 eswtUpdateSizes(); |
|
953 } |
|
954 |
|
955 public void controlMoved(ControlEvent e) |
|
956 { |
|
957 } |
|
958 } |
|
959 |
|
960 } |