javauis/lcdui_qt/src/javax/microedition/lcdui/Displayable.java
branchRCL_3
changeset 65 ae942d28ec0e
equal deleted inserted replaced
60:6c158198356e 65:ae942d28ec0e
       
     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 }