class RuGUI::BaseView

A base class for views.

To use this class create a subclass and reimplement setup_widgets, if you want to create your interface by hand. If you want to use a builder file just call use_builder and, optionally, call builder_file passing the filename to use.

Each adapter may implement additional features, extending this class, look for it in adapter classes.

The view may have ViewHelpers, which works as ‘models’ for views, i.e., they have observable properties that can be observed by the view. A default helper, named as {view_name}Helper is registered if it exists. For example, for a view named MyView, the default view helper should be named MyViewHelper. This helper can be accessed as a helper attribute. Other helpers may be registered if needed.

Example (using GTK framework adapter):

class MyGladeView < RuGUI::BaseView
  builder_file 'my_file.glade' # this is optional, if the glade file was called my_glade_view.glade this wouldn't be needed.
  root :top_window
  use_builder
end

class MyHandView < RuGUI::BaseView
  def setup_widgets
    # do your hand-made code here...
  end
end

Attributes

controllers[RW]
glade[RW]
unnamed_widgets[R]
widgets[R]

Public Class Methods

builder_file(file) click to toggle source

Sets the builder file to use when creating this view.

# File lib/rugui/base_view.rb, line 179
def builder_file(file)
  self.configured_builder_file = file
end
framework_adapter_class() click to toggle source
# File lib/rugui/base_view.rb, line 196
def framework_adapter_class
  class_adapter_for('BaseView')
end
new() click to toggle source
# File lib/rugui/base_view.rb, line 46
def initialize
  @controllers = {}
  @helpers = {}
  @unnamed_widgets = []
  @widgets = {}

  register_default_helper
  setup_view_helpers
  build_from_builder_file if use_builder?
  setup_widgets
  autoconnect_signals(self)
end
root(root_widget_name) click to toggle source

Sets the name of the root widget for this view.

This is specially useful when more than one view uses the same glade file, but each one uses a diferent widget tree inside that glade file.

Other use for this is when building a reusable widget, composed of the contents of a glade file. One could create a window, place a vertical box, and then place elements inside this vertical box. Later, this glade file is used to insert the contents of the vertical box inside another vertical box in other glade file.

# File lib/rugui/base_view.rb, line 174
def root(root_widget_name)
  self.configured_root = root_widget_name
end
use_builder(display_root = true) click to toggle source

Tells whether we should use a builder file when creating this view.

By default the root widget will be displayed, but you can pass false to this method to prevent it for being displayed.

# File lib/rugui/base_view.rb, line 187
def use_builder(display_root = true)
  self.configured_builder_file_usage = true
  self.configured_display_root = display_root

  self.configured_builder_file_extension = self.framework_adapter_class.builder_file_extension
  default_builder_file_path = RuGUI.root.join('app', 'resources', "#{self.configured_builder_file_extension}")
  RuGUI.configuration.builder_files_paths << default_builder_file_path unless RuGUI.configuration.builder_files_paths.include?(default_builder_file_path)
end
use_glade() click to toggle source

Call this method at class level if the view should be built from a glade file.

# File lib/rugui/framework_adapters/GTK.rb, line 233
def use_glade
  self.logger.warn('DEPRECATED - Call use_builder class method instead in your view.')
  use_builder
end

Public Instance Methods

add_signal_handler_for_widget_type(widget_type, signal, &block) click to toggle source

Adds a signal handler for all widgets of the given type.

# File lib/rugui/framework_adapters/GTK.rb, line 191
def add_signal_handler_for_widget_type(widget_type, signal, &block)
  widgets = []
  widgets.concat(@widgets.values.select { |widget| widget.kind_of?(widget_type) }) unless @widgets.empty?
  widgets.concat(@unnamed_widgets.select { |widget| widget.kind_of?(widget_type) }) unless @unnamed_widgets.empty?

  widgets.each do |widget|
    widget.signal_connect(signal, &block) unless widget.destroyed?
  end
end
add_widget_to_container(widget, container_widget_or_name) click to toggle source

Adds the given widget to a container widget.

# File lib/rugui/base_view.rb, line 76
def add_widget_to_container(widget, container_widget_or_name)
  self.framework_adapter.add_widget_to_container(widget, from_widget_or_name(container_widget_or_name))
end
build_from_builder_file() click to toggle source

Framework adapters should implement this if they support builder files.

# File lib/rugui/base_view.rb, line 146
def build_from_builder_file
  filename = get_builder_file
  raise BuilderFileNotFoundError, "Could not find builder file for view #{self.class.name}. UI file paths: #{RuGUI.configuration.builder_files_paths.join(', ')}." if filename.nil?

  self.framework_adapter.build_widgets_from(filename)
  self.framework_adapter.register_widgets
end
builder_file() click to toggle source

Returns the builder file.

# File lib/rugui/base_view.rb, line 131
def builder_file
  self.configured_builder_file
end
builder_file_extension() click to toggle source

Returns the builder file extension.

# File lib/rugui/base_view.rb, line 136
def builder_file_extension
  self.configured_builder_file_extension
end
change_widget_style(widget_or_name, widget_path_style) click to toggle source

Changes the widget style to use the given widget style.

This widget style should be declared in a gtkrc file, by specifying a style using a widget path, such as:

widget "main_window" style "main_window_style"
widget "main_window_other" style "main_window_other_style"

In this example, if you called this method like this:

change_widget_style(:main_window, 'main_window_other')
change_widget_style(self.main_window, 'main_window_other')     # or, passing the widget instance directly

The widget style would be set to “main_window_other_style”.

NOTE: Unfortunately, gtk doesn’t offer an API to get declared styles, so you must set a style to a widget. Since the widget name set in the style definition doesn’t need to point to an existing widget we can use this to simplify the widget styling here.

# File lib/rugui/framework_adapters/GTK.rb, line 220
def change_widget_style(widget_or_name, widget_path_style)
  if widget_or_name.is_a?(Gtk::Widget)
    widget = widget_or_name
  else
    widget = @glade[widget_or_name.to_s]
  end
  style = Gtk::RC.get_style_by_paths(Gtk::Settings.default, widget_path_style.to_s, nil, nil)
  widget.style = style
end
connect(sender, signal, slot, receiver = nil) click to toggle source

An utility method to connect Qt signals between two Qt::Object.

If receiver is given, it will be used instead of the view itself.

# File lib/rugui/framework_adapters/Qt4.rb, line 166
def connect(sender, signal, slot, receiver = nil)
  sender = from_widget_or_name(sender)
  receiver = receiver.nil? ? self : from_widget_or_name(receiver)
  if receiver.is_a?(Qt::Object)
    Qt::Object.connect(sender, SIGNAL(signal), receiver, SLOT(slot))
  elsif receiver.is_a?(RuGUI::BaseObject)
    sender.connect(SIGNAL(signal)) { |*args| receiver.send(slot, *args) if receiver.respond_to?(slot) }
  end
end
display_root?() click to toggle source
# File lib/rugui/base_view.rb, line 159
def display_root?
  !!self.configured_display_root
end
framework_adapter() click to toggle source

Returns the framework_adapter for this class.

# File lib/rugui/base_view.rb, line 63
def framework_adapter
  framework_adapter_for('BaseView')
end
include_view(container_widget_name, view) click to toggle source

Includes a view root widget inside the given container widget.

# File lib/rugui/base_view.rb, line 86
def include_view(container_widget_name, view)
  raise RootWidgetNotSetForIncludedView, "You must set a root for views to be included." if view.root_widget.nil?
  add_widget_to_container(view.root_widget, container_widget_name)
end
post_registration(controller) click to toggle source

Called after the view is registered in a controller.

# File lib/rugui/base_view.rb, line 122
def post_registration(controller)
end
register_controller(controller, name = nil) click to toggle source

Registers a controller as receiver of signals from the view widgets.

# File lib/rugui/base_view.rb, line 103
def register_controller(controller, name = nil)
  name ||= controller.class.to_s.underscore
  autoconnect_signals(controller)
  @controllers[name.to_sym] = controller
end
register_helper(helper, name = nil) click to toggle source

Registers a view helper for the view.

# File lib/rugui/base_view.rb, line 110
def register_helper(helper, name = nil)
  helper = create_instance_if_possible(helper) if helper.is_a?(String) or helper.is_a?(Symbol)
  unless helper.nil?()
    name ||= helper.class.to_s.underscore
    helper.register_observer(self, name)
    @helpers[name.to_sym] = helper
    create_attribute_reader(:helpers, name)
    helper.post_registration(self)
  end
end
remove_all_children(container_widget) click to toggle source

Removes all children from the given container widget

# File lib/rugui/base_view.rb, line 98
def remove_all_children(container_widget)
  self.framework_adapter.remove_all_children(container_widget)
end
remove_view(container_widget_name, view) click to toggle source

Removes a view root widget from the given container widget.

# File lib/rugui/base_view.rb, line 92
def remove_view(container_widget_name, view)
  raise RootWidgetNotSetForIncludedView, "You must set a root for views to be removed." if view.root_widget.nil?
  remove_widget_from_container(view.root_widget, container_widget_name)
end
remove_widget_from_container(widget, container_widget_or_name) click to toggle source

Adds the given widget to a container widget.

# File lib/rugui/base_view.rb, line 81
def remove_widget_from_container(widget, container_widget_or_name)
  self.framework_adapter.remove_widget_from_container(widget, from_widget_or_name(container_widget_or_name))
end
root() click to toggle source

Returns the name of the root widget for this view.

# File lib/rugui/base_view.rb, line 155
def root
  self.configured_root.to_s unless self.configured_root.nil?
end
root_widget() click to toggle source

Returns the root widget if one is set.

# File lib/rugui/base_view.rb, line 126
def root_widget
  send(root.to_sym) if not root.nil?
end
setup_view_helpers() click to toggle source

Reimplement this method to setup view helpers.

# File lib/rugui/base_view.rb, line 72
def setup_view_helpers
end
setup_widgets() click to toggle source

Reimplement this method to create widgets by hand.

# File lib/rugui/base_view.rb, line 68
def setup_widgets
end
use_builder?() click to toggle source

Returns true if builder file is being used for this view.

# File lib/rugui/base_view.rb, line 141
def use_builder?
  self.configured_builder_file_usage
end

Protected Instance Methods

add_widget(widget, widget_name = nil) click to toggle source

Adds the widget to the view.

If widget_name is not given one is assumed the widget`s name will be used instead. If the widget doesn’t have a name it will be added as an unnamed widget (accessible through unnamed_widgets property.

# File lib/rugui/base_view.rb, line 219
def add_widget(widget, widget_name = nil)
  widget_name ||= widget.name
  widget_name = widget_name.to_s

  unless widget_name.nil? || widget_name.empty?
    create_attribute_for_widget(widget_name)
    send("#{widget_name}=", widget)
    @widgets[widget_name] = widget
  else
    @unnamed_widgets << widget
  end
end
autoconnect_signals(receiver) click to toggle source
# File lib/rugui/base_view.rb, line 240
def autoconnect_signals(receiver)
  receiver.autoconnect_declared_signals(self)
  self.framework_adapter.autoconnect_signals(receiver)
end
build_widget(widget_type, widget_name = nil, parent = nil, *args) click to toggle source

Builds a widget of the given type, possibly adding it to a parent widget, and display it.

The *args are passed to the widget constructor.

# File lib/rugui/base_view.rb, line 206
def build_widget(widget_type, widget_name = nil, parent = nil, *args)
  widget = widget_type.new(*args)
  self.framework_adapter.set_widget_name(widget, widget_name)
  add_widget(widget, widget_name)
  add_widget_to_container(widget, parent) unless parent.nil?
  widget.show
end
from_widget_or_name(widget_or_name) click to toggle source
# File lib/rugui/base_view.rb, line 232
def from_widget_or_name(widget_or_name)
  if widget_or_name.is_a?(String) || widget_or_name.is_a?(Symbol)
    send(widget_or_name)
  else
    widget_or_name
  end
end

Private Instance Methods

create_attribute_for_widget(widget_name) click to toggle source
# File lib/rugui/base_view.rb, line 265
      def create_attribute_for_widget(widget_name)
        self.instance_eval <<-instance_eval
          def #{widget_name}
            @#{widget_name}
          end

          def #{widget_name}=(widget)
            @#{widget_name} = widget
          end
        instance_eval
      end
create_attribute_reader(entity, name) click to toggle source

Creates an attribute reader for the some entity.

# File lib/rugui/base_view.rb, line 278
      def create_attribute_reader(entity, name)
        self.class.class_eval <<-class_eval
          def #{name}
            @#{entity}[:#{name}]
          end
        class_eval
      end
create_instance_if_possible(klass_name, *args) click to toggle source

Creates an instance of the given class.

# File lib/rugui/base_view.rb, line 287
def create_instance_if_possible(klass_name, *args)
  klass_name.to_s.camelize.constantize.new(*args)
rescue NameError
  # Couldn't create instance.
end
get_builder_file() click to toggle source
# File lib/rugui/base_view.rb, line 246
def get_builder_file
  filename = (not self.builder_file.nil?) ? self.builder_file : "#{self.class.to_s.underscore}.#{builder_file_extension}"

  # The builder file given may already contain a full path to a glade file.
  return filename if File.file?(filename)

  filename = "#{filename}.#{builder_file_extension}" unless File.extname(filename) == ".#{builder_file_extension}"

  paths = RuGUI.configuration.builder_files_paths.select do |path|
    File.file?(File.join(path, filename))
  end
  File.join(paths.first, filename) unless paths.empty?
end
register_default_helper() click to toggle source

Attempts to register the default helper for the view

# File lib/rugui/base_view.rb, line 261
def register_default_helper
  register_helper("#{self.class.name}Helper", :helper)
end