From: Its Me Date: 2004-04-08T04:09:19+09:00 Subject: Re: Simplified GTK I love it! Here with several (imo) improvements: 1. use dyamically scoped variables (really appropriate) 2. can use 1. to set up any overridable defaults e.g. with_context(:VBox=>{:direction=>:top_down}) { ... } find_in_context [:VBox, :direction] 3. return handles to widgets 4. can add widgets "after the fact" 5. can add externally created widget instances ######################## # Begin code require 'gtk2' class Gtk::Window def add_child c self.add c end end class Gtk::HBox def add_child c self.pack_start c end end class Gtk::VBox def add_child c self.pack_start c end end # BEGIN: dynamically scoped variables # Modified version of Avi Bryant's code # Can lookup a symbol OR a path (list of symbols) # Used for widget's :parent, can be used for all GTK defaults def with_context(params) k, name = catch(:context) {yield; return} k.call(lookup(params,name) || find_in_context(name)) end def find_in_context(name) callcc{|k| throw(:context, [k, name])} end def lookup(params, name) return params[name] if name.is_a? Symbol if name.is_a? Array name.each do |n| params = params[n] end return params end throw :Wrong_type end # END: dynamically scoped variables p lookup ( {:a=>{:b=>{:c=>3}}}, [:a, :b] ) class EzGtkWindow # could easily set up defaults for all widget configuration # use dynamically scoped variables for easy temporary overriding def main window = Gtk::Window.new with_context(:parent=>window) { yield } window end def hbox hbox = Gtk::HBox.new(false) parent = find_in_context(:parent) parent.add_child(hbox) with_context(:parent=>hbox) { yield } hbox end def vbox vbox = Gtk::VBox.new(false) parent = find_in_context(:parent) parent.add_child(vbox) with_context(:parent=>vbox) { yield } vbox end def button(string, &block) button = Gtk::Button.new(string) button.signal_connect("clicked", block) parent = find_in_context(:parent) parent.add_child(button) button end def external(widget) find_in_context(:parent).add_child(widget) end end class MyWindow < EzGtkWindow def initialize @m = main { @hb = hbox { @vb = vbox { @b1 = button("Do it") { puts "pressed btn1"; $stdout.flush } @b2 = button("This too") { puts "pressed btn2"; $stdout.flush } } @vb2 = vbox { @b3 = button("Quit") { puts Gtk.main_quit; $stdout.flush } } } } with_context (:parent=>@vb2) { @b4 = button("Added later") { puts "Added later"; $stdout.flush } } @external = Gtk::Button.new("Externally Created") with_context (:parent=>@vb2) { external(@external) } [@m, @hb, @b1, @b2, @vb2, @b3, @b4, @external].each { |w| p w.class } @m.show_all end end Gtk.init c = MyWindow.new Gtk.main # End code