Saturday, April 11, 2009

Properties of LinearLayouts

I'm jotting this down so that I don't get stuck on it; it's no kind of show-stopper and can be changed later. I've been simplifying all of the interfaces in the OIWL lately, and I'm now trying to decide what to do with LinearLayout. Specifically, I'm trying to determine what properties linear layouts need to store. Of course they need to know the position and sizes of each of their component boxes, but what else? What about the padding (distance from border to contained widget) within those boxes? What about the horizontal and vertical alignment within each box? What about margins (spacing between each box)?

Each of these could be simulated with other Widgets: For padding, perhaps create simple a Padder widget or something that can be a layout that manages a single Widget and stores padding from each side. For alignment, a similar Aligner widget or something that stores horizontal and vertical alignment could be employed. Might be an easy way to get drawn borders as well. For margins, we could simply put a Spacer widget in a box between a given set of boxes.

The downside to using additional widgets is that each Widget adds overhead to both the memory footprint and rendering time of a given screen. I don't know whether the overhead on either of these is significant enough to merit worry. For now though, I will maintain simple-as-possible widgets, which means LinearLayouts will be without alignment and padding properties. By default, all widgets in a LinearLayout will be centered vertically and horizontally within a box (arbitrary as well).

Wednesday, March 11, 2009

Flicking Frames in SIWL

I ran into a problem with my implementation of FlickableFrame for SIWLExtensions. It turns out that ItemWidgets will block their containing Frame from receiving pointer pressed events. I'm not crystal clear under exactly what circumstances this happens (I believe it is when the pointer is pressed inside of a widget's bounding box), but it is my assessment that flickable frames with widgets are not feasible without lower-level access into SIWL*.

Sadness.

Note, there are ways around this, such as drawing text and images directly onto the frame (i.e. not using StaticText or StaticImage widgets for display) or using a ListFrame (though that's fraught with limitations too). However, unless I can find a way to get around recalculating widget positions every time a layout is drawn, the drawing of Frames is too slow for flicking anyway. This demonstrates the importance of robust event-handling and flexible windowing systems on mobile touch devices, and on tactile devices in general. This is what I'm trying to do with OpenSIWL.

* even as I made that pronouncement I started thinking of a method using a transparent widget covering the drawable area of the frame that intercepts all pointer events and, if they do not match the flick signature, calls the appropriate pointer event handlers on the frame (or rather some other functions that call the handlers, since they're declared protected and final in Frame).

Tuesday, March 10, 2009

New SIWLExtensions tests

Uploaded two more SIWLExtensions test. These ones are to check the StaticText widget and the padding on LinearLayouts. I need to improve test coverage :).

Monday, March 9, 2009

First SIWLExtension Tests

Uploaded a functional test suite for a new portion of this project (see this blog post for more info) to extend the SIWL in addition to making a better toolkit. The suite only has one test in it right now; the source code of the test (with its lack of positioning instructions) is more interesting than the actual test. Check it out!

Sunday, March 8, 2009

Hard Drive Issues and SIWL Extensions

The hard drive in my laptop (which is the only computer that I currently own and develop on at home) appears to have some bad sectors. Luckily I dual boot, and the problem is restricted to one of my partitions. However I haven't been doing much coding this weekend as I have devoted most of my computer time to fixing the issue.

My computer troubles have given me a bit of time to think about what I'm working on though. While I believe that a better GUI framework than SIWL is completely feasible and I think that such an open library is still something I'd like to put together, I think I'm going to port my layouts to SIWL and release them with my flick and StaticText code before continuing to work on the OIWL. There are applications to be created now that I don't want to wait for me.

I do wish that the SIWL design was more extensible--it would make my endeavors unneccesary.

Thursday, March 5, 2009

Event Handling in OIWL

I've been trying to pull inspiration for the design of the OIWL widget library from a few places. One set of places, of course, is other widget libraries that I use (like wxpython and gtkmm) or admire (like android.widget). For example, many libraries that I'm fond of use semi-automatic placement of widgets within layouts, so I decided to use layouts pretty liberally in my design.

I'm having difficulty deciding how to handle events though. Here's some notes:
  • Only Frames (i.e. MIDP Canvas objects) actually receive user events. A frame must then pass information of the event along to its Widget objects.
  • Some events should block others. For example, if I'm going to flick a frame, I don't want buttons to think that I'm looking to click them. Likewise, if I'm clicking a button that's on top of another, I want to be clicking the top button and not both of them (notwithstanding the fact that my buttons shouldn't be overlapping).
  • I'm thinking a WidgetParent should pass user events down to its direct children. Its children can choose to handle the event and block others from handling the event (return true) or not (return false). If none of its children blocks the event, then the parent can then choose to handle and block or not. Seems reasonable every time I think about it. I think it's simple enough if all the events that one cares about are pointer presses, drags, and releases. However, there are still issues:
    • Consider "complex" events like clicking (i.e. a pointer press and release without leaving the widget or without moving from the same spot), double clicking, and flicking (i.e. pointer press followed by drag and a pointer release while the pointer is still moving).
    • More concretely, consider the case of a button on a frame or widget that can scroll. There are instances when it's infeasible to require the user to press a portion of the screen where there are no widgets in order to drag the frame -- like in the case of a list frame, in which the entire view is covered by what are essentially buttons (list items). How then would we distinguish the first part of a button tap (pointer down) from the first part of a view scroll (pointer down)?
      But maybe the question answers itself. Both a button tap and a view widget scroll should be assumed to be started by the pointer press. However, when the pointer starts to drag, the view widget should check whether the button wants to handle the drag event. When the view widget learns that the button does not want to handle the drag, it should assume that it should begin scrolling and tell the button (and all of its child widgets) to cancel whatever in-progress events they have.
So I'll try implementing this model: When the Frame receives a pointerPressed, it calls its layout's handleEvent method with the event type (Event.PRESSED) and the location data. The layout will then pass the event and data along to all of its children's handleEvent methods.

The first thing a given widget will do upon receiving the pointer press notification is check whether its children can satisfy an event with it. If one of them can, the widget will tell all of its other children to cancel their in-process events and it will return true.

If none of a widget's children can satisfy an event with a given user input, then the widget has three options. If the widget doesn't care about pointer pressed input, then it will simply and immediately return false. If a widget needs the Event.PRESSED to start an event (like a button tap), then it will mark that event as started, but still return false. If a given widget can complete an event with the Event.PRESSED, then it will cancel all of its children's in-process events and then do whatever it does on that event and return true.

Saturday, February 28, 2009

New Test Suite

I uploaded a small test suite (3 tests right now) that I will continually add to. Just click a phone button to proceed to the next test. The latest manifestation should be available here.