wxruby3-shapes 0.9.0.pre.beta.3 → 0.9.6

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/INSTALL.md +5 -7
  3. data/README.md +38 -6
  4. data/assets/logo.svg +339 -0
  5. data/assets/logo.xpm +60 -0
  6. data/assets/screenshot.png +0 -0
  7. data/assets/social.png +0 -0
  8. data/bin/wx-shapes +1 -1
  9. data/lib/wx/shapes/arrow_base.rb +4 -11
  10. data/lib/wx/shapes/arrows/circle_arrow.rb +22 -11
  11. data/lib/wx/shapes/arrows/circle_prong_arrow.rb +48 -0
  12. data/lib/wx/shapes/arrows/cross_bar_arrow.rb +57 -0
  13. data/lib/wx/shapes/arrows/cross_bar_circle_arrow.rb +56 -0
  14. data/lib/wx/shapes/arrows/cross_bar_prong_arrow.rb +49 -0
  15. data/lib/wx/shapes/arrows/crossed_circle.rb +46 -0
  16. data/lib/wx/shapes/arrows/cup_arrow.rb +65 -0
  17. data/lib/wx/shapes/arrows/diamond_arrow.rb +8 -13
  18. data/lib/wx/shapes/arrows/double_cross_bar_arrow.rb +27 -0
  19. data/lib/wx/shapes/arrows/filled_arrow.rb +60 -0
  20. data/lib/wx/shapes/arrows/line_arrow.rb +67 -0
  21. data/lib/wx/shapes/arrows/open_arrow.rb +22 -23
  22. data/lib/wx/shapes/arrows/prong_arrow.rb +42 -0
  23. data/lib/wx/shapes/arrows/solid_arrow.rb +21 -35
  24. data/lib/wx/shapes/arrows/square_arrow.rb +37 -0
  25. data/lib/wx/shapes/auto_layout.rb +2 -2
  26. data/lib/wx/shapes/base.rb +1 -1
  27. data/lib/wx/shapes/canvas_history.rb +20 -0
  28. data/lib/wx/shapes/connection_point.rb +10 -6
  29. data/lib/wx/shapes/diagram.rb +98 -78
  30. data/lib/wx/shapes/events.rb +8 -8
  31. data/lib/wx/shapes/printout.rb +3 -16
  32. data/lib/wx/shapes/serializable.rb +2 -436
  33. data/lib/wx/shapes/serialize/wx.rb +30 -18
  34. data/lib/wx/shapes/shape.rb +211 -168
  35. data/lib/wx/shapes/shape_canvas.rb +728 -267
  36. data/lib/wx/shapes/shape_data_object.rb +99 -18
  37. data/lib/wx/shapes/shape_handle.rb +18 -11
  38. data/lib/wx/shapes/shape_list.rb +34 -67
  39. data/lib/wx/shapes/shapes/bitmap_shape.rb +23 -24
  40. data/lib/wx/shapes/shapes/box_shape.rb +389 -0
  41. data/lib/wx/shapes/shapes/circle_shape.rb +19 -22
  42. data/lib/wx/shapes/shapes/control_shape.rb +77 -41
  43. data/lib/wx/shapes/shapes/curve_shape.rb +38 -31
  44. data/lib/wx/shapes/shapes/diamond_shape.rb +7 -17
  45. data/lib/wx/shapes/shapes/edit_text_shape.rb +6 -9
  46. data/lib/wx/shapes/shapes/ellipse_shape.rb +12 -15
  47. data/lib/wx/shapes/shapes/flex_grid_shape.rb +58 -33
  48. data/lib/wx/shapes/shapes/grid_shape.rb +259 -161
  49. data/lib/wx/shapes/shapes/line_shape.rb +155 -161
  50. data/lib/wx/shapes/shapes/manager_shape.rb +77 -0
  51. data/lib/wx/shapes/shapes/multi_sel_rect.rb +8 -8
  52. data/lib/wx/shapes/shapes/ortho_shape.rb +31 -36
  53. data/lib/wx/shapes/shapes/polygon_shape.rb +23 -29
  54. data/lib/wx/shapes/shapes/rect_shape.rb +95 -53
  55. data/lib/wx/shapes/shapes/round_ortho_shape.rb +6 -8
  56. data/lib/wx/shapes/shapes/round_rect_shape.rb +20 -24
  57. data/lib/wx/shapes/shapes/square_shape.rb +14 -17
  58. data/lib/wx/shapes/shapes/text_shape.rb +95 -53
  59. data/lib/wx/shapes/version.rb +1 -1
  60. data/lib/wx/shapes/wx.rb +16 -7
  61. data/lib/wx/wx-shapes/cmd/test.rb +1 -1
  62. data/samples/demo/arrows.json +1 -0
  63. data/samples/demo/arrows.yaml +793 -0
  64. data/samples/demo/art/HBox.xpm +22 -0
  65. data/samples/demo/art/VBox.xpm +22 -0
  66. data/samples/demo/art/logo.xpm +60 -0
  67. data/samples/demo/class.json +1 -0
  68. data/samples/demo/class.yaml +5631 -0
  69. data/samples/demo/demo.rb +301 -91
  70. data/samples/demo/dialogs.rb +1405 -0
  71. data/samples/demo/erd.json +1 -0
  72. data/samples/demo/erd.yaml +4072 -0
  73. data/samples/demo/frame_canvas.rb +409 -33
  74. data/samples/sample1/art/logo.xpm +60 -0
  75. data/samples/sample1/sample.rb +11 -11
  76. data/samples/sample2/art/logo.xpm +60 -0
  77. data/samples/sample2/sample.rb +2 -2
  78. data/samples/sample2/sample_shape.rb +15 -15
  79. data/samples/sample3/art/logo.xpm +60 -0
  80. data/samples/sample3/sample.rb +3 -3
  81. data/samples/sample4/art/logo.xpm +60 -0
  82. data/samples/sample4/sample.rb +2 -2
  83. data/tests/lib/wxapp_runner.rb +4 -0
  84. data/tests/serializer_tests.rb +8 -441
  85. data/tests/test_grid_shapes.rb +2 -2
  86. data/tests/test_serialize_xml.rb +17 -0
  87. data/tests/test_serialize_yaml.rb +2 -2
  88. metadata +78 -28
  89. data/lib/wx/shapes/serialize/core.rb +0 -40
  90. data/lib/wx/shapes/serialize/id.rb +0 -82
  91. data/lib/wx/shapes/serializer/json.rb +0 -258
  92. data/lib/wx/shapes/serializer/yaml.rb +0 -125
  93. data/samples/demo/art/sample.xpm +0 -251
  94. data/samples/sample1/art/sample.xpm +0 -251
  95. data/samples/sample2/art/sample.xpm +0 -251
  96. data/samples/sample3/art/sample.xpm +0 -251
  97. data/samples/sample4/art/sample.xpm +0 -251
@@ -0,0 +1,77 @@
1
+ # Wx::SF::ContainerShape - container shape mixin
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ module Wx::SF
5
+
6
+ # Mixin for container shape classes that control there child shape size/position/alignment.
7
+ module ManagerShape
8
+
9
+ # Returns true if the shape manages (size/position/alignment) of it's child shapes.
10
+ # @return [Boolean] true
11
+ def is_manager
12
+ true
13
+ end
14
+ alias :manager? :is_manager
15
+
16
+ # Update the shape's position in order to its alignment
17
+ def do_alignment
18
+ super
19
+
20
+ # do alignment of shape's children
21
+ do_children_layout
22
+ end
23
+
24
+ protected
25
+
26
+ def do_children_layout
27
+ raise NotImplementedError, 'Manager shapes need override'
28
+ end
29
+
30
+ # Move and resize given shape so it will fit the given bounding rectangle.
31
+ #
32
+ # The shape is aligned inside the given bounding rectangle in accordance to the shape's
33
+ # valign and halign flags.
34
+ # @param [Shape] shape modified shape
35
+ # @param [Wx::Rect] rct Bounding rectangle
36
+ # @see Shape#set_v_align
37
+ # @see Shape#set_h_align
38
+ def fit_shape_to_rect(shape, rct)
39
+ shape_bb = shape.get_bounding_box
40
+ prev_pos = shape.get_relative_position
41
+
42
+ # do vertical alignment
43
+ case shape.get_v_align
44
+ when Shape::VALIGN::TOP
45
+ shape.set_relative_position(prev_pos.x, rct.top + shape.get_v_border)
46
+ when Shape::VALIGN::MIDDLE
47
+ shape.set_relative_position(prev_pos.x, rct.top + (rct.height/2 - shape_bb.height/2))
48
+ when Shape::VALIGN::BOTTOM
49
+ shape.set_relative_position(prev_pos.x, rct.bottom - shape_bb.height - shape.get_v_border)
50
+ when Shape::VALIGN::EXPAND
51
+ shape.set_relative_position(prev_pos.x, rct.top + shape.get_v_border)
52
+ shape.scale(1.0, (rct.height - 2*shape.get_v_border).to_f/shape_bb.height)
53
+ else
54
+ shape.set_relative_position(prev_pos.x, rct.top)
55
+ end
56
+
57
+ prev_pos = shape.get_relative_position
58
+
59
+ # do horizontal alignment
60
+ case shape.get_h_align
61
+ when Shape::HALIGN::LEFT
62
+ shape.set_relative_position(rct.left + shape.get_h_border, prev_pos.y)
63
+ when Shape::HALIGN::CENTER
64
+ shape.set_relative_position(rct.left + (rct.width/2 - shape_bb.width/2), prev_pos.y)
65
+ when Shape::HALIGN::RIGHT
66
+ shape.set_relative_position(rct.right - shape_bb.width - shape.get_h_border, prev_pos.y)
67
+ when Shape::HALIGN::EXPAND
68
+ shape.set_relative_position(rct.left + shape.get_h_border, prev_pos.y)
69
+ shape.scale((rct.width - 2*shape.get_h_border).to_f/shape_bb.width, 1.0)
70
+ else
71
+ shape.set_relative_position(rct.left, prev_pos.y)
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -60,7 +60,7 @@ module Wx::SF
60
60
  lst_selection.each do |shape|
61
61
  # scale main parent shape
62
62
  if !shape.is_a?(LineShape)
63
- shape.scale(sx, 1, WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
63
+ shape.scale(sx, 1, children: WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
64
64
  if shape.has_style?(STYLE::POSITION_CHANGE)
65
65
  dx = (shape.get_absolute_position.x - (get_absolute_position.x + DEFAULT_ME_OFFSET))/(get_rect_size.x - 2*DEFAULT_ME_OFFSET)*handle.get_delta.x
66
66
  shape.move_by(dx, 0)
@@ -90,7 +90,7 @@ module Wx::SF
90
90
 
91
91
  lst_selection.each do |shape|
92
92
  if !shape.is_a?(LineShape)
93
- if shape.has_style?(STYLE:POSITION_CHANGE)
93
+ if shape.has_style?(STYLE::POSITION_CHANGE)
94
94
  if shape.get_parent_shape
95
95
  shape.set_relative_position(shape.get_relative_position.x*sx, shape.get_relative_position.y)
96
96
  else
@@ -98,7 +98,7 @@ module Wx::SF
98
98
  shape.move_by(dx, 0)
99
99
  end
100
100
  end
101
- shape.scale(sx, 1, WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
101
+ shape.scale(sx, 1, children: WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
102
102
  shape.fit_to_children unless shape.has_style?(STYLE::NO_FIT_TO_CHILDREN)
103
103
  else
104
104
  if shape.has_style?(STYLE::POSITION_CHANGE)
@@ -132,7 +132,7 @@ module Wx::SF
132
132
  shape.move_by(0, dy)
133
133
  end
134
134
  end
135
- shape.scale(1, sy, WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
135
+ shape.scale(1, sy, children: WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
136
136
  shape.fit_to_children unless shape.has_style?(STYLE::NO_FIT_TO_CHILDREN)
137
137
  else
138
138
  if shape.has_style?(STYLE::POSITION_CHANGE)
@@ -153,12 +153,12 @@ module Wx::SF
153
153
  def on_bottom_handle(handle)
154
154
  if get_parent_canvas && !any_height_exceeded(handle.get_delta)
155
155
  sy = (get_rect_size.y - 2*DEFAULT_ME_OFFSET + handle.get_delta.y).to_f/(get_rect_size.y - 2*DEFAULT_ME_OFFSET)
156
-
156
+
157
157
  lst_selection = get_parent_canvas.get_selected_shapes
158
158
 
159
159
  lst_selection.each do |shape|
160
160
  if !shape.is_a?(LineShape)
161
- shape.scale(1, sy, WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
161
+ shape.scale(1, sy, children: WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
162
162
  if shape.has_style?(STYLE::POSITION_CHANGE)
163
163
  dy = (shape.get_absolute_position.y - (get_absolute_position.y + DEFAULT_ME_OFFSET))/(get_rect_size.y - 2*DEFAULT_ME_OFFSET)*handle.get_delta.y
164
164
  shape.move_by(0, dy)
@@ -187,7 +187,7 @@ module Wx::SF
187
187
  lst_selection = get_parent_canvas.get_selected_shapes
188
188
  # determine whether any shape in the selection exceeds its bounds
189
189
  lst_selection.each do |shape|
190
- return true if !shape.is_a?(LineShape) && (shape.get_bounding_box.width + delta.x) <= 1
190
+ return true if !shape.is_a?(LineShape) && (shape.get_bounding_box.width + delta.x) < 1
191
191
  end
192
192
  return false
193
193
  end
@@ -202,7 +202,7 @@ module Wx::SF
202
202
  lst_selection = get_parent_canvas.get_selected_shapes
203
203
  # determine whether any shape in the selection exceeds its bounds
204
204
  lst_selection.each do |shape|
205
- return true if !shape.is_a?(LineShape) && (shape.get_bounding_box.height + delta.y) <= 1
205
+ return true if !shape.is_a?(LineShape) && (shape.get_bounding_box.height + delta.y) < 1
206
206
  end
207
207
  return false
208
208
  end
@@ -11,14 +11,12 @@ module Wx::SF
11
11
 
12
12
  SEGMENTCPS = ::Struct.new(:src, :trg)
13
13
 
14
- # @overload initialize()
15
- # default constructor
16
- # @overload initialize(src, trg, path, manager)
17
- # @param [Wx::SF::Serializable::ID] src ID of the source shape
18
- # @param [Wx::SF::Serializable::ID] trg ID of the target shape
19
- # @param [Array<Wx::RealPoint>] path List of the line control points (can be empty)
20
- # @param [Diagram] diagram containing diagram
21
- def initialize(*args)
14
+ # Constructor
15
+ # @param [Shape] src source shape
16
+ # @param [Shape] trg target shape
17
+ # @param [Array<Wx::RealPoint>] path List of the line control points (can be empty)
18
+ # @param [Diagram] diagram containing diagram
19
+ def initialize(src = nil, trg = nil, path: nil, diagram: nil)
22
20
  super
23
21
  end
24
22
 
@@ -31,33 +29,33 @@ module Wx::SF
31
29
 
32
30
  src = trg = cp_src = cp_trg = nil
33
31
 
34
- shape = @diagram.find_shape(@src_shape_id)
35
- if shape
36
- cp_src = shape.get_nearest_connection_point(get_mod_src_point)
32
+ if @src_shape
33
+ cp_src = @src_shape.get_nearest_connection_point(get_mod_src_point)
37
34
  end
38
- shape = @diagram.find_shape(@trg_shape_id)
39
- if shape
40
- cp_trg = shape.get_nearest_connection_point(get_mod_trg_point)
35
+ if @trg_shape
36
+ cp_trg = @trg_shape.get_nearest_connection_point(get_mod_trg_point)
41
37
  end
42
38
 
43
39
  case @mode
44
40
  when LINEMODE::READY
45
41
  # draw basic line parts
46
- line_segment_count.times do |i|
42
+ n = line_segment_count-1
43
+ (0..n).each do |i|
47
44
  src, trg = get_line_segment(i)
45
+ # at starting (src) segment draw src arrow and get updated arrow connection point
46
+ if i == 0 && @src_arrow
47
+ asrc, atrg = get_first_subsegment(src, trg, get_used_connection_points(cp_src, cp_trg, 0))
48
+ src = @src_arrow.draw(atrg, asrc, dc)
49
+ cp_src = nil
50
+ end
51
+ # at end (tgt) segment draw tgt arrow and get updated connection point
52
+ if i == n && @trg_arrow
53
+ asrc, atrg = get_last_subsegment(src, trg, get_used_connection_points(cp_src, cp_trg, @lst_points.size))
54
+ trg = @trg_arrow.draw(asrc, atrg, dc)
55
+ cp_trg = nil
56
+ end
48
57
  draw_line_segment(dc, src, trg, get_used_connection_points(cp_src, cp_trg, i))
49
58
  end
50
- # draw target arrow
51
- if @trg_arrow
52
- asrc, atrg = get_last_subsegment(src, trg, get_used_connection_points(cp_src, cp_trg, @lst_points.size))
53
- @trg_arrow.draw(asrc, atrg, dc)
54
- end
55
- # draw source arrow
56
- if @src_arrow
57
- src, trg = get_line_segment(0)
58
- asrc, atrg = get_first_subsegment(src, trg, get_used_connection_points(cp_src, cp_trg, 0))
59
- @src_arrow.draw(atrg, asrc, dc)
60
- end
61
59
 
62
60
  when LINEMODE::UNDERCONSTRUCTION
63
61
  # draw basic line parts
@@ -71,11 +69,10 @@ module Wx::SF
71
69
  if @lst_points.size>1
72
70
  draw_line_segment(dc, trg, @unfinished_point.to_real, get_used_connection_points(cp_src, cp_trg, @lst_points.size))
73
71
  else
74
- src_shape = @diagram.find_shape(@src_shape_id)
75
- if src_shape
76
- if src_shape.get_connection_points.empty?
72
+ if @src_shape
73
+ if @src_shape.get_connection_points.empty?
77
74
  draw_line_segment(dc,
78
- src_shape.get_border_point(src_shape.get_center, @unfinished_point.to_real),
75
+ @src_shape.get_border_point(@src_shape.get_center, @unfinished_point.to_real),
79
76
  @unfinished_point.to_real,
80
77
  get_used_connection_points(cp_src, cp_trg, 0))
81
78
  else
@@ -133,13 +130,11 @@ module Wx::SF
133
130
  cp_src = nil
134
131
  cp_trg = nil
135
132
 
136
- shape = @diagram.find_shape(@src_shape_id)
137
- if shape
138
- cp_src = shape.get_nearest_connection_point(get_mod_src_point)
133
+ if @src_shape
134
+ cp_src = @src_shape.get_nearest_connection_point(get_mod_src_point)
139
135
  end
140
- shape = @diagram.find_shape(@trg_shape_id)
141
- if shape
142
- cp_trg = shape.get_nearest_connection_point(get_mod_trg_point)
136
+ if @trg_shape
137
+ cp_trg = @trg_shape.get_nearest_connection_point(get_mod_trg_point)
143
138
  end
144
139
 
145
140
  # Get all polyline segments
@@ -19,23 +19,14 @@ module Wx::SF
19
19
 
20
20
  property :connect_to_vertex, :vertices
21
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)
22
+ # Constructor.
23
+ # @param [Wx::RealPoint,Wx::Point] pos Initial position
24
+ # @param [Array<Wx::RealPoint>] vertices Array of the polygon vertices
25
+ # @param [Wx::SF::Diagram] diagram parent diagram
26
+ def initialize(pos = Shape::DEFAULT::POSITION, vertices: [], diagram: nil)
27
+ super(pos, Wx::RealPoint.new(1,1), diagram: diagram)
30
28
  @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
29
+ set_vertices(vertices)
39
30
  end
40
31
 
41
32
  # Set connecting mode.
@@ -104,8 +95,9 @@ module Wx::SF
104
95
  intersection
105
96
  else
106
97
  success = false
98
+ min_dist = 0.0
107
99
  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)
100
+ if (tmp_intersection = Wx::SF::Shape.lines_intersection(pt, pts[(i+1) % pts.size], start, end_pt))
109
101
  if !success
110
102
  min_dist = intersection.distance_to(end_pt)
111
103
  intersection = tmp_intersection
@@ -166,12 +158,14 @@ module Wx::SF
166
158
  def fit_vertices_to_bounding_box
167
159
  minx, miny, maxx, maxy = get_extents
168
160
 
169
- sx = rect_size.x/(maxx - minx)
170
- sy = rect_size.y/(maxy - miny)
161
+ width = (maxx - minx)
162
+ height = (maxy - miny)
163
+ sx = rect_size.x/width
164
+ sy = rect_size.y/height
171
165
 
172
166
  @vertices.each do |pt|
173
- pt.x *= sx
174
- pt.y *= sy
167
+ pt.x = (width != 0.0) ? pt.x*sx : minx
168
+ pt.y = (height != 0.0) ? pt.y*sy : miny
175
169
  end
176
170
  end
177
171
 
@@ -227,8 +221,8 @@ module Wx::SF
227
221
  def draw_normal(dc)
228
222
  # HINT: overload it for custom actions...
229
223
 
230
- dc.with_pen(@border) do
231
- dc.with_brush(@fill) do
224
+ dc.with_pen(border) do
225
+ dc.with_brush(fill) do
232
226
  draw_polygon_shape(dc)
233
227
  end
234
228
  end
@@ -241,7 +235,7 @@ module Wx::SF
241
235
  # HINT: overload it for custom actions...
242
236
 
243
237
  dc.with_pen(Wx::Pen.new(get_hover_colour, 1)) do
244
- dc.with_brush(@fill) do
238
+ dc.with_brush(fill) do
245
239
  draw_polygon_shape(dc)
246
240
  end
247
241
  end
@@ -255,7 +249,7 @@ module Wx::SF
255
249
  # HINT: overload it for custom actions...
256
250
 
257
251
  dc.with_pen(Wx::Pen.new(get_hover_colour, 2)) do
258
- dc.with_brush(@fill) do
252
+ dc.with_brush(fill) do
259
253
  draw_polygon_shape(dc)
260
254
  end
261
255
  end
@@ -266,7 +260,7 @@ module Wx::SF
266
260
  def draw_shadow(dc)
267
261
  # HINT: overload it for custom actions...
268
262
 
269
- if @fill.get_style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
263
+ if fill.get_style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
270
264
  dc.with_pen(Wx::TRANSPARENT_PEN) do
271
265
  dc.with_brush(get_parent_canvas.get_shadow_fill) do
272
266
  offset = get_parent_canvas.get_shadow_offset
@@ -280,15 +274,15 @@ module Wx::SF
280
274
  end
281
275
 
282
276
  # Deserialize attributes and recalculate rectangle size afterwards.
283
- # @param [Hash] data
284
277
  # @return [self]
285
- def from_serialized(data)
286
- super
278
+ def deserialize_finalize
287
279
  normalize_vertices
288
280
  fit_vertices_to_bounding_box
289
281
  self
290
282
  end
291
283
 
284
+ define_deserialize_finalizer :deserialize_finalize
285
+
292
286
  end
293
287
 
294
288
  end
@@ -7,64 +7,76 @@ module Wx::SF
7
7
 
8
8
  # default values
9
9
  module DEFAULT
10
+ class << self
11
+ # Default value of RectShape fill data member.
12
+ def fill; fill ||= Wx::WHITE_BRUSH.dup; end
13
+ # Default value of RectShape @border data member.
14
+ def border; @border ||= Wx::BLACK_PEN.dup; end
15
+ end
10
16
  # Default value of RectShape @rect_size data member.
11
17
  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
18
  end
19
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
20
+ property rect_size: :serialize_rect_size
21
+ property({ fill: :serialize_rect_fill,
22
+ border: :serialize_rect_border },
23
+ optional: true)
24
+
25
+ # Constructor.
26
+ # @param [Wx::RealPoint,Wx::Point] pos Initial position
27
+ # @param [Wx::RealPoint,Wx::Size,Wx::Point,Array(Float,Float)] size Initial size
28
+ # @param [Wx::SF::Diagram] diagram parent diagram
29
+ def initialize(pos = Shape::DEFAULT::POSITION, size = DEFAULT::SIZE, diagram: nil)
30
+ super(pos, diagram: diagram)
31
+ set_rect_size(size.to_real_point)
32
+ @fill = nil
33
+ @border = nil
41
34
  end
42
35
 
43
36
  # Set rectangle's fill style.
44
- # @param [Wx::Brush] brush Reference to a brush object
45
- def set_fill(brush)
46
- @fill = brush
37
+ # @overload set_fill(brush)
38
+ # @param [Wx::Brush] brush
39
+ # @overload set_fill(color, style=Wx::BrushStyle::BRUSHSTYLE_SOLID)
40
+ # @param [Wx::Colour,Symbol,String] color brush color
41
+ # @param [Wx::BrushStyle] style
42
+ # @overload set_fill(stipple_bitmap)
43
+ # @param [Wx::Bitmap] stipple_bitmap
44
+ def set_fill(*args)
45
+ @fill = if args.size == 1 && Wx::Brush === args.first
46
+ args.first
47
+ else
48
+ Wx::Brush.new(*args)
49
+ end
47
50
  end
48
51
  alias :fill= :set_fill
49
52
 
50
53
  # Get current fill style.
51
54
  # @return [Wx::Brush] Current brush
52
55
  def get_fill
53
- @fill
56
+ @fill || (@diagram&.shape_canvas ? @diagram.shape_canvas.fill_brush : DEFAULT.fill)
54
57
  end
55
58
  alias :fill :get_fill
56
59
 
57
60
  # Set rectangle's border style.
58
- # @param [Wx::Pen] pen Reference to a pen object
59
- def set_border(pen)
60
- @border = pen
61
+ # @overload set_border(pen)
62
+ # @param [Wx::Pen] pen
63
+ # @overload set_border(color, width=1, style=Wx::PenStyle::PENSTYLE_SOLID)
64
+ # @param [Wx::Colour,String,Symbol] color
65
+ # @param [Integer] width
66
+ # @param [Wx::PenStyle] style
67
+ def set_border(*args)
68
+ @border = if args.size == 1 && Wx::Pen === args.first
69
+ args.first
70
+ else
71
+ Wx::Pen.new(*args)
72
+ end
61
73
  end
62
74
  alias :border= :set_border
63
75
 
64
76
  # Get current border style.
65
77
  # @return [Wx::Pen] Current pen
66
78
  def get_border
67
- @border
79
+ @border || (@diagram&.shape_canvas ? @diagram.shape_canvas.border_pen : DEFAULT.border)
68
80
  end
69
81
  alias :border :get_border
70
82
 
@@ -73,9 +85,11 @@ module Wx::SF
73
85
  # @param [Float] x Horizontal size
74
86
  # @param [Float] y Vertical size
75
87
  # @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
88
+ # @param [Wx::RealPoint,Array(Float, Float)] size New size
89
+ def set_rect_size(*args)
90
+ x, y = args.size == 1 ? args.first.to_real_point : args
91
+ # set new size while preventing 'invisible' shapes
92
+ @rect_size = Wx::RealPoint.new([1.0, x].max, [1.0, y].max)
79
93
  end
80
94
  alias :rect_size= :set_rect_size
81
95
 
@@ -163,7 +177,7 @@ module Wx::SF
163
177
  def fit_to_children
164
178
  # HINT: overload it for custom actions...
165
179
 
166
- # get bounding box of the shape and children set be inside it
180
+ # get bounding box of the shape and children set to be inside it
167
181
  ch_bb = get_bounding_box
168
182
  shp_bb = ch_bb.dup
169
183
 
@@ -183,7 +197,7 @@ module Wx::SF
183
197
  move_to(shp_bb.get_position.x, shp_bb.get_position.y)
184
198
  @rect_size = Wx::RealPoint.new(shp_bb.get_size.x.to_f, shp_bb.get_size.y.to_f)
185
199
  if has_style?(STYLE::EMIT_EVENTS)
186
- evt = ShapeEvent.new(EVT_SF_SHAPE_SIZE_CHANGED, id)
200
+ evt = ShapeEvent.new(EVT_SF_SHAPE_SIZE_CHANGED, self.object_id)
187
201
  evt.set_shape(self)
188
202
  get_parent_canvas.get_event_handler.process_event(evt)
189
203
  end
@@ -200,11 +214,11 @@ module Wx::SF
200
214
  end
201
215
 
202
216
  # 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).
217
+ # (new implementation should call default one ore scale shape's children manually if necessary).
204
218
  # @param [Float] x Horizontal scale factor
205
219
  # @param [Float] y Vertical scale factor
206
220
  # @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)
221
+ def scale(x, y, children: WITHCHILDREN)
208
222
  # HINT: overload it for custom actions...
209
223
  if x > 0 && y > 0
210
224
  scale_rectangle(x, y)
@@ -218,8 +232,7 @@ module Wx::SF
218
232
 
219
233
  # Handle action at handle drag beginning
220
234
  def do_begin_handle
221
- @prev_position = @relative_position.dup
222
- @prev_size = @rect_size.dup
235
+ # noop
223
236
  end
224
237
 
225
238
  # Scale the rectangle size for this shape.
@@ -270,8 +283,8 @@ module Wx::SF
270
283
  def draw_normal(dc)
271
284
  # HINT: overload it for custom actions...
272
285
 
273
- dc.with_pen(@border) do
274
- dc.with_brush(@fill) do
286
+ dc.with_pen(border) do
287
+ dc.with_brush(fill) do
275
288
  dc.draw_rectangle(get_absolute_position.to_point, @rect_size.to_size)
276
289
  end
277
290
  end
@@ -283,8 +296,8 @@ module Wx::SF
283
296
  def draw_hover(dc)
284
297
  # HINT: overload it for custom actions...
285
298
 
286
- dc.with_pen(Wx::Pen.new(@hover_color, 1)) do
287
- dc.with_brush(@fill) do
299
+ dc.with_pen(Wx::Pen.new(hover_colour, 1)) do
300
+ dc.with_brush(fill) do
288
301
  dc.draw_rectangle(get_absolute_position.to_point, @rect_size.to_size)
289
302
  end
290
303
  end
@@ -297,8 +310,8 @@ module Wx::SF
297
310
  def draw_highlighted(dc)
298
311
  # HINT: overload it for custom actions...
299
312
 
300
- dc.with_pen(Wx::Pen.new(@hover_color, 2)) do
301
- dc.with_brush(@fill) do
313
+ dc.with_pen(Wx::Pen.new(hover_colour, 2)) do
314
+ dc.with_brush(fill) do
302
315
  dc.draw_rectangle(get_absolute_position.to_point, @rect_size.to_size)
303
316
  end
304
317
  end
@@ -309,7 +322,7 @@ module Wx::SF
309
322
  def draw_shadow(dc)
310
323
  # HINT: overload it for custom actions...
311
324
 
312
- if @fill.style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
325
+ if fill.style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
313
326
  dc.with_pen(Wx::TRANSPARENT_PEN) do
314
327
  dc.with_brush(get_parent_canvas.get_shadow_fill) do
315
328
  dc.draw_rectangle((get_absolute_position + get_parent_canvas.get_shadow_offset).to_point, @rect_size.to_size)
@@ -325,6 +338,7 @@ module Wx::SF
325
338
  # HINT: overload it for custom actions...
326
339
 
327
340
  @rect_size.x += handle.get_delta.x
341
+ @rect_size.x = 1.0 if @rect_size.x < 1.0
328
342
  end
329
343
 
330
344
  # Event handler called during dragging of the left shape handle.
@@ -334,7 +348,11 @@ module Wx::SF
334
348
  # HINT: overload it for custom actions...
335
349
 
336
350
  dx = handle.get_delta.x.to_f
337
-
351
+
352
+ if (@rect_size.x - dx) < 1.0
353
+ dx = @rect_size.x - 1.0
354
+ end
355
+
338
356
  # update position of children
339
357
  unless has_style?(STYLE::LOCK_CHILDREN)
340
358
  @child_shapes.each do |child|
@@ -353,7 +371,11 @@ module Wx::SF
353
371
  # HINT: overload it for custom actions...
354
372
 
355
373
  dy = handle.get_delta.y.to_f
356
-
374
+
375
+ if (@rect_size.y - dy) < 1.0
376
+ dy = @rect_size.y - 1.0
377
+ end
378
+
357
379
  # update position of children
358
380
  unless has_style?(STYLE::LOCK_CHILDREN)
359
381
  @child_shapes.each do |child|
@@ -372,7 +394,27 @@ module Wx::SF
372
394
  # HINT: overload it for custom actions...
373
395
 
374
396
  @rect_size.y += handle.get_delta.y
397
+ @rect_size.y = 1.0 if @rect_size.y < 1.0
398
+ end
399
+
400
+ def serialize_rect_size(*val)
401
+ @rect_size = val.first unless val.empty?
402
+ @rect_size
375
403
  end
404
+ private :serialize_rect_size
405
+
406
+ def serialize_rect_fill(*val)
407
+ @fill = val.first unless val.empty?
408
+ @fill
409
+ end
410
+ private :serialize_rect_fill
411
+
412
+ def serialize_rect_border(*val)
413
+ @border = val.first unless val.empty?
414
+ @border
415
+ end
416
+ private :serialize_rect_border
417
+
376
418
  end
377
419
 
378
420
  end
@@ -13,14 +13,12 @@ module Wx::SF
13
13
 
14
14
  property :max_radius
15
15
 
16
- # @overload initialize()
17
- # default constructor
18
- # @overload initialize(src, trg, path, manager)
19
- # @param [Wx::SF::Serializable::ID] src ID of the source shape
20
- # @param [Wx::SF::Serializable::ID] trg ID of the target shape
21
- # @param [Array<Wx::RealPoint>] path List of the line control points (can be empty)
22
- # @param [Diagram] diagram containing diagram
23
- def initialize(*args)
16
+ # Constructor
17
+ # @param [Shape] src source shape
18
+ # @param [Shape] trg target shape
19
+ # @param [Array<Wx::RealPoint>] path List of the line control points (can be empty)
20
+ # @param [Diagram] diagram containing diagram
21
+ def initialize(src = nil, trg = nil, path: nil, diagram: nil)
24
22
  super
25
23
  @max_radius = MAX_RADIUS
26
24
  end