Back to index

LispMe UI support

Please read the PalmOS documentation describing many details of the Pilot's user interface, event and resource system. This chapter shows the Scheme aspect only.

There are currently 2 ways to write programs dealing with user interaction.

Using event

The primitive procedure event gets an event from the Pilot event queue. As LispMe's own user interface normally responds to events, too, and you would only see a subset of the events, you can deactivate LispMe's UI with own-gui.

An event is represented as a list, whose first element is a symbol denoting the event type (e.g. key-down or frm-open) and whose other elements are the event parameters, different for each event type. All supported events are listed in the Catalog under the category UI event. Some PalmOS events are not translated this way, they're all represented by (#f) and should be ignored by your code.

The procedure event expects one parameter specifying whether it should wait for an event (true) or return immediately (false). In the latter case the return value is (timeout) when there's no event queued.

To avoid interference between LispMe's own event handling and your application (e.g. a pen tap in the output field would activate the output field event handling, which won't let your application see subsequent pen-moves and pen-ups), you can disable most controls and fields of LispMe's main dialog by calling (own-gui #t). In this case the fields are not drawn, too, so you won't see any output of write for example, until you enable them again by using the GUI controls menu command.

In spite of this, you would still have to use the drawing primitives to provide user feedback, so I think this approach is only feasible for very simple interactions like the ; Tic-Tac-Toe sample program.

The event handler approach

This method is much more versatile, in fact it allows interfaces to be written in Scheme which behave like other Pilot software.

To create an application this way, you need two things:

General

This part of LispMe is by no means finished. Currently, LispMe supports only the most common UI functions, but this will change in future. Please give me feedback what additional UI functions you consider indispensable! OTOH, the Pilot has very limited resources and I'm reaching its limits again and again even now, so don't be disappointed when I'm quite selective with adding new features. Currently supported UI elements are Currently not supported are tables.

Names for UI functions and events are generally chosen like the corresponding ones from the original Palm API but have been adapted to Scheme's spelling style.

Creating the resources

There are several tools to create the resource DB containing all the UI elements of your application, some running on your desktop PC, and at least one running directly on the Pilot. The type of the resource DB doesn't really matter, it shouldn't be appl or HACK to avoid listing it in the application launcher or Hackmaster. Just use Rsrc (like 'resource').

I registered the creator ids fbU0 upto fbU9, which you should use for your LispMe resources.

Using PilRC and PRCTools, a typical makefile for a resource DB looks like this:

SHELL=sh
APPID     = fbU0
APPTYPE   = Rsrc
ICONTEXT  = "demo"

demo.prc: demo.rcp
	pilrc demo.rcp .
	# Create ICON IDs 9000 and 9001 instead of 1000 ann 1001  
	mv tAIB03e9.bin tAIB2329.bin
	mv tAIB03e8.bin tAIB2328.bin
	build-prc -t $(APPTYPE) demo.prc $(ICONTEXT) $(APPID) *.bin

all:    demo.prc
Please don't use ID numbers in the range 9000-9999 in your resources, these are used by LispMe itself and a crash or strange behavior is possible in this case. IDs from 1000 to 8999 are perfectly safe.

One exception to this rule is when you want to create custom icons for the starter application. See here for details.

Opening and closing forms

Forms (the Pilot term for dialog) are handled in a stack-like fashion. Exactly one form (the top-most) is accessible by the user. To open a new form you can Calling frm-return closes the current form and re-activates the form which opened it (using frm-popup) The parameter of frm-return is passed to the continuation stored and thus it will be the return value of the frm-popup call.

You can't replace LispMe's main form by frm-goto, so the first form in your interactive LispMe program must be invoked by frm-popup. The maximum form nesting depth is 6. Have a look at this sample program.

The event handler

The event handler is an ordinary Scheme closure which is called, whenever the current form receives an event. The procedure must be callable with a variable number of arguments, where the first argument is always the symbolic event and the rest arguments the event's parameters, as the handler is applyd to the event represented as a list. So an event handler should begin like this: (lambda (event . args) ...)

An event handler should return a boolean value indicating if the event has been handled (true) or should be passed on to the next handler (false).

While the event handler is running, the Pilot won't respond to any user action (not even the off button!), so there's the danger that an infinite loop in a handler locks your Pilot and you'd have to reset it. To avoid this, there's a watchdog timer which aborts an event handler after a time interval configurable in the Preferences Dialog.

Now for the fun stuff separating Scheme from lower-level languages: Just like any other closure in Scheme, an event handler is called in the environment in effect when its lambda abstraction has been executed. Thus you can write a higher-order function returning event handlers whose state is kept in the enclosing environment and you can have several instances of the same dialog (but with different values) in an object-oriented fashion.

Or, you can concatenate several event handling procedures using higher-order combiners, e.g. to include common handling code for a particular menu into many different dialogs.

Or create powerful macros to generate event handlers...

One last warning:Don't try to call a continuation created in an event handler when the associated form has been closed already. The PalmOS forms are not part of the continuation context and won't exist anymore. Same for leaving an event handler by an outward continuation. Generally, don't jump from one event handler to another via continuations (but jumping is perfectly safe within the dynamic context of a single event handler).

Associated language elements

ctl-enter ctl-get-label ctl-get-val ctl-hit ctl-repeat ctl-select
ctl-set-label ctl-set-val error event fld-changed
fld-copy fld-cut fld-dirty? fld-enter fld-get-scroll
fld-get-text fld-paste fld-scroll fld-set-dirty fld-set-text
fld-undo frm-alert frm-close frm-get-focus frm-get-prop
frm-goto frm-help frm-open frm-popup frm-return
frm-set-focus frm-show frm-title-enter frm-title-select frm-update
key-down lst-enter lst-get-sel lst-get-text lst-select
lst-set-list lst-set-sel menu message own-gui
pen-down pen-move pen-up pop-select scl-enter
scl-exit scl-get-val scl-repeat scl-set-val timeout
wait-pen