Prototyping Widgets

I implemented keyboard handling in the module implementing user interface widgets so that it can be shared between all the different widget implementations. It also spares the developer from having to manage how the keyboard is read and figure out which widgets need to receive key codes. This meant having to implement a simple event system.

The LineEdit widget is the first widget to support keyboard input, implementing a key method that is called when a key code is delivered to it. Widgets are held by Panel objects that normally send key codes to the widgets inside them, but they can also intercept them. In one test program, the two panels intercept key codes and switch between each other when the Tab key is pressed.

 
Switching between panels

What started the investigation into keyboard input handling was an attempt to draw more complex widgets, starting with a calendar widget. This only draws a simple array of cells for each of the days in a month. Once that was done, the next step was obviously to allow different days to be selected.


A basic calendar widget

With a framework in place to handle key codes, and having split out the CalendarWidget into its own module, it seems like it might also be useful to move LineEdit into a separate module and implement a simple text editor widget. The TextEdit widget is a bit more complicated than LineEdit because it needs to be able to handle multi-line text.


A very simple text editor

Moving widgets out of a common module proved to be awkward because the main Panels module contains variables for the display and default font that need to be initialised. Each “child” module uses these variables, so it needs to have a reference to the same Panels module object — it can't load a new one and use that instead. If you arrive at Limbo from Python you tend to assume that all module references will refer to a single module instance, which is not the case.

Another change accompanied the creation of new modules for different widget types. It seemed reasonable to keep specific implementations of draw and key methods in those modules. Since there was already support for key handling callbacks for Panel objects, I created a drawing function and a key handling function (when relevant) for each widget and made the constructor functions set them up for each new widget instance.

The widgets also seem to work fairly well on the target device, apart from some minor colour representation issues and a problem with cursor key handling that I hope to figure out.


David Boddie
28 December 2021