glimmer-dsl-tk 0.0.24 → 0.0.28

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.
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.24
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.28
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/) has a very fast app startup time and a small memory footprint courtesy of [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,18 +74,23 @@ 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)
79
- - [Smart Defaults and Convensions](#smart-defaults-and-convensions)
77
+ - [Text API](#text-api)
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
- - [Bidirectional Data-Binding](#bidirectional-data-binding)
87
+ - [Data-Binding](#data-binding)
86
88
  - [Label Data-Binding](#label-data-binding)
87
89
  - [Combobox Data-Binding](#combobox-data-binding)
88
90
  - [List Single Selection Data-Binding](#list-single-selection-data-binding)
89
91
  - [List Multi Selection Data-Binding](#list-multi-selection-data-binding)
90
92
  - [Entry Data-Binding](#entry-data-binding)
93
+ - [Spinbox Data-Binding](#spinbox-data-binding)
91
94
  - [Checkbutton Data-Binding](#checkbutton-data-binding)
92
95
  - [Radiobutton Data-Binding](#radiobutton-data-binding)
93
96
  - [Command Callback](#command-callback)
@@ -106,7 +109,10 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
106
109
  - [Hello, List Single Selection!](#hello-list-single-selection)
107
110
  - [Hello, List Multi Selection!](#hello-list-multi-selection)
108
111
  - [Hello, Entry!](#hello-entry)
112
+ - [Hello, Text!](#hello-text)
113
+ - [Hello, Spinbox!](#hello-spinbox)
109
114
  - [Hello, Computed!](#hello-computed)
115
+ - [Hello, Drag and Drop!](#hello-drag-and-drop)
110
116
  - [Help](#help)
111
117
  - [Issues](#issues)
112
118
  - [Chat](#chat)
@@ -143,7 +149,7 @@ gem install glimmer-dsl-tk
143
149
 
144
150
  Add the following to `Gemfile`:
145
151
  ```
146
- gem 'glimmer-dsl-tk', '~> 0.0.24'
152
+ gem 'glimmer-dsl-tk', '~> 0.0.28'
147
153
  ```
148
154
 
149
155
  And, then run:
@@ -256,6 +262,7 @@ keyword(args) | attributes | event bindings & callbacks
256
262
  `checkbutton` | `text`, `variable` (Boolean), `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `onvalue` (default: `1`), `offvalue` (default: `0`) | `command {}`
257
263
  `combobox` | `state`, `text` | `'ComboboxSelected'`
258
264
  `entry` | `width`, `text`, `validate`, `show` (`'none', 'focus', 'focusin', 'focusout', 'key', or 'all'`) | `'validate'`, `'invalid'`, `'change'`, `validatecommand {}`, `invalidcommand {}`
265
+ `spinbox` | `text`, `from`, `to`, `increment`, `format`, [more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `command {}`, `'increment'`, `'decrement'`
259
266
  `frame(text: nil)` | `width`, `height`, `borderwidth`, `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`) | None
260
267
  `label` | `text`, `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `font` (`'default', 'text', 'fixed', 'menu', 'heading', 'caption', 'small_caption', 'icon', 'tooltip'`), `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`), `justify` (`'left', 'center', 'right'`), `foreground`, `background` | None
261
268
  `list` | `selectmode`, `selection` | None
@@ -263,6 +270,7 @@ keyword(args) | attributes | event bindings & callbacks
263
270
  `notebook` | None | None
264
271
  `radiobutton` | `text`, `variable` (Boolean), `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `value` (default: `text`) | `command {}`
265
272
  `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'`
273
+ `text` | `text`, [many more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `'modified'`, `'selection'`
266
274
 
267
275
  #### Common Attributes
268
276
 
@@ -312,7 +320,68 @@ keyword(args) | attributes | event bindings & callbacks
312
320
  - `invalid?`
313
321
  - `hover?`
314
322
 
315
- ### Smart Defaults and Convensions
323
+ #### Text API
324
+
325
+ [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.
326
+
327
+ 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.
328
+
329
+ - `add_format(region_start, region_end, option, value)`
330
+ - `remove_format(region_start, region_end, option, value)`
331
+ - `toggle_format(region_start, region_end, option, value)`
332
+ - `add_font_format(region_start, region_end, font_option, value)`
333
+ - `remove_font_format(region_start, region_end, font_option, value)`
334
+ - `toggle_font_format(region_start, region_end, font_option, value)`
335
+ - `add_selection_format(region_start, region_end, option, value)`
336
+ - `remove_selection_format(region_start, region_end, option, value)`
337
+ - `toggle_selection_format(region_start, region_end, option, value)`
338
+ - `add_selection_font_format(region_start, region_end, font_option, value)`
339
+ - `remove_selection_font_format(region_start, region_end, font_option, value)`
340
+ - `toggle_selection_font_format(region_start, region_end, font_option, value)`
341
+
342
+ Available options:
343
+
344
+ - `background`
345
+ - `bgstipple`
346
+ - `borderwidth`
347
+ - `elide`
348
+ - `fgstipple`
349
+ - `foreground`
350
+ - `justify`
351
+ - `lmargin1`
352
+ - `lmargin2`
353
+ - `offset`
354
+ - `overstrike`
355
+ - `relief`
356
+ - `rmargin`
357
+ - `spacing1`
358
+ - `spacing2`
359
+ - `spacing3`
360
+ - `tabs`
361
+ - `tabstyle`
362
+ - `underline`
363
+ - `wrap`
364
+
365
+ Available font options:
366
+
367
+ - `family` (default: `'Courier New'`)
368
+ - `size` (default: `13`)
369
+ - `weight` (default: `'normal'`) (e.g. `'bold'`)
370
+ - `slant` (default: `'roman'`) (e.g. `'italic`')
371
+ - `underline` (default: `false`)
372
+ - `overstrike` (default: `false`)
373
+
374
+ Other useful built-in API methods:
375
+
376
+ - `text_cut`
377
+ - `text_copy`
378
+ - `text_paste`
379
+ - `text_edit_undo`
380
+ - `text_edit_redo`
381
+
382
+ Check out the [Hello, Text!](#hello-text) sample for a good demonstration of the `text` widget features.
383
+
384
+ ### Smart Defaults and Conventions
316
385
 
317
386
  #### Event Bindings
318
387
 
@@ -320,11 +389,25 @@ Any events that normally can be accepted by the Tk `bind` or `protocol` methods
320
389
 
321
390
  #### Grid Layout
322
391
 
323
- `grid` layout is the default on most widgets (which support it).
392
+ `grid` layout with `sticky: 'nsew'` is the default on all widgets except toplevel widgets.
393
+
394
+ Also, any widget that is the first in a series of siblings has `column_weight` as `1` to automatically resize with window resizing by default.
395
+
396
+ To override that behavior, you may set alternative `grid` keyword args if needed (e.g. `grid sticky: '', column_weight: 0` disables the smart defaults).
324
397
 
325
- #### Label/Button Image
398
+ #### Image Attribute
326
399
 
327
- 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`)
400
+ 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:
401
+ - `subsample(x_divider, y_divider)`: Specifies that the source image should be reduced in size by using only every xth pixel in the X direction and yth pixel in the Y direction. Negative values will cause the image to be flipped about the Y or X axes, respectively. If y is not given, the default value is the same as x.
402
+ - `zoom(x_multiplier, y_multiplier)`: Specifies that the source region should be magnified by a factor of x in the X direction and y in the Y direction. If y is not given, the default value is the same as x. With this option, each pixel in the source image will be expanded into a block of x x y pixels in the destination image, all the same color. x and y must be greater than 0.
403
+ - `from(x1, y1, x2, y2)`: Specifies a rectangular sub-region of the source image to be copied. (x1,y1) and (x2,y2) specify diagonally opposite corners of the rectangle. If x2 and y2 are not specified, the default value is the bottom-right corner of the source image. The pixels copied will include the left and top edges of the specified rectangle but not the bottom or right edges. If the :from option is not given, the default is the whole source image.
404
+ - `to(x1, y1, x2, y2)`: Specifies a rectangular sub-region of the destination image to be affected. (x1,y1) and (x2,y2) specify diagonally opposite corners of the rectangle. If x2 and y2 are not specified, the default value is (x1,y1) plus the size of the source region (after subsampling and zooming, if specified). If x2 and y2 are specified, the source region will be replicated if necessary to fill the destination region in a tiled fashion.
405
+ - `shrink`: Specifies that the size of the destination image should be reduced, if necessary, so that the region being copied into is at the bottom-right corner of the image. This option will not affect the width or height of the image if the user has specified a non-zero value for the :width or :height configuration option, respectively.
406
+ - `compositingrule` (can be `'overlay'` or `'set'`): Specifies how transparent pixels in the source image are combined with the destination image. When a compositing rule of <tt>overlay</tt> is set, the old contents of the destination image are visible, as if the source image were printed on a piece of transparent film and placed over the top of the destination. When a compositing rule of <tt>set</tt> is set, the old contents of the destination image are discarded and the source image is used as-is. The default compositing rule is <tt>overlay</tt>.
407
+
408
+ #### Frame Padding
409
+
410
+ Frames have a padding of `15` all around by default to produce more user-friendly graphical user interfaces.
328
411
 
329
412
  #### Notebook Frame
330
413
 
@@ -354,6 +437,16 @@ root {
354
437
  }.open
355
438
  ```
356
439
 
440
+ #### Root Background
441
+
442
+ `root` `background` color attribute is automatically set to `'#ececec'` on the Mac to avoid having a non-native-looking light-colored background.
443
+
444
+ #### Text Defaults
445
+
446
+ `text` widget has these defaults:
447
+ - `wrap = 'none'`
448
+ - `font = {family: 'Courier New'}`
449
+
357
450
  ## The Grid Geometry Manager
358
451
 
359
452
  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.
@@ -372,9 +465,17 @@ Example:
372
465
  }
373
466
  ```
374
467
 
468
+ Extra convenience options may be passed to `grid` when using [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk):
469
+ - `min_width`: alias for `columnminsize` being called on `TkGrid.columnconfigure`
470
+ - `min_height`: alias for `rowminsize` being called on `TkGrid.rowconfigure`
471
+ - `column_weight`: alias for `columnweight` being called on `TkGrid.columnconfigure`
472
+ - `row_weight`: alias for `rowweight` being called on `TkGrid.rowconfigure`
473
+
474
+ Note also the [Grid Layout](#grid-layout) conventions (e.g. `column_weight` is automatically set to `1` for the first widget in a series of siblings to automatically have all resize when window resize)
475
+
375
476
  More details can be found in the [Hello, Computed!](#hello-computed) sample below.
376
477
 
377
- ## Bidirectional Data-Binding
478
+ ## Data-Binding
378
479
 
379
480
  Glimmer supports Shine syntax bidirectional data-binding via the `<=>` operator (read-write) and unidirectional data-binding via the `<=` operator (read-only), which takes a model and an attribute (the `bind` keyword may also be used as the old-style of data-binding).
380
481
 
@@ -404,7 +505,7 @@ This assumes a `Person` model with a `country` attribute representing their curr
404
505
 
405
506
  ```ruby
406
507
  combobox {
407
- state 'readonly'
508
+ readonly true # this applies to text editing only (item selection still triggers a write to model)
408
509
  text <=> [person, :country]
409
510
  }
410
511
  ```
@@ -477,6 +578,28 @@ It automatically handles all the Tk plumbing behind the scenes.
477
578
 
478
579
  More details can be found in [Hello, Entry!](#hello-entry) and [Hello, Computed!](#hello-computed) samples below.
479
580
 
581
+ ### Spinbox Data-Binding
582
+
583
+ Example:
584
+
585
+ This assumes a `Person` model with a `donation` attribute.
586
+
587
+ ```ruby
588
+ spinbox {
589
+ from 1.0 # minimum value
590
+ to 150.0 # maximum value
591
+ increment 5.0 # increment on up and down
592
+ format '%0.2f'
593
+ text <=> [person, :country]
594
+ }
595
+ ```
596
+
597
+ That code binds the `textvariable` value of the `spinbox` to the `donation` attribute on the `person` model.
598
+
599
+ It automatically handles all the Tk plumbing behind the scenes.
600
+
601
+ More details can be found in [Hello, Spinbox!](#hello-spinbox) sample below.
602
+
480
603
  ### Checkbutton Data-Binding
481
604
 
482
605
  Example:
@@ -525,7 +648,7 @@ More details can be found in the [Hello, Radiobutton!](#hello-radiobutton) sampl
525
648
 
526
649
  ## Command Callback
527
650
 
528
- `button` and `checkbutton` can set a `command` block to trigger when the user clicks the button/checkbutton. This may be done with the `command` keyword, passing in a block directly.
651
+ `button`, `spinbox`, `radiobutton` and `checkbutton` can set a `command` block to trigger when the user clicks the button/checkbutton. This may be done with the `command` keyword, passing in a block directly.
529
652
 
530
653
  Example:
531
654
 
@@ -539,6 +662,18 @@ Example:
539
662
  }
540
663
  ```
541
664
 
665
+ Alternatively, it can be treated as simply an event for consistency with other event bindings:
666
+
667
+ ```ruby
668
+ button {
669
+ text "Reset Selection"
670
+
671
+ on('command') do
672
+ person.reset_country
673
+ end
674
+ }
675
+ ```
676
+
542
677
  More details can be found in the [Hello, Button!](#hello-button) sample below.
543
678
 
544
679
  ## Gotchas
@@ -547,6 +682,22 @@ More details can be found in the [Hello, Button!](#hello-button) sample below.
547
682
 
548
683
  ## Samples
549
684
 
685
+ The easiest way to run samples is by launching the Glimmer Meta-Sample (the Sample of Samples).
686
+
687
+ Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
688
+
689
+ ```
690
+ ruby -r glimmer-dsl-tk -e "require 'samples/elaborate/meta_sample'"
691
+ ```
692
+
693
+ Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
694
+
695
+ ```
696
+ ruby -r ./lib/glimmer-dsl-tk.rb samples/elaborate/meta_sample.rb
697
+ ```
698
+
699
+ ![glimmer dsl tk screenshot sample meta sample](images/glimmer-dsl-tk-screenshot-sample-elaborate-meta-sample.png)
700
+
550
701
  ### Hello, World!
551
702
 
552
703
  Glimmer code (from [samples/hello/hello_world.rb](samples/hello/hello_world.rb)):
@@ -1107,6 +1258,8 @@ Glimmer app:
1107
1258
 
1108
1259
  ### Hello, Label!
1109
1260
 
1261
+ 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>
1262
+
1110
1263
  Glimmer code (from [samples/hello/hello_label.rb](samples/hello/hello_label.rb)):
1111
1264
 
1112
1265
  ```ruby
@@ -1329,12 +1482,12 @@ Glimmer code (from [samples/hello/hello_combobox.rb](samples/hello/hello_combobo
1329
1482
  root {
1330
1483
  title 'Hello, Combobox!'
1331
1484
 
1332
- combobox { |proxy|
1333
- state 'readonly'
1485
+ combobox {
1486
+ readonly true # this applies to text editing only (item selection still triggers a write to model)
1334
1487
  text <=> [person, :country]
1335
1488
  }
1336
1489
 
1337
- button { |proxy|
1490
+ button {
1338
1491
  text "Reset Selection"
1339
1492
  command {
1340
1493
  person.reset_country
@@ -1438,86 +1591,6 @@ Glimmer app:
1438
1591
 
1439
1592
  ![glimmer dsl tk screenshot sample hello list multi selection](images/glimmer-dsl-tk-screenshot-sample-hello-list-multi-selection.png)
1440
1593
 
1441
- ### Hello, Computed!
1442
-
1443
- Glimmer code (from [samples/hello/hello_computed.rb](samples/hello/hello_computed.rb)):
1444
-
1445
- ```ruby
1446
- # ... more code precedes
1447
- root {
1448
- title 'Hello, Computed!'
1449
-
1450
- frame {
1451
- grid column: 0, row: 0, padx: 5, pady: 5
1452
-
1453
- label {
1454
- grid column: 0, row: 0, sticky: 'w'
1455
- text 'First Name: '
1456
- }
1457
- entry {
1458
- grid column: 1, row: 0
1459
- width 15
1460
- text <=> [@contact, :first_name]
1461
- }
1462
-
1463
- label {
1464
- grid column: 0, row: 1, sticky: 'w'
1465
- text 'Last Name: '
1466
- }
1467
- entry {
1468
- grid column: 1, row: 1
1469
- width 15
1470
- text <=> [@contact, :last_name]
1471
- }
1472
-
1473
- label {
1474
- grid column: 0, row: 2, sticky: 'w'
1475
- text 'Year of Birth: '
1476
- }
1477
- entry {
1478
- grid column: 1, row: 2
1479
- width 15
1480
- text <=> [@contact, :year_of_birth]
1481
- }
1482
-
1483
- label {
1484
- grid column: 0, row: 3, sticky: 'w'
1485
- text 'Name: '
1486
- }
1487
- label {
1488
- grid column: 1, row: 3, sticky: 'w'
1489
- text <=> [@contact, :name, computed_by: [:first_name, :last_name]]
1490
- }
1491
-
1492
- label {
1493
- grid column: 0, row: 4, sticky: 'w'
1494
- text 'Age: '
1495
- }
1496
- label {
1497
- grid column: 1, row: 4, sticky: 'w'
1498
- text <=> [@contact, :age, on_write: :to_i, computed_by: [:year_of_birth]]
1499
- }
1500
- }
1501
- }.open
1502
- # ... more code follows
1503
- ```
1504
-
1505
- Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
1506
-
1507
- ```
1508
- ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_computed'"
1509
- ```
1510
-
1511
- Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
1512
-
1513
- ```
1514
- ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_computed.rb
1515
- ```
1516
-
1517
- Glimmer app:
1518
-
1519
- ![glimmer dsl tk screenshot sample hello computed](images/glimmer-dsl-tk-screenshot-sample-hello-computed.png)
1520
-
1521
1594
  ### Hello, Entry!
1522
1595
 
1523
1596
  Glimmer code (from [samples/hello/hello_entry.rb](samples/hello/hello_entry.rb)):
@@ -1542,7 +1615,7 @@ class HelloEntry
1542
1615
  title 'Hello, Entry!'
1543
1616
 
1544
1617
  label {
1545
- grid sticky: 'ew', column_weight: 1
1618
+ grid sticky: 'ew'
1546
1619
  text 'default entry'
1547
1620
  }
1548
1621
  entry {
@@ -1625,6 +1698,219 @@ Glimmer app:
1625
1698
  ![glimmer dsl tk screenshot sample hello entry](images/glimmer-dsl-tk-screenshot-sample-hello-entry.png)
1626
1699
  ![glimmer dsl tk screenshot sample hello entry validated](images/glimmer-dsl-tk-screenshot-sample-hello-entry-validated.png)
1627
1700
 
1701
+ ### Hello, Text!
1702
+
1703
+ 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>
1704
+
1705
+ Glimmer code (from [samples/hello/hello_text.rb](samples/hello/hello_text.rb)):
1706
+
1707
+ ```ruby
1708
+ require 'glimmer-dsl-tk'
1709
+
1710
+ class HelloText
1711
+ include Glimmer
1712
+
1713
+ COLOR_OPTIONS = %w[black purple blue green orange yellow red white].map(&:capitalize)
1714
+ FOREGROUND_PROMPT = '<select foreground>'
1715
+ BACKGROUND_PROMPT = '<select background>'
1716
+
1717
+ def initialize
1718
+ @foreground = FOREGROUND_PROMPT
1719
+ @background = BACKGROUND_PROMPT
1720
+ end
1721
+
1722
+ attr_accessor :foreground
1723
+
1724
+ def foreground_options
1725
+ [FOREGROUND_PROMPT] + COLOR_OPTIONS
1726
+ end
1727
+
1728
+ attr_accessor :background
1729
+
1730
+ def background_options
1731
+ [BACKGROUND_PROMPT] + COLOR_OPTIONS
1732
+ end
1733
+
1734
+ def launch
1735
+ root {
1736
+ title 'Hello, Text!'
1737
+
1738
+ frame {
1739
+ grid row: 0, column: 0
1740
+
1741
+ button {
1742
+ grid row: 0, column: 0, column_weight: 0
1743
+ text 'B'
1744
+ style font: {weight: 'bold'}
1745
+
1746
+ on('command') do
1747
+ @text.toggle_selection_font_format('weight', 'bold')
1748
+ end
1749
+ }
1750
+
1751
+ button {
1752
+ grid row: 0, column: 1, column_weight: 0
1753
+ text 'I'
1754
+ style font: {slant: 'italic'}
1755
+
1756
+ on('command') do
1757
+ @text.toggle_selection_font_format('slant', 'italic')
1758
+ end
1759
+ }
1760
+
1761
+ button {
1762
+ grid row: 0, column: 2, column_weight: 0
1763
+ text 'U'
1764
+ style font: {underline: true}
1765
+
1766
+ on('command') do
1767
+ @text.toggle_selection_font_format('underline', true)
1768
+ end
1769
+ }
1770
+
1771
+ combobox {
1772
+ grid row: 0, column: 4, column_weight: 1
1773
+ readonly true
1774
+ text <=> [self, :foreground, after_write: ->(value) { @text.add_selection_format('foreground', value == FOREGROUND_PROMPT ? 'black' : value) }]
1775
+ }
1776
+
1777
+ combobox {
1778
+ grid row: 0, column: 5, column_weight: 1
1779
+ readonly true
1780
+ text <=> [self, :background, after_write: ->(value) { @text.add_selection_format('background', value == BACKGROUND_PROMPT ? 'black' : value) }]
1781
+ }
1782
+ }
1783
+
1784
+ @text = text {
1785
+ grid row: 1, column: 0, row_weight: 1
1786
+ wrap 'word'
1787
+ text <<~MULTI_LINE_STRING
1788
+ 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.
1789
+
1790
+ Parents at Eden High School in St. Catharines, Ontario launched a petition to remove principal Sharon Burns after discovering she's an IRON MAIDEN fan.
1791
+
1792
+ The petition, titled "Eden High School Principal, Sharon Burns, Needs to Be Transferred Immediately!" read, "We are deeply disturbed that the principal assigned to the school blatantly showed Satanic symbols and her allegiance to Satanic practices on her public social media platforms where all the students can see them under @edenprincipal (not her personal account)."
1793
+
1794
+ More than 500 people signed the petition to transfer Burns after she posted a picture of herself flashing the "devil horns" hand sign with a doll of the MAIDEN zombie mascot Eddie behind her as well as a personalized license plate reading "IRNMADEN" and a handwritten note that reads "Eddie 666" on a car's dashboard.
1795
+
1796
+
1797
+ The number 666 is used to represent the devil, and is featured prominently in MAIDEN's artwork by the band, whose classic third album is titled "The Number Of The Beast".
1798
+
1799
+ The petition was later updated to state that the demand for her transfer is not because of her love for metal, but for "openly displaying her own handmade sign with the 666 clearly displayed on it".
1800
+
1801
+ The creator of the original petition wrote: "Sharon knows full well what she did was simply inappropriate, unnecessary and not professional but has yet to publicly admit so and is willing to allow people to believe a completely different story, making very real concerns seem petty."
1802
+
1803
+ Meanwhile, a counter-petition supporting Burns garnered over 20,000 signatures.
1804
+
1805
+ "It is ridiculous that a couple of parents judge her role as a principal only based on an Instagram post. (About liking the band IRON MAIDEN. That's it.) Eden High School is a public school. Not a Christian school," the petition titled "We need Mrs Burns" stated. "She has made Eden a safe space for so many people. She spreads nothing but love and kindness."
1806
+
1807
+ After the complaints were aired, the District School Board of Niagara spoke with Burns and the parents who launched the petition, and the issue is over as far as the board is concerned, Kim Sweeney, the board's chief communications officer, told the National Post. No disciplinary action or policy changes were needed.
1808
+
1809
+ "Our belief is that taste in music is subjective and we support that both students and staff enjoy a wide variety of genres," Sweeney said.
1810
+
1811
+ The original petition has since been removed.
1812
+ MULTI_LINE_STRING
1813
+ }
1814
+ }.open
1815
+ end
1816
+ end
1817
+
1818
+ HelloText.new.launch
1819
+ ```
1820
+
1821
+ Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
1822
+
1823
+ ```
1824
+ ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_text'"
1825
+ ```
1826
+
1827
+ Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
1828
+
1829
+ ```
1830
+ ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_text.rb
1831
+ ```
1832
+
1833
+ Glimmer app:
1834
+
1835
+ ![glimmer dsl tk screenshot sample hello text](images/glimmer-dsl-tk-screenshot-sample-hello-text.png)
1836
+
1837
+ ### Hello, Spinbox!
1838
+
1839
+ Glimmer code (from [samples/hello/hello_spinbox.rb](samples/hello/hello_spinbox.rb)):
1840
+
1841
+ ```ruby
1842
+ require 'glimmer-dsl-tk'
1843
+
1844
+ class HelloSpinbox
1845
+ class Person
1846
+ attr_accessor :donation
1847
+ end
1848
+
1849
+ include Glimmer
1850
+
1851
+ def initialize
1852
+ @person = Person.new
1853
+ @person.donation = 5.0 # in dollars
1854
+ end
1855
+
1856
+ def launch
1857
+ root {
1858
+ title 'Hello, Spinbox!'
1859
+
1860
+ label {
1861
+ text 'Please select the amount you would like to donate to the poor:'
1862
+ }
1863
+
1864
+ frame {
1865
+ label {
1866
+ grid row: 0, column: 0
1867
+ text 'Amount:'
1868
+ font 'caption'
1869
+ }
1870
+
1871
+ label {
1872
+ grid row: 0, column: 1
1873
+ text '$'
1874
+ }
1875
+
1876
+ spinbox { |sb|
1877
+ grid row: 0, column: 2
1878
+ from 1.0 # minimum value
1879
+ to 150.0 # maximum value
1880
+ increment 5.0 # increment on up and down
1881
+ format '%0.2f'
1882
+ text <=> [@person, :donation]
1883
+ }
1884
+
1885
+ label {
1886
+ grid row: 1, column: 0, columnspan: 3
1887
+ text <=> [@person, :donation, on_read: ->(value) { "Thank you for your donation of $#{"%.2f" % value.to_f}"}]
1888
+ }
1889
+
1890
+ }
1891
+ }.open
1892
+ end
1893
+ end
1894
+
1895
+ HelloSpinbox.new.launch
1896
+ ```
1897
+
1898
+ Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
1899
+
1900
+ ```
1901
+ ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_spinbox'"
1902
+ ```
1903
+
1904
+ Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
1905
+
1906
+ ```
1907
+ ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_spinbox.rb
1908
+ ```
1909
+
1910
+ Glimmer app:
1911
+
1912
+ ![glimmer dsl tk screenshot sample hello spinbox](images/glimmer-dsl-tk-screenshot-sample-hello-spinbox.png)
1913
+
1628
1914
  ### Hello, Computed!
1629
1915
 
1630
1916
  Glimmer code (from [samples/hello/hello_computed.rb](samples/hello/hello_computed.rb)):
@@ -1705,6 +1991,167 @@ Glimmer app:
1705
1991
 
1706
1992
  ![glimmer dsl tk screenshot sample hello computed](images/glimmer-dsl-tk-screenshot-sample-hello-computed.png)
1707
1993
 
1994
+ ### Hello, Drag and Drop!
1995
+
1996
+ Glimmer code (from [samples/hello/hello_drag_and_drop.rb](samples/hello/hello_drag_and_drop.rb)):
1997
+
1998
+ ```ruby
1999
+ require "glimmer-dsl-tk"
2000
+ require "glimmer/tk/drag_and_drop_extension"
2001
+
2002
+ include Glimmer
2003
+
2004
+ root {
2005
+ title "Hello, Drag and Drop!"
2006
+ frame {
2007
+ padding 5
2008
+ labelframe {
2009
+ text "Drag sources"
2010
+ padding 5
2011
+ label {
2012
+ text "Entry"
2013
+ grid :row => 0, :column => 0
2014
+ }
2015
+ entry {
2016
+ text "Drag entry text"
2017
+ width 30
2018
+ grid :row => 0, :column => 1, :pady => 5, :sticky => "e"
2019
+ on_drag_start { |event|
2020
+ event.data = event.source.textvariable&.value
2021
+ event.source.configure(:cursor => "hand2")
2022
+ TkLabel.new(event.tooltip) {
2023
+ text event.data + " "
2024
+ bg "yellow"
2025
+ bitmap "warning"
2026
+ compound "right"
2027
+ }.pack
2028
+ }
2029
+ on_drag_motion { |event|
2030
+ if event.drop_accepted
2031
+ event.source.configure(:cursor => "hand1")
2032
+ else
2033
+ event.source.configure(:cursor => "hand2")
2034
+ end
2035
+ event.tooltip.geometry("+#{event.x_root + 10}+#{event.y_root - 4}")
2036
+ }
2037
+ }
2038
+ label {
2039
+ text "Label"
2040
+ grid :row => 1, :column => 0
2041
+ }
2042
+ label {
2043
+ text "Drag label text"
2044
+ width 30
2045
+ grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
2046
+ drag_source true
2047
+ }
2048
+ label {
2049
+ text "Combobox"
2050
+ grid :row => 2, :column => 0
2051
+ }
2052
+ combobox {
2053
+ text "Spain"
2054
+ values %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
2055
+ width 27
2056
+ grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
2057
+ on_drag_start { |event|
2058
+ event.data = event.source.textvariable&.value
2059
+ }
2060
+ }
2061
+ label {
2062
+ text "Button"
2063
+ grid :row => 3, :column => 0
2064
+ }
2065
+ button {
2066
+ text "Drag it"
2067
+ grid :row => 3, :column => 1, :pady => 5, :sticky => "w"
2068
+ drag_source true
2069
+ }
2070
+ }
2071
+
2072
+ labelframe {
2073
+ text "Drop targets"
2074
+ grid :sticky => "nsew", :pady => 15
2075
+ padding 5
2076
+ label {
2077
+ text "Entry"
2078
+ grid :row => 0, :column => 0
2079
+ }
2080
+ entry {
2081
+ width 30
2082
+ grid :row => 0, :column => 1, :pady => 5, :sticky => "e"
2083
+ on_drop { |event|
2084
+ event.target.textvariable.value = event.data
2085
+ }
2086
+ }
2087
+ label {
2088
+ text "Label"
2089
+ grid :row => 1, :column => 0
2090
+ }
2091
+ label {
2092
+ width 30
2093
+ grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
2094
+ borderwidth 2
2095
+ relief "solid"
2096
+ on_drop { |event|
2097
+ event.target.textvariable.value = event.data
2098
+ }
2099
+ }
2100
+ label {
2101
+ text "Combobox"
2102
+ grid :row => 2, :column => 0
2103
+ }
2104
+ combobox {
2105
+ width 27
2106
+ grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
2107
+ on_drop { |event|
2108
+ event.target.textvariable.value = event.data
2109
+ }
2110
+ }
2111
+ label {
2112
+ text "Button"
2113
+ grid :row => 3, :column => 0
2114
+ }
2115
+ button {
2116
+ text "Drop here"
2117
+ grid :row => 3, :column => 1, :pady => 5, :sticky => "w"
2118
+ on_drop { |event|
2119
+ event.target.text = event.data
2120
+ }
2121
+ }
2122
+ label {
2123
+ text "Checkbutton"
2124
+ grid :row => 4, :column => 0
2125
+ }
2126
+ checkbutton {
2127
+ text "Drop here to destroy a widget\n(except button)"
2128
+ grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
2129
+ on_drop { |event|
2130
+ event.target.text = event.data
2131
+ event.source.destroy unless event.source.is_a? Tk::Button
2132
+ }
2133
+ }
2134
+ }
2135
+ }
2136
+ }.open
2137
+ ```
2138
+
2139
+ Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
2140
+
2141
+ ```
2142
+ ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_drag_and_drop'"
2143
+ ```
2144
+
2145
+ Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
2146
+
2147
+ ```
2148
+ ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_drag_and_drop.rb
2149
+ ```
2150
+
2151
+ Glimmer app:
2152
+
2153
+ ![glimmer dsl tk screenshot sample hello drag and drop](images/glimmer-dsl-tk-screenshot-sample-hello-drag-and-drop.png)
2154
+
1708
2155
  ## Help
1709
2156
 
1710
2157
  ### Issues
@@ -1738,6 +2185,7 @@ These features have been planned or suggested. You might see them in a future ve
1738
2185
  ## Contributors
1739
2186
 
1740
2187
  * [Andy Maleh](https://github.com/AndyObtiva) (Founder)
2188
+ * [vin1antme](https://github.com/vin1antme)
1741
2189
 
1742
2190
  [Click here to view contributor commits.](https://github.com/AndyObtiva/glimmer-dsl-tk/graphs/contributors)
1743
2191