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 +4 -4
- data/CHANGELOG.md +32 -2
- data/README.md +143 -57
- data/VERSION +1 -1
- data/glimmer-dsl-tk.gemspec +0 -0
- data/lib/glimmer/data_binding/tk/one_time_observer.rb +39 -0
- data/lib/glimmer/dsl/tk/data_binding_expression.rb +3 -2
- data/lib/glimmer/dsl/tk/widget_expression.rb +5 -1
- data/lib/glimmer/tk/entry_proxy.rb +1 -1
- data/lib/glimmer/tk/root_proxy.rb +2 -77
- data/lib/glimmer/tk/text_proxy.rb +137 -25
- data/lib/glimmer/tk/toplevel_proxy.rb +119 -0
- data/lib/glimmer/tk/widget_proxy.rb +57 -13
- data/samples/hello/hello_text.rb +110 -38
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69e1f06607f60b2864e78e6e1eb9bfde7cf98f8d8eca2d14f12bf218d781dcb3
|
4
|
+
data.tar.gz: 7c552bb85c6b87eeefe8117b5f3d2df922ff27618f564e6dd37df63b57c17d98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
-
|
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.
|
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
|
-
- [
|
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.
|
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`).
|
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'
|
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(
|
352
|
-
- `remove_selection_format(
|
353
|
-
- `toggle_selection_format(
|
354
|
-
- `add_selection_font_format(
|
355
|
-
- `remove_selection_font_format(
|
356
|
-
- `toggle_selection_font_format(
|
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/
|
2041
|
+
image File.expand_path("images/align-left.png", __dir__), subsample: 32
|
2030
2042
|
|
2031
2043
|
on('command') do
|
2032
|
-
@text.
|
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/
|
2050
|
+
image File.expand_path("images/align-center.png", __dir__), subsample: 32
|
2039
2051
|
|
2040
2052
|
on('command') do
|
2041
|
-
@text.
|
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/
|
2059
|
+
image File.expand_path("images/align-right.png", __dir__), subsample: 32
|
2048
2060
|
|
2049
2061
|
on('command') do
|
2050
|
-
@text.
|
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/
|
2073
|
+
image File.expand_path("images/picture.png", __dir__), subsample: 32
|
2062
2074
|
|
2063
2075
|
on('command') do
|
2064
|
-
@text.
|
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/
|
2082
|
+
image File.expand_path("images/search.png", __dir__), subsample: 32
|
2071
2083
|
|
2072
2084
|
on('command') do
|
2073
|
-
|
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/
|
2096
|
+
image File.expand_path("images/cut.png", __dir__), subsample: 32
|
2080
2097
|
|
2081
2098
|
on('command') do
|
2082
|
-
@text.
|
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/
|
2105
|
+
image File.expand_path("images/copy.png", __dir__), subsample: 32
|
2094
2106
|
|
2095
2107
|
on('command') do
|
2096
|
-
@text.
|
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/
|
2114
|
+
image File.expand_path("images/paste.png", __dir__), subsample: 32
|
2103
2115
|
|
2104
2116
|
on('command') do
|
2105
|
-
@text.
|
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/
|
2129
|
+
image File.expand_path("images/undo.png", __dir__), subsample: 32
|
2117
2130
|
|
2118
2131
|
on('command') do
|
2119
|
-
@text.
|
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
|
-
}
|
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
|
-
###
|
2716
|
+
### CryptoPunks GUI
|
2634
2717
|
|
2635
|
-
This is a Graphical User Interface for the famous [
|
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
|
-
![
|
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
|
-
|
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.
|
1
|
+
0.0.34
|
data/glimmer-dsl-tk.gemspec
CHANGED
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
|
|