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,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