wxruby3-shapes 0.9.0.pre.beta.3 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|