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,907 @@
|
|
|
1
|
+
# Wx::SF::LineShape - line shape class
|
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
|
3
|
+
|
|
4
|
+
require 'wx/shapes/arrow_base'
|
|
5
|
+
|
|
6
|
+
module Wx::SF
|
|
7
|
+
|
|
8
|
+
class LineShape < Shape
|
|
9
|
+
|
|
10
|
+
# Default values
|
|
11
|
+
module DEFAULT
|
|
12
|
+
# Default value of undefined ID.
|
|
13
|
+
UNKNOWNID = nil
|
|
14
|
+
# Default value of LineShape @pen data member.
|
|
15
|
+
PEN = Wx::Pen.new(Wx::BLACK) if Wx::App.is_main_loop_running
|
|
16
|
+
Wx.add_delayed_constant(self, :PEN) { Wx::Pen.new(Wx::BLACK) }
|
|
17
|
+
# Default value of LineShape @dock_point data member.
|
|
18
|
+
DOCKPOINT = 0
|
|
19
|
+
# Default value of LineShape @dock_point data member (start line point).
|
|
20
|
+
DOCKPOINT_START = -1
|
|
21
|
+
# Default value of LineShape @dock_point data member (end line point).
|
|
22
|
+
DOCKPOINT_END = -2
|
|
23
|
+
# Default value of LineShape @dock_point data member (middle dock point).
|
|
24
|
+
DOCKPOINT_CENTER = 2**64
|
|
25
|
+
# Default value of LineShape @src_offset and LineShape @trg_offset data members.
|
|
26
|
+
OFFSET = Wx::RealPoint.new(-1, -1)
|
|
27
|
+
# Default value of LineShape @src_point and LineShape @trg_point data members.
|
|
28
|
+
POINT = Wx::RealPoint.new(0, 0)
|
|
29
|
+
# Default value of LineShape @stand_alone data member.
|
|
30
|
+
STANDALONE = false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# The modes in which the line shape can stay.
|
|
34
|
+
class LINEMODE < Wx::Enum
|
|
35
|
+
READY = self.new(0)
|
|
36
|
+
UNDERCONSTRUCTION = self.new(1)
|
|
37
|
+
SRCCHANGE = self.new(2)
|
|
38
|
+
TRGCHANGE = self.new(3)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
property :src_shape_id, :trg_shape_id
|
|
42
|
+
property src_point: :serialize_src_point, trg_point: :serialize_trg_point
|
|
43
|
+
property :stand_alone, :src_arrow, :trg_arrow, :src_offset, :trg_offset,
|
|
44
|
+
:dock_point, :line_pen, :control_points
|
|
45
|
+
|
|
46
|
+
# @overload initialize()
|
|
47
|
+
# default constructor
|
|
48
|
+
# @overload initialize(src, trg, path, manager)
|
|
49
|
+
# @param [Wx::SF::Serializable::ID] src ID of the source shape
|
|
50
|
+
# @param [Wx::SF::Serializable::ID] trg ID of the target shape
|
|
51
|
+
# @param [Array<Wx::RealPoint>] path List of the line control points (can be empty)
|
|
52
|
+
# @param [Diagram] diagram containing diagram
|
|
53
|
+
# @overload initialize(src, trg, path, manager)
|
|
54
|
+
# @param [Wx::RealPoint] src starting line point
|
|
55
|
+
# @param [Wx::RealPoint] trg end line point
|
|
56
|
+
# @param [Array<Wx::RealPoint>,nil] path List of the line control points (can be empty or nil)
|
|
57
|
+
# @param [Diagram] diagram containing diagram
|
|
58
|
+
def initialize(*args)
|
|
59
|
+
if args.empty?
|
|
60
|
+
super()
|
|
61
|
+
@src_shape_id = @trg_shape_id = DEFAULT::UNKNOWNID
|
|
62
|
+
@src_point = DEFAULT::POINT.dup
|
|
63
|
+
@trg_point = DEFAULT::POINT.dup
|
|
64
|
+
@stand_alone = DEFAULT::STANDALONE
|
|
65
|
+
@lst_points = []
|
|
66
|
+
else
|
|
67
|
+
src, trg, path, diagram = args
|
|
68
|
+
super(Shape::DEFAULT::POSITION.dup, diagram)
|
|
69
|
+
if src.respond_to?(:to_real_point) && trg.respond_to?(:to_real_point)
|
|
70
|
+
@src_point = src.to_real_point
|
|
71
|
+
@trg_point = trg.to_real_point
|
|
72
|
+
@src_shape_id = @trg_shape_id = DEFAULT::UNKNOWNID
|
|
73
|
+
@stand_alone = true
|
|
74
|
+
elsif src.is_a?(Wx::SF::Serializable::ID) && trg.is_a?(Wx::SF::Serializable::ID)
|
|
75
|
+
@src_point = DEFAULT::POINT.dup
|
|
76
|
+
@trg_point = DEFAULT::POINT.dup
|
|
77
|
+
@src_shape_id = src
|
|
78
|
+
@trg_shape_id = trg
|
|
79
|
+
@stand_alone = false
|
|
80
|
+
else
|
|
81
|
+
::Kernel.raise ArgumentError, "Invalid arguments #{args}"
|
|
82
|
+
end
|
|
83
|
+
path ||= []
|
|
84
|
+
@lst_points = path.select { |pt| pt.respond_to?(:to_real_point) }.collect { |pt| pt.to_real_point }
|
|
85
|
+
::Kernel.raise ArgumentError, "Invalid arguments #{args}" unless path.size == @lst_points.size
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
@src_arrow = nil
|
|
89
|
+
@trg_arrow = nil
|
|
90
|
+
|
|
91
|
+
@dock_point = DEFAULT::DOCKPOINT
|
|
92
|
+
@pen = DEFAULT::PEN
|
|
93
|
+
|
|
94
|
+
@src_offset = DEFAULT::OFFSET.dup
|
|
95
|
+
@trg_offset = DEFAULT::OFFSET.dup
|
|
96
|
+
|
|
97
|
+
@mode = LINEMODE::READY
|
|
98
|
+
@prev_position = Wx::RealPoint.new
|
|
99
|
+
@unfinished_point = Wx::Point.new
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Get source shape id.
|
|
103
|
+
# @return [Wx::SF::Serializable::ID]
|
|
104
|
+
def get_src_shape_id
|
|
105
|
+
@src_shape_id
|
|
106
|
+
end
|
|
107
|
+
alias :src_shape_id :get_src_shape_id
|
|
108
|
+
|
|
109
|
+
# Set source shape id.
|
|
110
|
+
# @param [Wx::SF::Serializable::ID] id
|
|
111
|
+
def set_src_shape_id(id)
|
|
112
|
+
@src_shape_id = id
|
|
113
|
+
end
|
|
114
|
+
alias :src_shape_id= :set_src_shape_id
|
|
115
|
+
|
|
116
|
+
# Get target shape id.
|
|
117
|
+
# @return [Wx::SF::Serializable::ID]
|
|
118
|
+
def get_trg_shape_id
|
|
119
|
+
@trg_shape_id
|
|
120
|
+
end
|
|
121
|
+
alias :trg_shape_id :get_trg_shape_id
|
|
122
|
+
|
|
123
|
+
# Set target shape id.
|
|
124
|
+
# @param [Wx::SF::Serializable::ID] id
|
|
125
|
+
def set_trg_shape_id(id)
|
|
126
|
+
@trg_shape_id = id
|
|
127
|
+
end
|
|
128
|
+
alias :trg_shape_id= :set_trg_shape_id
|
|
129
|
+
|
|
130
|
+
# Get source point.
|
|
131
|
+
# @return [Wx::RealPoint]
|
|
132
|
+
def get_src_point
|
|
133
|
+
unless @stand_alone
|
|
134
|
+
src_shape = @diagram.find_shape(@src_shape_id)
|
|
135
|
+
|
|
136
|
+
if src_shape && !@lst_points.empty?
|
|
137
|
+
if src_shape.get_connection_points.empty?
|
|
138
|
+
return src_shape.get_border_point(get_mod_src_point, @lst_points.first)
|
|
139
|
+
else
|
|
140
|
+
return get_mod_src_point
|
|
141
|
+
end
|
|
142
|
+
else
|
|
143
|
+
if @mode != LINEMODE::UNDERCONSTRUCTION
|
|
144
|
+
pt1, _ = get_direct_line
|
|
145
|
+
else
|
|
146
|
+
pt1 = get_mod_src_point
|
|
147
|
+
end
|
|
148
|
+
return pt1
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
return Wx::RealPoint.new
|
|
152
|
+
end
|
|
153
|
+
@src_point
|
|
154
|
+
end
|
|
155
|
+
alias :src_point :get_src_point
|
|
156
|
+
|
|
157
|
+
# Set source point.
|
|
158
|
+
# @param [Wx::RealPoint] pt
|
|
159
|
+
def set_src_point(pt)
|
|
160
|
+
@src_point = pt.to_real_point
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Get target point.
|
|
164
|
+
# @return [Wx::RealPoint]
|
|
165
|
+
def get_trg_point
|
|
166
|
+
unless @stand_alone
|
|
167
|
+
trg_shape = @diagram.find_shape(@trg_shape_id)
|
|
168
|
+
|
|
169
|
+
if trg_shape && !@lst_points.empty?
|
|
170
|
+
if trg_shape.get_connection_points.empty?
|
|
171
|
+
return trg_shape.get_border_point(get_mod_trg_point, @lst_points.last)
|
|
172
|
+
else
|
|
173
|
+
return get_mod_trg_point
|
|
174
|
+
end
|
|
175
|
+
else
|
|
176
|
+
if @mode != LINEMODE::UNDERCONSTRUCTION
|
|
177
|
+
_, pt2 = get_direct_line
|
|
178
|
+
else
|
|
179
|
+
pt2 = @unfinished_point.to_real
|
|
180
|
+
end
|
|
181
|
+
return pt2
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
return Wx::RealPoint.new
|
|
185
|
+
end
|
|
186
|
+
@trg_point
|
|
187
|
+
end
|
|
188
|
+
alias :trg_point :get_trg_point
|
|
189
|
+
|
|
190
|
+
# Set target point.
|
|
191
|
+
# @param [Wx::RealPoint] pt
|
|
192
|
+
def set_trg_point(pt)
|
|
193
|
+
@trg_point = pt.to_real_point
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Get source arrow.
|
|
197
|
+
# @return [Wx::SF::ArrowBase]
|
|
198
|
+
def get_src_arrow
|
|
199
|
+
@src_arrow
|
|
200
|
+
end
|
|
201
|
+
alias :src_arrow :get_src_arrow
|
|
202
|
+
|
|
203
|
+
# Set source arrow
|
|
204
|
+
# @overload set_src_arrow(arrow)
|
|
205
|
+
# @param [Wx::SF::ArrowBase] arrow
|
|
206
|
+
# @return [Wx::SF::ArrowBase,nil] the new source arrow object if invalid
|
|
207
|
+
# @overload set_src_arrow(arrow_klass)
|
|
208
|
+
# @param [Class] arrow_klass
|
|
209
|
+
# @return [Wx::SF::ArrowBase,nil] the new source arrow object if invalid
|
|
210
|
+
def set_src_arrow(arg)
|
|
211
|
+
if (arg.is_a?(::Class) && arg < ArrowBase) || arg.is_a?(ArrowBase)
|
|
212
|
+
@src_arrow = arg.is_a?(ArrowBase) ? arg : arg.new
|
|
213
|
+
@src_arrow.set_parent_shape(self)
|
|
214
|
+
end
|
|
215
|
+
nil
|
|
216
|
+
end
|
|
217
|
+
alias :src_arrow= :set_src_arrow
|
|
218
|
+
|
|
219
|
+
# Get target arrow.
|
|
220
|
+
# @return [Wx::SF::ArrowBase]
|
|
221
|
+
def get_trg_arrow
|
|
222
|
+
@trg_arrow
|
|
223
|
+
end
|
|
224
|
+
alias :trg_arrow :get_trg_arrow
|
|
225
|
+
|
|
226
|
+
# Set target arrow
|
|
227
|
+
# @overload set_trg_arrow(arrow)
|
|
228
|
+
# @param [Wx::SF::ArrowBase] arrow
|
|
229
|
+
# @return [Wx::SF::ArrowBase,nil] the new source arrow object if invalid
|
|
230
|
+
# @overload set_trg_arrow(arrow_klass)
|
|
231
|
+
# @param [Class] arrow_klass
|
|
232
|
+
# @return [Wx::SF::ArrowBase,nil] the new source arrow object if invalid
|
|
233
|
+
def set_trg_arrow(arg)
|
|
234
|
+
if (arg.is_a?(::Class) && arg < ArrowBase) || arg.is_a?(ArrowBase)
|
|
235
|
+
@trg_arrow = arg.is_a?(ArrowBase) ? arg : arg.new
|
|
236
|
+
@trg_arrow.set_parent_shape(self)
|
|
237
|
+
end
|
|
238
|
+
nil
|
|
239
|
+
end
|
|
240
|
+
alias :trg_arrow= :set_trg_arrow
|
|
241
|
+
|
|
242
|
+
# Get line type
|
|
243
|
+
# @return [Wx::Pen]
|
|
244
|
+
def get_line_pen
|
|
245
|
+
@pen
|
|
246
|
+
end
|
|
247
|
+
alias :line_pen :get_line_pen
|
|
248
|
+
|
|
249
|
+
# Set line type
|
|
250
|
+
# @param [Wx::Pen] pen line type
|
|
251
|
+
def set_line_pen(pen)
|
|
252
|
+
@pen = pen
|
|
253
|
+
end
|
|
254
|
+
alias :line_pen= :set_line_pen
|
|
255
|
+
|
|
256
|
+
# Set the line dock point. It is a zero based index of the line
|
|
257
|
+
# control point which will act as the shape position (value returned by Shape#get_relative_position function).
|
|
258
|
+
# @param [Integer] index Zero based index of the line control point
|
|
259
|
+
def set_dock_point(index)
|
|
260
|
+
@dock_point = index
|
|
261
|
+
end
|
|
262
|
+
alias :dock_point= :set_dock_point
|
|
263
|
+
|
|
264
|
+
# Get the line dock point. It is a zero based index of the line
|
|
265
|
+
# control point which will act as the shape position (value returned by Shape#get_relative_position function).
|
|
266
|
+
# @return [Integer] Zero based index of the line control point (-1 means UNDEFINED)
|
|
267
|
+
def get_dock_point
|
|
268
|
+
@dock_point
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# Returns true if stand alone line
|
|
272
|
+
# @return [Boolean]
|
|
273
|
+
def get_stand_alone
|
|
274
|
+
@stand_alone
|
|
275
|
+
end
|
|
276
|
+
alias :stand_alone? :get_stand_alone
|
|
277
|
+
|
|
278
|
+
# Set stand alone line mode
|
|
279
|
+
# @param [Boolean] f flag
|
|
280
|
+
def set_stand_alone(f = true)
|
|
281
|
+
@stand_alone = !!f
|
|
282
|
+
end
|
|
283
|
+
alias :stand_alone= :set_stand_alone
|
|
284
|
+
|
|
285
|
+
# Get starting and ending line points.
|
|
286
|
+
# @return [Array(Wx::RealPoint, Wx::RealPoint)] starting line point and ending line point
|
|
287
|
+
def get_direct_line
|
|
288
|
+
if @stand_alone
|
|
289
|
+
return [@src_point, @trg_point]
|
|
290
|
+
else
|
|
291
|
+
src_shape = get_diagram.find_shape(@src_shape_id)
|
|
292
|
+
trg_shape = get_diagram.find_shape(@trg_shape_id)
|
|
293
|
+
|
|
294
|
+
if src_shape && trg_shape
|
|
295
|
+
trg_center = get_mod_trg_point
|
|
296
|
+
src_center = get_mod_src_point
|
|
297
|
+
|
|
298
|
+
if src_shape.get_parent_shape == trg_shape || trg_shape.get_parent_shape == src_shape
|
|
299
|
+
trg_bb = trg_shape.get_bounding_box
|
|
300
|
+
src_bb = src_shape.get_bounding_box
|
|
301
|
+
|
|
302
|
+
if trg_bb.contains?(src_center.x.to_i, src_center.y.to_i)
|
|
303
|
+
if src_center.y > trg_center.y
|
|
304
|
+
src = Wx::RealPoint.new(src_center.x, src_bb.bottom.to_f)
|
|
305
|
+
trg = Wx::RealPoint.new(src_center.x, trg_bb.bottom.to_f)
|
|
306
|
+
else
|
|
307
|
+
src = Wx::RealPoint.new(src_center.x, src_bb.top.to_f)
|
|
308
|
+
trg = Wx::RealPoint.new(src_center.x, trg_bb.top.to_f)
|
|
309
|
+
end
|
|
310
|
+
return [src, trg]
|
|
311
|
+
elsif src_bb.contains?(trg_center.x.to_i, trg_center.y.to_i)
|
|
312
|
+
if trg_center.y > src_center.y
|
|
313
|
+
src = Wx::RealPoint.new(trg_center.x, src_bb.bottom.to_f)
|
|
314
|
+
trg = Wx::RealPoint.new(trg_center.x, trg_bb.bottom.to_f)
|
|
315
|
+
else
|
|
316
|
+
src = Wx::RealPoint.new(trg_center.x, src_bb.top.to_f)
|
|
317
|
+
trg = Wx::RealPoint.new(trg_center.x, trg_bb.top.to_f)
|
|
318
|
+
end
|
|
319
|
+
return [src, trg]
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
if src_shape.get_connection_points.empty?
|
|
324
|
+
src = src_shape.get_border_point(src_center, trg_center)
|
|
325
|
+
else
|
|
326
|
+
src = src_center
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
if trg_shape.get_connection_points.empty?
|
|
330
|
+
trg = trg_shape.get_border_point(trg_center, src_center)
|
|
331
|
+
else
|
|
332
|
+
trg = trg_center
|
|
333
|
+
end
|
|
334
|
+
return [src, trg]
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
nil # should not happen
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# Get a list of the line's control points (their positions).
|
|
341
|
+
# @return [Array<Wx::RealPoint>] List of control points' positions
|
|
342
|
+
def get_control_points
|
|
343
|
+
@lst_points
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
# Get a position of given line dock point.
|
|
347
|
+
# @param [Integer] dp Dock point
|
|
348
|
+
# @return [Wx::RealPoint] The dock point's position if exists, otherwise the line center
|
|
349
|
+
def get_dock_point_position(dp)
|
|
350
|
+
pts_cnt = @lst_points.size
|
|
351
|
+
|
|
352
|
+
if dp >= 0
|
|
353
|
+
if pts_cnt > dp
|
|
354
|
+
return @lst_points[dp]
|
|
355
|
+
elsif pts_cnt > 0
|
|
356
|
+
return @lst_points[pts_cnt/2]
|
|
357
|
+
end
|
|
358
|
+
elsif dp == -1 # start line point
|
|
359
|
+
return get_src_point
|
|
360
|
+
elsif dp == -2 # end line point
|
|
361
|
+
return get_trg_point
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
get_center
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# Initialize line's starting point with existing fixed connection point.
|
|
368
|
+
# @param [Wx::SF::ConnectionPoint] cp Pointer to connection point
|
|
369
|
+
def set_starting_connection_point(cp)
|
|
370
|
+
if cp && cp.get_parent_shape
|
|
371
|
+
pos_cp = cp.get_connection_point
|
|
372
|
+
rct_bb = cp.get_parent_shape.get_bounding_box
|
|
373
|
+
|
|
374
|
+
@src_offset.x = (pos_cp.x - rct_bb.left).to_f / rct_bb.width
|
|
375
|
+
@src_offset.y = (pos_cp.y - rct_bb.top).to_f / rct_bb.height
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# Initialize line's ending point with existing fixed connection point.
|
|
380
|
+
# @param [Wx::SF::ConnectionPoint] cp Pointer to connection point
|
|
381
|
+
def set_ending_connection_point(cp)
|
|
382
|
+
if cp && cp.get_parent_shape
|
|
383
|
+
pos_cp = cp.get_connection_point
|
|
384
|
+
rct_bb = cp.get_parent_shape.get_bounding_box
|
|
385
|
+
|
|
386
|
+
@trg_offset.x = (pos_cp.x - rct_bb.left).to_f / rct_bb.width
|
|
387
|
+
@trg_offset.y = (pos_cp.y - rct_bb.top).to_f / rct_bb.height
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
# Get number of line segments for this shape.
|
|
392
|
+
# @return [Integer] number of line segments
|
|
393
|
+
def get_line_segment_count
|
|
394
|
+
@lst_points.size+1
|
|
395
|
+
end
|
|
396
|
+
alias :line_segment_count :get_line_segment_count
|
|
397
|
+
alias :segment_count :get_line_segment_count
|
|
398
|
+
|
|
399
|
+
# Get starting and ending point of line segment defined by its index.
|
|
400
|
+
# @param [Integer] index Index of desired line segment
|
|
401
|
+
# @return [Array(Wx::RealPoint,Wx::RealPoint)] starting and ending point of line segment
|
|
402
|
+
def get_line_segment(index)
|
|
403
|
+
if @lst_points.empty?
|
|
404
|
+
return get_direct_line if index == 0
|
|
405
|
+
else
|
|
406
|
+
if index == 0
|
|
407
|
+
return [get_src_point, @lst_points.first.dup]
|
|
408
|
+
elsif index == @lst_points.size
|
|
409
|
+
return [@lst_points.last.dup, get_trg_point]
|
|
410
|
+
elsif index > 0 && index < @lst_points.size
|
|
411
|
+
return @lst_points[index-1, 2].collect {|p| p.dup}
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
[Wx::RealPoint.new, Wx::RealPoint.new]
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# Get line's bounding box. The function can be overridden if necessary.
|
|
418
|
+
# @return [Wx::Rect] Bounding rectangle
|
|
419
|
+
def get_bounding_box
|
|
420
|
+
line_rct = nil
|
|
421
|
+
|
|
422
|
+
# calculate control points area if they exist
|
|
423
|
+
if !@lst_points.empty?
|
|
424
|
+
prev_pt = get_src_point
|
|
425
|
+
|
|
426
|
+
@lst_points.each do |pt|
|
|
427
|
+
if line_rct.nil?
|
|
428
|
+
line_rct = Wx::Rect.new(prev_pt.to_point, pt.to_point)
|
|
429
|
+
else
|
|
430
|
+
line_rct.union!(Wx::Rect.new(prev_pt.to_point, pt.to_point))
|
|
431
|
+
end
|
|
432
|
+
prev_pt = pt
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
line_rct.union!(Wx::Rect.new(prev_pt.to_point, get_trg_point.to_point))
|
|
436
|
+
else
|
|
437
|
+
# include starting point
|
|
438
|
+
pt = get_src_point
|
|
439
|
+
line_rct = Wx::Rect.new(pt.x.to_i, pt.y.to_i, 1, 1)
|
|
440
|
+
|
|
441
|
+
# include ending point
|
|
442
|
+
pt = get_trg_point
|
|
443
|
+
line_rct.union!(Wx::Rect.new(pt.x.to_i, pt.y.to_i, 1, 1))
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# include unfinished point if the line is under construction
|
|
447
|
+
if @mode == LINEMODE::UNDERCONSTRUCTION || @mode == LINEMODE::SRCCHANGE || @mode == LINEMODE::TRGCHANGE
|
|
448
|
+
if line_rct.nil?
|
|
449
|
+
line_rct = Wx::Rect.new(@unfinished_point.x, @unfinished_point.y, 1, 1)
|
|
450
|
+
else
|
|
451
|
+
line_rct.union!(Wx::Rect.new(@unfinished_point.x, @unfinished_point.y, 1, 1))
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
line_rct ? line_rct : Wx::Rect.new
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
# Get the shape's absolute position in the canvas.
|
|
459
|
+
# @return [Wx::RealPoint] Shape's position
|
|
460
|
+
def get_absolute_position
|
|
461
|
+
get_dock_point_position(@dock_point)
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
# Get intersection point of the shape border and a line leading from
|
|
465
|
+
# 'start_pt' point to 'end_pt' point. The function can be overridden if necessary.
|
|
466
|
+
# @param [Wx::RealPoint] _start_pt Starting point of the virtual intersection line
|
|
467
|
+
# @param [Wx::RealPoint] _end_pt Ending point of the virtual intersection line
|
|
468
|
+
# @return [Wx::RealPoint] Intersection point
|
|
469
|
+
def get_border_point(_start_pt, _end_pt)
|
|
470
|
+
get_absolute_position
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
# Test whether the given point is inside the shape. The function
|
|
474
|
+
# can be overridden if necessary.
|
|
475
|
+
# @param pos Examined point
|
|
476
|
+
# @return TRUE if the point is inside the shape area, otherwise FALSE
|
|
477
|
+
def contains?(pos)
|
|
478
|
+
return true if @mode != LINEMODE::UNDERCONSTRUCTION && get_hit_linesegment(pos) >= 0
|
|
479
|
+
false
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
# Move the shape to the given absolute position. The function
|
|
483
|
+
# can be overridden if necessary.
|
|
484
|
+
# @param [Float] x X coordinate
|
|
485
|
+
# @param [Float] y Y coordinate
|
|
486
|
+
def move_to(x, y)
|
|
487
|
+
move_by(x - @prev_position.x, y - @prev_position.y)
|
|
488
|
+
@prev_position.x = x
|
|
489
|
+
@prev_position.y = y
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
# Move the shape by the given offset. The function
|
|
493
|
+
# can be overridden if necessary.
|
|
494
|
+
# @param [Float] x X offset
|
|
495
|
+
# @param [Float] y Y offset
|
|
496
|
+
def move_by(x, y)
|
|
497
|
+
@lst_points.each do |pt|
|
|
498
|
+
pt.x += x
|
|
499
|
+
pt.y += y
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
if @stand_alone
|
|
503
|
+
@src_point += [x, y]
|
|
504
|
+
@trg_point += [x, y]
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
update unless @child_shapes.empty?
|
|
508
|
+
|
|
509
|
+
get_diagram.set_modified if get_diagram
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
# Function called by the framework responsible for creation of shape handles
|
|
513
|
+
# at the creation time. The function can be overridden if necessary.
|
|
514
|
+
def create_handles
|
|
515
|
+
# first clear all previously used handles and then create new ones
|
|
516
|
+
@handles.clear
|
|
517
|
+
|
|
518
|
+
# create control points handles
|
|
519
|
+
@lst_points.size.times { |i| add_handle(Shape::Handle::TYPE::LINECTRL, i) }
|
|
520
|
+
|
|
521
|
+
# create border handles
|
|
522
|
+
add_handle(Shape::Handle::TYPE::LINESTART)
|
|
523
|
+
add_handle(Shape::Handle::TYPE::LINEEND)
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
# Event handler called during dragging of the shape handle.
|
|
527
|
+
# The function can be overridden if necessary.
|
|
528
|
+
#
|
|
529
|
+
# The function is called by the framework (by the shape canvas).
|
|
530
|
+
# @param [Wx::SF::Shape::Handle] handle Reference to dragged handle
|
|
531
|
+
def on_handle(handle)
|
|
532
|
+
case handle.type
|
|
533
|
+
when Shape::Handle::TYPE::LINECTRL
|
|
534
|
+
pt = @lst_points[handle.id]
|
|
535
|
+
if pt
|
|
536
|
+
pt.x = handle.get_position.x
|
|
537
|
+
pt.y = handle.get_position.y
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
when Shape::Handle::TYPE::LINEEND
|
|
541
|
+
@unfinished_point = handle.get_position
|
|
542
|
+
@trg_point = handle.get_position.to_real if @stand_alone
|
|
543
|
+
|
|
544
|
+
when Shape::Handle::TYPE::LINESTART
|
|
545
|
+
@unfinished_point = handle.get_position
|
|
546
|
+
@src_point = handle.get_position.to_real if @stand_alone
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
super
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
# Event handler called when the user finished dragging of the shape handle.
|
|
553
|
+
# The function can be overridden if necessary.
|
|
554
|
+
#
|
|
555
|
+
# The function is called by the framework (by the shape canvas).
|
|
556
|
+
# Default implementation does nothing.
|
|
557
|
+
# @param [Wx::SF::Shape::Handle] handle Reference to dragged handle
|
|
558
|
+
def on_end_handle(handle)
|
|
559
|
+
# update percentual offset of the line's ending points
|
|
560
|
+
parent = get_parent_canvas.get_shape_under_cursor
|
|
561
|
+
|
|
562
|
+
if parent && !@stand_alone
|
|
563
|
+
bb_rect = parent.get_bounding_box
|
|
564
|
+
|
|
565
|
+
case handle.type
|
|
566
|
+
when Shape::Handle::TYPE::LINESTART
|
|
567
|
+
if parent.id == @src_shape_id
|
|
568
|
+
@src_offset.x = (handle.get_position.x - bb_rect.left).to_f / bb_rect.width
|
|
569
|
+
@src_offset.y = (handle.get_position.y - bb_rect.top).to_f / bb_rect.height
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
when Shape::Handle::TYPE::LINEEND
|
|
573
|
+
if parent.id == @trg_shape_id
|
|
574
|
+
@trg_offset.x = (handle.get_position.x - bb_rect.left).to_f / bb_rect.width
|
|
575
|
+
@trg_offset.y = (handle.get_position.y - bb_rect.top).to_f / bb_rect.height
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
super
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
# Event handler called at the beginning of the shape dragging process.
|
|
584
|
+
# The function can be overridden if necessary.
|
|
585
|
+
#
|
|
586
|
+
# The function is called by the framework (by the shape canvas).
|
|
587
|
+
# @param [Wx::Point] pos Current mouse position
|
|
588
|
+
# @see Wx::SF::ShapeCanvas
|
|
589
|
+
def on_begin_drag(pos)
|
|
590
|
+
@prev_position = get_absolute_position
|
|
591
|
+
|
|
592
|
+
super
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
# Event handler called when the shape is double-clicked by
|
|
596
|
+
# the left mouse button. The function can be overridden if necessary.
|
|
597
|
+
#
|
|
598
|
+
# The function is called by the framework (by the shape canvas).
|
|
599
|
+
# @param [Wx::Point] pos Current mouse position
|
|
600
|
+
# @see Wx::SF::ShapeCanvas
|
|
601
|
+
def on_left_double_click(pos)
|
|
602
|
+
# HINT: override it for custom actions
|
|
603
|
+
|
|
604
|
+
if get_parent_canvas
|
|
605
|
+
# remove existing handle if exist otherwise create a new one at the
|
|
606
|
+
# given position
|
|
607
|
+
handle = get_parent_canvas.get_topmost_handle_at_position(pos)
|
|
608
|
+
if handle && handle.get_parent_shape == self
|
|
609
|
+
if handle.type == Shape::Handle::TYPE::LINECTRL
|
|
610
|
+
if has_style?(STYLE::EMIT_EVENTS)
|
|
611
|
+
evt = Wx::SF::ShapeHandleEvent.new(EVT_SF_LINE_HANDLE_REMOVE, id)
|
|
612
|
+
evt.set_shape(self)
|
|
613
|
+
evt.set_handle(handle)
|
|
614
|
+
get_parent_canvas.get_event_handler.process_event(evt)
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
@lst_points.delete_at(handle.id)
|
|
618
|
+
|
|
619
|
+
create_handles
|
|
620
|
+
show_handles(true)
|
|
621
|
+
end
|
|
622
|
+
else
|
|
623
|
+
index = get_hit_linesegment(pos)
|
|
624
|
+
if index > -1
|
|
625
|
+
@lst_points.insert(index, Wx::RealPoint.new(pos.x, pos.y))
|
|
626
|
+
|
|
627
|
+
create_handles
|
|
628
|
+
show_handles(true)
|
|
629
|
+
|
|
630
|
+
if has_style?(STYLE::EMIT_EVENTS)
|
|
631
|
+
handle = get_parent_canvas.get_topmost_handle_at_position(pos)
|
|
632
|
+
if handle
|
|
633
|
+
evt = ShapeHandleEvent.new(EVT_SF_LINE_HANDLE_ADD, id)
|
|
634
|
+
evt.set_shape(this)
|
|
635
|
+
evt.set_handle(handle)
|
|
636
|
+
get_parent_canvas.get_event_handler.process_event(evt)
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
end
|
|
640
|
+
end
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
# Scale the shape size by in both directions. The function can be overridden if necessary
|
|
645
|
+
# (new implementation should call default one or scale shape's children manually if necessary).
|
|
646
|
+
# @param [Float] x Horizontal scale factor
|
|
647
|
+
# @param [Float] y Vertical scale factor
|
|
648
|
+
# @param [Boolean] children true if the shape's children should be scaled as well, otherwise the shape will be updated after scaling via update() function.
|
|
649
|
+
def scale(x, y, children = WITHCHILDREN)
|
|
650
|
+
@lst_points.each do |pt|
|
|
651
|
+
pt.x *= x
|
|
652
|
+
pt.y *= y
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
# call default function implementation (needed for scaling of shape's children)
|
|
656
|
+
super
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
# Get current working mode.
|
|
660
|
+
# @return [LINEMODE] Current working mode
|
|
661
|
+
# @see LINEMODE
|
|
662
|
+
def get_line_mode
|
|
663
|
+
@mode
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
protected
|
|
667
|
+
|
|
668
|
+
# Draw the shape in the normal way. The function can be overridden if necessary.
|
|
669
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
|
670
|
+
def draw_normal(dc)
|
|
671
|
+
dc.with_pen(@pen) do
|
|
672
|
+
draw_complete_line(dc)
|
|
673
|
+
end
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
# Draw the shape in the hower mode (the mouse cursor is above the shape).
|
|
677
|
+
# The function can be overridden if necessary.
|
|
678
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
|
679
|
+
def draw_hover(dc)
|
|
680
|
+
dc.with_pen(Wx::Pen.new(@hover_color, 1)) do
|
|
681
|
+
draw_complete_line(dc)
|
|
682
|
+
end
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
# Draw the shape in the highlighted mode (another shape is dragged over this
|
|
686
|
+
# shape and this shape will accept the dragged one if it will be dropped on it).
|
|
687
|
+
# The function can be overridden if necessary.
|
|
688
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
|
689
|
+
def draw_highlighted(dc)
|
|
690
|
+
dc.with_pen(Wx::Pen.new(@hover_color, 2)) do
|
|
691
|
+
draw_complete_line(dc)
|
|
692
|
+
end
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
# Draw completed line.
|
|
696
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
|
697
|
+
def draw_complete_line(dc)
|
|
698
|
+
return unless diagram
|
|
699
|
+
|
|
700
|
+
case @mode
|
|
701
|
+
when LINEMODE::READY
|
|
702
|
+
# draw basic line parts
|
|
703
|
+
src = trg = nil
|
|
704
|
+
line_segment_count.times do |i|
|
|
705
|
+
src, trg = get_line_segment(i)
|
|
706
|
+
dc.draw_line(src.to_point, trg.to_point)
|
|
707
|
+
end
|
|
708
|
+
# draw target arrow
|
|
709
|
+
@trg_arrow.draw(src, trg, dc) if @trg_arrow
|
|
710
|
+
# draw source arrow
|
|
711
|
+
if @src_arrow
|
|
712
|
+
src, trg = get_line_segment(0)
|
|
713
|
+
@src_arrow.draw(trg, src, dc)
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
when LINEMODE::UNDERCONSTRUCTION
|
|
717
|
+
# draw basic line parts
|
|
718
|
+
src = trg = nil
|
|
719
|
+
@lst_points.size.times do |i|
|
|
720
|
+
src, trg = get_line_segment(i)
|
|
721
|
+
dc.draw_line(src.to_point, trg.to_point)
|
|
722
|
+
end
|
|
723
|
+
# draw unfinished line segment if any (for interactive line creation)
|
|
724
|
+
dc.with_pen(Wx::Pen.new(Wx::BLACK, 1, Wx::PENSTYLE_DOT)) do
|
|
725
|
+
if @lst_points.size > 0
|
|
726
|
+
dc.draw_line(trg, @unfinished_point)
|
|
727
|
+
else
|
|
728
|
+
src_shape = diagram.find_shape(@src_shape_id)
|
|
729
|
+
if src_shape
|
|
730
|
+
if src_shape.get_connection_points.empty?
|
|
731
|
+
dc.draw_line((src_shape.get_border_point(src_shape.get_center, @unfinished_point.to_real)).to_point,
|
|
732
|
+
@unfinished_point)
|
|
733
|
+
else
|
|
734
|
+
dc.draw_line(get_mod_src_point.to_point, @unfinished_point)
|
|
735
|
+
end
|
|
736
|
+
end
|
|
737
|
+
end
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
when LINEMODE::SRCCHANGE
|
|
741
|
+
# draw basic line parts
|
|
742
|
+
src = trg = nil
|
|
743
|
+
@lst_points.size.times do |i|
|
|
744
|
+
src, trg = get_line_segment(i+1)
|
|
745
|
+
dc.draw_line(src.to_point, trg.to_point)
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
# draw linesegment being updated
|
|
749
|
+
src, trg = get_line_segment(0)
|
|
750
|
+
|
|
751
|
+
dc.set_pen(Wx::Pen.new(Wx::BLACK, 1, Wx::PENSTYLE_DOT)) unless @stand_alone
|
|
752
|
+
dc.draw_line(@unfinished_point, trg.to_point)
|
|
753
|
+
dc.set_pen(Wx::NULL_PEN) unless @stand_alone
|
|
754
|
+
|
|
755
|
+
when LINEMODE::TRGCHANGE
|
|
756
|
+
# draw basic line parts
|
|
757
|
+
src = trg = nil
|
|
758
|
+
if @lst_points.empty?
|
|
759
|
+
trg = get_src_point
|
|
760
|
+
else
|
|
761
|
+
@lst_points.size.times do |i|
|
|
762
|
+
src, trg = get_line_segment(i)
|
|
763
|
+
dc.draw_line(src.to_point, trg.to_point)
|
|
764
|
+
end
|
|
765
|
+
end
|
|
766
|
+
# draw linesegment being updated
|
|
767
|
+
dc.set_pen(Wx::Pen.new(Wx::BLACK, 1, Wx::PENSTYLE_DOT)) unless @stand_alone
|
|
768
|
+
dc.draw_line(trg.to_point, @unfinished_point)
|
|
769
|
+
dc.set_pen(Wx::NULL_PEN) unless @stand_alone
|
|
770
|
+
end
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
# Get index of the line segment intersecting the given point.
|
|
774
|
+
# @param [Wx::Point] pos Examined point
|
|
775
|
+
# @return [Integer] Zero-based index of line segment located under the given point
|
|
776
|
+
def get_hit_linesegment(pos)
|
|
777
|
+
return -1 unless get_bounding_box.contains?(pos)
|
|
778
|
+
|
|
779
|
+
pos = pos.to_point
|
|
780
|
+
# Get all polyline segments
|
|
781
|
+
line_segment_count.times do |i|
|
|
782
|
+
src, trg = get_line_segment(i)
|
|
783
|
+
|
|
784
|
+
# calculate line segment bounding box
|
|
785
|
+
ls_bb = Wx::Rect.new(src.to_point, trg.to_point)
|
|
786
|
+
ls_bb.inflate!(2)
|
|
787
|
+
|
|
788
|
+
# convert line segment to its parametric form
|
|
789
|
+
a = trg.y - src.y
|
|
790
|
+
b = src.x - trg.x
|
|
791
|
+
c = -a*src.x - b*src.y
|
|
792
|
+
|
|
793
|
+
# calculate distance of the line and give point
|
|
794
|
+
d = (a*pos.x + b*pos.y + c)/::Math.sqrt(a*a + b*b)
|
|
795
|
+
# NaN will be the result if src and trg are equal
|
|
796
|
+
# (which can happen for lines between parent and child shapes)
|
|
797
|
+
return i if (d.nan? || d.to_i.abs <= 5) && ls_bb.contains?(pos)
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
-1
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
# Set line shape's working mode.
|
|
804
|
+
# @param [LINEMODE] mode Working mode
|
|
805
|
+
# @see LINEMODE
|
|
806
|
+
def set_line_mode(mode)
|
|
807
|
+
@mode = mode
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
# Set next potential control point position (useful in LINEMODE::UNDERCONSTRUCTION working mode).
|
|
811
|
+
# @param [Wx::Point] pos New potential control point position
|
|
812
|
+
# @see LINEMODE
|
|
813
|
+
def set_unfinished_point(pos)
|
|
814
|
+
@unfinished_point = pos.to_point
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
# Get modified starting line point .
|
|
818
|
+
# @return [Wx::RealPoint] Modified starting line point
|
|
819
|
+
def get_mod_src_point
|
|
820
|
+
src_shape = diagram.find_shape(@src_shape_id)
|
|
821
|
+
return Wx::RealPoint.new unless src_shape
|
|
822
|
+
|
|
823
|
+
if @src_offset != DEFAULT::OFFSET
|
|
824
|
+
bb_rct = src_shape.get_bounding_box
|
|
825
|
+
mod_point = src_shape.get_absolute_position
|
|
826
|
+
|
|
827
|
+
mod_point.x += bb_rct.width.to_f * @src_offset.x
|
|
828
|
+
mod_point.y += bb_rct.height.to_f * @src_offset.y
|
|
829
|
+
else
|
|
830
|
+
mod_point = src_shape.get_center
|
|
831
|
+
end
|
|
832
|
+
|
|
833
|
+
conn_pt = src_shape.get_nearest_connection_point(mod_point)
|
|
834
|
+
mod_point = conn_pt.get_connection_point if conn_pt
|
|
835
|
+
|
|
836
|
+
mod_point
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
# Get modified ending line point .
|
|
840
|
+
# @return [Wx::RealPoint] Modified ending line point
|
|
841
|
+
def get_mod_trg_point
|
|
842
|
+
trg_shape = diagram.find_shape(@trg_shape_id)
|
|
843
|
+
return Wx::RealPoint.new unless trg_shape
|
|
844
|
+
|
|
845
|
+
if @trg_offset != DEFAULT::OFFSET
|
|
846
|
+
bb_rct = trg_shape.get_bounding_box
|
|
847
|
+
mod_point = trg_shape.get_absolute_position
|
|
848
|
+
|
|
849
|
+
mod_point.x += bb_rct.width.to_f * @trg_offset.x
|
|
850
|
+
mod_point.y += bb_rct.height.to_f * @trg_offset.y
|
|
851
|
+
else
|
|
852
|
+
mod_point = trg_shape.get_center
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
conn_pt = trg_shape.get_nearest_connection_point(mod_point)
|
|
856
|
+
mod_point = conn_pt.get_connection_point if conn_pt
|
|
857
|
+
|
|
858
|
+
mod_point
|
|
859
|
+
end
|
|
860
|
+
|
|
861
|
+
private
|
|
862
|
+
|
|
863
|
+
# Set control points. Deserialization only.
|
|
864
|
+
# @param [Array<Wx::RealPoint>] pts
|
|
865
|
+
def set_control_points(pts)
|
|
866
|
+
@lst_points.replace(pts)
|
|
867
|
+
end
|
|
868
|
+
|
|
869
|
+
# Serialization only
|
|
870
|
+
# @return [Wx::RealPoint]
|
|
871
|
+
def get_src_offset
|
|
872
|
+
@src_offset
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
# Deserialization only
|
|
876
|
+
# @param [Wx::RealPoint] offs
|
|
877
|
+
def set_src_offset(offs)
|
|
878
|
+
@src_offset = offs.to_real_point
|
|
879
|
+
end
|
|
880
|
+
|
|
881
|
+
# Serialization only
|
|
882
|
+
# @return [Wx::RealPoint]
|
|
883
|
+
def get_trg_offset
|
|
884
|
+
@trg_offset
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
# Deserialization only
|
|
888
|
+
# @param [Wx::RealPoint] offs
|
|
889
|
+
def set_trg_offset(offs)
|
|
890
|
+
@trg_offset = offs.to_real_point
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
# (De-)Serialization only
|
|
894
|
+
def serialize_src_point(*arg)
|
|
895
|
+
@src_point = arg.shift unless arg.empty?
|
|
896
|
+
@src_point
|
|
897
|
+
end
|
|
898
|
+
|
|
899
|
+
# (De-)Serialization only
|
|
900
|
+
def serialize_trg_point(*arg)
|
|
901
|
+
@trg_point = arg.shift unless arg.empty?
|
|
902
|
+
@trg_point
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
end
|