Idea: Simplified GTK

H

Hal Fulton

Gregory said:
Gaah! I've been working on an implementation of EzGtk and I came across this problem:

What's a good way to specify packing options using EzGtk style? - Or for that matter, alignment?

I'm not ready to let this thread die. ;)
Mostly came up during this

vbox {
expand false # don't expand and fill, give other widgets priority
menubar {
menu "File" {
menuitem "Open" { ... }
...
}
align_right
menu "Help" {
...
}
}
expand true # Widgets after this get all the extra space
scintilla { ... }
}

Thoughts? ideas?

I thought these options were constant for the container? I guess
I'm wrong about that?
(Regarding the 'scintilla' bit: I wrote a ruby-gtk2 binding for scintilla last December (for gtk2, as opposed to fxscintilla). I just haven't bothered finishing it up yet, or figured out how get extconf working to make it releasable. It's still highly usable - the only things not implemented are those that involve styles (where a string is a set of 16 bit "characters" - one character byte, one style byte))

That's very cool. Scintilla is as powerful as they come (afaik). Its
learning curve ranges from shallow to vertical, though.


Hal
 
G

Gregory Millam

Received: Fri, 9 Apr 2004 13:23:17 +0900
I thought these options were constant for the container? I guess
I'm wrong about that?

If homogeneous is false in the creation of the widget, then expand and fill determine what it looks like afterwards. The example I gave earlier was what I ended up using - method based context. (all the context bits like that are controlled by method_missing as it is, and are only valid methods if their current context has a context named that)

vbox {
expand false
fill false
menubar { ... }
expand true
fill true
scintilla
}

Flesh out menubar, and tada, instant mini-editor.
That's very cool. Scintilla is as powerful as they come (afaik). Its
learning curve ranges from shallow to vertical, though.

I've rarely actually used it to code. I only wrote the rbscintilla.so for a programming contest - My team was making a "Collaborative client-server based IDE" for the contest. We couldn't finish enough of it to make it usable, though, and the perl team won with a file browser. *cough* (we had 12 hours to code the whole thing. If we had just /1/ hour more, we'd have had it complete enough to win)

Using scintilla in Gtk is easy, though.

require 'rbscintilla'
sci = Gtk::Scintilla.new # or in EzGtk, just "sci = scintilla"
# Add it to a window and stuff.
# load file
sci.text = IO.readlines(filename).join("\n")
# Go ahead and edit, it's already all set up and editable.
# Now asave
File.open(filename,"w") do |f| f.write(sci.text) end

- Greg
 
G

gabriele renzi

il Fri, 9 Apr 2004 14:41:24 +0900, Gregory Millam
Using scintilla in Gtk is easy, though.

require 'rbscintilla'
sci = Gtk::Scintilla.new # or in EzGtk, just "sci = scintilla"
# Add it to a window and stuff.
# load file
sci.text = IO.readlines(filename).join("\n")
# Go ahead and edit, it's already all set up and editable.
# Now asave
File.open(filename,"w") do |f| f.write(sci.text) end

- Greg

yup, just put the work on rubyforge even if not fully completed.
People loves 'release early' :)
 
K

Kero

Since the only thing that can happen to a button is that someone
button "Options..." {
options_dialog {
are_you_sure_dialog {
process_new_options
}
}
}

Even when I'm putting widgets in these blocks, I'm not doing any layout.
There is logic in this, to some extent only :(

button {
image "funny.png"
label "Options..."
}

which may be about layout, such that

button {
label "Options"
image "funny.png"
}

has the image on the other side...

Personally, I prefer to put extra options in the parameter list, since a
block has two meanings (for containers and non-containers), i.e.

button("Options...", :image=>"funny.png") {
# pop up dialog, etc
}

and I'd even assume the text is centered, normally, so the image can be on
either side, until you specify :align=>:right or :left which will put the
image on the right and align the text to it.

And in case you hadn't noticed: I prefer to mention default things
(text and action for buttons) without explicitely naming them. It allows
for shorter code, but should never be confusing like widget("foo", "bar",
"baz").

I am thinking whether to pick this up with Wise :)
http://wise.rubyforge.org/
this declarative way of putting things, takes out the mess with
parent-widgets I have there :)

As a challenge to you: how should a tree-widget be declared? Totally
disregard the current gtk-api, 'coz that's waaay too inconvenient for my
taste. Please improve on this:

tree:)columns=>["ID", "name", "grade", "remark"]) {
branch(1, "Kero", "B") {
branch(nil, "math", "B")
branch(nil, "cs", "A", "MSc :)")
branch(nil, "physics", "C")
}
}

[snip]
My own idea was having it closer to this:

button {
label "name"
on_click { ... }
(right click, mouseover, etc can be set here too)
}

With a shortcut:

button_onclick "name" {
...
}

The big question we should be asking ourselves here - which one follows
the POLS? ;).

Since button() {} will return the button itself (well, what else could it
return? it should return something...) you could do this:

button("name", :tooltip=>"this does...") {
# do it
}.bind:)mouse_over) {
# mention something in a statusbar or so
}

The desire for mouse_over falls in the "everything must be possible"
category, imho, whereas the default action comes from "things you do often
should be easy". The :tooltip handles the mouse-over, but also the
associated timing issues. This already works in Wise :)

and for those that don't like the default block to execute (block only for
layout)

button("name").bind:)action) {
# do it
}

or maybe without :action, since that would be default?

Bye,
Kero.

--

wanna keep developing software?
http://demo.ffii.org/index.php

+--- Kero ----------------------- kero@chello@nl ---+
| all the meaningless and empty words I spoke |
| Promises -- The Cranberries |
+--- M38c --- http://httpd.chello.nl/k.vangelder ---+
 
K

Kero

What's a good way to specify packing options using EzGtk style? - Or
I thought these options were constant for the container? I guess I'm
wrong about that?

Some layout options are for the container (can only find "space between
widgets" right now), others are for each of the widgets inside it (expand,
fill, weight), yet others deal only with size/layout within the widget
(anchor/align, border_width and (for canvases-like things only)
width+height).

I suggest to put the second category with the widgets
itself, not in the container, which can make behaviour for things like
scrollbars more natural (expand in one direction, fixed in the other).

Some containers ("panes", like ScrollPane, SplitPane) behave differently
when shrinking/enlarging (adding scrollbars spontaneously).

Bye,
Kero.
 
K

Kero

But coding using the EzGtk example doesn't feel so much like a program,
as describing a layout for something. Feels like writing for a different
purpose, even though it /is/ just typical ruby code.

They read to me like:
main do # main does:
vbox do # vbox does:
end
end

compared to:

main { # Inside of main ...
vbox { # inside vbox inside of main
}
}
}
But like you said, same difference.

To stress the difference between action-blocks and layout-blocks, why not
use do-end for the actions and { } for the layout?

vbox {
button "Options" do
options_dialog do ... end
end
}

Never thought I'd actually propose a coding guideline... Usually I
hate them :)

Bye,
Kero.
 
H

Hal Fulton

Kero said:
To stress the difference between action-blocks and layout-blocks, why not
use do-end for the actions and { } for the layout?

Thanks for weighing in on this, Kero. I can't help but feel if this
thread stays alive long enough, something good will come from it. :)

I sympathize with your comment above, but I have a habit in Ruby
almost from Day 1 of using braces for one-line blocks and do/end for
multiple lines.

Personally I'd rather just remember that containers contain things,
and non-containers have default actions.

Besides, someday someone would exchange {} for do/end and wonder why
his code didn't change behavior. ;)

Hmm, we should get vruz in on this. (vruz, are you listening??) He is
very interested in gui toolkits and their usability.


Hal
 
G

Gregory Millam

Received: Sun, 11 Apr 2004 04:17:06 +0900
Thanks for weighing in on this, Kero. I can't help but feel if this
thread stays alive long enough, something good will come from it. :)

I sympathize with your comment above, but I have a habit in Ruby
almost from Day 1 of using braces for one-line blocks and do/end for
multiple lines.

Personally I'd rather just remember that containers contain things,
and non-containers have default actions.

Besides, someday someone would exchange {} for do/end and wonder why
his code didn't change behavior. ;)

Hmm, we should get vruz in on this. (vruz, are you listening??) He is
very interested in gui toolkits and their usability.

Been meaning to chime in on Kero's posts, but got distracted with coding :D. And this is a timely reminder.

Buttons are capable of more than just labels. One of my tests has a button with an image.

button {
image "filename.jpg"
on_click do
...
end
}

And yet another one which uses its own block to define a context menu

button {
label "context menu"
cm = cmenu {
menuitem("Save as") do
...
end
submenu("foo") {
menuitem("bar") do
...
end
}
}
on_click do
popup cm
end
}

Kero's mentioning of the GtkTree has been sticking in my mind like a painful sea urchin. No matter how I approach it, it either seems too unwieldy, not functional enough, or not Ez. Mostly trying to think of how I'd display, say, gaim's buddy list in it. -> Need select actions, etc. :-/.

What I've got implemented in my ezgtk so far -

windows, hbox, vbox, buttons, labels, images, my scintilla widget,
menus, notebooks with pages (tabbed widgets), a basic dialog example
... that's about it so far.

- Greg
 
A

Asim Jalis

Been meaning to chime in on Kero's posts, but got distracted
with coding :D. And this is a timely reminder.

Buttons are capable of more than just labels. One of my tests
has a button with an image.

And yet another one which uses its own block to define a
context menu

One solution could be to have different kinds of buttons. A
simple button where the block is the action, and other more
sophisticated buttons that support images, and context menus.

A simple button, a text-box, a label and few other basic controls
could allow all kinds of amazing things to be done.

For example, HTML and the web/UI model works so well, because it
provides just few basic controls, rather than a lot.

This gives it an edge over models which provide no controls and
over other models which provide so much power that the simple
case is hidden behind the structure in place to support the
complicated case.


Asim
 
R

Robert Feldt

I know you lose some flexibility (or you make it one level harder),
but I can't help wanting it to look like this:

def app_logic
main {
hbox {
vbox {
button("Do it") { puts "pressed btn1" }
button("This too") { puts "pressed btn2" }
}
vbox {
button("Third button") { puts "pressed btn3" }
}
}
}
end

Even if something like this (your idea) has some shortcomings, I still
think it's worth doing. It will be very useful for the situations
when its shortcomings aren't an issue (for example, quick and dirty
little GUI apps).
Have you checked out Rich's Guitopia? Looks similar to this. We plan to
use something like that as the top layer for a GUI toolkit one of my
students is doing.

Regards,

Robert
 
C

Chad Fowler

Have you checked out Rich's Guitopia? Looks similar to this. We plan
to use something like that as the top layer for a GUI toolkit one of
my students is doing.

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. :)

Chad
 
H

Hal Fulton

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

I'm willing to contribute to the effort. But since my knowledge of
any/all of the toolkits is imperfect, I'd never be able to do it
alone.


Hal
 
R

Robert Feldt

Chad said:
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. :)
:) 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
 
K

Kero

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

guitopia, actually :)

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 ---+
 
H

Hal Fulton

Kero said:
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?)

wrt hiring you... as the U2 song said, "If I could, I would." ;)
guitopia, actually :)

GUtopIa, I think. :) Gosh, Huck.

I suppose I will devote my time to learning GTK better. It doesn't
appear that any full-featured "ez" alternative is on the horizon
(though I would love to see it in a year or so and would not mind
contributing to Utopia or whatever).


Hal
 
K

Kero

So now all I need is a nice chunk of time to play with Wise and all
wrt hiring you... as the U2 song said, "If I could, I would." ;)

Thank you :)

Quickly wrote a partial wrapper around Wise; can I have your code now,
Hal? (forgotten right now whether it's hidden in this thread somewhere :)

Note: Wise makes any widget a top-level window if the parent==nil

Side note: I see patterns in the wrapper already, wasn't there some
proposal of a pre-initialize and post-initialize to be able to coordinate
super() within constructors more flexibly?
GUtopIa, I think. :) Gosh, Huck.

that's plausible, too ;)

I'll have to check the Rouge code again, as well.

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


# Spawned from [Idea: Simplified GTK]

# However, I do not like the concept of "main" which prevents you from
# running two instances in parallel by explicit design

module Whatever
# example code
# There are two types of blocks, those from layout-components, which are
# executed when the UI is built and those from leaf-widgets, which are
# executed as default action when the widget is manipulated by the user.
def Whatever::run_example()
vbox("Sample app Window") {
button("Top") { puts "Pressed top button" }
hbox("Invisible title") {
button("B-Left") { puts "pressed bottom left" }
button("B-Right") { puts "pressed bottom right" }
}
}
# wait until GUI is done, e.g. by user closing all windows
wait_for_gui_thread
end
end

require "wise"
module Whatever
include Wise

@@parent_stack = []
def Whatever::vbox(title="")
parent = @@parent_stack[-1]
vlist = VList.new(parent, :title=>title, :map=>false)
@@parent_stack << vlist
begin
yield() if block_given?
vlist.map()
ensure
@@parent_stack.pop
end
end

def Whatever::hbox(title="")
parent = @@parent_stack[-1]
hlist = HList.new(parent, :title=>title, :map=>false)
@@parent_stack << hlist
begin
yield() if block_given?
hlist.map()
ensure
@@parent_stack.pop
end
end

def Whatever::button(label, options={}, &when_clicked)
parent = @@parent_stack[-1]
title = options.delete:)title) || label
Button.new(parent, :text=>label, :title=>title, &when_clicked)
end

def Whatever::wait_for_gui_thread()
Wise::main_thread()
end

run_example()
end
 
J

Jean-Hugues ROBERT

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
Yes !
So: an IdentityHash in ruby is just a Hash, but
with obj.object_id() in it vs the obj itself.
Makes a lot of sense.
Thanks George !

Jean-Hugues
PS: As one said, in Computer Science everything is solvable by adding one
indirection level.

class IdentityHash < Hash
def [](k)
super k.object_id
end

def []=(k, v)
super k.object_id, v
end
end

Note that this will, of necessity, prevent this from doing anything
meaningful:

i = IdentityHash.new
i["abc"] = "def"
puts i["abc"] # => nil

-austin

Many thanks austin.
a = "abc"
i = IdentityHash.new
i[a] = "def"
puts i[a] # => "def" !

That is exactly what an IdentityHash should do.

In my case, I use it more like this

visited = IdentityHash.new
def walk( graph, &block )
for node in graph do
next if visited[node] # Avoid circular path
visited[node] = true
block.yield node
walk( node, &block) if node.respond_to: each
end
end

Thanks again Austin.

Jean-Hugues

 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top