module Iowa
# Provides high level functionality for all component subclasses.
# Each "page" in an Iowa app is a Component subclass.
class Component < Element
# Returns an empty hash.
def Component.bindings
{}
end
# Returns the template for the component.
def Component.template
Iowa.app.templateForComponent(self.name)
end
# Finds and returns the named component. Other methods calling this
# one with different values for session and prevPage could induce some
# interesting (or bizarre) behaviors. See pageNamed(name) below for
# the standard invocation.
def Component.pageNamed(name, session, prevPage=nil)
Iowa.app.reloadModified(name,true)
klass = ElementClasses[name.to_s.downcase]
if(klass && klass.ancestors.include?(Component))
page = klass.new("page", {}, {}, nil)
page.prevPage = prevPage
page.session = session
page
else
el = ''
ElementClasses.each_pair do |k,v|
el << "#{k} == #{v}<br/>\n"
end
raise "#{name}: no such page in #{el}"
end
end
# Provides a method to define component attributes which another
# component can bind to.
def Component.attr_binding(*symbols)
symbols.each do |symbol|
class_eval %{
def #{symbol}
@bindings['#{symbol}'].get(@parent)
end
def #{symbol}=(val)
@bindings['#{symbol}'].set(@parent, val)
end
}
end
end
# Standard invocation of Component.pageNamed. Returns the component
# corresponding the the given name.
def page_named(name)
Component.pageNamed(name, @session, self)
end
alias :pageNamed :page_named
attr_accessor :session, :prevPage, :subcomponents, :parent
# Handle the initial tasks that establish the state of the new object.
def initialize(name, bindings, attributes, parent)
@creation_time = Time.now
@parent = parent
if parent
@session = parent.session
end
@subcomponents = {}
super(name, bindings, attributes)
awake()
end
# Stub, intended to be overridden in the subclasses, to define behavior
# that occurs only once, when the object is first created.
def awake
end
# Stub, intended to be overridden in the subclasses, to define behavior
# that occurs when backtracking.
def handle_backtrack
end
alias :handleBacktrack :handle_backtrack
# Stub, intended to be overridden in the subclasses, to define behavior
# that occurs each time the component is displayed.
def setup
end
# Returns the Application object.
def application
Iowa.app
end
# Trigger an action on the component.
def invokeAction(action, &b)
send(action, &b)
end
def handleResponse(context)
@template = self.class.template
setup
handleRequestOrResponse(:handleResponse, context)
end
def handleRequest(context)
handleRequestOrResponse(:handleRequest, context)
end
def handleRequestOrResponse(method, context)
Iowa.app.reloadModified(self.class.to_s,true)
context.pushRoot self
@template.send(method, context)
context.popRoot
end
def getBinding(binding)
@bindings[binding].get(@parent)
end
def setBinding(binding, value)
@bindings[binding].set(@parent, value)
end
def dup
copy = super
@subcomponents.each do |name, child|
newChild = child.dup
newChild.parent = copy
copy.subcomponents[name] = newChild
end
copy
end
def back
if @prevPage
yield @prevPage
end
end
def reload
end
def creation_time
@creation_time
end
end
end