tkwrapper 1.0.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|