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