glimmer-dsl-tk 0.0.45 → 0.0.49
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +207 -42
- data/VERSION +1 -1
- data/glimmer-dsl-tk.gemspec +0 -0
- data/lib/glimmer/tk/drag_and_drop_event.rb +23 -0
- data/lib/glimmer/tk/{drag_and_drop_extension.rb → draggable_and_droppable.rb} +44 -21
- data/lib/glimmer/tk/menu_proxy.rb +12 -3
- data/lib/{os.rb → glimmer/tk/os.rb} +24 -12
- data/lib/glimmer/tk/widget_proxy.rb +5 -0
- data/lib/glimmer-dsl-tk.rb +4 -5
- data/samples/hello/hello_button.rb +6 -6
- data/samples/hello/hello_contextual_menu.rb +156 -0
- data/samples/hello/hello_drag_and_drop.rb +17 -24
- data/samples/hello/hello_menu_bar.rb +1 -1
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 362c0a5cd2265930f395295435fd7d7b9cc63b20d3c68afba754a57bf6c6dd38
|
4
|
+
data.tar.gz: c38b13a059e821f94de00fbb15c979f3fd4a9a8869d33fac0c0b39da38b25717
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39de4985ef3f10898d7d45d6c336780ad9222e560e20b2d35832f649363fbf60db2d3a2831251c44ba2cc1ca7d34f4adfe3394198c7f95408664976937051a82
|
7
|
+
data.tar.gz: 554fffc52441411d7cf81fd0baefb5ca0fbc3406a7f6b61e960599f684bb855a97abfa2892a01bd8ce9f0f0214a6d5664e403ff618ab53fe184c178b83471917
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.0.49
|
4
|
+
|
5
|
+
- [API Breaking] Update menu bar support to require `menu_bar` keyword under `root` or `toplevel`
|
6
|
+
- Support contextual menu by nesting `menu` keyword under `root` or `toplevel`
|
7
|
+
|
8
|
+
## 0.0.48
|
9
|
+
|
10
|
+
- Moved `OS` class to `Glimmer::Tk::OS` to avoid clashing with os gem when installed for users
|
11
|
+
- Moved `DragAndDropEvent` from `Glimmer::Tk::DraggableAndDroppable` into `Glimmer::Tk` namespace directly as `Glimmer::Tk::DragAndDropEvent`
|
12
|
+
|
13
|
+
## 0.0.47
|
14
|
+
|
15
|
+
- Upgrade to glimmer 2.5.1 (includes more advanced data-binding/observer features)
|
16
|
+
|
17
|
+
## 0.0.46
|
18
|
+
|
19
|
+
- Support `drag_source true` on `list` widget
|
20
|
+
- Support `drop_target true` keyword alternative to `on_drop` for cases where it is implied what to drop (text in the case of label, entry, combo, list, and button)
|
21
|
+
- Support `on('drag_start')` (instead of `on_drag_start`), `on('drag_motion')`, and `on('drop')` for consistency with Glimmer DSL for general Tk listener style (`on('event')`)
|
22
|
+
|
3
23
|
## 0.0.45
|
4
24
|
|
5
25
|
- Support `lbl` widget as the non-tile-themed version of `label` (i.e. `::TkLabel` not `::Tk::Tile::TLabel`)
|
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.49
|
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)
|
@@ -53,7 +53,7 @@ Glimmer app:
|
|
53
53
|
|
54
54
|
NOTE: Glimmer DSL for Tk is currently in early alpha mode (incomplete). Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still an early alpha, so the more feedback and issues you report the better.
|
55
55
|
|
56
|
-
Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
56
|
+
Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems you might be interested in:
|
57
57
|
- [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
|
58
58
|
- [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)
|
59
59
|
- [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui): Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development GUI Library)
|
@@ -125,6 +125,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
125
125
|
- [Hello, Scrollbar!](#hello-scrollbar)
|
126
126
|
- [Hello, Scrollbar Frame!](#hello-scrollbar-frame)
|
127
127
|
- [Hello, Menu Bar!](#hello-menu-bar)
|
128
|
+
- [Hello, Contextual Menu!](#hello-contextual-menu)
|
128
129
|
- [Applications](#applications)
|
129
130
|
- [Glimmer Tk Calculator](#glimmer-tk-calculator)
|
130
131
|
- [Y3network Ruby UI](#y3network-ruby-ui)
|
@@ -182,7 +183,7 @@ gem install glimmer-dsl-tk
|
|
182
183
|
|
183
184
|
Add the following to `Gemfile`:
|
184
185
|
```
|
185
|
-
gem 'glimmer-dsl-tk', '0.0.
|
186
|
+
gem 'glimmer-dsl-tk', '0.0.49'
|
186
187
|
```
|
187
188
|
|
188
189
|
And, then run:
|
@@ -306,10 +307,11 @@ keyword(args) | attributes | event bindings & callbacks
|
|
306
307
|
`spinbox` | `text`, `from`, `to`, `increment`, `format`, [more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `command {}`, `'increment'`, `'decrement'`
|
307
308
|
`frame(text: nil)` | `width`, `height`, `borderwidth`, `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`) | None
|
308
309
|
`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
|
309
|
-
`lbl` (non-
|
310
|
+
`lbl` (non-tile-themed version of `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`, `bg`, `bitmap`, [more here](https://tcl.tk/man/tcl8.6/TkCmd/label.htm) | None
|
310
311
|
`list` | `selectmode`, `selection` | None
|
311
312
|
`message_box(type: , message: , detail: , title: , icon: , default: , parent: )` | None | None
|
312
313
|
`menu(label: nil) (label is nil if nested under root/toplevel for menu bar)` | None | None
|
314
|
+
`menu_bar` | None | None
|
313
315
|
`menu_item(style = :command, label: , underline: )` (style also can be `:radiobutton`, `:checkbutton`, `:separator`, `:about`, `:preferences`, `:quit`, `:help`) | `state`, `accelerator`, `selection` & `variable` (if `:radiobutton` or `:checkbutton`), `image`, `compound` | `command`
|
314
316
|
`notebook` | None | None
|
315
317
|
`radiobutton` | `text`, `variable` (Boolean), `image` (optional keyword args: `subsample`, `zoom`, `from`, `to`, `shrink`, `compositingrule`), `compound` (`'center', 'top', 'bottom', 'left', 'right'`), `value` (default: `text`) | `command {}`
|
@@ -480,14 +482,23 @@ Check out the [Hello, Scrollbar!](#hello-scrollbar) sample for a `text` demo wit
|
|
480
482
|
|
481
483
|
#### Drag and Drop API
|
482
484
|
|
483
|
-
Drag and drop works by simply designating a widget as a drag source with attribute `drag_source true`
|
485
|
+
Drag and drop works by simply designating a widget as a drag source with attribute `drag_source true` and another widget as a drop target with attribute `drop_target true`.
|
484
486
|
|
485
|
-
Alternatively, add listeners:
|
486
|
-
- `
|
487
|
-
- `
|
487
|
+
Alternatively, add listeners on the drag source:
|
488
|
+
- `on('drag_start') {|event| ...}`: fires on drag start receiving an `event` arg to set `data` and configure `source`
|
489
|
+
- `on('drag_motion') {|event| ...}`: fires on drag motion receiving an `event` arg to check `event#drop_accepted`, and configure `source` and `tooltip`
|
488
490
|
|
489
|
-
|
490
|
-
- `
|
491
|
+
And on the drop target, add listener:
|
492
|
+
- `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.
|
493
|
+
|
494
|
+
These are all the available attributes on event, which is of type `DragAndDropEvent`:
|
495
|
+
- `source`: drag source widget proxy
|
496
|
+
- `target`: drop target widget proxy
|
497
|
+
- `tooltip`: tooltip widget proxy
|
498
|
+
- `x_root`: x coordinate from top-left root corner
|
499
|
+
- `y_root`: y coordinate from top-left root corner
|
500
|
+
- `data`: data being transferred through drag and drop
|
501
|
+
- `drop_accepted`: boolean indicating if drop was accepted
|
491
502
|
|
492
503
|
Learn more at the [Hello, Drag and Drop!](#hello-drag-and-drop) sample.
|
493
504
|
|
@@ -834,6 +845,9 @@ More details can be found in the [Hello, Button!](#hello-button) sample below.
|
|
834
845
|
- Widget blocks are always declared with curly braces `{}` to clearly visualize hierarchical view code and separate from logic code.
|
835
846
|
- Widget attribute declarations always have arguments that are never wrapped inside parentheses and never take a block.
|
836
847
|
- Widget listeners are always declared with `on` keyword receiving listener event name as an argument. Their multi-line blocks have a `do; end` style to distinguish as logic from widget keywords and attributes.
|
848
|
+
- In a widget's content block, group attributes on top first, with the `grid` geometry management attribute being first, and separate by an empty line from nested widgets and listeners following afterwards.
|
849
|
+
- In a widget's content block, after attributes, you may either include nested widgets second and listeners third or vice versa.
|
850
|
+
- Unlike attributes, nested widgets and listeners are all separated by an empty line to make readability easier except where it helps to group two widgets together (e.g. label and described entry)
|
837
851
|
- Pure logic multi-line blocks that do not constitute GUI DSL view elements in general always have `do; end` style to clearly separate logic code from view code.
|
838
852
|
|
839
853
|
## Samples
|
@@ -1038,14 +1052,14 @@ class HelloButton
|
|
1038
1052
|
text 'Text Button'
|
1039
1053
|
}
|
1040
1054
|
|
1041
|
-
button {
|
1055
|
+
button { |b|
|
1042
1056
|
text <= [self, :count, on_read: ->(value) { "Click To Increment: #{value} " }]
|
1043
1057
|
default 'active'
|
1044
1058
|
focus true
|
1045
1059
|
|
1046
|
-
command
|
1060
|
+
on('command') do
|
1047
1061
|
self.count += 1
|
1048
|
-
|
1062
|
+
end
|
1049
1063
|
}
|
1050
1064
|
}
|
1051
1065
|
|
@@ -1060,9 +1074,9 @@ class HelloButton
|
|
1060
1074
|
button {
|
1061
1075
|
image File.expand_path('../../icons/glimmer.png', __dir__), subsample: 5
|
1062
1076
|
|
1063
|
-
command
|
1077
|
+
on('command') do
|
1064
1078
|
message_box(title: 'Image Button', message: 'Image Button Clicked!')
|
1065
|
-
|
1079
|
+
end
|
1066
1080
|
}
|
1067
1081
|
}
|
1068
1082
|
|
@@ -1077,12 +1091,12 @@ class HelloButton
|
|
1077
1091
|
['center', 'top', 'bottom', 'left', 'right'].each do |compound_option|
|
1078
1092
|
button {
|
1079
1093
|
image File.expand_path('../../icons/glimmer.png', __dir__), subsample: 5
|
1080
|
-
text
|
1094
|
+
text "#{compound_option.capitalize} Image"
|
1081
1095
|
compound compound_option
|
1082
1096
|
|
1083
|
-
command
|
1097
|
+
on('command') do
|
1084
1098
|
message_box(title: 'Text Image Button', message: 'Text Image Button Clicked!', detail: "(#{compound_option})")
|
1085
|
-
|
1099
|
+
end
|
1086
1100
|
}
|
1087
1101
|
end
|
1088
1102
|
}
|
@@ -2729,11 +2743,12 @@ root {
|
|
2729
2743
|
text "Drag entry text"
|
2730
2744
|
width 30
|
2731
2745
|
|
2746
|
+
# drag_source true
|
2732
2747
|
# This is how to do `drag_source true` the manual way for use in exceptional cases
|
2733
|
-
|
2748
|
+
on('drag_start') do |event|
|
2734
2749
|
event.data = event.source.text
|
2735
2750
|
event.source.configure(:cursor => "hand2")
|
2736
|
-
event.tooltip.content {
|
2751
|
+
event.tooltip.content { # re-open tooltip content and add a label
|
2737
2752
|
lbl { # non-tile-theme version of label
|
2738
2753
|
text event.data + " "
|
2739
2754
|
bg "yellow"
|
@@ -2742,7 +2757,7 @@ root {
|
|
2742
2757
|
}
|
2743
2758
|
}
|
2744
2759
|
end
|
2745
|
-
|
2760
|
+
on('drag_motion') do |event|
|
2746
2761
|
if event.drop_accepted?
|
2747
2762
|
event.source.configure(:cursor => "hand1")
|
2748
2763
|
else
|
@@ -2762,9 +2777,7 @@ root {
|
|
2762
2777
|
values %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
|
2763
2778
|
width 27
|
2764
2779
|
|
2765
|
-
|
2766
|
-
event.data = event.source.text
|
2767
|
-
end
|
2780
|
+
drag_source true
|
2768
2781
|
}
|
2769
2782
|
|
2770
2783
|
label {
|
@@ -2778,7 +2791,9 @@ root {
|
|
2778
2791
|
selection 'Canada'
|
2779
2792
|
height 3
|
2780
2793
|
|
2781
|
-
|
2794
|
+
# drag_source true
|
2795
|
+
# This is another alternative to `drag_source true` with manual specification of transferred data only
|
2796
|
+
on('drag_start') do |event|
|
2782
2797
|
event.data = event.source.selection.first
|
2783
2798
|
end
|
2784
2799
|
}
|
@@ -2809,9 +2824,7 @@ root {
|
|
2809
2824
|
borderwidth 2
|
2810
2825
|
relief "solid"
|
2811
2826
|
|
2812
|
-
|
2813
|
-
event.target.text = event.data
|
2814
|
-
end
|
2827
|
+
drop_target true
|
2815
2828
|
}
|
2816
2829
|
|
2817
2830
|
label {
|
@@ -2822,9 +2835,7 @@ root {
|
|
2822
2835
|
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
2823
2836
|
width 30
|
2824
2837
|
|
2825
|
-
|
2826
|
-
event.target.text = event.data
|
2827
|
-
}
|
2838
|
+
drop_target true
|
2828
2839
|
}
|
2829
2840
|
|
2830
2841
|
label {
|
@@ -2835,9 +2846,7 @@ root {
|
|
2835
2846
|
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
2836
2847
|
width 27
|
2837
2848
|
|
2838
|
-
|
2839
|
-
event.target.text = event.data
|
2840
|
-
end
|
2849
|
+
drop_target true
|
2841
2850
|
}
|
2842
2851
|
|
2843
2852
|
label {
|
@@ -2849,9 +2858,7 @@ root {
|
|
2849
2858
|
selectmode 'browse'
|
2850
2859
|
height 3
|
2851
2860
|
|
2852
|
-
|
2853
|
-
event.target.items += [event.data]
|
2854
|
-
end
|
2861
|
+
drop_target true
|
2855
2862
|
}
|
2856
2863
|
|
2857
2864
|
label {
|
@@ -2862,9 +2869,7 @@ root {
|
|
2862
2869
|
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
2863
2870
|
text "Drop here"
|
2864
2871
|
|
2865
|
-
|
2866
|
-
event.target.text = event.data
|
2867
|
-
end
|
2872
|
+
drop_target true
|
2868
2873
|
}
|
2869
2874
|
|
2870
2875
|
label {
|
@@ -2874,8 +2879,10 @@ root {
|
|
2874
2879
|
checkbutton {
|
2875
2880
|
grid :row => 5, :column => 1, :pady => 5, :sticky => "w"
|
2876
2881
|
text "Drop here to destroy a widget"
|
2877
|
-
|
2878
|
-
|
2882
|
+
|
2883
|
+
# drop_target true
|
2884
|
+
# This is an alternative to `drop_target true` with manual consumption of transferred data
|
2885
|
+
on('drop') do |event|
|
2879
2886
|
event.target.text = event.data
|
2880
2887
|
# execute asynchronously after 100ms to ensure all events have been processed before destruction
|
2881
2888
|
::Tk.after(100) {event.source.destroy}
|
@@ -3491,6 +3498,164 @@ Glimmer app:
|
|
3491
3498
|
|
3492
3499
|
![glimmer dsl tk screenshot sample hello menu-bar](images/glimmer-dsl-tk-screenshot-sample-hello-menu-bar-help.png)
|
3493
3500
|
|
3501
|
+
### Hello, Contextual Menu!
|
3502
|
+
|
3503
|
+
Glimmer code (from [samples/hello/hello_contextual_menu.rb](samples/hello/hello_contextual_menu.rb)):
|
3504
|
+
|
3505
|
+
```ruby
|
3506
|
+
require 'glimmer-dsl-tk'
|
3507
|
+
|
3508
|
+
include Glimmer
|
3509
|
+
|
3510
|
+
COLORS = [:white, :red, :yellow, :green, :blue, :magenta, :gray, :black]
|
3511
|
+
|
3512
|
+
Tk::Tile::Style.theme_use 'classic' if OS.mac? # this enables setting background on label just for demo purposes
|
3513
|
+
|
3514
|
+
root { |r|
|
3515
|
+
title 'Hello, Contextual Menu!'
|
3516
|
+
|
3517
|
+
@label = label {
|
3518
|
+
grid row_weight: 1, column_weight: 1
|
3519
|
+
text 'Right-Click To Pop Up Contextual Menu!'
|
3520
|
+
font size: 50
|
3521
|
+
anchor 'center'
|
3522
|
+
}
|
3523
|
+
|
3524
|
+
menu {
|
3525
|
+
menu(label: 'Edit', underline: 0) {
|
3526
|
+
menu_item(label: 'Cut', underline: 2) {
|
3527
|
+
accelerator OS.mac? ? 'Command+X' : 'Control+X'
|
3528
|
+
}
|
3529
|
+
|
3530
|
+
menu_item(label: 'Copy', underline: 0) {
|
3531
|
+
accelerator OS.mac? ? 'Command+C' : 'Control+C'
|
3532
|
+
}
|
3533
|
+
|
3534
|
+
menu_item(label: 'Paste', underline: 0) {
|
3535
|
+
accelerator OS.mac? ? 'Command+V' : 'Control+V'
|
3536
|
+
}
|
3537
|
+
}
|
3538
|
+
|
3539
|
+
menu(label: 'Options', underline: 0) {
|
3540
|
+
menu_item(:checkbutton, label: 'Enabled', underline: 0) {
|
3541
|
+
on('command') do
|
3542
|
+
@select_one_menu.children.each { |menu_item| menu_item.state = menu_item.state == 'disabled' ? 'normal' : 'disabled' }
|
3543
|
+
@select_multiple_menu.children.each { |menu_item| menu_item.state = menu_item.state == 'disabled' ? 'normal' : 'disabled' }
|
3544
|
+
end
|
3545
|
+
}
|
3546
|
+
|
3547
|
+
@select_one_menu = menu(label: 'Select One', underline: 7) {
|
3548
|
+
menu_item(:radiobutton, label: 'Option 1') {
|
3549
|
+
state 'disabled'
|
3550
|
+
}
|
3551
|
+
menu_item(:radiobutton, label: 'Option 2') {
|
3552
|
+
state 'disabled'
|
3553
|
+
}
|
3554
|
+
menu_item(:radiobutton, label: 'Option 3') {
|
3555
|
+
state 'disabled'
|
3556
|
+
}
|
3557
|
+
}
|
3558
|
+
|
3559
|
+
@select_multiple_menu = menu(label: 'Select Multiple', underline: 7) {
|
3560
|
+
menu_item(:checkbutton, label: 'Option 4') {
|
3561
|
+
state 'disabled'
|
3562
|
+
}
|
3563
|
+
menu_item(:checkbutton, label: 'Option 5') {
|
3564
|
+
state 'disabled'
|
3565
|
+
}
|
3566
|
+
menu_item(:checkbutton, label: 'Option 6') {
|
3567
|
+
state 'disabled'
|
3568
|
+
}
|
3569
|
+
}
|
3570
|
+
}
|
3571
|
+
|
3572
|
+
menu(label: 'Language', underline: 3) {
|
3573
|
+
['denmark', 'finland', 'france', 'germany', 'italy', 'mexico', 'netherlands', 'norway', 'usa'].each do |image_name|
|
3574
|
+
menu_item(:radiobutton, label: image_name.capitalize) {
|
3575
|
+
selection image_name == 'usa'
|
3576
|
+
image File.expand_path("images/#{image_name}.png", __dir__)
|
3577
|
+
}
|
3578
|
+
end
|
3579
|
+
}
|
3580
|
+
|
3581
|
+
menu(label: 'Country', underline: 0) {
|
3582
|
+
['denmark', 'finland', 'france', 'germany', 'italy', 'mexico', 'netherlands', 'norway', 'usa'].each do |image_name|
|
3583
|
+
menu_item(:radiobutton, label: image_name.capitalize) {
|
3584
|
+
selection image_name == 'usa'
|
3585
|
+
image File.expand_path("images/#{image_name}.png", __dir__)
|
3586
|
+
compound 'left'
|
3587
|
+
}
|
3588
|
+
end
|
3589
|
+
}
|
3590
|
+
|
3591
|
+
menu(label: 'Format', underline: 3) {
|
3592
|
+
menu(label: 'Background Color', underline: 0) {
|
3593
|
+
COLORS.each { |color_style|
|
3594
|
+
menu_item(:radiobutton, label: color_style.to_s.split('_').map(&:capitalize).join(' ')) {
|
3595
|
+
on('command') do
|
3596
|
+
@label.background = color_style
|
3597
|
+
end
|
3598
|
+
}
|
3599
|
+
}
|
3600
|
+
}
|
3601
|
+
|
3602
|
+
menu(label: 'Foreground Color', underline: 11) {
|
3603
|
+
COLORS.each { |color_style|
|
3604
|
+
menu_item(:radiobutton, label: color_style.to_s.split('_').map(&:capitalize).join(' ')) {
|
3605
|
+
on('command') do
|
3606
|
+
@label.foreground = color_style
|
3607
|
+
end
|
3608
|
+
}
|
3609
|
+
}
|
3610
|
+
}
|
3611
|
+
}
|
3612
|
+
|
3613
|
+
menu(label: 'View', underline: 0) {
|
3614
|
+
menu_item(:radiobutton, label: 'Small', underline: 0) {
|
3615
|
+
accelerator 'Control+S'
|
3616
|
+
|
3617
|
+
on('command') do
|
3618
|
+
@label.font = {size: 25}
|
3619
|
+
end
|
3620
|
+
}
|
3621
|
+
|
3622
|
+
menu_item(:radiobutton, label: 'Medium', underline: 0) {
|
3623
|
+
accelerator 'Control+M'
|
3624
|
+
selection true
|
3625
|
+
|
3626
|
+
on('command') do
|
3627
|
+
@label.font = {size: 50}
|
3628
|
+
end
|
3629
|
+
}
|
3630
|
+
|
3631
|
+
menu_item(:radiobutton, label: 'Large', underline: 0) {
|
3632
|
+
accelerator 'Control+L'
|
3633
|
+
|
3634
|
+
on('command') do
|
3635
|
+
@label.font = {size: 75}
|
3636
|
+
end
|
3637
|
+
}
|
3638
|
+
}
|
3639
|
+
}
|
3640
|
+
}.open
|
3641
|
+
```
|
3642
|
+
|
3643
|
+
Run with [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
3644
|
+
|
3645
|
+
```
|
3646
|
+
ruby -r glimmer-dsl-tk -e "require 'samples/hello/hello_contextual_menu'"
|
3647
|
+
```
|
3648
|
+
|
3649
|
+
Alternatively, run from cloned project without [glimmer-dsl-tk](https://rubygems.org/gems/glimmer-dsl-tk) gem installed:
|
3650
|
+
|
3651
|
+
```
|
3652
|
+
ruby -r ./lib/glimmer-dsl-tk.rb samples/hello/hello_contextual_menu.rb
|
3653
|
+
```
|
3654
|
+
|
3655
|
+
Glimmer app:
|
3656
|
+
|
3657
|
+
![glimmer dsl tk screenshot sample hello contextual-menu](images/glimmer-dsl-tk-screenshot-sample-hello-contextual-menu.png)
|
3658
|
+
|
3494
3659
|
## Applications
|
3495
3660
|
|
3496
3661
|
### Glimmer Tk Calculator
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.49
|
data/glimmer-dsl-tk.gemspec
CHANGED
Binary file
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Glimmer
|
2
|
+
module Tk
|
3
|
+
DragAndDropEvent = Struct.new(:source, :target, :tooltip, :x_root, :y_root, :data, :drop_accepted) do
|
4
|
+
alias drop_accepted? drop_accepted
|
5
|
+
|
6
|
+
def as_json(*)
|
7
|
+
klass = self.class.name
|
8
|
+
{
|
9
|
+
JSON.create_id => klass,
|
10
|
+
"v" => [values[0].object_id, values[1].object_id, values[2].object_id].concat(values.drop 3),
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json(*args)
|
15
|
+
as_json.to_json(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.json_create(object)
|
19
|
+
new(*[ObjectSpace._id2ref(object["v"][0]), ObjectSpace._id2ref(object["v"][1]).proxy, ObjectSpace._id2ref(object["v"][2])].concat(object["v"].drop 3))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -19,12 +19,26 @@
|
|
19
19
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
|
+
require_relative 'drag_and_drop_event'
|
22
23
|
require "json"
|
23
24
|
|
24
25
|
module Glimmer
|
25
26
|
module Tk
|
26
|
-
|
27
|
+
module DraggableAndDroppable
|
27
28
|
attr_accessor :on_drag_motion_block
|
29
|
+
|
30
|
+
def handle_listener(listener_name, &listener)
|
31
|
+
case listener_name.to_s.downcase
|
32
|
+
when 'drag_start'
|
33
|
+
self.on_drag_start_block = listener
|
34
|
+
when 'drag_motion'
|
35
|
+
self.on_drag_motion_block = listener
|
36
|
+
when 'drop'
|
37
|
+
self.on_drop_block = listener
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
28
42
|
|
29
43
|
def drag_source=(value)
|
30
44
|
@drag_source = value
|
@@ -35,6 +49,15 @@ module Glimmer
|
|
35
49
|
end
|
36
50
|
end
|
37
51
|
|
52
|
+
def drop_target=(value)
|
53
|
+
@drop_target = value
|
54
|
+
if @drop_target
|
55
|
+
make_droppable
|
56
|
+
else
|
57
|
+
make_non_droppable
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
38
61
|
def on_drag_start_block=(block)
|
39
62
|
@on_drag_start_block = block
|
40
63
|
make_draggable
|
@@ -43,11 +66,11 @@ module Glimmer
|
|
43
66
|
def on_drop_block=(value)
|
44
67
|
@on_drop_block = value
|
45
68
|
self.tk.bind("<DropEvent>", proc { |tk_event|
|
46
|
-
drop_event = DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
69
|
+
drop_event = Glimmer::Tk::DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
47
70
|
@on_drop_block.call(drop_event) if self == drop_event.target
|
48
71
|
})
|
49
72
|
self.tk.bind("<DropCheckEvent>", proc { |tk_event|
|
50
|
-
drop_check_event = DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
73
|
+
drop_check_event = Glimmer::Tk::DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
51
74
|
drop_check_event.source.event_generate("<DropAcceptedEvent>")
|
52
75
|
})
|
53
76
|
end
|
@@ -64,11 +87,17 @@ module Glimmer
|
|
64
87
|
tooltip = WidgetProxy.new('toplevel', root_parent_proxy, [])
|
65
88
|
tooltip.overrideredirect(1) #create tooltip window to display dragged data
|
66
89
|
tooltip.geometry("+#{tk_event.x_root + 10}+#{tk_event.y_root - 2}")
|
67
|
-
drag_event = DragAndDropEvent.new(self, nil, tooltip, tk_event.x_root, tk_event.y_root, nil, false)
|
90
|
+
drag_event = Glimmer::Tk::DragAndDropEvent.new(self, nil, tooltip, tk_event.x_root, tk_event.y_root, nil, false)
|
68
91
|
if @drag_source
|
69
92
|
tk_event.widget.configure(:cursor => "hand2")
|
70
93
|
# Default data to drag is text
|
71
|
-
drag_event.data = if textvariable_defined?
|
94
|
+
drag_event.data = if textvariable_defined?
|
95
|
+
tk.textvariable.value
|
96
|
+
elsif has_attribute?('text')
|
97
|
+
tk.text
|
98
|
+
elsif has_attribute?('selection')
|
99
|
+
selection.first
|
100
|
+
end
|
72
101
|
tooltip_label = WidgetProxy.new('label', tooltip, [])
|
73
102
|
tooltip_label.text = drag_event.data
|
74
103
|
tooltip_label.pack # TODO look into using grid instead to be consistent with the modern Tk way
|
@@ -118,24 +147,18 @@ module Glimmer
|
|
118
147
|
@tk.bind_remove("<DropAcceptedEvent>")
|
119
148
|
end
|
120
149
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
{
|
127
|
-
JSON.create_id => klass,
|
128
|
-
"v" => [values[0].object_id, values[1].object_id, values[2].object_id].concat(values.drop 3),
|
129
|
-
}
|
130
|
-
end
|
131
|
-
|
132
|
-
def to_json(*args)
|
133
|
-
as_json.to_json(*args)
|
150
|
+
def make_droppable
|
151
|
+
self.on_drop_block = Proc.new do |event|
|
152
|
+
event.target.text = event.data if event.target.has_attribute?('text')
|
153
|
+
event.target.items += [event.data] if event.target.has_attribute?('items')
|
154
|
+
event.target.selection += [event.data] if event.target.has_attribute?('selection')
|
134
155
|
end
|
156
|
+
end
|
135
157
|
|
136
|
-
|
137
|
-
|
138
|
-
|
158
|
+
def make_non_droppable
|
159
|
+
@tk.bind_remove('<DropEvent>')
|
160
|
+
@tk.bind_remove('<DropCheckEvent>')
|
161
|
+
@on_drop_block = nil
|
139
162
|
end
|
140
163
|
end
|
141
164
|
end
|
@@ -34,7 +34,16 @@ module Glimmer
|
|
34
34
|
def post_add_content
|
35
35
|
case @parent_proxy
|
36
36
|
when ToplevelProxy
|
37
|
-
@
|
37
|
+
if @keyword == 'menu_bar'
|
38
|
+
@parent_proxy.tk['menu'] = @tk
|
39
|
+
else
|
40
|
+
if OS.mac?
|
41
|
+
@parent_proxy.tk.bind '2', proc{|x,y| tk.popup(x,y)}, "%X %Y"
|
42
|
+
@parent_proxy.tk.bind 'Control-1', proc{|x,y| tk.popup(x,y)}, "%X %Y"
|
43
|
+
else
|
44
|
+
@parent_proxy.tk.bind '3', proc{|x,y| tk.popup(x,y)}, "%X %Y"
|
45
|
+
end
|
46
|
+
end
|
38
47
|
end
|
39
48
|
end
|
40
49
|
|
@@ -75,8 +84,7 @@ module Glimmer
|
|
75
84
|
# elsif @parent_proxy.parent_proxy.is_a?(ToplevelProxy) && OS.windows? && system?
|
76
85
|
# @tk = ::TkSysMenu_System.new(@parent_proxy.tk).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
77
86
|
else
|
78
|
-
|
79
|
-
@tk = tk_widget_class.new(@parent_proxy.tk).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
87
|
+
@tk = ::Tk::Menu.new(@parent_proxy.tk).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
80
88
|
end
|
81
89
|
case @parent_proxy
|
82
90
|
when MenuProxy
|
@@ -85,5 +93,6 @@ module Glimmer
|
|
85
93
|
end
|
86
94
|
end
|
87
95
|
end
|
96
|
+
MenuBarProxy = MenuProxy
|
88
97
|
end
|
89
98
|
end
|
@@ -19,18 +19,30 @@
|
|
19
19
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
22
|
+
require 'tk'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module Tk
|
26
|
+
class OS
|
27
|
+
class << self
|
28
|
+
def mac?
|
29
|
+
::Tk.windowingsystem == 'aqua'
|
30
|
+
end
|
31
|
+
|
32
|
+
def windows?
|
33
|
+
::Tk.windowingsystem == 'win32'
|
34
|
+
end
|
35
|
+
|
36
|
+
def linux?
|
37
|
+
::Tk.windowingsystem == 'x11'
|
38
|
+
end
|
39
|
+
end
|
34
40
|
end
|
35
41
|
end
|
36
42
|
end
|
43
|
+
|
44
|
+
begin
|
45
|
+
OS
|
46
|
+
rescue
|
47
|
+
::OS = Glimmer::Tk::OS
|
48
|
+
end
|
@@ -21,6 +21,7 @@
|
|
21
21
|
|
22
22
|
require 'glimmer/data_binding/tk/one_time_observer'
|
23
23
|
require 'glimmer/tk/widget'
|
24
|
+
require 'glimmer/tk/draggable_and_droppable'
|
24
25
|
|
25
26
|
module Glimmer
|
26
27
|
module Tk
|
@@ -69,6 +70,8 @@ module Glimmer
|
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
73
|
+
prepend DraggableAndDroppable
|
74
|
+
|
72
75
|
FONTS_PREDEFINED = %w[default text fixed menu heading caption small_caption icon tooltip]
|
73
76
|
|
74
77
|
attr_reader :parent_proxy, :tk, :args, :keyword, :children, :bind_ids, :destroyed
|
@@ -155,6 +158,7 @@ module Glimmer
|
|
155
158
|
end
|
156
159
|
|
157
160
|
def has_state?(attribute)
|
161
|
+
attribute = attribute.to_s
|
158
162
|
attribute = attribute.sub(/\?$/, '').sub(/=$/, '')
|
159
163
|
if @tk.respond_to?(:tile_state)
|
160
164
|
begin
|
@@ -170,6 +174,7 @@ module Glimmer
|
|
170
174
|
end
|
171
175
|
|
172
176
|
def has_attributes_attribute?(attribute)
|
177
|
+
attribute = attribute.to_s
|
173
178
|
attribute = attribute.sub(/\?$/, '').sub(/=$/, '')
|
174
179
|
@tk.respond_to?(:attributes) && @tk.attributes.keys.include?(attribute.to_s)
|
175
180
|
end
|
data/lib/glimmer-dsl-tk.rb
CHANGED
@@ -29,7 +29,6 @@ require 'puts_debuggerer' if ENV['pd'].to_s.downcase == 'true'
|
|
29
29
|
require 'tk'
|
30
30
|
#require 'tkextlib/bwidget' # does not work on Windows
|
31
31
|
#require 'tkextlib/iwidgets' # does not work on Windows
|
32
|
-
require 'os'
|
33
32
|
require 'facets/hash/symbolize_keys'
|
34
33
|
require 'facets/string/underscore'
|
35
34
|
require 'facets/string/camelcase'
|
@@ -38,8 +37,8 @@ require 'delegate'
|
|
38
37
|
# Internal requires
|
39
38
|
# require 'ext/glimmer/config'
|
40
39
|
# require 'ext/glimmer'
|
40
|
+
require 'glimmer/tk/os'
|
41
41
|
require 'glimmer/dsl/tk/dsl'
|
42
|
-
require 'glimmer/tk/drag_and_drop_extension'
|
43
42
|
|
44
43
|
Glimmer::Config.loop_max_count = -1
|
45
44
|
|
@@ -49,11 +48,11 @@ Glimmer::Config.excluded_keyword_checkers << lambda do |method_symbol, *args|
|
|
49
48
|
result ||= method == 'load_iseq'
|
50
49
|
end
|
51
50
|
|
52
|
-
Tk::Tile::Style.theme_use 'clam' if OS.linux?
|
51
|
+
::Tk::Tile::Style.theme_use 'clam' if OS.linux?
|
53
52
|
|
54
53
|
::TkOption.add '*tearOff', 0
|
55
54
|
|
56
|
-
class ::Tk::TkSysMenu_Window < Tk::Menu
|
57
|
-
include Tk::SystemMenu
|
55
|
+
class ::Tk::TkSysMenu_Window < ::Tk::Menu
|
56
|
+
include ::Tk::SystemMenu
|
58
57
|
SYSMENU_NAME = 'window'
|
59
58
|
end
|
@@ -47,9 +47,9 @@ class HelloButton
|
|
47
47
|
default 'active'
|
48
48
|
focus true
|
49
49
|
|
50
|
-
on('command')
|
50
|
+
on('command') do
|
51
51
|
self.count += 1
|
52
|
-
|
52
|
+
end
|
53
53
|
}
|
54
54
|
}
|
55
55
|
|
@@ -64,9 +64,9 @@ class HelloButton
|
|
64
64
|
button {
|
65
65
|
image File.expand_path('../../icons/glimmer.png', __dir__), subsample: 5
|
66
66
|
|
67
|
-
on('command')
|
67
|
+
on('command') do
|
68
68
|
message_box(title: 'Image Button', message: 'Image Button Clicked!')
|
69
|
-
|
69
|
+
end
|
70
70
|
}
|
71
71
|
}
|
72
72
|
|
@@ -84,9 +84,9 @@ class HelloButton
|
|
84
84
|
text "#{compound_option.capitalize} Image"
|
85
85
|
compound compound_option
|
86
86
|
|
87
|
-
on('command')
|
87
|
+
on('command') do
|
88
88
|
message_box(title: 'Text Image Button', message: 'Text Image Button Clicked!', detail: "(#{compound_option})")
|
89
|
-
|
89
|
+
end
|
90
90
|
}
|
91
91
|
end
|
92
92
|
}
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# Copyright (c) 2020-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer-dsl-tk'
|
23
|
+
|
24
|
+
include Glimmer
|
25
|
+
|
26
|
+
COLORS = [:white, :red, :yellow, :green, :blue, :magenta, :gray, :black]
|
27
|
+
|
28
|
+
Tk::Tile::Style.theme_use 'classic' if OS.mac? # this enables setting background on label just for demo purposes
|
29
|
+
|
30
|
+
root { |r|
|
31
|
+
title 'Hello, Contextual Menu!'
|
32
|
+
|
33
|
+
@label = label {
|
34
|
+
grid row_weight: 1, column_weight: 1
|
35
|
+
text 'Right-Click To Pop Up Contextual Menu!'
|
36
|
+
font size: 50
|
37
|
+
anchor 'center'
|
38
|
+
}
|
39
|
+
|
40
|
+
menu {
|
41
|
+
menu(label: 'Edit', underline: 0) {
|
42
|
+
menu_item(label: 'Cut', underline: 2) {
|
43
|
+
accelerator OS.mac? ? 'Command+X' : 'Control+X'
|
44
|
+
}
|
45
|
+
|
46
|
+
menu_item(label: 'Copy', underline: 0) {
|
47
|
+
accelerator OS.mac? ? 'Command+C' : 'Control+C'
|
48
|
+
}
|
49
|
+
|
50
|
+
menu_item(label: 'Paste', underline: 0) {
|
51
|
+
accelerator OS.mac? ? 'Command+V' : 'Control+V'
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
menu(label: 'Options', underline: 0) {
|
56
|
+
menu_item(:checkbutton, label: 'Enabled', underline: 0) {
|
57
|
+
on('command') do
|
58
|
+
@select_one_menu.children.each { |menu_item| menu_item.state = menu_item.state == 'disabled' ? 'normal' : 'disabled' }
|
59
|
+
@select_multiple_menu.children.each { |menu_item| menu_item.state = menu_item.state == 'disabled' ? 'normal' : 'disabled' }
|
60
|
+
end
|
61
|
+
}
|
62
|
+
|
63
|
+
@select_one_menu = menu(label: 'Select One', underline: 7) {
|
64
|
+
menu_item(:radiobutton, label: 'Option 1') {
|
65
|
+
state 'disabled'
|
66
|
+
}
|
67
|
+
menu_item(:radiobutton, label: 'Option 2') {
|
68
|
+
state 'disabled'
|
69
|
+
}
|
70
|
+
menu_item(:radiobutton, label: 'Option 3') {
|
71
|
+
state 'disabled'
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
@select_multiple_menu = menu(label: 'Select Multiple', underline: 7) {
|
76
|
+
menu_item(:checkbutton, label: 'Option 4') {
|
77
|
+
state 'disabled'
|
78
|
+
}
|
79
|
+
menu_item(:checkbutton, label: 'Option 5') {
|
80
|
+
state 'disabled'
|
81
|
+
}
|
82
|
+
menu_item(:checkbutton, label: 'Option 6') {
|
83
|
+
state 'disabled'
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
menu(label: 'Language', underline: 3) {
|
89
|
+
['denmark', 'finland', 'france', 'germany', 'italy', 'mexico', 'netherlands', 'norway', 'usa'].each do |image_name|
|
90
|
+
menu_item(:radiobutton, label: image_name.capitalize) {
|
91
|
+
selection image_name == 'usa'
|
92
|
+
image File.expand_path("images/#{image_name}.png", __dir__)
|
93
|
+
}
|
94
|
+
end
|
95
|
+
}
|
96
|
+
|
97
|
+
menu(label: 'Country', underline: 0) {
|
98
|
+
['denmark', 'finland', 'france', 'germany', 'italy', 'mexico', 'netherlands', 'norway', 'usa'].each do |image_name|
|
99
|
+
menu_item(:radiobutton, label: image_name.capitalize) {
|
100
|
+
selection image_name == 'usa'
|
101
|
+
image File.expand_path("images/#{image_name}.png", __dir__)
|
102
|
+
compound 'left'
|
103
|
+
}
|
104
|
+
end
|
105
|
+
}
|
106
|
+
|
107
|
+
menu(label: 'Format', underline: 3) {
|
108
|
+
menu(label: 'Background Color', underline: 0) {
|
109
|
+
COLORS.each { |color_style|
|
110
|
+
menu_item(:radiobutton, label: color_style.to_s.split('_').map(&:capitalize).join(' ')) {
|
111
|
+
on('command') do
|
112
|
+
@label.background = color_style
|
113
|
+
end
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
menu(label: 'Foreground Color', underline: 11) {
|
119
|
+
COLORS.each { |color_style|
|
120
|
+
menu_item(:radiobutton, label: color_style.to_s.split('_').map(&:capitalize).join(' ')) {
|
121
|
+
on('command') do
|
122
|
+
@label.foreground = color_style
|
123
|
+
end
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
menu(label: 'View', underline: 0) {
|
130
|
+
menu_item(:radiobutton, label: 'Small', underline: 0) {
|
131
|
+
accelerator 'Control+S'
|
132
|
+
|
133
|
+
on('command') do
|
134
|
+
@label.font = {size: 25}
|
135
|
+
end
|
136
|
+
}
|
137
|
+
|
138
|
+
menu_item(:radiobutton, label: 'Medium', underline: 0) {
|
139
|
+
accelerator 'Control+M'
|
140
|
+
selection true
|
141
|
+
|
142
|
+
on('command') do
|
143
|
+
@label.font = {size: 50}
|
144
|
+
end
|
145
|
+
}
|
146
|
+
|
147
|
+
menu_item(:radiobutton, label: 'Large', underline: 0) {
|
148
|
+
accelerator 'Control+L'
|
149
|
+
|
150
|
+
on('command') do
|
151
|
+
@label.font = {size: 75}
|
152
|
+
end
|
153
|
+
}
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}.open
|
@@ -53,11 +53,12 @@ root {
|
|
53
53
|
text "Drag entry text"
|
54
54
|
width 30
|
55
55
|
|
56
|
+
# drag_source true
|
56
57
|
# This is how to do `drag_source true` the manual way for use in exceptional cases
|
57
|
-
|
58
|
+
on('drag_start') do |event|
|
58
59
|
event.data = event.source.text
|
59
60
|
event.source.configure(:cursor => "hand2")
|
60
|
-
event.tooltip.content {
|
61
|
+
event.tooltip.content { # re-open tooltip content and add a label
|
61
62
|
lbl { # non-tile-theme version of label
|
62
63
|
text event.data + " "
|
63
64
|
bg "yellow"
|
@@ -66,7 +67,7 @@ root {
|
|
66
67
|
}
|
67
68
|
}
|
68
69
|
end
|
69
|
-
|
70
|
+
on('drag_motion') do |event|
|
70
71
|
if event.drop_accepted?
|
71
72
|
event.source.configure(:cursor => "hand1")
|
72
73
|
else
|
@@ -86,9 +87,7 @@ root {
|
|
86
87
|
values %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
|
87
88
|
width 27
|
88
89
|
|
89
|
-
|
90
|
-
event.data = event.source.text
|
91
|
-
end
|
90
|
+
drag_source true
|
92
91
|
}
|
93
92
|
|
94
93
|
label {
|
@@ -102,7 +101,9 @@ root {
|
|
102
101
|
selection 'Canada'
|
103
102
|
height 3
|
104
103
|
|
105
|
-
|
104
|
+
# drag_source true
|
105
|
+
# This is another alternative to `drag_source true` with manual specification of transferred data only
|
106
|
+
on('drag_start') do |event|
|
106
107
|
event.data = event.source.selection.first
|
107
108
|
end
|
108
109
|
}
|
@@ -133,9 +134,7 @@ root {
|
|
133
134
|
borderwidth 2
|
134
135
|
relief "solid"
|
135
136
|
|
136
|
-
|
137
|
-
event.target.text = event.data
|
138
|
-
end
|
137
|
+
drop_target true
|
139
138
|
}
|
140
139
|
|
141
140
|
label {
|
@@ -146,9 +145,7 @@ root {
|
|
146
145
|
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
147
146
|
width 30
|
148
147
|
|
149
|
-
|
150
|
-
event.target.text = event.data
|
151
|
-
}
|
148
|
+
drop_target true
|
152
149
|
}
|
153
150
|
|
154
151
|
label {
|
@@ -159,9 +156,7 @@ root {
|
|
159
156
|
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
160
157
|
width 27
|
161
158
|
|
162
|
-
|
163
|
-
event.target.text = event.data
|
164
|
-
end
|
159
|
+
drop_target true
|
165
160
|
}
|
166
161
|
|
167
162
|
label {
|
@@ -173,9 +168,7 @@ root {
|
|
173
168
|
selectmode 'browse'
|
174
169
|
height 3
|
175
170
|
|
176
|
-
|
177
|
-
event.target.items += [event.data]
|
178
|
-
end
|
171
|
+
drop_target true
|
179
172
|
}
|
180
173
|
|
181
174
|
label {
|
@@ -186,9 +179,7 @@ root {
|
|
186
179
|
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
187
180
|
text "Drop here"
|
188
181
|
|
189
|
-
|
190
|
-
event.target.text = event.data
|
191
|
-
end
|
182
|
+
drop_target true
|
192
183
|
}
|
193
184
|
|
194
185
|
label {
|
@@ -198,8 +189,10 @@ root {
|
|
198
189
|
checkbutton {
|
199
190
|
grid :row => 5, :column => 1, :pady => 5, :sticky => "w"
|
200
191
|
text "Drop here to destroy a widget"
|
201
|
-
|
202
|
-
|
192
|
+
|
193
|
+
# drop_target true
|
194
|
+
# This is an alternative to `drop_target true` with manual consumption of transferred data
|
195
|
+
on('drop') do |event|
|
203
196
|
event.target.text = event.data
|
204
197
|
# execute asynchronously after 100ms to ensure all events have been processed before destruction
|
205
198
|
::Tk.after(100) {event.source.destroy}
|
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.49
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.
|
19
|
+
version: 2.5.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.
|
26
|
+
version: 2.5.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: puts_debuggerer
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -208,7 +208,8 @@ files:
|
|
208
208
|
- lib/glimmer/dsl/tk/widget_expression.rb
|
209
209
|
- lib/glimmer/tk/checkbutton_proxy.rb
|
210
210
|
- lib/glimmer/tk/combobox_proxy.rb
|
211
|
-
- lib/glimmer/tk/
|
211
|
+
- lib/glimmer/tk/drag_and_drop_event.rb
|
212
|
+
- lib/glimmer/tk/draggable_and_droppable.rb
|
212
213
|
- lib/glimmer/tk/entry_proxy.rb
|
213
214
|
- lib/glimmer/tk/frame_proxy.rb
|
214
215
|
- lib/glimmer/tk/label_proxy.rb
|
@@ -217,6 +218,7 @@ files:
|
|
217
218
|
- lib/glimmer/tk/menu_item_proxy.rb
|
218
219
|
- lib/glimmer/tk/menu_proxy.rb
|
219
220
|
- lib/glimmer/tk/notebook_proxy.rb
|
221
|
+
- lib/glimmer/tk/os.rb
|
220
222
|
- lib/glimmer/tk/radiobutton_proxy.rb
|
221
223
|
- lib/glimmer/tk/root_proxy.rb
|
222
224
|
- lib/glimmer/tk/scrollbar_frame_proxy.rb
|
@@ -228,7 +230,6 @@ files:
|
|
228
230
|
- lib/glimmer/tk/variable_owner.rb
|
229
231
|
- lib/glimmer/tk/widget.rb
|
230
232
|
- lib/glimmer/tk/widget_proxy.rb
|
231
|
-
- lib/os.rb
|
232
233
|
- samples/elaborate/meta_sample.rb
|
233
234
|
- samples/hello/hello_built_in_dialog.rb
|
234
235
|
- samples/hello/hello_button.rb
|
@@ -236,6 +237,7 @@ files:
|
|
236
237
|
- samples/hello/hello_combobox.rb
|
237
238
|
- samples/hello/hello_computed.rb
|
238
239
|
- samples/hello/hello_computed/contact.rb
|
240
|
+
- samples/hello/hello_contextual_menu.rb
|
239
241
|
- samples/hello/hello_drag_and_drop.rb
|
240
242
|
- samples/hello/hello_entry.rb
|
241
243
|
- samples/hello/hello_frame.rb
|