Class: Rtml::Widget
- Inherits:
-
Object
- Object
- Rtml::Widget
- Extended by:
- Rtml::WidgetCore::ClassMethods
- Includes:
- Assigns
- Defined in:
- lib/rtml/widget.rb
Overview
The Widget is the driving force behind RubyTML. It is interaction with Widgets of all shapes and sizes that produces a document model and, finally, the TML document itself. A Widget is so named because it is a generic class that can be made to encapsulate any desired functionality. The Rtml::Widget base class takes care of interfacing content generation code with the RTML project as a whole.
If you’ve done any RTML programming at all, you’ve been using Widgets. Does the following code look familiar?
screen :idle, :next => :main, :timeout => 3 do
display
end
Even core functionality such as the “screen” method is traced back to a Widget – in this case, Rtml::Widgets::Screens
.
Since interfacing with the various components of RTML is handled by the base class, writing a Widget is easy:
class Rtml::Widgets::CardParser < Rtml::Widget
affects :screen
entry_point :card
def card( = {})
raise ":parser must be provided" unless [:parser]
parent.build :card, :parser => [:parser], :parser_params => ([:params] || 'read_data')
end
end
When invoked from a Screen, this code will produce a TML card parser element:
screen . . . do
card :parser => :mag #=> <card parser='mag' params='read_data' />
end
If you are just interested in using the Widgets, you are encouraged to read the documentation for the various Widgets themselves. If you find that you need to program a new Widget in order to address some missing functionality, you can generate one easily with the command line generator:
ruby script/generate widget my_widget [entry_point1 entry_point2 . . .]
Direct Known Subclasses
Constant Summary collapse
- RDOC_ACCESSORS =
These are the accessors that RDoc uses to define what a particular RTML-specific attribute maps to.
There are 3 kinds of accessors:
-
Shared variable
-
These are used to create variables that are different across parent objects, but which are shared between multiple Widgets (whether totally separate, or instances of the same) on the same instantiated parent. It’s a little complicated, but it’s critical in (for example) tracking TML variable definitions.
-
-
Valid parent
-
These are the names of TML elements (or “document” for document-level Widgets) that are allowed to instantiate the Widget in question by calling its entry points.
-
-
Entry point
-
These are instance methods defined by the Widget which are proxied into potential parent objects. Calling an entry point results in the configuration and eventual instantiation of the Widget which declared the entry point.
-
-
{ :shared => 'shared variable', :affects => 'valid parent', :entry_point => "entry point", }
- @@widget_id_tracker =
0
Instance Attribute Summary collapse
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#source_type ⇒ Object
(also: #parent_type)
readonly
Returns the value of attribute source_type.
Instance Method Summary collapse
-
#disable_subprocessing! ⇒ Object
By default, if a Widget’s entry point is called with a block argument, it will be passed into the #process method of the entry point’s return value.
- #document ⇒ Object
-
#enable_subprocessing! ⇒ Object
Use this to enable subprocessing after it has already been disabled.
-
#initialize(parent) ⇒ Widget
constructor
A new instance of Widget.
-
#method_missing(name, *args, &block) ⇒ Object
Any method other than one of this widget’s entry points will be delegated into #parent.
- #respond_to?(*a, &b) ⇒ Boolean
-
#subprocessing_disabled? ⇒ Boolean
(also: #disable_subprocessing?)
Returns true if subprocessing has been disabled.
- #validate_parent(*options) ⇒ Object
-
#widget_id ⇒ Object
A guaranteed unique ID for this Widget.
Methods included from Assigns
Constructor Details
#initialize(parent) ⇒ Widget
Returns a new instance of Widget.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/rtml/widget.rb', line 109 def initialize(parent) @parent = parent set_source_type! parent. << self self.class.shared_variables.each do |sv| unless @parent.instance_variable_get("@#{sv[:name]}") if sv[:default_value] if sv[:default_value].kind_of?(Class) @parent.instance_variable_set("@#{sv[:name]}", sv[:default_value].new) else @parent.instance_variable_set("@#{sv[:name]}", sv[:default_value].dup) end end end end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
Any method other than one of this widget’s entry points will be delegated into #parent. The parent’s methods are not known until runtime, and it’s extraordinarily slow to generate delegation for those methods on the fly. Method_missing is the happy middle ground.
98 99 100 101 102 103 |
# File 'lib/rtml/widget.rb', line 98 def method_missing(name, *args, &block) name = name.to_s unless name.kind_of?(String) return parent.send(name, *args, &block) unless entry_points.include?(name) || !parent.respond_to?(name) # FIXME: Why does super raise an ArgumentError("no id given")? raise NoMethodError, "Method missing: #{name}" end |
Instance Attribute Details
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
74 75 76 |
# File 'lib/rtml/widget.rb', line 74 def parent @parent end |
#source_type ⇒ Object (readonly) Also known as: parent_type
Returns the value of attribute source_type.
75 76 77 |
# File 'lib/rtml/widget.rb', line 75 def source_type @source_type end |
Instance Method Details
#disable_subprocessing! ⇒ Object
By default, if a Widget’s entry point is called with a block argument, it will be passed into the #process method of the entry point’s return value. This is called subprocessing – that is, processing the element to be returned at a lower level. This method disables subprocessing and its related assertions. It’s useful, for instance, if you want to manually control how or when the block argument is processed, or if you want to ignore it entirely.
There is a class method of the same name that has the same effect for the entire class; this instance method can disable subprocessing for particular instances, and is useful if you only want subprocessing under certain conditions.
147 148 149 |
# File 'lib/rtml/widget.rb', line 147 def disable_subprocessing! @disable_subprocessing = true end |
#document ⇒ Object
86 87 88 |
# File 'lib/rtml/widget.rb', line 86 def document @document ||= (parent.kind_of?(Rtml::Document) || !parent.respond_to?(:document) ? parent : parent.document) end |
#enable_subprocessing! ⇒ Object
Use this to enable subprocessing after it has already been disabled. See #disable_subprocessing!
135 136 137 |
# File 'lib/rtml/widget.rb', line 135 def enable_subprocessing! @disable_subprocessing = false end |
#respond_to?(*a, &b) ⇒ Boolean
105 106 107 |
# File 'lib/rtml/widget.rb', line 105 def respond_to?(*a, &b) super || parent.respond_to?(*a, &b) end |
#subprocessing_disabled? ⇒ Boolean Also known as: disable_subprocessing?
Returns true if subprocessing has been disabled. See also #disable_subprocessing!
128 129 130 131 |
# File 'lib/rtml/widget.rb', line 128 def subprocessing_disabled? @disable_subprocessing = self.class.disable_subprocessing? unless defined?(@disable_subprocessing) @disable_subprocessing end |
#validate_parent(*options) ⇒ Object
78 79 80 81 82 83 84 |
# File 'lib/rtml/widget.rb', line 78 def validate_parent(*) = .flatten.collect { |o| o.kind_of?(String) ? o : o.to_s } unless .include?(parent.name) || .include?(parent.class.name) || ((.include?(:document) || .include?('document')) && parent.kind_of?(Rtml::Document)) raise ArgumentError, "Expected parent to be one of #{.to_sentence}; found #{parent.name}" end end |
#widget_id ⇒ Object
A guaranteed unique ID for this Widget.
91 92 93 |
# File 'lib/rtml/widget.rb', line 91 def @widget_id ||= (@@widget_id_tracker += 1) end |