glimmer-dsl-tk 0.0.26 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +107 -31
- data/VERSION +1 -1
- data/glimmer-dsl-tk.gemspec +0 -0
- data/lib/glimmer/tk/text_proxy.rb +197 -34
- data/lib/glimmer/tk/widget_proxy.rb +11 -5
- data/samples/hello/hello_text.rb +33 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73b915eb9db0314df3594942c5c4a1205d3ae63a923f01e4dee9f3ee03c75ac0
|
4
|
+
data.tar.gz: 31f1293d6d56d4966207a00b2aa453775adc51ab86aaf71f4dc40bfa5e0dabda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
[](http://badge.fury.io/rb/glimmer-dsl-tk)
|
4
4
|
[](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
|
-
|
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
|
-
- [
|
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.
|
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
|
-
####
|
389
|
+
#### Image Attribute
|
335
390
|
|
336
|
-
|
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:
|
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:
|
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.
|
1
|
+
0.0.27
|
data/glimmer-dsl-tk.gemspec
CHANGED
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
|
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
|
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
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
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
|
data/samples/hello/hello_text.rb
CHANGED
@@ -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:
|
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:
|
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.
|
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-
|
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.
|
291
|
+
rubygems_version: 3.2.29
|
292
292
|
signing_key:
|
293
293
|
specification_version: 4
|
294
294
|
summary: Glimmer DSL for Tk
|