Idea: Simplified GTK

Received: Thu, 8 Apr 2004 03:13:24 +0900
And lo, Hal wrote:

Correct assessment. But there are times when you’d want to capture
references to the widgets.

That’s the reason I yielded with the widget itself. The code I wrote is just a hack, and would probably be better like this

def vbox
myvbox = VBox.new
… (same)
myvbox /* return the widget */
end

That way, one could even make something that does:

@myvbox = vbox { … }

It would also be nicer to have a class-independent method for this, so you could:

myvbox = EzGtk.vbox { … }

So it wouldn’t use class variables. Perhaps a thread-global variable?

Thread.current[“storefunc”] = …

There are a large number of cleaner ways to rewrite the code I gave above.

You could also have other EzGtk constructs like …

main {
title “Hello”
width 20
height 20
}

def width (x)
@currentstackwidget.height = x
end

Other simple things like that.

That button () construct doesn’t quite strike me as correct - and could probably be done better

button “buttonname” {
on_click { … }
}

Make it more generic across container-type objects. OTOH, Buttons are rarely used as such a container. ponder ponder ponder

Maybe
button_onclick “buttonname” {

}

I’d be interested in giving a hand if you like this idea and want to go with it. Just email me.

  • Greg Millam

In article 200404071430.54512@vadim.nasardinov,

That’s pretty interesting. I’ve never yet conceived of a state-
machine approach in that kind of situation.

I liked this book a lot:
“Constructing the User Interface with Statecharts”
by Ian Horrocks
ISBN: 0201342782

(But then again, since I don’t write GUIs, I haven’t had a chance
to try out Horrocks’ ideas in practice.)

Looks like an interesting book.

As I mentioned earlier, as a former hardware engineer (you use state
machines everywhere in hardware design) it just seems natural to use a
state-machine as the underlying logic for a GUI. You’ve got events coming
in (button presses, generally) and you transistion to different states in
the machine depending upon the interaction and data provided by the user.
It’s easy to keep the underlying logic seperate from the actual GUI
code when you use a state-machine.

So in the UI I’m currently developing (I say UI because it can be
console-based or GUI based depending on the environment it’s running in) I
have a login-state for logging into a site (asks for user-name and serial
number). If the user is using the GUI they type in the info into a
couple of text boxes and then hit the ‘next’ button and the http
connection is attempted, if successful the machine moves into the next
state and the GUI is notified to display the next tab. In this case the
next botton generates the event to the
state-machine. If the user is using the console version of the same app,
in the login-state they’re asked to enter their email address and then to
enter their serial number. The second ‘return’ after entering the
serial number triggers the event to the state-machine and the connection
is attempted, and again, if the connection was successful the machine
moves into the next state where another set of questions is asked on the
console. The same state-machine can be used in both cases since the
state-machine itself has no GUI/UI code in it.

I kind of thought everyone did things this way, but it sounds like it
isn’t common practice.

Do others use state-machines for this sort of thing?

Phil

···

Vadim Nasardinov vadimn@redhat.com wrote:

On Wednesday 07 April 2004 14:19, Hal Fulton wrote:

“Hal Fulton” hal9000@hypermetrics.com wrote in message
news:407444BD.1090604@hypermetrics.com

You coded the same thing I did in half the time, and it’s prettier. I
find that disgusting. :wink:

I was using an explicit stack in a class variable for the containers.
This is much nicer, and I need to eyeball it and make sure I get it.

Dynamically scoped variables do precisely what your “explicit stack” was
doing:

http://pragprog.com/pragdave/Tech/Random/StackContext.rdoc

The code I posted elsewhere on this thread uses Avi Bryant’s implementation.
It let’s us set up defaults with systematic overriding, including default
blocks:

class A
@@defaults = {:HBox => {:fill => …} }
end

def foo
with_context (:A.defaults) {
bar
}
end

def bar
with_context ( {:other => “stuff”} ) {
baz
}
end

def baz
…find_in_context (:other)
…find_in_context (:HBox)
…find_in_context [:HBox, :fill]
end

(Avi Bryan’t startlingly concise implementation uses continuations.
Continuations make my head hurt but they sure seem to be powerful things).

I just encountered a rare case where I need a Hash where keys
are object id. Class Hash compares keys by value. As a result
two different String with the same value are considered the
same key. This is fine in most cases. But right now I need to
be more restrictive and I need two String objects to be treated
as two keys even if they have the same value.

Not entirely true.

Hash uses #hash and #eql? to decide how to store entries. Some objects
(String) implement #hash, but by default Ruby uses #object_id for #hash:

irb(main):001:0> f = “foo”
irb(main):002:0> f.hash
=> 876516207
irb(main):003:0> f.id
=> 67718468
irb(main):004:0> o = Object.new
=> #Object:0x81277c4
irb(main):005:0> o.hash
=> 67714018
irb(main):006:0> o.id
=> 67714018

I think IdentityHash is a probable name for such a beast, yet
I could not find one in Ruby and I don’t see any method in
class Hash that I could redefine in a derived class to change
the way keys are compared.

How about instead extending Strings you want stored uniquely to return
#object_id for #hash?

···

Jean-Hugues ROBERT (jean_hugues_robert@yahoo.com) wrote:


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Received: Fri, 9 Apr 2004 03:44:16 +0900
And lo, Its wrote:

Hmmm. From platform-independent toolkit to toolkit-independent platform? If
doable, it would make a lot of very protracted and agonizing decisions about
which toolkit much simpler for a whole bunch of poor saps like me.

I like that idea.

And I just wrote a mini editor in EzGtk :-/. I don’t know much about the Fox or TK bindings, but if they provide boxes a la gtk’s hbox and vbox, or something mimicing that, it should be easy to port my EzGtk to … oh, “EzGui” and just use

EzGui.init(EzGui::Gtk)
EzGui.init(EzGui::Fox) … or whatever.

In article A82143D5-8957-11D8-A64E-000A95CD7A8E@talbott.ws,

···

Nathaniel Talbott nathaniel@talbott.ws wrote:

On Apr 7, 2004, at 13:19, Hal Fulton wrote:

If I were you, I’d put together a working example (not too complex,
not too simple) and write an article about it. Bet Dr Dobbs would
go for it.

Well, I’m not him, but I’ll go ahead and do a little “show and tell”
here… I recently worked on an application with a Fox GUI, and in the
process I wrapped some code around Fox to make GUI creation easier.
Part of my thinking when I built it was that there are two things we do
when we set up a GUI, and it would be cleaner if we did them as two
steps instead of mashing them together. Those two steps are setting up
the components relationships to one another, and setting up the
component’s properties, event handlers, etc. So I ended up with code
that looks like this:

class LoginDialog
include FXUtil

attr_reader :credentials

def initialize(app)
  super()
  create(app)
end

def create(app)
  template(app) do
    dialog("Login"){vertical{
    matrix{label(:please_log_in); empty
           label("User name:");   text_field(:username)
           label("Password:");    text_field(:password)}
    horizontal(:buttons){button(:ok); button(:cancel)}}}
  end

  setup :please_log_in do |w|
    w.text = "Please log in"
    w.bold = true
  end

  setup :username do |w|
    w.columns_visible = 20
  end

  setup :password do |w|
    w.options |= TEXTFIELD_PASSWD
    w.columns_visible = 20
    w.on_keypress do |source, selector, event|
      if(event.text == "\r")
        ok(source)
      else
        false
      end
    end
  end

  setup :buttons do |w|
    w.options = LAYOUT_CENTER_X
  end

  setup :ok do |w|
    w.text = "&OK"
    w.options |= BUTTON_DEFAULT|BUTTON_INITIAL
    w.on_click{|source, s, e| ok(source)}
  end

  setup :cancel do |w|
    w.text = "&Cancel"
    w.on_click{|source, s, e| cancel(source)}
  end

  build
end

def ok(source)
  @credentials = [widget(:username).text, widget(:password).text]
  widget.handle(source, MKUINT(FXDialogBox::ID_ACCEPT, 

SEL_COMMAND), nil)
end

def cancel(source)
  widget.handle(source, MKUINT(FXDialogBox::ID_CANCEL, 

SEL_COMMAND), nil)
end

def execute
  widget(:username).setFocus
  (widget.execute(PLACEMENT_SCREEN) == 1) ? true : false
end

end

Currently ‘FXUtil’ is in no way ready for prime time, but hopefully
this code (which is presently live production code) illustrates one
better way that I found of building GUIs.

Interesting. I’d be interested in seeing your implementation of setup and
template. Would that be possible? Wouldn’t have to see everything.

Phil

Well, you’re certainly welcome to see it, though I’m not sure how much
it will help you:

   def template(parent)
     raise "You must call super in initialize!" 

unless(defined?(@widgets))
@real_parent = parent
yield
end

   def setup(name, &block)
     raise "Invalid widget name #{name}" unless(@widgets[name])
     @widgets[name].setup(&block)
   end

One thing that is key to the implementation is that I don’t manipulate
the real Fox widgets… instead, I wrap each one that I use and the
final widgets only get built when I call build at the end of the create
method. Here’s the implementation for one widget wrapper:

   class TextField < Widget
     widget_attr :columns_visible => 1
     widget_attr :options => TEXTFIELD_NORMAL|LAYOUT_FILL_X

     widget_event :on_change, SEL_CHANGED
     widget_event :on_keypress, SEL_KEYPRESS

     def do_build(real_parent)
       FXTextField::new(real_parent, @columns_visible, nil, 0, 

@options)
end
end

Probably all I’ve really done is to tease you more… at some point I
would like to release the utility, but I’m not doing Ruby much right
now (new Java contract) so it may be a little while.

HTH,

Nathaniel
Terralien, Inc.

<:((><

···

On Apr 8, 2004, at 14:22, Phil Tomson wrote:

Interesting. I’d be interested in seeing your implementation of setup
and
template. Would that be possible? Wouldn’t have to see everything.

Actually, its been here for more than a year (maybe two):

http://freeride.rubyforge.org/wiki/wiki.pl?RougeArchitecture/Alpha

But its not bound to a GUI yet. Just an experiment in using Ruby to
encode this kind of declarative UI.

Code is available here:

http://www.infoether.com/ruby/utopia-0.2.0.zip

-rich

···

On Apr 11, 2004, at 3:57 PM, Chad Fowler wrote:

Yes. It’s not exactly like this–better, actually. But, it’s not
available publicly yet. I think he calls it Utopia (Gutopia was
apparently a name someone else attached to the same idea).

Sounds like your students work on some pretty great projects. :slight_smile:

Chad

Chad Fowler wrote:

Yes. It’s not exactly like this–better, actually. But, it’s not
available publicly yet. I think he calls it Utopia (Gutopia was
apparently a name someone else attached to the same idea).

Sounds like your students work on some pretty great projects. :slight_smile:

:slight_smile: I’m not sure how far they will get; many of them will simply be
proofs-of-concepts I guess. We’ll see in 2 months…

Regards,

Robert

Gregory Millam wrote:

Correct assessment. But there are times when you’d want to capture
references to the widgets.

That’s the reason I yielded with the widget itself. The code I wrote is just a
hack, and would probably be better like this

def vbox
myvbox = VBox.new
… (same)
myvbox /* return the widget */
end

That way, one could even make something that does:

@myvbox = vbox { … }

That seems reasonable, as long as we avoid doing an instance_eval. (see
below)

It would also be nicer to have a class-independent method for this, so you could:

myvbox = EzGtk.vbox { … }

So it wouldn’t use class variables. Perhaps a thread-global variable?

Thread.current[“storefunc”] = …

That is going right over my head at the moment.

You could also have other EzGtk constructs like …

main {
title “Hello”
width 20
height 20
}

def width (x)
@currentstackwidget.height = x
end

Well, I was thinking of a different method. I made a #setup method (not
used in the code I showed) that would yield the widget so that you could
make changes to that widget.

My basic vision for blocks was:

  1. For containers, establish that container as a context
  2. For non-containers, associate the block with the “most common”
    message for that widget

Re: 2, Note that it would still be possible to associate other blocks
with other messages.

ALSO: Note that I never used instance_eval (except in #setup). This is
important, because any @var referenced is an @var of App, regardless
of block nesting.

Other simple things like that.

That button () construct doesn’t quite strike me as correct - and could probably be done better

button “buttonname” {
on_click { … }
}

Make it more generic across container-type objects. OTOH, Buttons are rarely used as such a container. ponder ponder ponder

Maybe
button_onclick “buttonname” {

}

For my part, I still like the idea of a “default message” for a given
non-container widget. I can be convinced I’m wrong, though.

I’d be interested in giving a hand if you like this idea and want to go with it. Just email me.

Cc’ing now.

Hal

“Its Me” itsme213@hotmail.com writes:

(Avi Bryan’t startlingly concise implementation uses continuations.
Continuations make my head hurt but they sure seem to be powerful
things).

I have to say, his implementation using callcc is pretty bad-ass.
Thanks for the link… Reading and understanding that code helped me
understand continuations quite a bit more than I used to.

···


Josh Huber

Phil Tomson wrote:

Do others use state-machines for [driving the logic of rich user interfaces]?

Ain’t know about Ruby [yet], but when writing thick GUIs in Java I use
state machines for anything bigger than a simple popup dialog.

Resulting code is somewhat more verbose, but comes out rather stable due
to very clean separation of buttons and logic.

In really complex situations, write a separate class for each state.
Transition from state to state is then a factory method in the
originating state, which creates an instance of the destination state,
and passes control there. Main loop (translated to Ruby) is something like:

state = InitialState.new
state = state.getNextState until state.final?

Best regards,
Alexey Verkhovsky

I just encountered a rare case where I need a Hash where keys
are object id. Class Hash compares keys by value. As a result
two different String with the same value are considered the
same key. This is fine in most cases. But right now I need to
be more restrictive and I need two String objects to be treated
as two keys even if they have the same value.

Not entirely true.

Hash uses #hash and #eql? to decide how to store entries. Some objects
(String) implement #hash, but by default Ruby uses #object_id for #hash:

Thanks for the clarification.

I think IdentityHash is a probable name for such a beast, yet
I could not find one in Ruby and I don’t see any method in
class Hash that I could redefine in a derived class to change
the way keys are compared.

How about instead extending Strings you want stored uniquely to return
#object_id for #hash?

Would be OK if my IdentityHash were to contain strings only. But I
need to put arbitrary objects in it.

BTW: I need that to detect “true” circular paths when walking a tree/graph.
Rigth now I detect false circulars when nodes’ values compare equal
where in fact it is two different node objects (with the same “value”).

Thanks.

Jean-Hugues

···

At 05:58 08/04/2004 +0900, you wrote:

Jean-Hugues ROBERT (jean_hugues_robert@yahoo.com) wrote:


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04


Web: http://hdl.handle.net/1030.37/1.1
Phone: +33 (0) 4 92 27 74 17

Oh, cool. I had no idea. Anyone on this thread want to bind utopia to
Gtk (or whatever)? :slight_smile:

Chad

···

On 11/4/2004, at 11:16 PM, Richard Kilmer wrote:

Actually, its been here for more than a year (maybe two):

http://freeride.rubyforge.org/wiki/wiki.pl?RougeArchitecture/Alpha

But its not bound to a GUI yet. Just an experiment in using Ruby to
encode this kind of declarative UI.

Code is available here:

NameBright - Coming Soon

Actually, its been here for more than a year (maybe two):

http://freeride.rubyforge.org/wiki/wiki.pl?RougeArchitecture/Alpha

But its not bound to a GUI yet. Just an experiment in using Ruby to
encode this kind of declarative UI.

I’m grasping everything on that page now. I suggest cutting the examples
in smaller pieces to show either

  • setting widget properties
  • showing auto-update
    and declare first_name somewhere.

But I was only looking at easy widget manipulation back then, not easy
application + gui building. I suppose that’s what they call “learning”.

So now all I need is a nice chunk of time to play with Wise and all
these API ideas (read: I have a couple of weekends in the upcoming months
and some evenings. It’s unlikely I can spend much of that on Wise, since
there are so many other things to do. Can someone hire me to do this,
perhaps?)

Yes. It’s not exactly like this–better, actually. But, it’s not
available publicly yet. I think he calls it Utopia (Gutopia was
apparently a name someone else attached to the same idea).

guitopia, actually :slight_smile:

And we all know there is another project with the name rouge as well.

±-- Kero ----------------------- kero@chello@nl —+

all the meaningless and empty words I spoke |
Promises – The Cranberries |
±-- M38c — http://httpd.chello.nl/k.vangelder —+

Gregory Millam wrote:

That button () construct doesn’t quite strike me as correct -
and could probably be done better

button “buttonname” {
on_click { … }
}

Make it more generic across container-type objects. OTOH,
Buttons are rarely used as such a container. ponder ponder
ponder

Maybe
button_onclick “buttonname” {

}

Since the only thing that can happen to a button is that someone
clicks it it might be more concise to leave the onclick out.
Something like:

button “name” {

}

BTW, this is a great line of thinking. I have often craved a more
ruby-esque GUI API. This could finally make GUI programming fun.

Asim

See also Borges:

http://borges.rubyforge.org
http://rubyforge.org/projects/borges/

···

Josh Huber (huber+rt@alum.wpi.edu) wrote:

“Its Me” itsme213@hotmail.com writes:

(Avi Bryan’t startlingly concise implementation uses continuations.
Continuations make my head hurt but they sure seem to be powerful
things).

I have to say, his implementation using callcc is pretty bad-ass.
Thanks for the link… Reading and understanding that code helped me
understand continuations quite a bit more than I used to.


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Jean-Hugues ROBERT jean_hugues_robert@yahoo.com writes:

BTW: I need that to detect “true” circular paths when walking a tree/graph.
Rigth now I detect false circulars when nodes’ values compare equal
where in fact it is two different node objects (with the same “value”).

Can you just hash the ids?

hash[obj.id] = blah

In article 40748346.70007@mail.ru,

Phil Tomson wrote:

Do others use state-machines for [driving the logic of rich user interfaces]?

Ain’t know about Ruby [yet], but when writing thick GUIs in Java I use
state machines for anything bigger than a simple popup dialog.

Resulting code is somewhat more verbose, but comes out rather stable due
to very clean separation of buttons and logic.

In really complex situations, write a separate class for each state.

I’m doing things this way. Each state has a do_action method that gets
called to do tasks and then transition to next state based on user input
and the results of the actions.

All of the state classes are singletons.

Transition from state to state is then a factory method in the
originating state, which creates an instance of the destination state,
and passes control there. Main loop (translated to Ruby) is something like:

state = InitialState.new
state = state.getNextState until state.final?

I’ve got a StateMachine class, here’s most of it:

class StateMachine
include Observable
def initialize(state=InitialState)
@current_state = state
end

def handle_event(event_class)
@current_state.instance.do_action(event_class)
@current_state = @current_state.instance.next_state
changed
notify_observers(@current_state)
end


end

As long as the State classes define a do_action method and a next_state
accessor it’s usable by this StateMachine class. Either the State class
sets up a default next_state or it sets it’s @next_state attrib during the
call to do_action. I suppose I could just have do_action return the
next_state, as well, but I think the way I have it looks a bit clearer.

Another nice consequence of doing things this way (with a state
machine) is that you can set up
some unit tests that test your state_machine without needing to have the
GUI connected up. That way you can thoroughly test your logic without
needing to do a whole bunch of GUI testing to get at it. (of course you’ll
still need to do final GUI testing, but perhaps not as much, besides, I’m
not sure how to setup unit tests for a GUI otherwise, I suspect there
are ways, but they’re probably very specific to the toolkit being used
or you have to have a GUI testing tool).

Phil

···

Alexey Verkhovsky alex_verk@mail.ru wrote:

“Alexey Verkhovsky” alex_verk@mail.ru wrote in message
news:40748346.70007@mail.ru

Resulting code is somewhat more verbose, but comes out rather stable due
to very clean separation of buttons and logic.

Have you considered generating the state machine code from an explict
description of the machine?

state (:s1) { … some static conditions when in :s1, entry/exit actions,
etc.for s1 }
state (:s2, s2) { …}
transition (:s1, :s2, :e1) { … }

It should be quite possible, particularly since you have full Ruby blocks
alongside.