class Rtml::Widgets::HighlevelVariableProcessing < Rtml::Widget
affects :screen
entry_point :terminal_variables, :tvars, :_if, :_elsif, :_else, :_end
shared :setvars => Rtml::HighLevel::VariableManager.new
disable_subprocessing!
# Provides a higher-level conditional construct as an alternative to using next and variant tags to generate
# a TML branch.
#
# Examples:
# screen :main do
# _if(tvars[:amount] == 0) { goto :amount_too_low }
# _elsif(tvars[:amount] > 10000) { goto :amount_too_high }
# _else { goto :swipe_card }
# end
#
def _if(condition, &block)
scrid = "#{parent.property('id')}_if"
conditional_goto(scrid, condition, &block)
end
# Provides a higher-level conditional construct as an alternative to using next and variant tags to generate
# a TML branch.
#
# Examples:
# screen :main do
# _if(tvars[:amount] == 0) { goto :amount_too_low }
# _elsif(tvars[:amount] > 10000) { goto :amount_too_high }
# _else { goto :swipe_card }
# end
#
def _elsif(condition, &block)
scrid = "#{parent.property('id')}_elsif"
conditional_goto(scrid, condition, &block)
end
alias _elseif _elsif
# Provides a higher-level conditional construct as an alternative to using next and variant tags to generate
# a TML branch.
#
# Examples:
# screen :main do
# _if(tvars[:amount] == 0) { goto :amount_too_low }
# _elsif(tvars[:amount] > 10000) { goto :amount_too_high }
# _else { goto :swipe_card }
# end
#
def _else(&block)
scrid = "#{parent.property('id')}_else"
conditional_goto(scrid, nil, &block)
end
# Returns a handle to the list of TML variables. Follow this with an array operator to access and manipulate
# the variable assignments for this screen.
#
# You can use the alias #tvars for shorthand access to this method.
#
# Examples:
# screen :init do =>
# terminal_variables[:amount] = 0 =>
# terminal_variables[:first_name] = 'John' =>
# terminal_variables[:last_name] = 'Smith' =>
# terminal_variables[:full_name] = tvars[:first_name] + => op="plus" ro="tmlvar:last_name" />
# end =>
#
# You can also use periods instead of array operators to do the same thing:
#
# Examples:
# screen :init do =>
# terminal_variables.amount = 0 =>
# terminal_variables.first_name = 'John' =>
# terminal_variables.last_name = 'Smith' =>
# terminal_variables.full_name = tvars.first_name + => op="plus" ro="tmlvar:last_name" />
# end =>
def terminal_variables
setvars.screen ||= parent
setvars
end
alias tvars terminal_variables
alias tml terminal_variables
private
def conditional_goto(scrid, condition, &blk)
unless (document.root / "screen[id='#{scrid}']").empty?
scrid = "#{scrid}_#{widget_id}"
end
destination = parent.property('next') || ((c = parent / 'next').empty? ? 'assert' : c.first.property('uri'))
if condition.nil?
parent.goto scrid
parent.property('next', nil)
else
parent.goto scrid, :if => condition
end
r = document.screen(scrid, :next => destination)
method_name = "method_wrapper_for_#{scrid}"
block = blk
(class << r; self; end).instance_eval do
define_method method_name, &block
new_method = instance_method(method_name)
define_method method_name do
new_method.bind(self).call
end
end
ret = r.send(method_name)
if r.elements.length == 1 && (nxt = r.elements.first).name == 'next' && nxt.elements.empty?
# all user did was "goto" -- that should result in a variant in parent, not a whole new screen.
# This is mostly for TML legibility.
if condition.blank?
parent.goto nxt.property('uri')
else
parent.goto nxt.property('uri'), :if => condition
end
document.remove_screen(r)
end
ret
# r
end
def document
@document ||= parent.document
end
end