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.
- checksums.yaml +7 -0
- data/.yardopts +12 -0
- data/CREDITS.md +18 -0
- data/INSTALL.md +39 -0
- data/LICENSE +21 -0
- data/README.md +118 -0
- data/assets/screenshot.png +0 -0
- data/bin/wx-shapes +9 -0
- data/lib/wx/shapes/arrow_base.rb +86 -0
- data/lib/wx/shapes/arrows/circle_arrow.rb +39 -0
- data/lib/wx/shapes/arrows/diamond_arrow.rb +33 -0
- data/lib/wx/shapes/arrows/open_arrow.rb +56 -0
- data/lib/wx/shapes/arrows/solid_arrow.rb +69 -0
- data/lib/wx/shapes/art/shape_canvas/page.xpm +73 -0
- data/lib/wx/shapes/auto_layout.rb +358 -0
- data/lib/wx/shapes/base.rb +33 -0
- data/lib/wx/shapes/canvas_history.rb +84 -0
- data/lib/wx/shapes/connection_point.rb +238 -0
- data/lib/wx/shapes/core.rb +19 -0
- data/lib/wx/shapes/diagram.rb +659 -0
- data/lib/wx/shapes/events.rb +389 -0
- data/lib/wx/shapes/printout.rb +136 -0
- data/lib/wx/shapes/serializable.rb +440 -0
- data/lib/wx/shapes/serialize/core.rb +40 -0
- data/lib/wx/shapes/serialize/id.rb +82 -0
- data/lib/wx/shapes/serialize/wx.rb +104 -0
- data/lib/wx/shapes/serializer/json.rb +258 -0
- data/lib/wx/shapes/serializer/yaml.rb +125 -0
- data/lib/wx/shapes/shape.rb +2129 -0
- data/lib/wx/shapes/shape_canvas.rb +3285 -0
- data/lib/wx/shapes/shape_data_object.rb +43 -0
- data/lib/wx/shapes/shape_handle.rb +287 -0
- data/lib/wx/shapes/shape_list.rb +161 -0
- data/lib/wx/shapes/shapes/bitmap_shape.rb +257 -0
- data/lib/wx/shapes/shapes/circle_shape.rb +136 -0
- data/lib/wx/shapes/shapes/control_shape.rb +483 -0
- data/lib/wx/shapes/shapes/curve_shape.rb +231 -0
- data/lib/wx/shapes/shapes/diamond_shape.rb +62 -0
- data/lib/wx/shapes/shapes/edit_text_shape.rb +317 -0
- data/lib/wx/shapes/shapes/ellipse_shape.rb +106 -0
- data/lib/wx/shapes/shapes/flex_grid_shape.rb +78 -0
- data/lib/wx/shapes/shapes/grid_shape.rb +404 -0
- data/lib/wx/shapes/shapes/line_shape.rb +907 -0
- data/lib/wx/shapes/shapes/multi_sel_rect.rb +214 -0
- data/lib/wx/shapes/shapes/ortho_shape.rb +357 -0
- data/lib/wx/shapes/shapes/polygon_shape.rb +294 -0
- data/lib/wx/shapes/shapes/rect_shape.rb +378 -0
- data/lib/wx/shapes/shapes/round_ortho_shape.rb +131 -0
- data/lib/wx/shapes/shapes/round_rect_shape.rb +142 -0
- data/lib/wx/shapes/shapes/square_shape.rb +119 -0
- data/lib/wx/shapes/shapes/text_shape.rb +324 -0
- data/lib/wx/shapes/thumbnail.rb +234 -0
- data/lib/wx/shapes/version.rb +12 -0
- data/lib/wx/shapes/wx.rb +29 -0
- data/lib/wx/shapes.rb +18 -0
- data/lib/wx/wx-shapes/base.rb +87 -0
- data/lib/wx/wx-shapes/cmd/sampler.rb +58 -0
- data/lib/wx/wx-shapes/cmd/test.rb +27 -0
- data/rakelib/yard/templates/default/fulldoc/html/css/wxruby3.css +7 -0
- data/rakelib/yard/templates/default/layout/html/setup.rb +5 -0
- data/rakelib/yard/yard/relative_markdown_links/version.rb +8 -0
- data/rakelib/yard/yard/relative_markdown_links.rb +39 -0
- data/rakelib/yard/yard-custom-templates.rb +2 -0
- data/rakelib/yard/yard-relative_markdown_links.rb +4 -0
- data/samples/demo/art/AlignBottom.xpm +35 -0
- data/samples/demo/art/AlignCenter.xpm +35 -0
- data/samples/demo/art/AlignLeft.xpm +35 -0
- data/samples/demo/art/AlignMiddle.xpm +35 -0
- data/samples/demo/art/AlignRight.xpm +35 -0
- data/samples/demo/art/AlignTop.xpm +35 -0
- data/samples/demo/art/Bitmap.xpm +25 -0
- data/samples/demo/art/Circle.xpm +22 -0
- data/samples/demo/art/Curve.xpm +21 -0
- data/samples/demo/art/Diamond.xpm +22 -0
- data/samples/demo/art/EditText.xpm +21 -0
- data/samples/demo/art/Ellipse.xpm +22 -0
- data/samples/demo/art/FixedRect.xpm +22 -0
- data/samples/demo/art/FlexGrid.xpm +22 -0
- data/samples/demo/art/GC.xpm +23 -0
- data/samples/demo/art/Grid.xpm +22 -0
- data/samples/demo/art/Line.xpm +21 -0
- data/samples/demo/art/NoSource.xpm +69 -0
- data/samples/demo/art/OrthoLine.xpm +21 -0
- data/samples/demo/art/Rect.xpm +22 -0
- data/samples/demo/art/RoundOrthoLine.xpm +21 -0
- data/samples/demo/art/RoundRect.xpm +22 -0
- data/samples/demo/art/Shadow.xpm +23 -0
- data/samples/demo/art/StandAloneLine.xpm +22 -0
- data/samples/demo/art/Text.xpm +21 -0
- data/samples/demo/art/Tool.xpm +23 -0
- data/samples/demo/art/sample.xpm +251 -0
- data/samples/demo/demo.rb +658 -0
- data/samples/demo/frame_canvas.rb +422 -0
- data/samples/demo/images/motyl.bmp +0 -0
- data/samples/demo/images/motyl2.bmp +0 -0
- data/samples/sample1/art/sample.xpm +251 -0
- data/samples/sample1/sample.rb +263 -0
- data/samples/sample2/art/sample.xpm +251 -0
- data/samples/sample2/sample.rb +133 -0
- data/samples/sample2/sample_canvas.rb +35 -0
- data/samples/sample2/sample_shape.rb +108 -0
- data/samples/sample3/art/sample.xpm +251 -0
- data/samples/sample3/sample.rb +281 -0
- data/samples/sample4/art/sample.xpm +251 -0
- data/samples/sample4/sample.rb +180 -0
- data/tests/art/motyl.bmp +0 -0
- data/tests/lib/wxapp_runner.rb +64 -0
- data/tests/serializer_tests.rb +521 -0
- data/tests/test_grid_shapes.rb +42 -0
- data/tests/test_serialize.rb +7 -0
- data/tests/test_serialize_yaml.rb +17 -0
- 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
|