limelight 0.2.1-java → 0.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. data/bin/ll.bat +1 -1
  2. data/lib/i4jruntime.jar +0 -0
  3. data/lib/junit-4.4.jar +0 -0
  4. data/lib/limelight.jar +0 -0
  5. data/lib/limelight/animation.rb +3 -3
  6. data/lib/limelight/builtin/players.rb +2 -1
  7. data/lib/limelight/builtin/players/combo_box.rb +8 -2
  8. data/lib/limelight/builtin/players/image.rb +47 -0
  9. data/lib/limelight/builtin/styles.rb +1 -1
  10. data/lib/limelight/casting_director.rb +70 -39
  11. data/lib/limelight/commands/command.rb +150 -0
  12. data/lib/limelight/commands/create_command.rb +79 -0
  13. data/lib/limelight/commands/freeze_command.rb +113 -0
  14. data/lib/limelight/commands/open_command.rb +49 -0
  15. data/lib/limelight/commands/pack_command.rb +45 -0
  16. data/lib/limelight/dsl/build_exception.rb +51 -0
  17. data/lib/limelight/dsl/menu_bar.rb +71 -0
  18. data/lib/limelight/dsl/production_builder.rb +71 -0
  19. data/lib/limelight/dsl/prop_builder.rb +155 -0
  20. data/lib/limelight/dsl/stage_builder.rb +105 -0
  21. data/lib/limelight/dsl/styles_builder.rb +134 -0
  22. data/lib/limelight/file_loader.rb +46 -0
  23. data/lib/limelight/gems.rb +45 -0
  24. data/lib/limelight/java_couplings.rb +7 -2
  25. data/lib/limelight/java_util.rb +2 -15
  26. data/lib/limelight/main.rb +7 -5
  27. data/lib/limelight/producer.rb +87 -66
  28. data/lib/limelight/production.rb +42 -4
  29. data/lib/limelight/prop.rb +84 -70
  30. data/lib/limelight/scene.rb +75 -20
  31. data/lib/limelight/specs/spec_helper.rb +58 -0
  32. data/lib/limelight/stage.rb +11 -6
  33. data/lib/limelight/string.rb +35 -0
  34. data/lib/limelight/studio.rb +29 -0
  35. data/lib/limelight/templates/production_templater.rb +42 -0
  36. data/lib/limelight/templates/scene_templater.rb +41 -0
  37. data/lib/limelight/templates/sources/freezing/limelight_init.rb.template +5 -0
  38. data/lib/limelight/templates/sources/production/init.rb.template +15 -0
  39. data/lib/limelight/templates/sources/production/production.rb.template +9 -0
  40. data/lib/limelight/templates/sources/production/stages.rb.template +17 -0
  41. data/lib/limelight/templates/sources/production/styles.rb.template +12 -0
  42. data/lib/limelight/templates/sources/scene/props.rb.template +6 -0
  43. data/lib/limelight/templates/sources/scene/styles.rb.template +18 -0
  44. data/lib/limelight/templates/templater.rb +128 -0
  45. data/lib/limelight/templates/templater_logger.rb +36 -0
  46. data/lib/limelight/theater.rb +21 -7
  47. data/lib/limelight/util.rb +22 -6
  48. data/lib/limelight/version.rb +2 -2
  49. data/productions/examples/8thlight.com/styles.rb +1 -1
  50. data/productions/examples/langstons_ant/html_javascript/ant.html +1 -1
  51. data/productions/examples/langstons_ant/init.rb +1 -0
  52. data/productions/examples/langstons_ant/players/log.rb +2 -2
  53. data/productions/examples/langstons_ant/players/world.rb +0 -26
  54. data/productions/examples/sandbox.llp +0 -0
  55. data/productions/examples/sandbox/click_me/players/chromaton.rb +10 -4
  56. data/productions/examples/sandbox/floaters/players/floater.rb +4 -2
  57. data/productions/examples/sandbox/gradients/players/spinner.rb +5 -1
  58. data/productions/examples/sandbox/gradients/players/teaser.rb +2 -2
  59. data/productions/examples/sandbox/gradients/players/wave.rb +2 -2
  60. data/productions/examples/sandbox/gradients/players/waves.rb +2 -2
  61. data/productions/examples/sandbox/header.rb +1 -0
  62. data/productions/examples/sandbox/images/logo.png +0 -0
  63. data/productions/examples/sandbox/images_scene/props.rb +25 -0
  64. data/productions/examples/sandbox/images_scene/styles.rb +30 -0
  65. data/productions/examples/sandbox/inputs/styles.rb +1 -1
  66. data/productions/examples/sandbox/scrolling/props.rb +12 -12
  67. data/productions/examples/sandbox/teaser/players/fader.rb +2 -8
  68. data/productions/stage_composer/inspector/styles.rb +2 -2
  69. data/productions/startup/styles.rb +2 -2
  70. data/spec/builtin/players/button_spec.rb +0 -1
  71. data/spec/builtin/players/image_spec.rb +41 -0
  72. data/spec/casting_director_spec.rb +114 -44
  73. data/spec/commands/command_spec.rb +18 -0
  74. data/spec/commands/create_command_spec.rb +74 -0
  75. data/spec/commands/freeze_command_spec.rb +59 -0
  76. data/spec/commands/open_command_spec.rb +30 -0
  77. data/spec/commands/pack_command_spec.rb +23 -0
  78. data/spec/dsl/production_builder_spec.rb +46 -0
  79. data/spec/{prop_builder_spec.rb → dsl/prop_builder_spec.rb} +80 -24
  80. data/spec/{stage_builder_spec.rb → dsl/stage_builder_spec.rb} +4 -4
  81. data/spec/{styles_builder_spec.rb → dsl/styles_builder_spec.rb} +6 -6
  82. data/spec/{loaders/file_loader_spec.rb → file_loader_spec.rb} +4 -4
  83. data/spec/gems_spec.rb +83 -0
  84. data/spec/java_util_spec.rb +1 -17
  85. data/spec/main_spec.rb +17 -0
  86. data/spec/producer_spec.rb +89 -79
  87. data/spec/production_spec.rb +28 -3
  88. data/spec/prop_spec.rb +82 -16
  89. data/spec/scene_spec.rb +73 -3
  90. data/spec/spec_helper.rb +37 -1
  91. data/spec/stage_spec.rb +10 -1
  92. data/spec/string_spec.rb +35 -0
  93. data/spec/studio_spec.rb +14 -0
  94. data/spec/styles_spec.rb +14 -0
  95. data/spec/templates/production_templater_spec.rb +44 -0
  96. data/spec/templates/scene_templater_spec.rb +25 -0
  97. data/spec/templates/templater_logger_spec.rb +38 -0
  98. data/spec/templates/templater_spec.rb +104 -0
  99. data/spec/theater_spec.rb +12 -21
  100. metadata +75 -23
  101. data/bin/icons/splash.png +0 -0
  102. data/lib/limelight/build_exception.rb +0 -48
  103. data/lib/limelight/commands.rb +0 -52
  104. data/lib/limelight/loaders/file_scene_loader.rb +0 -49
  105. data/lib/limelight/menu_bar.rb +0 -68
  106. data/lib/limelight/production_builder.rb +0 -66
  107. data/lib/limelight/prop_builder.rb +0 -119
  108. data/lib/limelight/stage_builder.rb +0 -103
  109. data/lib/limelight/styles_builder.rb +0 -131
  110. data/spec/commands_spec.rb +0 -34
  111. data/spec/production_builder_spec.rb +0 -48
@@ -0,0 +1,113 @@
1
+ require 'limelight/commands/command'
2
+
3
+ module Limelight
4
+ module Commands
5
+
6
+ # Freeze a gem into the production. Frozen gems are unpacked into the root level gem directory.
7
+ # Limelight will automatically require a production's frozen gems when loaded.
8
+ #
9
+ # Usage: limelight freeze [options] <gem_name|gem_file>
10
+ # freeze a gem into a production.
11
+ # options:
12
+ # -h, --help Prints this usage summary.
13
+ # -p, --production=<production> Specify the production where the gem will be frozen. Default is '.'.
14
+ # -v, --version=<version> Specify the gem version. Defaults to latest. Ignored if file provided.
15
+ #
16
+ class FreezeCommand < Command
17
+
18
+ install_as "freeze"
19
+
20
+ def self.description #:nodoc:
21
+ return "freeze a gem into a production."
22
+ end
23
+
24
+ attr_reader :gem_name, :production_path, :gem_version
25
+
26
+ def initialize() #:nodoc:
27
+ @production_path = "."
28
+ # self.print_backtrace = true
29
+ end
30
+
31
+ def is_gem_file?(name) #:nodoc:
32
+ return File.extname(name) == ".gem"
33
+ end
34
+
35
+ protected ###########################################
36
+
37
+ def process #:nodoc:
38
+ check_production_path
39
+ gem_path = is_gem_file?(@gem_name) ? @gem_name : find_system_gem
40
+ raise "Gem file does not exist: #{gem_path}" if !File.exists?(gem_path)
41
+ freeze_gem(gem_path)
42
+ end
43
+
44
+ def parse_remainder(args) #:nodoc:
45
+ @gem_name = args.shift
46
+ raise "Gem name paramter missing." if @gem_name.nil?
47
+ end
48
+
49
+ def build_options(spec) #:nodoc:
50
+ spec.on("-p <production>", "--production=<production>", "Specify the production where the gem will be frozen. Default is '.'.") { |value| @production_path = value }
51
+ spec.on("-v <version>", "--version=<version>", "Specify the gem version. Defaults to latest. Ignored if file provided.") { |value| @gem_version = value }
52
+ end
53
+
54
+ def parameter_description #:nodoc:
55
+ return "[options] <gem_name|gem_file>"
56
+ end
57
+
58
+ def do_requires #:nodoc:
59
+ require 'limelight/util'
60
+ require 'limelight/templates/templater'
61
+ require 'rubygems'
62
+ require 'rubygems/commands/unpack_command'
63
+ end
64
+
65
+ private #############################################
66
+
67
+ def check_production_path
68
+ if !(Util.is_limelight_production?(@production_path) || Util.is_limelight_scene?(@production_path))
69
+ raise "The production path '#{@production_path}' doesn't appear to be a Limelight production directory."
70
+ end
71
+ end
72
+
73
+ def find_system_gem
74
+ if @gem_version
75
+ @gem_spec = Gem.cache.find_name(@gem_name, "= #{@gem_version}").first
76
+ raise "Could not find gem (#{@gem_name}-#{@gem_version})." if @gem_spec.nil?
77
+ else
78
+ @gem_spec = Gem.cache.find_name(@gem_name).sort_by { |g| g.version }.last
79
+ raise "Could not find gem (#{@gem_name})." if @gem_spec.nil?
80
+ end
81
+
82
+ return Gem::Commands::UnpackCommand.new.get_path(@gem_name, @gem_spec.version.version)
83
+ end
84
+
85
+ def freeze_gem(gem_path)
86
+ @gem_spec = Gem::Format.from_file_by_path(gem_path).spec unless @gem_spec
87
+ @gem_dir_name = "#{@gem_spec.name}-#{@gem_spec.version}"
88
+
89
+ establish_gem_dir
90
+
91
+ gem_installer = Gem::Installer.new(gem_path)
92
+ @templater.logger.log("unpacking gem", @gem_dir_path)
93
+ gem_installer.unpack(@gem_dir_path)
94
+
95
+ install_limelight_hook
96
+ end
97
+
98
+ def establish_gem_dir
99
+ @templater = Templates::Templater.new(@production_path)
100
+ @gem_dir_path = File.join(@production_path, "__resources", "gems", @gem_dir_name)
101
+ raise "The gem (#{@gem_dir_name}) is already frozen." if File.exists?(@gem_dir_path)
102
+ @templater.directory(File.join("__resources", "gems", @gem_dir_name))
103
+ end
104
+
105
+ def install_limelight_hook
106
+ tokens = { :GEM_NAME => @gem_dir_name, :PATHS => @gem_spec.require_paths.inspect }
107
+ @templater.file(File.join("__resources", "gems", @gem_dir_name, "limelight_init.rb"), "freezing/limelight_init.rb.template", tokens)
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,49 @@
1
+ require 'limelight/commands/command'
2
+
3
+ module Limelight
4
+ module Commands
5
+
6
+ # See the following usage summary.
7
+ #
8
+ # Usage: limelight open <production_path>
9
+ # Open a limelight production.
10
+ # options:
11
+ # -h, --help Prints this usage summary.
12
+ #
13
+ class OpenCommand < Command
14
+
15
+ install_as "open"
16
+
17
+ DEFAULT_PRODUCTION = File.expand_path($LIMELIGHT_HOME + "/productions/startup")
18
+
19
+ def initialize
20
+ self.print_backtrace = true
21
+ end
22
+
23
+ def self.description
24
+ return "Open a limelight production."
25
+ end
26
+
27
+ protected ###########################################
28
+
29
+ def parameter_description
30
+ return "<production_path>"
31
+ end
32
+
33
+ def do_requires
34
+ Main.initialize_context
35
+ require 'limelight/producer'
36
+ end
37
+
38
+ def parse_remainder(args)
39
+ @production_path = args.shift || DEFAULT_PRODUCTION
40
+ end
41
+
42
+ def process
43
+ Limelight::Producer.open(@production_path)
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,45 @@
1
+ #- Copyright 2008 8th Light, Inc. All Rights Reserved.
2
+ #- Limelight and all included source files are distributed under terms of the GNU LGPL.
3
+
4
+ require 'limelight/commands/command'
5
+
6
+ module Limelight
7
+ module Commands
8
+
9
+ # See the following usage summary.
10
+ #
11
+ # Usage: limelight pack <production_path>
12
+ # Pack a limelight production into a .llp file.
13
+ # options:
14
+ # -h, --help Prints this usage summary.
15
+ #
16
+ class PackCommand < Command
17
+
18
+ install_as "pack"
19
+
20
+ def self.description #:nodoc:
21
+ return "Pack a limelight production into a .llp file."
22
+ end
23
+
24
+ protected ###########################################
25
+
26
+ def parameter_description #:nodoc:
27
+ return "<production_path>"
28
+ end
29
+
30
+ def parse_remainder(args) #:nodoc:
31
+ @production_path = args.shift
32
+ raise "Missing production path" if @production_path.nil?
33
+ end
34
+
35
+ def process #:nodoc:
36
+ packer = Limelight::Util::Packer.new
37
+ packer.pack(@production_path)
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+
45
+ end
@@ -0,0 +1,51 @@
1
+ #- Copyright 2008 8th Light, Inc. All Rights Reserved.
2
+ #- Limelight and all included source files are distributed under terms of the GNU LGPL.
3
+
4
+ module Limelight
5
+
6
+ module DSL
7
+
8
+ # An Exception used by many of the DSL Builders. Allows nice errors messages, with line numbers, to be printed.
9
+ #
10
+ class BuildException < Exception
11
+
12
+ attr_reader :filename, :line_number
13
+
14
+ def initialize(filename, file_contents, e)
15
+ @filename = filename
16
+ @file_contents = file_contents
17
+ @original_exception = e
18
+ @line_number = find_line_number
19
+ super(build_error_message)
20
+ set_backtrace(e.backtrace)
21
+ end
22
+
23
+ def find_line_number
24
+ lines = [@original_exception.message].concat @original_exception.backtrace
25
+ line_number = nil
26
+ lines.each do |line|
27
+ match = line.match(/\(eval\):(\d+):/)
28
+ if (match)
29
+ line_number = match[1].to_i
30
+ break
31
+ end
32
+ end
33
+ return line_number
34
+ end
35
+
36
+ def build_error_message
37
+ lines = @file_contents.split("\n")
38
+ start_line = @line_number - 4 < 0 ? 0 : @line_number - 4
39
+ end_line = @line_number + 2 >= lines.size ? lines.size - 1: @line_number + 2
40
+ message = "#{@filename}:#{@line_number}: #{@original_exception.message}"
41
+ message << "\n\t----- #{@filename} lines #{start_line + 1} - #{end_line + 1} -----"
42
+ (start_line..end_line).each do |i|
43
+ message << "\n\t#{i == @line_number - 1 ? "*": " "} #{i+1}: #{lines[i]}"
44
+ end
45
+ message << "\n"
46
+ return message
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,71 @@
1
+ #- Copyright 2008 8th Light, Inc. All Rights Reserved.
2
+ #- Limelight and all included source files are distributed under terms of the GNU LGPL.
3
+
4
+ module Limelight
5
+
6
+ module DSL
7
+
8
+ class AnonymousActionListener #:nodoc:
9
+ include java.awt.event.ActionListener
10
+
11
+ def initialize(context, symbol)
12
+ @context = context
13
+ @symbol = symbol
14
+ end
15
+
16
+ def actionPerformed(e)
17
+ method = @context.method(@symbol)
18
+ method.call
19
+ end
20
+ end
21
+
22
+ # A class used to build menu bars using a DSL.
23
+ #
24
+ # MenuBar.build(self) do
25
+ # menu("File") do
26
+ # item("Open", :open_chosen_scene)
27
+ # item("Refresh", :reload)
28
+ # end
29
+ # end
30
+ #
31
+ # This example created one menu named 'File' with two menu items: 'Open' and 'Refresh'. The seconds parameter of the
32
+ # menu items is the symbol of a method on the context that will be invoked when the menu item is selected.
33
+ #
34
+ class MenuBar
35
+
36
+ def self.build(context, &prop)
37
+ builder = self.new(context)
38
+ builder.instance_eval(&prop)
39
+ return builder.menu_bar
40
+ end
41
+
42
+ attr_reader :menu_bar
43
+
44
+ # This builder must be provided with a context. All menu item actions will be invoked on the context.
45
+ #
46
+ def initialize(context)
47
+ @context = context
48
+ @menu_bar = javax.swing.JMenuBar.new
49
+ end
50
+
51
+ # Creates a new menu with the provided name
52
+ #
53
+ def menu(name)
54
+ @menu = javax.swing.JMenu.new(name)
55
+ @menu_bar.add(@menu)
56
+ yield
57
+ end
58
+
59
+ # Created a new menu item with the provided name. The symbols paramter is the name of a method on the context
60
+ # that will be invoked when the item is selected.
61
+ #
62
+ def item(name, symbol)
63
+ menu_item = javax.swing.JMenuItem.new(name)
64
+ @menu.add(menu_item)
65
+ menu_item.addActionListener(AnonymousActionListener.new(@context, symbol))
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,71 @@
1
+ #- Copyright 2008 8th Light, Inc. All Rights Reserved.
2
+ #- Limelight and all included source files are distributed under terms of the GNU LGPL.
3
+
4
+ require 'limelight/production'
5
+ require 'limelight/limelight_exception'
6
+ require 'limelight/util'
7
+
8
+ module Limelight
9
+
10
+ # A trigger to configure Production objects using the ProductionBuilder DSL.
11
+ #
12
+ # See Limelight::ProductionBuilder
13
+ #
14
+ def self.build_production(production, &block)
15
+ builder = DSL::ProductionBuilder.new(production)
16
+ builder.instance_eval(&block) if block
17
+ return builder.__production__
18
+ end
19
+
20
+ module DSL
21
+ # The basis of the DSL for building Style objects.
22
+ #
23
+ # name "Stage Composer"
24
+ # attribute :controller
25
+ # attribute :inspector
26
+ #
27
+ # The above example names the Production 'Stage Composer' and creates two attributes on the Production: 'controller'
28
+ # and 'inspector'
29
+ #
30
+ class ProductionBuilder
31
+
32
+ Limelight::Util.lobotomize(self)
33
+
34
+ class << self
35
+
36
+ attr_accessor :current_attribute
37
+
38
+ end
39
+
40
+ attr_reader :__production__
41
+
42
+ def initialize(production)
43
+ @__production__ = production
44
+ end
45
+
46
+ def method_missing(sym, value) #:nodoc:
47
+ setter_sym = "#{sym}=".to_s
48
+ raise ProductionBuilderException.new(sym) if !@__production__.respond_to?(setter_sym)
49
+ @__production__.send(setter_sym, value)
50
+ end
51
+
52
+ # Creates an attribute on the Production
53
+ #
54
+ def attribute(sym)
55
+ ProductionBuilder.current_attribute = sym
56
+ class << @__production__
57
+ attr_accessor ProductionBuilder.current_attribute
58
+ end
59
+ end
60
+ end
61
+
62
+ # Thrown if there is an error in the ProductionBuilder DSL
63
+ #
64
+ class ProductionBuilderException < LimelightException
65
+ def initialize(name)
66
+ super("'#{name}' is not a valid production property")
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,155 @@
1
+ #- Copyright 2008 8th Light, Inc. All Rights Reserved.
2
+ #- Limelight and all included source files are distributed under terms of the GNU LGPL.
3
+
4
+ require 'limelight/prop'
5
+ require 'limelight/scene'
6
+ require 'limelight/dsl/build_exception'
7
+ require 'limelight/util'
8
+
9
+ module Limelight
10
+
11
+ # A trigger to build a Limelight::Scene using the PropBuilder DSL.
12
+ #
13
+ # See Limelight::PropBuilder
14
+ #
15
+ def self.build_scene(root, options={}, &block)
16
+ loader = options.delete(:build_loader)
17
+ instance_variables = options.delete(:instance_variables)
18
+ root.add_options(options)
19
+ builder = DSL::PropBuilder.new(root)
20
+ builder.__install_instance_variables(instance_variables)
21
+ builder.__loader__ = loader
22
+ builder.instance_eval(&block) if block
23
+ return root
24
+ end
25
+
26
+ module DSL
27
+
28
+ # The basis of the DSL for building Limelight::Prop objects.
29
+ #
30
+ # Sample usage:
31
+ #
32
+ # builder = Limelight::PropBuilder.new(a_prop)
33
+ # builder.instance_eval(&block)
34
+ #
35
+ # The prop passed into the constructor will be the root of the contructed Prop tree.
36
+ # The block passed into instance_eval contains the DSL for building props.
37
+ #
38
+ # Example block/DSL:
39
+ #
40
+ # parent :id => "the_parent" do
41
+ # child_one do
42
+ # grand_child_one :id => "gc_1", :styles => "grand_child"
43
+ # grand_child_two :id => "gc_2", :styles => "grand_child"
44
+ # end
45
+ # child_two
46
+ # end
47
+ #
48
+ # The above example will create a Limelight::Prop named 'parent' and add it to the root prop passed into the builder.
49
+ # The 'parent' prop will contain two props named 'child_one' and 'child_two'. 'child_one' will contain two props named
50
+ # 'grand_child_one' and 'grand_child_two'. 'child_two' has no child props nor do 'grand_child_one' or 'grand_child_two'.
51
+ #
52
+ # An options Hash may be passed into each prop. The key, value pairs in the hash will be used to set properties on the prop
53
+ # when it is added to a Limelight::Scene.
54
+ #
55
+ # See Limelight::Prop
56
+ #
57
+ class PropBuilder
58
+
59
+ alias :__instance_variables :instance_variables
60
+ alias :__instance_variable_get :instance_variable_get
61
+ alias :__instance_variable_set :instance_variable_set
62
+
63
+ Limelight::Util.lobotomize(self)
64
+
65
+ # Returns the root prop either passed in or created by this builder.
66
+ #
67
+ attr_reader :__prop__
68
+ attr_accessor :__loader__
69
+
70
+ # Creates a new builder. If a prop is passed it, it will be the root on which props are created.
71
+ # If the paramter is a Hash, the Hash will be used to construct a prop that will be used as the root.
72
+ #
73
+ def initialize(options)
74
+ if options.is_a?(Prop)
75
+ @__prop__ = options
76
+ else
77
+ @__prop__ = Prop.new(options)
78
+ end
79
+ end
80
+
81
+ # Add extra initialization options to the prop currently under construction.
82
+ #
83
+ # tree :id => "stump" do
84
+ # __ :height => "100%", :width => "30", :background_color => :brown
85
+ # branch :height => "100", :width => "20"
86
+ # branch do
87
+ # __ :height => "100", :width => "20"
88
+ # end
89
+ # end
90
+ #
91
+ # In the above example, the 'tree' prop has the following initialization options: id, height, width, background_color.
92
+ # The two 'branch' child props are identical.
93
+ #
94
+ def __(options)
95
+ @__prop__.add_options(options)
96
+ end
97
+
98
+ # Installs props from another file using the prop DSL. The path will be relative to the
99
+ # root directory of the current production.
100
+ #
101
+ def __install(file, instance_variables = {})
102
+ raise "Cannot install external props because no loader was provided" if @__loader__.nil?
103
+ raise "External prop file: '#{file}' doesn't exist" if !@__loader__.exists?(file)
104
+ content = @__loader__.load(file)
105
+ begin
106
+ self.__install_instance_variables(instance_variables)
107
+ self.instance_eval(content)
108
+ rescue Exception => e
109
+ raise BuildException.new(file, content, e)
110
+ end
111
+ end
112
+
113
+ # Installs instance variables, specified by the passed hash, into the PropBuilder instance.
114
+ # The following call...
115
+ #
116
+ # __install_instance_variables :one => "1", "two" => "two", :three => 3
117
+ #
118
+ # ...will result in the following instance variables.
119
+ #
120
+ # @one = "1"
121
+ # @two = "2"
122
+ # @three = 3
123
+ #
124
+ # Instance variables are propogated to nested builders so that they need only be defined
125
+ # on the top level builder and all children will have access to them.
126
+ #
127
+ def __install_instance_variables(instance_variables)
128
+ return if instance_variables.nil?
129
+ instance_variables.each_pair do |key, value|
130
+ name = "@#{key}"
131
+ __instance_variable_set(name, value)
132
+ end
133
+ end
134
+
135
+ def __install_instance_variables_from_builder(source) #:nodoc:
136
+ source.__instance_variables.each do |name|
137
+ if !__instance_variable_get(name)
138
+ value = source.__instance_variable_get(name)
139
+ __instance_variable_set(name, value)
140
+ end
141
+ end
142
+ end
143
+
144
+ def method_missing(sym, options={}, &prop) # :nodoc:
145
+ options[:name] ||= sym.to_s
146
+ builder = PropBuilder.new(options)
147
+ builder.__install_instance_variables_from_builder(self)
148
+ builder.__loader__ = @__loader__
149
+ builder.instance_eval(&prop) if prop
150
+ @__prop__.add(builder.__prop__)
151
+ end
152
+ end
153
+
154
+ end
155
+ end