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
@@ -7,7 +7,7 @@ module Glimmer
7
7
 
8
8
  def url=(value)
9
9
  @url = value
10
- redraw
10
+ dom_element.attr('src', @url)
11
11
  end
12
12
 
13
13
  def element
@@ -7,7 +7,7 @@ module Glimmer
7
7
 
8
8
  def text=(value)
9
9
  @text = value
10
- redraw
10
+ dom_element.html(@text)
11
11
  end
12
12
 
13
13
  def element
@@ -30,7 +30,7 @@ module Glimmer
30
30
  input_disabled = @enabled ? {} : {'disabled': 'disabled'}
31
31
  input_args = input_args.merge(type: 'password') if has_style?(:password)
32
32
  @dom ||= html {
33
- button(input_args.merge(id: input_id, class: name, style: input_style, style: 'min-width: 27px;').merge(input_disabled)) {
33
+ button(input_args.merge(id: input_id, class: name, style: input_style, style: 'min-width: 27px; min-height: 27px;').merge(input_disabled)) {
34
34
  input_text.to_s == '' ? ' ' : input_text
35
35
  }
36
36
  }.to_s
@@ -0,0 +1,119 @@
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
+ module Glimmer
23
+ module SWT
24
+ # Proxy for org.eclipse.swt.graphics.Color
25
+ #
26
+ # Invoking `#swt_color` returns the SWT Color object wrapped by this proxy
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class ColorProxy
30
+ SWT_COLOR_TRANSLATION = {
31
+ "widget_foreground" => [0, 0, 0],
32
+ "blue" => [0, 0, 255],
33
+ "widget_dark_shadow" => [0, 0, 0],
34
+ "title_foreground" => [0, 0, 0],
35
+ "yellow" => [255, 255, 0],
36
+ "widget_highlight_shadow" => [255, 255, 255],
37
+ "dark_cyan" => [0, 128, 128],
38
+ "list_foreground" => [0, 0, 0],
39
+ "dark_blue" => [0, 0, 128],
40
+ "dark_yellow" => [128, 128, 0],
41
+ "cyan" => [0, 255, 255],
42
+ "info_background" => [236, 235, 236],
43
+ "link_foreground" => [0, 104, 218],
44
+ "title_inactive_foreground" => [0, 0, 0],
45
+ "title_background_gradient" => [179, 215, 255],
46
+ "red" => [255, 0, 0],
47
+ "title_inactive_background_gradient" => [220, 220, 220],
48
+ "transparent" => [255, 255, 255],
49
+ "widget_light_shadow" => [232, 232, 232],
50
+ "dark_magenta" => [128, 0, 128],
51
+ "white" => [255, 255, 255],
52
+ "list_selection" => [179, 215, 255],
53
+ "gray" => [192, 192, 192],
54
+ "widget_border" => [0, 0, 0],
55
+ "widget_background" => [236, 236, 236],
56
+ "info_foreground" => [0, 0, 0],
57
+ "title_inactive_background" => [220, 220, 220],
58
+ "widget_disabled_foreground" => [220, 220, 220],
59
+ "list_background" => [255, 255, 255],
60
+ "magenta" => [255, 0, 255],
61
+ "title_background" => [0, 99, 225],
62
+ "text_disabled_background" => [255, 255, 255],
63
+ "black" => [0, 0, 0],
64
+ "dark_gray" => [128, 128, 128],
65
+ "list_selection_text" => [0, 0, 0],
66
+ "dark_red" => [128, 0, 0],
67
+ "widget_normal_shadow" => [159, 159, 159],
68
+ "dark_green" => [0, 128, 0],
69
+ "green" => [0, 255, 0]
70
+ }
71
+
72
+ attr_reader :args, :red, :green, :blue, :alpha
73
+
74
+ # Initializes a proxy for an SWT Color object
75
+ #
76
+ # Takes a standard color single argument, rgba 3 args, or rgba 4 args
77
+ #
78
+ # A standard color is a string/symbol representing one of the
79
+ # SWT.COLOR_*** constants like SWT.COLOR_RED, but in underscored string
80
+ # format (e.g :color_red).
81
+ # Glimmer can also accept standard color names without the color_ prefix,
82
+ # and it will automatically figure out the SWT.COLOR_*** constant
83
+ # (e.g. :red)
84
+ #
85
+ # rgb is 3 arguments representing Red, Green, Blue numeric values
86
+ #
87
+ # rgba is 4 arguments representing Red, Green, Blue, and Alpha numeric values
88
+ #
89
+ def initialize(*args)
90
+ @args = args
91
+ case @args.size
92
+ when 1
93
+ @alpha = nil
94
+ if @args.first.is_a?(String) || @args.first.is_a?(Symbol)
95
+ standard_color = @args.first.to_s.downcase.sub('COLOR_', '')
96
+ @red, @green, @blue = SWT_COLOR_TRANSLATION[standard_color]
97
+ else
98
+ @red, @green, @blue = [0, 0, 0]
99
+ end
100
+ when 3..4
101
+ @red, @green, @blue, @alpha = @args
102
+ end
103
+ end
104
+
105
+ def to_css
106
+ if alpha.nil?
107
+ "rgb(#{red}, #{green}, #{blue})"
108
+ else
109
+ "rgba(#{red}, #{green}, #{blue}, #{alpha_css})"
110
+ end
111
+ end
112
+
113
+ def alpha_css
114
+ alpha.to_f / 255
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -23,7 +23,16 @@ module Glimmer
23
23
 
24
24
  def items=(the_items)
25
25
  @items = the_items
26
- redraw
26
+ items_dom = items.to_a.map do |item|
27
+ option_hash = {value: item}
28
+ option_hash[:selected] = 'selected' if @text == item
29
+ html {
30
+ option(option_hash) {
31
+ item
32
+ }
33
+ }.to_s
34
+ end
35
+ dom_element.html(items_dom)
27
36
  end
28
37
 
29
38
  def observation_request_to_event_mapping
@@ -41,20 +50,12 @@ module Glimmer
41
50
  end
42
51
 
43
52
  def dom
44
- select_text = @text
45
53
  items = @items
46
54
  select_id = id
47
55
  select_style = css
48
56
  select_class = name
49
57
  @dom ||= html {
50
58
  select(id: select_id, class: select_class, style: select_style) {
51
- items.to_a.each do |item|
52
- option_hash = {value: item}
53
- option_hash[:selected] = 'selected' if select_text == item
54
- option(option_hash) {
55
- item
56
- }
57
- end
58
59
  }
59
60
  }.to_s
60
61
  end
@@ -11,21 +11,21 @@ module Glimmer
11
11
  @layout = GridLayoutProxy.new(self, [])
12
12
  end
13
13
 
14
- def redraw
15
- super()
16
- @children.each do |child|
17
- add_child(child) # TODO think of impact of this on performance, and of other alternatives
18
- end
19
- end
20
-
21
14
  def dom
22
15
  div_id = id
23
16
  div_style = css
24
- div_class = "#{name} grid-layout"
17
+ div_class = name
25
18
  @dom ||= html {
26
19
  div(id: div_id, class: div_class, style: div_style)
27
20
  }.to_s
28
21
  end
22
+
23
+ def layout=(the_layout)
24
+ @layout = the_layout
25
+ end
26
+
29
27
  end
28
+
30
29
  end
30
+
31
31
  end
@@ -1,5 +1,5 @@
1
1
  module Glimmer
2
- module Opal
2
+ module SWT
3
3
  class DisplayProxy
4
4
  class << self
5
5
  def instance
@@ -18,6 +18,8 @@ module Glimmer
18
18
  end
19
19
  Async::Task.new(&executer)
20
20
  end
21
+ # sync_exec kept for API compatibility reasons
22
+ alias sync_exec async_exec
21
23
  end
22
24
  end
23
25
  end
@@ -0,0 +1,84 @@
1
+ require 'glimmer/swt/layout_proxy'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ class FillLayoutProxy < LayoutProxy
6
+ include Glimmer
7
+
8
+ STYLE = <<~CSS
9
+ .fill-layout {
10
+ display: flex;
11
+ }
12
+
13
+ .fill-layout > * {
14
+ width: 100%;
15
+ height: 100%;
16
+ }
17
+
18
+ .fill-layout-horizontal {
19
+ flex-direction: row;
20
+ }
21
+
22
+ .fill-layout-vertical {
23
+ flex-direction: column;
24
+ }
25
+ CSS
26
+
27
+ attr_reader :type, :margin_width, :margin_height, :spacing
28
+
29
+ def initialize(parent, args)
30
+ super(parent, args)
31
+ @type = @args.first || :horizontal
32
+ self.margin_width = 15
33
+ self.margin_height = 15
34
+ @parent.css_classes << 'fill-layout'
35
+ @parent.css_classes << (horizontal? ? 'fill-layout-horizontal' : 'fill-layout-vertical')
36
+ @parent.dom_element.add_class('fill-layout')
37
+ @parent.dom_element.add_class(horizontal? ? 'fill-layout-horizontal' : 'fill-layout-vertical')
38
+ end
39
+
40
+ def horizontal?
41
+ @type == :horizontal
42
+ end
43
+
44
+ def vertical?
45
+ @type == :vertical
46
+ end
47
+
48
+ def margin_width=(pixels)
49
+ @margin_width = pixels
50
+ # Using padding for width since margin-right isn't getting respected with width 100%
51
+ @parent.dom_element.css('padding-left', @margin_width)
52
+ @parent.dom_element.css('padding-right', @margin_width)
53
+ end
54
+
55
+ def margin_height=(pixels)
56
+ @margin_height = pixels
57
+ @parent.dom_element.css('margin-top', @margin_height)
58
+ @parent.dom_element.css('margin-bottom', @margin_height)
59
+ end
60
+
61
+ def spacing=(spacing)
62
+ @spacing = spacing.to_i
63
+ # TODO implement changes to accomodate layout_data in the future
64
+ @parent.style_element.html css {
65
+ s("##{@parent.id} > *") {
66
+ if horizontal?
67
+ margin_right "#{@spacing}px"
68
+ elsif vertical?
69
+ margin_bottom "#{@spacing}px"
70
+ end
71
+ }
72
+ s("##{@parent.id} > :last-child") {
73
+ if horizontal?
74
+ margin_right 0
75
+ elsif vertical?
76
+ margin_bottom 0
77
+ end
78
+ }
79
+ }.to_s
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,79 @@
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/error'
23
+
24
+ module Glimmer
25
+ module SWT
26
+ # Proxy for org.eclipse.swt.graphics.Font
27
+ #
28
+ # This class can be optionally used with WidgetProxy to manipulate
29
+ # an SWT widget font (reusing its FontData but building a new Font)
30
+ #
31
+ # Otherwise, if no WidgetProxy is passed to constructor, it builds new FontData
32
+ #
33
+ # Invoking `#swt_font` returns the SWT Font object wrapped by this proxy
34
+ #
35
+ # Follows the Proxy Design Pattern
36
+ class FontProxy
37
+ ERROR_INVALID_FONT_STYLE = " is an invalid font style! Valid values are :normal, :bold, and :italic"
38
+ FONT_STYLES = [:normal, :bold, :italic]
39
+
40
+ attr_reader :widget_proxy, :font_properties
41
+
42
+ # Builds a new font proxy from passed in widget_proxy and font_properties hash,
43
+ #
44
+ # It begins with existing SWT widget font and amends it with font properties.
45
+ #
46
+ # Font properties consist of: :name, :height, and :style (one needed minimum)
47
+ #
48
+ # Style (:style value) can only be one of FontProxy::FONT_STYLES values:
49
+ # that is :normal, :bold, or :italic
50
+ def initialize(widget_proxy = nil, font_properties)
51
+ @widget_proxy = widget_proxy
52
+ @font_properties = font_properties.symbolize_keys
53
+ detect_invalid_font_property(font_properties)
54
+ end
55
+
56
+ def name
57
+ font_properties[:name]
58
+ end
59
+
60
+ def height
61
+ font_properties[:height]
62
+ end
63
+
64
+ def style
65
+ font_properties[:style]
66
+ end
67
+
68
+ private
69
+
70
+ def detect_invalid_font_property(font_properties)
71
+ [font_properties[:style]].flatten.select do |style|
72
+ style.is_a?(Symbol) || style.is_a?(String)
73
+ end.each do |style|
74
+ raise Error, style.to_s + ERROR_INVALID_FONT_STYLE if !FONT_STYLES.include?(style.to_sym)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -3,18 +3,19 @@ require 'glimmer/swt/layout_proxy'
3
3
  module Glimmer
4
4
  module SWT
5
5
  class GridLayoutProxy < LayoutProxy
6
- attr_reader :num_columns, :make_columns_equal_width, :horizontal_spacing, :vertical_spacing
6
+ attr_reader :num_columns, :make_columns_equal_width, :horizontal_spacing, :vertical_spacing, :margin_width, :margin_height
7
7
 
8
8
  def initialize(parent, args)
9
9
  super(parent, args)
10
- @horizontal_spacing = 10
11
- @vertical_spacing = 10
12
- @num_columns = @args.first || 1
10
+ self.horizontal_spacing = 10
11
+ self.vertical_spacing = 10
12
+ self.num_columns = @args.first || 1
13
13
  reapply
14
14
  end
15
15
 
16
16
  def num_columns=(columns)
17
17
  @num_columns = columns
18
+ # TODO do the following instead of reapply
18
19
  # @parent.add_css_class("num-columns-#{@num_columns}")
19
20
  reapply
20
21
  end
@@ -36,6 +37,35 @@ module Glimmer
36
37
  # @parent.add_css_class("vertical-spacing-#{@vertical_spacing}")
37
38
  reapply
38
39
  end
40
+
41
+ def margin_width=(pixels)
42
+ @margin_width = pixels
43
+ # Using padding for width since margin-right isn't getting respected with width 100%
44
+ @parent.dom_element.css('padding-left', @margin_width)
45
+ @parent.dom_element.css('padding-right', @margin_width)
46
+ end
47
+
48
+ def margin_height=(pixels)
49
+ @margin_height = pixels
50
+ @parent.dom_element.css('margin-top', @margin_height)
51
+ @parent.dom_element.css('margin-bottom', @margin_height)
52
+ end
53
+
54
+ def reapply
55
+ layout_css = <<~CSS
56
+ display: grid;
57
+ grid-template-columns: #{'auto ' * @num_columns.to_i};
58
+ grid-template-rows: min-content;
59
+ grid-row-gap: #{@vertical_spacing}px;
60
+ grid-column-gap: #{@horizontal_spacing}px;
61
+ justify-content: start;
62
+ align-items: start;
63
+ align-content: start;
64
+ CSS
65
+ layout_css.split(";").map(&:strip).map {|l| l.split(':').map(&:strip)}.each do |key, value|
66
+ @parent.dom_element.css(key, value) unless key.nil?
67
+ end
68
+ end
39
69
  end
40
70
  end
41
71
  end