glimmer-dsl-opal 0.8.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +640 -186
  5. data/VERSION +1 -1
  6. data/lib/display.rb +1 -1
  7. data/lib/glimmer-dsl-opal.rb +10 -5
  8. data/lib/glimmer-dsl-opal/ext/file.rb +1 -1
  9. data/lib/glimmer-dsl-opal/ext/glimmer/dsl/engine.rb +47 -0
  10. data/lib/glimmer-dsl-opal/samples/elaborate/contact_manager/contact_repository.rb +4 -4
  11. data/lib/glimmer-dsl-opal/samples/elaborate/tic_tac_toe.rb +2 -2
  12. data/lib/glimmer-dsl-opal/samples/hello/hello_browser.rb +1 -1
  13. data/lib/glimmer-dsl-opal/samples/hello/hello_button.rb +1 -1
  14. data/lib/glimmer-dsl-opal/samples/hello/hello_checkbox.rb +1 -1
  15. data/lib/glimmer-dsl-opal/samples/hello/hello_checkbox_group.rb +1 -1
  16. data/lib/glimmer-dsl-opal/samples/hello/hello_combo.rb +1 -1
  17. data/lib/glimmer-dsl-opal/samples/hello/hello_computed.rb +1 -1
  18. data/lib/glimmer-dsl-opal/samples/hello/hello_computed/contact.rb +21 -0
  19. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_shell.rb +1 -1
  20. data/lib/glimmer-dsl-opal/samples/hello/hello_custom_widget.rb +1 -1
  21. data/lib/glimmer-dsl-opal/samples/hello/hello_date_time.rb +1 -1
  22. data/lib/glimmer-dsl-opal/samples/hello/hello_dialog.rb +78 -0
  23. data/lib/glimmer-dsl-opal/samples/hello/hello_group.rb +1 -1
  24. data/lib/glimmer-dsl-opal/samples/hello/hello_list_multi_selection.rb +1 -1
  25. data/lib/glimmer-dsl-opal/samples/hello/hello_list_single_selection.rb +1 -1
  26. data/lib/glimmer-dsl-opal/samples/hello/hello_menu_bar.rb +241 -0
  27. data/lib/glimmer-dsl-opal/samples/hello/hello_message_box.rb +1 -1
  28. data/lib/glimmer-dsl-opal/samples/hello/hello_pop_up_context_menu.rb +1 -1
  29. data/lib/glimmer-dsl-opal/samples/hello/hello_radio.rb +1 -1
  30. data/lib/glimmer-dsl-opal/samples/hello/hello_radio_group.rb +1 -1
  31. data/lib/glimmer-dsl-opal/samples/hello/hello_tab.rb +1 -1
  32. data/lib/glimmer-dsl-opal/samples/hello/hello_table.rb +1 -1
  33. data/lib/glimmer-dsl-opal/samples/hello/hello_world.rb +4 -4
  34. data/lib/glimmer-dsl-swt.rb +1 -1
  35. data/lib/glimmer/config/opal_logger.rb +16 -0
  36. data/lib/glimmer/dsl/opal/async_exec_expression.rb +1 -1
  37. data/lib/glimmer/dsl/opal/block_property_expression.rb +1 -1
  38. data/lib/glimmer/dsl/opal/checkbox_group_selection_data_binding_expression.rb +1 -1
  39. data/lib/glimmer/dsl/opal/color_expression.rb +1 -1
  40. data/lib/glimmer/dsl/opal/custom_widget_expression.rb +1 -1
  41. data/lib/glimmer/dsl/opal/dialog_expression.rb +20 -0
  42. data/lib/glimmer/dsl/opal/display_expression.rb +1 -1
  43. data/lib/glimmer/dsl/opal/dsl.rb +1 -1
  44. data/lib/glimmer/dsl/opal/exec_expression.rb +1 -1
  45. data/lib/glimmer/dsl/opal/font_expression.rb +1 -1
  46. data/lib/glimmer/dsl/opal/menu_bar_expression.rb +1 -1
  47. data/lib/glimmer/dsl/opal/menu_expression.rb +1 -1
  48. data/lib/glimmer/dsl/opal/radio_group_selection_data_binding_expression.rb +1 -1
  49. data/lib/glimmer/dsl/opal/rgb_expression.rb +1 -1
  50. data/lib/glimmer/dsl/opal/rgba_expression.rb +1 -1
  51. data/lib/glimmer/dsl/opal/shell_expression.rb +0 -4
  52. data/lib/glimmer/dsl/opal/swt_expression.rb +4 -4
  53. data/lib/glimmer/dsl/opal/sync_exec_expression.rb +1 -1
  54. data/lib/glimmer/swt.rb +1 -1
  55. data/lib/glimmer/swt/color_proxy.rb +1 -1
  56. data/lib/glimmer/swt/control_editor.rb +1 -1
  57. data/lib/glimmer/swt/custom/checkbox_group.rb +1 -1
  58. data/lib/glimmer/swt/custom/radio_group.rb +1 -1
  59. data/lib/glimmer/swt/dialog_proxy.rb +173 -0
  60. data/lib/glimmer/swt/display_proxy.rb +8 -4
  61. data/lib/glimmer/swt/font_proxy.rb +1 -1
  62. data/lib/glimmer/swt/label_proxy.rb +22 -1
  63. data/lib/{glimmer-dsl-opal/ext/struct.rb → glimmer/swt/latest_dialog_proxy.rb} +17 -12
  64. data/lib/glimmer/swt/latest_message_box_proxy.rb +42 -0
  65. data/lib/glimmer/swt/latest_shell_proxy.rb +55 -0
  66. data/lib/glimmer/swt/layout_data_proxy.rb +4 -0
  67. data/lib/glimmer/swt/list_proxy.rb +0 -18
  68. data/lib/glimmer/swt/make_shift_shell_proxy.rb +1 -1
  69. data/lib/glimmer/swt/menu_item_proxy.rb +96 -9
  70. data/lib/glimmer/swt/menu_proxy.rb +136 -25
  71. data/lib/glimmer/swt/message_box_proxy.rb +31 -13
  72. data/lib/glimmer/swt/row_layout_proxy.rb +22 -2
  73. data/lib/glimmer/swt/shell_proxy.rb +16 -4
  74. data/lib/glimmer/swt/style_constantizable.rb +1 -1
  75. data/lib/glimmer/swt/swt_proxy.rb +1 -1
  76. data/lib/glimmer/swt/tab_folder_proxy.rb +1 -1
  77. data/lib/glimmer/swt/table_editor.rb +1 -1
  78. data/lib/glimmer/swt/table_item_proxy.rb +1 -1
  79. data/lib/glimmer/swt/table_proxy.rb +1 -1
  80. data/lib/glimmer/swt/widget_proxy.rb +14 -2
  81. data/lib/glimmer/ui/custom_shell.rb +2 -2
  82. data/lib/glimmer/ui/custom_widget.rb +1 -1
  83. data/lib/glimmer/util/proc_tracker.rb +1 -1
  84. data/lib/net/http.rb +30 -2
  85. data/lib/os.rb +1 -1
  86. metadata +33 -5
@@ -28,6 +28,14 @@ module Glimmer
28
28
  @shells ||= []
29
29
  end
30
30
 
31
+ def message_boxes
32
+ @message_boxes ||= []
33
+ end
34
+
35
+ def dialogs
36
+ @dialogs ||= []
37
+ end
38
+
31
39
  def render
32
40
  # No rendering as body is rendered as part of ShellProxy.. this class only serves as an SWT Display utility
33
41
  end
@@ -74,10 +82,6 @@ module Glimmer
74
82
  ]
75
83
  }
76
84
  end
77
-
78
- def shells
79
- @shells ||= []
80
- end
81
85
  end
82
86
  end
83
87
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Andy Maleh
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,3 +1,24 @@
1
+ # Copyright (c) 2020-2021 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/widget_proxy'
2
23
  # require 'glimmer/swt/image_proxy'
3
24
 
@@ -16,7 +37,7 @@ module Glimmer
16
37
  end
17
38
 
18
39
  def html_text
19
- text.gsub("\n", '<br />')
40
+ text&.gsub("\n", '<br />')
20
41
  end
21
42
 
22
43
  def background_image=(*image_options)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Andy Maleh
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -19,19 +19,24 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
- class Struct
23
- class << self
24
- alias new_original new
25
- def new(*args, &block)
26
- new_original(*args, &block).tap do |struct_class|
27
- if args.size >= 2 && args.last.is_a?(Hash) && args.last[:keyword_init]
28
- struct_class.define_method(:initialize) do |struct_class_keyword_args|
29
- struct_class_keyword_args.each do |attribute, value|
30
- send("#{attribute}=", value)
31
- end
32
- end
22
+ module Glimmer
23
+ module SWT
24
+ class LatestDialogProxy #< DialogProxy
25
+ # TODO consider overriding all methods from DialogProxy and proxying to them
26
+ # TODO consider the idea of promoting this object into the real dialog once Document is ready
27
+
28
+ def initialize(parent, args, block)
29
+ # No Op
30
+ end
31
+
32
+ def open
33
+ Document.ready? do
34
+ DisplayProxy.instance.dialogs.last&.open
33
35
  end
34
36
  end
37
+
35
38
  end
39
+
36
40
  end
41
+
37
42
  end
@@ -0,0 +1,42 @@
1
+ # Copyright (c) 2020-2021 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
+ class LatestMessageBoxProxy #< MessageBoxProxy
25
+ # TODO consider overriding all methods from MessageBoxProxy and proxying to them
26
+ # TODO consider the idea of promoting this object into the real message_box once Document is ready
27
+
28
+ def initialize(parent, args, block)
29
+ # No Op
30
+ end
31
+
32
+ def open
33
+ Document.ready? do
34
+ DisplayProxy.instance.message_boxes.last&.open
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright (c) 2020-2021 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
+ class LatestShellProxy #< ShellProxy
25
+ def initialize(parent, args, block)
26
+ # No Op
27
+ end
28
+
29
+ def method_missing(method, *args, &block)
30
+ if latest_shell.nil?
31
+ super(method, *args, &block)
32
+ else
33
+ latest_shell.send(method, *args, &block)
34
+ end
35
+ end
36
+
37
+ def respond_to?(method, *args, &block)
38
+ super || latest_shell&.respond_to?(method, *args, &block)
39
+ end
40
+
41
+ def open
42
+ Document.ready? do
43
+ latest_shell&.open
44
+ end
45
+ end
46
+
47
+ def latest_shell
48
+ @latest_shell ||= DisplayProxy.instance.shells.last
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -17,6 +17,8 @@ module Glimmer
17
17
  :grab_excess_vertical_space,
18
18
  :width_hint,
19
19
  :height_hint
20
+ alias width width_hint
21
+ alias height height_hint
20
22
 
21
23
  def initialize(parent, args)
22
24
  @parent = parent
@@ -35,12 +37,14 @@ module Glimmer
35
37
  @parent.dom_element.css('width', "#{@width_hint}px")
36
38
  # reapply
37
39
  end
40
+ alias width= width_hint=
38
41
 
39
42
  def height_hint=(height_hint)
40
43
  @height_hint = height_hint
41
44
  @parent.dom_element.css('height', "#{@height_hint}px")
42
45
  # reapply
43
46
  end
47
+ alias height= height_hint=
44
48
 
45
49
  def horizontal_alignment=(horizontal_alignment)
46
50
  @horizontal_alignment = horizontal_alignment
@@ -13,24 +13,6 @@ module Glimmer
13
13
  padding-left: 10px;
14
14
  padding-right: 10px;
15
15
  }
16
- li.menu-item {
17
- padding-left: initial;
18
- padding-right: initial;
19
- }
20
- .ui-menu {
21
- /* TODO consider auto-sizing in the future */
22
- font-size: initial;
23
- width: 150px;
24
- border-radius: 5px;
25
- }
26
- .ui-menu-item:first-child > .ui-menu-item-wrapper {
27
- border-top-left-radius: 5px;
28
- border-top-right-radius: 5px;
29
- }
30
- .ui-menu-item:last-child > .ui-menu-item-wrapper {
31
- border-bottom-left-radius: 5px;
32
- border-bottom-right-radius: 5px;
33
- }
34
16
  li.empty-list-item {
35
17
  color: transparent;
36
18
  }
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Andy Maleh
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Andy Maleh
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -30,20 +30,98 @@ module Glimmer
30
30
  # Follows the Proxy Design Pattern since it's a proxy for an HTML based menu
31
31
  # Follows the Adapter Design Pattern since it's adapting a Glimmer DSL for SWT widget
32
32
  class MenuItemProxy < WidgetProxy
33
+ STYLE = <<~CSS
34
+ .menu-item.disabled {
35
+ background-color: lightgrey;
36
+ color: grey;
37
+ }
38
+ .menu-item.disabled .menu, .menu-item.disabled .menu * {
39
+ display: none;
40
+ opacity: 0;
41
+ }
42
+ CSS
43
+
44
+ attr_accessor :accelerator # TODO consider doing something with it
45
+
46
+ def initialize(parent, args)
47
+ args.push(:push) if args.empty?
48
+ super(parent, args)
49
+ # TODO do not add the following event till post_add_content to avoid adding if already one on_widget_selected event existed
50
+ on_widget_selected {
51
+ # No Op, just trigger selection
52
+ }
53
+ end
54
+
33
55
  def post_initialize_child(child)
34
56
  @children << child
35
57
  end
36
58
 
59
+ def cascade?
60
+ args.include?(:cascade)
61
+ end
62
+
63
+ def push?
64
+ args.include?(:push)
65
+ end
66
+
67
+ def radio?
68
+ args.include?(:radio)
69
+ end
70
+
71
+ def check?
72
+ args.include?(:check)
73
+ end
74
+
75
+ def separator?
76
+ args.include?(:separator)
77
+ end
78
+
37
79
  def text
38
80
  @text
39
81
  end
40
82
 
41
83
  def text=(value)
42
84
  @text = value
43
- dom_element.html(html {div {value}}.to_s)
85
+ dom_element.find('.menu-item-text').html(@text)
44
86
  @text
45
87
  end
46
88
 
89
+ def selection
90
+ @selection
91
+ end
92
+
93
+ def selection=(value)
94
+ @selection = value
95
+ icon_suffix = check? ? 'check' : 'bullet'
96
+ dom_element.find('.menu-item-selection').toggle_class("ui-icon ui-icon-#{icon_suffix}", @selection)
97
+ @selection
98
+ end
99
+
100
+ def toggle_selection!
101
+ self.selection = !selection
102
+ end
103
+
104
+ def enabled=(value)
105
+ @enabled = value
106
+ dom_element.toggle_class('disabled', !@enabled)
107
+ @enabled
108
+ end
109
+
110
+ def div_content
111
+ div_attributes = {}
112
+ icon_suffix = check? ? 'check' : 'bullet'
113
+ div(div_attributes) {
114
+ unless separator? # empty content automatically gets a separator style in jQuery-UI
115
+ span(class: "menu-item-selection #{"ui-icon ui-icon-#{icon_suffix}" if selection}") {}
116
+ span(class: 'ui-menu-icon ui-icon ui-icon-caret-1-e') {} if cascade? && !parent.bar?
117
+ span(class: 'menu-item-text') {
118
+ @text
119
+ }
120
+ ''
121
+ end
122
+ }
123
+ end
124
+
47
125
  def root_menu
48
126
  the_menu = parent
49
127
  the_menu = the_menu.parent_menu until the_menu.root_menu?
@@ -60,9 +138,19 @@ module Glimmer
60
138
  event: 'mouseup',
61
139
  event_handler: -> (event_listener) {
62
140
  -> (event) {
63
- remove_event_listener_proxies
64
- root_menu.close
65
- event_listener.call(event)
141
+ if enabled && (push? || radio? || check?)
142
+ if check?
143
+ self.toggle_selection!
144
+ elsif radio? && !selection
145
+ parent.children.detect(&:selection)&.selection = false
146
+ self.selection = true
147
+ end
148
+ if !root_menu.bar?
149
+ remove_event_listener_proxies
150
+ root_menu.close
151
+ end
152
+ event_listener.call(event)
153
+ end
66
154
  }
67
155
  },
68
156
  },
@@ -74,11 +162,10 @@ module Glimmer
74
162
  end
75
163
 
76
164
  def dom
165
+ # TODO support rendering image
77
166
  @dom ||= html {
78
- li(id: id, class: name) {
79
- div {
80
- @text
81
- }
167
+ li(id: id, class: "#{name} #{'disabled' unless enabled}") {
168
+ div_content
82
169
  }
83
170
  }.to_s
84
171
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Andy Maleh
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -45,33 +45,85 @@ module Glimmer
45
45
  #
46
46
  # Follows the Proxy Design Pattern
47
47
  class MenuProxy < WidgetProxy
48
+ STYLE = <<~CSS
49
+ .menu.menu-bar {
50
+ position: absolute;
51
+ top: -30px;
52
+ border-radius: 0;
53
+ width: 100%;
54
+ }
55
+ .menu.menu-bar .menu {
56
+ border-radius: 0;
57
+ }
58
+ .menu-bar .menu-item {
59
+ width: 180px;
60
+ }
61
+ .menu-bar > .menu-item {
62
+ display: inline-block;
63
+ width: 150px;
64
+ }
65
+ li.menu-item {
66
+ padding-left: initial;
67
+ padding-right: initial;
68
+ }
69
+ .menu {
70
+ /* TODO consider auto-sizing in the future */
71
+ font-size: initial;
72
+ border-radius: 5px;
73
+ }
74
+ .menu:not(.menu-bar) {
75
+ width: 150px;
76
+ }
77
+ .menu-bar .ui-menu:not(.menu-bar) {
78
+ width: 180px;
79
+ }
80
+ .ui-menu-item:first-child > .ui-menu-item-wrapper {
81
+ border-top-left-radius: 5px;
82
+ border-top-right-radius: 5px;
83
+ }
84
+ .ui-menu-item:last-child > .ui-menu-item-wrapper {
85
+ border-bottom-left-radius: 5px;
86
+ border-bottom-right-radius: 5px;
87
+ }
88
+ .menu-bar .ui-menu-item:first-child > .ui-menu-item-wrapper {
89
+ border-top-left-radius: 0;
90
+ border-top-right-radius: 0;
91
+ }
92
+ .menu-bar .ui-menu-item:last-child > .ui-menu-item-wrapper {
93
+ border-bottom-left-radius: 0;
94
+ border-bottom-right-radius: 0;
95
+ }
96
+
97
+ CSS
98
+
48
99
  attr_reader :menu_item_proxy, :menu_parent
49
100
 
50
101
  def initialize(parent, args)
51
- # TODO handle :bar swt style
52
- # TODO handle :pop_up swt style
53
- # TODO handle :cascade swt style
102
+ # TODO refactor/simplify code below
54
103
  @children = []
55
104
  index = args.delete(args.last) if args.last.is_a?(Numeric)
56
- styles = args.map(&:to_sym)
57
- if !styles.include?(:bar) && !parent.is_a?(MenuProxy)
58
- styles = styles.unshift(:pop_up)
105
+ args = args.map {|arg| arg.is_a?(String) ? arg.to_sym : arg}
106
+ if parent.is_a?(ShellProxy)
107
+ args = args.unshift(:bar)
108
+ elsif parent.is_a?(MenuProxy)
109
+ args = args.unshift(:drop_down)
110
+ else
111
+ args = args.unshift(:pop_up)
59
112
  end
60
-
61
113
  if parent.is_a?(MenuProxy)
62
114
  @menu_item_proxy = SWT::WidgetProxy.for('menu_item', parent, [:cascade] + [index].compact)
63
- super(@menu_item_proxy)
115
+ super(@menu_item_proxy, args)
64
116
  @menu_item_proxy.menu = self
65
117
  elsif parent.is_a?(ShellProxy)
66
- super(parent, style('menu', styles))
67
- else
68
- super(parent)
118
+ super(parent, args)
119
+ else # widget pop up
120
+ super(parent, args)
69
121
  end
70
122
 
71
- if styles.include?(:bar)
123
+ if bar?
72
124
  # Assumes a parent shell
73
125
  parent.menu_bar = self
74
- elsif styles.include?(:pop_up)
126
+ elsif pop_up?
75
127
  parent.menu = self
76
128
  end
77
129
  # TODO IMPLEMENT PROPERLY
@@ -80,6 +132,18 @@ module Glimmer
80
132
  # }
81
133
  end
82
134
 
135
+ def bar?
136
+ args.include?(:bar)
137
+ end
138
+
139
+ def pop_up?
140
+ args.include?(:pop_up)
141
+ end
142
+
143
+ def drop_down?
144
+ args.include?(:drop_down)
145
+ end
146
+
83
147
  def text
84
148
  @menu_item_proxy&.text
85
149
  end
@@ -88,6 +152,20 @@ module Glimmer
88
152
  @menu_item_proxy&.text = text_value
89
153
  end
90
154
 
155
+ def enabled
156
+ if drop_down?
157
+ menu_item_proxy.enabled
158
+ else
159
+ true
160
+ end
161
+ end
162
+
163
+ def enabled=(value)
164
+ if drop_down?
165
+ menu_item_proxy.enabled = value
166
+ end
167
+ end
168
+
91
169
  def can_handle_observation_request?(observation_request, super_only: false)
92
170
  super_result = super(observation_request)
93
171
  if observation_request.start_with?('on_') && !super_result && !super_only
@@ -115,21 +193,42 @@ module Glimmer
115
193
  end
116
194
  end
117
195
 
118
- def render
196
+ def post_add_content
197
+ if bar?
198
+ # delay this till all children rendered (perhaps post_add_content block)
199
+ parent_dom_element.css('position', 'relative')
200
+ parent_dom_element.css('margin-top', '30px')
201
+ redraw
202
+ `$(#{path}).menu({
203
+ position: { my: "top", at: "bottom" },
204
+ icons: { submenu: "ui-icon-blank" }
205
+ });`
206
+ the_element = dom_element
207
+ the_element.on('mouseover') { |event|
208
+ if event.page_x.between?(the_element.offset.left, the_element.offset.left + the_element.width) and
209
+ event.page_y.between?(the_element.offset.top, the_element.offset.top + the_element.height)
210
+ `$(#{path}).menu('option', 'position', { my: 'left top', at: 'left bottom' })`
211
+ end
212
+ }
213
+ the_element.on('menublur') {
214
+ `$(#{path}).menu('option', 'position', { my: 'left top', at: 'right top' })`
215
+ }
216
+ minimum_width = children.to_a.map(&:dom_element).map(&:width).reduce(:+)
217
+ the_element.css('min-width', minimum_width)
218
+ end
219
+ end
220
+
221
+ def render(custom_parent_dom_element: nil, brand_new: false)
119
222
  # TODO attach to top nav bar if parent is shell
120
223
  # TODO attach listener to parent to display on right click
121
- if parent.is_a?(MenuProxy) || parent.is_a?(MenuItemProxy) || parent.menu_requested?
122
- super
123
- if root_menu?
124
- id_css = "##{id}"
125
- `$(#{id_css}).menu();`
224
+ if parent.is_a?(MenuProxy) || parent.is_a?(MenuItemProxy) || parent.menu_requested? || parent.is_a?(ShellProxy)
225
+ super(custom_parent_dom_element: custom_parent_dom_element, brand_new: brand_new)
226
+ if root_menu? && !bar?
227
+ `$(#{path}).menu();`
126
228
  @close_event_handler = lambda do |event|
127
- if event.target.parents('.ui-menu').empty?
128
- close
129
- end
229
+ close if event.target.parents('.ui-menu').empty?
130
230
  end
131
231
  Element['body'].on('click', &@close_event_handler)
132
- @menu_initialized = true
133
232
  end
134
233
  end
135
234
  end
@@ -143,6 +242,12 @@ module Glimmer
143
242
  !parent.is_a?(MenuProxy) && !parent.is_a?(MenuItemProxy)
144
243
  end
145
244
 
245
+ def root_menu
246
+ the_menu = self
247
+ the_menu = the_menu.parent_menu until the_menu.root_menu?
248
+ the_menu
249
+ end
250
+
146
251
  def parent_menu
147
252
  parent.parent unless root_menu?
148
253
  end
@@ -152,11 +257,17 @@ module Glimmer
152
257
  end
153
258
 
154
259
  def dom
260
+ css_class = name
261
+ css_class += ' menu-bar' if bar?
262
+ css_class += ' menu-drop-down' if drop_down?
263
+ css_class += ' menu-pop-up' if pop_up?
155
264
  @dom ||= html {
156
- ul(id: id, class: name) {
265
+ ul(id: id, class: css_class) {
157
266
  }
158
267
  }.to_s
159
268
  end
160
269
  end
270
+
271
+ MenuBarProxy = MenuProxy
161
272
  end
162
273
  end