glimmer-dsl-opal 0.1.0 → 0.2.0

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +195 -167
  4. data/VERSION +1 -1
  5. data/lib/glimmer-dsl-opal.rb +24 -7
  6. data/lib/glimmer-dsl-opal/ext/exception.rb +5 -0
  7. data/lib/glimmer-dsl-opal/missing/net/http.rb +17 -0
  8. data/lib/glimmer-dsl-opal/missing/uri.rb +26 -0
  9. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager.rb +0 -0
  10. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact.rb +0 -0
  11. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact_manager_presenter.rb +0 -0
  12. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact_repository.rb +24 -99
  13. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/login.rb +0 -0
  14. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe.rb +0 -0
  15. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe/board.rb +0 -0
  16. data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe/cell.rb +0 -0
  17. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_browser.rb +0 -0
  18. data/lib/glimmer-dsl-opal/samples/hello/hello_combo.rb +63 -0
  19. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_computed.rb +0 -0
  20. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_computed/contact.rb +0 -0
  21. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_shell.rb +155 -0
  22. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_widget.rb +86 -0
  23. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_list_multi_selection.rb +0 -0
  24. data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_list_single_selection.rb +0 -0
  25. data/lib/glimmer-dsl-opal/samples/hello/hello_tab.rb +50 -0
  26. data/lib/glimmer-dsl-opal/samples/hello/hello_world.rb +29 -0
  27. data/lib/{jquery.js → glimmer-dsl-opal/vendor/jquery.js} +0 -0
  28. data/lib/glimmer/data_binding/ext/observable_model.rb +1 -1
  29. data/lib/glimmer/dsl/opal/async_exec_expression.rb +2 -2
  30. data/lib/glimmer/dsl/opal/color_expression.rb +38 -0
  31. data/lib/glimmer/dsl/opal/custom_widget_expression.rb +57 -0
  32. data/lib/glimmer/dsl/opal/dsl.rb +7 -0
  33. data/lib/glimmer/dsl/opal/font_expression.rb +47 -0
  34. data/lib/glimmer/dsl/opal/property_expression.rb +5 -2
  35. data/lib/glimmer/dsl/opal/rgb_expression.rb +32 -0
  36. data/lib/glimmer/dsl/opal/rgba_expression.rb +32 -0
  37. data/lib/glimmer/dsl/opal/swt_expression.rb +46 -0
  38. data/lib/glimmer/dsl/opal/widget_expression.rb +2 -1
  39. data/lib/glimmer/dsl/opal/widget_listener_expression.rb +16 -3
  40. data/lib/glimmer/swt.rb +499 -0
  41. data/lib/glimmer/swt/browser_proxy.rb +1 -1
  42. data/lib/glimmer/swt/button_proxy.rb +2 -2
  43. data/lib/glimmer/swt/color_proxy.rb +119 -0
  44. data/lib/glimmer/swt/combo_proxy.rb +10 -9
  45. data/lib/glimmer/swt/composite_proxy.rb +8 -8
  46. data/lib/glimmer/{opal → swt}/display_proxy.rb +3 -1
  47. data/lib/glimmer/swt/fill_layout_proxy.rb +84 -0
  48. data/lib/glimmer/swt/font_proxy.rb +79 -0
  49. data/lib/glimmer/swt/grid_layout_proxy.rb +34 -4
  50. data/lib/glimmer/swt/label_proxy.rb +7 -3
  51. data/lib/glimmer/swt/layout_proxy.rb +15 -13
  52. data/lib/glimmer/swt/list_proxy.rb +17 -12
  53. data/lib/glimmer/swt/message_box_proxy.rb +4 -7
  54. data/lib/glimmer/swt/row_layout_proxy.rb +105 -0
  55. data/lib/glimmer/swt/shell_proxy.rb +32 -22
  56. data/lib/glimmer/swt/style_constantizable.rb +154 -0
  57. data/lib/glimmer/swt/swt_proxy.rb +53 -0
  58. data/lib/glimmer/swt/tab_folder_proxy.rb +8 -8
  59. data/lib/glimmer/swt/tab_item_proxy.rb +15 -32
  60. data/lib/glimmer/swt/table_proxy.rb +0 -18
  61. data/lib/glimmer/swt/widget_proxy.rb +140 -39
  62. data/lib/glimmer/ui/custom_shell.rb +73 -0
  63. data/lib/glimmer/ui/custom_widget.rb +290 -0
  64. data/lib/glimmer/util/proc_tracker.rb +39 -0
  65. metadata +88 -57
  66. data/lib/glimmer/opal/element_proxy.rb +0 -312
  67. data/lib/samples/elaborate/launch +0 -6
  68. data/lib/samples/hello/hello_combo.rb +0 -34
  69. data/lib/samples/hello/hello_tab.rb +0 -24
  70. data/lib/samples/hello/hello_world.rb +0 -8
  71. data/lib/samples/hello/launch +0 -10
  72. data/lib/samples/launch +0 -4
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2020 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/swt'
23
+ require 'glimmer/swt/style_constantizable'
24
+
25
+ module Glimmer
26
+ module SWT
27
+ # Proxy for org.eclipse.swt.SWT
28
+ #
29
+ # Follows the Proxy Design Pattern
30
+ class SWTProxy
31
+ include StyleConstantizable
32
+
33
+ class << self
34
+ def constant_source_class
35
+ SWT
36
+ end
37
+
38
+ def constant_value_none
39
+ SWT::NONE
40
+ end
41
+
42
+ def extra_styles
43
+ EXTRA_STYLES
44
+ end
45
+ end
46
+
47
+ EXTRA_STYLES = {
48
+ NO_RESIZE: self[:shell_trim, :resize!, :max!],
49
+ NO_SORT: -7,
50
+ }
51
+ end
52
+ end
53
+ end
@@ -12,20 +12,16 @@ module Glimmer
12
12
 
13
13
  def add_child(child)
14
14
  unless @children.include?(child)
15
- @children << child
15
+ @children << child
16
+ tabs_dom_element.append(child.tab_dom)
17
+ child.render
16
18
  end
19
+
17
20
  if @children.size == 1
18
21
  child.show
19
22
  end
20
23
  end
21
24
 
22
- def redraw
23
- super()
24
- @children.each do |child|
25
- add_child(child) # TODO think of impact of this on performance
26
- end
27
- end
28
-
29
25
  def hide_all_tab_content
30
26
  @children.each(&:hide)
31
27
  end
@@ -38,6 +34,10 @@ module Glimmer
38
34
  id + '-tabs'
39
35
  end
40
36
 
37
+ def tabs_dom_element
38
+ Document.find(tabs_path)
39
+ end
40
+
41
41
  def dom
42
42
  tab_folder_id = id
43
43
  tab_folder_id_style = css
@@ -8,7 +8,6 @@ module Glimmer
8
8
 
9
9
  def initialize(parent, args)
10
10
  super(parent, args)
11
- css_classes << 'tab-item'
12
11
  content {
13
12
  on_widget_selected {
14
13
  @parent.hide_all_tab_content
@@ -18,22 +17,20 @@ module Glimmer
18
17
  end
19
18
 
20
19
  def show
21
- # TODO refactor/rewrite via simply class application in jquery
22
- # Document.find(path).remove_class('hide')
23
20
  @content_visible = true
24
- redraw
21
+ dom_element.remove_class('hide')
22
+ tab_dom_element.add_class('selected')
25
23
  end
26
24
 
27
25
  def hide
28
- # TODO refactor/rewrite via simply class application in jquery
29
- # Document.find(path).add_class('hide')
30
26
  @content_visible = false
31
- redraw
27
+ dom_element.add_class('hide')
28
+ tab_dom_element.remove_class('selected')
32
29
  end
33
30
 
34
31
  def text=(value)
35
32
  @text = value
36
- redraw
33
+ tab_dom_element.html(@text)
37
34
  end
38
35
 
39
36
  def selector
@@ -52,47 +49,33 @@ module Glimmer
52
49
  tab_path
53
50
  end
54
51
 
55
- def redraw
56
- if @tab_dom
57
- old_tab_dom = @tab_dom
58
- @tab_dom = nil
59
- Document.find(tab_path).replace_with(tab_dom)
60
- else
61
- Document.find(parent.tabs_path).append(tab_dom)
62
- end
63
- super()
64
- end
65
-
66
52
  def tab_path
67
53
  "#{parent.tabs_path} > ##{tab_id}"
68
54
  end
69
55
 
56
+ def tab_dom_element
57
+ Document.find(tab_path)
58
+ end
59
+
70
60
  def tab_id
71
61
  id + '-tab'
72
62
  end
73
63
 
64
+ # This contains the clickable tab area with tab names
74
65
  def tab_dom
75
- tab_selected = @content_visible ? 'selected' : ''
76
66
  @tab_dom ||= html {
77
- button(id: tab_id, class: "tab #{tab_selected}") {
67
+ button(id: tab_id, class: "tab") {
78
68
  @text
79
69
  }
80
70
  }.to_s
81
71
  end
82
72
 
73
+ # This contains the tab content
83
74
  def dom
84
- tab_item_id = id
85
- tab_item_id_style = css
86
- tab_item_css_classes = css_classes
87
- css_classes << name
88
- if @content_visible
89
- tab_item_css_classes.delete('hide')
90
- else
91
- tab_item_css_classes << 'hide'
92
- end
93
- tab_item_class_string = tab_item_css_classes.to_a.join(' ')
75
+ tab_item_id = id
76
+ tab_item_class_string = [name, 'hide'].join(' ')
94
77
  @dom ||= html {
95
- div(id: tab_item_id, style: tab_item_id_style, class: tab_item_class_string) {
78
+ div(id: tab_item_id, class: tab_item_class_string) {
96
79
  }
97
80
  }.to_s
98
81
  end
@@ -105,24 +105,6 @@ module Glimmer
105
105
  @columns.to_a.each(&:redraw)
106
106
  end
107
107
 
108
- # def redraw
109
- # if @dom
110
- # old_dom = @dom
111
- # @dom = nil
112
- # old_dom.replace dom
113
- # else
114
- # dom
115
- # end
116
- # if @last_redrawn_children != @children
117
- # items_dom_element.empty
118
- # @last_redrawn_children = @children
119
- # @children = []
120
- # @last_redrawn_children.each do |child|
121
- # add_child(child)
122
- # end
123
- # end
124
- # end
125
-
126
108
  def element
127
109
  'table'
128
110
  end
@@ -1,5 +1,27 @@
1
+ # Copyright (c) 2020 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
1
22
  require 'glimmer/swt/event_listener_proxy'
2
23
  require 'glimmer/swt/property_owner'
24
+ require 'glimmer/swt/swt_proxy'
3
25
 
4
26
  module Glimmer
5
27
  module SWT
@@ -7,12 +29,12 @@ module Glimmer
7
29
  include Glimmer
8
30
  include PropertyOwner
9
31
 
10
- attr_reader :parent, :args, :path, :css_classes, :css, :children, :enabled
32
+ attr_reader :parent, :args, :path, :children, :enabled, :foreground, :background, :font
11
33
 
12
34
  class << self
13
35
  # Factory Method that translates a Glimmer DSL keyword into a WidgetProxy object
14
36
  def for(keyword, parent, args)
15
- the_widget_class = widget_class(keyword) || Glimmer::SWT::LabelProxy
37
+ the_widget_class = widget_class(keyword)
16
38
  the_widget_class.new(parent, args)
17
39
  end
18
40
 
@@ -44,18 +66,50 @@ module Glimmer
44
66
  def reset_max_id_numbers!
45
67
  @max_id_numbers = {}
46
68
  end
69
+
70
+ def underscored_widget_name(widget_proxy)
71
+ widget_proxy.class.name.split(/::|\./).last.sub(/Proxy$/, '').underscore
72
+ end
47
73
  end
48
74
 
75
+ DEFAULT_INITIALIZERS = {
76
+ "composite" => lambda do |composite_proxy|
77
+ if composite_proxy.layout.nil?
78
+ layout = GridLayoutProxy.new(composite_proxy, [])
79
+ composite_proxy.layout = layout
80
+ layout.margin_width = 15
81
+ layout.margin_height = 15
82
+ end
83
+ end,
84
+ # "scrolled_composite" => lambda do |scrolled_composite|
85
+ # scrolled_composite.expand_horizontal = true
86
+ # scrolled_composite.expand_vertical = true
87
+ # end,
88
+ # "table" => lambda do |table|
89
+ # table.setHeaderVisible(true)
90
+ # table.setLinesVisible(true)
91
+ # end,
92
+ "table_column" => lambda do |table_column_proxy|
93
+ table_column_proxy.width = 80
94
+ end,
95
+ # "group" => lambda do |group_proxy|
96
+ # group_proxy.layout = GridLayoutProxy.new(group_proxy, []) if group.layout.nil?
97
+ # end,
98
+ }
99
+
49
100
  def initialize(parent, args)
50
101
  @parent = parent
51
102
  @args = args
52
- @children = Set.new
53
- @css_classes = Set.new
54
- @css = ''
103
+ @children = Set.new # TODO consider moving to composite
55
104
  @enabled = true
56
- @parent.add_child(self)
105
+ DEFAULT_INITIALIZERS[self.class.underscored_widget_name(self)]&.call(self)
106
+ @parent.add_child(self) # TODO rename to post_initialize_child to be closer to glimmer-dsl-swt terminology
57
107
  end
58
108
 
109
+ def css_classes
110
+ dom_element.attr('class').to_s.split
111
+ end
112
+
59
113
  def dispose
60
114
  Document.find(path).remove
61
115
  end
@@ -71,28 +125,44 @@ module Glimmer
71
125
 
72
126
  def add_child(child)
73
127
  @children << child
74
- child.redraw
128
+ child.render
75
129
  end
76
130
 
77
131
  def enabled=(value)
78
132
  @enabled = value
79
- # TODO consider relying less on redraw in setters in the future
80
- redraw
133
+ dom_element.prop('disabled', !@enabled)
134
+ end
135
+
136
+ def foreground=(value)
137
+ @foreground = value
138
+ dom_element.css('color', foreground.to_css) unless foreground.nil?
139
+ end
140
+
141
+ def background=(value)
142
+ @background = value
143
+ dom_element.css('background-color', background.to_css) unless background.nil?
144
+ end
145
+
146
+ def font=(value)
147
+ @font = value.is_a?(FontProxy) ? value : FontProxy.new(self, value)
148
+ dom_element.css('font-family', @font.name) unless @font.nil?
149
+ dom_element.css('font-style', 'italic') if @font&.style == :italic
150
+ dom_element.css('font-weight', 'bold') if @font&.style == :bold
151
+ dom_element.css('font-size', "#{@font.height}px") unless @font.nil?
81
152
  end
82
153
 
83
154
  def parent_path
84
155
  @parent.path
85
156
  end
86
157
 
87
- def redraw
88
- if @dom && !Document.find(path).empty?
89
- old_element = Document.find(path)
90
- old_dom = @dom
91
- @dom = nil
92
- old_element.replace_with(dom.gsub('<html>', '').gsub('</html>', ''))
158
+ def render
159
+ old_element = dom_element
160
+ brand_new = @dom.nil? || old_element.empty?
161
+ build_dom
162
+ if brand_new
163
+ Document.find(parent_path).append(@dom)
93
164
  else
94
- @dom = nil
95
- Document.find(parent_path).append(dom.gsub('<html>', '').gsub('</html>', ''))
165
+ old_element.replace_with(@dom)
96
166
  end
97
167
  @observation_requests&.clone&.each do |keyword, event_listener_set|
98
168
  event_listener_set.each do |event_listener|
@@ -101,8 +171,15 @@ module Glimmer
101
171
  end
102
172
  end
103
173
  children.each do |child|
104
- child.redraw
105
- end
174
+ child.render
175
+ end
176
+ end
177
+ alias redraw render
178
+
179
+ def build_dom
180
+ @dom = nil
181
+ @dom = dom
182
+ @dom = @parent.layout.dom(@dom) if @parent.respond_to?(:layout) && @parent.layout
106
183
  end
107
184
 
108
185
  def content(&block)
@@ -133,33 +210,23 @@ module Glimmer
133
210
  end
134
211
 
135
212
  def add_css_class(css_class)
136
- @css_classes << css_class
137
- redraw
213
+ dom_element.add_class(css_class)
138
214
  end
139
215
 
140
- def add_css_classes(css_classes)
141
- @css_classes += css_classes
142
- redraw
216
+ def add_css_classes(css_classes_to_add)
217
+ css_classes_to_add.each {|css_class| add_css_class(css_class)}
143
218
  end
144
219
 
145
220
  def remove_css_class(css_class)
146
- @css_classes.delete(css_class)
147
- redraw
148
- end
149
-
150
- def remove_css_classes(css_classes)
151
- @css_classes -= css_classes
152
- redraw
221
+ dom_element.remove_class(css_class)
153
222
  end
154
223
 
155
- def clear_css_classes(css_class)
156
- @css_classes.clear
157
- redraw
224
+ def remove_css_classes(css_classes_to_remove)
225
+ css_classes_to_remove.each {|css_class| remove_css_class(css_class)}
158
226
  end
159
227
 
160
- def css=(css)
161
- @css = css
162
- redraw
228
+ def clear_css_classes
229
+ css_classes.each {|css_class| remove_css_class(css_class)}
163
230
  end
164
231
 
165
232
  def has_style?(symbol)
@@ -170,6 +237,20 @@ module Glimmer
170
237
  Document.find(path)
171
238
  end
172
239
 
240
+ def style_element
241
+ style_element_id = "#{id}-style"
242
+ style_element_selector = "style##{style_element_id}"
243
+ element = dom_element.find(style_element_selector)
244
+ if element.empty?
245
+ new_element = Element.new(:style)
246
+ new_element.attr('id', style_element_id)
247
+ new_element.attr('class', "#{name.gsub('_', '-')}-instance-style widget-instance-style")
248
+ dom_element.prepend(new_element)
249
+ element = dom_element.find(style_element_selector)
250
+ end
251
+ element
252
+ end
253
+
173
254
  def parent_dom_element
174
255
  Document.find(parent_path)
175
256
  end
@@ -178,6 +259,19 @@ module Glimmer
178
259
  path
179
260
  end
180
261
 
262
+ def can_handle_observation_request?(observation_request)
263
+ # TODO sort this out for Opal
264
+ observation_request = observation_request.to_s
265
+ if observation_request.start_with?('on_swt_')
266
+ constant_name = observation_request.sub(/^on_swt_/, '')
267
+ SWTProxy.has_constant?(constant_name)
268
+ elsif observation_request.start_with?('on_')
269
+ # event = observation_request.sub(/^on_/, '')
270
+ # can_add_listener?(event) || can_handle_drag_observation_request?(observation_request) || can_handle_drop_observation_request?(observation_request)
271
+ true # TODO filter by valid listeners only in the future
272
+ end
273
+ end
274
+
181
275
  def handle_observation_request(keyword, &event_listener)
182
276
  return unless observation_request_to_event_mapping.keys.include?(keyword)
183
277
  @observation_requests ||= {}
@@ -222,8 +316,15 @@ module Glimmer
222
316
  end
223
317
 
224
318
  def property_type_converters
319
+ color_converter = lambda do |value|
320
+ if value.is_a?(Symbol) || value.is_a?(String)
321
+ ColorProxy.new(value)
322
+ else
323
+ value
324
+ end
325
+ end
225
326
  @property_type_converters ||= {
226
- # :background => color_converter,
327
+ :background => color_converter,
227
328
  # :background_image => lambda do |value|
228
329
  # if value.is_a?(String)
229
330
  # if value.start_with?('uri:classloader')
@@ -243,7 +344,7 @@ module Glimmer
243
344
  # value
244
345
  # end
245
346
  # end,
246
- # :foreground => color_converter,
347
+ :foreground => color_converter,
247
348
  # :font => lambda do |value|
248
349
  # if value.is_a?(Hash)
249
350
  # font_properties = value