Académique Documents
Professionnel Documents
Culture Documents
Version 1.54
SuperWaba Companion
Table of Contents
PART I THE PLATFORM..................................................................................................8
Overview..............................................................................................................................9
Chapter 1 - Welcome.........................................................................................................10
Current Symbian Limitations...........................................................................................13
Chapter 2 - Installation Instructions...................................................................................14
Palm OS.........................................................................................................................14
Windows CE...................................................................................................................15
Symbian OS....................................................................................................................16
Windows 98 and beyond................................................................................................17
Linux...............................................................................................................................18
Running as Applet..........................................................................................................19
Running as Application...................................................................................................19
Chapter 3 - Running the Samples......................................................................................21
Using ANT......................................................................................................................21
Troubleshooting..............................................................................................................21
Chapter 4 - Warp and Exegen Deploying the application...............................................23
Warp Instructions...........................................................................................................23
Exegen Instructions........................................................................................................25
RenameFont Instructions................................................................................................28
Wxgn Instructions...........................................................................................................28
Chapter 5 - Configuring build.xml to use in your own projects...........................................29
Chapter 6 - Configuring IDEs to Debug and Run SuperWaba Programs..........................30
NetBeans or Forte..........................................................................................................30
JBuilder 6 Personal and Pro...........................................................................................31
Visual Cafe (3.1).............................................................................................................32
Linux ..............................................................................................................................32
Eclipse 2.1 and 3.0.........................................................................................................34
Microsoft Visual J++.......................................................................................................35
General Settings.............................................................................................................35
Optional arguments to waba.applet.Applet ....................................................................36
Chapter 7 - Unicode Support.............................................................................................37
Part II USER INTERFACE...............................................................................................39
Overview............................................................................................................................40
Chapter 8 Types of User Interface..................................................................................42
Chapter 9 The MainWindow class..................................................................................44
Chapter 10 Adding Controls............................................................................................46
Chapter 11 Events...........................................................................................................51
Chapter 12 Basic Controls..............................................................................................55
waba.ui.Button................................................................................................................55
waba.ui.Check................................................................................................................57
waba.ui.ComboBox.........................................................................................................58
waba.ui.Edit....................................................................................................................60
waba.ui.Label.................................................................................................................63
waba.ui.ListBox...............................................................................................................64
waba.ui.PopList..............................................................................................................66
waba.ui.ProgressBar......................................................................................................68
waba.ui.Radio.................................................................................................................68
SuperWaba Companion
waba.ui.ScrollBar............................................................................................................70
Chapter 13 - Advanced Controls........................................................................................73
waba.ui.MenuBar and waba.ui.PopupMenu...................................................................73
waba.ui.PushButtonGroup..............................................................................................76
waba.ui.TabPanel...........................................................................................................78
waba.ui.MessageBox......................................................................................................81
waba.ui.InputDialog........................................................................................................83
waba.ui.Grid...................................................................................................................84
Chapter 14 The Window class........................................................................................86
Chapter 15 Utility Classes...............................................................................................91
waba.ui.Calculator..........................................................................................................91
waba.ui.Calendar............................................................................................................92
waba.ui.Keyboard...........................................................................................................93
Chapter 16 Splitting your application's logic using waba.ui.Container...........................94
PART III INPUT & OUTPUT............................................................................................97
Overview............................................................................................................................98
Chapter 17 - waba.io.Stream.............................................................................................99
Chapter 18 - waba.io.Catalog..........................................................................................100
Useful tips.....................................................................................................................102
addRecord....................................................................................................................103
addRecord....................................................................................................................103
close.............................................................................................................................104
delete............................................................................................................................105
listCatalogs...................................................................................................................105
getRecordCount...........................................................................................................106
isOpen..........................................................................................................................106
rename..........................................................................................................................106
setRecordPos...............................................................................................................107
inspectRecord...............................................................................................................107
getAttributes.................................................................................................................108
setAttributes..................................................................................................................109
getRecordPos...............................................................................................................109
getRecordSize..............................................................................................................110
resizeRecord................................................................................................................110
deleteRecord................................................................................................................111
readBytes......................................................................................................................111
writeBytes.....................................................................................................................112
skipBytes......................................................................................................................113
getRecordOffset...........................................................................................................113
getRecordAttributes......................................................................................................114
setRecordAttributes......................................................................................................114
setRecordOffset............................................................................................................115
getName.......................................................................................................................115
Chapter 19 - waba.io.DataStream....................................................................................116
DataStream Constructor...............................................................................................118
close.............................................................................................................................118
pad................................................................................................................................119
skip...............................................................................................................................119
readBoolean.................................................................................................................120
readByte.......................................................................................................................120
SuperWaba Companion
readBytes......................................................................................................................120
readBytes......................................................................................................................121
readFloat......................................................................................................................121
readIntLE......................................................................................................................121
readShortLE..................................................................................................................122
readInt..........................................................................................................................122
readShort......................................................................................................................122
readDouble...................................................................................................................123
readLong......................................................................................................................123
readUnsignedByte........................................................................................................123
readUnsignedShort.......................................................................................................123
writeIntLE......................................................................................................................124
writeShortLE.................................................................................................................124
writeBoolean.................................................................................................................125
writeByte.......................................................................................................................125
writeByte.......................................................................................................................126
writeBytes.....................................................................................................................126
writeBytes.....................................................................................................................127
writeFloat......................................................................................................................127
writeInt..........................................................................................................................128
writeShort......................................................................................................................128
writeDouble...................................................................................................................129
writeLong......................................................................................................................129
readString.....................................................................................................................129
readStringArray............................................................................................................130
writeString.....................................................................................................................130
writeStringArray............................................................................................................131
readCString..................................................................................................................131
writeCString..................................................................................................................132
Chapter 20 - waba.io.ResizeStream................................................................................133
startRecord...................................................................................................................134
startRecord...................................................................................................................134
restartRecord................................................................................................................134
endRecord....................................................................................................................135
readBytes......................................................................................................................135
writeBytes.....................................................................................................................136
close.............................................................................................................................136
Chapter 21 - waba.io.ByteArrayStream............................................................................138
close.............................................................................................................................139
getBuffer.......................................................................................................................139
count.............................................................................................................................139
readBytes......................................................................................................................140
reset..............................................................................................................................140
skipBytes......................................................................................................................141
reuse.............................................................................................................................141
writeBytes.....................................................................................................................141
available.......................................................................................................................142
Chapter 22 - Dealing with large databases......................................................................143
Chapter 23 waba.io.Socket...........................................................................................145
close.............................................................................................................................146
SuperWaba Companion
isOpen..........................................................................................................................146
setReadTimeout...........................................................................................................146
readBytes......................................................................................................................146
writeBytes.....................................................................................................................147
disconnect....................................................................................................................147
refreshBeforeEachRead...............................................................................................147
lastError........................................................................................................................147
Configuring...................................................................................................................150
Testing..........................................................................................................................151
Chapter 24 waba.io.SerialPort......................................................................................153
close.............................................................................................................................153
isOpen..........................................................................................................................154
setFlowControl..............................................................................................................154
setReadTimeout...........................................................................................................154
readBytes......................................................................................................................154
writeBytes.....................................................................................................................154
readCheck....................................................................................................................155
lastError........................................................................................................................155
Configuration................................................................................................................155
Testing..........................................................................................................................156
SerialPDB..................................................................................................................157
SerialSocket..............................................................................................................158
Chapter 25 waba.io.File................................................................................................160
isAvailable....................................................................................................................160
close.............................................................................................................................161
createDir.......................................................................................................................161
delete............................................................................................................................161
exists.............................................................................................................................161
getSize..........................................................................................................................162
getPath.........................................................................................................................162
isDir..............................................................................................................................162
isOpen..........................................................................................................................162
listFiles.........................................................................................................................163
readBytes......................................................................................................................163
writeBytes.....................................................................................................................164
rename..........................................................................................................................164
setPos...........................................................................................................................165
setAttributes..................................................................................................................165
getAttributes.................................................................................................................166
setTime.........................................................................................................................166
getTime.........................................................................................................................167
getCardVolume.............................................................................................................167
lastError........................................................................................................................167
PART IV EXTENSION LIBRARIES...............................................................................169
Chapter 26 Scanner Library..........................................................................................170
Chapter 27 Printer Library.............................................................................................171
OVERVIEW..................................................................................................................171
Troubleshooting............................................................................................................171
Chapter 28 Catalog Search Library...............................................................................174
OVERVIEW..................................................................................................................174
SuperWaba Companion
Sample .........................................................................................................................174
Chapter 29 Image Library.............................................................................................176
OVERVIEW..................................................................................................................176
Jpeg Error list...............................................................................................................177
Chapter 30 ZLib Native Compression...........................................................................180
OVERVIEW..................................................................................................................180
Sample..........................................................................................................................180
Chapter 31 Conduit Synchronization............................................................................183
OVERVIEW..................................................................................................................183
Conduit class................................................................................................................183
RemoteCatalog class....................................................................................................185
RemoteCatalogRecord class........................................................................................186
RemoteFile...................................................................................................................187
Conduit Registration.....................................................................................................187
Important Tips...............................................................................................................188
Sample for reading.......................................................................................................190
Sample for writing.........................................................................................................191
Sample for RemoteFile.................................................................................................192
PART V NATIVE LIBRARIES........................................................................................193
Overview..........................................................................................................................194
Chapter 33 The Java Library.........................................................................................195
Chapter 34 The Native Library......................................................................................200
Chapter 35 Java Library Generation.............................................................................211
SuperWaba Global Extension Library..........................................................................211
SuperWaba Local Extension Library............................................................................211
Chapter 36 Configuration of the Project file for CodeWarrior.......................................213
Chapter 37 Configuration of the Project file for eVC 3.0...............................................218
Chapter 38 Configuration of the Project file for VC 7....................................................220
Chapter 39 Native libraries for Linux/PalmOS using gcc..............................................221
Build setup....................................................................................................................221
Build configuration........................................................................................................226
Build..............................................................................................................................226
Platform build environment requirements.....................................................................227
Common requirements..............................................................................................227
Linux target requirements.........................................................................................227
PalmOS/m68k target requirements...........................................................................227
PalmOS5/ARM target requirements..........................................................................227
PalmOS5/ARM VMware based development environment.......................................228
Chapter 40 Native libraries for Symbian OS.................................................................231
Introduction...................................................................................................................231
Official recommended implementation.........................................................................231
Symbian OS globals hack (unofficial)...........................................................................235
Chapter 41 How to use the Libraries.............................................................................237
Chapter 42 Web Services.............................................................................................238
Introduction...................................................................................................................238
Preparing the server.....................................................................................................238
Running the test...........................................................................................................239
Creating and Deploying your Web Service..................................................................241
Using your Web Service...............................................................................................241
Understanding the SOAP request................................................................................243
SuperWaba Companion
SuperWaba Companion
SuperWaba Companion
Overview
Welcome to SuperWaba. This tutorial combines the SuperWaba introduction with
the old User Interface, Input/Output, Library and Optimization Tricks tutorials, plus the
Printer Library, CatalogSearch Library and the Image Library tutorials. It will be extended
to include the other packages as well. The Game tutorial was left standalone because it is
also released in the GPL version of the SuperWaba SDK.
This tutorial assumes that you know how to write Java programs. If not, I suggest
that you take a basic course in Java at
http://java.sun.com/docs/books/tutorial/java/index.html
Some conventions used in this tutorial:
Please read the Copyright terms in appendix II. By reading this book, you're
agreeing with them.
SuperWaba Companion
10
Chapter 1 - Welcome
Thank you for your interest in SuperWaba. If you don't know where to start, here are
some tips:
1. SuperWaba is not Java. Although it is 99% compatible with the Java language (the
only bytecode that is not implemented is synchronized), it cannot be called a Java VM
due to copyright restrictions. To use SuperWaba, you will have to forget the JDK API and
use the SuperWaba provided API (just like you would if using J2ME). Make a good read
of the API javadocs: they will show you the library differences between JDK and
SuperWaba APIs.
2. SuperWaba can run in four locations:
1. On the PDA (currently in Palm OS from 3.0 up, most Windows CE models, and most
Symbian OS phones), using a proprietary bytecode interpreter,
2. On the desktop, using the Sun JDK
3. On the desktop, using a Java-enabled browser
4. On the desktop, standalone, using the proprietary bytecode interpreter compiled for
the Windows platform (Windows 98 or beyond) and Linux.
2a. PALM OS: The VM part that needs to be installed in the Palm OS device consists of at
least three files:
SuperWaba.pdb: contains the classes available in the following packages: waba.fx,
waba.ui, waba.io, waba.sys, waba.lang, waba.util (these classes are located under
SuperwabaSDK/src/java/waba/*).
SuperWaba.prc: contains the bytecode interpreter, the class loader and the garbage
collector.
SWNatives.prc: contains the implementation for the native methods (E.G.:
Graphics.drawLine)
2b. WINDOWS CE: The VM components that must be installed in the Windows
CE/Pocket PC are:
SuperWaba.pdb: performs the same function as its Palm OS counterpart named above
SuperWaba.exe: the counterpart of the SuperWaba.prc and SWNatives.prc files used
by Palm OS.
SDL.dll, SDL_net.dll: these are the runtime engines for the Simple Direct-media Layer
library. This library enables SuperWaba to use open-gl under Windows CE, boosting
the graphics performance.
MSW.pdb: contains font files required by SuperWaba
2c. UIQ/SYMBIAN OS 7: SuperWaba's VM components must be installed using the
uiq/SuperWaba.sis file. This file contains:
SuperWaba.pdb: the counterpart of the Palm OS file with the same name
SuperWaba.app: the counterpart of the Palm OS files SuperWaba.prc and
SWNatives.prc
MSW.pdb: contains font files required by SuperWaba
SuperWaba Companion
11
When you create a SuperWaba application (Hello.java), you must compile it using JDK,
and you'll get a classfile (Hello.class). Then, you must run the superwaba.tools.Warp
tool, which will package Hello.class with all other classes and resources it references
SuperWaba Companion
12
(supported extensions are .class, .wav, .bmp, .gif, .jpeg, jpg, .png, .txt) into the file
Hello.pdb. You can see the Hello.pdb file as something similar to a JAR file.
The device does not recognize a pdb file, so you must also have a launcher. The
launcher depends on the platform (prc for Palm OS, exe/lnk files for Windows CE, and
app for Symbian). It will contain application's icon and its version, among other
information. To create the launcher, you use superwaba.tools.Exegen. Exegen also
creates installation files so you can easily install the application in Windows CE (cab),
Symbian (sis) and Palm OS (install.exe).
4. There are some examples in the SuperwabaSDK/src/java/superwaba/samples
directories. These samples use almost all the SuperWaba class library, so it is a good
source of information from where you can start your applications.
5. Currently there are no User Interface creators for SuperWaba. Perhaps, there is a
great standalone tool that lets you create user interfaces. You can even use it in your
device. See superwaba.samples.app.guiBuilder. It generates the code necessary to run
the application, which can be exported to the desktop to be compiled.
6. If you have questions, point your newsgroup reader to
news://news.superwaba.net/pilot.programmer.waba and ask questions there. But,
PLEASE, download all messages first and do a search on them. Your question may have
already been answered, and you'll save your time and the time of people at the
newsgroup. Make sure you have downloaded all messages: there are more than 25000. If
you're having problems, download the Mozilla Thunderbird e-mail client from
www.mozilla.org).
Note: there's a mirror of the newsgroup in
http://groups.google.com/groups?group=pilot.programmer.waba. Don't post messages
to it! It does not reflect the actual server (news.superwaba.net), but the old one
(news.falch.net).
7. A Professional package subscription includes 3 support incidents. Please read the email you received after you subscribed for more information on how to post questions.
8. When running your application on POSE, don't forget to turn off some settings in
"Settings/Debugging":
Hardware Register Access
Proscribed Function Call
Screen Access
Although emulators for Windows CE exist, we do not provide a special SuperWaba.exe
file to run on them because they are very poor. Better use the standalone Windows
(Win32) version of SuperWaba.exe produces better results.
9. DON'T use the Jikes compiler with SuperWaba.
10. Be sure to read the FAQ and the WIKI at the SuperWaba site, and check the API
javadocs at SuperWabaSDK/docs/html/index.html
SuperWaba Companion
13
SuperWaba Companion
14
Palm OS
You can use the installation files for Palm OS located in bin/installers/vm/palm,
otherwise you can manually install the following files in your device, depending on your
Palm OS version / model:
For Palm OS >= 5 devices if the libraries DB2e, IrPrint or PrintBoy are not used by your
program, you can install the new ARM VM, which is up to 20 times faster than the 68k
ones. The files are located in folder palm/arm/PalmOS5. These three libraries are
NOT PORTED to Palm OS 5 ARM.
For Palm OS >= 5 and Palm OS 4.1 16 bpp devices that can't emulate 8bpp (including
Tungsten W and Kyocera 7135) Files located in folder
palm/68k/PalmOS5_or_4_with_16bits_screen
SuperWaba.prc (VM)
SWNatives.prc (native methods)
Zire 71 and other Palm OS 5 devices that continuously reset Files located in folder
palm/68k/PalmOS5_AvoidAutoReset
SuperWaba.prc (VM)
SWNatives.prc (native methods)
2. When installing a SuperWaba program on Palm OS, be sure to install both prc and pdb
files generated. You can create an install.exe file to make the install easier. See Exegen's
/inst parameter.
3. If you're using files from the superwaba.ext package, install the corresponding library
file (located in xplat crossplatform folder). Some samples also need an extension
library to run. Check the corresponding chapter in this document.
4. When creating your own programs, be sure to use the same Creator ID in both
EXEGEN and WARP (or just use the default one). Otherwise, the program won't run.
SuperWaba Companion
15
Windows CE
Windows CE files can be easily installed using cab files. So, To install the SuperWaba
VM on your device, run the SuperWabaSDK/bin/installers/vm/ce/ CEinstall_RunMe.bat
file.
Note: Intermec Norand 600 series PDAs require manual installation of the SuperWaba
VM. Use the VM located in folder SuperWabaSDK/lib/vm/ce/PPC211/x86.
Sometimes the cab installer does not work and you will have to install the files manually.
This often occurs on new devices. If this is your case, follow the instructions below:
1. Install these files in your WINDOWS CE device under a newly created /SuperWaba
folder (from the root).
SuperWaba.exe (VM) ***
SDL.dll and SDL_net.dll (Simple Direct-media Layer runtimes)
SuperWaba.pdb (API Classes)
MSW.pdb (Font file)
2. *** Windows CE has more than 10 possible choices of the SuperWaba.exe/SDL*.dll
files that must be installed. These choices are the combination between the target
platform and the processor type.
The possible targets are: HPC2000, HPC211, PocketPC, PPC211 (PocketPC also
runs on .NET)
The possible processors are: ARM, SH3 and MIPS
You must choose the right SuperWaba.exe file located under the
SuperWabaSDK/lib/vm/ce directories. If you install the wrong file, you will simply get an
error message from the operating system. The most used VM is PocketPC/ARM.
3. File SuperWaba.pdb is located in folder xplat. File MSW.pdb is located in folder fonts.
4. When installing a SuperWaba program, be sure to install both EXE and PDB files
generated with Exegen and Warp. The EXE file must be installed in the Start Menu,
ideally under a folder called SuperWaba, along with other SuperWaba programs.
5. The PDB file must be installed in a directory specific for your program. You cannot
install it in the /SuperWaba directory. The directory is specified when running the
EXEGEN program and has, by default, the same name of your Main class.
6. If you're using classes from the ext package, install the corresponding library file
(located in folders xplat and ce). Some samples also need an extension library to run.
6a. SuperWaba global libraries must be installed in the /SuperWaba directory.
6b. SuperWaba local libraries must be installed in the application's directory.
SuperWaba Companion
16
7. You can also install optional fonts. Remember, all fonts must be placed under the
/SuperWaba directory.
8. When creating your own programs, be sure to use the same Creator ID in both
EXEGEN and WARP (or just use the default one).
9. If you don't follow all these 8 rules above, your program will not run.
10. To run the welcome application on Windows CE, click in the SuperWaba.exe file
using the File Explorer or create a SuperWaba.lnk file with the following line, installing it
in the Start Menu:
24#\SuperWaba\SuperWaba.exe
11. The picture below shows a sample of directory organization (sdl.dll and sdl_net.dll are
missing from the picture):
12. It is possible to install the VM and the files in a different directory instead of
/SuperWaba. To do this, you must install the VM using the cab files and select a directory
other than the default (a registry key will store the directory you choosen, and the vm will
run) or, if you can't use the cab files (new devices may not be recognized by the cab files),
you must install SuperWaba manually and create the following registry key:
Class: HKEY_LOCAL_MACHINE
Hierarchy: SOFTWARE\\Apps\\SuperWaba VM"
Name: "InstallDir"
Type: REG_SZ
And then specify, in the Data, the directory where you had installed the VM.
Symbian OS
SuperWaba Companion
17
This is the easiest one to install: the only way to install is using a SIS (Symbian
Installation System) file. To create it, you must pass the /sis parameter to Exegen. Then
Exegen will create the file and a double-click installs on the device.
You have to install the VM and the programs in the same drive (memory card is safer).
SuperWaba Companion
18
Linux
Install the SuperWaba package corresponding to your Linux distribution. Currently, two
package formats are provided:
To install on Redhat 9.0 or newer, run your preferred package manager and install the
bin/installers/vm/linux/superwaba-5.0.0-2.i386.rpm file. If you prefer command line, log
in as root, and run the following command:
rpm -Uvh bin/installers/vm/linux/superwaba-x.y.z-n.i386.rpm
To install on Debian, run your preferred package manager and install the
bin/installers/vm/linux/superwaba-5.0.0-3.i386.deb file. If you prefer command line, log
in as root, and run the following command:
dpkg -i bin/installers/vm/linux/superwaba-x.y.z-n.i386.deb
Both packages install a minimal SuperWaba runtime environment at the following prefix
/usr/local. The bin subfolder contains a helper script named superwaba to run the VM
and the lib/superwaba subfolder contains the required runtime files.
Insofar /usr/local/bin should be in your PATH environment variable, you should now be
able to run the VM, by just entering superwaba on the command line.
To display the list of supported options, run superwaba help.
SuperWaba Companion
19
To execute an application, you need its pdb file and its creator ID, you also have to know
the application mainclass (the class inheriting from the Waba MainWindow class).
NOTE: If you don't know an application creator ID, you may list the pdb content with Warp
which displays the creator field you have to provide to identify the pdb file to launch the
application.
The command line to run an application is:
superwaba [options] <class-name> <class-path> <creator-id>
...where <class-name> is the class name with it's package name with / (not .) as
package separator and without the trailing .class, <class-path> is the absolute path of
the directory containg the application pdb file, and the <creator-id> the PalmOS crid.
for instance to run the Ping game, enter:
superwaba superwaba/samples/ext/game/ping/Ping \
$SUPERWABA_ROOT/lib/samples/palm/ext/game/ping PiNg
You may also install the packaged SuperWaba samples for Redhat or Debian. Those
packages are available in the "bin/installers/samples/linux" folder. Install them as you
installed the VM (see the instructions above). The samples are installed in the folder
"/usr/local/share/superwaba/samples". All samples are provided with their launching script
(generated with Exegen).
Running as Applet
1. Package all the classes you need into a jar file. The main waba classes are packaged
into the file SuperWabaSDK/lib/vm/applet/Waba_only.jar. If your class uses any of the
extension libraries, then you must use the file SuperWabaSDK/lib/SuperWaba.jar file
instead.
2. Create the html file. Note that the code is not your application's main class, but it is
always waba.applet.Applet. The main class is specified using the parameter appClass.
You must also specify the used jar files, in the archive tag (separated by comma).
Check the samples in the folder SuperWabaSDK/bin/installers/samples/applet.
Running as Application
1. We recommend that you do not package the files into the jar file, unless you're
deploying the application to your client.
2. You must call something like this:
java -classpath .;/SuperWabaSDK/lib/SuperWaba.jar waba.applet.Applet
<your_main_class_here>
SuperWaba Companion
20
Do not forget the . (dot) in the classpath, or your classes won't be found. We assume in
the line above that the SDK was installed in the root and that you're in the same folder
where your main class resides.
SuperWaba Companion
21
Troubleshooting
If, after you install the sample in the device, an error message appears saying Can't find
class, you'll need to install also a SuperWaba Extension Library. Next is a list of the
samples and their required libraries. Note that some of them require a native library, and
the needed file may be a prc (for Palm OS) or a dll (for Windows). The root folder for the
samples below is SuperWabaSDK/src/java/superwaba/samples.
SuperWaba Companion
22
SuperWaba Companion
23
All these files are written in Java, and thus need the java.exe file to run. Below is a
command-line sample:
java.exe -classpath
/SuperWabaSDK/lib/SuperWaba.jar;/SuperWabaSDK/lib/SuperWabaTools.jar
superwaba.tools.Warp <your command-line here>
java.exe -classpath
/SuperWabaSDK/lib/SuperWaba.jar;/SuperWabaSDK/lib/SuperWabaTools.jar
superwaba.tools.Exegen <your command-line here>
NOTE: If you specified the SUPERWABA_ROOT environment variable, you may also use
the Windows or Linux helper scripts bin/Warp[.bat] and bin/Exegen[.bat]
Warp Instructions
(Super)Waba Application Resource Packager for Java Version 5.0
Copyright (C) Rob Nielsen 1999-2001. All rights reserved
Copyright (C) SuperWaba Ltda 2002-2005. All rights reserved
Usage: java superwaba.tools.Warp command [options] pdbfile [files]
Commands (case insensitive):
c Create new pdb file
l List contents of a pdb file
Options Description
/?
SuperWaba Companion
24
Options Description
/!
Replaces the ! in the internal representation of the file, putting in the prc and
removing from the pdb.
/c
/r
/q
/$
/x
/i
/ll
/lg
/t
Includes any .txt file referenced in the sources into the pdb, so it can be loaded
using Vm.getFile. Note that the txt cannot be larger than 64kb
SuperWaba Companion
25
Exegen Instructions
SuperWaba Launch Executable Generator for Java Version 5.0
Copyright (C) Rob Nielsen 1999-2001. All rights reserved
Copyright (C) SuperWaba Ltda 2002-2005. All rights reserved
Usage: java superwaba.tools.Exegen [options] exefile [main-class] [pdbfile]
Options
Description
/?
/$
/!
Removes the ! that is appended to the PDB name, putting on the PRC name
/0x
/16
Specifies that this app can run in 16bpp screens (check the FAQ)
/C
/E
/F
/I
/INST
/H
/L
/LNK
/M
/NOPRC
/NOSEMAP Don't use the semaphore to increase available memory on Palm devices.
HORE
/P
SuperWaba Companion
Options
26
Description
/SH
/SIS
/T
/V
/X
/Y
/Z
This program generates a Palm OS .prc and Windows CE application .exe files These
executables are used to launch (start up) a SuperWaba program.
If you don't specify the pdb file, its name will be the same of the exefile. If you don't
specify the [main-class], it will be the same of the exe too.
File extensions are generated automatically. For example, if you specify myapp as the
exefile, a myapp.exe and myapp.prc will be created.
A PalmOS PRC creator and PRC name will be assigned based on the pdbFile and exefile
respectively. The exefile must be 30 characters or less.
The ! parameter is useful when you want to update the application's pdb file from a
remote server. You must use this option in both Warp and Exegen, otherwise one file will
overwrite the other.
The /W and /H parameters define the default width and height of the application's window.
The value of 0 for either will cause the main window to appear at a default size which is
different on each platform.
The icons are automatically scanned, first in the current directory, next in the classpath
(including jar files). You may provide the following files: (WIDTHxHEIGHTxBPP):
icon15x9x1.bmp, icon15x9x8.bmp, icon16x16x4.bmp, icon22x22x1.bmp,
icon22x22x8.bmp, icon32x32x1.bmp, icon32x32x4.bmp, icon32x32x8.bmp,
icon48x48x8.bmp, icon30x18x1.bmp, icon30x18x8.bmp, icon44x44x1.bmp,
icon44x44x8.bmp. If you specify a prefix (E.g.: AAAA_), the searched files will be
AAAA_icon22x22x8.bmp, AAAA_icon22x22x1.bmp, etc. The 15x9, 22x22, 30x18 and
44x44 are for Palm OS (last 2 are for double density displays, E.G. Palm OS 5 and Sony
Clie), and the others for Windows CE. Note that for Palm OS you must create bitmaps
with the web-safe-palette. A gif with this palette is located under
SuperWabaSDK/samples. You can copy the icon files in
SuperWabaSDK/src/java/superwaba/tools/icons to your application's directory and edit
them. For Windows CE, the palette CANNOT BE THE WEBSAFE one. This happens
because in the Web safe palette, index 0 is white, and WinCE devices expect that index 0
will be black. A warning will be issued if you use an incorrect palette when generating the
SuperWaba Companion
27
exe files for WinCE. To correct this problem, you may use any image editor to increase
the image to 16bpp or more and then decrease it again to 256 colors and save the image.
Most editors don't use the web safe palette, which will correct the problem. Symbian OS
use the bitmaps with sizes 20x16x8 and 32x32x8.
The /Z parameter is used to create a bunch of cab files so your application can easily be
installed on all compatible Windows CE platforms. You may pass, optionally, a .swz file
with some global and local libraries used by your app. For example, if you need to install
the TinyLarge.pdb font and also a custom database, E.g. mydata.pdb, you must copy all
files to the current directory, then create a myapp.swz file with your favorite text editor with
the following contents:
[G]TinyLarge.pdb
[L]mydata.pdb
The [G] denotes a global library (fonts are always global libraries), and the [L] denotes a
local library. The user will then have two options to start the installation process:
1. Run the created xxx_install.bat file, or
2. If the cab files are available on the internet, the user may launch the browser from
inside the device, connect to the site and choose the appropriate cab file. The browser
will then download and install the file.
The /SIS parameter is analogous to /Z, but it targets the Epoc/Symbian platform. It can
also accept a .swz file to specify aditional files to be installed. The files must be specified
using a relative path: it searches in ., .., and build. The .swz file may also contain the
required S60v3 signing information that are a private key, its password and a certificate.
Add the following lines:
[PKEY]<path>/your_private.key
[PASS]your private key password
[CERT]<path>/your_certificate.cer
The /INST parameter is analogous to /SIS, but it targets the Palm OS platform. It can
accept a .swz file as the same way as specified above. An install.txt, if present, will be
used as the text to be shown during the installation.
The /SH parameter assumes that SuperWaba files are installed on
/usr/local/lib/superwaba and that the samples are installed under
/usr/local/share/superwaba/samples
The /Z parameter works only on the Windows platform. Optionally, you can also pass a
complete .inf file instead of a .swz file. See the SWCalc directory for an inf file sample for
how to create an installation that packages the SuperWaba files with your application.
The /L and the /LNK parameters cannot be used at the same time, because the file
created has the same extension (in the case both are specified, Windows CE will not be
created, and a warning will be given.
The /LNK assumes that SuperWaba VM for Win32 is installed under c:\\SuperWaba, and
the samples are installed under c:\\SuperWaba\\<exefile>.
SuperWaba Companion
28
The /T option specifies the title that will be shown in the window. The default is the class
name. Max title length = 40 chars
The /F specifies full screen in PocketPC (no title neither start button).
For the /P parameter, note that all applications must stay under '\\SuperWaba'. Spaces, /,
\\ and \ in the directory name are not alowed, except for Win32 whose full path (without
spaces!) may be specified.
NOTE: It is HIGHLY recommended that you ask the user to download the vm from
www.superwaba.org/install site, because it will always contain the last version, and your
installation may overwrite a newer vm.
The /NOSEMAPHORE disables the usage of the semaphore, a trick that allows PalmOS
devices to use more memory than the standard. In new devices, this may improve
application's stability, specially when using SIR, but your program may crash due to outof-memory errors. For instance, in an almost empty Treo 650, using the semaphore you
have about 27M of available RAM memory, while not using it you have 4.8MB. Read the
optimization tricks tutorial to learn how to minimize memory usage. A side effect of
disabling the semaphore is that the VM speed increases by 20%.
Examples:
java superwaba.tools.Exegen /I myicons_ /P Scribble scribble
java superwaba.tools.Exegen /W 160 /H 160 Calc CalcWindow calc
java superwaba.tools.Exegen /Z SWCalc.swz SWCalc
java superwaba.tools.Exegen ExtGadgets superwaba.samples.ext.ui.gadgets.ExtGadgets
Note: all examples above assume that the classpath environment variable includes
.;/SuperWabaSDK/lib/SuperWaba.jar;/SuperWabaSDK/lib/SuperWabaTools.jar
RenameFont Instructions
Usage: java superwaba.tools.RenameFont <fontpath> <oldfontname> <newfontname>
Please don't append the .pdb extension to the font names.
Note that the original files are preserved.
Wxgn Instructions
Usage: java superwaba.tools.Wxgn Warp_commands z Exegen_commands
Note that z is the separator
Lets you run Warp and Exegen together. Prc files only have to be built once, unless you
change any of the Exegen parameters (class name, creator id, etc).
SuperWaba Companion
29
Example Value
Description
project name
ACME
sw.root
c:/SuperWabaSDK
version
1.0
app.creator
ACme
app.name
Live
main.class
acme.coyote.Live
app.title
Live
app.package
Note that this ant file is simply used to call Exegen and Warp (very useful to use from
Eclipse). It does not create the cab files nor the sis files. If you want to create them, just
change this line
<arg line="/L"/>
to
<arg line="/L /Z /sis"/>
These options are explained in chapter 4.
SuperWaba Companion
30
NetBeans or Forte
Thanks to Jean Rissoto, Ed. J Szalajeski and Vince Nguyen
In NetBeans (or Forte)
Click the Tools menu, select Options and go to the Debugging and Execution folder:
Expand the folder
Select the "Execution Types" icon (looks like 2 arrows) and expand the tree.
Right Click your mouse on the root of the Execution Types, and select New.. External
Execution Name the Type ExternalSuperWaba
Right Click the ExternalSuperWaba Item just created, from the context menu select
Properties, and change the External Process to
-cp {filesystems} waba.applet.Applet /datapath . /x 10 /y 10 /scale 2 /bpp
8 {classname}
Project settings:
Select your project's mount directory in the filesystem explorer, (the directory with your
source files)
SuperWaba Companion
31
Right Click your main class file, select properties from the context menu
Select the Execution Tab,
Change the Compiler to Internal Compilation
Change the Debugger to DefaultSuperWaba (your item created above should be in the
drop down combo box)
Change the executor to ExternalSuperWaba
The arguments can be adjusted from this property page too.
(Recommended arguments)
Arguments: /dataPath j:\\apps\\my\\donnees /x 10 /y 160 /bpp 8
/scale 2
j:\apps\my .... is the path to the datas of my app...
/x 10 /y 160 /bpp 8 /scale see explanations below at end of text.
SuperWaba Companion
32
You're done and ready to do everything you need now. The trick is that you have to
execute/debug the waba.applet.Applet class with the Name of your main window
subclass as the application parameters. Be sure to run/debug waba.applet.Applet as an
application and not as an applet:
Put a breakpoint on the first line of your onStart method and launch Debug. It will stop
where you did set your breakpoint. If you don't do that, you will debug waba.applet.Applet,
which is probably not what you want to do.
Linux
Thanks to Christopher C. Stump and Frank Diebolt
Establishing a SuperWaba development environment under Linux is a rather easy task.
Linux users can also use GUI environments such as Eclipse. All the tools necessary for
SuperWaba development are available in the SuperWaba SDK which can be downloaded
from www.superwaba.org. Once the package is obtained, it needs to be unzipped.
We will assume the SDK is used only by yourself, so may unzip the packagein a subfolder
of your home directory
SuperWaba Companion
33
SuperWaba Companion
34
to create a .pdb file. The second argument is the name of the to-be-created .pdb file, and
the third argument is all of the .class program files.
Exegen is a java program that can also be found in same directory as Warp. Exegen's
purpose is to create the .prc file, which is the SuperWaba program in Palm OS executable
form. The first argument to Exegen is the name of the to-be-created .prc file. The second
argument is the name of the main source code file. The third argument is the name of the
.wrp file.
If the above steps were successful, then a ready-to-use/test Palm OS application should
be in the current directory. There should be files called MySuperWabaApp.prc and
MySuperWabaApp.pdb . Both of these files, along with the SuperWaba virtual machine
files, must be installed on a Palm unit or POSE in order to run the application. The
SuperWaba virtual machine files can be found in {full path to the SDK}/ . Of course, the
above command line arguments can be tedious to type over and over again while
developing. Therefore, it is much nicer to place all of the commands in a simple shell
script, like this Bash script, so everything can be easily run in sequence with a single
command:
#Invoke shell script to handle SuperWaba app creation
[command prompt]$ ./superwaba_maker.sh
NOTE: When you start a new application or need an application skeleton for a quick test,
simply run the PERL {full path to the SDK}/bin/makeApp.pl script which generates a
minimal java source file and an Ant build.xml to compile and build the application and to
run its applet version.
SuperWaba Companion
35
General Settings
To be able to do the setup in any IDE, you must do as described:
SuperWaba Companion
36
SuperWaba Companion
37
SuperWaba Companion
38
Currently there's no IME (input method) for unicode (in other words, you'll not be able to
input data in Unicode format). One will be uploaded by Alsan during end of December
2003.
Note that this is the first release with unicode support, so in the future versions many
things may change.
Please help us enhance the Unicode support, by providing new tools, fonts and more
documentation (localized docs are also welcome). Changes may be posted at
http://superwaba.sourceforge.net in the patches section.
SuperWaba Companion
39
SuperWaba Companion
40
Overview
The figure below shows the hierarchy of the classes in the waba.ui package,
followed with a brief description of each.
SuperWaba Companion
41
MainWindow the father Window to where all events are sent; all SW programs must
have one and only one MainWindow.
MenuBar a menu bar with captions displayed at the top of the MainWindow when the
user presses the menu key or the windows title (if any).
MessageBox a Window that displays a text, arrows to scroll the text and a set of user
configurable buttons (with an Ok button as default)
PenEvent event issued by the VM when the user uses the stylus in the devices
touch-screen.
PopList displays a popup Window with a listbox inside it. Used by the ComboBox
class.
PopupMenu displays a menu when its corresponding caption is selected from the
MenuBar.
ProgressBar A bar used to track progresses.
PushButtonGroup a matrix of selectable buttons.
Radio a radio button with text associated.
RadioGroup keeps a set of attached Radio buttons synchronized; when a Radio is
selected, all the other are unselected by the RadioGroup.
ScrollBar a horizontal or vertical scroll bar
TabPanel a container with tabs. Each tab has a Container where other controls can
be added. At each tab selection, the containers are swapped.
Timer event issued by the VM when any active timer has finished its countdown.
Welcome the application that is called when the user clicks on the SuperWaba icon
at the device.
Window parent of all other windows and of MainWindow. Must be only extended by
popup windows.
NativeMethods stores the definition of all native methods used in this package; this
class must not be used directly by the user.
NativeMethods4JDK stores the implementation, using the Java Development Kit, of
all native methods used in this package; this class must not be used directly by the
user.
The NativeMethods and NativeMethods4JDK are for internal use only and will not
be described in this tutorial.
SuperWaba Companion
42
PalmOS looks better with a white background, WinCE looks better with bright
background.
In the figures below you can see both types, from a snapshot of the UIGadgets
program, running on the desktop emulating the device. Next to each description you find
the command line options to test the behavior. The command line below can be used with:
java waba.applet.Applet <cmd-line below> superwaba.samples.ui.gadgets.UIGadgets
(We assume that the location of the compiled UIGadgets is in the classpath)
(A) PalmOS style with white background in a 160x160 grayscale device with 4 colors.
/bpp 2 /scale 1 /uiStyle PalmOS
(B) WinCE style with bright background in a 160x160 grayscale device with 16 colors.
/bpp 4 /scale 1
(C) Flat style with 64k colors in a 176x189 Nokia phone
/bpp 16 /w 176 /h 189 /scale 1 /uiStyle Flat
(D) Flat style in a 160x160 device with 256 colors.
/bpp 8 /scale 1 /uiStyle Flat
(E) PalmOS style with white background in a 160x160 color device.
/bpp 8 /scale 1 /uiStyle PalmOS
(F) WinCE style with color background in a 160x160 color device.
/bpp 8 /scale 1
SuperWaba Companion
43
(A)
(B)
(D)
(E)
(G)
(C)
(F)
(H)
SuperWaba Companion
44
There must be only one class per application extending MainWindow. Every
SuperWaba program must have one class that extends waba.ui.MainWindow.
MainWindow is the interface between the VM and the SuperWaba program: it receives all
events and dispatches them.
The VM first calls the MainWindow default constructor (in this case, the Foo())
and after that it calls the onStart method (which belongs to the Container class and can
also be used for classes that extend it). You can place all your controls in the constructor
and ignore the onStart method; or you can place them in the onStart method and
ignore the constructor. However, the latter approach is recommended because if you run
your program as an applet and you dont use this approach, the applet may not appear
correctly.
SuperWaba Companion
45
MainWindow has a public static member called defaultFont, that is used to set
the default font used in each new control created. To change the default font to another
one, assign a new font to this member in your MainWindow constructor.
Other important methods in this class are:
exit(int exitCode): exits the program, calling onExit before. Good to be put
in a Quit menu item.
addTimer(Control target, int millis): adds a timer. The Timer event
will be issued to the target every millis milliseconds.
removeTimer(Timer timer): removes the given timer from the timers queue.
getCommandLine(): if this process was executed by another process (e.g.: using
the waba.sys.Vm.exec method), this method gets the command line passed.
when you click on the application icon, theres no command line.
addThread(Thread t, boolean highPriority): adds, to the VMs thread
queue, the given thread. High priority threads have the same priority as system
events; so, no event is issued while those threads are running.
threads in SuperWaba are non-preemptive, behaving like the ones in Windows
98.
removeThread(Thread t): removes the given thread from the VMs thread
queue.
getMainWindow(): returns the instance of the current MainWindow. You can use
it to get access to methods of the MainWindow class from outside the class. Is it
also possible to cast the returned class to the class that is extending MainWindow
(this is a normal Java behaviour). So, if UiGadgets is running, it is correct to do:
UIGadgets instance = (UIGadgets)MainWindow.getMainWindow();
SuperWaba Companion
46
The coordinates are always relative to the parents coordinates. This is easy to
understand, as this document has a relative position to the PDF viewer window, not to
your screen monitor.
Starting on version 5.5, the controls can be traversed using the 5-way navigation
present on most PDAs. and Smartphones. It is automatically activated on penless devices
(such most Smartphones), but can be activated on pen devices by making
Settings.keyboardFocusTraversable=true. The order of the traversal is defined
by the order of the elements in the Container.tabOrder member. The controls are added
to the vector in the order as they are added to the container. This may not be optimal; you
may assign a new order by adding the controls to the vector as this.tabOrder = new
Vector(new Object[]{ed1,btn1,btn2,ed2});
SuperWaba lets you place controls in two ways:
1. The hard way, by setting the x,y,width,height with numbers. E.g.:
control.setRect(10,10,80,12).
2. The smart way, by using constants for relative coordinates. The constants allowed
are:
Coordinate X
o LEFT: place the control at the position 0 horizontal. If the parent is a
Window, align the control at the left of the windows client rect.
o RIGHT: align the control at the right. If the parent is a Window, align the
control at the right of the windows client rect.
o CENTER: center horizontally the control in the container.
o BEFORE: place the control before the last one added.
o AFTER: place the control after the last one added.
o SAME: place the control at the same x coordinate of the last one added.
Coordinate Y
o TOP: place the control at position 0 vertical. If the parent is a Window,
align the control at the top of the windows client rect.
SuperWaba Companion
47
o BOTTOM: place the control at the bottom of the container. If the parent is
a Window, align the control at the bottom of the windows client rect.
o CENTER: center vertically the control in the container.
o BEFORE: place the control before the last one added.
o AFTER: place the control after the last one added.
o SAME: place the control at the same y coordinate of the last one added.
Width
o PREFERRED: lets the control determine its best width. This is normally
computed using the controls text width in the selected font.
o FILL: the controls width will fill the space left until the end of the
container. Cannot be used with RIGHT/CENTER.
o SAME: set the control's width with the same width of the last control
added.
o FIT: set the control's width to fit between the specified x position and the
last control added x position. For example, if you place a Label at LEFT,
a Button at RIGHT and want to place an Edit between those two controls,
use FIT as the control's width using the Label as relative control.
Height
o PREFERRED: lets the control determine its best height. This is normally
computed using the controls text height in the selected font.
o FILL: the controls height will fill the space left until the end of the
container. Cannot be used with BOTTOM/CENTER.
o SAME: set the control's height with the same height of the last control
added.
o FIT: set the control's height to fit between the specified y position and
the last control added y position. For example, if you place a Button at
TOP, a Label at BOTTOM, and want to place a ListBox between both, use
FIT as the control's height using the Button as relative control.
If you use LEFT/TOP/RIGHT/BOTTOM with the first control added to a Window, it will
use the coordinates of the Windows client rect, which are the Window area excluding the
title and the borders, if any.
You may not use FIT in both width/height. It won't work as expected because you can't
specify two controls to make it relative to. The width/height is always related to the last
control added. FIT is used by many samples; search for them in the
SuperWabaSDK/src/java/superwaba/samples folder.
Before calling setRect, the control must be added to the container and have its
characteristics (like font, border type, etc) set. This is needed because the control
position is computed based on its parent container and the control's size is computed
based on its characteristics.
The constants described above have one important feature: a variable or a number
can be used to increment/decrement the result value. Examples: CENTER+2, BOTTOM-5,
PREFERRED+4, FILL+2, BEFORE-5. Note that by using anything above 5 will make your
code appear wrong in other resolutions.
SuperWaba Companion
48
The use of relative positioning is highly recommended. Its use makes the program
portable between different resolutions and fonts. As a practical example, see the figures
E and F/G of UIGadgets in chapter 2. Because relative positioning was used, the controls
were correctly arranged in all resolutions.
Here are the methods related to gadgets placement in the Control class:
1. setRect(int x, int y, int width, int height): sets the control
bounds with the given parameters. If relative coordinates are used, they will be
relative to the last added control.
2. setRect(Rect r): same as setRect(r.x, r.y, r.width, r.height)
3. setRect(int x, int y, int width, int height, Control
relative): same if 1, but relative coordinates will be relative to the given
control instead of the last one added.
The Container class also has some handy methods to set the controls bounds:
1. add(Control control, int x, int y): same of add(control);
control.setRect(x, y, PREFERRED, PREFERRED);
2. add(Control control, int x, int y, Control relative): same of
add(control); control.setRect(x, y, PREFERRED, PREFERRED,
relative);
The last two methods are good when youre adding controls that do not need to have
any of its characteristics (like font and border) changed. If you change the characteristics
after calling those methods, you'll get strange results, because the control does not
reposition/resizes itself when you change a characteristic (just as an example, suppose
that the default font has 11 in height, and you add the control; then you change the font to
one with height 22; the control will not be resized and you'll see only half of the text).
Below are some examples of how to use the relative constants:
add(new
add(new
add(new
add(new
add(new
Label("1"),
Label("2"),
Label("3"),
Label("4"),
Label("5"),
CENTER, CENTER);
AFTER, SAME);
SAME, AFTER);
BEFORE, SAME);
BEFORE, BEFORE);
SuperWaba Companion
49
repaintNow has a pitfall if the control is not a Window. If the controls parent Window
uses an offscreen image for double buffering (by calling setDoubleBuffer(true)), the
offscreen image is not updated. So, if the parent Window is a popup window with double
buffering and the user moves it, the updates you painted under the repaintNow will be
lost. There are no problems if the popup Window does not use double buffering but if it
does use double buffering and you call repaint instead of repaintNow. Double buffer
is an important feature; but be sure to test it.
SuperWaba Companion
50
SDL platforms (Epoc, Windows 98/2K/XP and Windows CE) always use offscreen
windows, so calling the setDoubleBuffer method is useless. This method will be
deprecated and removed in the future.
Here are some useful members in the Control class
onPaint(Graphics g): this is the method called when the control is going to
be painted. You can use the given Graphics object to draw what you need on
screen. The default's control font is already set, and the clipping is also set to the
control's bounds.
onBoundsChanged: called after the user invoked the setRect method. Good to
compute positions that are dependant on the bounds.
onColorsChanged(boolean colorsChanged): Called after a setEnabled,
setForeColor and setBackColor methods were called and when a control has
been added to a Container. If colorsChanged is true, it was called from
setForeColor/setBackColor/Container.add; otherwise, it was called from
setEnabled
onWindowPaintFinished: every time the _doPaint finishes paintings all
controls, this method is called. You can then do actions needed after the screen
has finished the paint. Note that this method is only called on controls that
extends Window and on the focused control.
onFontChanged: called after the setFont method is invoked.
SuperWaba Companion
51
Chapter 11 Events
We have learned how to create a main window and add controls to it. Now we need
to learn how to handle user and system interactions with the controls.
Each user interaction generates an event. Events are bundled in 3 classes:
KeyEvent, PenEvent and ControlEvent. The event is specified in the type class
member.
The event model of SuperWaba is almost identical to the one used in JDK 1.0.
There are two basic types of events: pen events and key events. Below we see
how each event is handled by the Window and forwarded to the target control:
1. The user types a key on the device. The VM intercepts the key and sends it to the
Window, which in turn creates a KeyEvent with type KEY_PRESS, the key code, and
then forwards the event to the control that currently owns the focus.
2. The user presses the touchscreen of the handheld, generating a point with x,y
coordinates. The VM sends the event to the Window; the Window searches for the control
whose bounds contain the point; it then converts the point to the controls local
coordinates, and dispatches a PenEvent with type PEN_DOWN and with the x,y
coordinates to the control. When the user releases the touchscreen a PEN_UP event is
generated as described for the PEN_DOWN. The other two possible pen events are
PEN_MOVE and PEN_DRAGGED.
PEN_MOVE events are not generated in PalmOS, only in WindowsCE and in the applet.
The two events above are handled by the controls, which may convert them to
other events, defined in the ControlEvent class. Below we see how and who generates
each of the events defined in that class:
1. PRESSED: this event is posted by controls when they receive a PEN_DOWN (like
Check, Radio, TabPanel), a PEN_UP (Button, ListBox, PushButtonGroup, ScrollBar) or
even a WINDOW_CLOSED (ComboBox).
2. FOCUS_IN and FOCUS_OUT: posted by the Window when a control different from the
current one is clicked. The FOCUS_OUT is first posted to the old control, and the event
FOCUS_IN is then posted to the new control to inform it that it is receiving focus.
3. TIMER: this is a special event that is posted to the control that has assigned a timer; it
is called when the timer countdown has reached zero.
4. WINDOW_CLOSED: called from the unpop method to notify all controls that a window
has been closed. Some controls, like the ComboBox, has a PopList assigned to it; when
the PopList issues a WINDOW_CLOSED event, the ComboBox receives it and converts to
a PRESSED event.
5. WINDOW_MOVED: issued when a window has just been moved (popup windows in
SuperWaba can be moved around the screen by dragging the windows title). The event
is broadcasted to all controls inside the window; most controls use this event to reinitialize
or translate an instantiated waba.fx.Graphics object.
SuperWaba Companion
52
If your control creates a Graphics object at initialization time, it must recreate when it
receives a WINDOW_MOVED event, otherwise it will paint things in an invalid place or even
nothing may be painted.
Now that we have all events described, lets see how to use them.
A control posts an event using the postEvent method. This method posts the
event to the control and to all of its parents. So, if we have a Button inside a TabPanel in
the Window, the event is propagated as follows:
Window.onEvent
TabPanel.onEvent
Container.onEvent
Button.onEvent
SuperWaba Companion
53
break;
}
}
type: this is the event number, used to detect which event was posted.
target: this one informs who is receiving the event (E.g.: the VM posts a
PenEvent.PEN_DOWN to a control) or who is posting it (E.g.: the Control posts an
ControlEvent.PRESSED).
timeStamp: contains the time stamp at which the event was created.
consumed: when set to true during the event propagation, breaks the propagation
chain.
SuperWaba Companion
54
Here were ending our Events chapter. In the next chapters, we will see in more
detail all user interface gadgets available in the waba.ui package.
SuperWaba Companion
55
waba.ui.Button
Buttons are the most used types of controls. They are used to invoke an action or
to confirm something, like <ok> or <cancel>. Here are some characteristics of SuperWaba
buttons:
If you create an image button and call setText, the button is transformed to a text-only
button.
The preferred size is computed as below:
text height / image height
gap
text width / image width
gap
In this figure, the red rectangle is the buttons text or image; the black rectangle is
the buttons border, if any. The text width/height are computed using the FontMetrics of
the current controls font (if it is a text button) or by getting the width/height of the image (if
it is an image button). The gap is set using the setGap method or the commonGap
member.
Thats why you must set the characteristics of controls before calling setRect to set
their bounds.
SuperWaba Companion
56
There is an easy way of setting the gap of multiple buttons: use the static int
commonGap member. For example, you set Button.commonGap=2, add all the buttons
that will have this common gap, and then reset it to zero.
Here are some examples of how to construct buttons, taken from the
ButtonExample:
Button btn1 = new Button("Border none enabled");
btn1.setBorder(Button.BORDER_NONE);
add(btn1,LEFT,TOP);
Button btn2 = new Button("Border simple enabled");
btn2.setBorder(Button.BORDER_SIMPLE);
add(btn2,LEFT,AFTER+5);
Button btn3 = new Button("Border 3d enabled");
btn3.setGap(1);
add(btn3,LEFT,AFTER+5);
Button btn4 = new Button("Border none disabled");
btn4.setBorder(Button.BORDER_NONE);
add(btn4,LEFT,AFTER+10);
btn4.setEnabled(false);
Button btn5 = new Button("Border simple disabled");
btn5.setBorder(Button.BORDER_SIMPLE);
add(btn5,LEFT,AFTER+5);
btn5.setEnabled(false);
Button btn6 = new Button("Border 3d disabled");
btn6.setGap(1);
add(btn6,LEFT,AFTER+5);
btn6.setEnabled(false);
Button.commonGap = 2;
String imgName = "Diskette.bmp";
Button btn7 = new Button(new Image(imgName));
add(btn7,LEFT,AFTER+10);
Button btn8 = new Button(new Image(imgName));
add(btn8,AFTER+10,SAME);
btn8.setEnabled(false);
Button.commonGap = 0;
The following picture shows the output of the code above in both user interface
styles:
WindowsCE
PalmOS
SuperWaba Companion
57
You can simulate the button being pressed by calling the method press and passing
true as parameter.
The Button class has a handy static method called createArrowButton, used to
create a Button with an arrow image. For more details on the arguments, see
Graphics.drawArrow.
Images are not controls, they can't be added to a container. The Button class can
be used to add an Image to the screen, removing the border and not acting on an event.
To make the button behave like this, construct it with an image and call the
onlyShowImage method.
You can change the color used when the button is pressed (useful when the UI is in
PalmOS style) using the setPressedColor method.
waba.ui.Check
Check box is a control that have a rectangle with a check inside and a text at right,
and are used for items that have an on/off state.
The preferred size is computed as below:
Text height + 0/2
4
14/16
Text width
In this figure, the red rectangle is the checkbox text. The check box width (green) and the
controls height (blue) depends on the user interface style (first number is for PalmOS and
2nd number is for WinCE)
The Check's text will be always right justified in the control's width.
Below we see an example code of how to create a Check in SuperWaba, taken
from the CheckExample.java file:
chk1 = new Check("Checked enabled");
SuperWaba Companion
58
add(chk1,LEFT,TOP+5);
chk1.setChecked(true);
Check chk2 = new Check("Unchecked enabled");
add(chk2,LEFT,AFTER+5);
Check chk3 = new Check("Check disabled");
add(chk3,LEFT,AFTER+5);
chk3.setChecked(true);
chk3.setEnabled(false);
WindowsCE
PalmOS
As the Button control, the only event that the Check control posts is the
ControlEvent.PRESSED. Below we see an example of how to handle a click on the
checkbox:
public void onEvent(Event event)
{
switch (event.type)
{
case ControlEvent.PRESSED:
if (event.target == chk1)
{
String state = chk1.getChecked()?"checked":"unchecked";
new MessageBox("SuperWaba", "Checkbox "+state).popupModal();
}
break;
}
}
waba.ui.ComboBox
ComboBox is a very useful control to display a list of items where only one can be
selected. It consists of a text with a button and a PopList control that is popped up when
the button is pressed. Then the user selects one item and the PopList window closes.
The PopList is placed depending on the user interface style: if using PalmOS, the
poplist is placed covering the control. Otherwise, if WinCE, it is placed below the control.
The PopList height also depends on the control's position: it will open in the direction that
has the most space left (above or below). If you set the public member fullHeight to
true, then it will have the same height as the screen, maximizing the number of items
displayed. In the same way, the fullWidth will set the width to the screen's one.
SuperWaba Companion
59
There's a way to change the ComboBox's ScrollBar default width: you must play with
the Button.commonGap, which is a static member from the Button class (see chapter 6,
waba.ui.Button), and the extraArrowSize, which is a static member from the
ComboBox class. The Button.commonGap increases the size of the button inside the
ComboBox's ScrollBar, and the ComboBox.extraArrowSize increases the size of the
arrow drawn inside the button. After the ComboBox creation, you must reset both to 0,
otherwise they will affect all future ComboBoxes and Buttons created.
Its preferred size is computed as below:
Text height + 4
PopList preferred width*
* This is the width of the largest item plus the width of the ScrollBar.
In this figure, the red rectangle represents the control.
The ComboBox has three types of constructors:
1. ComboBox(Object []items): This one is the most used. You can pass a String
array as the items.
2. ComboBox(ListBox userListBox): This is used when you want to display a
user-defined ListBox as the Popup window.
3. ComboBox(PopList userPopList): This is used when you want to display a
user-defined PopList. Set the userListBox like this: new
PopList(userListBox)
4. ComboBox(): The default constructor creates an empty ComboBox.
The ComboBox has a very useful method that does a sort of the items: qsort().
It is possible to make a ListBox scroll horizontally (see waba.ui.ListBox). To be able
to scroll the ListBox associated with this ComboBox, two methods are provided:
setOffset and getNeededHorizontalScrollValue.
Below we see an example code, taken from the ComboBoxExample.java file:
String []items1 = {"","Orange","Apple","Grape","Lemon"};
String []items2 = {"One","Two","Three", ...};
String []items3 = {"Disabled","Enabled"};
cb1 = new ComboBox(items1);
add(cb1,LEFT,TOP+5);
ComboBox cb2 = new ComboBox();
cb2.add(items2);
cb2.add("Twenty one");
add(cb2,RIGHT,AFTER+5);
SuperWaba Companion
60
Windows CE
PalmOS
waba.ui.Edit
Edit is a control used to get text input when the user type keystrokes in the grafitti
area. It allows you to select text and cut/copy/paste it. Here are some other features:
There are two constructors: the default (with no arguments) that creates an Edit
with no constraints, and one constructor that receives a mask string. The mask is
used only to compute the preferred width. Maybe in the future it will be used for
other purposes.
If you pass an empty mask , the width will be set to FILL.
You can limit the maximum length of characters that can be entered, by using the
setMaxLength method. If the user tries to enter text above the limit, a beep is
sounded and the text is ignored. If you set a text greater than the max length, it will
be truncated.
You can also set the valid characters that can be entered by using the
setValidChars method. There are some predefined character sets that can be
localized if necessary:
o numbersSet = "0123456789"
SuperWaba Companion
61
o currencyCharsSet = "0123456789.+-"
o dateSet = numbersSet + Settings.dateSeparator
Those character sets are used in the setMode method. In this method you can use
one of the following constants:
o NORMAL : in this mode any character can be entered, and when pressing the
abc/123 keys the waba.ui.Keyboard is popped up.
o DATE: this mode uses the dateSet and the waba.ui.Calendar is the one
popped up.
o CURRENCY: the currencyCharsSet is used and the
waba.ui.Calculator is the one popped up.
o PASSWORD: any character can be entered and the waba.ui.Keyboard is
the one popped up. Only the last character typed is displayed in this mode,
all the others are replaced by an asterisk (*).
o PASSWORD_ALL: same of PASSWORD except that all characters are replaced
by an asterisk (*), including the last one.
The edit can be set as read-only by directly setting the editable member. By
setting the member hasCursorWhenNotEditable to false the cursor will not
appear when not editable.
There's a public member named overwrite which, if set to true, turns off insert
mode (ie, characters will be replaced if written over).
The member alignment lets you control the alignment of the text inside the Edit
after it looses the focus. This means that, when it has focus, it is always leftaligned, but when it looses, it may align the text to the right.
You can invoke the default popup keyboard for the edit using the popupKCC
method (KCC = Keyboard, Calculator and Calendar).
You may specify which keyboard will be popped up, overriding the default
behaviour, using the setKeyboard method, passing the constants KBD_NONE,
KBD_DEFAULT, KBD_KEYBOARD, KBD_CALCULATOR, KBD_CALENDAR.
You may force all characters entered to be automatically converted to upper or to
lower case using the method setCapitaliseMode and giving the parameters
ALL_NORMAL, ALL_UPPER and ALL_LOWER.
The member autoSelect makes the Edit automatically select the text when it
receives the focus. This is always true for penless devices.
There is a multiline Edit available in: superwaba.ext.xplat.ui.MultiEdit.
The method setCursorPos(start, end) can be used to set the selected text
of the Edit (if start != end). It can be used to set the cursor position, if start equals
end. Start must be less or equal to end, and both must be >= 0. It can also be used
to clear the selectedText, calling <code>setCursorPos(-1,0)</code>. Note: if you're
setting the cursor position before the edit is drawn for the first time, the edit will not
be scrolled if the end position goes beyond the limits. Important! No bound
checking is made. Be sure to not call this method with invalid positions!
The method getCursorPos returns an int array with the start (array index 0) and
end (array index 1) positions of the cursor. It can be used to find the selected text,
which will be the substring(start,end).
Here is how the preferred size is computed:
SuperWaba Companion
62
Text height
(plus 4 if WinCE)
if mask is null, ScreenWidth/4.
If the mask is , use the FILL,
otherwise it is the masks width;
both cases plus (4 if PalmOS, 10 if WinCE)
Below we see an example code, taken from the EditExample.java file:
ed1 = new Edit();
add(ed1);
ed1.setRect(LEFT,TOP+5,80,PREFERRED);
Edit ed2 = new Edit("9999.99");
ed2.setMode(Edit.CURRENCY);
add(ed2,LEFT,AFTER+5);
Edit ed3 = new Edit("99/99/9999");
ed3.setMode(Edit.DATE);
add(ed3,LEFT,AFTER+5);
Edit ed4 = new Edit("AAAAA");
ed4.setMode(Edit.PASSWORD);
add(ed4,LEFT,AFTER+5);
Edit ed5 = new Edit();
ed5.setMaxLength(4);
ed5.setValidChars("123ABC");
add(ed5);
ed5.setRect(LEFT,AFTER+5,40,PREFERRED);
String txt = "Can't Edit";
Edit ed6 = new Edit(txt);
ed6.setEditable(false);
ed6.setText(txt);
add(ed6,LEFT,AFTER+5);
Windows CE
PalmOS
The Edit control does not post any event, but you may intercept the
ControlEvent.FOCUS_OUT to validate the edits text.
SuperWaba Companion
63
waba.ui.Label
This control is used to display static text. The Label in SuperWaba can also display
multiple lines of text, separated by the character |. Here are some other features:
Label has two constructors: one with a text (that may be changed at runtime) and
one with text and an alignment parameter. The alignment can be LEFT, CENTER
and RIGHT. The text is used to compute the preferred size. If you pass an empty
string as text, the preferred width will be FILL. You can set/change the label's
alignment accessing the public member align.
You can call the set3d method to make the label have a 3d look, by drawing it with
the foreground color and with a color a little brighter than the background color.
Labels can look inverted, by swapping the background and the foreground colors.
To do this, use the setInvert method.
If the Label is a multiline one, you can use the method scroll(boolean down)
to make it scroll up and down, and also the canScroll(boolean down) method
to peek if it can be scrolled in the desired direction. To see a good usage example
of this feature, see the waba.ui.MessageBox class.
In the WinCE user interface style, a Label doesn't have the same height of an Edit.
You can adjust this setting the commonVGap public static attribute to 4. It makes
easier to vertical align Labels with Edits.
The three align constants are inherited from the waba.ui.Control class, where they are
used in the setRect method. Furthermore, you can use new Label(my
text,Label.CENTER) or new Label(my text, CENTER); it will work in the same
way.
Labels cant be inverted and 3d at the same time. Calling set3d cancels
setInverted and vice-versa.
The setText method, used to change the labels text, does not change the controls
bounds. You must be sure that the label has enough size to hold the text otherwise it will
be clipped.
Theres a handy method in the waba.sys.Convert class called
insertLineBreak(int maxWidth, char separator, waba.fx.FontMetrics
fm, String text). It is used to parse the text that will be used in the mutiline Label.
The string is not parsed automatically at runtime because this is a slow operation. You
may use it sending the resulting String to the console and pasting the result into your
code. Here is a usage example:
waba.sys.Convert.insertLineBreak(Settings.screenWidth6,'|',getFontMetrics(getFont()),"This is a very long text and i
dont want to waste my time parsing it to be fit in the
MessageBox!"). Note that Settings.screenWidth-6 is the maximum alowed width
to make the text fit in a MessageBox (where the multi line label is used); by using this
value, it may work correctly in other screen resolutions because the font is proportional to
it.
Below we can see how the preferred size is computed:
SuperWaba Companion
64
And here is the code output. The output is the same in both WinCE and PalmOS:
waba.ui.ListBox
SuperWaba Companion
65
The ListBox control looks like an opened ComboBox (in fact, the ComboBox uses
the ListBox control). You may use the ListBox instead of the ComboBox if the screen has
more space available. Below are some features of ListBox:
ListBox has two constructors: the default that creates a ListBox with no items and
another that accepts an object array with the items.
Items may be added or deleted at runtime, with the following methods: add,
remove, setItemAt, getItemAt, getSelectedItem, getSelectedIndex,
indexOf, select(int item), select(object) and size.
The setSimpleBorder method is used to change the border style from 3d to
simple.
If the ListBox owns the focus and you type a letter, the first item with the typed
letter is selected. Typying again selects the next item, and so on.
The up/down keys can be used to scroll the ListBox.
You may use the method qsort to sort the items in the ListBox.
ListBox can be horizontally scrolled. Although this is not implemented by the
control, it has two methods that can aid you on this task: setOffset and
getNeededHorizontalScrollValue. The first one sets the offset from where
the text is drawn (negative values makes the text flow to left, positive values to the
right). The second one determines the maximum number of pixels that can be
scrolled. See superwaba.ext.xplat.unit.SWUnit for an example on how to use
these methods.
By default, the selection is drawn using the current item's width. This behaviour can
be changed by setting useFullWidthOnSelection to true.
You can extend ListBox to implement a customized type, like a color-chooser
ListBox (see superwaba.ext.xplat.ui.ColorList). If doing so, the following methods
must be overridden:
protected void drawItem(Graphics g, int index,
int dx, int dy)
protected int getItemWidth(int index)
Below you see how the preferred size is computed:
gap
The gap depends on the border type: if simple border, gap = 4, otherwise gap = 6.
Next we see an example code, taken from the ListBoxExample.java file:
String []items1 = {"Orange","Apple","Grape","Lemon"};
String []items2 = {"One","Two","Three", ...};
String []items3 = {"Disabled",""};
SuperWaba Companion
66
Windows CE
PalmOS
Be careful when setting the items with a String array. The array is assigned as is, no
copy is made. So, if you use the same array in another control and an item inside the
array is changed, this change will reflect in both controls. However, if you add a new item,
then a new array is created to store the added item and the program works correctly. The
best practice is to have one array for each ListBox control. To create a copy of a String
array, you can use waba.sys.Convert.cloneStringArray.
As with the ComboBox control, the ListBox also posts the
ControlEvent.PRESSED when an item is clicked. Below is an example of how to handle
the event:
public void onEvent(Event event)
{
switch (event.type)
{
case ControlEvent.PRESSED:
if (event.target == lb1)
new MessageBox("SuperWaba","Item selected: "+
lb1.getSelectedItem()).popupModal();
break;
}
}
waba.ui.PopList
The PopList is a popup window with a ListBox inside it. When an item is selected,
the window is closed. It is used with the ComboBox class. Some characteristics are
described below:
SuperWaba Companion
67
It has two constructors: the default creates an empty ListBox, and the other
receives a ListBox as parameter (it can be used when you create a customized
ListBox).
The lb member is public, it can be accessed directly.
The setRect method must be used differently: you must pass the parents
bounds (if any) because the PopList computes its bounds making sure that the
parent is not hidden. The size is computed using the ListBox items count. It sets
the position above or below the parent, depending on that computed size.
If the style is WinCE, the window is popped up in a way to not hide the parent
control. In PalmOS, the PopList hides the parent control because thats the way
PalmOS ComboBox control needs to work. You can force the control to not hide
its parent setting the dontHideParent public flag to true.
As with ComboBox, you can set the fullHeight and fullWidth flag to true
to maximize the view size.
The PopList does not have a concept of preferred size because its bounds are
computed dynamically.
The example code, taken from the PopListExample.java file, is an Edit with a
PopList, where you can select the text to be pasted in the Edit:
String []items = {"Orange","Apple","Grape","Lemon"};
add(new Label("Press the menu to open the poplist"),LEFT,TOP+10);
add(ed = new Edit());
ed.setRect(LEFT,AFTER+2,100,PREFERRED);
pop = new PopList();
pop.lb.add(items);
Rect r = ed.getRect();
pop.setRect(r.x,r.y,r.width,r.height);
ed.requestFocus();
Windows CE
PalmOS
SuperWaba Companion
68
if (pop.isVisible())
pop.unpop();
else
pop.popupModal();
break;
case ControlEvent.WINDOW_CLOSED:
if (event.target == pop)
ed.setText((String)pop.lb.getSelectedItem());
break;
}
}
waba.ui.ProgressBar
The ProgressBar is the standard bar used to display a progress. It consists of a bar
and a text that is displayed with the bar.
It has two constructors: the default one, which constructs a ProgressBar with
minimum=0 and maximum=100, and another where these two values are passed as
parameters.
There are several public members: min, max, value (minimum value, maximum value
and the current value, respectively), prefix (which is the text prefix), suffix (text
suffix) and textColor, the color of the text, drawBorder (if true default the
border is drawn with the text's color). All these members can be set and retrieved
directly.
There are two methods for that set these values and display the changes immediately:
setValue(value) and setValue(value, prefix, suffix). The first one
changes the current value, and the second one changes the value plus both text prefix
and suffix.
The displayed text is: prefix + value + suffix
The default value for prefix is an empty String, and for the suffix is the percent
symbol (%)
The preferred height is fmH+2 and the preferred width is the parent container's width-6
or the screen width, if the control was not added to its container yet.
Windows CE and PalmOS
The ProgressBar control does not post events.
waba.ui.Radio
Radio is a control used when you have a few options where only one option must
be selected at a time (like a ComboBox or a ListBox). They are usually grouped together
so that when one is selected, all the others in the group are de-selected. This can be
easily achieved with the waba.ui.RadioGroup class, as described below in the example
code. It has two constructors: one that receives text, and one that also receives a
RadioGroup.
SuperWaba Companion
69
The RadioGroup cant be added to a container because it is only a class, and does not
extend waba.ui.Control. Also, it does not post events. The RadioGroup class contains a
useful method getSelectedIndex, which returns the index of the selected radio, and
also the setSelectedIndex, to set the current radio. These indexes are based in the
order that the radios are added to the container.
You may use the getRadioGroup method to make it easier to parse the events.
Here is how the preferred size is computed:
Text height
(+ 2 if WinCE)
12 if PalmOS, 14 if WinCE
Text width
The blue rectangle represents the opened/closed circle and the red rectangle represents
the text.
Below you will see example code, taken from the RadioExample.java file:
rgFruits = new RadioGroup();
add(rOrange = new Radio("Orange",rgFruits),LEFT,TOP+5);
add(rApple = new Radio("Apple",rgFruits),LEFT,AFTER);
add(rGrape = new Radio("Grape",rgFruits),LEFT,AFTER);
add(rLemon = new Radio("Lemon",rgFruits),LEFT,AFTER);
rOrange.setChecked(true);
String []numbers = {"One","Two","Three"};
rgNumbers = new RadioGroup();
for (int i =0; i < numbers.length; i++)
add(new Radio(numbers[i],rgNumbers),
i==0?CENTER:SAME, i==0?(TOP+5):AFTER);
add(rEna = new Radio("Enable"),RIGHT,BOTTOM);
add(rDis = new Radio("Disable"),BEFORE-2,BOTTOM);
rDis.setEnabled(false);
rDis.setChecked(true);
Windows CE
PalmOS
SuperWaba Companion
70
The Radio control posts a ControlEvent.PRESSED event when the user clicks
on it. Below is an example of its use:
public void onEvent(Event event)
{
switch (event.type)
{
case ControlEvent.PRESSED:
if (event.target instanceof waba.ui.Radio)
{
Radio r = (Radio)event.target;
RadioGroup rg = r.getRadioGroup();
if (rg == rgFruits)
{
repaintNow(); // the MessageBox below will popup before the
// screen is updated to unselect the Radio
new MessageBox("SuperWaba",r.getText()+" juice")).popupModal();
}
else
if (rg == rgNumbers)
{
repaintNow();
new MessageBox("SuperWaba","Number selected:
"+r.getText()).popupModal();
}
else
// no RadioGroup; we have to handle by ourselfes
if (r == rEna)
{
rEna.setChecked(true);
rDis.setChecked(false);
rDis.setEnabled(true);
}
else
if (r == rDis)
{
rEna.setChecked(false);
rDis.setChecked(true);
rDis.setEnabled(false);
}
}
break;
...
waba.ui.ScrollBar
ScrollBar is a control that can be used when you want the user to select a value
from a range of values. It consists of two arrow buttons and one bar that can be dragged
to make scrolling easier. The ScrollBar can be horizontal or vertical. Below are some
other features:
There are two constructors: the default one constructs a vertical ScrollBar. The
other one receives as parameter a constant defining the orientation:
ScrollBar.HORIZONTAL or ScrollBar.VERTICAL.
The following constraints can be set:
o maximum (setMaximum and getMaximum): maximum value of the
ScrollBar.
SuperWaba Companion
71
There's a way to change the ScrollBar's default width: you must play with the
Button.commonGap, which is a static member from the Button class (see chapter 6,
waba.ui.Button), and the extraArrowSize, which is a static member from the ScrollBar
class. The Button.commonGap increases the size of the button inside the ScrollBar, and
the ScrollBar.extraArrowSize increases the size of the arrow inside the Button.
After the ComboBox creation, you must reset them to 0, otherwise they will affect all future
ComboBoxes and Buttons created.
Next you see how the preferred size is computed for both ScrollBar types:
arrow
button's
height
d
arrow button's
height
1
pixel
arrow
button's
width
arrow
button's
height
1 pixel
arrow
button's
width
arrow button's
width
The blue rectangles represent the arrow buttons. The yellow rectangles represent the
bars.
SuperWaba Companion
72
In ScrollBar, the preferred size is the minimum size. If you set the size below this
value, the ScrollBar will not be drawn correctly.
Below you see a code example for the ScrollBar, taken from the ScrollBar.java file:
add(sb1 = new ScrollBar(ScrollBar.HORIZONTAL));
sb1.setLiveScrolling(true);
sb1.setRect(LEFT,TOP+5, 60, PREFERRED);
add(sb2 = new ScrollBar(ScrollBar.VERTICAL));
sb2.setRect(LEFT+15, AFTER+5, PREFERRED, 60);
ScrollBar sb3 = new ScrollBar();
add(sb3);
sb3.setRect(SAME, AFTER+5, PREFERRED, 30);
sb3.setVisibleItems(20);
sb3.setEnabled(false);
Windows CE
PalmOS
SuperWaba Companion
73
Since WinCE devices dont have a menu key, the ACTION key, if not intercepted by
the user, is used to open the menu.
The user can disable this by setting Vm.actionEqualsMenu to false.
The MenuBar is assigned per Window. This means that each window can have its
own menu bar. Because the Window.menuBar member is a waba.ui.Control, you may use
third party menu controls with the Window. When the user activates the menu, the
Window class calls the menuBar.setVisible method. This makes the popup action
generic enough to use any menu control available.
The menu bar is always placed at position 0,0 on screen, regardless if it belongs to the
MainWindow or to a popup window. This increases the available area for the captions.
Currently MenuBar and PopupMenu have only the look and feel of PalmOS. To make
it more beautiful in Windows CE and in Color devices, you can use the methods
MenuBar.setPopColors and MenuBar.setCursorColor.
The items are vertically grouped in a String array, where the first item of the array
is the caption that is used by the MenuBar control and the others are the items used in the
PopupMenu control. A menu is composed of a matrix of Strings, assigned in the only
available constructor. Although not a good design practice, storing items in a String
instead of a class (like MenuItem) makes the program faster and lowers the memory
usage.
Here are some features of the menu classes:
SuperWaba Companion
74
The menu item must be set as checked when constructing the menu, it cannot be
changed from a simple item to a checked item at runtime, or the width of the popup menu
will not be correctly computed.
Below you can see an example, taken from the MenuExample.java file:
String col0[] =
{
"Caption0",
"*Item1", // disabled
"-",
// item2
"?Item3_checkable", // checkable
};
String col1[] =
{
"Caption1",
"Item1 - popup",
"Item2",
};
String col2[] =
{
"Caption2",
"Item1",
"Item2",
"Item3",
"Item4",
"Item5",
};
SuperWaba Companion
75
Mono device
Color device
When the user clicks on a menu item, the window closes. You must handle the
ControlEvent.WINDOW_CLOSED event and discover which item was chosen. You may
use the value returned by the getSelectedMenuItem method as the index of a switch
statement.
public void onEvent(Event event)
{
switch (event.type)
{
case ControlEvent.WINDOW_CLOSED:
String sel = null;
if (event.target == mbar)
switch (mbar.getSelectedMenuItem())
{
case -1: break; // no item selected
case
1: sel = "Caption 0 - Item 1 - cannot be clicked
(disabled)"; break;
case
3: sel = "Caption 0 - Item 3 "+mbar.isChecked(3); break;
case 101: sel = "Caption 1 - Item 1";
new WindowWithMenu().popupModal(); break;
case 102: sel = "Caption 1 - Item 2"; break;
case
case
case
case
case
201:
202:
203:
204:
205:
sel
sel
sel
sel
sel
=
=
=
=
=
"Caption
"Caption
"Caption
"Caption
"Caption
2
2
2
2
2
Item
Item
Item
Item
Item
1";
2";
3";
4";
5";
break;
break;
break;
break;
break;
}
edSel.setText(sel != null ? (mbar.getSelectedMenuItem()+" - "+sel)
: "");
break;
}
}
SuperWaba Companion
76
waba.ui.PushButtonGroup
The PushButtonGroup is a very powerful control. Below you see some of its
features:
SuperWaba Companion
77
As any other control, the font can be changed after the constructor is called and before
the setRect is called.
Below is how the preferred size is computed:
(maximum text width + insideGap) if allSameWidth,
(text width + insideGap) otherwise.
text height +
(2 if simpleBorder)
pushbutton
gap
gap
The controls total width is the sum of all pushbuttons widths and gaps, minus one gap;
and the controls total height is the sum of all pushbuttons heights and gaps, minus one
gap.
Next you see an example, taken from the PushButtonGroupExample.java file:
// PushButtonGroup(String[] names, boolean atLeastOne,
// int selected, int gap, int insideGap, int rows,
// boolean allSameWidth, byte type)
pbg1 = new PushButtonGroup(items1,false,-1,-1,6,4,true, PushButtonGroup.BUTTON);
add(pbg1,LEFT,TOP+2);
pbg2 = new PushButtonGroup(items1,false,-1,-1,6,4,true, PushButtonGroup.BUTTON);
pbg2.setSimpleBorder(true);
add(pbg2,AFTER+10,SAME);
pbg3 = new PushButtonGroup(items1,false,-1,-1,6,4,true, PushButtonGroup.BUTTON);
add(pbg3,AFTER+10,SAME);
pbg3.setEnabled(false);
pbg4 = new PushButtonGroup(items1,false,-1,-1,6,4,true, PushButtonGroup.BUTTON);
pbg4.setSimpleBorder(true);
add(pbg4,AFTER+10,SAME);
pbg4.setEnabled(false);
pbg5 = new PushButtonGroup(items2,false,-1,4,6,1,false, PushButtonGroup.CHECK);
add(pbg5,LEFT,AFTER+3,pbg1); // positioning relative to pbg1
pbg6 = new PushButtonGroup(items3,false,-1,1,6,1,false, PushButtonGroup.NORMAL);
add(pbg6,RIGHT,AFTER+3);
pbg7 = new PushButtonGroup(items4,false,-1,3,10,3,true, PushButtonGroup.NORMAL);
add(pbg7,CENTER,AFTER+3);
lab = new Label("",CENTER);
add(lab);
lab.setRect(CENTER,AFTER+3,100,PREFERRED);
SuperWaba Companion
78
WindowsCE
PalmOS
waba.ui.TabPanel
This control consists of some tabs and a container attached to each tab. When a
tab is clicked, the current container is removed and the tabs container is added. This
control is used to save space when you have many controls that can be grouped together
and placed in different containers. Below you see some features:
There is only one constructor. It receives a String array with the captions for the
tab. For each caption, one Container is created for it. As default, the first tab is
made active.
Tabs can be placed on top or on bottom. Therefore, you can use the setType
method giving the constants TabPanel.TABS_TOP and
TabPanel.TABS_BOTTOM.
The tabs are drawn with the controls backColor unless you specify the color for
each tab using the setPanelsBackColor(Color []backColors) method.
This method receives a waba.fx.Color array and the number of colors must
match the number of captions.
The captions color may be changed by using the setCaptionsColor method.
There's two public members:
SuperWaba Companion
79
o beepOn (true as default) that controls if a beep will sound when the a tab is
clicked.
o lastActiveTab: Stores the last active tab index, or -1 if none was
previously selected.
Here are some other useful methods:
o getPanel(int i): used to return the asked Container. It is used when
adding controls to the container.
o setType(int type): can be TAB_TOP or TAB_BOTTOM, and specify
where the tabs will be placed.
o setGaps(int gapL, int gapR, int gapT, int gapB): used to set
the gaps (Left, Right, Top, Bottom) between the containers and the
TabPanel.
o setBorderStyle(byte style): used to set the type of border for the
TabPanel. You can use, as parameters, the Window.NO_BORDER (that only
draws a line under the tabs) and Window.RECT_BORDER (default).
o setPanel(int i, Container container): Replace the default
created container of index i with the given one. By using this you can avoid
adding a container to a container and avoid wasting memory and time. Note
that you must do this before the first setRect for this tabPanel, otherwise,
you must explicitly call setRect in the TabPanel again to update the added
container bounds.
o setActiveTab(int tabIndex): Sets the currently active tab, switching
the containers.
o setCaptionColor(Color c) and setPanelsBackColor(Color
[]backColors): Used to set the color for the tabs and set the background
color for each panel.
o getClientRect: returns the rect where the containers are placed,
excluding title and borders.
Below is described how the preferred size is computed:
Text height + 4
20
SuperWaba Companion
80
lWarn.setRect(LEFT,BOTTOM,FILL,PREFERRED);
// now add the TabPanel placing it in all client rect
// but no overlapping the warning
String []captions = {"Name/Tel.","Address"};
add(tp = new TabPanel(captions));
tp.setGaps(2,2,2,2); // before calling tp.setRect
tp.setRect(getClientRect().modifiedBy(0,0,0,lWarn.getPreferredHeight()));
// panel 0
tp.setPanel(0, new NameTel());
// panel 1
Container c = tp.getPanel(1);
c.add(new Label("Addr1:"),LEFT+5,TOP+5);
c.add(edAddr1 = new Edit(""),AFTER+5,SAME-1);
c.add(new Label("Addr2:"),LEFT+5,AFTER+10);
c.add(edAddr2 = new Edit(""),AFTER+5,SAME-1);
TabPanel has the same look and feel in both user interface types. Here is the
screen shot of the output:
SuperWaba Companion
81
waba.ui.MessageBox
This one is a popup window used to show a text in a label with some user-defined
buttons (like <Ok> and <Cancel>). Here are some characteristics of this control:
SuperWaba Companion
82
MessageBox has the same look and feel in both user interface styles. Here is some
output:
SuperWaba Companion
83
}
break;
}
waba.ui.InputDialog
This one is a popup window used to get a text input from the user. It shows text in a
label, the Edit and some user-defined buttons (like <Ok> and <Cancel>). Here are some
characteristics of this control:
SuperWaba Companion
84
waba.ui.Grid
The Grid class is used to display tabulated data, which is represented as a String
matrix (each row is a String array). Here are some features:
Vertical scrollbar, used to scroll up and down the information on the grid.
Horizontal scrolling in case the columns widths are grater than the screen width
An easy to use interface for adding/removing information to the grid
Optional check column, this is a column that is clickable marking an specific line as
checked/unchecked, this is useful if you want the user to be able to select multiple lines
displayed on the grid.
Columns can be resized so that the user can see all the information displayed in a
given column
Style configuration, you can set the color of captions boxes all the way thru the stripes
colors and vertical line types. The grid is compatible with your application's style (Flat,
WinCE, etc... )
SuperWaba Companion
85
String []gridCaptions = {"Caption 1", "Caption 2", "Caption 3", "Caption 4",
"Caption 5", "Caption 6", "Caption 7" };
int ww = fm.getTextWidth("xxxxxxxxx");
int gridWidths[] = {ww, ww, ww, ww, ww, ww, ww};
int gridAligns[] = { LEFT,LEFT,LEFT,LEFT,LEFT,LEFT,LEFT};
grid = new Grid( gridCaptions, gridWidths, gridAligns, false );
grid.firstStripeColor = Color.GREEN;
grid.secondStripeColor = Color.YELLOW;
grid.verticalLineStyle = Grid.VERT_NONE;
add( grid );
grid.setRect( LEFT, AFTER+2, FILL, FIT, btnRemove );
String items[][] = new String[4][7];
for( int i = 0; i < 4; i++ )
for( int j = 0; j < 7; j++ )
items[i][j] = "BRAZIL "+j;
grid.setItems( items );
SuperWaba Companion
86
Windows can have a title that is set in the setTitle method or in the constructor.
The window border can be selected from multiple styles by using the
setBorderStyle method or in the Window constructor. Below you see the possible
styles:
NO_BORDER
RECT_BORDER
TAB_BORDER
ROUND_BORDER
TAB_ONLY_BORDER
There are two constructors: the default one, that creates a Window with no title and
no border, and one constructor with both title and border parameters.
Windows can be moved around the screen by dragging the windows title. If the
window has no title, it cant be moved. You can make a titled window unmovable by
calling the makeUnmovable method.
The title font can be changed using the setTitleFont method. By default, the
font is the one used by MainWindow, with bold style.
Windows can be double buffered. This means painting occurs first in an image
buffer and when finished, the image is drawn on the screen. This can speed up
drawing and make its appearance smoother. This feature can be activated by
SuperWaba Companion
87
calling the setDoubleBuffer method. The image in the buffer can be obtained
through the getOffScreen method.
Only one control can hold the focus at a time. To change focus to another control,
use the setFocus method (this can also be done through the requestFocus
method in the waba.ui.Control class). The getFocus method returns the
control that currently owns the focus.
The rectangle area excluding the border and the title is defined as the client
rectangle. You can get it with the getClientRect method.
A window can be popped up by calling the popupModal method and can be
unpopped by calling the unpop method.The popup process saves the area behind
the Window that is being popped up and the unpop process restores that area. The
unpop method posts a ControlEvent.WINDOW_CLOSED event to the caller
window. The popupModal method can be called like this.popupModal().
A window can also be popped up by calling the popupBlockingModal method,
and be unpopped by the same unpop method described above. The big difference
is that in popupModal, the program execution continues to the next line, while in
popupBlockingModal, the program execution is halted and only continues when
the popped up Window is dismissed. Menu, MessageBox, ComboBox and PopLists
are popped up using popupModal, because execution does not need to be halted.
InputDialog, Calendar, Calculator, usualy are popped up using
popupBlockingModal because the user may want to get the result of the dialog
in an easy way.
You can't use popupBlockingModal to popup alternating windows that call each
other recursively. For example, suppose that from Win1 you call
win2.popupBlockingModal(), then at Win2 you call unpop and then
win1.popupBlockingModal(). Then, from Win1 you do unpop again and
win2.popupBlockingModal(), and so on. This will lead to a hard reset on the device
due to a native stack overflow. To fix this, just replace the popupBlockingModal by
popupModal.
The topmost window (the one who receive events) can be obtained with the static
method getTopMost. To check if this window is the topmost, use the
isTopMost method.
You may check if this window is visible using the isVisible method. This method is
inherited from waba.ui.Control, but it simply checks if the current window is the
topmost one.
Using the setStatePosition method can show PalmOS Grafitti state characters. To
hide it, call setStatePosition(HIDE_STATE,HIDE_STATE). This method is
also used in Windows CE and Pocket PC to show/hide the virtual keyboard (when
applicable). Just use as parameter VK_HIDE, VK_TOP and VK_BOTTOM to hide,
display the virtual keyboard at top of the screen or at the bottom of the screen.
Note that this will have no effect in devices that don't have a virtual keyboard.
Each window can have a menu attached by using the method setMenuBar. The
menuBar can be made visible programmatically by calling the popupMenuBar
method.
Suppose you wish to allow the user to abort a task being executed by pressing.
You can use the method pumpEvents to process all events in the queue.
SuperWaba Companion
88
If you divide your application logic to classes that extend Container and are
displayed one at a time in the MainWindow, you can use the method swap to make
things easier to manage. See samples/ui/ContainerSwitch in the SDK for a good
example.
The methods getPreferredWidth and getPreferredHeight have a special
meaning for the Window class. They return the minimum width/height needed for
the correct display of this Window. The getPreferredWidth returns the width of
the title (if any) plus the width of the border (if any). The getPreferredHeight
returns the height of the title (if any) plus the height of the border (if any).
As already mentioned, the contents behind the window being popped up are saved
so they can be restored later. They are saved using the saveBehind method and
restored by using the loadBehind method. This last one has a parameter that, if
true, releases the memory used in the backup operation. You can explicitly avoid
the save operation by calling the dontSaveBehind method. It is useful when you
popup a Window in the constructor of the application, before the controls have
been drawn. High resolution devices may have some memory problems after a few
popped up windows, so disabling this feature can be useful. This method has a
parameter, repaintOnClose, that:
o if true, the parent window is fully repainted when the window is unpopped.
o if false, nothing is done when the window unpops and you must handle the
restore/repaint by yourself.
SDL devices (Windows CE, Windows 98/2K/XP and Epoc) have no direct-screen
access. To update the screen after something is changed, you must call the static
method updateScreen. This method is already called by the system when an area
is invalidated and by the repaintNow method in class Control.
There are some useful protected methods that may be implemented by controls
that extend waba.ui.Window. Those methods are placeholders and there is no need to
call the super method.
onClickedOutside(int x, int y): This method is used in popup windows. If the user
clicks outside the windows bounds, this method is called giving the absolute
coordinates of the clicked point. There are two options:
o If you had handled the action, return true in this method.
o Otherwise, false must be returned and if the beepIfOut member is true, a
beep is played (in other words, beepIfOut can be set to false to disable this
beep).
onPopup(): Called just after the behind contents are saved and before the popup
process begin. When this method is called, the topmost window is still the parent of
the Window being popped up.
postPopup(): Called after the popup process ended. When this method is called,
the popped up window is fully functional. It is a good place to put a
control.requestFocus() to make the window popup with the focus in a default
control.
onUnpop(): Called just before the unpop process begin.
postUnpop(): Called after the unpop process ended. When this method is called,
the unpopped window has gone away and the parent Window is currently the
topmost.
SuperWaba Companion
89
Some other important members of the Window class are explained here:
boolean needsPaint: true if there are any controls marked for repaint.
boolean flicker: if true, the background area is erased during the repaint
process. This causes flickering if the window is not double buffered.
Window topmost: stores the topmost Window.
boolean canDrag: if true and if this is a popup window, the user is allowed to
drag the title and make the window move around.
boolean highResPrepared: This extremely important member is used when
your program runs in devices with a screen resolution greater than the default
160x160 of Palm OS. Some devices have 320x320, 240x320, etc. For each device,
the font is usually proportional to the resolution. Since SuperWaba programs are
placed in a relative way, and since the relativeness depends on the Window's size,
your popped up Window would look squashed because the Windows bounds are
usualy set with an absolute coordinate. To avoid this, the Window manager checks
if your Window is prepared for high resolution devices (i.e., you tested it against
other resolutions and set the right value for the Window depending on each case).
If your Window is not prepared, then the setRect method will multiply the size of
the Window by a factor that depends on how much the screen resolution has
changed from the basic 160x160 (E.g.: in a 240x320 device, a 80x40 Window will
be changed to 120x80). Also, the window will be centered on screen. So, if you
have tested your Window in other resolutions, set this flag to true.
Never mess with the public member zStack. It is used to store the windows that are
currently popped up. It is made public because the waba.applet.Applet class uses it.
A very common mistake is to popup a Window without setting its bounds. If no bounds
are set, the window will not receive events.
Next is explained how controls inside a Window are repainted:
1. The programmer calls the repaint method of some controls, or a control is clicked
and marks itself for repaint.
2. The damageRect method in class Window creates a rectangle (stored in the
paintX, paintY, paintWidth and paintHeight members) with the union of
the bounds of all controls marked for repaint.
3. The next time a VM event is posted, the _doPaint method of the topmost window
is called. This method paints the windows title/border (if any) and calls the onPaint
method of all containers and controls that lies inside the rectangle area marked for
repaint. This explains why nothing in the window is updated when you receive
events directly from a native library (the Scanner class, for example). Because the
VM is not receiving the event, it never validates the window. In these cases, you
must update the window yourself, calling repaintNow or the validate methods.
Many classes in the waba.ui package extend waba.ui.Window. Examples of such
classes are waba.ui.Calculator and waba.ui.Calendar. Other good examples are
waba.ui.MessageBox and waba.ui.PopList.
It's important to be aware that it is not a good practice to create classes that extend
SuperWaba Companion
90
Window if they will occupy the whole screen, because they use a lot of memory to store
the underlying area. Opening the menu may lead to time-consuming redraws of all
opened windows due to out-of-memory problems. In these cases, it is better to extend
waba.ui.Container, as explained in chapter 10.
SuperWaba Companion
91
waba.ui.Calculator
This class implements a very simple calculator. It lets you enter two numbers,
select an operation and compute the result. Youre then able to paste the result or the first
operand.
The Calculator class can be used standalone. Just pop it up and get the pasted
result by using the getAnswer method. The formatting precision of each entered number
is defined by the decimalPlaces public field. The code below shows an example taken
from the onEvent method in the CalculatorExample.java file:
public void onEvent(Event event)
{
switch (event.type)
{
case ControlEvent.PRESSED:
if (event.target == btn)
{
if (calc == null)
calc = new Calculator();
calc.popupModal();
}
...
}
SuperWaba Companion
Windows CE
92
PalmOS
waba.ui.Calendar
This is a calendar where a date can be chosen. It pops up with the current day as default
and the user can scroll through the month/years. When a day is selected the window
closes and the chosen date is pasted into the Edit.
The Calendar control can be used standalone, as it shows the example below,
taken from the onEvent method in CalendarExample.java file:
public void onEvent(Event event)
{
switch (event.type)
{
case ControlEvent.PRESSED:
if (event.target == btn)
{
if (cal == null)
cal = new Calendar();
cal.popupModal();
}
}
When the window is closed, you can handle the ControlEvent.WINDOW_CLOSED event
to get the results.
public void onEvent(Event event)
{
switch (event.type)
{
case ControlEvent.WINDOW_CLOSED:
if (event.target == cal)
{
Date d = cal.getSelectedDate();
lab.setText(d==null?"no date choosen":d.toString());
}
/*cal = null;
Note: If your program uses the Calendar control only a few
times, i suggest that you set cal to null so it can get garbage
collected. Calendar objects waste memory and it is always a
good idea
to save memory when possible*/
break;
}
}
SuperWaba Companion
93
Windows CE
PalmOS
waba.ui.Keyboard
This class replaces the original PalmOS keyboard. The original keyboard cannot
be used in Java because it is restricted to use with original PalmOS controls. The
waba.ui.Keyboard contains all characters from the original keyboard plus some other
keys. It can also be easily extended to other languages. It currently supports the following
languages, set with the method setLanguage:
LANG_NORMAL (Americas)
LANG_GERMAN
LANG_HEBREW
LANG_TURKISH
The Keyboard class cannot be used standalone; it can only be used if called from
inside an Edit control. Below are snap shots of both styles:
Windows CE
PalmOS
SuperWaba Companion
94
Now we need to fill our containers with controls. We will do this with the method
onStart, the same one that we normally use in the MainWindow class. You may be
asking: why can't we add the controls to the classes constructors? The answer is simple:
because in the contructor, the size and parent of CDEdit and CDSearch are unknown.
Why is this information so important? First, without the size you will not be able to use
relative positioning. Second, without the parent you will not be able to create a Graphics
object and use some relative positioning options.
So, we can now use the onStart method to initialize our containers:
public class CDEdit extends waba.ui.Container
{
public void onStart()
{
...
}
}
public class CDSearch extends waba.ui.Container
{
public void onStart()
{
...
}
}
We have our containers filled with controls, and can now handle the events in the
onEvent method. For example:
SuperWaba Companion
95
Now we must, of course, create our MainWindow, which will control the flow of the
application.
public class CDTeca extends waba.ui.MainWindow
{
static CDSearch cdsearch;
static CDEdit cdedit;
public CDTeca()
{
super(CDTeca, TAB_BORDER);
setDoubleBuffer(true);
}
public void onStart()
{
// now we get our client rect, excluding the border and the title
Rect r = getClientRect();
cdedit = new CDEdit();
cdedit.setRect(r);
cdsearch = new CDSearch();
cdsearch.setRect(r);
swap(cdsearch); // <-- here, the onStart method of CDSearch will be
called
}
}
At some point of the program, we will need to swap out the CDSearch container
and replace it with the CDEdit container. This can be done in various ways, such as:
1. Menu invocation: you create two menu options that, when chosen, swaps in the other
container.
2. At some event of cdsearch, it asks the main window to swap it out and swap in cdedit.
E.g.: MainWindow.getMainWindow().swap(CDTeca.cdedit). We can do this
because cdedit is a static member. If it was not a static member, we could do:
((CDTeca)MainWindow.getMainWindow()).cdedit to access the cdedit
member.
When you have only two or three containers that will be switched in the whole
application, you can use the TabPanel class to automate the swap for you. For example,
look at this:
SuperWaba Companion
96
TabPanel tp;
public void onStart()
{
tp = new TabPanel(new String[]{Edit,Search});
tp.setRect(getClientRect());
tp.setPanel(0, new CDEdit());
tp.setPanel(1, new CDSearch());
}
The TabPanel will automatically set control's bounds and call the onStart method.
It is recommended that your class extend Window instead of Container only when its
size will be smaller than the screen's size. Using Containers saves a lot of system
resources.
There are some useful methods in the Container class:
SuperWaba Companion
97
SuperWaba Companion
98
Overview
The purpose of this part is to teach you how to use the classes in the waba.io
package. The classes that will be covered in this tutorial are outlined below:
a) waba.io.SerialPort: used to send and receive bytes via Serial cradle, USB, IrComm
and Bluetooth.
b) waba.io.Socket: used to send and receive bytes via a TCP/IP connection.
c) waba.io.File: used to create files and manage directories.
d) waba.io.Catalog: used to store data on the handheld
waba.io.ByteArrayStream: a resizable buffer that can be used to feed data to a
stream or to store data coming from a stream. It can be used to emulate a virtual
stream.
waba.io.DataStream: used to read/write primitive types and Strings.
waba.io.ResizeStream: used when creating a Catalog record of unknown size.
When output to the record is complete, the ResizeStream shrinks the record to the
optimal size.
waba.util.IntHashtable: used to speedup the search of a record inside a Catalog,
given a key representing the record contents. (Just a brief overview).
waba.io.Stream: is the main Class of all classes inside the waba.io package. It can
be viewed as a generic stream where data can flow in and out of the device. All
classes inside package waba.io extend this Class, and most classes receive a
waba.io.Stream in their constructor parameter. This allows you to combine different
streams to meet your needs.
For example, you can attach waba.io.ResizeStream to waba.io.Catalog and then
attach waba.io.DataStream to waba.io.ResizeStream, so you can store and retrieve
primitive types from the Catalog.
Another example is to use waba.io.DataStream attached to
waba.io.ByteArrayStream. This lets you write primitive types to a virtual stream, and then
send the buffer contents anywhere.
In the first chapter, youll see the methods inside waba.io.Stream; next the
waba.io.Catalog class is described in detail (chapter 2), followed by the
waba.io.DataStream. Then in chapter 4 youll see waba.io.ResizeStream, and in chapter 5
you will see waba.io.ByteArrayStream. Chapter 6 describes an approach to deal with
large databases in SuperWaba. In Chapter 7 you will see waba.io.Sockets, then
waba.io.SerialPort. After this, in chapter 9 you'll see waba.io.File and, finally, in the last
chapter you will learn some tricks and tips.
SuperWaba Companion
99
Chapter 17 - waba.io.Stream
Stream is an abstract class that all other classes inside the waba.io package
extend. It defines the behavior that a stream must have. Below are shown the list of
methods in this class:
boolean close() - Closes the stream.
int readBytes(byte[] buf, int start, int count) - Reads bytes from the stream.
int writeBytes(byte[] buf, int start, int count) - Writes bytes to the stream.
boolean isOpen() - Returns true if the stream is still open.
The Stream is used as a connector between waba.io classes. Most classes in that
package receive a Stream as a parameter to the constructor. This way, when you connect
the streams Catalog ResizeStream DataStream, the DataStream calls the
ResizeStream readBytes which in turn calls the Catalog readBytes. In the same way,
DataStream.close calls ResizeStream.close which calls Catalog.close.
SuperWaba Companion
100
Chapter 18 - waba.io.Catalog
Catalog is the most important class of this package. It lets you store persistent data
into the underlying Palm OS database system.
Starting in SuperWaba 3.0, the PDB file that the Catalog class represents was
made cross-platform. This means that a catalog created in Palm OS will be read in
Windows CE/Pocket PC, and vice-versa.
A catalog is the most rudimentary kind of database system. It is just an array of
records. Each record can have a distinct size. There are no user indexes, no table
definition, no field definition, nothing. Only you and your program know the format and the
contents of each record. From the operating systems point of view, the record content is
just raw data.
A PDB database has two components: First is an array of record handles that is
resized, as records are added/deleted. Second is the collection of chunks in the
database heap. If your database has all of its chunks the same size, then you might be
able to reduce the chance of memory fragmentation, but because all of the chunks in
the database heap can be moved around when unlocked, this isn't a huge concern
(although it might have problems on Palm OS 1.0 and 2.0, because fragmentation is
more of a problem with multiple 64K heaps).
The figure below shows the two possible kinds of catalogs:
Record 0
Record 1
Record 2
Record 3
Record 4
Record 5
All records same size
Record 0
Record 1
Record 2
Record 3
Record 4
Record 5
Each record of a different size
Theres no really performance loss when dealing with different record sizes.
Catalogs have some size restrictions:
In Palm OS, the number of records, not the size of the file, mostly determines the
length of time a PDB file takes to install on the device. Having more records greatly
increases the time required for a hotsync with that database, even for installation or
backup. A 1MB PDB with 50 records would install much quicker than a 1MB PDB with
10,000 records. Consider this when creating big databases; youll probably drop your
hotsync time from several hours to a few minutes.
SuperWaba Companion
101
Starting in Palm OS 3.0, there is a new type of storage called File. Files can be greater
than 64Kb, but the truth is that files are emulated using a catalog. This makes the access
of data inside the File slower than if dealing directly with catalogs.
Below is shown a basic approach to deal with catalogs inside a program:
Step 2 is needed because a catalog can have many records, and you must set the
current record before storing or retrieving data.
In the device, if the program does not explicitly close a catalog, it will be closed when
the object is garbage collected or when the program exits.
Note that this is not true under JDK, because under the JDK finalize does not work
well. In the desktop, if you dont close the catalog, nothing is written to disk. Starting with
version 3.2, the catalog is closed when the application exits normally. But if you abort the
Java appliction by pressing ^c in the DOS shell without explicitly closing the catalog,
nothing is saved).
Although the Catalog class has two constructors, only one is available for users:
public Catalog(String name, int mode)
In this constructor, you give the name of the catalog and the mode to open the
catalog. The available modes are READ_ONLY, WRITE_ONLY, READ_WRITE,
CREATE, which are self-explanatory. But there are some things you must know:
4. In all platforms, READ_ONLY, WRITE_ONLY, READ_WRITE, have all the
same effect. In Palm OS, since there are no concurrent operations, theres no
need to open it in exclusive modes. In Windows CE/32 and Symbian, the file
must be created in RW mode because the Catalog emulation has to save
information on the disk.
5. When CREATE is used,
a. If the catalog exists, it is not re-created, but remains the way it is and the
mode is changed to READ_WRITE.
b. If the catalog doesnt exist, it is created and the mode is changed to
READ_WRITE.
To test if a catalog exists, open it with READ_ONLY and call the isOpen method.
Now lets take a deeper look at the name parameter. It t may match the following
pattern:
name.CRTR.TYPE
SuperWaba Companion
102
Useful tips
Some useful tips when dealing with databases:
If your record stores lots of information, put the relevant ones (the ones that may
be used in searches) in the beginning.
When storing dates that will be used as keys, store them as integers in the format
YYYYMMDD (E.g.: 19700325) as the first information of the record. With this, you
may keep the database ordered and do a binary search just by comparing the first
int.
See the methods findString and findInteger in this tutorial.
SuperWaba Companion
103
It's better to write lots of Strings in one record than only one String in different
records. The write and read times are less for the former.
The Catalog.inspectRecord is faster than a (Catalog.setRecordPos +
Catalog.readBytes).
If you want to save the state of your application when exiting, use
Settings.appSettings instead of writing them to a Catalog; its handier.
Dont call hashCode in arrays ([]) of objects or primitive data types: in
SuperWaba, if you call myArray.toString() or myArray.hashCode() youll
get a fatal error on the device.
Remember: writing for PDAs require you to do good software engineering. Dont
store unnecessary information on the PDA.
If you open a Catalog for read only, don't use Catalog ResizeStrem
DataStream, but attach the DataStream directly to the Catalog. You'll have a 6%
speed improvement.
addRecord
public int addRecord(int size)
Adds a record to the end of the catalog. If this operation is successful, the position
of the new record is returned and the current position is set to the new record. If it
is unsuccessful the current position is unset and -1 is returned.
Parameters:
size - the size in bytes of the record to add
addRecord
SuperWaba Companion
104
Adds a record to the specified position of the catalog, shifting up all the other
records. If this operation is successful, the position of the new record is returned
and the current position is set to the new record. If it is unsuccessful the current
position is unset and -1 is returned.
Just as an historical note, this was the first method implemented in the very first
version of SuperWaba, on 06/30/2000.
Parameters:
size - the size in bytes of the record to add
close
public boolean close()
Closes the catalog. Returns true if the operation is successful and false otherwise.
Overrides:
close in class Stream
SuperWaba Companion
105
c.close();
delete
public boolean delete()
Deletes the catalog. Returns true if the operation is successful and false otherwise.
Note that this behavior is different when running on the desktop and running on the
device, because in applets we cannot erase files on the server, in this case all the
records are deleted, but the file still exists, with the palm-info-header. The file will
be deleted only if you're running as an application on the desktop.
listCatalogs
public static String[] listCatalogs()
Below is an example:
String []catalogs = Catalog.listCatalogs();
// need to check for null because some databases can't be
// read, thus null is returned in place
int n = catalogs.length;
for (int i = 0; i < n; i++)
// must test with null. Is this a SuperWaba application?
if (catalogs[i] != null && catalogs[i].endsWith("Wrp2"))
Vm.debug(catalogs[i]+ is a SW app!);
SuperWaba Companion
106
getRecordCount
public int getRecordCount()
Returns the number of records in the catalog or -1 if the catalog is not open.
isOpen
public boolean isOpen()
Returns true if the catalog is open and false otherwise. This can be used to check if
opening or creating a catalog was successful.
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
...
rename
public boolean rename(String newName)
Renames the currently open catalog to the given name. You can use it to change
the creator and/or type if needed. The name must be in the form
"MyNewCatalogName.CRTR.TYPE".
On the desktop only, the old file may remain if deletion is not possible (in other
words, on the desktop the rename operation may work like a "copy oldName
newName").
SuperWaba Companion
107
setRecordPos
public boolean setRecordPos(int pos)
Sets the current record position and locks the given record. The value
-1 can be passed to unset and unlock the current record. If the operation is
successful, true is returned and the read/write offset is set to the beginning of the
record. Otherwise, false is returned.
Always test that the method return true.
inspectRecord
public int inspectRecord(byte[] buf,
int recPosition)
Inspects a record. Use this method with care, as none of the parameters are
checked for validity. Neither the offset nor the current record positions are changed
SuperWaba Companion
108
by this method. This method must be used only for a fast way of viewing the
contents of a record, such as searching for a specific header or filling a grid of
data. buf.length bytes (at maximum) are read from the record into buf. Returns the
number of bytes read (can be different from buf.length if buf.length is greater than
the record size) or -1 if an error prevented the read operation from occurring.
getAttributes
public int getAttributes()
Retrieves this catalog's attributes. The DB_ATTR_xxx masks are used to retrieve
its states:
DB_ATTR_READ_ONLY: If set, the database is read-only.
DB_ATTR_APPINFODIRTY: If set, the database has been modified since last
hotsync.
DB_ATTR_BACKUP: If set, the database will be backed up in the next hotsync if
no application conduit is available.
DB_ATTR_OK_TO_INSTALL_NEWER: The backup conduit can install a newer
vesion of this database with a different name if the current database is open.
DB_ATTR_RESET_AFTER_INSTALL: The hotsync application forces a reset after
installing this database.
DB_ATTR_COPY_PREVENTION: Dont let this application be beamed or copied to
another device.
DB_ATTR_STREAM: This database is a file stream.
SuperWaba Companion
109
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.READ_WRITE);
if (c.isOpen())
{
int attr = c.getAttributes();
boolean isReadOnly = (attr & Catalog.DB_ATTR_READ_ONLY) != 0;
boolean isDirty
= (attr & Catalog.DB_ATTR_APPINFODIRTY) != 0;
boolean toBackup
= (attr & Catalog.DB_ATTR_BACKUP) != 0;
boolean canInstall = (attr & Catalog.DB_ATTR_OK_TO_INSTALL_NEWER) != 0;
boolean pleaseReset= (attr & Catalog.DB_ATTR_RESET_AFTER_INSTALL) != 0;
boolean cantCopy
= (attr & Catalog.DB_ATTR_COPY_PREVENTION) != 0;
boolean isStream
= (attr & Catalog.DB_ATTR_STREAM) != 0;
}
setAttributes
public void setAttributes(int attrs)
Sets this catalog's attributes, defined by the DB_ATTR_xxx constants. The original
attributes must be retrieved prior to applying this value. If not, you can lose your
database and your app will crash.
getRecordPos
public int getRecordPos()
And now, well see the actions that can be done with the records.
SuperWaba Companion
110
getRecordSize
public int getRecordSize()
Returns the size of the current record in bytes or -1 if there is no current record.
resizeRecord
public boolean resizeRecord(int size)
Resizes a record. This method changes the size (in bytes) of the current record.
The contents of the existing record are preserved if the new size is larger than the
existing size. If the new size is less than the existing size, the contents of the
record are also preserved but truncated to the new size. Returns true if the
operation is successful and false otherwise.
Parameters:
size - the new size of the record
SuperWaba Companion
111
deleteRecord
public boolean deleteRecord()
Deletes the current record and sets the current record position to -1. The record is
immediately removed from the catalog and all subsequent records are moved up
one position.
readBytes
public int readBytes(byte[] buf,
int start,
int count)
Read bytes from the current record into a byte array. Returns the number of bytes
actually read or -1 if an error prevented the read operation from occurring. After the
read is complete, the number of bytes written advances the offset of the current
record.
Overrides:
readBytes in class Stream
Parameters:
buf - the byte array to read data into
start - the start position in the array
count - the number of bytes to read
SuperWaba Companion
112
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
byte []b = new byte[2];
b[0] = 11; b[1] = 22; // lets fill the array with something.
c.addRecord(2);
c.writeBytes(b,0,b.length);
c.setRecordPos(c.getRecordPos()); // reset the offset to the beginning
c.readBytes(b,0,b.length);
Vm.debug(Record store +b[0]+,+b[1]);
}
writeBytes
public int writeBytes(byte[] buf,
int start,
int count)
Writes to the current record. Returns the number of bytes written or -1 if an error
prevented the write operation from occurring. After the write is complete, the
number of bytes written advances the offset of the current record.
Overrides:
writeBytes in class Stream
Parameters:
buf - the byte array to write data from
start - the start position in the byte array
count - the number of bytes to write
You must make sure that the record is large enough to hold the contents you
want to write. If it does not have enough space, you must use resizeRecord before
to resize the record. This is done automatically when using waba.io.ResizeStream.
SuperWaba Companion
113
skipBytes
public int skipBytes(int count)
Changes the offset in the current record by the given number of bytes. The offset
defines where read and write operations start from in the record. Returns the
number of bytes actually skipped or -1 if an error occurs.
Parameters:
count - the number of bytes to skip. Can be less than zero.
getRecordOffset
public int getRecordOffset()
Returns the internal record offset. You may use this value in conjunction with
the skipBytes method. Note that setRecordPos resets the offset to 0.
SuperWaba Companion
114
getRecordAttributes
public byte getRecordAttributes()
Retrieves the attributes of the current record. Use the REC_ATTR_xxx masks to
set/retrieve its states. Returns 0 if database doesnt exists.
setRecordAttributes
public void setRecordAttributes(byte attr)
Sets the attributes of the current record. Use the REC_ATTR_xxx masks to
set/retrieve its states.
SuperWaba Companion
115
if (c.isOpen())
{
if (c.setRecordPos(2))
c.setRecordAttributes(Catalog.REC_ATTR_DIRTY | REC_ATTR_SECRET);
}
setRecordOffset
public void setRecordOffset(int ofs)
getName
public String getName()
SuperWaba Companion
116
Chapter 19 - waba.io.DataStream
DataStream is a wrapper that you can place around any Stream such as a SerialPort,
Catalog, Socket, ByteArrayStream or ResizeStream, which lets you read and write
primitive SuperWaba data types like integers, floats, longs, doubles and Strings in a
simple and standardized manner.
Into the same record you can write integers, floats, longs, strings, or bytes, without the
need of a delimiter, as long as you read them back in the same order.
All methods that write values to the stream return the number of bytes written. For
example, the writeInt method returns 4 and writeDouble returns 8. This is useful to the
waba.io.ResizeStream class so it can know how many bytes the current record has and
expand/shrink as necessary. It may also be useful for you to do this control by yourself.
All Strings in SuperWaba are written and read in the Pascal format, with the length
first, followed by the char array. This approach was chosen because reading the length,
creating an array with that length and reading the char array at once is much faster than
reading byte per byte until the zero String end marker is found (like in the C format for
dealing with Strings). You must be aware of this because all other programs outside
SuperWaba (like servers, C programs and the internal databases as Memo, To-Do, etc)
use the C format.
The most common bug that happens when you read a String written in the C format
using the readString method (instead of the readCString one) is an out of memory
exception. This happens because the first two bytes, which would be letters, are
interpreted as the length of the String. Suppose you try to read SuperWaba\0. Su will
be read as the length of the String, in this case, 0x5375 = 21365 bytes!
The primitive data types are written in the big endian format (E.g.: 0x12345678 is
written as bytes 12 34 56 78), which is the format of the 68000 processor. Most other
programs, like the ones written for the Intel and Arm processors, use the little endian
format (E.g.: 0x12345678 is written as bytes 78 56 34 12). Be aware of this when
interchanging primitive types between platforms, like in TCP/IP and Serial connections,
and use the correct one (if you write using writeInt, read it using the analogous readInt).
To avoid the problems of compatibility mentioned above, it is recommended that you
always use the waba.io.DataStream to send and receive those primitives and Strings
between different platforms. You can use the following class to join the JDK and
SuperWaba streams. You can see the full class under the directory where this tutorial is.
public class JDKSWStream extends waba.io.Stream
{
/** Use this member to read or write primitive types. */
public waba.io.DataStream ds;
private java.io.InputStream is;
private java.io.OutputStream os;
/** Open the stream for input only */
public JDKSWStream(java.io.InputStream is)
SuperWaba Companion
{
this(is,null);
}
/** Open the stream for output only */
public JDKSWStream(java.io.OutputStream os)
{
this(null,os);
}
/** Open the stream for input and output */
public JDKSWStream(java.io.InputStream is, java.io.OutputStream os)
{
this.is = is;
this.os = os;
ds = new waba.io.DataStream(this);
}
/** Read from the input stream */
public int readBytes(byte buf[], int start, int count)
{
if (is != null)
try
{
is.read(buf,start,count);
return count;
}
catch (Exception e) {}
return -1;
}
/** Write to the output stream */
public int writeBytes(byte buf[], int start, int count)
{
if (os != null)
try
{
os.write(buf,start,count);
return count;
}
catch (Exception e) {}
return -1;
}
/** Close the underlying streams */
public boolean close()
{
try
{
if (is != null) is.close();
if (os != null) os.close();
} catch (Exception e) {}
return true;
}
}
117
SuperWaba Companion
118
java.io.FileOutputStream fos;
java.io.FileInputStream fis;
JDKSWStream jss;
// create first a file and feed it with data
fos = new java.io.FileOutputStream("test1.dat");
jss = new JDKSWStream(fos);
jss.ds.writeInt(25031970);
jss.ds.writeDouble(3.1416);
jss.ds.writeString("I'm being serialized!");
jss.close();
// now read from this file and send it to another file.
// Note that the input/output could also be a serial or tcp/ip connection
fis = new java.io.FileInputStream("test1.dat");
fos = new java.io.FileOutputStream("test2.dat");
jss = new JDKSWStream(fis,fos);
// read the stored values
int myInt = jss.ds.readInt();
double myDouble = jss.ds.readDouble();
// and send them to another stream
jss.ds.writeInt(myInt);
jss.ds.writeDouble(myDouble);
// read and write directly. Just as example.
jss.ds.writeString(jss.ds.readString());
// Dump values and close.
System.out.println("int: "+myInt);
System.out.println("double: "+myDouble);
jss.close();
} catch (Exception e) {e.printStackTrace();}
}
Next we show all methods and constructors for the DataStream class:
DataStream Constructor
public DataStream(Stream stream)
Constructs a new DataStream, which sits upon the given stream using big endian
notation for multibyte values.
The current available streams that you can give as parameters are:
waba.io.Catalog, waba.io.SerialPort, waba.io.Socket, waba.io.ResizeStream and
waba.io.ByteArrayStream. The most common one is waba.io.ResizeStream,
because it makes the buffer grow when writing bytes. When reading bytes, you can
attach directly to any of the other classes.
Parameters:
stream - the base stream
close
public boolean close()
SuperWaba Companion
119
Closes the stream. This method simply calls the close method of the underlying
stream.
A very common mistake occurs when you call this close method, and also call
the streams close method. This is not necessary. For example, if you have a
DataStream directly attached to a Catalog, you can just call myDataStream.close().
Theres no need to call myCatalog.close(), because myDataStream.close() will call
myCatalog.close(). Note that this mistake is not harmful.
Overrides:
close in class Stream
pad
public int pad(int n)
Pads the stream writing n bytes. All bytes will be 0. This method is useful when you
want to clean the rest of the record, filling it with zeros. It is also useful when youre
using a DataStream object attached to a ResizeStream; in this case, you can make
sure that the record has a specific number of bytes. This last case is shown below.
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
ResizeStream rs = new ResizeStream(c, 64);
DataStream ds = new DataStream(rs);
rs.startRecord();
int n = 0;
n += ds.writeString(Michelle);
n += ds.writeInt(25);
ds.pad(64-n);
// note: without the pad above, the endRecord below would shrink
// the record to 4+8+2 = 14 bytes.
rs.endRecord();
c.close();
}
skip
public void skip(int n)
Skips reading the next n bytes in the stream. Note that, contrary to the
Catalog.skipBytes method, this method does not skip backwards, only forward. For
example, in a socket connection theres no way to pull back the input data.
Parameters:
n - the number of bytes to skip
Below is an example:
SuperWaba Companion
120
readBoolean
public boolean readBoolean()
Reads a boolean from the stream as a byte. True is returned if the byte is not zero,
false if it is zero.
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
DataStream ds = new DataStream(port);
boolean firstBoolean = ds.readBoolean();
readByte
public byte readByte()
Reads a single byte from the stream. The returned value will range from -128 to
127.
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
DataStream ds = new DataStream(port);
byte firstByte = ds.readByte();
readBytes
public int readBytes(byte[] buf,
int start,
int count)
Reads bytes from the stream. Returns the number of bytes actually read or -1 if an
error prevented the read operation from occurring.
Overrides:
readBytes in class Stream
Parameters:
buf - the byte array to read data into
start - the start position in the array
count - the number of bytes to read
SuperWaba Companion
121
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
DataStream ds = new DataStream(port);
byte []buf = new byte[16];
int read = ds.readBytes(buf,0,buf.length); // reads 16 bytes.
readBytes
public int readBytes(byte[] buf)
Reads bytes from the stream. Returns the number of bytes actually read or -1 if an
error prevented the read operation from occurring.
Parameters:
buf - the byte array to read data into
readFloat
public float readFloat()
Reads a float value from the stream as four bytes in IEEE 754 format.
Returns:
the float value
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
DataStream ds = new DataStream(port);
float firstFloat = ds.readFloat();
readIntLE
public int readIntLE()
Reads an integer using little endian from the stream as four bytes. The returned
value will range from -2147483648 to 2147483647.
Returns:
An integer
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
SuperWaba Companion
122
readShortLE
public short readShortLE()
Reads a short from the stream as two bytes in the little endian format. The returned
value will range from -32768 to 32767.
Returns:
A short
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
DataStream ds = new DataStream(port);
short firstShortLe = ds.readShortLE();
readInt
public int readInt()
Reads an integer from the stream as four bytes. The returned value will range from
-2147483648 to 2147483647.
Returns:
An integer
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
DataStream ds = new DataStream(port);
int firstInt = ds.readInt();
readShort
public short readShort()
Reads a short from the stream as two bytes. The returned value will range from
-32768 to 32767.
Returns:
A short
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
SuperWaba Companion
123
{
DataStream ds = new DataStream(port);
short firstShort = ds.readShort();
readDouble
public double readDouble()
readLong
public long readLong()
readUnsignedByte
public int readUnsignedByte()
Reads a single unsigned byte from the stream. The returned value will range from
0 to 255. Note that the unsigned byte is stored in an integer (otherwise it could not
be unsigned).
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
DataStream ds = new DataStream(port);
int firstUnsignedByte = ds.readUnsignedByte();
readUnsignedShort
SuperWaba Companion
124
Reads an unsigned short from the stream as two bytes. The returned value will
range from 0 to 65535. As the unsigned byte, the result is also stored in an integer.
Returns:
A short (stored in an integer)
Below is an example:
SerialPort port = new SerialPort(0, 9600);
if (port.isOpen())
{
DataStream ds = new DataStream(port);
int firstUnsignedShort = ds.readUnsignedShort();
writeIntLE
public int writeIntLE(int i)
writeShortLE
public int writeShortLE(int i)
SuperWaba Companion
125
writeBoolean
public int writeBoolean(boolean bool)
Writes a boolean to the stream as a byte. True values are written as 1 and false
values as 0.
Parameters:
b - the boolean to write
Returns:
the number of bytes written
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
DataStream ds = new DataStream(c);
int n = 0;
c.addRecord(2); // number of bytes that will be written
boolean iAmHappy = true;
boolean iAmRich = false;
n += ds.writeBoolean(iAmHappy);
n += ds.writeBoolean(iAmRich);
c.close();
Vm.debug(Total of +n+ bytes written);
}
writeByte
public int writeByte(byte by)
SuperWaba Companion
126
writeByte
public int writeByte(int by)
Writes a single byte to the stream. In this method an integer is used instead of a
byte.
Parameters:
b - the byte to write (only least significant byte is written)
Returns:
the number of bytes written
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
DataStream ds = new DataStream(c);
int n = 0;
c.addRecord(1); // number of bytes that will be written
int byte1 = 100;
n += ds.writeByte(byte1);
c.close();
Vm.debug(Total of +n+ bytes written);
}
writeBytes
public int writeBytes(byte[] buf,
int start,
int count)
Writes bytes to the stream. Returns the number of bytes actually written or -1 if an
error prevented the write operation from occurring.
Overrides:
writeBytes in class Stream
Parameters:
buf - the byte array to write data from
start - the start position in the byte array
count - the number of bytes to write
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
SuperWaba Companion
127
if (c.isOpen())
{
DataStream ds = new DataStream(c);
int n = 0;
byte []bytes = new byte[16];
for (int i = 0; i < bytes.length; i++)
bytes[i] = (byte)i;
c.addRecord(bytes.length); // number of bytes that will be written
n += ds.writeBytes(bytes,0,bytes.length);
c.close();
Vm.debug(Total of +n+ bytes written);
}
writeBytes
public int writeBytes(byte[] buf)
Writes bytes to the stream. Returns the number of bytes actually written or -1 if an
error prevented the write operation from occurring.
Parameters:
buf - the byte array to write data from
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
DataStream ds = new DataStream(c);
int n = 0;
byte []bytes = new byte[16];
for (int i = 0; i < bytes.length; i++)
bytes[i] = (byte)i;
c.addRecord(bytes.length); // number of bytes that will be written
n += ds.writeBytes(bytes);
c.close();
Vm.debug(Total of +n+ bytes written);
}
writeFloat
public int writeFloat(float f)
Writes a float value to the stream as four bytes in IEEE 754 format
Parameters:
f - the float to write
Returns:
the number of bytes written
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
DataStream ds = new DataStream(c);
SuperWaba Companion
128
int n = 0;
c.addRecord(4); // number of bytes that will be written
float myFloat = 123.456f;
n += ds.writeFloat(myFloat);
c.close();
Vm.debug(Total of +n+ bytes written);
}
writeInt
public int writeInt(int i)
writeShort
public int writeShort(int i)
Writes a short to the stream as two bytes. There is no short type in Waba but we
often want to use only two bytes in storage. An int is used but the upper two bytes
are ignored.
Parameters:
i - the short to write
Returns:
the number of bytes written
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
DataStream ds = new DataStream(c);
int n = 0;
c.addRecord(1); // number of bytes that will be written
short myShort = (short)32000;
n += ds.writeShort(myShort);
SuperWaba Companion
c.close();
Vm.debug(Total of +n+ bytes written);
}
writeDouble
public int writeDouble(double d)
writeLong
public int writeLong(long l)
readString
public String readString()
Reads a String, converting from bytes to java format using the current
waba.sys.CharacterConverter.
129
SuperWaba Companion
130
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.READ_WRITE);
if (c.isOpen())
{
DataStream ds = new DataStream(c);
String s1 = ds.readString();
String s2 = ds.readString();
String s3 = ds.readString();
c.close();
}
readStringArray
public String[] readStringArray()
Reads an array of Strings. Note: to use this method, the String array must have
been written using the writeStringArray method in this class.
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.READ_WRITE);
if (c.isOpen())
{
DataStream ds = new DataStream(c);
String []as = ds.readStringArray();
if (as == null)
Vm.debug(Empty String array was readen);
else
Vm.debug(The array contains +as.length+ strings);
c.close();
}
writeString
public int writeString(String s)
Writes the String into the stream, converting it from international format to a byte
array using the current waba.sys.CharacterConverter. The String is written by writing a
short with the byte array size and followed by the byte array itself.
A null String is written as 2 consecutive zeros.
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
int n = 0;
ResizeStream rs = new ResizeStream(c,128);
DataStream ds = new DataStream(rs);
rs.startRecord();
n += ds.writeString(SuperWaba);
n += ds.writeString(The REAL Power);
SuperWaba Companion
131
writeStringArray
public int writeStringArray(String[] v)
Writes the string array into the stream. The length of the array is stored in the first
2 bytes (as a short) and the strings are stored in sequence.
A null array is written as 2 consecutive zeros.
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
int n = 0;
ResizeStream rs = new ResizeStream(c,128);
DataStream ds = new DataStream(rs);
rs.startRecord();
String []as = {SuperWaba,The REAL Power,Of Portable Computing};
n += ds.writeStringArray(as);
rs.endRecord();
c.close();
Vm.debug(Total of +n+ bytes written);
}
readCString
public String readCString()
Reads a C-style string from the stream. This is a NUL (0) terminated series of
characters. This format is commonly used by other Palm applications. Note: if
you're creating your own stream, choose readString instead of readCString,
because readCString is much slower. Also, this method does not handle
international characters correctly.
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.READ_WRITE);
if (c.isOpen())
{
DataStream ds = new DataStream(c);
String s1 = ds.readCString();
String s2 = ds.readCString();
String s3 = ds.readCString();
c.close();
}
SuperWaba Companion
132
writeCString
public int writeCString(String s)
Writes a C-style string to the stream. This means that all the characters of the
string are written out, followed by a NUL (0) character. This format is commonly
used by other Palm applications. Note: if you're creating your own stream, choose
writeString instead of writeCString, because writeCString is much slower. Also, this
method does not handle international characters correctly.
Parameters:
s - the string to write
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
int n = 0;
ResizeStream rs = new ResizeStream(c,128);
DataStream ds = new DataStream(rs);
rs.startRecord();
n += ds.writeCString(SuperWaba);
n += ds.writeCString(The REAL Power);
n += ds.writeCString(Of portable computing);
rs.endRecord();
c.close();
Vm.debug(Total of +n+ bytes written);
}
SuperWaba Companion
133
Chapter 20 - waba.io.ResizeStream
The ResizeStream class is very useful when youre dealing with Catalogs in SuperWaba.
A Catalog can resize its record as needed, and because the device has very limited
memory, in general your applications do not write fixed size records. The ResizeStream
class is very handy to help you create variable sized records.
It works as described below:
You call startRecord. This will create a new record with the specified initial size.
You keep writing bytes to it.
Before transferring the bytes to the record, its current size is checked.
If the record needs to grow, ResizeStream calls Catalog.resizeRecord to get more
space.
When the record is finished, you call endRecord; it then shrinks the record to the exact
amount of bytes written.
SuperWaba Companion
134
startRecord
public boolean startRecord(int pos)
Inserts the record at the specified position in the Catalog. If the position is greater
than the number of records in the Catalog, then the record is added at the end.
Returns:
true if operation was successful, false otherwise.
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
ResizeStream rs = new ResizeStream(c,128);
DataStream ds = new DataStream(rs);
// start a new record inserting it at position 0
rs.startRecord(0);
ds.writeCString(SuperWaba);
ds.writeCString(The REAL Power);
ds.writeCString(Of portable computing);
rs.endRecord();
c.close();
}
startRecord
public boolean startRecord()
restartRecord
public boolean restartRecord(int pos)
SuperWaba Companion
135
Restart writing the record in the given pos. If pos is greater than the size of the
stream, the record is appended.
This method is useful when you want to overwrite an existing record.
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
ResizeStream rs = new ResizeStream(c,128);
DataStream ds = new DataStream(rs);
// overwrite record 0.
rs.restartRecord(0);
ds.writeCString(SuperWaba);
ds.writeCString(The REAL Power);
ds.writeCString(Of portable computing);
rs.endRecord();
c.close();
}
endRecord
public void endRecord()
readBytes
public int readBytes(byte[] buf,
int start,
int count)
This method simply reads the bytes from the associated catalog.
This method just calls catalog.readBytes. Nothing special is done.
SuperWaba Companion
Overrides:
readBytes in class Stream
Parameters:
buf - the byte array to read data into
start - the start position in the array
count - the number of bytes to read
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.READ_WRITE);
if (c.isOpen())
{
ResizeStream rs = new ResizeStream(c, 2);
DataStream ds = new DataStream(rs);
// Here ds.readString calls DataStream.readBytes, which in turn
// calls ResizeStream.readBytes which calls Catalog.readBytes.
// The ResizeStream here is useless but not harmful.
String oneString = ds.readString();
c.close();
}
writeBytes
public int writeBytes(byte[] buf,
int start,
int count)
close
public boolean close()
136
SuperWaba Companion
137
Closes the catalog. This method does exactly that: calls the method close in the
Catalog class. So, its not necessary to call this method and the Catalogs close
method.
Overrides:
close in class Stream
Below is an example:
Catalog c = new Catalog("guich.Crtr.Type",Catalog.CREATE);
if (c.isOpen())
{
ResizeStream rs = new ResizeStream(c,128);
DataStream ds = new DataStream(rs);
rs.startRecord();
ds.writeString(SuperWaba);
rs.endRecord();
// lets close the catalog.
rs.close();
}
SuperWaba Companion
138
Chapter 21 - waba.io.ByteArrayStream
The ByteArrayStream is commonly used as a buffer. Sometimes, it is faster or less
resource consuming to send more data at once. For example, when youre using sockets,
its far faster to send 50kb of data at once instead of 10 packets of 5kb each. So, you add
all the data to a ByteArrayStream and after that you send its buffer to the socket (or
SerialPort or Catalog).
When writing to the buffer, it expands dynamically as needed (at a 20% rate).
A ByteArrayStream must not be used for read and write operations at the same time.
You must read or write to it. When you use it as a write-only buffer, each time the
writeBytes method is called, an internal cursor position is advanced. When you use it as a
read-only buffer, the same position is also advanced. So, theres only one position
variable for both operations. If you want to write 10 bytes and after this read them, you
must call the reset method to reset the cursor position to 0.
SuperWaba Companion
139
close
public boolean close()
getBuffer
public byte[] getBuffer()
count
public int count()
Returns the current internal cursor position. If the buffer is being used as writeonly, this method will return the number of bytes written to the buffer. If the buffer is
being as read-only, this method will return the number of bytes read at the moment.
SuperWaba Companion
140
Below is an example:
// create the image and fill it with something
Image img = new Image(160,160);
Graphics g = img.getGraphics();
for (int i =0; i < 16; i++)
{
g.setBackColor(new Color(10*i,10*i,10*i));
g.fillRect(i*10,0,10,160);
}
// save the bmp in a ByteArrayStream
ByteArrayStream bas = new ByteArrayStream(4096);
DataStream ds = new DataStream(bas);
img.createBmp(ds);
// get how many bytes the image occupies.
int totalBytesWritten = bas.count();
readBytes
public int readBytes(byte[] buf,
int start,
int count)
Transfers count bytes from the internal class buffer to buf. The start parameter
indicates where to start writing in the array buf.
Does not perform range checking! Use this method with care!
Overrides:
readBytes in class Stream
Returns:
the number of bytes readen.
Below is an example:
ByteArrayStream bas = new ByteArrayStream(16);
DataStream ds = new DataStream(bas);
ds.writeByte(1);
ds.writeByte(2);
ds.writeByte(3);
ds.writeByte(4);
byte []b = new byte[4];
bas.reset();
bas.readBytes(b,0,4); // just read the stored bytes.
reset
public void reset()
SuperWaba Companion
141
skipBytes
public int skipBytes(int count)
Skips the number of bytes from the current position. It may be < than 0. Returns the
number of bytes skipped, or -1 if error.
Below is an example:
ByteArrayStream bas = new ByteArrayStream(16);
DataStream ds = new DataStream(bas);
ds.writeString(SuperWaba);
ds.writeInt(1234);
// reset the position so we can read what we wrote
bas.reset();
// skip the string, reading its size and skipping the rest
bas.skipBytes(ds.readUnsignedShort()*2); // char = 2 bytes
int theNumber = ds.readInt();
reuse
public void reuse()
Reuses the already read part of the buffer. This method shifts the buffer from the
current position to 0, so you can reuse the buffer, avoid exceeding the memory
limits.
Below is an example:
ByteArrayStream bas = new ByteArrayStream(60000);
bas.writeBytes(new byte[60000]);
bas.reset();
bas.readBytes(new byte[50000]); // read only 50000 bytes.
bas.reuse(); // here the bytes at 50000 to 59999 are
// shifted to positions 0 to 9999, and
// the rest of the buffer is now available
writeBytes
public int writeBytes(byte[] buf,
int start,
int count)
SuperWaba Companion
Overrides:
writeBytes in class Stream
Parameters:
buf - the byte array to write data from
start - the start position in the byte array
count - the number of bytes to write
Below is an example:
ByteArrayStream bas = new ByteArrayStream(16);
DataStream ds = new DataStream(bas);
byte []buf = {(byte)1, (byte)2, (byte)3, (byte)4};
// writes the buf to the ByteArrayStream
bas.writeBytes(buf,0,4);
bas.reset();
int = ds.readInt(); // read 1 2 3 4 as an int
available
public int available()
Returns the number of bytes available from the actual read position,
computed from buffer.length-pos.
Below is an example:
ByteArrayStream bas = new ByteArrayStream(16);
DataStream ds = new DataStream(bas);
byte []buf = {(byte)1, (byte)2, (byte)3, (byte)4};
// writes the buf to the ByteArrayStream
bas.writeBytes(buf,0,4);
bas.reset();
int = ds.readShort(); // read 1 2
int avail = bas.available(); // return 2 (bytes available)
142
SuperWaba Companion
143
Note that this may not lead to unique identifiers for all records in your database; youll
need to test it (using equals) before use.
Once you get a key that uniquely identifies your record, you can use the
waba.util.IntHashtable class. This class uses an integer as the hash value and the stored
value is also an integer. In our case, the value will be the position of the record in the
Catalog. Of course, this approach needs to make sure that the database will not be
modified (a static database, such as a dictionary). The good news is that the search will
have retrieval complexity of O(1): it will be instantaneous.
To create the indexes of the static database, you can run SuperWabas class at the
desktop. Then you just synchronize the index to the PDA.
The following functions can be used to create the index database, read again the
IntHashtable and search for a String.
SuperWaba Companion
144
SuperWaba Companion
145
Chapter 23 waba.io.Socket
The Socket class is one of the most useful classes of SuperWaba: it enables you to
open TCP/IP connections from your PDA. Of course, to do this, your PDA must have a
modem, attached or embedded on it. Although powerful, it is also a big source of
headaches, since it will rely on each device characteristics, and sometimes this can be a
real pain.
Next are some examples of devices that you can use to open Socket connections
in SuperWaba:
In most cases, using sockets is something simple: first, you have to setup your
phone and select the provider address, the phone destination, etc. Then, you just open
the socket; it will dial the number and connect. Then you send and receive bytes based
on a protocol, and then close and disconnect. In nearly all cases, it is not a good idea to
keep the line open, since you (or someone else) will be paying for that. Unless, of course,
a GPRS connection is used (GPRS connections are based in the number of bytes
sent/received, not on the open time).
When you create a Socket object for the first time, a system dialog will appear
saying something like connecting.... Then, if the connection is successful, it will close
and control will return to your program.
Under Java and Windows CE, if no network is present, the socket constructor may
hang for an extended period of time due to the implementation of sockets in the
underlying OS. This is a known problem.
You cannot open a socket before the main event loop. In other words, you cannot
open a socket in the app's constructor, or even in the onStart method. The socket can
only be openned after the onStart method finishes. You may setup a timer in the onStart
that, when called, opens the socket. Or maybe open it in the onWindowPaintFinished
method. Or simply open the socket after a button press.
Palm OS devices can't open a socket connection when the PDA is in the cradle. But
this can be easily done with Windows CE devices.
There's a class, superwaba.ext.ce.io.gprs.GPRS that can be used to open GPRS
connections on Pocket PC 2002 Smartphones.
SuperWaba Companion
146
close
public boolean close()
This method closes the logical socket connection. Note that in most cases, calling
close is not enough to disconnect the modem. This happens because there may
exist more than one socket open at the same time. If close is not called, the socket
will be closed by the garbage collector when the object gets collected.
isOpen
public boolean isOpen()
Used to verify if the socket was successfully opened. If isOpen returns false, you
may want to check the lastError variable (described ahead).
setReadTimeout
public boolean setReadTimeout(int millis)
Sets the time in which the socket will wait for something to be read until it returns
the control to the program. A good practice is to set a small timeout, and retry the
read a couple of times.
readBytes
public int readBytes(byte[] buf,
int start,
int count)
Reads the given number of bytes from the open socket connection. It returns the
number of bytes really read, which may be smaller than the requested one.
SuperWaba Companion
147
writeBytes
public int writeBytes(byte[] buf,
int start,
int count)
Writes the given number of bytes from the open socket connection. It returns the
number of bytes really written, which may be smaller than the sent one.
disconnect
public boolean disconnect()
refreshBeforeEachRead
boolean refreshBeforeEachRead
lastError
int lastError
This member stores the last error generated by a method call. Since basic
SuperWaba packages dont generate exceptions, you must always check if a
method call returns success (most of them return a boolean or -1 if problems are
detected), and then check lastError. Each method call resets this to 0 when it is
called, and sets to one of the following values if an error occurs:
SuperWaba Companion
148
4609
DNSBadProtocol
4676
NotOpen
4610
DNSTruncated
4677
StillOpen
4611
DNSNoRecursion
4678
ParamErr
4612
DNSIrrelevant
4679
NoMoreSockets
4613
DNSNotInLocalCache
4680
OutOfResources
4614
DNSNoPort
4681
OutOfMemory
4615
IPCantFragment
4682
SocketNotOpen
4616
IPNoRoute
4683
SocketBusy
4617
IPNoSrc
4684
MessageTooBig
4618
IPNoDst
4685
SocketNotConnected
4619
IPktOverflow
4686
NoInterfaces
4620
TooManyTCPConnections
4687
BufTooSmall
4621
NoDNSServers
4688
Unimplemented
4622
InterfaceDown
4689
PortInUse
4623
NoChannel
4690
QuietTimeNotElapsed
4624
DieState
4691
Internal
4625
ReturnedInMail
4692
Timeout
4626
ReturnedNoTransfer
4693
SocketAlreadyConnected
4627
ReturnedIllegal
4694
SocketClosedByRemote
4628
ReturnedCongest
4695
OutOfCmdBlocks
4629
ReturnedError
4696
WrongSocketType
4630
ReturnedBusy
4697
SocketNotListening
4631
GMANState
4698
UnknownSetting
4632
QuitOnTxFail
4699
InvalidSettingSize
4633
FlexListFull
4700
PrefNotFound
4634
SenderMAN
4701
InvalidInterface
4635
IllegalType
4702
InterfaceNotFound
4636
IllegalState
4703
TooManyInterfaces
4637
IllegalFlags
4704
BufWrongSize
4638
IllegalSendlist
4705
UserCancel
4639
IllegalMPAKLength
4706
BadScript
4640
IllegalAddressee
4707
NoSocket
4641
IllegalPacketClass
4708
SocketRcvBufFull
4642
BufferLength
4709
SuperWaba Companion
149
4643
NiCdLowBattery
4710
UnexpectedCmd
4644
RFinterfaceFatal
4711
NoTCB
4645
IllegalLogout
4712
NilRemoteWindowSize
4646
AAARadioLoad
4713
NoTimerProc
4647
AntennaDown
4714
SocketInputShutdown
4648
NiCdCharging
4715
CmdBlockNotCheckedOut
4649
AntennaWentDown
4716
CmdNotDone
4650
NotActivated
4717
UnknownProtocol
4651
RadioTemp
4718
UnknownService
4652
NiCdChargeError
4729
UnreachableDest
4653
NiCdSag
4720
ReadOnlySetting
4654
NiCdChargeSuspend
4721
WouldBlock
4655
reserved
4722
AlreadyInProgress
4656
ConfigNotFound
4723
PPPTimeout
4657
ConfigCantDelete
4724
PPPBroughtDown
4658
ConfigTooMany
4725
AuthFailure
4659
ConfigBadName
4726
PPPAddressRefused
4660
ConfigNotAlias
4727
DNSNameTooLong
4661
ConfigCantPointToAlias
4728
DNSBadName
4662
ConfigEmpty
4729
DNSBadArgs
4663
AlreadyOpenWithOtherConfig 4730
DNSLabelTooLong
4664
ConfigAliasErr
DNSAllocationFailure
4665
NoMultiPktAddr
DNSTimeout
4666
OutOfPackets
4733
DNSUnreachable
4667
MultiPktAddrReset
4734
DNSFormat
4668
StaleMultiPktAddr
4735
DNSServerFailure
4669
ScptPluginMissing
4736
DNSNonexistantName
4670
ScptPluginLaunchFail
4737
DNSNIY
4671
ScptPluginCmdFail
4738
DNSRefused
4672
ScptPluginInvalidCmd
4739
DNSImpossible
4673
TelMissingComponent
4740
DNSNoRRS
4674
TelErrorNotHandled
4741
DNSAborted
4675
4731
4732
SuperWaba Companion
150
NoTone
4353
NoModem
4358
NoCarrier
4354
OutOfMemory
4359
LineBusy
4355
PrefsNotSetup
4360
UserCancelled
4356
DialStringErr
4361
CmdError
4357
mdmErrNoPhoneNum
4362
65526
(-10)
65523
(-13)
65525
(-11)
65522
(-14)
65524
(-12)
* See nmpalm_wabaio.c for details
The Windows CE error code list is too big to put here. You can download it from
this link: http://www.superwaba.org/etc/winerror.h
Configuring
Next will be explained how to configure a dial up connection on some PDAs. The
configurations on other PDAs may be almost identical to these ones.
Palm Vx with an external modem
1. Go to Prefs app, select Connection. Select the type of configuration you need. Click
Edit. Change what's needed. Click Details. Change the speed or other setting if
needed.
2. Still in Prefs app, select Network. Enter a service name, choose the user name, the
password, the phone and the same connection you choose in step 1.
3. Hit connect to verify if you can dial with success.
Kyocera Smartphone QCP6035
1. Go to Prefs app, select Connection. Select Wireless Modem.
2. Still in Prefs app, select Network. Enter a service name, choose the user name, the
password, the phone and the same connection you choose in step 1 (Wireless
Modem).
4. Hit connect to verify if you can dial with success.
Tungsten T with a mobile phone
1. Download the list of updated phone links from here:
http://www.palmone.com/us/support/downloads/phonelink.html
SuperWaba Companion
151
2. Install the phone link entry for the phone you're targetting
3. Go to the Phone Link app. Click Phone Connection and select the manufacturer and
model. If your model isn't listed, go to step 1. Click next, select your PDA's connection
to what you're going to dial: Infrared, cable, bluetooth, etc. When asked Would you
like to use this as the default connection for your phone applications, click Yes.
4. Go to the Prefs app. Select Communication. Click Phone. Make sure your connection
match the one specified in step 3.
5. Click Network. Enter your service, user name, password, connection and phone.
6. Hit connect to verify if everything is ok.
If you're using a GPRS connection, in step 5 you need to enter the right information
from this pdf: http://www.superwaba.com.br/etc/GPRS_Network_parameters.pdf
For example, to connect using TIM: Service=tim gprs, user name=tim, password=tim,
phone=*99***1#. Then you'll get a beautiful GPRS connection.
Testing
We already said that what is going to be written and read must follow a pattern, or
protocol. In the example below, we will use the HTTP protocol to connect to a server,
request a page from that server, and read a few bytes back.
socket = new Socket(www.google.com, 80, 15000);
if (!socket.isOpen())
status("Cant open socket: "+socket.lastError);
else
{
socket.setReadTimeout(500);
byte buf[] = new byte[10]; // we'll read only 10 bytes
byte []bytes = "GET / HTTP/1.0\n\n".getBytes();
socket.writeBytes(bytes,0,bytes.length);
int tries = 0;
do
{
int count = socket.readBytes(buf, 0, buf.length);
if (count == buf.length)
{
status(Read: +new String(buf,0,count));
break;
}
else status("couldnt read: "+socket.lastError);
// some sites can take a longer delay to start sending things,
// so we loop until we find something to read
} while (tries++ < 4 && socket.lastError == 4626);
status("Closing socket");
socket.close();
status("Socket closed: "+socket.lastError);
}
// Ps: status(String) is a method that displays the text in a listbox.
You can also use the superwaba.ext.xplat.io.http classes to handle http connections.
SuperWaba Companion
152
Note, in the example above, that there's a loop while the error is 4626. In my tests,
I found that sometimes this error can occur, and if I retry a few times, the connection is
established. Just setting a big read timeout is not enough.
You can easily connect to an ASP or Servlet or whatever page you want; you only
need to make sure that you pass the correct parameters.
Socket socket = new Socket(200.215.250.0, 80, 25000);
if (socket.isOpen())
{
String url = "GET /servlet/VerifyUser?user=" + user +
"&pass=" + password + "\n";
byte[] inBuf = new byte[1000];
byte[] outBuf = url.getBytes();
int read;
// fetch page
if (socket.writeBytes(outBuf, 0, outBuf.length) == outBuf.length)
read = socket.readBytes(inBuf, 0, inBuf.length);
socket.close();
}
Socket.disconnect(); // not necessary, just illustrative
You could also connect directly to a program listening on some host, using a
protocol that you have created. For an example of such protocol, see the
SuperWabaSDK\src\superwaba\ext\xplat\io\SerialSocket and SerialSocketServer classes.
Avoid using large buffers in Palm OS 5, because, in this version, a temporary buffer is
allocated and deallocated. Data read/written is copied to this buffer and when the
operation is done, it is moved to the provided user buffer.
SuperWaba Companion
153
Chapter 24 waba.io.SerialPort
The SerialPort class is used to connect the device to the external world using a
serial cable, bluetooth, or IR instead of a Modem.
Dealing with Serial connections is also another painful task with some
combinations of PDAs and desktop operating systems. One of the biggest pains is with
the combination of USB and Windows 98/2k/XP platforms. It simply doesn't work!
The SerialPort has three constructors:
close
public boolean close()
SuperWaba Companion
154
This method closes the connection. If close is not called, the socket will be closed
by the garbage collector when the object gets collected.
isOpen
public boolean isOpen()
Returns true if the port is open and false otherwise. This can be used to check if
opening the serial port was successful. This method does not clear the lastError
flag. If false is returned, check for the lastError flag to find the reason the port could
not be opened.
setFlowControl
public boolean setFlowControl(boolean on)
Turns RTS/CTS flow control (hardware flow control) on or off. No serial XON/XOFF
flow control (commonly called software flow control) is used and RTS/CTS flow
control (commonly called hardware flow control) is turn on by default on all
platforms but Windows CE.
setReadTimeout
public boolean setReadTimeout(int millis)
Sets the timeout value for read operations. The value specifies the number of
milliseconds to wait from the time of last activity before timing out a read operation.
Passing a value of 0 sets no timeout causing any read operation to return
immediately with or without data. The default timeout is 100 milliseconds. This
method returns true if successful and false if the value passed is negative or the
port is not open.
readBytes
public int readBytes(byte buf[], int start, int count)
Reads bytes from the port into a byte array. Returns the number of bytes actually
read or -1 if an error prevented the read operation from occurring. The read will
timeout if no activity takes place within the timeout value for the port.
writeBytes
public int writeBytes(byte buf[], int start, int count)
SuperWaba Companion
155
Writes to the port. Returns the number of bytes written or -1 if an error prevented
the write operation from occurring. If data can't be written to the port and flow
control is on, the write operation will time out and fail after approximately 2
seconds.
readCheck
public int readCheck()
Returns the number of bytes currently available to be read from the serial port's
queue.
Like in the Socket class, the SerialPort also has a lastError member.
lastError
int lastError
This stores the last error generated by a method call. Since basic SuperWaba
packages don't generate exceptions, you must always check if a method call
returns success (most of them return a boolean or -1 if there are problems), and
then check lastError. Each method call resets this to 0 when it is called, and sets to
one of the following values if an error occurs:
SuperWaba Custom VM Codes
No Serial Library available
65525
(-11)
65522
(-14)
769
AlreadyOpen
775
BadPort
770
StillOpen
776
NoMem
771
NotOpen
777
BadConnID
772
NotSupported
778
TimeOut
773
NoDevicesAvail
779
LineErr
774
USBConfigurationFailed
780
The Windows CE error code list is too big to put here. You can download it from
this link: http://www.superwaba.org/etc/winerror.h
Configuration
The configuration for Palm OS and Windows CE is straight forward: no setup is
needed. The problem relies on the destination: if it is another device, then you'll have to
SuperWaba Companion
156
try the baud rates until you find the correct one. If the destination is a desktop computer,
then, prepare for some problems.
I don't use Linux/Unix, but users say that there's no problem connecting the PDA in
a cradle to it, even if the cradle is USB.
But using Windows is only easy if your PDA has a serial connection. You will have
to kill hotsync, and then start some kind of server or a program (like HyperTerm) to
receive the sending bytes. Unfortunately, using USB with Windows is impossible.
The best approach you can use to connect a PalmOS PDA to Windows is buying a
USB-TO-SERIAL cable, and then opening the connection using SerialPort.DEFAULT.
You can also try to use a free utility called IrCOMM2k, which maps the IRCOMM to a port
that can be used under Windows 2k. Then you could create a program that listens to this
port and transfer data to/from the device. The program's site is here:
http://www.stud.uni-hannover.de/~kiszka/IrCOMM2k/English/index.html
You can also test the SerialPort class at desktop, under JDK. For this, you will just
need to add, to your classpath, the SuperWabaSDK\bin\tools\commapi\comm.jar file. This
file adds support for serialport under JDK (the version inside the SDK is for the Windows
platform. Please visit Sun's site to download the version for Linux and Mac). SuperWaba's
file waba.io.NativeMethods4JDK use the methods of this class, but due to a trick (using
introspection to call the methods), you can compile SuperWaba files without the
comm.jar in the classpath. We will use it in next topic. To emulate the various ports in
JDK, we use a file called swserial.properties. This file is read from the current directory
by the SWSDK when you try to use SerialPort under Windows/Linux/Mac. The file
contents are:
DEFAULT=COM1
IRCOMM=COM2
SIR=COM3
USB=COM4
You can change the file if you want, to match your desktop's configuration. If the
file is not found, these default settings are used.
Testing
In the SDK samples directory there are some interesting programs made by
SuperWaba users. We won't get into the details of each program here, but they will be
described so you may look into them by yourself. The parent directory for all listed
programs is: SuperWabaSDK/java/src/.
SuperWaba Companion
157
Now we're going to run two sample programs that can be very useful. They both
were tested using devices connected to a desktop's serial port (also works with USB-TOSERIAL cable).
The first program is PDBConduit. The PDBConduit program has a protocol that can
be used to send/receive text files to/from the desktop, as well as pieces of PDB files. The
PDBConduit is placed in two directories: the SuperWabaSDK\java\src contains the client
application example, superwaba.samples.ext.io.pdbconduit.PDBConduit, that runs in the
device. The directory SuperWabaSDK\src\java contains the server and the client
interface, named superwaba.ext.xplat.io.SerialPDBServer and
superwaba.ext.xplat.io.SerialPDB, respectively.
SerialPDB
The SerialPDB interface, used by the client, contains the methods below:
SerialPDB(int baud, int timeout): the constructor, where you specify the
baud rate and the read timeout. Note that the program is hardcoded to use
SerialPort.DEFAULT.
isOpen(): returns true if the port is opened.
boolean put(Catalog cat2send, String name, int startRecord, int
endRecord, boolean onlyDirty, boolean resetDirtyAttr): Send the
specified catalog to the server. If onlyDirty is true, only dirty records will be sent. You
may also specify resetDirtyAttr to reset the flag in all record sync'ed. startRecord and
endRecord can be -1 to send all Catalog. You may specify in the name the full path to
the catalog.
boolean get(Catalog fillIn, String name, int startRecord, int
endRecord, boolean onlyDirty, boolean resetDirtyAttr): Requests the
server to send the specified catalog, placing the records in the given fillIn catalog.
startRecord and endRecord can be -1 to bring the full Catalog. If onlyDirty is true, only
dirty records will be received. You may also specify resetDirtyAttr to reset the flag in all
record sync'ed. You may specify in the name parameter the full path to the file.
boolean put(String fileName, boolean deleteIfExists, String
[]strings): Send the following String array to the server, placing it in the given txt
filename. You may specify the full path to the fileName.
String[] get(String fileName): Get a String array from the server from the
specified text file. You may specify the full path to the fileName.
delete(String fileName): Delete a catalog at the server. This method does NOT
delete a txt (txt files are always overwritten)!
shutdownServer(): Shuts down the server.
Now let's test the program:
SuperWaba Companion
158
SerialSocket
The second program described is SerialSocket. You may know that the PalmOS
devices can't open a Socket directly from the cradle (however, this is a trivial operation on
a Windows CE device). After reading the article Cure Your Waba Woes with a Serial
Socket, an article written by Rick Grehan at JavaPro Magazine, I changed it a bit and
created this useful library.
SerialSocket acts just like the SerialPDB: you have a client, a client interface and a
server. The server receive the commands from the client and routes them to the network,
sending answers back.
Our client test program will be the same SocketTest program we used in last
chapter. The program has an option where you choose if you want to use the real Socket
class or the SerialSocket. This can be easily done because
superwaba.ext.xplat.io.SerialSocket extends waba.io.Socket. It has the same methods of
waba.io.Socket, plus one method, shutdownServer, which can be used to shut down the
server.
SuperWaba Companion
159
SuperWaba Companion
160
Chapter 25 waba.io.File
The waba.io.File class was introduced in SuperWaba version 3.5. Its usage
depends on the platform:
On the desktop and on Windows CE / Pocket PC devices, it access the file system and
memory cards, managing directories and files.
On PalmOS devices with an OS version greater than 3.5 and a memory card, it access
the virtual file system, enabling you to manage directories and files on the memory
card only. However, you will not be able to access the default storage memory using
the waba.io.File (you must still use waba.io.Catalog in this case).
File(String path, int mode): Opens a file with the given name and mode. If
mode is CREATE, the file will be created if it does not exist. The DONT_OPEN mode
allows the exists(), rename(), delete(), listDir(), createDir() and isDir() methods to be
called without requiring the file to be opened for reading or writing. The other mode
options are READ_ONLY, WRITE_ONLY and READ_WRITE. Note that the filename
must not contain accented characters. Also, the path separator MUST be the slash
"/".
File(String path): Opens a file in DONT_OPEN mode. This constructor is
useful for directory manipulation and to check if a file exists. No read/write operation
can be done with a File object created in this mode.
Don't forget to try the samples/io/File/FileTest.java sample. Next we will see the
various methods in this class:
isAvailable
public static boolean isAvailable()
Returns true if a File System is available in the current PDA. In Windows CE and
on the desktop, this always returns true. In Palm OS, it will depend if the file has an
external card (Secure Digital, Smart Media, etc). Using other methods in this class
without first checking if this class is available in the target device will simply reset
it. Starting on SuperWaba 5.5, the isAvailable also checks if the card is inserted on
Palm OS devices only.
Below is an example:
SuperWaba Companion
161
close
public boolean close()
Closes the file. Returns true if the operation is successful and false otherwise. If
you don't explicitly close the file, it will be closed by the garbage collector.
createDir
public boolean createDir()
Creates a directory. Returns true if the operation is successful and false otherwise.
Below is an example:
File f = new File("/TempDir");
if (!f.exists())
f.createDir();
delete
public boolean delete()
Deletes the file or directory (the directory must be empty). Returns true if the
operation is successful and false otherwise. After this operation, this File object is
invalid and must not be used further.
Below is an example:
File f = new File("/TestRename/Test2.txt");
ok = f.delete();
new MessageBox(Test File.delete, ok?"Test2.txt deleted":("Test2.txt not
deleted. err="+f.lastError).popupModal();
exists
public boolean exists()
SuperWaba Companion
162
getSize
public int getSize()
Returns the size of the file in bytes. If the file is not opened, 0 will be returned.
Below is an example:
File f = new File("/Teste.txt",File.CREATE);
DataStream ds = new DataStream(f);
ds.writeString("Test");
ds.writeInt(1234);
new MessageBox(Test File.getSize, "File size now is: "+f.getSize()+
bytes)popupModal();
getPath
public String getPath()
Return the file's path. The getPath is also used in the File.toString method
implementation.
Below is an example:
File f = new File("/TempDir");
Vm.debug(Path is: +f.getPath());
isDir
public boolean isDir()
isOpen
SuperWaba Companion
163
Returns true if the file is open for reading or writing and false otherwise. This can
be used to check if opening or creating a file was successful.
Below is an example:
File f = new File("/Teste.txt",File.CREATE);
new MessageBox(File created?, f.isOpen() ? Created! : Not
created.).popupModal();
listFiles
public String []listFiles()
Lists the files contained in a directory. The strings returned are the names of the
files and directories contained within this directory. This method returns null if the
directory can't be read or if the operation fails. Volume labels are returned between
[ ], and paths have a / after the name. Using this pattern makes easy and fast
finding if a String is a path, a file or a volume label.
Below is an example:
void recursiveList(String path, Vector v)
{
if (path == null) return;
File file = new File(path);
String []list = file.listFiles();
if (list != null)
for (int i =0; i < list.length; i++)
if (list[i] != null)
{
v.addElement(path+list[i]);
if (list[i].endsWith("/")) // is a path?
recursiveList(path+list[i],v);
}
}
Vector v = new Vector(50);
recursiveList("/",v);
String []files = (String[])v.toObjectArray();
if (files == null)
files = new String[]{"No files"};
else
if (files[0].charAt(1) == '[') // is it a volume label?
files[0] = files[0].substring(1); // remove the preceding slash
add(new ComboBox(files), LEFT,TOP);
readBytes
public int readBytes(byte b[], int off, int len)
SuperWaba Companion
164
Reads bytes from the file into a byte array. Returns the number of bytes actually
read or -1 if an error prevented the read operation from occurring. After the read is
complete, the location of the file pointer (where read and write operations start
from) is advanced the number of bytes read.
Below is an example:
File f = new File("/Teste.txt",File.CREATE);
byte []buf = SuperWaba = POWER!.getBytes();
f.writeBytes(buf,0,buf.length);
f.setPos(0);
if (f.readBytes(buf,0,buf.length) == buf.length)
new MessageBox(Test, new String(buf)).popupModal();
writeBytes
public int writeBytes(byte buf[], int start, int count)
Writes to the file. Returns the number of bytes written or -1 if an error prevented
the write operation from occurring. After the write is complete, the file pointer
(where read and write operations start from) is advanced the number of bytes
written.
See readBytes for an example.
rename
public boolean rename(String path)
Renames the file. You must give the full directory specification for the file, to
maintain compatibility between all platforms. WinCE platforms let you move a file
using rename, while Palm OS does not let you move the file. Returns true if the
renaming was successful and false otherwise. After this operation, this File object
is invalid and must not be reused.
Below is an example:
File f = new File("/TempRename");
f.createDir();
boolean ok = f.rename("/TestRename");
if (ok)
{
// file object is now invalid. create a new one.
f = new File("/TestRename");
Vm.debug("TestRename.isDir? "+f.isDir());
f = new File("/TestRename/Teste.txt",File.CREATE);
// Rename Teste.txt to Teste2.txt
ok = f.rename("/TestRename/Teste2.txt");
if (ok)
{
SuperWaba Companion
165
setPos
public boolean setPos(int pos)
Sets the file pointer for read and write operations to the given position. The position
passed is an absolute position, in bytes, from the beginning of the file. To set the
position to just after the end of the file, you can call:
file.setPos(file.getSize());
setAttributes
public void setAttributes(int attr)
Sets this file attributes. This method does not work on the desktop. The file must be
opened in a mode different than DONT_OPEN. The attr parameter must be one or
more ATTR_xxx constants ORed together: ATTR_ARCHIVE, ATTR_HIDDEN,
ATTR_READ_ONLY, ATTR_SYSTEM. These values are platform independent, ie,
they are internally mapped to the target platform values. Values different from the
given ATTR_xxx constants are simply ignored.
Below is an example:
String getAttrDescription(int attr)
{
String s = "";
if ((attr & File.ATTR_ARCHIVE) != 0)
s += "A";
if ((attr & File.ATTR_HIDDEN) != 0)
s += "H";
if ((attr & File.ATTR_READ_ONLY) != 0)
s += "R";
if ((attr & File.ATTR_SYSTEM) != 0)
s += "S";
return s;
}
File f = new File("TestAttr.txt",File.CREATE);
int attr = f.getAttributes();
Vm.debug("File attributes: "+getAttrDescription(attr));
SuperWaba Companion
166
// Setting to hidden
f.setAttributes(attr | File.ATTR_HIDDEN);
attr = f.getAttributes();
Vm.debug("Attributes changed to "+getAttrDescription(attr));
getAttributes
public int getAttributes()
Gets this file attributes. See the ATTR_xxx constants, which can be ORed together.
This method does not work on the desktop. The file must be opened in a mode
different than DONT_OPEN. Returns -1 if failure, otherwise the attributes ORed
together.
See setAttributes for an example
setTime
public void setTime(byte whichTime, waba.sys.Time time)
Sets the time for the given time type. The whichTime must be one of the following
constants, ORed together:
TIME_ALL: This sets all times to the given time
TIME_CREATED: time in which the file was created
TIME_MODIFIED: last time the file was modified (written)
TIME_ACCESSED: last time the file was accessed (read)
The TIME_xxx constants are platform independent, what means that they will be
mapped internally to the values used by each operating system.
This method does not work on the desktop, running under JDK.
The file must be opened in a mode different than DONT_OPEN.
Below is an example:
File f = new File("TestAttr.txt",File.CREATE);
Time t;
Vm.debug("File Created Time:");
t = f.getTime(File.TIME_CREATED);
Vm.debug(""+new Date(t)+" "+t);
Vm.debug("File Modified Time:");
t = f.getTime(File.TIME_MODIFIED);
Vm.debug(""+new Date(t)+" "+t);
Vm.debug("File Acessed Time:");
t = f.getTime(File.TIME_ACCESSED);
Vm.debug(""+new Date(t)+" "+t);
SuperWaba Companion
167
getTime
public waba.sys.Time getTime(byte whichTime)
getCardVolume
public String getCardVolume()
Returns the volume File for the Windows CE and Pocket PC devices. In these
devices, the volume has a special folder name, but since there's no system call that
informs this, we must just test the existence of each folder, returning the first one
that exists.
This method does not work on the desktop.
Like the Socket and SerialPort classes, the File class also has a lastError member.
lastError
int lastError
This stores the last error generated by a method call. Because basic SuperWaba
packages do not generate exceptions, you must always check if a method call
returns success (most of them return a boolean or -1 if problems are detected) and
then check lastError. Each method resets this to 0 when it is called, and if an error
occurs sets it to one of the following values before returning:
SuperWaba Companion
168
10753
NoFileSystem
10763
FileGeneric
10754
BadData
10764
FileBadRef
10755
DirNotEmpty
10765
FileStillOpen
10756
BadName
10766
FilePermissionDenied
10757
VolumeFull
10767
FileAlreadyExists
10758
Unimplemented
10768
FileEOF
10759
NotADirectory
10769
FileNotFound
10760
IsADirectory
10770
VolumeBadRef
10761
DirectoryNotFound
10771
VolumeStillMounted
10762
NameShortened
10772
The Windows CE error codes list is too big to put here. You can download it from
this link: http://www.superwaba.org/etc/winerror.h
SuperWaba Companion
169
SuperWaba Companion
170
There are some samples for the Scanner library in the folder
SuperWabaSDK\src\java\superwaba\samples\ext\io\scanner. Note that this sample does
not work with the Opticon scanner.
Note that the SDIO and Opticon libraries are available only with the Professional
subscription.
SuperWaba Companion
171
Troubleshooting
SuperWaba Companion
172
PalmIoPrintIrPrint.prc
XPlatIoPrint.pdb
4. If you have a notebook near, disable its IR Wireless port. It may interfere with the
device IR.
Although my printer has support for graphics at Windows, it does not work with
PrintBoy. What's wrong?
Quoted by the PrintBoy author:
This is because the deskjet printers can't render and entire page in memory; they
lay down the ink as they move down the page and aren't smart enough to feed the paper
back through to get to the top of the page again if a command comes it that tells it to draw
something back up the page. For example, if you tell the printer to draw two vertical lines
2 inches apart it will get the command for the first line and draw it. Now it is below the
point where it can start the next line.
It might be ok telling it to print horizontal lines if they are sorted in descending Y
direction but don't quote me on that.
In general it is required to sort your page in descending Y direction for these types
of printers. Someday, when the page is being rendered on the device in raster format,
then sent to the printer, this won't be a problem. But IMO that's prohibitively slow at this
point. Maybe the new ARM processors will do a better job but you still have the relatively
slow SIR link to deal with.
I'm trying to print using Graphics but the formFeed+finishPage doesnt work.
This happens when you try to use an unsupported operation with PrintBoy (like
writting lines in a deskjet printer). You must test the Printer Capabilities before doing
some kinds of action.
Whenever you do a wrong action, like an invalid command or not being too near
the ir device, a fatal reset is likely to occur.
Are you using the last SuperWaba version?
The printing routines must be fast. There should be no big delays between the
commands you send to the printer, otherwise it will "forget" and won't work.
When i run the application, i get some messages in the memobook log file: "Cannot
find native method..."
You forgot to add the Vm.attachNativeLibrary. Check the samples.
When i try some functions, i got something like "Please try another driver".
SuperWaba Companion
173
SuperWaba Companion
174
Sample
if (Vm.attachNativeLibrary("XPlatIoSearch"))
{
Catalog cat = new
Catalog("TestDB."+Settings.appCreatorId+".DATA",
Catalog.READ_ONLY);
CatalogSearch catSearch = new CatalogSearch(cat);
String text = "a9999"; // string to search
int offset = 0; // offset in record
int startRec = 10; // start searching from record 10
cat.setRecordPos(startRec);
// now we convert the String to a byte array
// Note that we're searching for the exact string,
// case sensitive and whole word only.
int length = 0;
ByteArrayStream bas = new ByteArrayStream(16);
DataStream ds = new DataStream(bas);
length += ds.writeString(text);
byte []toSearch = bas.getBuffer(); // the buffer may be
greater than length
SuperWaba Companion
175
SuperWaba Companion
176
superwaba.ext.xplat.fx.gif
superwaba.ext.xplat.fx.jpeg
superwaba.ext.xplat.fx.png
Check the other samples in the package superwaba.samples.ext.fx.
(), where you can construct the object and then load the image with the load method.
(String filename): this one is used when you add the image to your PDB using
Warp. Note that it cannot have a path qualifier, just the name of the image.
(waba.io.Stream stream): here you can use any type of streams (Socket,
SerialPort, Catalog, File) to read an image. You can also use the
superwaba.ext.xplat.io.RecordPipe to read an image split into various records
of a Catalog.
Important: there's currently a limitation that may result in corrupted images when you read
from a Stream like waba.io.File or waba.io.Catalog. If this happen, you must read the
entire image to memory and then pass it to the 3rd constructor above. Here's a sample on
how to read a Jpeg image using waba.io.File (the same may apply to the other streams):
JpegImage img = new JpegImage();
File f = new File("DCIM/photo.jpg");
SuperWaba Companion
177
SuperWaba Companion
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
87
88
89
90
178
SuperWaba Companion
91
92
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
179
SuperWaba Companion
180
Sample
There's a sample at the folder src/java/superwaba/samples/ext/zlib/test that shows
how to compress and uncompress.
This other sample shows how to read a text file at desktop, line per line, compress
it into a Catalog that can later be decompressed at the PDA. The files are located in a
folder at the companion_samples folder, and are named CompressAtDesktop.java and
DecompressAtPDA.java.
This is the main compression part:
for (int i =0; i <= n; i++)
{
// write the input line on the uncompressed stream
dsOut.writeString(lines[i]);
written++;
// reached the limit or the last input line?
int c = os.count();
if (c > limit || i == n)
{
// now we compress the data.
SuperWaba Companion
181
// note that the compression buffer must have the exact size of the stream
ByteArrayStream temp = new ByteArrayStream(c);
temp.writeBytes(outBuf,0,c);
temp.reset(); // let the compressor read the data from the beginning
os.reset(); // reuse the output buffer, now to store the compressed data
int size = ZLib.deflate(ZLib.BEST_COMPRESSION, temp, os); // compress it
// save on the catalog
if (cat.addRecord(size) >= 0)
{
cat.writeBytes(outBuf,0,size);
System.out.println("Compressed: "+c+" -> "+size+" bytes ("+written+"
lines)");
}
else throw new Exception("Error when writing "+size+" bytes");
os.reset(); // restart the output buffer to be able to add more lines
written = 0;
}
}
SuperWaba Companion
}
}
182
SuperWaba Companion
183
Conduits are always attached to a single creator id (but may be attached to multiple
users on a single machine). Desktop will only call your conduit during a hotsync if the
application with the corresponding creator id is installed. Thus, in the very first
synchronization, the one that installs your application, your conduit will NOT be called,
since there are no applications with the conduit's creator id. This is not true for
ActiveSync: when the conduit is registered, it will always run.
Conduit class
SuperWaba Companion
184
This abstract class is the one that defines that your SuperWaba application is a
conduit. It extends waba.ui.MainWindow, and so, you can display controls on it.
Palm Desktop Conduits has two states: configuration and synchronization. The
configuration occurs when the user select the customize option on the HotSync menu
icon. The synchronization happens when the user presses the hotsync button on the
cradle or on the PDA. Now, ActiveSync conduits also has both states, but there's no way
to access the configuration through ActiveSync; you must create a link to invoke the
configuration's screen.
There are, thus, two methods that must be implemented to handle these two states:
protected abstract void doSync()
protected abstract void doConfig()
In a normal SuperWaba program, you create your user interface in the onStart
method. When creating a conduit, the user interface creation must be handled instead in
the two distinct methods above. Note that your program is responsible for closing itself
and return the control to the caller process. Note also that, during a hotsync, no other
conduits will be run until your conduit application finishes.
A good way to separate the synchronization's logic from the configuration's is to
create two classes that extend waba.ui.Container and implement the logic inside each
class (see chapter 16), and, on each method above, do a swap to your classes. This is
the code for the PainterConduit class:
public class PainterConduit extends Conduit
{
public PainterConduit()
{
super("", TAB_ONLY_BORDER);
}
protected void doConfig()
{
setTitle("Painter Conduit - Configuration");
swap(new SetupPanel());
}
protected void doSync()
{
setTitle("Painter Conduit - Synchronization");
swap(new SyncPanel());
}
}
Note that the default constructor, Conduit(), is not implemented by the Conduit
class, thus you must always use the super(title, border_type) constructor.
There are two other useful public static methods:
log(String text): prints a text in the HotSync.Log file, inside the user's folder. For
Pocket PC, it writes text to the debugconsole.txt file, just like a Vm.debug would.
SuperWaba Companion
185
yield(): this one lets hotsync take a breath. What you think would happen if your
program never return control to HotSync during a configuration? Simple: the
connection between the computer and the PDA would die. So, the way to tell HS that
your program is alive and also to let HotSync keep the connection alive is to call often
the yield method. Note that there's a thread on the Conduit class that keeps yielding
while there are no events on your conduit; but if you're inside a loop bringing things
from the server, you must remember to call this method by yourself. Fortunately, it is
very easy to know if hotsync is happy or not: the animated arrows will stop when
hotsync is not being yielded. Note that this method does nothing on Pocket PC
conduits.
RemoteCatalog class
This is the class that handles a catalog (PDB file) stored on the PDA. It is used with
the superwaba.ext.xplat.sync.RemoteCatalogRecord class, which in turn
represents a single record of the PDB. This model resembles the one used in Palm
Desktop's JSync.
The RemoteCatalogRecord contains two abstract records: write and read.
The underlying C++ API has some restrictions that are passed over to SuperWaba:
Only ONE catalog can be open at a time. Trying to open more than one, before closing
the prior, will result in a RuntimeException.
You must not read and write at a catalog at the same time. First, do all the readings,
then all the writings (or vice-versa).
Access the records in sequence, it is much faster.
If you plan to delete records from the pdb, be careful: this can be a very high timeconsuming operation. The usual way to treat this is to delete records always from the
end, or delete the whole catalog and create another one with the same name.
Lets see the available methods inside the RemoteCatalog class:
SuperWaba Companion
186
RemoteCatalogRecord class
This abstract class is used to read and write data, and is used in conjunction with
the methods readRecord and writeRecord of the RemoteCatalog class.
Two methods must be implemented:
protected abstract void write(DataStream ds)
protected abstract void read(DataStream ds)
With the given DataStream, you can read or write all your needed data.
There are also two useful members:
SuperWaba Companion
187
RemoteFile
This class is used to copy a whole file between the desktop and the Pocket PC. We
plan to extend it in the future to also handle data on the card of a Palm OS device (using
the functions provided by the Virtual File System).
Only static members are provided to list, copy to/from and delete files, as shown
below:
String[] listFiles(String dir): list the files from the given dir. The strings
returned are the names of the files and directories contained within this directory. This
method returns null if the directory can't be read or if the operation fails. Path names
ends with /, so it is easy to distinguish them from a file. The dir parameter can contain
wildcards, and can use '\' or '/' (it will be internally converted to '\'). If it doesn't ends
with a wildcard, *.* will be appended.
copyToRemote(String srcFile, String dstFile): Copies a file from desktop
to remote. Note that dstFile must be the file name, not just a folder. For example, to
copy a file Test.jpg to a folder \Palm, the function must be called as
copyToRemote("c:\\folder\\Test.jpg","\\Palm\\Test.jpg").
copyFromRemote(String srcFile, String dstFile): Copies on the opposite
direction when compared to copyToRemote.
delete(String fileOrFolder): deletes a file or a folder from the remote device.
Read-only files are also deleted.
Conduit Registration
If you don't had installed both ActiveSync and PalmDesktop, you will have to copy
some dlls to the windows/system32 directory, otherwise the conduits will not be
registered. These dlls are located in folder bin/tools/dlls. If you had installed PalmDesktop
but not ActiveSync, you must copy the files rapi.dll and ceutil.dll to the system32 folder.
Otherwise, if you had installed ActiveSync but not PalmDesktop, you must copy all the dlls
in the hotsync folder to system32.
As said before, a Conduit must be registered to be recognized by HotSync or by
ActiveSync. Fortunately, the Conduit class has a method to register and another to
unregister a conduit. You can do this by invoking SuperWaba.exe from the command line,
passing some parameters. This is how you do it:
For Palm Desktop:
To register a conduit:
cd C:\SuperWaba
SuperWaba.exe <full command line to your app> /rp <full command line to your
app>
To unregister a conduit:
cd C:\SuperWaba
SuperWaba.exe <full command line to your app> /up <app creator id>
SuperWaba Companion
188
To register:
c:\superwaba >superwaba.exe
superwaba/samples/ext/sync/painter/PainterConduit PainterConduit
PAin /rp superwaba/samples/ext/sync/painter/PainterConduit
PainterConduit PAin<enter>
To unregister:
c:\superwaba >superwaba.exe
superwaba/samples/ext/sync/painter/PainterConduit PainterConduit
PAin /up PAin<enter>
As noticied above, we're invoking the SuperWaba.exe to interpret our Conduit
class, which is located under c:\SuperWaba\PainterConduit and has creator id PAin to
register or unregister the application itself. And all this must be done from inside
c:\SuperWaba.
It is possible to execute SuperWaba.exe from outside the c:\superwaba folder. Starting
on version 5.1, when the VM starts, it checks if it the current folder has SuperWaba on its
name. If not, then it will try to change to \SuperWaba. This is very useful if your
installation program cannot change the current directory. Note that there are two
restrictions: one, SuperWaba must already be installed on c:\SuperWaba; two, the
following dlls must be in the SuperWaba's folder: cmds21.dll, condmgr.dll, hsapi.dll. They
are present in the Palm Desktop program and may be deleted after the conduit's
registration.
Important Tips
The conduit's creator id MUST MATCH the one used for the application, otherwise, the
Pocket PC conduit will not work as expected.
SuperWaba Companion
189
It is always worth to remember that, if your application is not installed in the PDA, the
conduit for Palm Desktop will not run.
It is not possible to use JDBC from your SuperWaba's program. So, if you plan to
retrieve data via waba.io.Socket, you should use the HttpStream class to communicate
with a server program (an asp page, perl, servlet, or anything else). This server
program will then use JDBC or any other kinds of database communication.
Only during a hotync is possible to find the name of the user who's handheld is being
synchronized, through the waba.sys.Settings.userName member. It is not
possible to get the userName during the configuration stage.
Also during a hotsync, the waba.sys.Settings.romVersion member will store the
rom version of the device being synchronized.
All the SuperWaba API and native libraries will run on Windows (like CatalogSearch,
ZLib, Gif/Png/JPeg images, etc).
You must install SuperWaba on the user's machine so that your conduit can run.
Fortunately, there's an installshield setup prepared for this on
SuperWabaSDK\bin\installers\vm\win32 (it also installs the Conduit files).
To install your program on the user's PDA, you can create an installation using Exegen
The SuperWaba Global Library files are XPlatSyncConduit.pdb and
XPlatSyncConduit.dll.
You MUST NEVER try to install these two files on the PDA: they target only Microsoft
Windows 98 and beyond.
The required Palm Desktop software is: 4.1.0 for Windows 2000 (and before), and
4.1.4 for Windows XP.
The conduit, when registered using the /r option, registers itself for all users. If you
want to register a conduit for a single user, you must update the created registry key
(inside HKEY_CURRENT_USER\Software\U.S. Robotics\Pilot
Desktop\Applicaton<number>), adding a Creator key.
It is always a good idea to read the C++SyncCompanion.pdf present in the Conduit
Development Kit available at http://www.palmos.com/dev/tech/conduits/
The used CDK was 4.03, not 6.01. This ensures compatibility with old Palm Desktops.
As any SuperWaba program, the conduit must also respect the limit of 65500 bytes for
arrays and other data structures. Keep this in mind if you're planning to receive a huge
file or a String bigger than 65500/2 chars in length.
The ActiveSync conduit uses a trick. There's a special registry key that is called when
a device is connected. This key is located at
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\AutoStartOnConnect.
Search the web and you'll find more information about it. The conduit for Pocket PC
uses the Remote API to communicate with the device.
There's no way to call the configuration panel from ActiveSync; you must, instead, run
the program passing the parameter /ca, like this (which runs the setup for the
PaintConduit sample):
c:\superwaba >SuperWaba superwaba/samples/ext/sync/painter/PainterConduit
PainterConduit PAin /ca
SuperWaba Companion
190
SuperWaba Companion
191
{
boolean bringImages = "yes".equals(Settings.appSettings);
if (bringImages)
{
add(status = new Label("",CENTER),LEFT,BOTTOM);
MainWindow.getMainWindow().repaintNow();
showStatus("Synchronizing Painter for "+Settings.userName,false);
String catName = "BMP.PAin.BITM";
String []cats =
RemoteCatalog.listCatalogs(Convert.chars2int("PAin"),Convert.chars2int("BITM"));
if (cats == null)
showStatus("No bitmaps to synchronize",true);
else
if (cats[0].equals(catName))
{
RemoteCatalog rc = new RemoteCatalog(catName);
showStatus("Retrieving record...",false);
PaintRecord pr = new PaintRecord();
if (rc.isOpen() && rc.getRecordCount() > 0 && rc.readRecord(0,pr))
{
if (bmp.getWidth() > 0)
{
rc.delete(); // already closes it (of course).
showStatus("Bitmap stored on "+bmpName,true);
Button btn = new Button(bmp);
btn.onlyShowImage();
add(btn,CENTER,TOP+3);
repaintNow();
Vm.sleep(2000); // let the user
}
else showStatus("Error when loading bitmap",true);
}
else
{
showStatus("Error! Bitmap not synchronized.",true);
if (rc.isOpen())
rc.close();
}
}
}
MainWindow.getMainWindow().exit(0);
}
private void showStatus(String s, boolean log2)
{
status.setText(s);
status.repaintNow();
if (log2)
{
Conduit.log(s);
Vm.sleep(1000);
}
}
}
SuperWaba Companion
192
SuperWaba Companion
263
SuperWaba Companion
264
Appendix I - Thanks to
All SuperWaba community who are always helping to improve this software.
Special thanks to:
Thanks also to Greg Ouzounian and to Steve Kelem who made some grammatical
revisions.
SuperWaba Companion
265
Appendix II - Copyright
All contents of this tutorial, including text, programs, applets, source code, and images are
copyrighted and owned by SuperWaba Ltda, all rights reserved. No material can be
reproduced and/or distributed electronically or in print without written permission.
The use of the source code for the examples is permitted to the company that purchased
this subscription, only.
SuperWaba Companion
266
1.01
added ComboBox field
1.02
fixed IrPrint neede files. 196
added Known Incompatibilities topic. 15
1.03
removed ComboBox field added in 1.01
added Edit.alignment field 64
1.04
added comments 202
1.1
added long/float comments. 183
added new Conduit Synchronization chapter (31), and renumbered the following
ones.
added minDragBarSize. 75
changed info for read modes. 104
info on new Flat ui style. 45-46
1.11
fixed toc
added memory info on conduits.
removed blank pages
important tip at 204
changed ziplib sample.
1.12
enhanced the conduit synchronization chapter.
1.2
enhanced the Conduit API chapter.
1.42
added "PalmOS5/ARM VMware based development environment" on chapter 38
1.43
added conduit dll installation instructions. 231
1.44
rnovais - improved PDBDriver's section
1.45
rnovais improved PDBDriver table's structure information.
1.46
rnovais added the RENAME TABLE command in PDBDriver.
guich added "Logging and Debugging" at PDBDriver's section
rnovais added the RENAME COLUMN command in PDBDriver.
1.47
Added new chapter PDBDriver Synchronization Sample
1.48
rnovais added Date and DateTime data type in PDBDriver's section
rnovais added ResultSet.getDate(col | colName) and ResultSet.getDateTime(col |
colName) methods in ResultSet's section
1.49
SuperWaba Companion
267