How to use eSWT with Midlets

From Eclipsepedia

Revision as of 11:27, 24 March 2008 by Gercan.acm.org (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

eSWT provides a rich set UI components and can be used as an alternative UI toolkit to MIDP LCDUI provided that the MIDP runtime provider supports it. This describes how to use eSWT as the MIDlet UI, covering the issues outside of MIDP2 specification bthat need to be taken into account when eSWT is used by the MIDlets instead of LCDUI. The process of creating application code using editors, IDEs, compilers or such is not discussed in this document. This document is only covering the application design.

Contents

Displays, MIDlets and MIDletSuites

org.eclipse.swt.widgets.Display class in eSWT represents the connection point from Java to the native UI functionality. Creating one instance of Display can be perceived as creating one instance of eSWT. A MIDlet wishing to use eSWT for its UI will have to create an eSWT Display instance. It is possible to have multiple MIDlets using eSWT UI in the same MIDlet suite. In this case each MIDlet should create its own Display instance.

eSWT in the MIDlet life cycle

Starting up

When a MIDlet using eSWT for its UI has entered the active state for the first time and MIDlet.startApp() is being called then the MIDlet should immediately begin acquiring the UI resources. The first step is to create the thread that will be the eSWT UI thread.

The eSWT UI Thread

To avoid hanging the event dispatcher it’s not allowed to execute the eSWT event loop directly in the thread that called MIDlet.startApp() but a new thread must be created. I.e. in the first MIDlet.startApp() call the MIDlet should create and start a new thread that will be the eSWT UI thread. The MIDlet should then allow MIDlet.startApp() to return.

Creating the Display

In the UI thread the MIDlet should at first construct a Display instance. Finally the thread should enter an event loop dispatching eSWT events. The Display for the MIDlet should be created immediately after the UI thread has been started and it should not be disposed until the MIDlet is about to enter the destroyed state.

Pausing

When MIDlet.pauseApp() is being called and a MIDlet is entering the paused state then it can release any other eSWT resources but it should not dispose the Display instance. When a paused MIDlet is resumed then it should continue with the existing Display instance and the existing eSWT UI thread.

Destroying

System exit

When a MIDlet is notified by system that it will be destroyed with call MIDlet.destroyApp() any eSWT resources allocated by the MIDlet including graphic contexts, images, fonts and colors should be disposed*. Finally before returning from MIDlet.destroyApp() the Display should be disposed to release all the remaining eSWT UI resources.

Application initiated exit

When the application initiates exiting then the eSWT UI Thread event loop should exit. Then clean-up equivalent to the system exit case described in above should be performed. Finally MIDlet.notifyDestroyed() should be called to have the MIDlet enter destroyed state.

Code example of MIDlet lifecycle with eSWT

import javax.microedition.midlet.*;

import org.eclipse.ercp.swt.mobile.Command;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;

public class HelloWorld extends MIDlet implements Runnable, SelectionListener, PaintListener {

  // A handle to the eSWT UI thread created by this MIDlet. 
  private Thread UIThread;
  // The eSWT Display created by this MIDlet in the eSWT UI thread.
  // When this is created the MIDlet gets connected to the native UI
  // functionality and eSWT UI toolkit is initialised for it. 
  private Display display;
  // A Shell widget created by this MIDlet. 
  private Shell shell;
  // A custom color resource owned by this MIDlet. 
  private Color myColor;
  // A boolean to set when the event loop should exit. 
  private boolean exiting = false;

  public void startApp() {
    // Create the eSWT UI thread. 
    if(UIThread == null) {
      UIThread = new Thread(this);
      UIThread.start();
    }
  }

  public void pauseApp() {
    // Here we could reduce the resources but we should keep the Display 
    // instance and the eSWT UI Thread. 
  }

  // destroyApp is called when the MIDlet is terminated from the task list 
  // with the clear key, or the end key is pressed when the MIDlet is focused. 
  // It might also be called when the system needs to close applications 
  // e.g. in low memory conditions. 
  public void destroyApp(boolean unconditional) {
    // Make the event loop exit in the eSWT UI thread.
    exitEventLoop();
    // Wait for the eSWT UI thread to die. 
    try {
      UIThread.join();
    } catch(InterruptedException e) {
    }
  }

  // This method can be called from any thread to make the event loop to exit. 
  void exitEventLoop() {
    exiting = true;
    Display.getDefault().wake();
  }
  
  // The eSWT UI Thread. 
  public void run() {
    // Create the Display. 
    display = new Display();

    shell = new Shell(display);
    shell.open();

    Command exitCommand = new Command(shell, Command.EXIT, 0);
    exitCommand.setText("Exit");
    exitCommand.addSelectionListener(this);

    // Allocate some resources that we will own. 
    myColor = new Color(display, 100, 100, 0);

    // Print the hello world greeting on the Shell.
    shell.addPaintListener(this);
    shell.redraw();

    // Execute the eSWT event loop. 
    while(!exiting) {
      if(!display.readAndDispatch()) {
        display.sleep();
      }
    }
    
    // Clean up and destroy the MIDlet.
    myColor.dispose();
    display.dispose();
    notifyDestroyed();
  }

  public void widgetDefaultSelected(SelectionEvent e) {
  }

  public void widgetSelected(SelectionEvent e) {
    // Exit command selected, exit the event loop. 
    exitEventLoop();
  }

  public void paintControl(PaintEvent e) {
    // Print a hello world greeting using the custom color resource. 
    e.gc.setForeground(myColor);
    e.gc.drawText("Hello world!", 0, 0, SWT.DRAW_TRANSPARENT);
  }
}