glimmer-dsl-tk 0.0.31 → 0.0.35

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: 883bb9d265c58ea872a90069aba8e308ee4688653d2ca200fb5289976850dc1c
4
- data.tar.gz: 34f92aa593f48fbe0edf1b469ebc5ec0b81e2789a8995d1b04cd77748c72c081
3
+ metadata.gz: daadce6a22be7ae817b7e0a3f5679a8c3d04d7ed6a0205fa30b03da206dc156a
4
+ data.tar.gz: f0324e91b54ac7e3179ffe122de59f714731d336d982937a92e76c6d0fd95079
5
5
  SHA512:
6
- metadata.gz: a8a0d78446483775e82da34e94ede3a1566b2e1201cd5c3bbbfaa1ed27f424bcb1d61826b7f600616550e999bcec117560d52742f3a4779d94dd8aa7adf18661
7
- data.tar.gz: fbc6ad5515dc20099c7e1c1827738f7d2edc133575f030afa69c2256c3e2bc6981986e494ada3498eeda6e4809bc5409dd7a61cc91666898d0dd48d7f1805277
6
+ metadata.gz: 461c26dee79b7a387eddc3107f342dffe14b39d49f307ab469a49afda8112af2ad75a350f88ab64fad616e458a217570c0f3414570c195aeef884c170bff9656
7
+ data.tar.gz: b7b2cd0c333de05d2c923ed461147fd245d58f55a622e57f7631c049b32344b7730801e3c49e271e5a0d7e884dcb1f64981f0feb5a57300952e05f191b1537eb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.35
4
+
5
+ - Improved Meta-Sample by utilizing Ruby from `RbConfig.ruby`
6
+ - Improved girb_runner.rb to be more platform independent
7
+ - Fixed `text` widget binding of standard bind events (e.g. `'KeyPress'` or `'ButtonPress'`)
8
+ - Fixed Hello, Text! issue with not being able to bring up Find Dialog once all text is deleted and new text is entered
9
+ - Fixed undo/redo issue
10
+
11
+ ## 0.0.34
12
+
13
+ - When applying a `text` selection format without having a selection, have it apply to current insert mark word
14
+ - Support registering multiple general event listeners on `text` widget (previously, later event listener registrations replaced former ones)
15
+ - 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`)
16
+ - Make sure to only allow `text` undo/redo when there are changes to be undoed/redoed
17
+ - Fix issue with Hello, Text! Find Dialog not coming up with keyboard shortcut (e.g. CMD+F) anymore
18
+ - 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)
19
+
20
+ ## 0.0.33
21
+
22
+ - Support `text` widget `InsertMarkMoved` listener event to track insert mark movement (or aliases `InsertMarkMove`, `insert_mark_move`, `insert_mark_moved`, all case-insensitive)
23
+ - Support `entry` widget `changed` and `modified` listener event aliases for `change` event
24
+ - 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
25
+ - 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.
26
+ - 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
27
+ - 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
28
+
29
+ ## 0.0.32
30
+
31
+ - Hello, Text! Find Dialog toolbar button
32
+ - Hello, Text! Find Dialog Windows/Linux CONTROL+F shortcut alternative to Mac CMD+F
33
+
3
34
  ## 0.0.31
4
35
 
5
36
  - Improve Hello, Text! (toolbar buttons: justify left, justify center, justify right)
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.35
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)
@@ -55,8 +55,9 @@ NOTE: Glimmer DSL for Tk is currently in early alpha mode (incomplete). Please h
55
55
 
56
56
  Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
57
57
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
58
- - [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui): Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
59
58
  - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)
59
+ - [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui): Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
60
+ - [glimmer-dsl-gtk](https://github.com/AndyObtiva/glimmer-dsl-gtk): Ruby-GNOME Desktop Development GUI Library
60
61
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
61
62
  - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
62
63
 
@@ -158,7 +159,7 @@ gem install glimmer-dsl-tk
158
159
 
159
160
  Add the following to `Gemfile`:
160
161
  ```
161
- gem 'glimmer-dsl-tk', '~> 0.0.30'
162
+ gem 'glimmer-dsl-tk', '~> 0.0.35'
162
163
  ```
163
164
 
164
165
  And, then run:
@@ -200,7 +201,7 @@ The Glimmer GUI DSL follows these simple concepts in mapping from Tk syntax:
200
201
  - **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.
201
202
  - **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'`)
202
203
  - **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`)
203
- - **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.
204
+ - **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.
204
205
 
205
206
  Example of an app written in [Tk](https://www.tcl.tk/) imperative syntax:
206
207
 
@@ -273,7 +274,7 @@ keyword(args) | attributes | event bindings & callbacks
273
274
  `choose_directory(options = nil)` | None | None
274
275
  `choose_font(options = nil) {|font| ... }` | None | None
275
276
  `combobox` | `state`, `text` | `'ComboboxSelected'`
276
- `entry` | `width`, `text`, `validate`, `show` (`'none', 'focus', 'focusin', 'focusout', 'key', or 'all'`) | `'validate'`, `'invalid'`, `'change'`, `validatecommand {}`, `invalidcommand {}`
277
+ `entry` | `width`, `text`, `validate`, `show` (`'none', 'focus', 'focusin', 'focusout', 'key', or 'all'`) | `'validate'`, `'invalid'`, `'change'` (alias: `'changed'`), `validatecommand {}`, `invalidcommand {}`
277
278
  `get_multiple_open_file(options = nil)` | None | None
278
279
  `get_open_file(options = nil)` | None | None
279
280
  `get_save_file(options = nil)` | None | None
@@ -286,7 +287,7 @@ keyword(args) | attributes | event bindings & callbacks
286
287
  `radiobutton` | `text`, `variable` (Boolean), `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `value` (default: `text`) | `command {}`
287
288
  `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'`
288
289
  `separator` | `orient` (`'horizontal' (default) or 'vertical'`) | None
289
- `text` | `value`, [many more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `'modified'`, `'selection'`
290
+ `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'`)
290
291
 
291
292
  Options for `get_open_file` and `get_multiple_open_file` include:
292
293
  - `filetypes`: `Hash` of `'Group Name' => '.ext'` entries (e.g. `filetypes: {'PNG Images' => '.png'}`
@@ -349,15 +350,20 @@ The `text` widget is enhanced by [Glimmer DSL for Tk](https://rubygems.org/gems/
349
350
  - `add_font_format(region_start, region_end, font_option, value)`
350
351
  - `remove_font_format(region_start, region_end, font_option, value)`
351
352
  - `toggle_font_format(region_start, region_end, font_option, value)`
352
- - `add_selection_format(region_start, region_end, option, value)`
353
- - `remove_selection_format(region_start, region_end, option, value)`
354
- - `toggle_selection_format(region_start, region_end, option, value)`
355
- - `add_selection_font_format(region_start, region_end, font_option, value)`
356
- - `remove_selection_font_format(region_start, region_end, font_option, value)`
357
- - `toggle_selection_font_format(region_start, region_end, font_option, value)`
353
+ - `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.
354
+ - `remove_selection_format(option, value, no_selection_default: :insert_word)`
355
+ - `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.
356
+ - `add_selection_font_format(font_option, value, no_selection_default: :insert_word)`
357
+ - `remove_selection_font_format(font_option, value, no_selection_default: :insert_word)`
358
+ - `toggle_selection_font_format(font_option, value, no_selection_default: :insert_word)`
358
359
  - `text#insert_image(text_index, *image_args)`: inserts image into `text` `value` content at `text_index` location (e.g. `'insert'`)
359
360
  - `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
360
361
 
362
+ The `:no_selection_default` keyword arg to `*_selection_*` methods determines what region to cover when no explicit selection is set:
363
+ - `:insert_word`: current word for insert mark
364
+ - `:insert_letter`: current letter for insert mark
365
+ - `:none`: no behavior when no selection is in place
366
+
361
367
  Available options:
362
368
 
363
369
  - `background`
@@ -1869,7 +1875,7 @@ Glimmer app:
1869
1875
 
1870
1876
  ### Hello, Text!
1871
1877
 
1872
- You may use the META+F shortcut to bring up the Find Dialog.
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.
1873
1879
 
1874
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>
1875
1881
 
@@ -1921,7 +1927,7 @@ class HelloText
1921
1927
  MULTI_LINE_STRING
1922
1928
  end
1923
1929
 
1924
- attr_accessor :document
1930
+ attr_accessor :document, :find_text
1925
1931
 
1926
1932
  attr_accessor :foreground
1927
1933
 
@@ -1947,8 +1953,16 @@ class HelloText
1947
1953
  [FONT_SIZE_PROMPT] + (9..64).to_a.map(&:to_s)
1948
1954
  end
1949
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
+
1950
1964
  def launch
1951
- root {
1965
+ @root = root {
1952
1966
  title 'Hello, Text!'
1953
1967
  width 1280
1954
1968
  height 800
@@ -1956,11 +1970,6 @@ class HelloText
1956
1970
  frame {
1957
1971
  grid row: 0, column: 0
1958
1972
 
1959
- label {
1960
- grid row: 0, column: 0, columnspan: 17
1961
- text 'Select a region of text and then apply formatting from the toolbar'
1962
- }
1963
-
1964
1973
  column_index = -1
1965
1974
 
1966
1975
  combobox {
@@ -1992,7 +2001,7 @@ class HelloText
1992
2001
  orient 'vertical'
1993
2002
  }
1994
2003
 
1995
- button {
2004
+ @bold_button = button {
1996
2005
  grid row: 1, column: column_index += 1, column_weight: 0
1997
2006
  text 'B'
1998
2007
  style font: {weight: 'bold'}
@@ -2002,7 +2011,7 @@ class HelloText
2002
2011
  end
2003
2012
  }
2004
2013
 
2005
- button {
2014
+ @italic_button = button {
2006
2015
  grid row: 1, column: column_index += 1, column_weight: 0
2007
2016
  text 'I'
2008
2017
  style font: {slant: 'italic'}
@@ -2012,7 +2021,7 @@ class HelloText
2012
2021
  end
2013
2022
  }
2014
2023
 
2015
- button {
2024
+ @underline_button = button {
2016
2025
  grid row: 1, column: column_index += 1, column_weight: 0
2017
2026
  text 'U'
2018
2027
  style font: {underline: true}
@@ -2021,36 +2030,36 @@ class HelloText
2021
2030
  @text.toggle_selection_font_format('underline', true)
2022
2031
  end
2023
2032
  }
2024
-
2033
+
2025
2034
  separator {
2026
2035
  grid row: 1, column: column_index += 1, column_weight: 0
2027
2036
  orient 'vertical'
2028
2037
  }
2029
2038
 
2030
- button {
2039
+ @justify_left_button = button {
2031
2040
  grid row: 1, column: column_index += 1, column_weight: 0
2032
- image File.expand_path("images/cut.png", __dir__), subsample: 32
2041
+ image File.expand_path("images/align-left.png", __dir__), subsample: 32
2033
2042
 
2034
2043
  on('command') do
2035
- @text.text_cut
2044
+ @text.add_selection_format('justify', 'left')
2036
2045
  end
2037
2046
  }
2038
2047
 
2039
- button {
2048
+ @justify_center_button = button {
2040
2049
  grid row: 1, column: column_index += 1, column_weight: 0
2041
- image File.expand_path("images/copy.png", __dir__), subsample: 32
2050
+ image File.expand_path("images/align-center.png", __dir__), subsample: 32
2042
2051
 
2043
2052
  on('command') do
2044
- @text.text_copy
2053
+ @text.add_selection_format('justify', 'center')
2045
2054
  end
2046
2055
  }
2047
2056
 
2048
- button {
2057
+ @justify_right_button = button {
2049
2058
  grid row: 1, column: column_index += 1, column_weight: 0
2050
- image File.expand_path("images/paste.png", __dir__), subsample: 32
2059
+ image File.expand_path("images/align-right.png", __dir__), subsample: 32
2051
2060
 
2052
2061
  on('command') do
2053
- @text.text_paste
2062
+ @text.add_selection_format('justify', 'right')
2054
2063
  end
2055
2064
  }
2056
2065
 
@@ -2061,51 +2070,51 @@ class HelloText
2061
2070
 
2062
2071
  button {
2063
2072
  grid row: 1, column: column_index += 1, column_weight: 0
2064
- image File.expand_path("images/align-left.png", __dir__), subsample: 32
2073
+ image File.expand_path("images/picture.png", __dir__), subsample: 32
2065
2074
 
2066
2075
  on('command') do
2067
- @text.add_selection_format('justify', 'left')
2076
+ @text.get_open_file_to_insert_image
2068
2077
  end
2069
2078
  }
2070
2079
 
2071
2080
  button {
2072
2081
  grid row: 1, column: column_index += 1, column_weight: 0
2073
- image File.expand_path("images/align-center.png", __dir__), subsample: 32
2082
+ image File.expand_path("images/search.png", __dir__), subsample: 32
2074
2083
 
2075
2084
  on('command') do
2076
- @text.add_selection_format('justify', 'center')
2085
+ show_find_dialog
2077
2086
  end
2078
2087
  }
2079
2088
 
2089
+ separator {
2090
+ grid row: 1, column: column_index += 1, column_weight: 0
2091
+ orient 'vertical'
2092
+ }
2093
+
2080
2094
  button {
2081
2095
  grid row: 1, column: column_index += 1, column_weight: 0
2082
- image File.expand_path("images/align-right.png", __dir__), subsample: 32
2096
+ image File.expand_path("images/cut.png", __dir__), subsample: 32
2083
2097
 
2084
2098
  on('command') do
2085
- @text.add_selection_format('justify', 'right')
2099
+ @text.text_cut
2086
2100
  end
2087
2101
  }
2088
2102
 
2089
- separator {
2090
- grid row: 1, column: column_index += 1, column_weight: 0
2091
- orient 'vertical'
2092
- }
2093
-
2094
2103
  button {
2095
2104
  grid row: 1, column: column_index += 1, column_weight: 0
2096
- image File.expand_path("images/undo.png", __dir__), subsample: 32
2105
+ image File.expand_path("images/copy.png", __dir__), subsample: 32
2097
2106
 
2098
2107
  on('command') do
2099
- @text.edit_undo
2108
+ @text.text_copy
2100
2109
  end
2101
2110
  }
2102
2111
 
2103
2112
  button {
2104
2113
  grid row: 1, column: column_index += 1, column_weight: 0
2105
- image File.expand_path("images/redo.png", __dir__), subsample: 32
2114
+ image File.expand_path("images/paste.png", __dir__), subsample: 32
2106
2115
 
2107
2116
  on('command') do
2108
- @text.edit_redo
2117
+ @text.text_paste
2109
2118
  end
2110
2119
  }
2111
2120
 
@@ -2114,12 +2123,22 @@ class HelloText
2114
2123
  orient 'vertical'
2115
2124
  }
2116
2125
 
2126
+
2117
2127
  button {
2118
2128
  grid row: 1, column: column_index += 1, column_weight: 0
2119
- image File.expand_path("images/picture.png", __dir__), subsample: 32
2129
+ image File.expand_path("images/undo.png", __dir__), subsample: 32
2120
2130
 
2121
2131
  on('command') do
2122
- @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
2123
2142
  end
2124
2143
  }
2125
2144
  }
@@ -2129,8 +2148,67 @@ class HelloText
2129
2148
  wrap 'word'
2130
2149
  undo true
2131
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
2132
2168
  }
2133
- }.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
+ }
2134
2212
  end
2135
2213
  end
2136
2214
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.31
1
+ 0.0.35
data/bin/girb_runner.rb CHANGED
@@ -27,7 +27,7 @@ require_relative '../lib/glimmer-dsl-tk'
27
27
 
28
28
  include Glimmer
29
29
 
30
- GIRB_RUNNER_EXIT_FILE = "#{Etc.getpwuid.dir}/.girb_runner_exit"
30
+ GIRB_RUNNER_EXIT_FILE = "#{Dir.home}/.girb_runner_exit"
31
31
  FileUtils.rm_rf GIRB_RUNNER_EXIT_FILE
32
32
 
33
33
  @exit_method = method(:exit)
Binary file
@@ -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
  }
@@ -27,59 +27,106 @@ module Glimmer
27
27
  #
28
28
  # Follows the Proxy Design Pattern
29
29
  class TextProxy < WidgetProxy
30
+ ALL_TAG = '__all__'
31
+ FORMAT_DEFAULT_MAP = {
32
+ 'justify' => 'left',
33
+ }
34
+
30
35
  def handle_listener(listener_name, &listener)
31
36
  case listener_name.to_s.downcase
32
37
  when '<<modified>>', '<modified>', 'modified'
33
38
  modified_listener = Proc.new do |*args|
39
+ @modified_count ||= 0
40
+ @modified_count += 1
34
41
  listener.call(*args)
42
+ @insert_mark_moved_proc&.call
35
43
  @tk.modified = false
36
44
  end
37
- bind('<Modified>', modified_listener)
45
+ @tk.bind('<Modified>', modified_listener)
38
46
  when '<<selection>>', '<selection>', 'selection'
39
- bind('<Selection>', listener)
47
+ @tk.bind('<Selection>', listener)
40
48
  when 'destroy'
41
49
  super
42
- else
43
- @tk.tag_add('__all__', '1.0', 'end') unless @tk.tag_names.include?('__all__')
44
- # TODO make listener pass an event that has a modifiers attribute for easy representation of :shift, :meta, :control, etc... while a letter button is pressed
45
- begin
46
- @tk.tag_bind('__all__', listener_name, &listener)
47
- rescue => e
48
- Glimmer::Config.logger.debug {"Unable to bind to #{listener_name} .. attempting to surround with <>"}
49
- Glimmer::Config.logger.debug {e.full_message}
50
- listener_name = "<#{listener_name}" if !listener_name.start_with?('<')
51
- listener_name = "#{listener_name}>" if !listener_name.end_with?('>')
52
- @tk.tag_bind('__all__', listener_name, &listener)
50
+ when 'insertmarkmove', 'insertmarkmoved', 'insert_mark_move', 'insert_mark_moved'
51
+ if @insert_mark_moved_proc.nil?
52
+ handle_listener('KeyPress') do |event|
53
+ @insert_mark_moved_proc&.call
54
+ end
55
+ handle_listener('KeyRelease') do |event|
56
+ @insert_mark_moved_proc&.call
57
+ end
58
+ handle_listener('ButtonPress') do |event|
59
+ @insert_mark_moved_proc&.call
60
+ end
61
+ handle_listener('ButtonRelease') do |event|
62
+ @insert_mark_moved_proc&.call
63
+ end
64
+ end
65
+ @insert_mark = @tk.index('insert')
66
+ @insert_mark_moved_proc = Proc.new do
67
+ new_insert_mark = @tk.index('insert')
68
+ if new_insert_mark != @insert_mark
69
+ @insert_mark = new_insert_mark
70
+ listener.call(new_insert_mark)
71
+ end
53
72
  end
73
+ else
74
+ super
54
75
  end
55
76
  end
56
-
57
- def add_selection_format(option, value)
58
- process_selection_ranges { |range_start, range_end| add_format(range_start, range_end, option, value) }
77
+
78
+ def edit_undo
79
+ # <Modified> fires twice the first time, which is equivalent to one change.
80
+ if @modified_count.to_i > 2
81
+ # must count the extra 2 modified count that will occur upon undo too
82
+ @modified_count -= 4
83
+ @tk.edit_undo
84
+ end
59
85
  end
60
86
 
61
- def remove_selection_format(option, value)
62
- process_selection_ranges { |range_start, range_end| remove_format(range_start, range_end, option, value) }
87
+ def edit_redo
88
+ begin
89
+ @tk.edit_redo
90
+ rescue => e
91
+ # No Op
92
+ end
63
93
  end
64
94
 
65
- def toggle_selection_format(option, value)
66
- process_selection_ranges { |range_start, range_end| toggle_format(range_start, range_end, option, value) }
95
+ def add_selection_format(option, value, no_selection_default: :insert_word)
96
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| add_format(range_start, range_end, option, value) }
67
97
  end
68
98
 
69
- def add_selection_font_format(option, value)
70
- process_selection_ranges { |range_start, range_end| add_font_format(range_start, range_end, option, value) }
99
+ def remove_selection_format(option, value, no_selection_default: :insert_word)
100
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| remove_format(range_start, range_end, option, value) }
71
101
  end
72
102
 
73
- def remove_selection_font_format(option, value)
74
- process_selection_ranges { |range_start, range_end| remove_font_format(range_start, range_end, option, value) }
103
+ def toggle_selection_format(option, value, no_selection_default: :insert_word)
104
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| toggle_format(range_start, range_end, option, value) }
75
105
  end
76
106
 
77
- def toggle_selection_font_format(option, value)
78
- process_selection_ranges { |range_start, range_end| toggle_font_format(range_start, range_end, option, value) }
107
+ def add_selection_font_format(option, value, no_selection_default: :insert_word)
108
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| add_font_format(range_start, range_end, option, value) }
79
109
  end
80
110
 
81
- def process_selection_ranges(&processor)
82
- @tk.tag_ranges('sel').each do |region|
111
+ def remove_selection_font_format(option, value, no_selection_default: :insert_word)
112
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| remove_font_format(range_start, range_end, option, value) }
113
+ end
114
+
115
+ def toggle_selection_font_format(option, value, no_selection_default: :insert_word)
116
+ process_selection_ranges(no_selection_default: no_selection_default) { |range_start, range_end| toggle_font_format(range_start, range_end, option, value) }
117
+ end
118
+
119
+ def process_selection_ranges(no_selection_default: :insert_word, &processor)
120
+ regions = @tk.tag_ranges('sel')
121
+ if regions.empty?
122
+ case no_selection_default
123
+ when :insert_word
124
+ regions = [[@tk.index('insert wordstart'), @tk.index('insert wordend + 1 char')]]
125
+ when :insert_letter
126
+ regions = [[@tk.index('insert'), @tk.index('insert + 1 char')]]
127
+ end
128
+ end
129
+ regions.each do |region|
83
130
  range_start = region.first
84
131
  range_end = region.last
85
132
  processor.call(range_start, range_end)
@@ -91,7 +138,7 @@ module Glimmer
91
138
  end
92
139
 
93
140
  def applied_format_tags(region_start, region_end, option, value)
94
- tag_names = @tk.tag_names - ['sel']
141
+ tag_names = @tk.tag_names - ['sel', ALL_TAG]
95
142
 
96
143
  tag_names.select do |tag_name|
97
144
  @tk.tag_ranges(tag_name).any? do |range|
@@ -102,9 +149,26 @@ module Glimmer
102
149
  end
103
150
  end
104
151
 
152
+ def applied_format_value(text_index = nil, option)
153
+ text_index ||= @tk.index('insert')
154
+ region_start = text_index
155
+ region_end = text_index
156
+ tag_names = @tk.tag_names - ['sel', ALL_TAG]
157
+
158
+ values = tag_names.map do |tag_name|
159
+ @tk.tag_ranges(tag_name).map do |range|
160
+ if text_index_less_than_or_equal_to_other_text_index?(range.first, region_start) && text_index_greater_than_or_equal_to_other_text_index?(range.last, region_end)
161
+ @tk.tag_cget(tag_name, option)
162
+ end
163
+ end
164
+ end.flatten.reject {|value| value.to_s.empty?}
165
+
166
+ values.last || (@tk.send(option) rescue FORMAT_DEFAULT_MAP[option])
167
+ end
168
+
105
169
  def add_format(region_start, region_end, option, value)
106
170
  @@tag_number = 0 unless defined?(@@tag_number)
107
- tag = "tag#{@@tag_number += 1}"
171
+ tag = "tag_#{option}_#{@@tag_number += 1}"
108
172
  @tk.tag_configure(tag, {option => value})
109
173
  @tk.tag_add(tag, region_start, region_end)
110
174
  tag
@@ -155,15 +219,14 @@ module Glimmer
155
219
  def applied_font_format_tags_and_regions(region_start, region_end)
156
220
  lines = value.split("\n")
157
221
  tags_and_regions = []
158
- all_tag_names = @tk.tag_names - ['sel']
222
+ all_tag_names = (@tk.tag_names - ['sel', ALL_TAG]).select {|tag_name| tag_name.include?('_font_')}
159
223
  (region_start.to_i..region_end.to_i).each do |line_number|
160
224
  start_character_index = 0
161
225
  start_character_index = region_start.to_s.split('.').last.to_i if line_number == region_start.to_i
162
- end_character_index = lines[line_number - 1].size
226
+ end_character_index = lines[line_number - 1].to_s.size
163
227
  end_character_index = region_end.to_s.split('.').last.to_i if line_number == region_end.to_i
164
228
  (start_character_index...end_character_index).each do |character_index|
165
229
  text_index = "#{line_number}.#{character_index}"
166
- # TODO reimplement the following using @tk.tag_names without arg since passing an arg seems broken and returns inaccurate results
167
230
  region_tag = all_tag_names.reverse.find do |tag|
168
231
  @tk.tag_cget(tag, 'font') && @tk.tag_ranges(tag).any? do |range_start, range_end|
169
232
  text_index_less_than_or_equal_to_other_text_index?(range_start, text_index) && text_index_greater_than_or_equal_to_other_text_index?(range_end, text_index)
@@ -179,6 +242,27 @@ module Glimmer
179
242
  end
180
243
  tags_and_regions
181
244
  end
245
+
246
+ def applied_font_format_value(text_index = nil, font_option)
247
+ text_index ||= @tk.index('insert')
248
+ region_start = text_index
249
+ region_end = @tk.index("#{text_index} + 1 chars")
250
+ tag_names = applied_font_format_tags_and_regions(region_start, region_end).map(&:first)
251
+
252
+ values = tag_names.map do |tag_name|
253
+ @tk.tag_ranges(tag_name).map do |range|
254
+ if text_index_less_than_or_equal_to_other_text_index?(range.first, region_start) && text_index_greater_than_or_equal_to_other_text_index?(range.last, region_end)
255
+ @tk.tag_cget(tag_name, 'font')
256
+ end
257
+ end
258
+ end.flatten.reject {|value| value.to_s.empty?}
259
+
260
+ font = values.last
261
+
262
+ value = font && font.send(font_option)
263
+
264
+ value || Hash[@tk.font.actual][font_option]
265
+ end
182
266
 
183
267
  def add_font_format(region_start, region_end, font_option, value)
184
268
  applied_font_format_tags_and_regions(region_start, region_end).each do |tag, tag_region_start, tag_region_end|
@@ -348,11 +432,16 @@ module Glimmer
348
432
  self.wrap = 'none'
349
433
  self.padx = 5
350
434
  self.pady = 5
435
+ # on('Modified') { apply_all_tag }
351
436
  end
352
437
 
353
438
  def clone_font(font)
354
439
  ::TkFont.new(Hash[font.actual])
355
440
  end
441
+
442
+ # def apply_all_tag
443
+ # @tk.tag_add(ALL_TAG, '1.0', 'end')
444
+ # end
356
445
  end
357
446
  end
358
447
  end
@@ -56,7 +56,7 @@ class MetaSample
56
56
 
57
57
  def run_sample(sample)
58
58
  Thread.new do
59
- command = "ruby -r #{glimmer_dsl_tk_file} #{sample} 2>&1"
59
+ command = "#{RbConfig.ruby} -r #{glimmer_dsl_tk_file} #{sample} 2>&1"
60
60
  result = ''
61
61
  IO.popen(command) do |f|
62
62
  f.each_line do |line|
@@ -99,7 +99,7 @@ class HelloText
99
99
  end
100
100
 
101
101
  def launch
102
- root { |r|
102
+ @root = root {
103
103
  title 'Hello, Text!'
104
104
  width 1280
105
105
  height 800
@@ -107,11 +107,6 @@ class HelloText
107
107
  frame {
108
108
  grid row: 0, column: 0
109
109
 
110
- label {
111
- grid row: 0, column: 0, columnspan: 17
112
- text 'Select a region of text and then apply formatting from the toolbar'
113
- }
114
-
115
110
  column_index = -1
116
111
 
117
112
  combobox {
@@ -143,7 +138,7 @@ class HelloText
143
138
  orient 'vertical'
144
139
  }
145
140
 
146
- button {
141
+ @bold_button = button {
147
142
  grid row: 1, column: column_index += 1, column_weight: 0
148
143
  text 'B'
149
144
  style font: {weight: 'bold'}
@@ -153,7 +148,7 @@ class HelloText
153
148
  end
154
149
  }
155
150
 
156
- button {
151
+ @italic_button = button {
157
152
  grid row: 1, column: column_index += 1, column_weight: 0
158
153
  text 'I'
159
154
  style font: {slant: 'italic'}
@@ -163,7 +158,7 @@ class HelloText
163
158
  end
164
159
  }
165
160
 
166
- button {
161
+ @underline_button = button {
167
162
  grid row: 1, column: column_index += 1, column_weight: 0
168
163
  text 'U'
169
164
  style font: {underline: true}
@@ -172,36 +167,36 @@ class HelloText
172
167
  @text.toggle_selection_font_format('underline', true)
173
168
  end
174
169
  }
175
-
170
+
176
171
  separator {
177
172
  grid row: 1, column: column_index += 1, column_weight: 0
178
173
  orient 'vertical'
179
174
  }
180
175
 
181
- button {
176
+ @justify_left_button = button {
182
177
  grid row: 1, column: column_index += 1, column_weight: 0
183
- image File.expand_path("images/cut.png", __dir__), subsample: 32
178
+ image File.expand_path("images/align-left.png", __dir__), subsample: 32
184
179
 
185
180
  on('command') do
186
- @text.text_cut
181
+ @text.add_selection_format('justify', 'left')
187
182
  end
188
183
  }
189
184
 
190
- button {
185
+ @justify_center_button = button {
191
186
  grid row: 1, column: column_index += 1, column_weight: 0
192
- image File.expand_path("images/copy.png", __dir__), subsample: 32
187
+ image File.expand_path("images/align-center.png", __dir__), subsample: 32
193
188
 
194
189
  on('command') do
195
- @text.text_copy
190
+ @text.add_selection_format('justify', 'center')
196
191
  end
197
192
  }
198
193
 
199
- button {
194
+ @justify_right_button = button {
200
195
  grid row: 1, column: column_index += 1, column_weight: 0
201
- image File.expand_path("images/paste.png", __dir__), subsample: 32
196
+ image File.expand_path("images/align-right.png", __dir__), subsample: 32
202
197
 
203
198
  on('command') do
204
- @text.text_paste
199
+ @text.add_selection_format('justify', 'right')
205
200
  end
206
201
  }
207
202
 
@@ -212,51 +207,51 @@ class HelloText
212
207
 
213
208
  button {
214
209
  grid row: 1, column: column_index += 1, column_weight: 0
215
- image File.expand_path("images/align-left.png", __dir__), subsample: 32
210
+ image File.expand_path("images/picture.png", __dir__), subsample: 32
216
211
 
217
212
  on('command') do
218
- @text.add_selection_format('justify', 'left')
213
+ @text.get_open_file_to_insert_image
219
214
  end
220
215
  }
221
216
 
222
217
  button {
223
218
  grid row: 1, column: column_index += 1, column_weight: 0
224
- image File.expand_path("images/align-center.png", __dir__), subsample: 32
219
+ image File.expand_path("images/search.png", __dir__), subsample: 32
225
220
 
226
221
  on('command') do
227
- @text.add_selection_format('justify', 'center')
222
+ show_find_dialog
228
223
  end
229
224
  }
230
225
 
226
+ separator {
227
+ grid row: 1, column: column_index += 1, column_weight: 0
228
+ orient 'vertical'
229
+ }
230
+
231
231
  button {
232
232
  grid row: 1, column: column_index += 1, column_weight: 0
233
- image File.expand_path("images/align-right.png", __dir__), subsample: 32
233
+ image File.expand_path("images/cut.png", __dir__), subsample: 32
234
234
 
235
235
  on('command') do
236
- @text.add_selection_format('justify', 'right')
236
+ @text.text_cut
237
237
  end
238
238
  }
239
239
 
240
- separator {
241
- grid row: 1, column: column_index += 1, column_weight: 0
242
- orient 'vertical'
243
- }
244
-
245
240
  button {
246
241
  grid row: 1, column: column_index += 1, column_weight: 0
247
- image File.expand_path("images/undo.png", __dir__), subsample: 32
242
+ image File.expand_path("images/copy.png", __dir__), subsample: 32
248
243
 
249
244
  on('command') do
250
- @text.edit_undo
245
+ @text.text_copy
251
246
  end
252
247
  }
253
248
 
254
249
  button {
255
250
  grid row: 1, column: column_index += 1, column_weight: 0
256
- image File.expand_path("images/redo.png", __dir__), subsample: 32
251
+ image File.expand_path("images/paste.png", __dir__), subsample: 32
257
252
 
258
253
  on('command') do
259
- @text.edit_redo
254
+ @text.text_paste
260
255
  end
261
256
  }
262
257
 
@@ -265,12 +260,22 @@ class HelloText
265
260
  orient 'vertical'
266
261
  }
267
262
 
263
+
268
264
  button {
269
265
  grid row: 1, column: column_index += 1, column_weight: 0
270
- image File.expand_path("images/picture.png", __dir__), subsample: 32
266
+ image File.expand_path("images/undo.png", __dir__), subsample: 32
271
267
 
272
268
  on('command') do
273
- @text.get_open_file_to_insert_image
269
+ @text.edit_undo
270
+ end
271
+ }
272
+
273
+ button {
274
+ grid row: 1, column: column_index += 1, column_weight: 0
275
+ image File.expand_path("images/redo.png", __dir__), subsample: 32
276
+
277
+ on('command') do
278
+ @text.edit_redo
274
279
  end
275
280
  }
276
281
  }
@@ -281,50 +286,66 @@ class HelloText
281
286
  undo true
282
287
  value <=> [self, :document]
283
288
 
289
+ on('InsertMarkMoved') do
290
+ self.font_family = @text.applied_font_format_value('family')
291
+ self.font_size = @text.applied_font_format_value('size')
292
+ @bold_button.default = @text.applied_font_format_value('weight') == 'bold' ? 'active' : 'normal'
293
+ @italic_button.default = @text.applied_font_format_value('slant') == 'italic' ? 'active' : 'normal'
294
+ @underline_button.default = @text.applied_font_format_value('underline') == true ? 'active' : 'normal'
295
+ self.background = @text.applied_format_value('background')
296
+ self.foreground = @text.applied_format_value('foreground')
297
+ @justify_left_button.default = @text.applied_format_value('justify') == 'left' ? 'active' : 'normal'
298
+ @justify_center_button.default = @text.applied_format_value('justify') == 'center' ? 'active' : 'normal'
299
+ @justify_right_button.default = @text.applied_format_value('justify') == 'right' ? 'active' : 'normal'
300
+ end
301
+
284
302
  on('KeyPress') do |event|
285
- if event.state == 8 && event.char == 'f'
286
- toplevel(r) { |tl|
287
- title 'Find'
288
-
289
- label {
290
- text 'Text:'
291
- }
292
- entry { |e|
293
- focus true
294
- text <=> [
295
- self,
296
- :find_text,
297
- after_write: lambda do
298
- text_index = @text.search(/#{find_text}/i, 'insert')
299
- unless text_index.to_s.empty?
300
- @text.tag_remove('sel', '1.0', 'end')
301
- @text.tag_add('sel', text_index, "#{text_index} + #{find_text.size} chars")
302
- end
303
- end
304
- ]
305
-
306
- on('KeyPress') do |event|
307
- if event.keysym == 'Return'
308
- find
309
- elsif event.keysym == 'Escape'
310
- tl.grab_release
311
- tl.destroy
312
- end
313
- end
314
- }
315
- button {
316
- text 'Find'
317
- default 'active'
303
+ show_find_dialog if (event.keysym == 'f') && ((OS.mac? && event.state == 8) || (!OS.mac? && event.state == 4))
304
+ end
305
+ }
306
+ }
307
+ @root.open
308
+ end
309
+
310
+ def show_find_dialog
311
+ toplevel(@root) { |tl|
312
+ title 'Find'
313
+
314
+ label {
315
+ text 'Text:'
316
+ }
317
+ entry { |e|
318
+ focus true
319
+ text <=> [
320
+ self,
321
+ :find_text,
322
+ after_write: lambda do
323
+ text_index = @text.search(/#{find_text}/i, 'insert')
324
+ unless text_index.to_s.empty?
325
+ @text.tag_remove('sel', '1.0', 'end')
326
+ @text.tag_add('sel', text_index, "#{text_index} + #{find_text.size} chars")
327
+ end
328
+ end
329
+ ]
318
330
 
319
- on('command') do
320
- find
321
- end
322
- }
323
- }
331
+ on('KeyPress') do |event|
332
+ if event.keysym == 'Return'
333
+ find
334
+ elsif event.keysym == 'Escape'
335
+ tl.grab_release
336
+ tl.destroy
324
337
  end
325
338
  end
326
339
  }
327
- }.open
340
+ button {
341
+ text 'Find'
342
+ default 'active'
343
+
344
+ on('command') do
345
+ find
346
+ end
347
+ }
348
+ }
328
349
  end
329
350
  end
330
351
 
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.31
4
+ version: 0.0.35
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-28 00:00:00.000000000 Z
11
+ date: 2021-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer