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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.24
1
+ 0.0.28
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
@@ -38,7 +38,7 @@ module Glimmer
38
38
 
39
39
  def interpret(parent, keyword, *args, &block)
40
40
  args = [parent] + args unless parent.nil?
41
- Glimmer::Tk::RootProxy.new(*args)
41
+ Glimmer::Tk::RootProxy.new(*args, &block)
42
42
  end
43
43
 
44
44
  def add_content(parent, keyword, *args, &block)
@@ -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,7 +31,7 @@ module Glimmer
31
31
  include Commandable
32
32
 
33
33
  def sibling_radio_buttons
34
- @parent_proxy.children.select {|child| child.is_a?(RadiobuttonProxy)}
34
+ @parent_proxy.children.select {|child| child.is_a?(RadiobuttonProxy) && child != self}
35
35
  end
36
36
 
37
37
  private
@@ -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
- get_attribute(:width)
74
+ geometry.split(REGEX_GEOMETRY)[0].to_i
99
75
  end
100
76
 
101
77
  def height
102
- get_attribute(:height)
78
+ geometry.split(REGEX_GEOMETRY)[1].to_i
103
79
  end
104
80
 
105
81
  def x
106
- get_attribute(:x)
82
+ sign_number(x_sign, geometry.split(REGEX_GEOMETRY)[2].to_i)
107
83
  end
108
84
 
109
85
  def y
110
- get_attribute(:y)
86
+ sign_number(y_sign, geometry.split(REGEX_GEOMETRY)[3].to_i)
111
87
  end
112
88
 
113
89
  def width=(value)
114
- set_attribute(: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}"
115
92
  end
116
93
 
117
94
  def height=(value)
118
- set_attribute(: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}"
119
97
  end
120
98
 
121
99
  def x=(value)
122
- set_attribute(:x, value)
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
- set_attribute(:y, value)
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