glimmer-dsl-tk 0.0.57 → 0.0.60

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: 0e0e1ed1843f904d42892c7fe2546383717da65d7cfd0690b1b66101a5b68576
4
- data.tar.gz: af96af00f8b06606ac584ab14d5d8d360977a58ec354053a0826edc470c0d57f
3
+ metadata.gz: 9c0553115fdb0b7a912c59f6feda8b475e76c546fc2db32984037e7bbc8db204
4
+ data.tar.gz: 450c7795ef8adafe88db9fbfdf78691933f79b06f1f4b1e899f5ddacac3da567
5
5
  SHA512:
6
- metadata.gz: '01787afce29bc0b1d4656b8ab646f0eb4501a8b8feb23979ad99970f6e5d6bb75d5945bb0b9a9a91cdb34f36d6bdf9226ec3e3aa60368206cd98b40daa2cd0a1'
7
- data.tar.gz: 677f8d13ab20b7857c613167d1d21eed0dec3f1b19a8b29ba4b4cec49545186446c2c9bacbaf9e0741c16ceb2d20e60136c482dc6e78783d8b1d435ed4239be8
6
+ metadata.gz: 256d0e2d25fd50791b979cf92ba9dad8dedf77941e6e6394f1474f41f20a035bb601f6cc2af3b2bab8ed0b3acf11825d041a3d65d5d8941da85e6fc563c7c23b
7
+ data.tar.gz: b122dd08e9a6b2ec400ecf49c15d0be69fcc3c4e4fbe4de9c427dc0b1a085cae6ab8c95deca79272f28ecb21479477a6792ae434544c64013ebfe8cc4b8b49de
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.60
4
+
5
+ - Update Hello, Built-in Dialog! with more options for customizing dialogs
6
+ - Support setting colors as rgb colors via `r, g, b` (e.g. `foreground 210, 48, 110`)
7
+ - Accept hex color strings not starting with `#` (e.g. `background 'f828d7'`)
8
+
9
+ ## 0.0.59
10
+
11
+ - Auto-Default to `validate 'key'` on an `entry` when defining `validatecommand {}`, `on('validate') {}`, `invalidcommand {}`, `on('invalid') {}`
12
+
13
+ ## 0.0.58
14
+
15
+ - Support `@tk.textvariable.trace('write')` kind of variable tracing via `on_var(trace_operation) {}` listeners (e.g. `on_textvariable('write') {}`)
16
+ - Use `on_textvariable` in `samples/hello/hello_entry.rb`
17
+ - Improve validation text in `samples/hello/hello_entry.rb` to say "... not a valid phone!"
18
+
3
19
  ## 0.0.57
4
20
 
5
21
  - Hello, Theme! sample
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Tk 0.0.57
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Tk 0.0.60
2
2
  ## Ruby Tk Desktop Development GUI Library
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-tk.svg)](http://badge.fury.io/rb/glimmer-dsl-tk)
4
4
  [![Ruby](https://github.com/AndyObtiva/glimmer-dsl-tk/actions/workflows/ruby.yml/badge.svg)](https://github.com/AndyObtiva/glimmer-dsl-tk/actions/workflows/ruby.yml)
@@ -195,7 +195,7 @@ gem install glimmer-dsl-tk
195
195
 
196
196
  Add the following to `Gemfile`:
197
197
  ```
198
- gem 'glimmer-dsl-tk', '0.0.57'
198
+ gem 'glimmer-dsl-tk', '0.0.60'
199
199
  ```
200
200
 
201
201
  And, then run:
@@ -309,14 +309,14 @@ keyword(args) | attributes | event bindings & callbacks
309
309
  ------------- | ---------- | ---------
310
310
  `button` | `text`, `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `default` (`'active', 'normal'`) | `command {}`
311
311
  `checkbutton` | `text`, `variable` (Boolean), `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `onvalue` (default: `1`), `offvalue` (default: `0`) | `command {}`
312
- `choose_color(options = nil)` | None | None
313
- `choose_directory(options = nil)` | None | None
314
- `choose_font(options = nil) {|font| ... }` | None | None
312
+ `choose_color(parent: nil, initialcolor: 'white', title: 'Colors')` | None | None
313
+ `choose_directory(parent: nil)` | None | None
314
+ `choose_font(family: nil, size: nil, weight: nil) {|font| ... }` | None | None
315
315
  `combobox` | `state`, `text` | `'ComboboxSelected'`
316
316
  `entry` | `width`, `text`, `validate`, `show` (`'none', 'focus', 'focusin', 'focusout', 'key', or 'all'`) | `'validate'`, `'invalid'`, `'change'` (alias: `'changed'`), `validatecommand {}`, `invalidcommand {}`
317
- `get_multiple_open_file(options = nil)` | None | None
318
- `get_open_file(options = nil)` | None | None
319
- `get_save_file(options = nil)` | None | None
317
+ `get_multiple_open_file(parent: nil, title: '')` | None | None
318
+ `get_open_file(parent: nil, title: '')` | None | None
319
+ `get_save_file(parent: nil, title: '')` | None | None
320
320
  `spinbox` | `text`, `from`, `to`, `increment`, `format`, [more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `command {}`, `'increment'`, `'decrement'`
321
321
  `frame(text: nil)` | `width`, `height`, `borderwidth`, `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`) | None
322
322
  `label` | `text`, `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `font` (`'default', 'text', 'fixed', 'menu', 'heading', 'caption', 'small_caption', 'icon', 'tooltip'`), `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`), `justify` (`'left', 'center', 'right'`), `foreground`, `background` | None
@@ -343,6 +343,8 @@ Options for `get_open_file` and `get_multiple_open_file` include:
343
343
  #### Common Attributes
344
344
 
345
345
  - `grid`: `Hash` of `:row`, `:column`, `:padx`, `:pady`, `:sticky` (`'e', 'w', 'n', 's'` or any combination of direction letters)
346
+ - `foreground`: [Built-in Color](https://tcl.tk/man/tcl8.6/TkCmd/colors.htm) (e.g. `'AliceBlue'`) or Hex color (e.g. `'#ffd807'`)
347
+ - `background`: [Built-in Color](https://tcl.tk/man/tcl8.6/TkCmd/colors.htm) (e.g. `'AliceBlue'`) or Hex color (e.g. `'#ffd807'`)
346
348
 
347
349
  #### Common Event Bindings
348
350
 
@@ -2181,12 +2183,13 @@ class HelloEntry
2181
2183
  def launch
2182
2184
  root {
2183
2185
  title 'Hello, Entry!'
2184
-
2186
+ minsize 230, 0
2187
+
2185
2188
  label {
2186
2189
  grid sticky: 'ew'
2187
2190
  text 'default entry'
2188
2191
  }
2189
- entry {
2192
+ entry { |the_entry|
2190
2193
  grid sticky: 'ew'
2191
2194
  text <=> [self, :default]
2192
2195
  }
@@ -2205,11 +2208,14 @@ class HelloEntry
2205
2208
  grid sticky: 'ew'
2206
2209
  text 'entry with event handlers'
2207
2210
  }
2208
- entry {
2211
+ entry { |the_entry|
2209
2212
  grid sticky: 'ew'
2210
2213
  text <=> [self, :telephone]
2211
- validate 'key'
2212
2214
 
2215
+ # validate 'key' # default when on('validate') or on('invalid') is specified
2216
+ ## Validation happens on key change by default when validation listeners are specified
2217
+ ## (other accepted values: 'none', 'focus', 'focusin', 'focusout', 'key', or 'all')
2218
+
2213
2219
  ## this event kicks in just after the user typed and before modifying the text variable
2214
2220
  on('validate') do |new_text_variable|
2215
2221
  telephone?(new_text_variable.value)
@@ -2217,7 +2223,7 @@ class HelloEntry
2217
2223
 
2218
2224
  ## this event kicks in just after the text variable is validated and before it is modified
2219
2225
  on('invalid') do |validate_args|
2220
- @validated_entry_label.text = "#{validate_args.string} is not valid!"
2226
+ @validated_entry_label.text = "#{validate_args.value} is not a valid phone!"
2221
2227
  @validated_entry_label.foreground = 'red'
2222
2228
  end
2223
2229
 
@@ -2227,6 +2233,13 @@ class HelloEntry
2227
2233
  @validated_entry_label.text = 'entry with event handlers'
2228
2234
  @validated_entry_label.foreground = nil
2229
2235
  end
2236
+
2237
+ ## this is similar to on('change') (which is Glimmer-specific), but more low level at the Tk level
2238
+ ## it is the equivalent of calling: the_entry.tk.textvariable.trace('write') { puts "..." }
2239
+ ## More at: https://tkdocs.com/tutorial/widgets.html#entry and https://tcl.tk/man/tcl8.6/TclCmd/trace.htm#M14
2240
+ on_textvariable('write') do
2241
+ puts "\"#{the_entry.text}\" has been written to entry!"
2242
+ end
2230
2243
  }
2231
2244
 
2232
2245
  label {
@@ -4274,9 +4287,9 @@ https://github.com/ancorgs/y3network-ruby-ui
4274
4287
 
4275
4288
  This is a Graphical User Interface for the famous [cryptopunks Ruby gem](https://github.com/cryptopunksnotdead/cryptopunks/tree/master/cryptopunks).
4276
4289
 
4277
- https://github.com/cryptopunksnotdead/cryptopunks-gui
4290
+ https://github.com/cryptopunksnotdead/cryptopunks/tree/master/cryptopunks-gui
4278
4291
 
4279
- ![CryptoPunks GUI Screenshot](https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks-gui/master/screenshots/cryptopunks-gui-screenshot.png)
4292
+ ![CryptoPunks GUI Screenshot](https://raw.githubusercontent.com/cryptopunksnotdead/cryptopunks/master/cryptopunks-gui/screenshots/cryptopunks-gui-screenshot.png)
4280
4293
 
4281
4294
  ### Circule
4282
4295
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.57
1
+ 0.0.60
Binary file
@@ -37,6 +37,7 @@ module Glimmer
37
37
  Tk,
38
38
  %w[
39
39
  list_selection_data_binding
40
+ variable_listener
40
41
  data_binding
41
42
  attribute
42
43
  shine_data_binding
@@ -0,0 +1,41 @@
1
+ # Copyright (c) 2020-2022 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/dsl/expression'
23
+ require 'glimmer/tk/widget_proxy'
24
+
25
+ module Glimmer
26
+ module DSL
27
+ module Tk
28
+ class VariableListenerExpression < Expression
29
+ def can_interpret?(parent, keyword, *args, &block)
30
+ parent.is_a?(Glimmer::Tk::WidgetProxy) && keyword.match(/^on_.*/) && textual?(args.first)
31
+ end
32
+
33
+ def interpret(parent, keyword, *args, &block)
34
+ variable_name = keyword.sub(/^on_/, '')
35
+ operation = args.first.to_s
36
+ parent.tk.send(variable_name).trace(operation, &block)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -31,13 +31,24 @@ module Glimmer
31
31
  include TextVariableOwner
32
32
 
33
33
  def validatecommand_block=(proc)
34
+ self.validate = 'key' unless validate
34
35
  tk.validatecommand(proc)
35
36
  end
36
37
 
37
38
  def invalidcommand_block=(proc)
39
+ self.validate = 'key' unless validate
38
40
  tk.invalidcommand(proc)
39
41
  end
40
42
 
43
+ def validate
44
+ @validate
45
+ end
46
+
47
+ def validate=(value)
48
+ @validate = value
49
+ @tk.validate(value)
50
+ end
51
+
41
52
  def handle_listener(listener_name, &listener)
42
53
  case listener_name.to_s.downcase
43
54
  when 'change', 'changed', 'modified'
@@ -192,6 +192,7 @@ module Glimmer
192
192
 
193
193
  def set_attribute(attribute, *args)
194
194
  begin
195
+ args = normalize_attribute_arguments(attribute, args)
195
196
  widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
196
197
  if respond_to?(attribute_setter(attribute), super_only: true)
197
198
  send(attribute_setter(attribute), *args)
@@ -308,6 +309,30 @@ module Glimmer
308
309
  @tk.style = style
309
310
  end
310
311
 
312
+ def normalize_attribute_arguments(attribute, args)
313
+ attribute_argument_normalizers[attribute]&.call(args) || args
314
+ end
315
+
316
+ def attribute_argument_normalizers
317
+ color_normalizer = lambda do |args|
318
+ if args.size > 1 || args.first.is_a?(Numeric)
319
+ rgb = args
320
+ rgb = rgb.map(&:to_s).map(&:to_i)
321
+ rgb = 3.times.map { |n| rgb[n] || 0}
322
+ hex = rgb.map { |color| color.to_s(16).ljust(2, '0') }.join
323
+ ["##{hex}"]
324
+ elsif args.size == 1 && args.first.is_a?(String) && !args.first.start_with?('#')
325
+ ["##{args.first}"]
326
+ else
327
+ args
328
+ end
329
+ end
330
+ @attribute_argument_normalizers ||= {
331
+ 'background' => color_normalizer,
332
+ 'foreground' => color_normalizer,
333
+ }
334
+ end
335
+
311
336
  def widget_custom_attribute_mapping
312
337
  # TODO consider extracting to modules/subclasses
313
338
  @widget_custom_attribute_mapping ||= {
@@ -534,10 +559,12 @@ module Glimmer
534
559
 
535
560
  def method_missing(method, *args, &block)
536
561
  method = method.to_s
562
+ attribute_name = method.sub(/=$/, '')
563
+ args = normalize_attribute_arguments(attribute_name, args)
537
564
  if args.empty? && block.nil? && ((widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][method]) || has_state?(method) || has_attributes_attribute?(method))
538
565
  get_attribute(method)
539
566
  elsif method.end_with?('=') && block.nil? && ((widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][method.sub(/=$/, '')]) || has_state?(method) || has_attributes_attribute?(method))
540
- set_attribute(method.sub(/=$/, ''), *args)
567
+ set_attribute(attribute_name, *args)
541
568
  else
542
569
  tk.send(method, *args, &block)
543
570
  end
@@ -31,21 +31,47 @@ root { |w|
31
31
  y 150
32
32
 
33
33
  frame {
34
- %w[get_open_file get_multiple_open_file get_save_file choose_directory choose_color].each do |dialog|
34
+ %w[get_open_file get_multiple_open_file get_save_file choose_directory].each do |dialog|
35
+ dialog_name = dialog.split('_').map(&:capitalize).join(' ')
35
36
  button {
36
- text dialog.split('_').map(&:capitalize).join(' ')
37
+ text dialog_name
37
38
 
38
39
  on('command') do
39
- result = send(dialog, parent: w)
40
+ # parent is optional.
41
+ # It is recommended to set parent to display dialog on top of.
42
+ #
43
+ # title is optional (defaults to blank).
44
+ # It is not supported by choose_directory (its title is always blank).
45
+ result = send(dialog, parent: w, title: dialog_name)
46
+ # Uniformly handle both a singular result (e.g. from get_open_file)
47
+ # and an array of results (e.g. from get_multiple_open_file)
40
48
  @result_label.text = [result].flatten.join("\n")
41
49
  end
42
50
  }
43
51
  end
44
52
 
53
+ button {
54
+ text 'Choose Color'
55
+
56
+ on('command') do
57
+ # parent is optional.
58
+ # It is recommended to set parent to display dialog on top of.
59
+ #
60
+ # title is optional (defaults to 'Colors').
61
+ #
62
+ # initialcolor is optional (defaults to 'white').
63
+ # It can be a built-in color (e.g. 'AliceBlue') or hex (e.g. '#FFFF00')
64
+ # Full list of built-in colors is at: https://tcl.tk/man/tcl8.6/TkCmd/colors.htm
65
+ chosen_color = choose_color(parent: w, title: 'Choose Color', initialcolor: '#FFFF00')
66
+ @result_label.text = chosen_color
67
+ end
68
+ }
69
+
45
70
  button {
46
71
  text 'Choose Font'
47
72
 
48
73
  on('command') do
74
+ # Initial family, size, and weight are optional.
49
75
  choose_font(family: 'Courier New', size: '30', weight: 'bold') do |chosen_font|
50
76
  @result_label.text = chosen_font
51
77
  end
@@ -36,12 +36,13 @@ class HelloEntry
36
36
  def launch
37
37
  root {
38
38
  title 'Hello, Entry!'
39
-
39
+ minsize 230, 0
40
+
40
41
  label {
41
42
  grid sticky: 'ew'
42
43
  text 'default entry'
43
44
  }
44
- entry {
45
+ entry { |the_entry|
45
46
  grid sticky: 'ew'
46
47
  text <=> [self, :default]
47
48
  }
@@ -60,11 +61,14 @@ class HelloEntry
60
61
  grid sticky: 'ew'
61
62
  text 'entry with event handlers'
62
63
  }
63
- entry {
64
+ entry { |the_entry|
64
65
  grid sticky: 'ew'
65
66
  text <=> [self, :telephone]
66
- validate 'key'
67
67
 
68
+ # validate 'key' # default when on('validate') or on('invalid') is specified
69
+ ## Validation happens on key change by default when validation listeners are specified
70
+ ## (other accepted values: 'none', 'focus', 'focusin', 'focusout', 'key', or 'all')
71
+
68
72
  ## this event kicks in just after the user typed and before modifying the text variable
69
73
  on('validate') do |new_text_variable|
70
74
  telephone?(new_text_variable.value)
@@ -72,7 +76,7 @@ class HelloEntry
72
76
 
73
77
  ## this event kicks in just after the text variable is validated and before it is modified
74
78
  on('invalid') do |validate_args|
75
- @validated_entry_label.text = "#{validate_args.value} is not valid!"
79
+ @validated_entry_label.text = "#{validate_args.value} is not a valid phone!"
76
80
  @validated_entry_label.foreground = 'red'
77
81
  end
78
82
 
@@ -82,6 +86,13 @@ class HelloEntry
82
86
  @validated_entry_label.text = 'entry with event handlers'
83
87
  @validated_entry_label.foreground = nil
84
88
  end
89
+
90
+ ## this is similar to on('change') (which is Glimmer-specific), but more low level at the Tk level
91
+ ## it is the equivalent of calling: the_entry.tk.textvariable.trace('write') { puts "..." }
92
+ ## More at: https://tkdocs.com/tutorial/widgets.html#entry and https://tcl.tk/man/tcl8.6/TclCmd/trace.htm#M14
93
+ on_textvariable('write') do
94
+ puts "\"#{the_entry.text}\" has been written to entry!"
95
+ end
85
96
  }
86
97
 
87
98
  label {
@@ -80,8 +80,13 @@ class HelloLabel
80
80
  anchor 'center'
81
81
  justify 'center' # other options are: 'left' and 'right'
82
82
  font 'caption' # other options are: 'default', 'text', 'fixed', 'menu', 'heading', 'small_caption', 'icon', 'tooltip'
83
- foreground 'blue'
84
83
  relief 'sunken' # other options are: 'flat' (default), 'raised', 'solid', 'ridge', 'groove'
84
+ foreground 38, 20, 138 # RGB (Red Green Blue) color
85
+
86
+ # Other supported color arguments:
87
+ # foreground 'blue' # built-in color alternative from https://tcl.tk/man/tcl8.6/TkCmd/colors.htm
88
+ # foreground '#ff0000' # hex color
89
+ # foreground 'ff0000' # hex color missing the # prefix
85
90
  }
86
91
  }
87
92
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-tk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.57
4
+ version: 0.0.60
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-28 00:00:00.000000000 Z
11
+ date: 2022-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -170,8 +170,8 @@ dependencies:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
172
  version: 0.7.0
173
- description: Glimmer DSL for Tk (MRI Ruby Desktop Development GUI Library) - Ruby
174
- DSL for Tcl/Tk with bidirectional/unidirectional data-binding support.
173
+ description: Glimmer DSL for Tk (Ruby Tk Desktop Development GUI Library) - Ruby DSL
174
+ for Tcl/Tk with bidirectional/unidirectional data-binding support.
175
175
  email: andy.am@gmail.com
176
176
  executables:
177
177
  - girb
@@ -205,6 +205,7 @@ files:
205
205
  - lib/glimmer/dsl/tk/on_expression.rb
206
206
  - lib/glimmer/dsl/tk/root_expression.rb
207
207
  - lib/glimmer/dsl/tk/shine_data_binding_expression.rb
208
+ - lib/glimmer/dsl/tk/variable_listener_expression.rb
208
209
  - lib/glimmer/dsl/tk/widget_expression.rb
209
210
  - lib/glimmer/tk/checkbutton_proxy.rb
210
211
  - lib/glimmer/tk/combobox_proxy.rb