Journey into SuperWaba

Ever wonder what it takes to write programs for your PDA? I did, and so now I am beginning a journey to try my hand at writing something for the PalmOS. SuperWaba, a variation of Java for the PDA, is my language of choice. And I'm a novice, which makes it all the more unpredictable. Hope you'll come along for the ride! Note: You can read multiple posts on one page if you click on an archive link.

Monday, August 30, 2004

Time to Try A New Approach to the Game

Well, last nite I finally got the chance to continue on my SuperWaba journey by trying to turn the program shell with components into a HiLo program. I didn't get it quite working. Very, very close I think, but am getting fatal error. But as I have discovered that code is probably not the best way to run the program anyway, I'll start over rather than try to fix it.

Lesson #1: Keep things "entirely" event-driven.
Using the main game logic as a do loop is not the best way to handle event-driven programming. In fact, I believe it's just plain wrong. For one thing, it messes up the logic for game ending, aborting, restarting etc. Instead, it makes more sense to maintain status of the game at all times, and then determine what to do based on that status and the new even to be handled. Probably should have realized that from the start. Seems so obvious to me now.

Lesson #2: Dialogs and popups and menus are sub-classes of Window, which is a subclass of Container. That means that you really can't do those elements directly from a container unless it is a Window (e.g. a MainWindow). Of course a MainWindow has other problems with popupBlockingModal() as we saw before.
This indicates to me that all the window related elements need to be either be handled from logic in the main window or from logic in the container, but making use of the main window. There are MainWindow.getMainWindow() functions, or something close to that, which makes that window available for use from a container, so I think it might work from code in a container, but not sure yet.

Open Question #1: Where does the event logic handling go?
Guessed Answer: My best guess right now is that it goes where the controls are. If it's a container with screen elements, then that container probabaly needs to handle the response to the element events, passing it on to the window only when it falls outside the realm of what that container does. This would preserve some sense of encapsulation, which is supposed to be important in Java/OO coding, and it seems to make sense.
An alternative might be to pass all events to the main window and handle them there, but that doesn't seem appropriate.

So my next step is to try to rewrite the HiLo game based on these principles and lessons to see if it makes more sense that way. I suppose I should probably be looking at more sample code to get ideas, but to be honest it just seems to take too long to figure out if the program is even relevant to what I'm doing before I even start to understand the code and why it was written that way. So it might be a good thing to do, but for right now while I still feel like I have a viable path to follow I'll continue to reinvent the wheel on my own. Seem more fun and quicker for now.

BTW, I'm adding my email address in the intro now, but replacing @ with "AT" to reduce spam. Please feel free to contact me.

Until next time, take care!

Wednesday, August 25, 2004

Off Topic: SuperWaba is on my ToDo List!

Just a quick update to let anyone following this blog that I still plan to continue. But between being short-staffed at work and having way too much going on outside of work, there just isn't enough time. In fact, as a fan of David Allen's "Geting Things Done" book, I'm going to spend some time getting things back in order, re-evaluating my priorities, and cleaning out everything that's not important which is sucking up all my time.

As a Christian, I want to approach this like every other search for wisdom about a topic in life... I plan to pray about it. I have to confess that I've let my prayer life slip recently. I've let my heart be distracted by everything from programming to work to sports to whatever. At first, that seems to work fine. But as my time with God fades, my tenderness of heart towards God fades, and prayer becomes difficult. It seems like God is so distant. And then I notice that I've lost that sense of being carried thru each day by His help. And, unfortunately for those around me, I don't have as much patience or peacefulness, so I'm pretty sure I'm harder to deal with. So everyone that knows me should encourage me to pray more... even if you don't believe in God! (yes, sorry, the topic of God is going to come up every now and then. can't help it because it does affect everything i do in one way or another. or at least my goal is for it to affect everything i do!)

Anyway, I don't expect SW to drop off my list. I might spend less time on it, but programming in some form is too important to me right now. And SW is the method, for now at least. Of course with the time constraint and the SW difficulties, I may head to NSBasic not too long from now! In fact, I saw a web page the other day with a bunch of Hello World programs for Palm in languages like an on-board C compiler (the name of which I should know but can't remember right now), a version of pascal, HotPaw basic, iziBasic, SuperWaba, etc. It made me think back on that previous posting about why things are so difficult. Some Hello World programs were just a few simple lines. Others, like the onboard C, were really complicated. Granted, they can probably be generated by an IDE wizard, but gee whiz, that's rediculous! One of these days the hardware will be fast enough that typical functions won't have to be optimized very much to get a responsive GUI, and the code can be simplified.

Thursday, August 19, 2004

Program Shell for New HiLo Game Version

Here's the shell of the new version I'm working on. Three classes this time!
Formatting (tabs) is lost when I post so it's a little hard to read. Anyone know how to avoid that?
There is also some remnants left from the first version of HiLo in the guessing logic. It's only there as a start for me when I add guessing functionality. The point of this code is just to get the container stuff working.

==================
import waba.ui.*;
import waba.fx.*;
import waba.util.Random;
import waba.sys.Convert;

public class HiLoGame extends MainWindow {

public static WelcomeWindow welcomeWindow;
public static GameWindow gameWindow;
MessageBox mbAbout;
public static Graphics g;
MenuBar mbar;

public HiLoGame() {
// Do generic housekeeping to get started
highResPrepared = true;
waba.sys.Settings.setPalmOSStyle(true);
g = new Graphics(this);
setDoubleBuffer(true);
// Set up this programs overall window
// Could probably replace with:
// super("HiLo Guessing Game",TAB_ONLY_BORDER);
setBorderStyle(TAB_ONLY_BORDER);
setTitle("HiLo Guessing Game");
// Prepare this for use in the about menu item
mbAbout = new MessageBox("BobSoft",
"This is Bob's HiLo Guessing Game on Palm!|Enjoy..." );
}

public void onStart() {
// gameWindow is the screen where the game is played
gameWindow = new GameWindow();
//Show the welcome window on startup
welcomeWindow = new WelcomeWindow();
swap(welcomeWindow);

// Setup a menubar
String menu[][] =
{
{"File", "NewGame", "*Options","*HiScores","Exit"},
{"Help","About", "*Test"}
};
mbar = new MenuBar(menu);
setMenuBar(mbar);
}

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 101: popupModal(mbAbout); break;
case 102: break;
case 001: /*end game*/ //playGame();
setTitle("HiLo Guessing Game");
break;
case 004: exit(0); break; // End Program
}
}
}

public void onPaint(Graphics g) {

}
}
=================

/** Container class to handle the welcome screen
*/

import waba.fx.*;
import waba.sys.*;
import waba.util.*;
import waba.ui.*;

public class WelcomeWindow extends Container {
Button exitBtn, beginBtn;

public WelcomeWindow()
{
setBorderStyle(BORDER_LOWERED);
}

public void onStart()
{
add(new Label("Welcome|to|HiLo Game|by|BobSoft"),CENTER,CENTER);
add(exitBtn = new Button("Exit Program"), RIGHT,BOTTOM-5);
add(beginBtn = new Button("Begin Game"), LEFT,BOTTOM-5);
}

public void onEvent(Event event)
{
if (event.type == ControlEvent.PRESSED)
{
if (event.target == beginBtn)
{
MainWindow.getMainWindow().swap(HiLoGame.gameWindow);
}
else if (event.target == exitBtn)
MainWindow.getMainWindow().exit(0);
}
}
}

===================

/** Container class to handle the game playing screen
*/

import waba.fx.*;
import waba.sys.*;
import waba.util.*;
import waba.ui.*;

public class GameWindow extends Container {
Button exitBtn, beginBtn;
String guessDialogButtons[] = {"Guess", "Abort Game"};
InputDialog getGuess;
int target, guess, guessNbr;
int guessCnt;
String resultText, promptText;
Random randomObject;


public GameWindow()
{
setBorderStyle(BORDER_LOWERED);
randomObject = new Random();
}

public void initNewGame() {
target = randomObject.rand(1,100);
guessCnt = 1;
guess = 0;
promptText = "Enter Guess #"+guessCnt+":";
HiLoGame.g.clearScreen();
};

public void playGame() {
initNewGame();
resultText = "This is your first guess.";
do {
getGuess = new InputDialog(resultText, promptText, "", guessDialogButtons);
//popupBlockingModal(getGuess);
guess = Convert.toInt(getGuess.getValue());
resultText = "Your last guess of ("+guess+") was "+calcGuessResult();
guessCnt++;
promptText = "Enter Guess #"+guessCnt+":";
}
while (getGuess.getPressedButtonIndex()==0);
}

public String calcGuessResult() {
String result;
if (guess > target) result = new String("too high.");
else if (guess < target) result = new String("too low.");
else { result = new String("correct on "+guessCnt+" tries!");
initNewGame(); guessCnt = 0;
promptText = "Starting new game... " + promptText;
}
return result;
}

public void onStart()
{
add(new Label("Play Game Here!"),CENTER,CENTER);
add(exitBtn = new Button("Exit Game"), RIGHT,BOTTOM-5);
add(beginBtn = new Button("Begin Game"), LEFT,BOTTOM-5);
}

public void newGame()
{
//Set everything to newGame status and reset the screen widgets
}

public void onEvent(Event event)
{
if (event.type == ControlEvent.PRESSED)
{
if (event.target == beginBtn)
newGame();
else if (event.target == exitBtn)
MainWindow.getMainWindow().exit(0);
}
}
}

============================

Another Way to Code the HiLo Game

After running into the problems with popupBlockingModal() in the main window constructor and main window onStart() method, I started looking further into the alternate way of handling screen contents.

The basic idea (see the sample code for ContainerSwitch included with the SuperWaba download) is that you can extend the Container class with your class that sort of reflects one screen of activity and controls for your program.

Think of the hilo game. You might have a welcome screen and a main activity screen. You can code this as one class for each screen, where the classes extend Container. Then you can swap back and forth from the MainWindow to make whichever container class current and visible. Actually, visible is different than current, but if you use the Window.swap() method, the window you swap into place becomes visible automatically.

Note also that you can always reference the MainWindow with the static method:
MainWindow.getMainWindow()

In my code, I have three classes. I chose not to try to let the main program class contain any screen contents. Those were all done via separate classes that are extentions of Container. This is slightly different from the ContainerSwitch sample code which puts controls on the main window and swaps other containers in and out from there. I suppose I could have done something like that and saved a Class, but for now I wanted to do what was easier for me to keep in my head.

I've also used public static members for the main window class. If you are an expert in Java and SuperWaba, I'm sure my code makes it really obvious that I'm not comfortable with scope and encapsulation yet, especially in this new sort of GUI/event world I'm exploring. But hopefully that will become clearer to me and cleaner in the code as time passes.

As long posts gave me a problem before, I'll use a separate post for the code I've got so far with containers representing screens. There's absolutely no functioning guessing code for the guts of the game, but that shouldn't be too hard to add after the fact.

See ya!

Sunday, August 15, 2004

Code for a simple HiLo Game in SuperWaba

Here's the promised code. Seems that Blogger doesn't either doesn't like to publish from the FireFox browser, or the original post was too long with the code included.
Sorry about the formatting.... it just doesn't seem to keep track of the indents once it gets published.

===============================
import waba.ui.*;
import waba.fx.*;
import waba.util.Random;
import waba.sys.Convert;

public class HiLoGame extends MainWindow {

MenuBar mbar;
String menu[][] = {
{"File", "NewGame", "*Options","*HiScores","Exit"},
{"Help","About", "*Test"}
};
String guessDialogButtons[] = {"Guess", "Abort Game"};
MessageBox mbAbout;
InputDialog getGuess;
Graphics g;
int target, guess, guessNbr;
int guessCnt;
String resultText, promptText;
Random randomObject;

public HiLoGame() {
highResPrepared = true;
randomObject = new Random();
g = new Graphics(this);
setDoubleBuffer(true);
setBorderStyle(TAB_ONLY_BORDER);
setTitle("HiLo Guessing Game");
mbar = new MenuBar(menu);
setMenuBar(mbar);
mbAbout = new MessageBox("BobSoft",
"Welcome to Bob's HiLo Guessing Game on Palm!|Enjoy..." ); }

public void playGame() {
initNewGame();
resultText = "This is your first guess.";
do {
getGuess = new InputDialog(resultText, promptText, "", guessDialogButtons);
popupBlockingModal(getGuess);
guess = Convert.toInt(getGuess.getValue());
resultText = "Your last guess of ("+guess+") was "+calcGuessResult();
guessCnt++;
promptText = "Enter Guess #"+guessCnt+":";
}
while (getGuess.getPressedButtonIndex()==0);
}

public String calcGuessResult() {
String result;
if (guess > target) result = new String("too high.");
else if (guess < target) result = new String("too low.");
else { result = new String("correct on "+guessCnt+" tries!");
initNewGame(); guessCnt = 0;
promptText = "Starting new game... " + promptText;
}
return result;
}

public void initNewGame() {
target = randomObject.rand(1,100);
guessCnt = 1;
guess = 0;
promptText = "Enter Guess #"+guessCnt+":";
g.clearScreen();
};

public void onStart() {
}

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 101: popupModal(mbAbout); break;
case 102: break;
case 001: /*end game*/ playGame();
setTitle("HiLo Guessing Game");
break;
case 004: exit(0); break; // End Program
}
}
}

public void onPaint(Graphics g) {

}

}

===============================

First Simple SuperWaba Program Complete!!!!

YIPPEE!!!!!!

It's been a long, long road. But finally a success. It's not much to look at, but it is a real live SuperWaba program that does something more than say "HELLO WORLD!"

Below you will find the code for a simple HiLo game along the lines of the description in the previous post. None of the bells and whistles are implemented. I don't honestly know if I'll take this any further, but for today I'm happy.

TRANSLATION: "I'm tired, and the next steps look just as hard as the previous steps, and I'm uncertain about continued success. But I'm too hooked on the adventure to stop now."

I'm a little embarrased because the code is not exactly simple and organized. But I'm also proud of it because of the simple fact that it works, and it took some work to get there. What you see is more remnants of false starts than a creation done with a single effort. In other words, it's the code equivalent of a screen door thats held together with more duck tape than screen material.

And bottom line is that I feel now like I have finished my original mission for this blog... to write a simple program in SuperWaba, and capture the journey so that others can follow with the advantage of my trials and tribulations. This blog may be wordy, but I sure wish that I had had something like this available when I started out!

LESSONS AND TRICKS: Any success like this leaves behind it a trail of lessons. Here's a few that are still fresh in my mind...
1) As noted before, you can't use a popupBlockingModal to display a MessageBox or InputDialog from the main window constructor. That is because the event handler has not been set up yet, so the program just hangs. There is a workaround posted on the FAQs, but I didn't understand how to use it, and it even seems to refer to classes that don't exist. My workaround was to move the game play code that needs popupBlockingModal into the even handler for menu items. In other words, you start a game only from a menu item. That guarantees that the event handler has already been set up.
2) There's a lot of goofy code. E.g. The whole initialization of a new game is a bit bogus and confusing because it can happen in multiple places in different manners, but it works. And the counter handling is a bit goofy also.
3) When a game finished the title bar completely disappears, so it is added again after completing a game. You can abort a game by pressing that button.
4) Custom buttons can be chosen in InputDialog by adding a String array with all the button labels in it as a 4th parameter in the constructor. When looking for the results you use getPressedButtonIndex() and compare it to the button number starting with 0. The edit text entered is found with getValue().
5) You need to use the Convert class to do basic type conversions. For example, when converting from String to int, I had to use Convert.toInt(String) instead of the Java function Integer.parseInt(String).
6) SuperWaba is NOT Java. It didn't really sink into my head how much SuperWaba is not Java until I wrote this code. It really isn't Java. There are some similarities, and the syntax is the same, but all the libraries are different. You have to learn them just like you had to learn Java libraries. And with SuperWaba there's more issues because it's more limited and because you're programming for a very limited device. This is certainly a limitation, but hey it's an open source language that is just getting started. I suspect that if it flourishes, we may find it to become more and more powerful and robust.
7) Programming isn't a whole lot easier with SuperWaba than it was with assembly coding with my Z80, or doing BASIC or Pascal. Well, yes, it is a bit nicer. But only a bit. I'm not sure whether it's because I'm not used to GUI programming or because I haven't really done real programming in so long, or because I'm just not spending the time it deserves because I'm so busy. But it's really a pain to make things work right now! Like I said before, things do get easier when you do them often and are familiar with how to go about it. Then you can concentrate more on what you are trying to accomplish rather than the elementary stuff. I still hear that call of NSBasic ringing in my ear. But hey, I already spent some big bucks on the SuperWaba tutorials (which seem more like manuals to me) so maybe I'll stick with it for a while as time allows. If I get really frustrated, I'll see if the alternative is better or worse!

Take care.
Below are some additional ideas on what a HiLo Game could include, and on my next blog post the code for my first simple program. I wanted to include it here, but seems I'm out of blog space. Hope that means this post is too long and not that the entire blog is full. That would be crazy to have happened so fast.
And as always, for those trying to learn SuperWaba, good luck!

Further ideas on HiLo gaming:
* I'm thinking now of more things that you could do with hilo guessing games. Like make it 2-d or 3-d and try to corral various animated items that prefer to escape. Once you start looking at that, it could expand into various terrains, and all kinds of special devices to gain advantage either on the hunter or the escapee side of things. AI is another possiblity instead of the target being completely random. And multiple targets could figure in. I'm sure I can come up with many more ideas than I'm willing to program!

Saturday, August 14, 2004

A Couple of SuperWaba "Gotchas"

As promised, here is some further information about some of the problems I ran into when trying to code a HiLo Guessing game.

1) Like with every new language learned, I'm spending a lot of time trying to "get my bearings" and figure out what pieces available, what are needed and what goes where, etc.
2) The popupBlockingModal() command, used to display a message box or input dialog cannot be used in the main constructor or the onStart() method of the Main Window. The workaround is probably clear to a Java-whiz, or to a pro with SuperWaba, but to me it is going to take a little more study to understand how to make it work.

The approach I decided on for my first attempt at a simple HiLo game was to put things like "New Game" in the menu, and the constructor would hold most of the generic setup, and a playGame() method would intialize the game members (variables), which are basically all going to be static. That means that regardless of where they are referred to within this single class program, they are the same variable. It is implemented that way by defining the static variable in the class definition before the contructor method. Then, I think, even if a new object is created and assigned to that static variable from inside of a method, the object value of the variable is available anywhere in any method of the class. (Note: Upon reflection, static variables were not needed, just the location of the variable definitions outside the methods of the class, so it's accessible anywhere inside the object. Doesn't really matter for this app, I think, whether they are static or not.)

My plan was to handle the main game activity by a series of InputDialog boxes. A new one pops up every time a guess is entered. It contains text that indicates what the last guess was, how many guesses have been made, and whether the last guess was too high, too low or correct.

The user then has the choice to enter a new guess or abort the game. If the guess was correct, a new secret number is selected and the first guess is requested. If the user is done, he just the abort button.

Note: This technique of handling game endings is one way to make a simple game addictive. If the next game is already started up, it "invites" you to continue one more time rather than abort. It's especially enticing if there is some sort of cumulative scoring that includes multiple games. I noticed this first when playing a solitaire game that's set up this way. It was hard to put down. Eventually, after leaving permanent marks on my touch screen and wasting way too many hours playing, I was forced to remove it from my Palm!

BTW, I have all kinds of ideas for future versions if I don't get fed up with SuperWaba first. For example:
*) Allow guessing with alphanumeric guesses and using lexicographical ordering
*) Allow guessing numbers in different bases, such as hexadecimal
*) Allow random movement of the secret target between each guess, and with specified ranges and probabilities.
*) A progress bar that graphically indicates the min/max values, and the remaining hi-lo range of possible target values based on previous guesses and potential movement of the target.

I think this makes for an interesting programming exercise that would include some graphics, but isn't really going to require too much out of me.

An aside: To be honest, all the overhead required to do simple things is making me a little less thrilled with SuperWaba as a hobby language. I'm sure it's speed and power is an advantage relative to alternatives like NSBasic, but as someone with little spare time, it just doesn't seem like the best choice for me right now. In High School, this would have been the ultimate joy, especially compared to the languages and computer hardware that was available to me at the time. But in those days I had the luxury of devoting a lot of time on these things. Currently, I have to be careful with my time, and am already using too much of it on this! But like I keep saying, time will tell. Sometimes things that sound hard at first turn out to be pretty simple once you learn what you're doing. Especially if you are using something all the time.

Have I mentioned recently that I really appreciate Daniel Tauschke's MobileCreator IDE? It's great! While it may make sense to switch to the open source Eclipse IDE (it's well-known in the Java world also, so it might be something with more general application), I really like the integration and simplicity that MobileCreator provides. And I appreciate his making it available in a free starter version appropriate for hobbiests. If I were to ever get serious with SuperWaba, I'd have to consider his professional version very seriously just because I like his product and would like to support his work. And some really exciting news... he is apparently going to be adding a GUI builder into either his IDE or Eclipse. That's based on a newsgroup posting and not official yet, but I'm sure looking forward to seeing what he has coming!

So, anyway, now that you know my plan, let me briefly indicate the struggles so far. Number 1 is just as to be expected. New language, new issues, hard to tell how to go about doing some simple things. And often even after making these things work, it's hard to remember exactly what was involved because I got to the solution in such a roundabout and incremental way through trial and error.

Number 2 refers to something that is posted under the SuperWaba Wiki FAQs...
=====================
Question

Why does using popupBlockingModal() to show a MessageBox? in onStart() hang?

The window that you are trying to pop the MessageBox? up on top of is not ready yet.

To get round this, use a Container to hold the code that wishes to do a popupBlockingModal, and do Window.getTopMost().popupBlockingWindow() from within it. This will work in the onStart() method of the Container because you create the main Window before the Container is initialised. This is an example of the use of Swap to load a container from a main Window class:

   public void onStart() {

/* Now we get our client rect, excluding the border and the title */
Rect r = getClientRect();
/* Prepare the splash screen. */
splash=new SplashScreen(); // A Container
splash.setRect(r);
/* Swap in the SplashScreen module. */
swap(splash);

}
=====================

I'm not exactly sure how I'm going to make this work yet, so there's some more experimentation and learning to do. That one-hour iziBasic program I wrote keeps running though my mind... it was so easy!

Hope to have some answers next time, or at least a workaround.
Until then, if you are trying SuperWaba yourself, good luck.
And if you're a SuperWaba expert, how about some help in the comment section?!

As my some of my online associates say... Cheers!

Ed: Is So Much Programming Complexity Necessary?

Well, it's time for an update. Unfortunately, it's not going to be the update I hoped for.
Granted, I haven't had a lot of time to spend on this. But, still, I thought I was going to proudly announce this week that I have written a simple HiLo guessing game on my Palm in SuperWaba. Instead I'm writing this additional editorial, and the next post will describe some of my issues.

In less than an hour, and right on my Palm device, I was able to write something of about the same complexity as a HiLo game in iziBasic, and using part of the GUI interface to do it (as opposed to doing it as a command line program).

One conclusion... something like NSBasic must be much easier than what I'm trying to do with SuperWaba. And with NSBasic, it would be a commercial product so I could get support. When I come up with all kinds of problems with SuperWaba, there's really not a lot I can do. I am reluctant to post to the bulletin board unless I've really worked on it and it's a "significant" and well-thought out question. They seem a bit stuffy on the whole. Probably because everyone is treating it like "serious" business and they don't have time for beginners. I think they need to consider a seperate group for beginners. I know it can lead to a lot of stupid questions, some of which will still get ignored. But at least it would provide a place for someone like me to have a shot at making things work without too much frustration, because others that have been through it before can help out. And, btw, if you take a look at support prices, you'll find that it's not exactly the sort of thing a hobbiest can afford.

One more negative feature of SuperWaba is that the GUI seems to be generally a little messy in appearance. I haven't looked at all the sample programs, and there are some elements of the GUI that do seem to look pretty nice. But my first impressions are that programs tend to look, well, really ugly.

So why do I want to continue this journey if it seems like the hard way? Well, for one thing, I want to get "over the hump" so I know how to do it even if I don't continue. For another thing, I like Java. I'm starting to wonder more every day why that's true, but there's something "clean" or "pure" about Java code compared to variations of C, Basic, Pascal, etc. What I'm starting to get tired of in Java is nagging SW difficulties in getting started, and the enormous overhead and complexity to do simple things.

Before I go on, let me indicate that I'm not so naive as to think programming is simple and it's only the technology that makes it hard. No. In fact I know that even defining the requirements is a tremendously challenging exercise. And I also have dug in to "hard" and "complex" items in coding. Including writing cross-assemblers, writing machine language code without an assembler, writing routines in Pascal on one of the early Macs to handle abstract algebraic manipuations of things you only see in advanced graduate mathematics. Etc. Etc. I know that things sometimes take work.

So what do I mean by this? Well, consider what it takes just to have a program shell that can be used to handle opening a main window, a menu bar and process events. I don't mean actually putting all the items in the menu and populating the window and capturing and handling all the specific events. I just mean the shell that has a place to do that stuff. Kind of like a scaffolding for your code. In my mind, it's not all that much more advanced than my old machine language and Fortran coding days. The syntax is simpler and the editors are better, and we now have an incredible advance with OO, but some things still seem to work in similar ways.

Now, granted, an IDE can do some of the work for you with wizards and tools. And if you are the organized type, you can even create a library of program shells. (If you are less organized, like me, you just keep a folder with some examples you previously worked with, and you do surgery on them until they look like what you are trying to do.)

But what a nuisance to keep having to place code in multiple places to add a menu item. Or to do a standard pop-up window. Or just about everything you do in Java! (Not too unlike most languages, I'm forced to admit.)

Is the technology of software development and programming languages/environments so immature that we haven't been able to handle something simpler? Or are the tool developers so used to doing this that they don't see it as something worth eliminating?

I saw a new technology the other day that started with an "A" I believe. It was a new way of creating software, supposedly. But you know how big claims are put on incremental technologies. Someone takes a very simple idea and all of a sudden they believe they have changed the fundamental nature of programming.

Well, as best I can tell, this technology, as it is currently implemented, is really a wrapper around every method in Java. As a result, it gives the coder the ability to change specs in those wrappers to do interesting things. For example, if you want to audit the flow of the program you can just change the wrapper once and it affects everything. Now you can see that with a little thought, there are other things that can be managed in more global way by handling it at the point of entry/exit from other code.

That's what comes to mind when I think of how you have to define a variable, create an object, look for certain events, etc. etc when adding a simple control to a Java program. You are doing a very specific thing with your program in terms of requrements and functionality, but Java forces the coder to artificially patch code into multiple places in the program. Yes, it gives a sense of flexibility -- you can create just about anything it seems like -- but what about the 80/20 rule. If you look at programs, I bet that the typical features of 80% of Java programs have very similar kinds of code and requirements. Shouldn't that be handled better?

Two approaches seem to have made some headway in this area. One is code generators that use UML class diagrams to get the code started. But realistically, I'm not sure how much time this saves. Another, which is much more effective, is the GUI builders in IDEs. But isn't it kind of rediculous to have all that translation work going on in the IDE? Why not let the programming language support the typical kinds of things a GUI builder has to handle. No, I don't mean the layout part. That's natural to keep that distinct from the language (I think). But what about all the other specifications. Once the GUI builder gets the layout, look at the messy code that has to be scattered all over once it's translated.

That's not very efficient in my mind, and it seems like there's a big gap between programming languages and the actual things we are usually trying to get programs to do. Languages should support the basic things better, and it shouldn't have to spread code all over to implement ONE concept. Why is the IDE doing all the work to simplify programming. Java took some small steps, and people jumped on board even though there wasn't really much help from IDEs in the early days for programmers in Java. Now the IDEs are catching up. If Fortran and COBOL were like Vodka, then maybe it's time to move from Java to Coke and find a simple way to program that can handle both the scattered code required now and helpful sometimes maybe for flexibility, and also handle translation of real requirements for simple functionality into ONE single change to the program! Back to the GUI thing... why is it so cryptic to do event handling? It's way too much work for simple tasks. Even adding a menu item and setting up a place to handle it. Experienced programmers probably don't care because the IDE does it or because they can do it in their sleep. But if you add up all the work and mind processing cycles spent on that same kind of artificial work across the whole development process, isn't that crazy? Kind of like how it makes you wonder why refactoring, as in changing a method name, has to be such a chore. Whether done by hand or by a tool, there's a lot of work and things to keep track of. Is it hard because it's just a hard concept, or because we haven't figured out how to reflect the simplicity in a development language and environment?

Okay, that's as far as I'm going to go with that. But to summarize... I don't think the simple programming tasks common to most programs should be so difficult and require code to be touched in so many places for a simple program element. But until I am a better programmer, and can come up with some answers, I guess it's just another complaint.

I'd also say, I'm losing my appreciation for SuperWaba in the sense it seems like it may not be a great choice for a hobbiest due to some of the complexity and issues and lack of support options. But I will press on and study some more examples and try some more smaller pieces of sample code and try to get things working. I may change my mind after I know more about this whole thing.

But in the back of my mind right now, I'm thinking... Just work on this enough to feel like you can do some basic stuff and write a hilo guessing game, and then try something a little more fun like NSBasic. Only time will tell!

Saturday, August 07, 2004

OffTopic: iziBasic

I was a bit frustrated the other day at the amount of time it's taking me to get going with SuperWaba. I'm making progress, so it's okay, but it seems like a lot of work just to get going.

As a diversion, since I have written console-style BASIC programs in the past, I thought I'd give iziBasic a try. I read through the simple manual and wrote a simple Hello World program that loops a few times and prints out "Hello World", then waits for you to tap a button to end. What is here in this post is an adaption of some info I posted previously to a 1src.com developers forum. (A nice Palm site to visit!)

All this took me about an hour to prepare and about 20 mins to write that first program and get it running (which I did while waiting at a doctor's office!) Couldn't have done that with SuperWaba. One of the reasons I could do that was iziBasic is an on-board compiler, and I had the manual and sample code on there for reference as well as the editor and compiler for the actual programming. You just edit a memo document or an uncompressed/unencrypted DOC file, and then you can compile and run the program. Works great!

A few things to note though:
1) It's much more simple and limited that SuperWaba, so it may be easy to get started, but you just can't do as much.
2) The free version is nice, but has some small limitations. First it uses a standard about screen saying it's written in iziBasic. Second, a few instructions are not available. I don't know which ones. The good thing is that it should give you time to make a real good trial before you have to pay. But if it works out that you'll use it, I hope you'll register and contribute to support the author.
3) The math parser is limited, so it does operations left to right instead of by arithmetic priority.
4) The language is simple and is a one-pass compiler, so there are some limitations as expected.

But the great thing is that it's easy, you can program on-board, it can be either console-based or use some simple GUI, and it compiles into a .prc program. I think this might be a good choice for the novice programmer trying to get started programming on a Palm PDA.

One more note. You have to name the source file appropriately for the compiler to find it. It can either be a memo or an uncompressed/unencrypted DOC file, but it MUST end with .ibas or it won't realize it's there. That's not in the documentation so it's a bit confusing.

All in all, this looks pretty promising.

Some new information:
* The parsing is very simple-minded, so you need to put line breaks at exactly the right place.
* You also need to assign values to variables a lot. For example, you can't do "IF a> b-c THEN..." Instead you have to set d=b-c and then to "IF a>d THEN...". Another example is that you can't do "A=MESSAGEBOX("This is the message.",1). Instead you have to do B$ = "This is the message." and then A=MESSAGEBOX(B$,1). In other words, many parameters must just be the variable, not a literal or a calculation.
* Variable names for strings and numbers are one letter only (so there are only 26 of each, and you cannot use multiple letter names. This means you have to write a list of variable names and their meaning to keep track. That's not very easy to do when you're programming on-board the Palm. This limitation is the only really serious one I see in iziBasic.) And there is only one array for strings and one for numbers. The first 26 values of the index in an array correspond to the variables A$-Z$ or A-Z, so if you want a bigger array, you put a DIM statement at the beginning of the program, and use the values bigger than 26. Yuk!

This is not enough for me to say iziBasic is no good. Actually it is pretty good except for the variable name limitations. It's an on-board BASIC, it does simple GUI, and it compiles to a runtime program file. For that maybe I'm willing to put up with some minor limitations in the parser.

If you are using iziBasic, let me know what you think, and what you're using it for!

Tuesday, August 03, 2004

A couple of great sample SW programs!

Well, I've only had a couple of hours to spend on this recently, but it has turned out very profitable! I did a little reading of the GUI tutorial and it gave me a little information, but not much perspective.

I knew that wasn't really going to get me to the point I could write some programs, so I continued the hunt by looking for a sample program that I might be able to understand. Bingo!

Here are two great ones: Unit Converter and Mastermind, both by Martin Maier. And both have source code available on the Superwaba.org site (you will be redirected, but that will get you there). Look for sample applications. There's a pretty long list, so you might find some other great ones also, but this is a nice start.

Unit converter is just one class. I suspect that sort of thing is pretty common with SuperWaba. Most simple programs are probably going to be an odd mix of procedural coding and OO language. But on the PDA, you really want to keep the class count down to save memory, and probably the interface and activities of an app will usually be pretty simple. In other words, you probably don't start coding most small SuperWaba apps by using Rational Rose to create all the UML diagrams. Of course, I might be wrong, especially for larger programs, because I'm just basing this on a feel from two tiny programs.

The MasterMind program does a lot of graphics stuff for the board and peg/hole locations. It handles color and black and white PDAs, and even compensates with a scaleFactor of 1 or 2 for hires/normal res screens. I don't really expect to worry about all that with what I'm doing for fun, but it's good to see one way it can be handled.

I don't know if Martin is a typical coder with great style or not, but he sure has helped me to see how SuperWaba programs can work. Here's a few highlights that may help you read through the Unit Converter code...

* You always start a program in a class that extends MainWindow. There are several main pieces that make up the program.

The static class stuff is first. It contains things like the string arrays with menu options, some base members/variables, and the fixed specifics that control the conversion stuff. This area is for things that don't require object instances and are global in nature for that class. I'm not too sure yet how best to distinguish in the "grey" areas between static and instance variables, but I'm sure that will come with practice. It was usually pretty obvious when I was doing the old persistence coding in ages past, but I don't even remember what sort of criteria I used back then. At any rate, you can look at the listing and get an idea of what Martin puts there.

Next is the default constructor for that main program class which is called first by the VM when the program starts. You can set up all your main window parameters and features like the menu bar and frame type and choose PalmOS style (as opposed to PPC style). He also prepares a couple of messageBox items for use later. DoubleBuffer true is, I think, a setting that provides additional screen buffering to smooth out the display so it doesn't flicker.

Then comes the onStart method. This is called after the main constructor. Apparently it matters what goes in the constructor vs the onStart method when running as an applet, but that really isn't a concern for me. This is the likely location for all the controls to be set up on the window. The tutorial seems to be an ideal reference for the GUI controls, but I can't say for sure because I'm just getting started. To be honest, the GUI tutorial really looks more like a manual to me, but that's probably a good thing.

Note that methods starting with "on" are methods that serve a standard function for the object, but are intended to be overwritten by the programmer. In the onStart, it contains stuff that happens at the start of the program after the main program window constructor.

In MasterMind, a graphics object is created because all the drawing happens by calling methods in a graphics object. Seems to be tied to the window that it's drawing in, but I'm not sure about all that. If you are drawing within an onPaint method (which is where you put instructions for repainting a window), you will have a graphics object already because it is being passed as an argument to onPaint. If you are drawing (e.g. lines or shapes) outside of onPaint, you'll need to create a new graphics instance.

onStart seems to put everything on the Unit Converter screen, and is actually pretty easy to follow, I think, for anyone who has written code in any 3G language like C, Fortran, Basic, Java, etc. (I guess that's 3G. I think case tools were supposed to be 4G, but that never really eliminated regular programming, so I'm not really sure what the G's stand for now. Maybe IDEs are like 4G?? Maybe someone out there can clarify for me.)

The last important section is the event handling piece in the onEvent method. (If you're new to Java, methods are like procedures or functions that are associated with the class, and contained/defined in the class along with the variables.)

You can see that he names the controls by starting with an abbreviation for the type of control and then a descriptive name. E.g. lblResultValue is a label that has the result value text label in it. And lbDestination is the destination list box control. Etc.

You interact with these controls by calling methods on them (by putting a period after the name, and then the method call with parameters.)

The events are event objects. When an event happens, the VM calls the onEvent method, passing an event object that contains all the info about the event, and you provide the code for onEvent to figure out what to do based on what happened.

You can look again at the code and see that if something was PRESSED, it is handled based on the case. If it was a press of the calculate button (determined by the control indicated by event.target), it does the calculation and shows the result. If it was the drop down box for a new choice of datatype, then it resets the listbox to have the appropriate values for that kind of data. If it was the list box on the left (source) side, or the list box on the right (destination) side, it resets the label below to match that unit of measure.

The only thing that doesn't make a lot of sense to me is the last part with the menu. It falls under an event.type == ControlEvent.WINDOW_CLOSED. I would have thought that window closed means end the program, so I don't know why menu choices fall under there. They seem like they should exist a level up with the other stuff. But for some reason they are handled under "window closed" event types. Maybe that's just a SW thing that you take as an assumption? Or maybe it's a Java thing? I just don't know, but I imagine I'll find out in time. It's most probably in the GUI tutorial somewhere.

So that's our update for tonight. Took almost as long to write it as to review the code!
I'd tell you what's next, but I have to think about it first. Might be a while because I have a lot going on, but don't worry... I'll be back fairly soon. Thanks for reading!

P.S. I'd love a comment if anyone finds this interesting, or has any tips for me!