tkwrapper 1.0.2 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/tkwrapper.rb +1 -0
- data/lib/util/hash_recursive.rb +3 -6
- data/lib/util/tk/cell.rb +36 -0
- data/lib/util/tk/finder.rb +49 -0
- data/lib/util/tk/font.rb +51 -0
- data/lib/util/tk/tk.rb +8 -0
- data/lib/widgets/auto_resize_entry.rb +12 -38
- data/lib/widgets/base/base.rb +1 -0
- data/lib/widgets/base/comparator_item_store.rb +41 -0
- data/lib/widgets/base/configuration.rb +18 -18
- data/lib/widgets/base/manager.rb +29 -14
- data/lib/widgets/base/match.rb +18 -0
- data/lib/widgets/base/matcher.rb +58 -0
- data/lib/widgets/base/matches.rb +34 -0
- data/lib/widgets/base/widget.rb +27 -84
- data/lib/widgets/grid.rb +5 -5
- data/lib/widgets/menu.rb +8 -5
- metadata +10 -3
- data/lib/widgets/base/widgets.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81c1971220f794d1e17288aac5b75221393727be934288a4993a621c35b3282d
|
4
|
+
data.tar.gz: f2a841f6f3a6a7ee040c85fe0f2081234780bf1ff0bf4aeb70de9cf4c2a75055
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22cf843324096411be2441088df910d723ecc353aa6b54dd64ba5703b2fcd47bec3c2424a38e910fefb187fdcf23ec60dd44640de3f0657a3cb2969e84da016c
|
7
|
+
data.tar.gz: acb296b0e78c570e7d80ba96d91c4ebf62ecfd1ce7c97fac088546d599e0468a23dafac325ee14ae9fa0d4d08a9c8c70e5972df849346a05d8e2ac3ee9fb1154
|
data/lib/tkwrapper.rb
CHANGED
data/lib/util/hash_recursive.rb
CHANGED
@@ -19,12 +19,9 @@ module Util
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def self.
|
23
|
-
hash.
|
24
|
-
value
|
25
|
-
next recursive_transform_key_value!(value, &block) if value.is_a?(Hash)
|
26
|
-
|
27
|
-
block.call(key, value)
|
22
|
+
def self.clone_recursive(hash)
|
23
|
+
hash.transform_values do |value|
|
24
|
+
value.is_a?(Hash) ? clone_recursive(value) : value
|
28
25
|
end
|
29
26
|
end
|
30
27
|
end
|
data/lib/util/tk/cell.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'tk'
|
4
|
+
|
5
|
+
class TkWrapper::Util::Tk::Cell
|
6
|
+
def initialize(widget)
|
7
|
+
@widget = widget
|
8
|
+
end
|
9
|
+
|
10
|
+
# returns the bounding box of the tk_widget
|
11
|
+
def bbox
|
12
|
+
return unless (container = container_parent)
|
13
|
+
|
14
|
+
grid_info = TkGrid.info(@widget.tk_widget)
|
15
|
+
start_col = grid_info['column']
|
16
|
+
end_col = start_col + grid_info['columnspan'] - 1
|
17
|
+
start_row = grid_info['row']
|
18
|
+
end_row = start_row + grid_info['rowspan'] - 1
|
19
|
+
|
20
|
+
TkGrid.bbox(container.tk_widget, start_col, start_row, end_col, end_row)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# the first parent, which contains a tk_widget, which is really different
|
26
|
+
# from self.tk_widget
|
27
|
+
def container_parent
|
28
|
+
container = @widget.parent
|
29
|
+
while container.tk_widget == @widget.tk_widget
|
30
|
+
return unless container.parent # not in a grid?
|
31
|
+
|
32
|
+
container = container.parent
|
33
|
+
end
|
34
|
+
container
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "#{LIB_DIR}/widgets/base/manager"
|
4
|
+
require "#{LIB_DIR}/widgets/base/matcher"
|
5
|
+
require_relative 'tk'
|
6
|
+
|
7
|
+
class TkWrapper::Util::Tk::Finder
|
8
|
+
Matcher = TkWrapper::Widgets::Base::Matcher
|
9
|
+
|
10
|
+
def initialize(widgets: nil)
|
11
|
+
@widgets = widgets
|
12
|
+
end
|
13
|
+
|
14
|
+
def each_widget_match(widgets, matchers, &block)
|
15
|
+
widgets.each do |widget|
|
16
|
+
widget.ids.each do |id|
|
17
|
+
matchers.each do |matcher|
|
18
|
+
(match = matcher.match(id, widget)) && block.call(match)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def find(comparators, widgets = @widgets)
|
25
|
+
matchers = create_value_matchers(comparators)
|
26
|
+
|
27
|
+
each_widget_match(widgets, matchers) do |match|
|
28
|
+
return match.widget if match
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_all(comparators, widgets = @widgets)
|
33
|
+
matchers = create_value_matchers(comparators)
|
34
|
+
matches = TkWrapper::Widgets::Base::Matches.new
|
35
|
+
|
36
|
+
each_widget_match(widgets, matchers) do |match|
|
37
|
+
matches.push(match)
|
38
|
+
end
|
39
|
+
|
40
|
+
matches
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def create_value_matchers(comparators)
|
46
|
+
comparators = [comparators] unless comparators.is_a?(Array)
|
47
|
+
comparators.map { |comparator| Matcher.new(comparator: comparator) }
|
48
|
+
end
|
49
|
+
end
|
data/lib/util/tk/font.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tk'
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
require_relative 'tk'
|
7
|
+
|
8
|
+
class TkWrapper::Util::Tk::Font
|
9
|
+
def initialize(tk_widget)
|
10
|
+
@tk_widget = tk_widget
|
11
|
+
end
|
12
|
+
|
13
|
+
%i[family size weight slant underline overstrike].each do |option|
|
14
|
+
define_method("#{option}=") do |value, **args|
|
15
|
+
load unless @config
|
16
|
+
args[:update] ||= false
|
17
|
+
@config[option] = value
|
18
|
+
update if args[:update]
|
19
|
+
end
|
20
|
+
|
21
|
+
define_method(option) do
|
22
|
+
load unless @config
|
23
|
+
@config[option]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_update(&block)
|
28
|
+
block.call(self)
|
29
|
+
update
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_missing(method, *args)
|
33
|
+
if TkFont.respond_to?(method)
|
34
|
+
TkFont.send(method, @tk_widget.font, *args)
|
35
|
+
else
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def respond_to_missing?(method, *)
|
41
|
+
TkFont.respond_to?(method) || super
|
42
|
+
end
|
43
|
+
|
44
|
+
def load
|
45
|
+
@config = TkFont.actual(@tk_widget.font).to_h.transform_keys(&:to_sym)
|
46
|
+
end
|
47
|
+
|
48
|
+
def update
|
49
|
+
@tk_widget.font = TkFont.new(@config)
|
50
|
+
end
|
51
|
+
end
|
data/lib/util/tk/tk.rb
ADDED
@@ -4,57 +4,31 @@ class TkWrapper::Widgets::AutoResizeEntry < TkWrapper::Widgets::Entry
|
|
4
4
|
# auto resizes on user input, only works if in the grid geometry manager of tk
|
5
5
|
attr_accessor :min_width, :add_width
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@min_width = config
|
9
|
-
@add_width = config
|
10
|
-
super(
|
7
|
+
def initialize(**args)
|
8
|
+
@min_width = args[:config][:min_width] || 0
|
9
|
+
@add_width = args[:config][:add_width] || 0
|
10
|
+
super(**args)
|
11
11
|
end
|
12
12
|
|
13
|
-
def build(parent,
|
14
|
-
super(parent,
|
13
|
+
def build(parent, **args)
|
14
|
+
super(parent, **args)
|
15
15
|
parent.tk_widget.bind('Configure') { resize }
|
16
16
|
tk_widget.textvariable = TkVariable.new unless tk_widget.textvariable
|
17
17
|
tk_widget.textvariable.trace('write') { resize }
|
18
18
|
resize
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
|
23
|
-
{ config: { grid: {
|
24
|
-
row: grid_info['row'],
|
25
|
-
column: grid_info['column'],
|
26
|
-
columnspan: grid_info['columnspan'],
|
27
|
-
sticky: 'nw'
|
28
|
-
} } }
|
21
|
+
def value=(value)
|
22
|
+
tk_widget.textvariable.value = value
|
29
23
|
end
|
30
24
|
|
31
|
-
def
|
32
|
-
|
33
|
-
label.build(@parent)
|
34
|
-
label.tk_widget.text = tk_widget.textvariable.value
|
35
|
-
label.tk_widget.lower
|
36
|
-
result = block.call(label)
|
37
|
-
label.tk_widget.destroy
|
38
|
-
result
|
39
|
-
end
|
40
|
-
|
41
|
-
def text_width_in_pixel
|
42
|
-
create_dummy_label_with_same_size do |label|
|
43
|
-
@parent.tk_widget.update
|
44
|
-
label.tk_widget.winfo_width
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def textwidth_and_maxwidth_in_pixel
|
49
|
-
create_dummy_frame_with_same_size_label do |frame, label|
|
50
|
-
{ text_width: label.tk_widget.winfo_width,
|
51
|
-
max_width: frame.tk_widget.winfo_width }
|
52
|
-
end
|
25
|
+
def value
|
26
|
+
tk_widget.textvariable.value
|
53
27
|
end
|
54
28
|
|
55
29
|
def resize
|
56
|
-
max_width =
|
57
|
-
text_width =
|
30
|
+
max_width = @cell.bbox[2]
|
31
|
+
text_width = @font.measure(value)
|
58
32
|
new_width = [[@min_width, text_width + @add_width].max, max_width].min
|
59
33
|
tk_widget.width = 0
|
60
34
|
tk_widget.grid(ipadx: new_width / 2.0)
|
data/lib/widgets/base/base.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'matcher'
|
4
|
+
|
5
|
+
class TkWrapper::Widgets::Base::ComparatorItemStore
|
6
|
+
Matcher = TkWrapper::Widgets::Base::Matcher
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@key_map = {} # for fast lookup
|
10
|
+
@comparator_map = {} # for lookup using comparisons by Matcher class
|
11
|
+
end
|
12
|
+
|
13
|
+
def push(key, *items)
|
14
|
+
if [String, Symbol].include?(key)
|
15
|
+
(@key_map[key] ||= []).concat(items)
|
16
|
+
else
|
17
|
+
(@comparator_map[key] ||= []).concat(items)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# returns [{items: [...], match: Match}, {items: [...]}, ...]
|
22
|
+
def items_and_matches_for_widget(widget)
|
23
|
+
widget.ids.reduce([]) do |items, id|
|
24
|
+
items + items_from_key_map(id) + items_from_comparator_map(id, widget)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def items_from_key_map(id)
|
31
|
+
(items = @key_map[id]) ? [{ items: items }] : []
|
32
|
+
end
|
33
|
+
|
34
|
+
def items_from_comparator_map(id, widget)
|
35
|
+
matcher = Matcher.new(value: id)
|
36
|
+
|
37
|
+
@comparator_map.filter_map do |(comparator, items)|
|
38
|
+
(m = matcher.match(comparator, widget)) && { items: items, match: m }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -5,7 +5,7 @@ require "#{LIB_DIR}/util/hash_recursive.rb"
|
|
5
5
|
require_relative 'base'
|
6
6
|
|
7
7
|
class TkWrapper::Widgets::Base::Configuration
|
8
|
-
|
8
|
+
attr_reader :config
|
9
9
|
|
10
10
|
GRID_SPECIAL_VALUES = {
|
11
11
|
onecell: {
|
@@ -20,32 +20,24 @@ class TkWrapper::Widgets::Base::Configuration
|
|
20
20
|
}
|
21
21
|
}.freeze
|
22
22
|
|
23
|
-
NON_TK_OPTIONS = %i[
|
23
|
+
NON_TK_OPTIONS = %i[
|
24
|
+
tk_class tearoff weights menu min_width add_width
|
25
|
+
].freeze
|
24
26
|
|
25
27
|
def initialize(config)
|
26
|
-
@config =
|
28
|
+
@config = parse_and_clone(config)
|
27
29
|
end
|
28
30
|
|
29
|
-
def merge
|
31
|
+
def merge(*configurations)
|
30
32
|
configurations = configurations.map do |configuration|
|
31
|
-
|
33
|
+
configuration = configuration.config if configuration.is_a?(self.class)
|
32
34
|
|
33
|
-
|
35
|
+
parse_and_clone(configuration)
|
34
36
|
end
|
35
37
|
|
36
38
|
Util.merge_recursive!(@config, *configurations)
|
37
39
|
end
|
38
40
|
|
39
|
-
def parse!(config)
|
40
|
-
Util.each_recursive(config) do |hash, key, value|
|
41
|
-
next if value.is_a?(Hash)
|
42
|
-
|
43
|
-
hash[key] = parse_value(key, value)
|
44
|
-
end
|
45
|
-
|
46
|
-
config
|
47
|
-
end
|
48
|
-
|
49
41
|
def [](key)
|
50
42
|
key = key.to_sym
|
51
43
|
return self.class.new(@config[key]) if @config[key].is_a?(Hash)
|
@@ -55,7 +47,13 @@ class TkWrapper::Widgets::Base::Configuration
|
|
55
47
|
|
56
48
|
def []=(key, value)
|
57
49
|
key = key.to_sym
|
58
|
-
@config[key] =
|
50
|
+
@config[key] = parse_and_clone(value, key)
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse_and_clone(value, key = nil)
|
54
|
+
return parse_value(key, value) unless value.is_a?(Hash)
|
55
|
+
|
56
|
+
value.each_with_object({}) { |(k, v), h| h[k] = parse_and_clone(v, k) }
|
59
57
|
end
|
60
58
|
|
61
59
|
def parse_value(key, value)
|
@@ -114,6 +112,8 @@ class TkWrapper::Widgets::Base::Configuration
|
|
114
112
|
end
|
115
113
|
|
116
114
|
def merge_global_configurations(manager, widget)
|
117
|
-
|
115
|
+
return unless manager
|
116
|
+
|
117
|
+
merge(*manager.configurations(widget))
|
118
118
|
end
|
119
119
|
end
|
data/lib/widgets/base/manager.rb
CHANGED
@@ -1,32 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'comparator_item_store'
|
4
|
+
|
4
5
|
class TkWrapper::Widgets::Base::Manager
|
6
|
+
ComparatorItemStore = TkWrapper::Widgets::Base::ComparatorItemStore
|
7
|
+
|
5
8
|
def initialize
|
6
|
-
@configurations =
|
7
|
-
@modifications =
|
9
|
+
@configurations = ComparatorItemStore.new
|
10
|
+
@modifications = ComparatorItemStore.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_configurations(matcher = nil, configuration = nil, **configurations)
|
14
|
+
add_configuration(matcher, configuration) if configuration
|
15
|
+
|
16
|
+
configurations.each { |mat, cfg| add_configuration(mat, cfg) }
|
8
17
|
end
|
9
18
|
|
10
|
-
def add_configuration(
|
11
|
-
@configurations.push(
|
19
|
+
def add_configuration(comparator, configuration)
|
20
|
+
@configurations.push(comparator, configuration)
|
12
21
|
end
|
13
22
|
|
14
23
|
def add_modification(matcher, &callback)
|
15
|
-
@modifications.push(
|
24
|
+
@modifications.push(matcher, callback)
|
16
25
|
end
|
17
26
|
|
18
27
|
def configurations(widget)
|
19
|
-
@configurations.
|
20
|
-
|
21
|
-
end
|
28
|
+
config_list = @configurations.items_and_matches_for_widget(widget)
|
29
|
+
config_list.map { |configs| configs[:items] }.flatten(1)
|
22
30
|
end
|
23
31
|
|
24
32
|
def execute_modifications(widget)
|
25
|
-
@modifications.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
33
|
+
item_list = @modifications.items_and_matches_for_widget(widget)
|
34
|
+
item_list.each do |items|
|
35
|
+
items[:items].each do |callback|
|
36
|
+
callback.call(widget, items[:match])
|
37
|
+
end
|
30
38
|
end
|
31
39
|
end
|
40
|
+
|
41
|
+
def configure(widget)
|
42
|
+
widget.config.merge(*configurations(widget))
|
43
|
+
end
|
44
|
+
|
45
|
+
alias modify add_modification
|
46
|
+
alias config add_configurations
|
32
47
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# single 'match' as part of a Matches object
|
4
|
+
class TkWrapper::Widgets::Base::Match
|
5
|
+
attr_reader :key, :widget, :match
|
6
|
+
|
7
|
+
def initialize(value, cls: nil, match: nil, widget: nil)
|
8
|
+
@key = match&.[](0) || value
|
9
|
+
@widget = widget
|
10
|
+
@match = match
|
11
|
+
@cls = cls
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def tk_widget
|
16
|
+
@widget&.tk_widget
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "#{LIB_DIR}/widgets/base/match"
|
4
|
+
|
5
|
+
class TkWrapper::Widgets::Base::Matcher
|
6
|
+
Match = TkWrapper::Widgets::Base::Match
|
7
|
+
|
8
|
+
def initialize(value: nil, comparator: nil)
|
9
|
+
@match_function = curry_match_function(value, comparator)
|
10
|
+
end
|
11
|
+
|
12
|
+
# args:
|
13
|
+
# [] if widget and matcher were provided on initialization
|
14
|
+
# [widget] if matcher was provided on initialization
|
15
|
+
# [matcher] if widget was provided on initialization
|
16
|
+
# [widget, matcher] if neither widget nor matcher were provided on initial.
|
17
|
+
def match(*args)
|
18
|
+
@match_function.call(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def match_regex(value, comparator, widget)
|
24
|
+
(match = comparator.match(value)) &&
|
25
|
+
Match.new(value, match: match, widget: widget)
|
26
|
+
end
|
27
|
+
|
28
|
+
def match_string(value, comparator, widget)
|
29
|
+
value == comparator && Match.new(value, widget: widget)
|
30
|
+
end
|
31
|
+
|
32
|
+
def match_class(value, comparator, widget)
|
33
|
+
widget.is_a?(comparator) &&
|
34
|
+
Match.new(value, cls: comparator, widget: widget)
|
35
|
+
end
|
36
|
+
|
37
|
+
def match_f(value, comparator, widget)
|
38
|
+
case comparator
|
39
|
+
when String, Symbol then match_string(value, comparator, widget)
|
40
|
+
when Regexp then match_regex(value, comparator, widget)
|
41
|
+
when Class then match_class(value, comparator, widget)
|
42
|
+
when nil then Match(value, { widget: widget })
|
43
|
+
else false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def curry_match_function(value, comparator)
|
48
|
+
if value && comparator
|
49
|
+
->(widget) { match_f(value, comparator, widget) }
|
50
|
+
elsif value
|
51
|
+
->(x_comparator, widget) { match_f(value, x_comparator, widget) }
|
52
|
+
elsif comparator
|
53
|
+
->(x_value, widget) { match_f(x_value, comparator, widget) }
|
54
|
+
else
|
55
|
+
->(x_value, x_comparator, widget) { match_f(x_value, x_comparator, widget) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'match'
|
2
|
+
|
3
|
+
# matches widgets against conditions and stores matching widgets and matches
|
4
|
+
class TkWrapper::Widgets::Base::Matches
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@matches = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def push(match)
|
12
|
+
(@matches[match.key] ||= []).push(match)
|
13
|
+
end
|
14
|
+
|
15
|
+
def concat(matches)
|
16
|
+
matches.each { |match| push(match) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def each(&block)
|
20
|
+
@matches.each do |(key, matches_for_key)|
|
21
|
+
matches_for_key.each do |match|
|
22
|
+
block.call([match.widget, key, match.match, match])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](key)
|
28
|
+
case @matches[key].size
|
29
|
+
when 0 then nil
|
30
|
+
when 1 then @matches[key][0]
|
31
|
+
else @matches[key]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/widgets/base/widget.rb
CHANGED
@@ -1,39 +1,28 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
require 'tk'
|
4
|
-
|
1
|
+
require "#{LIB_DIR}/util/tk/cell"
|
2
|
+
require "#{LIB_DIR}/util/tk/finder"
|
5
3
|
require "#{LIB_DIR}/tk_extensions"
|
6
4
|
|
7
5
|
require_relative 'base'
|
8
6
|
|
9
7
|
class TkWrapper::Widgets::Base::Widget
|
8
|
+
extend Forwardable
|
10
9
|
include TkExtensions
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
def_delegators :@finder, :find, :find_all
|
11
13
|
|
12
14
|
attr_accessor :config
|
13
|
-
attr_reader :parent, :childs
|
15
|
+
attr_reader :parent, :ids, :cell, :childs, :manager
|
14
16
|
|
15
17
|
def tk_class() end
|
16
18
|
|
17
|
-
def
|
18
|
-
@
|
19
|
-
|
20
|
-
|
21
|
-
def self.config(matcher, configuration)
|
22
|
-
manager.add_configuration(matcher, configuration)
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.modify(matcher, &callback)
|
26
|
-
manager.add_modification(matcher, &callback)
|
27
|
-
end
|
28
|
-
|
29
|
-
def manager
|
30
|
-
TkWrapper::Widgets::Base::Widget.manager
|
31
|
-
end
|
32
|
-
|
33
|
-
def initialize(config: {}, childs: [])
|
19
|
+
def initialize(config: {}, childs: [], manager: nil, ids: [])
|
20
|
+
@cell = TkWrapper::Util::Tk::Cell.new(self)
|
21
|
+
@finder = TkWrapper::Util::Tk::Finder.new(widgets: self)
|
34
22
|
@config = TkWrapper::Widgets::Base::Configuration.new(config)
|
35
23
|
@childs = childs.is_a?(Array) ? childs : [childs]
|
36
|
-
@
|
24
|
+
@manager = manager
|
25
|
+
@ids = ids.is_a?(Array) ? ids : [ids]
|
37
26
|
end
|
38
27
|
|
39
28
|
def create_tk_widget(parent)
|
@@ -52,79 +41,33 @@ class TkWrapper::Widgets::Base::Widget
|
|
52
41
|
(@tk_widget = create_tk_widget(parent)) || parent&.tk_widget
|
53
42
|
end
|
54
43
|
|
55
|
-
def build(parent, configure: true)
|
44
|
+
def build(parent, configure: true, manager: nil)
|
56
45
|
@parent = parent
|
57
46
|
tk_widget # creates the widget if possible and not yet created
|
47
|
+
@font = TkWrapper::Util::Tk::Font.new(tk_widget)
|
48
|
+
@manager ||= manager
|
49
|
+
@config.merge(*@manager.configurations(self)) if @manager
|
58
50
|
self.configure if configure
|
59
|
-
manager
|
60
|
-
@childs.each { |child| child.build(self) }
|
51
|
+
@manager&.execute_modifications(self)
|
52
|
+
@childs.each { |child| child.build(self, manager: @manager) }
|
61
53
|
end
|
62
54
|
|
63
55
|
def configure
|
64
|
-
@config.merge_global_configurations(manager, self)
|
65
56
|
@config.configure_tk_widget(tk_widget)
|
66
57
|
@config.configure_tearoff
|
67
58
|
end
|
68
59
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
when nil
|
76
|
-
true
|
77
|
-
else
|
78
|
-
is_a?(matcher)
|
60
|
+
def each(&block)
|
61
|
+
nodes_to_walk = [self]
|
62
|
+
until nodes_to_walk.empty?
|
63
|
+
node = nodes_to_walk.pop
|
64
|
+
block.call(node)
|
65
|
+
nodes_to_walk = node.childs + nodes_to_walk
|
79
66
|
end
|
80
67
|
end
|
81
68
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
85
|
-
node = nodes_to_scan.pop
|
86
|
-
return node if node.check_match(matcher)
|
87
|
-
|
88
|
-
nodes_to_scan = node.childs + nodes_to_scan
|
89
|
-
end
|
69
|
+
def push(child)
|
70
|
+
@childs.push(child)
|
71
|
+
child.build(self)
|
90
72
|
end
|
91
|
-
|
92
|
-
def find_all(matcher)
|
93
|
-
found_nodes = []
|
94
|
-
nodes_to_scan = [self]
|
95
|
-
|
96
|
-
until nodes_to_scan.empty?
|
97
|
-
node = nodes_to_scan.pop
|
98
|
-
found_nodes.push(node) if node.check_match(matcher)
|
99
|
-
|
100
|
-
nodes_to_scan = node.childs + nodes_to_scan
|
101
|
-
end
|
102
|
-
|
103
|
-
found_nodes
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# the first parent, which contains a tk_widget, which is really different
|
108
|
-
# from self.tk_widget
|
109
|
-
def get_container_parent
|
110
|
-
container = @parent
|
111
|
-
while container.tk_widget == tk_widget
|
112
|
-
return unless container.parent # not in a grid?
|
113
|
-
|
114
|
-
container = container.parent
|
115
|
-
end
|
116
|
-
container
|
117
|
-
end
|
118
|
-
|
119
|
-
# returns the bounding box of the tk_widget
|
120
|
-
def cell_bbox
|
121
|
-
return unless (container = get_container_parent)
|
122
|
-
|
123
|
-
grid_info = TkGrid.info(tk_widget)
|
124
|
-
start_col = grid_info['column']
|
125
|
-
end_col = start_col + grid_info['columnspan'] - 1
|
126
|
-
start_row = grid_info['row']
|
127
|
-
end_row = start_row + grid_info['rowspan'] - 1
|
128
|
-
|
129
|
-
TkGrid.bbox(container.tk_widget, start_col, start_row, end_col, end_row)
|
130
73
|
end
|
data/lib/widgets/grid.rb
CHANGED
@@ -10,8 +10,8 @@ class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
|
|
10
10
|
TkWidgets::Frame
|
11
11
|
end
|
12
12
|
|
13
|
-
def initialize(
|
14
|
-
super(
|
13
|
+
def initialize(**arguments)
|
14
|
+
super(**arguments)
|
15
15
|
@childs.map! { |row| row.is_a?(Array) ? row : [row] }
|
16
16
|
configure_cells_for_grid
|
17
17
|
@childs.flatten! && @childs.select! { |cell| cell.is_a?(Widget) }
|
@@ -22,7 +22,7 @@ class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
|
|
22
22
|
row.each_with_index do |cell, col_i|
|
23
23
|
next unless cell.is_a?(Widget)
|
24
24
|
|
25
|
-
|
25
|
+
cell.config.merge({ grid: { row: row_i, column: col_i } })
|
26
26
|
|
27
27
|
configure_colspan(cell, row_i, col_i)
|
28
28
|
configure_rowspan(cell, row_i, col_i)
|
@@ -35,7 +35,7 @@ class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
|
|
35
35
|
colspan = cols_after_cell.reduce(1) do |span, content|
|
36
36
|
content == :right ? span + 1 : (break span)
|
37
37
|
end
|
38
|
-
|
38
|
+
cell.config.merge({ grid: { columnspan: colspan } })
|
39
39
|
end
|
40
40
|
|
41
41
|
def configure_rowspan(cell, row_i, col_i)
|
@@ -43,6 +43,6 @@ class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
|
|
43
43
|
rowspan = rows_after_cell.reduce(1) do |span, row|
|
44
44
|
row[col_i] == :bottom ? span + 1 : (break span)
|
45
45
|
end
|
46
|
-
|
46
|
+
cell.config.merge({ grid: { rowspan: rowspan } })
|
47
47
|
end
|
48
48
|
end
|
data/lib/widgets/menu.rb
CHANGED
@@ -5,8 +5,8 @@ class TkWrapper::Widgets::Menu < TkWrapper::Widgets::Base::Widget
|
|
5
5
|
TkWidgets::TkMenu
|
6
6
|
end
|
7
7
|
|
8
|
-
def build(parent)
|
9
|
-
super(parent)
|
8
|
+
def build(parent, **args)
|
9
|
+
super(parent, **args)
|
10
10
|
parent.tk_widget['menu'] = tk_widget
|
11
11
|
end
|
12
12
|
|
@@ -15,15 +15,18 @@ class TkWrapper::Widgets::Menu < TkWrapper::Widgets::Base::Widget
|
|
15
15
|
TkWidgets::TkMenu
|
16
16
|
end
|
17
17
|
|
18
|
-
def build(parent)
|
19
|
-
|
18
|
+
def build(parent, **args)
|
19
|
+
args[:configure] = false
|
20
|
+
super(parent, **args)
|
20
21
|
@config[:menu] = tk_widget
|
21
22
|
parent.tk_widget.add :cascade, **@config.config
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
26
|
class Command < TkWrapper::Widgets::Base::Widget
|
26
|
-
def build(parent)
|
27
|
+
def build(parent, **args)
|
28
|
+
args[:configure] = false
|
29
|
+
super(parent, **args)
|
27
30
|
parent.tk_widget.add :command, **@config.config
|
28
31
|
end
|
29
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tkwrapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Schnitzler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: reception@e.mail.de
|
@@ -19,13 +19,20 @@ files:
|
|
19
19
|
- lib/tk_extensions.rb
|
20
20
|
- lib/tkwrapper.rb
|
21
21
|
- lib/util/hash_recursive.rb
|
22
|
+
- lib/util/tk/cell.rb
|
23
|
+
- lib/util/tk/finder.rb
|
24
|
+
- lib/util/tk/font.rb
|
25
|
+
- lib/util/tk/tk.rb
|
22
26
|
- lib/util/virtual_methods.rb
|
23
27
|
- lib/widgets/auto_resize_entry.rb
|
24
28
|
- lib/widgets/base/base.rb
|
29
|
+
- lib/widgets/base/comparator_item_store.rb
|
25
30
|
- lib/widgets/base/configuration.rb
|
26
31
|
- lib/widgets/base/manager.rb
|
32
|
+
- lib/widgets/base/match.rb
|
33
|
+
- lib/widgets/base/matcher.rb
|
34
|
+
- lib/widgets/base/matches.rb
|
27
35
|
- lib/widgets/base/widget.rb
|
28
|
-
- lib/widgets/base/widgets.rb
|
29
36
|
- lib/widgets/entry.rb
|
30
37
|
- lib/widgets/frame.rb
|
31
38
|
- lib/widgets/grid.rb
|
data/lib/widgets/base/widgets.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class TkWrapper::Widgets::Base::Widgets
|
4
|
-
def initialize
|
5
|
-
@configurations = []
|
6
|
-
@modifications = []
|
7
|
-
end
|
8
|
-
|
9
|
-
def add_configuration(matcher, configuration)
|
10
|
-
@configurations.push(matcher, configuration)
|
11
|
-
end
|
12
|
-
|
13
|
-
def add_modification(matcher, &callback)
|
14
|
-
@modifications.push(matcher, callback)
|
15
|
-
end
|
16
|
-
|
17
|
-
def configurations(widget)
|
18
|
-
@configurations.filter_map do |(matcher, config)|
|
19
|
-
config if widget.check_match(matcher)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def execute_modifications(widget)
|
24
|
-
@modifications.each do |(matcher, callback)|
|
25
|
-
next unless (match = widget.check_match(matcher))
|
26
|
-
|
27
|
-
arguments = match.is_a?(MatchData) ? [widget, match] : [widget]
|
28
|
-
callback.call(*arguments)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|