glimmer-dsl-tk 0.0.44 → 0.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +59 -55
- 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 +39 -9
- 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 +21 -2
- data/samples/hello/hello_drag_and_drop.rb +45 -53
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a9655c46ab2b4638e96077e0795a6b7201456baf020ade27838d139797d3a44
|
4
|
+
data.tar.gz: dc2b2924a180df216a16161aa938b4429f814a59f18e0fba945b73eb40513bd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cab872767a730b059ebdaee18a124f0ded5e9fa0d5f980592b2c9fc9a20d756894846a4662b1f20043108987424daf6b79f895df639d1e273b66cad90f8437ae
|
7
|
+
data.tar.gz: 5a92bbe321b0ca538fbebc84d5e076047b2a761294f47be236f041853873c60787ce593dd142e7a5ba9671b9cdc7faaf1ca6d9f41c9a45fed1dde8cc55b5f184
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.0.45
|
4
|
+
|
5
|
+
- Support `lbl` widget as the non-tile-themed version of `label` (i.e. `::TkLabel` not `::Tk::Tile::TLabel`)
|
6
|
+
- Add `#proxy` method to all Tk widgets to return Glimmer widget proxy objects (e.g. `Tk::Tile::TButton#proxy` returns `Glimmer::Tk::WidgetProxy` object)
|
7
|
+
- Provide question mark alias of `event.drop_accepted` (i.e. `drop_accepted?`)
|
8
|
+
- Have `DragAndDropEvent` `source`/`target` be the enhanced Glimmer widget proxy instead of the unenhanced Tk widget
|
9
|
+
- Look into improving code that uses `TkLabel` explicitly in Hello, Drag and Drop! (do `event.tooltip.content {label {...} }` with Glimmer DSL instead)
|
10
|
+
- Add Glimmer Style Guide
|
11
|
+
- Fix issue with dropping button and list unto checkbox in Hello, Drag and Drop!
|
12
|
+
|
3
13
|
## 0.0.44
|
4
14
|
|
5
15
|
- Fix issue with not being able to drop list into checkbox in Hello, Drag and Drop! by disabling functionality for list just like button
|
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.45
|
2
2
|
## MRI Ruby Desktop Development GUI Library
|
3
3
|
[](http://badge.fury.io/rb/glimmer-dsl-tk)
|
4
4
|
[](https://github.com/AndyObtiva/glimmer-dsl-tk/actions/workflows/ruby.yml)
|
@@ -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.45'
|
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
|
@@ -824,6 +828,14 @@ More details can be found in the [Hello, Button!](#hello-button) sample below.
|
|
824
828
|
|
825
829
|
- Setting `background` attribute on `frame` or `label` does not work in `'aqua'` theme on the Mac (only in `'classic'` theme)
|
826
830
|
|
831
|
+
## Glimmer Style Guide
|
832
|
+
|
833
|
+
- Widget arguments are always wrapped by parentheses.
|
834
|
+
- Widget blocks are always declared with curly braces `{}` to clearly visualize hierarchical view code and separate from logic code.
|
835
|
+
- Widget attribute declarations always have arguments that are never wrapped inside parentheses and never take a block.
|
836
|
+
- 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.
|
837
|
+
- 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
|
+
|
827
839
|
## Samples
|
828
840
|
|
829
841
|
The easiest way to run samples is by launching the Glimmer Meta-Sample (the Sample of Samples).
|
@@ -2699,27 +2711,39 @@ root {
|
|
2699
2711
|
|
2700
2712
|
label {
|
2701
2713
|
grid :row => 0, :column => 0
|
2702
|
-
text "
|
2714
|
+
text "Label"
|
2715
|
+
}
|
2716
|
+
label {
|
2717
|
+
grid :row => 0, :column => 1, :pady => 10, :sticky => "e"
|
2718
|
+
text "Drag label text"
|
2719
|
+
width 30
|
2720
|
+
drag_source true
|
2703
2721
|
}
|
2704
2722
|
|
2723
|
+
label {
|
2724
|
+
grid :row => 1, :column => 0
|
2725
|
+
text "Entry"
|
2726
|
+
}
|
2705
2727
|
entry {
|
2706
|
-
grid :row =>
|
2728
|
+
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
2707
2729
|
text "Drag entry text"
|
2708
2730
|
width 30
|
2709
2731
|
|
2732
|
+
# This is how to do `drag_source true` the manual way for use in exceptional cases
|
2710
2733
|
on_drag_start do |event|
|
2711
|
-
event.data = event.source.
|
2734
|
+
event.data = event.source.text
|
2712
2735
|
event.source.configure(:cursor => "hand2")
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2736
|
+
event.tooltip.content {
|
2737
|
+
lbl { # non-tile-theme version of label
|
2738
|
+
text event.data + " "
|
2739
|
+
bg "yellow"
|
2740
|
+
bitmap "warning"
|
2741
|
+
compound "right"
|
2742
|
+
}
|
2743
|
+
}
|
2719
2744
|
end
|
2720
|
-
|
2721
2745
|
on_drag_motion do |event|
|
2722
|
-
if event.drop_accepted
|
2746
|
+
if event.drop_accepted?
|
2723
2747
|
event.source.configure(:cursor => "hand1")
|
2724
2748
|
else
|
2725
2749
|
event.source.configure(:cursor => "hand2")
|
@@ -2728,23 +2752,10 @@ root {
|
|
2728
2752
|
end
|
2729
2753
|
}
|
2730
2754
|
|
2731
|
-
label {
|
2732
|
-
grid :row => 1, :column => 0
|
2733
|
-
text "Label"
|
2734
|
-
}
|
2735
|
-
|
2736
|
-
label {
|
2737
|
-
grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
|
2738
|
-
text "Drag label text"
|
2739
|
-
width 30
|
2740
|
-
drag_source true
|
2741
|
-
}
|
2742
|
-
|
2743
2755
|
label {
|
2744
2756
|
grid :row => 2, :column => 0
|
2745
2757
|
text "Combobox"
|
2746
2758
|
}
|
2747
|
-
|
2748
2759
|
combobox {
|
2749
2760
|
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
2750
2761
|
text "Spain"
|
@@ -2752,7 +2763,7 @@ root {
|
|
2752
2763
|
width 27
|
2753
2764
|
|
2754
2765
|
on_drag_start do |event|
|
2755
|
-
event.data = event.source.
|
2766
|
+
event.data = event.source.text
|
2756
2767
|
end
|
2757
2768
|
}
|
2758
2769
|
|
@@ -2760,8 +2771,7 @@ root {
|
|
2760
2771
|
grid :row => 3, :column => 0
|
2761
2772
|
text 'List'
|
2762
2773
|
}
|
2763
|
-
|
2764
|
-
country_list = list {
|
2774
|
+
list {
|
2765
2775
|
grid :row => 3, :column => 1, :pady => 5, :sticky => "e"
|
2766
2776
|
selectmode 'browse'
|
2767
2777
|
items %w[USA Canada Mexico]
|
@@ -2769,7 +2779,7 @@ root {
|
|
2769
2779
|
height 3
|
2770
2780
|
|
2771
2781
|
on_drag_start do |event|
|
2772
|
-
event.data = event.source.selection.
|
2782
|
+
event.data = event.source.selection.first
|
2773
2783
|
end
|
2774
2784
|
}
|
2775
2785
|
|
@@ -2777,7 +2787,6 @@ root {
|
|
2777
2787
|
grid :row => 4, :column => 0
|
2778
2788
|
text "Button"
|
2779
2789
|
}
|
2780
|
-
|
2781
2790
|
button {
|
2782
2791
|
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
2783
2792
|
text "Drag it"
|
@@ -2792,45 +2801,42 @@ root {
|
|
2792
2801
|
|
2793
2802
|
label {
|
2794
2803
|
grid :row => 0, :column => 0
|
2795
|
-
text "
|
2804
|
+
text "Label"
|
2796
2805
|
}
|
2797
|
-
|
2798
|
-
|
2799
|
-
grid :row => 0, :column => 1, :pady => 5, :sticky => "e"
|
2806
|
+
label {
|
2807
|
+
grid :row => 0, :column => 1, :pady => 10, :sticky => "e"
|
2800
2808
|
width 30
|
2809
|
+
borderwidth 2
|
2810
|
+
relief "solid"
|
2801
2811
|
|
2802
|
-
on_drop
|
2803
|
-
event.target.
|
2804
|
-
|
2812
|
+
on_drop do |event|
|
2813
|
+
event.target.text = event.data
|
2814
|
+
end
|
2805
2815
|
}
|
2806
2816
|
|
2807
2817
|
label {
|
2808
2818
|
grid :row => 1, :column => 0
|
2809
|
-
text "
|
2819
|
+
text "Entry"
|
2810
2820
|
}
|
2811
|
-
|
2812
|
-
|
2813
|
-
grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
|
2821
|
+
entry {
|
2822
|
+
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
2814
2823
|
width 30
|
2815
|
-
borderwidth 2
|
2816
|
-
relief "solid"
|
2817
2824
|
|
2818
|
-
on_drop
|
2819
|
-
event.target.
|
2820
|
-
|
2825
|
+
on_drop { |event|
|
2826
|
+
event.target.text = event.data
|
2827
|
+
}
|
2821
2828
|
}
|
2822
2829
|
|
2823
2830
|
label {
|
2824
2831
|
grid :row => 2, :column => 0
|
2825
2832
|
text "Combobox"
|
2826
2833
|
}
|
2827
|
-
|
2828
2834
|
combobox {
|
2829
2835
|
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
2830
2836
|
width 27
|
2831
2837
|
|
2832
2838
|
on_drop do |event|
|
2833
|
-
event.target.
|
2839
|
+
event.target.text = event.data
|
2834
2840
|
end
|
2835
2841
|
}
|
2836
2842
|
|
@@ -2838,14 +2844,13 @@ root {
|
|
2838
2844
|
grid :row => 3, :column => 0
|
2839
2845
|
text 'List'
|
2840
2846
|
}
|
2841
|
-
|
2842
2847
|
list {
|
2843
2848
|
grid :row => 3, :column => 1, :pady => 5, :sticky => "e"
|
2844
2849
|
selectmode 'browse'
|
2845
2850
|
height 3
|
2846
2851
|
|
2847
2852
|
on_drop do |event|
|
2848
|
-
event.target.
|
2853
|
+
event.target.items += [event.data]
|
2849
2854
|
end
|
2850
2855
|
}
|
2851
2856
|
|
@@ -2853,7 +2858,6 @@ root {
|
|
2853
2858
|
grid :row => 4, :column => 0
|
2854
2859
|
text "Button"
|
2855
2860
|
}
|
2856
|
-
|
2857
2861
|
button {
|
2858
2862
|
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
2859
2863
|
text "Drop here"
|
@@ -2867,14 +2871,14 @@ root {
|
|
2867
2871
|
grid :row => 5, :column => 0
|
2868
2872
|
text "Checkbutton"
|
2869
2873
|
}
|
2870
|
-
|
2871
2874
|
checkbutton {
|
2872
2875
|
grid :row => 5, :column => 1, :pady => 5, :sticky => "w"
|
2873
|
-
text "Drop here to destroy a widget
|
2876
|
+
text "Drop here to destroy a widget"
|
2874
2877
|
|
2875
2878
|
on_drop do |event|
|
2876
2879
|
event.target.text = event.data
|
2877
|
-
|
2880
|
+
# execute asynchronously after 100ms to ensure all events have been processed before destruction
|
2881
|
+
::Tk.after(100) {event.source.destroy}
|
2878
2882
|
end
|
2879
2883
|
}
|
2880
2884
|
}
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.45
|
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,3 +1,24 @@
|
|
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
|
@@ -23,7 +44,7 @@ module Glimmer
|
|
23
44
|
@on_drop_block = value
|
24
45
|
self.tk.bind("<DropEvent>", proc { |tk_event|
|
25
46
|
drop_event = DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
26
|
-
@on_drop_block.call(drop_event) if self
|
47
|
+
@on_drop_block.call(drop_event) if self == drop_event.target
|
27
48
|
})
|
28
49
|
self.tk.bind("<DropCheckEvent>", proc { |tk_event|
|
29
50
|
drop_check_event = DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
@@ -40,23 +61,30 @@ module Glimmer
|
|
40
61
|
bind("<DropAcceptedEvent>", proc { |event| drag_event.drop_accepted = true })
|
41
62
|
bind("B1-Motion", proc { |tk_event|
|
42
63
|
if drag_event.nil?
|
43
|
-
tooltip =
|
64
|
+
tooltip = WidgetProxy.new('toplevel', root_parent_proxy, [])
|
65
|
+
tooltip.overrideredirect(1) #create tooltip window to display dragged data
|
44
66
|
tooltip.geometry("+#{tk_event.x_root + 10}+#{tk_event.y_root - 2}")
|
45
|
-
drag_event = DragAndDropEvent.new(self
|
67
|
+
drag_event = DragAndDropEvent.new(self, nil, tooltip, tk_event.x_root, tk_event.y_root, nil, false)
|
46
68
|
if @drag_source
|
47
69
|
tk_event.widget.configure(:cursor => "hand2")
|
48
70
|
# Default data to drag is text
|
49
71
|
drag_event.data = if textvariable_defined? then tk.textvariable.value elsif has_attribute?(:text) then tk.text end
|
50
|
-
|
72
|
+
tooltip_label = WidgetProxy.new('label', tooltip, [])
|
73
|
+
tooltip_label.text = drag_event.data
|
74
|
+
tooltip_label.pack # TODO look into using grid instead to be consistent with the modern Tk way
|
51
75
|
elsif !@on_drag_start_block.nil?
|
52
76
|
@on_drag_start_block.call(drag_event)
|
53
|
-
|
77
|
+
if tooltip.winfo_children().length == 0
|
78
|
+
tooltip_label = WidgetProxy.new('label', tooltip, [])
|
79
|
+
tooltip_label.text = drag_event.data
|
80
|
+
tooltip_label.pack # TODO look into using grid instead to be consistent with the modern Tk way
|
81
|
+
end
|
54
82
|
end
|
55
83
|
else
|
56
84
|
drag_event.x_root, drag_event.y_root = tk_event.x_root, tk_event.y_root
|
57
85
|
drag_event.drop_accepted = false
|
58
86
|
move_over_widget = tk_event.widget.winfo_containing(tk_event.x_root, tk_event.y_root)
|
59
|
-
drag_event.target = move_over_widget
|
87
|
+
drag_event.target = move_over_widget.proxy
|
60
88
|
move_over_widget.event_generate("<DropCheckEvent>", :data => drag_event.to_json)
|
61
89
|
if @on_drag_motion_block.nil?
|
62
90
|
# Default motion behavior:
|
@@ -75,7 +103,7 @@ module Glimmer
|
|
75
103
|
})
|
76
104
|
bind("ButtonRelease-1", proc { |tk_event|
|
77
105
|
if drag_event
|
78
|
-
drag_event.target = tk_event.widget.winfo_containing(tk_event.x_root, tk_event.y_root)
|
106
|
+
drag_event.target = tk_event.widget.winfo_containing(tk_event.x_root, tk_event.y_root).proxy
|
79
107
|
drag_event.source.configure(:cursor => "")
|
80
108
|
drag_event.target.event_generate("<DropEvent>", :data => drag_event.to_json)
|
81
109
|
drag_event.tooltip.destroy
|
@@ -91,6 +119,8 @@ module Glimmer
|
|
91
119
|
end
|
92
120
|
|
93
121
|
DragAndDropEvent = Struct.new(:source, :target, :tooltip, :x_root, :y_root, :data, :drop_accepted) do
|
122
|
+
alias drop_accepted? drop_accepted
|
123
|
+
|
94
124
|
def as_json(*)
|
95
125
|
klass = self.class.name
|
96
126
|
{
|
@@ -104,9 +134,9 @@ module Glimmer
|
|
104
134
|
end
|
105
135
|
|
106
136
|
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))
|
137
|
+
new(*[ObjectSpace._id2ref(object["v"][0]), ObjectSpace._id2ref(object["v"][1]).proxy, ObjectSpace._id2ref(object["v"][2])].concat(object["v"].drop 3))
|
108
138
|
end
|
109
139
|
end
|
110
140
|
end
|
111
141
|
end
|
112
|
-
end
|
142
|
+
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,7 @@
|
|
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'
|
23
24
|
|
24
25
|
module Glimmer
|
25
26
|
module Tk
|
@@ -70,7 +71,8 @@ module Glimmer
|
|
70
71
|
|
71
72
|
FONTS_PREDEFINED = %w[default text fixed menu heading caption small_caption icon tooltip]
|
72
73
|
|
73
|
-
attr_reader :parent_proxy, :tk, :args, :keyword, :children
|
74
|
+
attr_reader :parent_proxy, :tk, :args, :keyword, :children, :bind_ids, :destroyed
|
75
|
+
alias destroyed? destroyed
|
74
76
|
|
75
77
|
# Initializes a new Tk Widget
|
76
78
|
#
|
@@ -288,8 +290,10 @@ module Glimmer
|
|
288
290
|
end
|
289
291
|
|
290
292
|
def destroy
|
293
|
+
unbind_all
|
291
294
|
@tk.destroy
|
292
295
|
@on_destroy_procs&.each {|p| p.call(@tk)}
|
296
|
+
@destroyed = true
|
293
297
|
end
|
294
298
|
|
295
299
|
def apply_style(options)
|
@@ -491,6 +495,16 @@ module Glimmer
|
|
491
495
|
handle_listener(listener_name, &listener)
|
492
496
|
end
|
493
497
|
|
498
|
+
def unbind_all
|
499
|
+
@listeners&.keys&.each do |key|
|
500
|
+
if key.to_s.downcase.include?('command')
|
501
|
+
@tk.send(key, '')
|
502
|
+
else
|
503
|
+
@tk.bind(key, '')
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
494
508
|
def content(&block)
|
495
509
|
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Tk::WidgetExpression.new, keyword, *args, &block)
|
496
510
|
end
|
@@ -514,6 +528,11 @@ module Glimmer
|
|
514
528
|
!super_only && tk.respond_to?(method, *args, &block)
|
515
529
|
end
|
516
530
|
|
531
|
+
# inspect is overridden to prevent printing very long stack traces
|
532
|
+
def inspect
|
533
|
+
"#{super[0, 150]}... >"
|
534
|
+
end
|
535
|
+
|
517
536
|
private
|
518
537
|
|
519
538
|
# The griddable parent widget proxy to apply grid to (is different from @tk in composite widgets like notebook or scrolledframe)
|
@@ -528,7 +547,7 @@ module Glimmer
|
|
528
547
|
|
529
548
|
def build_widget
|
530
549
|
tk_widget_class = self.class.tk_widget_class_for(@keyword)
|
531
|
-
@tk = tk_widget_class.new(@parent_proxy.tk, *args)
|
550
|
+
@tk = tk_widget_class.new(@parent_proxy.tk, *args).tap {|tk| tk.singleton_class.include(Glimmer::Tk::Widget); tk.proxy = self}
|
532
551
|
end
|
533
552
|
|
534
553
|
def initialize_defaults
|
@@ -35,27 +35,39 @@ root {
|
|
35
35
|
|
36
36
|
label {
|
37
37
|
grid :row => 0, :column => 0
|
38
|
-
text "
|
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
|
39
45
|
}
|
40
46
|
|
47
|
+
label {
|
48
|
+
grid :row => 1, :column => 0
|
49
|
+
text "Entry"
|
50
|
+
}
|
41
51
|
entry {
|
42
|
-
grid :row =>
|
52
|
+
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
43
53
|
text "Drag entry text"
|
44
54
|
width 30
|
45
55
|
|
56
|
+
# This is how to do `drag_source true` the manual way for use in exceptional cases
|
46
57
|
on_drag_start do |event|
|
47
|
-
event.data = event.source.
|
58
|
+
event.data = event.source.text
|
48
59
|
event.source.configure(:cursor => "hand2")
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
60
|
+
event.tooltip.content {
|
61
|
+
lbl { # non-tile-theme version of label
|
62
|
+
text event.data + " "
|
63
|
+
bg "yellow"
|
64
|
+
bitmap "warning"
|
65
|
+
compound "right"
|
66
|
+
}
|
67
|
+
}
|
55
68
|
end
|
56
|
-
|
57
69
|
on_drag_motion do |event|
|
58
|
-
if event.drop_accepted
|
70
|
+
if event.drop_accepted?
|
59
71
|
event.source.configure(:cursor => "hand1")
|
60
72
|
else
|
61
73
|
event.source.configure(:cursor => "hand2")
|
@@ -64,23 +76,10 @@ root {
|
|
64
76
|
end
|
65
77
|
}
|
66
78
|
|
67
|
-
label {
|
68
|
-
grid :row => 1, :column => 0
|
69
|
-
text "Label"
|
70
|
-
}
|
71
|
-
|
72
|
-
label {
|
73
|
-
grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
|
74
|
-
text "Drag label text"
|
75
|
-
width 30
|
76
|
-
drag_source true
|
77
|
-
}
|
78
|
-
|
79
79
|
label {
|
80
80
|
grid :row => 2, :column => 0
|
81
81
|
text "Combobox"
|
82
82
|
}
|
83
|
-
|
84
83
|
combobox {
|
85
84
|
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
86
85
|
text "Spain"
|
@@ -88,7 +87,7 @@ root {
|
|
88
87
|
width 27
|
89
88
|
|
90
89
|
on_drag_start do |event|
|
91
|
-
event.data = event.source.
|
90
|
+
event.data = event.source.text
|
92
91
|
end
|
93
92
|
}
|
94
93
|
|
@@ -96,8 +95,7 @@ root {
|
|
96
95
|
grid :row => 3, :column => 0
|
97
96
|
text 'List'
|
98
97
|
}
|
99
|
-
|
100
|
-
country_list = list {
|
98
|
+
list {
|
101
99
|
grid :row => 3, :column => 1, :pady => 5, :sticky => "e"
|
102
100
|
selectmode 'browse'
|
103
101
|
items %w[USA Canada Mexico]
|
@@ -105,7 +103,7 @@ root {
|
|
105
103
|
height 3
|
106
104
|
|
107
105
|
on_drag_start do |event|
|
108
|
-
event.data = event.source.selection.
|
106
|
+
event.data = event.source.selection.first
|
109
107
|
end
|
110
108
|
}
|
111
109
|
|
@@ -113,7 +111,6 @@ root {
|
|
113
111
|
grid :row => 4, :column => 0
|
114
112
|
text "Button"
|
115
113
|
}
|
116
|
-
|
117
114
|
button {
|
118
115
|
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
119
116
|
text "Drag it"
|
@@ -128,45 +125,42 @@ root {
|
|
128
125
|
|
129
126
|
label {
|
130
127
|
grid :row => 0, :column => 0
|
131
|
-
text "
|
128
|
+
text "Label"
|
132
129
|
}
|
133
|
-
|
134
|
-
|
135
|
-
grid :row => 0, :column => 1, :pady => 5, :sticky => "e"
|
130
|
+
label {
|
131
|
+
grid :row => 0, :column => 1, :pady => 10, :sticky => "e"
|
136
132
|
width 30
|
133
|
+
borderwidth 2
|
134
|
+
relief "solid"
|
137
135
|
|
138
|
-
on_drop
|
139
|
-
event.target.
|
140
|
-
|
136
|
+
on_drop do |event|
|
137
|
+
event.target.text = event.data
|
138
|
+
end
|
141
139
|
}
|
142
140
|
|
143
141
|
label {
|
144
142
|
grid :row => 1, :column => 0
|
145
|
-
text "
|
143
|
+
text "Entry"
|
146
144
|
}
|
147
|
-
|
148
|
-
|
149
|
-
grid :row => 1, :column => 1, :pady => 10, :sticky => "e"
|
145
|
+
entry {
|
146
|
+
grid :row => 1, :column => 1, :pady => 5, :sticky => "e"
|
150
147
|
width 30
|
151
|
-
borderwidth 2
|
152
|
-
relief "solid"
|
153
148
|
|
154
|
-
on_drop
|
155
|
-
event.target.
|
156
|
-
|
149
|
+
on_drop { |event|
|
150
|
+
event.target.text = event.data
|
151
|
+
}
|
157
152
|
}
|
158
153
|
|
159
154
|
label {
|
160
155
|
grid :row => 2, :column => 0
|
161
156
|
text "Combobox"
|
162
157
|
}
|
163
|
-
|
164
158
|
combobox {
|
165
159
|
grid :row => 2, :column => 1, :pady => 5, :sticky => "e"
|
166
160
|
width 27
|
167
161
|
|
168
162
|
on_drop do |event|
|
169
|
-
event.target.
|
163
|
+
event.target.text = event.data
|
170
164
|
end
|
171
165
|
}
|
172
166
|
|
@@ -174,14 +168,13 @@ root {
|
|
174
168
|
grid :row => 3, :column => 0
|
175
169
|
text 'List'
|
176
170
|
}
|
177
|
-
|
178
171
|
list {
|
179
172
|
grid :row => 3, :column => 1, :pady => 5, :sticky => "e"
|
180
173
|
selectmode 'browse'
|
181
174
|
height 3
|
182
175
|
|
183
176
|
on_drop do |event|
|
184
|
-
event.target.
|
177
|
+
event.target.items += [event.data]
|
185
178
|
end
|
186
179
|
}
|
187
180
|
|
@@ -189,7 +182,6 @@ root {
|
|
189
182
|
grid :row => 4, :column => 0
|
190
183
|
text "Button"
|
191
184
|
}
|
192
|
-
|
193
185
|
button {
|
194
186
|
grid :row => 4, :column => 1, :pady => 5, :sticky => "w"
|
195
187
|
text "Drop here"
|
@@ -203,14 +195,14 @@ root {
|
|
203
195
|
grid :row => 5, :column => 0
|
204
196
|
text "Checkbutton"
|
205
197
|
}
|
206
|
-
|
207
198
|
checkbutton {
|
208
199
|
grid :row => 5, :column => 1, :pady => 5, :sticky => "w"
|
209
|
-
text "Drop here to destroy a widget
|
200
|
+
text "Drop here to destroy a widget"
|
210
201
|
|
211
202
|
on_drop do |event|
|
212
203
|
event.target.text = event.data
|
213
|
-
|
204
|
+
# execute asynchronously after 100ms to ensure all events have been processed before destruction
|
205
|
+
::Tk.after(100) {event.source.destroy}
|
214
206
|
end
|
215
207
|
}
|
216
208
|
}
|
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.45
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
@@ -212,6 +212,7 @@ files:
|
|
212
212
|
- lib/glimmer/tk/entry_proxy.rb
|
213
213
|
- lib/glimmer/tk/frame_proxy.rb
|
214
214
|
- lib/glimmer/tk/label_proxy.rb
|
215
|
+
- lib/glimmer/tk/lbl_proxy.rb
|
215
216
|
- lib/glimmer/tk/list_proxy.rb
|
216
217
|
- lib/glimmer/tk/menu_item_proxy.rb
|
217
218
|
- lib/glimmer/tk/menu_proxy.rb
|
@@ -225,6 +226,7 @@ files:
|
|
225
226
|
- lib/glimmer/tk/toplevel_proxy.rb
|
226
227
|
- lib/glimmer/tk/treeview_proxy.rb
|
227
228
|
- lib/glimmer/tk/variable_owner.rb
|
229
|
+
- lib/glimmer/tk/widget.rb
|
228
230
|
- lib/glimmer/tk/widget_proxy.rb
|
229
231
|
- lib/os.rb
|
230
232
|
- samples/elaborate/meta_sample.rb
|