#------------------------------------------------------------------------
# (The MIT License)
#
# Copyright (c) 2008-2011 Rhomobile, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# http://rhomobile.com
#------------------------------------------------------------------------
require 'rho/rhoapplication'
require 'rho/rhocontroller'
require 'rho/rho'
module Rho
class RhoController
begin
is_translator_exist = true
is_translator_exist = Rho::file_exist?( File.join(__rhoGetRuntimeDir(), 'lib/rhodes_translator' + RHO_RB_EXT) ) if !Rho::System.isRhoSimulator
if is_translator_exist
require 'rhodes_translator'
include RhodesTranslator::Translator
include RhodesTranslator::Binding
include RhodesTranslator::Validation
end
rescue Exception => e
end
def self.layout(name)
@layout = name
end
def self.get_layout_name
@layout.nil? ? 'layout' : @layout
end
def self.renderfile(filename, req = {}, res = {})
begin
res = ""
if filename.end_with?(RHO_ERB_EXT)
if RhoApplication::current_controller()
puts "reuse current action controller."
res = RhoApplication::current_controller().inst_render_index(filename, req, res)
else
res = (RhoController.new).inst_render_index(filename, req, res)
end
else
res = IO.read(filename)
end
if System.get_property('platform') != 'WP8'
RhoController.start_objectnotify()
RhoController.start_geoview_notification()
end
res
rescue Exception => exception
raise
end
end
def inst_render_index(filename, req, res)
rho_info 'inst_render_index'
@request, @response = req, res
@params = RhoSupport::query_params req
#@request, @response = {}
#@params = {}
require 'rho/rhoviewhelpers'
@content = eval_compiled_file(filename, getBinding() )
if !xhr?
rho_info 'index layout'
layout = File.dirname(filename) + "/layout" + RHO_ERB_EXT
@content = eval_compiled_file(layout, getBinding() ) if Rho::file_exist?(layout)
else
if @request["headers"]["Transition-Enabled"] == "true"
#puts "add 'div' in inst_render_index"
@content = "
#{@content}
"
end
end
@content
end
def getBinding
binding
end
@@cached_metadata = {}
def self.cached_metadata
@@cached_metadata
end
def self.clean_cached_metadata
@@cached_metadata.clear()
#puts "meta deleted"
end
def __get_model
model = nil
begin
model = Object.const_get(@request['model'].to_sym()) if Object.const_defined?(@request['model'].to_sym() )
rescue Exception => exc
end
end
def render(options = nil)
if @params['rho_callback']
rho_error( "render call in callback. Call WebView.navigate instead" )
return ""
end
RhoProfiler.start_counter('ERB_RENDER')
options = {} if options.nil? or !options.is_a?(Hash)
options = options.symbolize_keys
metaenabled = false
action = nil
action = options[:action] if options[:action]
action = @request['action'].nil? ? default_action : @request['action'] unless action
if @request['model'] != nil
model = __get_model()
if model && model.respond_to?( :metadata ) and model.metadata != nil
if $".include?( "rhodes_translator")
metaenabled = model.metadata[action.to_s] != nil
else
rho_error( "unable to load rhodes_translator gem." )
end
end
end
if not options[:string].nil?
@content = options[:string]
@back_action = options[:back] if options[:back]
options[:layout] = false if options[:layout].nil?
elsif metaenabled
@content = render_metadata(action,model.metadata)
elsif not options[:partial].nil? # render the file and return, don't set rendered true for a partial.
@content = render_partial(options)
options[:layout] = false
else
if options[:file].nil? or !options[:file].is_a?(String)
fname = @request[:modelpath]+action.to_s+RHO_ERB_EXT
if Rho::file_exist?(fname)
@content = eval_compiled_file(fname, getBinding() )
else
@content = ""
end
else
options[:file] = options[:file].gsub(/\.erb$/,"").gsub(/^\/app/,"")
@content = eval_compiled_file(RhoApplication::get_app_path(@request['application'])+options[:file]+RHO_ERB_EXT, getBinding() )
options[:layout] = false if options[:layout].nil?
end
end
#rho_info 'render content: ' + @content.length.to_s
if xhr? and options[:use_layout_on_ajax] != true
options[:layout] = false
if options[:partial].nil? && @request["headers"]["Transition-Enabled"] == "true"
#puts "add 'div' in render"
if !(@request["headers"]["Accept"] =~ /^\*\/\*/ || @request["headers"]["Accept"] =~ /^text\/html/)
@response["headers"]["Content-Type"] = @request["headers"]["Accept"].gsub(/\,.*/, '')
else
@content = "#{@content}
"
end
end
elsif options[:layout].nil? or options[:layout] == true
options[:layout] = self.class.get_layout_name
end
if options[:layout] != false
layoutfile = RhoApplication::get_app_path(@request['application']) + options[:layout].to_s + RHO_ERB_EXT
@content = eval_compiled_file(layoutfile, binding ) if Rho::file_exist?(layoutfile)
rho_info 'Layout file: ' + layoutfile + '. Content size: ' + @content.length.to_s
end
RhoController.start_objectnotify()
RhoController.start_geoview_notification()
@back_action = options[:back] if options[:back]
@rendered = true
RhoProfiler.stop_counter('ERB_RENDER')
@content
end
def render_metadata(action = nil,metadata = nil)
if metadata.nil?
model = nil
model = Object.const_get(@request['model'].to_sym) if Object.const_defined?(@request['model'].to_sym)
if model && model.respond_to?( :metadata ) and model.metadata != nil
metadata = model.metadata
end
end
if action.nil?
action = @request['action'].nil? ? default_action : @request['action']
end
return "" if metadata.nil?
action = action.to_s
data = {}
self.instance_variables.each do |sym|
data[sym.to_s] = self.instance_variable_get sym
end
data["self"] = self
prepared = bind(data,metadata[action])
translate(prepared,action)
end
def render_partial(options = nil)
options = {} if options.nil? or !options.is_a?(Hash)
options = options.symbolize_keys
splitpartial = options[:partial].split('/')
partial_name = splitpartial[-1]
model = nil
if splitpartial.length > 1
model = splitpartial[-2]
end
options[:locals] = {} if options[:locals].nil? or !options[:locals].is_a?(Hash)
content = ""
if options[:collection].nil?
locals = self.clone
class << locals
def set_vars(obj = nil)
@vars = {}
if obj
obj.each do |key,value|
@vars[key.to_sym()] = value if key && key.length > 0
end
end
end
def method_missing(name, *args)
unless name == Fixnum
if name[name.length()-1] == '='
@vars[name.to_s.chop.to_sym()] = args[0]
else
@vars[name]
end
end
end
def get_binding
binding
end
end
locals.set_vars(options[:locals])
modelpath = @request[:modelpath]
modelpath = Rho::RhoFSConnector.get_model_path("app",model) if model
content = eval_compiled_file(modelpath+'_' + partial_name.to_s+RHO_ERB_EXT, locals.get_binding )
else
#xruby issue - https://www.pivotaltracker.com/story/show/3454121
content = render_partial_collection(options,partial_name)
end
content
end
def render_partial_collection(options, partial_name)
i = 0
content = ""
options[:collection].each do |x|
options[:locals][partial_name] = x
options[:locals][partial_name + '_counter'] = i
i = i + 1
#puts "render partial: #{x}"
content += render_partial :partial => options[:partial], :locals => options[:locals]
end
content
end
@@m_geoview_callback = nil
@@m_geoview_callback_data = nil
@@m_geoview_timeout_sec = 0
def set_geoview_notification(callback, callback_data="", timeout_sec=0)
@@m_geoview_callback = callback
@@m_geoview_callback_data = callback_data
@@m_geoview_timeout_sec = timeout_sec
end
def self.start_geoview_notification()
GeoLocation.set_view_notification(@@m_geoview_callback, @@m_geoview_callback_data, @@m_geoview_timeout_sec)
@@m_geoview_callback = nil
@@m_geoview_callback_data = nil
@@m_geoview_timeout_sec = 0
end
@@m_arObjectNotify = []
@@m_arSrcIDNotify = []
def add_objectnotify(arg)
return unless arg
if arg.is_a?(Array)
arg.each do |item|
@@m_arObjectNotify.push(strip_braces(item.object))
@@m_arSrcIDNotify.push(item.source_id)
end
else
@@m_arObjectNotify.push(strip_braces(arg.object))
@@m_arSrcIDNotify.push(arg.source_id)
end
end
def self.start_objectnotify()
if defined?(RHOCONNECT_CLIENT_PRESENT)
Rho::RhoConnectClient.clean_objectnotify()
end
return unless @@m_arObjectNotify && @@m_arObjectNotify.length > 0
if defined?(RHOCONNECT_CLIENT_PRESENT)
0.upto(@@m_arObjectNotify.length()-1) do |i|
Rho::RhoConnectClient::add_objectnotify(@@m_arSrcIDNotify[i], @@m_arObjectNotify[i])
end
end
@@m_arObjectNotify = []
@@m_arSrcIDNotify = []
end
end # RhoController
end # Rho