glimmer-dsl-tk 0.0.42 → 0.0.46
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -1
- data/README.md +148 -80
- data/VERSION +1 -1
- data/glimmer-dsl-tk.gemspec +0 -0
- data/lib/glimmer/dsl/tk/list_selection_data_binding_expression.rb +1 -1
- data/lib/glimmer/tk/{drag_and_drop_extension.rb → draggable_and_droppable.rb} +83 -11
- data/lib/glimmer/tk/lbl_proxy.rb +33 -0
- data/lib/glimmer/tk/menu_proxy.rb +5 -5
- data/lib/glimmer/tk/root_proxy.rb +1 -1
- data/lib/glimmer/tk/scrollbar_frame_proxy.rb +1 -1
- data/lib/glimmer/tk/widget.rb +28 -0
- data/lib/glimmer/tk/widget_proxy.rb +28 -4
- data/lib/glimmer-dsl-tk.rb +1 -1
- data/lib/os.rb +36 -0
- data/samples/hello/hello_button.rb +6 -6
- data/samples/hello/hello_drag_and_drop.rb +108 -64
- metadata +5 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5313d90447c3c864cdbc16c6704c6bcb07fc2b8adcd51f136d92762be919327e
|
4
|
+
data.tar.gz: e4e48e9330f79b4a5c677651336560805485d6d0b036fc7c248f3b0a338e0f82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41b3096f2f320ae2bd277b71f4f98ca8ba0f43e05d50eba9adc1a200106d698c17a67bee78082e2f62cb1179d2185df0765e1e9b4a83fc4de15d367a4701e83d
|
7
|
+
data.tar.gz: 74761ae2d6f037d7c237d47da581ff2be8bf5f2c2c6e96a9656b900b5bc19ea39442afc14b16b9d2f5ac5ff370887973262b0d2cc8223a2fa7080972a63c564d
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,37 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.0.46
|
4
|
+
|
5
|
+
- Support `drag_source true` on `list` widget
|
6
|
+
- 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)
|
7
|
+
- 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')`)
|
8
|
+
|
9
|
+
## 0.0.45
|
10
|
+
|
11
|
+
- Support `lbl` widget as the non-tile-themed version of `label` (i.e. `::TkLabel` not `::Tk::Tile::TLabel`)
|
12
|
+
- Add `#proxy` method to all Tk widgets to return Glimmer widget proxy objects (e.g. `Tk::Tile::TButton#proxy` returns `Glimmer::Tk::WidgetProxy` object)
|
13
|
+
- Provide question mark alias of `event.drop_accepted` (i.e. `drop_accepted?`)
|
14
|
+
- Have `DragAndDropEvent` `source`/`target` be the enhanced Glimmer widget proxy instead of the unenhanced Tk widget
|
15
|
+
- Look into improving code that uses `TkLabel` explicitly in Hello, Drag and Drop! (do `event.tooltip.content {label {...} }` with Glimmer DSL instead)
|
16
|
+
- Add Glimmer Style Guide
|
17
|
+
- Fix issue with dropping button and list unto checkbox in Hello, Drag and Drop!
|
18
|
+
|
19
|
+
## 0.0.44
|
20
|
+
|
21
|
+
- Fix issue with not being able to drop list into checkbox in Hello, Drag and Drop! by disabling functionality for list just like button
|
22
|
+
|
23
|
+
## 0.0.43
|
24
|
+
|
25
|
+
- Modified Hello, Drag and Drop! to include a list
|
26
|
+
- Removed the need to require `'glimmer/tk/drag_and_drop_extension'` to do drag and drop; it is automatically included in `require 'glimmer-dsl-tk'` now.
|
27
|
+
- Remove 'os' gem due to Tk having the capability to detect the OS it is on using `Tk.windowingsystem` (include Glimmer implementation of `OS` class having `OS.mac?`, `OS.windows?` and `OS.linux?`)
|
28
|
+
- Default to 'clam' Tk theme on Linux ('alt' looks a bit too classic with certain widgets)
|
29
|
+
|
3
30
|
## 0.0.42
|
4
31
|
|
5
32
|
- Add vertical/horizontal scrollbars to Meta-Sample
|
6
33
|
- Keep only vertical scrollbar in Hello, Text!
|
7
|
-
- Fix issue with including bwidgets and iwidgets in Windows
|
34
|
+
- Fix issue with including bwidgets and iwidgets in Windows (by removing from default requires, leaving to users to require manually when needed only and only systems that support them)
|
8
35
|
- Fix Hello, Menu Bar! sample in Windows (by disabling Windows-special System menu, which does not seem to be working in Tk)
|
9
36
|
|
10
37
|
## 0.0.41
|
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.46
|
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)
|
@@ -100,6 +100,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
100
100
|
- [Radiobutton Data-Binding](#radiobutton-data-binding)
|
101
101
|
- [Command Callback](#command-callback)
|
102
102
|
- [Gotchas](#gotchas)
|
103
|
+
- [Glimmer Style Guide](#glimmer-style-guide)
|
103
104
|
- [Samples](#samples)
|
104
105
|
- [Hello, World!](#hello-world)
|
105
106
|
- [Hello, Button!](#hello-button)
|
@@ -181,7 +182,7 @@ gem install glimmer-dsl-tk
|
|
181
182
|
|
182
183
|
Add the following to `Gemfile`:
|
183
184
|
```
|
184
|
-
gem 'glimmer-dsl-tk', '0.0.
|
185
|
+
gem 'glimmer-dsl-tk', '0.0.46'
|
185
186
|
```
|
186
187
|
|
187
188
|
And, then run:
|
@@ -225,6 +226,8 @@ The Glimmer GUI DSL follows these simple concepts in mapping from Tk syntax:
|
|
225
226
|
- **Content/Options Block**: Any keyword may optionally be followed by a Ruby curly-brace block containing nested widgets (content) and attributes (options). Attributes are simply Tk option keywords followed by arguments and no block (e.g. `title 'Hello, World!'` under a `root`)
|
226
227
|
- **Event Binding Block**: `on(event) {}` keyword receiving a Tk binding event name (e.g. `KeyPress` or `ComboboxSelected`). Surrounding event by `<>` is optional as [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk) can take care of that automatically.
|
227
228
|
|
229
|
+
Note that Glimmer widgets are proxy objects (wrappers) for Tk widgets. To get wrapped Tk widget from a Glimmer widget, you simply invoke `#tk` method. To get the proxy of a wrapped Tk widget, you may invoke `#proxy` method.
|
230
|
+
|
228
231
|
Example of an app written in [Tk](https://www.tcl.tk/) imperative syntax:
|
229
232
|
|
230
233
|
```ruby
|
@@ -303,6 +306,7 @@ keyword(args) | attributes | event bindings & callbacks
|
|
303
306
|
`spinbox` | `text`, `from`, `to`, `increment`, `format`, [more attributes](https://tcl.tk/man/tcl8.6/TkCmd/text.htm#M116) | `command {}`, `'increment'`, `'decrement'`
|
304
307
|
`frame(text: nil)` | `width`, `height`, `borderwidth`, `relief` (`'flat' (default), 'raised', 'sunken', 'solid', 'ridge', 'groove'`) | None
|
305
308
|
`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-theme 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
|
306
310
|
`list` | `selectmode`, `selection` | None
|
307
311
|
`message_box(type: , message: , detail: , title: , icon: , default: , parent: )` | None | None
|
308
312
|
`menu(label: nil) (label is nil if nested under root/toplevel for menu bar)` | None | None
|
@@ -476,14 +480,23 @@ Check out the [Hello, Scrollbar!](#hello-scrollbar) sample for a `text` demo wit
|
|
476
480
|
|
477
481
|
#### Drag and Drop API
|
478
482
|
|
479
|
-
Drag and drop works by simply designating a widget as a drag source with attribute `drag_source true`
|
483
|
+
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
|
+
|
485
|
+
Alternatively, add listeners on the drag source:
|
486
|
+
- `on('drag_start') {|event| ...}`: fires on drag start receiving an `event` arg to set `data` and configure `source`
|
487
|
+
- `on('drag_motion') {|event| ...}`: fires on drag motion receiving an `event` arg to check `event#drop_accepted`, and configure `source` and `tooltip`
|
480
488
|
|
481
|
-
|
482
|
-
- `
|
483
|
-
- `on_drag_motion {|event| ...}`: fires on drag motion receiving an `event` arg to check `event#drop_accepted`, and configure `source` and `tooltip`
|
489
|
+
And on the drop target, add listener:
|
490
|
+
- `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.
|
484
491
|
|
485
|
-
|
486
|
-
- `
|
492
|
+
These are all the available attributes on event, which is of type `DragAndDropEvent`:
|
493
|
+
- `source`: drag source widget proxy
|
494
|
+
- `target`: drop target widget proxy
|
495
|
+
- `tooltip`: tooltip widget proxy
|
496
|
+
- `x_root`: x coordinate from top-left root corner
|
497
|
+
- `y_root`: y coordinate from top-left root corner
|
498
|
+
- `data`: data being transferred through drag and drop
|
499
|
+
- `drop_accepted`: boolean indicating if drop was accepted
|
487
500
|
|
488
501
|
Learn more at the [Hello, Drag and Drop!](#hello-drag-and-drop) sample.
|
489
502
|
|
@@ -824,6 +837,17 @@ More details can be found in the [Hello, Button!](#hello-button) sample below.
|
|
824
837
|
|
825
838
|
- Setting `background` attribute on `frame` or `label` does not work in `'aqua'` theme on the Mac (only in `'classic'` theme)
|
826
839
|
|
840
|
+
## Glimmer Style Guide
|
841
|
+
|
842
|
+
- Widget arguments are always wrapped by parentheses.
|
843
|
+
- Widget blocks are always declared with curly braces `{}` to clearly visualize hierarchical view code and separate from logic code.
|
844
|
+
- Widget attribute declarations always have arguments that are never wrapped inside parentheses and never take a block.
|
845
|
+
- 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.
|
846
|
+
- 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.
|
847
|
+
- In a widget's content block, after attributes, you may either include nested widgets second and listeners third or vice versa.
|
848
|
+
- 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)
|
849
|
+
- 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.
|
850
|
+
|
827
851
|
## Samples
|
828
852
|
|
829
853
|
The easiest way to run samples is by launching the Glimmer Meta-Sample (the Sample of Samples).
|
@@ -1026,14 +1050,14 @@ class HelloButton
|
|
1026
1050
|
text 'Text Button'
|
1027
1051
|
}
|
1028
1052
|
|
1029
|
-
button {
|
1053
|
+
button { |b|
|
1030
1054
|
text <= [self, :count, on_read: ->(value) { "Click To Increment: #{value} " }]
|
1031
1055
|
default 'active'
|
1032
1056
|
focus true
|
1033
1057
|
|
1034
|
-
command
|
1058
|
+
on('command') do
|
1035
1059
|
self.count += 1
|
1036
|
-
|
1060
|
+
end
|
1037
1061
|
}
|
1038
1062
|
}
|
1039
1063
|
|
@@ -1048,9 +1072,9 @@ class HelloButton
|
|
1048
1072
|
button {
|
1049
1073
|
image File.expand_path('../../icons/glimmer.png', __dir__), subsample: 5
|
1050
1074
|
|
1051
|
-
command
|
1075
|
+
on('command') do
|
1052
1076
|
message_box(title: 'Image Button', message: 'Image Button Clicked!')
|
1053
|
-
|
1077
|
+
end
|
1054
1078
|
}
|
1055
1079
|
}
|
1056
1080
|
|
@@ -1065,12 +1089,12 @@ class HelloButton
|
|
1065
1089
|
['center', 'top', 'bottom', 'left', 'right'].each do |compound_option|
|
1066
1090
|
button {
|
1067
1091
|
image File.expand_path('../../icons/glimmer.png', __dir__), subsample: 5
|
1068
|
-
text
|
1092
|
+
text "#{compound_option.capitalize} Image"
|
1069
1093
|
compound compound_option
|
1070
1094
|
|
1071
|
-
command
|
1095
|
+
on('command') do
|
1072
1096
|
message_box(title: 'Text Image Button', message: 'Text Image Button Clicked!', detail: "(#{compound_option})")
|
1073
|
-
|
1097
|
+
end
|
1074
1098
|
}
|
1075
1099
|
end
|
1076
1100
|
}
|
@@ -2683,140 +2707,184 @@ Glimmer app:
|
|
2683
2707
|
Glimmer code (from [samples/hello/hello_drag_and_drop.rb](samples/hello/hello_drag_and_drop.rb)):
|
2684
2708
|
|
2685
2709
|
```ruby
|
2686
|
-
require
|
2687
|
-
require "glimmer/tk/drag_and_drop_extension"
|
2710
|
+
require 'glimmer-dsl-tk'
|
2688
2711
|
|
2689
2712
|
include Glimmer
|
2690
2713
|
|
2691
2714
|
root {
|
2692
2715
|
title "Hello, Drag and Drop!"
|
2716
|
+
|
2693
2717
|
frame {
|
2694
2718
|
padding 5
|
2719
|
+
|
2695
2720
|
labelframe {
|
2696
2721
|
text "Drag sources"
|
2697
2722
|
padding 5
|
2723
|
+
|
2698
2724
|
label {
|
2699
|
-
text "Entry"
|
2700
2725
|
grid :row => 0, :column => 0
|
2726
|
+
text "Label"
|
2727
|
+
}
|
2728
|
+
label {
|
2729
|
+
grid :row => 0, :column => 1, :pady => 10, :sticky => "e"
|
2730
|
+
text "Drag label text"
|
2731
|
+
width 30
|
2732
|
+
drag_source true
|
2733
|
+
}
|
2734
|
+
|
2735
|
+
label {
|
2736
|
+
grid :row => 1, :column => 0
|
2737
|
+
text "Entry"
|
2701
2738
|
}
|
2702
2739
|
entry {
|
2740
|
+
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
2703
2741
|
text "Drag entry text"
|
2704
2742
|
width 30
|
2705
|
-
|
2706
|
-
|
2707
|
-
|
2743
|
+
|
2744
|
+
# drag_source true
|
2745
|
+
# This is how to do `drag_source true` the manual way for use in exceptional cases
|
2746
|
+
on_drag_start do |event|
|
2747
|
+
event.data = event.source.text
|
2708
2748
|
event.source.configure(:cursor => "hand2")
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
|
2717
|
-
|
2749
|
+
event.tooltip.content { # re-open tooltip content and add a label
|
2750
|
+
lbl { # non-tile-theme version of label
|
2751
|
+
text event.data + " "
|
2752
|
+
bg "yellow"
|
2753
|
+
bitmap "warning"
|
2754
|
+
compound "right"
|
2755
|
+
}
|
2756
|
+
}
|
2757
|
+
end
|
2758
|
+
on_drag_motion do |event|
|
2759
|
+
if event.drop_accepted?
|
2718
2760
|
event.source.configure(:cursor => "hand1")
|
2719
2761
|
else
|
2720
2762
|
event.source.configure(:cursor => "hand2")
|
2721
2763
|
end
|
2722
2764
|
event.tooltip.geometry("+#{event.x_root + 10}+#{event.y_root - 4}")
|
2723
|
-
|
2724
|
-
}
|
2725
|
-
label {
|
2726
|
-
text "Label"
|
2727
|
-
grid :row => 1, :column => 0
|
2728
|
-
}
|
2729
|
-
label {
|
2730
|
-
text "Drag label text"
|
2731
|
-
width 30
|
2732
|
-
grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
|
2733
|
-
drag_source true
|
2765
|
+
end
|
2734
2766
|
}
|
2767
|
+
|
2735
2768
|
label {
|
2736
|
-
text "Combobox"
|
2737
2769
|
grid :row => 2, :column => 0
|
2770
|
+
text "Combobox"
|
2738
2771
|
}
|
2739
2772
|
combobox {
|
2773
|
+
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
2740
2774
|
text "Spain"
|
2741
2775
|
values %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
|
2742
2776
|
width 27
|
2743
|
-
|
2744
|
-
|
2745
|
-
|
2746
|
-
|
2777
|
+
|
2778
|
+
drag_source true
|
2779
|
+
}
|
2780
|
+
|
2781
|
+
label {
|
2782
|
+
grid :row => 3, :column => 0
|
2783
|
+
text 'List'
|
2784
|
+
}
|
2785
|
+
list {
|
2786
|
+
grid :row => 3, :column => 1, :pady => 5, :sticky => "e"
|
2787
|
+
selectmode 'browse'
|
2788
|
+
items %w[USA Canada Mexico]
|
2789
|
+
selection 'Canada'
|
2790
|
+
height 3
|
2791
|
+
|
2792
|
+
# drag_source true
|
2793
|
+
# This is another alternative to `drag_source true` with manual specification of transferred data only
|
2794
|
+
on_drag_start do |event|
|
2795
|
+
event.data = event.source.selection.first
|
2796
|
+
end
|
2747
2797
|
}
|
2798
|
+
|
2748
2799
|
label {
|
2800
|
+
grid :row => 4, :column => 0
|
2749
2801
|
text "Button"
|
2750
|
-
grid :row => 3, :column => 0
|
2751
2802
|
}
|
2752
2803
|
button {
|
2804
|
+
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
2753
2805
|
text "Drag it"
|
2754
|
-
grid :row => 3, :column => 1, :pady => 5, :sticky => "w"
|
2755
2806
|
drag_source true
|
2756
2807
|
}
|
2757
2808
|
}
|
2758
2809
|
|
2759
2810
|
labelframe {
|
2760
|
-
text "Drop targets"
|
2761
2811
|
grid :sticky => "nsew", :pady => 15
|
2812
|
+
text "Drop targets"
|
2762
2813
|
padding 5
|
2814
|
+
|
2763
2815
|
label {
|
2764
|
-
text "Entry"
|
2765
2816
|
grid :row => 0, :column => 0
|
2817
|
+
text "Label"
|
2766
2818
|
}
|
2767
|
-
|
2819
|
+
label {
|
2820
|
+
grid :row => 0, :column => 1, :pady => 10, :sticky => "e"
|
2768
2821
|
width 30
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2822
|
+
borderwidth 2
|
2823
|
+
relief "solid"
|
2824
|
+
|
2825
|
+
drop_target true
|
2773
2826
|
}
|
2827
|
+
|
2774
2828
|
label {
|
2775
|
-
text "Label"
|
2776
2829
|
grid :row => 1, :column => 0
|
2830
|
+
text "Entry"
|
2777
2831
|
}
|
2778
|
-
|
2832
|
+
entry {
|
2833
|
+
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
2779
2834
|
width 30
|
2780
|
-
|
2781
|
-
|
2782
|
-
relief "solid"
|
2783
|
-
on_drop { |event|
|
2784
|
-
event.target.textvariable.value = event.data
|
2785
|
-
}
|
2835
|
+
|
2836
|
+
drop_target true
|
2786
2837
|
}
|
2838
|
+
|
2787
2839
|
label {
|
2788
|
-
text "Combobox"
|
2789
2840
|
grid :row => 2, :column => 0
|
2841
|
+
text "Combobox"
|
2790
2842
|
}
|
2791
2843
|
combobox {
|
2792
|
-
width 27
|
2793
2844
|
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2845
|
+
width 27
|
2846
|
+
|
2847
|
+
drop_target true
|
2797
2848
|
}
|
2849
|
+
|
2798
2850
|
label {
|
2799
|
-
text "Button"
|
2800
2851
|
grid :row => 3, :column => 0
|
2852
|
+
text 'List'
|
2853
|
+
}
|
2854
|
+
list {
|
2855
|
+
grid :row => 3, :column => 1, :pady => 5, :sticky => "e"
|
2856
|
+
selectmode 'browse'
|
2857
|
+
height 3
|
2858
|
+
|
2859
|
+
drop_target true
|
2860
|
+
}
|
2861
|
+
|
2862
|
+
label {
|
2863
|
+
grid :row => 4, :column => 0
|
2864
|
+
text "Button"
|
2801
2865
|
}
|
2802
2866
|
button {
|
2867
|
+
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
2803
2868
|
text "Drop here"
|
2804
|
-
|
2805
|
-
|
2806
|
-
event.target.text = event.data
|
2807
|
-
}
|
2869
|
+
|
2870
|
+
drop_target true
|
2808
2871
|
}
|
2872
|
+
|
2809
2873
|
label {
|
2874
|
+
grid :row => 5, :column => 0
|
2810
2875
|
text "Checkbutton"
|
2811
|
-
grid :row => 4, :column => 0
|
2812
2876
|
}
|
2813
2877
|
checkbutton {
|
2814
|
-
|
2815
|
-
|
2816
|
-
|
2878
|
+
grid :row => 5, :column => 1, :pady => 5, :sticky => "w"
|
2879
|
+
text "Drop here to destroy a widget"
|
2880
|
+
|
2881
|
+
# drop_target true
|
2882
|
+
# This is an alternative to `drop_target true` with manual consumption of transferred data
|
2883
|
+
on_drop do |event|
|
2817
2884
|
event.target.text = event.data
|
2818
|
-
|
2819
|
-
|
2885
|
+
# execute asynchronously after 100ms to ensure all events have been processed before destruction
|
2886
|
+
::Tk.after(100) {event.source.destroy}
|
2887
|
+
end
|
2820
2888
|
}
|
2821
2889
|
}
|
2822
2890
|
}
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.46
|
data/glimmer-dsl-tk.gemspec
CHANGED
Binary file
|
@@ -50,7 +50,7 @@ module Glimmer
|
|
50
50
|
#TODO check if nested data binding works for list widget and other widgets that need custom data binding
|
51
51
|
list_selection_binding.observe(model, model_binding.property_name_expression)
|
52
52
|
|
53
|
-
parent.
|
53
|
+
parent.on('<TreeviewSelect>') do
|
54
54
|
model_binding.call(list_selection_binding.evaluate_property)
|
55
55
|
end
|
56
56
|
end
|
@@ -1,9 +1,43 @@
|
|
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
|
+
|
1
22
|
require "json"
|
2
23
|
|
3
24
|
module Glimmer
|
4
25
|
module Tk
|
5
|
-
|
26
|
+
module DraggableAndDroppable
|
6
27
|
attr_accessor :on_drag_motion_block
|
28
|
+
|
29
|
+
def handle_listener(listener_name, &listener)
|
30
|
+
case listener_name.to_s.downcase
|
31
|
+
when 'drag_start'
|
32
|
+
self.on_drag_start_block = listener
|
33
|
+
when 'drag_motion'
|
34
|
+
self.on_drag_motion_block = listener
|
35
|
+
when 'drop'
|
36
|
+
self.on_drop_block = listener
|
37
|
+
else
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
7
41
|
|
8
42
|
def drag_source=(value)
|
9
43
|
@drag_source = value
|
@@ -14,6 +48,15 @@ module Glimmer
|
|
14
48
|
end
|
15
49
|
end
|
16
50
|
|
51
|
+
def drop_target=(value)
|
52
|
+
@drop_target = value
|
53
|
+
if @drop_target
|
54
|
+
make_droppable
|
55
|
+
else
|
56
|
+
make_non_droppable
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
17
60
|
def on_drag_start_block=(block)
|
18
61
|
@on_drag_start_block = block
|
19
62
|
make_draggable
|
@@ -23,7 +66,7 @@ module Glimmer
|
|
23
66
|
@on_drop_block = value
|
24
67
|
self.tk.bind("<DropEvent>", proc { |tk_event|
|
25
68
|
drop_event = DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
26
|
-
@on_drop_block.call(drop_event) if self
|
69
|
+
@on_drop_block.call(drop_event) if self == drop_event.target
|
27
70
|
})
|
28
71
|
self.tk.bind("<DropCheckEvent>", proc { |tk_event|
|
29
72
|
drop_check_event = DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
@@ -40,23 +83,36 @@ module Glimmer
|
|
40
83
|
bind("<DropAcceptedEvent>", proc { |event| drag_event.drop_accepted = true })
|
41
84
|
bind("B1-Motion", proc { |tk_event|
|
42
85
|
if drag_event.nil?
|
43
|
-
tooltip =
|
86
|
+
tooltip = WidgetProxy.new('toplevel', root_parent_proxy, [])
|
87
|
+
tooltip.overrideredirect(1) #create tooltip window to display dragged data
|
44
88
|
tooltip.geometry("+#{tk_event.x_root + 10}+#{tk_event.y_root - 2}")
|
45
|
-
drag_event = DragAndDropEvent.new(self
|
89
|
+
drag_event = DragAndDropEvent.new(self, nil, tooltip, tk_event.x_root, tk_event.y_root, nil, false)
|
46
90
|
if @drag_source
|
47
91
|
tk_event.widget.configure(:cursor => "hand2")
|
48
92
|
# Default data to drag is text
|
49
|
-
drag_event.data = if textvariable_defined?
|
50
|
-
|
93
|
+
drag_event.data = if textvariable_defined?
|
94
|
+
tk.textvariable.value
|
95
|
+
elsif has_attribute?('text')
|
96
|
+
tk.text
|
97
|
+
elsif has_attribute?('selection')
|
98
|
+
selection.first
|
99
|
+
end
|
100
|
+
tooltip_label = WidgetProxy.new('label', tooltip, [])
|
101
|
+
tooltip_label.text = drag_event.data
|
102
|
+
tooltip_label.pack # TODO look into using grid instead to be consistent with the modern Tk way
|
51
103
|
elsif !@on_drag_start_block.nil?
|
52
104
|
@on_drag_start_block.call(drag_event)
|
53
|
-
|
105
|
+
if tooltip.winfo_children().length == 0
|
106
|
+
tooltip_label = WidgetProxy.new('label', tooltip, [])
|
107
|
+
tooltip_label.text = drag_event.data
|
108
|
+
tooltip_label.pack # TODO look into using grid instead to be consistent with the modern Tk way
|
109
|
+
end
|
54
110
|
end
|
55
111
|
else
|
56
112
|
drag_event.x_root, drag_event.y_root = tk_event.x_root, tk_event.y_root
|
57
113
|
drag_event.drop_accepted = false
|
58
114
|
move_over_widget = tk_event.widget.winfo_containing(tk_event.x_root, tk_event.y_root)
|
59
|
-
drag_event.target = move_over_widget
|
115
|
+
drag_event.target = move_over_widget.proxy
|
60
116
|
move_over_widget.event_generate("<DropCheckEvent>", :data => drag_event.to_json)
|
61
117
|
if @on_drag_motion_block.nil?
|
62
118
|
# Default motion behavior:
|
@@ -75,7 +131,7 @@ module Glimmer
|
|
75
131
|
})
|
76
132
|
bind("ButtonRelease-1", proc { |tk_event|
|
77
133
|
if drag_event
|
78
|
-
drag_event.target = tk_event.widget.winfo_containing(tk_event.x_root, tk_event.y_root)
|
134
|
+
drag_event.target = tk_event.widget.winfo_containing(tk_event.x_root, tk_event.y_root).proxy
|
79
135
|
drag_event.source.configure(:cursor => "")
|
80
136
|
drag_event.target.event_generate("<DropEvent>", :data => drag_event.to_json)
|
81
137
|
drag_event.tooltip.destroy
|
@@ -90,7 +146,23 @@ module Glimmer
|
|
90
146
|
@tk.bind_remove("<DropAcceptedEvent>")
|
91
147
|
end
|
92
148
|
|
149
|
+
def make_droppable
|
150
|
+
self.on_drop_block = Proc.new do |event|
|
151
|
+
event.target.text = event.data if event.target.has_attribute?('text')
|
152
|
+
event.target.items += [event.data] if event.target.has_attribute?('items')
|
153
|
+
event.target.selection += [event.data] if event.target.has_attribute?('selection')
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def make_non_droppable
|
158
|
+
@tk.bind_remove('<DropEvent>')
|
159
|
+
@tk.bind_remove('<DropCheckEvent>')
|
160
|
+
@on_drop_block = nil
|
161
|
+
end
|
162
|
+
|
93
163
|
DragAndDropEvent = Struct.new(:source, :target, :tooltip, :x_root, :y_root, :data, :drop_accepted) do
|
164
|
+
alias drop_accepted? drop_accepted
|
165
|
+
|
94
166
|
def as_json(*)
|
95
167
|
klass = self.class.name
|
96
168
|
{
|
@@ -104,9 +176,9 @@ module Glimmer
|
|
104
176
|
end
|
105
177
|
|
106
178
|
def self.json_create(object)
|
107
|
-
new(*[ObjectSpace._id2ref(object["v"][0]), ObjectSpace._id2ref(object["v"][1]), ObjectSpace._id2ref(object["v"][2])].concat(object["v"].drop 3))
|
179
|
+
new(*[ObjectSpace._id2ref(object["v"][0]), ObjectSpace._id2ref(object["v"][1]).proxy, ObjectSpace._id2ref(object["v"][2])].concat(object["v"].drop 3))
|
108
180
|
end
|
109
181
|
end
|
110
182
|
end
|
111
183
|
end
|
112
|
-
end
|
184
|
+
end
|
@@ -0,0 +1,33 @@
|
|
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/tk/widget_proxy'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module Tk
|
26
|
+
# Non-Themable (non-Tile) Tk Label
|
27
|
+
class LblProxy < WidgetProxy
|
28
|
+
def build_widget
|
29
|
+
@tk = ::TkLabel.new(@parent_proxy.tk, *args).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -63,20 +63,20 @@ module Glimmer
|
|
63
63
|
def build_widget
|
64
64
|
if application?
|
65
65
|
if OS.mac?
|
66
|
-
@tk = ::TkSysMenu_Apple.new(@parent_proxy.tk)
|
66
|
+
@tk = ::TkSysMenu_Apple.new(@parent_proxy.tk).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
67
67
|
@parent_proxy.tk.add :cascade, :menu => @tk
|
68
68
|
end
|
69
69
|
else
|
70
70
|
if @parent_proxy.parent_proxy.is_a?(ToplevelProxy) && (OS.mac? || OS.linux?) && help?
|
71
|
-
@tk = ::TkSysMenu_Help.new(@parent_proxy.tk)
|
71
|
+
@tk = ::TkSysMenu_Help.new(@parent_proxy.tk).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
72
72
|
elsif @parent_proxy.parent_proxy.is_a?(ToplevelProxy) && OS.mac? && window?
|
73
|
-
@tk = ::Tk::TkSysMenu_Window.new(@parent_proxy.tk)
|
73
|
+
@tk = ::Tk::TkSysMenu_Window.new(@parent_proxy.tk).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
74
74
|
# Windows system menu does not seem to work
|
75
75
|
# elsif @parent_proxy.parent_proxy.is_a?(ToplevelProxy) && OS.windows? && system?
|
76
|
-
# @tk = ::TkSysMenu_System.new(@parent_proxy.tk)
|
76
|
+
# @tk = ::TkSysMenu_System.new(@parent_proxy.tk).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
77
77
|
else
|
78
78
|
tk_widget_class = self.class.tk_widget_class_for(@keyword)
|
79
|
-
@tk = tk_widget_class.new(@parent_proxy.tk)
|
79
|
+
@tk = tk_widget_class.new(@parent_proxy.tk).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
80
80
|
end
|
81
81
|
case @parent_proxy
|
82
82
|
when MenuProxy
|
@@ -28,7 +28,7 @@ module Glimmer
|
|
28
28
|
# Follows the Proxy Design Pattern
|
29
29
|
class RootProxy < ToplevelProxy
|
30
30
|
def initialize(*args, &block)
|
31
|
-
@tk = ::TkRoot.new
|
31
|
+
@tk = ::TkRoot.new.tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
32
32
|
@tk.minsize = DEFAULT_WIDTH, DEFAULT_HEIGHT
|
33
33
|
initialize_defaults
|
34
34
|
post_add_content if block.nil?
|
@@ -103,7 +103,7 @@ module Glimmer
|
|
103
103
|
build_yscrollbar
|
104
104
|
build_xscrollbar
|
105
105
|
tk_widget_class = self.class.tk_widget_class_for('frame')
|
106
|
-
@tk = tk_widget_class.new(@canvas_proxy.tk, *args)
|
106
|
+
@tk = tk_widget_class.new(@canvas_proxy.tk, *args).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
107
107
|
TkcWindow.new(@canvas_proxy.tk, 0, 0, :anchor => "nw", :window => @tk)
|
108
108
|
end
|
109
109
|
|
@@ -0,0 +1,28 @@
|
|
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
|
+
module Glimmer
|
23
|
+
module Tk
|
24
|
+
module Widget
|
25
|
+
attr_accessor :proxy
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -20,6 +20,8 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer/data_binding/tk/one_time_observer'
|
23
|
+
require 'glimmer/tk/widget'
|
24
|
+
require 'glimmer/tk/draggable_and_droppable'
|
23
25
|
|
24
26
|
module Glimmer
|
25
27
|
module Tk
|
@@ -49,10 +51,10 @@ module Glimmer
|
|
49
51
|
# TODO consider exposing this via Glimmer::Config
|
50
52
|
potential_tk_widget_class_names = [
|
51
53
|
"::Tk::Tile::#{tk_widget_class_basename}",
|
52
|
-
"::Tk::BWidget::#{tk_widget_class_basename}",
|
53
|
-
"::Tk::Iwidgets::#{tk_widget_class_basename}",
|
54
54
|
"::Tk#{tk_widget_class_basename}",
|
55
55
|
"::Tk::#{tk_widget_class_basename}",
|
56
|
+
"::Tk::BWidget::#{tk_widget_class_basename}",
|
57
|
+
"::Tk::Iwidgets::#{tk_widget_class_basename}",
|
56
58
|
"::Glimmer::Tk::#{tk_widget_class_basename}Proxy",
|
57
59
|
]
|
58
60
|
tk_widget_class = nil
|
@@ -68,9 +70,12 @@ module Glimmer
|
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
73
|
+
prepend DraggableAndDroppable
|
74
|
+
|
71
75
|
FONTS_PREDEFINED = %w[default text fixed menu heading caption small_caption icon tooltip]
|
72
76
|
|
73
|
-
attr_reader :parent_proxy, :tk, :args, :keyword, :children
|
77
|
+
attr_reader :parent_proxy, :tk, :args, :keyword, :children, :bind_ids, :destroyed
|
78
|
+
alias destroyed? destroyed
|
74
79
|
|
75
80
|
# Initializes a new Tk Widget
|
76
81
|
#
|
@@ -153,6 +158,7 @@ module Glimmer
|
|
153
158
|
end
|
154
159
|
|
155
160
|
def has_state?(attribute)
|
161
|
+
attribute = attribute.to_s
|
156
162
|
attribute = attribute.sub(/\?$/, '').sub(/=$/, '')
|
157
163
|
if @tk.respond_to?(:tile_state)
|
158
164
|
begin
|
@@ -168,6 +174,7 @@ module Glimmer
|
|
168
174
|
end
|
169
175
|
|
170
176
|
def has_attributes_attribute?(attribute)
|
177
|
+
attribute = attribute.to_s
|
171
178
|
attribute = attribute.sub(/\?$/, '').sub(/=$/, '')
|
172
179
|
@tk.respond_to?(:attributes) && @tk.attributes.keys.include?(attribute.to_s)
|
173
180
|
end
|
@@ -288,8 +295,10 @@ module Glimmer
|
|
288
295
|
end
|
289
296
|
|
290
297
|
def destroy
|
298
|
+
unbind_all
|
291
299
|
@tk.destroy
|
292
300
|
@on_destroy_procs&.each {|p| p.call(@tk)}
|
301
|
+
@destroyed = true
|
293
302
|
end
|
294
303
|
|
295
304
|
def apply_style(options)
|
@@ -491,6 +500,16 @@ module Glimmer
|
|
491
500
|
handle_listener(listener_name, &listener)
|
492
501
|
end
|
493
502
|
|
503
|
+
def unbind_all
|
504
|
+
@listeners&.keys&.each do |key|
|
505
|
+
if key.to_s.downcase.include?('command')
|
506
|
+
@tk.send(key, '')
|
507
|
+
else
|
508
|
+
@tk.bind(key, '')
|
509
|
+
end
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
494
513
|
def content(&block)
|
495
514
|
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Tk::WidgetExpression.new, keyword, *args, &block)
|
496
515
|
end
|
@@ -514,6 +533,11 @@ module Glimmer
|
|
514
533
|
!super_only && tk.respond_to?(method, *args, &block)
|
515
534
|
end
|
516
535
|
|
536
|
+
# inspect is overridden to prevent printing very long stack traces
|
537
|
+
def inspect
|
538
|
+
"#{super[0, 150]}... >"
|
539
|
+
end
|
540
|
+
|
517
541
|
private
|
518
542
|
|
519
543
|
# The griddable parent widget proxy to apply grid to (is different from @tk in composite widgets like notebook or scrolledframe)
|
@@ -528,7 +552,7 @@ module Glimmer
|
|
528
552
|
|
529
553
|
def build_widget
|
530
554
|
tk_widget_class = self.class.tk_widget_class_for(@keyword)
|
531
|
-
@tk = tk_widget_class.new(@parent_proxy.tk, *args)
|
555
|
+
@tk = tk_widget_class.new(@parent_proxy.tk, *args).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
532
556
|
end
|
533
557
|
|
534
558
|
def initialize_defaults
|
data/lib/glimmer-dsl-tk.rb
CHANGED
data/lib/os.rb
ADDED
@@ -0,0 +1,36 @@
|
|
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
|
+
class OS
|
23
|
+
class << self
|
24
|
+
def mac?
|
25
|
+
Tk.windowingsystem == 'aqua'
|
26
|
+
end
|
27
|
+
|
28
|
+
def windows?
|
29
|
+
Tk.windowingsystem == 'win32'
|
30
|
+
end
|
31
|
+
|
32
|
+
def linux?
|
33
|
+
Tk.windowingsystem == 'x11'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
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
|
}
|
@@ -19,140 +19,184 @@
|
|
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
|
23
|
-
require "glimmer/tk/drag_and_drop_extension"
|
22
|
+
require 'glimmer-dsl-tk'
|
24
23
|
|
25
24
|
include Glimmer
|
26
25
|
|
27
26
|
root {
|
28
27
|
title "Hello, Drag and Drop!"
|
28
|
+
|
29
29
|
frame {
|
30
30
|
padding 5
|
31
|
+
|
31
32
|
labelframe {
|
32
33
|
text "Drag sources"
|
33
34
|
padding 5
|
35
|
+
|
34
36
|
label {
|
35
|
-
text "Entry"
|
36
37
|
grid :row => 0, :column => 0
|
38
|
+
text "Label"
|
39
|
+
}
|
40
|
+
label {
|
41
|
+
grid :row => 0, :column => 1, :pady => 10, :sticky => "e"
|
42
|
+
text "Drag label text"
|
43
|
+
width 30
|
44
|
+
drag_source true
|
45
|
+
}
|
46
|
+
|
47
|
+
label {
|
48
|
+
grid :row => 1, :column => 0
|
49
|
+
text "Entry"
|
37
50
|
}
|
38
51
|
entry {
|
52
|
+
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
39
53
|
text "Drag entry text"
|
40
54
|
width 30
|
41
|
-
|
42
|
-
|
43
|
-
|
55
|
+
|
56
|
+
# drag_source true
|
57
|
+
# This is how to do `drag_source true` the manual way for use in exceptional cases
|
58
|
+
on('drag_start') do |event|
|
59
|
+
event.data = event.source.text
|
44
60
|
event.source.configure(:cursor => "hand2")
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
61
|
+
event.tooltip.content { # re-open tooltip content and add a label
|
62
|
+
lbl { # non-tile-theme version of label
|
63
|
+
text event.data + " "
|
64
|
+
bg "yellow"
|
65
|
+
bitmap "warning"
|
66
|
+
compound "right"
|
67
|
+
}
|
68
|
+
}
|
69
|
+
end
|
70
|
+
on('drag_motion') do |event|
|
71
|
+
if event.drop_accepted?
|
54
72
|
event.source.configure(:cursor => "hand1")
|
55
73
|
else
|
56
74
|
event.source.configure(:cursor => "hand2")
|
57
75
|
end
|
58
76
|
event.tooltip.geometry("+#{event.x_root + 10}+#{event.y_root - 4}")
|
59
|
-
|
60
|
-
}
|
61
|
-
label {
|
62
|
-
text "Label"
|
63
|
-
grid :row => 1, :column => 0
|
77
|
+
end
|
64
78
|
}
|
79
|
+
|
65
80
|
label {
|
66
|
-
text "Drag label text"
|
67
|
-
width 30
|
68
|
-
grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
|
69
|
-
drag_source true
|
70
|
-
}
|
71
|
-
label {
|
72
|
-
text "Combobox"
|
73
81
|
grid :row => 2, :column => 0
|
82
|
+
text "Combobox"
|
74
83
|
}
|
75
84
|
combobox {
|
85
|
+
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
76
86
|
text "Spain"
|
77
87
|
values %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
|
78
88
|
width 27
|
79
|
-
|
80
|
-
|
81
|
-
event.data = event.source.textvariable&.value
|
82
|
-
}
|
89
|
+
|
90
|
+
drag_source true
|
83
91
|
}
|
92
|
+
|
84
93
|
label {
|
85
|
-
text "Button"
|
86
94
|
grid :row => 3, :column => 0
|
95
|
+
text 'List'
|
96
|
+
}
|
97
|
+
list {
|
98
|
+
grid :row => 3, :column => 1, :pady => 5, :sticky => "e"
|
99
|
+
selectmode 'browse'
|
100
|
+
items %w[USA Canada Mexico]
|
101
|
+
selection 'Canada'
|
102
|
+
height 3
|
103
|
+
|
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|
|
107
|
+
event.data = event.source.selection.first
|
108
|
+
end
|
109
|
+
}
|
110
|
+
|
111
|
+
label {
|
112
|
+
grid :row => 4, :column => 0
|
113
|
+
text "Button"
|
87
114
|
}
|
88
115
|
button {
|
116
|
+
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
89
117
|
text "Drag it"
|
90
|
-
grid :row => 3, :column => 1, :pady => 5, :sticky => "w"
|
91
118
|
drag_source true
|
92
119
|
}
|
93
120
|
}
|
94
121
|
|
95
122
|
labelframe {
|
96
|
-
text "Drop targets"
|
97
123
|
grid :sticky => "nsew", :pady => 15
|
124
|
+
text "Drop targets"
|
98
125
|
padding 5
|
126
|
+
|
99
127
|
label {
|
100
|
-
text "Entry"
|
101
128
|
grid :row => 0, :column => 0
|
129
|
+
text "Label"
|
102
130
|
}
|
103
|
-
|
131
|
+
label {
|
132
|
+
grid :row => 0, :column => 1, :pady => 10, :sticky => "e"
|
104
133
|
width 30
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
134
|
+
borderwidth 2
|
135
|
+
relief "solid"
|
136
|
+
|
137
|
+
drop_target true
|
109
138
|
}
|
139
|
+
|
110
140
|
label {
|
111
|
-
text "Label"
|
112
141
|
grid :row => 1, :column => 0
|
142
|
+
text "Entry"
|
113
143
|
}
|
114
|
-
|
144
|
+
entry {
|
145
|
+
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
115
146
|
width 30
|
116
|
-
|
117
|
-
|
118
|
-
relief "solid"
|
119
|
-
on_drop { |event|
|
120
|
-
event.target.textvariable.value = event.data
|
121
|
-
}
|
147
|
+
|
148
|
+
drop_target true
|
122
149
|
}
|
150
|
+
|
123
151
|
label {
|
124
|
-
text "Combobox"
|
125
152
|
grid :row => 2, :column => 0
|
153
|
+
text "Combobox"
|
126
154
|
}
|
127
155
|
combobox {
|
128
|
-
width 27
|
129
156
|
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
130
|
-
|
131
|
-
|
132
|
-
|
157
|
+
width 27
|
158
|
+
|
159
|
+
drop_target true
|
133
160
|
}
|
161
|
+
|
134
162
|
label {
|
135
|
-
text "Button"
|
136
163
|
grid :row => 3, :column => 0
|
164
|
+
text 'List'
|
165
|
+
}
|
166
|
+
list {
|
167
|
+
grid :row => 3, :column => 1, :pady => 5, :sticky => "e"
|
168
|
+
selectmode 'browse'
|
169
|
+
height 3
|
170
|
+
|
171
|
+
drop_target true
|
172
|
+
}
|
173
|
+
|
174
|
+
label {
|
175
|
+
grid :row => 4, :column => 0
|
176
|
+
text "Button"
|
137
177
|
}
|
138
178
|
button {
|
179
|
+
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
139
180
|
text "Drop here"
|
140
|
-
|
141
|
-
|
142
|
-
event.target.text = event.data
|
143
|
-
}
|
181
|
+
|
182
|
+
drop_target true
|
144
183
|
}
|
184
|
+
|
145
185
|
label {
|
186
|
+
grid :row => 5, :column => 0
|
146
187
|
text "Checkbutton"
|
147
|
-
grid :row => 4, :column => 0
|
148
188
|
}
|
149
189
|
checkbutton {
|
150
|
-
|
151
|
-
|
152
|
-
|
190
|
+
grid :row => 5, :column => 1, :pady => 5, :sticky => "w"
|
191
|
+
text "Drop here to destroy a widget"
|
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|
|
153
196
|
event.target.text = event.data
|
154
|
-
|
155
|
-
|
197
|
+
# execute asynchronously after 100ms to ensure all events have been processed before destruction
|
198
|
+
::Tk.after(100) {event.source.destroy}
|
199
|
+
end
|
156
200
|
}
|
157
201
|
}
|
158
202
|
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.46
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
@@ -38,26 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.13.1
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: os
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 1.0.0
|
48
|
-
- - "<"
|
49
|
-
- !ruby/object:Gem::Version
|
50
|
-
version: 2.0.0
|
51
|
-
type: :runtime
|
52
|
-
prerelease: false
|
53
|
-
version_requirements: !ruby/object:Gem::Requirement
|
54
|
-
requirements:
|
55
|
-
- - ">="
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: 1.0.0
|
58
|
-
- - "<"
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: 2.0.0
|
61
41
|
- !ruby/object:Gem::Dependency
|
62
42
|
name: tk
|
63
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -228,10 +208,11 @@ files:
|
|
228
208
|
- lib/glimmer/dsl/tk/widget_expression.rb
|
229
209
|
- lib/glimmer/tk/checkbutton_proxy.rb
|
230
210
|
- lib/glimmer/tk/combobox_proxy.rb
|
231
|
-
- lib/glimmer/tk/
|
211
|
+
- lib/glimmer/tk/draggable_and_droppable.rb
|
232
212
|
- lib/glimmer/tk/entry_proxy.rb
|
233
213
|
- lib/glimmer/tk/frame_proxy.rb
|
234
214
|
- lib/glimmer/tk/label_proxy.rb
|
215
|
+
- lib/glimmer/tk/lbl_proxy.rb
|
235
216
|
- lib/glimmer/tk/list_proxy.rb
|
236
217
|
- lib/glimmer/tk/menu_item_proxy.rb
|
237
218
|
- lib/glimmer/tk/menu_proxy.rb
|
@@ -245,7 +226,9 @@ files:
|
|
245
226
|
- lib/glimmer/tk/toplevel_proxy.rb
|
246
227
|
- lib/glimmer/tk/treeview_proxy.rb
|
247
228
|
- lib/glimmer/tk/variable_owner.rb
|
229
|
+
- lib/glimmer/tk/widget.rb
|
248
230
|
- lib/glimmer/tk/widget_proxy.rb
|
231
|
+
- lib/os.rb
|
249
232
|
- samples/elaborate/meta_sample.rb
|
250
233
|
- samples/hello/hello_built_in_dialog.rb
|
251
234
|
- samples/hello/hello_button.rb
|