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,62 @@
1
+ # Wx::SF::DiamondShape - Diamond shape class
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ require 'wx/shapes/shapes/polygon_shape'
5
+
6
+ module Wx::SF
7
+
8
+ class DiamondShape < PolygonShape
9
+
10
+ class << self
11
+ def diamond
12
+ @diamond ||= [Wx::RealPoint.new(0,25), Wx::RealPoint.new(50,0), Wx::RealPoint.new(100, 25), Wx::RealPoint.new(50, 50)]
13
+ end
14
+ end
15
+
16
+ # do not serialize because the vertices are assigned fixed in ctor
17
+ excludes :vertices
18
+
19
+ # @overload initialize()
20
+ # Default constructor.
21
+ # @overload initialize(pos, size, diagram)
22
+ # User constructor.
23
+ # @param [Wx::RealPoint] pos Initial position
24
+ # @param [Wx::SF::Diagram] diagram parent diagram
25
+ def initialize(*args)
26
+ if args.empty?
27
+ super
28
+ set_vertices(DiamondShape.diamond)
29
+ else
30
+ super(DiamondShape.diamond, *args)
31
+ end
32
+ end
33
+
34
+ # Test whether the given point is inside the shape. The function
35
+ # can be overridden if necessary.
36
+ # @param [Wx::Point] pos Examined point
37
+ # @return [Boolean] true if the point is inside the shape area, otherwise false
38
+ def contains?(pos)
39
+ bb_rct = get_bounding_box
40
+ return false unless bb_rct.contains?(pos)
41
+
42
+ center = get_center
43
+ k = (bb_rct.height/2).to_f/(bb_rct.width/2).to_f
44
+
45
+ if pos.x <= center.x
46
+ # test left-top quadrant
47
+ return true if (pos.y <= center.y) && (pos.y >= (center.y - (pos.x - bb_rct.left)*k))
48
+ # test left-bottom quadrant
49
+ return true if (pos.y >= center.y) && (pos.y <= (center.y + (pos.x - bb_rct.left)*k))
50
+ else
51
+ # test right-top quadrant
52
+ return true if (pos.y <= center.y) && (pos.y >= (bb_rct.top + (pos.x - center.x)*k))
53
+ # test left-bottom quadrant
54
+ return true if (pos.y >= center.y) && (pos.y <= (bb_rct.bottom - (pos.x - center.x)*k))
55
+ end
56
+
57
+ false
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,317 @@
1
+ # Wx::SF::EditTextShape - edit text shape class
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ require 'wx/shapes/shapes/text_shape'
5
+
6
+ module Wx::SF
7
+
8
+ CANCEL_TEXT_CHANGES = false
9
+ APPLY_TEXT_CHANGES = true
10
+
11
+ class ContentCtrl < Wx::TextCtrl
12
+
13
+ # Constructor.
14
+ # @param [Wx::Window] parent Pointer to the parent window
15
+ # @param [Integer] id ID of the text control window
16
+ # @param [Wx::SF::EditTextShape] parent_shape Pointer to the parent editable text shape
17
+ # @param [String] content Initial content of the text control
18
+ # @param [Wx::Point] pos Initial position
19
+ # @param [Wx::Size] size Initial size
20
+ # @param [Integer] style Window style
21
+ def initialize(parent, id, parent_shape, content, pos, size, style)
22
+ super(parent, id, content, pos, size, Wx::TE_PROCESS_ENTER | Wx::TE_PROCESS_TAB | Wx::NO_BORDER | style)
23
+ @parent = parent
24
+ @parent_shape = parent_shape
25
+ @prev_content = content
26
+
27
+ evt_kill_focus :on_kill_focus
28
+ evt_key_down :on_key_down
29
+
30
+ set_insertion_point_end
31
+ if @parent_shape
32
+ # update the font size in accordance to the canvas scale
33
+ font = @parent_shape.get_font
34
+ font.set_point_size((font.get_point_size * @parent_shape.get_parent_canvas.get_scale).to_i)
35
+
36
+ set_font(font)
37
+ set_background_colour(Wx::Colour.new(200, 200, 200))
38
+ set_focus
39
+ end
40
+ end
41
+
42
+ # Finish the editing process/
43
+ # @param [Boolean] apply If true then changes made in edited text will be applied on text shape, otherwise it will be canceled
44
+ def quit(apply = APPLY_TEXT_CHANGES)
45
+ self.hide
46
+
47
+ if @parent_shape
48
+ @parent_shape.send(:set_text_ctrl, nil)
49
+ @parent_shape.set_style(@parent_shape.send(:get_current_state))
50
+
51
+ # save canvas state if the textctrl content has changed...
52
+ if apply && @prev_content != get_value
53
+ @parent_shape.set_text(get_value)
54
+ @prev_content = get_value
55
+
56
+ # inform parent shape canvas about text change...
57
+ @parent_shape.get_parent_canvas.on_text_change(@parent_shape)
58
+ @parent_shape.get_parent_canvas.save_canvas_state
59
+ end
60
+
61
+ @parent_shape.update
62
+ @parent_shape.get_parent_canvas.refresh
63
+ end
64
+
65
+ self.destroy
66
+ end
67
+
68
+ protected
69
+
70
+ # Event handler called if the text control lost the focus.
71
+ # @param [Wx::FocusEvent] _event Reference to the event class instance
72
+ def on_kill_focus(_event)
73
+ # noop
74
+ end
75
+
76
+ # Event handler called if the key was pressed in the text control.
77
+ # @param [Wx::KeyEvent] event Reference to the event class instance
78
+ def on_key_down(event)
79
+ case event.get_key_code
80
+ when Wx::K_ESCAPE
81
+ quit(CANCEL_TEXT_CHANGES)
82
+ when Wx::K_TAB
83
+ quit(APPLY_TEXT_CHANGES)
84
+ when Wx::K_RETURN
85
+ # enter new line if SHIFT key was pressed together with the ENTER key
86
+ if Wx::get_key_state(Wx::K_SHIFT)
87
+ event.skip
88
+ else
89
+ quit(APPLY_TEXT_CHANGES)
90
+ end
91
+ else
92
+ event.skip
93
+ end
94
+ end
95
+
96
+ end
97
+
98
+ # Auxiliary class providing necessary functionality needed for dialog-based
99
+ # modification of a content of the text shape.
100
+ # @see EditTextShape
101
+ class DetachedContentCtrl < Wx::Dialog
102
+
103
+ # Constructor.
104
+ # @param [Wx::Window] parent Pointer to the parent window
105
+ # @param [Integer] id ID of the text control window
106
+ # @param [String] title Dialog's title
107
+ # @param [Wx::Point] pos Initial position
108
+ # @param [Wx::Size] size Initial size
109
+ # @param [Integer] style Window style
110
+ def initialize(parent, id = Wx::ID_ANY, title = 'Edit content',
111
+ pos = Wx::DEFAULT_POSITION, size = Wx::DEFAULT_SIZE,
112
+ style = Wx::DEFAULT_DIALOG_STYLE|Wx::RESIZE_BORDER)
113
+ set_size_hints(Wx::Size.new(-1,-1), Wx::DEFAULT_SIZE)
114
+
115
+ main_sizer = Wx::VBoxSizer.new
116
+
117
+ @text = Wx::TextCtrl.new(self, Wx::ID_ANY, '', Wx::DEFAULT_POSITION, [350,100], Wx::TE_MULTILINE)
118
+ @text.set_min_size([350,100])
119
+
120
+ main_sizer.add(@text, 1, Wx::ALL|Wx::EXPAND, 5)
121
+
122
+ button_sizer = Wx::StdDialogButtonSizer.new
123
+ button_sizer_ok = Wx::Button.new(self, Wx::ID_OK)
124
+ button_sizer.add_button(button_sizer_ok)
125
+ button_sizer_cancel = Wx::Button.new(self, Wx::ID_CANCEL)
126
+ button_sizer.add_button(button_sizer_cancel)
127
+ button_sizer.realize
128
+ main_sizer.add(button_sizer, 0, Wx::ALIGN_RIGHT|Wx::BOTTOM|Wx::RIGHT, 5)
129
+
130
+ set_sizer(main_sizer)
131
+ layout
132
+ main_sizer.fit(self)
133
+
134
+ centre(Wx::BOTH)
135
+ end
136
+
137
+ # Set content of dialog's text edit control.
138
+ # @param [String] txt Text content
139
+ def set_content(txt)
140
+ @text.set_value(txt)
141
+ end
142
+
143
+ # Get content of dialog's text edit control.
144
+ # @return [String] Edited text
145
+ def get_content
146
+ @text.get_value
147
+ end
148
+
149
+ end
150
+
151
+ # Class encapsulating the editable text shape. It extends the basic text shape.
152
+ # @see Wx::SF::TextShape
153
+ class EditTextShape < TextShape
154
+
155
+ class EDITTYPE < Wx::Enum
156
+ INPLACE = self.new(0)
157
+ DIALOG = self.new(1)
158
+ DISABLED = self.new(1)
159
+ end
160
+
161
+ # Default values
162
+ module DEFAULT
163
+ # Default value of EditTextShape @force_multiline data member
164
+ FORCE_MULTILINE = false
165
+ # Default value of EditTextShape @edit_type data member
166
+ EDIT_TYPE = EDITTYPE::INPLACE
167
+ end
168
+
169
+ property :force_multiline, :edit_type
170
+
171
+ # @overload initialize()
172
+ # Default constructor.
173
+ # @overload initialize(pos, txt, diagram)
174
+ # User constructor.
175
+ # @param [Wx::RealPoint] pos Initial position
176
+ # @param [String] txt Initial content
177
+ # @param [Wx::SF::Diagram] diagram parent diagram
178
+ def initialize(*args)
179
+ super
180
+ @text_ctrl = nil
181
+ @force_multiline = DEFAULT::FORCE_MULTILINE
182
+ @edit_type = DEFAULT::EDIT_TYPE
183
+ @current_state = 0
184
+ end
185
+
186
+ attr_reader :force_multiline
187
+
188
+ # Set way how the text shape's content can be edited.
189
+ # @param [EDITTYPE] type Edit control type
190
+ # @see EDITTYPE
191
+ def set_edit_type(type)
192
+ @edit_type = type
193
+ end
194
+ alias :edit_type= :set_edit_type
195
+
196
+ # Get current type of text shape's edit control.
197
+ # @return [EDITTYPE] Type of edit control
198
+ # @see EDITTYPE
199
+ def get_edit_type
200
+ @edit_type
201
+ end
202
+ alias :edit_type :get_edit_type
203
+
204
+ # Get assigned text control allowing user to change the
205
+ # shape's content directly in the canvas.
206
+ # @return [ContentCtrl] instance of wxSFContentCtrl class
207
+ def get_text_ctrl
208
+ @text_ctrl
209
+ end
210
+ alias :text_ctrl :get_text_ctrl
211
+
212
+ def set_text_ctrl(txt_ctrl)
213
+ @text_ctrl = txt_ctrl
214
+ end
215
+ private :set_text_ctrl
216
+
217
+ # Switch the shape to a label editing mode.
218
+ def edit_label
219
+ if get_parent_canvas
220
+ shp_pos = get_absolute_position
221
+ scale = get_parent_canvas.get_scale
222
+ dx, dy = get_parent_canvas.calc_unscrolled_position(0, 0)
223
+
224
+ case @edit_type
225
+ when EDITTYPE::INPLACE
226
+ shp_bb = get_bounding_box
227
+ style = 0
228
+ style = Wx::TE_MULTILINE if @force_multiline || @text.index("\n")
229
+
230
+ # set minimal control size
231
+ shp_bb.set_width(50) if @text == '' || (style == Wx::TE_MULTILINE && shp_bb.width < 50)
232
+
233
+ @current_state = get_style
234
+ remove_style(STYLE::SIZE_CHANGE)
235
+
236
+ @text_ctrl = ContentCtrl.new(get_parent_canvas, Wx::ID_ANY, self, @text,
237
+ [((shp_pos.x * scale) - dx).to_i, ((shp_pos.y * scale) - dy).to_i],
238
+ [(shp_bb.width * scale).to_i, (shp_bb.height * scale).to_i], style)
239
+
240
+ when EDITTYPE::DIALOG
241
+ prev_text = get_text
242
+
243
+ DetachedContentCtrl(get_parent_canvas) do |text_dlg|
244
+ text_dlg.set_content(prev_text)
245
+
246
+ if text_dlg.show_modal == Wx::ID_OK
247
+ if text_dlg.get_content != prev_text
248
+ set_text(text_dlg.get_content)
249
+
250
+ get_parent_canvas.on_text_change(self)
251
+ get_parent_canvas.save_canvas_state
252
+
253
+ update
254
+ get_parent_canvas.refresh(false)
255
+ end
256
+ end
257
+ end
258
+ end
259
+ end
260
+ end
261
+
262
+ # Force the edit text control to be multiline
263
+ # @param [Boolean] multiline If true then the associated text control will be always multiline
264
+ def set_force_multiline(multiline)
265
+ @force_multiline = multiline
266
+ end
267
+ alias :force_multiline= :set_force_multiline
268
+
269
+ # Event handler called when the shape was double-clicked.
270
+ # The function can be overridden if necessary.
271
+ # @param [Wx::Point] pos Mouse position.
272
+ def on_left_double_click(pos)
273
+ # HINT: override it if necessary...
274
+ edit_label
275
+ end
276
+
277
+ # Event handler called when any key is pressed (in the shape canvas).
278
+ # The function can be overridden if necessary.
279
+ #
280
+ # The function is called by the framework (by the shape canvas).
281
+ # @param [Integer] key The key code
282
+ # @return [Boolean] The function must return true if the default event routine should be called
283
+ # as well, otherwise false
284
+ # @see Shape#on_key
285
+ def on_key(key)
286
+ # HINT: override it if necessary...
287
+ if key == Wx::K_F2
288
+ edit_label if active? && visible?
289
+ end
290
+ super
291
+ end
292
+
293
+ protected
294
+
295
+ # Event handler called by ShapeCanvas to request,report canvas changes.
296
+ # @param [ShapeCanvas::CHANGE] change change type indicator
297
+ # @param [Array] _args any additional arguments
298
+ # @return [Boolean,nil]
299
+ def _on_canvas(change, *_args)
300
+ if change == ShapeCanvas::CHANGE::FOCUS
301
+ text_ctrl = get_text_ctrl
302
+ text_ctrl.quit(APPLY_TEXT_CHANGES) if text_ctrl
303
+ end
304
+ super
305
+ end
306
+
307
+ private
308
+
309
+ # Return cached state
310
+ # @return [Integer]
311
+ def get_current_state
312
+ @current_state
313
+ end
314
+
315
+ end
316
+
317
+ end
@@ -0,0 +1,106 @@
1
+ # Wx::SF::EllipseShape - ellipse shape class
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ module Wx::SF
5
+
6
+ # Class encapsulating the ellipse shape. It extends the basic rectangular shape.
7
+ class EllipseShape < RectShape
8
+
9
+ # @overload initialize()
10
+ # Default constructor.
11
+ # @overload initialize(pos, size, diagram)
12
+ # User constructor.
13
+ # @param [Wx::RealPoint] pos Initial position
14
+ # @param [Wx::RealPoint] size Initial size
15
+ # @param [Wx::SF::Diagram] diagram parent diagram
16
+ def initialize(*args)
17
+ super
18
+ end
19
+
20
+ # Test whether the given point is inside the shape. The function
21
+ # can be overridden if necessary.
22
+ # @param [Wx::Point] pos Examined point
23
+ # @return [Boolean] true if the point is inside the shape area, otherwise false
24
+ def contains?(pos)
25
+ a = get_rect_size.x/2
26
+ b = get_rect_size.y/2
27
+ apos = get_absolute_position
28
+
29
+ m = apos.x + a
30
+ n = apos.y + b
31
+
32
+ pos = pos.to_point
33
+ (((pos.x - m)*(pos.x - m))/(a*a) + ((pos.y - n)*(pos.y - n))/(b*b)) < 1
34
+ end
35
+
36
+ # Get intersection point of the shape border and a line leading from
37
+ # 'start' point to 'end_pt' point. The function can be overridden if necessary.
38
+ # @param [Wx::RealPoint] start Starting point of the virtual intersection line
39
+ # @param [Wx::RealPoint] end_pt Ending point of the virtual intersection line
40
+ # @return [Wx::RealPoint] Intersection point
41
+ def get_border_point(start, end_pt)
42
+ start = start.to_real_point; end_pt.to_real_point
43
+ dist = start.distance_to(end_pt)
44
+ center = get_absolute_position + [@rect_size.x/2, @rect_size.y/2]
45
+
46
+ if dist != 0.0
47
+ src_dx = @rect_size.x/2*(end_pt.x-start.x)/dist - (start.x-center.x)
48
+ src_dy = @rect_size.y/2*(end_pt.y-start.y)/dist - (start.y-center.y)
49
+
50
+ Wx::RealPoint.new(start.x + src_dx, start.y + src_dy)
51
+ else
52
+ center
53
+ end
54
+ end
55
+
56
+ protected
57
+
58
+ # Draw the shape in the normal way. The function can be overridden if necessary.
59
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
60
+ def draw_normal(dc)
61
+ dc.with_pen(@border) do
62
+ dc.with_brush(@fill) do
63
+ dc.draw_ellipse(get_absolute_position.to_point, @rect_size.to_size)
64
+ end
65
+ end
66
+ end
67
+
68
+ # Draw the shape in the hover mode (the mouse cursor is above the shape).
69
+ # The function can be overridden if necessary.
70
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
71
+ def draw_hover(dc)
72
+ dc.with_pen(Wx::Pen.new(@hover_color, 1)) do
73
+ dc.with_brush(@fill) do
74
+ dc.draw_ellipse(get_absolute_position.to_point, @rect_size.to_size)
75
+ end
76
+ end
77
+ end
78
+
79
+ # Draw the shape in the highlighted mode (another shape is dragged over this
80
+ # shape and this shape will accept the dragged one if it will be dropped on it).
81
+ # The function can be overridden if necessary.
82
+ # @param [Wx::DC] dc Reference to device context where the shape will be drawn to
83
+ def draw_highlighted(dc)
84
+ dc.with_pen(Wx::Pen.new(@hover_color, 2)) do
85
+ dc.with_brush(@fill) do
86
+ dc.draw_ellipse(get_absolute_position.to_point, @rect_size.to_size)
87
+ end
88
+ end
89
+ end
90
+
91
+ # Draw shadow under the shape. The function can be overridden if necessary.
92
+ # @param [Wx::DC] dc Reference to device context where the shadow will be drawn to
93
+ def draw_shadow(dc)
94
+ if @fill.style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
95
+ dc.with_pen(Wx::TRANSPARENT_PEN) do
96
+ dc.with_brush(get_parent_canvas.get_shadow_fill) do
97
+ dc.draw_ellipse((get_absolute_position + get_parent_canvas.get_shadow_offset).to_point,
98
+ @rect_size.to_size)
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,78 @@
1
+ # Wx::SF::FlexGridShape - flexible grid shape class
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ require 'wx/shapes/shapes/grid_shape'
5
+
6
+ module Wx::SF
7
+
8
+ # Class encapsulates a rectangular shape derived from {GridShape} class which acts as a flexible grid-based
9
+ # container able to manage other assigned child shapes (it can control their position). The managed
10
+ # shapes are aligned into defined grid with a behaviour similar to classic Wx::FlexGridSizer class.
11
+ class FlexGridShape < GridShape
12
+
13
+
14
+ # @overload initialize()
15
+ # Default constructor.
16
+ # @overload initialize(pos, size, rows, cols, cell_space, diagram)
17
+ # User constructor.
18
+ # @param [Wx::RealPoint] pos Initial position
19
+ # @param [Wx::RealPoint] size Initial size
20
+ # @param [Integer] cols Number of grid rows
21
+ # @param [Integer] rows Number of grid columns
22
+ # @param [Integer] cell_space Additional space between managed shapes
23
+ # @param [Wx::SF::Diagram] diagram parent diagram
24
+ def initialize(*args)
25
+ super
26
+ end
27
+
28
+ # Do layout of assigned child shapes
29
+ def do_children_layout
30
+ return if @cols == 0 || @rows == 0
31
+
32
+ # initialize size arrays
33
+ row_sizes = ::Array.new(@rows, 0)
34
+ col_sizes = ::Array.new(@cols, 0)
35
+
36
+ # prepare a storage for processed shapes pointers
37
+ grid_shapes = ::Array.new(@cells.size)
38
+
39
+ # get maximum size of all managed (child) shapes per row and column
40
+ @cells.each_with_index do |id, i|
41
+ if id
42
+ col = (i % @cols)
43
+ row = (i / @cols)
44
+
45
+ grid_shapes[i] = shape = @child_shapes[id]
46
+ curr_rect = shape.get_bounding_box
47
+
48
+ # update maximum rows and columns sizes
49
+ col_sizes[col] = curr_rect.width if (shape.get_h_align != HALIGN::EXPAND) && (curr_rect.width > col_sizes[col])
50
+ row_sizes[row] = curr_rect.height if (shape.get_v_align != VALIGN::EXPAND) && (curr_rect.height > row_sizes[row])
51
+ end
52
+ end
53
+
54
+ total_x = total_y = 0
55
+
56
+ # put managed shapes to appropriate positions
57
+ grid_shapes.each_with_index do |shape, i|
58
+ if shape
59
+ col = (i % @cols)
60
+ row = (i / @cols)
61
+ if col == 0
62
+ total_x = 0
63
+ total_y += row_sizes[row-1] if row > 0
64
+ else
65
+ total_x += col_sizes[col-1]
66
+ end
67
+
68
+ fit_shape_to_rect(shape,
69
+ Wx::Rect.new(total_x + (col+1)*@cell_space,
70
+ total_y + (row+1)*@cell_space,
71
+ col_sizes[col], row_sizes[row]))
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ end