Apologize in advance...this is a LONG response...

> -----Original Message-----
> 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:

<table border="1">                      
  <tr><th>name</th><th>author</th></tr> 
  <tr id="table1">                        
    <td id="name"><td id="author">      
  </tr>                                 
</table>                                
   

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 ;-)

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.

> 
> ~transami
> 
>   _(")_  v man
>    \v/
>    ^ ^