glimmer-dsl-tk 0.0.4 → 0.0.5

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: 631bc5fe4586f68987c644c71f33768414c8088601dfbe1cc641d0fc13656729
4
- data.tar.gz: abe0f504f6b7fd897af3964e24041331bba475a966c9e75fc22554b86b31cbef
3
+ metadata.gz: 8b2c3772ea3eeec35d08dfaebbe1db0a25d85b9569e7c88461a0886447c73928
4
+ data.tar.gz: 6b27a8f3a122a570732d64ca541703cb33fe21009d4e04f1d51cbf3ebdc96df8
5
5
  SHA512:
6
- metadata.gz: c9d211b7f70cbf38c2ad231343a1d5b73c14767d89468a1e99bf418209c03db079edf5ea116ef78c211f4e35795607ea7a9911acf48bffc3913ed53a0adcbc7a
7
- data.tar.gz: b7a66a93ad9d478a215c0c3d6348c9e934ce6dc34b04716d8f2d61a908dd62dd2fa4a4bc42fd4804bd53e0a6c5e4413dc2ea6495b3d2c87417e46d435cb82da9
6
+ metadata.gz: c470bb4fdc925295f92b6f743126edc5c2fef5480dc7913c66124a4489c6d093f163a70ba4410894043a51f715af2fb09aea5eff85f06031ba012467197b7dc0
7
+ data.tar.gz: 50ff417aab865e7dbdf0d5208d211cb19a5bd6fc4c1c193a695394e42b6f9715f2e1bbe7ada5985ad123ad3bbc75d879330b535afc7454d00522a27b33137322
@@ -1,5 +1,12 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.5
4
+
5
+ - Label text data-binding
6
+ - Entry text data-binding
7
+ - The `grid` geometry manager
8
+ - Hello, Computed! sample
9
+
3
10
  ## 0.0.4
4
11
 
5
12
  - `list` custom widget (since listbox is not tile themed yet in Tk)
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.4 (Desktop GUI)
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.5 (Desktop GUI)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-tk.svg)](http://badge.fury.io/rb/glimmer-dsl-tk)
3
3
  [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer-dsl-tk.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer-dsl-tk)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer-dsl-tk/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer-dsl-tk?branch=master)
@@ -77,7 +77,7 @@ gem install glimmer-dsl-tk
77
77
 
78
78
  Add the following to `Gemfile`:
79
79
  ```
80
- gem 'glimmer-dsl-tk', '~> 0.0.4'
80
+ gem 'glimmer-dsl-tk', '~> 0.0.5'
81
81
  ```
82
82
 
83
83
  And, then run:
@@ -163,6 +163,26 @@ root {
163
163
  }.open
164
164
  ```
165
165
 
166
+ ## The Grid Geometry Manager
167
+
168
+ The Grid Geometry Manager is supported via the `grid` keyword just as per the [Tk documentation](https://tkdocs.com/tutorial/grid.html), except by nesting under the widget it concerns.
169
+
170
+ Example:
171
+
172
+ ```ruby
173
+ label {
174
+ grid column: 0, row: 2, sticky: 'w'
175
+ text 'Year of Birth: '
176
+ }
177
+ entry {
178
+ grid column: 1, row: 2
179
+ width 15
180
+ text bind(@contact, :year_of_birth)
181
+ }
182
+ ```
183
+
184
+ More details can be found in the [Hello, Computed!](#hello-computed) sample below.
185
+
166
186
  ## Bidirectional Data-Binding
167
187
 
168
188
  Glimmer supports bidirectional data-binding via the `bind` keyword, which takes a model and an attribute.
@@ -180,8 +200,8 @@ This assumes a `Person` model with a `country` attribute representing their curr
180
200
  }
181
201
  ```
182
202
 
183
- It binds the `values` of the `combobox` to the `country_options` property on the `person` model (data-binding attribute + "_options" by convention).
184
- That binds the `text` selection of the `combobox` to the `country` property on the `person` model.
203
+ That code sets the `values` of the `combobox` to the `country_options` property on the `person` model (data-binding attribute + "_options" by convention).
204
+ It also binds the `text` selection of the `combobox` to the `country` property on the `person` model.
185
205
 
186
206
  It automatically handles all the Tk plumbing behind the scenes, such as using `TkVariable` and setting `combobox` `values` from `person.country_options` by convention (attribute_name + "_options").
187
207
 
@@ -202,7 +222,7 @@ This assumes a `Person` model with a `country` attribute representing their curr
202
222
  }
203
223
  ```
204
224
 
205
- It binds the `items` text of the `list` to the `country_options` property on the `person` model (data-binding attribute + "_options" by convention).
225
+ That code binds the `items` text of the `list` to the `country_options` property on the `person` model (data-binding attribute + "_options" by convention).
206
226
  It also binds the `selection` text of the `list` to the `country` property on the `person` model.
207
227
 
208
228
  It automatically handles all the Tk plumbing behind the scenes.
@@ -223,13 +243,49 @@ This assumes a `Person` model with a `provinces` attribute representing their cu
223
243
  }
224
244
  ```
225
245
 
226
- It binds the `items` text of the `list` to the `provinces_options` property on the `person` model (data-binding attribute + "_options" by convention)
246
+ That code binds the `items` text of the `list` to the `provinces_options` property on the `person` model (data-binding attribute + "_options" by convention)
227
247
  That binds the `selection` text of the `list` to the `provinces` property on the `person` model.
228
248
 
229
249
  It automatically handles all the Tk plumbing behind the scenes.
230
250
 
231
251
  More details can be found in the [Hello, List Multi Selection!](#hello-list-multi-selection) sample below.
232
252
 
253
+ ### Label Data-Binding
254
+
255
+ Example:
256
+
257
+ This assumes a `Person` model with a `country` attribute.
258
+
259
+ ```ruby
260
+ label {
261
+ text bind(person, :country)
262
+ }
263
+ ```
264
+
265
+ That code binds the `textvariable` value of the `label` to the `country` property on the `person` model.
266
+
267
+ It automatically handles all the Tk plumbing behind the scenes.
268
+
269
+ More details can be found in the [Hello, Computed!](#hello-computed) sample below.
270
+
271
+ ### Entry Data-Binding
272
+
273
+ Example:
274
+
275
+ This assumes a `Person` model with a `country` attribute.
276
+
277
+ ```ruby
278
+ entry {
279
+ text bind(person, :country)
280
+ }
281
+ ```
282
+
283
+ That code binds the `textvariable` value of the `entry` to the `country` property on the `person` model.
284
+
285
+ It automatically handles all the Tk plumbing behind the scenes.
286
+
287
+ More details can be found in the [Hello, Computed!](#hello-computed) sample below.
288
+
233
289
  ## Command Observer
234
290
 
235
291
  Buttons can set a `command` option to trigger when the user clicks the button. This may be done with the `command` keyword, passing in a block directly (no need for `proc` as per Tk)
@@ -408,9 +464,79 @@ Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem ins
408
464
  ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_list_multi_selection.rb'"
409
465
  ```
410
466
 
467
+ ### Hello, Computed!
468
+
469
+ Glimmer code (from [samples/hello/hello_computed.rb](samples/hello/hello_computed.rb)):
470
+
471
+ ```ruby
472
+ # ... more code precedes
473
+ root {
474
+ title 'Hello, Computed!'
475
+
476
+ frame {
477
+ grid column: 0, row: 0, padx: 5, pady: 5
478
+
479
+ label {
480
+ grid column: 0, row: 0, sticky: 'w'
481
+ text 'First Name: '
482
+ }
483
+ entry {
484
+ grid column: 1, row: 0
485
+ width 15
486
+ text bind(@contact, :first_name)
487
+ }
488
+
489
+ label {
490
+ grid column: 0, row: 1, sticky: 'w'
491
+ text 'Last Name: '
492
+ }
493
+ entry {
494
+ grid column: 1, row: 1
495
+ width 15
496
+ text bind(@contact, :last_name)
497
+ }
498
+
499
+ label {
500
+ grid column: 0, row: 2, sticky: 'w'
501
+ text 'Year of Birth: '
502
+ }
503
+ entry {
504
+ grid column: 1, row: 2
505
+ width 15
506
+ text bind(@contact, :year_of_birth)
507
+ }
508
+
509
+ label {
510
+ grid column: 0, row: 3, sticky: 'w'
511
+ text 'Name: '
512
+ }
513
+ label {
514
+ grid column: 1, row: 3, sticky: 'w'
515
+ text bind(@contact, :name, computed_by: [:first_name, :last_name])
516
+ }
517
+
518
+ label {
519
+ grid column: 0, row: 4, sticky: 'w'
520
+ text 'Age: '
521
+ }
522
+ label {
523
+ grid column: 1, row: 4, sticky: 'w'
524
+ text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
525
+ }
526
+ }
527
+ }.open
528
+ # ... more code follows
529
+ ```
530
+
531
+ Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
532
+
533
+ ```
534
+ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_computed.rb'"
535
+ ```
536
+
411
537
  Glimmer app:
412
538
 
413
- ![glimmer dsl tk screenshot sample hello list multi selection](images/glimmer-dsl-tk-screenshot-sample-hello-list-multi-selection.png)
539
+ ![glimmer dsl tk screenshot sample hello computed](images/glimmer-dsl-tk-screenshot-sample-hello-computed.png)
414
540
 
415
541
  ## Help
416
542
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.4
1
+ 0.0.5
@@ -55,4 +55,6 @@ require 'glimmer/tk/widget_proxy'
55
55
  require 'glimmer/tk/notebook_proxy'
56
56
  require 'glimmer/tk/frame_proxy'
57
57
  require 'glimmer/tk/button_proxy'
58
+ require 'glimmer/tk/label_proxy'
58
59
  require 'glimmer/tk/list_proxy'
60
+ require 'glimmer/tk/entry_proxy'
@@ -0,0 +1,38 @@
1
+ # Copyright (c) 2020 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/tk/widget_proxy'
23
+
24
+ module Glimmer
25
+ module Tk
26
+ # Proxy for Tk::Tile::TEntry
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class EntryProxy < WidgetProxy
30
+ def validatecommand_block=(proc)
31
+ tk.validatecommand(proc)
32
+ end
33
+ def invalidcommand_block=(proc)
34
+ tk.invalidcommand(proc)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ # Copyright (c) 2020 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/tk/widget_proxy'
23
+
24
+ module Glimmer
25
+ module Tk
26
+ # Proxy for Tk::Tile::TLabel
27
+ #
28
+ # Follows the Proxy Design Pattern
29
+ class LabelProxy < WidgetProxy
30
+ # TODO specify attribute setters
31
+ # def tk_widget_has_attribute_setter?(attribute)
32
+ # if ['anchor', 'justify'].include?(attribute.to_s)
33
+ # true
34
+ # else
35
+ # super
36
+ # end
37
+ # end
38
+ end
39
+ end
40
+ end
@@ -31,6 +31,12 @@ module Glimmer
31
31
  'combobox' => lambda do |tk|
32
32
  tk.textvariable = ::TkVariable.new
33
33
  end,
34
+ 'label' => lambda do |tk|
35
+ tk.textvariable = ::TkVariable.new
36
+ end,
37
+ 'entry' => lambda do |tk|
38
+ tk.textvariable = ::TkVariable.new
39
+ end,
34
40
  }
35
41
 
36
42
  class << self
@@ -75,7 +81,7 @@ module Glimmer
75
81
  def initialize(underscored_widget_name, parent_proxy, args)
76
82
  @parent_proxy = parent_proxy
77
83
  @args = args
78
- tk_widget_class = self.class.tk_widget_class_for(underscored_widget_name)
84
+ tk_widget_class = self.class.tk_widget_class_for(underscored_widget_name)
79
85
  @tk = tk_widget_class.new(@parent_proxy.tk, *args)
80
86
  # a common widget initializer
81
87
  @tk.grid
@@ -97,7 +103,7 @@ module Glimmer
97
103
  !!tk_widget_class_for(underscored_widget_name)
98
104
  end
99
105
 
100
- def tk_widget_has_attribute?(attribute)
106
+ def tk_widget_has_attribute_setter?(attribute)
101
107
  result = nil
102
108
  begin
103
109
  # TK Widget currently doesn't support respond_to? properly, so I have to resort to this trick for now
@@ -109,9 +115,22 @@ module Glimmer
109
115
  result
110
116
  end
111
117
 
118
+ def tk_widget_has_attribute_getter_setter?(attribute)
119
+ result = nil
120
+ begin
121
+ # TK Widget currently doesn't support respond_to? properly, so I have to resort to this trick for now
122
+ @tk.send(attribute, @tk.send(attribute))
123
+ result = true
124
+ rescue => e
125
+ result = false
126
+ end
127
+ result
128
+ end
129
+
112
130
  def has_attribute?(attribute, *args)
113
131
  (widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]) ||
114
- tk_widget_has_attribute?(attribute) ||
132
+ tk_widget_has_attribute_setter?(attribute) ||
133
+ tk_widget_has_attribute_getter_setter?(attribute) ||
115
134
  respond_to?(attribute_setter(attribute), args)
116
135
  end
117
136
 
@@ -119,8 +138,10 @@ module Glimmer
119
138
  widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
120
139
  if widget_custom_attribute
121
140
  widget_custom_attribute[:setter][:invoker].call(@tk, args)
122
- elsif tk_widget_has_attribute?(attribute)
141
+ elsif tk_widget_has_attribute_setter?(attribute)
123
142
  @tk.send(attribute_setter(attribute), *args) unless @tk.send(attribute) == args.first
143
+ elsif tk_widget_has_attribute_getter_setter?(attribute)
144
+ @tk.send(attribute, *args) unless @tk.send(attribute) == args.first
124
145
  else
125
146
  send(attribute_setter(attribute), args)
126
147
  end
@@ -130,7 +151,7 @@ module Glimmer
130
151
  widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
131
152
  if widget_custom_attribute
132
153
  widget_custom_attribute[:getter][:invoker].call(@tk, args)
133
- elsif tk_widget_has_attribute?(attribute)
154
+ elsif tk_widget_has_attribute_getter_setter?(attribute)
134
155
  @tk.send(attribute)
135
156
  else
136
157
  send(attribute)
@@ -149,6 +170,18 @@ module Glimmer
149
170
  setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first }},
150
171
  },
151
172
  },
173
+ ::Tk::Tile::TLabel => {
174
+ 'text' => {
175
+ getter: {name: 'text', invoker: lambda { |widget, args| @tk.textvariable&.value }},
176
+ setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first }},
177
+ },
178
+ },
179
+ ::Tk::Tile::TEntry => {
180
+ 'text' => {
181
+ getter: {name: 'text', invoker: lambda { |widget, args| @tk.textvariable&.value }},
182
+ setter: {name: 'text=', invoker: lambda { |widget, args| @tk.textvariable&.value = args.first unless @text_variable_edit }},
183
+ },
184
+ },
152
185
  }
153
186
  end
154
187
 
@@ -166,6 +199,21 @@ module Glimmer
166
199
  }
167
200
  end,
168
201
  },
202
+ ::Tk::Tile::TEntry => {
203
+ 'text' => lambda do |observer|
204
+ tk.validate = 'key'
205
+ tk.validatecommand { |new_tk_variable|
206
+ @text_variable_edit = new_tk_variable.value != @tk.textvariable.value
207
+ if @text_variable_edit
208
+ observer.call(new_tk_variable.value)
209
+ @text_variable_edit = nil
210
+ true
211
+ else
212
+ false
213
+ end
214
+ }
215
+ end,
216
+ },
169
217
  }
170
218
  end
171
219
 
@@ -0,0 +1,75 @@
1
+ require 'glimmer-dsl-tk'
2
+
3
+ require_relative 'hello_computed/contact'
4
+
5
+ class HelloComputed
6
+ include Glimmer
7
+
8
+ def initialize
9
+ @contact = Contact.new(
10
+ first_name: 'Barry',
11
+ last_name: 'McKibbin',
12
+ year_of_birth: 1985
13
+ )
14
+ end
15
+
16
+ def launch
17
+ root {
18
+ title 'Hello, Computed!'
19
+
20
+ frame {
21
+ grid column: 0, row: 0, padx: 5, pady: 5
22
+
23
+ label {
24
+ grid column: 0, row: 0, sticky: 'w'
25
+ text 'First Name: '
26
+ }
27
+ entry {
28
+ grid column: 1, row: 0
29
+ width 15
30
+ text bind(@contact, :first_name)
31
+ }
32
+
33
+ label {
34
+ grid column: 0, row: 1, sticky: 'w'
35
+ text 'Last Name: '
36
+ }
37
+ entry {
38
+ grid column: 1, row: 1
39
+ width 15
40
+ text bind(@contact, :last_name)
41
+ }
42
+
43
+ label {
44
+ grid column: 0, row: 2, sticky: 'w'
45
+ text 'Year of Birth: '
46
+ }
47
+ entry {
48
+ grid column: 1, row: 2
49
+ width 15
50
+ text bind(@contact, :year_of_birth)
51
+ }
52
+
53
+ label {
54
+ grid column: 0, row: 3, sticky: 'w'
55
+ text 'Name: '
56
+ }
57
+ label {
58
+ grid column: 1, row: 3, sticky: 'w'
59
+ text bind(@contact, :name, computed_by: [:first_name, :last_name])
60
+ }
61
+
62
+ label {
63
+ grid column: 0, row: 4, sticky: 'w'
64
+ text 'Age: '
65
+ }
66
+ label {
67
+ grid column: 1, row: 4, sticky: 'w'
68
+ text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
69
+ }
70
+ }
71
+ }.open
72
+ end
73
+ end
74
+
75
+ HelloComputed.new.launch
@@ -0,0 +1,21 @@
1
+ class HelloComputed
2
+ class Contact
3
+ attr_accessor :first_name, :last_name, :year_of_birth
4
+
5
+ def initialize(attribute_map)
6
+ @first_name = attribute_map[:first_name]
7
+ @last_name = attribute_map[:last_name]
8
+ @year_of_birth = attribute_map[:year_of_birth]
9
+ end
10
+
11
+ def name
12
+ "#{last_name}, #{first_name}"
13
+ end
14
+
15
+ def age
16
+ Time.now.year - year_of_birth.to_i
17
+ rescue
18
+ 0
19
+ end
20
+ end
21
+ end
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.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-13 00:00:00.000000000 Z
11
+ date: 2020-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -198,12 +198,16 @@ files:
198
198
  - lib/glimmer/dsl/tk/root_expression.rb
199
199
  - lib/glimmer/dsl/tk/widget_expression.rb
200
200
  - lib/glimmer/tk/button_proxy.rb
201
+ - lib/glimmer/tk/entry_proxy.rb
201
202
  - lib/glimmer/tk/frame_proxy.rb
203
+ - lib/glimmer/tk/label_proxy.rb
202
204
  - lib/glimmer/tk/list_proxy.rb
203
205
  - lib/glimmer/tk/notebook_proxy.rb
204
206
  - lib/glimmer/tk/root_proxy.rb
205
207
  - lib/glimmer/tk/widget_proxy.rb
206
208
  - samples/hello/hello_combo.rb
209
+ - samples/hello/hello_computed.rb
210
+ - samples/hello/hello_computed/contact.rb
207
211
  - samples/hello/hello_list_multi_selection.rb
208
212
  - samples/hello/hello_list_single_selection.rb
209
213
  - samples/hello/hello_tab.rb