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,214 @@
1
+ # Wx::SF::MultiSelRect - multi-sel rect 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 MultiSelRect < RectShape
9
+
10
+ # Default constructor.
11
+ def initialize
12
+ super
13
+ set_border(Wx::Pen.new(Wx::Colour.new(100, 100, 100), 1, Wx::PenStyle::PENSTYLE_DOT))
14
+ set_fill(Wx::TRANSPARENT_BRUSH)
15
+ end
16
+
17
+ # Event handler called at the beginning of the shape handle dragging process.
18
+ # The function can be overridden if necessary.
19
+ # @param [Shape::Handle] handle Reference to dragged shape handle
20
+ def on_begin_handle(handle)
21
+ # inform all selected shapes about begin of the handle dragging
22
+ if get_parent_canvas
23
+ lst_shapes = get_parent_canvas.get_selected_shapes
24
+ lst_shapes.each { |shape| shape.on_begin_handle(handle) }
25
+ end
26
+ end
27
+
28
+ # Event handler called during dragging of the shape handle.
29
+ # The function can be overridden if necessary.
30
+ #
31
+ # The function is called by the framework (by the shape canvas).
32
+ # @param [Shape::Handle] handle Reference to dragged handle
33
+ def on_handle(handle)
34
+ super
35
+ get_parent_canvas.invalidate_visible_rect
36
+ end
37
+
38
+ # Event handler called at the end of the shape handle dragging process.
39
+ # The function can be overridden if necessary.
40
+ # @param [Shape::Handle] handle Reference to dragged shape handle
41
+ def on_end_handle(handle)
42
+ # inform all selected shapes about end of the handle dragging
43
+ if get_parent_canvas
44
+ lst_shapes = get_parent_canvas.get_selected_shapes
45
+ lst_shapes.each { |shape| shape.on_end_handle(handle) }
46
+ end
47
+ end
48
+
49
+ protected
50
+
51
+ # Event handler called during dragging of the right shape handle.
52
+ # The function can be overridden if necessary.
53
+ # @param [Shape::Handle] handle Reference to dragged shape handle
54
+ def on_right_handle(handle)
55
+ if get_parent_canvas && !any_width_exceeded(handle.get_delta)
56
+ sx = (get_rect_size.x - 2*DEFAULT_ME_OFFSET + handle.get_delta.x).to_f/(get_rect_size.x - 2*DEFAULT_ME_OFFSET)
57
+
58
+ lst_selection = get_parent_canvas.get_selected_shapes
59
+
60
+ lst_selection.each do |shape|
61
+ # scale main parent shape
62
+ if !shape.is_a?(LineShape)
63
+ shape.scale(sx, 1, WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
64
+ if shape.has_style?(STYLE::POSITION_CHANGE)
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
+ shape.move_by(dx, 0)
67
+ end
68
+ shape.fit_to_children unless shape.has_style?(STYLE::NO_FIT_TO_CHILDREN)
69
+ else
70
+ if shape.contains_style(STYLE::POSITION_CHANGE)
71
+ shape.get_control_points.each do |cpt|
72
+ dx = (cpt.x - (get_absolute_position.x + DEFAULT_ME_OFFSET))/(get_rect_size.x - 2*DEFAULT_ME_OFFSET)*handle.get_delta.x
73
+ cpt.x += dx
74
+ cpt.x = cpt.x.floor
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ # Event handler called during dragging of the left shape handle.
83
+ # The function can be overridden if necessary.
84
+ # @param [Shape::Handle] handle Reference to dragged shape handle
85
+ def on_left_handle(handle)
86
+ if get_parent_canvas && !any_width_exceeded(Wx::Point.new(-handle.get_delta.x, 0))
87
+ sx = (get_rect_size.x - 2*DEFAULT_ME_OFFSET - handle.get_delta.x).to_f/(get_rect_size.x - 2*DEFAULT_ME_OFFSET)
88
+
89
+ lst_selection = get_parent_canvas.get_selected_shapes
90
+
91
+ lst_selection.each do |shape|
92
+ if !shape.is_a?(LineShape)
93
+ if shape.has_style?(STYLE:POSITION_CHANGE)
94
+ if shape.get_parent_shape
95
+ shape.set_relative_position(shape.get_relative_position.x*sx, shape.get_relative_position.y)
96
+ else
97
+ dx = handle.get_delta.x - (shape.get_absolute_position.x - (get_absolute_position.x + DEFAULT_ME_OFFSET))/(get_rect_size.x - 2*DEFAULT_ME_OFFSET)*handle.get_delta.x
98
+ shape.move_by(dx, 0)
99
+ end
100
+ end
101
+ shape.scale(sx, 1, WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
102
+ shape.fit_to_children unless shape.has_style?(STYLE::NO_FIT_TO_CHILDREN)
103
+ else
104
+ if shape.has_style?(STYLE::POSITION_CHANGE)
105
+ shape.get_control_points.each do |cpt|
106
+ dx = handle.get_delta.x - (cpt.x - (get_absolute_position.x + DEFAULT_ME_OFFSET))/(get_rect_size.x - 2*DEFAULT_ME_OFFSET)*handle.get_delta.x
107
+ cpt.x += dx
108
+ cpt.x = cpt.x.floor
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ # Event handler called during dragging of the top shape handle.
117
+ # The function can be overridden if necessary.
118
+ # @param [Shape::Handle] handle Reference to dragged shape handle
119
+ def on_top_handle(handle)
120
+ if get_parent_canvas && !any_height_exceeded(Wx::Point.new(0, -handle.get_delta.y))
121
+ sy = (get_rect_size.y - 2*DEFAULT_ME_OFFSET - handle.get_delta.y).to_f/(get_rect_size.y - 2*DEFAULT_ME_OFFSET)
122
+
123
+ lst_selection = get_parent_canvas.get_selected_shapes
124
+
125
+ lst_selection.each do |shape|
126
+ if !shape.is_a?(LineShape)
127
+ if shape.has_style?(STYLE::POSITION_CHANGE)
128
+ if shape.get_parent_shape
129
+ shape.set_relative_position(shape.get_relative_position.x, shape.get_relative_position.y*sy)
130
+ else
131
+ dy = handle.get_delta.y - (shape.get_absolute_position.y - (get_absolute_position.y + DEFAULT_ME_OFFSET))/(get_rect_size.y - 2*DEFAULT_ME_OFFSET)*handle.get_delta.y
132
+ shape.move_by(0, dy)
133
+ end
134
+ end
135
+ shape.scale(1, sy, WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
136
+ shape.fit_to_children unless shape.has_style?(STYLE::NO_FIT_TO_CHILDREN)
137
+ else
138
+ if shape.has_style?(STYLE::POSITION_CHANGE)
139
+ shape.get_control_points.each do |cpt|
140
+ dy = handle.get_delta.y - (cpt.y - (get_absolute_position.y + DEFAULT_ME_OFFSET))/(get_rect_size.y - 2*DEFAULT_ME_OFFSET)*handle.get_delta.y
141
+ cpt.y += dy
142
+ cpt.y = cpt.y.floor
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ # Event handler called during dragging of the bottom shape handle.
151
+ # The function can be overridden if necessary.
152
+ # @param handle Reference to dragged shape handle
153
+ def on_bottom_handle(handle)
154
+ if get_parent_canvas && !any_height_exceeded(handle.get_delta)
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
+
157
+ lst_selection = get_parent_canvas.get_selected_shapes
158
+
159
+ lst_selection.each do |shape|
160
+ if !shape.is_a?(LineShape)
161
+ shape.scale(1, sy, WITHCHILDREN) if shape.has_style?(STYLE::SIZE_CHANGE)
162
+ if shape.has_style?(STYLE::POSITION_CHANGE)
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
+ shape.move_by(0, dy)
165
+ end
166
+ shape.fit_to_children unless shape.has_style?(STYLE::NO_FIT_TO_CHILDREN)
167
+ else
168
+ if shape.has_style?(STYLE::POSITION_CHANGE)
169
+ shape.get_control_points.each do |cpt|
170
+ dy = (cpt.y - (get_absolute_position.y + DEFAULT_ME_OFFSET))/(get_rect_size.y - 2*DEFAULT_ME_OFFSET)*handle.get_delta.y
171
+ cpt.y += dy
172
+ cpt.y = cpt.y.floor
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+
180
+ private
181
+
182
+ # Auxiliary function.
183
+ # @param [Wx::Point] delta
184
+ # @return [Boolean]
185
+ def any_width_exceeded(delta)
186
+ if get_parent_canvas
187
+ lst_selection = get_parent_canvas.get_selected_shapes
188
+ # determine whether any shape in the selection exceeds its bounds
189
+ lst_selection.each do |shape|
190
+ return true if !shape.is_a?(LineShape) && (shape.get_bounding_box.width + delta.x) <= 1
191
+ end
192
+ return false
193
+ end
194
+ true
195
+ end
196
+
197
+ # Auxiliary function.
198
+ # @param [Wx::Point] delta
199
+ # @return [Boolean]
200
+ def any_height_exceeded(delta)
201
+ if get_parent_canvas
202
+ lst_selection = get_parent_canvas.get_selected_shapes
203
+ # determine whether any shape in the selection exceeds its bounds
204
+ lst_selection.each do |shape|
205
+ return true if !shape.is_a?(LineShape) && (shape.get_bounding_box.height + delta.y) <= 1
206
+ end
207
+ return false
208
+ end
209
+ true
210
+ end
211
+
212
+ end
213
+
214
+ end
@@ -0,0 +1,357 @@
1
+ # Wx::SF::OrthoLineShape - orthogonal line shape class
2
+ # Copyright (c) M.J.N. Corino, The Netherlands
3
+
4
+ require 'wx/shapes/shapes/line_shape'
5
+
6
+ module Wx::SF
7
+
8
+ # Orthogonal line shape. The class extends LineShape class and allows
9
+ # user to create connection line orthogonal to base axis.
10
+ class OrthoLineShape < LineShape
11
+
12
+ SEGMENTCPS = ::Struct.new(:src, :trg)
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)
22
+ super
23
+ end
24
+
25
+ protected
26
+
27
+ # Internal function used for drawing of completed line shape.
28
+ # @param [Wx::DC] dc Reference of the device context where the shape will be drawn to
29
+ def draw_complete_line(dc)
30
+ return unless @diagram
31
+
32
+ src = trg = cp_src = cp_trg = nil
33
+
34
+ shape = @diagram.find_shape(@src_shape_id)
35
+ if shape
36
+ cp_src = shape.get_nearest_connection_point(get_mod_src_point)
37
+ end
38
+ shape = @diagram.find_shape(@trg_shape_id)
39
+ if shape
40
+ cp_trg = shape.get_nearest_connection_point(get_mod_trg_point)
41
+ end
42
+
43
+ case @mode
44
+ when LINEMODE::READY
45
+ # draw basic line parts
46
+ line_segment_count.times do |i|
47
+ src, trg = get_line_segment(i)
48
+ draw_line_segment(dc, src, trg, get_used_connection_points(cp_src, cp_trg, i))
49
+ 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
+
62
+ when LINEMODE::UNDERCONSTRUCTION
63
+ # draw basic line parts
64
+ @lst_points.size.times do |i|
65
+ src, trg = get_line_segment(i)
66
+ draw_line_segment(dc, src, trg, get_used_connection_points(cp_src, cp_trg, i))
67
+ end
68
+
69
+ # draw unfinished line segment if any (for interactive line creation)
70
+ dc.with_pen(Wx::Pen.new(Wx::BLACK, 1, Wx::PenStyle::PENSTYLE_DOT)) do
71
+ if @lst_points.size>1
72
+ draw_line_segment(dc, trg, @unfinished_point.to_real, get_used_connection_points(cp_src, cp_trg, @lst_points.size))
73
+ else
74
+ src_shape = @diagram.find_shape(@src_shape_id)
75
+ if src_shape
76
+ if src_shape.get_connection_points.empty?
77
+ draw_line_segment(dc,
78
+ src_shape.get_border_point(src_shape.get_center, @unfinished_point.to_real),
79
+ @unfinished_point.to_real,
80
+ get_used_connection_points(cp_src, cp_trg, 0))
81
+ else
82
+ draw_line_segment(dc,
83
+ get_mod_src_point,
84
+ @unfinished_point.to_real,
85
+ get_used_connection_points(cp_src, cp_trg, 0))
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ when LINEMODE::SRCCHANGE
92
+ # draw basic line parts
93
+ @lst_points.size.times do |i|
94
+ src, trg = get_line_segment(i+1)
95
+ draw_line_segment(dc, src, trg, get_used_connection_points(cp_src, cp_trg, i+1))
96
+ end
97
+ # draw linesegment being updated
98
+ src, trg = get_line_segment(0)
99
+ dc.with_pen(Wx::Pen.new(Wx::BLACK, 1, Wx::PenStyle::PENSTYLE_DOT)) do
100
+ draw_line_segment(dc,
101
+ @unfinished_point.to_real,
102
+ trg,
103
+ get_used_connection_points(cp_src, cp_trg, 0))
104
+ end
105
+
106
+ when LINEMODE::TRGCHANGE
107
+ # draw basic line parts
108
+ if !@lst_points.empty?
109
+ @lst_points.size.times do |i|
110
+ src, trg = get_line_segment(i)
111
+ draw_line_segment(dc, src, trg, get_used_connection_points(cp_src, cp_trg, i))
112
+ end
113
+ else
114
+ trg = get_src_point
115
+ end
116
+ # draw linesegment being updated
117
+ dc.with_pen(Wx::Pen.new(Wx::BLACK, 1, Wx::PenStyle::PENSTYLE_DOT)) do
118
+ draw_line_segment(dc,
119
+ trg,
120
+ @unfinished_point.to_real,
121
+ get_used_connection_points(cp_src, cp_trg, @lst_points.size))
122
+ end
123
+
124
+ end
125
+ end
126
+
127
+ # Get index of the line segment intersecting the given point.
128
+ # @param [Wx::Point] pos Examined point
129
+ # @return Zero-based index of line segment located under the given point
130
+ def get_hit_linesegment(pos)
131
+ return -1 unless get_bounding_box.inflate!(5, 5).contains?(pos)
132
+
133
+ cp_src = nil
134
+ cp_trg = nil
135
+
136
+ shape = @diagram.find_shape(@src_shape_id)
137
+ if shape
138
+ cp_src = shape.get_nearest_connection_point(get_mod_src_point)
139
+ end
140
+ shape = @diagram.find_shape(@trg_shape_id)
141
+ if shape
142
+ cp_trg = shape.get_nearest_connection_point(get_mod_trg_point)
143
+ end
144
+
145
+ # Get all polyline segments
146
+ line_segment_count.times do |i|
147
+ pt_src, pt_trg = get_line_segment(i)
148
+
149
+ # test first subsegment
150
+ pt_s_src, pt_s_trg = get_first_subsegment( pt_src, pt_trg, get_used_connection_points(cp_src, cp_trg, i))
151
+ rct_bb = Wx::Rect.new(pt_s_src.to_point, pt_s_trg.to_point)
152
+ rct_bb.inflate!(5)
153
+
154
+ return i if rct_bb.contains?(pos)
155
+
156
+ # test middle subsegment
157
+ pt_s_src, pt_s_trg = get_middle_subsegment(pt_src, pt_trg, get_used_connection_points(cp_src, cp_trg, i))
158
+ rct_bb = Wx::Rect.new(pt_s_src.to_point, pt_s_trg.to_point)
159
+ rct_bb.inflate!(5)
160
+
161
+ return i if rct_bb.contains?(pos)
162
+
163
+ # test last subsegment
164
+ pt_s_src, pt_s_trg = get_last_subsegment( pt_src, pt_trg, get_used_connection_points(cp_src, cp_trg, i))
165
+ rct_bb = Wx::Rect.new(pt_s_src.to_point, pt_s_trg.to_point)
166
+ rct_bb.inflate!(5)
167
+
168
+ return i if rct_bb.contains?(pos)
169
+ end
170
+
171
+ -1
172
+ end
173
+
174
+ # Draw one orthogonal line segment.
175
+ # @param [Wx::DC] dc Device context
176
+ # @param [Wx::RealPoint] src Starting point of the ortho line segment
177
+ # @param [Wx::RealPoint] trg Ending point of the ortho line segment
178
+ # @param [SEGMENTCPS] cps Connection points used by the line segment
179
+ def draw_line_segment(dc, src, trg, cps)
180
+ direction = 0.0
181
+ src_pt = src.to_point
182
+ trg_pt = trg.to_point
183
+
184
+ if (trg.x == src.x) || (trg.y == src.y)
185
+ dc.draw_line(src_pt, trg_pt)
186
+ return
187
+ else
188
+ direction = get_segment_direction(src, trg, cps)
189
+ end
190
+
191
+ if is_two_segment(cps)
192
+ if direction < 1.0
193
+ dc.draw_line(src_pt.x, src_pt.y, trg_pt.x, src_pt.y)
194
+ dc.draw_line(trg_pt.x, src_pt.y, trg_pt.x, trg_pt.y)
195
+ else
196
+ dc.draw_line(src_pt.x, src_pt.y, src_pt.x, trg_pt.y)
197
+ dc.draw_line(src_pt.x, trg_pt.y, trg_pt.x, trg_pt.y)
198
+ end
199
+ else
200
+ pt_center = Wx::Point.new(((src.x + trg.x)/2).to_i, ((src.y + trg.y)/2).to_i)
201
+ if direction < 1.0
202
+ dc.draw_line(src_pt.x, src_pt.y, pt_center.x, src_pt.y)
203
+ dc.draw_line(pt_center.x, src_pt.y, pt_center.x, trg_pt.y)
204
+ dc.draw_line(pt_center.x, trg_pt.y, trg_pt.x, trg_pt.y)
205
+ else
206
+ dc.draw_line(src_pt.x, src_pt.y, src_pt.x, pt_center.y)
207
+ dc.draw_line(src_pt.x, pt_center.y, trg_pt.x, pt_center.y)
208
+ dc.draw_line(trg_pt.x, pt_center.y, trg_pt.x, trg_pt.y)
209
+ end
210
+ end
211
+ end
212
+
213
+ # Get first part of orthogonal line segment.
214
+ # @param [Wx::RealPoint] src Starting point of the ortho line segment
215
+ # @param [Wx::RealPoint] trg Ending point of the ortho line segment
216
+ # @param [SEGMENTCPS] cps Connection points used by the line segment
217
+ # @return [Array(Wx::RealPoint, Wx::RealPoint)] starting and ending point of the first part of ortho line segment
218
+ def get_first_subsegment(src, trg, cps)
219
+ direction = get_segment_direction(src, trg, cps)
220
+
221
+ if is_two_segment(cps)
222
+ if direction < 1.0
223
+ subsrc = src
224
+ subtrg = Wx::RealPoint.new(trg.x, src.y)
225
+ else
226
+ subsrc = src
227
+ subtrg = Wx::RealPoint.new(src.x, trg.y)
228
+ end
229
+ else
230
+ pt_center = Wx::RealPoint.new((src.x + trg.x)/2, (src.y + trg.y)/2)
231
+ if direction < 1.0
232
+ subsrc = src
233
+ subtrg = Wx::RealPoint.new(pt_center.x, src.y)
234
+ else
235
+ subsrc = src
236
+ subtrg = Wx::RealPoint.new(src.x, pt_center.y)
237
+ end
238
+ end
239
+ [subsrc, subtrg]
240
+ end
241
+
242
+ # Get middle part of orthogonal line segment.
243
+ # @param [Wx::RealPoint] src Starting point of the ortho line segment
244
+ # @param [Wx::RealPoint] trg Ending point of the ortho line segment
245
+ # @param [SEGMENTCPS] cps Connection points used by the line segment
246
+ # @return [Array(Wx::RealPoint, Wx::RealPoint)] starting and ending point of the second part of ortho line segment
247
+ def get_middle_subsegment(src, trg, cps)
248
+ direction = get_segment_direction(src, trg, cps)
249
+
250
+ if is_two_segment(cps)
251
+ if direction < 1.0
252
+ subsrc = src
253
+ subtrg = Wx::RealPoint.new(trg.x, src.y)
254
+ else
255
+ subsrc = src
256
+ subtrg = Wx::RealPoint.new(src.x, trg.y)
257
+ end
258
+ else
259
+ pt_center = Wx::RealPoint.new((src.x + trg.x)/2, (src.y + trg.y)/2)
260
+ if direction < 1.0
261
+ subsrc = Wx::RealPoint.new(pt_center.x, src.y)
262
+ subtrg = Wx::RealPoint.new(pt_center.x, trg.y)
263
+ else
264
+ subsrc = Wx::RealPoint.new(src.x, pt_center.y)
265
+ subtrg = Wx::RealPoint.new(trg.x, pt_center.y)
266
+ end
267
+ end
268
+ [subsrc, subtrg]
269
+ end
270
+
271
+ # Get last part of orthogonal line segment.
272
+ # @param [Wx::RealPoint] src Starting point of the ortho line segment
273
+ # @param [Wx::RealPoint] trg Ending point of the ortho line segment
274
+ # @param [SEGMENTCPS] cps Connection points used by the line segment
275
+ # @return [Array(Wx::RealPoint, Wx::RealPoint)] starting and ending point of the third part of ortho line segment
276
+ def get_last_subsegment(src, trg, cps)
277
+ direction = get_segment_direction(src, trg, cps)
278
+
279
+ if is_two_segment(cps)
280
+ if direction < 1.0
281
+ subsrc = Wx::RealPoint.new(trg.x, src.y)
282
+ else
283
+ subsrc = Wx::RealPoint.new(src.x, trg.y)
284
+ end
285
+ else
286
+ pt_center = Wx::RealPoint.new((src.x + trg.x)/2, (src.y + trg.y)/2)
287
+ if direction < 1.0
288
+ subsrc = Wx::RealPoint.new(pt_center.x, trg.y)
289
+ else
290
+ subsrc = Wx::RealPoint.new(trg.x, pt_center.y)
291
+ end
292
+ end
293
+ [subsrc, trg]
294
+ end
295
+
296
+ # Get direction of the line segment.
297
+ # @param [Wx::RealPoint] src Starting point of the ortho line segment
298
+ # @param [Wx::RealPoint] trg Ending point of the ortho line segment
299
+ # @param [SEGMENTCPS] cps Connection points used by the line segment
300
+ # @return [Float] Direction number
301
+ def get_segment_direction(src, trg, cps)
302
+ direction = 0
303
+
304
+ if trg.x == src.x
305
+ direction = 1
306
+ else
307
+ direction = (trg.y - src.y).abs / (trg.x - src.x).abs
308
+
309
+ cp = nil
310
+ if cps.src && !cps.trg
311
+ cp = cps.src
312
+ elsif !cps.src && cps.trg
313
+ cp = cps.trg
314
+ elsif cps.src && cps.trg
315
+ cp = cps.src
316
+ end
317
+
318
+ if cp
319
+ case cp.get_ortho_direction
320
+ when ConnectionPoint::CPORTHODIR::VERTICAL
321
+ direction = 1.0
322
+ when ConnectionPoint::CPORTHODIR::HORIZONTAL
323
+ direction = 0.0
324
+ end
325
+ end
326
+ end
327
+
328
+ direction
329
+ end
330
+
331
+ # Determine which available connection points are used by given line segment.
332
+ # @param [Wx::SF::ConnectionPoint] src Potential source connection point (can be nil)
333
+ # @param [Wx::SF::ConnectionPoint] trg Potential target connection point (can be nil)
334
+ # @param [Integer] i Index of the line segment
335
+ # @return [SEGMENTCPS] Structure containing used connection points
336
+ def get_used_connection_points(src, trg, i)
337
+ if @lst_points.empty?
338
+ SEGMENTCPS.new(src, trg)
339
+ elsif i == 0
340
+ SEGMENTCPS.new(src, nil)
341
+ elsif i == @lst_points.size
342
+ SEGMENTCPS.new(nil, trg)
343
+ else
344
+ SEGMENTCPS.new(nil, nil)
345
+ end
346
+ end
347
+
348
+ # Determine whether a line using give connection point should be drawn as two-segmented.
349
+ # @param [SEGMENTCPS] cps Used connection points
350
+ # @return [Boolean] true if the line should be just two-segmented
351
+ def is_two_segment(cps)
352
+ cps.src && cps.trg && (cps.src.get_ortho_direction != cps.trg.get_ortho_direction)
353
+ end
354
+
355
+ end
356
+
357
+ end