glimmer 0.5.11 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.markdown +129 -15
  3. data/lib/glimmer.rb +13 -1
  4. data/lib/glimmer/css/rule_set.rb +27 -0
  5. data/lib/glimmer/css/style_sheet.rb +20 -0
  6. data/lib/glimmer/dsl/css/css_expression.rb +21 -0
  7. data/lib/glimmer/dsl/css/dsl.rb +10 -0
  8. data/lib/glimmer/dsl/css/p_expression.rb +25 -0
  9. data/lib/glimmer/dsl/css/property_expression.rb +22 -0
  10. data/lib/glimmer/dsl/css/rule_set_expression.rb +25 -0
  11. data/lib/glimmer/dsl/css/s_expression.rb +26 -0
  12. data/lib/glimmer/dsl/engine.rb +90 -18
  13. data/lib/glimmer/dsl/expression.rb +9 -4
  14. data/lib/glimmer/dsl/static_expression.rb +13 -13
  15. data/lib/glimmer/dsl/swt/async_exec_expression.rb +14 -0
  16. data/lib/glimmer/dsl/swt/bind_expression.rb +37 -0
  17. data/lib/glimmer/dsl/swt/color_expression.rb +17 -0
  18. data/lib/glimmer/dsl/swt/column_properties_expression.rb +24 -0
  19. data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +42 -0
  20. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +36 -0
  21. data/lib/glimmer/dsl/swt/data_binding_expression.rb +34 -0
  22. data/lib/glimmer/dsl/swt/display_expression.rb +19 -0
  23. data/lib/glimmer/dsl/swt/dsl.rb +26 -0
  24. data/lib/glimmer/dsl/swt/exec_expression.rb +28 -0
  25. data/lib/glimmer/dsl/swt/layout_data_expression.rb +25 -0
  26. data/lib/glimmer/dsl/swt/layout_expression.rb +27 -0
  27. data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +44 -0
  28. data/lib/glimmer/dsl/swt/menu_bar_expression.rb +33 -0
  29. data/lib/glimmer/dsl/swt/menu_expression.rb +32 -0
  30. data/lib/glimmer/dsl/swt/observe_expression.rb +32 -0
  31. data/lib/glimmer/dsl/swt/property_expression.rb +22 -0
  32. data/lib/glimmer/dsl/swt/rgb_expression.rb +12 -0
  33. data/lib/glimmer/dsl/swt/rgba_expression.rb +12 -0
  34. data/lib/glimmer/dsl/swt/shell_expression.rb +20 -0
  35. data/lib/glimmer/dsl/swt/swt_expression.rb +25 -0
  36. data/lib/glimmer/dsl/swt/sync_exec_expression.rb +15 -0
  37. data/lib/glimmer/dsl/swt/tab_item_expression.rb +33 -0
  38. data/lib/glimmer/dsl/swt/table_items_data_binding_expression.rb +31 -0
  39. data/lib/glimmer/dsl/swt/tree_items_data_binding_expression.rb +31 -0
  40. data/lib/glimmer/dsl/swt/tree_properties_expression.rb +26 -0
  41. data/lib/glimmer/dsl/swt/widget_expression.rb +27 -0
  42. data/lib/glimmer/dsl/swt/widget_listener_expression.rb +32 -0
  43. data/lib/glimmer/dsl/top_level_expression.rb +7 -0
  44. data/lib/glimmer/dsl/xml/dsl.rb +11 -0
  45. data/lib/glimmer/dsl/xml/html_expression.rb +25 -0
  46. data/lib/glimmer/dsl/xml/meta_expression.rb +23 -0
  47. data/lib/glimmer/dsl/xml/name_space_expression.rb +37 -0
  48. data/lib/glimmer/dsl/xml/node_parent_expression.rb +33 -0
  49. data/lib/glimmer/dsl/xml/tag_expression.rb +29 -0
  50. data/lib/glimmer/dsl/xml/text_expression.rb +22 -0
  51. data/lib/glimmer/dsl/xml/xml_expression.rb +21 -0
  52. data/lib/glimmer/rake_task.rb +1 -1
  53. data/lib/glimmer/swt/shell_proxy.rb +1 -2
  54. data/lib/glimmer/swt/widget_proxy.rb +6 -3
  55. data/lib/glimmer/ui/custom_widget.rb +8 -4
  56. data/lib/glimmer/ui/video.rb +31 -28
  57. data/lib/glimmer/xml/depth_first_search_iterator.rb +22 -0
  58. data/lib/glimmer/xml/name_space_visitor.rb +21 -0
  59. data/lib/glimmer/xml/node.rb +75 -0
  60. data/lib/glimmer/xml/node_visitor.rb +13 -0
  61. data/lib/glimmer/xml/xml_visitor.rb +65 -0
  62. data/samples/gladiator.rb +52 -12
  63. metadata +55 -31
  64. data/lib/glimmer/dsl.rb +0 -26
  65. data/lib/glimmer/dsl/async_exec_expression.rb +0 -12
  66. data/lib/glimmer/dsl/bind_expression.rb +0 -35
  67. data/lib/glimmer/dsl/color_expression.rb +0 -22
  68. data/lib/glimmer/dsl/column_properties_expression.rb +0 -22
  69. data/lib/glimmer/dsl/combo_selection_data_binding_expression.rb +0 -40
  70. data/lib/glimmer/dsl/custom_widget_expression.rb +0 -33
  71. data/lib/glimmer/dsl/data_binding_expression.rb +0 -32
  72. data/lib/glimmer/dsl/display_expression.rb +0 -14
  73. data/lib/glimmer/dsl/exec_expression.rb +0 -23
  74. data/lib/glimmer/dsl/layout_data_expression.rb +0 -23
  75. data/lib/glimmer/dsl/layout_expression.rb +0 -25
  76. data/lib/glimmer/dsl/list_selection_data_binding_expression.rb +0 -42
  77. data/lib/glimmer/dsl/menu_bar_expression.rb +0 -31
  78. data/lib/glimmer/dsl/menu_expression.rb +0 -30
  79. data/lib/glimmer/dsl/observe_expression.rb +0 -27
  80. data/lib/glimmer/dsl/property_expression.rb +0 -20
  81. data/lib/glimmer/dsl/shell_expression.rb +0 -16
  82. data/lib/glimmer/dsl/swt_expression.rb +0 -23
  83. data/lib/glimmer/dsl/sync_exec_expression.rb +0 -13
  84. data/lib/glimmer/dsl/tab_item_expression.rb +0 -31
  85. data/lib/glimmer/dsl/table_items_data_binding_expression.rb +0 -29
  86. data/lib/glimmer/dsl/tree_items_data_binding_expression.rb +0 -29
  87. data/lib/glimmer/dsl/tree_properties_expression.rb +0 -24
  88. data/lib/glimmer/dsl/widget_expression.rb +0 -25
  89. data/lib/glimmer/dsl/widget_listener_expression.rb +0 -30
@@ -1,4 +1,6 @@
1
1
  require 'glimmer/error'
2
+ require 'glimmer/swt/widget_proxy'
3
+ require 'glimmer/ui/custom_widget'
2
4
 
3
5
  module Glimmer
4
6
  module DSL
@@ -10,6 +12,12 @@ module Glimmer
10
12
  # english versino of Ruby's boolean operations. This allows easy DSL-like
11
13
  # readability of the rules, and easy tagging with pd when troubleshooting.
12
14
  class Expression
15
+ class << self
16
+ def dsl
17
+ @dsl ||= name.split(/::/)[-2].downcase.to_sym
18
+ end
19
+ end
20
+
13
21
  # Checks if it can interpret parameters (subclass must override)
14
22
  def can_interpret?(parent, keyword, *args, &block)
15
23
  raise Error, "#can_interpret? must be implemented by an Expression subclass"
@@ -29,7 +37,7 @@ module Glimmer
29
37
 
30
38
  # Checks if parent object is a widget
31
39
  def widget?(parent)
32
- parent.is_a?(SWT::WidgetProxy) or parent.is_a?(UI::CustomWidget)
40
+ parent.is_a?(Glimmer::SWT::WidgetProxy) or parent.is_a?(Glimmer::UI::CustomWidget)
33
41
  end
34
42
 
35
43
  # Checks if object is a Symbol or a String
@@ -39,6 +47,3 @@ module Glimmer
39
47
  end
40
48
  end
41
49
  end
42
-
43
- require 'glimmer/swt/widget_proxy'
44
- require 'glimmer/ui/custom_widget'
@@ -1,4 +1,6 @@
1
1
  require 'glimmer/error'
2
+ require 'glimmer/dsl/engine'
3
+ require 'glimmer/dsl/expression'
2
4
  require 'glimmer/swt/widget_proxy'
3
5
  require 'glimmer/ui/custom_widget'
4
6
 
@@ -12,20 +14,18 @@ module Glimmer
12
14
  # (not needed if it only checks for keyword)
13
15
  #
14
16
  # StaticExpression subclasses must define `#interpret`.
17
+ #
18
+ # The direct parent namespace of a StaticExpression subclass must match the DSL name (case-insensitive)
19
+ # (e.g. Glimmer::DSL::SWT::WidgetExpression has a DSL of :swt)
15
20
  class StaticExpression < Expression
16
- def self.inherited(base)
17
- keyword = base.name.split(/::/).last.sub(/Expression$/, '').underscore
18
- static_expression = base.new
19
- Glimmer.define_method(keyword) do |*args, &block|
20
- parent = Glimmer::DSL::Engine.current_parent
21
- if !static_expression.can_interpret?(parent, keyword, *args, &block)
22
- raise Error, "Invalid use of Glimmer keyword #{keyword} with args #{args} under parent #{parent}"
23
- else
24
- Glimmer.logger&.debug "#{base.name} will handle expression keyword #{keyword}"
25
- static_expression.interpret(parent, keyword, *args, &block).tap do |ui_object|
26
- Glimmer::DSL::Engine.add_content(ui_object, static_expression, &block) unless block.nil?
27
- end
28
- end
21
+ class << self
22
+ def inherited(base)
23
+ Glimmer::DSL::Engine.add_static_expression(base.new)
24
+ super
25
+ end
26
+
27
+ def keyword
28
+ @keyword ||= name.split(/::/).last.sub(/Expression$/, '').underscore
29
29
  end
30
30
  end
31
31
 
@@ -0,0 +1,14 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/swt/exec_expression'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ module SWT
7
+ # Asynchronously executes code block against the SWT Event Loop
8
+ # to manipulate SWT UI objects on the UI thread safely
9
+ class AsyncExecExpression < StaticExpression
10
+ include ExecExpression
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,37 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ module SWT
7
+ # Responsible for setting up the return value of the bind keyword (command symbol)
8
+ # as a ModelBinding. It is then used by another command handler like
9
+ # DataBindingCommandHandler for text and selection properties on Text and Spinner
10
+ # or TableItemsDataBindingCommandHandler for items in a Table
11
+ class BindExpression < StaticExpression
12
+ def can_interpret?(parent, keyword, *args, &block)
13
+ (
14
+ keyword == 'bind' and
15
+ (
16
+ (
17
+ (args.size == 2) and
18
+ textual?(args[1])
19
+ ) ||
20
+ (
21
+ (args.size == 3) and
22
+ textual?(args[1]) and
23
+ (args[2].is_a?(Hash))
24
+ )
25
+ )
26
+ )
27
+ end
28
+
29
+ def interpret(parent, keyword, *args, &block)
30
+ binding_options = args[2] || {}
31
+ binding_options[:on_read] = binding_options.delete(:on_read) || binding_options.delete('on_read') || block
32
+ DataBinding::ModelBinding.new(args[0], args[1].to_s, binding_options)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/swt/color_proxy'
3
+ require 'glimmer/swt/display_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module SWT
8
+ class ColorExpression < StaticExpression
9
+ include_package 'org.eclipse.swt.widgets'
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::SWT::ColorProxy.new(*args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ require 'glimmer/dsl/static_expression'
2
+
3
+ module Glimmer
4
+ module DSL
5
+ module SWT
6
+ # Responsible for providing a readable keyword (command symbol) to capture
7
+ # and return column properties for use in TreeItemsDataBindingCommandHandler
8
+ class ColumnPropertiesExpression < StaticExpression
9
+ include_package 'org.eclipse.swt.widgets'
10
+
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ keyword == 'column_properties' and
13
+ block.nil? and
14
+ widget?(parent) and
15
+ parent.swt_widget.is_a?(Table)
16
+ end
17
+
18
+ def interpret(parent, keyword, *args, &block)
19
+ args
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
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
+ module SWT
8
+ class ComboSelectionDataBindingExpression < Expression
9
+ include_package 'org.eclipse.swt.widgets'
10
+
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ keyword == 'selection' and
13
+ block.nil? and
14
+ widget?(parent) and
15
+ parent.swt_widget.is_a?(Combo) and
16
+ args.size == 1 and
17
+ args[0].is_a?(DataBinding::ModelBinding) and
18
+ args[0].evaluate_options_property.is_a?(Array)
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ model_binding = args[0]
23
+
24
+ #TODO make this options observer dependent and all similar observers in widget specific data binding handlers
25
+ # TODO consider delegating some of this work
26
+ widget_binding = DataBinding::WidgetBinding.new(parent, 'items')
27
+ widget_binding.call(model_binding.evaluate_options_property)
28
+ model = model_binding.base_model
29
+ widget_binding.observe(model, model_binding.options_property_name)
30
+
31
+ widget_binding = DataBinding::WidgetBinding.new(parent, 'text')
32
+ widget_binding.call(model_binding.evaluate_property)
33
+ widget_binding.observe(model, model_binding.property_name_expression)
34
+
35
+ parent.on_widget_selected do
36
+ model_binding.call(widget_binding.evaluate_property)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,36 @@
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
+
7
+ module Glimmer
8
+ module DSL
9
+ module SWT
10
+ class CustomWidgetExpression < Expression
11
+ include ParentExpression
12
+
13
+ def can_interpret?(parent, keyword, *args, &block)
14
+ custom_widget_class = UI::CustomWidget.for(keyword)
15
+ custom_widget_class and
16
+ (widget?(parent) or
17
+ custom_widget_class.ancestors.include?(UI::CustomShell))
18
+ end
19
+
20
+ def interpret(parent, keyword, *args, &block)
21
+ options = args.last.is_a?(Hash) ? args.pop : {}
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
36
+ end
@@ -0,0 +1,34 @@
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
+ module SWT
8
+ # Responsible for wiring two-way data-binding for text and selection properties
9
+ # on Text, Button, and Spinner widgets.
10
+ # Does so by using the output of the bind(model, property) command in the form
11
+ # of a ModelBinding, which is then connected to an anonymous widget observer
12
+ # (aka widget_data_binder as per widget_data_binders array)
13
+ #
14
+ # Depends on BindCommandHandler
15
+ class DataBindingExpression < Expression
16
+ def can_interpret?(parent, keyword, *args, &block)
17
+ args.size == 1 and
18
+ args[0].is_a?(DataBinding::ModelBinding)
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) if parent.respond_to?(:add_observer, [model_binding, keyword])
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/dsl/top_level_expression'
4
+ require 'glimmer/swt/display_proxy'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module SWT
9
+ class DisplayExpression < StaticExpression
10
+ include TopLevelExpression
11
+ include ParentExpression
12
+
13
+ def interpret(parent, keyword, *args, &block)
14
+ Glimmer::SWT::DisplayProxy.instance(*args)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'glimmer/dsl/engine'
2
+ Dir[File.expand_path('../*_expression.rb', __FILE__)].each {|f| require f}
3
+
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
+
9
+ # Every expression has a corresponding Expression subclass
10
+ # in glimmer/dsl
11
+
12
+ Glimmer::DSL::Engine.add_dynamic_expressions(
13
+ Glimmer::DSL::SWT,
14
+ %w[
15
+ layout
16
+ widget_listener
17
+ combo_selection_data_binding
18
+ list_selection_data_binding
19
+ tree_items_data_binding
20
+ table_items_data_binding
21
+ data_binding
22
+ property
23
+ widget
24
+ custom_widget
25
+ ]
26
+ )
@@ -0,0 +1,28 @@
1
+ require 'glimmer/dsl/top_level_expression'
2
+ require 'glimmer/swt/display_proxy'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ module SWT
7
+ # Mixin for common code in async_exec and sync_exec expressions
8
+ # Uses name in subclass to auto-derive exec_operation
9
+ module ExecExpression
10
+ include TopLevelExpression
11
+
12
+ def exec_operation
13
+ @exec_operation ||= self.class.name.split(/::/).last.sub(/Expression$/, '').underscore
14
+ end
15
+
16
+ def can_interpret?(parent, keyword, *args, &block)
17
+ keyword == exec_operation and
18
+ block_given? and
19
+ args.empty?
20
+ end
21
+
22
+ def interpret(parent, keyword, *args, &block)
23
+ Glimmer::SWT::DisplayProxy.instance.send(exec_operation, &block)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ require 'glimmer'
2
+ require 'glimmer/dsl/static_expression'
3
+ require 'glimmer/dsl/parent_expression'
4
+ require 'glimmer/swt/layout_data_proxy'
5
+
6
+ # TODO consider turning static keywords like layout_data into methods
7
+
8
+ module Glimmer
9
+ module DSL
10
+ module SWT
11
+ class LayoutDataExpression < StaticExpression
12
+ include ParentExpression
13
+
14
+ def can_interpret?(parent, keyword, *args, &block)
15
+ keyword == 'layout_data' and
16
+ widget?(parent)
17
+ end
18
+
19
+ def interpret(parent, keyword, *args, &block)
20
+ Glimmer::SWT::LayoutDataProxy.new(parent, args)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ require 'glimmer'
2
+ require 'glimmer/dsl/expression'
3
+ require 'glimmer/dsl/parent_expression'
4
+ require 'glimmer/swt/layout_proxy'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module SWT
9
+ class LayoutExpression < Expression
10
+ include ParentExpression
11
+
12
+ include_package 'org.eclipse.swt.widgets'
13
+
14
+ def can_interpret?(parent, keyword, *args, &block)
15
+ keyword.to_s.end_with?('_layout') and
16
+ widget?(parent) and
17
+ parent.swt_widget.is_a?(Composite) and
18
+ Glimmer::SWT::LayoutProxy.layout_exists?(keyword.to_s)
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ Glimmer::SWT::LayoutProxy.new(keyword, parent, args)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+ require 'glimmer/data_binding/widget_binding'
4
+ require 'glimmer/data_binding/list_selection_binding'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module SWT
9
+ class ListSelectionDataBindingExpression < Expression
10
+ include_package 'org.eclipse.swt.widgets'
11
+
12
+ def can_interpret?(parent, keyword, *args, &block)
13
+ keyword == 'selection' and
14
+ block.nil? and
15
+ widget?(parent) and
16
+ parent.swt_widget.is_a?(List) and
17
+ args.size == 1 and
18
+ args[0].is_a?(DataBinding::ModelBinding) and
19
+ args[0].evaluate_options_property.is_a?(Array)
20
+ end
21
+
22
+ def interpret(parent, keyword, *args, &block)
23
+ model_binding = args[0]
24
+ widget_binding = DataBinding::WidgetBinding.new(parent, 'items')
25
+ widget_binding.call(model_binding.evaluate_options_property)
26
+ model = model_binding.base_model
27
+ #TODO make this options observer dependent and all similar observers in widget specific data binding interpretrs
28
+ widget_binding.observe(model, model_binding.options_property_name)
29
+
30
+ property_type = :string
31
+ property_type = :array if parent.has_style?(:multi)
32
+ list_selection_binding = DataBinding::ListSelectionBinding.new(parent, property_type)
33
+ list_selection_binding.call(model_binding.evaluate_property)
34
+ #TODO check if nested data binding works for list widget and other widgets that need custom data binding
35
+ list_selection_binding.observe(model, model_binding.property_name_expression)
36
+
37
+ parent.on_widget_selected do
38
+ model_binding.call(list_selection_binding.evaluate_property)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end