tkwrapper 1.5.0 → 1.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: abffb1cc7ae4efaf8b26ebdd49acca56837989829713473f21971f8a5f5a9063
4
- data.tar.gz: 1e659e3049a41d4aff307f700ac27cc86d014ec844134aa65bc7bd20c2f692db
3
+ metadata.gz: 3ffefbd7d08458a1cfa097980b725729a14165d4b0a6a63319d2b651ed64369d
4
+ data.tar.gz: 87bd8af7b88ad3951a44829763fae77e5fb874a934d129b8b205c42f7c14af9b
5
5
  SHA512:
6
- metadata.gz: efbad85fe488198ff115feac31872163da0da8b796ef0a21babf33d21976e14da0f809a93a502cbfc0f9225e4446e30c1b567680af2b3c7e7eae862cf0b5f64b
7
- data.tar.gz: 7d0addd32901d46c6d0175219ee83dd4478f699bc05ec7804f0a76dac02b1950a11f7a22dafa494996961bc8f25582c1f6be4f36c3cf19c9b3a3e5050cb0df9f
6
+ metadata.gz: 5a80b659836c0627f762a40c6c275a398d0cd786153e5687ab57e6c4ba4116db8d8cb91f238bb3ca00e15624dfe14d73fa283ed9489d3dc7d546ff08254b8518
7
+ data.tar.gz: 22d9d0c242d08248fd569c70f4a068cbe8e1725218bfd876db691e8ec93df5968021560f15770b816c150863f4191edc3f63466ac0472cba2df357b2267af48b
data/lib/util/array.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Util
4
+ def self.first_not_nil(array, default = nil)
5
+ index = indexes.find { |i| !array[i].nil? }
6
+ index.nil? ? default : array[index]
7
+ end
8
+ end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Util
4
- def self.merge_recursive!(*hashes)
4
+ def self.merge_recursive!(*hashes, overwrite: true)
5
5
  hashes[0].merge!(*hashes[1..]) do |_key, old, new|
6
6
  if old.is_a?(Hash) && new.is_a?(Hash)
7
7
  merge_recursive!(old, new)
8
8
  else
9
- new
9
+ overwrite ? new : old
10
10
  end
11
11
  end
12
12
  end
data/lib/util/tk/cell.rb CHANGED
@@ -17,6 +17,7 @@ class TkWrapper::Util::Tk::Cell
17
17
  start_row = grid_info['row']
18
18
  end_row = start_row + grid_info['rowspan'] - 1
19
19
 
20
+ container.tk_widget.update
20
21
  TkGrid.bbox(container.tk_widget, start_col, start_row, end_col, end_row)
21
22
  end
22
23
 
@@ -15,6 +15,7 @@ class TkWrapper::Util::Tk::Finder
15
15
  end
16
16
 
17
17
  def iter(comparators, widgets = @widgets, lookup = @lookup)
18
+ comparators = [comparators] unless comparators.is_a?(Array)
18
19
  Enumerator.new do |y|
19
20
  comparators = each_widget_lookup_match(lookup, comparators) { |m| y << m }
20
21
  each_widget_comparator_match(widgets, comparators) { |m| y << m }
@@ -33,7 +34,6 @@ class TkWrapper::Util::Tk::Finder
33
34
  private
34
35
 
35
36
  def create_value_matchers(comparators)
36
- comparators = [comparators] unless comparators.is_a?(Array)
37
37
  comparators.map { |comparator| Matcher.new(comparator: comparator) }
38
38
  end
39
39
 
@@ -55,7 +55,8 @@ class TkWrapper::Util::Tk::Finder
55
55
  matchers = create_value_matchers(comparators)
56
56
 
57
57
  widgets.each do |widget|
58
- widget.ids.each do |id|
58
+ ids = widget.ids.empty? ? [nil] : widget.ids
59
+ ids.each do |id|
59
60
  matchers.each do |matcher|
60
61
  (match = matcher.match(id, widget)) && block.call(match)
61
62
  end
data/lib/util/tk/font.rb CHANGED
@@ -48,4 +48,18 @@ class TkWrapper::Util::Tk::Font
48
48
  def update
49
49
  @tk_widget.font = TkFont.new(@config)
50
50
  end
51
+
52
+ def char_width
53
+ measure('0')
54
+ end
55
+
56
+ def linespace
57
+ metrics['linespace']
58
+ end
59
+
60
+ def metrics
61
+ @tk_widget.font.metrics.each_with_object({}) do |(key, value), metrics|
62
+ metrics[key] = value
63
+ end
64
+ end
51
65
  end
@@ -12,7 +12,7 @@ class TkWrapper::Widgets::AutoResizeEntry < TkWrapper::Widgets::Entry
12
12
 
13
13
  def build(parent, **args)
14
14
  super(parent, **args)
15
- parent.tk_widget.bind('Configure') { resize }
15
+ parent.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
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'text'
4
+
5
+ class TkWrapper::Widgets::AutoResizeText < TkWrapper::Widgets::Frame
6
+ attr_reader :text
7
+
8
+ def initialize(**args)
9
+ @min_number_chars = 8
10
+ @min_number_lines = 2
11
+
12
+ super(**args)
13
+
14
+ @longest_line_width = 0
15
+ @config.merge({ grid: :onecell }, overwrite: false)
16
+ end
17
+
18
+ def create_childs
19
+ @text = Text.new(config: {
20
+ grid: { sticky: 'nsew' },
21
+ width: @min_number_chars,
22
+ height: @min_number_lines
23
+ })
24
+ end
25
+
26
+ def build(parent, **args)
27
+ super(parent, **args)
28
+ @text.bind('<Modified>', &method(:autoresize))
29
+ TkGrid.propagate(tk_widget, 0)
30
+ resize(lines: @min_number_lines, chars: @min_number_chars)
31
+ end
32
+
33
+ def resize(height: nil, width: nil, lines: nil, chars: nil)
34
+ width = width_needed_for_chars(chars) if chars
35
+ height = height_needed_for_lines(lines) if lines
36
+
37
+ opts.width = width if width
38
+ opts.height = height if height
39
+ end
40
+
41
+ private
42
+
43
+ # width of cursor + borders (textfield + frame) + padding (textfield + frame)
44
+ def additional_width_needed_for_textfield
45
+ @text.opts.insertwidth +
46
+ @text.accumulated_border_and_padding_width +
47
+ accumulated_border_and_padding_width
48
+ end
49
+
50
+ def additional_height_needed_for_textfield
51
+ # TODO: cursor height?
52
+ @text.accumulated_border_and_padding_height +
53
+ accumulated_border_and_padding_height
54
+ end
55
+
56
+ def width_needed_for_chars(num_chars)
57
+ text.font.char_width * num_chars + additional_width_needed_for_textfield
58
+ end
59
+
60
+ def height_needed_for_lines(num_lines)
61
+ @text.height_of_lines(num_lines) + additional_height_needed_for_textfield
62
+ end
63
+
64
+ def width_needed_for_textfield
65
+ @text.longest_line_width + additional_width_needed_for_textfield
66
+ end
67
+
68
+ def height_needed_for_textfield
69
+ @text.height_of_lines + additional_height_needed_for_textfield
70
+ end
71
+
72
+ def max_width
73
+ [@cell.bbox[2], 0].max
74
+ end
75
+
76
+ def min_width
77
+ [max_width, width_needed_for_chars(@min_number_chars)].min
78
+ end
79
+
80
+ def min_height
81
+ height_needed_for_lines(@min_number_lines)
82
+ end
83
+
84
+ def autoresize
85
+ return unless @text.tk_widget.modified?
86
+
87
+ width = [[min_width, width_needed_for_textfield].max, max_width].min
88
+ height = [min_height, height_needed_for_textfield].max
89
+
90
+ resize(height: height, width: width)
91
+
92
+ @text.tk_widget.modified(false)
93
+ end
94
+ end
@@ -28,14 +28,14 @@ class TkWrapper::Widgets::Base::Configuration
28
28
  @config = parse_and_clone(config)
29
29
  end
30
30
 
31
- def merge(*configurations)
31
+ def merge(*configurations, overwrite: true)
32
32
  configurations = configurations.map do |configuration|
33
33
  configuration = configuration.config if configuration.is_a?(self.class)
34
34
 
35
35
  parse_and_clone(configuration)
36
36
  end
37
37
 
38
- Util.merge_recursive!(@config, *configurations)
38
+ Util.merge_recursive!(@config, *configurations, overwrite: overwrite)
39
39
  end
40
40
 
41
41
  def [](key)
@@ -77,17 +77,23 @@ class TkWrapper::Widgets::Base::Configuration
77
77
  @config[:grid].reject { |option, _| NON_TK_OPTIONS.include?(option) }
78
78
  end
79
79
 
80
+ def configure_grid(tk_widget)
81
+ grid = grid(only_tk_options: true)
82
+ return if grid.empty?
83
+
84
+ tk_widget.grid(grid)
85
+ end
86
+
80
87
  def configure_tk_widget(tk_widget)
81
88
  @config.each do |option, value|
82
89
  next if NON_TK_OPTIONS.include?(option)
83
90
 
84
- if option == :grid
85
- grid = grid(only_tk_options: true)
86
- next if grid.empty?
87
- next tk_widget.grid(grid) if option == :grid
91
+ case option
92
+ when :grid then configure_grid(tk_widget)
93
+ when :pack then tk_widget.pack(value)
94
+ when :place then tk_widget.place(value)
95
+ else tk_widget[option] = value
88
96
  end
89
-
90
- tk_widget[option] = value
91
97
  end
92
98
 
93
99
  configure_weights(tk_widget)
@@ -47,6 +47,10 @@ class TkWrapper::Widgets::Base::Manager
47
47
  widget.config.merge(*configurations(widget))
48
48
  end
49
49
 
50
+ def tk_widget(id)
51
+ @widgets[id].tk_widget
52
+ end
53
+
50
54
  alias modify add_modification
51
55
  alias config add_configurations
52
56
  end
@@ -39,7 +39,7 @@ class TkWrapper::Widgets::Base::Matcher
39
39
  when String, Symbol then match_string(value, comparator, widget)
40
40
  when Regexp then match_regex(value, comparator, widget)
41
41
  when Class then match_class(value, comparator, widget)
42
- when nil then Match(value, { widget: widget })
42
+ when nil then Match.new(value, widget: widget)
43
43
  else false
44
44
  end
45
45
  end
@@ -25,10 +25,10 @@ class TkWrapper::Widgets::Base::Matches
25
25
  end
26
26
 
27
27
  def [](key)
28
- case @matches[key].size
29
- when 0 then nil
30
- when 1 then @matches[key][0]
31
- else @matches[key]
28
+ case @matches[key]&.size
29
+ when 0, nil then nil
30
+ when 1 then @matches[key][0]
31
+ else @matches[key]
32
32
  end
33
33
  end
34
34
 
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TkWrapper::Widgets::Base::Padding
4
+ def initialize(widget)
5
+ @widget = widget
6
+ end
7
+
8
+ def set(left: nil, top: nil, right: nil, bottom: nil)
9
+ values = get
10
+ @widget.tk_widget.padding = [
11
+ left || values.left,
12
+ top || values.top,
13
+ right || values.right,
14
+ bottom || values.bottom
15
+ ]
16
+ end
17
+
18
+ def get
19
+ (left, top, right, bottom) = @widget.tk_widget.padding.split
20
+
21
+ {
22
+ left: left || 0,
23
+ top: top || left || 0,
24
+ right: right || left || 0,
25
+ bottom: bottom || top || left || 0
26
+ }
27
+ end
28
+
29
+ def left
30
+ get[:left]
31
+ end
32
+
33
+ def top
34
+ get[:top]
35
+ end
36
+
37
+ def right
38
+ get[:right]
39
+ end
40
+
41
+ def bottom
42
+ get[:bottom]
43
+ end
44
+
45
+ def left=(left)
46
+ set(left: left)
47
+ end
48
+
49
+ def top=(top)
50
+ set(top: top)
51
+ end
52
+
53
+ def right=(right)
54
+ set(right: right)
55
+ end
56
+
57
+ def bottom=(bottom)
58
+ set(bottom: bottom)
59
+ end
60
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'padding'
4
+
5
+ class TkWrapper::Widgets::Base::TkOptions
6
+ attr_reader :padding
7
+
8
+ def self.default_to_zero(*properties)
9
+ properties.each do |property|
10
+ define_method(property) do
11
+ value = @widget.tk_widget[property]
12
+ value.is_a?(Numeric) ? value : 0
13
+ end
14
+ end
15
+ end
16
+
17
+ default_to_zero :padx, :insertwidth, :borderwidth,
18
+ :spacing1, :spacing2, :spacing3
19
+
20
+ def initialize(widget)
21
+ @widget = widget
22
+ @padding = TkWrapper::Widgets::Base::Padding.new(@widget)
23
+ end
24
+
25
+ def padding=(hash)
26
+ @padding.set(**hash)
27
+ end
28
+
29
+ def method_missing(key, value = nil)
30
+ if key[-1] == '='
31
+ @widget.tk_widget[key[0..-2].to_sym] = value
32
+ else
33
+ @widget.tk_widget[key]
34
+ end
35
+ end
36
+
37
+ def respond_to_missing?(*)
38
+ # no known way to check if tk_widget[key] exists
39
+ false
40
+ end
41
+ end
@@ -1,28 +1,49 @@
1
1
  require "#{LIB_DIR}/util/tk/cell"
2
2
  require "#{LIB_DIR}/util/tk/finder"
3
- require "#{LIB_DIR}/tk_extensions"
4
3
 
5
4
  require_relative 'base'
5
+ require_relative 'window_info'
6
+ require_relative 'tk_options'
6
7
 
7
8
  class TkWrapper::Widgets::Base::Widget
8
9
  extend Forwardable
9
- include TkExtensions
10
10
  include Enumerable
11
11
 
12
12
  def_delegators :@finder, :find, :find_all
13
+ def_delegators :tk_widget, :update
14
+ def_delegator :tk_widget, :bind_append, :bind
15
+ def_delegator :@manager, :widgets, :managed
13
16
 
14
17
  attr_accessor :config
15
- attr_reader :parent, :ids, :cell, :childs, :manager
18
+ attr_reader :parent, :ids, :cell, :childs, :manager, :winfo, :opts, :font
16
19
 
17
20
  def tk_class() end
18
21
 
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)
22
+ def initialize(parent: nil, config: {}, childs: [], manager: nil, ids: [], id: [])
23
+ initialize_utilities
22
24
  @config = TkWrapper::Widgets::Base::Configuration.new(config)
23
- @childs = childs.is_a?(Array) ? childs : [childs]
24
25
  @manager = manager
25
- @ids = ids.is_a?(Array) ? ids : [ids]
26
+ @ids = init_id(id) + init_id(ids)
27
+ @parent = parent
28
+ modify_configuration(@config)
29
+ @childs = normalize_childs(childs)
30
+ parent&.push(self)
31
+ end
32
+
33
+ def initialize_utilities
34
+ @cell = TkWrapper::Util::Tk::Cell.new(self)
35
+ @winfo = TkWrapper::Widgets::Base::WindowInfo.new(self)
36
+ @opts = TkWrapper::Widgets::Base::TkOptions.new(self)
37
+ @finder = TkWrapper::Util::Tk::Finder.new(widgets: self)
38
+ end
39
+
40
+ def init_id(id)
41
+ id.is_a?(Array) ? id : [id]
42
+ end
43
+
44
+ def normalize_childs(childs)
45
+ childs = create_childs || childs
46
+ childs.is_a?(Array) ? childs : [childs]
26
47
  end
27
48
 
28
49
  def create_tk_widget(parent)
@@ -30,7 +51,7 @@ class TkWrapper::Widgets::Base::Widget
30
51
 
31
52
  return unless tk_class
32
53
 
33
- parent&.tk_widget ? tk_class.new(parent.tk_widget) : tk_class.new
54
+ tk_class.new(parent&.tk_widget)
34
55
  end
35
56
 
36
57
  # if parent is provided and self has no tk_class, the tk_widget of the
@@ -41,23 +62,6 @@ class TkWrapper::Widgets::Base::Widget
41
62
  (@tk_widget = create_tk_widget(parent)) || parent&.tk_widget
42
63
  end
43
64
 
44
- def build(parent, configure: true, manager: nil)
45
- @parent = parent
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
50
- self.configure if configure
51
- @manager&.execute_modifications(self)
52
- @manager&.widgets&.push(self)
53
- @childs.each { |child| child.build(self, manager: @manager) }
54
- end
55
-
56
- def configure
57
- @config.configure_tk_widget(tk_widget)
58
- @config.configure_tearoff
59
- end
60
-
61
65
  def each(&block)
62
66
  nodes_to_walk = [self]
63
67
  until nodes_to_walk.empty?
@@ -69,6 +73,43 @@ class TkWrapper::Widgets::Base::Widget
69
73
 
70
74
  def push(child)
71
75
  @childs.push(child)
72
- child.build(self)
76
+ child.build(self, manager: @manager)
77
+ end
78
+
79
+ protected
80
+
81
+ def build_childs
82
+ @childs.each { |child| child.build(self, manager: @manager) }
83
+ end
84
+
85
+ def modify_configuration(config) end
86
+
87
+ def create_childs() end
88
+
89
+ def before_build(**args) end
90
+
91
+ def after_build() end
92
+
93
+ def inner_build(configure: true, manager: nil)
94
+ tk_widget # creates the widget if possible and not yet created
95
+ @font = TkWrapper::Util::Tk::Font.new(tk_widget)
96
+ @manager ||= manager
97
+ @config.merge(*@manager.configurations(self), overwrite: false) if @manager
98
+ self.configure if configure
99
+ @manager&.execute_modifications(self)
100
+ @manager&.widgets&.push(self)
101
+ build_childs
102
+ end
103
+
104
+ def build(parent, configure: true, manager: nil)
105
+ @parent = parent
106
+ before_build(configure: configure, manager: manager)
107
+ inner_build(configure: configure, manager: manager)
108
+ after_build
109
+ end
110
+
111
+ def configure
112
+ @config.configure_tk_widget(tk_widget)
113
+ @config.configure_tearoff
73
114
  end
74
115
  end
@@ -17,6 +17,7 @@ class TkWrapper::Widgets::Base::WidgetStore
17
17
  widget.ids.each do |id|
18
18
  (@lookup[id] ||= []).push(widget)
19
19
  end
20
+ (@lookup[nil] ||= []).push(widget) if widget.ids.empty?
20
21
  end
21
22
 
22
23
  def each(&block)
@@ -26,7 +27,7 @@ class TkWrapper::Widgets::Base::WidgetStore
26
27
  end
27
28
 
28
29
  def [](key)
29
- @lookup[key].size == 1 ? @lookup[key].first : @lookup[key]
30
+ @lookup[key]&.size == 1 ? @lookup[key].first : @lookup[key]
30
31
  end
31
32
 
32
33
  private
@@ -0,0 +1,17 @@
1
+ class TkWrapper::Widgets::Base::WindowInfo
2
+ def initialize(widget)
3
+ @widget = widget
4
+ end
5
+
6
+ def method_missing(name, *args)
7
+ if @widget.tk_widget.respond_to?("winfo_#{name}")
8
+ @widget.tk_widget.send("winfo_#{name}", *args)
9
+ else
10
+ super
11
+ end
12
+ end
13
+
14
+ def respond_to_missing?(name, *)
15
+ @widget.tk_widget.respond_to?("winfo_#{name}") || super
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tkextlib/tile'
4
+
5
+ class TkWrapper::Widgets::Button < TkWrapper::Widgets::Base::Widget
6
+ def tk_class
7
+ Tk::Tile::Button
8
+ end
9
+ end
data/lib/widgets/entry.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tkextlib/tile'
4
+
3
5
  class TkWrapper::Widgets::Entry < TkWrapper::Widgets::Base::Widget
4
6
  def tk_class
5
- TkWidgets::Entry
7
+ Tk::Tile::Entry
6
8
  end
7
9
  end
data/lib/widgets/frame.rb CHANGED
@@ -1,7 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tkextlib/tile'
4
+
3
5
  class TkWrapper::Widgets::Frame < TkWrapper::Widgets::Base::Widget
4
6
  def tk_class
5
- TkWidgets::Frame
7
+ Tk::Tile::Frame
8
+ end
9
+
10
+ def accumulated_border_and_padding_width
11
+ opts.padding.left + opts.padding.right + 2 * opts.borderwidth
12
+ end
13
+
14
+ def accumulated_border_and_padding_height
15
+ opts.padding.top + opts.padding.bottom + 2 * opts.borderwidth
6
16
  end
7
17
  end
data/lib/widgets/grid.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tkextlib/tile'
4
+
3
5
  # classification of TkGrid
4
6
  class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
5
7
  attr_reader :parent, :matrix
@@ -7,14 +9,16 @@ class TkWrapper::Widgets::Grid < TkWrapper::Widgets::Base::Widget
7
9
  Widget = TkWrapper::Widgets::Base::Widget
8
10
 
9
11
  def tk_class
10
- TkWidgets::Frame
12
+ Tk::Tile::Frame
11
13
  end
12
14
 
13
15
  def initialize(**arguments)
16
+ parent = arguments.delete(:parent)
14
17
  super(**arguments)
15
18
  @childs.map! { |row| row.is_a?(Array) ? row : [row] }
16
19
  configure_cells_for_grid
17
20
  @childs.flatten! && @childs.select! { |cell| cell.is_a?(Widget) }
21
+ parent&.push(self)
18
22
  end
19
23
 
20
24
  def configure_cells_for_grid
data/lib/widgets/label.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tkextlib/tile'
4
+
3
5
  class TkWrapper::Widgets::Label < TkWrapper::Widgets::Base::Widget
4
6
  def tk_class
5
- TkWidgets::Label
7
+ Tk::Tile::Label
6
8
  end
7
9
  end
data/lib/widgets/menu.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tk'
4
+
3
5
  class TkWrapper::Widgets::Menu < TkWrapper::Widgets::Base::Widget
4
6
  def tk_class
5
- TkWidgets::TkMenu
7
+ TkMenu
6
8
  end
7
9
 
8
10
  def build(parent, **args)
@@ -12,7 +14,7 @@ class TkWrapper::Widgets::Menu < TkWrapper::Widgets::Base::Widget
12
14
 
13
15
  class Cascade < TkWrapper::Widgets::Base::Widget
14
16
  def tk_class
15
- TkWidgets::TkMenu
17
+ TkMenu
16
18
  end
17
19
 
18
20
  def build(parent, **args)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TkWrapper::Widgets::MountPoint < TkWrapper::Widgets::Base::Widget
4
+ def initialize(**args)
5
+ super(**args)
6
+ end
7
+
8
+ def build_childs(skip: true)
9
+ super() unless skip
10
+ end
11
+
12
+ def mount=(childs)
13
+ mount(childs)
14
+ end
15
+
16
+ def mount(childs = nil)
17
+ if childs
18
+ @childs = childs.is_a?(Array) ? childs : [childs]
19
+ end
20
+ @childs.each do |child|
21
+ child.config.merge(@config)
22
+ end
23
+ build_childs(skip: false)
24
+ end
25
+ end
data/lib/widgets/root.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tk'
4
+
3
5
  class TkWrapper::Widgets::Root < TkWrapper::Widgets::Base::Widget
4
6
  def initialize(**arguments)
5
7
  super(**arguments)
@@ -7,6 +9,6 @@ class TkWrapper::Widgets::Root < TkWrapper::Widgets::Base::Widget
7
9
  end
8
10
 
9
11
  def tk_class
10
- TkWidgets::TkRoot
12
+ TkRoot
11
13
  end
12
14
  end
data/lib/widgets/text.rb CHANGED
@@ -1,7 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tk'
4
+
3
5
  class TkWrapper::Widgets::Text < TkWrapper::Widgets::Base::Widget
4
6
  def tk_class
5
- TkWidgets::TkText
7
+ TkText
8
+ end
9
+
10
+ def pos(key)
11
+ match = tk_widget.index(key).match(/(.*)\.(.*)/)
12
+ [match[1].to_i, match[2].to_i]
13
+ end
14
+
15
+ def count_lines
16
+ pos('end')[0] - 1
17
+ end
18
+
19
+ def current_line_nr
20
+ pos('insert')[0]
21
+ end
22
+
23
+ def value=(value)
24
+ tk_widget.delete('1.0', 'end')
25
+ tk_widget.insert('1.0', value)
26
+ end
27
+
28
+ def lines(start_pos = '1.0', end_pos = 'end')
29
+ start_pos = start_pos.is_a?(String) ? start_pos : "#{start_pos}.0"
30
+ end_pos = end_pos.is_a?(String) ? end_pos : "#{end_pos}.0"
31
+ tk_widget.get(start_pos, end_pos).split("\n")
32
+ end
33
+
34
+ def longest_line_width
35
+ lines.map { |line| @font.measure(line) }.max || 0
36
+ end
37
+
38
+ # includes spacing1 and spacing2 (add. space above and below line)
39
+ # does not include spacing3 (additional space between lines)
40
+ def line_height_including_padding
41
+ # linespace: max height of characters of the font
42
+ # spacing1: additional space above line
43
+ # spacing3: additional space below line
44
+ @font.linespace + opts.spacing1 + opts.spacing3
45
+ end
46
+
47
+ def height_of_lines(num_lines = count_lines)
48
+ h = num_lines * line_height_including_padding
49
+
50
+ # spacing 3: additional space between lines
51
+ h + [num_lines - 1, 0].max * opts.spacing3
52
+ end
53
+
54
+ def resize(lines: nil, chars: nil)
55
+ tk_widget['height'] = lines if lines
56
+ tk_widget['width'] = chars if chars
57
+ end
58
+
59
+ def accumulated_border_and_padding_width
60
+ 2 * (opts.padx + opts.borderwidth)
61
+ end
62
+
63
+ def accumulated_border_and_padding_height
64
+ 2 * (opts.pady + opts.borderwidth)
6
65
  end
7
66
  end
@@ -9,6 +9,9 @@ require_relative 'frame'
9
9
  require_relative 'label'
10
10
  require_relative 'menu'
11
11
  require_relative 'text'
12
+ require_relative 'auto_resize_text'
12
13
  require_relative 'entry'
13
14
  require_relative 'auto_resize_entry'
14
15
  require_relative 'grid'
16
+ require_relative 'mount_point'
17
+ require_relative 'button'
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.5.0
4
+ version: 1.7.2
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-19 00:00:00.000000000 Z
11
+ date: 2021-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tk
@@ -30,8 +30,8 @@ executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
- - lib/tk_extensions.rb
34
33
  - lib/tkwrapper.rb
34
+ - lib/util/array.rb
35
35
  - lib/util/hash_recursive.rb
36
36
  - lib/util/tk/cell.rb
37
37
  - lib/util/tk/finder.rb
@@ -39,6 +39,7 @@ files:
39
39
  - lib/util/tk/tk.rb
40
40
  - lib/util/virtual_methods.rb
41
41
  - lib/widgets/auto_resize_entry.rb
42
+ - lib/widgets/auto_resize_text.rb
42
43
  - lib/widgets/base/base.rb
43
44
  - lib/widgets/base/comparator_item_store.rb
44
45
  - lib/widgets/base/configuration.rb
@@ -46,13 +47,18 @@ files:
46
47
  - lib/widgets/base/match.rb
47
48
  - lib/widgets/base/matcher.rb
48
49
  - lib/widgets/base/matches.rb
50
+ - lib/widgets/base/padding.rb
51
+ - lib/widgets/base/tk_options.rb
49
52
  - lib/widgets/base/widget.rb
50
53
  - lib/widgets/base/widget_store.rb
54
+ - lib/widgets/base/window_info.rb
55
+ - lib/widgets/button.rb
51
56
  - lib/widgets/entry.rb
52
57
  - lib/widgets/frame.rb
53
58
  - lib/widgets/grid.rb
54
59
  - lib/widgets/label.rb
55
60
  - lib/widgets/menu.rb
61
+ - lib/widgets/mount_point.rb
56
62
  - lib/widgets/root.rb
57
63
  - lib/widgets/text.rb
58
64
  - lib/widgets/widgets.rb
data/lib/tk_extensions.rb DELETED
@@ -1,49 +0,0 @@
1
- require 'tk'
2
- require 'tkextlib/tile'
3
-
4
- module TkExtensions
5
- # allow a Tk widget to have multiple bindings for the same event
6
- module MultiBind
7
- def bind(event, &callback)
8
- @bindings ||= {}
9
-
10
- unless @bindings[event]
11
- @bindings[event] = []
12
- super(event) { execute_all_bindings(event) }
13
- end
14
-
15
- @bindings[event].push(callback)
16
- end
17
-
18
- def execute_all_bindings(event)
19
- @bindings[event].each(&:call)
20
- end
21
- end
22
-
23
- module TkWidgets
24
- # from several Tk widgets create subclasses, which include MultiBind
25
- # the reason why we loop over strings and not the classes themselve is, that
26
- # the class names may be aliases (e.g. Tk::Tile::Entry is an alias for
27
- # Tk::Tile::TEntry)
28
- tk_class_names = [
29
- 'TkRoot', # becomes TkExtensions::TkRoot
30
- 'TkText', # becomes TkExtensions::TkText
31
- 'TkMenu', # becomes TkExtensions::TkMenu
32
- 'Tk::Tile::Entry', # becomes TkExtensions::Entry
33
- 'Tk::Tile::Frame', # becomes TkExtensions::Frame
34
- 'Tk::Tile::Label' # becomes TkExtensions::Label
35
- ]
36
- tk_class_names.each do |tk_class_name|
37
- # extract last part of the name (e.g. Tk::Tile::Entry => Entry)
38
- new_child_class_name = tk_class_name.match(/([^:]*)$/)[1]
39
- # get the class from the class constant name
40
- tk_class = const_get(tk_class_name)
41
- # create a new child class of tk_class and have it include MultiBind, which
42
- # overwrites the bind method of that class to allow for multiple bindings
43
- new_child_class = Class.new(tk_class) { include(MultiBind) }
44
- # make the new class known to the TkExtensions namespace to allow to use it
45
- # by e.g. TkExtensions::Entry
46
- const_set(new_child_class_name, new_child_class)
47
- end
48
- end
49
- end