glimmer-dsl-tk 0.0.3 → 0.0.4

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: 2f57063e358754b89fbd0a57cb118fb9764595a8965eba5884aeb2988ab2d6b1
4
- data.tar.gz: f55e3fc96a9388dd218d7c674cdf1585831c44a3f6412741e0e65f53185e2d98
3
+ metadata.gz: 631bc5fe4586f68987c644c71f33768414c8088601dfbe1cc641d0fc13656729
4
+ data.tar.gz: abe0f504f6b7fd897af3964e24041331bba475a966c9e75fc22554b86b31cbef
5
5
  SHA512:
6
- metadata.gz: 272ea64f1a285ebcef28edb4bc2092f1c8ac78bf9ea36e086f1555ba47a454cb09b8c698e06d5ed0aa76abab1fb7946535bae139e9d444663de8185483bba7f4
7
- data.tar.gz: e6fa9a29aa2b6a7c096007489a0b0e07d0658f6c79ef836a4cbd4d2fc1300330ef19b97bb6ea62e5d7cac9e00f5a2fca32ee745b167cc8f0d826cacd98a13b1c
6
+ metadata.gz: c9d211b7f70cbf38c2ad231343a1d5b73c14767d89468a1e99bf418209c03db079edf5ea116ef78c211f4e35795607ea7a9911acf48bffc3913ed53a0adcbc7a
7
+ data.tar.gz: b7a66a93ad9d478a215c0c3d6348c9e934ce6dc34b04716d8f2d61a908dd62dd2fa4a4bc42fd4804bd53e0a6c5e4413dc2ea6495b3d2c87417e46d435cb82da9
@@ -1,5 +1,19 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.4
4
+
5
+ - `list` custom widget (since listbox is not tile themed yet in Tk)
6
+ - `girb` (Glimmer IRB)
7
+ - Hello, List Single Selection! sample
8
+ - Hello, List Multi Selection! sample
9
+
10
+ ## 0.0.3
11
+
12
+ - Combobox support
13
+ - Button command event observer support
14
+ - Combobox text data-binding
15
+ - Hello, Combo! sample
16
+
3
17
  ## 0.0.2
4
18
 
5
19
  - Notebook/frame support
data/README.md CHANGED
@@ -1,9 +1,11 @@
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.3 (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.4 (Desktop GUI)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-tk.svg)](http://badge.fury.io/rb/glimmer-dsl-tk)
3
+ [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer-dsl-tk.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer-dsl-tk)
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)
3
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/ce2853efdbecf6ebdc73/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer-dsl-tk/maintainability)
4
6
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5
7
 
6
- [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [Tk](https://www.tcl.tk/) enables desktop development with [Glimmer](https://github.com/AndyObtiva/glimmer).
8
+ [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [Tk](https://www.tcl.tk/) enables desktop development with [Glimmer](https://github.com/AndyObtiva/glimmer) in [Ruby](https://github.com/ruby/ruby).
7
9
 
8
10
  [Tcl/Tk](https://www.tcl.tk/) has evolved into a practical desktop GUI toolkit due to gaining true native widgets on Mac, Windows, and Linux in [Tk version 8.5](https://www.tcl.tk/software/tcltk/8.5.html#:~:text=Highlights%20of%20Tk%208.5&text=Font%20rendering%3A%20Now%20uses%20anti,and%20window%20layout%2C%20and%20more.).
9
11
 
@@ -42,6 +44,8 @@ Glimmer app:
42
44
 
43
45
  ![glimmer dsl tk screenshot sample hello world](images/glimmer-dsl-tk-screenshot-sample-hello-world.png)
44
46
 
47
+ NOTE: Glimmer DSL for Tk is in alpha mode. Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is by no means perfect, so the more feedback and issues you report the better.
48
+
45
49
  Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
46
50
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop GUI)
47
51
  - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
@@ -66,8 +70,6 @@ Afterwards, if you open `irb`, you should be able to run `require 'tk'` successf
66
70
 
67
71
  Run this command to install directly:
68
72
  ```
69
- gem install logging
70
- gem install super_module
71
73
  gem install glimmer-dsl-tk
72
74
  ```
73
75
 
@@ -75,9 +77,7 @@ gem install glimmer-dsl-tk
75
77
 
76
78
  Add the following to `Gemfile`:
77
79
  ```
78
- gem 'logging'
79
- gem 'super_module'
80
- gem 'glimmer-dsl-tk', '~> 0.0.3'
80
+ gem 'glimmer-dsl-tk', '~> 0.0.4'
81
81
  ```
82
82
 
83
83
  And, then run:
@@ -85,6 +85,16 @@ And, then run:
85
85
  bundle
86
86
  ```
87
87
 
88
+ ## Girb (Glimmer IRB)
89
+
90
+ You can run the `girb` command (`bin/girb` if you cloned the project locally):
91
+
92
+ ```
93
+ girb
94
+ ```
95
+
96
+ This gives you `irb` with the `glimmer-dsl-tk` gem loaded and the `Glimmer` module mixed into the main object for easy experimentation with GUI.
97
+
88
98
  ## Tk Concepts
89
99
 
90
100
  Here is a summary taken from the official [Tk Concepts Tutorial](https://tkdocs.com/tutorial/concepts.html)
@@ -153,10 +163,12 @@ root {
153
163
  }.open
154
164
  ```
155
165
 
156
- ### Bidirectional Data-Binding
166
+ ## Bidirectional Data-Binding
157
167
 
158
168
  Glimmer supports bidirectional data-binding via the `bind` keyword, which takes a model and an attribute.
159
169
 
170
+ ### Combo Data-Binding
171
+
160
172
  Example:
161
173
 
162
174
  This assumes a `Person` model with a `country` attribute representing their current country and a `country_options` attribute representing available options for the country attribute.
@@ -168,20 +180,64 @@ This assumes a `Person` model with a `country` attribute representing their curr
168
180
  }
169
181
  ```
170
182
 
183
+ It binds the `values` of the `combobox` to the `country_options` property on the `person` model (data-binding attribute + "_options" by convention).
171
184
  That binds the `text` selection of the `combobox` to the `country` property on the `person` model.
172
185
 
173
186
  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").
174
187
 
175
188
  More details can be found in the [Hello, Combo!](#hello-combo) sample below.
176
189
 
177
- ### Command
190
+ ### List Single Selection Data-Binding
191
+
192
+ Tk does not support a native themed listbox, so Glimmer implements its own `list` widget on top of `Tk::Tile::Treeview`. It is set to single selection via selectmode 'browse'.
193
+
194
+ Example:
195
+
196
+ This assumes a `Person` model with a `country` attribute representing their current country and a `country_options` attribute representing available options for the country attribute.
197
+
198
+ ```ruby
199
+ list {
200
+ selectmode 'browse'
201
+ text bind(person, :country)
202
+ }
203
+ ```
204
+
205
+ It binds the `items` text of the `list` to the `country_options` property on the `person` model (data-binding attribute + "_options" by convention).
206
+ It also binds the `selection` text of the `list` to the `country` property on the `person` model.
207
+
208
+ It automatically handles all the Tk plumbing behind the scenes.
209
+
210
+ More details can be found in the [Hello, List Single Selection!](#hello-list-single-selection) sample below.
211
+
212
+ ### List Multi Selection Data-Binding
213
+
214
+ Tk does not support a native themed listbox, so Glimmer implements its own `list` widget on top of `Tk::Tile::Treeview`. It is set to multi selection by default.
215
+
216
+ Example:
217
+
218
+ This assumes a `Person` model with a `provinces` attribute representing their current country and a `provinces_options` attribute representing available options for the provinces attribute.
219
+
220
+ ```ruby
221
+ list {
222
+ text bind(person, :provinces)
223
+ }
224
+ ```
225
+
226
+ It binds the `items` text of the `list` to the `provinces_options` property on the `person` model (data-binding attribute + "_options" by convention)
227
+ That binds the `selection` text of the `list` to the `provinces` property on the `person` model.
228
+
229
+ It automatically handles all the Tk plumbing behind the scenes.
230
+
231
+ More details can be found in the [Hello, List Multi Selection!](#hello-list-multi-selection) sample below.
232
+
233
+ ## Command Observer
178
234
 
179
235
  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)
180
236
 
181
237
  Example:
182
238
 
183
239
  ```ruby
184
- button { |proxy|
240
+ button {
185
241
  text "Reset Selection"
186
242
  command {
187
243
  person.reset_country
@@ -291,6 +347,71 @@ Glimmer app:
291
347
  ![glimmer dsl tk screenshot sample hello combo](images/glimmer-dsl-tk-screenshot-sample-hello-combo.png)
292
348
  ![glimmer dsl tk screenshot sample hello combo dropdown](images/glimmer-dsl-tk-screenshot-sample-hello-combo-dropdown.png)
293
349
 
350
+ ### Hello, List Single Selection!
351
+
352
+ Glimmer code (from [samples/hello/hello_list_single_selection.rb](samples/hello/hello_list_single_selection.rb)):
353
+
354
+ ```ruby
355
+ # ... more code precedes
356
+ root {
357
+ title 'Hello, List Single Selection!'
358
+
359
+ list {
360
+ selectmode 'browse'
361
+ selection bind(person, :country)
362
+ }
363
+
364
+ button {
365
+ text "Reset Selection To Default Value"
366
+
367
+ command { person.reset_country }
368
+ }
369
+ }.open
370
+ # ... more code follows
371
+ ```
372
+
373
+ Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
374
+
375
+ ```
376
+ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_list_single_selection.rb'"
377
+ ```
378
+
379
+ Glimmer app:
380
+
381
+ ![glimmer dsl tk screenshot sample hello list single selection](images/glimmer-dsl-tk-screenshot-sample-hello-list-single-selection.png)
382
+
383
+ ### Hello, List Multi Selection!
384
+
385
+ Glimmer code (from [samples/hello/hello_list_multi_selection.rb](samples/hello/hello_list_multi_selection.rb)):
386
+
387
+ ```ruby
388
+ # ... more code precedes
389
+ root {
390
+ title 'Hello, List Multi Selection!'
391
+
392
+ list {
393
+ selection bind(person, :provinces)
394
+ }
395
+
396
+ button {
397
+ text "Reset Selection To Defaults"
398
+
399
+ command { person.reset_provinces }
400
+ }
401
+ }.open
402
+ # ... more code follows
403
+ ```
404
+
405
+ Run (with the [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed):
406
+
407
+ ```
408
+ ruby -r glimmer-dsl-tk -e "require '../samples/hello/hello_list_multi_selection.rb'"
409
+ ```
410
+
411
+ Glimmer app:
412
+
413
+ ![glimmer dsl tk screenshot sample hello list multi selection](images/glimmer-dsl-tk-screenshot-sample-hello-list-multi-selection.png)
414
+
294
415
  ## Help
295
416
 
296
417
  ### Issues
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+
3
+ GIRB_RUNNER="$(realpath $(dirname $0))/girb_runner.rb"
4
+
5
+ irb $@ -r $GIRB_RUNNER
6
+
7
+ if !(test -f ~/.girb_runner_exit); then
8
+ rm -rf ~/.girb_runner_exit
9
+ exec $0
10
+ fi
@@ -0,0 +1,26 @@
1
+ require 'puts_debuggerer'
2
+ require 'fileutils'
3
+ require 'etc'
4
+
5
+ require_relative '../lib/glimmer-dsl-tk'
6
+
7
+ include Glimmer
8
+
9
+ GIRB_RUNNER_EXIT_FILE = "#{Etc.getpwuid.dir}/.girb_runner_exit"
10
+ FileUtils.rm_rf GIRB_RUNNER_EXIT_FILE
11
+
12
+ @exit_method = method(:exit)
13
+
14
+ @exit_girb_block = lambda do
15
+ FileUtils.touch GIRB_RUNNER_EXIT_FILE
16
+ end
17
+
18
+ def self.exit(*args)
19
+ @exit_girb_block.call
20
+ @exit_method.call(*args)
21
+ end
22
+
23
+ def self.quit(*args)
24
+ @exit_girb_block.call
25
+ @exit_method.call(*args)
26
+ end
@@ -0,0 +1,75 @@
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/data_binding/observable'
23
+ require 'glimmer/data_binding/observer'
24
+
25
+ module Glimmer
26
+ module DataBinding
27
+ module Tk
28
+ # Tk List widget selection binding
29
+ class ListSelectionBinding
30
+ include Glimmer
31
+ include Observable
32
+ include Observer
33
+
34
+ attr_reader :widget_proxy
35
+
36
+ PROPERTY_TYPE_UPDATERS = {
37
+ :string => lambda do |widget_proxy, value|
38
+ widget_proxy.selection = value.to_s
39
+ end,
40
+ :array => lambda do |widget_proxy, value|
41
+ widget_proxy.selection = (value || [])
42
+ end
43
+ }
44
+
45
+ PROPERTY_EVALUATORS = {
46
+ :string => lambda do |selection_array|
47
+ return nil if selection_array.empty?
48
+ selection_array.map(&:text)[0]
49
+ end,
50
+ :array => lambda do |selection_array|
51
+ selection_array.map(&:text)
52
+ end
53
+ }
54
+
55
+ # Initialize with list widget and property_type
56
+ # property_type :string represents default list single selection
57
+ # property_type :array represents list multi selection
58
+ def initialize(widget_proxy)
59
+ property_type = widget_proxy.selectmode == 'browse' ? :string : :array
60
+ @widget_proxy = widget_proxy
61
+ @property_type = property_type
62
+ end
63
+
64
+ def call(value)
65
+ PROPERTY_TYPE_UPDATERS[@property_type].call(@widget_proxy, value) unless evaluate_property == value
66
+ end
67
+
68
+ def evaluate_property
69
+ selection_array = @widget_proxy.tk.selection.to_a
70
+ PROPERTY_EVALUATORS[@property_type].call(selection_array)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -17,14 +17,15 @@ module Glimmer
17
17
  end
18
18
 
19
19
  def interpret(parent, keyword, *args, &block)
20
+ parent.class
20
21
  model_binding = args[0]
21
22
  widget_binding_parameters = [parent, keyword]
22
23
  widget_binding = DataBinding::Tk::WidgetBinding.new(*widget_binding_parameters)
23
- widget_binding.call(model_binding.evaluate_property)
24
24
  #TODO make this options observer dependent and all similar observers in widget specific data binding handlers
25
25
  widget_binding.observe(model_binding)
26
26
  # TODO simplify this logic and put it where it belongs
27
27
  parent.add_observer(model_binding, keyword) if parent.respond_to?(:add_observer, [model_binding, keyword])
28
+ widget_binding.call(model_binding.evaluate_property)
28
29
  end
29
30
  end
30
31
  end
@@ -36,6 +36,7 @@ module Glimmer
36
36
  Engine.add_dynamic_expressions(
37
37
  Tk,
38
38
  %w[
39
+ list_selection_data_binding
39
40
  data_binding
40
41
  block_attribute
41
42
  attribute
@@ -0,0 +1,60 @@
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/dsl/expression'
23
+ require 'glimmer/data_binding/model_binding'
24
+ require 'glimmer/data_binding/tk/widget_binding'
25
+ require 'glimmer/data_binding/tk/list_selection_binding'
26
+
27
+ module Glimmer
28
+ module DSL
29
+ module Tk
30
+ class ListSelectionDataBindingExpression < Expression
31
+ def can_interpret?(parent, keyword, *args, &block)
32
+ keyword == 'selection' and
33
+ block.nil? and
34
+ parent.is_a?(Glimmer::Tk::ListProxy) and
35
+ args.size == 1 and
36
+ args[0].is_a?(DataBinding::ModelBinding) and
37
+ args[0].evaluate_options_property.is_a?(Array)
38
+ end
39
+
40
+ def interpret(parent, keyword, *args, &block)
41
+ model_binding = args[0]
42
+ widget_binding = DataBinding::Tk::WidgetBinding.new(parent, 'items')
43
+ widget_binding.call(model_binding.evaluate_options_property)
44
+ model = model_binding.base_model
45
+ #TODO make this options observer dependent and all similar observers in widget specific data binding interpretrs
46
+ widget_binding.observe(model, model_binding.options_property_name)
47
+
48
+ list_selection_binding = DataBinding::Tk::ListSelectionBinding.new(parent)
49
+ list_selection_binding.call(model_binding.evaluate_property)
50
+ #TODO check if nested data binding works for list widget and other widgets that need custom data binding
51
+ list_selection_binding.observe(model, model_binding.property_name_expression)
52
+
53
+ parent.tk.bind('<TreeviewSelect>') do
54
+ model_binding.call(list_selection_binding.evaluate_property)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -55,3 +55,4 @@ 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/list_proxy'
@@ -0,0 +1,60 @@
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
+ # Custom list widget implementation
27
+ class ListProxy < WidgetProxy
28
+ def initialize(underscored_widget_name, parent_proxy, args)
29
+ super('treeview', parent_proxy, args)
30
+ @tk.show = 'tree'
31
+ end
32
+
33
+ def widget_custom_attribute_mapping
34
+ @widget_custom_attribute_mapping ||= {
35
+ ::Tk::Tile::Treeview => {
36
+ 'items' => {
37
+ getter: {name: 'items', invoker: lambda { |widget, args| tk.children('').map(&:text) }},
38
+ setter: {name: 'items=', invoker: lambda { |widget, args|
39
+ @tk.delete @tk.children('')
40
+ args.first.each do |child|
41
+ @tk.insert('', 'end', :text => child)
42
+ end
43
+ }},
44
+ },
45
+ 'selection' => {
46
+ getter: {name: 'selection', invoker: lambda { |widget, args| @tk.selection.map(&:text) }},
47
+ setter: {name: 'selection=', invoker: lambda { |widget, args|
48
+ selection_args = args.first.is_a?(Array) ? args.first : [args.first]
49
+ selection_items = selection_args.map do |arg|
50
+ @tk.children('').detect {|item| item.text == arg}
51
+ end
52
+ @tk.selection_set(*selection_items)
53
+ }},
54
+ },
55
+ },
56
+ }
57
+ end
58
+ end
59
+ end
60
+ end
@@ -45,7 +45,28 @@ module Glimmer
45
45
  rescue
46
46
  Glimmer::Tk::WidgetProxy
47
47
  end
48
- end
48
+ end
49
+
50
+ # This supports widgets in and out of basic Tk
51
+ def tk_widget_class_for(underscored_widget_name)
52
+ tk_widget_class_basename = underscored_widget_name.camelcase(:upper)
53
+ potential_tk_widget_class_names = [
54
+ "::Tk::Tile::#{tk_widget_class_basename}",
55
+ "::Tk::#{tk_widget_class_basename}",
56
+ "::Tk#{tk_widget_class_basename}",
57
+ "::Glimmer::Tk::#{tk_widget_class_basename}Proxy",
58
+ ]
59
+ tk_widget_class = nil
60
+ potential_tk_widget_class_names.each do |tk_widget_name|
61
+ begin
62
+ tk_widget_class = eval(tk_widget_name)
63
+ break
64
+ rescue RuntimeError, SyntaxError, NameError => e
65
+ Glimmer::Config.logger.debug e.full_message
66
+ end
67
+ end
68
+ tk_widget_class
69
+ end
49
70
  end
50
71
 
51
72
  # Initializes a new Tk Widget
@@ -56,13 +77,8 @@ module Glimmer
56
77
  @args = args
57
78
  tk_widget_class = self.class.tk_widget_class_for(underscored_widget_name)
58
79
  @tk = tk_widget_class.new(@parent_proxy.tk, *args)
59
- begin
60
- # a common widget initializer
61
- @tk.grid
62
- rescue => e
63
- # catching error just in case a widget doesn't support it
64
- Glimmer::Config.logger.debug e.full_message
65
- end
80
+ # a common widget initializer
81
+ @tk.grid
66
82
  DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@tk)
67
83
  @parent_proxy.post_initialize_child(self)
68
84
  end
@@ -81,24 +97,11 @@ module Glimmer
81
97
  !!tk_widget_class_for(underscored_widget_name)
82
98
  end
83
99
 
84
- # This supports widgets in and out of basic Tk
85
- def self.tk_widget_class_for(underscored_widget_name)
86
- tk_widget_name = "::Tk::Tile::#{underscored_widget_name.camelcase(:upper)}"
87
- tk_widget_class = eval(tk_widget_name)
88
- tk_widget_class
89
- rescue SyntaxError, NameError => e
90
- puts e.full_message
91
- nil
92
- rescue => e
93
- puts e.full_message
94
- nil
95
- end
96
-
97
- def tk_widget_has_attribute?(attribute_name)
100
+ def tk_widget_has_attribute?(attribute)
98
101
  result = nil
99
102
  begin
100
103
  # TK Widget currently doesn't support respond_to? properly, so I have to resort to this trick for now
101
- @tk.send(attribute_setter(attribute_name), @tk.send(attribute_name))
104
+ @tk.send(attribute_setter(attribute), @tk.send(attribute))
102
105
  result = true
103
106
  rescue => e
104
107
  result = false
@@ -106,32 +109,36 @@ module Glimmer
106
109
  result
107
110
  end
108
111
 
109
- def has_attribute?(attribute_name, *args)
110
- tk_widget_has_attribute?(attribute_name) || respond_to?(attribute_setter(attribute_name), args)
112
+ def has_attribute?(attribute, *args)
113
+ (widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]) ||
114
+ tk_widget_has_attribute?(attribute) ||
115
+ respond_to?(attribute_setter(attribute), args)
111
116
  end
112
117
 
113
- def set_attribute(attribute_name, *args)
114
- widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute_name.to_s]
118
+ def set_attribute(attribute, *args)
119
+ widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
115
120
  if widget_custom_attribute
116
121
  widget_custom_attribute[:setter][:invoker].call(@tk, args)
117
- elsif tk_widget_has_attribute?(attribute_name)
118
- @tk.send(attribute_setter(attribute_name), *args) unless @tk.send(attribute_name) == args.first
122
+ elsif tk_widget_has_attribute?(attribute)
123
+ @tk.send(attribute_setter(attribute), *args) unless @tk.send(attribute) == args.first
119
124
  else
120
- send(attribute_setter(attribute_name), args)
125
+ send(attribute_setter(attribute), args)
121
126
  end
122
127
  end
123
128
 
124
- def get_attribute(attribute_name)
125
- widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute_name.to_s]
129
+ def get_attribute(attribute)
130
+ widget_custom_attribute = widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][attribute.to_s]
126
131
  if widget_custom_attribute
127
132
  widget_custom_attribute[:getter][:invoker].call(@tk, args)
133
+ elsif tk_widget_has_attribute?(attribute)
134
+ @tk.send(attribute)
128
135
  else
129
- @tk.send(attribute_name)
136
+ send(attribute)
130
137
  end
131
- end
138
+ end
132
139
 
133
- def attribute_setter(attribute_name)
134
- "#{attribute_name}="
140
+ def attribute_setter(attribute)
141
+ "#{attribute}="
135
142
  end
136
143
 
137
144
  def widget_custom_attribute_mapping
@@ -145,10 +152,10 @@ module Glimmer
145
152
  }
146
153
  end
147
154
 
148
- def widget_property_listener_installers
149
- @tk_widget_property_listener_installers ||= {
155
+ def widget_attribute_listener_installers
156
+ @tk_widget_attribute_listener_installers ||= {
150
157
  ::Tk::Tile::TCombobox => {
151
- :text => lambda do |observer|
158
+ 'text' => lambda do |observer|
152
159
  if observer.is_a?(Glimmer::DataBinding::ModelBinding)
153
160
  model = observer.model
154
161
  options_model_property = observer.property_name + '_options'
@@ -158,13 +165,13 @@ module Glimmer
158
165
  observer.call(@tk.textvariable.value)
159
166
  }
160
167
  end,
161
- }
168
+ },
162
169
  }
163
170
  end
164
171
 
165
- def add_observer(observer, property_name)
166
- property_listener_installers = @tk.class.ancestors.map {|ancestor| widget_property_listener_installers[ancestor]}.compact
167
- widget_listener_installers = property_listener_installers.map{|installer| installer[property_name.to_s.to_sym]}.compact if !property_listener_installers.empty?
172
+ def add_observer(observer, attribute)
173
+ attribute_listener_installers = @tk.class.ancestors.map {|ancestor| widget_attribute_listener_installers[ancestor]}.compact
174
+ widget_listener_installers = attribute_listener_installers.map{|installer| installer[attribute.to_s]}.compact if !attribute_listener_installers.empty?
168
175
  widget_listener_installers.to_a.first&.call(observer)
169
176
  end
170
177
 
@@ -173,10 +180,17 @@ module Glimmer
173
180
  end
174
181
 
175
182
  def method_missing(method, *args, &block)
176
- tk.send(method, *args, &block)
183
+ method = method.to_s
184
+ if args.empty? && block.nil? && widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][method]
185
+ get_attribute(method)
186
+ elsif widget_custom_attribute_mapping[tk.class] && widget_custom_attribute_mapping[tk.class][method.sub(/=$/, '')] && method.end_with?('=') && block.nil?
187
+ set_attribute(method.sub(/=$/, ''), *args)
188
+ else
189
+ tk.send(method, *args, &block)
190
+ end
177
191
  rescue => e
178
192
  Glimmer::Config.logger.debug {"Neither WidgetProxy nor #{tk.class.name} can handle the method ##{method}"}
179
- super
193
+ super(method.to_sym, *args, &block)
180
194
  end
181
195
 
182
196
  def respond_to?(method, *args, &block)
@@ -1,3 +1,24 @@
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
+
1
22
  require 'glimmer-dsl-tk'
2
23
 
3
24
  class Person
@@ -0,0 +1,69 @@
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-dsl-tk'
23
+
24
+ class Person
25
+ attr_accessor :provinces, :provinces_options
26
+
27
+ def initialize
28
+ self.provinces_options=[
29
+ "",
30
+ "Quebec",
31
+ "Ontario",
32
+ "Manitoba",
33
+ "Saskatchewan",
34
+ "Alberta",
35
+ "British Columbia",
36
+ "Nova Skotia",
37
+ "Newfoundland"
38
+ ]
39
+ self.provinces = ["Quebec", "Manitoba", "Alberta"]
40
+ end
41
+
42
+ def reset_provinces
43
+ self.provinces = ["Quebec", "Manitoba", "Alberta"]
44
+ end
45
+ end
46
+
47
+ class HelloListMultiSelection
48
+ include Glimmer
49
+
50
+ def launch
51
+ person = Person.new
52
+
53
+ root {
54
+ title 'Hello, List Multi Selection!'
55
+
56
+ list {
57
+ selection bind(person, :provinces)
58
+ }
59
+
60
+ button {
61
+ text "Reset Selection To Defaults"
62
+
63
+ command { person.reset_provinces }
64
+ }
65
+ }.open
66
+ end
67
+ end
68
+
69
+ HelloListMultiSelection.new.launch
@@ -0,0 +1,60 @@
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-dsl-tk'
23
+
24
+ class Person
25
+ attr_accessor :country, :country_options
26
+
27
+ def initialize
28
+ self.country_options=["", "Canada", "US", "Mexico"]
29
+ self.country = "Canada"
30
+ end
31
+
32
+ def reset_country
33
+ self.country = "Canada"
34
+ end
35
+ end
36
+
37
+ class HelloListSingleSelection
38
+ include Glimmer
39
+
40
+ def launch
41
+ person = Person.new
42
+
43
+ root {
44
+ title 'Hello, List Single Selection!'
45
+
46
+ list {
47
+ selectmode 'browse'
48
+ selection bind(person, :country)
49
+ }
50
+
51
+ button {
52
+ text "Reset Selection To Default Value"
53
+
54
+ command { person.reset_country }
55
+ }
56
+ }.open
57
+ end
58
+ end
59
+
60
+ HelloListSingleSelection.new.launch
@@ -1,3 +1,24 @@
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
+
1
22
  require 'glimmer-dsl-tk'
2
23
 
3
24
  class HelloTab
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.3
4
+ version: 0.0.4
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-12 00:00:00.000000000 Z
11
+ date: 2020-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -172,7 +172,8 @@ dependencies:
172
172
  version: 0.7.0
173
173
  description: Glimmer DSL for Tk (Ruby Desktop GUI)
174
174
  email: andy.am@gmail.com
175
- executables: []
175
+ executables:
176
+ - girb
176
177
  extensions: []
177
178
  extra_rdoc_files:
178
179
  - CHANGELOG.md
@@ -183,21 +184,28 @@ files:
183
184
  - LICENSE.txt
184
185
  - README.md
185
186
  - VERSION
187
+ - bin/girb
188
+ - bin/girb_runner.rb
186
189
  - lib/glimmer-dsl-tk.rb
190
+ - lib/glimmer/data_binding/tk/list_selection_binding.rb
187
191
  - lib/glimmer/data_binding/tk/widget_binding.rb
188
192
  - lib/glimmer/dsl/tk/attribute_expression.rb
189
193
  - lib/glimmer/dsl/tk/bind_expression.rb
190
194
  - lib/glimmer/dsl/tk/block_attribute_expression.rb
191
195
  - lib/glimmer/dsl/tk/data_binding_expression.rb
192
196
  - lib/glimmer/dsl/tk/dsl.rb
197
+ - lib/glimmer/dsl/tk/list_selection_data_binding_expression.rb
193
198
  - lib/glimmer/dsl/tk/root_expression.rb
194
199
  - lib/glimmer/dsl/tk/widget_expression.rb
195
200
  - lib/glimmer/tk/button_proxy.rb
196
201
  - lib/glimmer/tk/frame_proxy.rb
202
+ - lib/glimmer/tk/list_proxy.rb
197
203
  - lib/glimmer/tk/notebook_proxy.rb
198
204
  - lib/glimmer/tk/root_proxy.rb
199
205
  - lib/glimmer/tk/widget_proxy.rb
200
206
  - samples/hello/hello_combo.rb
207
+ - samples/hello/hello_list_multi_selection.rb
208
+ - samples/hello/hello_list_single_selection.rb
201
209
  - samples/hello/hello_tab.rb
202
210
  - samples/hello/hello_world.rb
203
211
  homepage: http://github.com/AndyObtiva/glimmer-dsl-tk