glimmer-dsl-tk 0.0.25 → 0.0.29
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +835 -122
- data/VERSION +1 -1
- data/glimmer-dsl-tk.gemspec +0 -0
- data/lib/glimmer/dsl/tk/built_in_dialog_expression.rb +57 -0
- data/lib/glimmer/dsl/tk/dsl.rb +1 -0
- data/lib/glimmer/tk/drag_and_drop_extension.rb +112 -0
- data/lib/glimmer/tk/label_proxy.rb +0 -9
- data/lib/glimmer/tk/root_proxy.rb +10 -34
- data/lib/glimmer/tk/text_proxy.rb +285 -9
- data/lib/glimmer/tk/widget_proxy.rb +88 -34
- data/samples/elaborate/meta_sample.rb +6 -6
- data/samples/hello/hello_built_in_dialog.rb +68 -0
- data/samples/hello/hello_combobox.rb +2 -1
- data/samples/hello/hello_drag_and_drop.rb +159 -0
- data/samples/hello/hello_entry.rb +2 -2
- data/samples/hello/hello_message_box.rb +0 -4
- data/samples/hello/hello_separator.rb +69 -0
- data/samples/hello/hello_text.rb +246 -0
- data/samples/hello/images/copy.png +0 -0
- data/samples/hello/images/cut.png +0 -0
- data/samples/hello/images/paste.png +0 -0
- data/samples/hello/images/picture.png +0 -0
- data/samples/hello/images/redo.png +0 -0
- data/samples/hello/images/search.png +0 -0
- data/samples/hello/images/undo.png +0 -0
- metadata +19 -6
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.29
|
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
|
-
|
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,11 +74,16 @@ 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
|
-
|
77
|
+
- [Text API](#text-api)
|
78
|
+
- [Drag and Drop API](#drag-and-drop-api)
|
79
|
+
- [Smart Defaults and Conventions](#smart-defaults-and-conventions)
|
80
80
|
- [Grid Layout](#grid-layout)
|
81
|
-
- [
|
81
|
+
- [Image Attribute](#image-attribute)
|
82
|
+
- [Frame Padding](#frame-padding)
|
82
83
|
- [Notebook Frame](#notebook-frame)
|
83
84
|
- [Icon Photo](#icon-photo)
|
85
|
+
- [Root Background](#root-background)
|
86
|
+
- [Text Defaults](#text-defaults)
|
84
87
|
- [The Grid Geometry Manager](#the-grid-geometry-manager)
|
85
88
|
- [Data-Binding](#data-binding)
|
86
89
|
- [Label Data-Binding](#label-data-binding)
|
@@ -88,8 +91,8 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
88
91
|
- [List Single Selection Data-Binding](#list-single-selection-data-binding)
|
89
92
|
- [List Multi Selection Data-Binding](#list-multi-selection-data-binding)
|
90
93
|
- [Entry Data-Binding](#entry-data-binding)
|
91
|
-
- [Spinbox Data-Binding](#spinbox-data-binding)
|
92
94
|
- [Text Data-Binding](#text-data-binding)
|
95
|
+
- [Spinbox Data-Binding](#spinbox-data-binding)
|
93
96
|
- [Checkbutton Data-Binding](#checkbutton-data-binding)
|
94
97
|
- [Radiobutton Data-Binding](#radiobutton-data-binding)
|
95
98
|
- [Command Callback](#command-callback)
|
@@ -108,8 +111,12 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
108
111
|
- [Hello, List Single Selection!](#hello-list-single-selection)
|
109
112
|
- [Hello, List Multi Selection!](#hello-list-multi-selection)
|
110
113
|
- [Hello, Entry!](#hello-entry)
|
114
|
+
- [Hello, Text!](#hello-text)
|
111
115
|
- [Hello, Spinbox!](#hello-spinbox)
|
112
116
|
- [Hello, Computed!](#hello-computed)
|
117
|
+
- [Hello, Drag and Drop!](#hello-drag-and-drop)
|
118
|
+
- [Hello, Built-in Dialog!](#hello-built-in-dialog)
|
119
|
+
- [Hello, Separator!](#hello-separator)
|
113
120
|
- [Help](#help)
|
114
121
|
- [Issues](#issues)
|
115
122
|
- [Chat](#chat)
|
@@ -146,7 +153,7 @@ gem install glimmer-dsl-tk
|
|
146
153
|
|
147
154
|
Add the following to `Gemfile`:
|
148
155
|
```
|
149
|
-
gem 'glimmer-dsl-tk', '~> 0.0.
|
156
|
+
gem 'glimmer-dsl-tk', '~> 0.0.29'
|
150
157
|
```
|
151
158
|
|
152
159
|
And, then run:
|
@@ -257,8 +264,14 @@ keyword(args) | attributes | event bindings & callbacks
|
|
257
264
|
------------- | ---------- | ---------
|
258
265
|
`button` | `text`, `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `default` (`'active', 'normal'`) | `command {}`
|
259
266
|
`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 {}`
|
267
|
+
`choose_color(options = nil)` | None | None
|
268
|
+
`choose_directory(options = nil)` | None | None
|
269
|
+
`choose_font(options = nil) {|font| ... }` | None | None
|
260
270
|
`combobox` | `state`, `text` | `'ComboboxSelected'`
|
261
271
|
`entry` | `width`, `text`, `validate`, `show` (`'none', 'focus', 'focusin', 'focusout', 'key', or 'all'`) | `'validate'`, `'invalid'`, `'change'`, `validatecommand {}`, `invalidcommand {}`
|
272
|
+
`get_multiple_open_file(options = nil)` | None | None
|
273
|
+
`get_open_file(options = nil)` | None | None
|
274
|
+
`get_save_file(options = nil)` | None | None
|
262
275
|
`spinbox` | `text`, `from`, `to`, `increment`, `format`, [more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `command {}`, `'increment'`, `'decrement'`
|
263
276
|
`frame(text: nil)` | `width`, `height`, `borderwidth`, `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`) | None
|
264
277
|
`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
|
@@ -269,6 +282,9 @@ keyword(args) | attributes | event bindings & callbacks
|
|
269
282
|
`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'`
|
270
283
|
`text` | `text`, [many more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `'modified'`, `'selection'`
|
271
284
|
|
285
|
+
Options for `get_open_file` and `get_multiple_open_file` include:
|
286
|
+
- `filetypes`: `Hash` of `'Group Name' => '.ext'` entries (e.g. `filetypes: {'PNG Images' => '.png'}`
|
287
|
+
|
272
288
|
#### Common Attributes
|
273
289
|
|
274
290
|
- `grid`: `Hash` of `:row`, `:column`, `:padx`, `:pady`, `:sticky` (`'e', 'w', 'n', 's'` or any combination of direction letters)
|
@@ -317,7 +333,81 @@ keyword(args) | attributes | event bindings & callbacks
|
|
317
333
|
- `invalid?`
|
318
334
|
- `hover?`
|
319
335
|
|
320
|
-
|
336
|
+
#### Text API
|
337
|
+
|
338
|
+
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.
|
339
|
+
|
340
|
+
- `add_format(region_start, region_end, option, value)`
|
341
|
+
- `remove_format(region_start, region_end, option, value)`
|
342
|
+
- `toggle_format(region_start, region_end, option, value)`
|
343
|
+
- `add_font_format(region_start, region_end, font_option, value)`
|
344
|
+
- `remove_font_format(region_start, region_end, font_option, value)`
|
345
|
+
- `toggle_font_format(region_start, region_end, font_option, value)`
|
346
|
+
- `add_selection_format(region_start, region_end, option, value)`
|
347
|
+
- `remove_selection_format(region_start, region_end, option, value)`
|
348
|
+
- `toggle_selection_format(region_start, region_end, option, value)`
|
349
|
+
- `add_selection_font_format(region_start, region_end, font_option, value)`
|
350
|
+
- `remove_selection_font_format(region_start, region_end, font_option, value)`
|
351
|
+
- `toggle_selection_font_format(region_start, region_end, font_option, value)`
|
352
|
+
- `text#insert_image(text_index, *image_args)`: inserts image into `text` `value` content at `text_index` location (e.g. `'insert'`)
|
353
|
+
- `text#get_open_file_to_insert_image(text_index = 'insert')`: opens a file dialog to select one of the available image formats and then inserts image into `text` `value` content
|
354
|
+
|
355
|
+
Available options:
|
356
|
+
|
357
|
+
- `background`
|
358
|
+
- `bgstipple`
|
359
|
+
- `borderwidth`
|
360
|
+
- `elide`
|
361
|
+
- `fgstipple`
|
362
|
+
- `foreground`
|
363
|
+
- `justify`
|
364
|
+
- `lmargin1`
|
365
|
+
- `lmargin2`
|
366
|
+
- `offset`
|
367
|
+
- `overstrike`
|
368
|
+
- `relief`
|
369
|
+
- `rmargin`
|
370
|
+
- `spacing1`
|
371
|
+
- `spacing2`
|
372
|
+
- `spacing3`
|
373
|
+
- `tabs`
|
374
|
+
- `tabstyle`
|
375
|
+
- `underline`
|
376
|
+
- `wrap`
|
377
|
+
|
378
|
+
Available font options:
|
379
|
+
|
380
|
+
- `family` (default: `'Courier New'`)
|
381
|
+
- `size` (default: `13`)
|
382
|
+
- `weight` (default: `'normal'`) (e.g. `'bold'`)
|
383
|
+
- `slant` (default: `'roman'`) (e.g. `'italic`')
|
384
|
+
- `underline` (default: `false`)
|
385
|
+
- `overstrike` (default: `false`)
|
386
|
+
|
387
|
+
Other useful built-in API methods:
|
388
|
+
|
389
|
+
- `text_cut`
|
390
|
+
- `text_copy`
|
391
|
+
- `text_paste`
|
392
|
+
- `text_edit_undo`
|
393
|
+
- `text_edit_redo`
|
394
|
+
|
395
|
+
Check out the [Hello, Text!](#hello-text) sample for a good demonstration of the `text` widget features.
|
396
|
+
|
397
|
+
#### Drag and Drop API
|
398
|
+
|
399
|
+
Drag and drop works by simply designating a widget as a drag source with attribute `drag_source true`
|
400
|
+
|
401
|
+
Alternatively, add listeners:
|
402
|
+
- `on_drag_start {|event| ...}`: fires on drag start receiving an `event` arg to set `data` and configure `source`
|
403
|
+
- `on_drag_motion {|event| ...}`: fires on drag motion receiving an `event` arg to check `event#drop_accepted`, and configure `source` and `tooltip`
|
404
|
+
|
405
|
+
On the drop target, you simply define:
|
406
|
+
- `on_drop { |event| ...}`: fires on drop, receiving an `event` arg with `event#target` and `event#data` (set during drag). You can even destroy the `event#source` if you want to get rid of the dragged widget.
|
407
|
+
|
408
|
+
Learn more at the [Hello, Drag and Drop!](#hello-drag-and-drop) sample.
|
409
|
+
|
410
|
+
### Smart Defaults and Conventions
|
321
411
|
|
322
412
|
#### Event Bindings
|
323
413
|
|
@@ -325,11 +415,25 @@ Any events that normally can be accepted by the Tk `bind` or `protocol` methods
|
|
325
415
|
|
326
416
|
#### Grid Layout
|
327
417
|
|
328
|
-
`grid` layout is the default on
|
418
|
+
`grid` layout with `sticky: 'nsew'` is the default on all widgets except toplevel widgets.
|
419
|
+
|
420
|
+
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.
|
421
|
+
|
422
|
+
To override that behavior, you may set alternative `grid` keyword args if needed (e.g. `grid sticky: '', column_weight: 0` disables the smart defaults).
|
423
|
+
|
424
|
+
#### Image Attribute
|
425
|
+
|
426
|
+
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:
|
427
|
+
- `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.
|
428
|
+
- `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.
|
429
|
+
- `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.
|
430
|
+
- `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.
|
431
|
+
- `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.
|
432
|
+
- `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>.
|
329
433
|
|
330
|
-
####
|
434
|
+
#### Frame Padding
|
331
435
|
|
332
|
-
|
436
|
+
Frames have a padding of `15` all around by default to produce more user-friendly graphical user interfaces.
|
333
437
|
|
334
438
|
#### Notebook Frame
|
335
439
|
|
@@ -359,6 +463,16 @@ root {
|
|
359
463
|
}.open
|
360
464
|
```
|
361
465
|
|
466
|
+
#### Root Background
|
467
|
+
|
468
|
+
`root` `background` color attribute is automatically set to `'#ececec'` on the Mac to avoid having a non-native-looking light-colored background.
|
469
|
+
|
470
|
+
#### Text Defaults
|
471
|
+
|
472
|
+
`text` widget has these defaults:
|
473
|
+
- `wrap = 'none'`
|
474
|
+
- `font = {family: 'Courier New'}`
|
475
|
+
|
362
476
|
## The Grid Geometry Manager
|
363
477
|
|
364
478
|
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.
|
@@ -377,9 +491,19 @@ Example:
|
|
377
491
|
}
|
378
492
|
```
|
379
493
|
|
494
|
+
Extra convenience options may be passed to `grid` when using [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk):
|
495
|
+
- `column_span`: alias for `columnspan` keyword arg
|
496
|
+
- `row_span`: alias for `rowspan` keyword arg
|
497
|
+
- `min_width`: alias for `columnminsize` being called on `TkGrid.columnconfigure`
|
498
|
+
- `min_height`: alias for `rowminsize` being called on `TkGrid.rowconfigure`
|
499
|
+
- `column_weight`: alias for `columnweight` being called on `TkGrid.columnconfigure`
|
500
|
+
- `row_weight`: alias for `rowweight` being called on `TkGrid.rowconfigure`
|
501
|
+
|
502
|
+
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)
|
503
|
+
|
380
504
|
More details can be found in the [Hello, Computed!](#hello-computed) sample below.
|
381
505
|
|
382
|
-
##
|
506
|
+
## Data-Binding
|
383
507
|
|
384
508
|
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).
|
385
509
|
|
@@ -409,7 +533,7 @@ This assumes a `Person` model with a `country` attribute representing their curr
|
|
409
533
|
|
410
534
|
```ruby
|
411
535
|
combobox {
|
412
|
-
|
536
|
+
readonly true # this applies to text editing only (item selection still triggers a write to model)
|
413
537
|
text <=> [person, :country]
|
414
538
|
}
|
415
539
|
```
|
@@ -482,45 +606,45 @@ It automatically handles all the Tk plumbing behind the scenes.
|
|
482
606
|
|
483
607
|
More details can be found in [Hello, Entry!](#hello-entry) and [Hello, Computed!](#hello-computed) samples below.
|
484
608
|
|
485
|
-
###
|
609
|
+
### Text Data-Binding
|
486
610
|
|
487
611
|
Example:
|
488
612
|
|
489
|
-
This assumes a `Person` model with a `
|
613
|
+
This assumes a `Person` model with a `biography` attribute.
|
490
614
|
|
491
615
|
```ruby
|
492
|
-
|
493
|
-
|
494
|
-
to 150.0 # maximum value
|
495
|
-
increment 5.0 # increment on up and down
|
496
|
-
format '%0.2f'
|
497
|
-
text <=> [person, :country]
|
616
|
+
text {
|
617
|
+
value <=> [person, :biography]
|
498
618
|
}
|
499
619
|
```
|
500
620
|
|
501
|
-
That code binds the `
|
621
|
+
That code binds the `value` of `text` to the `biography` attribute on the `person` model.
|
502
622
|
|
503
623
|
It automatically handles all the Tk plumbing behind the scenes.
|
504
624
|
|
505
|
-
More details can be found in [Hello,
|
625
|
+
More details can be found in [Hello, Text!](#hello-text) sample below.
|
506
626
|
|
507
|
-
###
|
627
|
+
### Spinbox Data-Binding
|
508
628
|
|
509
629
|
Example:
|
510
630
|
|
511
|
-
This assumes a `Person` model with a `
|
631
|
+
This assumes a `Person` model with a `donation` attribute.
|
512
632
|
|
513
633
|
```ruby
|
514
|
-
|
515
|
-
|
634
|
+
spinbox {
|
635
|
+
from 1.0 # minimum value
|
636
|
+
to 150.0 # maximum value
|
637
|
+
increment 5.0 # increment on up and down
|
638
|
+
format '%0.2f'
|
639
|
+
text <=> [person, :country]
|
516
640
|
}
|
517
641
|
```
|
518
642
|
|
519
|
-
That code binds the
|
643
|
+
That code binds the `textvariable` value of the `spinbox` to the `donation` attribute on the `person` model.
|
520
644
|
|
521
|
-
It automatically handles all the Tk plumbing behind the scenes
|
645
|
+
It automatically handles all the Tk plumbing behind the scenes.
|
522
646
|
|
523
|
-
More details can be found in [
|
647
|
+
More details can be found in [Hello, Spinbox!](#hello-spinbox) sample below.
|
524
648
|
|
525
649
|
### Checkbutton Data-Binding
|
526
650
|
|
@@ -570,7 +694,7 @@ More details can be found in the [Hello, Radiobutton!](#hello-radiobutton) sampl
|
|
570
694
|
|
571
695
|
## Command Callback
|
572
696
|
|
573
|
-
`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.
|
697
|
+
`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.
|
574
698
|
|
575
699
|
Example:
|
576
700
|
|
@@ -584,6 +708,18 @@ Example:
|
|
584
708
|
}
|
585
709
|
```
|
586
710
|
|
711
|
+
Alternatively, it can be treated as simply an event for consistency with other event bindings:
|
712
|
+
|
713
|
+
```ruby
|
714
|
+
button {
|
715
|
+
text "Reset Selection"
|
716
|
+
|
717
|
+
on('command') do
|
718
|
+
person.reset_country
|
719
|
+
end
|
720
|
+
}
|
721
|
+
```
|
722
|
+
|
587
723
|
More details can be found in the [Hello, Button!](#hello-button) sample below.
|
588
724
|
|
589
725
|
## Gotchas
|
@@ -608,6 +744,128 @@ ruby -r ./lib/glimmer-dsl-tk.rb samples/elaborate/meta_sample.rb
|
|
608
744
|
|
609
745
|
![glimmer dsl tk screenshot sample meta sample](images/glimmer-dsl-tk-screenshot-sample-elaborate-meta-sample.png)
|
610
746
|
|
747
|
+
Code:
|
748
|
+
|
749
|
+
```ruby
|
750
|
+
require 'glimmer-dsl-tk'
|
751
|
+
require 'facets'
|
752
|
+
require 'fileutils'
|
753
|
+
|
754
|
+
class MetaSample
|
755
|
+
include Glimmer
|
756
|
+
|
757
|
+
attr_accessor :selected_sample_index
|
758
|
+
|
759
|
+
def initialize
|
760
|
+
@selected_sample_index = 0
|
761
|
+
end
|
762
|
+
|
763
|
+
def samples
|
764
|
+
if @samples.nil?
|
765
|
+
sample_files = Dir.glob(File.join(File.expand_path('../hello', __dir__), '**', 'hello_*.rb'))
|
766
|
+
sample_file_names = sample_files.map { |f| File.basename(f, '.rb') }
|
767
|
+
sample_file_names = sample_file_names.reject { |f| f == 'meta_sample' || f.match(/\d$/) }
|
768
|
+
@samples = sample_file_names.map { |f| f.underscore.titlecase }
|
769
|
+
end
|
770
|
+
@samples
|
771
|
+
end
|
772
|
+
|
773
|
+
def file_path_for(sample)
|
774
|
+
File.join(File.expand_path('../hello', __dir__), "#{sample.underscore}.rb")
|
775
|
+
end
|
776
|
+
|
777
|
+
def glimmer_dsl_tk_file
|
778
|
+
File.expand_path('../../lib/glimmer-dsl-tk', __dir__)
|
779
|
+
end
|
780
|
+
|
781
|
+
def selected_sample
|
782
|
+
samples[@selected_sample_index]
|
783
|
+
end
|
784
|
+
|
785
|
+
def run_sample(sample)
|
786
|
+
Thread.new do
|
787
|
+
command = "ruby -r #{glimmer_dsl_tk_file} #{sample} 2>&1"
|
788
|
+
result = ''
|
789
|
+
IO.popen(command) do |f|
|
790
|
+
f.each_line do |line|
|
791
|
+
result << line
|
792
|
+
puts line
|
793
|
+
$stdout.flush
|
794
|
+
end
|
795
|
+
end
|
796
|
+
::Tk.after(100) do
|
797
|
+
message_box(parent: @root, title: 'Error Running Sample', message: result) if result.downcase.include?('error')
|
798
|
+
end
|
799
|
+
end
|
800
|
+
end
|
801
|
+
|
802
|
+
def launch
|
803
|
+
@root = root {
|
804
|
+
title 'Glimmer Meta-Sample'
|
805
|
+
width 1280
|
806
|
+
height 720
|
807
|
+
|
808
|
+
frame {
|
809
|
+
grid row: 0, column: 0, column_weight: 0, row_weight: 1
|
810
|
+
|
811
|
+
samples.each_with_index do |sample, index|
|
812
|
+
radiobutton {
|
813
|
+
text sample
|
814
|
+
variable <=> [self, :selected_sample_index, on_write: ->(v) {v ? index : selected_sample_index}, on_read: ->(v) {v == index}]
|
815
|
+
|
816
|
+
on('command') do
|
817
|
+
@selected_sample_index = index
|
818
|
+
@code_text.value = File.read(file_path_for(selected_sample))
|
819
|
+
end
|
820
|
+
}
|
821
|
+
end
|
822
|
+
|
823
|
+
frame {
|
824
|
+
button {
|
825
|
+
grid row: 0, column: 0
|
826
|
+
text 'Launch'
|
827
|
+
|
828
|
+
on('command') do
|
829
|
+
begin
|
830
|
+
parent_dir = File.join(Dir.home, '.glimmer-dsl-tk', 'samples', 'hello')
|
831
|
+
FileUtils.mkdir_p(parent_dir)
|
832
|
+
sample_file = File.join(parent_dir, "#{selected_sample.underscore}.rb")
|
833
|
+
File.write(sample_file, @code_text.value)
|
834
|
+
FileUtils.cp_r(File.expand_path('../../icons', __dir__), File.dirname(File.dirname(parent_dir)))
|
835
|
+
FileUtils.cp_r(File.expand_path('../hello/images', __dir__), parent_dir)
|
836
|
+
sample_namespace_directory = File.expand_path("../hello/#{selected_sample.underscore}", __dir__)
|
837
|
+
FileUtils.cp_r(sample_namespace_directory, parent_dir) if Dir.exist?(sample_namespace_directory)
|
838
|
+
run_sample(sample_file)
|
839
|
+
rescue => e
|
840
|
+
puts e.full_message
|
841
|
+
puts 'Unable to write code changes! Running original sample...'
|
842
|
+
run_sample(file_path_for(selected_sample))
|
843
|
+
end
|
844
|
+
end
|
845
|
+
}
|
846
|
+
button {
|
847
|
+
grid row: 0, column: 1
|
848
|
+
text 'Reset'
|
849
|
+
|
850
|
+
on('command') do
|
851
|
+
@code_text.value = File.read(file_path_for(selected_sample))
|
852
|
+
end
|
853
|
+
}
|
854
|
+
}
|
855
|
+
}
|
856
|
+
|
857
|
+
@code_text = text {
|
858
|
+
grid row: 0, column: 1, column_weight: 1
|
859
|
+
value File.read(file_path_for(selected_sample))
|
860
|
+
}
|
861
|
+
}
|
862
|
+
@root.open
|
863
|
+
end
|
864
|
+
end
|
865
|
+
|
866
|
+
MetaSample.new.launch
|
867
|
+
```
|
868
|
+
|
611
869
|
### Hello, World!
|
612
870
|
|
613
871
|
Glimmer code (from [samples/hello/hello_world.rb](samples/hello/hello_world.rb)):
|
@@ -1168,6 +1426,8 @@ Glimmer app:
|
|
1168
1426
|
|
1169
1427
|
### Hello, Label!
|
1170
1428
|
|
1429
|
+
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>
|
1430
|
+
|
1171
1431
|
Glimmer code (from [samples/hello/hello_label.rb](samples/hello/hello_label.rb)):
|
1172
1432
|
|
1173
1433
|
```ruby
|
@@ -1297,8 +1557,6 @@ root { |r|
|
|
1297
1557
|
title 'Hello, Message Box!'
|
1298
1558
|
|
1299
1559
|
frame {
|
1300
|
-
grid sticky: 'nsew', padx: 15, pady: 15
|
1301
|
-
|
1302
1560
|
button {
|
1303
1561
|
text 'Please Click To Win a Surprise'
|
1304
1562
|
|
@@ -1350,8 +1608,6 @@ root { |r|
|
|
1350
1608
|
}
|
1351
1609
|
|
1352
1610
|
frame {
|
1353
|
-
grid sticky: 'nsew', padx: 15, pady: 15
|
1354
|
-
|
1355
1611
|
label {
|
1356
1612
|
grid row: 0, column: 0
|
1357
1613
|
text 'Result:'
|
@@ -1379,7 +1635,6 @@ ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_message_box.rb
|
|
1379
1635
|
Glimmer app:
|
1380
1636
|
|
1381
1637
|
![glimmer dsl tk screenshot sample hello message box](images/glimmer-dsl-tk-screenshot-sample-hello-message-box.png)
|
1382
|
-
![glimmer dsl tk screenshot sample hello message box open](images/glimmer-dsl-tk-screenshot-sample-hello-message-box-open.png)
|
1383
1638
|
|
1384
1639
|
### Hello, Combobox!
|
1385
1640
|
|
@@ -1390,12 +1645,12 @@ Glimmer code (from [samples/hello/hello_combobox.rb](samples/hello/hello_combobo
|
|
1390
1645
|
root {
|
1391
1646
|
title 'Hello, Combobox!'
|
1392
1647
|
|
1393
|
-
combobox {
|
1394
|
-
|
1648
|
+
combobox {
|
1649
|
+
readonly true # this applies to text editing only (item selection still triggers a write to model)
|
1395
1650
|
text <=> [person, :country]
|
1396
1651
|
}
|
1397
1652
|
|
1398
|
-
button {
|
1653
|
+
button {
|
1399
1654
|
text "Reset Selection"
|
1400
1655
|
command {
|
1401
1656
|
person.reset_country
|
@@ -1499,86 +1754,6 @@ Glimmer app:
|
|
1499
1754
|
|
1500
1755
|
![glimmer dsl tk screenshot sample hello list multi selection](images/glimmer-dsl-tk-screenshot-sample-hello-list-multi-selection.png)
|
1501
1756
|
|
1502
|
-
### Hello, Computed!
|
1503
|
-
|
1504
|
-
Glimmer code (from [samples/hello/hello_computed.rb](samples/hello/hello_computed.rb)):
|
1505
|
-
|
1506
|
-
```ruby
|
1507
|
-
# ... more code precedes
|
1508
|
-
root {
|
1509
|
-
title 'Hello, Computed!'
|
1510
|
-
|
1511
|
-
frame {
|
1512
|
-
grid column: 0, row: 0, padx: 5, pady: 5
|
1513
|
-
|
1514
|
-
label {
|
1515
|
-
grid column: 0, row: 0, sticky: 'w'
|
1516
|
-
text 'First Name: '
|
1517
|
-
}
|
1518
|
-
entry {
|
1519
|
-
grid column: 1, row: 0
|
1520
|
-
width 15
|
1521
|
-
text <=> [@contact, :first_name]
|
1522
|
-
}
|
1523
|
-
|
1524
|
-
label {
|
1525
|
-
grid column: 0, row: 1, sticky: 'w'
|
1526
|
-
text 'Last Name: '
|
1527
|
-
}
|
1528
|
-
entry {
|
1529
|
-
grid column: 1, row: 1
|
1530
|
-
width 15
|
1531
|
-
text <=> [@contact, :last_name]
|
1532
|
-
}
|
1533
|
-
|
1534
|
-
label {
|
1535
|
-
grid column: 0, row: 2, sticky: 'w'
|
1536
|
-
text 'Year of Birth: '
|
1537
|
-
}
|
1538
|
-
entry {
|
1539
|
-
grid column: 1, row: 2
|
1540
|
-
width 15
|
1541
|
-
text <=> [@contact, :year_of_birth]
|
1542
|
-
}
|
1543
|
-
|
1544
|
-
label {
|
1545
|
-
grid column: 0, row: 3, sticky: 'w'
|
1546
|
-
text 'Name: '
|
1547
|
-
}
|
1548
|
-
label {
|
1549
|
-
grid column: 1, row: 3, sticky: 'w'
|
1550
|
-
text <=> [@contact, :name, computed_by: [:first_name, :last_name]]
|
1551
|
-
}
|
1552
|
-
|
1553
|
-
label {
|
1554
|
-
grid column: 0, row: 4, sticky: 'w'
|
1555
|
-
text 'Age: '
|
1556
|
-
}
|
1557
|
-
label {
|
1558
|
-
grid column: 1, row: 4, sticky: 'w'
|
1559
|
-
text <=> [@contact, :age, on_write: :to_i, computed_by: [:year_of_birth]]
|
1560
|
-
}
|
1561
|
-
}
|
1562
|
-
}.open
|
1563
|
-
# ... more code follows
|
1564
|
-
```
|
1565
|
-
|
1566
|
-
Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
1567
|
-
|
1568
|
-
```
|
1569
|
-
ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_computed'"
|
1570
|
-
```
|
1571
|
-
|
1572
|
-
Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
1573
|
-
|
1574
|
-
```
|
1575
|
-
ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_computed.rb
|
1576
|
-
```
|
1577
|
-
|
1578
|
-
Glimmer app:
|
1579
|
-
|
1580
|
-
![glimmer dsl tk screenshot sample hello computed](images/glimmer-dsl-tk-screenshot-sample-hello-computed.png)
|
1581
|
-
|
1582
1757
|
### Hello, Entry!
|
1583
1758
|
|
1584
1759
|
Glimmer code (from [samples/hello/hello_entry.rb](samples/hello/hello_entry.rb)):
|
@@ -1603,7 +1778,7 @@ class HelloEntry
|
|
1603
1778
|
title 'Hello, Entry!'
|
1604
1779
|
|
1605
1780
|
label {
|
1606
|
-
grid sticky: 'ew'
|
1781
|
+
grid sticky: 'ew'
|
1607
1782
|
text 'default entry'
|
1608
1783
|
}
|
1609
1784
|
entry {
|
@@ -1686,6 +1861,234 @@ Glimmer app:
|
|
1686
1861
|
![glimmer dsl tk screenshot sample hello entry](images/glimmer-dsl-tk-screenshot-sample-hello-entry.png)
|
1687
1862
|
![glimmer dsl tk screenshot sample hello entry validated](images/glimmer-dsl-tk-screenshot-sample-hello-entry-validated.png)
|
1688
1863
|
|
1864
|
+
### Hello, Text!
|
1865
|
+
|
1866
|
+
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>
|
1867
|
+
|
1868
|
+
Glimmer code (from [samples/hello/hello_text.rb](samples/hello/hello_text.rb)):
|
1869
|
+
|
1870
|
+
```ruby
|
1871
|
+
require 'glimmer-dsl-tk'
|
1872
|
+
|
1873
|
+
class HelloText
|
1874
|
+
include Glimmer
|
1875
|
+
|
1876
|
+
COLOR_OPTIONS = %w[black purple blue green orange yellow red white].map(&:capitalize)
|
1877
|
+
FONT_FAMILY_OPTIONS = ::TkFont.families
|
1878
|
+
FOREGROUND_PROMPT = '<foreground>'
|
1879
|
+
BACKGROUND_PROMPT = '<background>'
|
1880
|
+
FONT_FAMILY_PROMPT = '<font family>'
|
1881
|
+
FONT_SIZE_PROMPT = '<font size>'
|
1882
|
+
|
1883
|
+
def initialize
|
1884
|
+
@foreground = FOREGROUND_PROMPT
|
1885
|
+
@background = BACKGROUND_PROMPT
|
1886
|
+
@font_family = FONT_FAMILY_PROMPT
|
1887
|
+
@font_size = FONT_SIZE_PROMPT
|
1888
|
+
end
|
1889
|
+
|
1890
|
+
attr_accessor :foreground
|
1891
|
+
|
1892
|
+
def foreground_options
|
1893
|
+
[FOREGROUND_PROMPT] + COLOR_OPTIONS
|
1894
|
+
end
|
1895
|
+
|
1896
|
+
attr_accessor :background
|
1897
|
+
|
1898
|
+
def background_options
|
1899
|
+
[BACKGROUND_PROMPT] + COLOR_OPTIONS
|
1900
|
+
end
|
1901
|
+
|
1902
|
+
attr_accessor :font_family
|
1903
|
+
|
1904
|
+
def font_family_options
|
1905
|
+
[FONT_FAMILY_PROMPT] + FONT_FAMILY_OPTIONS
|
1906
|
+
end
|
1907
|
+
|
1908
|
+
attr_accessor :font_size
|
1909
|
+
|
1910
|
+
def font_size_options
|
1911
|
+
[FONT_SIZE_PROMPT] + (9..64).to_a.map(&:to_s)
|
1912
|
+
end
|
1913
|
+
|
1914
|
+
def launch
|
1915
|
+
root {
|
1916
|
+
title 'Hello, Text!'
|
1917
|
+
|
1918
|
+
frame {
|
1919
|
+
grid row: 0, column: 0
|
1920
|
+
|
1921
|
+
column_index = -1
|
1922
|
+
|
1923
|
+
combobox {
|
1924
|
+
grid row: 0, column: column_index += 1, column_weight: 1
|
1925
|
+
readonly true
|
1926
|
+
text <=> [self, :font_family, after_write: ->(value) { @text.toggle_selection_font_format('family', value == FONT_FAMILY_PROMPT ? 'Courier New' : value) }]
|
1927
|
+
}
|
1928
|
+
|
1929
|
+
combobox {
|
1930
|
+
grid row: 0, column: column_index += 1, column_weight: 1
|
1931
|
+
readonly true
|
1932
|
+
text <=> [self, :font_size, after_write: ->(value) { @text.toggle_selection_font_format('size', value == FONT_SIZE_PROMPT ? 13 : value) }]
|
1933
|
+
}
|
1934
|
+
|
1935
|
+
combobox {
|
1936
|
+
grid row: 0, column: column_index += 1, column_weight: 1
|
1937
|
+
readonly true
|
1938
|
+
text <=> [self, :foreground, after_write: ->(value) { @text.add_selection_format('foreground', value == FOREGROUND_PROMPT ? 'black' : value) }]
|
1939
|
+
}
|
1940
|
+
|
1941
|
+
combobox {
|
1942
|
+
grid row: 0, column: column_index += 1, column_weight: 1
|
1943
|
+
readonly true
|
1944
|
+
text <=> [self, :background, after_write: ->(value) { @text.add_selection_format('background', value == BACKGROUND_PROMPT ? 'white' : value) }]
|
1945
|
+
}
|
1946
|
+
|
1947
|
+
separator {
|
1948
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
1949
|
+
orient 'vertical'
|
1950
|
+
}
|
1951
|
+
|
1952
|
+
button {
|
1953
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
1954
|
+
text 'B'
|
1955
|
+
style font: {weight: 'bold'}
|
1956
|
+
|
1957
|
+
on('command') do
|
1958
|
+
@text.toggle_selection_font_format('weight', 'bold')
|
1959
|
+
end
|
1960
|
+
}
|
1961
|
+
|
1962
|
+
button {
|
1963
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
1964
|
+
text 'I'
|
1965
|
+
style font: {slant: 'italic'}
|
1966
|
+
|
1967
|
+
on('command') do
|
1968
|
+
@text.toggle_selection_font_format('slant', 'italic')
|
1969
|
+
end
|
1970
|
+
}
|
1971
|
+
|
1972
|
+
button {
|
1973
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
1974
|
+
text 'U'
|
1975
|
+
style font: {underline: true}
|
1976
|
+
|
1977
|
+
on('command') do
|
1978
|
+
@text.toggle_selection_font_format('underline', true)
|
1979
|
+
end
|
1980
|
+
}
|
1981
|
+
|
1982
|
+
separator {
|
1983
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
1984
|
+
orient 'vertical'
|
1985
|
+
}
|
1986
|
+
|
1987
|
+
button {
|
1988
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
1989
|
+
image File.expand_path("images/cut.png", __dir__), subsample: 32
|
1990
|
+
|
1991
|
+
on('command') do
|
1992
|
+
@text.text_cut
|
1993
|
+
end
|
1994
|
+
}
|
1995
|
+
|
1996
|
+
button {
|
1997
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
1998
|
+
image File.expand_path("images/copy.png", __dir__), subsample: 32
|
1999
|
+
|
2000
|
+
on('command') do
|
2001
|
+
@text.text_copy
|
2002
|
+
end
|
2003
|
+
}
|
2004
|
+
|
2005
|
+
button {
|
2006
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
2007
|
+
image File.expand_path("images/paste.png", __dir__), subsample: 32
|
2008
|
+
|
2009
|
+
on('command') do
|
2010
|
+
@text.text_paste
|
2011
|
+
end
|
2012
|
+
}
|
2013
|
+
|
2014
|
+
separator {
|
2015
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
2016
|
+
orient 'vertical'
|
2017
|
+
}
|
2018
|
+
|
2019
|
+
button {
|
2020
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
2021
|
+
image File.expand_path("images/undo.png", __dir__), subsample: 32
|
2022
|
+
|
2023
|
+
on('command') do
|
2024
|
+
@text.edit_undo
|
2025
|
+
end
|
2026
|
+
}
|
2027
|
+
|
2028
|
+
button {
|
2029
|
+
grid row: 0, column: column_index += 1, column_weight: 0
|
2030
|
+
image File.expand_path("images/redo.png", __dir__), subsample: 32
|
2031
|
+
|
2032
|
+
on('command') do
|
2033
|
+
@text.edit_redo
|
2034
|
+
end
|
2035
|
+
}
|
2036
|
+
}
|
2037
|
+
|
2038
|
+
@text = text {
|
2039
|
+
grid row: 1, column: 0, row_weight: 1
|
2040
|
+
wrap 'word'
|
2041
|
+
undo true
|
2042
|
+
value <<~MULTI_LINE_STRING
|
2043
|
+
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.
|
2044
|
+
|
2045
|
+
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.
|
2046
|
+
|
2047
|
+
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)."
|
2048
|
+
|
2049
|
+
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.
|
2050
|
+
|
2051
|
+
|
2052
|
+
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".
|
2053
|
+
|
2054
|
+
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".
|
2055
|
+
|
2056
|
+
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."
|
2057
|
+
|
2058
|
+
Meanwhile, a counter-petition supporting Burns garnered over 20,000 signatures.
|
2059
|
+
|
2060
|
+
"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."
|
2061
|
+
|
2062
|
+
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.
|
2063
|
+
|
2064
|
+
"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.
|
2065
|
+
|
2066
|
+
The original petition has since been removed.
|
2067
|
+
MULTI_LINE_STRING
|
2068
|
+
}
|
2069
|
+
}.open
|
2070
|
+
end
|
2071
|
+
end
|
2072
|
+
|
2073
|
+
HelloText.new.launch
|
2074
|
+
```
|
2075
|
+
|
2076
|
+
Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
2077
|
+
|
2078
|
+
```
|
2079
|
+
ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_text'"
|
2080
|
+
```
|
2081
|
+
|
2082
|
+
Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
2083
|
+
|
2084
|
+
```
|
2085
|
+
ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_text.rb
|
2086
|
+
```
|
2087
|
+
|
2088
|
+
Glimmer app:
|
2089
|
+
|
2090
|
+
![glimmer dsl tk screenshot sample hello text](images/glimmer-dsl-tk-screenshot-sample-hello-text.png)
|
2091
|
+
|
1689
2092
|
### Hello, Spinbox!
|
1690
2093
|
|
1691
2094
|
Glimmer code (from [samples/hello/hello_spinbox.rb](samples/hello/hello_spinbox.rb)):
|
@@ -1843,6 +2246,315 @@ Glimmer app:
|
|
1843
2246
|
|
1844
2247
|
![glimmer dsl tk screenshot sample hello computed](images/glimmer-dsl-tk-screenshot-sample-hello-computed.png)
|
1845
2248
|
|
2249
|
+
### Hello, Drag and Drop!
|
2250
|
+
|
2251
|
+
Glimmer code (from [samples/hello/hello_drag_and_drop.rb](samples/hello/hello_drag_and_drop.rb)):
|
2252
|
+
|
2253
|
+
```ruby
|
2254
|
+
require "glimmer-dsl-tk"
|
2255
|
+
require "glimmer/tk/drag_and_drop_extension"
|
2256
|
+
|
2257
|
+
include Glimmer
|
2258
|
+
|
2259
|
+
root {
|
2260
|
+
title "Hello, Drag and Drop!"
|
2261
|
+
frame {
|
2262
|
+
padding 5
|
2263
|
+
labelframe {
|
2264
|
+
text "Drag sources"
|
2265
|
+
padding 5
|
2266
|
+
label {
|
2267
|
+
text "Entry"
|
2268
|
+
grid :row => 0, :column => 0
|
2269
|
+
}
|
2270
|
+
entry {
|
2271
|
+
text "Drag entry text"
|
2272
|
+
width 30
|
2273
|
+
grid :row => 0, :column => 1, :pady => 5, :sticky => "e"
|
2274
|
+
on_drag_start { |event|
|
2275
|
+
event.data = event.source.textvariable&.value
|
2276
|
+
event.source.configure(:cursor => "hand2")
|
2277
|
+
TkLabel.new(event.tooltip) {
|
2278
|
+
text event.data + " "
|
2279
|
+
bg "yellow"
|
2280
|
+
bitmap "warning"
|
2281
|
+
compound "right"
|
2282
|
+
}.pack
|
2283
|
+
}
|
2284
|
+
on_drag_motion { |event|
|
2285
|
+
if event.drop_accepted
|
2286
|
+
event.source.configure(:cursor => "hand1")
|
2287
|
+
else
|
2288
|
+
event.source.configure(:cursor => "hand2")
|
2289
|
+
end
|
2290
|
+
event.tooltip.geometry("+#{event.x_root + 10}+#{event.y_root - 4}")
|
2291
|
+
}
|
2292
|
+
}
|
2293
|
+
label {
|
2294
|
+
text "Label"
|
2295
|
+
grid :row => 1, :column => 0
|
2296
|
+
}
|
2297
|
+
label {
|
2298
|
+
text "Drag label text"
|
2299
|
+
width 30
|
2300
|
+
grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
|
2301
|
+
drag_source true
|
2302
|
+
}
|
2303
|
+
label {
|
2304
|
+
text "Combobox"
|
2305
|
+
grid :row => 2, :column => 0
|
2306
|
+
}
|
2307
|
+
combobox {
|
2308
|
+
text "Spain"
|
2309
|
+
values %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
|
2310
|
+
width 27
|
2311
|
+
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
2312
|
+
on_drag_start { |event|
|
2313
|
+
event.data = event.source.textvariable&.value
|
2314
|
+
}
|
2315
|
+
}
|
2316
|
+
label {
|
2317
|
+
text "Button"
|
2318
|
+
grid :row => 3, :column => 0
|
2319
|
+
}
|
2320
|
+
button {
|
2321
|
+
text "Drag it"
|
2322
|
+
grid :row => 3, :column => 1, :pady => 5, :sticky => "w"
|
2323
|
+
drag_source true
|
2324
|
+
}
|
2325
|
+
}
|
2326
|
+
|
2327
|
+
labelframe {
|
2328
|
+
text "Drop targets"
|
2329
|
+
grid :sticky => "nsew", :pady => 15
|
2330
|
+
padding 5
|
2331
|
+
label {
|
2332
|
+
text "Entry"
|
2333
|
+
grid :row => 0, :column => 0
|
2334
|
+
}
|
2335
|
+
entry {
|
2336
|
+
width 30
|
2337
|
+
grid :row => 0, :column => 1, :pady => 5, :sticky => "e"
|
2338
|
+
on_drop { |event|
|
2339
|
+
event.target.textvariable.value = event.data
|
2340
|
+
}
|
2341
|
+
}
|
2342
|
+
label {
|
2343
|
+
text "Label"
|
2344
|
+
grid :row => 1, :column => 0
|
2345
|
+
}
|
2346
|
+
label {
|
2347
|
+
width 30
|
2348
|
+
grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
|
2349
|
+
borderwidth 2
|
2350
|
+
relief "solid"
|
2351
|
+
on_drop { |event|
|
2352
|
+
event.target.textvariable.value = event.data
|
2353
|
+
}
|
2354
|
+
}
|
2355
|
+
label {
|
2356
|
+
text "Combobox"
|
2357
|
+
grid :row => 2, :column => 0
|
2358
|
+
}
|
2359
|
+
combobox {
|
2360
|
+
width 27
|
2361
|
+
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
2362
|
+
on_drop { |event|
|
2363
|
+
event.target.textvariable.value = event.data
|
2364
|
+
}
|
2365
|
+
}
|
2366
|
+
label {
|
2367
|
+
text "Button"
|
2368
|
+
grid :row => 3, :column => 0
|
2369
|
+
}
|
2370
|
+
button {
|
2371
|
+
text "Drop here"
|
2372
|
+
grid :row => 3, :column => 1, :pady => 5, :sticky => "w"
|
2373
|
+
on_drop { |event|
|
2374
|
+
event.target.text = event.data
|
2375
|
+
}
|
2376
|
+
}
|
2377
|
+
label {
|
2378
|
+
text "Checkbutton"
|
2379
|
+
grid :row => 4, :column => 0
|
2380
|
+
}
|
2381
|
+
checkbutton {
|
2382
|
+
text "Drop here to destroy a widget\n(except button)"
|
2383
|
+
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
2384
|
+
on_drop { |event|
|
2385
|
+
event.target.text = event.data
|
2386
|
+
event.source.destroy unless event.source.is_a? Tk::Button
|
2387
|
+
}
|
2388
|
+
}
|
2389
|
+
}
|
2390
|
+
}
|
2391
|
+
}.open
|
2392
|
+
```
|
2393
|
+
|
2394
|
+
Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
2395
|
+
|
2396
|
+
```
|
2397
|
+
ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_drag_and_drop'"
|
2398
|
+
```
|
2399
|
+
|
2400
|
+
Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
2401
|
+
|
2402
|
+
```
|
2403
|
+
ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_drag_and_drop.rb
|
2404
|
+
```
|
2405
|
+
|
2406
|
+
Glimmer app:
|
2407
|
+
|
2408
|
+
![glimmer dsl tk screenshot sample hello drag and drop](images/glimmer-dsl-tk-screenshot-sample-hello-drag-and-drop.png)
|
2409
|
+
|
2410
|
+
### Hello, Built-in Dialog!
|
2411
|
+
|
2412
|
+
Glimmer code (from [samples/hello/hello_built_in_dialog.rb](samples/hello/hello_built_in_dialog.rb)):
|
2413
|
+
|
2414
|
+
```ruby
|
2415
|
+
require 'glimmer-dsl-tk'
|
2416
|
+
|
2417
|
+
include Glimmer
|
2418
|
+
|
2419
|
+
root { |w|
|
2420
|
+
title 'Hello, Built-in Dialog!'
|
2421
|
+
width 400
|
2422
|
+
height 400
|
2423
|
+
x 150
|
2424
|
+
y 150
|
2425
|
+
|
2426
|
+
frame {
|
2427
|
+
%w[get_open_file get_multiple_open_file get_save_file choose_directory choose_color].each do |dialog|
|
2428
|
+
button {
|
2429
|
+
text dialog.split('_').map(&:capitalize).join(' ')
|
2430
|
+
|
2431
|
+
on('command') do
|
2432
|
+
result = send(dialog, parent: w)
|
2433
|
+
@result_label.text = [result].flatten.join("\n")
|
2434
|
+
end
|
2435
|
+
}
|
2436
|
+
end
|
2437
|
+
|
2438
|
+
button {
|
2439
|
+
text 'Choose Font'
|
2440
|
+
|
2441
|
+
on('command') do
|
2442
|
+
choose_font(family: 'Courier New', size: '30', weight: 'bold') do |chosen_font|
|
2443
|
+
@result_label.text = chosen_font(parent: w)
|
2444
|
+
end
|
2445
|
+
end
|
2446
|
+
}
|
2447
|
+
}
|
2448
|
+
|
2449
|
+
frame {
|
2450
|
+
grid sticky: 'nsew', padx: 15, pady: 15
|
2451
|
+
|
2452
|
+
label {
|
2453
|
+
grid row: 0, column: 0
|
2454
|
+
text 'Result:'
|
2455
|
+
}
|
2456
|
+
|
2457
|
+
@result_label = label {
|
2458
|
+
grid row: 0, column: 1
|
2459
|
+
}
|
2460
|
+
}
|
2461
|
+
}.open
|
2462
|
+
```
|
2463
|
+
|
2464
|
+
Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
2465
|
+
|
2466
|
+
```
|
2467
|
+
ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_built_in_dialog'"
|
2468
|
+
```
|
2469
|
+
|
2470
|
+
Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
2471
|
+
|
2472
|
+
```
|
2473
|
+
ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_built_in_dialog.rb
|
2474
|
+
```
|
2475
|
+
|
2476
|
+
Glimmer app:
|
2477
|
+
|
2478
|
+
![glimmer dsl tk screenshot sample hello built in dialog 1](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-get-open-file.png)
|
2479
|
+
![glimmer dsl tk screenshot sample hello built in dialog 2](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-get-open-file-done.png)
|
2480
|
+
|
2481
|
+
![glimmer dsl tk screenshot sample hello built in dialog 3](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-choose-color.png)
|
2482
|
+
![glimmer dsl tk screenshot sample hello built in dialog 4](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-choose-color-done.png)
|
2483
|
+
|
2484
|
+
![glimmer dsl tk screenshot sample hello built in dialog 5](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-choose-font.png)
|
2485
|
+
![glimmer dsl tk screenshot sample hello built in dialog 6](images/glimmer-dsl-tk-screenshot-sample-hello-built-in-dialog-choose-font-done.png)
|
2486
|
+
|
2487
|
+
### Hello, Separator!
|
2488
|
+
|
2489
|
+
Glimmer code (from [samples/hello/hello_separator.rb](samples/hello/hello_separator.rb)):
|
2490
|
+
|
2491
|
+
```ruby
|
2492
|
+
require 'glimmer-dsl-tk'
|
2493
|
+
|
2494
|
+
include Glimmer
|
2495
|
+
|
2496
|
+
root {
|
2497
|
+
title 'Hello, Separator!'
|
2498
|
+
width 200
|
2499
|
+
height 200
|
2500
|
+
|
2501
|
+
label {
|
2502
|
+
grid row: 0, column: 0, min_width: 100, min_height: 100, column_weight: 0, sticky: 'nsew'
|
2503
|
+
text 'Label 1'
|
2504
|
+
anchor 'center'
|
2505
|
+
}
|
2506
|
+
|
2507
|
+
separator {
|
2508
|
+
grid row: 0, column: 1
|
2509
|
+
orient 'vertical'
|
2510
|
+
}
|
2511
|
+
|
2512
|
+
label {
|
2513
|
+
grid row: 0, column: 2, min_width: 100, min_height: 100, sticky: 'nsew'
|
2514
|
+
text 'Label 2'
|
2515
|
+
anchor 'center'
|
2516
|
+
}
|
2517
|
+
|
2518
|
+
separator {
|
2519
|
+
grid row: 1, column: 0, column_span: 3
|
2520
|
+
orient 'horizontal'
|
2521
|
+
}
|
2522
|
+
|
2523
|
+
label {
|
2524
|
+
grid row: 2, column: 0, min_width: 100, min_height: 100, sticky: 'nsew'
|
2525
|
+
text 'Label 3'
|
2526
|
+
anchor 'center'
|
2527
|
+
}
|
2528
|
+
|
2529
|
+
separator {
|
2530
|
+
grid row: 2, column: 1
|
2531
|
+
orient 'vertical'
|
2532
|
+
}
|
2533
|
+
|
2534
|
+
label {
|
2535
|
+
grid row: 2, column: 2, min_width: 100, min_height: 100, sticky: 'nsew'
|
2536
|
+
text 'Label 4'
|
2537
|
+
anchor 'center'
|
2538
|
+
}
|
2539
|
+
}.open
|
2540
|
+
```
|
2541
|
+
|
2542
|
+
Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
2543
|
+
|
2544
|
+
```
|
2545
|
+
ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_separator'"
|
2546
|
+
```
|
2547
|
+
|
2548
|
+
Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
2549
|
+
|
2550
|
+
```
|
2551
|
+
ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_separator.rb
|
2552
|
+
```
|
2553
|
+
|
2554
|
+
Glimmer app:
|
2555
|
+
|
2556
|
+
![glimmer dsl tk screenshot sample hello separator](images/glimmer-dsl-tk-screenshot-sample-hello-separator.png)
|
2557
|
+
|
1846
2558
|
## Help
|
1847
2559
|
|
1848
2560
|
### Issues
|
@@ -1876,6 +2588,7 @@ These features have been planned or suggested. You might see them in a future ve
|
|
1876
2588
|
## Contributors
|
1877
2589
|
|
1878
2590
|
* [Andy Maleh](https://github.com/AndyObtiva) (Founder)
|
2591
|
+
* [vin1antme](https://github.com/vin1antme)
|
1879
2592
|
|
1880
2593
|
[Click here to view contributor commits.](https://github.com/AndyObtiva/glimmer-dsl-tk/graphs/contributors)
|
1881
2594
|
|