ReactiveUI

 

ReactiveUI is going to be a new user interface for Squeak. It will be able to be a drop-in replacement for Morphic and MVC.

 

ReactiveUI will run in a Site and will use the APIs provided by a SiteBrowser.

 

Status

 

No code yet; only the ideas below. This project will not be started until the Unnamed Grand Project has been released, and this will be built using UGP as a base.

 

Why?

  • MVC is pretty old and tightly bundled with BitBlt / Forms. It doesn't use Canvas (because Canvas didn't exist back then!).
  • Morphic is cruddy. It has too many layers of crud - too many methods doing too many things.
  • Morphic is too slow. It won't run on my Jornada 820, and it even feels sluggish on modern UIs.

 

Requirements

 

  • The UI never blocks. Never. The user is always in control.
  • The user can always see the reason for a wait.
  • The user can always cancel the reason for waiting.
  • UI elements / widgets which are not related to the reason for waiting remain always reactive. For example, a window waiting on a network connection can be closed.

 

This is done by:

  • The mouse pointer is never turned into an hourglass. Individual widgets are drawn to show that they (or their models) are busy.
  • Waiting is done on a per-widget basis rather than on a per-application basis.
  • "Applications" firstly put up a user interface, and then do activities which might take a while to complete rather than the other way around. The user interface should always show immediately. Splash screens are unnecessary and should be forbidden.

 

UI Principles

 

These are defined at a higher level than the requirements above:

 

  • The UI should flow like a page of text. The first thing a user does is at the top left, the last thing a user does is at the bottom right.
    • [cancel] is always to the left of [okay] because the user would normally do [okay] last.
    • [create] is always above [delete]
    • Ideally, closing the window should be in the bottom right corner.
    • The very first thing the user does when the UI is first presented is at the top left corner of the screen. The last thing the user (normally) would do is at the bottom right corner of the screen.
    • This may need to be customised for localisations that use right-to-left or top-to-bottom text.
  • The active window is the brightest window on the screen (i.e. darken the rest of the screen).
  • Modal windows should not block the rest of the UI - instead, they should only block the relevant part of the UI, or maybe be automatically self-destroying if the user clicks out of them.
  • The UI is based around a mental model of associated objects. Every widget on the screen has a target object which it is displaying a particular aspect of. Everything has a context menu.
  • There should always be a way of using the keyboard to control the UI, and the UI should train the user to do so.
    • Idea: if the user holds down SHIFT, CTRL, ALT, or another modifier key, then a keyboard would pop up on the screen showing what all the keys are mapped to, including commands like cut/copy/paste etc.
    • Idea2: There should be a standard keyboard mapping for commands. There should be e.g. standard full-screen, zoom-in and zoom-out keys etc.
  • Windows should have headings which make it obvious what they are - like <h1> in HTML. The title bar is then essentially redundant.

 

Basic design.

 

ReactiveUI will run on a Canvas. It can run within Morphic, MVC, or full-screen. It will be a "Reactive User Interface" as the name suggests; it will always be responsive by intelligently using threads.

 

Every 100ms, the whole UI will be redrawn with optimisations that prevent things that are current from being re-redrawn.

 

The root Canvas of ReactiveUI will have some widget that takes the place of the PasteUpMorph in Morphic. This contains sub-widgets. This main widget will receive all events and cause all redraws, and will pass events down to it's subwidgets. Subwidgets then pass those events to their subwidgets etc. Events are things like keypresses, mouse movements etc.

 

There will be a core set of sub-widgets which can draw themselves very quickly: buttons, lists boxes, sliders, tables etc which form the core widget set. They store enough state in themselves to draw themselves WITHOUT CALLING METHODS on their targets. In this way, reactiveness is guaranteed.

 

If a sub-widget is not in this core set of trusted quickly drawing widgets, then it will be forced to draw itself in a separate thread of execution.

 

When targets change, these widgets will update their state (somehow). This will happen in separate threads and will not affect drawing operation timing at all. There are two ways I can think of for updating state: (1) use the magic Object>>addDependant:... APIs, or (2) after each redraw fork off a thread to check if the target has changed.

 

Threaded architecture.

 

The following threads are needed:

 

Drawing thread

 

The drawing thread draws the display. This thread draws the whole display and then sleeps until the next screen refresh. Trusted widgets (the built-in ones) have >>drawOn: invoked directly by this thread, but untrusted widgets are drawn in a managed forked thread to preserve reactiveness. If untrusted widgets do not finish drawing themselves before the next screen refresh, the progress of their drawing is replaced on screen with a "widget is busy" canvas until the thread completes.

 

Widgets are assumed to have already done all of their layout and content filling; the draw method should be as fast as possible. Drawing theads should never block.

 

XXX this is slow. It is faster if each widget can redraw itself in event-handling code.

 

Event handling thread

 

Events are received from the input devices and occur on a particular sub-canvas - either as a mouse event or as a keyboard event on the canvas which has keyboard focus. Events should be delivered in sequence through a SharedQueue; this is done to prevent, for example, keyboard or mouse events from arriving and being processed out of order. Writing to an event queue should be non-blocking; reading from and event queue should block until an event is available.

 

XXX this is potentially slow - event reactivity would depend on the scheduler's behaviour.

 

Layout

 

The layout can be computed at any stage. Typically, it would be eagerly computed rather than lazily computed.

 

Event handling

 

Events carry the Canvas of the current Widget with them so that the widget can quickly redraw itself without needing to recurse the entire drawing graph again.

 

Two different event streams are used: one for when the user edits text and manipulates widgets, and another for the application's updates to widgets. When the user edits things, the model should be updated, but when a widget's value is modified (e.g. as a result of the model changing by other means), no update events should be propogated (cf: Swing's JTextField's setText(...) method, which is used for both and causes headaches).

 

A timer or stepper could also provide a source of events for animations.

 

Idea: perhaps applications should be able to insert their own events, e.g. command events can either come from the keyboard or from a tool bar.

 

Layout

 

Every widget has a minimum size, maximum size and preferred size (cf: Swing's JComponent).

 

Every widget can be greedy (taking all available space), conservative (only taking the required space) or static (having a preferred size and sticking to it).

 

Core Widgets

 

The Core widgets are "built-in" and trusted; they are drawn in the same thread as the GUI. Core widgets use a model but store enough state to very quickly redraw themselves.

 

Core widgets include:

 

One-line textboxes.

 

 

Specialised textboxes (numbers / currency / etc)...?

 

 

Lists:

  • Drop-down lists.

  • Single-selection lists.

  • Multi-selection lists.

  • Multi-line textboxes (each line of text is a list item with special handling for when a line is inserted into to wrap text around...)

  • Tables (essentially a multi-column list with a header).

  • Trees (lists of indented items with special graphics).

     

    Lists would have a model that keeps track of the current selection and items in the list.

    Items in the list are lazily loaded; it is possible to have a list of items on the UI which can't fit in memory.

     

     

Check boxes.

Radio buttons.

Panels / groups.

Menus:

  • Drop-down menus.

  • Context menus.

  • Pictorial menus / toolbars.

Windows.

Sliders.

Images / Icons ( /movies and animations as well?).

Some mechanism for "custom" widgets to draw on Canvases and react to events?

 

From these components, more complex components such as dialogs can be built.

 

Document editor

 

A document is a collection of paragraphs. Types of paragraphs include:

  • Text up to a carriage return.
  • Headings
  • Bullet points.
  • Inserted objects - images, graphs, etc.
  • header, footers.
  • Custom types, e.g. "pre-formatted text"?

 

Each paragraph can be locked by a particular user for editing, allowing multiple users to edit the document at the same time. Changes to a document can be recorded on a per-paragraph basis so that changes between versions of the document can be viewed.

 

A document is stored as a list of paragraphs (cf: Swing elements).

 

Also stored in that document are formatting changes - changes of margin, alignment, number of columns, whether a particular paragraph is floating or not, etc. It's a good idea to look at the OpenDoc format for suggestions.

 

Code can be a type of paragraph! This will allow automatic formatting and execution inline.


Page Information

  • 1 month ago [history]
  • View page source
  • You're not logged in
  • No tags yet learn more

Wiki Information

Recent PBwiki Blog Posts