I probably should have made this thread a lot earlier, but better late than never!

As I'm working on Calcular Automation and my Rubik's Cube simulator, I'm finding that I want to create a GUI. Especially the cellular automation program will require some (relatively) advanced GUI stuff, beyond just buttons and basic menus. I'll need sliders (for configuring colors), weird checkbox-based things, number selectors, and text input. I have a vague idea of how to do some of these things; for example, I've looked at how Cacluzap and Pacman handle text input and it seems they use a LUT of sorts for the keypresses. But I was wondering what the best way to go about a GUI would be.

The obvious solution (which I would rather avoid) is hard-coding the various instruments for every single screen where they are used. Although this would be easy, it would be painfully copy-paste-based, take up a LOT of space on-calc, and would be next to impossible to modify the behavior of any one GUI control.

I've also considered setting up a modular system in which there's a certain delegated section of memory for GUI controls, each control gets a certain amount of data to store what it needs, and then there's some number somewhere that keeps track of the currently active control. Each control has it's own rendering routine, given an X and Y position, its allotted memory, and possibly a width and height. Whenever a key is pressed, it is redirected to a routine for that GUI control to manage (assuming the GUI control cares). These keys would probably just include [2nd], [Enter], and the arrow keys (which would usually move to the next control). This would also take a fair bit of memory to set up, but creating a new GUI "window" would be as simple as typing up some data to LDIR into the GUI memory and redraw.

So... what do you think is the best solution? Am I overthinking this? Is there a better way? I know most modern OSes use a modular system, but many things may have to change for a calculator. Should I aim for somewhere in between the two systems I've proposed, and if so how? Thank you all for the help!
I've been meaning to respond to this topic, but before I compose a long post based on my experiences creating Doors CS's GUI API, I want to make sure that it's still a subject that is near and dear to your heart. Also, have you had any thoughts on the implementation since you first posted the topic?
KermMartian wrote:
I've been meaning to respond to this topic, but before I compose a long post based on my experiences creating Doors CS's GUI API, I want to make sure that it's still a subject that is near and dear to your heart. Also, have you had any thoughts on the implementation since you first posted the topic?

I've already set up a system that seems to be working where each GUI control has some graphics routines and stuff that are referenced by a LUT. It works, but is far from perfect (partially because I can only stack controls vertically; if I want to put two controls side-by-side I have to create a special control just for that, then have some hard-coded madness to switch between the two mini-controls.) Here's a GIF of the current system I have:

EDIT: As you can see, the GUIs also must be a fixed width and the rest of the screen must be redrawn constantly. Using vBuf2 is not an options because that's where all of the data for the cells is stored. :/

Right now I am trying to write 16.8 fixed-point math routines. Addition and subtraction are obviously very easy, so the next step is multiplication. I have this routine here, but it doesn't work. :/ EDIT: Fixed now! Turns out to get HLu in A you need dec sp \ push hl \ inc sp \ pop af, not push hl \ dec sp \ pop af \ inc sp.
That font looks rather familiar to me. Have you been using my font editor? Very Happy

Fun fact: The font is actually taken from the Sharp PC-1500A pocket computer, which was a device I found in the attic and used before I had a graphing calculator. (They were all the rage in the 80s.) I happened to like how the font has a bit more personality than the more typical 5x7 font.

What you describe is actually quite similar to the GUI system I use in Solitaire for the CSE. While I'm actually quite happy with the implementation I came up with, I don't feel like trying to port it to the eZ80; instead, I decided to rewrite it and expand it.

The Solitaire GUI is somewhat awkward in several respects, but it's optimized to have some simplicity in implementation, and to store as much as possible in flash. The GUI data are stored as a linked-list, allowing most widgets to be in flash, while still having a few seamlessly stored in RAM. Each widget is defined by a struct, which gives information about what it is, where it is on screen, and how the arrow keys can be used to navigate to other controls. Widget actions are looked up using a look-up table, of course. This is done at least twice, first for drawing the widget, and later for when the user interacts with it.

The Solitaire GUI system doesn't really have a concept of container objects, like you have. Nor does it automatically position things. Instead, every object's location is hard-coded. This was done because, one, the objects' locations are fixed anyway, and two, because it eliminates the need for most objects to have any RAM. (Most objects in the GUI just end up being fixed things like lines and labels whose text never changes.) For objects that do need RAM, they have a pointer to the variable they change. Again, this system isn't very flexible, but it saves RAM.

My concept for an eZ80 GUI is more complex, allowing widgets to have (semi-)dynamically allocated RAM, in addition to fixed data, thereby allowing for automatically positioning objects.

Anyway, I'm guessing you're using an index register to pass to your widget routines a pointer to the widget's data. If not, you really should refactor it to be that way, especially since the eZ80 doesn't suck at index register performance. Creating a special object to allow controls to be placed side-by-side isn't strange. It's called a container object, and such things are common in PC GUIs. Depending on how dynamic you want your GUI to be, you may need to compute the size of a dialog in two passes (or possibly more, but a design that needs that can probably be avoided): the first pass just gets an idea of how big things are in the dialog, and the second actually computes positions.

Also, redrawing things a lot isn't unusual, either. With early PC GUIs, RAM was limited, and there wasn't RAM for every object in every window to cache a copy of itself. Instead, widgets had to redraw themselves when a portion of the widget was uncovered. Today, more modern APIs might cache bitmaps, but the desktop GUI foundation in Windows still follows a design in which programs receive redraw messages instead of the OS caching window bitmaps.

PC GUIs can be rather complicated. For example, in .NET, grid layouts actually involve attaching data to widgets to have information about where it is in the grid, and if it takes up multiple rows and/or columns. You may want to avoid such complexity.

Finally, have you considered using a reduced color mode? You can do double-buffering with 256 color mode, and fit a whole screen buffer in scrap RAM with 16 color mode.
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum