glimmer-dsl-opal 0.26.3 → 0.28.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +68 -2
- data/VERSION +1 -1
- data/lib/glimmer/dsl/opal/dsl.rb +3 -0
- data/lib/glimmer/dsl/opal/image_expression.rb +67 -0
- data/lib/glimmer/dsl/opal/shape_expression.rb +34 -6
- data/lib/glimmer/swt/c_tab_folder_proxy.rb +1 -1
- data/lib/glimmer/swt/canvas_proxy.rb +27 -0
- data/lib/glimmer/swt/composite_proxy.rb +0 -2
- data/lib/glimmer/swt/custom/shape/arc.rb +72 -0
- data/lib/glimmer/swt/custom/shape/image.rb +54 -0
- data/lib/glimmer/swt/custom/shape/line.rb +50 -0
- data/lib/glimmer/swt/custom/shape/oval.rb +58 -0
- data/lib/glimmer/swt/custom/shape/point.rb +50 -0
- data/lib/glimmer/swt/custom/shape/polygon.rb +50 -0
- data/lib/glimmer/swt/custom/shape/polyline.rb +50 -0
- data/lib/glimmer/swt/custom/shape/rectangle.rb +50 -0
- data/lib/glimmer/swt/custom/shape/text.rb +64 -0
- data/lib/glimmer/swt/custom/shape.rb +111 -0
- data/lib/glimmer/swt/image_proxy.rb +29 -0
- data/lib/glimmer/swt/point.rb +2 -0
- data/lib/glimmer/swt/rectangle.rb +7 -0
- data/lib/glimmer/swt/text_proxy.rb +82 -20
- data/lib/glimmer/swt/widget_proxy.rb +17 -5
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris.rb +3 -7
- data/lib/glimmer-dsl-opal/samples/hello/hello_canvas.rb +91 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_text.rb +149 -0
- data/lib/glimmer-dsl-opal/samples/hello/images/scaffold_app.png +0 -0
- data/lib/glimmer-dsl-opal/vendor/two.min.js +24 -0
- data/lib/glimmer-dsl-opal.rb +1 -0
- metadata +20 -2
@@ -0,0 +1,29 @@
|
|
1
|
+
module Glimmer
|
2
|
+
module SWT
|
3
|
+
# emulating org.eclipse.swt.graphics.Image
|
4
|
+
class ImageProxy
|
5
|
+
class << self
|
6
|
+
def create(*args, &content)
|
7
|
+
if args.size == 1 && args.first.is_a?(ImageProxy)
|
8
|
+
args.first
|
9
|
+
else
|
10
|
+
new(*args, &content)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :file_path, :width, :height
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
19
|
+
# TODO support a parent as a first argument before the file path
|
20
|
+
@file_path = args.first
|
21
|
+
@width = options[:width]
|
22
|
+
@height = options[:height]
|
23
|
+
end
|
24
|
+
|
25
|
+
# TODO implement scale_to
|
26
|
+
end
|
27
|
+
# TODO alias as org.eclipse.swt.graphics.Image
|
28
|
+
end
|
29
|
+
end
|
data/lib/glimmer/swt/point.rb
CHANGED
@@ -3,7 +3,26 @@ require 'glimmer/swt/widget_proxy'
|
|
3
3
|
module Glimmer
|
4
4
|
module SWT
|
5
5
|
class TextProxy < WidgetProxy
|
6
|
-
attr_reader :text
|
6
|
+
attr_reader :text, :border, :left, :center, :right, :read_only, :wrap, :multi
|
7
|
+
alias border? border
|
8
|
+
alias left? left
|
9
|
+
alias center? center
|
10
|
+
alias right? right
|
11
|
+
alias read_only? read_only
|
12
|
+
alias wrap? wrap
|
13
|
+
alias multi? multi
|
14
|
+
|
15
|
+
def initialize(parent, args, block)
|
16
|
+
args << :border if args.empty?
|
17
|
+
@border = !!args.detect { |arg| SWTProxy[arg] == SWTProxy[:border] }
|
18
|
+
@left = !!args.detect { |arg| SWTProxy[arg] == SWTProxy[:left] }
|
19
|
+
@center = !!args.detect { |arg| SWTProxy[arg] == SWTProxy[:center] }
|
20
|
+
@right = !!args.detect { |arg| SWTProxy[arg] == SWTProxy[:right] }
|
21
|
+
@read_only = !!args.detect { |arg| SWTProxy[arg] == SWTProxy[:read_only] }
|
22
|
+
@wrap = !!args.detect { |arg| SWTProxy[arg] == SWTProxy[:wrap] }
|
23
|
+
@multi = !!args.detect { |arg| SWTProxy[arg] == SWTProxy[:multi] }
|
24
|
+
super(parent, args, block)
|
25
|
+
end
|
7
26
|
|
8
27
|
def text=(value)
|
9
28
|
@text = value
|
@@ -11,43 +30,86 @@ module Glimmer
|
|
11
30
|
end
|
12
31
|
|
13
32
|
def element
|
14
|
-
'input'
|
33
|
+
@wrap || @multi ? 'textarea' : 'input'
|
15
34
|
end
|
16
35
|
|
17
36
|
def observation_request_to_event_mapping
|
37
|
+
myself = self
|
18
38
|
{
|
19
|
-
'
|
20
|
-
|
21
|
-
|
22
|
-
-> (
|
23
|
-
|
24
|
-
|
25
|
-
|
39
|
+
'on_verify_text' => [
|
40
|
+
{
|
41
|
+
event: 'beforeinput',
|
42
|
+
event_handler: -> (event_listener) {
|
43
|
+
-> (event) {
|
44
|
+
event.define_singleton_method(:widget) {myself}
|
45
|
+
event.define_singleton_method(:text) {`#{event.to_n}.originalEvent.data` || ''}
|
46
|
+
selection_start = `#{event.target}[0].selectionStart`
|
47
|
+
selection_end = `#{event.target}[0].selectionEnd`
|
48
|
+
if `#{event.to_n}.originalEvent.inputType` == 'deleteContentBackward' && selection_start == selection_end
|
49
|
+
selection_start -= 1
|
50
|
+
selection_start = 0 if selection_start < 0
|
51
|
+
end
|
52
|
+
event.define_singleton_method(:start) do
|
53
|
+
selection_start
|
54
|
+
end
|
55
|
+
event.define_singleton_method(:end) {selection_end}
|
56
|
+
doit = true
|
57
|
+
event.define_singleton_method(:doit=) do |value|
|
58
|
+
doit = value
|
59
|
+
end
|
60
|
+
event.define_singleton_method(:doit) { doit }
|
61
|
+
event_listener.call(event)
|
62
|
+
|
63
|
+
if !doit
|
64
|
+
`#{event.to_n}.originalEvent.returnValue = false`
|
65
|
+
end
|
66
|
+
|
67
|
+
doit
|
68
|
+
}
|
69
|
+
}
|
70
|
+
},
|
71
|
+
{
|
72
|
+
event: 'input',
|
73
|
+
event_handler: -> (event_listener) {
|
74
|
+
-> (event) {
|
75
|
+
event.define_singleton_method(:widget) {myself}
|
76
|
+
@text = event.target.value
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
],
|
81
|
+
'on_modify_text' => [
|
82
|
+
{
|
83
|
+
event: 'input',
|
84
|
+
event_handler: -> (event_listener) {
|
85
|
+
-> (event) {
|
86
|
+
# TODO add all attributes for on_modify_text modify event
|
87
|
+
event.define_singleton_method(:widget) {myself}
|
26
88
|
@text = event.target.value
|
27
89
|
event_listener.call(event)
|
28
|
-
|
29
|
-
# TODO Fix doit false, it's not stopping input
|
30
|
-
event.prevent
|
31
|
-
event.prevent_default
|
32
|
-
event.stop_propagation
|
33
|
-
event.stop_immediate_propagation
|
34
|
-
end
|
90
|
+
}
|
35
91
|
}
|
36
92
|
}
|
37
|
-
|
93
|
+
],
|
38
94
|
}
|
39
95
|
end
|
40
96
|
|
41
97
|
def dom
|
42
98
|
text_text = @text
|
43
99
|
text_id = id
|
44
|
-
text_style =
|
100
|
+
text_style = 'min-width: 27px; '
|
101
|
+
text_style += 'border: none; ' if !@border
|
102
|
+
text_style += 'text-align: left; ' if @left
|
103
|
+
text_style += 'text-align: center; ' if @center
|
104
|
+
text_style += 'text-align: right; ' if @right
|
45
105
|
text_class = name
|
46
|
-
options = {type: 'text', id: text_id, style: text_style, class: text_class, value: text_text
|
106
|
+
options = {type: 'text', id: text_id, style: text_style, class: text_class, value: text_text}
|
47
107
|
options = options.merge('disabled': 'disabled') unless @enabled
|
108
|
+
options = options.merge('readonly': 'readonly') if @read_only
|
109
|
+
options = options.merge('contenteditable': 'true')
|
48
110
|
options = options.merge(type: 'password') if has_style?(:password)
|
49
111
|
@dom ||= html {
|
50
|
-
|
112
|
+
send(element, options)
|
51
113
|
}.to_s
|
52
114
|
end
|
53
115
|
end
|
@@ -30,7 +30,7 @@ module Glimmer
|
|
30
30
|
class WidgetProxy
|
31
31
|
include Glimmer
|
32
32
|
include PropertyOwner
|
33
|
-
|
33
|
+
|
34
34
|
Event = Struct.new(:widget, keyword_init: true)
|
35
35
|
|
36
36
|
JS_KEY_CODE_TO_SWT_KEY_CODE_MAP = {
|
@@ -158,7 +158,7 @@ module Glimmer
|
|
158
158
|
@block = block
|
159
159
|
# TODO consider changing children to an array (why is it a Set if order matters?)
|
160
160
|
@children = Set.new # TODO consider moving to composite
|
161
|
-
@enabled = true
|
161
|
+
@enabled = true if @enabled.nil?
|
162
162
|
DEFAULT_INITIALIZERS[self.class.underscored_widget_name(self).to_s.to_sym]&.call(self)
|
163
163
|
@parent.post_initialize_child(self) # TODO rename to post_initialize_child to be closer to glimmer-dsl-swt terminology
|
164
164
|
end
|
@@ -331,9 +331,10 @@ module Glimmer
|
|
331
331
|
brand_new = @dom.nil? || old_element.empty? || brand_new
|
332
332
|
build_dom(layout: !custom_parent_dom_element) # TODO handle custom parent layout by passing parent instead of parent dom element
|
333
333
|
if brand_new
|
334
|
-
|
334
|
+
# TODO make a method attach to allow subclasses to override if needed
|
335
|
+
attach(the_parent_dom_element)
|
335
336
|
else
|
336
|
-
old_element
|
337
|
+
reattach(old_element)
|
337
338
|
end
|
338
339
|
observation_requests&.each do |keyword, event_listener_set|
|
339
340
|
event_listener_set.each do |event_listener|
|
@@ -347,6 +348,14 @@ module Glimmer
|
|
347
348
|
content_on_render_blocks.each { |content_block| content(&content_block) } unless skip_content_on_render_blocks?
|
348
349
|
end
|
349
350
|
alias redraw render
|
351
|
+
|
352
|
+
def attach(the_parent_dom_element)
|
353
|
+
the_parent_dom_element.append(@dom)
|
354
|
+
end
|
355
|
+
|
356
|
+
def reattach(old_element)
|
357
|
+
old_element.replace_with(@dom)
|
358
|
+
end
|
350
359
|
|
351
360
|
def content_on_render_blocks
|
352
361
|
@content_on_render_blocks ||= []
|
@@ -367,7 +376,7 @@ module Glimmer
|
|
367
376
|
def build_dom(layout: true)
|
368
377
|
# TODO consider passing parent element instead and having table item include a table cell widget only for opal
|
369
378
|
@dom = nil
|
370
|
-
@dom = dom
|
379
|
+
@dom = dom # TODO unify how to build dom for most widgets based on element, id, and name (class)
|
371
380
|
@dom = @parent.get_layout.dom(@dom) if @parent.respond_to?(:layout) && @parent.get_layout
|
372
381
|
@dom
|
373
382
|
end
|
@@ -616,6 +625,7 @@ module Glimmer
|
|
616
625
|
JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
|
617
626
|
}
|
618
627
|
event.define_singleton_method(:key_code, &event.method(:keyCode))
|
628
|
+
event.define_singleton_method(:widget) {myself}
|
619
629
|
event.define_singleton_method(:character) {event.which.chr}
|
620
630
|
event.define_singleton_method(:stateMask) do
|
621
631
|
state_mask = 0
|
@@ -658,6 +668,7 @@ module Glimmer
|
|
658
668
|
JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
|
659
669
|
}
|
660
670
|
event.define_singleton_method(:key_code, &event.method(:keyCode))
|
671
|
+
event.define_singleton_method(:widget) {myself}
|
661
672
|
event.define_singleton_method(:character) {event.which.chr}
|
662
673
|
event.define_singleton_method(:stateMask) do
|
663
674
|
state_mask = 0
|
@@ -1141,6 +1152,7 @@ require 'glimmer/swt/combo_proxy'
|
|
1141
1152
|
require 'glimmer/swt/c_combo_proxy'
|
1142
1153
|
require 'glimmer/swt/checkbox_proxy'
|
1143
1154
|
require 'glimmer/swt/composite_proxy'
|
1155
|
+
require 'glimmer/swt/canvas_proxy'
|
1144
1156
|
require 'glimmer/swt/date_time_proxy'
|
1145
1157
|
require 'glimmer/swt/group_proxy'
|
1146
1158
|
require 'glimmer/swt/label_proxy'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c)
|
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
|
@@ -25,11 +25,7 @@ require_relative 'tetris/view/playfield'
|
|
25
25
|
require_relative 'tetris/view/score_lane'
|
26
26
|
require_relative 'tetris/view/high_score_dialog'
|
27
27
|
require_relative 'tetris/view/tetris_menu_bar'
|
28
|
-
|
29
|
-
def location
|
30
|
-
`#@native.location`
|
31
|
-
end
|
32
|
-
end
|
28
|
+
|
33
29
|
class Tetris
|
34
30
|
include Glimmer::UI::CustomShell
|
35
31
|
|
@@ -147,7 +143,7 @@ class Tetris
|
|
147
143
|
def show_about_dialog
|
148
144
|
message_box {
|
149
145
|
text 'Glimmer Tetris'
|
150
|
-
message "Glimmer Tetris\n\nGlimmer DSL for SWT Sample\n\nUse arrow keys for movement\nand right/left alt/shift keys for rotation\nAlternatively:\nLeft is A\nRight is D\nDown is S\nUp is W\nRotate Left is Q\nRotate Right is E\n\
|
146
|
+
message "Glimmer Tetris\n\nGlimmer DSL for SWT Sample\n\nUse arrow keys for movement\nand right/left alt/shift keys for rotation\nAlternatively:\nLeft is A\nRight is D\nDown is S\nUp is W\nRotate Left is Q\nRotate Right is E\n\nCopyright (c) 2007-2021 Andy Maleh"
|
151
147
|
}.open
|
152
148
|
end
|
153
149
|
end
|
@@ -0,0 +1,91 @@
|
|
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
|
+
class HelloCanvas
|
23
|
+
include Glimmer::UI::CustomShell
|
24
|
+
|
25
|
+
before_body do
|
26
|
+
@image_object = image(File.expand_path('./images/scaffold_app.png', __dir__), width: 50)
|
27
|
+
end
|
28
|
+
|
29
|
+
body {
|
30
|
+
shell {
|
31
|
+
text 'Hello, Canvas!'
|
32
|
+
minimum_size 320, 400
|
33
|
+
|
34
|
+
canvas {
|
35
|
+
background :yellow
|
36
|
+
|
37
|
+
rectangle(0, 0, 220, 400) {
|
38
|
+
background rgb(255, 0, 0)
|
39
|
+
}
|
40
|
+
rectangle(50, 20, 300, 150, 30, 50) {
|
41
|
+
background :magenta
|
42
|
+
}
|
43
|
+
rectangle(50, 20, 300, 150, 30, 50) {
|
44
|
+
foreground :yellow
|
45
|
+
}
|
46
|
+
rectangle(205, 50, 86, 97) {
|
47
|
+
foreground :yellow
|
48
|
+
}
|
49
|
+
rectangle(67, 75, 128, 38) {
|
50
|
+
background :yellow
|
51
|
+
}
|
52
|
+
rectangle(150, 200, 100, 70) {
|
53
|
+
background :dark_magenta
|
54
|
+
}
|
55
|
+
rectangle(50, 200, 30, 70) {
|
56
|
+
background :magenta
|
57
|
+
}
|
58
|
+
oval(110, 310, 100, 100) {
|
59
|
+
background :yellow
|
60
|
+
}
|
61
|
+
arc(210, 210, 100, 100, 30, -77) {
|
62
|
+
background :red
|
63
|
+
}
|
64
|
+
text('Picasso', 67, 103) {
|
65
|
+
foreground :dark_magenta
|
66
|
+
font name: 'Courier', height: 30
|
67
|
+
}
|
68
|
+
image(@image_object, 205, 55)
|
69
|
+
polygon(250, 210, 260, 170, 270, 210, 290, 230) {
|
70
|
+
background :dark_yellow
|
71
|
+
}
|
72
|
+
polyline(250, 110, 260, 70, 270, 110, 290, 130, 250, 110) {
|
73
|
+
foreground :black
|
74
|
+
}
|
75
|
+
3.times do |n|
|
76
|
+
line(250, 120 + n*10, 270 + n*10, 80 + n*10) {
|
77
|
+
foreground :yellow
|
78
|
+
}
|
79
|
+
end
|
80
|
+
10.times do |n|
|
81
|
+
point(220 + n*5, 100 + n*5) {
|
82
|
+
foreground :yellow
|
83
|
+
}
|
84
|
+
end
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
HelloCanvas.launch
|
91
|
+
|
@@ -0,0 +1,149 @@
|
|
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
|
+
class HelloText
|
23
|
+
include Glimmer::UI::CustomShell
|
24
|
+
|
25
|
+
attr_accessor :default, :no_border, :center, :left, :right, :password, :telephone, :read_only, :wrap, :multi
|
26
|
+
|
27
|
+
before_body do
|
28
|
+
self.default = 'default is :border style'
|
29
|
+
self.no_border = 'no border'
|
30
|
+
self.center = 'centered'
|
31
|
+
self.left = 'left-aligned'
|
32
|
+
self.right = 'right-aligned'
|
33
|
+
self.password = 'password'
|
34
|
+
self.telephone = '555-555-5555'
|
35
|
+
self.read_only = 'Telephone area code is 555'
|
36
|
+
self.wrap = 'wraps if text content is too long like this example'
|
37
|
+
self.multi = "multi-line enables hitting enter,\nbut works like wrap on the web"
|
38
|
+
end
|
39
|
+
|
40
|
+
body {
|
41
|
+
shell {
|
42
|
+
grid_layout 2, false
|
43
|
+
|
44
|
+
text 'Hello, Text!'
|
45
|
+
minimum_size 350, 100
|
46
|
+
|
47
|
+
label {
|
48
|
+
text 'text'
|
49
|
+
}
|
50
|
+
text { # includes :border style by default
|
51
|
+
layout_data :fill, :center, true, false
|
52
|
+
text <=> [self, :default]
|
53
|
+
}
|
54
|
+
|
55
|
+
label {
|
56
|
+
text 'text(:none)'
|
57
|
+
}
|
58
|
+
text(:none) { # no border
|
59
|
+
layout_data :fill, :center, true, false
|
60
|
+
text <=> [self, :no_border]
|
61
|
+
}
|
62
|
+
|
63
|
+
label {
|
64
|
+
text 'text(:center, :border)'
|
65
|
+
}
|
66
|
+
text(:center, :border) {
|
67
|
+
layout_data :fill, :center, true, false
|
68
|
+
text <=> [self, :center]
|
69
|
+
}
|
70
|
+
|
71
|
+
label {
|
72
|
+
text 'text(:left, :border)'
|
73
|
+
}
|
74
|
+
text(:left, :border) {
|
75
|
+
layout_data :fill, :center, true, false
|
76
|
+
text <=> [self, :left]
|
77
|
+
}
|
78
|
+
|
79
|
+
label {
|
80
|
+
text 'text(:right, :border)'
|
81
|
+
}
|
82
|
+
text(:right, :border) {
|
83
|
+
layout_data :fill, :center, true, false
|
84
|
+
text <=> [self, :right]
|
85
|
+
}
|
86
|
+
|
87
|
+
label {
|
88
|
+
text 'text(:password, :border)'
|
89
|
+
}
|
90
|
+
text(:password, :border) {
|
91
|
+
layout_data :fill, :center, true, false
|
92
|
+
text <=> [self, :password]
|
93
|
+
}
|
94
|
+
|
95
|
+
label {
|
96
|
+
text 'text(:read_only, :border)'
|
97
|
+
}
|
98
|
+
text(:read_only, :border) {
|
99
|
+
layout_data :fill, :center, true, false
|
100
|
+
text <= [self, :read_only]
|
101
|
+
}
|
102
|
+
|
103
|
+
label {
|
104
|
+
text 'text with event handlers'
|
105
|
+
}
|
106
|
+
text {
|
107
|
+
layout_data :fill, :center, true, false
|
108
|
+
text <=> [self, :telephone]
|
109
|
+
|
110
|
+
# this event kicks in just after the user typed and before modifying the text attribute value
|
111
|
+
on_verify_text do |verify_event|
|
112
|
+
new_text = verify_event.widget.text.clone
|
113
|
+
# new_text[verify_event.start...verify_event.end] = verify_event.text # Opal does not allow string mutation like JRuby in Glimmer DSL for SWT
|
114
|
+
new_text = "#{new_text[0...verify_event.start]}#{verify_event.text}#{new_text[verify_event.end..-1]}"
|
115
|
+
verify_event.doit = telephone?(new_text)
|
116
|
+
end
|
117
|
+
|
118
|
+
# this event kicks in just after the text widget is verified and modified
|
119
|
+
on_modify_text do |modify_event|
|
120
|
+
self.read_only = "Telephone area code is #{modify_event.widget.text.gsub(/[^0-9]/, '')[0...3]}"
|
121
|
+
end
|
122
|
+
}
|
123
|
+
|
124
|
+
label {
|
125
|
+
text 'text(:wrap, :border)'
|
126
|
+
}
|
127
|
+
text(:wrap, :border) {
|
128
|
+
layout_data(:fill, :center, true, false) {
|
129
|
+
width_hint 100
|
130
|
+
}
|
131
|
+
text <=> [self, :wrap]
|
132
|
+
}
|
133
|
+
|
134
|
+
label {
|
135
|
+
text 'text(:multi, :border)'
|
136
|
+
}
|
137
|
+
text(:multi, :border) {
|
138
|
+
layout_data :fill, :center, true, false
|
139
|
+
text <=> [self, :multi]
|
140
|
+
}
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
def telephone?(text)
|
145
|
+
!!text.match(/^\d{0,3}[-.\/]?\d{0,3}[-.\/]?\d{0,4}$/)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
HelloText.launch
|