wxruby3-shapes 0.9.0.pre.beta.3 → 0.9.6
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 +4 -4
- data/INSTALL.md +5 -7
- data/README.md +38 -6
- data/assets/logo.svg +339 -0
- data/assets/logo.xpm +60 -0
- data/assets/screenshot.png +0 -0
- data/assets/social.png +0 -0
- data/bin/wx-shapes +1 -1
- data/lib/wx/shapes/arrow_base.rb +4 -11
- data/lib/wx/shapes/arrows/circle_arrow.rb +22 -11
- data/lib/wx/shapes/arrows/circle_prong_arrow.rb +48 -0
- data/lib/wx/shapes/arrows/cross_bar_arrow.rb +57 -0
- data/lib/wx/shapes/arrows/cross_bar_circle_arrow.rb +56 -0
- data/lib/wx/shapes/arrows/cross_bar_prong_arrow.rb +49 -0
- data/lib/wx/shapes/arrows/crossed_circle.rb +46 -0
- data/lib/wx/shapes/arrows/cup_arrow.rb +65 -0
- data/lib/wx/shapes/arrows/diamond_arrow.rb +8 -13
- data/lib/wx/shapes/arrows/double_cross_bar_arrow.rb +27 -0
- data/lib/wx/shapes/arrows/filled_arrow.rb +60 -0
- data/lib/wx/shapes/arrows/line_arrow.rb +67 -0
- data/lib/wx/shapes/arrows/open_arrow.rb +22 -23
- data/lib/wx/shapes/arrows/prong_arrow.rb +42 -0
- data/lib/wx/shapes/arrows/solid_arrow.rb +21 -35
- data/lib/wx/shapes/arrows/square_arrow.rb +37 -0
- data/lib/wx/shapes/auto_layout.rb +2 -2
- data/lib/wx/shapes/base.rb +1 -1
- data/lib/wx/shapes/canvas_history.rb +20 -0
- data/lib/wx/shapes/connection_point.rb +10 -6
- data/lib/wx/shapes/diagram.rb +98 -78
- data/lib/wx/shapes/events.rb +8 -8
- data/lib/wx/shapes/printout.rb +3 -16
- data/lib/wx/shapes/serializable.rb +2 -436
- data/lib/wx/shapes/serialize/wx.rb +30 -18
- data/lib/wx/shapes/shape.rb +211 -168
- data/lib/wx/shapes/shape_canvas.rb +728 -267
- data/lib/wx/shapes/shape_data_object.rb +99 -18
- data/lib/wx/shapes/shape_handle.rb +18 -11
- data/lib/wx/shapes/shape_list.rb +34 -67
- data/lib/wx/shapes/shapes/bitmap_shape.rb +23 -24
- data/lib/wx/shapes/shapes/box_shape.rb +389 -0
- data/lib/wx/shapes/shapes/circle_shape.rb +19 -22
- data/lib/wx/shapes/shapes/control_shape.rb +77 -41
- data/lib/wx/shapes/shapes/curve_shape.rb +38 -31
- data/lib/wx/shapes/shapes/diamond_shape.rb +7 -17
- data/lib/wx/shapes/shapes/edit_text_shape.rb +6 -9
- data/lib/wx/shapes/shapes/ellipse_shape.rb +12 -15
- data/lib/wx/shapes/shapes/flex_grid_shape.rb +58 -33
- data/lib/wx/shapes/shapes/grid_shape.rb +259 -161
- data/lib/wx/shapes/shapes/line_shape.rb +155 -161
- data/lib/wx/shapes/shapes/manager_shape.rb +77 -0
- data/lib/wx/shapes/shapes/multi_sel_rect.rb +8 -8
- data/lib/wx/shapes/shapes/ortho_shape.rb +31 -36
- data/lib/wx/shapes/shapes/polygon_shape.rb +23 -29
- data/lib/wx/shapes/shapes/rect_shape.rb +95 -53
- data/lib/wx/shapes/shapes/round_ortho_shape.rb +6 -8
- data/lib/wx/shapes/shapes/round_rect_shape.rb +20 -24
- data/lib/wx/shapes/shapes/square_shape.rb +14 -17
- data/lib/wx/shapes/shapes/text_shape.rb +95 -53
- data/lib/wx/shapes/version.rb +1 -1
- data/lib/wx/shapes/wx.rb +16 -7
- data/lib/wx/wx-shapes/cmd/test.rb +1 -1
- data/samples/demo/arrows.json +1 -0
- data/samples/demo/arrows.yaml +793 -0
- data/samples/demo/art/HBox.xpm +22 -0
- data/samples/demo/art/VBox.xpm +22 -0
- data/samples/demo/art/logo.xpm +60 -0
- data/samples/demo/class.json +1 -0
- data/samples/demo/class.yaml +5631 -0
- data/samples/demo/demo.rb +301 -91
- data/samples/demo/dialogs.rb +1405 -0
- data/samples/demo/erd.json +1 -0
- data/samples/demo/erd.yaml +4072 -0
- data/samples/demo/frame_canvas.rb +409 -33
- data/samples/sample1/art/logo.xpm +60 -0
- data/samples/sample1/sample.rb +11 -11
- data/samples/sample2/art/logo.xpm +60 -0
- data/samples/sample2/sample.rb +2 -2
- data/samples/sample2/sample_shape.rb +15 -15
- data/samples/sample3/art/logo.xpm +60 -0
- data/samples/sample3/sample.rb +3 -3
- data/samples/sample4/art/logo.xpm +60 -0
- data/samples/sample4/sample.rb +2 -2
- data/tests/lib/wxapp_runner.rb +4 -0
- data/tests/serializer_tests.rb +8 -441
- data/tests/test_grid_shapes.rb +2 -2
- data/tests/test_serialize_xml.rb +17 -0
- data/tests/test_serialize_yaml.rb +2 -2
- metadata +78 -28
- data/lib/wx/shapes/serialize/core.rb +0 -40
- data/lib/wx/shapes/serialize/id.rb +0 -82
- data/lib/wx/shapes/serializer/json.rb +0 -258
- data/lib/wx/shapes/serializer/yaml.rb +0 -125
- data/samples/demo/art/sample.xpm +0 -251
- data/samples/sample1/art/sample.xpm +0 -251
- data/samples/sample2/art/sample.xpm +0 -251
- data/samples/sample3/art/sample.xpm +0 -251
- data/samples/sample4/art/sample.xpm +0 -251
@@ -0,0 +1,389 @@
|
|
1
|
+
# Wx::SF::BoxShape - box shape class
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
3
|
+
|
4
|
+
require 'wx/shapes/shapes/rect_shape'
|
5
|
+
require 'wx/shapes/shapes/manager_shape'
|
6
|
+
|
7
|
+
module Wx::SF
|
8
|
+
|
9
|
+
# Class encapsulates a rectangular shape derived from Wx::SF::RectShape class which acts as a box-shaped
|
10
|
+
# container able to manage other assigned child shapes (it can control their position). The managed
|
11
|
+
# shapes are stacked into defined box (slots) according to it's primary orientation with a behaviour similar to
|
12
|
+
# classic Wx::BoxSizer class. The box will be automatically resized along it's primary axis to accommodate
|
13
|
+
# the combined sizes of the managed shapes. The minimum size of the box along it's secondary axis is
|
14
|
+
# determined by the maximum size of the managed shapes.
|
15
|
+
# When adding or removing shapes the stack of shapes will always be kept contiguous (without empty slots).
|
16
|
+
# Managed shapes will never be resized along the primary axis but may be resized and/or positioned along
|
17
|
+
# the secondary axis according to the contained shape's alignment setting (EXPAND).
|
18
|
+
class BoxShape < RectShape
|
19
|
+
|
20
|
+
include ManagerShape
|
21
|
+
|
22
|
+
# Orientation values
|
23
|
+
class ORIENTATION < Wx::Enum
|
24
|
+
HORIZONTAL = self.new(0)
|
25
|
+
VERTICAL = self.new(1)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Default values
|
29
|
+
class DEFAULT
|
30
|
+
# default box orientation
|
31
|
+
ORIENTATION = ORIENTATION::HORIZONTAL
|
32
|
+
# Default value of GridShape @cell_space data member.
|
33
|
+
SPACING = 3
|
34
|
+
end
|
35
|
+
|
36
|
+
class << self
|
37
|
+
|
38
|
+
# Returns the minimum size for *empty* boxes
|
39
|
+
# @return [Wx::Size]
|
40
|
+
def get_min_size
|
41
|
+
@min_size ||= Wx::Size.new(20, 20)
|
42
|
+
end
|
43
|
+
alias :min_size :get_min_size
|
44
|
+
|
45
|
+
# Sets the minimum size for *empty* boxes
|
46
|
+
# @overload set_min_size(sz)
|
47
|
+
# @param [Wx::Size] sz
|
48
|
+
# @overload set_min_size(w, h)
|
49
|
+
# @param [Integer] w
|
50
|
+
# @param [Integer] h
|
51
|
+
def set_min_size(arg1, arg2 = nil)
|
52
|
+
@min_size = if arg2.nil?
|
53
|
+
raise ArgumentError, 'Expected Wx::Size' unless Wx::Size === arg1
|
54
|
+
arg1
|
55
|
+
else
|
56
|
+
Wx::Size.new(arg1, arg2)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
alias :min_size= :set_min_size
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
property :spacing, :orientation, :slots
|
64
|
+
|
65
|
+
# Constructor.
|
66
|
+
# @param [Wx::RealPoint,Wx::Point] pos Initial position
|
67
|
+
# @param [Wx::RealPoint,Wx::Point,Wx::Size] size Initial size
|
68
|
+
# @param [Wx::SF::BoxShape::ORIENTATION] orientation box orientation
|
69
|
+
# @param [Integer] spacing Additional space between managed shapes
|
70
|
+
# @param [Wx::SF::Diagram] diagram parent diagram
|
71
|
+
def initialize(pos = Shape::DEFAULT::POSITION, size = RectShape::DEFAULT::SIZE, orientation: DEFAULT::ORIENTATION, spacing: DEFAULT::SPACING, diagram: nil)
|
72
|
+
super(pos, size, diagram: diagram)
|
73
|
+
@orientation = orientation || DEFAULT::ORIENTATION
|
74
|
+
@spacing = spacing || 0
|
75
|
+
@slots = []
|
76
|
+
end
|
77
|
+
|
78
|
+
# Get the box shape orientation.
|
79
|
+
# @return [Wx::SF::BoxShape::ORIENTATION]
|
80
|
+
def get_orientation
|
81
|
+
@orientation
|
82
|
+
end
|
83
|
+
alias :orientation :get_orientation
|
84
|
+
|
85
|
+
# Get number of filled slots (i.e. managed shapes)
|
86
|
+
# @return [Integer]
|
87
|
+
def get_slot_count
|
88
|
+
@slots.size
|
89
|
+
end
|
90
|
+
alias :slot_count :get_slot_count
|
91
|
+
|
92
|
+
# Set space between slots (managed shapes).
|
93
|
+
# @param [Integer] spacing Spacing size
|
94
|
+
# @return [Integer] new spacing size
|
95
|
+
def set_spacing(spacing)
|
96
|
+
@spacing = spacing
|
97
|
+
end
|
98
|
+
alias :spacing= :set_spacing
|
99
|
+
|
100
|
+
# Get space between slots (managed shapes).
|
101
|
+
# @return [Integer] Spacing size
|
102
|
+
def get_spacing
|
103
|
+
@spacing
|
104
|
+
end
|
105
|
+
alias :spacing :get_spacing
|
106
|
+
|
107
|
+
# Iterate all slots. If a block is given passes slot index and shape for each slot to block.
|
108
|
+
# Returns Enumerator if no block given.
|
109
|
+
# @overload each_slot()
|
110
|
+
# @return [Enumerator]
|
111
|
+
# @overload each_slot(&block)
|
112
|
+
# @yieldparam [Integer] slot
|
113
|
+
# @yieldparam [Shape,nil] shape
|
114
|
+
# @return [Object]
|
115
|
+
def each_slot(&block)
|
116
|
+
if block
|
117
|
+
@slots.each_with_index do |shape, slot|
|
118
|
+
block.call(slot, shape)
|
119
|
+
end
|
120
|
+
else
|
121
|
+
::Enumerator.new do |y|
|
122
|
+
@slots.each_with_index do |shape, slot|
|
123
|
+
y << [slot, shape]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Get managed shape specified by slot index.
|
130
|
+
# @param [Integer] slot slot index of requested shape
|
131
|
+
# @return [Shape, nil] shape object of given slot if exists, otherwise nil
|
132
|
+
def get_managed_shape(slot)
|
133
|
+
@slots[slot]
|
134
|
+
end
|
135
|
+
|
136
|
+
# Clear information about managed shapes and remove all slots.
|
137
|
+
#
|
138
|
+
# Note that this function doesn't remove managed (child) shapes from the parent box shape
|
139
|
+
# (they are still its child shapes but aren't managed anymore).
|
140
|
+
def clear_box
|
141
|
+
@slots.clear
|
142
|
+
end
|
143
|
+
|
144
|
+
# Append given shape to the box at the last managed position.
|
145
|
+
# @param [Shape] shape shape to append
|
146
|
+
# @return [Boolean] true on success, otherwise false
|
147
|
+
def append_to_box(shape)
|
148
|
+
insert_to_box(@slots.size, shape)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Insert given shape to the box at the given position.
|
152
|
+
# The given shape is inserted before the existing item at index 'slot', thus insert_to_box(0, something)
|
153
|
+
# will insert an item in such way that it will become the first box element. Any occupied slots at given
|
154
|
+
# position or beyond will be shifted to the next position.
|
155
|
+
# @param [Integer] slot slot index for inserted shape
|
156
|
+
# @param [Shape] shape shape to insert
|
157
|
+
# @return [Boolean] true on success, otherwise false
|
158
|
+
def insert_to_box(slot, shape)
|
159
|
+
if shape && shape.is_a?(Shape) && is_child_accepted(shape.class)
|
160
|
+
# protect duplicated occurrences
|
161
|
+
return false if @slots.index(shape)
|
162
|
+
|
163
|
+
# protect unbounded index
|
164
|
+
return false if slot > @slots.size
|
165
|
+
|
166
|
+
# add the shape to the children list if necessary
|
167
|
+
unless @child_shapes.include?(shape)
|
168
|
+
if @diagram
|
169
|
+
@diagram.reparent_shape(shape, self)
|
170
|
+
else
|
171
|
+
shape.set_parent_shape(self)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
@slots.insert(slot, shape)
|
176
|
+
|
177
|
+
return true
|
178
|
+
end
|
179
|
+
false
|
180
|
+
end
|
181
|
+
|
182
|
+
# Remove given shape from the box.
|
183
|
+
# Shifts any occupied cells beyond the slots containing the given shape to the previous position.
|
184
|
+
# @param [Shape] shape shape which should be removed
|
185
|
+
# @note Note this does *not* remove the shape as a child shape.
|
186
|
+
def remove_from_box(shape)
|
187
|
+
@slots.delete(shape)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Update shape (align all child shapes and resize it to fit them)
|
191
|
+
def update(recurse = true)
|
192
|
+
# check for stale links to of de-assigned shapes
|
193
|
+
@slots.delete_if do |shape|
|
194
|
+
!@child_shapes.include?(shape)
|
195
|
+
end
|
196
|
+
|
197
|
+
# check whether all child shapes are present in the slots array...
|
198
|
+
@child_shapes.each do |child|
|
199
|
+
unless @slots.include?(child)
|
200
|
+
# see if we can match the position of the new child with the position of another
|
201
|
+
# (previously assigned) managed shape
|
202
|
+
find_child_slot(child)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# do self-alignment
|
207
|
+
do_alignment
|
208
|
+
|
209
|
+
# fit the shape to its children
|
210
|
+
fit_to_children unless has_style?(STYLE::NO_FIT_TO_CHILDREN)
|
211
|
+
|
212
|
+
# do it recursively on all parent shapes
|
213
|
+
if recurse && (parent = get_parent_shape)
|
214
|
+
parent.update(recurse)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Resize the shape to bound all child shapes. The function can be overridden if necessary.
|
219
|
+
def fit_to_children
|
220
|
+
# get bounding box of the shape and children set to be inside it
|
221
|
+
abs_pos = get_absolute_position
|
222
|
+
ch_bb = Wx::Rect.new(abs_pos.to_point, [0, 0])
|
223
|
+
|
224
|
+
@child_shapes.each do |child|
|
225
|
+
ch_bb = child.get_complete_bounding_box(ch_bb, BBMODE::SELF | BBMODE::CHILDREN) if child.has_style?(STYLE::ALWAYS_INSIDE)
|
226
|
+
end
|
227
|
+
|
228
|
+
if @child_shapes.empty?
|
229
|
+
# do not let the empty box shape 'disappear' due to zero sizes...
|
230
|
+
ch_bb.width = get_h_align == HALIGN::EXPAND ? @rect_size.x.to_i-@spacing : GridShape.min_size.width
|
231
|
+
ch_bb.height = get_v_align == VALIGN::EXPAND ? @rect_size.y.to_i-@spacing : GridShape.min_size.height
|
232
|
+
end
|
233
|
+
|
234
|
+
@rect_size = Wx::RealPoint.new(ch_bb.width + @spacing, ch_bb.height + @spacing)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Event handler called when any shape is dropped above this shape (and the dropped
|
238
|
+
# shape is accepted as a child of this shape). The function can be overridden if necessary.
|
239
|
+
#
|
240
|
+
# The function is called by the framework (by the shape canvas).
|
241
|
+
# @param [Wx::RealPoint] _pos Relative position of dropped shape
|
242
|
+
# @param [Shape] child dropped shape
|
243
|
+
def on_child_dropped(_pos, child)
|
244
|
+
# see if we can match the position of the new child with the position of another
|
245
|
+
# (previously assigned) managed shape
|
246
|
+
if child && !child.is_a?(LineShape)
|
247
|
+
# if the child already had a slot
|
248
|
+
if @slots.index(child)
|
249
|
+
# remove it from there; this provides support for reordering child shapes by dragging
|
250
|
+
remove_from_box(child)
|
251
|
+
end
|
252
|
+
|
253
|
+
# insert child based on it's current (possibly dropped) position
|
254
|
+
find_child_slot(child)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
protected
|
259
|
+
|
260
|
+
# Do layout of assigned child shapes
|
261
|
+
def do_children_layout
|
262
|
+
return if @slots.empty?
|
263
|
+
|
264
|
+
max_size = 0
|
265
|
+
|
266
|
+
# get maximum size of all managed (child) shapes
|
267
|
+
@child_shapes.each do |shape|
|
268
|
+
curr_rect = shape.get_bounding_box
|
269
|
+
curr_rect.inflate!(shape.h_border.abs.to_i, shape.v_border.abs.to_i)
|
270
|
+
|
271
|
+
if @orientation == ORIENTATION::VERTICAL
|
272
|
+
max_size = curr_rect.width if shape.get_h_align != HALIGN::EXPAND && curr_rect.width > max_size
|
273
|
+
else
|
274
|
+
max_size = curr_rect.height if shape.get_v_align != VALIGN::EXPAND && curr_rect.height > max_size
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
# if this box itself is expanded for the appropriate dimension check the max child size against the box size
|
279
|
+
if @orientation == ORIENTATION::VERTICAL && get_h_align == HALIGN::EXPAND
|
280
|
+
box_rect = get_bounding_box
|
281
|
+
# if this box is horizontally expanded use it's width if larger
|
282
|
+
max_size = box_rect.width - 2*@spacing if (box_rect.width-2*@spacing) > max_size
|
283
|
+
elsif @orientation == ORIENTATION::HORIZONTAL && get_v_align == VALIGN::EXPAND
|
284
|
+
box_rect = get_bounding_box
|
285
|
+
# if this box is vertically expanded use it's height if larger
|
286
|
+
max_size = box_rect.height - 2*@spacing if (box_rect.height-2*@spacing) > max_size
|
287
|
+
end
|
288
|
+
|
289
|
+
offset = @spacing
|
290
|
+
@slots.each do |shape|
|
291
|
+
if @orientation == ORIENTATION::VERTICAL
|
292
|
+
shape_h = shape.get_bounding_box.height + (2*shape.get_v_border).to_i
|
293
|
+
fit_shape_to_rect(shape, Wx::Rect.new(@spacing,
|
294
|
+
offset,
|
295
|
+
max_size, shape_h))
|
296
|
+
offset += shape_h+@spacing
|
297
|
+
else
|
298
|
+
shape_w = shape.get_bounding_box.width + (2*shape.get_h_border).to_i
|
299
|
+
fit_shape_to_rect(shape, Wx::Rect.new(offset,
|
300
|
+
@spacing,
|
301
|
+
shape_w, max_size))
|
302
|
+
offset += shape_w+@spacing
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# called after the shape has been newly imported/pasted/dropped
|
308
|
+
# checks the slots for stale links
|
309
|
+
def on_import
|
310
|
+
# check for existence of non-included shapes
|
311
|
+
@slots.delete_if do |shape|
|
312
|
+
!@child_shapes.include?(shape)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def find_child_slot(child)
|
317
|
+
crct = child.get_bounding_box
|
318
|
+
# if the child intersects this box shape we look
|
319
|
+
# for the slot it should go into
|
320
|
+
if intersects?(crct)
|
321
|
+
# find the slot with a shape that is positioned below/after
|
322
|
+
# the new child
|
323
|
+
slot = @slots.find_index do |shape|
|
324
|
+
# determine if new child is positioned above/in front of existing child shape
|
325
|
+
srct = shape.get_bounding_box
|
326
|
+
if @orientation == ORIENTATION::VERTICAL
|
327
|
+
crct.bottom <= srct.bottom || crct.top <= srct.top
|
328
|
+
else
|
329
|
+
crct.right <= srct.right || crct.left <= srct.left
|
330
|
+
end
|
331
|
+
end
|
332
|
+
if slot # if found
|
333
|
+
# insert before other shape
|
334
|
+
@slots.insert(slot, child)
|
335
|
+
return
|
336
|
+
end
|
337
|
+
end
|
338
|
+
# otherwise append
|
339
|
+
@slots << child
|
340
|
+
end
|
341
|
+
|
342
|
+
private
|
343
|
+
|
344
|
+
# Deserialization only.
|
345
|
+
|
346
|
+
# Set the orientation of the box shape.
|
347
|
+
# @param [Wx::SF::BoxShape::ORIENTATION] orientation
|
348
|
+
def set_orientation(orientation)
|
349
|
+
@orientation = orientation
|
350
|
+
end
|
351
|
+
|
352
|
+
def get_slots
|
353
|
+
@slots
|
354
|
+
end
|
355
|
+
def set_slots(slots)
|
356
|
+
@slots = slots
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
# Convenience class encapsulating a BoxShape with vertical orientation.
|
362
|
+
class VBoxShape < BoxShape
|
363
|
+
|
364
|
+
# Constructor.
|
365
|
+
# @param [Wx::RealPoint,Wx::Point] pos Initial position
|
366
|
+
# @param [Wx::RealPoint,Wx::Point,Wx::Size] size Initial size
|
367
|
+
# @param [Integer] spacing Additional space between managed shapes
|
368
|
+
# @param [Wx::SF::Diagram] diagram parent diagram
|
369
|
+
def initialize(pos = Shape::DEFAULT::POSITION, size = RectShape::DEFAULT::SIZE, spacing: DEFAULT::SPACING, diagram: nil)
|
370
|
+
super(pos, size, orientation: ORIENTATION::VERTICAL, spacing: spacing, diagram: diagram)
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
374
|
+
|
375
|
+
# Convenience class encapsulating a BoxShape with horizontal orientation.
|
376
|
+
class HBoxShape < BoxShape
|
377
|
+
|
378
|
+
# Constructor.
|
379
|
+
# @param [Wx::RealPoint,Wx::Point] pos Initial position
|
380
|
+
# @param [Wx::RealPoint,Wx::Point,Wx::Size] size Initial size
|
381
|
+
# @param [Integer] spacing Additional space between managed shapes
|
382
|
+
# @param [Wx::SF::Diagram] diagram parent diagram
|
383
|
+
def initialize(pos = Shape::DEFAULT::POSITION, size = RectShape::DEFAULT::SIZE, spacing: DEFAULT::SPACING, diagram: nil)
|
384
|
+
super(pos, size, orientation: ORIENTATION::HORIZONTAL, spacing: spacing, diagram: diagram)
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
388
|
+
|
389
|
+
end
|
@@ -8,21 +8,18 @@ module Wx::SF
|
|
8
8
|
# Class encapsulating the circle shape.
|
9
9
|
class CircleShape < SquareShape
|
10
10
|
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
pos, rad, diagram = args
|
24
|
-
super(pos, rad*2, diagram)
|
25
|
-
end
|
11
|
+
# Default values
|
12
|
+
module DEFAULT
|
13
|
+
# Default circle radius
|
14
|
+
RADIUS = 25.0
|
15
|
+
end
|
16
|
+
|
17
|
+
# Constructor.
|
18
|
+
# @param [Wx::RealPoint] pos Initial position
|
19
|
+
# @param [Float] radius Initial circle radius
|
20
|
+
# @param [Wx::SF::Diagram] diagram parent diagram
|
21
|
+
def initialize(pos = Shape::DEFAULT::POSITION, radius = DEFAULT::RADIUS, diagram: nil)
|
22
|
+
super(pos, radius*2, diagram: diagram)
|
26
23
|
end
|
27
24
|
|
28
25
|
def get_radius
|
@@ -72,8 +69,8 @@ module Wx::SF
|
|
72
69
|
# HINT: overload it for custom actions...
|
73
70
|
pos = get_absolute_position
|
74
71
|
|
75
|
-
dc.with_pen(
|
76
|
-
dc.with_brush(
|
72
|
+
dc.with_pen(border) do
|
73
|
+
dc.with_brush(fill) do
|
77
74
|
dc.draw_circle((pos.x + @rect_size.x/2).to_i,
|
78
75
|
(pos.y + @rect_size.y/2).to_i,
|
79
76
|
(@rect_size.x/2).to_i)
|
@@ -88,8 +85,8 @@ module Wx::SF
|
|
88
85
|
# HINT: overload it for custom actions...
|
89
86
|
pos = get_absolute_position
|
90
87
|
|
91
|
-
dc.with_pen(Wx::Pen.new(
|
92
|
-
dc.with_brush(
|
88
|
+
dc.with_pen(Wx::Pen.new(hover_colour, 1)) do
|
89
|
+
dc.with_brush(fill) do
|
93
90
|
dc.draw_circle((pos.x + @rect_size.x/2).to_i,
|
94
91
|
(pos.y + @rect_size.y/2).to_i,
|
95
92
|
(@rect_size.x/2).to_i)
|
@@ -105,8 +102,8 @@ module Wx::SF
|
|
105
102
|
# HINT: overload it for custom actions...
|
106
103
|
pos = get_absolute_position
|
107
104
|
|
108
|
-
dc.with_pen(Wx::Pen.new(
|
109
|
-
dc.with_brush(
|
105
|
+
dc.with_pen(Wx::Pen.new(hover_colour, 2)) do
|
106
|
+
dc.with_brush(fill) do
|
110
107
|
dc.draw_circle((pos.x + @rect_size.x/2).to_i,
|
111
108
|
(pos.y + @rect_size.y/2).to_i,
|
112
109
|
(@rect_size.x/2).to_i)
|
@@ -120,7 +117,7 @@ module Wx::SF
|
|
120
117
|
# HINT: overload it for custom actions...
|
121
118
|
pos = get_absolute_position
|
122
119
|
|
123
|
-
if
|
120
|
+
if fill.style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
|
124
121
|
dc.with_pen(Wx::TRANSPARENT_PEN) do
|
125
122
|
dc.with_brush(get_parent_canvas.get_shadow_fill) do
|
126
123
|
dc.draw_circle((pos.x + @rect_size.x/2 + get_parent_canvas.get_shadow_offset.x).to_i,
|
@@ -123,35 +123,29 @@ module Wx::SF
|
|
123
123
|
module DEFAULT
|
124
124
|
CONTROLOFFSET = 0
|
125
125
|
PROCESSEVENTS = EVTPROCESSING::KEY2CANVAS | EVTPROCESSING::MOUSE2CANVAS
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
property :event_processing, :control_offset, :mod_fill, :mod_border
|
133
|
-
|
134
|
-
# @overload initialize()
|
135
|
-
# Default constructor.
|
136
|
-
# @overload initialize(pos, size, diagram)
|
137
|
-
# User constructor.
|
138
|
-
# @param [Wx::Window] ctrl managed GUI control
|
139
|
-
# @param [Wx::RealPoint] pos Initial position
|
140
|
-
# @param [Wx::RealPoint] size Initial size
|
141
|
-
# @param [Wx::SF::Diagram] diagram parent diagram
|
142
|
-
def initialize(*args)
|
143
|
-
if args.empty?
|
144
|
-
super
|
145
|
-
@control = nil
|
146
|
-
else
|
147
|
-
ctrl = args.shift
|
148
|
-
super(*args)
|
149
|
-
set_control(ctrl)
|
126
|
+
class << self
|
127
|
+
def mod_fill; @mod_fill ||= Wx::Brush.new(Wx::BLUE, Wx::BrushStyle::BRUSHSTYLE_BDIAGONAL_HATCH); end
|
128
|
+
def mod_border; @mod_border ||= Wx::Pen.new(Wx::BLUE, 1, Wx::PenStyle::PENSTYLE_SOLID); end
|
129
|
+
def ctrl_fill; @ctrl_fill ||= Wx::TRANSPARENT_BRUSH.dup; end
|
130
|
+
def ctrl_border; @ctrl_border ||= Wx::TRANSPARENT_PEN.dup; end
|
150
131
|
end
|
132
|
+
end
|
133
|
+
|
134
|
+
property :event_processing, :control_offset
|
135
|
+
property({ mod_fill: :serialize_mod_fill, mod_border: :serialize_mod_border }, optional: true)
|
136
|
+
|
137
|
+
# Constructor.
|
138
|
+
# @param [Wx::RealPoint] pos Initial position
|
139
|
+
# @param [Wx::RealPoint] size Initial size
|
140
|
+
# @param [Wx::Window] control managed GUI control
|
141
|
+
# @param [Wx::SF::Diagram] diagram parent diagram
|
142
|
+
def initialize(pos = Shape::DEFAULT::POSITION, size = RectShape::DEFAULT::SIZE, control: nil, diagram: nil)
|
143
|
+
super(pos, size, diagram: diagram)
|
144
|
+
set_control(control)
|
151
145
|
add_style(Shape::STYLE::PROCESS_DEL)
|
152
146
|
@process_events = DEFAULT::PROCESSEVENTS
|
153
|
-
@mod_fill =
|
154
|
-
@mod_border =
|
147
|
+
@mod_fill = nil
|
148
|
+
@mod_border = nil
|
155
149
|
@control_offset = DEFAULT::CONTROLOFFSET
|
156
150
|
|
157
151
|
@event_sink = EventSink.new(self)
|
@@ -160,9 +154,6 @@ module Wx::SF
|
|
160
154
|
@prev_style = 0
|
161
155
|
@prev_fill = nil
|
162
156
|
@prev_border = nil
|
163
|
-
|
164
|
-
@fill = Wx::TRANSPARENT_BRUSH
|
165
|
-
@border = Wx::TRANSPARENT_PEN
|
166
157
|
end
|
167
158
|
|
168
159
|
# Set managed GUI control.
|
@@ -211,6 +202,20 @@ module Wx::SF
|
|
211
202
|
end
|
212
203
|
end
|
213
204
|
|
205
|
+
# Get current fill style.
|
206
|
+
# @return [Wx::Brush] Current brush
|
207
|
+
def get_fill
|
208
|
+
@fill || (@diagram&.shape_canvas ? @diagram.shape_canvas.control_fill : DEFAULT.ctrl_fill)
|
209
|
+
end
|
210
|
+
alias :fill :get_fill
|
211
|
+
|
212
|
+
# Get current border style.
|
213
|
+
# @return [Wx::Pen] Current pen
|
214
|
+
def get_border
|
215
|
+
@border || (@diagram&.shape_canvas ? @diagram.shape_canvas.control_border : DEFAULT.ctrl_border)
|
216
|
+
end
|
217
|
+
alias :border :get_border
|
218
|
+
|
214
219
|
# Get managed GUI control.
|
215
220
|
# @return [Wx::Window] the GUI control
|
216
221
|
def get_control
|
@@ -232,27 +237,46 @@ module Wx::SF
|
|
232
237
|
end
|
233
238
|
|
234
239
|
# Set control shape's background style used during its modification.
|
235
|
-
# @
|
236
|
-
|
237
|
-
|
240
|
+
# @overload set_mod_fill(brush)
|
241
|
+
# @param [Wx::Brush] brush
|
242
|
+
# @overload set_mod_fill(color, style=Wx::BrushStyle::BRUSHSTYLE_SOLID)
|
243
|
+
# @param [Wx::Colour,Symbol,String] color brush color
|
244
|
+
# @param [Wx::BrushStyle] style
|
245
|
+
# @overload set_mod_fill(stipple_bitmap)
|
246
|
+
# @param [Wx::Bitmap] stipple_bitmap
|
247
|
+
def set_mod_fill(*args)
|
248
|
+
@mod_fill = if args.size == 1 && Wx::Brush === args.first
|
249
|
+
args.first
|
250
|
+
else
|
251
|
+
Wx::Brush.new(*args)
|
252
|
+
end
|
238
253
|
end
|
239
254
|
|
240
255
|
# Get control shape's background style used during its modification.
|
241
256
|
# @return [Wx::Brush] Used brush
|
242
257
|
def get_mod_fill
|
243
|
-
@mod_fill
|
258
|
+
@mod_fill || (@diagram&.shape_canvas ? @diagram.shape_canvas.control_mod_fill : DEFAULT.mod_fill)
|
244
259
|
end
|
245
260
|
|
246
261
|
# Set control shape's border style used during its modification.
|
247
|
-
# @
|
262
|
+
# @overload set_mod_border(pen)
|
263
|
+
# @param [Wx::Pen] pen
|
264
|
+
# @overload set_mod_border(color, width=1, style=Wx::PenStyle::PENSTYLE_SOLID)
|
265
|
+
# @param [Wx::Colour,String,Symbol] color
|
266
|
+
# @param [Integer] width
|
267
|
+
# @param [Wx::PenStyle] style
|
248
268
|
def set_mod_border(pen)
|
249
|
-
@mod_border =
|
269
|
+
@mod_border = if args.size == 1 && Wx::Pen === args.first
|
270
|
+
args.first
|
271
|
+
else
|
272
|
+
Wx::Pen.new(*args)
|
273
|
+
end
|
250
274
|
end
|
251
275
|
|
252
276
|
# Get control shape's border style used during its modification.
|
253
277
|
# @return [Wx::Pen] Used pen
|
254
278
|
def get_mod_border
|
255
|
-
@mod_border
|
279
|
+
@mod_border || (@diagram&.shape_canvas ? @diagram.shape_canvas.control_mod_border : DEFAULT.mod_border)
|
256
280
|
end
|
257
281
|
|
258
282
|
# Set control shape's offset (a gap between the shape's border and managed GUI control).
|
@@ -315,7 +339,7 @@ module Wx::SF
|
|
315
339
|
# @param [Float] x Horizontal scale factor
|
316
340
|
# @param [Float] y Vertical scale factor
|
317
341
|
# @param children true if the shape's children should be scaled as well, otherwise the shape will be updated after scaling via update() function.
|
318
|
-
def scale(x, y, children
|
342
|
+
def scale(x, y, children: WITHCHILDREN)
|
319
343
|
super
|
320
344
|
update_control
|
321
345
|
end
|
@@ -337,7 +361,7 @@ module Wx::SF
|
|
337
361
|
end
|
338
362
|
|
339
363
|
# Update shape (align all child shapes an resize it to fit them)
|
340
|
-
def update
|
364
|
+
def update(recurse = true)
|
341
365
|
super
|
342
366
|
update_control
|
343
367
|
end
|
@@ -365,7 +389,7 @@ module Wx::SF
|
|
365
389
|
# @see ShapeCanvas
|
366
390
|
def on_begin_drag(pos)
|
367
391
|
@prev_fill = @fill
|
368
|
-
@fill =
|
392
|
+
@fill = get_mod_fill
|
369
393
|
canvas = get_parent_canvas
|
370
394
|
if canvas
|
371
395
|
@prev_style = canvas.get_style
|
@@ -406,9 +430,9 @@ module Wx::SF
|
|
406
430
|
# @param [Shape::Handle] handle Reference to dragged handle
|
407
431
|
def on_begin_handle(handle)
|
408
432
|
@prev_border = @border
|
409
|
-
@border =
|
433
|
+
@border = get_mod_border
|
410
434
|
@prev_fill = @fill
|
411
|
-
@fill =
|
435
|
+
@fill = get_mod_fill
|
412
436
|
|
413
437
|
if @control
|
414
438
|
@control.hide
|
@@ -478,6 +502,18 @@ module Wx::SF
|
|
478
502
|
end
|
479
503
|
end
|
480
504
|
|
505
|
+
# (de-)serialize mod_fill; allows for nil values
|
506
|
+
def serialize_mod_fill(*val)
|
507
|
+
@mod_fill = val.first unless val.empty?
|
508
|
+
@mod_fill
|
509
|
+
end
|
510
|
+
|
511
|
+
# (de-)serialize mod_fill; allows for nil values
|
512
|
+
def serialize_mod_border(*val)
|
513
|
+
@mod_border = val.first unless val.empty?
|
514
|
+
@mod_border
|
515
|
+
end
|
516
|
+
|
481
517
|
end
|
482
518
|
|
483
519
|
end
|