| 
  • If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

ReactiveUIDesign

Page history last edited by Michael van der Gulik 14 years, 7 months ago

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 

  • Everything is FAST! And by FAST, I mean that the user gets a reaction in the next screen refresh, even if widgets still need to be filled in with data. Opening a new window is not a CPU intensive activity.
  • 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.
    • There should be a standard keyboard binding for "Do the next thing" - usually corresponding to a "confirm" or "next" button on the screen. Ditto for "cancel". A candidate could be "CTRL-enter". Often this would often accept changes and close the window, although it may take the user on to the next step of, e.g. a Wizard.
  • 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).

 

See TableLayout for Swing. It's awesome. Clone 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)...?

These would be specialised depending on the model used.

 

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

  • A particular column in a table might be a tree. Make sure that alignment still happens.

     

Check boxes.

Radio buttons.

Panels / groups.

Menus:

  • Drop-down menus (which are Lists)

  • 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.

 

Actions

cf: Actions from Java/Swing: http://www.leepoint.net/notes-java/GUI/events/actions.html

 

An action is a command from the user. Actions are the model for:

  • Buttons.
  • RadioButtons.
  • keyboard shortcuts, commands.
  • menu entries.
  • Many other widgets - pressing "enter" on an item or doing some kind of click on it.
  • Drop-down boxes: selecting an item.

 

The user should be able to generically set keyboard bindings to perform certain actions - e.g. CTRL-s for the "Save" action. A prominent occurance of this letter in the label should be underlined. Actions also have a tool-tip; this could also display the key binding to the user. (Idea: the user can re-assign keybindings? Subcanvas sends actions to the application rather than keystrokes?)

 

An action is either being performed ("busy"), or not. When an action is busy, it cannot be performed again. When a user clicks a button, the butten is rendered in a pressed state, possibly with animations, until the action has completed. The user cannot click the button again until the action is complete.

 

While an action is being performed, the UI is informed of its busy status. Any button that is bound to that action should appear in a depressed state, a menu item might have a spinner next to it to show that it is busy, etc. Spinners, status bars and so forth might be bound to an action as well and might display that action's progress. Other panels or widgets might be also bound to an action so that they appear as "disabled" while that action is busy.

 

An Action might have a progress indicator with updateable text? Beware though; the action might modify or close the UI.

 

Actions can be enabled or not. If not enabled, buttons using that Action are displayed as disabled.

 

Java/Swing's Actions have icons.

 

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. Code could also "errors", which is inert text inserted into the code where syntax errors (et al) occur (in a box? Red background?). Code can contain "printIts" which are also inert text. "errors" and "printIts" are removed before code is executed, and commands might exist to remove all of these from code.

 

Links

Java has lots of UI stuff and Swing has a few reusable ideas (and a lot of crap as well).

 

Keyboard shortcuts: http://java.sun.com/products/jlf/ed2/book/Appendix.A.html

Comments (0)

You don't have permission to comment on this page.