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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cb173f133301f49a6f4ddfc86578e450b563ff842b96274b6003b784b2e8acb
4
- data.tar.gz: 810087c40f044768c6394a968b945fdc2e3c4c0d1eb8caac2b3421259c431d61
3
+ metadata.gz: 0a9655c46ab2b4638e96077e0795a6b7201456baf020ade27838d139797d3a44
4
+ data.tar.gz: dc2b2924a180df216a16161aa938b4429f814a59f18e0fba945b73eb40513bd6
5
5
  SHA512:
6
- metadata.gz: 8842b20e509fd9c0f918953942665ac5a0609cbc91b0faf020c808e736890e1d2617abb579b384696711ecb0d40bf7ab82a5a0e669a1ff878bede9ed061c6abb
7
- data.tar.gz: 983740e737d7e066f56411ddea5ab7ab607bf196579d519e41aea07bd4c5e8d24b2dcd178086a3d8f35aa8e6ae7b0b8995cb27e3846516887ad4908e07758847
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.44
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
  [![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.44'
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 "Entry"
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 => 0, :column => 1, :pady => 5, :sticky => "e"
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.textvariable&.value
2734
+ event.data = event.source.text
2712
2735
  event.source.configure(:cursor => "hand2")
2713
- TkLabel.new(event.tooltip) {
2714
- text event.data + " "
2715
- bg "yellow"
2716
- bitmap "warning"
2717
- compound "right"
2718
- }.pack
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.textvariable&.value
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.to_a.first.text
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 "Entry"
2804
+ text "Label"
2796
2805
  }
2797
-
2798
- entry {
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 { |event|
2803
- event.target.textvariable.value = event.data
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 "Label"
2819
+ text "Entry"
2810
2820
  }
2811
-
2812
- label {
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 do |event|
2819
- event.target.textvariable.value = event.data
2820
- end
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.textvariable.value = event.data
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.insert('', 'end', :text => event.data)
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\n(except button)"
2876
+ text "Drop here to destroy a widget"
2874
2877
 
2875
2878
  on_drop do |event|
2876
2879
  event.target.text = event.data
2877
- event.source.destroy unless event.source.is_a? Tk::Button
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.44
1
+ 0.0.45
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.tk.bind('<TreeviewSelect>') do
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.tk == drop_event.target
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 = TkToplevel.new(root).overrideredirect(1) #create tooltip window to display dragged data
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.tk, nil, tooltip, tk_event.x_root, tk_event.y_root, nil, false)
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
- TkLabel.new(tooltip) { text drag_event.data }.pack
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
- TkLabel.new(tooltip) { text drag_event.data }.pack if tooltip.winfo_children().length == 0
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 "Entry"
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 => 0, :column => 1, :pady => 5, :sticky => "e"
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.textvariable&.value
58
+ event.data = event.source.text
48
59
  event.source.configure(:cursor => "hand2")
49
- TkLabel.new(event.tooltip) {
50
- text event.data + " "
51
- bg "yellow"
52
- bitmap "warning"
53
- compound "right"
54
- }.pack
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.textvariable&.value
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.to_a.first.text
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 "Entry"
128
+ text "Label"
132
129
  }
133
-
134
- entry {
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 { |event|
139
- event.target.textvariable.value = event.data
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 "Label"
143
+ text "Entry"
146
144
  }
147
-
148
- label {
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 do |event|
155
- event.target.textvariable.value = event.data
156
- end
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.textvariable.value = event.data
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.insert('', 'end', :text => event.data)
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\n(except button and list)"
200
+ text "Drop here to destroy a widget"
210
201
 
211
202
  on_drop do |event|
212
203
  event.target.text = event.data
213
- event.source.destroy unless event.source.is_a?(Tk::Button) || event.source.is_a?(Tk::Tile::Treeview)
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.44
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