wxruby3-shapes 0.9.0.pre.beta.3

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.
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