glimmer-dsl-tk 0.0.45 → 0.0.49

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