Eve Application Development

Michael L Brereton - 31 December 2007, http://www.ewesoft.com/

 

Beginners Guide - Contents

<< Previous: Setting up the SDK

>> Next: Using EveMaker

Starting Your Application

Eve Application Development

Starting Your Application

The main() method

The eveMain() method

Displaying a User Interface – Forms

Form Exit Buttons

Form Validation

Form Display Options

Displaying SoftKeyBars in Forms

 

 

This chapter deals with some issues that will be important to experienced Java programmers who wish to get working on Eve as quickly as possible. Since the Eve VM can execute applications from separate class files, just like a Java VM, the use of the EveMaker Program Builder during initial program development is not necessary. EveMaker is really used for packaging your application for deployment. Hence programmers can start writing and testing programs without reading the chapter on EveMaker.

The main() method

You can start your Eve application using a static void main(String []args) method as in standard Java, however you must begin and end the method with two special function calls. GUI Applications should do this:

 

import eve.ui.Application;
import eve.ui.MessageBox;
 
public class HelloWorld {
 
     public static void main(String[] args)
     {
             Application.startApplication(args);
             new MessageBox("Hello World","This is my first message box!",
                            MessageBox.MBOK).execute();
             Application.exit(0);
     }
}
 

As you can see, the first line of the main() method should be Application.startApplication (String args[]). This starts and initializes the Eve System and GUI library. This is only necessary if you are using the main() method for starting your Eve application. It is not necessary if you are starting your Eve application by overriding the Application class or any of the other allowed starting classes. You should also use Application.exit(int code) to exit your Eve application.

 

A non-GUI, command line only application should start like this:

 

import eve.sys.Vm;
 
public class HelloWorld {
 
     public static void main(String[] args)
     {
             Vm.startEve(args);
             System.out.println("Hello World!");
             Vm.exit(0);
     }
}

 

Note that the System.out.println() method has no effect when run on a mobile system that does not support consoles (e.g. WindowCE/PocketPC).

 

Also, avoid using System.exit(), System.loadLibrary() and System.getProperty() - they will fail when running as an Applet. Instead use Application.exit() or Vm.exit(), Vm.loadLibrary() and Vm.getProperty().

The eveMain() method

 

This is a special optional method very similar to the main() method and has the same form:

 

public static void eveMain(String[] args);

 

This method is called before main() is called and can be used to customize the behavior of the VM before it creates the Application’s default main window. The first window created by the VM becomes the Application’s main window and if one is not created within eveMain() then the VM creates a default window that is appropriate for the current platform. In eveMain() you are given a chance to explicitly create the window yourself thereby achieving behavior that may be required by your particular Application.

Displaying a User Interface – Forms

Like most GUI systems, Eve UI elements consist of Control objects placed within Container objects (which are themselves types of Control objects) to form a tree of displayable Controls. In order for the Controls to be displayed, the top-level Container must be placed in a Frame which must be then placed in a Window. While this is a fairly complicated process, you will most likely never have to do it. Instead you would have a Form as your top level Control.

 

A Form “knows” how to place itself correctly in a Frame and then how to display that Frame within a Window (and whether or not a new Window should be opened or whether an existing Window should be used instead). You would simply call one of the show() or execute() methods of the Form to display the Form on the screen. All options regarding the Frame and Window used by the Form (e.g. if the created Window should be maximized) are set using the Form itself.

 

After the Form is displayed it receives UI events (user input, repainting and resizing) from its containing Window. Each Window has its own Event Thread which is used to receive native UI events from the underlying OS and then convert them to Eve events which are sent to the correct Control objects within the Window. When writing Event Handlers (covered in a later chapter) you must be careful not to block the Thread that called the Event Handler for any significant amount of time, as this will block the Window from receiving UI Events and make the application unresponsive. The only exception to this is the execute() method, which is explained below.

 

In the first example above we did this:

 

     new MessageBox("Hello World","This is my first message box!",
                     MessageBox.MBOK).execute();

 

A MessageBox is a type of Form and you can see that we used the execute() method which displays it modally and then waits for it to close. There are three ways of displaying a Form:

 

1.      execute() – which displays a Form modally and waits for the Form to close (via the exit(int exitCode)) method. When a Form is opened modally it blocks user input to other Forms until it closes or until another Form is also opened modally.

2.      exec() – which displays a Form modally but returns immediately. You can call waitUntilClosed() at any time after to wait until the Form has been closed and to get the exitCode value.

3.      show() – which displays a Form non-modally and returns immediately.

Note that execute() and exec() will create a new Event Thread to handle UI events for the current Window, so that even though waitUntilClosed() blocks the current Thread (which may have been the original Event Thread) the original Window will still receive UI events because of the newly created Event Thread. This is why it is safe to call execute() at any time, including within an Event Handler.

 

You can specify that you wish the Form to be displayed within an existing Window instead of in a new Window by using execute(Frame parent) or show(Frame parent). To get the containing Frame for any Control call getFrame() on the Control.

Form Exit Buttons

Here is an example of a Form that we add a Panel to containing a number of Controls. The addNext(), addLast() and other methods will be explained in the next Chapter.

 

package evesamples.ui;
import eve.fx.Insets;
import eve.fx.gui.WindowConstants;
import eve.ui.Button;
import eve.ui.Form;
import eve.ui.Panel;
import eve.ui.Gui;
 
//##################################################################
public class TestForm extends Form{
//##################################################################
 
//===================================================================
public TestForm()
//===================================================================
{
             title = "Testing Panel";
             Panel p = new Panel();
             p.setText("Testing the panel");
             p.addNext(new Button("Hello"));
             p.addLast(new Button("There!"));
             p.addNext(new Button("How"));
             p.addLast(new Button("are you?"));
             addLast(p);
 
             doButtons(OKB|DEFCANCELB);
}
 
//##################################################################
}
//##################################################################

 

Note that there is no main() method in this class. Because it inherits from Form the VM will automatically create it using the public default constructor and then call execute() on it. When the Form exits the application will automatically exit as well. We can therefore run this by doing:

eve evesamples.ui.TestForm

 

or:

 

            java -cp eve.jar;./ Eve evesamples.ui.TestForm

 

The doButtons(int buttons) method is a quick way of adding buttons to the bottom of a Form. The values you can use here are:

 

OKB – the OK button.

CANCELB – the Cancel button.

DEFOKB – the OK Button where Enter is the hotkey for the button.

DEFCANCELB – the Cancel button where Esc (or Cancel on a mobile device) is the hotkey for the button.

YESB – the Yes button.

NOB – the No button.

 

Pressing these buttons results in a call to exit() with the following constant int values:

 

IDOK – the OK button was pressed.

IDCANCEL – a Cancel button was pressed.

IDYES – (same as IDOK) the Yes button was pressed.

IDNO – the No button was pressed.

 

If the user presses the ‘X’ button for the Window then exit() is called with a value of IDCANCEL.

Form Validation

It is possible to validate a Form before exiting (and possibly aborting the exit) by overriding the boolean canExit(int exitCode) method. For example if we add this method to the Form above:

 

//===================================================================
protected boolean canExit(int exitCode)
//===================================================================
{
             if (exitCode != IDCANCEL){
                     Gui.flashMessage("Please cancel!",this);
                     return false;
             }
             return true;
}

 

Run this new code and the Form will not exit unless the Cancel or ‘X’ button is pressed. The Gui.flashMessage(String message, Control parent) is a convenient way of flashing a simple message to the user – particularly appropriate for mobile devices.

 

Form Display Options

The main way of controlling how a Form is displayed is by adjusting the windowFlagsToSet and windowFlagsToClear fields of the Form. Normally a new Window is displayed in a way that is consistent with the underlying OS – however you can explicitly turn on or off certain Window properties by setting bits in either or both of these two fields.

 

The bit values to use should be any of the eve.fx.gui.WindowConstants.FLAG_XXX  values (see the API). For example if we modify the constructor by adding the following two lines:

 

             
             doButtons(OKB|CANCELB);
             windowFlagsToSet |= WindowConstants.FLAG_MAXIMIZE;
             windowFlagsToClear |= WindowConstants.FLAG_HAS_CLOSE_BUTTON;
}

 

If you run this using the native Eve VM – the Form will be maximized on the screen (since we set the FLAG_MAXIMIZE bit) and will not display an ‘X’ button (since we clear the FLAG_HAS_CLOSE_BUTTON bit). However under Java the ‘X’ button is still displayed since there does not seem to be any way to remove it under Java.

 

The title of a Form can be set and the Window title will normally be set to this value when the Form is displayed. There is also a windowTitle for a Form. If this is not null it will override the title field and it will be used for the Window title instead. However if windowTitle has the special constant value WINDOW_TITLE_DONT_CHANGE then the Window will not have its title changed by the display of the Form.

 

The windowIcon can be set for a Form to be an ImageData object (explained later) or a DeviceIcon (a better choice) created by eve.sys.Device.createIcon().

 

Some other options for a Form include (their names explain their purpose):

 

public boolean inheritSoftKeys = false;
public boolean resizable = !Gui.isPDA;
public boolean moveable = !Gui.isPDA;
public boolean hasTitle = true;
public boolean resizeOnSIP = false;
public boolean keepFrame = true;
public boolean noBorder = Gui.hasSoftKeys;
public boolean hasTopBar = !Gui.hasSoftKeys;
public boolean exitSystemOnClose = false;

 

Displaying SoftKeyBars in Forms

SoftKeys refer to the two Button/Menus that appear at the bottom of Windows Mobile 5/6 devices and other mobile devices.  This is the preferred method for selection options and actions for modern mobile devices. The Eve UI library fully supports the use of SoftKey bars in any number of configurations and SoftKeyBar setup and event handling should normally be done in your application Forms.

 

The image below shows the Eve Launcher running simulating a Windows Mobile 5 device. The SoftKeyBar displayed for the active Form has a menu assigned to the first key (on the left) and a single button (Exit) assigned to the right.

 

 

When you create a Form you should determine what type of SoftKeyBar (if any) is available on the system using: SoftKeyBar.getType(). This returns:

o       TYPE_NONE – for no SoftKeyBar support.

o       TYPE_SINGLE – for a SoftKeyBar with only one button/menu item.

o       TYPE_DOUBLE – for a SoftKeyBar with two buttons/menu items (the maximum supported by Eve).

o       TYPE_MENU – for a SoftKeyBar with only one item that must be a menu and which may be hidden until the user presses the special “Menu” key  (e.g. on Android)

 

Once you determine the type and number of keys you can begin setting up the SoftKeyBar for your Form. You do this by creating a new SoftKeyBar object and then setting the one or two keys for the bar using one of the setKey() methods. Then you assign the created SoftKeyBar to the Form using the Form.setSoftKeyBarFor() method.

 

Forms actually allow you to specify different SoftKeyBars for different Controls on the Form depending on which Control has the keyboard focus. The Form method:

 

public void setSoftKeyBarFor(Control c, SoftKeyBar bar)

 

Will set up the Form such that when the specified Control has the focus the assigned SoftKeyBar will be displayed. If the c parameter is null, then this will be the default SoftKeyBar for the Form and is displayed for all Controls which do not have a specific SoftKeyBar assigned to them. The method below is used to assign a SoftKeyBar to a number of Controls in a Vector.

 

public void setSoftKeyBarForAll(Vector controls, SoftKeyBar bar)

 

The simplest way to handle SoftKey commands is to assign an Action to each Button or MenuItem used within a SoftKeyBar. When the Button is pressed or when the MenuItem is selected the handleAction(String action) method of the Form will be called. Note that MenuItems and Buttons have an individual field called action. If this field is not set the default behaviour is for the normal text for the Button or MenuItem to be used as the action.

 

To summarize, to correctly use the SoftKeyBar in a Form you should follow these steps:

1.      Determine how many keys, if any, are available on the current platform.

2.      Create Menus and/or Buttons for assignments to the SoftKeys.

3.      Create a SoftKeyBar and assign the created Menus and Buttons to the keys.

4.      Assign the SoftKeyBar to the Form.

5.      If there are different Menus/Button combinations for different active Controls in the Form, then create SoftKeyBars for the different Controls as necessary.

6.      Override the handleAction() method to handle the user selection of the SoftKeyBar Menus and Buttons.

 

There is also a special method call: Gui.simulateSoftKeysOnPDA(int softKeyBarType). This method will ensure that, if run on a PDA (or a simulated PDA – a device with a touch screen, no mouse pointer and no keyboard) which does not normally use SoftKey bars (e.g. PocketPC 200x) the Eve library will run as if the system did in fact have a SoftKey bar. This is useful when writing software targeting Windows Mobile 5/6 devices but which may also be run on a PocketPC or other PDA which does not normally have native SoftKey bars. The Eve VM Launcher uses this method so that its interface on a PocketPC is exactly the same as on Windows Mobile devices.

 

This method, if used, must be called in the eveMain() method so as to have effect before any native windows are created.

 

All these concepts are shown in the example shown below:

 

package evesamples.ui;
 
import eve.ui.Application;
import eve.ui.Button;
import eve.ui.Control;
import eve.ui.Form;
import eve.ui.Gui;
import eve.ui.Input;
import eve.ui.InputStack;
import eve.ui.Menu;
import eve.ui.MenuItem;
import eve.ui.SoftKeyBar;
 
public class SoftKeyDemo extends Form{
 
     Input myInput, secondInput;
     public SoftKeyDemo()
     {
             title = "SoftKeyBar Demo";
             maximizeOnPDA();
             InputStack is = new InputStack();
             myInput = is.addInput("Input:","");
             secondInput = is.addInput("Another:","");
             addLast(is).setCell(HSTRETCH);
             addLast(new Button("Hello Button")).setCell(HSTRETCH);
             //
             Button b = new Button("Exit Now","eve/exitsmall.png");
             b.action = "exit_action";
             //
             if (SoftKeyBar.getType() != SoftKeyBar.TYPE_NONE){
                     //
                     if (true){
                            //
                            // Create a bar that is different for the inputs.
                            //
                            SoftKeyBar sk = new SoftKeyBar();
                            Menu left = new Menu();
                            //
                            // Make a menu with three items.
                            //
                            Menu fixedText = new Menu(new String[]{"One","Two","Three"},"Fixed Text");
                            left.addItem(fixedText);
                            left.addItem(new MenuItem("Clear","clear_action"));
                            if (SoftKeyBar.numberOfKeys() == 1){
                                    left.addItem("-");
                                    left.addItem(sk.createMenuItem(b));
                            }else{
                                    sk.setKey(2,b);
                            }
                            sk.setKey(1, "Actions", left);
                            setSoftKeyBarFor(myInput, sk);
                            setSoftKeyBarFor(secondInput, sk);
                     }
                     if (true){
                            //
                            //Create a default bar for all other controls.
                            //
                            SoftKeyBar sk = new SoftKeyBar();
                            sk.setKey(SoftKeyBar.numberOfKeys(),b);
                            setSoftKeyBarFor(null, sk);
                     }
             }else{
                     addButton(b);
             }
     }
     public static void eveMain(String[] args)
     {
             //
             // Try using these other values: TYPE_SINGLE, TYPE_MENU
             //
             Gui.simulateSoftkeysOnPDA(SoftKeyBar.TYPE_DOUBLE);
     }
     public boolean handleAction(String action)
     {
             Control c = Gui.focusedControl();
             if (action.equals("clear_action")){
                     if (c != null) c.setText("");
                     return true;
             }else if (action.equals("exit_action")){
                     exit(IDOK);
                     return true;
             }else{
                     if (c != null) c.setText(action);
                     return true;
             }
     }
     public static void main(String[] args)
     {
             Application.startApplication(args);
             new SoftKeyDemo().execute();
             Application.exit(0);
     }
}

 

Here is how it looks when run as a PDA. The left image is what is displayed when one of the inputs has the focus, the center image is what is displayed when the user selects the “Actions” SoftKey and the right image is what is displayed when none of the inputs have the focus.

 

       eve /p5 evesamples.ui.SoftKeyDemo

 

              

 

and here is how it looks when run as a normal desktop application:

 

       eve evesamples.ui.SoftKeyDemo

 

 

You will note that in the line:

 

     Menu fixedText = new Menu(new String[]{"One","Two","Three"},"Fixed Text");

 

I created a Menu from an array of Strings. This creation method does not allow me to specify at that time what the action String should be. I could have instead created an empty Menu and then added MenuItems to it instead. When creating the individual MenuItem objects I can specify what the action for each item should be. There is also a convenience SoftKeyBar method called createMenuItem(String label, String action, Iimage icon) that can be used to create a new MenuItem for adding to a Menu that will be set to a SoftKeyBar.