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
Public Class Methods
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
# File lib/rugui/base_view.rb, line 196 def framework_adapter_class class_adapter_for('BaseView') end
# 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
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
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
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
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
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
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
Returns the builder file.
# File lib/rugui/base_view.rb, line 131 def builder_file self.configured_builder_file end
Returns the builder file extension.
# File lib/rugui/base_view.rb, line 136 def builder_file_extension self.configured_builder_file_extension end
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
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
# File lib/rugui/base_view.rb, line 159 def display_root? !!self.configured_display_root end
Returns the framework_adapter
for this class.
# File lib/rugui/base_view.rb, line 63 def framework_adapter framework_adapter_for('BaseView') end
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
Called after the view is registered in a controller.
# File lib/rugui/base_view.rb, line 122 def post_registration(controller) end
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
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
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
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
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
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
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
Reimplement this method to setup view helpers.
# File lib/rugui/base_view.rb, line 72 def setup_view_helpers end
Reimplement this method to create widgets by hand.
# File lib/rugui/base_view.rb, line 68 def setup_widgets end
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
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
# File lib/rugui/base_view.rb, line 240 def autoconnect_signals(receiver) receiver.autoconnect_declared_signals(self) self.framework_adapter.autoconnect_signals(receiver) end
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
# 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
# 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
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
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
# 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
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