Hi all, New wxRuby event handling offers the choice between using blocks or methods seamlessly and easily. This is great respectively for simple app and more complex app. Nevertheless, currently the creation of an application, a frame, or a dialog is very tedious for simple app : - you need to create a subclass of Wx::App, Wx::Frame ... - you need to put the initialization code in the initialize method for Frame and Dialog - you need to call explicitly the main_loop on the app ... So I defined some sugar classes (I called them Candy :-) ) to ease the writing of simple app. The idea is to take a block for all the initialization code and to embed all other things (like calling the main_loop method for an app). class CandyApp < Wx::App attr_accessor :init_block def self.create &block # Create and run the application app = new app.init_block = block app.main_loop end def on_init instance_eval &init_block true end end class CandyFrame < Wx::Frame def self.create *args, &block frame = new args frame.instance_eval &block frame end def initialize args super *args end end Given these simple additional classes, the minimal app sample can be written like this : CandyApp.create do self.app_name = ''Minimal'' frame = CandyFrame.create(nil, :title => "Minimal wxRuby App", :size => [ 400, 300 ]) do menu_file = Wx::Menu.new() menu_help = Wx::Menu.new() menu_help.append(Wx::ID_ABOUT, "&About...\tF1", "Show about dialog") menu_file.append(Wx::ID_EXIT, "E&xit\tAlt-X", "Quit this program") menu_bar = Wx::MenuBar.new() menu_bar.append(menu_file, "&File") menu_bar.append(menu_help, "&Help") set_menu_bar(menu_bar) create_status_bar(2) set_status_text("Welcome to wxRuby!") evt_menu Wx::ID_EXIT, :on_quit evt_menu Wx::ID_ABOUT, :on_about end frame.show end I find it very readable and less tedious to write (see the attached source files). What do you think about it ? This is only a proof of concept and I also intend to add support for XRC initialization for CandyDialog and CandyFrame. Cheers. Chauk-Mean. -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: minimal.rb Url: http://rubyforge.org/pipermail/wxruby-development/attachments/20070927/61862020/attachment-0002.pl -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: wxcandy.rb Url: http://rubyforge.org/pipermail/wxruby-development/attachments/20070927/61862020/attachment-0003.pl
Chauk-Mean P wrote:> So I defined some sugar classes (I called them Candy :-) ) to ease the > writing of simple app. The idea is to take a block for all the > initialization code and to embed all other things (like calling the > main_loop method for an app).This looks pretty neat, thanks, haven''t had a chance to play with it. Having the standard initializers for Windows (and perhaps App) yield to a block seems easy and rubyish and backwards-compatible. I''ll look at this further when back cheers alex
Chauk-Mean P wrote:> New wxRuby event handling offers the choice between using blocks or > methods seamlessly and easily. This is great respectively for simple > app and more complex app.I took another look at these suggestions and you''re right that they reduce the initialisation tedium quite a bit for simple apps. I used a slightly different implementation in class Wx::App def self.run(&block) app_klass = Class.new(self) app_klass.class_eval do define_method(:on_init, &block) end the_app = app_klass.new the_app.main_loop end Otherwise the way it works is similar, although you have to return a true value from the "run" block. Since it chops about 5 or 6 lines out of the minimal sample, and I think is also easier to understand what is going on for simple apps than the main_loop/on_init pair, I''m inclined to add this - unless others disagree? alex
Alex, 2007/10/17, Alex Fenton <alex at pressure.to>:> Chauk-Mean P wrote: > > New wxRuby event handling offers the choice between using blocks or > > methods seamlessly and easily. This is great respectively for simple > > app and more complex app. > I took another look at these suggestions and you''re right that they > reduce the initialisation tedium quite a bit for simple apps. I used a > slightly different implementation in class Wx::App > ... > Otherwise the way it works is similar, although you have to return a > true value from the "run" block.That''s looking great also :-) ! But you just mention the Wx::App, what about the similar sugar related with Wx::Frame and Wx::Dialog ?> Since it chops about 5 or 6 lines out of the minimal sample, and I think > is also easier to understand what is going on for simple apps than the > main_loop/on_init pair, I''m inclined to add this - unless others disagree?I hope that others will find that also useful. If so, do you intend to add these sugar elements to wxRuby 1.9.2 ? Cheers. Chauk-Mean.
Chauk-Mean P wrote:> But you just mention the Wx::App, what about the similar sugar related > with Wx::Frame and Wx::Dialog ? >I think it would be a no-pain addition to make the initialisers yield to an optional block, which would have a similar effect.> I hope that others will find that also useful. If so, do you intend to > add these sugar elements to wxRuby 1.9.2 ? >Yes, I think so. Ideally we''d test it out in wxSugar first but seems OK just to add it. alex
2007/10/18, Alex Fenton <alex at pressure.to>:> Chauk-Mean P wrote: > > But you just mention the Wx::App, what about the similar sugar related > > with Wx::Frame and Wx::Dialog ? > > > I think it would be a no-pain addition to make the initialisers yield to > an optional block, which would have a similar effect.I agree. For my proof of concept, I just didn''t want to touch the initial classes.> > I hope that others will find that also useful. If so, do you intend to > > add these sugar elements to wxRuby 1.9.2 ? > > > Yes, I think so. Ideally we''d test it out in wxSugar first but seems OK > just to add it.Very cool :-) Cheers. Chauk-Mean.
Alex, I''ve seen that you just committed changes related with this post. Here are some comments. 2007/10/18, Alex Fenton <alex at pressure.to>:> Chauk-Mean P wrote: > > But you just mention the Wx::App, what about the similar sugar related > > with Wx::Frame and Wx::Dialog ? > > > I think it would be a no-pain addition to make the initialisers yield to > an optional block, which would have a similar effect.Indeed, a Wx::Window can take an optional block during its initialization. Nevertheless, this block transmits the window instance as a parameter and you have to use this parameter in your block to make proper initialization. Example : frame = Wx::Frame.new (nil, :title => "My Frame") { |f| f.create_status_bar(2) f.set_status_text("Welcome to wxRuby !") } In my proposal, the use of instance_eval puts the block in the context of the instance. Thus, you can use directly methods accessible from this instance : frame = Wx::Frame.create (nil, :title => "My Frame") { create_status_bar(2) set_status_text("Welcome to wxRuby !") } I think it''s more convenient. Conversely, your Wx::App.run method is just perfect ! "run" is definitively a better name than just "create" :-). Cheers. Chauk-Mean.
Chauk-Mean P wrote:> In my proposal, the use of instance_eval puts the block in the context > of the instance. Thus, you can use directly methods accessible from > this instance : > > frame = Wx::Frame.create (nil, :title => "My Frame") { > create_status_bar(2) > set_status_text("Welcome to wxRuby !") > } > > I think it''s more convenient. >Thanks for the feedback. It''s a bit less typing. What I don''t like so much about using instance_eval rather than block/yield is that it temporarily switches the context and meaning of ''self'', and this isn''t obvious from the method name (new). eg: class MyFrame < Wx::Frame def choose_label ... def initialize self.background_colour = Wx::RED # one meaning of self Wx::Button.new(self) do self.background_colour = Wx::BLUE # different meaning of self self.label = choose_label # breaks, because implicit receiver has changed end end While experienced Rubyists will understand how self/binding/instance_eval work, I think the explicit block parameter form is more in line with vanilla ruby style - File.new doesn''t evaluate the block in the File object''s context. cheers alex
Alex, I was a bit absorbed in the CheckListBox patch but here are additional comments. 2007/10/22, Alex Fenton <alex at pressure.to>:> Chauk-Mean P wrote: > > In my proposal, the use of instance_eval puts the block in the context > > of the instance. Thus, you can use directly methods accessible from > > this instance> Thanks for the feedback. It''s a bit less typing. What I don''t like so > much about using instance_eval rather than block/yield is that it > temporarily switches the context and meaning of ''self'', and this isn''t > obvious from the method name (new).> While experienced Rubyists will understand how > self/binding/instance_eval work, I think the explicit block parameter > form is more in line with vanilla ruby style - File.new doesn''t evaluate > the block in the File object''s context.I agree for File.new and open. But in the same domain as wxRuby, Ruby Tk uses a similar approach as my proposal. Here is a minimal Tk app (from the Pickaxe book) : require ''tk'' root = TkRoot.new { title "Ex1" } TkLabel.new(root) do text ''Hello, World!'' pack(''padx'' => 15, ''pady'' => 15, ''side'' => ''left'') end Tk.mainloop As you can see, within the block of TkRoot.new and TkLabel.new, there is no parameter and the code within those blocks makes direct call to respectively title and text ... Matz wrote the TK library so I think it''s also the Ruby style :-). Cheers. Chauk-Mean. PS : The patch I sent for CheckListBox follows the current situation (block with one parameter).
Chauk-Mean P wrote:>> Thanks for the feedback. It''s a bit less typing. What I don''t like so >> much about using instance_eval rather than block/yield is that it >> temporarily switches the context and meaning of ''self'', and this isn''t >> obvious from the method name (new). >> > > But in the same domain as wxRuby, Ruby Tk uses a similar approach as > my proposal. Here is a minimal Tk app (from the Pickaxe book) : >Fair enough, thanks for the pointer. It''s more the scope/self confusion that bothers me personally than the ruby-ishness. I had a look at other big GUI toolkits and it seems some allow both versions: either one param with block/yield semantics or zero params with instance_eval. So I''m up for allowing either form, depending on whether a block param is requested. Unless anyone else wants to comment.. alex
2007/10/23, Alex Fenton <alex at pressure.to>:> Chauk-Mean P wrote: > > > > But in the same domain as wxRuby, Ruby Tk uses a similar approach as > > my proposal. Here is a minimal Tk app (from the Pickaxe book) : > > > Fair enough, thanks for the pointer. It''s more the scope/self confusion > that bothers me personally than the ruby-ishness. I had a look at other > big GUI toolkits and it seems some allow both versions: either one param > with block/yield semantics or zero params with instance_eval. > > So I''m up for allowing either form, depending on whether a block param > is requested.Excellent idea :-) Chauk-Mean.