wxruby3-shapes 0.9.0.pre.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +12 -0
  3. data/CREDITS.md +18 -0
  4. data/INSTALL.md +39 -0
  5. data/LICENSE +21 -0
  6. data/README.md +118 -0
  7. data/assets/screenshot.png +0 -0
  8. data/bin/wx-shapes +9 -0
  9. data/lib/wx/shapes/arrow_base.rb +86 -0
  10. data/lib/wx/shapes/arrows/circle_arrow.rb +39 -0
  11. data/lib/wx/shapes/arrows/diamond_arrow.rb +33 -0
  12. data/lib/wx/shapes/arrows/open_arrow.rb +56 -0
  13. data/lib/wx/shapes/arrows/solid_arrow.rb +69 -0
  14. data/lib/wx/shapes/art/shape_canvas/page.xpm +73 -0
  15. data/lib/wx/shapes/auto_layout.rb +358 -0
  16. data/lib/wx/shapes/base.rb +33 -0
  17. data/lib/wx/shapes/canvas_history.rb +84 -0
  18. data/lib/wx/shapes/connection_point.rb +238 -0
  19. data/lib/wx/shapes/core.rb +19 -0
  20. data/lib/wx/shapes/diagram.rb +659 -0
  21. data/lib/wx/shapes/events.rb +389 -0
  22. data/lib/wx/shapes/printout.rb +136 -0
  23. data/lib/wx/shapes/serializable.rb +440 -0
  24. data/lib/wx/shapes/serialize/core.rb +40 -0
  25. data/lib/wx/shapes/serialize/id.rb +82 -0
  26. data/lib/wx/shapes/serialize/wx.rb +104 -0
  27. data/lib/wx/shapes/serializer/json.rb +258 -0
  28. data/lib/wx/shapes/serializer/yaml.rb +125 -0
  29. data/lib/wx/shapes/shape.rb +2129 -0
  30. data/lib/wx/shapes/shape_canvas.rb +3285 -0
  31. data/lib/wx/shapes/shape_data_object.rb +43 -0
  32. data/lib/wx/shapes/shape_handle.rb +287 -0
  33. data/lib/wx/shapes/shape_list.rb +161 -0
  34. data/lib/wx/shapes/shapes/bitmap_shape.rb +257 -0
  35. data/lib/wx/shapes/shapes/circle_shape.rb +136 -0
  36. data/lib/wx/shapes/shapes/control_shape.rb +483 -0
  37. data/lib/wx/shapes/shapes/curve_shape.rb +231 -0
  38. data/lib/wx/shapes/shapes/diamond_shape.rb +62 -0
  39. data/lib/wx/shapes/shapes/edit_text_shape.rb +317 -0
  40. data/lib/wx/shapes/shapes/ellipse_shape.rb +106 -0
  41. data/lib/wx/shapes/shapes/flex_grid_shape.rb +78 -0
  42. data/lib/wx/shapes/shapes/grid_shape.rb +404 -0
  43. data/lib/wx/shapes/shapes/line_shape.rb +907 -0
  44. data/lib/wx/shapes/shapes/multi_sel_rect.rb +214 -0
  45. data/lib/wx/shapes/shapes/ortho_shape.rb +357 -0
  46. data/lib/wx/shapes/shapes/polygon_shape.rb +294 -0
  47. data/lib/wx/shapes/shapes/rect_shape.rb +378 -0
  48. data/lib/wx/shapes/shapes/round_ortho_shape.rb +131 -0
  49. data/lib/wx/shapes/shapes/round_rect_shape.rb +142 -0
  50. data/lib/wx/shapes/shapes/square_shape.rb +119 -0
  51. data/lib/wx/shapes/shapes/text_shape.rb +324 -0
  52. data/lib/wx/shapes/thumbnail.rb +234 -0
  53. data/lib/wx/shapes/version.rb +12 -0
  54. data/lib/wx/shapes/wx.rb +29 -0
  55. data/lib/wx/shapes.rb +18 -0
  56. data/lib/wx/wx-shapes/base.rb +87 -0
  57. data/lib/wx/wx-shapes/cmd/sampler.rb +58 -0
  58. data/lib/wx/wx-shapes/cmd/test.rb +27 -0
  59. data/rakelib/yard/templates/default/fulldoc/html/css/wxruby3.css +7 -0
  60. data/rakelib/yard/templates/default/layout/html/setup.rb +5 -0
  61. data/rakelib/yard/yard/relative_markdown_links/version.rb +8 -0
  62. data/rakelib/yard/yard/relative_markdown_links.rb +39 -0
  63. data/rakelib/yard/yard-custom-templates.rb +2 -0
  64. data/rakelib/yard/yard-relative_markdown_links.rb +4 -0
  65. data/samples/demo/art/AlignBottom.xpm +35 -0
  66. data/samples/demo/art/AlignCenter.xpm +35 -0
  67. data/samples/demo/art/AlignLeft.xpm +35 -0
  68. data/samples/demo/art/AlignMiddle.xpm +35 -0
  69. data/samples/demo/art/AlignRight.xpm +35 -0
  70. data/samples/demo/art/AlignTop.xpm +35 -0
  71. data/samples/demo/art/Bitmap.xpm +25 -0
  72. data/samples/demo/art/Circle.xpm +22 -0
  73. data/samples/demo/art/Curve.xpm +21 -0
  74. data/samples/demo/art/Diamond.xpm +22 -0
  75. data/samples/demo/art/EditText.xpm +21 -0
  76. data/samples/demo/art/Ellipse.xpm +22 -0
  77. data/samples/demo/art/FixedRect.xpm +22 -0
  78. data/samples/demo/art/FlexGrid.xpm +22 -0
  79. data/samples/demo/art/GC.xpm +23 -0
  80. data/samples/demo/art/Grid.xpm +22 -0
  81. data/samples/demo/art/Line.xpm +21 -0
  82. data/samples/demo/art/NoSource.xpm +69 -0
  83. data/samples/demo/art/OrthoLine.xpm +21 -0
  84. data/samples/demo/art/Rect.xpm +22 -0
  85. data/samples/demo/art/RoundOrthoLine.xpm +21 -0
  86. data/samples/demo/art/RoundRect.xpm +22 -0
  87. data/samples/demo/art/Shadow.xpm +23 -0
  88. data/samples/demo/art/StandAloneLine.xpm +22 -0
  89. data/samples/demo/art/Text.xpm +21 -0
  90. data/samples/demo/art/Tool.xpm +23 -0
  91. data/samples/demo/art/sample.xpm +251 -0
  92. data/samples/demo/demo.rb +658 -0
  93. data/samples/demo/frame_canvas.rb +422 -0
  94. data/samples/demo/images/motyl.bmp +0 -0
  95. data/samples/demo/images/motyl2.bmp +0 -0
  96. data/samples/sample1/art/sample.xpm +251 -0
  97. data/samples/sample1/sample.rb +263 -0
  98. data/samples/sample2/art/sample.xpm +251 -0
  99. data/samples/sample2/sample.rb +133 -0
  100. data/samples/sample2/sample_canvas.rb +35 -0
  101. data/samples/sample2/sample_shape.rb +108 -0
  102. data/samples/sample3/art/sample.xpm +251 -0
  103. data/samples/sample3/sample.rb +281 -0
  104. data/samples/sample4/art/sample.xpm +251 -0
  105. data/samples/sample4/sample.rb +180 -0
  106. data/tests/art/motyl.bmp +0 -0
  107. data/tests/lib/wxapp_runner.rb +64 -0
  108. data/tests/serializer_tests.rb +521 -0
  109. data/tests/test_grid_shapes.rb +42 -0
  110. data/tests/test_serialize.rb +7 -0
  111. data/tests/test_serialize_yaml.rb +17 -0
  112. metadata +242 -0
@@ -0,0 +1,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