glimmer-dsl-swt 4.17.5.0 → 4.17.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -2
  3. data/README.md +250 -83
  4. data/VERSION +1 -1
  5. data/glimmer-dsl-swt.gemspec +20 -5
  6. data/lib/glimmer/data_binding/tree_items_binding.rb +20 -2
  7. data/lib/glimmer/dsl/swt/checkbox_group_selection_data_binding_expression.rb +61 -0
  8. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +2 -0
  9. data/lib/glimmer/dsl/swt/dialog_expression.rb +1 -0
  10. data/lib/glimmer/dsl/swt/directory_dialog_expression.rb +48 -0
  11. data/lib/glimmer/dsl/swt/dsl.rb +2 -0
  12. data/lib/glimmer/dsl/swt/file_dialog_expression.rb +48 -0
  13. data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +61 -0
  14. data/lib/glimmer/dsl/swt/shell_expression.rb +3 -3
  15. data/lib/glimmer/dsl/swt/widget_expression.rb +8 -8
  16. data/lib/glimmer/swt/custom/checkbox_group.rb +181 -0
  17. data/lib/glimmer/swt/custom/code_text.rb +39 -31
  18. data/lib/glimmer/swt/custom/radio_group.rb +176 -0
  19. data/lib/glimmer/swt/directory_dialog_proxy.rb +65 -0
  20. data/lib/glimmer/swt/expand_item_proxy.rb +0 -1
  21. data/lib/glimmer/swt/file_dialog_proxy.rb +66 -0
  22. data/lib/glimmer/swt/menu_proxy.rb +4 -4
  23. data/lib/glimmer/swt/shell_proxy.rb +5 -5
  24. data/lib/glimmer/swt/tab_item_proxy.rb +3 -3
  25. data/lib/glimmer/swt/widget_proxy.rb +27 -27
  26. data/lib/glimmer/ui/custom_shell.rb +3 -3
  27. data/lib/glimmer/ui/custom_widget.rb +3 -0
  28. data/samples/elaborate/meta_sample.rb +24 -19
  29. data/samples/hello/hello_checkbox.rb +85 -0
  30. data/samples/hello/hello_checkbox_group.rb +68 -0
  31. data/samples/hello/hello_combo.rb +12 -12
  32. data/samples/hello/hello_directory_dialog.rb +60 -0
  33. data/samples/hello/hello_expand_bar.rb +3 -1
  34. data/samples/hello/hello_file_dialog.rb +60 -0
  35. data/samples/hello/hello_group.rb +104 -0
  36. data/samples/hello/hello_list_multi_selection.rb +23 -23
  37. data/samples/hello/hello_list_single_selection.rb +18 -17
  38. data/samples/hello/hello_radio.rb +108 -0
  39. data/samples/hello/hello_radio_group.rb +84 -0
  40. data/samples/hello/hello_world.rb +3 -3
  41. metadata +19 -4
@@ -0,0 +1,181 @@
1
+ # Copyright (c) 2007-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/ui/custom_widget'
23
+
24
+ module Glimmer
25
+ module SWT
26
+ module Custom
27
+ # A custom widget rendering a group of checkboxes generated via data-binding
28
+ class CheckboxGroup
29
+ include Glimmer::UI::CustomWidget
30
+
31
+ body {
32
+ composite # just an empty composite to hold checkboxs upon data-binding `selection`
33
+ }
34
+
35
+ def items=(text_array)
36
+ selection_value = selection
37
+ @items = Array[*text_array]
38
+ build_checkboxes
39
+ end
40
+
41
+ def items
42
+ @items || []
43
+ end
44
+
45
+ def selection=(selection_texts)
46
+ items.count.times do |index|
47
+ checkbox = checkboxes[index]
48
+ item = items[index]
49
+ label_text = labels[index]&.text
50
+ checkbox.selection = selection_texts.to_a.include?(label_text)
51
+ end
52
+ selection_texts
53
+ end
54
+
55
+ def selection
56
+ selection_indices.map do |selection_index|
57
+ labels[selection_index]&.text
58
+ end
59
+ end
60
+
61
+ def selection_indices=(indices)
62
+ self.selection=(indices.to_a.map {|index| items[index]})
63
+ end
64
+ alias select selection_indices=
65
+
66
+ def selection_indices
67
+ checkboxes.each_with_index.map do |checkbox, index|
68
+ index if checkbox.selection
69
+ end.to_a.compact
70
+ end
71
+
72
+ def checkboxes
73
+ @checkboxes ||= []
74
+ end
75
+ alias checks checkboxes
76
+
77
+ def labels
78
+ @labels ||= []
79
+ end
80
+
81
+ def can_handle_observation_request?(observation_request)
82
+ checkboxes.first&.can_handle_observation_request?(observation_request) || super(observation_request)
83
+ end
84
+
85
+ def handle_observation_request(observation_request, &block)
86
+ observation_requests << [observation_request, block]
87
+ delegate_observation_request_to_checkboxes(observation_request, &block)
88
+ super
89
+ end
90
+
91
+ def delegate_observation_request_to_checkboxes(observation_request, &block)
92
+ if observation_request != 'on_widget_disposed'
93
+ checkboxes.count.times do |index|
94
+ checkbox = checkboxes[index]
95
+ label = labels[index]
96
+ listener_block = lambda do |event|
97
+ event.widget = self.swt_widget
98
+ block.call(event)
99
+ end
100
+ if observation_request == 'on_widget_selected'
101
+ checkbox.handle_observation_request(observation_request, &listener_block) if checkbox.can_handle_observation_request?(observation_request)
102
+ label.handle_observation_request('on_mouse_up', &listener_block)
103
+ else
104
+ checkbox.handle_observation_request(observation_request, &listener_block) if checkbox.can_handle_observation_request?(observation_request)
105
+ label.handle_observation_request(observation_request, &listener_block) if label.can_handle_observation_request?(observation_request)
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ def observation_requests
112
+ @observation_requests ||= Set.new
113
+ end
114
+
115
+ def has_attribute?(attribute_name, *args)
116
+ (@composites.to_a + @checkboxes.to_a + @labels.to_a).map do |widget_proxy|
117
+ return true if widget_proxy.has_attribute?(attribute_name, *args)
118
+ end
119
+ super
120
+ end
121
+
122
+ def set_attribute(attribute_name, *args)
123
+ excluded_attributes = ['selection']
124
+ unless excluded_attributes.include?(attribute_name.to_s)
125
+ (@composites.to_a + @checkboxes.to_a + @labels.to_a).each do |widget_proxy|
126
+ widget_proxy.set_attribute(attribute_name, *args) if widget_proxy.has_attribute?(attribute_name, *args)
127
+ end
128
+ end
129
+ super
130
+ end
131
+
132
+ private
133
+
134
+ def build_checkboxes
135
+ current_selection = selection
136
+ @composites.to_a.each(&:dispose)
137
+ @checkboxes = []
138
+ @labels = []
139
+ @composites = []
140
+ items.each do |item|
141
+ body_root.content {
142
+ @composites << composite {
143
+ grid_layout(2, false) {
144
+ margin_width 0
145
+ margin_height 0
146
+ horizontal_spacing 0
147
+ vertical_spacing 0
148
+ }
149
+ checkboxes << checkbox { |checkbox_proxy|
150
+ on_widget_selected {
151
+ self.selection_indices = checkboxes.each_with_index.map {|cb, i| i if cb.selection}.to_a.compact
152
+ }
153
+ }
154
+ labels << label { |label_proxy|
155
+ layout_data :fill, :center, true, false
156
+ text item
157
+ on_mouse_up { |event|
158
+ found_text = labels.each_with_index.detect {|l, i| event.widget == l.swt_widget}[0]&.text
159
+ selection_values = self.selection
160
+ if selection_values.include?(found_text)
161
+ selection_values.delete(found_text)
162
+ else
163
+ selection_values << found_text
164
+ end
165
+ self.selection = selection_values
166
+ }
167
+ }
168
+ }
169
+ }
170
+ end
171
+ observation_requests.to_a.each do |observation_request, block|
172
+ delegate_observation_request_to_checkboxes(observation_request, &block)
173
+ end
174
+ self.selection = current_selection
175
+ end
176
+ end
177
+
178
+ CheckGroup = CheckboxGroup
179
+ end
180
+ end
181
+ end
@@ -8,20 +8,20 @@ module Glimmer
8
8
  include Glimmer::UI::CustomWidget
9
9
 
10
10
  SYNTAX_COLOR_MAP = {
11
- Builtin: [215,58,73],
12
- Class: [3,47,98],
13
- Constant: [0,92,197],
11
+ Builtin: [215,58,73],
12
+ Class: [3,47,98],
13
+ Constant: [0,92,197],
14
14
  Double: [0,92,197],
15
15
  Escape: [:red],
16
- Function: [:blue],
17
- Instance: [227,98,9],
18
- Integer: [:blue],
16
+ Function: [:blue],
17
+ Instance: [227,98,9],
18
+ Integer: [:blue],
19
19
  Interpol: [:blue],
20
- Keyword: [:blue],
20
+ Keyword: [:blue],
21
21
  Name: [111,66,193], #purple
22
- Operator: [:red],
22
+ Operator: [:red],
23
23
  Pseudo: [:dark_red],
24
- Punctuation: [:blue],
24
+ Punctuation: [:blue],
25
25
  Single: [106,115,125], # Also, Comments
26
26
  Symbol: [:dark_green],
27
27
  Text: [75, 75, 75],
@@ -38,29 +38,32 @@ module Glimmer
38
38
  swt_widget&.text
39
39
  end
40
40
 
41
- def syntax_highlighting
41
+ def syntax_highlighting
42
42
  return [] if text.to_s.strip.empty?
43
- code = text
44
- return @syntax_highlighting if @last_code == code
45
- @last_code = code
46
- @lexer ||= Rouge::Lexer.find_fancy('ruby', code)
47
- lex = @lexer.lex(code).to_a
48
- code_size = 0
43
+ return @syntax_highlighting if already_syntax_highlighted?
44
+ @last_text = text
45
+ @lexer ||= Rouge::Lexer.find_fancy('ruby', text)
46
+ lex = @lexer.lex(text).to_a
47
+ text_size = 0
49
48
  lex_hashes = lex.map do |pair|
50
49
  {token_type: pair.first, token_text: pair.last}
51
50
  end.each do |hash|
52
- hash[:token_index] = code_size
53
- code_size += hash[:token_text].size
51
+ hash[:token_index] = text_size
52
+ text_size += hash[:token_text].size
54
53
  end
55
- code_lines = code.split("\n")
54
+ text_lines = text.split("\n")
56
55
  line_index = 0
57
- @syntax_highlighting = code_lines_map = code_lines.reduce({}) do |hash, line|
56
+ @syntax_highlighting = text_lines_map = text_lines.reduce({}) do |hash, line|
58
57
  line_hashes = []
59
58
  line_hashes << lex_hashes.shift while lex_hashes.any? && lex_hashes.first[:token_index].between?(line_index, line_index + line.size)
60
59
  hash.merge(line_index => line_hashes).tap do
61
60
  line_index += line.size + 1
62
- end
63
- end
61
+ end
62
+ end
63
+ end
64
+
65
+ def already_syntax_highlighted?
66
+ @last_text == text
64
67
  end
65
68
 
66
69
  before_body {
@@ -77,16 +80,21 @@ module Glimmer
77
80
  bottom_margin 5
78
81
 
79
82
  on_line_get_style { |line_style_event|
80
- styles = []
81
- syntax_highlighting[line_style_event.lineOffset].to_a.each do |token_hash|
82
- start_index = token_hash[:token_index]
83
- size = token_hash[:token_text].size
84
- token_color = SYNTAX_COLOR_MAP[token_hash[:token_type].name] || [:black]
85
- token_color = color(*token_color).swt_color
86
- styles << StyleRange.new(start_index, size, token_color, nil)
83
+ @styles ||= {}
84
+ @styles = {} unless already_syntax_highlighted?
85
+ if @styles[line_style_event.lineOffset].nil?
86
+ styles = []
87
+ syntax_highlighting[line_style_event.lineOffset].to_a.each do |token_hash|
88
+ start_index = token_hash[:token_index]
89
+ size = token_hash[:token_text].size
90
+ token_color = SYNTAX_COLOR_MAP[token_hash[:token_type].name] || [:black]
91
+ token_color = color(*token_color).swt_color
92
+ styles << StyleRange.new(start_index, size, token_color, nil)
93
+ end
94
+ @styles[line_style_event.lineOffset] = styles.to_java(StyleRange)
87
95
  end
88
- line_style_event.styles = styles.to_java(StyleRange) unless styles.empty?
89
- }
96
+ line_style_event.styles = @styles[line_style_event.lineOffset] unless @styles[line_style_event.lineOffset].empty?
97
+ }
90
98
  }
91
99
  }
92
100
  end
@@ -0,0 +1,176 @@
1
+ # Copyright (c) 2007-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/ui/custom_widget'
23
+
24
+ module Glimmer
25
+ module SWT
26
+ module Custom
27
+ # A custom widget rendering a group of radios generated via data-binding
28
+ class RadioGroup
29
+ include Glimmer::UI::CustomWidget
30
+
31
+ body {
32
+ composite # just an empty composite to hold radios upon data-binding `selection`
33
+ }
34
+
35
+ def items=(text_array)
36
+ selection_value = selection
37
+ @items = Array[*text_array]
38
+ build_radios
39
+ end
40
+
41
+ def items
42
+ @items || []
43
+ end
44
+
45
+ def selection=(text)
46
+ radios.count.times do |index|
47
+ radio = radios[index]
48
+ item = items[index]
49
+ radio.selection = item == text
50
+ end
51
+ end
52
+
53
+ def selection
54
+ selection_value = labels[selection_index]&.text unless selection_index == -1
55
+ selection_value.to_s
56
+ end
57
+
58
+ def selection_index=(index)
59
+ self.selection=(items[index])
60
+ end
61
+ alias select selection_index=
62
+
63
+ def selection_index
64
+ radios.index(radios.detect(&:selection)) || -1
65
+ end
66
+
67
+ def radios
68
+ @radios ||= []
69
+ end
70
+
71
+ def labels
72
+ @labels ||= []
73
+ end
74
+
75
+ def can_handle_observation_request?(observation_request)
76
+ radios.first&.can_handle_observation_request?(observation_request) || super(observation_request)
77
+ end
78
+
79
+ def handle_observation_request(observation_request, &block)
80
+ observation_requests << [observation_request, block]
81
+ delegate_observation_request_to_radios(observation_request, &block)
82
+ super
83
+ end
84
+
85
+ def delegate_observation_request_to_radios(observation_request, &block)
86
+ if observation_request != 'on_widget_disposed'
87
+ radios.count.times do |index|
88
+ radio = radios[index]
89
+ label = labels[index]
90
+ if observation_request == 'on_widget_selected'
91
+ radio_block = lambda do |event|
92
+ if event.widget.selection || selection_index == -1
93
+ event.widget = self.swt_widget
94
+ block.call(event)
95
+ end
96
+ end
97
+ label_block = lambda do |event|
98
+ self.selection_index = index
99
+ block.call(event)
100
+ end
101
+ radio.handle_observation_request(observation_request, &radio_block) if radio.can_handle_observation_request?(observation_request)
102
+ label.handle_observation_request('on_mouse_up', &label_block)
103
+ else
104
+ listener_block = lambda do |event|
105
+ event.widget = self.swt_widget
106
+ block.call(event)
107
+ end
108
+ radio.handle_observation_request(observation_request, &listener_block) if radio.can_handle_observation_request?(observation_request)
109
+ label.handle_observation_request(observation_request, &listener_block) if label.can_handle_observation_request?(observation_request)
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ def observation_requests
116
+ @observation_requests ||= Set.new
117
+ end
118
+
119
+ def has_attribute?(attribute_name, *args)
120
+ (@composites.to_a + @radios.to_a + @labels.to_a).map do |widget_proxy|
121
+ return true if widget_proxy.has_attribute?(attribute_name, *args)
122
+ end
123
+ super
124
+ end
125
+
126
+ def set_attribute(attribute_name, *args)
127
+ excluded_attributes = ['selection']
128
+ unless excluded_attributes.include?(attribute_name.to_s)
129
+ (@composites.to_a + @radios.to_a + @labels.to_a).each do |widget_proxy|
130
+ widget_proxy.set_attribute(attribute_name, *args) if widget_proxy.has_attribute?(attribute_name, *args)
131
+ end
132
+ end
133
+ super
134
+ end
135
+
136
+ private
137
+
138
+ def build_radios
139
+ current_selection = selection
140
+ @composites.to_a.each(&:dispose)
141
+ @radios = []
142
+ @labels = []
143
+ @composites = []
144
+ items.each do |item|
145
+ body_root.content {
146
+ @composites << composite {
147
+ grid_layout(2, false) {
148
+ margin_width 0
149
+ margin_height 0
150
+ horizontal_spacing 0
151
+ vertical_spacing 0
152
+ }
153
+ radios << radio { |radio_proxy|
154
+ on_widget_selected {
155
+ self.selection = items[radios.index(radio_proxy)]
156
+ }
157
+ }
158
+ labels << label { |label_proxy|
159
+ layout_data :fill, :center, true, false
160
+ text item
161
+ on_mouse_up {
162
+ self.selection = label_proxy.text
163
+ }
164
+ }
165
+ }
166
+ }
167
+ end
168
+ observation_requests.to_a.each do |observation_request, block|
169
+ delegate_observation_request_to_radios(observation_request, &block)
170
+ end
171
+ self.selection = current_selection
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end