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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +195 -167
- data/VERSION +1 -1
- data/lib/glimmer-dsl-opal.rb +24 -7
- data/lib/glimmer-dsl-opal/ext/exception.rb +5 -0
- data/lib/glimmer-dsl-opal/missing/net/http.rb +17 -0
- data/lib/glimmer-dsl-opal/missing/uri.rb +26 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact_manager_presenter.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/contact_manager/contact_repository.rb +24 -99
- data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/login.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe/board.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/elaborate/tic_tac_toe/cell.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_browser.rb +0 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_combo.rb +63 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_computed.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_computed/contact.rb +0 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_custom_shell.rb +155 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_custom_widget.rb +86 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_list_multi_selection.rb +0 -0
- data/lib/{samples → glimmer-dsl-opal/samples}/hello/hello_list_single_selection.rb +0 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_tab.rb +50 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_world.rb +29 -0
- data/lib/{jquery.js → glimmer-dsl-opal/vendor/jquery.js} +0 -0
- data/lib/glimmer/data_binding/ext/observable_model.rb +1 -1
- data/lib/glimmer/dsl/opal/async_exec_expression.rb +2 -2
- data/lib/glimmer/dsl/opal/color_expression.rb +38 -0
- data/lib/glimmer/dsl/opal/custom_widget_expression.rb +57 -0
- data/lib/glimmer/dsl/opal/dsl.rb +7 -0
- data/lib/glimmer/dsl/opal/font_expression.rb +47 -0
- data/lib/glimmer/dsl/opal/property_expression.rb +5 -2
- data/lib/glimmer/dsl/opal/rgb_expression.rb +32 -0
- data/lib/glimmer/dsl/opal/rgba_expression.rb +32 -0
- data/lib/glimmer/dsl/opal/swt_expression.rb +46 -0
- data/lib/glimmer/dsl/opal/widget_expression.rb +2 -1
- data/lib/glimmer/dsl/opal/widget_listener_expression.rb +16 -3
- data/lib/glimmer/swt.rb +499 -0
- data/lib/glimmer/swt/browser_proxy.rb +1 -1
- data/lib/glimmer/swt/button_proxy.rb +2 -2
- data/lib/glimmer/swt/color_proxy.rb +119 -0
- data/lib/glimmer/swt/combo_proxy.rb +10 -9
- data/lib/glimmer/swt/composite_proxy.rb +8 -8
- data/lib/glimmer/{opal → swt}/display_proxy.rb +3 -1
- data/lib/glimmer/swt/fill_layout_proxy.rb +84 -0
- data/lib/glimmer/swt/font_proxy.rb +79 -0
- data/lib/glimmer/swt/grid_layout_proxy.rb +34 -4
- data/lib/glimmer/swt/label_proxy.rb +7 -3
- data/lib/glimmer/swt/layout_proxy.rb +15 -13
- data/lib/glimmer/swt/list_proxy.rb +17 -12
- data/lib/glimmer/swt/message_box_proxy.rb +4 -7
- data/lib/glimmer/swt/row_layout_proxy.rb +105 -0
- data/lib/glimmer/swt/shell_proxy.rb +32 -22
- data/lib/glimmer/swt/style_constantizable.rb +154 -0
- data/lib/glimmer/swt/swt_proxy.rb +53 -0
- data/lib/glimmer/swt/tab_folder_proxy.rb +8 -8
- data/lib/glimmer/swt/tab_item_proxy.rb +15 -32
- data/lib/glimmer/swt/table_proxy.rb +0 -18
- data/lib/glimmer/swt/widget_proxy.rb +140 -39
- data/lib/glimmer/ui/custom_shell.rb +73 -0
- data/lib/glimmer/ui/custom_widget.rb +290 -0
- data/lib/glimmer/util/proc_tracker.rb +39 -0
- metadata +88 -57
- data/lib/glimmer/opal/element_proxy.rb +0 -312
- data/lib/samples/elaborate/launch +0 -6
- data/lib/samples/hello/hello_combo.rb +0 -34
- data/lib/samples/hello/hello_tab.rb +0 -24
- data/lib/samples/hello/hello_world.rb +0 -8
- data/lib/samples/hello/launch +0 -10
- data/lib/samples/launch +0 -4
@@ -7,17 +7,21 @@ module Glimmer
|
|
7
7
|
|
8
8
|
def text=(value)
|
9
9
|
@text = value
|
10
|
-
|
10
|
+
dom_element.html(value)
|
11
11
|
end
|
12
12
|
|
13
13
|
def element
|
14
14
|
'label'
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
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 =
|
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
|
-
@
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
23
|
+
dom_element.find('.modal-content .text').html(@text)
|
26
24
|
end
|
27
25
|
|
28
26
|
def message=(msg)
|
29
27
|
@message = msg
|
30
|
-
|
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
|
-
|
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
|
-
|
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 <
|
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
|
-
|
16
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|