tk_component 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -0
- data/Gemfile.lock +16 -5
- data/bin/browser_demo.rb +49 -0
- data/bin/table_view_demo.rb +66 -0
- data/bin/tiles_demo.rb +48 -0
- data/lib/tk_component.rb +5 -0
- data/lib/tk_component/base.rb +49 -3
- data/lib/tk_component/basic_component.rb +8 -0
- data/lib/tk_component/browser_column_component.rb +70 -0
- data/lib/tk_component/browser_component.rb +66 -0
- data/lib/tk_component/builder/grid_map.rb +4 -4
- data/lib/tk_component/builder/node.rb +35 -11
- data/lib/tk_component/builder/tk_item.rb +354 -18
- data/lib/tk_component/menu.rb +4 -0
- data/lib/tk_component/r_browser_component.rb +33 -0
- data/lib/tk_component/table_view_component.rb +90 -0
- data/lib/tk_component/turtle.rb +100 -0
- data/lib/tk_component/version.rb +1 -1
- data/lib/tk_component/window.rb +4 -4
- metadata +16 -6
@@ -35,10 +35,10 @@ module TkComponent
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def set_weights(row, col, weights = {})
|
38
|
-
|
39
|
-
@row_weights[row] = ((rw = @row_weights[row]).present? ? [rw,
|
40
|
-
|
41
|
-
@column_weights[col] = ((cw = @column_weights[col]).present? ? [cw,
|
38
|
+
vw = weights[:y_flex]
|
39
|
+
@row_weights[row] = ((rw = @row_weights[row]).present? ? [rw, vw].max : vw) if vw
|
40
|
+
hw = weights[:x_flex]
|
41
|
+
@column_weights[col] = ((cw = @column_weights[col]).present? ? [cw, hw].max : hw) if hw
|
42
42
|
end
|
43
43
|
|
44
44
|
def row_indexes
|
@@ -1,16 +1,19 @@
|
|
1
1
|
module TkComponent
|
2
2
|
module Builder
|
3
3
|
|
4
|
-
TK_CMDS = %w(label entry button canvas text scale group).to_set.freeze
|
4
|
+
TK_CMDS = %w(label entry button radio_set radio_button canvas text scale group tree tree_node hscroll_bar vscroll_bar hpaned vpaned).to_set.freeze
|
5
5
|
LAYOUT_CMDS = %w(frame hframe vframe row cell).to_set.freeze
|
6
|
-
EVENT_CMDS = %w(on_change on_mouse_down on_mouse_up on_mouse_drag on_mouse_wheel on_click on_event).to_set.freeze
|
6
|
+
EVENT_CMDS = %w(on_change on_mouse_down on_mouse_up on_mouse_drag on_mouse_wheel on_click on_select on_item_open on_event).to_set.freeze
|
7
7
|
TOKENS = (TK_CMDS + LAYOUT_CMDS + EVENT_CMDS).freeze
|
8
8
|
|
9
|
+
LAYOUT_OPTIONS = %i(column row rowspan columnspan sticky x_flex y_flex)
|
10
|
+
|
9
11
|
class Node
|
10
12
|
attr_accessor :name
|
11
13
|
attr_accessor :options
|
12
14
|
attr_accessor :sub_nodes
|
13
15
|
attr_accessor :grid
|
16
|
+
attr_accessor :weights
|
14
17
|
attr_accessor :grid_map
|
15
18
|
attr_accessor :event_handlers
|
16
19
|
attr_accessor :tk_item
|
@@ -29,14 +32,14 @@ module TkComponent
|
|
29
32
|
@name = name
|
30
33
|
@options = options.with_indifferent_access
|
31
34
|
@sub_nodes = []
|
32
|
-
@grid = {}
|
35
|
+
@grid = {}.with_indifferent_access
|
36
|
+
@weights = {}.with_indifferent_access
|
33
37
|
@grid_map = GridMap.new
|
34
38
|
@event_handlers = []
|
35
39
|
@tk_item = nil
|
36
40
|
end
|
37
41
|
|
38
42
|
def short(level = 0)
|
39
|
-
puts(" " * level + " #{@name}")
|
40
43
|
@sub_nodes.each do |n|
|
41
44
|
n.short(level + 4)
|
42
45
|
end
|
@@ -44,10 +47,12 @@ module TkComponent
|
|
44
47
|
end
|
45
48
|
|
46
49
|
def insert_component(component_class, parent_component, options = {}, &block)
|
47
|
-
|
50
|
+
layout_options = options.slice(*LAYOUT_OPTIONS)
|
51
|
+
c_node = node_from_command(:frame, layout_options, &block)
|
48
52
|
comp = component_class.new(options.merge(parent: parent_component, parent_node: c_node))
|
49
53
|
comp.generate(parent_component, options)
|
50
54
|
parent_component.add_child(comp)
|
55
|
+
comp
|
51
56
|
end
|
52
57
|
|
53
58
|
def add_event_handler(name, lambda, options = {})
|
@@ -61,9 +66,25 @@ module TkComponent
|
|
61
66
|
sub_nodes.each do |n|
|
62
67
|
n.build(self, parent_component)
|
63
68
|
end
|
69
|
+
apply_grid
|
70
|
+
built
|
71
|
+
end
|
72
|
+
|
73
|
+
def apply_grid
|
64
74
|
self.tk_item.apply_internal_grid(grid_map)
|
65
75
|
end
|
66
76
|
|
77
|
+
def built
|
78
|
+
self.tk_item.built
|
79
|
+
end
|
80
|
+
|
81
|
+
def rebuilt
|
82
|
+
end
|
83
|
+
|
84
|
+
def remove
|
85
|
+
self.tk_item.remove
|
86
|
+
end
|
87
|
+
|
67
88
|
def prepare_option_events(component)
|
68
89
|
option_events = options.extract!(*EVENT_CMDS)
|
69
90
|
option_events.each do |k, v|
|
@@ -74,6 +95,7 @@ module TkComponent
|
|
74
95
|
end
|
75
96
|
|
76
97
|
def prepare_grid
|
98
|
+
self.grid_map = GridMap.new
|
77
99
|
return unless self.sub_nodes.any?
|
78
100
|
current_row = -1
|
79
101
|
current_col = -1
|
@@ -90,13 +112,15 @@ module TkComponent
|
|
90
112
|
current_col = 0 if current_col < 0
|
91
113
|
current_row, current_col = grid_map.get_next_cell(current_row, current_col, going_down)
|
92
114
|
binding.pry if n.options.nil?
|
93
|
-
grid = n.
|
94
|
-
n.grid
|
95
|
-
|
96
|
-
|
115
|
+
n.grid = {}.with_indifferent_access if n.grid.nil?
|
116
|
+
n.grid.merge!(n.options.extract!(:column, :row, :rowspan, :columnspan, :sticky))
|
117
|
+
n.grid.merge!(column: current_col, row: current_row)
|
118
|
+
rowspan = n.grid[:rowspan] || 1
|
119
|
+
columnspan = n.grid[:columnspan] || 1
|
97
120
|
grid_map.fill(current_row, current_col, rowspan, columnspan, true)
|
98
|
-
weights = n.
|
99
|
-
|
121
|
+
n.weights = {}.with_indifferent_access if n.weights.nil?
|
122
|
+
n.weights.merge!(n.options.extract!(:x_flex, :y_flex))
|
123
|
+
grid_map.set_weights(current_row, current_col, n.weights)
|
100
124
|
n.prepare_grid
|
101
125
|
final_sub_nodes << n
|
102
126
|
end
|
@@ -11,34 +11,43 @@ module TkComponent
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def initialize(parent_item, name, options = {}, grid = {}, event_handlers = [])
|
14
|
-
|
15
|
-
raise "Don't know how to create #{name}" unless tk_class
|
16
|
-
@native_item = tk_class.new(parent_item.native_item)
|
14
|
+
@native_item = create_native_item(parent_item.native_item, name, options, grid, event_handlers)
|
17
15
|
apply_options(options)
|
18
16
|
set_grid(grid)
|
19
17
|
set_event_handlers(event_handlers)
|
20
18
|
end
|
21
19
|
|
22
|
-
def
|
20
|
+
def create_native_item(parent_native_item, name, options = {}, grid = {}, event_handlers = [])
|
21
|
+
native_item_class(parent_native_item, name, options, grid, event_handlers).new(parent_native_item)
|
22
|
+
end
|
23
|
+
|
24
|
+
def native_item_class(parent_native_item, name, options = {}, grid = {}, event_handlers = [])
|
25
|
+
tk_class = TK_CLASSES[name.to_sym]
|
26
|
+
raise "Don't know how to create #{name}" unless tk_class.present?
|
27
|
+
return tk_class
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove
|
31
|
+
@native_item.destroy
|
32
|
+
end
|
33
|
+
|
34
|
+
def apply_options(options, to_item = self.native_item)
|
23
35
|
options.each do |k,v|
|
24
|
-
apply_option(k, v)
|
36
|
+
apply_option(k, v, to_item)
|
25
37
|
end
|
26
38
|
end
|
27
39
|
|
28
|
-
def apply_option(option, value)
|
29
|
-
|
40
|
+
def apply_option(option, value, to_item = self.native_item)
|
41
|
+
to_item.public_send(option, value)
|
30
42
|
end
|
31
43
|
|
32
|
-
def set_grid(grid)
|
33
|
-
|
44
|
+
def set_grid(grid, to_item = self.native_item)
|
45
|
+
to_item.grid(grid)
|
34
46
|
end
|
35
47
|
|
36
48
|
def apply_internal_grid(grid_map)
|
37
|
-
puts(grid_map)
|
38
49
|
grid_map.column_indexes.each { |c| TkGrid.columnconfigure(self.native_item, c, weight: grid_map.column_weight(c)) }
|
39
50
|
grid_map.row_indexes.each { |r| TkGrid.rowconfigure(self.native_item, r, weight: grid_map.row_weight(r)) }
|
40
|
-
# grid_map.column_indexes.each { |c| TkGrid.columnconfigure(self.native_item, c, weight: 1) }
|
41
|
-
# grid_map.row_indexes.each { |r| TkGrid.rowconfigure(self.native_item, r, weight: 1) }
|
42
51
|
end
|
43
52
|
|
44
53
|
def set_event_handlers(event_handlers)
|
@@ -55,10 +64,17 @@ module TkComponent
|
|
55
64
|
Event.bind_event(event_handler.name, self, event_handler.options, event_handler.lambda)
|
56
65
|
end
|
57
66
|
end
|
67
|
+
|
68
|
+
def built
|
69
|
+
end
|
70
|
+
|
71
|
+
def focus
|
72
|
+
self.native_item.focus
|
73
|
+
end
|
58
74
|
end
|
59
75
|
|
60
76
|
module ValueTyping
|
61
|
-
def apply_option(option, v)
|
77
|
+
def apply_option(option, v, to_item = self.native_item)
|
62
78
|
case option.to_sym
|
63
79
|
when :value
|
64
80
|
self.value = v
|
@@ -90,15 +106,23 @@ module TkComponent
|
|
90
106
|
attr_accessor :tk_variable
|
91
107
|
|
92
108
|
def initialize(parent_item, name, options = {}, grid = {}, event_handlers = [])
|
93
|
-
|
109
|
+
create_variable
|
94
110
|
super
|
95
|
-
|
111
|
+
apply_variable
|
96
112
|
end
|
97
113
|
|
98
114
|
def variable_name
|
99
115
|
:variable
|
100
116
|
end
|
101
117
|
|
118
|
+
def apply_variable
|
119
|
+
self.native_item&.public_send(variable_name, @tk_variable)
|
120
|
+
end
|
121
|
+
|
122
|
+
def create_variable
|
123
|
+
@tk_variable = TkVariable.new
|
124
|
+
end
|
125
|
+
|
102
126
|
delegate :value, to: :tk_variable
|
103
127
|
delegate :"value=", to: :tk_variable
|
104
128
|
end
|
@@ -127,8 +151,83 @@ module TkComponent
|
|
127
151
|
end
|
128
152
|
end
|
129
153
|
|
154
|
+
class TkRadioSet < TkItemWithVariable
|
155
|
+
# The variable for the radio set is only to be used by radio buttons inside it
|
156
|
+
# Thus, we don't try to link it to the actual item
|
157
|
+
def apply_variable
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class TkRadioButton < TkItemWithVariable
|
162
|
+
# We need to use the tk_variable created by the parent_item
|
163
|
+
# So we set it here and skip creation below
|
164
|
+
def initialize(parent_item, name, options = {}, grid = {}, event_handlers = [])
|
165
|
+
@tk_variable = parent_item.tk_variable
|
166
|
+
super
|
167
|
+
end
|
168
|
+
|
169
|
+
def create_variable
|
170
|
+
end
|
171
|
+
|
172
|
+
# It is unfortunate that native TK radio buttons use 'value' to
|
173
|
+
# spedify the value for each of them, colliding with the 'value'
|
174
|
+
# methods for our items with variables. Thus, we need to
|
175
|
+
# override the setting of the 'value' option to revert it to the
|
176
|
+
# default functionality
|
177
|
+
def apply_option(option, v, to_item = self.native_item)
|
178
|
+
case option.to_sym
|
179
|
+
when :value
|
180
|
+
to_item.public_send(option, v)
|
181
|
+
else
|
182
|
+
super
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
module Scrollable
|
188
|
+
ROOT_FRAME_OPTIONS = %i|width height relief borderwidth padx pady padding| + TkComponent::Builder::LAYOUT_OPTIONS
|
189
|
+
|
190
|
+
def initialize(parent_item, name, options = {}, grid = {}, event_handlers = [])
|
191
|
+
return super unless (s_options = options.delete(:scrollers)) && s_options.present? && s_options != 'none'
|
192
|
+
frame_item = TK_CLASSES[:frame].new(parent_item.native_item) # Containing frame
|
193
|
+
real_native_item = create_native_item(frame_item, name, options, grid, event_handlers)
|
194
|
+
f_options = options.extract!(*ROOT_FRAME_OPTIONS)
|
195
|
+
apply_options(f_options, frame_item) # Apply the applicable options to the enclosing frame
|
196
|
+
@native_item = real_native_item
|
197
|
+
apply_options(options, real_native_item)
|
198
|
+
set_grid(grid, frame_item)
|
199
|
+
real_native_item.grid( :column => 0, :row => 0, :sticky => 'nwes')
|
200
|
+
if s_options.include?('x')
|
201
|
+
h_scrollbar = TK_CLASSES[:hscroll_bar].new(frame_item)
|
202
|
+
h_scrollbar.orient('horizontal')
|
203
|
+
h_scrollbar.command proc { |*args| real_native_item.xview(*args) }
|
204
|
+
real_native_item['xscrollcommand'] = proc { |*args| h_scrollbar.set(*args) }
|
205
|
+
h_scrollbar.grid( :column => 0, :row => 1, :sticky => 'wes')
|
206
|
+
end
|
207
|
+
if s_options.include?('y')
|
208
|
+
v_scrollbar = TK_CLASSES[:vscroll_bar].new(frame_item)
|
209
|
+
v_scrollbar.orient('vertical')
|
210
|
+
v_scrollbar.command proc { |*args| real_native_item.yview(*args) }
|
211
|
+
real_native_item['yscrollcommand'] = proc { |*args| v_scrollbar.set(*args) }
|
212
|
+
v_scrollbar.grid( :column => 1, :row => 0, :sticky => 'nse')
|
213
|
+
end
|
214
|
+
TkGrid.columnconfigure(frame_item, 0, :weight => 1)
|
215
|
+
TkGrid.columnconfigure(frame_item, 1, :weight => 0) if v_scrollbar.present?
|
216
|
+
TkGrid.rowconfigure(frame_item, 0, :weight => 1)
|
217
|
+
TkGrid.rowconfigure(frame_item, 1, :weight => 0) if h_scrollbar.present?
|
218
|
+
@native_item = real_native_item
|
219
|
+
set_event_handlers(event_handlers)
|
220
|
+
end
|
221
|
+
|
222
|
+
# We need to remove the parent native item, as it's the container we put in place initially
|
223
|
+
def remove
|
224
|
+
@native_item.winfo_parent.destroy
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
130
228
|
class TkText < TkItem
|
131
229
|
include ValueTyping
|
230
|
+
include Scrollable
|
132
231
|
|
133
232
|
def value
|
134
233
|
native_item.get('1.0', 'end')
|
@@ -138,6 +237,24 @@ module TkComponent
|
|
138
237
|
native_item.replace('1.0', 'end', text)
|
139
238
|
end
|
140
239
|
|
240
|
+
def selected_text
|
241
|
+
ranges = native_item.tag_ranges('sel')
|
242
|
+
return nil if ranges.empty?
|
243
|
+
native_item.get(ranges.first.first, ranges.first.last)
|
244
|
+
end
|
245
|
+
|
246
|
+
def current_line
|
247
|
+
native_item.get('insert linestart', 'insert lineend')
|
248
|
+
end
|
249
|
+
|
250
|
+
def append_text(text)
|
251
|
+
native_item.insert('end', text)
|
252
|
+
end
|
253
|
+
|
254
|
+
def select_range(from, to)
|
255
|
+
native_item.tag_add('sel', from, to)
|
256
|
+
end
|
257
|
+
|
141
258
|
def set_event_handler(event_handler)
|
142
259
|
case event_handler.name
|
143
260
|
when :change
|
@@ -159,11 +276,214 @@ module TkComponent
|
|
159
276
|
end
|
160
277
|
end
|
161
278
|
|
279
|
+
class TkTree < TkItem
|
280
|
+
include Scrollable
|
281
|
+
@column_defs = []
|
282
|
+
|
283
|
+
def apply_options(options, to_item = self.native_item)
|
284
|
+
super
|
285
|
+
return unless @column_defs.present?
|
286
|
+
cols = @column_defs.map { |c| c[:key] }
|
287
|
+
to_item.columns(cols[1..-1].join(' ')) unless cols == ['#0']
|
288
|
+
@column_defs.each.with_index do |cd, idx|
|
289
|
+
key = idx == 0 ? '#0' : cd[:key]
|
290
|
+
column_conf = cd.slice(:width, :anchor)
|
291
|
+
to_item.column_configure(key, column_conf) unless column_conf.empty?
|
292
|
+
heading_conf = cd.slice(:text)
|
293
|
+
to_item.heading_configure(key, heading_conf) unless heading_conf.empty?
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
def apply_option(option, v, to_item = self.native_item)
|
298
|
+
case option.to_sym
|
299
|
+
when :column_defs
|
300
|
+
@column_defs = v
|
301
|
+
when :heading
|
302
|
+
@column_defs = [ { key: '#0', text: v } ]
|
303
|
+
else
|
304
|
+
super
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def set_event_handler(event_handler)
|
309
|
+
case event_handler.name
|
310
|
+
when :select
|
311
|
+
Event.bind_event('<TreeviewSelect>', self, event_handler.options, event_handler.lambda)
|
312
|
+
when :item_open
|
313
|
+
Event.bind_event('<TreeviewOpen>', self, event_handler.options, event_handler.lambda)
|
314
|
+
else
|
315
|
+
super
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def scroll_to_selection
|
320
|
+
scroll_to_item(@native_item.selection.first)
|
321
|
+
end
|
322
|
+
|
323
|
+
# Right now it only works well for non-nested trees
|
324
|
+
def scroll_to_item(tree_item)
|
325
|
+
return unless tree_item.present?
|
326
|
+
items = @native_item.children('')
|
327
|
+
rel_pos = items.index(tree_item).to_f / items.size.to_f
|
328
|
+
@native_item.after(200) { @native_item.yview_moveto(rel_pos) }
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
class TkTreeNode < TkItem
|
333
|
+
def initialize(parent_item, name, options = {}, grid = {}, event_handlers = [])
|
334
|
+
item_options = options.dup
|
335
|
+
parent_node = item_options.delete(:parent) || ''
|
336
|
+
parent_native_item = (parent_node == '' ? '' : parent_node.native_item)
|
337
|
+
at = item_options.delete(:at)
|
338
|
+
selected = item_options.delete(:selected)
|
339
|
+
@native_item = parent_item.native_item.insert(parent_native_item, at, item_options)
|
340
|
+
parent_item.native_item.selection_add(@native_item) if selected
|
341
|
+
set_event_handlers(event_handlers)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
class ScrollBar < TkItem
|
346
|
+
def apply_option(option, v, to_item = self.native_item)
|
347
|
+
case option.to_sym
|
348
|
+
when :linked_to
|
349
|
+
@linked_to = v
|
350
|
+
else
|
351
|
+
super
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
def set_event_handler(event_handler)
|
356
|
+
case event_handler.name
|
357
|
+
when :change
|
358
|
+
Event.Event.bind_command(event_handler.name, self, event_handler.options, event_handler.lambda)
|
359
|
+
else
|
360
|
+
super
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
def apply_options(options, to_item = self.native_item)
|
365
|
+
options.merge!(orient: orient)
|
366
|
+
super
|
367
|
+
end
|
368
|
+
|
369
|
+
def set_event_handlers(event_handlers)
|
370
|
+
bind_linked_to
|
371
|
+
super
|
372
|
+
end
|
373
|
+
|
374
|
+
def bind_linked_to
|
375
|
+
return unless @linked_to.present?
|
376
|
+
items = @linked_to.is_a?(Array) ? @linked_to.map(&:native_item) : [ @linked_to.native_item ]
|
377
|
+
self.native_item.command proc { |*args|
|
378
|
+
items.each do |item|
|
379
|
+
item.send(scroll_command, *args)
|
380
|
+
end
|
381
|
+
}
|
382
|
+
items.each do |item|
|
383
|
+
item.send(linked_scroll_command, proc { |*args| self.native_item.send(linked_scroll_event, *args) })
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def orient
|
388
|
+
raise "#{self.class.to_s} shouldn't be instantiated directly. Use 'H' or 'V' subclasses"
|
389
|
+
end
|
390
|
+
|
391
|
+
def scroll_command
|
392
|
+
raise "#{self.class.to_s} shouldn't be instantiated directly. Use 'H' or 'V' subclasses"
|
393
|
+
end
|
394
|
+
|
395
|
+
def linked_scroll_command
|
396
|
+
raise "#{self.class.to_s} shouldn't be instantiated directly. Use 'H' or 'V' subclasses"
|
397
|
+
end
|
398
|
+
|
399
|
+
def linked_scroll_event
|
400
|
+
raise "#{self.class.to_s} shouldn't be instantiated directly. Use 'H' or 'V' subclasses"
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
class HScrollbar < ScrollBar
|
405
|
+
def orient
|
406
|
+
'horizontal'
|
407
|
+
end
|
408
|
+
|
409
|
+
def scroll_command
|
410
|
+
:xview
|
411
|
+
end
|
412
|
+
|
413
|
+
def linked_scroll_command
|
414
|
+
:xscrollcommand
|
415
|
+
end
|
416
|
+
|
417
|
+
def linked_scroll_event
|
418
|
+
:set
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
class VScrollbar < ScrollBar
|
423
|
+
def orient
|
424
|
+
'vertical'
|
425
|
+
end
|
426
|
+
|
427
|
+
def scroll_command
|
428
|
+
:yview
|
429
|
+
end
|
430
|
+
|
431
|
+
def linked_scroll_command
|
432
|
+
:yscrollcommand
|
433
|
+
end
|
434
|
+
|
435
|
+
def linked_scroll_event
|
436
|
+
:set
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
class PanedWindow < TkItem
|
441
|
+
def create_native_item(parent_native_item, name, options = {}, grid = {}, event_handlers = [])
|
442
|
+
native_item_class(parent_native_item, name, options, grid, event_handlers).new(parent_native_item, orient: orient)
|
443
|
+
end
|
444
|
+
|
445
|
+
def built
|
446
|
+
# We need to synchronize children items to the panned window
|
447
|
+
added_panes = self.native_item.winfo_children - self.native_item.panes
|
448
|
+
removed_panes = self.native_item.panes - self.native_item.winfo_children
|
449
|
+
added_panes.each do |child|
|
450
|
+
self.native_item.add(child, weight: 1)
|
451
|
+
end
|
452
|
+
removed_panes.each do |child|
|
453
|
+
self.native_item.forget(child)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
def orient
|
458
|
+
raise "#{self.class.to_s} shouldn't be instantiated directly. Use 'H' or 'V' subclasses"
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
class HPanedWindow < PanedWindow
|
463
|
+
def orient
|
464
|
+
'horizontal'
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
class VPanedWindow < PanedWindow
|
469
|
+
def orient
|
470
|
+
'vertical'
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
162
474
|
class TkWindow < TkItem
|
163
475
|
def initialize(parent_item, name, options = {}, grid = {}, event_handlers = [])
|
164
|
-
|
476
|
+
if (options.delete(:root))
|
477
|
+
@native_item = TkRoot.new { title options[:title] }
|
478
|
+
else
|
479
|
+
@native_item = TkToplevel.new { title options[:title] }
|
480
|
+
end
|
165
481
|
apply_options(options)
|
166
482
|
end
|
483
|
+
|
484
|
+
def focus
|
485
|
+
self.native_item.set_focus
|
486
|
+
end
|
167
487
|
end
|
168
488
|
|
169
489
|
TK_CLASSES = {
|
@@ -174,10 +494,17 @@ module TkComponent
|
|
174
494
|
label: Tk::Tile::Label,
|
175
495
|
entry: Tk::Tile::Entry,
|
176
496
|
button: Tk::Tile::Button,
|
497
|
+
radio_set: Tk::Tile::Frame,
|
498
|
+
radio_button: Tk::Tile::RadioButton,
|
177
499
|
canvas: Tk::Canvas,
|
178
500
|
text: ::TkText,
|
179
501
|
scale: Tk::Tile::Scale,
|
180
|
-
group: Tk::Tile::LabelFrame
|
502
|
+
group: Tk::Tile::LabelFrame,
|
503
|
+
tree: Tk::Tile::Treeview,
|
504
|
+
hscroll_bar: Tk::Tile::Scrollbar,
|
505
|
+
vscroll_bar: Tk::Tile::Scrollbar,
|
506
|
+
hpaned: Tk::Tile::Paned,
|
507
|
+
vpaned: Tk::Tile::Paned
|
181
508
|
}
|
182
509
|
|
183
510
|
ITEM_CLASSES = {
|
@@ -188,10 +515,19 @@ module TkComponent
|
|
188
515
|
label: TkComponent::Builder::TkItem,
|
189
516
|
entry: TkComponent::Builder::TkEntry,
|
190
517
|
button: TkComponent::Builder::TkItem,
|
518
|
+
radio_set: TkComponent::Builder::TkRadioSet,
|
519
|
+
radio_button: TkComponent::Builder::TkRadioButton,
|
191
520
|
canvas: TkComponent::Builder::TkItem,
|
192
521
|
text: TkComponent::Builder::TkText,
|
193
522
|
scale: TkComponent::Builder::TkScale,
|
194
|
-
group: TkComponent::Builder::TkItem
|
523
|
+
group: TkComponent::Builder::TkItem,
|
524
|
+
tree: TkComponent::Builder::TkTree,
|
525
|
+
tree_node: TkComponent::Builder::TkTreeNode,
|
526
|
+
hscroll_bar: TkComponent::Builder::HScrollbar,
|
527
|
+
vscroll_bar: TkComponent::Builder::VScrollbar,
|
528
|
+
hpaned: TkComponent::Builder::HPanedWindow,
|
529
|
+
vpaned: TkComponent::Builder::VPanedWindow
|
530
|
+
|
195
531
|
}
|
196
532
|
end
|
197
533
|
end
|