glimmer-dsl-tk 0.0.22 → 0.0.26
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 +40 -0
- data/README.md +612 -46
- data/VERSION +1 -1
- data/glimmer-dsl-tk.gemspec +0 -0
- data/lib/glimmer/dsl/tk/format_expression.rb +39 -0
- data/lib/glimmer/dsl/tk/message_box_expression.rb +4 -1
- data/lib/glimmer/dsl/tk/root_expression.rb +1 -1
- data/lib/glimmer/dsl/tk/widget_expression.rb +0 -7
- data/lib/glimmer/tk/button_proxy.rb +2 -14
- data/lib/glimmer/tk/checkbutton_proxy.rb +5 -13
- data/lib/glimmer/tk/combobox_proxy.rb +34 -0
- data/lib/glimmer/tk/commandable.rb +42 -0
- data/lib/glimmer/tk/entry_proxy.rb +20 -0
- data/lib/glimmer/tk/frame_proxy.rb +9 -0
- data/lib/glimmer/tk/label_proxy.rb +8 -4
- data/lib/glimmer/tk/notebook_proxy.rb +3 -8
- data/lib/glimmer/tk/radiobutton_proxy.rb +46 -0
- data/lib/glimmer/tk/root_proxy.rb +17 -35
- data/lib/glimmer/tk/spinbox_proxy.rb +52 -0
- data/lib/glimmer/tk/text_proxy.rb +187 -0
- data/lib/glimmer/tk/text_variable_owner.rb +31 -0
- data/lib/glimmer/tk/variable_owner.rb +31 -0
- data/lib/glimmer/tk/widget_proxy.rb +167 -62
- data/lib/glimmer-dsl-tk.rb +1 -0
- data/samples/elaborate/meta_sample.rb +138 -0
- data/samples/hello/hello_checkbutton.rb +58 -17
- data/samples/hello/hello_combobox.rb +2 -1
- data/samples/hello/hello_entry.rb +104 -0
- data/samples/hello/hello_radiobutton.rb +107 -0
- data/samples/hello/hello_spinbox.rb +75 -0
- data/samples/hello/hello_text.rb +101 -0
- metadata +17 -3
@@ -0,0 +1,187 @@
|
|
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
|
+
require 'glimmer/tk/widget_proxy'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module Tk
|
26
|
+
# Proxy for Tk::Text
|
27
|
+
#
|
28
|
+
# Follows the Proxy Design Pattern
|
29
|
+
class TextProxy < WidgetProxy
|
30
|
+
def handle_listener(listener_name, &listener)
|
31
|
+
listener_name = listener_name.to_s.downcase
|
32
|
+
case listener_name
|
33
|
+
when '<<modified>>', '<modified>', 'modified'
|
34
|
+
modified_listener = Proc.new do |*args|
|
35
|
+
listener.call(*args)
|
36
|
+
@tk.modified = false
|
37
|
+
end
|
38
|
+
bind('<Modified>', modified_listener)
|
39
|
+
when '<<selection>>', '<selection>', 'selection'
|
40
|
+
bind('<Selection>', listener)
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def text=(value)
|
47
|
+
if value != @text
|
48
|
+
if @text && value.start_with?(@text)
|
49
|
+
insert('end', value[@text.size..-1])
|
50
|
+
else
|
51
|
+
delete('1.0', 'end')
|
52
|
+
insert('end', value)
|
53
|
+
end
|
54
|
+
@text = value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def text
|
59
|
+
@text = get("1.0", 'end')
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_selection_format(option, value)
|
63
|
+
process_selection_ranges { |range_start, range_end| add_format(range_start, range_end, option, value) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove_selection_format(option, value)
|
67
|
+
process_selection_ranges { |range_start, range_end| remove_format(range_start, range_end, option, value) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def toggle_selection_format(option, value)
|
71
|
+
process_selection_ranges { |range_start, range_end| toggle_format(range_start, range_end, option, value) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_selection_font_format(option, value)
|
75
|
+
process_selection_ranges { |range_start, range_end| add_font_format(range_start, range_end, option, value) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def remove_selection_font_format(option, value)
|
79
|
+
process_selection_ranges { |range_start, range_end| remove_font_format(range_start, range_end, option, value) }
|
80
|
+
end
|
81
|
+
|
82
|
+
def toggle_selection_font_format(option, value)
|
83
|
+
process_selection_ranges { |range_start, range_end| toggle_font_format(range_start, range_end, option, value) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def process_selection_ranges(&processor)
|
87
|
+
@tk.tag_ranges('sel').each do |region|
|
88
|
+
range_start = region.first
|
89
|
+
range_end = region.last
|
90
|
+
processor.call(range_start, range_end)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def applied_format?(region_start, region_end, option, value)
|
95
|
+
!applied_format_tags(region_start, region_end, option, value).empty?
|
96
|
+
end
|
97
|
+
|
98
|
+
def applied_format_tags(region_start, region_end, option, value)
|
99
|
+
tag_names = @tk.tag_names - ['sel']
|
100
|
+
|
101
|
+
tag_names.select do |tag_name|
|
102
|
+
@tk.tag_ranges(tag_name).any? do |range|
|
103
|
+
if range.first.to_f <= region_start.to_f && range.last.to_f >= region_end.to_f
|
104
|
+
@tk.tag_cget(tag_name, option) == value
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_format(region_start, region_end, option, value)
|
111
|
+
@@tag_number = 0 unless defined?(@@tag_number)
|
112
|
+
tag = "tag#{@@tag_number += 1}"
|
113
|
+
@tk.tag_configure(tag, {option => value})
|
114
|
+
@tk.tag_add(tag, region_start, region_end)
|
115
|
+
tag
|
116
|
+
end
|
117
|
+
|
118
|
+
def remove_format(region_start, region_end, option, value)
|
119
|
+
partial_intersection_option_applied_tags = tag_names.select do |tag_name|
|
120
|
+
@tk.tag_ranges(tag_name).any? do |range|
|
121
|
+
if range.first.to_f.between?(region_start.to_f, region_end.to_f) or
|
122
|
+
range.last.to_f.between?(region_start.to_f, region_end.to_f) or
|
123
|
+
(range.first.to_f <= region_start.to_f && range.last.to_f >= region_end.to_f)
|
124
|
+
@tk.tag_cget(tag_name, option) == value
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
partial_intersection_option_applied_tags.each do |tag_name|
|
130
|
+
@tk.tag_remove(tag_name, region_start, region_end)
|
131
|
+
end
|
132
|
+
|
133
|
+
nil
|
134
|
+
end
|
135
|
+
|
136
|
+
# toggles option/value tag (removes if already applied)
|
137
|
+
def toggle_format(region_start, region_end, option, value)
|
138
|
+
if applied_format?(region_start, region_end, option, value)
|
139
|
+
remove_format(region_start, region_end, option, value)
|
140
|
+
else
|
141
|
+
add_format(region_start, region_end, option, value)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# def applied_font_format?(region_start, region_end, option, value)
|
146
|
+
# !applied_font_format_tags(region_start, region_end, option, value).empty?
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# def applied_font_format_tags(region_start, region_end, option, value)
|
150
|
+
# tag_names = @tk.tag_names - ['sel']
|
151
|
+
#
|
152
|
+
# tag_names.select do |tag_name|
|
153
|
+
# @tk.tag_ranges(tag_name).any? do |range|
|
154
|
+
# if range.first.to_f <= region_start.to_f && range.last.to_f >= region_end.to_f
|
155
|
+
# @tk.tag_cget(tag_name, option) == value
|
156
|
+
# end
|
157
|
+
# end
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# def add_font_format(region_start, region_end, option, value)
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
# def remove_font_format(region_start, region_end, option, value)
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
### toggles option/value tag (removes if already applied)
|
168
|
+
# def toggle_font_format(region_start, region_end, option, value)
|
169
|
+
# if applied_font_format?(region_start, region_end, option, value)
|
170
|
+
### ensure removing from previous font combination (perhaps checking widget font too)
|
171
|
+
# remove_font_format(region_start, region_end, option, value)
|
172
|
+
# else
|
173
|
+
### ensure adding to previous font combination (perhaps checking widget font too)
|
174
|
+
# add_font_format(region_start, region_end, option, value)
|
175
|
+
# end
|
176
|
+
# end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def initialize_defaults
|
181
|
+
super
|
182
|
+
self.padx = 5
|
183
|
+
self.pady = 5
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,31 @@
|
|
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 Tk
|
24
|
+
module TextVariableOwner
|
25
|
+
def initialize_defaults
|
26
|
+
super
|
27
|
+
tk.textvariable = ::TkVariable.new
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
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 Tk
|
24
|
+
module VariableOwner
|
25
|
+
def initialize_defaults
|
26
|
+
super
|
27
|
+
tk.variable = ::TkVariable.new
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -26,8 +26,8 @@ module Glimmer
|
|
26
26
|
# Follows the Proxy Design Pattern
|
27
27
|
class WidgetProxy
|
28
28
|
class << self
|
29
|
-
def create(keyword, parent, args)
|
30
|
-
widget_proxy_class(keyword).new(keyword, parent, args)
|
29
|
+
def create(keyword, parent, args, &block)
|
30
|
+
widget_proxy_class(keyword).new(keyword, parent, args, &block)
|
31
31
|
end
|
32
32
|
|
33
33
|
def widget_proxy_class(keyword)
|
@@ -57,45 +57,35 @@ module Glimmer
|
|
57
57
|
Glimmer::Config.logger.debug e.full_message
|
58
58
|
end
|
59
59
|
end
|
60
|
-
tk_widget_class
|
60
|
+
tk_widget_class if tk_widget_class.respond_to?(:new)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
attr_reader :parent_proxy, :tk, :args, :keyword
|
64
|
+
attr_reader :parent_proxy, :tk, :args, :keyword, :children
|
65
65
|
|
66
|
-
DEFAULT_INITIALIZERS = {
|
67
|
-
'checkbutton' => lambda do |tk|
|
68
|
-
tk.variable = ::TkVariable.new
|
69
|
-
end,
|
70
|
-
'combobox' => lambda do |tk|
|
71
|
-
tk.textvariable = ::TkVariable.new
|
72
|
-
end,
|
73
|
-
'label' => lambda do |tk|
|
74
|
-
tk.textvariable = ::TkVariable.new
|
75
|
-
end,
|
76
|
-
'entry' => lambda do |tk|
|
77
|
-
tk.textvariable = ::TkVariable.new
|
78
|
-
end,
|
79
|
-
}
|
80
|
-
|
81
66
|
# Initializes a new Tk Widget
|
82
67
|
#
|
83
68
|
# Styles is a comma separate list of symbols representing Tk styles in lower case
|
84
|
-
def initialize(underscored_widget_name, parent_proxy, args)
|
69
|
+
def initialize(underscored_widget_name, parent_proxy, args, &block)
|
85
70
|
@parent_proxy = parent_proxy
|
86
71
|
@args = args
|
87
72
|
@keyword = underscored_widget_name
|
73
|
+
@block = block
|
88
74
|
tk_widget_class = self.class.tk_widget_class_for(underscored_widget_name)
|
89
75
|
@tk = tk_widget_class.new(@parent_proxy.tk, *args)
|
90
76
|
# a common widget initializer
|
91
|
-
@tk.grid unless @tk.is_a?(::Tk::Toplevel)
|
92
|
-
DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@tk)
|
93
77
|
@parent_proxy.post_initialize_child(self)
|
78
|
+
initialize_defaults
|
79
|
+
post_add_content if @block.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
def children
|
83
|
+
@children ||= []
|
94
84
|
end
|
95
85
|
|
96
86
|
# Subclasses may override to perform post initialization work on an added child
|
97
87
|
def post_initialize_child(child)
|
98
|
-
|
88
|
+
children << child
|
99
89
|
end
|
100
90
|
|
101
91
|
# Subclasses may override to perform post add_content work
|
@@ -154,41 +144,55 @@ module Glimmer
|
|
154
144
|
tk_widget_has_attribute_getter_setter?(attribute) or
|
155
145
|
has_state?(attribute) or
|
156
146
|
has_attributes_attribute?(attribute) or
|
157
|
-
respond_to?(attribute_setter(attribute), args)
|
147
|
+
respond_to?(attribute_setter(attribute), args) or
|
148
|
+
respond_to?(attribute_setter(attribute), *args, super_only: true) or
|
149
|
+
respond_to?(attribute, *args, super_only: true)
|
158
150
|
end
|
159
151
|
|
160
152
|
def set_attribute(attribute, *args)
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
153
|
+
begin
|
154
|
+
widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
|
155
|
+
if respond_to?(attribute_setter(attribute), super_only: true)
|
156
|
+
send(attribute_setter(attribute), *args)
|
157
|
+
elsif respond_to?(attribute, super_only: true) && self.class.instance_method(attribute).parameters.size > 0
|
158
|
+
send(attribute, *args)
|
159
|
+
elsif widget_custom_attribute
|
160
|
+
widget_custom_attribute[:setter][:invoker].call(@tk, args)
|
161
|
+
elsif tk_widget_has_attribute_setter?(attribute)
|
162
|
+
unless args.size == 1 && @tk.send(attribute) == args.first
|
163
|
+
if args.size == 1
|
164
|
+
@tk.send(attribute_setter(attribute), *args)
|
165
|
+
else
|
166
|
+
@tk.send(attribute_setter(attribute), args)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
elsif tk_widget_has_attribute_getter_setter?(attribute)
|
170
|
+
@tk.send(attribute, *args)
|
171
|
+
elsif has_state?(attribute)
|
172
|
+
attribute = attribute.sub(/=$/, '')
|
173
|
+
if !!args.first
|
174
|
+
@tk.tile_state(attribute)
|
168
175
|
else
|
169
|
-
@tk.
|
176
|
+
@tk.tile_state("!#{attribute}")
|
170
177
|
end
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
elsif has_state?(attribute)
|
175
|
-
attribute = attribute.sub(/=$/, '')
|
176
|
-
if !!args.first
|
177
|
-
@tk.tile_state(attribute)
|
178
|
+
elsif has_attributes_attribute?(attribute)
|
179
|
+
attribute = attribute.sub(/=$/, '')
|
180
|
+
@tk.attributes(attribute, args.first)
|
178
181
|
else
|
179
|
-
|
182
|
+
raise "#{self} cannot handle attribute #{attribute} with args #{args.inspect}"
|
180
183
|
end
|
181
|
-
|
182
|
-
attribute
|
183
|
-
|
184
|
-
|
185
|
-
send(attribute_setter(attribute), args)
|
184
|
+
rescue => e
|
185
|
+
Glimmer::Config.logger.debug {"Failed to set attribute #{attribute} with args #{args.inspect}. Attempting to set through style instead..."}
|
186
|
+
Glimmer::Config.logger.debug {e.full_message}
|
187
|
+
apply_style(attribute => args.first)
|
186
188
|
end
|
187
189
|
end
|
188
190
|
|
189
191
|
def get_attribute(attribute)
|
190
192
|
widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
|
191
|
-
if
|
193
|
+
if respond_to?(attribute, super_only: true)
|
194
|
+
send(attribute)
|
195
|
+
elsif widget_custom_attribute
|
192
196
|
widget_custom_attribute[:getter][:invoker].call(@tk, args)
|
193
197
|
elsif tk_widget_has_attribute_getter_setter?(attribute)
|
194
198
|
@tk.send(attribute)
|
@@ -207,7 +211,49 @@ module Glimmer
|
|
207
211
|
"#{attribute}="
|
208
212
|
end
|
209
213
|
|
214
|
+
def style=(styles)
|
215
|
+
styles.each do |attribute, value|
|
216
|
+
apply_style(attribute => value)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def grid(options = {})
|
221
|
+
options = options.stringify_keys
|
222
|
+
index_in_parent = @parent_proxy.children.index(self)
|
223
|
+
options['rowweight'] = options.delete('row_weight') if options.keys.include?('row_weight')
|
224
|
+
options['columnweight'] = options.delete('column_weight') if options.keys.include?('column_weight')
|
225
|
+
options['columnweight'] = options['rowweight'] = options.delete('weight') if options.keys.include?('weight')
|
226
|
+
options['rowminsize'] = options.delete('row_minsize') if options.keys.include?('row_minsize')
|
227
|
+
options['rowminsize'] = options.delete('minheight') if options.keys.include?('minheight')
|
228
|
+
options['rowminsize'] = options.delete('min_height') if options.keys.include?('min_height')
|
229
|
+
options['columnminsize'] = options.delete('column_minsize') if options.keys.include?('column_minsize')
|
230
|
+
options['columnminsize'] = options.delete('minwidth') if options.keys.include?('minwidth')
|
231
|
+
options['columnminsize'] = options.delete('min_width') if options.keys.include?('min_width')
|
232
|
+
options['columnminsize'] = options['rowminsize'] = options.delete('minsize') if options.keys.include?('minsize')
|
233
|
+
TkGrid.rowconfigure(@parent_proxy.tk, index_in_parent, 'weight'=> options.delete('rowweight')) if options.keys.include?('rowweight')
|
234
|
+
TkGrid.rowconfigure(@parent_proxy.tk, index_in_parent, 'minsize'=> options.delete('rowminsize')) if options.keys.include?('rowminsize')
|
235
|
+
TkGrid.columnconfigure(@parent_proxy.tk, index_in_parent, 'weight'=> options.delete('columnweight')) if options.keys.include?('columnweight')
|
236
|
+
TkGrid.columnconfigure(@parent_proxy.tk, index_in_parent, 'minsize'=> options.delete('columnminsize')) if options.keys.include?('columnminsize')
|
237
|
+
@tk.grid(options)
|
238
|
+
end
|
239
|
+
|
240
|
+
def font=(value)
|
241
|
+
@tk.font = value.is_a?(TkFont) ? value : TkFont.new(value)
|
242
|
+
rescue => e
|
243
|
+
Glimmer::Config.logger.debug {"Failed to set attribute #{attribute} with args #{args.inspect}. Attempting to set through style instead..."}
|
244
|
+
Glimmer::Config.logger.debug {e.full_message}
|
245
|
+
apply_style({"font" => value})
|
246
|
+
end
|
247
|
+
|
248
|
+
def apply_style(options)
|
249
|
+
@@style_number = 0 unless defined?(@@style_number)
|
250
|
+
style = "style#{@@style_number}.#{@tk.class.name.split('::').last}"
|
251
|
+
::Tk::Tile::Style.configure(style, options)
|
252
|
+
@tk.style = style
|
253
|
+
end
|
254
|
+
|
210
255
|
def widget_custom_attribute_mapping
|
256
|
+
# TODO consider extracting to modules/subclasses
|
211
257
|
@widget_custom_attribute_mapping ||= {
|
212
258
|
::Tk::Tile::TButton => {
|
213
259
|
'image' => {
|
@@ -221,10 +267,24 @@ module Glimmer
|
|
221
267
|
setter: {name: 'image=', invoker: lambda { |widget, args| @tk.image = image_argument(args) }},
|
222
268
|
},
|
223
269
|
'variable' => {
|
224
|
-
getter: {name: 'variable', invoker: lambda { |widget, args| @tk.variable&.value.
|
270
|
+
getter: {name: 'variable', invoker: lambda { |widget, args| @tk.variable&.value.to_s == @tk.onvalue.to_s }},
|
225
271
|
setter: {name: 'variable=', invoker: lambda { |widget, args| @tk.variable&.value = args.first.is_a?(Integer) ? args.first : (args.first ? 1 : 0) }},
|
226
272
|
},
|
227
273
|
},
|
274
|
+
::Tk::Tile::TRadiobutton => {
|
275
|
+
'image' => {
|
276
|
+
getter: {name: 'image', invoker: lambda { |widget, args| @tk.image }},
|
277
|
+
setter: {name: 'image=', invoker: lambda { |widget, args| @tk.image = image_argument(args) }},
|
278
|
+
},
|
279
|
+
'text' => {
|
280
|
+
getter: {name: 'text', invoker: lambda { |widget, args| @tk.text }},
|
281
|
+
setter: {name: 'text=', invoker: lambda { |widget, args| @tk.value = @tk.text = args.first }},
|
282
|
+
},
|
283
|
+
'variable' => {
|
284
|
+
getter: {name: 'variable', invoker: lambda { |widget, args| @tk.variable&.value == @tk.value }},
|
285
|
+
setter: {name: 'variable=', invoker: lambda { |widget, args| @tk.variable&.value = args.first ? @tk.value : @tk.variable&.value }},
|
286
|
+
},
|
287
|
+
},
|
228
288
|
::Tk::Tile::TCombobox => {
|
229
289
|
'text' => {
|
230
290
|
getter: {name: 'text', invoker: lambda { |widget, args| @tk.textvariable&.value }},
|
@@ -244,18 +304,31 @@ module Glimmer
|
|
244
304
|
::Tk::Tile::TEntry => {
|
245
305
|
'text' => {
|
246
306
|
getter: {name: 'text', invoker: lambda { |widget, args| @tk.textvariable&.value }},
|
247
|
-
setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first
|
307
|
+
setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first }},
|
308
|
+
},
|
309
|
+
},
|
310
|
+
::Tk::Tile::TSpinbox => {
|
311
|
+
'text' => {
|
312
|
+
getter: {name: 'text', invoker: lambda { |widget, args| @tk.textvariable&.value }},
|
313
|
+
setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first }},
|
314
|
+
},
|
315
|
+
},
|
316
|
+
::Tk::Root => {
|
317
|
+
'text' => {
|
318
|
+
getter: {name: 'text', invoker: lambda { |widget, args| @tk.title }},
|
319
|
+
setter: {name: 'text=', invoker: lambda { |widget, args| @tk.title = args.first }},
|
248
320
|
},
|
249
321
|
},
|
250
322
|
}
|
251
323
|
end
|
252
324
|
|
253
325
|
def widget_attribute_listener_installers
|
326
|
+
# TODO consider extracting to modules/subclasses
|
254
327
|
@tk_widget_attribute_listener_installers ||= {
|
255
328
|
::Tk::Tile::TCheckbutton => {
|
256
329
|
'variable' => lambda do |observer|
|
257
330
|
@tk.command {
|
258
|
-
observer.call(@tk.variable.value.
|
331
|
+
observer.call(@tk.variable.value.to_s == @tk.onvalue.to_s)
|
259
332
|
}
|
260
333
|
end,
|
261
334
|
},
|
@@ -273,16 +346,37 @@ module Glimmer
|
|
273
346
|
},
|
274
347
|
::Tk::Tile::TEntry => {
|
275
348
|
'text' => lambda do |observer|
|
276
|
-
tk.
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
349
|
+
@tk.textvariable.trace('write') {
|
350
|
+
observer.call(@tk.textvariable.value)
|
351
|
+
}
|
352
|
+
end,
|
353
|
+
},
|
354
|
+
::Tk::Tile::TSpinbox => {
|
355
|
+
'text' => lambda do |observer|
|
356
|
+
@tk.command {
|
357
|
+
observer.call(@tk.textvariable&.value)
|
358
|
+
}
|
359
|
+
@tk.validate('key')
|
360
|
+
@tk.validatecommand { |validate_args|
|
361
|
+
observer.call(validate_args.value)
|
362
|
+
new_icursor = validate_args.index
|
363
|
+
new_icursor += validate_args.string.size if validate_args.action == 1
|
364
|
+
@tk.icursor = new_icursor
|
365
|
+
true
|
366
|
+
}
|
367
|
+
end,
|
368
|
+
},
|
369
|
+
::Tk::Text => {
|
370
|
+
'text' => lambda do |observer|
|
371
|
+
handle_listener('modified') do
|
372
|
+
observer.call(text)
|
373
|
+
end
|
374
|
+
end,
|
375
|
+
},
|
376
|
+
::Tk::Tile::TRadiobutton => {
|
377
|
+
'variable' => lambda do |observer|
|
378
|
+
@tk.command {
|
379
|
+
observer.call(@tk.variable.value == @tk.value)
|
286
380
|
}
|
287
381
|
end,
|
288
382
|
},
|
@@ -341,10 +435,21 @@ module Glimmer
|
|
341
435
|
super(method.to_sym, *args, &block)
|
342
436
|
end
|
343
437
|
|
344
|
-
def respond_to?(method, *args, &block)
|
345
|
-
super ||
|
346
|
-
tk.respond_to?(method, *args, &block)
|
438
|
+
def respond_to?(method, *args, super_only: false, &block)
|
439
|
+
super(method, true) ||
|
440
|
+
!super_only && tk.respond_to?(method, *args, &block)
|
441
|
+
end
|
442
|
+
|
443
|
+
private
|
444
|
+
|
445
|
+
def initialize_defaults
|
446
|
+
options = {}
|
447
|
+
options[:sticky] = 'nsew'
|
448
|
+
options[:column_weight] = 1 if @parent_proxy.children.count == 1
|
449
|
+
grid(options) unless @tk.is_a?(::Tk::Toplevel)
|
347
450
|
end
|
348
451
|
end
|
349
452
|
end
|
350
453
|
end
|
454
|
+
|
455
|
+
Dir[File.expand_path('./*_proxy.rb', __dir__)].each {|f| require f}
|