glimmer-dsl-opal 0.0.3 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +1049 -35
  4. data/VERSION +1 -1
  5. data/lib/glimmer-dsl-opal.rb +5 -2
  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/data_binding/table_items_binding.rb +67 -0
  9. data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
  10. data/lib/glimmer/dsl/opal/browser_expression.rb +17 -0
  11. data/lib/glimmer/dsl/opal/column_properties_expression.rb +22 -0
  12. data/lib/glimmer/dsl/opal/dsl.rb +14 -0
  13. data/lib/glimmer/dsl/opal/list_expression.rb +17 -0
  14. data/lib/glimmer/dsl/opal/list_selection_data_binding_expression.rb +42 -0
  15. data/lib/glimmer/dsl/opal/message_box_expression.rb +20 -0
  16. data/lib/glimmer/dsl/opal/observe_expression.rb +32 -0
  17. data/lib/glimmer/dsl/opal/tab_folder_expression.rb +17 -0
  18. data/lib/glimmer/dsl/opal/tab_item_expression.rb +17 -0
  19. data/lib/glimmer/dsl/opal/table_column_expression.rb +17 -0
  20. data/lib/glimmer/dsl/opal/table_expression.rb +17 -0
  21. data/lib/glimmer/dsl/opal/table_items_data_binding_expression.rb +29 -0
  22. data/lib/glimmer/opal/display_proxy.rb +23 -0
  23. data/lib/glimmer/opal/div_proxy.rb +11 -2
  24. data/lib/glimmer/opal/document_proxy.rb +141 -11
  25. data/lib/glimmer/opal/element_proxy.rb +38 -15
  26. data/lib/glimmer/opal/grid_layout_proxy.rb +3 -1
  27. data/lib/glimmer/opal/iframe_proxy.rb +23 -0
  28. data/lib/glimmer/opal/input_proxy.rb +8 -4
  29. data/lib/glimmer/opal/label_proxy.rb +1 -1
  30. data/lib/glimmer/opal/layout_data_proxy.rb +23 -2
  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/select_proxy.rb +1 -1
  35. data/lib/glimmer/opal/tab_folder.rb +53 -0
  36. data/lib/glimmer/opal/tab_item.rb +98 -0
  37. data/lib/glimmer/opal/table_column.rb +50 -0
  38. data/lib/glimmer/opal/table_item.rb +136 -0
  39. data/lib/glimmer/opal/table_proxy.rb +149 -0
  40. data/lib/samples/elaborate/contact_manager.rb +1 -2
  41. data/lib/samples/elaborate/login.rb +0 -1
  42. data/lib/samples/elaborate/tic_tac_toe.rb +5 -5
  43. data/lib/samples/hello/hello_tab.rb +2 -2
  44. metadata +30 -14
  45. data/lib/glimmer/config.rb +0 -22
  46. data/lib/glimmer/dsl/engine.rb +0 -193
  47. data/lib/glimmer/dsl/expression.rb +0 -42
  48. data/lib/glimmer/dsl/expression_handler.rb +0 -48
  49. data/lib/glimmer/dsl/parent_expression.rb +0 -12
  50. data/lib/glimmer/dsl/static_expression.rb +0 -36
  51. data/lib/glimmer/dsl/top_level_expression.rb +0 -7
  52. data/lib/glimmer/error.rb +0 -6
  53. data/lib/glimmer/invalid_keyword_error.rb +0 -6
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.8
@@ -1,5 +1,7 @@
1
1
  require 'opal'
2
- require 'opal-parser'
2
+ require 'opal-async'
3
+ require 'browser'
4
+ require 'browser/effects'
3
5
  require 'glimmer'
4
6
 
5
7
  GLIMMER_DSL_OPAL_ROOT = File.expand_path('../..', __FILE__)
@@ -7,4 +9,5 @@ GLIMMER_DSL_OPAL_LIB = File.join(GLIMMER_DSL_OPAL_ROOT, 'lib')
7
9
 
8
10
  $LOAD_PATH.unshift(GLIMMER_DSL_OPAL_LIB)
9
11
 
10
- require 'glimmer/dsl/opal/dsl'
12
+ require 'glimmer/dsl/opal/dsl'
13
+ require 'glimmer/data_binding/ext/observable_model'
@@ -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,67 @@
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/opal/table_proxy'
6
+ require 'glimmer/opal/table_item'
7
+
8
+ module Glimmer
9
+ module DataBinding
10
+ class TableItemsBinding
11
+ include DataBinding::Observable
12
+ include DataBinding::Observer
13
+
14
+ def initialize(parent, model_binding, column_properties)
15
+ @last_model_collection = nil
16
+ @table = parent
17
+ @model_binding = model_binding
18
+ @column_properties = column_properties
19
+ if @table.respond_to?(:column_properties=)
20
+ @table.column_properties = @column_properties
21
+ ##else # assume custom widget
22
+ ## @table.body_root.column_properties = @column_properties
23
+ end
24
+ call(@model_binding.evaluate_property)
25
+ model = model_binding.base_model
26
+ observe(model, model_binding.property_name_expression)
27
+ ##@table.on_widget_disposed do |dispose_event| # doesn't seem needed within Opal
28
+ ## unregister_all_observables
29
+ ##end
30
+ end
31
+
32
+ def call(new_model_collection=nil)
33
+ if new_model_collection and new_model_collection.is_a?(Array)
34
+ observe(new_model_collection, @column_properties)
35
+ @model_collection = new_model_collection
36
+ end
37
+ populate_table(@model_collection, @table, @column_properties)
38
+ sort_table(@model_collection, @table, @column_properties)
39
+ end
40
+
41
+ def populate_table(model_collection, parent, column_properties)
42
+ return if model_collection&.sort_by(&:hash) == @last_model_collection&.sort_by(&:hash)
43
+ @last_model_collection = model_collection
44
+ # TODO improve performance
45
+ selected_table_item_models = parent.selection.map(&:get_data)
46
+ parent.remove_all
47
+ model_collection.each do |model|
48
+ table_item = Glimmer::Opal::TableItem.new(parent)
49
+ for index in 0..(column_properties.size-1)
50
+ table_item.set_text(index, model.send(column_properties[index]).to_s)
51
+ end
52
+ table_item.set_data(model)
53
+ end
54
+ selected_table_items = parent.search {|item| selected_table_item_models.include?(item.get_data) }
55
+ selected_table_items = [parent.items.first] if selected_table_items.empty? && !parent.items.empty?
56
+ parent.selection = selected_table_items unless selected_table_items.empty?
57
+ parent.redraw
58
+ end
59
+
60
+ def sort_table(model_collection, parent, column_properties)
61
+ return if model_collection == @last_model_collection
62
+ parent.items = parent.items.sort_by { |item| model_collection.index(item.get_data) }
63
+ @last_model_collection = model_collection
64
+ end
65
+ end
66
+ end
67
+ 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
@@ -0,0 +1,22 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/opal/table_proxy'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ module Opal
7
+ # Responsible for providing a readable keyword (command symbol) to capture
8
+ # and return column properties for use in TreeItemsDataBindingCommandHandler
9
+ class ColumnPropertiesExpression < StaticExpression
10
+ def can_interpret?(parent, keyword, *args, &block)
11
+ keyword == 'column_properties' and
12
+ block.nil? and
13
+ parent.is_a?(Glimmer::Opal::TableProxy)
14
+ end
15
+
16
+ def interpret(parent, keyword, *args, &block)
17
+ args
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -15,7 +15,19 @@ require 'glimmer/dsl/opal/combo_selection_data_binding_expression'
15
15
  require 'glimmer/dsl/opal/widget_listener_expression'
16
16
  require 'glimmer/dsl/opal/grid_layout_expression'
17
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'
18
25
  require 'glimmer/dsl/opal/layout_data_expression'
26
+ require 'glimmer/dsl/opal/list_selection_data_binding_expression'
27
+ require 'glimmer/dsl/opal/table_expression'
28
+ require 'glimmer/dsl/opal/table_column_expression'
29
+ require 'glimmer/dsl/opal/table_items_data_binding_expression'
30
+ require 'glimmer/dsl/opal/column_properties_expression'
19
31
 
20
32
  module Glimmer
21
33
  module DSL
@@ -24,7 +36,9 @@ module Glimmer
24
36
  Opal,
25
37
  %w[
26
38
  widget_listener
39
+ table_items_data_binding
27
40
  combo_selection_data_binding
41
+ list_selection_data_binding
28
42
  data_binding
29
43
  text
30
44
  property
@@ -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
@@ -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,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/table_column'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class TableColumnExpression < StaticExpression
9
+ include ParentExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::TableColumn.new(parent, args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end