GUI's and the Rouge, Part II

in part one of this message i mention the problem of non-POLS and
ugliness when it came to hand coding a GUI interface. follow this link.
it is example code of the Rouge’s utopia:

http://www.rubyide.org/cgi-bin/wiki.pl?RougeArchitecture/Alpha

i can honestly say this code is probably better than any i have ever
seen, but i’m sorry, it’s still just dosen’t look like my idea of gui
utopia. it is still a traditional approach, albiet very innovative in
its use of ruby’s OO and iterators, it nonetheless follows the same
overall design characteristics of other tools: defining each and every
widget, designating content and style, their coorelation, and binding
procedures before passing off execution control (app.controller.start)
to the gui engine. but, i hear you thinking, “what other way is there?
that’s just how it’s done!” well, i emphisized content above because its
the key to a better approach. we can get a taste of this by looking
amrita:

http://kari.to/amrita/sources/docs/QuickStart

the beauty of amrita lies in the fact that the data which is to appear
in the end result contributes to its design. thus, in part, the layout
does not have to be specified because the data itself designates it. the
end result is cleaner leaner code. in effect amrita has done what OO
design is intended to do, it has given precedence to the data model.

although amrita is a unidirection html/xhtml templating system, her
principles just as easily carry over to guis. arbitrarily, as
programmers, we can think of it like this: instead of widget.displays(x)
we get x.widgetized. let me provide a mock code fragment to help
clearify. we’ll call our imaginary gui toolkit, RougeDuex.

require ‘rougeduex’

class MyClass
attr_accessor avar
def initialize
@avar = ""
end
end

myobj = MyClass.new
myobj.avar.extend RougeDeux::WidgetFactory(:Label)

mywin = RougeDuex::WidgetFactory(:Window).show
mywin.embody {
pack myobj.avar, RougeDuex::TOP
}

myobj.avar = “Hello, World!”

and just like that we have a window with a label in it greeting us.

you might notice something a bit odd about this very simple example: the
window was displayed prior to the label being added. this is a key
point. by retaining execution, such that the gui is a spawned processes,
we retain the ability to modify it “on-the-fly”. just think of all the
neat tricks we can do with that! no longer are we limited to just the
event model of the gui’s engine. morever, notice that the class
definition is completly clean. there’s no mention of RougeDuex anywhere
in it, nonetheless it is direclty linked to our gui. should avar change
for any reason, so will our label. and if avar were a text entry field
or any other input widget, instead of a label, avar would automagically
reflect that input.

you may wonder how other aspects of avar as a label get designated. well
since avar was extended to be a label it gained a few things that allow
us to do that: myobj.avar.style={:color=>‘red’}, for example. no
problem!

also one might be concerned about performance with such dynamic
rendering, since anytime one changes a variable the gui requires
refreshing. well, a transaction model can help with that were it is
essential.

so there’s the ideal, my friends. i am sure certain elements of the
current Rouge project could be carried over into this, and i think the
end result would be the easiest, most intuitive and fun (like ruby!) gui
to ever have the priviledge of being coded by you :wink:

in the last part of my series (don’t ask me what posessed me to do this,
i don’t know!) i’ll go into the possabilities of implementation.

~transami

(") v man
\v/
^ ^

The main problem with this is that the data shouldn’t have to know
about how it’s going to be presented.

When you want to display something on (say) a PDA, you might choose to
have different representations (shorter strings, no colors, etc.).

Maybe the best strategy would be to have an intervening policy object
between the data and the widgets that determines how a given piece of
data would be presented in a particular kind of UI.

···

On Saturday 20 July 2002 10:00 am, Tom Sawyer wrote:

we can think of it like this: instead of widget.displays(x)
we get x.widgetized.


Ned Konz
http://bike-nomad.com
GPG key ID: BEEA7EFE

I’m sorry, Tom, but I don’t see a really new direction in your comments. It
appears that you have simply repackaged/renamed the current solutions to
writing a GUI program. Perhaps I am just slow-witted or perhaps my opinion
is premature and I should wait on more details. Let me specify the sources
of my confusion:

  1. GUI design is more of an art form than a technology. I don’t believe that
    good design of a user interface can be automated.
  2. How is replacing a GUI specification with a template an improvement? The
    same design decisions that go into a GUI specification will have to go into
    template design.
  3. It seems that you are unhappy with the concept of a mainloop and
    callbacks. Yet, the whole purpose of a GUI is not to just display data but
    to monitor the user’s actions and carry out his intent. The user’s
    keyboard/mouse actions are an event that triggers a cascade of internal
    events. How would you handle this?

What am I missing?

Apologize in advance…this is a LONG response…

From: Tom Sawyer [mailto:transami@transami.net]
Sent: Saturday, July 20, 2002 1:01 PM
To: ruby-talk ML
Subject: GUI’s and the Rouge, Part II

in part one of this message i mention the problem of non-POLS and
ugliness when it came to hand coding a GUI interface. follow this
link.
it is example code of the Rouge’s utopia:

http://www.rubyide.org/cgi-bin/wiki.pl?RougeArchitecture/Alpha

Well I have not looked at this in a bit. I wrote this in an evening as
more of a proof of concept than anything else. Sean Russell had ideas
that appear to follow yours more closely than mine. BTW: I have
uploaded the source that enabled this to:
http://www.infoether.com/ruby/utopia.zip

It does not show it in the example, but the attributes and available
widget definitions are completely extensible in the model (see
utopia.rb). Again, it was more of an experiment than a "real solution"
to the problem of GUI abstraction.

i can honestly say this code is probably better than any i have ever
seen, but i’m sorry, it’s still just dosen’t look like my idea of gui
utopia. it is still a traditional approach, albiet very innovative in
its use of ruby’s OO and iterators, it nonetheless follows the same
overall design characteristics of other tools: defining each and every
widget, designating content and style, their coorelation, and
binding
procedures before passing off execution control (app.controller.start)

First, execution control is not necessarily passed off by starting the
controller. It does not have to be, but since Ruby’s threading is
non-native, most UI toolkits kind of take over. This could be addressed
(without adding native threads to Ruby)…such as having another process
that presents and controls the UI and communicates to the Ruby process
via a socket…like X.

Second, I have no problem with binding an object-attribute in as a
binding to a widget. Like:

class MyClass
attr_accessor :avar
def initialize
@avar = ""
end
end
myobj = MyClass.new

myLabel(:label).text(bind_object(myobj, :avar))

and when the method bind_object is called it aliases the original avar=
method with one that updates the Label’s ‘text’ attribute (and vice
versa).

Or to more align with your example below:

myobj.extend Utopia::WidgetBinder
myobj.bind_widget(mainWindow.myLabel, :avar)

to the gui engine. but, i hear you thinking, “what other way is there?
that’s just how it’s done!” well, i emphisized content above because
its
the key to a better approach. we can get a taste of this by looking
amrita:

http://kari.to/amrita/sources/docs/QuickStart

the beauty of amrita lies in the fact that the data which is to appear
in the end result contributes to its design. thus, in part, the layout
does not have to be specified because the data itself designates it.
the
end result is cleaner leaner code. in effect amrita has done what OO
design is intended to do, it has given precedence to the data model.

Well, in amrita, the hierarchy of the data has to match the hierarchy of
the (HTML) UI. As can be shown in this example from the QuickStart doc
above:

name author

data = {
:table1=>[
{ :name=>“Ruby”, :author=>“matz” },
{ :name=>“perl”, :author=>“Larry Wall” },
{ :name=>“python”, :author=>“Guido van Rossum” },
]
}

You see, the minimum you need is a hierarchy in your design of the UI
because UIs are built using a “container/component” model. My example
from utopia presented a simple hierarchy, but one that needs to be
specified somewhere. That I fully specified all of the attributes of
the elements in the UI…up front…does not mean it needs to be so.
You could do:

require ‘utopia’

app = Utopia.new_application(“My Application”)

mainWindow = app.modeller.build(:window).body {
icon(:icon)
menu(:menubar).items {
file(:menu)
help(:menu)
}
fruit_panel(:panel).body {
firstName(:textfield)
lastName(:textfield)
favoriteFruit(:textarea)
submit(:button)
clear(:button)
}
}

Then do:

mainWindow.fruit_panel.body.firstName.text.bind_object(obj, :foo);

although amrita is a unidirection html/xhtml templating system, her
principles just as easily carry over to guis. arbitrarily, as
programmers, we can think of it like this: instead of
widget.displays(x)
we get x.widgetized. let me provide a mock code fragment to help
clearify. we’ll call our imaginary gui toolkit, RougeDuex.

require ‘rougeduex’

class MyClass
attr_accessor avar
def initialize
@avar = ""
end
end

myobj = MyClass.new
myobj.avar.extend RougeDeux::WidgetFactory(:Label)

mywin = RougeDuex::WidgetFactory(:Window).show
mywin.embody {
pack myobj.avar, RougeDuex::TOP
}

myobj.avar = “Hello, World!”

and just like that we have a window with a label in it greeting us.

OK, now give me syntax for the example I presented on the the rubyide
site. Your idea of mixing the widget capability into the object is
cool, but how the widgets get organized on the screen needs to be
defined somewhere.

you might notice something a bit odd about this very simple example:
the
window was displayed prior to the label being added. this is a key
point. by retaining execution, such that the gui is a spawned
processes,
we retain the ability to modify it “on-the-fly”. just think of all the
neat tricks we can do with that! no longer are we limited to just the
event model of the gui’s engine. morever, notice that the class

Again, I absolutely agree with you, and I don’t think we should be
limited to the event model of the GUI (OS’es aren’t).

definition is completly clean. there’s no mention of RougeDuex
anywhere
in it, nonetheless it is direclty linked to our gui. should avar
change
for any reason, so will our label. and if avar were a text entry field
or any other input widget, instead of a label, avar would
automagically
reflect that input.

Again, having the UI widgets bind to non-UI objects is cool, as I showed
above.

you may wonder how other aspects of avar as a label get designated.
well
since avar was extended to be a label it gained a few things that
allow
us to do that: myobj.avar.style={:color=>‘red’}, for example. no
problem!

also one might be concerned about performance with such dynamic
rendering, since anytime one changes a variable the gui requires
refreshing. well, a transaction model can help with that were it is
essential.

so there’s the ideal, my friends. i am sure certain elements of the
current Rouge project could be carried over into this, and i think the
end result would be the easiest, most intuitive and fun (like ruby!)
gui
to ever have the priviledge of being coded by you :wink:

I am not hung up on anything done so far (it was a quick hack), but we
need to see semi-realistic examples with windows, menus, events, etc.

in the last part of my series (don’t ask me what posessed me to do
this,
i don’t know!) i’ll go into the possabilities of implementation.

I will look forward to it.

···

-----Original Message-----

~transami

(") v man
\v/
^ ^

point. by retaining execution, such that the gui is a spawned processes,
we retain the ability to modify it “on-the-fly”. just think of all the
neat tricks we can do with that! no longer are we limited to just the
event model of the gui’s engine.

I’ve done something like that in the past from irb with:

Thread.new { Gtk.main }

you may wonder how other aspects of avar as a label get designated. well
since avar was extended to be a label it gained a few things that allow
us to do that: myobj.avar.style={:color=>‘red’},

That last one defies your purpose because it mixes model and
presentation (a lot).

Have you thought about automatic code generation? Rather than
having GUI code mixed in the model (implicitly or explicitly), what
about, given a model class, automatically generating a class that
in turn automatically generates the appropriate GUI? Something like…

class MyModel
def initialize
@avar = “”
@another = 0
end

def avar
@avar
end

def avar=(value)
@avar=value
end

def another
@another
end

def another=(value)
@another=value
end
end

setter_getter_pairs = [
[:avar, :avar=],
[:another, :another]
]

MyGui = GuiFactory.new(MyModel, setter_getter_pairs)

my_instance = MyModel.new

my_instance_gui = MyGui.new(my_instance, parent_widget)

Also consider chances like…

my_instance_gui = MyGui.new(my_instance, parent_widget, stylesheet)

I’ve defined avar= and another= explicitly. Remember that when you are
calling myobj.var=something, for GUI purposes you probably don’t want to
catch the assignment of whatever variable(s) get assigned within the var=()
method of myobj, but rather the symmetrical value returned by the var()
method (think of a class that stores the time in milliseconds
internally but gets it from and tells it to the rest of the world in
form of a string “Sunday 4, Mar…”).

My .$02.

Massimiliano

···

On Sun, Jul 21, 2002 at 02:00:47AM +0900, Tom Sawyer wrote:

Tom Sawyer wrote:

[snipped lots and lots of interesting stuff]

Tom, the RougeProject came from a convergence of two things: Sean Russell’s
personal desire for a more elegant way do GUIs in Ruby, and the FreeRIDE
project’s frustration of not being able to find a GUI toolkit that fully met
all of our requirements. What you see for the RougeProject on the FreeRIDE
wiki (http://www.rubyide.org/cgi-bin/wiki.pl?RougeProject) is result of a
month long ML discussion back in Feb/Mar amongst about a dozen Ruby
developers.

Most of us who participated in the discussion did so because we were all
intensely interested having a GUI toolkit had both the same sort of elegance
and ease-of-use that REXML brought to XML processing and did not have any
of the annoying deficiencies found in the currently available GUI toolkits.
This was a very tall order, both in terms of design and in the amount of
effort that would be required to implement it. But definitely worthwhile, if
it could be achieved.

More than half of the participants in these discussions were FreeRIDE
developers. We wanted to use such a GUI toolkit within FreeRIDE and had a
very personal interest in contributing ideas and helping to shape the
result. But FreeRIDE is, itself, a very large effort and we could not afford
to divert any development effort off of our own project.

So, as Rich Kilmer pointed out, the implementation effort has appeared to
have stalled (Sean, if I’m wrong about that, please correct me), not from
lack of interest, but for the lack of a strong and passionate leader who has
the available time to champion this project and rally other developers to
join in.

I’m hoping that your knowledge, energy, and enthusiasm can translate into a
sustainable project from which all of us in the Ruby community can benefit
(including FreeRIDE).

To that end, I would like to invite you to create one or more pages on the
FreeRIDE wiki to capture the results of your recent discussions and
thoughts. And if you are interested in pushing forward with this, I would
even be willing to set up and host a separate wiki just for this project.

Curt

thanks Ned,
a good point. but thanks to ruby we can deal with this farily easily w/o
having to resort to intervening objects by seperating parts of a class
definition. just as one extends a class now one can create conditional
extenstions dependent, say, on the platform. for exmaple:

pda.rb:
class MyClass
def initialize
super
avar.extend RougeDeux::WidgetFactory(:Label)
avar.style={:width=>10}
end
end

pc.rb:
class MyClass
def initialize
super
avar.extend RougeDeux::WidgetFactory(:Label)
avar.style={:width=>100}
end
end

myapp.rb:
class MyClass
attr_accessor avar
def initialize
@avar = ""
end
end
require pda.rb if $interface='PDA’
require pc.rb if $interface=‘PC’

so this is one approach. in a sense it is like an intervening object,
only it’s an intervening definition. (note: this does “confuscate” the
object, but it does it in a clean, well seperated manner) i’m sure there
are others ways. one thing i hadn’t taken into account, that your post
made me consider is the idea of stylesheets --convenient ways to set the
properties of a large number of widgets at once. but i’m sure that would
not be too difficult to factor in.

~transami

···

On Sat, 2002-07-20 at 12:25, Ned Konz wrote:

The main problem with this is that the data shouldn’t have to know
about how it’s going to be presented.

When you want to display something on (say) a PDA, you might choose to
have different representations (shorter strings, no colors, etc.).

Maybe the best strategy would be to have an intervening policy object
between the data and the widgets that determines how a given piece of
data would be presented in a particular kind of UI.


~transami

(") dobee dobee do…
\v/
^ ^

  1. GUI design is more of an art form than a technology. I don’t believe that
    good design of a user interface can be automated.

quite right! it can’t be. but we certainly can make the tools for its
PRODUCTION easier.

  1. How is replacing a GUI specification with a template an improvement? The
    same design decisions that go into a GUI specification will have to go into
    template design.

why do people use template systems at all? but actually i’m not saying a
template is neccessary. in fact my code example had no mention of a
template. so i’m not replacing a GUi spec with a template. yet i think
template systems are very powerful tools and Rouge or whatever should
have one.

  1. It seems that you are unhappy with the concept of a mainloop and
    callbacks. Yet, the whole purpose of a GUI is not to just display data but
    to monitor the user’s actions and carry out his intent. The user’s
    keyboard/mouse actions are an event that triggers a cascade of internal
    events. How would you handle this?

this would work much like the gui’s we use today. the gui engine still
processes events, and we still provide a means for action when those
events are triggered. i am only proposing the additional ability to
continue execution of the “main line” in parrallel to this. there’s
nothing wrong with triggers/events, but i believe it is limiting to be
wholly dependent on those and thus having to internalize ones code into
the gui constructs via procs. in effect, and i don’t think i have fully
explored this, i am trying to successfully turn the gui to app
interfacing inside-out.

~transami

···

On Sat, 2002-07-20 at 12:49, Albert Wagner wrote:


~transami

(") dobee dobee do…
\v/
^ ^

Apologize in advance…this is a LONG response…

no no that’s great!

Well I have not looked at this in a bit. I wrote this in an evening as
more of a proof of concept than anything else. Sean Russell had ideas
that appear to follow yours more closely than mine. BTW: I have
uploaded the source that enabled this to:
http://www.infoether.com/ruby/utopia.zip

great, i’ll check it out.

First, execution control is not necessarily passed off by starting the
controller. It does not have to be, but since Ruby’s threading is
non-native, most UI toolkits kind of take over. This could be addressed
(without adding native threads to Ruby)…such as having another process
that presents and controls the UI and communicates to the Ruby process
via a socket…like X.

that occured to me too. are there other means to this, or is socket
communication the only way. probably the best way anyway, though.

Second, I have no problem with binding an object-attribute in as a
binding to a widget. Like:

class MyClass
attr_accessor :avar
def initialize
@avar = ""
end
end
myobj = MyClass.new

myLabel(:label).text(bind_object(myobj, :avar))

and when the method bind_object is called it aliases the original avar=
method with one that updates the Label’s ‘text’ attribute (and vice
versa).

that’s great. i didn’t see this in utopia. i was able to manage the same
thing with my miterbox (my rouge like project). but that’s a one way
street. the difficulty here is going back the other way: when the bound
variable changes the gui gets automagically updated. i found this to be,
as of yet, an insurmountable problem.

Or to more align with your example below:

myobj.extend Utopia::WidgetBinder
myobj.bind_widget(mainWindow.myLabel, :avar)

this notation really works? cool!

Well, in amrita, the hierarchy of the data has to match the hierarchy of
the (HTML) UI.

OK, now give me syntax for the example I presented on the the rubyide
site. Your idea of mixing the widget capability into the object is
cool, but how the widgets get organized on the screen needs to be
defined somewhere.

I am not hung up on anything done so far (it was a quick hack), but we
need to see semi-realistic examples with windows, menus, events, etc.

i apologize, my example was not a good one for as showing off the amrita
concepts as applied to guis. i will work on doing so and post it.

also keep in mind, i don’t have all this fully flushed out. i have just
been spending a lot of time on the gui abstraction problem, because i
have a big bad old gui forntend to write. given its breadth i have been
trying to create an abstraction to facilitate this and make my life
easier in the long run. hence the source of these concepts. hopefully i
can work it out rather then having to hand code all of it.

in that light, just how far a long is utopia? is there any development
activty going on with it or related to the Rouge project? what’s the
status there?

thanks for the in depth reponse!

~transami

(") dobee dobee do…
\v/
^ ^

···

On Sat, 2002-07-20 at 13:26, Rich Kilmer wrote:

and a damn good $.02 it is!

i need your help with one thing though. could you give me a simple
example of generating a class?

thanks!

~transami

···

On Sat, 2002-07-20 at 13:30, Massimiliano Mirra wrote:

Have you thought about automatic code generation? Rather than
having GUI code mixed in the model (implicitly or explicitly), what
about, given a model class, automatically generating a class that
in turn automatically generates the appropriate GUI? Something like…

My .$02.

hey Ned! your concept of an intervening “object” turned out to be right
on! i didn’t realize it at first, but massimiliano was saying essentialy
the same thing. i worked through it all and you two were on the money.
thanks!

hope you like it…

~transami

(") v: i am not an alien
\v/
^ ^

···

On Sat, 2002-07-20 at 12:25, Ned Konz wrote:

Maybe the best strategy would be to have an intervening policy object
between the data and the widgets that determines how a given piece of
data would be presented in a particular kind of UI.

Ned Konz ned@bike-nomad.com wrote in message news:200207201125.13528@ned.bike-nomad.com

we can think of it like this: instead of widget.displays(x)
we get x.widgetized.

This ties into a discussion I was having about coding and testing html
– that it’s better to use widgets to make html easier to test, not to
prevent you from having to write html. i.e., instead of writing:

Form:Text.new( “name”, “default name”, :size => 30; :maxlength => 40 )
Form:Pass.new( “password”, “”, :size => 30; :maxlength => 40 )

to replace

Name:
Pass:

You have:

Login.form # => outputs the above html

which we thought of as an application specific widget containing the
two form elements. The goal here would be to break the presentation
into “widgetize” methods that make it easier to test the html.

However, this isn’t something that would the basis for a library.
These widgets need to be as general as possible to be useful, instead
of GUI widgets which are made to be as flexible as possible. I guess
the goal is to code for reuse within your application, not for reuse
outside of your application.

The main problem with this is that the data shouldn’t have to know
about how it’s going to be presented.

When you want to display something on (say) a PDA, you might choose to
have different representations (shorter strings, no colors, etc.).

I think it’s rare that you would want the same application on a PDA
and a desktop. The limitations of a PDA go beyond the size and color
depth of the framebuffer; there are also major input considerations.
In a MVC architecture I don’t see much benefit to sharing the the view
or controller code between dramatically different platforms (unless
the problem is dramatically simple, such as a calculater).

~ Patrick

···

On Saturday 20 July 2002 10:00 am, Tom Sawyer wrote:

From: Tom Sawyer [mailto:transami@transami.net]
Sent: Saturday, July 20, 2002 4:01 PM
To: ruby-talk ML
Subject: RE: GUI’s and the Rouge, Part II

Apologize in advance…this is a LONG response…

no no that’s great!

Well I have not looked at this in a bit. I wrote this in an evening
as

more of a proof of concept than anything else. Sean Russell had
ideas

that appear to follow yours more closely than mine. BTW: I have
uploaded the source that enabled this to:
http://www.infoether.com/ruby/utopia.zip

great, i’ll check it out.

First, execution control is not necessarily passed off by starting
the

controller. It does not have to be, but since Ruby’s threading is
non-native, most UI toolkits kind of take over. This could be
addressed

(without adding native threads to Ruby)…such as having another
process

that presents and controls the UI and communicates to the Ruby
process

via a socket…like X.

that occured to me too. are there other means to this, or is socket
communication the only way. probably the best way anyway, though.

Well, we could abstract the communications :wink: sockets would allow it
to be remoted…which would rock.

BTW, the "change the object’s attribute and you change the widget"
problem can be solved by aliasing the setter method on the attribute
with one that updates the UI and then calls the original method.

i apologize, my example was not a good one for as showing off the
amrita
concepts as applied to guis. i will work on doing so and post it.

also keep in mind, i don’t have all this fully flushed out. i have
just
been spending a lot of time on the gui abstraction problem, because i
have a big bad old gui forntend to write. given its breadth i have
been
trying to create an abstraction to facilitate this and make my life
easier in the long run. hence the source of these concepts. hopefully
i
can work it out rather then having to hand code all of it.

in that light, just how far a long is utopia? is there any development
activty going on with it or related to the Rouge project? what’s the
status there?

Utopia is what you got. It’s an exploration into the GUI abstraction
problem. Rouge stalled some months ago. Sean Russell has been focusing
on REXML and I don’t if he has advanced Rouge any. I am interested in
this, but I stopped working on it to focus on some other things
(jabber4r, FreeBASE/FreeRIDE, JXTA/RXTA, My own company, etc).

On an aside, you may actually want to look at FreeRIDE (the Ruby IDE) We
are abstracting GUI components to allow multiple ‘renderers’. It’s at
that site you were on (www.rubyide.org). It’s currently using RXRuby
and VERY alpha-stage, but may give you some ideas.

-rich

···

-----Original Message-----
On Sat, 2002-07-20 at 13:26, Rich Kilmer wrote:

I see from your posts about module_eval and define_method that you’ve
already discovered more than I could have told you. :slight_smile:

Massimiliano

···

On Sun, Jul 21, 2002 at 05:53:48PM +0900, Tom Sawyer wrote:

i need your help with one thing though. could you give me a simple
example of generating a class?

a bit of an intro: my original thought on the matter of making a
rubyesque gui api was to use the power of mixins to make objects
automagically linked to a gui form. while that still has some appeal,
massimillano mirra and ned konz pointed that this really meshes the gui
to tightly with the objects them self, resulting in poor SOC (seperation
on concerns) and limited code reuse. i thought about the matter in depth
and decided that they were right. there would be great advantage, if
done well, form creating an intermidiary beteen application objects and
the gui they are to interact with. so i set my sites on that goal and
reworked my ideas --the result looks quite promising. thank you
massimillano and ned.

but before i get into the nitty-gritty of ruby code. lets back up a
attack some over all architecture issues.

it was stated that a main goal of Rouge was to create a cross-compatible
gui api that “boiled down” into the native gui of each platform. in my
first post on these matters, i pointed out how ungodly difficult that
would be (as i had been trying to do that myself). in the end either you
left to “patch” your app for each platform or you simply have to give up
the features that they hold in common (at best). it really is simply too
much of pain to create such an system, not to mention maintaining it as
those underlying native api change. yet the goaol os a native look and
feel is not unachievable by other means. the solution is simply a matter
of using an underlying gui engine that is sufficiantly themeable. since
all the major gui’s are now themable themselves, we simply need to code
a theme manager that can import the themes of those other guis. we need
not use their underlying api, only their look and feel! so that’s what
can be done to solve that dilemma: use a sufficantly themeable gui api
and crreat and Themes and Behaviors Manger to emulate the look and feel
and even draw upon the native theme configuration files. this is a much
managable task then trying to channel down to the native guis
themselves. the only trick of course is finding that themeable gui api.

well, as things often are, it’s a tale of two. my first hope lied in a
gui api called ParaGUI:

http://www.bms-austria.com/projects/paragui/

this is a nice gui api based on SDL which is in turn based on OpenGL. it
is a little immature as of yet, but can be themed. but just to be sure i
looked around a bit more. i filter through a number of others, GLUT and
GLUI come to mind, but then i found something all together better. well,
that’s is at least how it looks. you never actually knwo until you get
into it, but even so we could always fall back to ParaGUI. but what i
found wasn’t labled strictly as a GUI, becasue it ws so much more. it
was a complete game sdk! but had all the standard gui widgets that one
could want but a whole lot more to boot. and yes, it was themeable. a
god send! check it out:

http://www.clanlib.org/documentation/ClanLib-0.7/Reference/html/classes.html

now were cooking. one last issue: execution control. rich kilmer
mentioned the possibility of using sockets: “This could be addressed
(without adding native threads to Ruby)…such as having another process
that presents and controls the UI and communicates to the Ruby process
via a socket…like X.” and i think too that this is a fantastic idea.
so that’s the final piece and we end up with basically this:

±----- ±-------+ ±-------±---------------+

A ~| Ruby | DRb? | Ruby ; Ruby | ClanLib |
Ruby ~| GUI |<------------>| GUI ; Wrap ±--------+
App ~| Client | yaml? | Server ; | Themer |
±----- ±-------+ ±-------±---------------+

now the communications layer can be optional, that’s now big task to
have it be able to work both ways, so were speed made be extra critcal
it could be left out. but that’s the over layout. and i think its a
design that that is well worth the effort to create.

i’m going to take a break now before going into the ruby code: but i
have created the beginnings of what i’m calling GUtopIa. more in a
bit…

~transami

yes, thanks. i managed to hack it out. :slight_smile:

···

On Mon, 2002-07-22 at 05:45, Massimiliano Mirra wrote:

I see from your posts about module_eval and define_method that you’ve
already discovered more than I could have told you. :slight_smile:


~transami

(") dobee dobee do…
\v/
^ ^

well, i just read over my last post. sorry about all the typos. i needed
a break and didn’t bother to proofread. but i’m sure you can make out
what i was trying to say where i blurbed. okay, now to the good stuff!

i spent the last few days hacking out the first steps in the creation of
a super-duper ruby gui api, which i have dubbed GUtopIa (thanks rich).
just to kick things off here’s a small clip of one of my examples (note
MyModels is drawn from an unshown require):

INTERFACE = ‘PDA’
fruitapp = FruitApp.new
mygui = GUtopIa::GUI.new(‘Fruity Fun Time’)
names = {
‘awindow’ => fruitapp.appname,
‘aradio’ => fruitapp.fruitbasket.name
}
bindings = {
fruitapp.fruitbasket.name => {
:value => Proc.new { fruitapp.fruit.isa },
:value= => Proc.new { |x| fruitapp.fruit.isa = x },
:items => Proc.new { fruitapp.fruitbasket.contains },
:event_change => Proc.new { fruitapp.pickafruit }
}
}
model = MyModels.pick_model(mygui, INTERFACE)
mygui.transaction(bindings, names, &model)
mygui.build

the idea is that you take an instance of your application (FruitApp in
this case), completely untouched --you don’t have to add or change a
single line of code (unless you want too :wink: you then create a model. a
model (not shown in example) is an executable description of the fixed
aspects of your gui. it has no references to any part of your app
(although you can do so if you don’t care about SOC) it is a completely
independent entity and as such can be reused in other fitting contexts.
you can also draw on multiple sub-models. then you create a binding (as
seen above). this describes how an instance of your application
“interfaces” with your model. and then presto out comes you gui-ized
app.

also note that GUtopIa uses a transaction mechinism. this effectivly
bundles an executable model into a single execution. not only does this
increase speed, but also offers a means to rollback the effects of a
transaction should there be an error, adding much greater stability to
your gui-ized application.

some other things to note: bindings are actually integrated directly
into the class models of the widgets. when a widget is created it is
subclassed into a specialized class of that widget which includes
methods to react to the bindings described.

i’ve attached my work thus far so you can checkout all of this in
detail. be sure to run example.rb (the snipet above) and check out
orig-example.rb, which is a non-SOC version of the original Rouge/Utopia
example. then check out gutopia.rb which is the heart of the matter.

so that’s the the word on implementation. i’ve taken the advice of
others and i have worked out what i think is shaping up to be the best
gui api design in existence. Curt Hibbs has offered me a wiki for this
project. (thanks curt) i will take him up on it. now i hope i can get
YOU enthused enough to help. there’s real potential here, to not only
create an awsome gui api for ruby that is unique and powerful, but also
create a full-fledge game sdk! this thing looks to be awesome indeed.

i need people to take on a few tasks. a ruby wrapper needs to be created
for ClanLib and we need to build a Themes and Behaviors manager. someone
needs to hack out the communications layer (i’ve tried it with DRb and
ROMP but they bomb). and i could use some help finishing off the main
api. if we can pull together on this, ruby, our favorite little
scripting language, will have its very own GUI to rival all others!

as you might be able to tell, i’m very excited! i hope you are too!

thanks for your time and hope to hear from you,

~transami :slight_smile:

example-app.rb (587 Bytes)

example-drb.rb (2.15 KB)

example-pre.rb (953 Bytes)

example-romp.rb (2.18 KB)

example.rb (2.13 KB)

gutopia-drb.rb (219 Bytes)

gutopia-romp.rb (272 Bytes)

gutopia.rb (5.72 KB)

orig-example.rb (2.9 KB)

Tom Sawyer wrote:

it was stated that a main goal of Rouge was to create a cross-compatible
gui api that “boiled down” into the native gui of each platform.

As you’ve found, it’s a major piece of work. I should know - I designed
and my company built such a product (called OpenUI) in the 1st half of
the 90’s. There are better toolkits out there for this now, of which I like
Qt and fxruby best. You definitely shouldn’t build your own, it’s a problem
that needs multiple hundreds of thousands of lines of code to solve.

i think too that this is a fantastic idea.
so that’s the final piece and we end up with basically this:

You’ve described the architecture of OpenUI, but perhaps haven’t understood
the factor that makes it really work: rich asynchronous message passing.

I’m still of the firm opinion that this is the single integrating feature
which is needed to revolutionise GUI programming. Message delivery needs
to be based on hierarchies of objects, including propagation of undelivered
(or partly-delivered) messages up the hierarchy, publish-subscribe propagation
down the hierarchy, and proxy-address mapping for remote objects. Add that to
the basic queueing facilities needed for asynchronous delivery, with a
priority-nesting feature to provide some minimal sequencing control for
consequential messaging (needed for remote validation for example), and you
have an exceptionally powerful and flexible application framework supporting
separation of presentation and semantic content to the fullest extent possible.

The native GUI widgets should be assembled into hierarchies not by API calls,
but by a hierarchical description language - XML probably. In fact I started
making “qtml” - a Qt markup language, which allows simple assembly of arbitrary
widget hierarchies (UIs), and embedded scripting to animate and control the UI.
I’d love to use Ruby with this, it’s the most suitable language for the purpose.

Sorry that much of the above discussion is kind-of schematic, incomplete and
probably confusing, I can discuss the ideas further if they ring anyone’s
bells. Suffice it to say that people who’ve used these ideas in the form of
our (now obsolescent) product have found them to be truly revolutionary.

···


Clifford Heath

Still looks like plain old Model-View-Controller to me. You’ve split the
controller into client and server parts. What is the purpose of separation
into different processes? I don’t mean to sound critical. I really don’t
understand what you are trying to achieve.

Tom Sawyer wrote:

[snip]

it was stated that a main goal of Rouge was to create a cross-compatible
gui api that “boiled down” into the native gui of each platform. in my
first post on these matters, i pointed out how ungodly difficult that
would be (as i had been trying to do that myself). in the end either you
left to “patch” your app for each platform or you simply have to give up
the features that they hold in common (at best). it really is simply too
much of pain to create such an system, not to mention maintaining it as
those underlying native api change. yet the goal os a native look and
feel is not unachievable by other means. the solution is simply a matter
of using an underlying gui engine that is sufficiantly themeable. since
all the major gui’s are now themable themselves, we simply need to code
a theme manager that can import the themes of those other guis. we need
not use their underlying api, only their look and feel! so that’s what
can be done to solve that dilemma: use a sufficantly themeable gui api
and crreat and Themes and Behaviors Manger to emulate the look and feel
and even draw upon the native theme configuration files. this is a much
managable task then trying to channel down to the native guis
themselves. the only trick of course is finding that themeable gui api.

This issue wasn’t so much native look-and-feel as it was native integration
(its not the same). Native integration means that the widgets have the same
behavior as native widgets (usually, because they are native widgets).
Sean Russell made a pretty clear case for this in this posting:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/32029

Sean also mentioned SWT from the Eclipse project, which does this for
Java:

http://www.eclipse.org/articles/Article-SWT-Design-1/SWT-Design-1.html

I think I said this before, but (just in case), the problem that the
FreeRIDE project had (and still has) finding an adequate Ruby GUI toolkit
that simultaneously satisfied the need for both native integration and
internationalization. Of course other features are important, too, but these
were the two big ones that just couldn’t be found in one package.

Curt