glimmer-dsl-tk 0.0.26 → 0.0.27

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: 23370b36e8a1902b5115b534e8d9510ff5660d9b5daa9bf31abec321976eb485
4
- data.tar.gz: ebb5477ba30c249375d96f81747f250ea45ea14b20bc0420b373c9a36b0d79fc
3
+ metadata.gz: 73b915eb9db0314df3594942c5c4a1205d3ae63a923f01e4dee9f3ee03c75ac0
4
+ data.tar.gz: 31f1293d6d56d4966207a00b2aa453775adc51ab86aaf71f4dc40bfa5e0dabda
5
5
  SHA512:
6
- metadata.gz: 7249831c8104e32a6cab14341757932acb621e8de027ff6b698e6f017361959b27174b8ecd1d9a6ea3aa428a93a4392a57ceee2d7c7f08f4513eddf95129a051
7
- data.tar.gz: 7cafb57cb7fc10656d70d101cc32e8e0e18e6636ff34ed4c2056b8f8dbc9ec428205f96643792adaf939c2fc0789974f11be4718e6f443fca74bf4c6aee6c21a
6
+ metadata.gz: 965f7054d8cad79a9aeed46dd189c8db263d3447b965afccf6a2bc4e5376b95fed6b21cd119e23110ea8c140ae9b4c07cbd0927087dacacb70641bb7afe2d341
7
+ data.tar.gz: c26996ed08d930161da7cf0814753fcffdba7339be1eea84135f5e3f1fac64abcdf1efc24daf1b23859d197b117f4de62c34a78d678823c3ea68edbf91a1dd11
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.27
4
+
5
+ - Improve Hello, Text! (toolbar buttons: bold, italic, underline)
6
+ - Set correct `wrap 'word'` attribute for `text` widget in Hello, Text!
7
+ - Default `text` widget to `wrap = 'none'`
8
+ - Default `text` widget to `font = {family: 'Courier New'}`
9
+ - Fix issue with unbolding text in `text` widget when selecting multiple lines with an empty line
10
+
3
11
  ## 0.0.26
4
12
 
5
13
  - Ensure spinbox data-binding updates on text key changes (without incrementing/decrementing)
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.26
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.27
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)
@@ -10,11 +10,9 @@
10
10
 
11
11
  [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [Tk](https://www.tcl.tk/) enables desktop development with [Glimmer](https://github.com/AndyObtiva/glimmer) in [Ruby](https://github.com/ruby/ruby).
12
12
 
13
- [Tcl/Tk](https://www.tcl.tk/) has recently improved by gaining native looking themed widgets on Mac, Windows, and Linux in [Tk version 8.5](https://www.tcl.tk/software/tcltk/8.5.html#:~:text=Highlights%20of%20Tk%208.5&text=Font%20rendering%3A%20Now%20uses%20anti,and%20window%20layout%2C%20and%20more.).
13
+ [Tcl/Tk](https://www.tcl.tk/) has recently improved by gaining native looking themed widgets on Mac, Windows, and Linux in [Tk version 8.5](https://www.tcl.tk/software/tcltk/8.5.html#:~:text=Highlights%20of%20Tk%208.5&text=Font%20rendering%3A%20Now%20uses%20anti,and%20window%20layout%2C%20and%20more.). Additionally, [Ruby](https://www.ruby-lang.org/en/) 3.0 Ractor (formerly known as [Guilds](https://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/)) supports truly parallel multi-threading, making both [MRI](https://github.com/ruby/ruby) and [Tk](https://www.tcl.tk/) finally viable for support in [Glimmer](https://github.com/AndyObtiva/glimmer) (Ruby Desktop Development GUI Library) as an alternative to [JRuby on SWT](https://github.com/AndyObtiva/glimmer-dsl-swt).
14
14
 
15
- Additionally, [Ruby](https://www.ruby-lang.org/en/) 3.0 Ractor (formerly known as [Guilds](https://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/)) supports truly parallel multi-threading, making both [MRI](https://github.com/ruby/ruby) and [Tk](https://www.tcl.tk/) finally viable for support in [Glimmer](https://github.com/AndyObtiva/glimmer) (Ruby Desktop Development GUI Library) as an alternative to [JRuby on SWT](https://github.com/AndyObtiva/glimmer-dsl-swt).
16
-
17
- The trade-off is that while [SWT](https://www.eclipse.org/swt/) provides a plethora of high quality reusable widgets for the Enterprise (such as [Nebula](https://www.eclipse.org/nebula/)), [Tk](https://www.tcl.tk/) enables very fast app startup time and a small memory footprint via [MRI Ruby](https://www.ruby-lang.org/en/).
15
+ The trade-off is that while [SWT](https://www.eclipse.org/swt/) provides a plethora of high quality reusable widgets for the Enterprise (such as [Nebula](https://github.com/AndyObtiva/glimmer-cw-nebula)), [Tk](https://www.tcl.tk/) enables very fast app startup time and a small memory footprint via [MRI Ruby](https://www.ruby-lang.org/en/).
18
16
 
19
17
  [Glimmer DSL for Tk](https://github.com/AndyObtiva/glimmer-dsl-tk) aims to provide a DSL similar to the [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) to enable more productive desktop development in Ruby with:
20
18
  - Declarative DSL syntax that visually maps to the GUI widget hierarchy
@@ -76,11 +74,15 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
76
74
  - [Supported Widgets](#supported-widgets)
77
75
  - [Common Attributes](#common-attributes)
78
76
  - [Common Themed Widget States](#common-themed-widget-states)
77
+ - [Text Extra API Methods](#text-extra-api-methods)
79
78
  - [Smart Defaults and Conventions](#smart-defaults-and-conventions)
80
79
  - [Grid Layout](#grid-layout)
81
- - [Label/Button Image](#labelbutton-image)
80
+ - [Image Attribute](#image-attribute)
81
+ - [Frame Padding](#frame-padding)
82
82
  - [Notebook Frame](#notebook-frame)
83
83
  - [Icon Photo](#icon-photo)
84
+ - [Root Background](#root-background)
85
+ - [Text Defaults](#text-defaults)
84
86
  - [The Grid Geometry Manager](#the-grid-geometry-manager)
85
87
  - [Data-Binding](#data-binding)
86
88
  - [Label Data-Binding](#label-data-binding)
@@ -146,7 +148,7 @@ gem install glimmer-dsl-tk
146
148
 
147
149
  Add the following to `Gemfile`:
148
150
  ```
149
- gem 'glimmer-dsl-tk', '~> 0.0.26'
151
+ gem 'glimmer-dsl-tk', '~> 0.0.27'
150
152
  ```
151
153
 
152
154
  And, then run:
@@ -317,6 +319,59 @@ keyword(args) | attributes | event bindings & callbacks
317
319
  - `invalid?`
318
320
  - `hover?`
319
321
 
322
+ #### Text Extra API Methods
323
+
324
+ [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) automatically provides a `text` attribute for the `text` widget that enables updating its content simply without worrying about whether to manually insert by index, delete, or append.
325
+
326
+ Also, the `text` widget is enhanced by [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) to enable simpler manipulation of text options without dealing with [tags](https://tkdocs.com/tutorial/text.html) directly. Simply specify region to mutate and option/value or font_option/value, and [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) takes care of the rest by automating work of adding/removing [tags](https://tkdocs.com/tutorial/text.html) behind the scenes.
327
+
328
+ - `add_format(region_start, region_end, option, value)`
329
+ - `remove_format(region_start, region_end, option, value)`
330
+ - `toggle_format(region_start, region_end, option, value)`
331
+ - `add_font_format(region_start, region_end, font_option, value)`
332
+ - `remove_font_format(region_start, region_end, font_option, value)`
333
+ - `toggle_font_format(region_start, region_end, font_option, value)`
334
+ - `add_selection_format(region_start, region_end, option, value)`
335
+ - `remove_selection_format(region_start, region_end, option, value)`
336
+ - `toggle_selection_format(region_start, region_end, option, value)`
337
+ - `add_selection_font_format(region_start, region_end, font_option, value)`
338
+ - `remove_selection_font_format(region_start, region_end, font_option, value)`
339
+ - `toggle_selection_font_format(region_start, region_end, font_option, value)`
340
+
341
+ Available options:
342
+
343
+ - `background`
344
+ - `bgstipple`
345
+ - `borderwidth`
346
+ - `elide`
347
+ - `fgstipple`
348
+ - `foreground`
349
+ - `justify`
350
+ - `lmargin1`
351
+ - `lmargin2`
352
+ - `offset`
353
+ - `overstrike`
354
+ - `relief`
355
+ - `rmargin`
356
+ - `spacing1`
357
+ - `spacing2`
358
+ - `spacing3`
359
+ - `tabs`
360
+ - `tabstyle`
361
+ - `underline`
362
+ - `wrap`
363
+
364
+ Available font options:
365
+
366
+ - `family` (default: `'Courier New'`)
367
+ - `size` (default: `13`)
368
+ - `weight` (default: `'normal'`) (e.g. `'bold'`)
369
+ - `slant` (default: `'roman'`) (e.g. `'italic`')
370
+ - `underline` (default: `false`)
371
+ - `overstrike` (default: `false`)
372
+
373
+ Check out the [Hello, Text!](#hello-text) sample for a good demonstration of the `text` widget.
374
+
320
375
  ### Smart Defaults and Conventions
321
376
 
322
377
  #### Event Bindings
@@ -331,9 +386,13 @@ Also, any widget that is the first in a series of siblings has `column_weight` a
331
386
 
332
387
  To override that behavior, you may set alternative `grid` keyword args if needed (e.g. `grid sticky: '', column_weight: 0` disables the smart defaults).
333
388
 
334
- #### Label/Button Image
389
+ #### Image Attribute
335
390
 
336
- Label and Button `image` attribute can accept image path directly as an alternative to `TkPhotoImage` object in addition to key values for automatic processing of image (`subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`)
391
+ Widget `image` attribute (e.g. `label` `image`) can accept image path directly as an alternative to `TkPhotoImage` object in addition to key values for automatic processing of image (`subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`)
392
+
393
+ #### Frame Padding
394
+
395
+ Frames have a padding of `15` all around by default to produce more user-friendly graphical user interfaces.
337
396
 
338
397
  #### Notebook Frame
339
398
 
@@ -367,6 +426,12 @@ root {
367
426
 
368
427
  `root` `background` color attribute is automatically set to `'#ececec'` on the Mac to avoid having a non-native-looking light-colored background.
369
428
 
429
+ #### Text Defaults
430
+
431
+ `text` widget has these defaults:
432
+ - `wrap = 'none'`
433
+ - `font = {family: 'Courier New'}`
434
+
370
435
  ## The Grid Geometry Manager
371
436
 
372
437
  The Grid Geometry Manager is supported via the `grid` keyword just as per the [Tk documentation](https://tkdocs.com/tutorial/grid.html), except by nesting under the widget it concerns.
@@ -520,24 +585,6 @@ It automatically handles all the Tk plumbing behind the scenes.
520
585
 
521
586
  More details can be found in [Hello, Spinbox!](#hello-spinbox) sample below.
522
587
 
523
- ### Text Data-Binding
524
-
525
- Example:
526
-
527
- This assumes a `Person` model with a `address` attribute.
528
-
529
- ```ruby
530
- text {
531
- text <=> [person, :address]
532
- }
533
- ```
534
-
535
- That code binds the text content of `text` to the `address` attribute on the `person` model.
536
-
537
- It automatically handles all the Tk plumbing behind the scenes (including fine-grained inserts and deletes, abstracting them all away).
538
-
539
- More details can be found in [Glimmer Meta-Sample](#samples) below.
540
-
541
588
  ### Checkbutton Data-Binding
542
589
 
543
590
  Example:
@@ -1636,8 +1683,6 @@ Glimmer app:
1636
1683
 
1637
1684
  ### Hello, Text!
1638
1685
 
1639
- [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) automatically provides a `text` attribute for the `text` widget that enables updating its content simply without worrying about whether to manually insert by index, delete, or append.
1640
-
1641
1686
  Glimmer code (from [samples/hello/hello_text.rb](samples/hello/hello_text.rb)):
1642
1687
 
1643
1688
  ```ruby
@@ -1674,14 +1719,44 @@ class HelloText
1674
1719
  frame {
1675
1720
  grid row: 0, column: 0
1676
1721
 
1722
+ button {
1723
+ grid row: 0, column: 0, column_weight: 0
1724
+ text 'B'
1725
+ style font: {weight: 'bold'}
1726
+
1727
+ on('command') do
1728
+ @text.toggle_selection_font_format('weight', 'bold')
1729
+ end
1730
+ }
1731
+
1732
+ button {
1733
+ grid row: 0, column: 1, column_weight: 0
1734
+ text 'I'
1735
+ style font: {slant: 'italic'}
1736
+
1737
+ on('command') do
1738
+ @text.toggle_selection_font_format('slant', 'italic')
1739
+ end
1740
+ }
1741
+
1742
+ button {
1743
+ grid row: 0, column: 2, column_weight: 0
1744
+ text 'U'
1745
+ style font: {underline: true}
1746
+
1747
+ on('command') do
1748
+ @text.toggle_selection_font_format('underline', true)
1749
+ end
1750
+ }
1751
+
1677
1752
  combobox {
1678
- grid row: 0, column: 0, column_weight: 1
1753
+ grid row: 0, column: 4, column_weight: 1
1679
1754
  readonly true
1680
1755
  text <=> [self, :foreground, after_write: ->(value) { @text.add_selection_format('foreground', value == FOREGROUND_PROMPT ? 'black' : value) }]
1681
1756
  }
1682
1757
 
1683
1758
  combobox {
1684
- grid row: 0, column: 1, column_weight: 1
1759
+ grid row: 0, column: 5, column_weight: 1
1685
1760
  readonly true
1686
1761
  text <=> [self, :background, after_write: ->(value) { @text.add_selection_format('background', value == BACKGROUND_PROMPT ? 'black' : value) }]
1687
1762
  }
@@ -1689,6 +1764,7 @@ class HelloText
1689
1764
 
1690
1765
  @text = text {
1691
1766
  grid row: 1, column: 0, row_weight: 1
1767
+ wrap 'word'
1692
1768
  text <<~MULTI_LINE_STRING
1693
1769
  According to the National Post, a heavy metal-loving high school principal in Canada will be allowed to keep her job, days after a public campaign to oust her made headlines around the globe.
1694
1770
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.26
1
+ 0.0.27
Binary file
@@ -100,7 +100,7 @@ module Glimmer
100
100
 
101
101
  tag_names.select do |tag_name|
102
102
  @tk.tag_ranges(tag_name).any? do |range|
103
- if range.first.to_f <= region_start.to_f && range.last.to_f >= region_end.to_f
103
+ 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)
104
104
  @tk.tag_cget(tag_name, option) == value
105
105
  end
106
106
  end
@@ -120,7 +120,7 @@ module Glimmer
120
120
  @tk.tag_ranges(tag_name).any? do |range|
121
121
  if range.first.to_f.between?(region_start.to_f, region_end.to_f) or
122
122
  range.last.to_f.between?(region_start.to_f, region_end.to_f) or
123
- (range.first.to_f <= region_start.to_f && range.last.to_f >= region_end.to_f)
123
+ (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))
124
124
  @tk.tag_cget(tag_name, option) == value
125
125
  end
126
126
  end
@@ -141,44 +141,207 @@ module Glimmer
141
141
  add_format(region_start, region_end, option, value)
142
142
  end
143
143
  end
144
+
145
+ # TODO Algorithm for font option formatting
146
+ # for a region, grab all the latest tags for each subregion as well as the widget font for subregions without a tag
147
+ # for each part of the region covered by a tag, augment its font with new font option (or remove if that is what is needed)
148
+ # Once add and remove are implemented, implement toggle
149
+ # Also, there is a need for a method that checks if a font option value applies to an entire region (to decide which way to toggle with toggle method)
150
+ def applied_font_format?(region_start, region_end, font_option, value)
151
+ applied_font_format_tags_and_regions(region_start, region_end).all? do |tag, region_start, region_end|
152
+ if tag.nil?
153
+ @tk.font.send(font_option) == value
154
+ else
155
+ @tk.tag_cget(tag, 'font').send(font_option) == value
156
+ end
157
+ end
158
+ end
159
+
160
+ def applied_font_format_tags_and_regions(region_start, region_end)
161
+ lines = text.split("\n")
162
+ tags_and_regions = []
163
+ all_tag_names = @tk.tag_names - ['sel']
164
+ (region_start.to_i..region_end.to_i).each do |line_number|
165
+ start_character_index = 0
166
+ start_character_index = region_start.to_s.split('.').last.to_i if line_number == region_start.to_i
167
+ end_character_index = lines[line_number - 1].size
168
+ end_character_index = region_end.to_s.split('.').last.to_i if line_number == region_end.to_i
169
+ (start_character_index...end_character_index).each do |character_index|
170
+ text_index = "#{line_number}.#{character_index}"
171
+ # TODO reimplement the following using @tk.tag_names without arg since passing an arg seems broken and returns inaccurate results
172
+ region_tag = all_tag_names.reverse.find do |tag|
173
+ @tk.tag_cget(tag, 'font') && @tk.tag_ranges(tag).any? do |range_start, range_end|
174
+ 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)
175
+ end
176
+ end
177
+ end_text_index = add_to_text_index(text_index, 1)
178
+ if tags_and_regions&.last && region_tag == tags_and_regions.last.first
179
+ tags_and_regions.last[2] = end_text_index
180
+ else
181
+ tags_and_regions << [region_tag, text_index, end_text_index]
182
+ end
183
+ end
184
+ end
185
+ tags_and_regions
186
+ end
187
+
188
+ def add_font_format(region_start, region_end, font_option, value)
189
+ applied_font_format_tags_and_regions(region_start, region_end).each do |tag, tag_region_start, tag_region_end|
190
+ if tag
191
+ bigger_region_tag = @tk.tag_ranges(tag).any? do |range_start, range_end|
192
+ text_index_less_than_other_text_index?(range_start, tag_region_start) || text_index_greater_than_other_text_index?(range_end, tag_region_end)
193
+ end
194
+ if bigger_region_tag
195
+ @tk.tag_ranges(tag).each do |range_start, range_end|
196
+ if text_index_less_than_other_text_index?(range_start, tag_region_start) && text_index_less_than_or_equal_to_other_text_index?(range_end, tag_region_end) && text_index_greater_than_or_equal_to_other_text_index?(range_end, tag_region_start)
197
+ font = @tk.tag_cget(tag, 'font')
198
+ remove_format(range_start, range_end, 'font', font)
199
+ add_format(range_start, tag_region_start, 'font', font)
200
+ font_clone = clone_font(font)
201
+ font_clone.send("#{font_option}=", value)
202
+ add_format(tag_region_start, tag_region_end, 'font', font_clone)
203
+ elsif text_index_greater_than_other_text_index?(range_end, tag_region_end) && text_index_greater_than_or_equal_to_other_text_index?(range_start, tag_region_start) && text_index_less_than_or_equal_to_other_text_index?(range_start, tag_region_end)
204
+ font = @tk.tag_cget(tag, 'font')
205
+ remove_format(range_start, range_end, 'font', font)
206
+ add_format(tag_region_end, range_end, 'font', font)
207
+ font_clone = clone_font(font)
208
+ font_clone.send("#{font_option}=", value)
209
+ add_format(tag_region_start, tag_region_end, 'font', font_clone)
210
+ elsif text_index_less_than_other_text_index?(range_start, tag_region_start) && text_index_greater_than_other_text_index?(range_end, tag_region_end)
211
+ font = @tk.tag_cget(tag, 'font')
212
+ remove_format(range_start, range_end, 'font', font)
213
+ add_format(range_start, tag_region_start, 'font', font)
214
+ remove_format(range_start, range_end, 'font', font)
215
+ add_format(tag_region_end, range_end, 'font', font)
216
+ font_clone = clone_font(font)
217
+ font_clone.send("#{font_option}=", value)
218
+ add_format(tag_region_start, tag_region_end, 'font', font_clone)
219
+ end
220
+ end
221
+ else
222
+ current_font = @tk.tag_cget(tag, 'font')
223
+ current_font.send("#{font_option}=", value)
224
+ end
225
+ else
226
+ add_format(tag_region_start, tag_region_end, 'font', default_font_attributes.merge(font_option => value))
227
+ end
228
+ end
229
+ end
230
+
231
+ def remove_font_format(region_start, region_end, font_option, value)
232
+ applied_font_format_tags_and_regions(region_start, region_end).each do |tag, tag_region_start, tag_region_end|
233
+ if tag
234
+ bigger_region_tag = @tk.tag_ranges(tag).any? do |range_start, range_end|
235
+ text_index_less_than_other_text_index?(range_start, tag_region_start) || text_index_greater_than_other_text_index?(range_end, tag_region_end)
236
+ end
237
+ if bigger_region_tag
238
+ @tk.tag_ranges(tag).each do |range_start, range_end|
239
+ if text_index_less_than_other_text_index?(range_start, tag_region_start) && text_index_less_than_or_equal_to_other_text_index?(range_end, tag_region_end) && text_index_greater_than_or_equal_to_other_text_index?(range_end, tag_region_start)
240
+ font = @tk.tag_cget(tag, 'font')
241
+ remove_format(range_start, range_end, 'font', font)
242
+ add_format(range_start, subtract_from_text_index(tag_region_start, 1), 'font', font)
243
+ font_clone = clone_font(font)
244
+ font_clone.send("#{font_option}=", default_for_font_option(font_option))
245
+ add_format(tag_region_start, tag_region_end, 'font', font_clone)
246
+ elsif text_index_greater_than_other_text_index?(range_end, tag_region_end) && text_index_greater_than_or_equal_to_other_text_index?(range_start, tag_region_start) && text_index_less_than_or_equal_to_other_text_index?(range_start, tag_region_end)
247
+ font = @tk.tag_cget(tag, 'font')
248
+ remove_format(range_start, range_end, 'font', font)
249
+ add_format(add_to_text_index(tag_region_end, 1), range_end, 'font', font)
250
+ font_clone = clone_font(font)
251
+ font_clone.send("#{font_option}=", default_for_font_option(font_option))
252
+ add_format(tag_region_start, tag_region_end, 'font', font_clone)
253
+ elsif text_index_less_than_other_text_index?(range_start, tag_region_start) && text_index_greater_than_other_text_index?(range_end, tag_region_end)
254
+ font = @tk.tag_cget(tag, 'font')
255
+ remove_format(range_start, range_end, 'font', font)
256
+ add_format(range_start, subtract_from_text_index(tag_region_start, 1), 'font', font)
257
+ remove_format(range_start, range_end, 'font', font)
258
+ add_format(add_to_text_index(tag_region_end, 1), range_end, 'font', font)
259
+ font_clone = clone_font(font)
260
+ font_clone.send("#{font_option}=", default_for_font_option(font_option))
261
+ add_format(tag_region_start, tag_region_end, 'font', font_clone)
262
+ end
263
+ end
264
+ else
265
+ current_font = @tk.tag_cget(tag, 'font')
266
+ current_font.send("#{font_option}=", default_for_font_option(font_option))
267
+ end
268
+ else
269
+ add_format(tag_region_start, tag_region_end, 'font', default_font_attributes.merge(font_option => default_for_font_option(font_option)))
270
+ end
271
+ end
272
+ end
273
+
274
+ # toggles option/value tag (removes if already applied)
275
+ def toggle_font_format(region_start, region_end, option, value)
276
+ if applied_font_format?(region_start, region_end, option, value)
277
+ remove_font_format(region_start, region_end, option, value)
278
+ else
279
+ add_font_format(region_start, region_end, option, value)
280
+ end
281
+ end
282
+
283
+ def default_for_font_option(font_option)
284
+ @tk.font.send(font_option)
285
+ end
286
+
287
+ def default_font_attributes
288
+ Hash[@tk.font.actual]
289
+ end
290
+
291
+ def add_to_text_index(text_index, addition)
292
+ text_index_parts = text_index.split('.')
293
+ line = text_index_parts.first
294
+ char_index = text_index_parts.last
295
+ char_index = char_index.to_i + addition
296
+ "#{line}.#{char_index}"
297
+ end
144
298
 
145
- # def applied_font_format?(region_start, region_end, option, value)
146
- # !applied_font_format_tags(region_start, region_end, option, value).empty?
147
- # end
148
- #
149
- # def applied_font_format_tags(region_start, region_end, option, value)
150
- # tag_names = @tk.tag_names - ['sel']
151
- #
152
- # tag_names.select do |tag_name|
153
- # @tk.tag_ranges(tag_name).any? do |range|
154
- # if range.first.to_f <= region_start.to_f && range.last.to_f >= region_end.to_f
155
- # @tk.tag_cget(tag_name, option) == value
156
- # end
157
- # end
158
- # end
159
- # end
160
- #
161
- # def add_font_format(region_start, region_end, option, value)
162
- # end
163
- #
164
- # def remove_font_format(region_start, region_end, option, value)
165
- # end
166
- #
167
- ### toggles option/value tag (removes if already applied)
168
- # def toggle_font_format(region_start, region_end, option, value)
169
- # if applied_font_format?(region_start, region_end, option, value)
170
- ### ensure removing from previous font combination (perhaps checking widget font too)
171
- # remove_font_format(region_start, region_end, option, value)
172
- # else
173
- ### ensure adding to previous font combination (perhaps checking widget font too)
174
- # add_font_format(region_start, region_end, option, value)
175
- # end
176
- # end
299
+ def subtract_from_text_index(text_index, subtraction)
300
+ add_to_text_index(text_index, -1 * subtraction)
301
+ end
302
+
303
+ def text_index_less_than_other_text_index?(region1, region2)
304
+ region1_parts = region1.to_s.split('.')
305
+ region2_parts = region2.to_s.split('.')
306
+ return true if region1_parts.first.to_i < region2_parts.first.to_i
307
+ return false if region1_parts.first.to_i > region2_parts.first.to_i
308
+ region1_parts.last.to_i < region2_parts.last.to_i
309
+ end
310
+
311
+ def text_index_less_than_or_equal_to_other_text_index?(region1, region2)
312
+ region1_parts = region1.to_s.split('.')
313
+ region2_parts = region2.to_s.split('.')
314
+ return true if region1_parts.first.to_i < region2_parts.first.to_i
315
+ return false if region1_parts.first.to_i > region2_parts.first.to_i
316
+ region1_parts.last.to_i <= region2_parts.last.to_i
317
+ end
318
+
319
+ def text_index_greater_than_other_text_index?(region1, region2)
320
+ region1_parts = region1.to_s.split('.')
321
+ region2_parts = region2.to_s.split('.')
322
+ return true if region1_parts.first.to_i > region2_parts.first.to_i
323
+ return false if region1_parts.first.to_i < region2_parts.first.to_i
324
+ region1_parts.last.to_i > region2_parts.last.to_i
325
+ end
326
+
327
+ def text_index_greater_than_or_equal_to_other_text_index?(region1, region2)
328
+ region1_parts = region1.to_s.split('.')
329
+ region2_parts = region2.to_s.split('.')
330
+ return true if region1_parts.first.to_i > region2_parts.first.to_i
331
+ return false if region1_parts.first.to_i < region2_parts.first.to_i
332
+ region1_parts.last.to_i >= region2_parts.last.to_i
333
+ end
334
+
335
+ def clone_font(font)
336
+ ::TkFont.new(Hash[font.actual])
337
+ end
177
338
 
178
339
  private
179
340
 
180
341
  def initialize_defaults
181
342
  super
343
+ self.font = {family: 'Courier New'}
344
+ self.wrap = 'none'
182
345
  self.padx = 5
183
346
  self.pady = 5
184
347
  end
@@ -34,7 +34,9 @@ module Glimmer
34
34
  begin
35
35
  class_name = "#{keyword.camelcase(:upper)}Proxy".to_sym
36
36
  Glimmer::Tk.const_get(class_name)
37
- rescue
37
+ rescue => e
38
+ Glimmer::Config.logger.debug {"Unable to instantiate custom class name for #{keyword} ... defaulting to Glimmer::Tk::WidgetProxy"}
39
+ Glimmer::Config.logger.debug {e.full_message}
38
40
  Glimmer::Tk::WidgetProxy
39
41
  end
40
42
  end
@@ -54,7 +56,7 @@ module Glimmer
54
56
  tk_widget_class = eval(tk_widget_name)
55
57
  break
56
58
  rescue RuntimeError, SyntaxError, NameError => e
57
- Glimmer::Config.logger.debug e.full_message
59
+ Glimmer::Config.logger.debug {e.full_message}
58
60
  end
59
61
  end
60
62
  tk_widget_class if tk_widget_class.respond_to?(:new)
@@ -104,6 +106,8 @@ module Glimmer
104
106
  @tk.send(attribute_setter(attribute), @tk.send(attribute))
105
107
  result = true
106
108
  rescue => e
109
+ Glimmer::Config.logger.debug { "No tk attribute setter for #{attribute}" }
110
+ Glimmer::Config.logger.debug { e.full_message }
107
111
  result = false
108
112
  end
109
113
  result
@@ -114,7 +118,8 @@ module Glimmer
114
118
  # TK Widget currently doesn't support respond_to? properly, so I have to resort to this trick for now
115
119
  @tk.send(attribute)
116
120
  true
117
- rescue
121
+ rescue => e
122
+ Glimmer::Config.logger.debug { "No tk attribute getter setter for #{attribute}" }
118
123
  false
119
124
  end
120
125
  end
@@ -125,7 +130,8 @@ module Glimmer
125
130
  begin
126
131
  @tk.tile_instate(attribute)
127
132
  true
128
- rescue
133
+ rescue => e
134
+ Glimmer::Config.logger.debug { "No tk state for #{attribute}" }
129
135
  false
130
136
  end
131
137
  else
@@ -247,7 +253,7 @@ module Glimmer
247
253
 
248
254
  def apply_style(options)
249
255
  @@style_number = 0 unless defined?(@@style_number)
250
- style = "style#{@@style_number}.#{@tk.class.name.split('::').last}"
256
+ style = "style#{@@style_number += 1}.#{@tk.class.name.split('::').last}"
251
257
  ::Tk::Tile::Style.configure(style, options)
252
258
  @tk.style = style
253
259
  end
@@ -52,14 +52,44 @@ class HelloText
52
52
  frame {
53
53
  grid row: 0, column: 0
54
54
 
55
+ button {
56
+ grid row: 0, column: 0, column_weight: 0
57
+ text 'B'
58
+ style font: {weight: 'bold'}
59
+
60
+ on('command') do
61
+ @text.toggle_selection_font_format('weight', 'bold')
62
+ end
63
+ }
64
+
65
+ button {
66
+ grid row: 0, column: 1, column_weight: 0
67
+ text 'I'
68
+ style font: {slant: 'italic'}
69
+
70
+ on('command') do
71
+ @text.toggle_selection_font_format('slant', 'italic')
72
+ end
73
+ }
74
+
75
+ button {
76
+ grid row: 0, column: 2, column_weight: 0
77
+ text 'U'
78
+ style font: {underline: true}
79
+
80
+ on('command') do
81
+ @text.toggle_selection_font_format('underline', true)
82
+ end
83
+ }
84
+
55
85
  combobox {
56
- grid row: 0, column: 0, column_weight: 1
86
+ grid row: 0, column: 4, column_weight: 1
57
87
  readonly true
58
88
  text <=> [self, :foreground, after_write: ->(value) { @text.add_selection_format('foreground', value == FOREGROUND_PROMPT ? 'black' : value) }]
59
89
  }
60
90
 
61
91
  combobox {
62
- grid row: 0, column: 1, column_weight: 1
92
+ grid row: 0, column: 5, column_weight: 1
63
93
  readonly true
64
94
  text <=> [self, :background, after_write: ->(value) { @text.add_selection_format('background', value == BACKGROUND_PROMPT ? 'black' : value) }]
65
95
  }
@@ -67,6 +97,7 @@ class HelloText
67
97
 
68
98
  @text = text {
69
99
  grid row: 1, column: 0, row_weight: 1
100
+ wrap 'word'
70
101
  text <<~MULTI_LINE_STRING
71
102
  According to the National Post, a heavy metal-loving high school principal in Canada will be allowed to keep her job, days after a public campaign to oust her made headlines around the globe.
72
103
 
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.26
4
+ version: 0.0.27
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-18 00:00:00.000000000 Z
11
+ date: 2021-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -288,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
288
288
  - !ruby/object:Gem::Version
289
289
  version: '0'
290
290
  requirements: []
291
- rubygems_version: 3.2.22
291
+ rubygems_version: 3.2.29
292
292
  signing_key:
293
293
  specification_version: 4
294
294
  summary: Glimmer DSL for Tk