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.
- 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,43 @@
|
|
1
|
+
# Wx::SF::ShapeDataObject - shape data object class
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
3
|
+
|
4
|
+
module Wx::SF
|
5
|
+
|
6
|
+
# Class encapsulating data object used during clipboard operations with shapes.
|
7
|
+
class ShapeDataObject < Wx::DataObjectSimpleBase
|
8
|
+
|
9
|
+
DataFormatID = 'ShapeFrameWorkDataFormat1_0'
|
10
|
+
|
11
|
+
# @overload initialize()
|
12
|
+
# Default constructor
|
13
|
+
# @overload initialize(selection)
|
14
|
+
# User constructor
|
15
|
+
# @param [Array<Wx::SF::Shape>] selection List of shapes which should be stored in the data object
|
16
|
+
def initialize(selection = nil)
|
17
|
+
super(Wx::DataFormat.new(DataFormatID))
|
18
|
+
@data = selection ? selection.serialize : ''
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns size of the data object
|
22
|
+
# @return [Integer]
|
23
|
+
def _get_data_size
|
24
|
+
@data.bytesize
|
25
|
+
end
|
26
|
+
|
27
|
+
# Exports data from data object.
|
28
|
+
# @return [Boolean] true on success, otherwise false
|
29
|
+
def _get_data
|
30
|
+
@data
|
31
|
+
end
|
32
|
+
|
33
|
+
# Function should inport data from data object from given buffer.
|
34
|
+
# @param [String] buf External input data buffer
|
35
|
+
# @return [Boolean] true on success, otherwise false
|
36
|
+
def _set_data(buf)
|
37
|
+
@data = buf ? buf : ''
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,287 @@
|
|
1
|
+
# Wx::SF::Shape::Handle - shape handle class
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
3
|
+
|
4
|
+
module Wx::SF
|
5
|
+
|
6
|
+
class Shape
|
7
|
+
|
8
|
+
# Class encapsulates shape's handle. The class shouldn't be used separately; see
|
9
|
+
# Wx::Shape class for more detailed information about functions used for managing of shape
|
10
|
+
# handles and handling their events
|
11
|
+
class Handle
|
12
|
+
|
13
|
+
# Handle type
|
14
|
+
class TYPE < Wx::Enum
|
15
|
+
LEFTTOP = self.new(0)
|
16
|
+
TOP = self.new(1)
|
17
|
+
RIGHTTOP = self.new(2)
|
18
|
+
RIGHT = self.new(3)
|
19
|
+
RIGHTBOTTOM = self.new(4)
|
20
|
+
BOTTOM = self.new(5)
|
21
|
+
LEFTBOTTOM = self.new(6)
|
22
|
+
LEFT = self.new(7)
|
23
|
+
LINECTRL = self.new(8)
|
24
|
+
LINESTART = self.new(9)
|
25
|
+
LINEEND = self.new(10)
|
26
|
+
UNDEF = self.new(11)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Constructor
|
30
|
+
# @param [Wx::Shape] parent Parent shape
|
31
|
+
# @param [TYPE] type Handle type
|
32
|
+
# @param [Integer] id Handle ID (useful only for line controls handles)
|
33
|
+
def initialize(parent=nil, type=TYPE::UNDEF, id=-1)
|
34
|
+
@parent_shape = parent
|
35
|
+
@type = type
|
36
|
+
@id = id
|
37
|
+
@start_pos = Wx::Point.new
|
38
|
+
@prev_pos = Wx::Point.new
|
39
|
+
@curr_pos = Wx::Point.new
|
40
|
+
|
41
|
+
@visible = false
|
42
|
+
@mouse_over = false
|
43
|
+
end
|
44
|
+
|
45
|
+
# Set or get handle's ID.
|
46
|
+
attr_accessor :id
|
47
|
+
|
48
|
+
# Get Handle type
|
49
|
+
# @return [TYPE] Handle type
|
50
|
+
def get_type
|
51
|
+
@type
|
52
|
+
end
|
53
|
+
alias :type :get_type
|
54
|
+
|
55
|
+
# Set Handle type
|
56
|
+
# @param [TYPE] type Handle type to set
|
57
|
+
def set_type(type)
|
58
|
+
@type = type
|
59
|
+
end
|
60
|
+
alias :type= :set_type
|
61
|
+
|
62
|
+
# Get parent shape.
|
63
|
+
# @return [Wx::Shape] parent shape
|
64
|
+
def get_parent_shape
|
65
|
+
@parent_shape
|
66
|
+
end
|
67
|
+
alias :parent_shape :get_parent_shape
|
68
|
+
|
69
|
+
# Get current handle position.
|
70
|
+
# @return [Wx::Point] Handle position
|
71
|
+
def get_position
|
72
|
+
@curr_pos
|
73
|
+
end
|
74
|
+
alias :position :get_position
|
75
|
+
|
76
|
+
# Get current handle delta (difference between current and previous position).
|
77
|
+
# @return [Wx::Point] Handle delta
|
78
|
+
def get_delta
|
79
|
+
@curr_pos - @prev_pos
|
80
|
+
end
|
81
|
+
alias :delta :get_delta
|
82
|
+
|
83
|
+
# Get current total handle delta (difference between current and starting position
|
84
|
+
# stored at the beginning of the dragging process).
|
85
|
+
# @return [Wx::Point] Total handle delta
|
86
|
+
def get_total_delta
|
87
|
+
@curr_pos - @start_pos
|
88
|
+
end
|
89
|
+
alias :total_delta :get_total_delta
|
90
|
+
|
91
|
+
# Show/hide handle
|
92
|
+
# @param [Boolean] show true if the handle should be visible (active), otherwise false
|
93
|
+
def show(show = true)
|
94
|
+
@visible = !!show
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns true if the handle is visible, otherwise false
|
98
|
+
def visible?
|
99
|
+
@visible
|
100
|
+
end
|
101
|
+
|
102
|
+
# Refresh (repaint) the handle
|
103
|
+
# @return [void]
|
104
|
+
def refresh
|
105
|
+
@parent_shape.refresh(DELAYED) if @parent_shape
|
106
|
+
end
|
107
|
+
|
108
|
+
# Find out whether given point is inside the handle.
|
109
|
+
# @param [Wx::Point,Array(Integer,Integer)] pos Examined point
|
110
|
+
# @return [Boolean] true if the point is inside the handle, otherwise false
|
111
|
+
def contains(pos)
|
112
|
+
handle_rect.contains?(pos)
|
113
|
+
end
|
114
|
+
alias contains? :contains
|
115
|
+
|
116
|
+
protected
|
117
|
+
|
118
|
+
# Draw handle.
|
119
|
+
# @param [Wx::DC] dc Device context where the handle will be drawn
|
120
|
+
def draw(dc)
|
121
|
+
if @visible && @parent_shape
|
122
|
+
if @mouse_over
|
123
|
+
draw_hover(dc)
|
124
|
+
else
|
125
|
+
draw_normal(dc)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Draw handle in the normal way.
|
131
|
+
# @param [Wx::DC] dc Device context where the handle will be drawn
|
132
|
+
def draw_normal(dc)
|
133
|
+
dc.with_pen(Wx::PLATFORM == 'WXGTK' ? Wx::TRANSPARENT_PEN : Wx::BLACK_PEN) do
|
134
|
+
if ShapeCanvas::gc_enabled?
|
135
|
+
dc.brush = Wx::Brush.new(Wx::Colour.new(0, 0, 0, 128))
|
136
|
+
else
|
137
|
+
dc.brush = Wx::BLACK_BRUSH
|
138
|
+
# dc.logical_function = Wx::RasterOperationMode::INVERT
|
139
|
+
end
|
140
|
+
|
141
|
+
dc.draw_rectangle(handle_rect)
|
142
|
+
# dc.logical_function = Wx::RasterOperationMode::COPY
|
143
|
+
|
144
|
+
dc.brush = Wx::NULL_BRUSH
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Draw handle in the "hover" way (the mouse pointer is above the handle area).
|
149
|
+
# @param [Wx::DC] dc Device context where the handle will be drawn
|
150
|
+
def draw_hover(dc)
|
151
|
+
if @parent_shape.contains_style(Shape::STYLE::SIZE_CHANGE)
|
152
|
+
dc.with_pen(Wx::BLACK_PEN) do
|
153
|
+
dc.with_brush(Wx::Brush.new(@parent_shape.hover_colour)) do
|
154
|
+
dc.draw_rectangle(handle_rect)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
else
|
158
|
+
draw_normal(dc)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Set parent shape.
|
163
|
+
# @param [Wx::Shape] parent parent shape to set
|
164
|
+
def parent_shape=(parent)
|
165
|
+
@parent_shape = parent
|
166
|
+
end
|
167
|
+
|
168
|
+
# Get handle rectangle.
|
169
|
+
# @return [Wx::Rect] Handle rectangle
|
170
|
+
def handle_rect
|
171
|
+
if @parent_shape
|
172
|
+
brct = @parent_shape.get_bounding_box
|
173
|
+
case @type
|
174
|
+
when TYPE::LEFTTOP
|
175
|
+
hrct = Wx::Rect.new(brct.top_left, Wx::Size.new(7,7))
|
176
|
+
when TYPE::TOP
|
177
|
+
hrct = Wx::Rect.new(Wx::Point.new(brct.left + brct.width/2, brct.top), Wx::Size.new(7,7))
|
178
|
+
when TYPE::RIGHTTOP
|
179
|
+
hrct = Wx::Rect.new(brct.top_right, Wx::Size.new(7,7))
|
180
|
+
when TYPE::RIGHT
|
181
|
+
hrct = Wx::Rect.new(Wx::Point.new(brct.right, brct.top + brct.height/2), Wx::Size.new(7,7))
|
182
|
+
when TYPE::RIGHTBOTTOM
|
183
|
+
hrct = Wx::Rect.new(brct.bottom_right, Wx::Size.new(7,7))
|
184
|
+
when TYPE::BOTTOM
|
185
|
+
hrct = Wx::Rect.new(Wx::Point.new(brct.left + brct.width/2, brct.bottom), Wx::Size.new(7,7))
|
186
|
+
when TYPE::LEFTBOTTOM
|
187
|
+
hrct = Wx::Rect.new(brct.bottom_left, Wx::Size.new(7,7))
|
188
|
+
when TYPE::LEFT
|
189
|
+
hrct = Wx::Rect.new(Wx::Point.new(brct.left, brct.top + brct.height/2), Wx::Size.new(7,7))
|
190
|
+
when TYPE::LINECTRL
|
191
|
+
pt = @parent_shape.get_control_points[@id]
|
192
|
+
hrct = Wx::Rect.new(Wx::Point.new(pt.x.to_i, pt.y.to_i), Wx::Size.new(7,7))
|
193
|
+
when TYPE::LINEEND, TYPE::LINESTART
|
194
|
+
pt = @type == TYPE::LINESTART ? @parent_shape.src_point : @parent_shape.trg_point
|
195
|
+
hrct = Wx::Rect.new(Wx::Point.new(pt.x.to_i, pt.y.to_i), Wx::Size.new(7,7))
|
196
|
+
else
|
197
|
+
hrct = Wx::Rect.new
|
198
|
+
end
|
199
|
+
|
200
|
+
hrct.offset!(-3, -3)
|
201
|
+
else
|
202
|
+
Wx::Rect.new
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
private
|
207
|
+
|
208
|
+
# Event handler called when the mouse pointer is moving above shape canvas.
|
209
|
+
# @param [Wx::Point] pos Current mouse position
|
210
|
+
def _on_mouse_move(pos)
|
211
|
+
if @visible
|
212
|
+
if contains?(pos)
|
213
|
+
unless @mouse_over
|
214
|
+
@mouse_over = true
|
215
|
+
refresh
|
216
|
+
end
|
217
|
+
else
|
218
|
+
if @mouse_over
|
219
|
+
@mouse_over = false
|
220
|
+
refresh
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# Event handler called when the handle is started to be dragged.
|
227
|
+
# @param [Wx::Point] pos Current mouse position
|
228
|
+
def _on_begin_drag(pos)
|
229
|
+
@prev_pos = @start_pos = @curr_pos = pos
|
230
|
+
@parent_shape.on_begin_handle(self) if @parent_shape
|
231
|
+
end
|
232
|
+
|
233
|
+
# Event handler called when the handle is dragged.
|
234
|
+
# @param [Wx::Point] pos Current mouse position
|
235
|
+
def _on_dragging(pos)
|
236
|
+
if @visible && @parent_shape && @parent_shape.contains_style(Shape::STYLE::SIZE_CHANGE)
|
237
|
+
if pos != @prev_pos
|
238
|
+
prev_rct = @parent_shape.get_bounding_box
|
239
|
+
|
240
|
+
@curr_pos = pos
|
241
|
+
|
242
|
+
case @type
|
243
|
+
when TYPE::LEFTTOP
|
244
|
+
@parent_shape.send(:_on_handle, self) if (pos.x < prev_rct.right) && (pos.y < prev_rct.bottom)
|
245
|
+
|
246
|
+
when TYPE::TOP
|
247
|
+
@parent_shape.send(:_on_handle, self) if (pos.y < prev_rct.bottom)
|
248
|
+
|
249
|
+
when TYPE::RIGHTTOP
|
250
|
+
@parent_shape.send(:_on_handle, self) if ((pos.x > prev_rct.left) && (pos.y < prev_rct.bottom))
|
251
|
+
|
252
|
+
when TYPE::RIGHT
|
253
|
+
@parent_shape.send(:_on_handle, self) if (pos.x > prev_rct.left)
|
254
|
+
|
255
|
+
when TYPE::RIGHTBOTTOM
|
256
|
+
@parent_shape.send(:_on_handle, self) if ((pos.x > prev_rct.left) && (pos.y > prev_rct.top))
|
257
|
+
|
258
|
+
when TYPE::BOTTOM
|
259
|
+
@parent_shape.send(:_on_handle, self) if (pos.y > prev_rct.top)
|
260
|
+
|
261
|
+
when TYPE::LEFTBOTTOM
|
262
|
+
@parent_shape.send(:_on_handle, self) if ((pos.x < prev_rct.right) && (pos.y > prev_rct.top))
|
263
|
+
|
264
|
+
when TYPE::LEFT
|
265
|
+
@parent_shape.send(:_on_handle, self) if (pos.x < prev_rct.right)
|
266
|
+
|
267
|
+
when TYPE::LINESTART, TYPE::LINEEND, TYPE::LINECTRL
|
268
|
+
@parent_shape.send(:_on_handle, self)
|
269
|
+
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
@prev_pos = pos
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
# Event handler called when the handle is released.
|
278
|
+
# @param [Wx::Point] _pos Current mouse position
|
279
|
+
def _on_end_drag(_pos)
|
280
|
+
@parent_shape.on_end_handle(self) if @parent_shape
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# Wx::SF::Shape - shape list class
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
3
|
+
|
4
|
+
require 'wx/shapes/serializable'
|
5
|
+
|
6
|
+
module Wx::SF
|
7
|
+
|
8
|
+
# This class implements an indexed container for unique, non-nil, shapes (no duplicates).
|
9
|
+
class ShapeList
|
10
|
+
|
11
|
+
include Serializable
|
12
|
+
include ::Enumerable
|
13
|
+
|
14
|
+
property :list
|
15
|
+
|
16
|
+
# Constructor.
|
17
|
+
# @param [ShapeList,::Enumerable,Shape,nil] enum shape container to copy, single shape to add or nil
|
18
|
+
def initialize(enum = nil)
|
19
|
+
if enum
|
20
|
+
if enum.is_a?(ShapeList)
|
21
|
+
@list = enum.instance_variable_get('@list').dup
|
22
|
+
@index = enum.instance_variable_get('@index').dup
|
23
|
+
elsif enum.is_a?(::Enumerable)
|
24
|
+
@list = []
|
25
|
+
@index = {}
|
26
|
+
enum.each { |elem| self << elem }
|
27
|
+
else
|
28
|
+
@list = []
|
29
|
+
@index = {}
|
30
|
+
self << enum
|
31
|
+
end
|
32
|
+
else
|
33
|
+
@list = []
|
34
|
+
@index = {}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Iterates over contained shapes.
|
39
|
+
# When a block given, passes each successive shape to the block.
|
40
|
+
# Allows the array to be modified during iteration.
|
41
|
+
# When no block given, returns a new ::Enumerator.
|
42
|
+
# @yieldparam [Shape] shape
|
43
|
+
# @return [self]
|
44
|
+
def each(&block)
|
45
|
+
@list.each(&block)
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
# Recursively collects shapes and returns collection.
|
50
|
+
# @param [Array<Shape>] collection container to return collected shapes in
|
51
|
+
def all(collection = [])
|
52
|
+
@list.inject(collection) { |list, shape| shape.instance_variable_get('@child_shapes').all(list << shape) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns true if the no shapes are contained, false otherwise.
|
56
|
+
# @return [Boolean]
|
57
|
+
def empty?
|
58
|
+
@list.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Empties the shape list.
|
62
|
+
# @return [self]
|
63
|
+
def clear
|
64
|
+
@list.clear
|
65
|
+
@index.clear
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Appends a new shape to the list if not yet in list.
|
70
|
+
# @param [Shape] shape shape to add
|
71
|
+
# @return [self]
|
72
|
+
def append(shape)
|
73
|
+
unless @index.has_key?(check_elem(shape).id)
|
74
|
+
@list << shape
|
75
|
+
@index[shape.id] = shape
|
76
|
+
end
|
77
|
+
self
|
78
|
+
end
|
79
|
+
alias :push :append
|
80
|
+
alias :<< :append
|
81
|
+
|
82
|
+
# Removes the first shape from the list (if any) and returns that.
|
83
|
+
# @return [Shape,nil] removed shape or nil if list empty
|
84
|
+
def shift
|
85
|
+
return nil if @list.empty?
|
86
|
+
@index.delete(@list.shift.id)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Removes the last shape from the list (if any) and returns that.
|
90
|
+
# @return [Shape,nil] removed shape or nil if list empty
|
91
|
+
def pop
|
92
|
+
return nil if @list.empty?
|
93
|
+
@index.delete(@list.pop.id)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Removes a shape matching the key given from the list and returns that.
|
97
|
+
# @param [Shape,Serializable::ID] key shape or shape ID to match
|
98
|
+
# @return [Shape,nil] removed shape or nil if none matched
|
99
|
+
def delete(key)
|
100
|
+
if key.is_a?(Shape)
|
101
|
+
return @list.delete(key) if @index.delete(key.id)
|
102
|
+
elsif key.is_a?(Serializable::ID)
|
103
|
+
return @list.delete(@index.delete(key)) if @index.has_key?(key)
|
104
|
+
end
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns true if a shape matches the given key or false if no shape matches.
|
109
|
+
# @param [Shape,Serializable::ID] key shape or shape ID to match
|
110
|
+
# @param [Boolean] recursive pass true to search recursively, false for non-recursive
|
111
|
+
# @return [Boolean]
|
112
|
+
def include?(key, recursive = false)
|
113
|
+
found = if key.is_a?(Serializable::ID)
|
114
|
+
@index.has_key?(key)
|
115
|
+
else
|
116
|
+
@list.include?(key)
|
117
|
+
end
|
118
|
+
found || (recursive && @list.any? { |child| child.instance_variable_get('@child_shapes').include?(key, recursive) })
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns the shape matching the given key or nil if no shape matches.
|
122
|
+
# Does not modify the list.
|
123
|
+
# @param [Integer,Serializable::ID] key shape list index or shape ID to match
|
124
|
+
# @param [Boolean] recursive pass true to search recursively, false for non-recursive
|
125
|
+
# @return [Shape,nil] matched shape or nil if none matched
|
126
|
+
def get(key, recursive = false)
|
127
|
+
shape = if key.is_a?(Serializable::ID)
|
128
|
+
@index[key]
|
129
|
+
else
|
130
|
+
@list.at(key.to_i)
|
131
|
+
end
|
132
|
+
shape || (recursive && @list.find { |child| child.get(key, recursive) })
|
133
|
+
end
|
134
|
+
alias :[] :get
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
# Get shape array. Serialization only.
|
139
|
+
# @return [Array<Shape>]
|
140
|
+
def get_list
|
141
|
+
@list
|
142
|
+
end
|
143
|
+
|
144
|
+
# Set shape array from deserialization.
|
145
|
+
# @param [Array<Shape>] list
|
146
|
+
def set_list(list)
|
147
|
+
@list = list
|
148
|
+
@list.each { |shape| @index[shape.id] = shape }
|
149
|
+
end
|
150
|
+
|
151
|
+
# Check intended list item
|
152
|
+
# @param [Shape] shape intended list item
|
153
|
+
# @return [Shape] checked shape
|
154
|
+
def check_elem(shape)
|
155
|
+
::Kernel.raise TypeError, 'Expected a Wx::SF::Shape' unless shape.is_a?(Wx::SF::Shape)
|
156
|
+
shape
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|