glimmer-dsl-opal 0.0.2 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +704 -40
  3. data/VERSION +1 -1
  4. data/lib/glimmer-dsl-opal.rb +3 -2
  5. data/lib/glimmer/data_binding/element_binding.rb +1 -1
  6. data/lib/glimmer/data_binding/ext/observable_model.rb +40 -0
  7. data/lib/glimmer/data_binding/list_selection_binding.rb +51 -0
  8. data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
  9. data/lib/glimmer/dsl/opal/browser_expression.rb +17 -0
  10. data/lib/glimmer/dsl/opal/button_expression.rb +1 -0
  11. data/lib/glimmer/dsl/opal/dsl.rb +15 -1
  12. data/lib/glimmer/dsl/opal/grid_layout_expression.rb +17 -0
  13. data/lib/glimmer/dsl/opal/layout_data_expression.rb +17 -0
  14. data/lib/glimmer/dsl/opal/list_expression.rb +17 -0
  15. data/lib/glimmer/dsl/opal/list_selection_data_binding_expression.rb +42 -0
  16. data/lib/glimmer/dsl/opal/message_box_expression.rb +20 -0
  17. data/lib/glimmer/dsl/opal/observe_expression.rb +32 -0
  18. data/lib/glimmer/dsl/opal/property_expression.rb +6 -2
  19. data/lib/glimmer/dsl/opal/tab_folder_expression.rb +17 -0
  20. data/lib/glimmer/dsl/opal/tab_item_expression.rb +17 -0
  21. data/lib/glimmer/dsl/opal/text_expression.rb +22 -0
  22. data/lib/glimmer/opal/display_proxy.rb +23 -0
  23. data/lib/glimmer/opal/div_proxy.rb +9 -1
  24. data/lib/glimmer/opal/document_proxy.rb +131 -5
  25. data/lib/glimmer/opal/element_proxy.rb +246 -11
  26. data/lib/glimmer/opal/grid_layout_proxy.rb +54 -0
  27. data/lib/glimmer/opal/iframe_proxy.rb +23 -0
  28. data/lib/glimmer/opal/input_proxy.rb +16 -1
  29. data/lib/glimmer/opal/label_proxy.rb +2 -1
  30. data/lib/glimmer/opal/layout_data_proxy.rb +31 -0
  31. data/lib/glimmer/opal/list_proxy.rb +80 -0
  32. data/lib/glimmer/opal/modal.rb +94 -0
  33. data/lib/glimmer/opal/point.rb +5 -0
  34. data/lib/glimmer/opal/property_owner.rb +22 -0
  35. data/lib/glimmer/opal/select_proxy.rb +2 -1
  36. data/lib/glimmer/opal/tab_folder.rb +46 -0
  37. data/lib/glimmer/opal/tab_item.rb +98 -0
  38. data/lib/samples/elaborate/login.rb +0 -1
  39. data/lib/samples/elaborate/tic_tac_toe.rb +5 -5
  40. data/lib/samples/hello/hello_tab.rb +2 -2
  41. metadata +25 -2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.7
@@ -1,5 +1,5 @@
1
1
  require 'opal'
2
- require 'opal-parser'
2
+ require 'opal-async'
3
3
  require 'glimmer'
4
4
 
5
5
  GLIMMER_DSL_OPAL_ROOT = File.expand_path('../..', __FILE__)
@@ -7,4 +7,5 @@ GLIMMER_DSL_OPAL_LIB = File.join(GLIMMER_DSL_OPAL_ROOT, 'lib')
7
7
 
8
8
  $LOAD_PATH.unshift(GLIMMER_DSL_OPAL_LIB)
9
9
 
10
- require 'glimmer/dsl/opal/dsl'
10
+ require 'glimmer/dsl/opal/dsl'
11
+ require 'glimmer/data_binding/ext/observable_model'
@@ -24,7 +24,7 @@ module Glimmer
24
24
 
25
25
  def call(value)
26
26
  converted_value = translated_value = @translator.call(value)
27
- @element.send(@property + '=', converted_value) unless evaluate_property == converted_value
27
+ @element.set_attribute(@property, converted_value) unless evaluate_property == converted_value
28
28
  end
29
29
 
30
30
  def evaluate_property
@@ -0,0 +1,40 @@
1
+ require 'glimmer/data_binding/observable'
2
+ require 'glimmer/data_binding/observer'
3
+ require 'glimmer/opal/display_proxy'
4
+
5
+ # This ensures all data-binding events happen async and block on modal display
6
+
7
+ module Glimmer
8
+ module DataBinding
9
+ # TODO prefix utility methods with double-underscore
10
+ module ObservableModel
11
+ include Observable
12
+ include Glimmer
13
+
14
+ def add_property_writer_observers(property_name)
15
+ property_writer_name = "#{property_name}="
16
+ method(property_writer_name)
17
+ ensure_array_object_observer(property_name, send(property_name))
18
+ begin
19
+ method("__original_#{property_writer_name}")
20
+ rescue
21
+ old_method = self.class.instance_method(property_writer_name)
22
+ define_singleton_method("__original_#{property_writer_name}", old_method)
23
+ define_singleton_method(property_writer_name) do |value|
24
+ old_value = self.send(property_name)
25
+ unregister_dependent_observers(property_name, old_value)
26
+ self.send("__original_#{property_writer_name}", value)
27
+ Glimmer::Opal::DisplayProxy.instance.async_exec do
28
+ notify_observers(property_name)
29
+ ensure_array_object_observer(property_name, value, old_value)
30
+ end
31
+ end
32
+ end
33
+ rescue => e
34
+ # ignore writing if no property writer exists
35
+ Glimmer::Config.logger&.debug "No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,51 @@
1
+ require 'glimmer/data_binding/observable'
2
+ require 'glimmer/data_binding/observer'
3
+
4
+ module Glimmer
5
+ module DataBinding
6
+ # SWT List element selection binding
7
+ class ListSelectionBinding
8
+ include Glimmer
9
+ include Observable
10
+ include Observer
11
+
12
+ attr_reader :element_proxy
13
+
14
+ PROPERTY_TYPE_UPDATERS = {
15
+ :string => lambda { |element_proxy, value| element_proxy.select(element_proxy.index_of(value.to_s)) },
16
+ :array => lambda { |element_proxy, value| element_proxy.selection=(value || []) }
17
+ }
18
+
19
+ PROPERTY_EVALUATORS = {
20
+ :string => lambda do |selection_array|
21
+ return nil if selection_array.empty?
22
+ selection_array[0]
23
+ end,
24
+ :array => lambda do |selection_array|
25
+ selection_array
26
+ end
27
+ }
28
+
29
+ # Initialize with list element and property_type
30
+ # property_type :string represents default list single selection
31
+ # property_type :array represents list multi selection
32
+ def initialize(element_proxy, property_type)
33
+ property_type = :string if property_type.nil? or property_type == :undefined
34
+ @element_proxy = element_proxy
35
+ @property_type = property_type
36
+ @element_proxy.on_widget_disposed do |dispose_event|
37
+ unregister_all_observables
38
+ end
39
+ end
40
+
41
+ def call(value)
42
+ PROPERTY_TYPE_UPDATERS[@property_type].call(@element_proxy, value) unless evaluate_property == value
43
+ end
44
+
45
+ def evaluate_property
46
+ selection_array = @element_proxy.selection.to_a #TODO refactor send('selection') into proper method invocation
47
+ PROPERTY_EVALUATORS[@property_type].call(selection_array)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/top_level_expression'
3
+ require 'glimmer/opal/display_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class AsyncExecExpression < StaticExpression
9
+ include TopLevelExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::DisplayProxy.instance.async_exec(&block)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/iframe_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class BrowserExpression < StaticExpression
9
+ include ParentExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::IframeProxy.new(parent, args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -9,6 +9,7 @@ module Glimmer
9
9
  include ParentExpression
10
10
 
11
11
  def interpret(parent, keyword, *args, &block)
12
+ args << {type: 'button'}
12
13
  Glimmer::Opal::InputProxy.new(parent, args)
13
14
  end
14
15
  end
@@ -10,9 +10,20 @@ require 'glimmer/dsl/opal/combo_expression'
10
10
  require 'glimmer/dsl/opal/composite_expression'
11
11
  require 'glimmer/dsl/opal/button_expression'
12
12
  require 'glimmer/dsl/opal/bind_expression'
13
- # require 'glimmer/dsl/opal/data_binding_expression'
13
+ require 'glimmer/dsl/opal/data_binding_expression'
14
14
  require 'glimmer/dsl/opal/combo_selection_data_binding_expression'
15
15
  require 'glimmer/dsl/opal/widget_listener_expression'
16
+ require 'glimmer/dsl/opal/grid_layout_expression'
17
+ require 'glimmer/dsl/opal/text_expression'
18
+ require 'glimmer/dsl/opal/list_expression'
19
+ require 'glimmer/dsl/opal/browser_expression'
20
+ require 'glimmer/dsl/opal/tab_folder_expression'
21
+ require 'glimmer/dsl/opal/tab_item_expression'
22
+ require 'glimmer/dsl/opal/message_box_expression'
23
+ require 'glimmer/dsl/opal/async_exec_expression'
24
+ require 'glimmer/dsl/opal/observe_expression'
25
+ require 'glimmer/dsl/opal/layout_data_expression'
26
+ require 'glimmer/dsl/opal/list_selection_data_binding_expression'
16
27
 
17
28
  module Glimmer
18
29
  module DSL
@@ -22,6 +33,9 @@ module Glimmer
22
33
  %w[
23
34
  widget_listener
24
35
  combo_selection_data_binding
36
+ list_selection_data_binding
37
+ data_binding
38
+ text
25
39
  property
26
40
  ]
27
41
  )
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/grid_layout_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class GridLayoutExpression < StaticExpression
9
+ include ParentExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::GridLayoutProxy.new(parent, args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/layout_data_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class LayoutDataExpression < StaticExpression
9
+ include ParentExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::LayoutDataProxy.new(parent, args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/list_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class ListExpression < StaticExpression
9
+ include ParentExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::ListProxy.new(parent, args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,42 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+ require 'glimmer/data_binding/element_binding'
4
+ require 'glimmer/data_binding/list_selection_binding'
5
+ require 'glimmer/opal/list_proxy'
6
+
7
+ module Glimmer
8
+ module DSL
9
+ module Opal
10
+ class ListSelectionDataBindingExpression < Expression
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ keyword == 'selection' and
13
+ block.nil? and
14
+ parent.is_a?(Glimmer::Opal::ListProxy) 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
+ element_binding = DataBinding::ElementBinding.new(parent, 'items')
23
+ element_binding.call(model_binding.evaluate_options_property)
24
+ model = model_binding.base_model
25
+ #TODO make this options observer dependent and all similar observers in widget specific data binding interpretrs
26
+ element_binding.observe(model, model_binding.options_property_name)
27
+
28
+ property_type = :string
29
+ property_type = :array if parent.has_style?(:multi)
30
+ list_selection_binding = DataBinding::ListSelectionBinding.new(parent, property_type)
31
+ list_selection_binding.call(model_binding.evaluate_property)
32
+ #TODO check if nested data binding works for list widget and other widgets that need custom data binding
33
+ list_selection_binding.observe(model, model_binding.property_name_expression)
34
+
35
+ parent.on_widget_selected do
36
+ model_binding.call(list_selection_binding.evaluate_property)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/top_level_expression'
3
+ require 'glimmer/dsl/parent_expression'
4
+ require 'glimmer/opal/modal'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module Opal
9
+ class MessageBoxExpression < StaticExpression
10
+ include TopLevelExpression
11
+ include ParentExpression
12
+
13
+ def interpret(parent, keyword, *args, &block)
14
+ parent = args.delete_at(0)
15
+ Glimmer::Opal::Modal.new(parent, args)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/top_level_expression'
3
+ require 'glimmer/data_binding/observer'
4
+ require 'glimmer/data_binding/model_binding'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module Opal
9
+ class ObserveExpression < StaticExpression
10
+ include TopLevelExpression
11
+
12
+ REGEX_NESTED_OR_INDEXED_PROPERTY = /([^\[]+)(\[[^\]]+\])?/
13
+
14
+ def can_interpret?(parent, keyword, *args, &block)
15
+ keyword == 'observe' and
16
+ block_given? and
17
+ (args.size == 2) and
18
+ textual?(args[1])
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ observer = DataBinding::Observer.proc(&block)
23
+ if args[1].to_s.match(REGEX_NESTED_OR_INDEXED_PROPERTY)
24
+ observer.observe(DataBinding::ModelBinding.new(args[0], args[1]))
25
+ else
26
+ observer.observe(args[0], args[1])
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -7,11 +7,15 @@ module Glimmer
7
7
  include TopLevelExpression
8
8
 
9
9
  def can_interpret?(parent, keyword, *args, &block)
10
- parent and keyword and block.nil?
10
+ parent and parent.respond_to?(:set_attribute) and keyword and block.nil?
11
11
  end
12
12
 
13
13
  def interpret(parent, keyword, *args, &block)
14
- parent.text = args.first.to_s
14
+ if keyword == 'text' # TODO move into property converters in element proxy
15
+ args = [args.first.to_s.gsub('&', '') ]
16
+ end
17
+ parent.set_attribute(keyword, *args)
18
+ args.first.to_s
15
19
  end
16
20
  end
17
21
  end
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/tab_folder'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class TabFolderExpression < StaticExpression
9
+ include ParentExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::TabFolder.new(parent, args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/tab_item'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class TabItemExpression < StaticExpression
9
+ include ParentExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::TabItem.new(parent, args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/input_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class TextExpression < Expression
9
+ include ParentExpression
10
+
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ keyword == 'text' and parent and block_given?
13
+ end
14
+
15
+ def interpret(parent, keyword, *args, &block)
16
+ args << {type: 'text'}
17
+ Glimmer::Opal::InputProxy.new(parent, args)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ module Glimmer
2
+ module Opal
3
+ class DisplayProxy
4
+ class << self
5
+ def instance
6
+ @instance ||= new
7
+ end
8
+ end
9
+
10
+ def async_exec(&block)
11
+ executer = lambda do
12
+ if $document.at_css('.modal')
13
+ sleep(0.05)
14
+ Async::Task.new(&executer)
15
+ else
16
+ block.call
17
+ end
18
+ end
19
+ Async::Task.new(&executer)
20
+ end
21
+ end
22
+ end
23
+ end