glimmer-dsl-tk 0.0.30 → 0.0.31
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -2
- data/README.md +16 -8
- data/VERSION +1 -1
- data/glimmer-dsl-tk.gemspec +0 -0
- data/lib/glimmer/data_binding/tk/one_time_observer.rb +39 -0
- data/lib/glimmer/dsl/tk/data_binding_expression.rb +3 -2
- data/lib/glimmer/dsl/tk/widget_expression.rb +5 -1
- data/lib/glimmer/tk/root_proxy.rb +2 -77
- data/lib/glimmer/tk/text_proxy.rb +14 -3
- data/lib/glimmer/tk/toplevel_proxy.rb +119 -0
- data/lib/glimmer/tk/widget_proxy.rb +57 -13
- data/samples/hello/hello_text.rb +53 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 883bb9d265c58ea872a90069aba8e308ee4688653d2ca200fb5289976850dc1c
|
4
|
+
data.tar.gz: 34f92aa593f48fbe0edf1b469ebc5ec0b81e2789a8995d1b04cd77748c72c081
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8a0d78446483775e82da34e94ede3a1566b2e1201cd5c3bbbfaa1ed27f424bcb1d61826b7f600616550e999bcec117560d52742f3a4779d94dd8aa7adf18661
|
7
|
+
data.tar.gz: fbc6ad5515dc20099c7e1c1827738f7d2edc133575f030afa69c2256c3e2bc6981986e494ada3498eeda6e4809bc5409dd7a61cc91666898d0dd48d7f1805277
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## 0.0.
|
3
|
+
## 0.0.31
|
4
4
|
|
5
5
|
- Improve Hello, Text! (toolbar buttons: justify left, justify center, justify right)
|
6
|
-
-
|
6
|
+
- `on('destroy') {|widget| ...}` support in widgets to better track calls to "destroy" method and `'<Destroy>'` binding event (as opposed to the unreliable tracking of '<Destroy>' alone)
|
7
|
+
- Support observing `text` general events (e.g. `'<KeyPress>'`) through `on(event) {}` (was not working before because it required applying a tag, a general `__all__` tag is applied automatically now on full range (`1.0` to `end`))
|
8
|
+
- Ensure unregistering observers (like data-binding observers) when destroying a widget
|
9
|
+
- Add `Glimmer::Tk::ToplevelProxy` widget proxy support similar to `Glimmer::Tk::RootProxy`
|
7
10
|
|
11
|
+
## 0.0.30
|
12
|
+
|
13
|
+
- Improve Hello, Text! (toolbar buttons: find dialog)
|
14
|
+
- Fixed Hello, Built-in Dialog! Font Dialog issue
|
8
15
|
## 0.0.29
|
9
16
|
|
10
17
|
- Hello, Built-in Dialog! (demonstrating all built-in dialogs like get_open_file and choose_color)
|
data/README.md
CHANGED
@@ -120,8 +120,9 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
|
|
120
120
|
- [Applications](#applications)
|
121
121
|
- [Glimmer Tk Calculator](#glimmer-tk-calculator)
|
122
122
|
- [Y3network Ruby UI](#y3network-ruby-ui)
|
123
|
-
- [
|
123
|
+
- [CryptoPunks GUI](#cryptopunks-gui)
|
124
124
|
- [Process](#process)
|
125
|
+
- [Resources](#resources)
|
125
126
|
- [Help](#help)
|
126
127
|
- [Issues](#issues)
|
127
128
|
- [Chat](#chat)
|
@@ -1868,6 +1869,8 @@ Glimmer app:
|
|
1868
1869
|
|
1869
1870
|
### Hello, Text!
|
1870
1871
|
|
1872
|
+
You may use the META+F shortcut to bring up the Find Dialog.
|
1873
|
+
|
1871
1874
|
Icons used in this sample were made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon"> www.flaticon.com</a>
|
1872
1875
|
|
1873
1876
|
Glimmer code (from [samples/hello/hello_text.rb](samples/hello/hello_text.rb)):
|
@@ -2150,6 +2153,8 @@ Glimmer app:
|
|
2150
2153
|
|
2151
2154
|
![glimmer dsl tk screenshot sample hello text](images/glimmer-dsl-tk-screenshot-sample-hello-text.png)
|
2152
2155
|
|
2156
|
+
![glimmer dsl tk screenshot sample hello text find dialog](images/glimmer-dsl-tk-screenshot-sample-hello-text-find-dialog.png)
|
2157
|
+
|
2153
2158
|
### Hello, Spinbox!
|
2154
2159
|
|
2155
2160
|
Glimmer code (from [samples/hello/hello_spinbox.rb](samples/hello/hello_spinbox.rb)):
|
@@ -2624,31 +2629,34 @@ Glimmer app:
|
|
2624
2629
|
|
2625
2630
|
https://github.com/ancorgs/glimmer-tk-calculator
|
2626
2631
|
|
2627
|
-
https://raw.githubusercontent.com/ancorgs/glimmer-tk-calculator/master/screenshot.png
|
2632
|
+
![Glimmer Tk Calculator Screenshot](https://raw.githubusercontent.com/ancorgs/glimmer-tk-calculator/master/screenshot.png)
|
2628
2633
|
|
2629
2634
|
### Y3network Ruby UI
|
2630
2635
|
|
2631
2636
|
https://github.com/ancorgs/y3network-ruby-ui
|
2632
2637
|
|
2633
|
-
###
|
2638
|
+
### CryptoPunks GUI
|
2634
2639
|
|
2635
|
-
This is a Graphical User Interface for the famous [
|
2640
|
+
This is a Graphical User Interface for the famous [cryptopunks Ruby gem](https://github.com/cryptopunksnotdead/cryptopunks/tree/master/cryptopunks).
|
2636
2641
|
|
2637
2642
|
https://github.com/AndyObtiva/cryptopunks-gui
|
2638
2643
|
|
2639
|
-
![
|
2644
|
+
![CryptoPunks GUI Screenshot](https://raw.githubusercontent.com/AndyObtiva/cryptopunks-gui/master/screenshots/cryptopunks-gui-screenshot.png)
|
2640
2645
|
|
2641
2646
|
## Process
|
2642
2647
|
|
2643
2648
|
[Glimmer Process](https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md)
|
2644
2649
|
|
2650
|
+
## Resources
|
2651
|
+
|
2652
|
+
- [Tk Tutorial](https://tkdocs.com/tutorial/index.html)
|
2653
|
+
- [Code Master Blog](https://andymaleh.blogspot.com/search/label/Tk)
|
2654
|
+
|
2645
2655
|
## Help
|
2646
2656
|
|
2647
2657
|
### Issues
|
2648
2658
|
|
2649
|
-
|
2650
|
-
|
2651
|
-
[Click here to submit an issue.](https://github.com/AndyObtiva/glimmer/issues)
|
2659
|
+
If you encounter [issues](https://github.com/AndyObtiva/glimmer-dsl-tk/issues) that are not reported, discover missing features that are not mentioned in [TODO.md](TODO.md), or think up better ways to use [Tk](https://www.tcl.tk/) than what is possible with [Glimmer DSL for Tk](https://rubygems.org/gems/glimmer-dsl-tk), you may submit an [issue](https://github.com/AndyObtiva/glimmer-dsl-tk/issues/new) or [pull request](https://github.com/AndyObtiva/glimmer-dsl-tk/compare) on [GitHub](https://github.com).
|
2652
2660
|
|
2653
2661
|
### Chat
|
2654
2662
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.31
|
data/glimmer-dsl-tk.gemspec
CHANGED
Binary file
|
@@ -0,0 +1,39 @@
|
|
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/data_binding/observer'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module DataBinding
|
26
|
+
module Tk
|
27
|
+
# Decorator for Observer that ensures it is only called once
|
28
|
+
# (subsequent invocations of call method do nothing)
|
29
|
+
module OneTimeObserver
|
30
|
+
def call(value)
|
31
|
+
unless @called
|
32
|
+
super
|
33
|
+
@called = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -38,12 +38,13 @@ module Glimmer
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def interpret(parent, keyword, *args, &block)
|
41
|
-
parent.class
|
42
41
|
model_binding = args[0]
|
43
42
|
widget_binding_parameters = [parent, keyword]
|
44
43
|
widget_binding = DataBinding::Tk::WidgetBinding.new(*widget_binding_parameters)
|
45
44
|
#TODO make this options observer dependent and all similar observers in widget specific data binding handlers
|
46
|
-
widget_binding.observe(model_binding)
|
45
|
+
registration = widget_binding.observe(model_binding)
|
46
|
+
parent.on('destroy') { registration.deregister }
|
47
|
+
|
47
48
|
# TODO simplify this logic and put it where it belongs
|
48
49
|
parent.add_observer(model_binding, keyword) if parent.respond_to?(:add_observer, [model_binding, keyword])
|
49
50
|
widget_binding.call(model_binding.evaluate_property)
|
@@ -33,11 +33,15 @@ module Glimmer
|
|
33
33
|
|
34
34
|
def can_interpret?(parent, keyword, *args, &block)
|
35
35
|
!EXCLUDED_KEYWORDS.include?(keyword) and
|
36
|
-
parent.respond_to?(:tk) and
|
37
36
|
Glimmer::Tk::WidgetProxy.widget_exists?(keyword)
|
37
|
+
(parent.respond_to?(:tk) or args.first.respond_to?(:tk))
|
38
38
|
end
|
39
39
|
|
40
40
|
def interpret(parent, keyword, *args, &block)
|
41
|
+
if keyword == 'toplevel' && args.first.respond_to?(:tk)
|
42
|
+
parent = args.first
|
43
|
+
args[0] = args.first.tk
|
44
|
+
end
|
41
45
|
Glimmer::Tk::WidgetProxy.create(keyword, parent, args, &block)
|
42
46
|
end
|
43
47
|
|
@@ -19,18 +19,14 @@
|
|
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 'glimmer/tk/
|
22
|
+
require 'glimmer/tk/toplevel_proxy'
|
23
23
|
|
24
24
|
module Glimmer
|
25
25
|
module Tk
|
26
26
|
# Proxy for TkRoot
|
27
27
|
#
|
28
28
|
# Follows the Proxy Design Pattern
|
29
|
-
class RootProxy <
|
30
|
-
REGEX_GEOMETRY = /[x+-]/
|
31
|
-
DEFAULT_WIDTH = 190
|
32
|
-
DEFAULT_HEIGHT = 95
|
33
|
-
|
29
|
+
class RootProxy < ToplevelProxy
|
34
30
|
def initialize(*args, &block)
|
35
31
|
@tk = ::TkRoot.new
|
36
32
|
@tk.minsize = DEFAULT_WIDTH, DEFAULT_HEIGHT
|
@@ -50,10 +46,6 @@ module Glimmer
|
|
50
46
|
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Tk::RootExpression.new, keyword, *args, &block)
|
51
47
|
end
|
52
48
|
|
53
|
-
def has_attribute?(attribute, *args)
|
54
|
-
%w[width height x y].include?(attribute.to_s) || super
|
55
|
-
end
|
56
|
-
|
57
49
|
def set_attribute(attribute, *args)
|
58
50
|
case attribute.to_s
|
59
51
|
when 'iconphoto'
|
@@ -70,45 +62,8 @@ module Glimmer
|
|
70
62
|
end
|
71
63
|
end
|
72
64
|
|
73
|
-
def width
|
74
|
-
geometry.split(REGEX_GEOMETRY)[0].to_i
|
75
|
-
end
|
76
|
-
|
77
|
-
def height
|
78
|
-
geometry.split(REGEX_GEOMETRY)[1].to_i
|
79
|
-
end
|
80
|
-
|
81
|
-
def x
|
82
|
-
sign_number(x_sign, geometry.split(REGEX_GEOMETRY)[2].to_i)
|
83
|
-
end
|
84
|
-
|
85
|
-
def y
|
86
|
-
sign_number(y_sign, geometry.split(REGEX_GEOMETRY)[3].to_i)
|
87
|
-
end
|
88
|
-
|
89
|
-
def width=(value)
|
90
|
-
@width = value.to_i
|
91
|
-
self.geometry = "#{value.to_i}x#{@height || DEFAULT_HEIGHT}#{x_sign}#{abs_x}#{y_sign}#{abs_y}"
|
92
|
-
end
|
93
|
-
|
94
|
-
def height=(value)
|
95
|
-
@height = value.to_i
|
96
|
-
self.geometry = "#{@width || DEFAULT_WIDTH}x#{value.to_i}#{x_sign}#{abs_x}#{y_sign}#{abs_y}"
|
97
|
-
end
|
98
|
-
|
99
|
-
def x=(value)
|
100
|
-
self.geometry = "#{@width || DEFAULT_WIDTH}x#{@height || DEFAULT_HEIGHT}#{value.to_i > 0 ? '+' : '-'}#{value.to_i.abs}#{y_sign}#{abs_y}"
|
101
|
-
end
|
102
|
-
|
103
|
-
def y=(value)
|
104
|
-
self.geometry = "#{@width || DEFAULT_WIDTH}x#{@height || DEFAULT_HEIGHT}#{x_sign}#{abs_x}#{value.to_i > 0 ? '+' : '-'}#{value.to_i.abs}"
|
105
|
-
end
|
106
|
-
|
107
65
|
def handle_listener(listener_name, &listener)
|
108
66
|
case listener_name.to_s.upcase
|
109
|
-
when 'WM_DELETE_WINDOW', 'DELETE_WINDOW'
|
110
|
-
listener_name = 'WM_DELETE_WINDOW'
|
111
|
-
@tk.protocol(listener_name, &listener)
|
112
67
|
when 'WM_OPEN_WINDOW', 'OPEN_WINDOW'
|
113
68
|
@on_open_window_procs ||= []
|
114
69
|
@on_open_window_procs << listener
|
@@ -128,36 +83,6 @@ module Glimmer
|
|
128
83
|
end
|
129
84
|
::Tk.mainloop
|
130
85
|
end
|
131
|
-
|
132
|
-
private
|
133
|
-
|
134
|
-
def sign_number(sign, number)
|
135
|
-
"#{sign}1".to_i * number
|
136
|
-
end
|
137
|
-
|
138
|
-
def abs_x
|
139
|
-
geometry.split(REGEX_GEOMETRY)[2].to_i
|
140
|
-
end
|
141
|
-
|
142
|
-
def abs_y
|
143
|
-
geometry.split(REGEX_GEOMETRY)[3].to_i
|
144
|
-
end
|
145
|
-
|
146
|
-
def x_sign
|
147
|
-
geometry_signs[0]
|
148
|
-
end
|
149
|
-
|
150
|
-
def y_sign
|
151
|
-
geometry_signs[1]
|
152
|
-
end
|
153
|
-
|
154
|
-
def geometry_signs
|
155
|
-
geometry.chars.select {|char| char.match(/[+-]/)}
|
156
|
-
end
|
157
|
-
|
158
|
-
def initialize_defaults
|
159
|
-
self.background = '#ececec' if OS.mac?
|
160
|
-
end
|
161
86
|
end
|
162
87
|
end
|
163
88
|
end
|
@@ -28,8 +28,7 @@ module Glimmer
|
|
28
28
|
# Follows the Proxy Design Pattern
|
29
29
|
class TextProxy < WidgetProxy
|
30
30
|
def handle_listener(listener_name, &listener)
|
31
|
-
|
32
|
-
case listener_name
|
31
|
+
case listener_name.to_s.downcase
|
33
32
|
when '<<modified>>', '<modified>', 'modified'
|
34
33
|
modified_listener = Proc.new do |*args|
|
35
34
|
listener.call(*args)
|
@@ -38,8 +37,20 @@ module Glimmer
|
|
38
37
|
bind('<Modified>', modified_listener)
|
39
38
|
when '<<selection>>', '<selection>', 'selection'
|
40
39
|
bind('<Selection>', listener)
|
41
|
-
|
40
|
+
when 'destroy'
|
42
41
|
super
|
42
|
+
else
|
43
|
+
@tk.tag_add('__all__', '1.0', 'end') unless @tk.tag_names.include?('__all__')
|
44
|
+
# TODO make listener pass an event that has a modifiers attribute for easy representation of :shift, :meta, :control, etc... while a letter button is pressed
|
45
|
+
begin
|
46
|
+
@tk.tag_bind('__all__', listener_name, &listener)
|
47
|
+
rescue => e
|
48
|
+
Glimmer::Config.logger.debug {"Unable to bind to #{listener_name} .. attempting to surround with <>"}
|
49
|
+
Glimmer::Config.logger.debug {e.full_message}
|
50
|
+
listener_name = "<#{listener_name}" if !listener_name.start_with?('<')
|
51
|
+
listener_name = "#{listener_name}>" if !listener_name.end_with?('>')
|
52
|
+
@tk.tag_bind('__all__', listener_name, &listener)
|
53
|
+
end
|
43
54
|
end
|
44
55
|
end
|
45
56
|
|
@@ -0,0 +1,119 @@
|
|
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
|
+
# Proxy for TkToplevel
|
27
|
+
#
|
28
|
+
# Follows the Proxy Design Pattern
|
29
|
+
class ToplevelProxy < WidgetProxy
|
30
|
+
REGEX_GEOMETRY = /[x+-]/
|
31
|
+
DEFAULT_WIDTH = 190
|
32
|
+
DEFAULT_HEIGHT = 95
|
33
|
+
|
34
|
+
attr_reader :tk
|
35
|
+
|
36
|
+
def has_attribute?(attribute, *args)
|
37
|
+
%w[width height x y].include?(attribute.to_s) || super
|
38
|
+
end
|
39
|
+
|
40
|
+
def width
|
41
|
+
geometry.split(REGEX_GEOMETRY)[0].to_i
|
42
|
+
end
|
43
|
+
|
44
|
+
def height
|
45
|
+
geometry.split(REGEX_GEOMETRY)[1].to_i
|
46
|
+
end
|
47
|
+
|
48
|
+
def x
|
49
|
+
sign_number(x_sign, geometry.split(REGEX_GEOMETRY)[2].to_i)
|
50
|
+
end
|
51
|
+
|
52
|
+
def y
|
53
|
+
sign_number(y_sign, geometry.split(REGEX_GEOMETRY)[3].to_i)
|
54
|
+
end
|
55
|
+
|
56
|
+
def width=(value)
|
57
|
+
@width = value.to_i
|
58
|
+
self.geometry = "#{value.to_i}x#{@height || DEFAULT_HEIGHT}#{x_sign}#{abs_x}#{y_sign}#{abs_y}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def height=(value)
|
62
|
+
@height = value.to_i
|
63
|
+
self.geometry = "#{@width || DEFAULT_WIDTH}x#{value.to_i}#{x_sign}#{abs_x}#{y_sign}#{abs_y}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def x=(value)
|
67
|
+
self.geometry = "#{@width || DEFAULT_WIDTH}x#{@height || DEFAULT_HEIGHT}#{value.to_i > 0 ? '+' : '-'}#{value.to_i.abs}#{y_sign}#{abs_y}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def y=(value)
|
71
|
+
self.geometry = "#{@width || DEFAULT_WIDTH}x#{@height || DEFAULT_HEIGHT}#{x_sign}#{abs_x}#{value.to_i > 0 ? '+' : '-'}#{value.to_i.abs}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def handle_listener(listener_name, &listener)
|
75
|
+
case listener_name.to_s.upcase
|
76
|
+
when 'WM_DELETE_WINDOW', 'DELETE_WINDOW'
|
77
|
+
listener_name = 'WM_DELETE_WINDOW'
|
78
|
+
@tk.protocol(listener_name, &listener)
|
79
|
+
else
|
80
|
+
super
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def sign_number(sign, number)
|
87
|
+
"#{sign}1".to_i * number
|
88
|
+
end
|
89
|
+
|
90
|
+
def abs_x
|
91
|
+
geometry.split(REGEX_GEOMETRY)[2].to_i
|
92
|
+
end
|
93
|
+
|
94
|
+
def abs_y
|
95
|
+
geometry.split(REGEX_GEOMETRY)[3].to_i
|
96
|
+
end
|
97
|
+
|
98
|
+
def x_sign
|
99
|
+
geometry_signs[0]
|
100
|
+
end
|
101
|
+
|
102
|
+
def y_sign
|
103
|
+
geometry_signs[1]
|
104
|
+
end
|
105
|
+
|
106
|
+
def geometry_signs
|
107
|
+
geometry.chars.select {|char| char.match(/[+-]/)}
|
108
|
+
end
|
109
|
+
|
110
|
+
def initialize_defaults
|
111
|
+
self.background = '#ececec' if OS.mac?
|
112
|
+
on('DELETE_WINDOW') do
|
113
|
+
grab_release
|
114
|
+
destroy
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -19,6 +19,8 @@
|
|
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 'glimmer/data_binding/tk/one_time_observer'
|
23
|
+
|
22
24
|
module Glimmer
|
23
25
|
module Tk
|
24
26
|
# Proxy for Tk Widget objects
|
@@ -83,6 +85,27 @@ module Glimmer
|
|
83
85
|
post_add_content if @block.nil?
|
84
86
|
end
|
85
87
|
|
88
|
+
def root_parent_proxy
|
89
|
+
current = self
|
90
|
+
current = current.parent_proxy while current.parent_proxy
|
91
|
+
current
|
92
|
+
end
|
93
|
+
|
94
|
+
def toplevel_parent_proxy
|
95
|
+
ancestor_proxies.find {|widget_proxy| widget_proxy.is_a?(ToplevelProxy)}
|
96
|
+
end
|
97
|
+
|
98
|
+
# returns list of ancestors ordered from direct parent to root parent
|
99
|
+
def ancestor_proxies
|
100
|
+
ancestors = []
|
101
|
+
current = self
|
102
|
+
while current.parent_proxy
|
103
|
+
ancestors << current.parent_proxy
|
104
|
+
current = current.parent_proxy
|
105
|
+
end
|
106
|
+
ancestors
|
107
|
+
end
|
108
|
+
|
86
109
|
def children
|
87
110
|
@children ||= []
|
88
111
|
end
|
@@ -227,7 +250,7 @@ module Glimmer
|
|
227
250
|
|
228
251
|
def grid(options = {})
|
229
252
|
options = options.stringify_keys
|
230
|
-
index_in_parent = @parent_proxy
|
253
|
+
index_in_parent = @parent_proxy&.children&.index(self)
|
231
254
|
options['rowspan'] = options.delete('row_span') if options.keys.include?('row_span')
|
232
255
|
options['columnspan'] = options.delete('column_span') if options.keys.include?('column_span')
|
233
256
|
options['rowweight'] = options.delete('row_weight') if options.keys.include?('row_weight')
|
@@ -240,10 +263,12 @@ module Glimmer
|
|
240
263
|
options['columnminsize'] = options.delete('minwidth') if options.keys.include?('minwidth')
|
241
264
|
options['columnminsize'] = options.delete('min_width') if options.keys.include?('min_width')
|
242
265
|
options['columnminsize'] = options['rowminsize'] = options.delete('minsize') if options.keys.include?('minsize')
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
266
|
+
if index_in_parent
|
267
|
+
TkGrid.rowconfigure(@parent_proxy.tk, index_in_parent, 'weight'=> options.delete('rowweight')) if options.keys.include?('rowweight')
|
268
|
+
TkGrid.rowconfigure(@parent_proxy.tk, index_in_parent, 'minsize'=> options.delete('rowminsize')) if options.keys.include?('rowminsize')
|
269
|
+
TkGrid.columnconfigure(@parent_proxy.tk, index_in_parent, 'weight'=> options.delete('columnweight')) if options.keys.include?('columnweight')
|
270
|
+
TkGrid.columnconfigure(@parent_proxy.tk, index_in_parent, 'minsize'=> options.delete('columnminsize')) if options.keys.include?('columnminsize')
|
271
|
+
end
|
247
272
|
@tk.grid(options)
|
248
273
|
end
|
249
274
|
|
@@ -259,6 +284,11 @@ module Glimmer
|
|
259
284
|
apply_style({"font" => value})
|
260
285
|
end
|
261
286
|
|
287
|
+
def destroy
|
288
|
+
@tk.destroy
|
289
|
+
@on_destroy_procs&.each {|p| p.call(@tk)}
|
290
|
+
end
|
291
|
+
|
262
292
|
def apply_style(options)
|
263
293
|
@@style_number = 0 unless defined?(@@style_number)
|
264
294
|
style = "style#{@@style_number += 1}.#{@tk.class.name.split('::').last}"
|
@@ -421,17 +451,31 @@ module Glimmer
|
|
421
451
|
|
422
452
|
def handle_listener(listener_name, &listener)
|
423
453
|
listener_name = listener_name.to_s
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
Glimmer::
|
428
|
-
|
429
|
-
|
430
|
-
listener_name
|
431
|
-
|
454
|
+
if listener_name == 'destroy'
|
455
|
+
# 'destroy' is a more reliable alternative listener binding to '<Destroy>'
|
456
|
+
@on_destroy_procs ||= []
|
457
|
+
listener.singleton_class.include(Glimmer::DataBinding::Tk::OneTimeObserver) unless listener.is_a?(Glimmer::DataBinding::Tk::OneTimeObserver)
|
458
|
+
@on_destroy_procs << listener
|
459
|
+
@tk.bind('<Destroy>', listener)
|
460
|
+
parent_proxy.handle_listener(listener_name, &listener) if parent_proxy
|
461
|
+
# TODO return a listener registration object that has a deregister method
|
462
|
+
else
|
463
|
+
begin
|
464
|
+
@tk.bind(listener_name, &listener)
|
465
|
+
rescue => e
|
466
|
+
Glimmer::Config.logger.debug {"Unable to bind to #{listener_name} .. attempting to surround with <>"}
|
467
|
+
Glimmer::Config.logger.debug {e.full_message}
|
468
|
+
listener_name = "<#{listener_name}" if !listener_name.start_with?('<')
|
469
|
+
listener_name = "#{listener_name}>" if !listener_name.end_with?('>')
|
470
|
+
@tk.bind(listener_name, &listener)
|
471
|
+
end
|
432
472
|
end
|
433
473
|
end
|
434
474
|
|
475
|
+
def on(listener_name, &listener)
|
476
|
+
handle_listener(listener_name, &listener)
|
477
|
+
end
|
478
|
+
|
435
479
|
def content(&block)
|
436
480
|
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Tk::WidgetExpression.new, keyword, *args, &block)
|
437
481
|
end
|
data/samples/hello/hello_text.rb
CHANGED
@@ -64,7 +64,7 @@ class HelloText
|
|
64
64
|
MULTI_LINE_STRING
|
65
65
|
end
|
66
66
|
|
67
|
-
attr_accessor :document
|
67
|
+
attr_accessor :document, :find_text
|
68
68
|
|
69
69
|
attr_accessor :foreground
|
70
70
|
|
@@ -90,8 +90,16 @@ class HelloText
|
|
90
90
|
[FONT_SIZE_PROMPT] + (9..64).to_a.map(&:to_s)
|
91
91
|
end
|
92
92
|
|
93
|
+
def find
|
94
|
+
text_index = @text.search(/#{find_text}/i, @text.tag_ranges('sel')&.first&.last || @text.index('insert'))
|
95
|
+
unless text_index.to_s.empty?
|
96
|
+
@text.tag_remove('sel', '1.0', 'end')
|
97
|
+
@text.tag_add('sel', text_index, "#{text_index} + #{find_text.size} chars")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
93
101
|
def launch
|
94
|
-
root {
|
102
|
+
root { |r|
|
95
103
|
title 'Hello, Text!'
|
96
104
|
width 1280
|
97
105
|
height 800
|
@@ -272,6 +280,49 @@ class HelloText
|
|
272
280
|
wrap 'word'
|
273
281
|
undo true
|
274
282
|
value <=> [self, :document]
|
283
|
+
|
284
|
+
on('KeyPress') do |event|
|
285
|
+
if event.state == 8 && event.char == 'f'
|
286
|
+
toplevel(r) { |tl|
|
287
|
+
title 'Find'
|
288
|
+
|
289
|
+
label {
|
290
|
+
text 'Text:'
|
291
|
+
}
|
292
|
+
entry { |e|
|
293
|
+
focus true
|
294
|
+
text <=> [
|
295
|
+
self,
|
296
|
+
:find_text,
|
297
|
+
after_write: lambda do
|
298
|
+
text_index = @text.search(/#{find_text}/i, 'insert')
|
299
|
+
unless text_index.to_s.empty?
|
300
|
+
@text.tag_remove('sel', '1.0', 'end')
|
301
|
+
@text.tag_add('sel', text_index, "#{text_index} + #{find_text.size} chars")
|
302
|
+
end
|
303
|
+
end
|
304
|
+
]
|
305
|
+
|
306
|
+
on('KeyPress') do |event|
|
307
|
+
if event.keysym == 'Return'
|
308
|
+
find
|
309
|
+
elsif event.keysym == 'Escape'
|
310
|
+
tl.grab_release
|
311
|
+
tl.destroy
|
312
|
+
end
|
313
|
+
end
|
314
|
+
}
|
315
|
+
button {
|
316
|
+
text 'Find'
|
317
|
+
default 'active'
|
318
|
+
|
319
|
+
on('command') do
|
320
|
+
find
|
321
|
+
end
|
322
|
+
}
|
323
|
+
}
|
324
|
+
end
|
325
|
+
end
|
275
326
|
}
|
276
327
|
}.open
|
277
328
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-tk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.31
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|
@@ -211,6 +211,7 @@ files:
|
|
211
211
|
- icons/glimmer.png
|
212
212
|
- lib/glimmer-dsl-tk.rb
|
213
213
|
- lib/glimmer/data_binding/tk/list_selection_binding.rb
|
214
|
+
- lib/glimmer/data_binding/tk/one_time_observer.rb
|
214
215
|
- lib/glimmer/data_binding/tk/widget_binding.rb
|
215
216
|
- lib/glimmer/dsl/tk/attribute_expression.rb
|
216
217
|
- lib/glimmer/dsl/tk/bind_expression.rb
|
@@ -240,6 +241,7 @@ files:
|
|
240
241
|
- lib/glimmer/tk/spinbox_proxy.rb
|
241
242
|
- lib/glimmer/tk/text_proxy.rb
|
242
243
|
- lib/glimmer/tk/text_variable_owner.rb
|
244
|
+
- lib/glimmer/tk/toplevel_proxy.rb
|
243
245
|
- lib/glimmer/tk/treeview_proxy.rb
|
244
246
|
- lib/glimmer/tk/variable_owner.rb
|
245
247
|
- lib/glimmer/tk/widget_proxy.rb
|