wxruby3-shapes 0.9.0.pre.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +12 -0
  3. data/CREDITS.md +18 -0
  4. data/INSTALL.md +39 -0
  5. data/LICENSE +21 -0
  6. data/README.md +118 -0
  7. data/assets/screenshot.png +0 -0
  8. data/bin/wx-shapes +9 -0
  9. data/lib/wx/shapes/arrow_base.rb +86 -0
  10. data/lib/wx/shapes/arrows/circle_arrow.rb +39 -0
  11. data/lib/wx/shapes/arrows/diamond_arrow.rb +33 -0
  12. data/lib/wx/shapes/arrows/open_arrow.rb +56 -0
  13. data/lib/wx/shapes/arrows/solid_arrow.rb +69 -0
  14. data/lib/wx/shapes/art/shape_canvas/page.xpm +73 -0
  15. data/lib/wx/shapes/auto_layout.rb +358 -0
  16. data/lib/wx/shapes/base.rb +33 -0
  17. data/lib/wx/shapes/canvas_history.rb +84 -0
  18. data/lib/wx/shapes/connection_point.rb +238 -0
  19. data/lib/wx/shapes/core.rb +19 -0
  20. data/lib/wx/shapes/diagram.rb +659 -0
  21. data/lib/wx/shapes/events.rb +389 -0
  22. data/lib/wx/shapes/printout.rb +136 -0
  23. data/lib/wx/shapes/serializable.rb +440 -0
  24. data/lib/wx/shapes/serialize/core.rb +40 -0
  25. data/lib/wx/shapes/serialize/id.rb +82 -0
  26. data/lib/wx/shapes/serialize/wx.rb +104 -0
  27. data/lib/wx/shapes/serializer/json.rb +258 -0
  28. data/lib/wx/shapes/serializer/yaml.rb +125 -0
  29. data/lib/wx/shapes/shape.rb +2129 -0
  30. data/lib/wx/shapes/shape_canvas.rb +3285 -0
  31. data/lib/wx/shapes/shape_data_object.rb +43 -0
  32. data/lib/wx/shapes/shape_handle.rb +287 -0
  33. data/lib/wx/shapes/shape_list.rb +161 -0
  34. data/lib/wx/shapes/shapes/bitmap_shape.rb +257 -0
  35. data/lib/wx/shapes/shapes/circle_shape.rb +136 -0
  36. data/lib/wx/shapes/shapes/control_shape.rb +483 -0
  37. data/lib/wx/shapes/shapes/curve_shape.rb +231 -0
  38. data/lib/wx/shapes/shapes/diamond_shape.rb +62 -0
  39. data/lib/wx/shapes/shapes/edit_text_shape.rb +317 -0
  40. data/lib/wx/shapes/shapes/ellipse_shape.rb +106 -0
  41. data/lib/wx/shapes/shapes/flex_grid_shape.rb +78 -0
  42. data/lib/wx/shapes/shapes/grid_shape.rb +404 -0
  43. data/lib/wx/shapes/shapes/line_shape.rb +907 -0
  44. data/lib/wx/shapes/shapes/multi_sel_rect.rb +214 -0
  45. data/lib/wx/shapes/shapes/ortho_shape.rb +357 -0
  46. data/lib/wx/shapes/shapes/polygon_shape.rb +294 -0
  47. data/lib/wx/shapes/shapes/rect_shape.rb +378 -0
  48. data/lib/wx/shapes/shapes/round_ortho_shape.rb +131 -0
  49. data/lib/wx/shapes/shapes/round_rect_shape.rb +142 -0
  50. data/lib/wx/shapes/shapes/square_shape.rb +119 -0
  51. data/lib/wx/shapes/shapes/text_shape.rb +324 -0
  52. data/lib/wx/shapes/thumbnail.rb +234 -0
  53. data/lib/wx/shapes/version.rb +12 -0
  54. data/lib/wx/shapes/wx.rb +29 -0
  55. data/lib/wx/shapes.rb +18 -0
  56. data/lib/wx/wx-shapes/base.rb +87 -0
  57. data/lib/wx/wx-shapes/cmd/sampler.rb +58 -0
  58. data/lib/wx/wx-shapes/cmd/test.rb +27 -0
  59. data/rakelib/yard/templates/default/fulldoc/html/css/wxruby3.css +7 -0
  60. data/rakelib/yard/templates/default/layout/html/setup.rb +5 -0
  61. data/rakelib/yard/yard/relative_markdown_links/version.rb +8 -0
  62. data/rakelib/yard/yard/relative_markdown_links.rb +39 -0
  63. data/rakelib/yard/yard-custom-templates.rb +2 -0
  64. data/rakelib/yard/yard-relative_markdown_links.rb +4 -0
  65. data/samples/demo/art/AlignBottom.xpm +35 -0
  66. data/samples/demo/art/AlignCenter.xpm +35 -0
  67. data/samples/demo/art/AlignLeft.xpm +35 -0
  68. data/samples/demo/art/AlignMiddle.xpm +35 -0
  69. data/samples/demo/art/AlignRight.xpm +35 -0
  70. data/samples/demo/art/AlignTop.xpm +35 -0
  71. data/samples/demo/art/Bitmap.xpm +25 -0
  72. data/samples/demo/art/Circle.xpm +22 -0
  73. data/samples/demo/art/Curve.xpm +21 -0
  74. data/samples/demo/art/Diamond.xpm +22 -0
  75. data/samples/demo/art/EditText.xpm +21 -0
  76. data/samples/demo/art/Ellipse.xpm +22 -0
  77. data/samples/demo/art/FixedRect.xpm +22 -0
  78. data/samples/demo/art/FlexGrid.xpm +22 -0
  79. data/samples/demo/art/GC.xpm +23 -0
  80. data/samples/demo/art/Grid.xpm +22 -0
  81. data/samples/demo/art/Line.xpm +21 -0
  82. data/samples/demo/art/NoSource.xpm +69 -0
  83. data/samples/demo/art/OrthoLine.xpm +21 -0
  84. data/samples/demo/art/Rect.xpm +22 -0
  85. data/samples/demo/art/RoundOrthoLine.xpm +21 -0
  86. data/samples/demo/art/RoundRect.xpm +22 -0
  87. data/samples/demo/art/Shadow.xpm +23 -0
  88. data/samples/demo/art/StandAloneLine.xpm +22 -0
  89. data/samples/demo/art/Text.xpm +21 -0
  90. data/samples/demo/art/Tool.xpm +23 -0
  91. data/samples/demo/art/sample.xpm +251 -0
  92. data/samples/demo/demo.rb +658 -0
  93. data/samples/demo/frame_canvas.rb +422 -0
  94. data/samples/demo/images/motyl.bmp +0 -0
  95. data/samples/demo/images/motyl2.bmp +0 -0
  96. data/samples/sample1/art/sample.xpm +251 -0
  97. data/samples/sample1/sample.rb +263 -0
  98. data/samples/sample2/art/sample.xpm +251 -0
  99. data/samples/sample2/sample.rb +133 -0
  100. data/samples/sample2/sample_canvas.rb +35 -0
  101. data/samples/sample2/sample_shape.rb +108 -0
  102. data/samples/sample3/art/sample.xpm +251 -0
  103. data/samples/sample3/sample.rb +281 -0
  104. data/samples/sample4/art/sample.xpm +251 -0
  105. data/samples/sample4/sample.rb +180 -0
  106. data/tests/art/motyl.bmp +0 -0
  107. data/tests/lib/wxapp_runner.rb +64 -0
  108. data/tests/serializer_tests.rb +521 -0
  109. data/tests/test_grid_shapes.rb +42 -0
  110. data/tests/test_serialize.rb +7 -0
  111. data/tests/test_serialize_yaml.rb +17 -0
  112. metadata +242 -0
@@ -0,0 +1,294 @@
1
+ # Wx::SF::PolygonShape - polygon shape class
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ require 'wx/shapes/shapes/rect_shape'
5
+
6
+ module Wx::SF
7
+
8
+ # Class extends the Wx::SF::RectShape and encapsulates general polygon shape
9
+ # defined by a set of its vertices. The class can be used as it is or as a base class
10
+ # for shapes with more complex form and functionality.
11
+ # @see Wx::SF::DiamondShape
12
+ class PolygonShape < RectShape
13
+
14
+ # default values
15
+ module DEFAULT
16
+ # Default value of Wx::SF::PolygonShape @connect_to_vertex data member.
17
+ VERTEXCONNECTIONS = true
18
+ end
19
+
20
+ property :connect_to_vertex, :vertices
21
+
22
+ # @overload initialize()
23
+ # Default constructor.
24
+ # @overload initialize(pos, size, diagram)
25
+ # User constructor.
26
+ # @param [Array<Wx::RealPoint>] pts Array of the polygon vertices
27
+ # @param [Wx::RealPoint] pos Initial position
28
+ # @param [Wx::SF::Diagram] diagram parent diagram
29
+ def initialize(*args)
30
+ @connect_to_vertex = DEFAULT::VERTEXCONNECTIONS
31
+ @vertices = []
32
+ if args.empty?
33
+ super
34
+ else
35
+ pts, pos, diagram = args
36
+ super(pos,Wx::RealPoint.new(1,1), diagram)
37
+ set_vertices(pts)
38
+ end
39
+ end
40
+
41
+ # Set connecting mode.
42
+ # @param [Boolean] enable Set this parameter to true if you want to connect
43
+ # line shapes to the polygon's vertices, otherwise the lines will be connected
44
+ # to the nearest point of the shape's border.
45
+ def set_connect_to_vertex(enable)
46
+ @connect_to_vertex = enable
47
+ end
48
+ alias :connect_to_vertex= :set_connect_to_vertex
49
+
50
+ # Get status of connecting mode.
51
+ # @return [Boolean] true if the line shapes will be connected to the polygon's vertices
52
+ def is_connected_to_vertex
53
+ @connect_to_vertex
54
+ end
55
+ alias :connected_to_vertex? :is_connected_to_vertex
56
+ alias :get_connect_to_vertex :is_connected_to_vertex
57
+
58
+ # Set the poly vertices which define its form.
59
+ # @param [Array<Wx::RealPoint>] pts Array of the vertices
60
+ def set_vertices(pts)
61
+ ::Kernel.raise ArgumentError, 'Expected an array of Wx::RealPoint' unless pts.all? { |pt| pt.is_a?(Wx::RealPoint) }
62
+ @vertices = pts.collect { |pt| pt.dup }
63
+ normalize_vertices
64
+ fit_bounding_box_to_vertices
65
+ end
66
+
67
+ # Get the poly vertices. Serialization only.
68
+ # @return [Array<Wx::RealPoint>]
69
+ def get_vertices
70
+ @vertices
71
+ end
72
+ private :get_vertices
73
+
74
+ # Resize the rectangle to bound all child shapes. The function can be overridden if necessary.
75
+ def fit_to_children
76
+ super
77
+ fit_vertices_to_bounding_box
78
+ end
79
+
80
+ # Get intersection point of the shape border and a line leading from
81
+ # 'start' point to 'end' point. The function can be overridden if necessary.
82
+ # @param [Wx::RealPoint] start Starting point of the virtual intersection line
83
+ # @param [Wx::RealPoint] end_pt Ending point of the virtual intersection line
84
+ # @return [Wx::RealPoint] Intersection point
85
+ def get_border_point(start, end_pt)
86
+ # HINT: override it for custom actions ...
87
+ start = start.to_real_point; end_pt.to_real_point
88
+ return get_center if @vertices.empty?
89
+
90
+ pts = get_translated_vertices
91
+ intersection = start
92
+
93
+ if @connect_to_vertex
94
+ intersection = pts.shift
95
+ min_dist = intersection.distance_to(end_pt)
96
+ pts.each do |pt|
97
+ tmp_min_dist = pt.distance_to(end_pt)
98
+ if tmp_min_dist < min_dist
99
+ min_dist = tmp_min_dist
100
+ intersection = pt
101
+ end
102
+ end
103
+
104
+ intersection
105
+ else
106
+ success = false
107
+ pts.each_with_index do |pt, i|
108
+ if tmp_intersection = Wx::SF::Shape.lines_intersection(pt, pts[(i+1) % pts.size], start, end_pt)
109
+ if !success
110
+ min_dist = intersection.distance_to(end_pt)
111
+ intersection = tmp_intersection
112
+ else
113
+ tmp_min_dist = intersection.distance_to(end_pt)
114
+ if tmp_min_dist < min_dist
115
+ min_dist = tmp_min_dist
116
+ intersection = tmp_intersection
117
+ end
118
+ end
119
+ success = true
120
+ end
121
+ end
122
+
123
+ success ? intersection : get_center
124
+ end
125
+ end
126
+
127
+ # Event handler called during dragging of the shape handle.
128
+ # The function can be overridden if necessary.
129
+ #
130
+ # The function is called by the framework (by the shape canvas).
131
+ # @param [Shape::Handle] handle Reference to dragged handle
132
+ def on_handle(handle)
133
+ super
134
+ fit_vertices_to_bounding_box
135
+ end
136
+
137
+ protected
138
+
139
+ # Scale the rectangle size for this shape.
140
+ # @param [Float] x Horizontal scale factor
141
+ # @param [Float] y Vertical scale factor
142
+ def scale_rectangle(x, y)
143
+ rect_size.x *= x
144
+ rect_size.y *= y
145
+
146
+ fit_vertices_to_bounding_box
147
+ end
148
+
149
+ # Move all vertices so the polygon's relative bounding box position
150
+ # will be located in the origin.
151
+ def normalize_vertices
152
+ # move all vertices so the polygon's relative bounding box will be located in the origin
153
+
154
+ minx, miny, _, _ = get_extents
155
+
156
+ dx = minx*(-1)
157
+ dy = miny*(-1)
158
+
159
+ @vertices.each do |pt|
160
+ pt.x += dx
161
+ pt.y += dy
162
+ end
163
+ end
164
+
165
+ # Scale polygon's vertices to fit into the rectangle bounding the polygon.
166
+ def fit_vertices_to_bounding_box
167
+ minx, miny, maxx, maxy = get_extents
168
+
169
+ sx = rect_size.x/(maxx - minx)
170
+ sy = rect_size.y/(maxy - miny)
171
+
172
+ @vertices.each do |pt|
173
+ pt.x *= sx
174
+ pt.y *= sy
175
+ end
176
+ end
177
+
178
+ # Scale the bounding rectangle to fit all polygons vertices.
179
+ def fit_bounding_box_to_vertices
180
+ minx, miny, maxx, maxy = get_extents
181
+
182
+ rect_size.x = maxx - minx
183
+ rect_size.y = maxy - miny
184
+ end
185
+
186
+ # Get polygon extents.
187
+ # @return [Array(Float,Float,Float,Float)] Positions of the left, top, right and bottom side of polygon's bounding box
188
+ def get_extents
189
+ return [0.0,0.0,0.0,0.0] if @vertices.empty?
190
+
191
+ @vertices.inject(nil) do |exts, pt|
192
+ if exts
193
+ exts[0] = pt.x if pt.x < exts[0]
194
+ exts[1] = pt.y if pt.y < exts[1]
195
+ exts[2] = pt.x if pt.x > exts[2]
196
+ exts[3] = pt.y if pt.y > exts[3]
197
+ else
198
+ exts = [pt.x, pt.y, pt.x, pt.y]
199
+ end
200
+ exts
201
+ end
202
+ end
203
+
204
+ # Get absolute positions of the polygon's vertices.
205
+ # @return [Array<Wx::RealPoint>] pts Array of translated polygon's vertices
206
+ def get_translated_vertices
207
+ abs_pos = get_absolute_position
208
+ @vertices.collect { |pt| abs_pos + pt }
209
+ end
210
+
211
+ # Get absolute positions of the polygon's vertices.
212
+ # @return [Array<Wx::Point>] pts Array of translated polygon's vertices
213
+ def get_translated_vertice_points
214
+ abs_pos = get_absolute_position.to_point
215
+ @vertices.collect { |pt| abs_pos + pt.to_point }
216
+ end
217
+
218
+ # Draw the polygon shape.
219
+ # @param [Wx::DC] dc Reference to the device context where the shape will be drawn to
220
+ def draw_polygon_shape(dc)
221
+ pts = get_translated_vertice_points
222
+ dc.draw_polygon(pts)
223
+ end
224
+
225
+ # Draw the shape in the normal way. The function can be overridden if necessary.
226
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
227
+ def draw_normal(dc)
228
+ # HINT: overload it for custom actions...
229
+
230
+ dc.with_pen(@border) do
231
+ dc.with_brush(@fill) do
232
+ draw_polygon_shape(dc)
233
+ end
234
+ end
235
+ end
236
+
237
+ # Draw the shape in the hover mode (the mouse cursor is above the shape).
238
+ # The function can be overridden if necessary.
239
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
240
+ def draw_hover(dc)
241
+ # HINT: overload it for custom actions...
242
+
243
+ dc.with_pen(Wx::Pen.new(get_hover_colour, 1)) do
244
+ dc.with_brush(@fill) do
245
+ draw_polygon_shape(dc)
246
+ end
247
+ end
248
+ end
249
+
250
+ # Draw the shape in the highlighted mode (another shape is dragged over this
251
+ # shape and this shape will accept the dragged one if it will be dropped on it).
252
+ # The function can be overridden if necessary.
253
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
254
+ def draw_highlighted(dc)
255
+ # HINT: overload it for custom actions...
256
+
257
+ dc.with_pen(Wx::Pen.new(get_hover_colour, 2)) do
258
+ dc.with_brush(@fill) do
259
+ draw_polygon_shape(dc)
260
+ end
261
+ end
262
+ end
263
+
264
+ # Draw shadow under the shape. The function can be overridden if necessary.
265
+ # @param [Wx::DC] dc Reference to device context where the shadow will be drawn to
266
+ def draw_shadow(dc)
267
+ # HINT: overload it for custom actions...
268
+
269
+ if @fill.get_style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
270
+ dc.with_pen(Wx::TRANSPARENT_PEN) do
271
+ dc.with_brush(get_parent_canvas.get_shadow_fill) do
272
+ offset = get_parent_canvas.get_shadow_offset
273
+
274
+ move_by(offset)
275
+ draw_polygon_shape(dc)
276
+ move_by(-offset.x, -offset.y)
277
+ end
278
+ end
279
+ end
280
+ end
281
+
282
+ # Deserialize attributes and recalculate rectangle size afterwards.
283
+ # @param [Hash] data
284
+ # @return [self]
285
+ def from_serialized(data)
286
+ super
287
+ normalize_vertices
288
+ fit_vertices_to_bounding_box
289
+ self
290
+ end
291
+
292
+ end
293
+
294
+ end
@@ -0,0 +1,378 @@
1
+ # Wx::SF::RectShape - rectangle shape class
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ module Wx::SF
5
+
6
+ class RectShape < Shape
7
+
8
+ # default values
9
+ module DEFAULT
10
+ # Default value of RectShape @rect_size data member.
11
+ SIZE = Wx::RealPoint.new(100, 50)
12
+ # Default value of RectShape @fill data member.
13
+ FILL = Wx::Brush.new(Wx::WHITE) if Wx::App.is_main_loop_running
14
+ Wx.add_delayed_constant(self, :FILL) { Wx::Brush.new(Wx::WHITE) }
15
+ # Default value of RectShape @border data member.
16
+ BORDER = Wx::Pen.new(Wx::BLACK) if Wx::App.is_main_loop_running
17
+ Wx.add_delayed_constant(self, :BORDER) { Wx::Pen.new(Wx::BLACK) }
18
+ end
19
+
20
+ property :rect_size, :fill, :border
21
+
22
+ # @overload initialize()
23
+ # Default constructor.
24
+ # @overload initialize(pos, size, diagram)
25
+ # User constructor.
26
+ # @param [Wx::RealPoint] pos Initial position
27
+ # @param [Wx::RealPoint] size Initial size
28
+ # @param [Wx::SF::Diagram] diagram parent diagram
29
+ def initialize(*args)
30
+ size = nil
31
+ if args.empty?
32
+ super
33
+ else
34
+ pos, size, diagram = args
35
+ super(pos, diagram)
36
+ end
37
+ @rect_size = size ? size.to_real_point : DEFAULT::SIZE.dup
38
+ @fill = DEFAULT::FILL
39
+ @border = DEFAULT::BORDER
40
+ @prev_size = @prev_position = Wx::RealPoint
41
+ end
42
+
43
+ # Set rectangle's fill style.
44
+ # @param [Wx::Brush] brush Reference to a brush object
45
+ def set_fill(brush)
46
+ @fill = brush
47
+ end
48
+ alias :fill= :set_fill
49
+
50
+ # Get current fill style.
51
+ # @return [Wx::Brush] Current brush
52
+ def get_fill
53
+ @fill
54
+ end
55
+ alias :fill :get_fill
56
+
57
+ # Set rectangle's border style.
58
+ # @param [Wx::Pen] pen Reference to a pen object
59
+ def set_border(pen)
60
+ @border = pen
61
+ end
62
+ alias :border= :set_border
63
+
64
+ # Get current border style.
65
+ # @return [Wx::Pen] Current pen
66
+ def get_border
67
+ @border
68
+ end
69
+ alias :border :get_border
70
+
71
+ # Set the rectangle size.
72
+ # @overload set_rect_size(x, y)
73
+ # @param [Float] x Horizontal size
74
+ # @param [Float] y Vertical size
75
+ # @overload set_rect_size(size)
76
+ # @param [Wx::RealPoint] size New size
77
+ def set_rect_size(arg1, arg2 = nil)
78
+ @rect_size = arg2 ? Wx::RealPoint.new(arg1.to_f, arg2.to_f) : arg1.to_real_point
79
+ end
80
+ alias :rect_size= :set_rect_size
81
+
82
+ # Get the rectangle size.
83
+ # @return [Wx::RealPoint] Current size
84
+ def get_rect_size
85
+ @rect_size
86
+ end
87
+ alias :rect_size :get_rect_size
88
+
89
+ # Get shape's bounding box. The function can be overridden if necessary.
90
+ # @return [Wx::Rect] Bounding rectangle
91
+ def get_bounding_box
92
+ apos = get_absolute_position
93
+ Wx::Rect.new([apos.x.to_i, apos.y.to_i], [@rect_size.x.to_i, @rect_size.y.to_i])
94
+ end
95
+
96
+ # Get intersection point of the shape border and a line leading from
97
+ # 'start' point to 'end' point. The function can be overridden if necessary.
98
+ # @param [Wx::RealPoint] start Starting point of the virtual intersection line
99
+ # @param [Wx::RealPoint] end_pt Ending point of the virtual intersection line
100
+ # @return [Wx::RealPoint] Intersection point
101
+ def get_border_point(start, end_pt)
102
+ # HINT: override it for custom actions ...
103
+ start = start.to_real_point; end_pt.to_real_point
104
+
105
+ # the function calculates intersection of line leading from the shape center to
106
+ # given point with the shape's bounding box
107
+ bb_rct = get_bounding_box
108
+
109
+ intersection = Shape.lines_intersection(bb_rct.top_left.to_real,
110
+ Wx::RealPoint.new(bb_rct.top_right.x + 1.0, bb_rct.top_right.y.to_f),
111
+ start, end_pt)
112
+ intersection ||= Shape.lines_intersection(Wx::RealPoint.new(bb_rct.top_right.x + 1.0, bb_rct.top_right.y.to_f),
113
+ Wx::RealPoint.new(bb_rct.bottom_right.x + 1.0, bb_rct.bottom_right.y + 1.0),
114
+ start, end_pt)
115
+ intersection ||= Shape.lines_intersection(Wx::RealPoint.new(bb_rct.bottom_right.x + 1.0, bb_rct.bottom_right.y + 1.0),
116
+ Wx::RealPoint.new(bb_rct.bottom_left.x.to_f, bb_rct.bottom_left.y + 1.0),
117
+ start, end_pt)
118
+ intersection ||= Shape.lines_intersection(Wx::RealPoint.new(bb_rct.bottom_left.x.to_f, bb_rct.bottom_left.y + 1),
119
+ bb_rct.top_left.to_real,
120
+ start, end_pt)
121
+ intersection || get_center
122
+ end
123
+
124
+ # Function called by the framework responsible for creation of shape handles
125
+ # at the creation time. The function can be overridden if necessary.
126
+ def create_handles
127
+ # HINT: overload it for custom actions...
128
+
129
+ add_handle(Shape::Handle::TYPE::LEFTTOP)
130
+ add_handle(Shape::Handle::TYPE::TOP)
131
+ add_handle(Shape::Handle::TYPE::RIGHTTOP)
132
+ add_handle(Shape::Handle::TYPE::RIGHT)
133
+ add_handle(Shape::Handle::TYPE::RIGHTBOTTOM)
134
+ add_handle(Shape::Handle::TYPE::BOTTOM)
135
+ add_handle(Shape::Handle::TYPE::LEFTBOTTOM)
136
+ add_handle(Shape::Handle::TYPE::LEFT)
137
+ add_handle(Shape::Handle::TYPE::LEFTTOP)
138
+ end
139
+
140
+ # Event handler called during dragging of the shape handle.
141
+ # The function can be overridden if necessary.
142
+ #
143
+ # The function is called by the framework (by the shape canvas).
144
+ # @param [Shape::Handle] handle Reference to dragged handle
145
+ def on_handle(handle)
146
+ # HINT: overload it for custom actions...
147
+ do_on_handle(handle)
148
+
149
+ super
150
+ end
151
+
152
+ # Event handler called when the user started to drag the shape handle.
153
+ # The function can be overridden if necessary.
154
+ #
155
+ # The function is called by the framework (by the shape canvas).
156
+ # @param [Shape::Handle] handle Reference to dragged handle
157
+ def on_begin_handle(handle)
158
+ do_begin_handle
159
+ super
160
+ end
161
+
162
+ # Resize the shape to bound all child shapes. The function can be overridden if necessary.
163
+ def fit_to_children
164
+ # HINT: overload it for custom actions...
165
+
166
+ # get bounding box of the shape and children set be inside it
167
+ ch_bb = get_bounding_box
168
+ shp_bb = ch_bb.dup
169
+
170
+ @child_shapes.each do |child|
171
+ if child.has_style?(STYLE::ALWAYS_INSIDE)
172
+ child.get_complete_bounding_box(ch_bb, BBMODE::SELF | BBMODE::CHILDREN)
173
+ end
174
+ end
175
+
176
+ unless ch_bb.empty?
177
+ unless shp_bb.contains?(ch_bb)
178
+ dx = ch_bb.left - shp_bb.left
179
+ dy = ch_bb.top - shp_bb.top
180
+
181
+ # resize parent shape
182
+ shp_bb.union!(ch_bb)
183
+ move_to(shp_bb.get_position.x, shp_bb.get_position.y)
184
+ @rect_size = Wx::RealPoint.new(shp_bb.get_size.x.to_f, shp_bb.get_size.y.to_f)
185
+ if has_style?(STYLE::EMIT_EVENTS)
186
+ evt = ShapeEvent.new(EVT_SF_SHAPE_SIZE_CHANGED, id)
187
+ evt.set_shape(self)
188
+ get_parent_canvas.get_event_handler.process_event(evt)
189
+ end
190
+
191
+ # move its "1st level" children if necessary
192
+ if dx < 0 || dy < 0
193
+ @child_shapes.each do |child|
194
+ child.move_by(dx.to_i.abs, 0) if dx < 0
195
+ child.move_by(0, dy.to_i.abs) if dy < 0
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+ # Scale the shape size by in both directions. The function can be overridden if necessary
203
+ # (new implementation should call default one ore scale shape's children manualy if neccesary).
204
+ # @param [Float] x Horizontal scale factor
205
+ # @param [Float] y Vertical scale factor
206
+ # @param [Boolean] children true if the shape's children should be scaled as well, otherwise the shape will be updated after scaling via update() function.
207
+ def scale(x, y, children = WITHCHILDREN)
208
+ # HINT: overload it for custom actions...
209
+ if x > 0 && y > 0
210
+ scale_rectangle(x, y)
211
+
212
+ # call default function implementation (needed for scaling of shape's children)
213
+ super
214
+ end
215
+ end
216
+
217
+ protected
218
+
219
+ # Handle action at handle drag beginning
220
+ def do_begin_handle
221
+ @prev_position = @relative_position.dup
222
+ @prev_size = @rect_size.dup
223
+ end
224
+
225
+ # Scale the rectangle size for this shape.
226
+ # @param [Float] x Horizontal scale factor
227
+ # @param [Float] y Vertical scale factor
228
+ def scale_rectangle(x, y)
229
+ set_rect_size(@rect_size.x * x, @rect_size.y * y)
230
+ end
231
+
232
+ # Handle's shape specific actions on handling handle events.
233
+ # The function can be overridden if necessary.
234
+ # @param [Shape::Handle] handle Reference to dragged handle
235
+ # @see #on_handle
236
+ def do_on_handle(handle)
237
+ case handle.type
238
+ when Shape::Handle::TYPE::LEFT
239
+ on_left_handle(handle)
240
+
241
+ when Shape::Handle::TYPE::LEFTTOP
242
+ on_left_handle(handle)
243
+ on_top_handle(handle)
244
+
245
+ when Shape::Handle::TYPE::LEFTBOTTOM
246
+ on_left_handle(handle)
247
+ on_bottom_handle(handle)
248
+
249
+ when Shape::Handle::TYPE::RIGHT
250
+ on_right_handle(handle)
251
+
252
+ when Shape::Handle::TYPE::RIGHTTOP
253
+ on_right_handle(handle)
254
+ on_top_handle(handle)
255
+
256
+ when Shape::Handle::TYPE::RIGHTBOTTOM
257
+ on_right_handle(handle)
258
+ on_bottom_handle(handle)
259
+
260
+ when Shape::Handle::TYPE::TOP
261
+ on_top_handle(handle)
262
+
263
+ when Shape::Handle::TYPE::BOTTOM
264
+ on_bottom_handle(handle)
265
+ end
266
+ end
267
+
268
+ # Draw the shape in the normal way. The function can be overridden if necessary.
269
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
270
+ def draw_normal(dc)
271
+ # HINT: overload it for custom actions...
272
+
273
+ dc.with_pen(@border) do
274
+ dc.with_brush(@fill) do
275
+ dc.draw_rectangle(get_absolute_position.to_point, @rect_size.to_size)
276
+ end
277
+ end
278
+ end
279
+
280
+ # Draw the shape in the hover mode (the mouse cursor is above the shape).
281
+ # The function can be overridden if necessary.
282
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
283
+ def draw_hover(dc)
284
+ # HINT: overload it for custom actions...
285
+
286
+ dc.with_pen(Wx::Pen.new(@hover_color, 1)) do
287
+ dc.with_brush(@fill) do
288
+ dc.draw_rectangle(get_absolute_position.to_point, @rect_size.to_size)
289
+ end
290
+ end
291
+ end
292
+
293
+ # Draw the shape in the highlighted mode (another shape is dragged over this
294
+ # shape and this shape will accept the dragged one if it will be dropped on it).
295
+ # The function can be overridden if necessary.
296
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
297
+ def draw_highlighted(dc)
298
+ # HINT: overload it for custom actions...
299
+
300
+ dc.with_pen(Wx::Pen.new(@hover_color, 2)) do
301
+ dc.with_brush(@fill) do
302
+ dc.draw_rectangle(get_absolute_position.to_point, @rect_size.to_size)
303
+ end
304
+ end
305
+ end
306
+
307
+ # Draw shadow under the shape. The function can be overridden if necessary.
308
+ # @param [Wx::DC] dc Reference to device context where the shadow will be drawn to
309
+ def draw_shadow(dc)
310
+ # HINT: overload it for custom actions...
311
+
312
+ if @fill.style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
313
+ dc.with_pen(Wx::TRANSPARENT_PEN) do
314
+ dc.with_brush(get_parent_canvas.get_shadow_fill) do
315
+ dc.draw_rectangle((get_absolute_position + get_parent_canvas.get_shadow_offset).to_point, @rect_size.to_size)
316
+ end
317
+ end
318
+ end
319
+ end
320
+
321
+ # Event handler called during dragging of the right shape handle.
322
+ # The function can be overridden if necessary.
323
+ # @param [Shape::Handle] handle Reference to dragged shape handle
324
+ def on_right_handle(handle)
325
+ # HINT: overload it for custom actions...
326
+
327
+ @rect_size.x += handle.get_delta.x
328
+ end
329
+
330
+ # Event handler called during dragging of the left shape handle.
331
+ # The function can be overridden if necessary.
332
+ # @param [Shape::Handle] handle Reference to dragged shape handle
333
+ def on_left_handle(handle)
334
+ # HINT: overload it for custom actions...
335
+
336
+ dx = handle.get_delta.x.to_f
337
+
338
+ # update position of children
339
+ unless has_style?(STYLE::LOCK_CHILDREN)
340
+ @child_shapes.each do |child|
341
+ child.move_by(-dx, 0) if child.get_h_align == HALIGN::NONE
342
+ end
343
+ end
344
+ # update position and size of the shape
345
+ @rect_size.x -= dx
346
+ @relative_position.x += dx
347
+ end
348
+
349
+ # Event handler called during dragging of the top shape handle.
350
+ # The function can be overridden if necessary.
351
+ # @param [Shape::Handle] handle Reference to dragged shape handle
352
+ def on_top_handle(handle)
353
+ # HINT: overload it for custom actions...
354
+
355
+ dy = handle.get_delta.y.to_f
356
+
357
+ # update position of children
358
+ unless has_style?(STYLE::LOCK_CHILDREN)
359
+ @child_shapes.each do |child|
360
+ child.move_by(0, -dy) if child.get_v_align == VALIGN::NONE
361
+ end
362
+ end
363
+ # update position and size of the shape
364
+ @rect_size.y -= dy
365
+ @relative_position.y += dy
366
+ end
367
+
368
+ # Event handler called during dragging of the bottom shape handle.
369
+ # The function can be overridden if necessary.
370
+ # @param [Shape::Handle] handle Reference to dragged shape handle
371
+ def on_bottom_handle(handle)
372
+ # HINT: overload it for custom actions...
373
+
374
+ @rect_size.y += handle.get_delta.y
375
+ end
376
+ end
377
+
378
+ end