Need help designing UI

Hi,

I’m working on a user interface and I’m hoping I can get some
feedback/advice. I have 3 main classes: Viewer, Toolbar and
ToolbarButton. Given that an instance of Viewer has an instance of
Toolbar and that Toolbar has a collection of ToolbarButtons, I’m trying
to decide how I want to implement the workflow for the “Close” process.
The creation of all these instances is all rather “pretty” at the moment
but no instances really “knows” or cares about the other. (parts is
parts!)

So, consider when the user clicks a “close window” ToolbarButton.
Somehow the Viewer must be informed that its time to close the window.

For some reason, I’m trying to avoid keeping a reference to the Viewer
in the button (like with a call back). I’m hoping for a somewhat more
interesting design. I’ve tried a variety of things over the years but
I’m curious what others have tried, got working and generally like.

Any comments would be greatly appreciated.

Scott

Over the years I’m sure there has been invented countless ways of
doing what you are asking, but I am personally most experienced with
the GUI system on BeOS, which I think is a very nice design.

Essentially all communication between various parts of the system
(from the OS to applications and back, from applications to their
windows and back, from windows to the GUI components and back) is done
via messages. A looper class is used to loop over messages coming in
and then the handling of these messages are delegated to a handler
class. On BeOS frequently the looper and handler are the same class.

Messages are handled first by their direct recipient (for example a
mouse down would be handled first by the component being clicked on.)
If the message cannot be handled by that recipient, it is passed up
the inheritance hierarchy until it is handled. Usually messages that
are used within an application itself are targeted directly to the
window, and then the window can delegate to the appropriate component.

So for you example, the “Close Window” toolbar button would have a
message with an associated CLOSE command constant, with the target of
the message being the window. When the button is clicked, the CLOSE
message will be sent to the window and the handling of that message
will close the window (of course.) The nice thing about this is that
the CLOSE message could be used from other places without having to
change how it is handled within the window.

Ryan

Ryan L. wrote:

Essentially all communication between various parts of the system
(from the OS to applications and back, from applications to their
windows and back, from windows to the GUI components and back) is done
via messages. A looper class is used to loop over messages coming in
and then the handling of these messages are delegated to a handler
class. On BeOS frequently the looper and handler are the same class.

Messages are handled first by their direct recipient (for example a
mouse down would be handled first by the component being clicked on.)
If the message cannot be handled by that recipient, it is passed up
the inheritance hierarchy until it is handled. Usually messages that
are used within an application itself are targeted directly to the
window, and then the window can delegate to the appropriate component.

So for you example, the “Close Window” toolbar button would have a
message with an associated CLOSE command constant, with the target of
the message being the window. When the button is clicked, the CLOSE
message will be sent to the window and the handling of that message
will close the window (of course.) The nice thing about this is that
the CLOSE message could be used from other places without having to
change how it is handled within the window.

Ryan

I think there are two essential design patterns here, one is message
dispatcher, and the other is chain of responsibility .

Ryan L. wrote:

So for you example, the “Close Window” toolbar button would have a
message with an associated CLOSE command constant, with the target of
the message being the window. When the button is clicked, the CLOSE
message will be sent to the window and the handling of that message
will close the window (of course.) The nice thing about this is that
the CLOSE message could be used from other places without having to
change how it is handled within the window.

Thanks for replying Ryan. This got me thinking about some design goals.
Your description sounds like MS Windows, in any case, it implies some
sort of Windowing management. What I’m building is pretty high level and
the overall impetous of the project is not the UI - more of a library
kind of thing. The UI is sweetness? So to keep things simple, I’m
thinking I need to concentrate on two things.

A command constant. Definitely warming to this idea. The constant as in
your description is merely a token to pass around.

Some form of context. A toolbarbutton is on a toolbar is on a viewer. In
a generic way, when the viewer gets created, it would register a context
which could be a simple random number. All sub-parts get the context?
When the toolbarbutton fires it broadcasts a command constant and the
context? Thinking out loud. Does avoid the references but now I gotta
pass around a random number. In Ruby - that’s a reference too. hmmmmm.

uncutstone wu wrote:

I think there are two essential design patterns here, one is message
dispatcher, and the other is chain of responsibility .

Thanks, will google that!

On 5/17/06, Scott L Holmes [email protected] wrote:

Some form of context. A toolbarbutton is on a toolbar is on a viewer. In
a generic way, when the viewer gets created, it would register a context
which could be a simple random number. All sub-parts get the context?
When the toolbarbutton fires it broadcasts a command constant and the
context? Thinking out loud. Does avoid the references but now I gotta
pass around a random number. In Ruby - that’s a reference too. hmmmmm.

For the command constant you should use Ruby symbols:

:this_is_a_symbol
:another_one

In other words anything starting with a colon. These are unique per
invocation of Ruby, and :this will always equals :this through-out the
program. So in your case using something like :cmd_close or :CMD_CLOSE
would be the best choice.

Ryan

Scott L Holmes wrote:

Hi,

I’m working on a user interface and I’m hoping I can get some
feedback/advice. I have 3 main classes: Viewer, Toolbar and
ToolbarButton. Given that an instance of Viewer has an instance of
Toolbar and that Toolbar has a collection of ToolbarButtons, I’m trying
to decide how I want to implement the workflow for the “Close” process.
The creation of all these instances is all rather “pretty” at the moment
but no instances really “knows” or cares about the other. (parts is
parts!)

So, consider when the user clicks a “close window” ToolbarButton.
Somehow the Viewer must be informed that its time to close the window.

For some reason, I’m trying to avoid keeping a reference to the Viewer
in the button (like with a call back). I’m hoping for a somewhat more
interesting design. I’ve tried a variety of things over the years but
I’m curious what others have tried, got working and generally like.

Any comments would be greatly appreciated.

Scott

Investigate a listener/dispatcher pattern, as used by the Java Swing
Framework.
Basically, have a control class (MainProgram) register itself as a
‘click listener’ on the close button (this is done with interfaces in
Java - obviously not necessary for ruby code). That way, the control
flow of the program is abstracted outside of your specific UI
components.

If every toolbar has a close button, then it may be better to have the
toolbar register itself as a click listener on the close button, and
then reposting this as a close event.

  • Xavier

Hi,

On 5/17/06, Scott L Holmes [email protected] wrote:

So, consider when the user clicks a “close window” ToolbarButton.
Somehow the Viewer must be informed that its time to close the window.

For some reason, I’m trying to avoid keeping a reference to the Viewer
in the button (like with a call back). I’m hoping for a somewhat more
interesting design. I’ve tried a variety of things over the years but
I’m curious what others have tried, got working and generally like.

Any comments would be greatly appreciated.

In a DOM-like system: on clicking the button, it would bubble up a
CloseWindow-event, which the Viewer would then catch and close the
window.

Pseudo-code:

class Object
def send_up(*args)
process_up_event(*args)
@parent.send_up(*args) if @parent
end
end

close_button.on_click{ close_button.send_up(:close_window) }
viewer.on_close_window{ exit }

viewer << toolbar
toolbar << close_button

Ilmari