glimmer-dsl-opal 0.0.2 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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