Module: GladeGUI

Overview

GladeGUI connects your class to a glade form. It will load a .glade file into memory, enabling your ruby programs to have a GUI interface.

GladeGUI works by adding an instance variable named “builder” to your class. The “builder” variable is an instance of Gtk::Builder It holds references to all your windows and widgets.

Include the GladeGUI interface

To use the GladeGUI interface, include this line in your code:

class MyClass
  include GladeGUI
end

GladeGUI will load a corresponding glade file for this class. It knows which glade file to load by using a naming convention:

/folder/MyClass.rb

Will load this glade file:

/folder/glade/MyClass.glade

The class, the class file name and the glade file name must match. You should always name your class, script, and glade file the same name (case sensitive).

builder variable holds all your widgets

So when you “load” your class's glade file where is it loaded?

GladeGUI adds an instance variable, builder to your class. It loads all the windows and widgets from your glade file into @builder. So, you use @builder to manipulate everything in you class's GUI. @builder is set when you call the show_glade() method, as this code shows:

class MyClass

  include GladeGUI

  def initialize()
    puts @builder.to_s  #  => nil
  end

  def before_show()
    puts @builder.to_s   #  => Gtk::Builder
  end  

end

After show_glade() is called, you can access any of your form's windows or widgets using the @builder variable:

@builder["window1"].title = "This is the title that appears at the top."

Here's another example: Suppose you have a glade form with a Gtk::Entry box on it named “email.” You could set the text that appears in the Gtk::Entry by setting the Gtk::Entry#text property:

@builder["email"].text = "harvey@harveyserver.com"

Now the email adddess is set with a new value:

Auto fill your glade form

You can streamline the process of setting-up your forms by auto-filling the widgets from instance variables with the same name.

When assigning names to widgets in glade, give them names that correspond to your instance variables. For example, if you want to edit an email address on the glade form, create an instance variable named @email in your class. Then, in glade, you add a Gtk::Entry widget to your form and set its name to “email”. The advantage of this is that GladeGUI will populate the “email” widget in glade using the @email variable. so you don’t need to include the above line of code. (see set_glade_variables() method.)

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#builderGtk::Builder

Returns The builder that holds references to everything in the glade form.

Returns:

  • (Gtk::Builder)

    The builder that holds references to everything in the glade form.



87
88
89
# File 'lib/GladeGUI.rb', line 87

def builder
  @builder
end

Instance Method Details

#buttonCancel__clicked(*a) ⇒ Object

Convenience method so you can just make a button named “buttonCancel” and it will work. This method isn't called in code, its triggered by a user clicking a button named “buttonCancel”.



402
403
404
# File 'lib/GladeGUI.rb', line 402

def buttonCancel__clicked(*a)
  @builder[:window1].destroy
end

#extract_key(widget) ⇒ String

retrieves the key inside a glade control name. Useful when handling events where the control name is returned, and you need to match it to an actual hash.

Examples:

# Widget in glade form has name of "button[5]"
var = @builder["button[5]"]
extract_key(var) => "5"

Parameters:

  • widget (String)

    Name for the widget in the glade form.

Returns:

  • (String)

    the key value.



419
420
421
# File 'lib/GladeGUI.rb', line 419

def extract_key(widget)
  widget.builder_name[/\[.+?\]/]
end

#get_glade_active_record(obj) ⇒ Object



446
447
448
449
450
451
452
# File 'lib/GladeGUI.rb', line 446

def get_glade_active_record(obj) 
  return if not defined? obj.attributes
  obj.attributes.each_pair do |key, val|
    new_val = get_control_value(key, obj)
    obj.send("#{key}=", new_val) unless new_val.nil?  
  end
end

#get_glade_all(obj = self) ⇒ Object

This method is the most useful method to retreive values from a glade form. It will

populate from active_record fields and instance variables.  It will simply 
call both of these methods:

 get_glade_active_record()
 get_glade_variables()

So, to retreive all the values of a form back into your ActiveRecord object and instance variables, simply call the set_glade_all() method instead.


209
210
211
212
# File 'lib/GladeGUI.rb', line 209

def get_glade_all(obj = self)
  get_glade_active_record(obj)
  get_glade_variables(obj)
end

#get_glade_variables(obj = self) ⇒ Object

Populates your instance variables from the glade form. This works for Gtk:Button, Gtk::Entry, Gtk::Label and Gtk::Checkbutton. So instead of having to assign instance variable:

You can write one line of code:

The optional parameter is seldom used because you usually want the glade form to populate from the calling class. If you passed another object, the form would populate from it.

Examples:

@name = @builder["name"].text 
@address = @builder["address"].text 
@eamil = @builder["email"].text 
@phone = @builder["phone"].text 
get_glade_variables()

Parameters:

  • obj (Object) (defaults to: self)

    Any object with instance variables with same names as in galde form.

Returns:

  • none



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/GladeGUI.rb', line 317

def get_glade_variables(obj = self)
  obj.instance_variables.each do |var_name|
    next if var_name == :@builder or var_name == :@top_level_window
    var = obj.instance_variable_get(var_name)
    var_name = var_name.to_s.gsub("@", "")  #fix for ruby 1.9 giving symbols
    if var.is_a? Hash
      var.each_pair do |key, val|
        if glade_value = get_control_value("#{var_name}[#{key.to_s}]", obj)
          var[key] = glade_value
        end 
      end
      obj.instance_variable_set("@"+ var_name, var)
    elsif var.is_a? Array
      var.each_index do |i|
        if glade_value = get_control_value("#{var_name}[#{i.to_s}]", obj)
          var[i] = glade_value
        end
      end
      obj.instance_variable_set("@"+ var_name, var)
    else
      glade_value = get_control_value(var_name, obj)
      obj.instance_variable_set("@"+ var_name, glade_value) unless glade_value.nil?
    end
  end
end

#load_gladeObject

This will Load the glade form according to the naming convention:

MyClass.rb => MyClass.glade.

It will create a Gtk::Builder object from your glade file. The Gtk::Builder object is stored in the instance variable, @builder. You can get a reference to any of the widgets on the glade form by using the @builder object:

Normally, you should give your widgets names of instance variables: i.e. @email so they can be autoloaded when the glade form is shown using the #show_glade method. For example, the value of the @email vaiable would be loaded into a Gtk:Entry named “email” in your glade form. It saves you from having to do this:

Examples:

widget = @builder["name"]
@builder[:email].text = @email


130
131
132
133
134
135
136
# File 'lib/GladeGUI.rb', line 130

def load_glade() 
  caller__FILE__ = my_class_file_path() 
  file_name = File.join(File.split(caller__FILE__)[0] , "glade", class_name(self) + ".glade")
  @builder = Gtk::Builder.new
  @builder << file_name
  @builder.connect_signals{ |handle| method(handle) }
end

#parse_signalsObject

Connects gtk's signals to your methods according to the naming convention widget__signal. For example,

when you place a button called "button1" in your glade form, and declare a method called 
"button1__clicked", they aren't connected to each other.  Clicking on the button does nothing
and the method never gets called.  After running parse_signals(), the "clicked" signal is
connected to the method named "button1__clicked" so when the user clicks the button, the method is called.

Remember that it will enforce the naming convention: name__signal (two underscores).

Examples:

methods

button1__clicked(*args)
self__row_activated(*args)
instance_variable__key_press_event(*args)


154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/GladeGUI.rb', line 154

def parse_signals()
  meths = self.class.instance_methods()
  meths.each do |meth|
    meth = meth.to_s #bug fix ruby 1.9 gives stmbol
    glade_name, signal_name = *(meth.split("__"))
    next if (signal_name.to_s == "" or glade_name.to_s == "") #covers nil
    if @builder
      @builder.objects.each do |obj|
        next unless obj.respond_to?(:builder_name)
        if obj.builder_name == glade_name or obj.builder_name =~ /^(?:#{class_name(self)}\.|)#{glade_name}\[[a-zA-Z\d_-]+\]$/ #arrays
          obj.signal_connect(signal_name) { |*args| method(meth.to_sym).call(*args) } 
        end
      end
    end
    obj = glade_name == "self" ? self : self.instance_variable_get("@" + glade_name)
    obj ||= eval(glade_name) if respond_to?(glade_name) and method(glade_name.to_sym).arity == 0 # no arguments!
    if obj.respond_to?("signal_connect")
      obj.signal_connect(signal_name) { |*args| method(meth.to_sym).call(*args) }
    end
  end
end

#set_drag_drop(hash) ⇒ Object

drag_to() will make it so you can drag-n-drop the source_widget onto the target widget.

You may pass a reference to a widget object, or a String that gives the name of the
widget on your glade form. So, it functions the same as this statement:

    widget_source.drag_to(widget_target)

It also functions the same as this statement:

    @builder["widget_source"].drag_to(@builder["widget_target"])


100
101
102
103
104
105
106
107
# File 'lib/GladeGUI.rb', line 100

def set_drag_drop(hash)
  hash.each do |key,val|
    src = key.is_a?(Gtk::Widget) ? key : @builder[key]
    target = @builder[val]
    src.extend(VR::Draggable) unless src.is_a?(VR::Draggable)
    src.add_target_widget(target)
  end
end

#set_glade_active_record(obj = self) ⇒ Object

Populates the glade form from the fields of an ActiveRecord object. So instead of having to assign each widget a value: You can write one line of code: The optional parameter is seldom used because you usually want the glade form to populate from the calling class. If you passed another object, the form would populate from it.

Examples:

@builder["name"].text = @name
@builder["address"].text = @address
@builder["email"].text = @eamil
@builder["phone"].text = @phone
set_glade_active_record()

Parameters:

  • obj (ActiveRecord::Base) (defaults to: self)

    Any activerecod base object.

Returns:

  • none



441
442
443
444
# File 'lib/GladeGUI.rb', line 441

def set_glade_active_record(obj = self)
  return if not defined? obj.attributes
  obj.attributes.each_pair { |key, val| fill_control(class_name(obj) + "." + key, val) }
end

#set_glade_all(obj = self) ⇒ Object

This method is the most useful method to populate a glade form. It will

populate from active_record fields and instance variables.  It will simply 
call both of these methods:

 set_glade_active_record()
 set_glade_variables()

So, to set all the values of a form, simply call the set_glade_all() method instead.


196
197
198
199
# File 'lib/GladeGUI.rb', line 196

def set_glade_all(obj = self) 
  set_glade_active_record(obj)
  set_glade_variables(obj)
end

#set_glade_hash(hash) ⇒ Object

Matches names in glade form to keys in a Hash.

Parameters:

  • hash (Hash)

    The hash with keys that match the names in the glade form.



218
219
220
221
# File 'lib/GladeGUI.rb', line 218

def set_glade_hash(hash)
  return unless hash.is_a?(Hash)
  hash.each { |key,val| fill_control( key.to_s, val.to_s) }
end

#set_glade_variables(obj = self) ⇒ Object

Populates the glade form from the instance variables of the class. So instead of having to assign each widget a value:

@builder["name"].text = @name
@builder["address"].text = @address
@builder["email"].text = @eamil
@builder["phone"].text = @phone

you can write one line of code:

set_glade_variables()

The optional parameter is seldom used because you usually want the glade form to populate from the calling class. If you passed another object, the form would populate from it.

obj - type Object



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/GladeGUI.rb', line 241

def set_glade_variables(obj = self)
  obj.instance_variables.each do |name|
    name = name.to_s #ruby 1.9 passes symbol!
    v = obj.instance_variable_get(name)
    name = name.gsub('@', '')
    if v.is_a?(Array) 
      v.each_index do |i|
        fill_control("#{name}[#{i.to_s}]", v[i] )
      end
    elsif v.is_a?(Hash)
      v.each_pair do |key, val|
        fill_control("#{name}[#{key.to_s}]", val)
      end        
    else
      fill_control(name, v)
    end
  end
end

#show_glade(parent = nil) ⇒ Object

The method you call to show the glade form.

It loads the glade form, sets all the form's widgets to your instance variables, connects all your methods to their signals, and starts Gtk.main loop if necessary.

Parameters:

  • parent (Object #builder) (defaults to: nil)

    Optional parent that this window will always be on top of.

Returns:

  • nothing.



381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/GladeGUI.rb', line 381

def show_glade(parent = nil)
  load_glade()
  if parent then
      @builder[:window1].transient_for = parent.builder[:window1]
  end
  before_show() if respond_to? :before_show
  parse_signals()
  set_glade_all()
  @builder[:window1].show  #show_all can't hide widgets in before_show
  @top_level_window = Gtk.main_level == 0 ? true : false
  Gtk.main if @top_level_window or @builder[:window1].modal?  # need new Gtk.main for blocking!
end

#try_to_select_text_in_combobox(cb, text) ⇒ Object



284
285
286
287
288
289
290
291
292
293
# File 'lib/GladeGUI.rb', line 284

def try_to_select_text_in_combobox(cb, text)
  i = 0
  cb.model.each do |model, path, iter|
    if iter[0] == text
      cb.active = i
      return
    end  
    i = i + 1
  end
end

#window1__destroy(*args) ⇒ Object

Called when window is destroyed when you execute: @builder[:window1].destroy It manages the Gtk.main loop for all the windows.



396
397
398
# File 'lib/GladeGUI.rb', line 396

def window1__destroy(*args)
  Gtk.main_quit if @top_level_window or @builder["window1"].modal?  
end

#window1__key_press_event(view, evt) ⇒ Object



406
407
408
409
# File 'lib/GladeGUI.rb', line 406

def window1__key_press_event(view, evt)
  return unless evt.keyval == Gdk::Keyval::KEY_F8
  oinspect
end