glimmer-dsl-opal 0.0.3 → 0.0.8

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 (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
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+ require 'glimmer/opal/table_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Opal
8
+ class TableExpression < StaticExpression
9
+ include ParentExpression
10
+
11
+ def interpret(parent, keyword, *args, &block)
12
+ Glimmer::Opal::TableProxy.new(parent, args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ require 'glimmer/dsl/expression'
2
+ require 'glimmer/data_binding/model_binding'
3
+ require 'glimmer/data_binding/table_items_binding'
4
+ require 'glimmer/opal/table_proxy'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module Opal
9
+ #Depends on BindCommandHandler and TableColumnPropertiesDataBindingCommandHandler
10
+ class TableItemsDataBindingExpression < Expression
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ keyword == "items" and
13
+ block.nil? and
14
+ parent.is_a?(Glimmer::Opal::TableProxy) and
15
+ args.size == 2 and
16
+ args[0].is_a?(DataBinding::ModelBinding) and
17
+ args[0].evaluate_property.is_a?(Array) and
18
+ args[1].is_a?(Array)
19
+ end
20
+
21
+ def interpret(parent, keyword, *args, &block)
22
+ model_binding = args[0]
23
+ column_properties = args[1]
24
+ DataBinding::TableItemsBinding.new(parent, model_binding, column_properties)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ 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
@@ -3,14 +3,23 @@ require 'glimmer/opal/element_proxy'
3
3
  module Glimmer
4
4
  module Opal
5
5
  class DivProxy < ElementProxy
6
+ attr_reader :layout
7
+
6
8
  def initialize(parent, args)
7
9
  super(parent, args)
8
- GridLayoutProxy.new(self, [])
10
+ @layout = GridLayoutProxy.new(self, [])
11
+ end
12
+
13
+ def redraw
14
+ super()
15
+ @children.each do |child|
16
+ add_child(child) # TODO think of impact of this on performance, and of other alternatives
17
+ end
9
18
  end
10
19
 
11
20
  def dom
12
21
  div_id = id
13
- div_style = style
22
+ div_style = css
14
23
  @dom ||= DOM {
15
24
  div(id: div_id, class: 'grid-layout', style: div_style)
16
25
  }
@@ -1,9 +1,11 @@
1
1
  require 'glimmer/opal/element_proxy'
2
+ require 'glimmer/opal/point'
2
3
 
3
4
  module Glimmer
4
5
  module Opal
5
6
  class DocumentProxy < ElementProxy
6
7
  # TODO consider renaming to ShellProxy to match SWT API
8
+ attr_reader :minimum_size
7
9
 
8
10
  def initialize(args)
9
11
  @args = args
@@ -23,28 +25,156 @@ module Glimmer
23
25
  $document.title = value
24
26
  end
25
27
  end
28
+
29
+ def minimum_size=(width_or_minimum_size, height = nil)
30
+ @minimum_size = height.nil? ? width_or_minimum_size : Point.new(width_or_minimum_size, height)
31
+ redraw
32
+ end
26
33
 
27
34
  def head_dom
28
35
  # TODO make grid-layout support grab excess space false
29
36
  @head_dom ||= DOM {
30
37
  head {
31
- # <<~CSS
32
- # <style>
33
- # div.grid-layout {
34
- # display: grid;
35
- # grid-template-columns: auto;
36
- # grid-row-gap: 10px;
37
- # justify-content: start;
38
- # }
39
- # </style>
40
- # CSS
38
+ <<~CSS
39
+ <style>
40
+ html {
41
+ width: 100%;
42
+ height: 100%;
43
+ }
44
+ body {
45
+ width: 100%;
46
+ height: 100%;
47
+ margin: 0;
48
+ }
49
+ body > iframe {
50
+ width: 100%;
51
+ height: 100%;
52
+ }
53
+ ul {
54
+ list-style: none;
55
+ padding: 0;
56
+ }
57
+ li {
58
+ cursor: default;
59
+ padding-left: 10px;
60
+ padding-right: 10px;
61
+ }
62
+ li.empty-list-item {
63
+ color: transparent;
64
+ }
65
+ .tabs {
66
+ overflow: hidden;
67
+ border: 1px solid #ccc;
68
+ background-color: #f1f1f1;
69
+ }
70
+
71
+ /* Style the buttons inside the tab */
72
+ .tabs .tab {
73
+ background-color: inherit;
74
+ float: left;
75
+ border: none;
76
+ outline: none;
77
+ cursor: pointer;
78
+ padding: 14px 16px;
79
+ transition: 0.3s;
80
+ font-size: 17px;
81
+ }
82
+
83
+ /* Change background color of buttons on hover */
84
+ .tabs .tab:hover {
85
+ background-color: #ddd;
86
+ }
87
+
88
+ /* Create an active/current tablink class */
89
+ .tabs .tab.active {
90
+ background-color: #ccc;
91
+ }
92
+
93
+ /* Style the tab content */
94
+ .tab-item {
95
+ padding: 6px 12px;
96
+ border: 1px solid #ccc;
97
+ border-top: none;
98
+ }
99
+
100
+ .hide {
101
+ display: none !important;
102
+ }
103
+
104
+ /* The Modal (background) */
105
+ .modal {
106
+ position: fixed; /* Stay in place */
107
+ z-index: 1; /* Sit on top */
108
+ padding-top: 100px; /* Location of the box */
109
+ left: 0;
110
+ top: 0;
111
+ width: 100%; /* Full width */
112
+ height: 100%; /* Full height */
113
+ overflow: auto; /* Enable scroll if needed */
114
+ background-color: rgb(0,0,0); /* Fallback color */
115
+ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
116
+ text-align: center;
117
+ }
118
+
119
+ /* Modal Content */
120
+ .modal-content {
121
+ background-color: #fefefe;
122
+ margin: auto;
123
+ border: 1px solid #888;
124
+ display: inline-block;
125
+ min-width: 200px;
126
+ }
127
+
128
+ .modal-content .text {
129
+ background: rgb(80, 116, 211);
130
+ color: white;
131
+ padding: 5px;
132
+ }
133
+
134
+ .modal-content .message {
135
+ padding: 20px;
136
+ }
137
+
138
+ /* The Close Button */
139
+ .close {
140
+ color: #aaaaaa;
141
+ float: right;
142
+ font-weight: bold;
143
+ margin: 5px;
144
+ }
145
+
146
+ .close:hover,
147
+ .close:focus {
148
+ color: #000;
149
+ text-decoration: none;
150
+ cursor: pointer;
151
+ }
152
+
153
+ .selected {
154
+ background: rgb(80, 116, 211);
155
+ color: white;
156
+ }
157
+
158
+ table {
159
+ border-spacing: 0;
160
+ }
161
+
162
+ table tr th,td {
163
+ cursor: default;
164
+ }
165
+
166
+ </style>
167
+ CSS
41
168
  }
42
169
  }
43
170
  end
44
171
 
45
172
  def dom
173
+ i = 0
174
+ body_style = ''
175
+ body_style += "min-width: #{@minimum_size.x}px; min-height: #{@minimum_size.y}px;" if @minimum_size
46
176
  @dom ||= DOM {
47
- body {
177
+ body(style: body_style) {
48
178
  }
49
179
  }
50
180
  end
@@ -5,26 +5,40 @@ module Glimmer
5
5
  class ElementProxy
6
6
  include Glimmer
7
7
  include PropertyOwner
8
- attr_reader :parent, :args, :css_classes, :style
8
+ attr_reader :parent, :args, :css_classes, :css, :children, :enabled
9
9
 
10
10
  def initialize(parent, args)
11
11
  @parent = parent
12
12
  @args = args
13
- @children = []
14
- @parent.add_child(self)
13
+ @children = Set.new
15
14
  @css_classes = Set.new
15
+ @css = ''
16
+ @enabled = true
17
+ @parent.add_child(self)
16
18
  end
17
19
 
18
20
  def add_child(child)
19
- return if @children.include?(child)
21
+ # return if @children.include?(child) # TODO consider adding an option to enable this if needed to prevent dom repetition
20
22
  @children << child
21
23
  dom << child.dom
22
24
  end
25
+
26
+ def enabled=(value)
27
+ @enabled = value
28
+ redraw
29
+ end
23
30
 
24
31
  def redraw
25
- old_dom = @dom
26
- @dom = nil
27
- old_dom.replace dom
32
+ if @dom
33
+ old_dom = @dom
34
+ @dom = nil
35
+ old_dom.replace dom
36
+ else
37
+ dom
38
+ end
39
+ @children.each do |child|
40
+ child.redraw
41
+ end
28
42
  end
29
43
 
30
44
  # Subclasses must override with their own mappings
@@ -37,6 +51,7 @@ module Glimmer
37
51
  end
38
52
 
39
53
  def id
54
+ # TODO replace hash with autoincrement per name
40
55
  "#{name}-#{hash}"
41
56
  end
42
57
 
@@ -70,18 +85,26 @@ module Glimmer
70
85
  redraw
71
86
  end
72
87
 
73
- def style=(css)
74
- @style = css
88
+ def css=(css)
89
+ @css = css
75
90
  redraw
76
91
  end
77
92
 
93
+ def has_style?(symbol)
94
+ @args.include?(symbol) # not a very solid implementation. Bring SWT constants eventually
95
+ end
96
+
78
97
  def handle_observation_request(keyword, &event_listener)
79
98
  return unless observation_request_to_event_mapping.keys.include?(keyword)
80
- event = observation_request_to_event_mapping[keyword][:event]
81
- event_handler = observation_request_to_event_mapping[keyword][:event_handler]
82
- potential_event_listener = event_handler&.call(event_listener)
83
- event_listener = event_handler&.call(event_listener) || event_listener
84
- delegate = $document.on(event, selector, &event_listener)
99
+ event = nil
100
+ delegate = nil
101
+ [observation_request_to_event_mapping[keyword]].flatten.each do |mapping|
102
+ event = mapping[:event]
103
+ event_handler = mapping[:event_handler]
104
+ potential_event_listener = event_handler&.call(event_listener)
105
+ event_listener = event_handler&.call(event_listener) || event_listener
106
+ delegate = $document.on(event, selector, &event_listener)
107
+ end
85
108
  EventListenerProxy.new(element_proxy: self, event: event, selector: selector, delegate: delegate)
86
109
  end
87
110
 
@@ -171,7 +194,7 @@ module Glimmer
171
194
  # },
172
195
  InputProxy => {
173
196
  :text => lambda do |observer|
174
- on_modify_text { |modify_event|
197
+ on_modify_text { |modify_event|
175
198
  observer.call(text)
176
199
  }
177
200
  end,
@@ -10,7 +10,9 @@ module Glimmer
10
10
  @parent = parent
11
11
  @args = args
12
12
  @parent.add_css_class('grid-layout')
13
+ @horizontal_spacing = 10
13
14
  @vertical_spacing = 10
15
+ @num_columns = @args.first || 1
14
16
  reapply
15
17
  end
16
18
 
@@ -39,7 +41,7 @@ module Glimmer
39
41
  end
40
42
 
41
43
  def reapply
42
- @parent.style = <<~CSS
44
+ @parent.css = <<~CSS
43
45
  display: grid;
44
46
  grid-template-columns: #{'auto ' * @num_columns.to_i};
45
47
  grid-row-gap: #{@vertical_spacing}px;
@@ -0,0 +1,23 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class IframeProxy < ElementProxy
6
+ attr_reader :url
7
+
8
+ def url=(value)
9
+ @url = value
10
+ redraw
11
+ end
12
+
13
+ def dom
14
+ iframe_id = id
15
+ iframe_url = url
16
+ @dom ||= DOM {
17
+ iframe(src: iframe_url, frameBorder: 0) {
18
+ }
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -19,8 +19,10 @@ module Glimmer
19
19
  event: 'keyup',
20
20
  event_handler: -> (event_listener) {
21
21
  -> (event) {
22
- @text = event.target.value
23
- event_listener.call(event)
22
+ if args.last[:type] == 'text'
23
+ @text = event.target.value
24
+ event_listener.call(event)
25
+ end
24
26
  }
25
27
  }
26
28
  }
@@ -30,10 +32,12 @@ module Glimmer
30
32
  def dom
31
33
  input_text = @text
32
34
  input_id = id
33
- input_style = style
35
+ input_style = css
34
36
  input_args = @args.last
37
+ input_disabled = @enabled ? {} : {'disabled': 'disabled'}
38
+ input_args = input_args.merge(type: 'password') if has_style?(:password)
35
39
  @dom ||= DOM {
36
- input input_args.merge(id: input_id, style: input_style, value: input_text)
40
+ input input_args.merge(id: input_id, style: input_style, value: input_text, style: 'min-width: 27px;').merge(input_disabled)
37
41
  }
38
42
  end
39
43
  end