ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


Palm Programming with Waba

by Matthew E. Ferris
04/19/2001

Last month we looked at the various options that are available to developers who want to write Palm OS applications using Java. This month we begin looking deeper into the solutions we profiled, and we begin with Waba, an open source, Java-like language. If you know Java, you know the syntax of Waba.

User Interface Controls

Let's begin with the user interface classes, since very few programs on a PDA are usable without a user interface. I'll look at data persistence next month.

Most of the classes for GUI building are contained in the waba.ui package. The inheritance hierarchy of these classes is much like Java's AWT. All of them of course extend java.lang.Object and waba.ui.Control. I would encourage you to consult the JavaDoc for the waba.ui package for particulars about the static data members and the methods for performing common tasks such like placing a control, making it visible, etc. The following classes extend the waba.ui.Control:

As the ancestor of these classes, Control contains methods for event handling and painting of controls. Let's look at an example of a simple Waba application that would prompt the user for some information; in this case, a name to lookup in a contact manager.

Palm screen shot.

The code for this class is

import waba.ui.*;

public class ContactManager extends MainWindow
{
Edit edit;
Label label;
Button button;

public ContactManager()
  {
  setTitle("Contact Manager");
  setBorderStyle(Window.RECT_BORDER);
  label = new Label("Enter name to search for:");
  label.setRect(5, 65, 110, 15);
  add(label);

  Edit edit = new Edit();
  edit.setRect(55, 80, 60, 15);
  add(edit);  

  button = new Button("Find");
  button.setRect(65, 110, 30, 15);
  add(button);
  
  }

public void onEvent(Event event)
  {
  if (event.type == ControlEvent.PRESSED)
    {
      if (event.target == button)
      {
      // lookup contact in Catalog...
      }
    }
  
  }
}

First we import the waba.ui package, since all of the user interface classes are located there. This class extends MainWindow. Every Waba application that has a user interface must extend MainWindow. Next we declare the variables we will need: an Edit, a Label, and a Button. In the constructor we call setTitle and setBorder, then initiate each of the GUI components. Notice that we also use absolute placement of the controls. This is a difference between Waba and Java. There is no concept of a layout manager. We pass in the x and y coordinates, plus the width and height of the control. The control is then dropped at that screen location.

Another nice feature of Waba is a mimic of the Palm keyboard. When you place the cursor in the Edit and tap the section of the Palm silkscreen where the ABC/123 are placed, the keyboard displays:

Palm screen shot.

Finally, the event handling occurs in the onEvent method, in a two-fold fashion. First, the event object itself is queried to determine the type of event. In this case we want to know if it's a PRESSED event. (Other types include FOCUS_IN, FOCUS_OUT, TIMER, and WINDOW_CLOSED). These are all defined in the ControlEvent class, which extends event. If the event matches the type we are looking for, then we want to determine the object that fired the event, referred to as the target. In our ContactManager application, we only want to respond to button presses. So if the user tapping the button fired the event, then we would execute the code to look up the name in the Catalog.

Other methods that are defined in the MainWindow class which could be useful are onStart and onExit. The onStart method might contain initialization code. It is called after the constructor finishes. The onExit method is called just prior to the application exiting, so any necessary cleanup such as writing unsaved data may be performed there.

Compiling the application

To compile a Waba class file into a prc file, which is executable under the Palm OS, you need to call two programs that come with Waba, warp and exegen. Both of these are found in the bin directory under the <waba_install> directory. The warp utility creates a WRP file and a PDB file. The WRP file is of no use to a Palm device, but recall that Waba also runs on Windows CE, which is what the WRP file is for. Warp will generate a default creatorID for the PDB file, but this can be overridden with the /c option, allowing you to specify a creator ID. The creator ID is a four-byte identifier that is used by the Palm OS to tie together applications and data. If you distribute an application commercially, it is a good idea to have a unique creatorID, so that your application and data do not inadvertently clash with some other application on the device. You can register a creatorID on the PalmOS web site.

Thus the following command would create a pdb file from our ContactManager class.

warp c /c cnTc ContactManager *.class

The first c tells warp to create the PDB file. The other flag is l, which will list the contents of the PDB file. The /c will set cnTc to be the creatorID associated with this PDB file. At least one byte of a creator ID must be uppercase. The next parameter is what the PDB file should be called -- in this case, ContactManager. Finally, the necessary class files should also be included in the PDB file. Our ContactManager application has only one class, so it is not important that we have specified the wildcard. However if the app had many classes, this syntax would add them all to the PDB file.

The Exegen utility is the other program that must be run against your application in order to ready it for Palm OS execution. This creates a PRC file, which will provide the Palm OS with its entry point into your application. Exegen's command line parameters look like

Exegen [options] exefile main-window-class warpfile [warpfile2...]

Thus for our ContactManager application, we would run

Exegen ContactManager ContactManager ContactManager

This would specify that the name of the PRC file should be called ContactManager, our class that extends the waba.ui.MainWindow class is called ContactManager, and the warp file, which contains our class file(s) is called ContactManager. As you see, you need to run the warp utility prior to running Exegen.

After this completes, you will then have a PDB and a PRC file, which you can alternately download to the Palm device itself, or to the Palm OS Emulator (POSE). POSE is a recommended utility for aiding the compile-edit-run cycle. It is far less trouble to run your app in the emulator than to do so in the device.

Of course before you can run this on either, you need to download the Waba VM itself. Download both the waba.prc and waba.pdb files

The other options that can be specified with Exegen are listed below:

/h Assign height of application's main window
/i Assign PalmOS PRC icon (e.g. /i sample.bmp)
/l Assign size of class heap (e.g. /l 10000)
/m Assign size of object heap (e.g. /m 20000)
/p Full path to directory containing warp file under WindowsCE
/s Assign size of stack (e.g. /s 2000)
/t Assign size of native stack (e.g. /t 50)
/w Assign width of application's main window

As you can see, there are several flags allowing you to optimize memory usage in your application. It has been my experience that some of these can make a profound difference. For example, without enough class heap size, the Keyboard will not display, but rather throws an exception.

Altering our earlier exegen command, then, we might run it as

exegen /q /i icon.bmp /t 1000 /s 2000 /m 65500 /l 40000 ContactManager

This allows us to set some memory allocations for the VM to make our class run more efficiently. It would be wise to experiment with different values here to find what is optimal for your application. This will depend on how many classes you have, and how many objects you initiate at one time. In device programming such as this, it is always a good idea to be stingy with the number of objects you create.

Other GUI classes

We have discussed some of the basic, essential classes in the waba.ui package. You can certainly guess the uses of checkboxes and radio buttons. These are standard AWT classes as well, and their functionality in Waba is no different. However, there are a couple of classes that you would not encounter in other implementations of Java for the Palm.

MessageBox is a class which opens a modal window within another window. From the name you can probably ascertain its uses. It should be noted that MessageBox is part of SuperWaba (by Guilherme Campos Hazan), mentioned in last month's article. You can also create a message box with a number of buttons on it, such as Yes/No/Cancel. The getPressedButtonIndex() will tell you which of the three buttons the user pressed.

The Tab Control allows you to add tabs to a window, thus increasing your screen real estate. For example, if we were to enhance our contact manager to be a kind of tool for sales force personnel to use in tracking prospects as well as current customers, our application might look like this:

Palm screen shot.

The code for our newly enhanced version follows:

import waba.ui.*;

public class ContactManager extends MainWindow
{
TabPanel tabpanel;
Contacts contacts;

ContactManager()
{
setTitle("ContactManager");
}
public void onStart()
{
String tabs[] = new String[]{"Contacts","Prospects"};
tabpanel = new TabPanel(tabs);
tabpanel.setRect(0, 15, this.width, this.height);
tabpanel.setGaps(2,2,2,2);
contacts = new Contacts();
contacts.setRect(10,10,160,110);
tabpanel.getPanel(0).add(contacts);
add(tabpanel);
}

public void onEvent(Event event)
{
if (event.type == ControlEvent.PRESSED && event.target == tabpanel)
{
if (tabpanel.getActiveTab() == 0)
;// save contact information
else
; // prospect information.
}
}
}

class Contacts extends Container
{
Label lblName = new Label("Name");
Edit edtName = new Edit();
Label lblAddr = new Label("Address");
Edit edtAddr = new Edit();
Label lblEmail = new Label("email");
Edit edtEmail = new Edit();
Button button = new Button ("OK");
public Contacts()
{
lblName.setRect(10,10,60,12);
edtName.setRect(10,22,90,12);
lblEmail.setRect(10,34,60,12);
edtEmail.setRect(10,46,90,12);
lblAddr.setRect(10,58,60,12);
edtAddr.setRect(10,70,90,12);
button.setRect(10,90, 30,12);

add(lblName);
add(edtName);
add(lblEmail);
add(edtEmail);
add(lblAddr);
add(edtAddr);
add(button);
}
}

Note that we have broken out some of the interface into a separate class, Contacts.java. This will be placed inside the first tab. Setting up the tab interface is fairly easy. We declare a TabPanel (again, part of SuperWaba), and set its boundaries, initiate the Contacts object and set its bounds, then add the Contacts object to the TabPanel. Finally, we add the TabPanel to the main window.

The other difference is in the event handling code. We need to determine which tab we are dealing with using the getaActiveTab() method. After that, we can proceed with the processing to add a contact or, alternately, add a prospect.

This gives us a good idea how to set up a user interface in Waba. You should also look at the API documentation for examples of those classes undiscussed in this article. For further information on Waba, please consult the following links.

Matthew E. Ferris is President, Chicagoland Java User Group, a Sun Certified Java Programmer, and a contributing Author for Professional Java Server Programming, Wrox Press.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.