tkwrapper 1.6.1 → 1.7.1

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: a67fc8eac231f5b0b875cdd2fba4f107a3b596206766a4e57793e4f3d1b71992
4
- data.tar.gz: 9bd2376b17ebf7e866f7858f98d2e9698575dec8a3fa2794c84c7b625048b33c
3
+ metadata.gz: 90b29c12036c765281e148238dd8b97afc06091749eeb5c8a8595ce8a3ddd589
4
+ data.tar.gz: 8c7b8f7f3b5c9b54a239d9d7d034b14d8cde4e700d848e98d2b77329da03aa8b
5
5
  SHA512:
6
- metadata.gz: b467177153264f4a1cf973e4ae321d57c94f421e14eddfac98db6766ed06ca133f7af73931ef3f2ca3b23800363dacc533c666fb883f2bcb01c19a5432250b75
7
- data.tar.gz: 00f36bd8f579688715d25b580a028e577f3820a83749b39bfd353c90ed32a3e0509ebcc5ca0306a3cf48576dd3d52d136e093ad26d87a33212cb84cb9a09b456
6
+ metadata.gz: 402470958a23a858dbe40ab101e31b61fd7ccbf6c240dbaa83a9c6e6727c94ca1a5e81e9d73ab571fc3c85b0ba275fece636793eacb487a98a60ed85bffc1661
7
+ data.tar.gz: 3f74e9a050ec620ea4d77bc0e518dff8fe4037e79c37d5ca111d85f33d52288dc663449ba760a963fa26fb5dd2bcafb6d6edd9ecc6b84ac0831f67e1456bdbf1
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
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
@@ -2,24 +2,97 @@
2
2
 
3
3
  require_relative 'text'
4
4
 
5
- class TkWrapper::Widgets::AutoResizeText < TkWrapper::Widgets::Text
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
+
6
26
  def build(parent, **args)
7
27
  super(parent, **args)
8
- bind('<Modified>', ->(ev) { resize(ev) })
9
- bind('<Modified>', -> { puts 'hihi' })
10
- end
11
-
12
- def resize(event)
13
- return unless tk_widget.modified?
14
-
15
- puts event
16
- puts 'yes!'
17
- tk_widget.modified(false)
18
- #max_width = [@cell.bbox[2], 0].max
19
- #puts @font.metrics
20
- #new_width = [[@min_width, text_width + @add_width].max, max_width].min
21
- #tk_widget.width = 0
22
- #tk_widget.grid(ipadx: new_width / 2.0)
23
- #@parent.tk_widget.update
28
+ @text.bind('<Modified>', &method(:autoresize))
29
+ TkGrid.propagate(tk_widget, 0)
30
+ resize(lines: @min_number_lines, chars: @min_number_chars)
31
+ #@text.resize(lines: @min_number_lines, chars: @min_number_chars)
32
+ end
33
+
34
+ # width of cursor + borders (textfield + frame) + padding (textfield + frame)
35
+ def additional_width_needed_for_textfield
36
+ @text.opts.insertwidth +
37
+ @text.accumulated_border_and_padding_width +
38
+ accumulated_border_and_padding_width
39
+ end
40
+
41
+ def additional_height_needed_for_textfield
42
+ # TODO: cursor height?
43
+ @text.accumulated_border_and_padding_height +
44
+ accumulated_border_and_padding_height
45
+ end
46
+
47
+ def width_needed_for_chars(num_chars)
48
+ text.font.char_width * num_chars + additional_width_needed_for_textfield
49
+ end
50
+
51
+ def height_needed_for_lines(num_lines)
52
+ @text.height_of_lines(num_lines) + additional_height_needed_for_textfield
53
+ end
54
+
55
+ def resize_width
56
+ opts.width = width_needed_for_textfield
57
+ @parent.tk_widget.update
58
+ end
59
+
60
+ def resize(height: nil, width: nil, lines: nil, chars: nil)
61
+ width = width_needed_for_chars(chars) if chars
62
+ height = height_needed_for_lines(lines) if lines
63
+
64
+ opts.width = width if width
65
+ opts.height = height if height
66
+ end
67
+
68
+ def width_needed_for_textfield
69
+ @text.longest_line_width + additional_width_needed_for_textfield
70
+ end
71
+
72
+ def height_needed_for_textfield
73
+ @text.height_of_lines + additional_height_needed_for_textfield
74
+ end
75
+
76
+ def max_width
77
+ [@cell.bbox[2], 0].max
78
+ end
79
+
80
+ def min_width
81
+ [max_width, width_needed_for_chars(@min_number_chars)].min
82
+ end
83
+
84
+ def min_height
85
+ height_needed_for_lines(@min_number_lines)
86
+ end
87
+
88
+ def autoresize
89
+ return unless @text.tk_widget.modified?
90
+
91
+ width = [[min_width, width_needed_for_textfield].max, max_width].min
92
+ height = [min_height, height_needed_for_textfield].max
93
+
94
+ resize(height: height, width: width)
95
+
96
+ @text.tk_widget.modified(false)
24
97
  end
25
98
  end
@@ -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
@@ -3,6 +3,7 @@ require "#{LIB_DIR}/util/tk/finder"
3
3
 
4
4
  require_relative 'base'
5
5
  require_relative 'window_info'
6
+ require_relative 'tk_options'
6
7
 
7
8
  class TkWrapper::Widgets::Base::Widget
8
9
  extend Forwardable
@@ -14,14 +15,12 @@ class TkWrapper::Widgets::Base::Widget
14
15
  def_delegator :@manager, :widgets, :managed
15
16
 
16
17
  attr_accessor :config
17
- attr_reader :parent, :ids, :cell, :childs, :manager, :winfo
18
+ attr_reader :parent, :ids, :cell, :childs, :manager, :winfo, :opts, :font
18
19
 
19
20
  def tk_class() end
20
21
 
21
22
  def initialize(parent: nil, config: {}, childs: [], manager: nil, ids: [], id: [])
22
- @cell = TkWrapper::Util::Tk::Cell.new(self)
23
- @winfo = TkWrapper::Widgets::Base::WindowInfo.new(self)
24
- @finder = TkWrapper::Util::Tk::Finder.new(widgets: self)
23
+ initialize_utilities
25
24
  @config = TkWrapper::Widgets::Base::Configuration.new(config)
26
25
  @manager = manager
27
26
  @ids = init_id(id) + init_id(ids)
@@ -31,6 +30,13 @@ class TkWrapper::Widgets::Base::Widget
31
30
  parent&.push(self)
32
31
  end
33
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
+
34
40
  def init_id(id)
35
41
  id.is_a?(Array) ? id : [id]
36
42
  end
@@ -10,4 +10,8 @@ class TkWrapper::Widgets::Base::WindowInfo
10
10
  super
11
11
  end
12
12
  end
13
+
14
+ def respond_to_missing?(name, *)
15
+ @widget.tk_widget.respond_to?("winfo_#{name}") || super
16
+ end
13
17
  end
data/lib/widgets/frame.rb CHANGED
@@ -6,4 +6,12 @@ class TkWrapper::Widgets::Frame < TkWrapper::Widgets::Base::Widget
6
6
  def tk_class
7
7
  Tk::Tile::Frame
8
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
16
+ end
9
17
  end
data/lib/widgets/text.rb CHANGED
@@ -6,4 +6,61 @@ class TkWrapper::Widgets::Text < TkWrapper::Widgets::Base::Widget
6
6
  def tk_class
7
7
  TkText
8
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 = lines.size)
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)
65
+ end
9
66
  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.6.1
4
+ version: 1.7.1
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-21 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
@@ -31,6 +31,7 @@ extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
33
  - lib/tkwrapper.rb
34
+ - lib/util/array.rb
34
35
  - lib/util/hash_recursive.rb
35
36
  - lib/util/tk/cell.rb
36
37
  - lib/util/tk/finder.rb
@@ -46,6 +47,8 @@ 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
51
54
  - lib/widgets/base/window_info.rb