freightrain 0.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +4 -0
 - data/Rakefile +33 -0
 - data/lib/extensions/gtk/dialog_helper.rb +50 -0
 - data/lib/extensions/gtk/gtk_bootstrapper.rb +32 -0
 - data/lib/extensions/gtk/interface_builder.rb +54 -0
 - data/lib/extensions/gtk/widgets/gtk_calendar.rb +18 -0
 - data/lib/extensions/gtk/widgets/gtk_combo_box.rb +41 -0
 - data/lib/extensions/gtk/widgets/gtk_image.rb +14 -0
 - data/lib/extensions/gtk/widgets/gtk_layout.rb +99 -0
 - data/lib/extensions/gtk/widgets/gtk_toggle_button.rb +13 -0
 - data/lib/extensions/gtk/widgets/gtk_toggle_tool_button.rb +11 -0
 - data/lib/extensions/gtk/widgets/gtk_treeview.rb +80 -0
 - data/lib/extensions/gtk/widgets/gtk_treeviewcolumn.rb +29 -0
 - data/lib/extensions/gtk/widgets/gtk_widget.rb +47 -0
 - data/lib/freightrain/auto_requirer.rb +24 -0
 - data/lib/freightrain/binding/binding_host.rb +35 -0
 - data/lib/freightrain/binding/binding_loader.rb +36 -0
 - data/lib/freightrain/binding/converters/boolean_converter.rb +15 -0
 - data/lib/freightrain/binding/converters/converter_factory.rb +22 -0
 - data/lib/freightrain/binding/converters/default_converter.rb +16 -0
 - data/lib/freightrain/binding/converters/float_converter.rb +16 -0
 - data/lib/freightrain/binding/converters/integer_converter.rb +16 -0
 - data/lib/freightrain/binding/freight_binding.rb +65 -0
 - data/lib/freightrain/bootstrapper.rb +35 -0
 - data/lib/freightrain/dialog_extension.rb +27 -0
 - data/lib/freightrain/elements/element_extension.rb +1 -0
 - data/lib/freightrain/elements/freight_element_view.rb +23 -0
 - data/lib/freightrain/elements/freight_element_view_model.rb +42 -0
 - data/lib/freightrain/elements/layout_widget.rb +11 -0
 - data/lib/freightrain/freight_view.rb +52 -0
 - data/lib/freightrain/freight_view_model.rb +45 -0
 - data/lib/freightrain/interface_builder.rb +23 -0
 - data/lib/freightrain/ioc/container.rb +21 -0
 - data/lib/freightrain/ioc/container_hookable.rb +32 -0
 - data/lib/freightrain/regions/freight_region.rb +32 -0
 - data/lib/freightrain/regions/region_host.rb +37 -0
 - data/lib/freightrain/services/freight_service.rb +14 -0
 - data/lib/freightrain/services/service_host.rb +30 -0
 - data/lib/freightrain/signals/freight_signal.rb +23 -0
 - data/lib/freightrain/signals/signal_host.rb +38 -0
 - data/lib/freightrain/string_patch.rb +24 -0
 - data/lib/freightrain/testhelpers/container_helpers.rb +22 -0
 - data/lib/freightrain/testhelpers.rb +2 -0
 - data/lib/freightrain.rb +8 -0
 - data/lib/scaffolding/commands/app.rb +29 -0
 - data/lib/scaffolding/commands/triad.rb +29 -0
 - data/lib/scaffolding/ftrain.rb +23 -0
 - data/lib/scaffolding/generator.rb +15 -0
 - data/lib/scaffolding/templates/application.ftt +11 -0
 - data/lib/scaffolding/templates/view.ftt +5 -0
 - data/lib/scaffolding/templates/view_bnd.ftt +0 -0
 - data/lib/scaffolding/templates/view_control_glade.ftt +16 -0
 - data/lib/scaffolding/templates/view_model.ftt +7 -0
 - data/lib/scaffolding/templates/view_toplevel_glade.ftt +12 -0
 - metadata +127 -0
 
    
        data/README
    ADDED
    
    
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'spec/rake/spectask'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rake/clean'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'rake/gempackagetask'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'rake/rdoctask'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'rake/testtask'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            spec = Gem::Specification.new do |s|
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.name = 'freightrain'
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.version = '0.5.9'
         
     | 
| 
      
 13 
     | 
    
         
            +
              s.add_dependency('require_all', '>= 1.1.0')
         
     | 
| 
      
 14 
     | 
    
         
            +
              s.add_dependency('needle', '>= 1.3.0')  
         
     | 
| 
      
 15 
     | 
    
         
            +
              s.has_rdoc = false
         
     | 
| 
      
 16 
     | 
    
         
            +
              s.summary = 'ruby desktop development made easy'
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.description = s.summary
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.author = 'Andrea Dallera'
         
     | 
| 
      
 19 
     | 
    
         
            +
              s.email = 'andrea@andreadallera.com'
         
     | 
| 
      
 20 
     | 
    
         
            +
              s.files = %w(README Rakefile) + Dir.glob("{bin,lib}/**/*")
         
     | 
| 
      
 21 
     | 
    
         
            +
              s.require_path = "lib"
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            Rake::GemPackageTask.new(spec) do |p|
         
     | 
| 
      
 25 
     | 
    
         
            +
              p.gem_spec = spec
         
     | 
| 
      
 26 
     | 
    
         
            +
              p.need_tar = true
         
     | 
| 
      
 27 
     | 
    
         
            +
              p.need_zip = true
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            Spec::Rake::SpecTask.new do |t|
         
     | 
| 
      
 31 
     | 
    
         
            +
              t.warning = true
         
     | 
| 
      
 32 
     | 
    
         
            +
              t.spec_files = FileList['spec/**/*.rb']
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,50 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Freightrain
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              module Toolkit
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                module DialogHelper
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def open_file_dialog(description = "Open file...")
         
     | 
| 
      
 9 
     | 
    
         
            +
                    raise "toplevel not implemented. If you want to use " +
         
     | 
| 
      
 10 
     | 
    
         
            +
                           "DialogHelper inside your class you should provide " +
         
     | 
| 
      
 11 
     | 
    
         
            +
                           "a toplevel widget via the toplevel method" unless respond_to? :toplevel
         
     | 
| 
      
 12 
     | 
    
         
            +
                    dialog = Gtk::FileChooserDialog.new(description,
         
     | 
| 
      
 13 
     | 
    
         
            +
                                                        toplevel,
         
     | 
| 
      
 14 
     | 
    
         
            +
                                                        Gtk::FileChooser::ACTION_OPEN,
         
     | 
| 
      
 15 
     | 
    
         
            +
                                                        nil,
         
     | 
| 
      
 16 
     | 
    
         
            +
                                                        [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
         
     | 
| 
      
 17 
     | 
    
         
            +
                                                        [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
         
     | 
| 
      
 18 
     | 
    
         
            +
                    if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
         
     | 
| 
      
 19 
     | 
    
         
            +
                      result = dialog.filename
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                    dialog.destroy
         
     | 
| 
      
 22 
     | 
    
         
            +
                    return result
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def yes_no_dialog(description, title = "Warning!", secondary_text = "It will not be possible to recover the deleted item")
         
     | 
| 
      
 26 
     | 
    
         
            +
                    raise "toplevel not implemented. If you want to use " +
         
     | 
| 
      
 27 
     | 
    
         
            +
                           "DialogHelper inside your class you should provide " +
         
     | 
| 
      
 28 
     | 
    
         
            +
                           "a toplevel widget via the toplevel method" unless respond_to? :toplevel
         
     | 
| 
      
 29 
     | 
    
         
            +
                      result = false
         
     | 
| 
      
 30 
     | 
    
         
            +
                      dialog = Gtk::MessageDialog.new(
         
     | 
| 
      
 31 
     | 
    
         
            +
                      toplevel,
         
     | 
| 
      
 32 
     | 
    
         
            +
                      Gtk::Dialog::MODAL,
         
     | 
| 
      
 33 
     | 
    
         
            +
                      Gtk::MessageDialog::QUESTION,
         
     | 
| 
      
 34 
     | 
    
         
            +
                      Gtk::MessageDialog::BUTTONS_YES_NO,
         
     | 
| 
      
 35 
     | 
    
         
            +
                      description)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      dialog.title = title
         
     | 
| 
      
 37 
     | 
    
         
            +
                      dialog.secondary_text = secondary_text
         
     | 
| 
      
 38 
     | 
    
         
            +
                      dialog.run do |response|
         
     | 
| 
      
 39 
     | 
    
         
            +
                          result = (response == Gtk::Dialog::RESPONSE_YES)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      end
         
     | 
| 
      
 41 
     | 
    
         
            +
                      dialog.destroy
         
     | 
| 
      
 42 
     | 
    
         
            +
                      return result
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                end #DialogHelper
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              end #Toolkit
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            end #Freightrain
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            #TODO: use require all
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'libglade2'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_image.rb"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_toggle_button.rb"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_toggle_tool_button.rb"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_widget.rb"
         
     | 
| 
      
 9 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_combo_box.rb"
         
     | 
| 
      
 10 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_calendar.rb"
         
     | 
| 
      
 11 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_treeview.rb"
         
     | 
| 
      
 12 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_treeviewcolumn.rb"
         
     | 
| 
      
 13 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/widgets/gtk_layout.rb"
         
     | 
| 
      
 14 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/interface_builder.rb"
         
     | 
| 
      
 15 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/dialog_helper.rb"
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            module Freightrain
         
     | 
| 
      
 18 
     | 
    
         
            +
              
         
     | 
| 
      
 19 
     | 
    
         
            +
              module Toolkit
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def self.start_main_loop
         
     | 
| 
      
 22 
     | 
    
         
            +
                  yield
         
     | 
| 
      
 23 
     | 
    
         
            +
                  Gtk.main
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def self.quit
         
     | 
| 
      
 27 
     | 
    
         
            +
                  Gtk.main_quit
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Freightrain
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              module Toolkit
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                class InterfaceBuilder
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @builder = Gtk::Builder.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def file_found?(file_name)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    return get_glade_file(file_name)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def create_objects_from_file(file_name)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @builder.add_from_file(get_glade_file(file_name))
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @control = @builder.objects.first.toplevel
         
     | 
| 
      
 19 
     | 
    
         
            +
                    return @builder.objects.select do
         
     | 
| 
      
 20 
     | 
    
         
            +
                      |obj| obj.respond_to?(:name)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end.map
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def create_object_accessors(widgets, view)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    widgets.each do |widget|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      name = widget.name
         
     | 
| 
      
 27 
     | 
    
         
            +
                      view.instance_eval "def #{name}; @widgets.select { |w| w.name == '#{name}'  }.first ;end;"
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def connect_signals()
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @builder.connect_signals do |signal|
         
     | 
| 
      
 33 
     | 
    
         
            +
                      yield(signal)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def get_glade_file(file_name)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    search_path = File.join(
         
     | 
| 
      
 39 
     | 
    
         
            +
                      Freightrain.app_path,
         
     | 
| 
      
 40 
     | 
    
         
            +
                      "views",
         
     | 
| 
      
 41 
     | 
    
         
            +
                      "**",
         
     | 
| 
      
 42 
     | 
    
         
            +
                      file_name.to_convention + ".glade")
         
     | 
| 
      
 43 
     | 
    
         
            +
                    results = Dir.glob(search_path)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    return results.first
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def control
         
     | 
| 
      
 48 
     | 
    
         
            +
                    return @control
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Gtk
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              class ComboBox
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def elements=(enumerable)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  list_store = Gtk::ListStore.new(::Object, String)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  enumerable.each do |item|
         
     | 
| 
      
 9 
     | 
    
         
            +
                    iterator = list_store.append        
         
     | 
| 
      
 10 
     | 
    
         
            +
                    iterator[0] = item
         
     | 
| 
      
 11 
     | 
    
         
            +
                    iterator[1] = item.send(@text)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                  self.model = list_store
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def selected
         
     | 
| 
      
 17 
     | 
    
         
            +
                  iter = self.active_iter
         
     | 
| 
      
 18 
     | 
    
         
            +
                  return iter[0] if iter
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def selected=(object)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  if self.model
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.model.each do |model, path, iter|
         
     | 
| 
      
 24 
     | 
    
         
            +
                      self.active_iter = iter if iter[0] == object
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def bind(options)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  if options[:property].to_sym == :elements
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @path = options[:path]
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @text = options[:text] || "to_s"
         
     | 
| 
      
 33 
     | 
    
         
            +
                    renderer = Gtk::CellRendererText.new
         
     | 
| 
      
 34 
     | 
    
         
            +
                    self.pack_start(renderer, true)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    self.add_attribute(renderer,:text, 1)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  super(options)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Gtk
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              class Image
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def image=(value)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  file = File.new(File.join(Dir.tmpdir,"tempimg#{self.object_id.to_s}"),'w')
         
     | 
| 
      
 8 
     | 
    
         
            +
                  file << value
         
     | 
| 
      
 9 
     | 
    
         
            +
                  file.close
         
     | 
| 
      
 10 
     | 
    
         
            +
                  self.pixbuf = Gdk::Pixbuf.new(File.join(Dir.tmpdir,"tempimg#{self.object_id.to_s}"))
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
                
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Gtk
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              class Layout
         
     | 
| 
      
 5 
     | 
    
         
            +
                include Freightrain::LayoutWidget
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                attr_writer :viewmodel
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_reader :elements
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 11 
     | 
    
         
            +
                  super
         
     | 
| 
      
 12 
     | 
    
         
            +
                  
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def setup
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @signals ||= {}
         
     | 
| 
      
 17 
     | 
    
         
            +
                  selected_callback   = @signals[:selected]
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @signals[:selected] = lambda do |value|
         
     | 
| 
      
 19 
     | 
    
         
            +
                                          elements.each do |item|
         
     | 
| 
      
 20 
     | 
    
         
            +
                                            item.set_selection(item.value == value)
         
     | 
| 
      
 21 
     | 
    
         
            +
                                          end
         
     | 
| 
      
 22 
     | 
    
         
            +
                                          selected_callback.call(value) if selected_callback
         
     | 
| 
      
 23 
     | 
    
         
            +
                                        end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @elements ||= []      
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @ready = true
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                #TODO:remove
         
     | 
| 
      
 29 
     | 
    
         
            +
                def default_display_logic(elements, enumerable)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #TODO: clean this mess        
         
     | 
| 
      
 31 
     | 
    
         
            +
                  height = elements.length
         
     | 
| 
      
 32 
     | 
    
         
            +
                  delta = enumerable.length - elements.length
         
     | 
| 
      
 33 
     | 
    
         
            +
                  delta.abs.times do
         
     | 
| 
      
 34 
     | 
    
         
            +
                    if delta > 0
         
     | 
| 
      
 35 
     | 
    
         
            +
                      item = self.get_new_item
         
     | 
| 
      
 36 
     | 
    
         
            +
                      self.put(item.control, 0, item.control.height_request * height)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      elements << item
         
     | 
| 
      
 38 
     | 
    
         
            +
                      height += 1
         
     | 
| 
      
 39 
     | 
    
         
            +
                    else
         
     | 
| 
      
 40 
     | 
    
         
            +
                      item = self.children.last
         
     | 
| 
      
 41 
     | 
    
         
            +
                      self.remove(item)
         
     | 
| 
      
 42 
     | 
    
         
            +
                      elements.delete_if {|element| element.control == item }
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  height_factor = self.get_new_item.control.height_request
         
     | 
| 
      
 46 
     | 
    
         
            +
                  self.height = elements.length * height_factor
         
     | 
| 
      
 47 
     | 
    
         
            +
                  (0...elements.length).each do |index|
         
     | 
| 
      
 48 
     | 
    
         
            +
                    elements[index].value = enumerable[index]
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def display_logic(enumerable)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  if @display_logic
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @display_logic.call(self, @elements, enumerable)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  else
         
     | 
| 
      
 56 
     | 
    
         
            +
                    default_display_logic(@elements, enumerable)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def set_display_logic
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @display_logic = lambda do |widget, elements, enumerable|
         
     | 
| 
      
 62 
     | 
    
         
            +
                    yield(widget, elements, enumerable)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def elements=(enumerable)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  setup unless @ready      
         
     | 
| 
      
 68 
     | 
    
         
            +
                  display_logic(enumerable)      
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                def selected
         
     | 
| 
      
 72 
     | 
    
         
            +
                  return @elements.select { |element| element.selected == true}.first
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                def selected=(val)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  @elements.each do |element|
         
     | 
| 
      
 77 
     | 
    
         
            +
                    element.set_selection(val == element.value)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def bind(options)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  if options[:property].to_s == "elements"
         
     | 
| 
      
 83 
     | 
    
         
            +
                    @viewmodel          = (options[:element].to_s + "_element_view_model").to_sym
         
     | 
| 
      
 84 
     | 
    
         
            +
                    options[:force]     = true
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  super(options)
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                def get_new_item
         
     | 
| 
      
 90 
     | 
    
         
            +
                  item = Freightrain[@viewmodel]
         
     | 
| 
      
 91 
     | 
    
         
            +
                  item.signals.each do |key, signal|
         
     | 
| 
      
 92 
     | 
    
         
            +
                   signal.connect(@signals[key]) if @signals[key]
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
                  return item
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,80 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Gtk
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              class TreeView
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def create_column(column_definition)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  renderer   = Gtk::CellRendererText.new
         
     | 
| 
      
 8 
     | 
    
         
            +
                  title      = column_definition.keys.first
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attributes = {}
         
     | 
| 
      
 10 
     | 
    
         
            +
                  column_definition.values.first.each do |binding|
         
     | 
| 
      
 11 
     | 
    
         
            +
                    attributes[binding["property"]] = @paths[binding["path"]]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                  column     = Gtk::TreeViewColumn.new(title, renderer, attributes)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  self.append_column column
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def bind(options)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  if options[:property].to_sym == :elements
         
     | 
| 
      
 19 
     | 
    
         
            +
                    columns = normalize_column_bindings(options[:columns])
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @paths  = get_paths(columns)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    columns.each do |column|
         
     | 
| 
      
 22 
     | 
    
         
            +
                      create_column(column)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  super(options)
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def elements=(enumerable)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  types = [::Object]
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @paths.length.times do
         
     | 
| 
      
 31 
     | 
    
         
            +
                    types << String #TODO: allow for different types
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  list_store = Gtk::ListStore.new(*types)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  enumerable.each do |item|
         
     | 
| 
      
 35 
     | 
    
         
            +
                    iterator = list_store.append
         
     | 
| 
      
 36 
     | 
    
         
            +
                    iterator[0] = item
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @paths.each do |key, index|
         
     | 
| 
      
 38 
     | 
    
         
            +
                      iterator[index] = item.send(key).to_s
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  self.model = list_store
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                private
         
     | 
| 
      
 45 
     | 
    
         
            +
                def normalize_column_bindings(columns)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  result = []
         
     | 
| 
      
 47 
     | 
    
         
            +
                  #step 1 : turn name/values only into arrays with 1 path
         
     | 
| 
      
 48 
     | 
    
         
            +
                  columns.each do |col|
         
     | 
| 
      
 49 
     | 
    
         
            +
                    unless col.values.first.kind_of?(Array)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      result << {col.keys.first => [{"path" => col.values.first}]}
         
     | 
| 
      
 51 
     | 
    
         
            +
                    else
         
     | 
| 
      
 52 
     | 
    
         
            +
                      result << col
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  #step 2 : add property key if not present
         
     | 
| 
      
 56 
     | 
    
         
            +
                  result.each do |col|
         
     | 
| 
      
 57 
     | 
    
         
            +
                    col.values.first.each do |bindings|
         
     | 
| 
      
 58 
     | 
    
         
            +
                      unless bindings["property"]
         
     | 
| 
      
 59 
     | 
    
         
            +
                        bindings["property"] = "text"
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                  return result
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def get_paths(columns)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  paths = {}
         
     | 
| 
      
 68 
     | 
    
         
            +
                  columns.each do |column|
         
     | 
| 
      
 69 
     | 
    
         
            +
                    column.values.each do |binding|
         
     | 
| 
      
 70 
     | 
    
         
            +
                      binding.each do |definition|
         
     | 
| 
      
 71 
     | 
    
         
            +
                        paths[definition["path"]] = paths.length + 1 unless paths[definition["path"]]
         
     | 
| 
      
 72 
     | 
    
         
            +
                      end
         
     | 
| 
      
 73 
     | 
    
         
            +
                    end
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
                  return paths
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
              
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Gtk
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              class TreeViewColumn
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                attr_accessor :path
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                attr_writer   :property
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_writer   :type
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def type
         
     | 
| 
      
 13 
     | 
    
         
            +
                  return @type if @type
         
     | 
| 
      
 14 
     | 
    
         
            +
                  return String
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def property
         
     | 
| 
      
 18 
     | 
    
         
            +
                  return @property if @property
         
     | 
| 
      
 19 
     | 
    
         
            +
                  return :text
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Gtk
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              class Widget
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def bind(binding_options)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @bindings ||= {}
         
     | 
| 
      
 8 
     | 
    
         
            +
                  binding = FreightBinding.new(self, binding_options)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #TODO: send out warning on override?
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @bindings[binding_options[:property]] = binding
         
     | 
| 
      
 11 
     | 
    
         
            +
                  return binding
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def bindings
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @bindings ||= {}
         
     | 
| 
      
 16 
     | 
    
         
            +
                  return @bindings.values
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def color_from_rgb(string)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  red   = ((string[0..1].hex.to_i + 1) * 256) - 1
         
     | 
| 
      
 21 
     | 
    
         
            +
                  green = ((string[2..3].hex.to_i + 1) * 256) - 1
         
     | 
| 
      
 22 
     | 
    
         
            +
                  blue  = ((string[4..5].hex.to_i + 1) * 256) - 1
         
     | 
| 
      
 23 
     | 
    
         
            +
                  return Gdk::Color.new(red, green, blue)
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def background=(color)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  self.modify_bg(Gtk::STATE_NORMAL, color_from_rgb(color))
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def foreground=(color)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  self.modify_fg(Gtk::STATE_NORMAL, color_from_rgb(color))
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def base_background=(color)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  self.modify_base(Gtk::STATE_NORMAL, color_from_rgb(color))
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def plug_in(region_widget)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  self.remove(self.children.first) unless self.children.empty?
         
     | 
| 
      
 40 
     | 
    
         
            +
                  self << region_widget
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Freightrain
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              def self.auto_require!
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                views_folder      = self.views_path
         
     | 
| 
      
 7 
     | 
    
         
            +
                viewmodels_folder = File.join(self.app_path, "viewmodels")
         
     | 
| 
      
 8 
     | 
    
         
            +
                services_folder   = File.join(self.app_path, "services")
         
     | 
| 
      
 9 
     | 
    
         
            +
                domain_folder     = File.join(self.app_path, "domain")
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                require_all views_folder
         
     | 
| 
      
 12 
     | 
    
         
            +
                require_all viewmodels_folder
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                if File.directory?(services_folder) && Dir.entries(services_folder).length > 2
         
     | 
| 
      
 15 
     | 
    
         
            +
                  require_all services_folder
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
                
         
     | 
| 
      
 18 
     | 
    
         
            +
                if File.directory?(domain_folder) && Dir.entries(domain_folder).length > 2
         
     | 
| 
      
 19 
     | 
    
         
            +
                  require_all domain_folder
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
              
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Freightrain
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              module BindingHost
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def load_bindings_from_file(widgets)      
         
     | 
| 
      
 7 
     | 
    
         
            +
                  loader = BindingLoader.new(self.class.name)      
         
     | 
| 
      
 8 
     | 
    
         
            +
                  loader.each_binding do |widget_name, options|
         
     | 
| 
      
 9 
     | 
    
         
            +
                    widget = widgets.select { |widget| widget.name == widget_name }.first
         
     | 
| 
      
 10 
     | 
    
         
            +
                    widget.bind(options) if widget
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
                
         
     | 
| 
      
 14 
     | 
    
         
            +
                def data_source=(source)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  bindings.each do |binding|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    binding.data_source = source
         
     | 
| 
      
 17 
     | 
    
         
            +
                    binding.update
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
                
         
     | 
| 
      
 21 
     | 
    
         
            +
                def bindings
         
     | 
| 
      
 22 
     | 
    
         
            +
                  return widgets.each.map { |widget| widget.bindings }.flatten
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def commit
         
     | 
| 
      
 26 
     | 
    
         
            +
                  bindings.each { |binding| binding.commit }
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def update
         
     | 
| 
      
 30 
     | 
    
         
            +
                  bindings.each { |binding| binding.update}
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Freightrain
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              class BindingLoader
         
     | 
| 
      
 7 
     | 
    
         
            +
                
         
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(class_name)      
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @search_path = File.join(
         
     | 
| 
      
 10 
     | 
    
         
            +
                    Freightrain.views_path,
         
     | 
| 
      
 11 
     | 
    
         
            +
                    "**",
         
     | 
| 
      
 12 
     | 
    
         
            +
                    class_name.to_convention + ".bnd.yml")      
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def filename
         
     | 
| 
      
 16 
     | 
    
         
            +
                  result = Dir.glob(@search_path)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  return result[0] || nil
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def each_binding
         
     | 
| 
      
 21 
     | 
    
         
            +
                  return nil unless filename
         
     | 
| 
      
 22 
     | 
    
         
            +
                  binding_collection = YAML.load_file(filename) || []
         
     | 
| 
      
 23 
     | 
    
         
            +
                  binding_collection.each do |widget, binding|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    binding = [binding] if binding.kind_of? Hash #needed if only 1 binding declared
         
     | 
| 
      
 25 
     | 
    
         
            +
                    binding.each do |binding_options|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      options = {}
         
     | 
| 
      
 27 
     | 
    
         
            +
                      binding_options.each do |key, value|
         
     | 
| 
      
 28 
     | 
    
         
            +
                        options[key.to_sym] = value
         
     | 
| 
      
 29 
     | 
    
         
            +
                      end
         
     | 
| 
      
 30 
     | 
    
         
            +
                      yield(widget, options)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end        
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Freightrain
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              class ConverterFactory
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def self.create(converter_name)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  name = converter_name.to_s.capitalize
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #first try to get one of the standard converters
         
     | 
| 
      
 9 
     | 
    
         
            +
                  if Freightrain.const_defined? "#{name}Converter"
         
     | 
| 
      
 10 
     | 
    
         
            +
                    return Freightrain.const_get("#{name}Converter").new
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #then, if not found, try to get a registered custom converter
         
     | 
| 
      
 13 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 14 
     | 
    
         
            +
                    return Freightrain["#{name}Converter".to_convention_sym]
         
     | 
| 
      
 15 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 16 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     |