glimmer-dsl-tk 0.0.30 → 0.0.34

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: 9c90a3de5c636e2d9fcce122eaa07691e49842721d356a6266e75ff3f77b15ed
4
- data.tar.gz: 82927885f588122a63c984c6acbd13110bc93197a075e8d3ef522bce98162ac9
3
+ metadata.gz: 69e1f06607f60b2864e78e6e1eb9bfde7cf98f8d8eca2d14f12bf218d781dcb3
4
+ data.tar.gz: 7c552bb85c6b87eeefe8117b5f3d2df922ff27618f564e6dd37df63b57c17d98
5
5
  SHA512:
6
- metadata.gz: ba0ba8c92a2294998b6b43ac7397a9f27d499becc7603d8e51823aac0a4f442152208ae316829c019ed5bdb3ee763c8165a7309c3789c3009328a64851aabb27
7
- data.tar.gz: b0a1bfe8894b410bbcf5781721fb3a044d0534b5f31260a128f9232db89d331ea7ec1843d288abc1ab16f17f046f3f869739d14c11bf74aa30bb7dbc59f9c551
6
+ metadata.gz: a6dad9353a12a78f0e8c4a2be45e440c2bebb3e0998957447332d0ab65ec3668eb447395cb32bb8bfa4c6feed3bee991d78b07dbe500c3716e914ed0e51b312c
7
+ data.tar.gz: 36bfc6aa1b337b33b6c6a658549b603658677ea0e4e1840ec1ef58727bb12c76031d08b22fd50960001c2881819e7ec1a7e672f1c29e57d63797d0ea106531f0
data/CHANGELOG.md CHANGED
@@ -1,10 +1,40 @@
1
1
  # Change Log
2
2
 
3
- ## 0.0.30
3
+ ## 0.0.34
4
+
5
+ - When applying a `text` selection format without having a selection, have it apply to current insert mark word
6
+ - Support registering multiple general event listeners on `text` widget (previously, later event listener registrations replaced former ones)
7
+ - Implement `:no_selection_default` option of `:insert_word`, `insert_letter`, or `none` for `text` selection formatting methods (`add_selection_format`, `remove_selection_format`, `toggle_selection_format`, `add_selection_font_format`, `remove_selection_font_format`, `toggle_selection_font_format`)
8
+ - Make sure to only allow `text` undo/redo when there are changes to be undoed/redoed
9
+ - Fix issue with Hello, Text! Find Dialog not coming up with keyboard shortcut (e.g. CMD+F) anymore
10
+ - Fix issue with Hello, Text! whereby after applying background, and foreground to a selection, you cannot apply bold, italic, or underline for the same selection (or font-size or font-family)
11
+
12
+ ## 0.0.33
13
+
14
+ - Support `text` widget `InsertMarkMoved` listener event to track insert mark movement (or aliases `InsertMarkMove`, `insert_mark_move`, `insert_mark_moved`, all case-insensitive)
15
+ - Support `entry` widget `changed` and `modified` listener event aliases for `change` event
16
+ - Autodiscover format options when moving cursor in `text` widget (auto-derive from applied tags and widget font) and show in top Hello, Text! toolbar comboboxes and buttons
17
+ - Fix issue with encountering error 'NoMethodError: undefined method "size" for' when launching Hello, Text!, performing Select-All (CMD+A or CONTROL+A) and then attempting to Bold all the text.
18
+ - Fix issue in Hello, Text! whereby bolding a small region of text affects the font of the following region of text till the end of the document
19
+ - Fix issue in Hello, Text! where if all text is copied and then pasted multiple times, the `text` widget loses its keyboard/mouse listeners and CMD+F does not work anymore to bring Find dialog
20
+
21
+ ## 0.0.32
22
+
23
+ - Hello, Text! Find Dialog toolbar button
24
+ - Hello, Text! Find Dialog Windows/Linux CONTROL+F shortcut alternative to Mac CMD+F
25
+
26
+ ## 0.0.31
4
27
 
5
28
  - Improve Hello, Text! (toolbar buttons: justify left, justify center, justify right)
6
- - Fixed Hello, Built-in Dialog! Font Dialog issue
29
+ - `on('destroy') {|widget| ...}` support in widgets to better track calls to "destroy" method and `'<Destroy>'` binding event (as opposed to the unreliable tracking of '<Destroy>' alone)
30
+ - Support observing `text` general events (e.g. `'<KeyPress>'`) through `on(event) {}` (was not working before because it required applying a tag, a general `__all__` tag is applied automatically now on full range (`1.0` to `end`))
31
+ - Ensure unregistering observers (like data-binding observers) when destroying a widget
32
+ - Add `Glimmer::Tk::ToplevelProxy` widget proxy support similar to `Glimmer::Tk::RootProxy`
7
33
 
34
+ ## 0.0.30
35
+
36
+ - Improve Hello, Text! (toolbar buttons: find dialog)
37
+ - Fixed Hello, Built-in Dialog! Font Dialog issue
8
38
  ## 0.0.29
9
39
 
10
40
  - Hello, Built-in Dialog! (demonstrating all built-in dialogs like get_open_file and choose_color)
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.30
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.34
2
2
  ## MRI Ruby 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)
@@ -120,8 +120,9 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
120
120
  - [Applications](#applications)
121
121
  - [Glimmer Tk Calculator](#glimmer-tk-calculator)
122
122
  - [Y3network Ruby UI](#y3network-ruby-ui)
123
- - [Cryptopunks GUI](#cryptopunks-gui)
123
+ - [CryptoPunks GUI](#cryptopunks-gui)
124
124
  - [Process](#process)
125
+ - [Resources](#resources)
125
126
  - [Help](#help)
126
127
  - [Issues](#issues)
127
128
  - [Chat](#chat)
@@ -157,7 +158,7 @@ gem install glimmer-dsl-tk
157
158
 
158
159
  Add the following to `Gemfile`:
159
160
  ```
160
- gem 'glimmer-dsl-tk', '~> 0.0.30'
161
+ gem 'glimmer-dsl-tk', '~> 0.0.34'
161
162
  ```
162
163
 
163
164
  And, then run:
@@ -199,7 +200,7 @@ The Glimmer GUI DSL follows these simple concepts in mapping from Tk syntax:
199
200
  - **Widget Keyword**: Any Tk widget (e.g. `Tk::Tile::Label`) or toplevel window (e.g. `TkRoot`) may be declared by its lower-case underscored name without the namespace (e.g. `label` or `root`). This is called a keyword and is represented in the Glimmer GUI DSL by a Ruby method behind the scenes.
200
201
  - **Args**: Any keyword method may optionally take arguments surrounded by parentheses (e.g. a `frame` nested under a `notebook` may receive tab options like `frame(text: 'Users')`, which gets used behind the scenes by Tk code such as `notebook.add tab, text: 'Users'`)
201
202
  - **Content/Options Block**: Any keyword may optionally be followed by a Ruby curly-brace block containing nested widgets (content) and attributes (options). Attributes are simply Tk option keywords followed by arguments and no block (e.g. `title 'Hello, World!'` under a `root`)
202
- - **Event Binding Block**: `on(event) {}` keyword receiving a Tk binding event name (e.g. `KeyPress` or `ComboboxSelected`). No need to surround event by `<>` as [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) takes care of that automatically.
203
+ - **Event Binding Block**: `on(event) {}` keyword receiving a Tk binding event name (e.g. `KeyPress` or `ComboboxSelected`). Surrounding event by `<>` is optional as [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) can take care of that automatically.
203
204
 
204
205
  Example of an app written in [Tk](https://www.tcl.tk/) imperative syntax:
205
206
 
@@ -272,7 +273,7 @@ keyword(args) | attributes | event bindings & callbacks
272
273
  `choose_directory(options = nil)` | None | None
273
274
  `choose_font(options = nil) {|font| ... }` | None | None
274
275
  `combobox` | `state`, `text` | `'ComboboxSelected'`
275
- `entry` | `width`, `text`, `validate`, `show` (`'none', 'focus', 'focusin', 'focusout', 'key', or 'all'`) | `'validate'`, `'invalid'`, `'change'`, `validatecommand {}`, `invalidcommand {}`
276
+ `entry` | `width`, `text`, `validate`, `show` (`'none', 'focus', 'focusin', 'focusout', 'key', or 'all'`) | `'validate'`, `'invalid'`, `'change'` (alias: `'changed'`), `validatecommand {}`, `invalidcommand {}`
276
277
  `get_multiple_open_file(options = nil)` | None | None
277
278
  `get_open_file(options = nil)` | None | None
278
279
  `get_save_file(options = nil)` | None | None
@@ -285,7 +286,7 @@ keyword(args) | attributes | event bindings & callbacks
285
286
  `radiobutton` | `text`, `variable` (Boolean), `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `value` (default: `text`) | `command {}`
286
287
  `root` | `title`, `iconphoto`, `background`, `alpha`, `fullscreen?`, `topmost?`, `transparent?`, `stackorder`, `winfo_screendepth`, `winfo_screenvisual`, `winfo_screenwidth`, `winfo_screenheight`, `winfo_pixels('li')`, `winfo_screen`, `wm_maxsize`, `state` (`'normal', 'iconic', 'withdrawn', 'icon', 'zoomed'`) | `'DELETE_WINDOW'`, `'OPEN_WINDOW'`
287
288
  `separator` | `orient` (`'horizontal' (default) or 'vertical'`) | None
288
- `text` | `value`, [many more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `'modified'`, `'selection'`
289
+ `text` | `value`, [many more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `'modified'`, `'selection'`, `'insert_mark_moved'` (alias: `'insert_mark_move', 'InsertMarkMove', 'InsertMarkMoved'`)
289
290
 
290
291
  Options for `get_open_file` and `get_multiple_open_file` include:
291
292
  - `filetypes`: `Hash` of `'Group Name' => '.ext'` entries (e.g. `filetypes: {'PNG Images' => '.png'}`
@@ -348,15 +349,20 @@ The `text` widget is enhanced by [Glimmer DSL for Tk](https://rubygems.org/gems/
348
349
  - `add_font_format(region_start, region_end, font_option, value)`
349
350
  - `remove_font_format(region_start, region_end, font_option, value)`
350
351
  - `toggle_font_format(region_start, region_end, font_option, value)`
351
- - `add_selection_format(region_start, region_end, option, value)`
352
- - `remove_selection_format(region_start, region_end, option, value)`
353
- - `toggle_selection_format(region_start, region_end, option, value)`
354
- - `add_selection_font_format(region_start, region_end, font_option, value)`
355
- - `remove_selection_font_format(region_start, region_end, font_option, value)`
356
- - `toggle_selection_font_format(region_start, region_end, font_option, value)`
352
+ - `add_selection_format(option, value, no_selection_default: :insert_word)`: adds format to selection. If there is no selection, then applies format to current insert mark word.
353
+ - `remove_selection_format(option, value, no_selection_default: :insert_word)`
354
+ - `toggle_selection_format(option, value, no_selection_default: :insert_word)`: toggles format on selection. If there is no selection, then toggles format on current insert mark word.
355
+ - `add_selection_font_format(font_option, value, no_selection_default: :insert_word)`
356
+ - `remove_selection_font_format(font_option, value, no_selection_default: :insert_word)`
357
+ - `toggle_selection_font_format(font_option, value, no_selection_default: :insert_word)`
357
358
  - `text#insert_image(text_index, *image_args)`: inserts image into `text` `value` content at `text_index` location (e.g. `'insert'`)
358
359
  - `text#get_open_file_to_insert_image(text_index = 'insert')`: opens a file dialog to select one of the available image formats and then inserts image into `text` `value` content
359
360
 
361
+ The `:no_selection_default` keyword arg to `*_selection_*` methods determines what region to cover when no explicit selection is set:
362
+ - `:insert_word`: current word for insert mark
363
+ - `:insert_letter`: current letter for insert mark
364
+ - `:none`: no behavior when no selection is in place
365
+
360
366
  Available options:
361
367
 
362
368
  - `background`
@@ -730,6 +736,7 @@ More details can be found in the [Hello, Button!](#hello-button) sample below.
730
736
  ## Gotchas
731
737
 
732
738
  - Setting `background` attribute on `frame` or `label` does not work in `'aqua'` theme on the Mac (only in `'classic'` theme)
739
+ - `text` widget does not track `KeyPress`/`KeyRelease` events perfectly (installed via `on()` listener keyword). It seems that when all text is deleted, it stops tracking key presses/releases until a number of new lines have been added to `text` `value` attribute
733
740
 
734
741
  ## Samples
735
742
 
@@ -1868,6 +1875,8 @@ Glimmer app:
1868
1875
 
1869
1876
  ### Hello, Text!
1870
1877
 
1878
+ You may press META+F to bring up the Find Dialog on the Mac and CONTROL+F to bring it up on Windows/Linux.
1879
+
1871
1880
  Icons used in this sample were made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon"> www.flaticon.com</a>
1872
1881
 
1873
1882
  Glimmer code (from [samples/hello/hello_text.rb](samples/hello/hello_text.rb)):
@@ -1918,7 +1927,7 @@ class HelloText
1918
1927
  MULTI_LINE_STRING
1919
1928
  end
1920
1929
 
1921
- attr_accessor :document
1930
+ attr_accessor :document, :find_text
1922
1931
 
1923
1932
  attr_accessor :foreground
1924
1933
 
@@ -1944,8 +1953,16 @@ class HelloText
1944
1953
  [FONT_SIZE_PROMPT] + (9..64).to_a.map(&:to_s)
1945
1954
  end
1946
1955
 
1956
+ def find
1957
+ text_index = @text.search(/#{find_text}/i, @text.tag_ranges('sel')&.first&.last || @text.index('insert'))
1958
+ unless text_index.to_s.empty?
1959
+ @text.tag_remove('sel', '1.0', 'end')
1960
+ @text.tag_add('sel', text_index, "#{text_index} + #{find_text.size} chars")
1961
+ end
1962
+ end
1963
+
1947
1964
  def launch
1948
- root {
1965
+ @root = root {
1949
1966
  title 'Hello, Text!'
1950
1967
  width 1280
1951
1968
  height 800
@@ -1953,11 +1970,6 @@ class HelloText
1953
1970
  frame {
1954
1971
  grid row: 0, column: 0
1955
1972
 
1956
- label {
1957
- grid row: 0, column: 0, columnspan: 17
1958
- text 'Select a region of text and then apply formatting from the toolbar'
1959
- }
1960
-
1961
1973
  column_index = -1
1962
1974
 
1963
1975
  combobox {
@@ -1989,7 +2001,7 @@ class HelloText
1989
2001
  orient 'vertical'
1990
2002
  }
1991
2003
 
1992
- button {
2004
+ @bold_button = button {
1993
2005
  grid row: 1, column: column_index += 1, column_weight: 0
1994
2006
  text 'B'
1995
2007
  style font: {weight: 'bold'}
@@ -1999,7 +2011,7 @@ class HelloText
1999
2011
  end
2000
2012
  }
2001
2013
 
2002
- button {
2014
+ @italic_button = button {
2003
2015
  grid row: 1, column: column_index += 1, column_weight: 0
2004
2016
  text 'I'
2005
2017
  style font: {slant: 'italic'}
@@ -2009,7 +2021,7 @@ class HelloText
2009
2021
  end
2010
2022
  }
2011
2023
 
2012
- button {
2024
+ @underline_button = button {
2013
2025
  grid row: 1, column: column_index += 1, column_weight: 0
2014
2026
  text 'U'
2015
2027
  style font: {underline: true}
@@ -2018,36 +2030,36 @@ class HelloText
2018
2030
  @text.toggle_selection_font_format('underline', true)
2019
2031
  end
2020
2032
  }
2021
-
2033
+
2022
2034
  separator {
2023
2035
  grid row: 1, column: column_index += 1, column_weight: 0
2024
2036
  orient 'vertical'
2025
2037
  }
2026
2038
 
2027
- button {
2039
+ @justify_left_button = button {
2028
2040
  grid row: 1, column: column_index += 1, column_weight: 0
2029
- image File.expand_path("images/cut.png", __dir__), subsample: 32
2041
+ image File.expand_path("images/align-left.png", __dir__), subsample: 32
2030
2042
 
2031
2043
  on('command') do
2032
- @text.text_cut
2044
+ @text.add_selection_format('justify', 'left')
2033
2045
  end
2034
2046
  }
2035
2047
 
2036
- button {
2048
+ @justify_center_button = button {
2037
2049
  grid row: 1, column: column_index += 1, column_weight: 0
2038
- image File.expand_path("images/copy.png", __dir__), subsample: 32
2050
+ image File.expand_path("images/align-center.png", __dir__), subsample: 32
2039
2051
 
2040
2052
  on('command') do
2041
- @text.text_copy
2053
+ @text.add_selection_format('justify', 'center')
2042
2054
  end
2043
2055
  }
2044
2056
 
2045
- button {
2057
+ @justify_right_button = button {
2046
2058
  grid row: 1, column: column_index += 1, column_weight: 0
2047
- image File.expand_path("images/paste.png", __dir__), subsample: 32
2059
+ image File.expand_path("images/align-right.png", __dir__), subsample: 32
2048
2060
 
2049
2061
  on('command') do
2050
- @text.text_paste
2062
+ @text.add_selection_format('justify', 'right')
2051
2063
  end
2052
2064
  }
2053
2065
 
@@ -2058,51 +2070,51 @@ class HelloText
2058
2070
 
2059
2071
  button {
2060
2072
  grid row: 1, column: column_index += 1, column_weight: 0
2061
- image File.expand_path("images/align-left.png", __dir__), subsample: 32
2073
+ image File.expand_path("images/picture.png", __dir__), subsample: 32
2062
2074
 
2063
2075
  on('command') do
2064
- @text.add_selection_format('justify', 'left')
2076
+ @text.get_open_file_to_insert_image
2065
2077
  end
2066
2078
  }
2067
2079
 
2068
2080
  button {
2069
2081
  grid row: 1, column: column_index += 1, column_weight: 0
2070
- image File.expand_path("images/align-center.png", __dir__), subsample: 32
2082
+ image File.expand_path("images/search.png", __dir__), subsample: 32
2071
2083
 
2072
2084
  on('command') do
2073
- @text.add_selection_format('justify', 'center')
2085
+ show_find_dialog
2074
2086
  end
2075
2087
  }
2076
2088
 
2089
+ separator {
2090
+ grid row: 1, column: column_index += 1, column_weight: 0
2091
+ orient 'vertical'
2092
+ }
2093
+
2077
2094
  button {
2078
2095
  grid row: 1, column: column_index += 1, column_weight: 0
2079
- image File.expand_path("images/align-right.png", __dir__), subsample: 32
2096
+ image File.expand_path("images/cut.png", __dir__), subsample: 32
2080
2097
 
2081
2098
  on('command') do
2082
- @text.add_selection_format('justify', 'right')
2099
+ @text.text_cut
2083
2100
  end
2084
2101
  }
2085
2102
 
2086
- separator {
2087
- grid row: 1, column: column_index += 1, column_weight: 0
2088
- orient 'vertical'
2089
- }
2090
-
2091
2103
  button {
2092
2104
  grid row: 1, column: column_index += 1, column_weight: 0
2093
- image File.expand_path("images/undo.png", __dir__), subsample: 32
2105
+ image File.expand_path("images/copy.png", __dir__), subsample: 32
2094
2106
 
2095
2107
  on('command') do
2096
- @text.edit_undo
2108
+ @text.text_copy
2097
2109
  end
2098
2110
  }
2099
2111
 
2100
2112
  button {
2101
2113
  grid row: 1, column: column_index += 1, column_weight: 0
2102
- image File.expand_path("images/redo.png", __dir__), subsample: 32
2114
+ image File.expand_path("images/paste.png", __dir__), subsample: 32
2103
2115
 
2104
2116
  on('command') do
2105
- @text.edit_redo
2117
+ @text.text_paste
2106
2118
  end
2107
2119
  }
2108
2120
 
@@ -2111,12 +2123,22 @@ class HelloText
2111
2123
  orient 'vertical'
2112
2124
  }
2113
2125
 
2126
+
2114
2127
  button {
2115
2128
  grid row: 1, column: column_index += 1, column_weight: 0
2116
- image File.expand_path("images/picture.png", __dir__), subsample: 32
2129
+ image File.expand_path("images/undo.png", __dir__), subsample: 32
2117
2130
 
2118
2131
  on('command') do
2119
- @text.get_open_file_to_insert_image
2132
+ @text.edit_undo
2133
+ end
2134
+ }
2135
+
2136
+ button {
2137
+ grid row: 1, column: column_index += 1, column_weight: 0
2138
+ image File.expand_path("images/redo.png", __dir__), subsample: 32
2139
+
2140
+ on('command') do
2141
+ @text.edit_redo
2120
2142
  end
2121
2143
  }
2122
2144
  }
@@ -2126,8 +2148,67 @@ class HelloText
2126
2148
  wrap 'word'
2127
2149
  undo true
2128
2150
  value <=> [self, :document]
2151
+
2152
+ on('KeyPress') do |event|
2153
+ show_find_dialog if (event.keysym == 'f') && ((OS.mac? && event.state == 8) || (!OS.mac? && event.state == 4))
2154
+ end
2155
+
2156
+ on('InsertMarkMoved') do
2157
+ self.font_family = @text.applied_font_format_value('family')
2158
+ self.font_size = @text.applied_font_format_value('size')
2159
+ @bold_button.default = @text.applied_font_format_value('weight') == 'bold' ? 'active' : 'normal'
2160
+ @italic_button.default = @text.applied_font_format_value('slant') == 'italic' ? 'active' : 'normal'
2161
+ @underline_button.default = @text.applied_font_format_value('underline') == true ? 'active' : 'normal'
2162
+ self.background = @text.applied_format_value('background')
2163
+ self.foreground = @text.applied_format_value('foreground')
2164
+ @justify_left_button.default = @text.applied_format_value('justify') == 'left' ? 'active' : 'normal'
2165
+ @justify_center_button.default = @text.applied_format_value('justify') == 'center' ? 'active' : 'normal'
2166
+ @justify_right_button.default = @text.applied_format_value('justify') == 'right' ? 'active' : 'normal'
2167
+ end
2129
2168
  }
2130
- }.open
2169
+ }
2170
+ @root.open
2171
+ end
2172
+
2173
+ def show_find_dialog
2174
+ toplevel(@root) { |tl|
2175
+ title 'Find'
2176
+
2177
+ label {
2178
+ text 'Text:'
2179
+ }
2180
+ entry { |e|
2181
+ focus true
2182
+ text <=> [
2183
+ self,
2184
+ :find_text,
2185
+ after_write: lambda do
2186
+ text_index = @text.search(/#{find_text}/i, 'insert')
2187
+ unless text_index.to_s.empty?
2188
+ @text.tag_remove('sel', '1.0', 'end')
2189
+ @text.tag_add('sel', text_index, "#{text_index} + #{find_text.size} chars")
2190
+ end
2191
+ end
2192
+ ]
2193
+
2194
+ on('KeyPress') do |event|
2195
+ if event.keysym == 'Return'
2196
+ find
2197
+ elsif event.keysym == 'Escape'
2198
+ tl.grab_release
2199
+ tl.destroy
2200
+ end
2201
+ end
2202
+ }
2203
+ button {
2204
+ text 'Find'
2205
+ default 'active'
2206
+
2207
+ on('command') do
2208
+ find
2209
+ end
2210
+ }
2211
+ }
2131
2212
  end
2132
2213
  end
2133
2214
 
@@ -2150,6 +2231,8 @@ Glimmer app:
2150
2231
 
2151
2232
  ![glimmer dsl tk screenshot sample hello text](images/glimmer-dsl-tk-screenshot-sample-hello-text.png)
2152
2233
 
2234
+ ![glimmer dsl tk screenshot sample hello text find dialog](images/glimmer-dsl-tk-screenshot-sample-hello-text-find-dialog.png)
2235
+
2153
2236
  ### Hello, Spinbox!
2154
2237
 
2155
2238
  Glimmer code (from [samples/hello/hello_spinbox.rb](samples/hello/hello_spinbox.rb)):
@@ -2624,31 +2707,34 @@ Glimmer app:
2624
2707
 
2625
2708
  https://github.com/ancorgs/glimmer-tk-calculator
2626
2709
 
2627
- https://raw.githubusercontent.com/ancorgs/glimmer-tk-calculator/master/screenshot.png
2710
+ ![Glimmer Tk Calculator Screenshot](https://raw.githubusercontent.com/ancorgs/glimmer-tk-calculator/master/screenshot.png)
2628
2711
 
2629
2712
  ### Y3network Ruby UI
2630
2713
 
2631
2714
  https://github.com/ancorgs/y3network-ruby-ui
2632
2715
 
2633
- ### Cryptopunks GUI
2716
+ ### CryptoPunks GUI
2634
2717
 
2635
- This is a Graphical User Interface for the famous [Cryptopunks Ruby gem](https://github.com/cryptopunksnotdead/cryptopunks/tree/master/cryptopunks).
2718
+ This is a Graphical User Interface for the famous [cryptopunks Ruby gem](https://github.com/cryptopunksnotdead/cryptopunks/tree/master/cryptopunks).
2636
2719
 
2637
2720
  https://github.com/AndyObtiva/cryptopunks-gui
2638
2721
 
2639
- ![Cryptopunks GUI Screenshot](https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/screenshots/cryptopunks-gui-screenshot.png)
2722
+ ![CryptoPunks GUI Screenshot](https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/screenshots/cryptopunks-gui-screenshot.png)
2640
2723
 
2641
2724
  ## Process
2642
2725
 
2643
2726
  [Glimmer Process](https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md)
2644
2727
 
2728
+ ## Resources
2729
+
2730
+ - [Tk Tutorial](https://tkdocs.com/tutorial/index.html)
2731
+ - [Code Master Blog](https://andymaleh.blogspot.com/search/label/Tk)
2732
+
2645
2733
  ## Help
2646
2734
 
2647
2735
  ### Issues
2648
2736
 
2649
- You may submit [issues](https://github.com/AndyObtiva/glimmer/issues) on [GitHub](https://github.com/AndyObtiva/glimmer/issues).
2650
-
2651
- [Click here to submit an issue.](https://github.com/AndyObtiva/glimmer/issues)
2737
+ If you encounter [issues](https://github.com/AndyObtiva/glimmer-dsl-tk/issues) that are not reported, discover missing features that are not mentioned in [TODO.md](TODO.md), or think up better ways to use [Tk](https://www.tcl.tk/) than what is possible with [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk), you may submit an [issue](https://github.com/AndyObtiva/glimmer-dsl-tk/issues/new) or [pull request](https://github.com/AndyObtiva/glimmer-dsl-tk/compare) on [GitHub](https://github.com).
2652
2738
 
2653
2739
  ### Chat
2654
2740
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.30
1
+ 0.0.34
Binary file
@@ -0,0 +1,39 @@
1
+ # Copyright (c) 2020-2021 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/observer'
23
+
24
+ module Glimmer
25
+ module DataBinding
26
+ module Tk
27
+ # Decorator for Observer that ensures it is only called once
28
+ # (subsequent invocations of call method do nothing)
29
+ module OneTimeObserver
30
+ def call(value)
31
+ unless @called
32
+ super
33
+ @called = true
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -38,12 +38,13 @@ module Glimmer
38
38
  end
39
39
 
40
40
  def interpret(parent, keyword, *args, &block)
41
- parent.class
42
41
  model_binding = args[0]
43
42
  widget_binding_parameters = [parent, keyword]
44
43
  widget_binding = DataBinding::Tk::WidgetBinding.new(*widget_binding_parameters)
45
44
  #TODO make this options observer dependent and all similar observers in widget specific data binding handlers
46
- widget_binding.observe(model_binding)
45
+ registration = widget_binding.observe(model_binding)
46
+ parent.on('destroy') { registration.deregister }
47
+
47
48
  # TODO simplify this logic and put it where it belongs
48
49
  parent.add_observer(model_binding, keyword) if parent.respond_to?(:add_observer, [model_binding, keyword])
49
50
  widget_binding.call(model_binding.evaluate_property)
@@ -33,11 +33,15 @@ module Glimmer
33
33
 
34
34
  def can_interpret?(parent, keyword, *args, &block)
35
35
  !EXCLUDED_KEYWORDS.include?(keyword) and
36
- parent.respond_to?(:tk) and
37
36
  Glimmer::Tk::WidgetProxy.widget_exists?(keyword)
37
+ (parent.respond_to?(:tk) or args.first.respond_to?(:tk))
38
38
  end
39
39
 
40
40
  def interpret(parent, keyword, *args, &block)
41
+ if keyword == 'toplevel' && args.first.respond_to?(:tk)
42
+ parent = args.first
43
+ args[0] = args.first.tk
44
+ end
41
45
  Glimmer::Tk::WidgetProxy.create(keyword, parent, args, &block)
42
46
  end
43
47
 
@@ -40,7 +40,7 @@ module Glimmer
40
40
 
41
41
  def handle_listener(listener_name, &listener)
42
42
  case listener_name.to_s.downcase
43
- when 'change'
43
+ when 'change', 'changed', 'modified'
44
44
  tk.textvariable.trace('write') {
45
45
  listener.call(@tk.textvariable)
46
46
  }