tkwrapper 1.0.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- 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 +10 -36
- data/lib/widgets/base/base.rb +1 -0
- data/lib/widgets/base/comparator_item_store.rb +41 -0
- data/lib/widgets/base/configuration.rb +16 -18
- data/lib/widgets/base/manager.rb +22 -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 +49 -59
- data/lib/widgets/grid.rb +7 -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: 957efe49807e9800759aa22439bc99f5ea4ef0ec620bc7ea0b7d549474839a7a
|
4
|
+
data.tar.gz: f654e23817c14ce6e59d67e7893f55c33c9168686faf66cbf0a96f955f4e7c6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4891b05ca78bff3d2119b6b4d8ba0be178836d1cdd7475e07ddc3be19100d766e0ca0d9878d4afc9be330ffbf3ea008914d4f4432b0e3eff2df8cc02534b74f4
|
7
|
+
data.tar.gz: 3ece495be24159cefde0ca65899c3022b181a3bb0d92e40727a9cbc2ca4494d376504a58313190a94fbf4dc8751949873753ec1c2313d9db4cc28fb29174a466
|
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_widget(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_widgets(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,10 +4,10 @@ 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(config: {}, childs: [])
|
8
|
-
@min_width = config
|
9
|
-
@add_width = config
|
10
|
-
super(config: config, childs: childs)
|
7
|
+
def initialize(config: {}, childs: [], id: nil)
|
8
|
+
@min_width = config[:min_width] || 0
|
9
|
+
@add_width = config[:add_width] || 0
|
10
|
+
super(config: config, childs: childs, id: id)
|
11
11
|
end
|
12
12
|
|
13
13
|
def build(parent, configure: true)
|
@@ -18,43 +18,17 @@ class TkWrapper::Widgets::AutoResizeEntry < TkWrapper::Widgets::Entry
|
|
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
|
+
id 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,6 @@ class TkWrapper::Widgets::Base::Configuration
|
|
114
112
|
end
|
115
113
|
|
116
114
|
def merge_global_configurations(manager, widget)
|
117
|
-
merge
|
115
|
+
merge(*manager.configurations(widget))
|
118
116
|
end
|
119
117
|
end
|
data/lib/widgets/base/manager.rb
CHANGED
@@ -1,32 +1,40 @@
|
|
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
|
8
11
|
end
|
9
12
|
|
10
|
-
def
|
11
|
-
|
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) }
|
17
|
+
end
|
18
|
+
|
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
|
32
40
|
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
@@ -3,14 +3,22 @@
|
|
3
3
|
require 'tk'
|
4
4
|
|
5
5
|
require "#{LIB_DIR}/tk_extensions"
|
6
|
+
require "#{LIB_DIR}/util/tk/font"
|
7
|
+
require "#{LIB_DIR}/util/tk/cell"
|
8
|
+
require "#{LIB_DIR}/util/tk/finder"
|
6
9
|
|
7
10
|
require_relative 'base'
|
8
11
|
|
9
12
|
class TkWrapper::Widgets::Base::Widget
|
13
|
+
extend Forwardable
|
10
14
|
include TkExtensions
|
15
|
+
include Enumerable
|
16
|
+
|
17
|
+
def_delegator :@finder, :find_widget, :find
|
18
|
+
def_delegator :@finder, :find_all_widgets, :find_all
|
11
19
|
|
12
20
|
attr_accessor :config
|
13
|
-
attr_reader :parent, :childs
|
21
|
+
attr_reader :parent, :ids, :cell, :childs
|
14
22
|
|
15
23
|
def tk_class() end
|
16
24
|
|
@@ -18,8 +26,8 @@ class TkWrapper::Widgets::Base::Widget
|
|
18
26
|
@manager ||= TkWrapper::Widgets::Base::Manager.new
|
19
27
|
end
|
20
28
|
|
21
|
-
def self.config(matcher, configuration)
|
22
|
-
manager.
|
29
|
+
def self.config(matcher = nil, configuration = nil, **configurations)
|
30
|
+
manager.add_configurations(matcher, configuration, **configurations)
|
23
31
|
end
|
24
32
|
|
25
33
|
def self.modify(matcher, &callback)
|
@@ -30,10 +38,30 @@ class TkWrapper::Widgets::Base::Widget
|
|
30
38
|
TkWrapper::Widgets::Base::Widget.manager
|
31
39
|
end
|
32
40
|
|
33
|
-
def
|
41
|
+
def each(&block)
|
42
|
+
nodes_to_walk = [self]
|
43
|
+
until nodes_to_walk.empty?
|
44
|
+
node = nodes_to_walk.pop
|
45
|
+
block.call(node)
|
46
|
+
nodes_to_walk = node.childs + nodes_to_walk
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(config: {}, childs: [], id: nil)
|
51
|
+
@cell = TkWrapper::Util::Tk::Cell.new(self)
|
52
|
+
@finder = TkWrapper::Util::Tk::Finder.new(widgets: self)
|
34
53
|
@config = TkWrapper::Widgets::Base::Configuration.new(config)
|
35
54
|
@childs = childs.is_a?(Array) ? childs : [childs]
|
36
|
-
@
|
55
|
+
@ids = []
|
56
|
+
add_ids(id)
|
57
|
+
add_ids(config[:id])
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_ids(ids)
|
61
|
+
return unless ids
|
62
|
+
|
63
|
+
ids = [ids] unless ids.is_a?(Array)
|
64
|
+
@ids.concat(ids)
|
37
65
|
end
|
38
66
|
|
39
67
|
def create_tk_widget(parent)
|
@@ -55,76 +83,38 @@ class TkWrapper::Widgets::Base::Widget
|
|
55
83
|
def build(parent, configure: true)
|
56
84
|
@parent = parent
|
57
85
|
tk_widget # creates the widget if possible and not yet created
|
86
|
+
@font = TkWrapper::Util::Tk::Font.new(tk_widget)
|
58
87
|
self.configure if configure
|
59
88
|
manager.execute_modifications(self)
|
60
89
|
@childs.each { |child| child.build(self) }
|
61
90
|
end
|
62
91
|
|
92
|
+
def push(child)
|
93
|
+
@childs.push(child)
|
94
|
+
child.build(self)
|
95
|
+
end
|
96
|
+
|
63
97
|
def configure
|
64
98
|
@config.merge_global_configurations(manager, self)
|
65
99
|
@config.configure_tk_widget(tk_widget)
|
66
100
|
@config.configure_tearoff
|
67
101
|
end
|
68
102
|
|
69
|
-
def
|
70
|
-
|
71
|
-
when Regexp
|
72
|
-
matcher.match(@id)
|
73
|
-
when String, Symbol
|
74
|
-
matcher == @id
|
75
|
-
when nil
|
76
|
-
true
|
77
|
-
else
|
78
|
-
is_a?(matcher)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def find(matcher)
|
83
|
-
nodes_to_scan = [self]
|
84
|
-
until nodes_to_scan.empty?
|
85
|
-
node = nodes_to_scan.pop
|
86
|
-
return node if node.check_match(matcher)
|
103
|
+
def modify(matchers, &callback)
|
104
|
+
items = find_all(matchers)
|
87
105
|
|
88
|
-
|
89
|
-
end
|
106
|
+
callback.call(items)
|
90
107
|
end
|
91
108
|
|
92
|
-
def
|
93
|
-
|
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
|
109
|
+
def modify_each(matchers, &callback)
|
110
|
+
items = find_all(matchers)
|
102
111
|
|
103
|
-
|
104
|
-
end
|
105
|
-
end
|
112
|
+
return unless items
|
106
113
|
|
107
|
-
|
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?
|
114
|
+
with_match = items[0].is_a?(Array)
|
113
115
|
|
114
|
-
|
116
|
+
items.each do |item|
|
117
|
+
with_match ? callback.call(item[0], item[1]) : callback.call(item)
|
118
|
+
end
|
115
119
|
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
120
|
end
|
data/lib/widgets/grid.rb
CHANGED
@@ -4,12 +4,14 @@
|
|
4
4
|
class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
|
5
5
|
attr_reader :parent, :matrix
|
6
6
|
|
7
|
+
Widget = TkWrapper::Widgets::Base::Widget
|
8
|
+
|
7
9
|
def tk_class
|
8
10
|
TkWidgets::Frame
|
9
11
|
end
|
10
12
|
|
11
|
-
def initialize(config: {}, childs: [])
|
12
|
-
super(config: config, childs: childs)
|
13
|
+
def initialize(config: {}, childs: [], id: nil)
|
14
|
+
super(config: config, childs: childs, id: id)
|
13
15
|
@childs.map! { |row| row.is_a?(Array) ? row : [row] }
|
14
16
|
configure_cells_for_grid
|
15
17
|
@childs.flatten! && @childs.select! { |cell| cell.is_a?(Widget) }
|
@@ -20,7 +22,7 @@ class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
|
|
20
22
|
row.each_with_index do |cell, col_i|
|
21
23
|
next unless cell.is_a?(Widget)
|
22
24
|
|
23
|
-
|
25
|
+
cell.config.merge({ grid: { row: row_i, column: col_i } })
|
24
26
|
|
25
27
|
configure_colspan(cell, row_i, col_i)
|
26
28
|
configure_rowspan(cell, row_i, col_i)
|
@@ -33,7 +35,7 @@ class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
|
|
33
35
|
colspan = cols_after_cell.reduce(1) do |span, content|
|
34
36
|
content == :right ? span + 1 : (break span)
|
35
37
|
end
|
36
|
-
|
38
|
+
cell.config.merge({ grid: { columnspan: colspan } })
|
37
39
|
end
|
38
40
|
|
39
41
|
def configure_rowspan(cell, row_i, col_i)
|
@@ -41,6 +43,6 @@ class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
|
|
41
43
|
rowspan = rows_after_cell.reduce(1) do |span, row|
|
42
44
|
row[col_i] == :bottom ? span + 1 : (break span)
|
43
45
|
end
|
44
|
-
|
46
|
+
cell.config.merge({ grid: { rowspan: rowspan } })
|
45
47
|
end
|
46
48
|
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.3.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
|