glimmer-dsl-tk 0.0.24 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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