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,17 +7,21 @@ module Glimmer
7
7
 
8
8
  def text=(value)
9
9
  @text = value
10
- redraw
10
+ dom_element.html(value)
11
11
  end
12
12
 
13
13
  def element
14
14
  'label'
15
15
  end
16
16
 
17
- def dom
17
+ def alignment
18
+ [:left, :center, :right].detect {|value| args.detect { |arg| SWTProxy[value] == arg } }
19
+ end
20
+
21
+ def dom
18
22
  label_text = @text
19
23
  label_id = id
20
- label_style = css
24
+ label_style = "text-align: #{alignment};"
21
25
  label_class = name
22
26
  @dom ||= html {
23
27
  label(id: label_id, style: label_style, class: label_class) {
@@ -31,8 +31,14 @@ module Glimmer
31
31
 
32
32
  def initialize(parent, args)
33
33
  @parent = parent
34
- @args = args
34
+ @parent.css_classes.each do |css_class|
35
+ @parent.remove_css_class(css_class) if css_class.include?('layout')
36
+ end
37
+ @args = args
35
38
  @parent.add_css_class(css_class)
39
+ @parent.layout = self
40
+ self.margin_width = 15 if respond_to?(:margin_width=)
41
+ self.margin_height = 15 if respond_to?(:margin_height=)
36
42
  end
37
43
 
38
44
  def css_class
@@ -40,21 +46,17 @@ module Glimmer
40
46
  end
41
47
 
42
48
  def reapply
43
- layout_css = <<~CSS
44
- display: grid;
45
- grid-template-columns: #{'auto ' * @num_columns.to_i};
46
- grid-row-gap: #{@vertical_spacing}px;
47
- grid-column-gap: #{@horizontal_spacing}px;
48
- justify-content: start;
49
- CSS
50
- layout_css.split(";").map(&:strip).map {|l| l.split(':').map(&:strip)}.each do |key, value|
51
- unless key.nil?
52
- @parent.dom_element.css(key, value)
53
- end
54
- end
49
+ # subclasses can override this
50
+ end
51
+
52
+ # Decorates widget dom. Subclasses may override. Returns widget dom by default.
53
+ def dom(widget_dom)
54
+ widget_dom
55
55
  end
56
56
  end
57
57
  end
58
58
  end
59
59
 
60
60
  require 'glimmer/swt/grid_layout_proxy'
61
+ require 'glimmer/swt/fill_layout_proxy'
62
+ require 'glimmer/swt/row_layout_proxy'
@@ -13,7 +13,18 @@ module Glimmer
13
13
 
14
14
  def items=(items)
15
15
  @items = items.map {|item| item.strip == '' ? ITEM_EMPTY : item}
16
- redraw # consider repopulating li's instead of redrawing when li's are available.
16
+ list_selection = selection
17
+ items_dom = @items.to_a.each_with_index.map do |item, index|
18
+ li_class = ''
19
+ li_class += ' selected' if list_selection.include?(item)
20
+ li_class += ' empty-list-item' if item == ITEM_EMPTY
21
+ html {
22
+ li(class: li_class) {
23
+ item
24
+ }
25
+ }.to_s
26
+ end
27
+ dom_element.html(items_dom)
17
28
  end
18
29
 
19
30
  def index_of(item)
@@ -23,7 +34,11 @@ module Glimmer
23
34
  # used for multi-selection taking an array
24
35
  def selection=(selection)
25
36
  @selection = selection
26
- redraw
37
+ dom_element.find('li').remove_class('selected')
38
+ @selection.each do |item|
39
+ index = @items.index(item)
40
+ dom_element.find("li:nth-child(#{index + 1})").add_class('selected')
41
+ end
27
42
  end
28
43
 
29
44
  # used for single selection taking an index
@@ -60,21 +75,11 @@ module Glimmer
60
75
  end
61
76
 
62
77
  def dom
63
- list_items = @items
64
78
  list_id = id
65
79
  list_style = css
66
80
  list_selection = selection
67
81
  @dom ||= html {
68
82
  ul(id: list_id, class: name, style: list_style) {
69
- list_items.to_a.each_with_index do |item, index|
70
- li_class = ''
71
- li_class += ' selected' if list_selection.include?(item)
72
- li_class += ' empty-list-item' if item == ITEM_EMPTY
73
- li(class: li_class) {
74
- item
75
- }
76
- end
77
- nil #TODO look into glimmer-dsl-xml and why it doesn't ignore collections like each_with_index
78
83
  }
79
84
  }.to_s
80
85
  end
@@ -10,8 +10,6 @@ module Glimmer
10
10
  @parent = parent
11
11
  @args = args
12
12
  @children = Set.new
13
- @css_classes = Set.new(['modal', name])
14
- @css = ''
15
13
  @enabled = true
16
14
  content do
17
15
  on_widget_selected {
@@ -22,12 +20,12 @@ module Glimmer
22
20
 
23
21
  def text=(txt)
24
22
  @text = txt
25
- redraw if @dom
23
+ dom_element.find('.modal-content .text').html(@text)
26
24
  end
27
25
 
28
26
  def message=(msg)
29
27
  @message = msg
30
- redraw if @dom
28
+ dom_element.find('.modal-content .message').html(@text)
31
29
  end
32
30
 
33
31
  def document
@@ -120,8 +118,7 @@ module Glimmer
120
118
  modal_style = css
121
119
  modal_text = text
122
120
  modal_message = message
123
- modal_css_classes = css_classes
124
- modal_class = modal_css_classes.to_a.join(' ')
121
+ modal_class = ['modal', name].join(' ')
125
122
  @dom ||= html {
126
123
  div(id: modal_id, style: modal_style, class: modal_class) {
127
124
  style(class: 'modal-style') {
@@ -131,7 +128,7 @@ module Glimmer
131
128
  header(class: 'text') {
132
129
  modal_text
133
130
  }
134
- tag(_name: 'p', id: 'message') {
131
+ tag(_name: 'p', id: 'message', class: 'message') {
135
132
  modal_message
136
133
  }
137
134
  input(type: 'button', class: 'close', autofocus: 'autofocus', value: 'OK')
@@ -0,0 +1,105 @@
1
+ require 'glimmer/swt/layout_proxy'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ class RowLayoutProxy < LayoutProxy
6
+ include Glimmer
7
+
8
+ STYLE = <<~CSS
9
+ .row-layout {
10
+ display: flex;
11
+ }
12
+
13
+ .row-layout-pack {
14
+ display: initial;
15
+ }
16
+
17
+ .row-layout-horizontal {
18
+ flex-direction: row;
19
+ }
20
+
21
+ .row-layout-horizontal.row-layout-pack {
22
+ flex-direction: none;
23
+ }
24
+
25
+ .row-layout-vertical {
26
+ flex-direction: column;
27
+ }
28
+
29
+ .row-layout-vertical.row-layout-pack {
30
+ flex-direction: none;
31
+ }
32
+ CSS
33
+
34
+ attr_reader :type, :margin_width, :margin_height, :spacing, :pack
35
+
36
+ def initialize(parent, args)
37
+ super(parent, args)
38
+ @type = @args.first || :horizontal
39
+ @marign_width = 15
40
+ @margin_height = 15
41
+ self.pack = true
42
+ @parent.dom_element.add_class('row-layout')
43
+ @parent.dom_element.add_class(horizontal? ? 'row-layout-horizontal' : 'row-layout-vertical')
44
+ end
45
+
46
+ def horizontal?
47
+ @type == :horizontal
48
+ end
49
+
50
+ def vertical?
51
+ @type == :vertical
52
+ end
53
+
54
+ def dom(widget_dom)
55
+ dom_result = widget_dom
56
+ dom_result += '<br />' if vertical? && @pack
57
+ dom_result
58
+ end
59
+
60
+ def pack=(value)
61
+ @pack = value
62
+ if @pack
63
+ @parent.dom_element.add_class('row-layout-pack')
64
+ else
65
+ @parent.dom_element.remove_class('row-layout-pack')
66
+ end
67
+ end
68
+
69
+ def margin_width=(pixels)
70
+ @margin_width = pixels
71
+ # Using padding for width since margin-right isn't getting respected with width 100%
72
+ @parent.dom_element.css('padding-left', @margin_width)
73
+ @parent.dom_element.css('padding-right', @margin_width)
74
+ end
75
+
76
+ def margin_height=(pixels)
77
+ @margin_height = pixels
78
+ @parent.dom_element.css('margin-top', @margin_height)
79
+ @parent.dom_element.css('margin-bottom', @margin_height)
80
+ end
81
+
82
+ def spacing=(spacing)
83
+ @spacing = spacing.to_i
84
+ # TODO implement changes to accomodate layout_data in the future
85
+ @parent.style_element.html css {
86
+ s("##{@parent.id} > *") {
87
+ if horizontal?
88
+ margin_right "#{@spacing}px"
89
+ elsif vertical?
90
+ margin_bottom "#{@spacing}px"
91
+ end
92
+ }
93
+ s("##{@parent.id} > :last-child") {
94
+ if horizontal?
95
+ margin_right 0
96
+ elsif vertical?
97
+ margin_bottom 0
98
+ end
99
+ }
100
+ }.to_s
101
+ end
102
+
103
+ end
104
+ end
105
+ end
@@ -1,19 +1,25 @@
1
- require 'glimmer/swt/widget_proxy'
1
+ require 'glimmer/swt/widget_proxy'
2
2
  require 'glimmer/swt/point'
3
3
 
4
4
  module Glimmer
5
5
  module SWT
6
- class ShellProxy < WidgetProxy
6
+ class ShellProxy < CompositeProxy
7
7
  # TODO consider renaming to ShellProxy to match SWT API
8
8
  attr_reader :minimum_size
9
9
 
10
+ WIDTH_MIN = 130
11
+ HEIGHT_MIN = 0
12
+
10
13
  def initialize(args)
11
14
  @args = args
12
15
  @children = []
13
- # Document.ready? do
16
+ # Document.ready? do end # TODO consider embedding this jQuery call in so outside consumers don't have to use it
14
17
  Document.find('body').empty unless ENV['RUBY_ENV'] == 'test'
15
- redraw
16
- # end
18
+ render
19
+ @layout = FillLayoutProxy.new(self, [])
20
+ @layout.margin_width = 0
21
+ @layout.margin_height = 0
22
+ self.minimum_size = Point.new(WIDTH_MIN, HEIGHT_MIN)
17
23
  end
18
24
 
19
25
  def element
@@ -29,14 +35,14 @@ module Glimmer
29
35
  end
30
36
 
31
37
  def text=(value)
32
- # Document.ready? do
33
- Document.title = value
34
- # end
38
+ Document.title = value
35
39
  end
36
40
 
37
41
  def minimum_size=(width_or_minimum_size, height = nil)
38
42
  @minimum_size = height.nil? ? width_or_minimum_size : Point.new(width_or_minimum_size, height)
39
- redraw
43
+ return if @minimum_size.nil?
44
+ dom_element.css('min-width', "#{@minimum_size.x}px")
45
+ dom_element.css('min-height', "#{@minimum_size.y}px")
40
46
  end
41
47
 
42
48
  def style_dom_css
@@ -57,11 +63,15 @@ module Glimmer
57
63
  width: 100%;
58
64
  height: 100%;
59
65
  }
60
- body, .shell {
66
+ body {
61
67
  width: 100%;
62
68
  height: 100%;
63
69
  margin: 0;
64
70
  }
71
+ .shell {
72
+ height: 100%;
73
+ margin: 0;
74
+ }
65
75
  .shell iframe {
66
76
  width: 100%;
67
77
  height: 100%;
@@ -179,7 +189,7 @@ module Glimmer
179
189
  end
180
190
 
181
191
  def style_dom_table_css
182
- <<~CSS
192
+ <<~CSS
183
193
  table {
184
194
  border-spacing: 0;
185
195
  }
@@ -193,15 +203,9 @@ module Glimmer
193
203
  def dom
194
204
  i = 0
195
205
  body_id = id
196
- body_class = name
197
- body_style = '' # a start for more styling further along
198
- if @minimum_size
199
- body_style += "min-width: #{@minimum_size.x}px; min-height: #{@minimum_size.y}px;" if @minimum_size
200
- Document.find('body').css('min-width', "#{@minimum_size.x}px")
201
- Document.find('body').css('min-height', "#{@minimum_size.y}px")
202
- end
206
+ body_class = ([name] + css_classes.to_a).join(' ')
203
207
  @dom ||= html {
204
- div(id: body_id, class: body_class, style: body_style) {
208
+ div(id: body_id, class: body_class) {
205
209
  style(class: 'common-style') {
206
210
  style_dom_css
207
211
  }
@@ -213,16 +217,22 @@ module Glimmer
213
217
  }
214
218
  style(class: 'tab-style') {
215
219
  style_dom_tab_css
216
- }
220
+ }
217
221
  # style(class: 'tab-item-style') {
218
222
  # style_dom_tab_item_css
219
223
  # }
220
224
  # style(class: 'modal-style') {
221
225
  # style_dom_modal_css
222
226
  # }
223
- style(class: 'table-style') {
227
+ style(class: 'table-style') {
224
228
  style_dom_table_css
225
- }
229
+ }
230
+ style(class: 'fill-layout-style') {
231
+ Glimmer::SWT::FillLayoutProxy::STYLE
232
+ }
233
+ style(class: 'row-layout-style') {
234
+ Glimmer::SWT::RowLayoutProxy::STYLE
235
+ }
226
236
  }
227
237
  }.to_s
228
238
  end
@@ -0,0 +1,154 @@
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
+ # Mixin for all proxy classes that manage style constants (e.g. SWT, DND, etc...)
27
+ module StyleConstantizable
28
+ module ClassMethods
29
+ REGEX_SYMBOL_NEGATIVITY = /^([^!]+)(!)?$/
30
+
31
+ def constant_source_class
32
+ raise 'Not implemented! Mixer must implement!'
33
+ end
34
+
35
+ def constant_value_none
36
+ # TODO instead of raising error try a convention instead like CLASSNAME::NONE by default
37
+ raise 'Not implemented! Mixer must implement!'
38
+ end
39
+
40
+ # hash of extra styles (i.e. new style combinations)
41
+ def extra_styles
42
+ raise 'Not implemented! Mixer must implement!'
43
+ end
44
+
45
+ def error_message_invalid_style
46
+ " is an invalid #{constant_source_class.name.split(':').last} style! Please choose a style from #{constant_source_class.name} class constants." # TODO parameterize
47
+ end
48
+
49
+ # Gets constants (e.g. SWT::CONSTANT) where constant is
50
+ # passed in as a lower case symbol
51
+ def [](*symbols)
52
+ symbols = symbols.first if symbols.size == 1 && symbols.first.is_a?(Array)
53
+ result = symbols.compact.map do |symbol|
54
+ constant(symbol).tap do |constant_value|
55
+ raise Glimmer::Error, symbol.to_s + error_message_invalid_style unless constant_value.is_a?(Integer)
56
+ end
57
+ end.reduce do |output, constant_value|
58
+ if constant_value < 0
59
+ output & constant_value
60
+ else
61
+ output | constant_value
62
+ end
63
+ end
64
+ result.nil? ? constant_value_none : result
65
+ end
66
+
67
+ # Returns style integer value for passed in symbol or allows
68
+ # passed in object to pass through (e.g. Integer). This makes is convenient
69
+ # to use symbols or actual style integers in Glimmer
70
+ # Does not raise error for invalid values. Just lets them pass as is.
71
+ # (look into [] operator if you want an error raised on invalid values)
72
+ def constant(symbol)
73
+ return symbol unless symbol.is_a?(Symbol) || symbol.is_a?(String)
74
+ symbol_string, negative = extract_symbol_string_negativity(symbol)
75
+ swt_constant_symbol = symbol_string.downcase == symbol_string ? symbol_string.upcase.to_sym : symbol_string.to_sym
76
+ bit_value = constant_source_class.const_get(swt_constant_symbol)
77
+ negative ? ~bit_value : bit_value
78
+ rescue => e
79
+ begin
80
+ # Glimmer::Config.logger.debug {e.full_message}
81
+ alternative_swt_constant_symbol = constant_source_class.constants.find {|c| c.to_s.upcase == swt_constant_symbol.to_s.upcase}
82
+ bit_value = constant_source_class.const_get(alternative_swt_constant_symbol)
83
+ negative ? ~bit_value : bit_value
84
+ rescue => e
85
+ # Glimmer::Config.logger.debug {e.full_message}
86
+ bit_value = extra_styles[swt_constant_symbol]
87
+ if bit_value
88
+ negative ? ~bit_value : bit_value
89
+ else
90
+ symbol
91
+ end
92
+ end
93
+ end
94
+
95
+ def extract_symbol_string_negativity(symbol)
96
+ if symbol.is_a?(Symbol) || symbol.is_a?(String)
97
+ symbol_negativity_match = symbol.to_s.match(REGEX_SYMBOL_NEGATIVITY)
98
+ symbol = symbol_negativity_match[1]
99
+ negative = !!symbol_negativity_match[2]
100
+ [symbol, negative]
101
+ else
102
+ negative = symbol < 0
103
+ [symbol, negative]
104
+ end
105
+ end
106
+
107
+ def negative?(symbol)
108
+ extract_symbol_string_negativity(symbol)[1]
109
+ end
110
+
111
+ def has_constant?(symbol)
112
+ return false unless symbol.is_a?(Symbol) || symbol.is_a?(String)
113
+ constant(symbol).is_a?(Integer)
114
+ end
115
+
116
+ def constantify_args(args)
117
+ args.map {|arg| constant(arg)}
118
+ end
119
+
120
+ # Deconstructs a style integer into symbols
121
+ # Useful for debugging
122
+ def deconstruct(integer)
123
+ constant_source_class.constants.reduce([]) do |found, c|
124
+ constant_value = constant_source_class.const_get(c) rescue -1
125
+ is_found = constant_value.is_a?(Integer) && (integer & constant_value) == integer
126
+ is_found ? found += [c] : found
127
+ end
128
+ end
129
+
130
+ # Reverse engineer a style integer into a symbol
131
+ # Useful for debugging
132
+ def reverse_lookup(integer)
133
+ constant_source_class.constants.reduce([]) do |found, c|
134
+ constant_value = constant_source_class.const_get(c) rescue -1
135
+ is_found = constant_value.is_a?(Integer) && integer == constant_value
136
+ is_found ? found += [c] : found
137
+ end
138
+ end
139
+
140
+ def include?(swt_constant, *symbols)
141
+ swt_constant & self[symbols] == self[symbols]
142
+ end
143
+
144
+ end
145
+
146
+ def self.included(klass)
147
+ klass.extend(ClassMethods)
148
+ end
149
+
150
+ end
151
+
152
+ end
153
+
154
+ end