glimmer-dsl-tk 0.0.30 → 0.0.34

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: 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
  }