glimmer-dsl-tk 0.0.24 → 0.0.28
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -0
- data/README.md +548 -100
- data/VERSION +1 -1
- data/glimmer-dsl-tk.gemspec +0 -0
- data/lib/glimmer/dsl/tk/format_expression.rb +39 -0
- data/lib/glimmer/dsl/tk/root_expression.rb +1 -1
- data/lib/glimmer/tk/drag_and_drop_extension.rb +112 -0
- data/lib/glimmer/tk/frame_proxy.rb +8 -0
- data/lib/glimmer/tk/label_proxy.rb +0 -9
- data/lib/glimmer/tk/radiobutton_proxy.rb +1 -1
- data/lib/glimmer/tk/root_proxy.rb +17 -35
- data/lib/glimmer/tk/spinbox_proxy.rb +52 -0
- data/lib/glimmer/tk/text_proxy.rb +350 -0
- data/lib/glimmer/tk/widget_proxy.rb +109 -35
- data/samples/elaborate/meta_sample.rb +138 -0
- data/samples/hello/hello_checkbutton.rb +0 -1
- data/samples/hello/hello_combobox.rb +2 -1
- data/samples/hello/hello_drag_and_drop.rb +159 -0
- data/samples/hello/hello_entry.rb +2 -2
- data/samples/hello/hello_radiobutton.rb +21 -1
- data/samples/hello/hello_spinbox.rb +75 -0
- data/samples/hello/hello_text.rb +222 -0
- data/samples/hello/images/copy.png +0 -0
- data/samples/hello/images/cut.png +0 -0
- data/samples/hello/images/paste.png +0 -0
- data/samples/hello/images/redo.png +0 -0
- data/samples/hello/images/undo.png +0 -0
- metadata +19 -6
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.28
|
data/glimmer-dsl-tk.gemspec
CHANGED
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Copyright (c) 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/static_expression'
|
23
|
+
require 'glimmer/tk/spinbox_proxy'
|
24
|
+
|
25
|
+
module Glimmer
|
26
|
+
module DSL
|
27
|
+
module Tk
|
28
|
+
class FormatExpression < StaticExpression
|
29
|
+
def can_interpret?(parent, keyword, *args, &block)
|
30
|
+
super && parent.is_a?(Glimmer::Tk::SpinboxProxy) && args.size == 1 && block.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def interpret(parent, keyword, *args, &block)
|
34
|
+
parent.tk.format(*args)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Tk
|
5
|
+
class WidgetProxy
|
6
|
+
attr_accessor :on_drag_motion_block
|
7
|
+
|
8
|
+
def drag_source=(value)
|
9
|
+
@drag_source = value
|
10
|
+
if @drag_source
|
11
|
+
make_draggable
|
12
|
+
else
|
13
|
+
make_non_draggable
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_drag_start_block=(block)
|
18
|
+
@on_drag_start_block = block
|
19
|
+
make_draggable
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_drop_block=(value)
|
23
|
+
@on_drop_block = value
|
24
|
+
self.tk.bind("<DropEvent>", proc { |tk_event|
|
25
|
+
drop_event = DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
26
|
+
@on_drop_block.call(drop_event) if self.tk == drop_event.target
|
27
|
+
})
|
28
|
+
self.tk.bind("<DropCheckEvent>", proc { |tk_event|
|
29
|
+
drop_check_event = DragAndDropEvent.json_create(JSON.parse("{" + tk_event.detail + "}"))
|
30
|
+
drop_check_event.source.event_generate("<DropAcceptedEvent>")
|
31
|
+
})
|
32
|
+
end
|
33
|
+
|
34
|
+
def textvariable_defined?
|
35
|
+
tk_widget_has_attribute_setter?(:textvariable) && !tk.textvariable.nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
def make_draggable
|
39
|
+
drag_event = nil
|
40
|
+
bind("<DropAcceptedEvent>", proc { |event| drag_event.drop_accepted = true })
|
41
|
+
bind("B1-Motion", proc { |tk_event|
|
42
|
+
if drag_event.nil?
|
43
|
+
tooltip = TkToplevel.new(root).overrideredirect(1) #create tooltip window to display dragged data
|
44
|
+
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)
|
46
|
+
if @drag_source
|
47
|
+
tk_event.widget.configure(:cursor => "hand2")
|
48
|
+
# Default data to drag is text
|
49
|
+
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
|
51
|
+
elsif !@on_drag_start_block.nil?
|
52
|
+
@on_drag_start_block.call(drag_event)
|
53
|
+
TkLabel.new(tooltip) { text drag_event.data }.pack if tooltip.winfo_children().length == 0
|
54
|
+
end
|
55
|
+
else
|
56
|
+
drag_event.x_root, drag_event.y_root = tk_event.x_root, tk_event.y_root
|
57
|
+
drag_event.drop_accepted = false
|
58
|
+
move_over_widget = tk_event.widget.winfo_containing(tk_event.x_root, tk_event.y_root)
|
59
|
+
drag_event.target = move_over_widget
|
60
|
+
move_over_widget.event_generate("<DropCheckEvent>", :data => drag_event.to_json)
|
61
|
+
if @on_drag_motion_block.nil?
|
62
|
+
# Default motion behavior:
|
63
|
+
# 1.Change cursor to show whether text can be dropped.
|
64
|
+
# 2.Move tooltip with dragged data.
|
65
|
+
if drag_event.drop_accepted
|
66
|
+
tk_event.widget.configure(:cursor => "hand1")
|
67
|
+
else
|
68
|
+
tk_event.widget.configure(:cursor => "hand2")
|
69
|
+
end
|
70
|
+
drag_event.tooltip.geometry("+#{tk_event.x_root + 10}+#{tk_event.y_root - 2}")
|
71
|
+
else
|
72
|
+
@on_drag_motion_block.call(drag_event)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
})
|
76
|
+
bind("ButtonRelease-1", proc { |tk_event|
|
77
|
+
if drag_event
|
78
|
+
drag_event.target = tk_event.widget.winfo_containing(tk_event.x_root, tk_event.y_root)
|
79
|
+
drag_event.source.configure(:cursor => "")
|
80
|
+
drag_event.target.event_generate("<DropEvent>", :data => drag_event.to_json)
|
81
|
+
drag_event.tooltip.destroy
|
82
|
+
drag_event = nil
|
83
|
+
end
|
84
|
+
})
|
85
|
+
end
|
86
|
+
|
87
|
+
def make_non_draggable
|
88
|
+
@tk.bind_remove("B1-Motion")
|
89
|
+
@tk.bind_remove("ButtonRelease-1")
|
90
|
+
@tk.bind_remove("<DropAcceptedEvent>")
|
91
|
+
end
|
92
|
+
|
93
|
+
DragAndDropEvent = Struct.new(:source, :target, :tooltip, :x_root, :y_root, :data, :drop_accepted) do
|
94
|
+
def as_json(*)
|
95
|
+
klass = self.class.name
|
96
|
+
{
|
97
|
+
JSON.create_id => klass,
|
98
|
+
"v" => [values[0].object_id, values[1].object_id, values[2].object_id].concat(values.drop 3),
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_json(*args)
|
103
|
+
as_json.to_json(*args)
|
104
|
+
end
|
105
|
+
|
106
|
+
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))
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
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/tk/widget_proxy'
|
23
|
+
require 'glimmer/tk/notebook_proxy'
|
23
24
|
|
24
25
|
module Glimmer
|
25
26
|
module Tk
|
@@ -38,6 +39,13 @@ module Glimmer
|
|
38
39
|
end
|
39
40
|
super
|
40
41
|
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def initialize_defaults
|
46
|
+
super unless @parent_proxy.is_a?(NotebookProxy)
|
47
|
+
self.padding = 15
|
48
|
+
end
|
41
49
|
end
|
42
50
|
end
|
43
51
|
end
|
@@ -29,15 +29,6 @@ module Glimmer
|
|
29
29
|
# Follows the Proxy Design Pattern
|
30
30
|
class LabelProxy < WidgetProxy
|
31
31
|
include TextVariableOwner
|
32
|
-
|
33
|
-
def set_attribute(attribute, *args)
|
34
|
-
if attribute.to_s == 'font'
|
35
|
-
args[0] = "tk_#{args[0]}_font".camelcase(:upper) if (args[0].is_a?(Symbol) || args[0].is_a?(String)) && args[0].to_s == args[0].to_s.downcase
|
36
|
-
super
|
37
|
-
else
|
38
|
-
super
|
39
|
-
end
|
40
|
-
end
|
41
32
|
end
|
42
33
|
end
|
43
34
|
end
|
@@ -31,9 +31,11 @@ module Glimmer
|
|
31
31
|
DEFAULT_WIDTH = 190
|
32
32
|
DEFAULT_HEIGHT = 95
|
33
33
|
|
34
|
-
def initialize(*args)
|
34
|
+
def initialize(*args, &block)
|
35
35
|
@tk = ::TkRoot.new
|
36
36
|
@tk.minsize = DEFAULT_WIDTH, DEFAULT_HEIGHT
|
37
|
+
initialize_defaults
|
38
|
+
post_add_content if block.nil?
|
37
39
|
end
|
38
40
|
|
39
41
|
def post_add_content
|
@@ -57,16 +59,6 @@ module Glimmer
|
|
57
59
|
when 'iconphoto'
|
58
60
|
args[0..-1] = [image_argument(args)]
|
59
61
|
super
|
60
|
-
when 'width'
|
61
|
-
@width = args.first.to_i
|
62
|
-
self.geometry = "#{args.first.to_i}x#{@height || DEFAULT_HEIGHT}#{x_sign}#{abs_x}#{y_sign}#{abs_y}"
|
63
|
-
when 'height'
|
64
|
-
@height = args.first.to_i
|
65
|
-
self.geometry = "#{@width || DEFAULT_WIDTH}x#{args.first.to_i}#{x_sign}#{abs_x}#{y_sign}#{abs_y}"
|
66
|
-
when 'x'
|
67
|
-
self.geometry = "#{@width || DEFAULT_WIDTH}x#{@height || DEFAULT_HEIGHT}#{args.first.to_i > 0 ? '+' : '-'}#{args.first.to_i.abs}#{y_sign}#{abs_y}"
|
68
|
-
when 'y'
|
69
|
-
self.geometry = "#{@width || DEFAULT_WIDTH}x#{@height || DEFAULT_HEIGHT}#{x_sign}#{abs_x}#{args.first.to_i > 0 ? '+' : '-'}#{args.first.to_i.abs}"
|
70
62
|
when 'resizable'
|
71
63
|
if args.size == 1 && !args.first.is_a?(Array)
|
72
64
|
self.resizable = [args.first]*2
|
@@ -78,52 +70,38 @@ module Glimmer
|
|
78
70
|
end
|
79
71
|
end
|
80
72
|
|
81
|
-
def get_attribute(attribute)
|
82
|
-
attribute = attribute.to_s
|
83
|
-
case attribute
|
84
|
-
when 'width'
|
85
|
-
geometry.split(REGEX_GEOMETRY)[0].to_i
|
86
|
-
when 'height'
|
87
|
-
geometry.split(REGEX_GEOMETRY)[1].to_i
|
88
|
-
when 'x'
|
89
|
-
sign_number(x_sign, geometry.split(REGEX_GEOMETRY)[2].to_i)
|
90
|
-
when 'y'
|
91
|
-
sign_number(y_sign, geometry.split(REGEX_GEOMETRY)[3].to_i)
|
92
|
-
else
|
93
|
-
super
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
73
|
def width
|
98
|
-
|
74
|
+
geometry.split(REGEX_GEOMETRY)[0].to_i
|
99
75
|
end
|
100
76
|
|
101
77
|
def height
|
102
|
-
|
78
|
+
geometry.split(REGEX_GEOMETRY)[1].to_i
|
103
79
|
end
|
104
80
|
|
105
81
|
def x
|
106
|
-
|
82
|
+
sign_number(x_sign, geometry.split(REGEX_GEOMETRY)[2].to_i)
|
107
83
|
end
|
108
84
|
|
109
85
|
def y
|
110
|
-
|
86
|
+
sign_number(y_sign, geometry.split(REGEX_GEOMETRY)[3].to_i)
|
111
87
|
end
|
112
88
|
|
113
89
|
def width=(value)
|
114
|
-
|
90
|
+
@width = value.to_i
|
91
|
+
self.geometry = "#{value.to_i}x#{@height || DEFAULT_HEIGHT}#{x_sign}#{abs_x}#{y_sign}#{abs_y}"
|
115
92
|
end
|
116
93
|
|
117
94
|
def height=(value)
|
118
|
-
|
95
|
+
@height = value.to_i
|
96
|
+
self.geometry = "#{@width || DEFAULT_WIDTH}x#{value.to_i}#{x_sign}#{abs_x}#{y_sign}#{abs_y}"
|
119
97
|
end
|
120
98
|
|
121
99
|
def x=(value)
|
122
|
-
|
100
|
+
self.geometry = "#{@width || DEFAULT_WIDTH}x#{@height || DEFAULT_HEIGHT}#{value.to_i > 0 ? '+' : '-'}#{value.to_i.abs}#{y_sign}#{abs_y}"
|
123
101
|
end
|
124
102
|
|
125
103
|
def y=(value)
|
126
|
-
|
104
|
+
self.geometry = "#{@width || DEFAULT_WIDTH}x#{@height || DEFAULT_HEIGHT}#{x_sign}#{abs_x}#{value.to_i > 0 ? '+' : '-'}#{value.to_i.abs}"
|
127
105
|
end
|
128
106
|
|
129
107
|
def handle_listener(listener_name, &listener)
|
@@ -176,6 +154,10 @@ module Glimmer
|
|
176
154
|
def geometry_signs
|
177
155
|
geometry.chars.select {|char| char.match(/[+-]/)}
|
178
156
|
end
|
157
|
+
|
158
|
+
def initialize_defaults
|
159
|
+
self.background = '#ececec' if OS.mac?
|
160
|
+
end
|
179
161
|
end
|
180
162
|
end
|
181
163
|
end
|
@@ -0,0 +1,52 @@
|
|
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
|
+
require 'glimmer/tk/text_variable_owner'
|
24
|
+
|
25
|
+
module Glimmer
|
26
|
+
module Tk
|
27
|
+
# Proxy for Tk::Tile::TSpinbox
|
28
|
+
#
|
29
|
+
# Follows the Proxy Design Pattern
|
30
|
+
class SpinboxProxy < WidgetProxy
|
31
|
+
include TextVariableOwner
|
32
|
+
|
33
|
+
def command_block=(proc)
|
34
|
+
tk.command(proc)
|
35
|
+
end
|
36
|
+
|
37
|
+
def handle_listener(listener_name, &listener)
|
38
|
+
case listener_name.to_s.downcase
|
39
|
+
when 'command', 'change'
|
40
|
+
command(&listener)
|
41
|
+
when 'increment', '<increment>', '<<increment>>'
|
42
|
+
bind('<Increment>', listener)
|
43
|
+
when 'decrement', '<decrement>', '<<decrement>>'
|
44
|
+
bind('<Decrement>', listener)
|
45
|
+
else
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|