UI subsystem interface design - Object
This is a discussion on UI subsystem interface design - Object ; I am trying to design an independent user-interface subsystem that
software can communicate with strictly by passing data by value.
Unfortunately, my first attempt feels rather awkward and I am filled
with an unspeakable dread that when I try to ...
-
UI subsystem interface design
I am trying to design an independent user-interface subsystem that
software can communicate with strictly by passing data by value.
Unfortunately, my first attempt feels rather awkward and I am filled
with an unspeakable dread that when I try to implement the design I
will discover that it is insufficient.
Because of this, I will now provide details of the design I have
created so that I might have hope of someone suggesting something
much better. At the very least I hope that someone will provide a
reference to a well designed UI-subsystem interface that I can borrow
from.
I will call the user-interface subsystem which I am designing 'the
subsystem', while the rest of the software that interacts with the
subsystem will be called 'the application'. When I refer to 'the
interface', I mean the interface between the subsystem and the
application, not the user-interface.
My fundamental design principle is that the interface should define
classes of primitive drawing objects. The application constructs its
UI by composing the primitive drawing objects and then giving those
objects as data to the subsystem, which will be responsible for doing
the drawing based upon the data it is given.
The most primitive class of drawing objects is the Window. Each
window is a rectangle and contains coordinates for its position
represented as floating-point numbers between 0 and 1. Windows
contain other windows recursively, and the actual position of each
window is relative to the containing window. So a window between
coordinates (0,0) and (1,1) always exactly covers the containing
window.
A fundamental helper class for windows is the Mapping class. A
mapping object in the context of this interface is a endomorphism on
objects within some class. Each window contains a mapping for Colors
and a mapping for Fonts.
A color object represents a color idea so that drawing can take place
with colors, and the mapping for a window defines the meaning of each
color used in terms of the colors of the containing window. Adjusting
the mappings of a window affects the way the UI looks for that window
and all contained windows.
The application can create its own color objects and color mappings
to control the way each window appears, but the color mapping of the
outermost window must convert all color objects into color objects
that are supplied by the subsystem so that the subsystem is able to
interpret the colors. To make this possible, the subsystem is
required to supply a ColorScheme object which is an intricate
container for color objects that allows the application to get colors
from the subsystem at varying levels of abstraction.
Font objects are exactly like color objects, except that font objects
represent type-setting information, including more than what one
would normally call 'the font' of some displayed text.
I use the term ID-objects for Font and Color objects because they are
atomic identifiers for the idea that they represent. There is no way
for the application to examine an id-object supplied by the subsystem
just as there is no way for the subsystem to examine an id-object
supplied by the application. However, both the subsystem and the
application will likely be able to examine its own id-objects. Color
objects created by the subsystem to give to the application likely
contain red-green-blue information that only the subsystem has access
to.
The Window class is abstract. The simplest subclass of Window is
called Drawing which represents something visible to the user. A
Drawing is restricted to only contain other Drawings, and contained
drawings hide part of the containing drawing by being painted over
the containing drawing.
There are three subclasses of Drawing: Text, Bitmap, Vector. They
correspond to the three major drawing modes that it would be nice to
support. 3D drawing would also be nice, but let's not get greedy.
These subclasses are concrete and each object contains what one would
expect from the name. A Text object contains a string to be shown in
the window and type-setting information. Bitmap contains an array of
colors. Vector is a graph of lines and points with color and
thickness, as well as perhaps other geometric objects such as
circles.
The other subclass of Window is called UIWindow and it represents an
area of the screen that reacts to the mouse. In addition to those
things which all windows have, a UIWindow has an Event object and an
Event mapping. When the user clicks on a UIWindow, the associated
event is given to the event mapping and the resulting even is given
to the event mapping of the containing UIWindow and so on until to
outermost UIWindow, then the final resulting Event is given to the
application as the notification that the user has clicked on
something.
Event objects are the third sort of id-objects and the primary job of
the application is to create event objects to associate with each
place that the user might click and then to interpret the events when
the objects are given back to the application. Event objects can also
be associated with keyboard events through a completely separate part
of the interface. Naturally, the application is also given the
coordinates of the mouse-click relative to the UIWindow that was
clicked.
The primary job of the subsystem it to take a single Window, render
it and report any events that the user generates upon seeing the
resulting display. When the rendering of the UI is to change, the
application must modify the Window object and then re-send it to the
subsystem.
That completes my brief description of what I have designed up until
now. I am concerned that when even a small part of the UI must change
the entire data for all of the UI must be sent to the subsystem. I
feel like I should have an interface for modifying the UI from the
application even after it has been sent to the subsystem, so that
small changes can be made efficiently with the cooperation of the
subsystem, however that would surely greatly complicate the interface
and I am not entirely certain how it should be done.
Are there any examples of a good data-passing UI subsystem interface
freely available?
-
Re: UI subsystem interface design
Brendan Guild <dont{}spam.me> writes:
>application even after it has been sent to the subsystem, so that
>small changes can be made efficiently with the cooperation of the
>subsystem, however that would surely greatly complicate the interface
>and I am not entirely certain how it should be done.
If the interface description would be XML, you could use
something similar to XPath to address specific parts of the
interface within an IMR (interface modification request).
This will be more easy as long as the structure of the
interface is constant and only dimensions are modified.
It will be more error prone, if an IMR also can change the
structure of the interface, because other parts of the
application still might expect the previous structure.
Another design might split the application: instead of a huge
monolithic application consider many small "applets" for each
part (window) of the UI. An applet controlling a window only
has responsibility for the window and its direct children -
as a kind of "layout-manager". So there will not be a huge
structure visibly to each applet, even though the nesting
of many applets might be large.
It might help to study how UIs are built in Smalltalk,
Squeak and Java - but you might already have done this.
-
Re: UI subsystem interface design
On Tue, 07 Nov 2006 04:20:16 GMT, Brendan Guild <dont{}spam.me> wrote:
>I am trying to design an independent user-interface subsystem that
>software can communicate with strictly by passing data by value.
>Unfortunately, my first attempt feels rather awkward and I am filled
>with an unspeakable dread that when I try to implement the design I
>will discover that it is insufficient.
The most common way to do it is to start off with a root window. In
Microsoft terms (and OS/2) terms (and probably a few others). This is
called the desktop window.
The root window contains an array of windows (called a kids-list).
Each element in that array can also contain its own kids-list (so your
windowing system kind of looks like an upside down tree). Not that a
kids-list element is usually in the form of a window id (integer) and
a pointer to the actual element in memory.
When an application runs it inserts its root window (usually the
frame-window) into the desktops kids-list. The same code that you
use to build you desktop, programmers use in their applications - what
that means is that a control such as an entry field, is just a window
(but you attach added behaviour).
How to attach that behaviour can be solved by using the appropriate
design patterns. You only need to send data to controls/windows that
have behaviour to process that data.
In the old days, one attached an observer (pattern) to a control that
needed to handle events. One used PostMessage and SendMessage for
asynchronous and synchronous data transmitting. Basically, stick your
data in an area of memory and then tell the window control to go get
it (the trick is in NOT moving the data around if you can get away
with it).
>Are there any examples of a good data-passing UI subsystem interface
>freely available?
Check out the open-source stuff or linux stuff, they'll most likely
have something around somewhere.
-
Re: UI subsystem interface design
On Tue, 07 Nov 2006 04:20:16 GMT, Brendan Guild wrote:
> I am trying to design an independent user-interface subsystem that
> software can communicate with strictly by passing data by value.
> Unfortunately, my first attempt feels rather awkward and I am filled
> with an unspeakable dread that when I try to implement the design I
> will discover that it is insufficient.
I don't think that by-value vs. by-reference is really THE issue here.
> Because of this, I will now provide details of the design I have
> created so that I might have hope of someone suggesting something
> much better. At the very least I hope that someone will provide a
> reference to a well designed UI-subsystem interface that I can borrow
> from.
>
> I will call the user-interface subsystem which I am designing 'the
> subsystem', while the rest of the software that interacts with the
> subsystem will be called 'the application'. When I refer to 'the
> interface', I mean the interface between the subsystem and the
> application, not the user-interface.
>
> My fundamental design principle is that the interface should define
> classes of primitive drawing objects. The application constructs its
> UI by composing the primitive drawing objects and then giving those
> objects as data to the subsystem, which will be responsible for doing
> the drawing based upon the data it is given.
>
> The most primitive class of drawing objects is the Window. Each
> window is a rectangle and contains coordinates for its position
> represented as floating-point numbers between 0 and 1. Windows
> contain other windows recursively, and the actual position of each
> window is relative to the containing window. So a window between
> coordinates (0,0) and (1,1) always exactly covers the containing
> window.
It must be rather a fixed-point type then. However the idea is not that
good. The problem is that windows get auto-scaled, which is in most cases
inappropriate.
> A fundamental helper class for windows is the Mapping class. A
> mapping object in the context of this interface is a endomorphism on
> objects within some class. Each window contains a mapping for Colors
> and a mapping for Fonts.
>
> A color object represents a color idea so that drawing can take place
> with colors, and the mapping for a window defines the meaning of each
> color used in terms of the colors of the containing window. Adjusting
> the mappings of a window affects the way the UI looks for that window
> and all contained windows.
Well, there are problems with that. Colors and fonts form a schema, you
need some inheritance mechanism for children to inherit the parent's style.
Aggregation is very not suitable here.
> The application can create its own color objects and color mappings
> to control the way each window appears, but the color mapping of the
> outermost window must convert all color objects into color objects
> that are supplied by the subsystem so that the subsystem is able to
> interpret the colors. To make this possible, the subsystem is
> required to supply a ColorScheme object which is an intricate
> container for color objects that allows the application to get colors
> from the subsystem at varying levels of abstraction.
>
> Font objects are exactly like color objects, except that font objects
> represent type-setting information, including more than what one
> would normally call 'the font' of some displayed text.
>
> I use the term ID-objects for Font and Color objects because they are
> atomic identifiers for the idea that they represent. There is no way
> for the application to examine an id-object supplied by the subsystem
> just as there is no way for the subsystem to examine an id-object
> supplied by the application. However, both the subsystem and the
> application will likely be able to examine its own id-objects. Color
> objects created by the subsystem to give to the application likely
> contain red-green-blue information that only the subsystem has access
> to.
Unfortunately colors and fonts require some resources allocated, especially
fonts do. So you cannot use them by-value.
> The Window class is abstract. The simplest subclass of Window is
> called Drawing which represents something visible to the user. A
> Drawing is restricted to only contain other Drawings, and contained
> drawings hide part of the containing drawing by being painted over
> the containing drawing.
>
> There are three subclasses of Drawing: Text, Bitmap, Vector. They
> correspond to the three major drawing modes that it would be nice to
> support. 3D drawing would also be nice, but let's not get greedy.
[ OpenGL, huh? It is quite declarative, it would be quite difficult to
marry it with your stuff. Any 4GL stuff would be. ]
> These subclasses are concrete and each object contains what one would
> expect from the name. A Text object contains a string to be shown in
> the window and type-setting information. Bitmap contains an array of
> colors. Vector is a graph of lines and points with color and
> thickness, as well as perhaps other geometric objects such as
> circles.
That was quite sketchy. The primitives you describe don't work well on the
window abstraction level. Either you need some quarks lesser than a window,
or you should drop the concept of a rectangular opaque non-overlapping area
(window). It is not a simple decision, but you should make it early.
> The other subclass of Window is called UIWindow and it represents an
> area of the screen that reacts to the mouse. In addition to those
> things which all windows have, a UIWindow has an Event object and an
> Event mapping. When the user clicks on a UIWindow, the associated
> event is given to the event mapping and the resulting even is given
> to the event mapping of the containing UIWindow and so on until to
> outermost UIWindow, then the final resulting Event is given to the
> application as the notification that the user has clicked on
> something.
Event handling is a vast theme. The first question is how would you compose
event handlers. The second question is how would you prevent deadlocks and
circular notifications. The third question is how would you deal with modal
things (usually it leads to multi-threading and opens yet another can of
worms). The fourth question is how would you do synchronous notifications.
All in all, window is an active object. That means you have to compose not
only passive (messages/subprograms) but also active (event handling loop)
behavior. It is a very hard nut.
> Event objects are the third sort of id-objects and the primary job of
> the application is to create event objects to associate with each
> place that the user might click and then to interpret the events when
> the objects are given back to the application. Event objects can also
> be associated with keyboard events through a completely separate part
> of the interface. Naturally, the application is also given the
> coordinates of the mouse-click relative to the UIWindow that was
> clicked.
>
> The primary job of the subsystem it to take a single Window, render
> it and report any events that the user generates upon seeing the
> resulting display. When the rendering of the UI is to change, the
> application must modify the Window object and then re-send it to the
> subsystem.
>
> That completes my brief description of what I have designed up until
> now. I am concerned that when even a small part of the UI must change
> the entire data for all of the UI must be sent to the subsystem. I
> feel like I should have an interface for modifying the UI from the
> application even after it has been sent to the subsystem, so that
> small changes can be made efficiently with the cooperation of the
> subsystem, however that would surely greatly complicate the interface
> and I am not entirely certain how it should be done.
>
> Are there any examples of a good data-passing UI subsystem interface
> freely available?
I saw no universal one. It is easy to criticize gtk, Qt, Windows API, MFC
etc. Too much depends on particular requirements. Both event and time frame
driven architectures have their place. And finally, no OOPL is suitable to
handle parallel types hierarchies required for "universal" case.
(I hope RM folks will jump in and teach us GUI design in SQL... (:-))
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
-
Re: UI subsystem interface design
Responding to Guild...
> My fundamental design principle is that the interface should define
> classes of primitive drawing objects. The application constructs its
> UI by composing the primitive drawing objects and then giving those
> objects as data to the subsystem, which will be responsible for doing
> the drawing based upon the data it is given.
>
> The most primitive class of drawing objects is the Window. Each
> window is a rectangle and contains coordinates for its position
> represented as floating-point numbers between 0 and 1. Windows
> contain other windows recursively, and the actual position of each
> window is relative to the containing window. So a window between
> coordinates (0,0) and (1,1) always exactly covers the containing
> window.
So far, so good. For a GUI the dominant abstractions will be
Window/Control. Typically a Window instance in the subsystem will map
to an object in the application and Control instances will map to
attributes of the object. The logical cohesion is achieved through
relationship instantiation.
>
> A fundamental helper class for windows is the Mapping class. A
> mapping object in the context of this interface is a endomorphism on
> objects within some class. Each window contains a mapping for Colors
> and a mapping for Fonts.
This is commonly known as a Specification object. It is dumb data
holder whose attributes are parametric values that control the
rendering. These would usually be created at startup from a
configuration file (e.g., Windows Resource file). When a Window or
Control instance is created, it would be related to a Specification
object that defined its characteristics in data.
Depending on the complexity of the GUI the Specification objects would
probably be subclassed since the attributes relevant to a text box are
likely to be different than the attributes of a radio button. The
Window/Control instance would be related to a single Specification
object of the appropriate subclass.
>
> A color object represents a color idea so that drawing can take place
> with colors, and the mapping for a window defines the meaning of each
> color used in terms of the colors of the containing window. Adjusting
> the mappings of a window affects the way the UI looks for that window
> and all contained windows.
I am not sure one needs distinct objects for characteristics like color.
The value for rendering just needs to be stored in a Specification
object. The subsystem will be talking to the OS Window Manager for
rendering and that usually just needs appropriate values.
>
> The application can create its own color objects and color mappings
> to control the way each window appears, but the color mapping of the
> outermost window must convert all color objects into color objects
> that are supplied by the subsystem so that the subsystem is able to
> interpret the colors. To make this possible, the subsystem is
> required to supply a ColorScheme object which is an intricate
> container for color objects that allows the application to get colors
> from the subsystem at varying levels of abstraction.
Unless you are doing complex graphics in a graphics pane, this seems
like overkill. A vanilla GUI usually has fixed colors for various
classes of instances (or elements of the instances). Thus a standard
Window instance has different elements (title bar, frame, foreground,
etc.) and each may have its own color. But all one needs to specify
that are attributes like titleBackgroundColor in the Specification object.
Unless the GUI is really complicated with multiple themes for windows or
custom windows/controls, I would be hesitant the break out the
individual elements like title bars and scroll bars. The notion of a
GUI "theme" can be expressed in the configuration data by simply using
the same values for the same element contexts.
>
> Font objects are exactly like color objects, except that font objects
> represent type-setting information, including more than what one
> would normally call 'the font' of some displayed text.
Same argument here because typically all one has to specify to the OS
Window Manger is font name, size, and a couple of other characteristic
values for italics, bold, etc. Those can be expressed in data values.
However, unlike color, one can make a case for fonts having their own
Specification objects simply because of the number of parameters.
Something like
* specifies R2 *
[Control] ----------------------- [FontSpec]
| *
| specifies
|
| R1
|
| 1
[ControlSpec]
A
|
+--------------+--------- ...
| |
[TextBox] [CombBox]
One would need some sort of explicit identity in [FontSpec] to pass the
information properly to the OS Window Manager.
>
> I use the term ID-objects for Font and Color objects because they are
> atomic identifiers for the idea that they represent. There is no way
> for the application to examine an id-object supplied by the subsystem
> just as there is no way for the subsystem to examine an id-object
> supplied by the application. However, both the subsystem and the
> application will likely be able to examine its own id-objects. Color
> objects created by the subsystem to give to the application likely
> contain red-green-blue information that only the subsystem has access
> to.
You are going to have to put some words around how these objects differ
from ordinary object identity. There has to be a mapping of the message
data packets in the subsystem interface and you will need some way to
ensure that mapping, but I don't see that being dedicated identity objects.
For example, in the application one might have an Account object with a
'balance' attribute. In the Application the specific Account has an
account number that represents explicit identity. In the GUI there is a
corresponding Window object with a unique window ID used by the OS
Window Manager. That Window object will have an attribute for
accountNumber and a related Control object for the "balance" text box.
Window.accountNumber will have the same value as Account.accountNumber
but, unlike Account, it will not be the window identifier, which will be
Window.windowID. Similarly, Account.balance will be the same value as
Control.value but you will need an identity for the Control object that
doesn't exist on the application side.
The identity of the Control is likely to be implicit (a pointer address)
but one still needs to have a consistent mapping. Typically that will
be handled positionally in the message data packet (e.g., the third
parameter of the displayAccount message will be Account.balance). The
subsystem interface handles the mapping to a factory object that will
create the Window and related Control instances. The subsystem
interface selects the right factory object based on the message ID and
then passes the message data packet arguments to that factory in the
proper order.
Similarly, the setBalance interface message from the application will
include values for Account.accountNumber and Account.balance. The
subsystem interface needs to know how to interpret the data packet for
setBalance to identify the right Window instance and navigate to the
right Control instance to set Control.value.
>
> The Window class is abstract. The simplest subclass of Window is
> called Drawing which represents something visible to the user. A
> Drawing is restricted to only contain other Drawings, and contained
> drawings hide part of the containing drawing by being painted over
> the containing drawing.
>
> There are three subclasses of Drawing: Text, Bitmap, Vector. They
> correspond to the three major drawing modes that it would be nice to
> support. 3D drawing would also be nice, but let's not get greedy.
> These subclasses are concrete and each object contains what one would
> expect from the name. A Text object contains a string to be shown in
> the window and type-setting information. Bitmap contains an array of
> colors. Vector is a graph of lines and points with color and
> thickness, as well as perhaps other geometric objects such as
> circles.
OK, this is more complicated than I thought (I assumed a typical GUI).
What goes on within a graphics pane of a window is much more complex.
The abstractions one will use for rendering graphics in a graphics pane
will depend strongly on what the rendering engine expects. The last
time I did any graphics was so long ago that anything specific I suggest
would likely be hopelessly out of date.
However, the basic idea here seems reasonable. The same sort of
approach would apply. One identifies what sorts of things one needs to
render, figures out what rendering engine abstractions are appropriate,
and then provides an infrastructure of Specification objects and
factories to create them. The same notions of identity mapping through
the interface would apply.
>
> The other subclass of Window is called UIWindow and it represents an
> area of the screen that reacts to the mouse. In addition to those
> things which all windows have, a UIWindow has an Event object and an
> Event mapping. When the user clicks on a UIWindow, the associated
> event is given to the event mapping and the resulting even is given
> to the event mapping of the containing UIWindow and so on until to
> outermost UIWindow, then the final resulting Event is given to the
> application as the notification that the user has clicked on
> something.
>
> Event objects are the third sort of id-objects and the primary job of
> the application is to create event objects to associate with each
> place that the user might click and then to interpret the events when
> the objects are given back to the application. Event objects can also
> be associated with keyboard events through a completely separate part
> of the interface. Naturally, the application is also given the
> coordinates of the mouse-click relative to the UIWindow that was
> clicked.
Since user actions are inherently asynchronous, it is quite reasonable
to employ event-based communications between the UI subsystem and the
application. The events, though, are simply the messages exchanged
between them (i.e., between subsystem and OS Window Manger and between
subsystem and application). There will be associated objects because of
the data packets.
I am not sure you need a notion of 'event' /within/ the subsystem,
though. It will probably be easier to construct the subsystem to be
synchronous and do any necessary serialization in the interfaces. The
OS already provides a queue to serialize its events (keyboard & mouse)
so one just needs to pop them when ready for processing. On the
application side things will probably already be serialized (i.e., the
application responds to UI events in knee-jerk fashion). Even if
application messages are asynchronous, one would probably serialize them
by having a queue in the subsystem interface implementation (e.g., a
Facade pattern class implementation).
>
> The primary job of the subsystem it to take a single Window, render
> it and report any events that the user generates upon seeing the
> resulting display. When the rendering of the UI is to change, the
> application must modify the Window object and then re-send it to the
> subsystem.
This sounds suspicious to me. Even simple applications usually have
multiple windows, even if they are not readily apparent to the user;
things like dialog boxes for options and whatnot. It is also easier to
use borderless windows to construct things like lists.
OTOH, if your main goal is a single graphics display and few other
controls are needed, then that could be a pane in a single window.
>
> That completes my brief description of what I have designed up until
> now. I am concerned that when even a small part of the UI must change
> the entire data for all of the UI must be sent to the subsystem. I
> feel like I should have an interface for modifying the UI from the
> application even after it has been sent to the subsystem, so that
> small changes can be made efficiently with the cooperation of the
> subsystem, however that would surely greatly complicate the interface
> and I am not entirely certain how it should be done.
When one builds using abstractions from the UI paradigm itself, that
should benefit maintainability greatly. That's because UIs are actually
pretty narrowly defined in terms of very basic building blocks (e.g.,
Window/Control). A graphics rendering engine will be more complex, but
still composes from basic widgets.
Better yet, the differences in those abstractions are described in data.
So a lot of changes can probably be made in the configuration data
without touching the code at all. Take a look at a Windows Resource
file. An entire GUI can be defined in terms of external data. All one
then need to "touch" is the identity mapping in the interface that links
the application view to the configuration data.
>
> Are there any examples of a good data-passing UI subsystem interface
> freely available?
Your OS Window Manager is the most obvious example. Your subsystem
interface is equivalent to the typical message loop in a Windows
program. It accepts a message from the OS Window Manager and dispatches
it to the appropriate receiver based on message ID. There would be an
equivalent subsystem interface one the application side to accept
messages from the application. And the application would have its own
interface to accept messages from the UI subsystem. [IOW, subsystem
interfaces are two-way. The Application Partitioning category of my
blog has a post on this.] All those interfaces do basically the same thing.
--
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.
H. S. Lahman
hsl{}pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info{}pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
-
Re: UI subsystem interface design
H. S. Lahman wrote:
> Responding to Guild...
>
> So far, so good. For a GUI the dominant abstractions will be
> Window/Control. Typically a Window instance in the subsystem will
> map to an object in the application and Control instances will map
> to attributes of the object. The logical cohesion is achieved
> through relationship instantiation.
Could you go into more detail on this point? What is a Control
instance and what would it's role be? I doubt that I would want let
an instance of something called Control be accessed by the subsystem,
because that would be passing a message containing an object (as
appearing high on your list of couplings between subsystems.) I want
to keep my UI system highly decoupled from the application using,
that is why I am restricting myself to data passed by value.
>> A fundamental helper class for windows is the Mapping class. A
>> mapping object in the context of this interface is a endomorphism
>> on objects within some class. Each window contains a mapping for
>> Colors and a mapping for Fonts.
>
> This is commonly known as a Specification object. It is dumb data
> holder whose attributes are parametric values that control the
> rendering.
I doubt it. Mappings are containers that take one object as a key and
spit out a corresponding object. In the case of my design, they
always spit out an object of the same class as the key, making them
an endomorphism for that class.
The idea is that the mappings can be used so that a complex GUI can
be constructed in parts with each part using its own set of colors
and fonts. Once a part of the GUI has been constructed, a mapping can
be applied to it to translate the abstract colors and fonts into more
concrete colors or fonts. So one part of the GUI could be constructed
using 'Heading 1' as a font, then a mapping could convert that to
'Centered 14pt Bold Arial' for rendering. Similarly, there might be a
color called 'Background' used in the application, but it would have
to be mapped to something that the ui subsystem understands, such as
'White'.
I do this because the structure that the application builds is quite
complicated and with mappings some of it might be reused or
simplified. The application must completely construct a data
representation of what the user is to see, then it is passed as data
to the subsystem to be converted by whatever means necessary into
something that actually appears on the screen.
> I am not sure one needs distinct objects for characteristics like
> color.
I am not sure of that either, but if I do not have objects for that,
then I cannot make them abstract. Different implementations of the
subsystem might have different concrete representations for colors,
and the application might like to work with fully abstract colors
such as 'Foreground', 'Background', and 'Highlight'.
> Unless you are doing complex graphics in a graphics pane, this
> seems like overkill. A vanilla GUI usually has fixed colors for
> various classes of instances (or elements of the instances). Thus
> a standard Window instance has different elements (title bar,
> frame, foreground, etc.) and each may have its own color. But all
> one needs to specify that are attributes like titleBackgroundColor
> in the Specification object.
Yes, very true! I am also interested in how one might have a fully
by-value data passing interface for creating a vanilla GUI with
buttons and scroll bars, etc. but the design I presented was intended
to be far more low-level than that.
>> I use the term ID-objects for Font and Color objects because they
>> are atomic identifiers for the idea that they represent. There is
>> no way for the application to examine an id-object supplied by
>> the subsystem just as there is no way for the subsystem to
>> examine an id-object supplied by the application. However, both
>> the subsystem and the application will likely be able to examine
>> its own id-objects. Color objects created by the subsystem to
>> give to the application likely contain red-green-blue information
>> that only the subsystem has access to.
>
> You are going to have to put some words around how these objects
> differ from ordinary object identity. There has to be a mapping
> of the message data packets in the subsystem interface and you
> will need some way to ensure that mapping, but I don't see that
> being dedicated identity objects.
Perhaps identity was the wrong word. The color or font objects
provide abstract representations for the application of certain
colors or fonts. I called them identifiers only because they do
nothing but abstractly reference something more concrete, not because
I expect them to be compared for identity.
I use them so abstractly because I do not to expose the internal
details of such low-level things to the application outside of the
subsystem. On the other hand, it would probably do no harm to have
the application directly give the subsystem red-green-blue color
combinations.
> For example, in the application one might have an Account object
> with a 'balance' attribute. In the Application the specific
> Account has an account number that represents explicit identity.
> In the GUI there is a corresponding Window object with a unique
> window ID used by the OS Window Manager. That Window object will
> have an attribute for accountNumber and a related Control object
> for the "balance" text box.
Why would the Window object have an attribute for accountNumber?
Perhaps you are using the term differently than I am, but even so it
seems strange. In the design I offered, Window objects were data
objects to be passed to the GUI subsystem. The GUI subsystem only
knows GUI stuff and had no clue about account numbers, so an
accountNumber attribute seems unlikely.
The designs that I can see that would have the Window object with an
accountNumber attribute are ones which have the object containing
behaviour and being passed to the subsystem so that the subsystem can
use that behaviour. But that is the sort of strong coupling which I
have been lead to believe is undesirable.
> The identity of the Control is likely to be implicit (a pointer
> address) but one still needs to have a consistent mapping.
Unfortunately, without knowing the intended purpose of a Control
object, it is difficult to interpret the advice you are giving here.
I will certainly look back upon it eagerly if you would offer a few
words about what Control represents.
> The subsystem interface handles the mapping to a factory object
> that will create the Window and related Control instances.
Is the factory created outside the subsystem and used by the
subsystem, or is this an implementation detail contained entirely
within the subsystem? If it is the former, then surely that is an
inappropriate coupling.
> Similarly, the setBalance interface message from the application
> will include values for Account.accountNumber and Account.balance.
> The subsystem interface needs to know how to interpret the data
> packet for setBalance to identify the right Window instance and
> navigate to the right Control instance to set Control.value.
So the subsystem is strictly only useful for accounting software? I
was rather hoping that it would be more general than that, something
to hide the vagaries of graphics libraries that do not offer the
strong decoupling of messages containing only data by value.
> I am not sure you need a notion of 'event' /within/ the subsystem,
> though.
Just to be clear, I am not trying to describe any sort of design for
anything within the subsystem. My post was solely designed to deal
with the interface for the subsystem. I assume that once I have a
quality interface design, the subsystem itself will fall easily into
place based on the interface.
>> The primary job of the subsystem it to take a single Window,
>> render it and report any events that the user generates upon
>> seeing the resulting display. When the rendering of the UI is to
>> change, the application must modify the Window object and then
>> re-send it to the subsystem.
>
> This sounds suspicious to me. Even simple applications usually
> have multiple windows, even if they are not readily apparent to
> the user; things like dialog boxes for options and whatnot. It is
> also easier to use borderless windows to construct things like
> lists.
I expected that the UI subsystem would have access to a single
contiguous area for drawing in. To make multiple windows within that
through the design I gave, one would just put multiple windows within
the main window. On the other hand, the UI might be fundamentally
based upon multiple windows in a shared windowing environment with
other applications, in which case the subsystem interface would have
to be modified to accept multiple windows, but doing that seems
beyond the scope of my project here.
>> Are there any examples of a good data-passing UI subsystem
>> interface freely available?
>
> Your OS Window Manager is the most obvious example. Your
> subsystem interface is equivalent to the typical message loop in a
> Windows program. It accepts a message from the OS Window Manager
> and dispatches it to the appropriate receiver based on message ID.
> There would be an equivalent subsystem interface one the
> application side to accept messages from the application. And the
> application would have its own interface to accept messages from
> the UI subsystem.
Yes, that is very true! I am so used to using libraries to hide that
sort of thing that I had forgotten for a moment how simple and
decoupled such a windowing system really is.
I would never have considered looking to something so low-level for
design ideas for my abstract UI subsystem interface. I am still
hoping that it won't be necessary to send a separate message for
every little drawing operation.
-
Re: UI subsystem interface design
Responding to Guild...
>>So far, so good. For a GUI the dominant abstractions will be
>>Window/Control. Typically a Window instance in the subsystem will
>>map to an object in the application and Control instances will map
>>to attributes of the object. The logical cohesion is achieved
>>through relationship instantiation.
>
>
> Could you go into more detail on this point? What is a Control
> instance and what would it's role be? I doubt that I would want let
> an instance of something called Control be accessed by the subsystem,
> because that would be passing a message containing an object (as
> appearing high on your list of couplings between subsystems.) I want
> to keep my UI system highly decoupled from the application using,
> that is why I am restricting myself to data passed by value.
In the GUI paradigm display is dominated by two abstractions: Windows
and Controls. Controls are elements within a particular Window, such as
titles, buttons, text boxes, radio buttons, scroll bars, etc. (See one
of the common GUI standards, such as Motif, for more precise definitions.)
In the GUI display paradigm one basically has:
[Window]
| 1
| element of
|
| R1
|
| *
[Control]
So a window is abstracted with a Window object and some set of related
Control objects. IOW, in the display a single application object like
an Account will be represented by multiple objects at a lower level of
abstraction. (Think: delegation on the GUI side.)
The decoupling is provided as the subsystem and application each map the
message in terms of their own semantics. So the GUI subsystem views the
displayAccount message and its associated data packet in terms of a
specific Window object and its related Control objects while the
application views that same message in terms of a single Account object
and its attributes.
>>>A fundamental helper class for windows is the Mapping class. A
>>>mapping object in the context of this interface is a endomorphism
>>>on objects within some class. Each window contains a mapping for
>>>Colors and a mapping for Fonts.
>>
>>This is commonly known as a Specification object. It is dumb data
>>holder whose attributes are parametric values that control the
>>rendering.
>
>
> I doubt it. Mappings are containers that take one object as a key and
> spit out a corresponding object. In the case of my design, they
> always spit out an object of the same class as the key, making them
> an endomorphism for that class.
All I can do is try to explain how Tried & True approach used in things
like commercial GUI builders going back to the '80s.
There are only two core classes of objects in the GUI display paradigm:
various flavors of Window and Control. Differences between them are
expressed purely in terms of parametric data. The application semantics
only appear in terms of text values for titles and labels that are
provided externally. Because things like the notion of 'themes' reuse
some of the same data, Specification objects are very commonly used to
hold the data.
[There will be lots of other objects in a GUI subsystem but they are
primarily infrastructure objects to instantiate Windows/Controls, read
configuration data from external sources (to instantiate Specification
objects!), and manage communications with the OS Window Manager.]
>
> The idea is that the mappings can be used so that a complex GUI can
> be constructed in parts with each part using its own set of colors
> and fonts. Once a part of the GUI has been constructed, a mapping can
> be applied to it to translate the abstract colors and fonts into more
> concrete colors or fonts. So one part of the GUI could be constructed
> using 'Heading 1' as a font, then a mapping could convert that to
> 'Centered 14pt Bold Arial' for rendering. Similarly, there might be a
> color called 'Background' used in the application, but it would have
> to be mapped to something that the ui subsystem understands, such as
> 'White'.
That is exactly what the parametric data in Specification objects
provides. The difference is that one can make changes to the
Specification objects without touching the code through the external
configuration data.
>>I am not sure one needs distinct objects for characteristics like
>>color.
>
>
> I am not sure of that either, but if I do not have objects for that,
> then I cannot make them abstract. Different implementations of the
> subsystem might have different concrete representations for colors,
> and the application might like to work with fully abstract colors
> such as 'Foreground', 'Background', and 'Highlight'.
The display objects just have a gazillion data attributes whose values
determine what the user sees. Foreground and background colors are
typically different attributes. For things like highlighting that are
dependent on dynamic context, someone has to understand the context.
That someone will then set the color to the appropriate value when the
highlighting context prevails.
[With modern GUI libraries, typically the control itself will handle
contexts like click-and-drag to select an entire field when editing in a
text box control. All one has to provide is an attribute value for what
the highlight color needs to be when highlighting is relevant. IOW, the
mouse/keyboard messages are dispatched to the <library> Control instance
and it does the editing internally.]
>>>I use the term ID-objects for Font and Color objects because they
>>>are atomic identifiers for the idea that they represent. There is
>>>no way for the application to examine an id-object supplied by
>>>the subsystem just as there is no way for the subsystem to
>>>examine an id-object supplied by the application. However, both
>>>the subsystem and the application will likely be able to examine
>>>its own id-objects. Color objects created by the subsystem to
>>>give to the application likely contain red-green-blue information
>>>that only the subsystem has access to.
>>
>>You are going to have to put some words around how these objects
>>differ from ordinary object identity. There has to be a mapping
>>of the message data packets in the subsystem interface and you
>>will need some way to ensure that mapping, but I don't see that
>>being dedicated identity objects.
>
>
> Perhaps identity was the wrong word. The color or font objects
> provide abstract representations for the application of certain
> colors or fonts. I called them identifiers only because they do
> nothing but abstractly reference something more concrete, not because
> I expect them to be compared for identity.
>
> I use them so abstractly because I do not to expose the internal
> details of such low-level things to the application outside of the
> subsystem. On the other hand, it would probably do no harm to have
> the application directly give the subsystem red-green-blue color
> combinations.
There should be no need to expose things like color and font rendering
to the application in any way under any circumstances. Those are pure
display support and they are driven by the GUI design, not the
application. All the application supplies is the data to be displayed.
How the data is displayed is determined by the GUI design, which
specifies things like color, font, scroll bars, specific controls, etc.
Those GUI design elements can then be captured in configuration data
that only the GUI subsystem needs to know about and access when it
instantiates the display objects.
Thus the application sends a message like
displayAccount: accountNumber, balance, address, ...
because that is all it knows about. The job of the GUI subsystem is to
know that an Account needs to be displayed in a particular Window with a
particular title, color scheme, etc. and that the Window will have a
suite of Control instances that will display Control.value with the
right labels, colors, fonts, etc. All those values come from the
configuration data that the GUI design defined.
The GUI subsystem just needs a mapping from message ID (displayAccount)
to the particular configuration data and a <usually positional> mapping
of the data packet to particular Control values.
>>For example, in the application one might have an Account object
>>with a 'balance' attribute. In the Application the specific
>>Account has an account number that represents explicit identity.
>>In the GUI there is a corresponding Window object with a unique
>>window ID used by the OS Window Manager. That Window object will
>>have an attribute for accountNumber and a related Control object
>>for the "balance" text box.
>
>
> Why would the Window object have an attribute for accountNumber?
Good catch. If it is to be displayed, it would be a value in a Control
instance like a TextBox. Nor is it explicit identity for the Window
object; that would usually be the handle provided by the OS Window
Manager. Nor is one likely to need it to map to the configuration data;
that would usually be done from the message ID since all accounts are
likely to be displayed with the same Window/Control display
characteristics (i.e., all would share the same Specification object!).
The only time it would be in an attribute was if it were a text title
for the Window. But normally labels are regarded as immutable so for it
to differ from one Account display to another, it would more properly be
placed in a Control.
I was actually being dyslexic in thinking about the mapping. If you
have two accounts being displayed at once there is a problem with
keeping track of which Window is which when messages from the
application are processed. One could do that by looking at the right
Control.value for the account number, but that would be seriously ugly.
Typically one does it through a lookup table that maps accountNumber
to WindowID to object reference when dispatching messages from the
application (or the OS Window Manager). So there is an accountNumber
that is used to uniquely map to Window instances, but it would not be an
attribute of the Window directly.
>>The subsystem interface handles the mapping to a factory object
>>that will create the Window and related Control instances.
>
>
> Is the factory created outside the subsystem and used by the
> subsystem, or is this an implementation detail contained entirely
> within the subsystem? If it is the former, then surely that is an
> inappropriate coupling.
Inside. It is an infrastructure object in the GUI subsystem. Its main
job is usually to read/find the correct configuration data to initialize
the object based on message ID. Typically a single factory object will
instantiate the Window object and all of its relevant Control objects
along with their relationships.
>>Similarly, the setBalance interface message from the application
>>will include values for Account.accountNumber and Account.balance.
>> The subsystem interface needs to know how to interpret the data
>>packet for setBalance to identify the right Window instance and
>>navigate to the right Control instance to set Control.value.
>
>
> So the subsystem is strictly only useful for accounting software? I
> was rather hoping that it would be more general than that, something
> to hide the vagaries of graphics libraries that do not offer the
> strong decoupling of messages containing only data by value.
No, it is just an example from a familiar problem space. There is a
message identifier and a pile of data in the message data packet. The
application and the GUI subsystem both have their own unique
interpretation of identity for that message and its elements in their
own terms. Each side knows how to map the message into unique object
identities on its side of the interface.
Thus the application will map the message in terms of one or more
identifiable problem space entities that it understands (Account, Cat,
Contract, Troll, etc.). Similarly, the GUI subsystem will map the
message into one or more identifiable problem space entities that it
understands (Window/Control objects). In subsystem subject matter terms
they are different problem spaces.
However, in overall application context at a higher level of abstraction
they map the same entities; just the subject matter abstraction of them
is different. That high level correspondence allows an unambiguous
mapping between the subject matter views through the configuration data.
IOw, the configuration data provides the mapping between the GUI
design view and application solution view.
>>>The primary job of the subsystem it to take a single Window,
>>>render it and report any events that the user generates upon
>>>seeing the resulting display. When the rendering of the UI is to
>>>change, the application must modify the Window object and then
>>>re-send it to the subsystem.
>>
>>This sounds suspicious to me. Even simple applications usually
>>have multiple windows, even if they are not readily apparent to
>>the user; things like dialog boxes for options and whatnot. It is
>>also easier to use borderless windows to construct things like
>>lists.
>
>
> I expected that the UI subsystem would have access to a single
> contiguous area for drawing in. To make multiple windows within that
> through the design I gave, one would just put multiple windows within
> the main window. On the other hand, the UI might be fundamentally
> based upon multiple windows in a shared windowing environment with
> other applications, in which case the subsystem interface would have
> to be modified to accept multiple windows, but doing that seems
> beyond the scope of my project here.
Actually, the GUI paradigm is the other way around. One does graphics
in a "graphics pane", which is an area /within/ a particular Window. If
one wants to provide graphics in multiple areas of the screen display,
one needs to provide a separate Window instance for each area. The
problem is that most graphics engines need to have a bounded area to
work in because the actual image may be much larger than the actual
display are. In addition, for efficiency the OS Window Manager needs to
separate valid messages for graphics from those of the more pedestrian
GUI displays. One way this is reflected is in the size of the
application; if a graphics pane is used at all the GUI code size will be
much larger because of additional infrastructure, etc.
[Note, BTW, that most GUI infrastructures usually implement controls,
icons, and whatnot as individual window objects. They just have
specific characteristics for modality, borders, position relative to a
"parent" window, and whatnot. Thus the notion of 'control' is really a
GUI design abstraction rather than an OS Window Manager construct.
These are not graphics panes, though, because the user doesn't modify
them "on the fly".]
>>>Are there any examples of a good data-passing UI subsystem
>>>interface freely available?
>>
>>Your OS Window Manager is the most obvious example. Your
>>subsystem interface is equivalent to the typical message loop in a
>>Windows program. It accepts a message from the OS Window Manager
>>and dispatches it to the appropriate receiver based on message ID.
>>There would be an equivalent subsystem interface one the
>>application side to accept messages from the application. And the
>>application would have its own interface to accept messages from
>>the UI subsystem.
>
>
> Yes, that is very true! I am so used to using libraries to hide that
> sort of thing that I had forgotten for a moment how simple and
> decoupled such a windowing system really is.
>
> I would never have considered looking to something so low-level for
> design ideas for my abstract UI subsystem interface. I am still
> hoping that it won't be necessary to send a separate message for
> every little drawing operation.
It shouldn't. Assuming you are doing real graphics, the level of
abstraction of the GUI subsystem interface is dictated by the problem
solution. So if the problem solution wants a rectangle in a particular
place, it asks for that. To do so it needs to specify major and minor
side lengths, a "master" corner position, and a rotation around that
corner. Those are all things the solution would natural need to know if
it is thinking about rectangles in <2D> space. But it doesn't have to
think about rendering of individual line segments at all.
[A simple rectangle is probably a bad example if the drawing
infrastructure you use for graphics is reasonably sophisticated because
there would probably be a resident Rectangle library object that would
hide all the line segment rendering anyway. So a better example might
be something like a Wall that the problem solution sees as h x w x t
between point A and point B. The rendering in the graphics subsystem
would then handle things like shading and the three strands of barbed
wire on top.]
Truth in advertising. As a general rule pure message-based interfaces
like events usually have somewhat finer granularity than other
interfaces. That's because the inherently asynchronous,
state-independent communications that they provide tend to require
somewhat more "handshaking" to synchronize things. However, it is
usually a pretty modest penalty for the decoupling provided.
Another hidden cost is explicit encode/decode. Each side needs to
encode or decode the message for every communication. That's tedious
and would not be necessary is one simply, say, passed an Account object
reference with all the data. But it isn't complicated and the
decoupling is usually worth a lot more than the effort.
--
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.
H. S. Lahman
hsl{}pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info{}pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
-
Re: UI subsystem interface design
Out of interest, dont obfusticate the problem.
Window managers are really really simple things to write and are not
generally OO, so any procedural langyage will do.
The reason they are not usually OO because they are just normally a
bunch of static functions hanging round a simple event manager.
-
Re: UI subsystem interface design
AndyW wrote:
> Out of interest, dont obfusticate the problem.
>
> Window managers are really really simple things to write and are not
> generally OO, so any procedural langyage will do.
>
> The reason they are not usually OO because they are just normally a
> bunch of static functions hanging round a simple event manager.
I don't quite get this statement. Are you strictly speaking of Window Managers
or including Toolkits? Win32, Motif and BOOPSI* (anyone remember that?
are
based on object-oriented principles, even if there are only coded in C.
*http://en.wikipedia.org/wiki/BOOPSI
Mike
-
Re: UI subsystem interface design
On Sun, 12 Nov 2006 23:45:56 GMT, Mike Austin <noone{}nowhere.com>
wrote:
>AndyW wrote:
>> Out of interest, dont obfusticate the problem.
>>
>> Window managers are really really simple things to write and are not
>> generally OO, so any procedural langyage will do.
>>
>> The reason they are not usually OO because they are just normally a
>> bunch of static functions hanging round a simple event manager.
>
>I don't quite get this statement. Are you strictly speaking of Window Managers
>or including Toolkits? Win32, Motif and BOOPSI* (anyone remember that?
are
>based on object-oriented principles, even if there are only coded in C.
>
I meant the basic windowing system, sans the attached API (for the
programmers). I think if you do the ****ysis on most GUs, they really
only consist of a couple of elements.
Often you'll find that the desktop of many OSes is nothing more than a
folder element, and a frame-window for an application is again, just a
folder (with a different look and feel).
Ditto if one does the ****ysis on the controls.
Similar Threads
-
By Application Development in forum C
Replies: 6
Last Post: 10-04-2007, 10:59 AM
-
By Application Development in forum Adobe Tools
Replies: 1
Last Post: 02-03-2007, 11:13 AM
-
By Application Development in forum basic.visual
Replies: 6
Last Post: 05-26-2006, 09:33 AM
-
By Application Development in forum Java-Games
Replies: 7
Last Post: 03-24-2006, 04:29 PM
-
By Application Development in forum XML SOAP
Replies: 0
Last Post: 11-04-2003, 08:06 PM