glimmer 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.markdown +324 -59
  3. data/lib/glimmer.rb +54 -63
  4. data/lib/glimmer/data_binding/list_selection_binding.rb +52 -0
  5. data/lib/glimmer/{swt → data_binding}/model_binding.rb +33 -5
  6. data/lib/glimmer/{swt → data_binding}/observable.rb +6 -3
  7. data/lib/glimmer/{swt → data_binding}/observable_array.rb +3 -1
  8. data/lib/glimmer/{swt → data_binding}/observable_model.rb +3 -2
  9. data/lib/glimmer/data_binding/observable_widget.rb +17 -0
  10. data/lib/glimmer/{swt → data_binding}/observer.rb +3 -3
  11. data/lib/glimmer/{shine.rb → data_binding/shine.rb} +2 -2
  12. data/lib/glimmer/{swt → data_binding}/table_items_binding.rb +12 -11
  13. data/lib/glimmer/{swt → data_binding}/tree_items_binding.rb +15 -12
  14. data/lib/glimmer/{swt → data_binding}/widget_binding.rb +2 -1
  15. data/lib/glimmer/dsl.rb +26 -0
  16. data/lib/glimmer/dsl/async_exec_expression.rb +12 -0
  17. data/lib/glimmer/dsl/bind_expression.rb +44 -0
  18. data/lib/glimmer/dsl/color_expression.rb +28 -0
  19. data/lib/glimmer/dsl/column_properties_expression.rb +22 -0
  20. data/lib/glimmer/dsl/combo_selection_data_binding_expression.rb +40 -0
  21. data/lib/glimmer/dsl/custom_widget_expression.rb +35 -0
  22. data/lib/glimmer/dsl/data_binding_expression.rb +33 -0
  23. data/lib/glimmer/dsl/display_expression.rb +12 -0
  24. data/lib/glimmer/dsl/engine.rb +80 -0
  25. data/lib/glimmer/dsl/exec_expression.rb +23 -0
  26. data/lib/glimmer/dsl/expression.rb +44 -0
  27. data/lib/glimmer/dsl/expression_handler.rb +48 -0
  28. data/lib/glimmer/dsl/layout_data_expression.rb +24 -0
  29. data/lib/glimmer/dsl/layout_expression.rb +26 -0
  30. data/lib/glimmer/dsl/list_selection_data_binding_expression.rb +42 -0
  31. data/lib/glimmer/dsl/observe_expression.rb +27 -0
  32. data/lib/glimmer/dsl/parent_expression.rb +12 -0
  33. data/lib/glimmer/dsl/property_expression.rb +20 -0
  34. data/lib/glimmer/dsl/shell_expression.rb +15 -0
  35. data/lib/glimmer/dsl/static_expression.rb +38 -0
  36. data/lib/glimmer/dsl/swt_expression.rb +23 -0
  37. data/lib/glimmer/dsl/sync_exec_expression.rb +13 -0
  38. data/lib/glimmer/dsl/tab_item_expression.rb +31 -0
  39. data/lib/glimmer/dsl/table_items_data_binding_expression.rb +29 -0
  40. data/lib/glimmer/dsl/tree_items_data_binding_expression.rb +30 -0
  41. data/lib/glimmer/dsl/tree_properties_expression.rb +24 -0
  42. data/lib/glimmer/dsl/widget_expression.rb +26 -0
  43. data/lib/glimmer/dsl/widget_listener_expression.rb +27 -0
  44. data/lib/glimmer/error.rb +6 -0
  45. data/lib/glimmer/invalid_keyword_error.rb +6 -0
  46. data/lib/glimmer/launcher.rb +39 -23
  47. data/lib/glimmer/swt/color_proxy.rb +48 -0
  48. data/lib/glimmer/swt/display_proxy.rb +49 -0
  49. data/lib/glimmer/swt/font_proxy.rb +72 -0
  50. data/lib/glimmer/swt/layout_data_proxy.rb +73 -0
  51. data/lib/glimmer/swt/{g_layout.rb → layout_proxy.rb} +24 -25
  52. data/lib/glimmer/swt/packages.rb +13 -0
  53. data/lib/glimmer/swt/shell_proxy.rb +108 -0
  54. data/lib/glimmer/swt/{g_swt.rb → swt_proxy.rb} +12 -5
  55. data/lib/glimmer/swt/tab_item_proxy.rb +59 -0
  56. data/lib/glimmer/swt/widget_listener_proxy.rb +17 -0
  57. data/lib/glimmer/swt/widget_proxy.rb +366 -0
  58. data/lib/glimmer/{swt → ui}/custom_shell.rb +4 -4
  59. data/lib/glimmer/{swt → ui}/custom_widget.rb +67 -51
  60. data/lib/glimmer/{swt → ui}/video.rb +13 -13
  61. data/lib/glimmer/{swt → util}/proc_tracker.rb +1 -1
  62. data/vendor/swt/linux/swt.jar +0 -0
  63. data/vendor/swt/mac/swt.jar +0 -0
  64. data/vendor/swt/windows/swt.jar +0 -0
  65. metadata +66 -70
  66. data/lib/glimmer/command_handler.rb +0 -15
  67. data/lib/glimmer/command_handler_chain_factory.rb +0 -32
  68. data/lib/glimmer/command_handler_chain_link.rb +0 -25
  69. data/lib/glimmer/command_handlers.rb +0 -46
  70. data/lib/glimmer/ext/module.rb +0 -20
  71. data/lib/glimmer/parent.rb +0 -7
  72. data/lib/glimmer/swt/command_handlers/bind_command_handler.rb +0 -56
  73. data/lib/glimmer/swt/command_handlers/color_command_handler.rb +0 -30
  74. data/lib/glimmer/swt/command_handlers/combo_selection_data_binding_command_handler.rb +0 -44
  75. data/lib/glimmer/swt/command_handlers/custom_widget_command_handler.rb +0 -26
  76. data/lib/glimmer/swt/command_handlers/data_binding_command_handler.rb +0 -40
  77. data/lib/glimmer/swt/command_handlers/display_command_handler.rb +0 -20
  78. data/lib/glimmer/swt/command_handlers/layout_command_handler.rb +0 -27
  79. data/lib/glimmer/swt/command_handlers/layout_data_command_handler.rb +0 -27
  80. data/lib/glimmer/swt/command_handlers/list_selection_data_binding_command_handler.rb +0 -49
  81. data/lib/glimmer/swt/command_handlers/observe_command_handler.rb +0 -35
  82. data/lib/glimmer/swt/command_handlers/property_command_handler.rb +0 -24
  83. data/lib/glimmer/swt/command_handlers/shell_command_handler.rb +0 -20
  84. data/lib/glimmer/swt/command_handlers/tab_item_command_handler.rb +0 -34
  85. data/lib/glimmer/swt/command_handlers/table_column_properties_data_binding_command_handler.rb +0 -29
  86. data/lib/glimmer/swt/command_handlers/table_items_data_binding_command_handler.rb +0 -34
  87. data/lib/glimmer/swt/command_handlers/tree_items_data_binding_command_handler.rb +0 -33
  88. data/lib/glimmer/swt/command_handlers/tree_properties_data_binding_command_handler.rb +0 -29
  89. data/lib/glimmer/swt/command_handlers/widget_command_handler.rb +0 -27
  90. data/lib/glimmer/swt/command_handlers/widget_listener_command_handler.rb +0 -48
  91. data/lib/glimmer/swt/g_color.rb +0 -41
  92. data/lib/glimmer/swt/g_display.rb +0 -36
  93. data/lib/glimmer/swt/g_font.rb +0 -71
  94. data/lib/glimmer/swt/g_layout_data.rb +0 -56
  95. data/lib/glimmer/swt/g_runnable.rb +0 -15
  96. data/lib/glimmer/swt/g_shell.rb +0 -106
  97. data/lib/glimmer/swt/g_tab_item_composite.rb +0 -41
  98. data/lib/glimmer/swt/g_widget.rb +0 -349
  99. data/lib/glimmer/swt/g_widget_listener.rb +0 -12
  100. data/lib/glimmer/swt/list_selection_binding.rb +0 -47
  101. data/lib/glimmer/swt_packages.rb +0 -15
  102. data/lib/glimmer/xml/command_handlers/html_command_handler.rb +0 -50
  103. data/lib/glimmer/xml/command_handlers/xml_command_handler.rb +0 -23
  104. data/lib/glimmer/xml/command_handlers/xml_name_space_command_handler.rb +0 -36
  105. data/lib/glimmer/xml/command_handlers/xml_tag_command_handler.rb +0 -28
  106. data/lib/glimmer/xml/command_handlers/xml_text_command_handler.rb +0 -24
  107. data/lib/glimmer/xml/depth_first_search_iterator.rb +0 -20
  108. data/lib/glimmer/xml/name_space_visitor.rb +0 -21
  109. data/lib/glimmer/xml/node.rb +0 -84
  110. data/lib/glimmer/xml/node_visitor.rb +0 -13
  111. data/lib/glimmer/xml/xml_visitor.rb +0 -63
  112. data/lib/glimmer/xml_command_handlers.rb +0 -18
@@ -8,8 +8,8 @@
8
8
  # alias original_compare <=>
9
9
  #
10
10
  # def <=>(other)
11
- # if (self[0].class.name == "GWidget")
12
- # add_contents(self[0]) {
11
+ # if (self[0].class.name == "WidgetProxy")
12
+ # content(self[0]) {
13
13
  # if (other.size == 2)
14
14
  # eval("#{self[1]} bind (other[0], other[1])")
15
15
  # elsif (other.size == 3)
@@ -1,14 +1,14 @@
1
- require_relative 'observable_array'
2
- require_relative 'observable_model'
3
- require_relative 'observable'
4
- require_relative 'observer'
1
+ require 'glimmer/data_binding/observable_array'
2
+ require 'glimmer/data_binding/observable_model'
3
+ require 'glimmer/data_binding/observable'
4
+ require 'glimmer/data_binding/observer'
5
+ require 'glimmer/swt/swt_proxy'
5
6
 
6
7
  module Glimmer
7
- module SWT
8
+ module DataBinding
8
9
  class TableItemsBinding
9
- include Glimmer
10
- include Observable
11
- include Observer
10
+ include DataBinding::Observable
11
+ include DataBinding::Observer
12
12
  include_package 'org.eclipse.swt'
13
13
  include_package 'org.eclipse.swt.widgets'
14
14
 
@@ -23,6 +23,7 @@ module Glimmer
23
23
  unregister_all_observables
24
24
  end
25
25
  end
26
+
26
27
  def call(model_collection=nil)
27
28
  if model_collection and model_collection.is_a?(Array)
28
29
  observe(model_collection, @column_properties)
@@ -30,16 +31,16 @@ module Glimmer
30
31
  end
31
32
  populate_table(@model_collection, @table, @column_properties)
32
33
  end
34
+
33
35
  def populate_table(model_collection, parent, column_properties)
34
- parent.widget.removeAll
36
+ parent.swt_widget.removeAll
35
37
  model_collection.each do |model|
36
- table_item = TableItem.new(parent.widget, GSWT[:none])
38
+ table_item = TableItem.new(parent.swt_widget, SWT::SWTProxy[:none])
37
39
  for index in 0..(column_properties.size-1)
38
40
  table_item.setText(index, model.send(column_properties[index]).to_s)
39
41
  end
40
42
  end
41
43
  end
42
-
43
44
  end
44
45
  end
45
46
  end
@@ -1,14 +1,15 @@
1
- require_relative 'observable_array'
2
- require_relative 'observable_model'
3
- require_relative 'observable'
4
- require_relative 'observer'
1
+ require 'glimmer/data_binding/observable_array'
2
+ require 'glimmer/data_binding/observable_model'
3
+ require 'glimmer/data_binding/observable'
4
+ require 'glimmer/data_binding/observer'
5
+ require 'glimmer/swt/swt_proxy'
5
6
 
6
7
  module Glimmer
7
- module SWT
8
+ module DataBinding
8
9
  class TreeItemsBinding
9
- include Glimmer
10
- include Observable
11
- include Observer
10
+ include DataBinding::Observable
11
+ include DataBinding::Observer
12
+
12
13
  include_package 'org.eclipse.swt'
13
14
  include_package 'org.eclipse.swt.widgets'
14
15
 
@@ -23,6 +24,7 @@ module Glimmer
23
24
  unregister_all_observables
24
25
  end
25
26
  end
27
+
26
28
  def call(model_tree_root_node=nil)
27
29
  if model_tree_root_node and model_tree_root_node.respond_to?(@tree_properties[:children])
28
30
  observe(model_tree_root_node, @tree_properties[:text])
@@ -31,19 +33,20 @@ module Glimmer
31
33
  end
32
34
  populate_tree(@model_tree_root_node, @tree, @tree_properties)
33
35
  end
36
+
34
37
  def populate_tree(model_tree_root_node, parent, tree_properties)
35
- parent.widget.removeAll
36
- populate_tree_node(model_tree_root_node, parent.widget, tree_properties)
38
+ parent.swt_widget.removeAll
39
+ populate_tree_node(model_tree_root_node, parent.swt_widget, tree_properties)
37
40
  end
41
+
38
42
  def populate_tree_node(model_tree_node, parent, tree_properties)
39
- table_item = TreeItem.new(parent, GSWT[:none])
43
+ table_item = TreeItem.new(parent, SWT::SWTProxy[:none])
40
44
  table_item.setText((model_tree_node && model_tree_node.send(tree_properties[:text])).to_s)
41
45
  [model_tree_node && model_tree_node.send(tree_properties[:children])].flatten.to_a.compact.each do |child|
42
46
  observe(child, @tree_properties[:text])
43
47
  populate_tree_node(child, table_item, tree_properties)
44
48
  end
45
49
  end
46
-
47
50
  end
48
51
  end
49
52
  end
@@ -1,8 +1,9 @@
1
+ require 'glimmer'
1
2
  require_relative 'observable'
2
3
  require_relative 'observer'
3
4
 
4
5
  module Glimmer
5
- module SWT
6
+ module DataBinding
6
7
  class WidgetBinding
7
8
  include Glimmer
8
9
  include Observable
@@ -0,0 +1,26 @@
1
+ require 'glimmer/dsl/engine'
2
+
3
+ module Glimmer
4
+ # Glimmer DSL expression configuration module
5
+ #
6
+ # When DSL engine interprets an expression, it attempts to handle
7
+ # with expressions listed here in the order specified.
8
+ module DSL
9
+ # Every expression has a corresponding AbstractExpression subclass
10
+ # in glimmer/dsl
11
+ # TODO rename to dynamic_expressions in the future when supporting static expressions
12
+ Engine.dynamic_expressions = %w[
13
+ layout
14
+ widget_listener
15
+ combo_selection_data_binding
16
+ list_selection_data_binding
17
+ tree_items_data_binding
18
+ table_items_data_binding
19
+ data_binding
20
+ color
21
+ property
22
+ widget
23
+ custom_widget
24
+ ]
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/exec_expression'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ # Asynchronously executes code block against the SWT Event Loop
7
+ # to manipulate SWT UI objects on the UI thread safely
8
+ class AsyncExecExpression < StaticExpression
9
+ include ExecExpression
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ # Responsible for setting up the return value of the bind keyword (command symbol)
7
+ # as a ModelBinding. It is then used by another command handler like
8
+ # DataBindingCommandHandler for text and selection properties on Text and Spinner
9
+ # or TableItemsDataBindingCommandHandler for items in a Table
10
+ class BindExpression < StaticExpression
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ (
13
+ keyword == 'bind' and
14
+ block.nil? and
15
+ widget?(parent) and
16
+ (
17
+ (
18
+ (args.size == 2) and
19
+ textual?(args[1])
20
+ ) ||
21
+ (
22
+ (args.size == 3) and
23
+ textual?(args[1]) and
24
+ (textual?(args[2]) or args[2].is_a?(Hash))
25
+ ) ||
26
+ (
27
+ (args.size == 4) and
28
+ textual?(args[1]) and
29
+ textual?(args[2]) and
30
+ (args[3].is_a?(Hash))
31
+ )
32
+ )
33
+ )
34
+ end
35
+
36
+ def interpret(parent, keyword, *args, &block)
37
+ property_type = args[2] if (args.size == 3) and !args[2].is_a?(Hash)
38
+ binding_options = args[2] if args[2].is_a?(Hash)
39
+ binding_options = args[3] if args[3].is_a?(Hash)
40
+ DataBinding::ModelBinding.new(args[0], args[1].to_s, property_type, binding_options)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,28 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/swt/color_proxy'
3
+ require 'glimmer/swt/display_proxy'
4
+
5
+ # TODO consider turning static keywords like rgba/rgb into methods
6
+ # Support color keyword
7
+
8
+ module Glimmer
9
+ module DSL
10
+ class ColorExpression < Expression
11
+ include_package 'org.eclipse.swt.widgets'
12
+
13
+ def can_interpret?(parent, keyword, *args, &block)
14
+ ['color', 'rgba', 'rgb'].include?(keyword) and
15
+ (1..4).include?(args.count)
16
+ end
17
+
18
+ def interpret(parent, keyword, *args, &block)
19
+ if args.first.is_a?(Display) or args.first.nil?
20
+ display = args.delete_at(0)
21
+ else
22
+ display = SWT::DisplayProxy.instance.swt_display
23
+ end
24
+ SWT::ColorProxy.new(*args)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ require 'glimmer/dsl/static_expression'
2
+
3
+ module Glimmer
4
+ module DSL
5
+ # Responsible for providing a readable keyword (command symbol) to capture
6
+ # and return column properties for use in TreeItemsDataBindingCommandHandler
7
+ class ColumnPropertiesExpression < StaticExpression
8
+ include_package 'org.eclipse.swt.widgets'
9
+
10
+ def can_interpret?(parent, keyword, *args, &block)
11
+ keyword == 'column_properties' and
12
+ block.nil? and
13
+ widget?(parent) and
14
+ parent.swt_widget.is_a?(Table)
15
+ end
16
+
17
+ def interpret(parent, keyword, *args, &block)
18
+ args
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,40 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+ require 'glimmer/data_binding/widget_binding'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ class ComboSelectionDataBindingExpression < Expression
8
+ include_package 'org.eclipse.swt.widgets'
9
+
10
+ def can_interpret?(parent, keyword, *args, &block)
11
+ keyword == 'selection' and
12
+ block.nil? and
13
+ widget?(parent) and
14
+ parent.swt_widget.is_a?(Combo) and
15
+ args.size == 1 and
16
+ args[0].is_a?(DataBinding::ModelBinding) and
17
+ args[0].evaluate_options_property.is_a?(Array)
18
+ end
19
+
20
+ def interpret(parent, keyword, *args, &block)
21
+ model_binding = args[0]
22
+
23
+ #TODO make this options observer dependent and all similar observers in widget specific data binding handlers
24
+ # TODO consider delegating some of this work
25
+ widget_binding = DataBinding::WidgetBinding.new(parent, 'items')
26
+ widget_binding.call(model_binding.evaluate_options_property)
27
+ model = model_binding.base_model
28
+ widget_binding.observe(model, model_binding.options_property_name)
29
+
30
+ widget_binding = DataBinding::WidgetBinding.new(parent, 'text')
31
+ widget_binding.call(model_binding.evaluate_property)
32
+ widget_binding.observe(model, model_binding.property_name_expression)
33
+
34
+ parent.on_widget_selected do
35
+ model_binding.call(widget_binding.evaluate_property)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,35 @@
1
+ require 'glimmer'
2
+ require 'glimmer/dsl/expression'
3
+ require 'glimmer/dsl/parent_expression'
4
+ require 'glimmer/ui/custom_widget'
5
+ require 'glimmer/ui/custom_shell'
6
+ require 'glimmer/ui/video' # this is interpreted here since it's a custom widget
7
+
8
+ module Glimmer
9
+ module DSL
10
+ class CustomWidgetExpression < Expression
11
+ include ParentExpression
12
+ def can_interpret?(parent, keyword, *args, &block)
13
+ custom_widget_class = UI::CustomWidget.for(keyword)
14
+ custom_widget_class and
15
+ (widget?(parent) or
16
+ custom_widget_class.ancestors.include?(UI::CustomShell))
17
+ end
18
+
19
+ def interpret(parent, keyword, *args, &block)
20
+ options = args.last.is_a?(Hash) ? args.pop : {}
21
+ Glimmer.logger.debug "Custom widget #{keyword} styles are: [" + args.inspect + "] and options are: #{options}"
22
+ UI::CustomWidget.for(keyword).new(parent, *args, options, &block)
23
+ end
24
+
25
+ def add_content(parent, &block)
26
+ # TODO consider avoiding source_location
27
+ if block.source_location == parent.content&.__getobj__.source_location
28
+ parent.content.call(parent) unless parent.content.called?
29
+ else
30
+ super
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+ require 'glimmer/data_binding/widget_binding'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ # Responsible for wiring two-way data-binding for text and selection properties
8
+ # on Text, Button, and Spinner widgets.
9
+ # Does so by using the output of the bind(model, property) command in the form
10
+ # of a ModelBinding, which is then connected to an anonymous widget observer
11
+ # (aka widget_data_binder as per widget_data_binders array)
12
+ #
13
+ # Depends on BindCommandHandler
14
+ class DataBindingExpression < Expression
15
+ def can_interpret?(parent, keyword, *args, &block)
16
+ args.size == 1 and
17
+ args[0].is_a?(DataBinding::ModelBinding) and
18
+ widget?(parent)
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ model_binding = args[0]
23
+ widget_binding_parameters = [parent, keyword]
24
+ widget_binding = DataBinding::WidgetBinding.new(*widget_binding_parameters)
25
+ widget_binding.call(model_binding.evaluate_property)
26
+ #TODO make this options observer dependent and all similar observers in widget specific data binding handlers
27
+ widget_binding.observe(model_binding)
28
+ # TODO simplify this logic and put it where it belongs
29
+ parent.add_observer(model_binding, keyword)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/swt/display_proxy'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ class DisplayExpression < StaticExpression
7
+ def interpret(parent, keyword, *args, &block)
8
+ SWT::DisplayProxy.instance(*args)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,80 @@
1
+ require 'glimmer'
2
+ Dir[File.expand_path('../*_expression.rb', __FILE__)].each {|f| require f}
3
+ require 'glimmer/dsl/expression_handler'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ # Glimmer DSL Engine
8
+ #
9
+ # Follows Interpreter and Chain of Responsibility Design Patterns
10
+ #
11
+ # When DSL engine interprets an expression, it attempts to handle
12
+ # with ordered expression array specified via `.expressions=` method.
13
+ #
14
+ # TODO support auto-loading static_expressions in the future for expressions where
15
+ # the keyword does not vary dynamically. These static keywords are then
16
+ # predefined as methods in Glimmer instead of needing method_missing
17
+ class Engine
18
+ class << self
19
+ # Sets an ordered array of DSL expressions to support
20
+ #
21
+ # Every expression has an underscored name corresponding to an upper
22
+ # camelcase AbstractExpression subclass name in glimmer/dsl
23
+ #
24
+ # They are used in order following the Chain of Responsibility Design
25
+ # Pattern when interpretting a DSL expression
26
+ #
27
+ # TODO rename to dynamic_expressions in the future when supporting static expressions
28
+ def dynamic_expressions=(expression_names)
29
+ @dynamic_expression_chain_of_responsibility = expression_names.reverse.reduce(nil) do |last_expresion_handler, expression_name|
30
+ Glimmer.logger.debug "Loading #{expression_class_name(expression_name)}..."
31
+ expression = expression_class(expression_name).new
32
+ expression_handler = ExpressionHandler.new(expression)
33
+ expression_handler.next = last_expresion_handler if last_expresion_handler
34
+ expression_handler
35
+ end
36
+ end
37
+
38
+ def expression_class(expression_name)
39
+ DSL.const_get(expression_class_name(expression_name).to_sym)
40
+ end
41
+
42
+ def expression_class_name(expression_name)
43
+ "#{expression_name}_expression".camelcase(:upper)
44
+ end
45
+
46
+ # Interprets Glimmer DSL keyword, args, and block (e.g. shell(:no_resize) { ... })
47
+ def interpret(keyword, *args, &block)
48
+ keyword = keyword.to_s
49
+ expression = @dynamic_expression_chain_of_responsibility.handle(current_parent, keyword, *args, &block)
50
+ expression.interpret(current_parent, keyword, *args, &block).tap do |ui_object|
51
+ add_content(ui_object, expression, &block)
52
+ end
53
+ end
54
+
55
+ # Adds content block to parent UI object
56
+ #
57
+ # This allows evaluating parent UI object properties and children
58
+ #
59
+ # For example, a shell widget would get properties set and children added
60
+ def add_content(parent, expression, &block)
61
+ parent_stack.push(parent)
62
+ expression.add_content(parent, &block) if block_given?
63
+ parent_stack.pop
64
+ end
65
+
66
+ # Current parent while evaluating Glimmer DSL (nil if just started or done evaluatiing)
67
+ #
68
+ # Parents are maintained in a stack while evaluating Glimmer DSL
69
+ # to ensure properly ordered interpretation of DSL syntax
70
+ def current_parent
71
+ parent_stack.last
72
+ end
73
+
74
+ def parent_stack
75
+ @parent_stack ||= []
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end