tkwrapper 1.5.0 → 1.7.2

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 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