Forum: Ruby Need help designing UI

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A2f17f7fe3a60a8eff6cb9ba879afe5a?d=identicon&s=25 Scott l Holmes (slholmes)
on 2006-05-17 18:09
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
4b174722d1b1a4bbd9672e1ab50c30a9?d=identicon&s=25 Ryan Leavengood (Guest)
on 2006-05-17 18:31
(Received via mailing list)
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
288733e11db1c6dbbf50871d2c6738c6?d=identicon&s=25 Uncutstone Wu (uncutstone)
on 2006-05-17 19:25
Ryan Leavengood 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 .
A2f17f7fe3a60a8eff6cb9ba879afe5a?d=identicon&s=25 Scott l Holmes (slholmes)
on 2006-05-17 19:26
Ryan Leavengood 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.
A2f17f7fe3a60a8eff6cb9ba879afe5a?d=identicon&s=25 Scott l Holmes (slholmes)
on 2006-05-17 19:29
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!
4b174722d1b1a4bbd9672e1ab50c30a9?d=identicon&s=25 Ryan Leavengood (Guest)
on 2006-05-17 20:29
(Received via mailing list)
On 5/17/06, Scott L Holmes <scottlholmes@gmail.com> 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
E20e89d58211a3631842daecc1245de2?d=identicon&s=25 Ilmari Heikkinen (Guest)
on 2006-05-18 06:17
(Received via mailing list)
Hi,

On 5/17/06, Scott L Holmes <scottlholmes@gmail.com> 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
A80d5b82cffdb82f75a7ee1f997ec3a1?d=identicon&s=25 Xavier (Guest)
on 2006-05-18 08:01
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
This topic is locked and can not be replied to.