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,131 @@
|
|
1
|
+
# Wx::SF::RoundOrthoLineShape - rounded orthogonal line shape class
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
3
|
+
|
4
|
+
require 'wx/shapes/shapes/ortho_shape'
|
5
|
+
|
6
|
+
module Wx::SF
|
7
|
+
|
8
|
+
# Rounded orthogonal line shape. The class extends OrthoLineShape class and allows
|
9
|
+
# user to create connection line orthogonal to base axis with round corners.
|
10
|
+
class RoundOrthoLineShape < OrthoLineShape
|
11
|
+
|
12
|
+
MAX_RADIUS = 7
|
13
|
+
|
14
|
+
property :max_radius
|
15
|
+
|
16
|
+
# @overload initialize()
|
17
|
+
# default constructor
|
18
|
+
# @overload initialize(src, trg, path, manager)
|
19
|
+
# @param [Wx::SF::Serializable::ID] src ID of the source shape
|
20
|
+
# @param [Wx::SF::Serializable::ID] trg ID of the target shape
|
21
|
+
# @param [Array<Wx::RealPoint>] path List of the line control points (can be empty)
|
22
|
+
# @param [Diagram] diagram containing diagram
|
23
|
+
def initialize(*args)
|
24
|
+
super
|
25
|
+
@max_radius = MAX_RADIUS
|
26
|
+
end
|
27
|
+
|
28
|
+
# Access (set/get) maximum radius.
|
29
|
+
attr_accessor :max_radius
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
# Draw one orthogonal line segment.
|
34
|
+
# @param [Wx::DC] dc Device context
|
35
|
+
# @param [Wx::RealPoint] src Starting point of the ortho line segment
|
36
|
+
# @param [Wx::RealPoint] trg Ending point of the ortho line segment
|
37
|
+
# @param [SEGMENTCPS] cps Connection points used by the line segment
|
38
|
+
def draw_line_segment(dc, src, trg, cps)
|
39
|
+
if (trg.x == src.x) || (trg.y == src.y)
|
40
|
+
dc.draw_line(src.to_point, trg.to_point)
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
direction = get_segment_direction(src, trg, cps)
|
45
|
+
src_pt = src.to_point
|
46
|
+
trg_pt = trg.to_point
|
47
|
+
|
48
|
+
dx = trg.x - src.x
|
49
|
+
dy = trg.y - src.y
|
50
|
+
kx = dx < 0 ? -1 : 1
|
51
|
+
ky = dy < 0 ? 1 : -1
|
52
|
+
|
53
|
+
pt_center = Wx::RealPoint.new((src.x + trg.x)/2, (src.y + trg.y)/2)
|
54
|
+
|
55
|
+
dc.with_brush(Wx::TRANSPARENT_BRUSH) do
|
56
|
+
|
57
|
+
if is_two_segment(cps)
|
58
|
+
if direction < 1.0
|
59
|
+
r = (dy * @max_radius/100).abs
|
60
|
+
r = @max_radius if r > @max_radius
|
61
|
+
|
62
|
+
dc.draw_line(src_pt.x, src_pt.y, (trg.x - r * kx).to_i, src_pt.y)
|
63
|
+
dc.draw_line(trg_pt.x, (src.y - r * ky).to_i, trg_pt.x, trg_pt.y)
|
64
|
+
|
65
|
+
if r > 0
|
66
|
+
if (ky > 0 && kx > 0) || (ky < 0 && kx < 0)
|
67
|
+
dc.draw_arc((trg.x - r * kx).to_i, src_pt.y, trg_pt.x, (src.y - r * ky).to_i, (trg.x - r * kx).to_i, (src.y - r * ky).to_i)
|
68
|
+
else
|
69
|
+
dc.draw_arc(trg_pt.x, (src.y - r * ky).to_i, (trg.x - r * kx).to_i, src_pt.y, (trg.x - r * kx).to_i, (src.y - r * ky).to_i)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
else
|
73
|
+
r = (dx * @max_radius/100).abs
|
74
|
+
r = @max_radius if r > @max_radius
|
75
|
+
|
76
|
+
dc.draw_line(src_pt.x, src_pt.y, src_pt.x, (trg.y + r * ky).to_i)
|
77
|
+
dc.draw_line((src.x + r * kx).to_i, trg_pt.y, trg_pt.x, trg_pt.y)
|
78
|
+
|
79
|
+
if r > 0
|
80
|
+
if (ky > 0 && kx > 0) || (ky < 0 && kx < 0)
|
81
|
+
dc.draw_arc((src.x + r * kx).to_i, trg_pt.y, src_pt.x, (trg.y + r * ky).to_i, (src.x + r * kx).to_i, (trg.y + r * ky).to_i)
|
82
|
+
else
|
83
|
+
dc.draw_arc(src_pt.x, (trg.y + r * ky).to_i, (src.x + r * kx).to_i, trg_pt.y, (src.x + r * kx).to_i, (trg.y + r * ky).to_i)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
else
|
89
|
+
if direction < 1
|
90
|
+
r = (dy * @max_radius/100).abs
|
91
|
+
r = @max_radius if r > @max_radius
|
92
|
+
|
93
|
+
dc.draw_line(src_pt.x, src_pt.y, (pt_center.x - r * kx).to_i, src_pt.y)
|
94
|
+
dc.draw_line(pt_center.x.to_i, (src.y - r * ky).to_i, pt_center.x.to_i, (trg.y + r * ky).to_i)
|
95
|
+
dc.draw_line((pt_center.x + r * kx).to_i, trg_pt.y, trg_pt.x, trg_pt.y)
|
96
|
+
|
97
|
+
if r > 0
|
98
|
+
if (ky > 0 && kx > 0) || (ky < 0 && kx < 0)
|
99
|
+
dc.draw_arc((pt_center.x - r * kx).to_i, src_pt.y, pt_center.x.to_i, (src.y - r * ky).to_i, (pt_center.x - r * kx).to_i, (src.y - r * ky).to_i)
|
100
|
+
dc.draw_arc((pt_center.x + r * kx).to_i, trg_pt.y, pt_center.x.to_i, (trg.y + r * ky).to_i, (pt_center.x + r * kx).to_i, (trg.y + r * ky).to_i)
|
101
|
+
else
|
102
|
+
dc.draw_arc(pt_center.x.to_i, (src.y - r * ky).to_i, (pt_center.x - r * kx).to_i, src_pt.y, (pt_center.x - r * kx).to_i, (src.y - r * ky).to_i)
|
103
|
+
dc.draw_arc(pt_center.x.to_i, (trg.y + r * ky).to_i, (pt_center.x + r * kx).to_i, trg_pt.y, (pt_center.x + r * kx).to_i, (trg.y + r * ky).to_i)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
r = (dx * @max_radius/100).abs
|
108
|
+
r = @max_radius if r > @max_radius
|
109
|
+
|
110
|
+
dc.draw_line(src_pt.x, src_pt.y, src_pt.x, (pt_center.y + r * ky).to_i)
|
111
|
+
dc.draw_line((src.x + r * kx).to_i, pt_center.y.to_i, (trg.x - r * kx).to_i, pt_center.y.to_i)
|
112
|
+
dc.draw_line(trg_pt.x, (pt_center.y - r * ky).to_i, trg_pt.x, trg_pt.y)
|
113
|
+
|
114
|
+
if r > 0
|
115
|
+
if (ky > 0 && kx > 0) || (ky < 0 && kx < 0)
|
116
|
+
dc.draw_arc((src.x + r * kx).to_i, pt_center.y.to_i, src_pt.x, (pt_center.y + r * ky).to_i, (src.x + r * kx).to_i, (pt_center.y + r * ky).to_i)
|
117
|
+
dc.draw_arc((trg.x - r * kx).to_i, pt_center.y.to_i, trg_pt.x, (pt_center.y - r * ky).to_i, (trg.x - r * kx).to_i, (pt_center.y - r * ky).to_i)
|
118
|
+
else
|
119
|
+
dc.draw_arc(src_pt.x, (pt_center.y + r * ky).to_i, (src.x + r * kx).to_i, pt_center.y.to_i, (src.x + r * kx).to_i, (pt_center.y + r * ky).to_i)
|
120
|
+
dc.draw_arc(trg_pt.x, (pt_center.y - r * ky).to_i, (trg.x - r * kx).to_i, pt_center.y.to_i, (trg.x - r * kx).to_i, (pt_center.y - r * ky).to_i)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# Wx::SF::RoundRectShape - rounded rectangle shape class
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
3
|
+
|
4
|
+
module Wx::SF
|
5
|
+
|
6
|
+
# Class encapsulating rounded rectangle. It extends the basic rectangular shape.
|
7
|
+
class RoundRectShape < RectShape
|
8
|
+
|
9
|
+
RADIUS = 20
|
10
|
+
|
11
|
+
property :radius
|
12
|
+
|
13
|
+
# @overload initialize()
|
14
|
+
# Default constructor.
|
15
|
+
# @overload initialize(pos, size, diagram)
|
16
|
+
# User constructor.
|
17
|
+
# @param [Wx::RealPoint] pos Initial position
|
18
|
+
# @param [Wx::RealPoint] size Initial size
|
19
|
+
# @param [Float] radius Corner radius
|
20
|
+
# @param [Wx::SF::Diagram] diagram parent diagram
|
21
|
+
def initialize(*args)
|
22
|
+
if args.empty?
|
23
|
+
super
|
24
|
+
@radius = RADIUS
|
25
|
+
else
|
26
|
+
pos, size, @radius, diagram = args
|
27
|
+
super(pos, size, diagram)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Access (get/set) radius.
|
32
|
+
attr_accessor :radius
|
33
|
+
|
34
|
+
# Test whether the given point is inside the shape. The function
|
35
|
+
# can be overridden if necessary.
|
36
|
+
# @param [Wx::Point] pos Examined point
|
37
|
+
# @return [Boolean] true if the point is inside the shape area, otherwise false
|
38
|
+
def contains?(pos)
|
39
|
+
return super if @radius == 0.0
|
40
|
+
|
41
|
+
pos = pos.to_point
|
42
|
+
# get original bounding box
|
43
|
+
shp_bb = get_bounding_box
|
44
|
+
|
45
|
+
# calculate modified boxes
|
46
|
+
hr = shp_bb.deflate(0, @radius.to_i)
|
47
|
+
vr = shp_bb.deflate(@radius.to_i, 0)
|
48
|
+
|
49
|
+
# test whether given position is inside body rect or rounded corners
|
50
|
+
if hr.contains?(pos)
|
51
|
+
return true
|
52
|
+
elsif vr.contains?(pos)
|
53
|
+
return true
|
54
|
+
elsif in_circle?(pos, shp_bb.top_left + [@radius, @radius.to_i])
|
55
|
+
return true
|
56
|
+
elsif in_circle?(pos, shp_bb.bottom_left + [@radius.to_i, -@radius.to_i])
|
57
|
+
return true
|
58
|
+
elsif in_circle?(pos, shp_bb.top_right + [-@radius.to_i, @radius.to_i])
|
59
|
+
return true
|
60
|
+
elsif in_circle?(pos, shp_bb.bottom_right + [-@radius.to_i, -@radius.to_i])
|
61
|
+
return true
|
62
|
+
end
|
63
|
+
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
# Draw the shape in the normal way. The function can be overridden if necessary.
|
70
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
71
|
+
def draw_normal(dc)
|
72
|
+
if @radius == 0.0
|
73
|
+
super
|
74
|
+
return
|
75
|
+
end
|
76
|
+
dc.with_pen(@border) do
|
77
|
+
dc.with_brush(@fill) do
|
78
|
+
dc.draw_rounded_rectangle(get_absolute_position.to_point, @rect_size.to_size, @radius)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Draw the shape in the hover mode (the mouse cursor is above the shape).
|
84
|
+
# The function can be overridden if necessary.
|
85
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
86
|
+
def draw_hover(dc)
|
87
|
+
if @radius == 0.0
|
88
|
+
super
|
89
|
+
return
|
90
|
+
end
|
91
|
+
dc.with_pen(Wx::Pen.new(@hover_color, 1)) do
|
92
|
+
dc.with_brush(@fill) do
|
93
|
+
dc.draw_rounded_rectangle(get_absolute_position.to_point, @rect_size.to_size, @radius)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Draw the shape in the highlighted mode (another shape is dragged over this
|
99
|
+
# shape and this shape will accept the dragged one if it will be dropped on it).
|
100
|
+
# The function can be overridden if necessary.
|
101
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
102
|
+
def draw_highlighted(dc)
|
103
|
+
if @radius == 0.0
|
104
|
+
super
|
105
|
+
return
|
106
|
+
end
|
107
|
+
dc.with_pen(Wx::Pen.new(@hover_color, 2)) do
|
108
|
+
dc.with_brush(@fill) do
|
109
|
+
dc.draw_rounded_rectangle(get_absolute_position.to_point, @rect_size.to_size, @radius)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Draw shadow under the shape. The function can be overridden if necessary.
|
115
|
+
# @param [Wx::DC] dc Reference to device context where the shadow will be drawn to
|
116
|
+
def draw_shadow(dc)
|
117
|
+
if @radius == 0.0
|
118
|
+
super
|
119
|
+
return
|
120
|
+
end
|
121
|
+
if @fill.style != Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT
|
122
|
+
dc.with_pen(Wx::TRANSPARENT_PEN) do
|
123
|
+
dc.with_brush(get_parent_canvas.get_shadow_fill) do
|
124
|
+
dc.draw_rounded_rectangle((get_absolute_position + get_parent_canvas.get_shadow_offset).to_point,
|
125
|
+
@rect_size.to_size, @radius)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Auxiliary function. Checks whether the point is inside a circle with given center. The circle's radius
|
132
|
+
# is the rounded rect corner radius.
|
133
|
+
# @param [Wx::Point] pos Examined point
|
134
|
+
# @param [Wx::Point] center Circle center
|
135
|
+
# @return [Boolean]
|
136
|
+
def in_circle?(pos, center)
|
137
|
+
center.to_real_point.distance_to(pos.to_real_point) <= @radius
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Wx::SF::SquareShape - square shape class
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
3
|
+
|
4
|
+
require 'wx/shapes/shapes/rect_shape'
|
5
|
+
|
6
|
+
module Wx::SF
|
7
|
+
|
8
|
+
class SquareShape < RectShape
|
9
|
+
|
10
|
+
|
11
|
+
# @overload initialize()
|
12
|
+
# Default constructor.
|
13
|
+
# @overload initialize(pos, size, diagram)
|
14
|
+
# User constructor.
|
15
|
+
# @param [Wx::RealPoint] pos Initial position
|
16
|
+
# @param [Float] size Initial size
|
17
|
+
# @param [Wx::SF::Diagram] diagram parent diagram
|
18
|
+
def initialize(*args)
|
19
|
+
if args.empty?
|
20
|
+
super
|
21
|
+
set_rect_size(100,100)
|
22
|
+
else
|
23
|
+
pos, sz, diagram = args
|
24
|
+
super(pos, Wx::RealPoint.new(sz, sz), diagram)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get shape's center. Default implementation does nothing. The function can be overridden if necessary.
|
29
|
+
# @return [Wx::RealPoint] Center point
|
30
|
+
def get_center
|
31
|
+
# Optimize
|
32
|
+
get_absolute_position + [@rect_size.x/2, @rect_size.y/2]
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
# Scale the rectangle size for this shape.
|
38
|
+
# @param [Float] x Horizontal scale factor
|
39
|
+
# @param [Float] y Vertical scale factor
|
40
|
+
def scale_rectangle(x, y)
|
41
|
+
if x == 1.0
|
42
|
+
s = y
|
43
|
+
elsif y == 1.0
|
44
|
+
s = x
|
45
|
+
elsif x >= y
|
46
|
+
s = x
|
47
|
+
else
|
48
|
+
s = y
|
49
|
+
end
|
50
|
+
|
51
|
+
set_rect_size(@rect_size.x * s, @rect_size.y * s)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Handle's shape specific actions on handling handle events.
|
55
|
+
# The function can be overridden if necessary.
|
56
|
+
# @param [Shape::Handle] handle Reference to dragged handle
|
57
|
+
# @see #on_handle
|
58
|
+
def do_on_handle(handle)
|
59
|
+
prev_size = @rect_size.dup
|
60
|
+
|
61
|
+
# perform standard operations
|
62
|
+
case handle.type
|
63
|
+
when Shape::Handle::TYPE::LEFTTOP,
|
64
|
+
Shape::Handle::TYPE::LEFT,
|
65
|
+
Shape::Handle::TYPE::LEFTBOTTOM
|
66
|
+
on_left_handle(handle)
|
67
|
+
when Shape::Handle::TYPE::RIGHTTOP,
|
68
|
+
Shape::Handle::TYPE::RIGHT,
|
69
|
+
Shape::Handle::TYPE::RIGHTBOTTOM
|
70
|
+
on_right_handle(handle)
|
71
|
+
when Shape::Handle::TYPE::TOP
|
72
|
+
on_top_handle(handle)
|
73
|
+
when Shape::Handle::TYPE::BOTTOM
|
74
|
+
on_bottom_handle(handle)
|
75
|
+
end
|
76
|
+
|
77
|
+
# calculate common size and some auxiliary values
|
78
|
+
if (prev_size.x < @rect_size.x) || (prev_size.y < @rect_size.y)
|
79
|
+
if @rect_size.x >= @rect_size.y
|
80
|
+
maxsize = @rect_size.x
|
81
|
+
else
|
82
|
+
maxsize = @rect_size.y
|
83
|
+
end
|
84
|
+
else
|
85
|
+
if @rect_size.x <= @rect_size.y
|
86
|
+
maxsize = @rect_size.x
|
87
|
+
else
|
88
|
+
maxsize = @rect_size.y
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
dx = maxsize - @rect_size.x
|
93
|
+
dy = maxsize - @rect_size.y
|
94
|
+
|
95
|
+
# normalize rect sizes
|
96
|
+
@rect_size.x = @rect_size.y = maxsize
|
97
|
+
|
98
|
+
# move rect if necessary
|
99
|
+
case handle.type
|
100
|
+
when Shape::Handle::TYPE::LEFT
|
101
|
+
move_by(-dx, -dy / 2)
|
102
|
+
when Shape::Handle::TYPE::LEFTTOP
|
103
|
+
move_by(-dx, -dy)
|
104
|
+
when Shape::Handle::TYPE::LEFTBOTTOM
|
105
|
+
move_by(-dx, 0)
|
106
|
+
when Shape::Handle::TYPE::RIGHT
|
107
|
+
move_by(0, -dy / 2)
|
108
|
+
when Shape::Handle::TYPE::RIGHTTOP
|
109
|
+
move_by(0, -dy)
|
110
|
+
when Shape::Handle::TYPE::TOP
|
111
|
+
move_by(-dx / 2, -dy)
|
112
|
+
when Shape::Handle::TYPE::BOTTOM
|
113
|
+
move_by(-dx / 2, 0)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,324 @@
|
|
1
|
+
# Wx::SF::TextShape - text shape class
|
2
|
+
# Copyright (c) M.J.N. Corino, The Netherlands
|
3
|
+
|
4
|
+
require 'wx/shapes/shapes/rect_shape'
|
5
|
+
|
6
|
+
module Wx::SF
|
7
|
+
|
8
|
+
class TextShape < RectShape
|
9
|
+
|
10
|
+
# default values
|
11
|
+
module DEFAULT
|
12
|
+
# Default value of TextShape @font data member.
|
13
|
+
FONT = Wx::SWISS_FONT if Wx::App.is_main_loop_running
|
14
|
+
Wx.add_delayed_constant(self, :FONT) { Wx::SWISS_FONT }
|
15
|
+
# Default value of TextShape @text_color data member.
|
16
|
+
TEXTCOLOR = Wx::BLACK if Wx::App.is_main_loop_running
|
17
|
+
Wx.add_delayed_constant(self, :TEXTCOLOR) { Wx::BLACK }
|
18
|
+
end
|
19
|
+
|
20
|
+
property :font, :text_colour, :text
|
21
|
+
|
22
|
+
# @overload initialize()
|
23
|
+
# Default constructor.
|
24
|
+
# @overload initialize(pos, size, diagram)
|
25
|
+
# User constructor.
|
26
|
+
# @param [Wx::RealPoint] pos Initial position
|
27
|
+
# @param [String] txt Text content
|
28
|
+
# @param [Wx::SF::Diagram] diagram parent diagram
|
29
|
+
def initialize(*args)
|
30
|
+
txt = nil
|
31
|
+
if args.empty?
|
32
|
+
super
|
33
|
+
else
|
34
|
+
pos, txt, diagram = args
|
35
|
+
super(pos, Wx::RealPoint.new, diagram)
|
36
|
+
end
|
37
|
+
@font = DEFAULT::FONT
|
38
|
+
@font.set_point_size(12)
|
39
|
+
|
40
|
+
@line_height = 12
|
41
|
+
|
42
|
+
@text_color = DEFAULT::TEXTCOLOR
|
43
|
+
@text = txt || 'Text'
|
44
|
+
|
45
|
+
@fill = Wx::TRANSPARENT_BRUSH
|
46
|
+
@border = Wx::TRANSPARENT_PEN
|
47
|
+
@rect_size = Wx::RealPoint.new
|
48
|
+
|
49
|
+
update_rect_size
|
50
|
+
end
|
51
|
+
|
52
|
+
# Set text font.
|
53
|
+
# @param [Wx::Font] font Font
|
54
|
+
def set_font(font)
|
55
|
+
@font = font
|
56
|
+
update_rect_size
|
57
|
+
end
|
58
|
+
alias :font= :set_font
|
59
|
+
|
60
|
+
# Get text font.
|
61
|
+
# @return [Wx::Font] Font
|
62
|
+
def get_font
|
63
|
+
@font
|
64
|
+
end
|
65
|
+
alias :font :get_font
|
66
|
+
|
67
|
+
# Set text.
|
68
|
+
# @param [String] txt Text content
|
69
|
+
def set_text(txt)
|
70
|
+
@text = txt
|
71
|
+
update_rect_size
|
72
|
+
end
|
73
|
+
alias :text= :set_text
|
74
|
+
|
75
|
+
# Get text.
|
76
|
+
# @return [String] Current text content
|
77
|
+
def get_text
|
78
|
+
@text
|
79
|
+
end
|
80
|
+
alias :text :get_text
|
81
|
+
|
82
|
+
|
83
|
+
# Set text color.
|
84
|
+
# @param [Wx::Colour] col Text color
|
85
|
+
def set_text_colour(col)
|
86
|
+
@text_color = col
|
87
|
+
end
|
88
|
+
alias :text_colour= :set_text_colour
|
89
|
+
|
90
|
+
# Get text color.
|
91
|
+
# @return [Wx::Colour] Current text color
|
92
|
+
def get_text_colour
|
93
|
+
@text_color
|
94
|
+
end
|
95
|
+
alias :text_colour :get_text_colour
|
96
|
+
|
97
|
+
# Update shape (align all child shapes and resize it to fit them)
|
98
|
+
def update
|
99
|
+
update_rect_size
|
100
|
+
super
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns size of current text using current font.
|
104
|
+
# @return [Wx::Size]
|
105
|
+
def get_text_extent
|
106
|
+
w = -1
|
107
|
+
h = -1
|
108
|
+
if get_parent_canvas
|
109
|
+
if ShapeCanvas.gc_enabled?
|
110
|
+
Wx::GraphicsContext.draw_on(get_parent_canvas) do |gc|
|
111
|
+
# calculate text extent
|
112
|
+
hd = -1
|
113
|
+
e = 0
|
114
|
+
|
115
|
+
gc.set_font(@font, Wx::BLACK)
|
116
|
+
|
117
|
+
# we must use split string to inspect all lines of possible multiline text
|
118
|
+
h = 0
|
119
|
+
@text.split("\n").each do |line|
|
120
|
+
wd, hd, d, e = gc.get_text_extent(line)
|
121
|
+
h += (hd + e).to_i
|
122
|
+
w = (wd + d).to_i if (wd + d) > w
|
123
|
+
end
|
124
|
+
@line_height = (hd + e).to_i
|
125
|
+
|
126
|
+
gc.set_font(Wx::NULL_FONT, Wx::BLACK)
|
127
|
+
end
|
128
|
+
else
|
129
|
+
get_parent_canvas.paint do |dc|
|
130
|
+
dc.set_font(@font)
|
131
|
+
w, h, @line_height = dc.get_multi_line_text_extent(@text)
|
132
|
+
dc.set_font(Wx::NULL_FONT)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
else
|
136
|
+
w = @rect_size.x.to_i
|
137
|
+
h = @rect_size.y.to_i
|
138
|
+
@line_height = (@rect_size.y/@text.split("\n").size).to_i
|
139
|
+
end
|
140
|
+
|
141
|
+
Wx::Size.new(w, h)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Updates rectangle size for this shape.
|
145
|
+
def update_rect_size
|
146
|
+
tsize = get_text_extent
|
147
|
+
|
148
|
+
if tsize.is_fully_specified
|
149
|
+
tsize.width = 1 if tsize.width <= 0
|
150
|
+
tsize.height = 1 if tsize.height <= 0
|
151
|
+
|
152
|
+
@rect_size.x = tsize.width.to_f
|
153
|
+
@rect_size.y = tsize.height.to_f
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
protected
|
158
|
+
|
159
|
+
# Scale the rectangle size for this shape.
|
160
|
+
# @param [Float] x Horizontal scale factor
|
161
|
+
# @param [Float] y Vertical scale factor
|
162
|
+
def scale_rectangle(x, y)
|
163
|
+
s = 1.0
|
164
|
+
|
165
|
+
if x == 1.0
|
166
|
+
s = y
|
167
|
+
elsif y == 1.0
|
168
|
+
s = x
|
169
|
+
elsif x >= y
|
170
|
+
s = x
|
171
|
+
else
|
172
|
+
s = y
|
173
|
+
end
|
174
|
+
|
175
|
+
size = @font.get_point_size * s
|
176
|
+
size = 5 if size < 5
|
177
|
+
|
178
|
+
@font.set_point_size(size)
|
179
|
+
update_rect_size
|
180
|
+
end
|
181
|
+
|
182
|
+
# Handle's shape specific actions on handling handle events.
|
183
|
+
# The function can be overridden if necessary.
|
184
|
+
# @param [Shape::Handle] handle Reference to dragged handle
|
185
|
+
# @see #on_handle
|
186
|
+
def do_on_handle(handle)
|
187
|
+
# HINT: overload it for custom actions...
|
188
|
+
prev_size = get_rect_size
|
189
|
+
|
190
|
+
# perform standard operations
|
191
|
+
case handle.get_type
|
192
|
+
when Shape::Handle::TYPE::LEFT
|
193
|
+
on_left_handle(handle)
|
194
|
+
when Shape::Handle::TYPE::RIGHT
|
195
|
+
on_right_handle(handle)
|
196
|
+
when Shape::Handle::TYPE::TOP
|
197
|
+
on_top_handle(handle)
|
198
|
+
when Shape::Handle::TYPE::BOTTOM
|
199
|
+
on_bottom_handle(handle)
|
200
|
+
end
|
201
|
+
|
202
|
+
new_size = @rect_size
|
203
|
+
|
204
|
+
sx = new_size.x / prev_size.x
|
205
|
+
sy = new_size.y / prev_size.y
|
206
|
+
scale(sx, sy)
|
207
|
+
|
208
|
+
case handle.get_type
|
209
|
+
when Shape::Handle::TYPE::LEFT
|
210
|
+
dx = @rect_size.x - prev_size.x
|
211
|
+
move_by(-dx, 0)
|
212
|
+
@child_shapes.each { |shape| shape.move_by(-dx, 0) }
|
213
|
+
|
214
|
+
when Shape::Handle::TYPE::TOP
|
215
|
+
dy = @rect_size.y - prev_size.y
|
216
|
+
move_by(0, -dy)
|
217
|
+
@child_shapes.each { |shape| shape.move_by(0, -dy) }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Draw the shape in the normal way. The function can be overridden if necessary.
|
222
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
223
|
+
def draw_normal(dc)
|
224
|
+
super
|
225
|
+
draw_text_content(dc)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Draw the shape in the hover mode (the mouse cursor is above the shape).
|
229
|
+
# The function can be overridden if necessary.
|
230
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
231
|
+
def draw_hover(dc)
|
232
|
+
super
|
233
|
+
draw_text_content(dc)
|
234
|
+
end
|
235
|
+
|
236
|
+
# Draw the shape in the highlighted mode (another shape is dragged over this
|
237
|
+
# shape and this shape will accept the dragged one if it will be dropped on it).
|
238
|
+
# The function can be overridden if neccessary.
|
239
|
+
# @param [Wx::DC] dc Reference to device context where the shape will be drawn to
|
240
|
+
def draw_highlighted(dc)
|
241
|
+
super
|
242
|
+
draw_text_content(dc)
|
243
|
+
end
|
244
|
+
|
245
|
+
# Draw shadow under the shape. The function can be overridden if necessary.
|
246
|
+
# @param [Wx::DC] dc Reference to device context where the shadow will be drawn to
|
247
|
+
def draw_shadow(dc)
|
248
|
+
# HINT: overload it for custom actions...
|
249
|
+
|
250
|
+
curr_color = @text_color
|
251
|
+
@text_color = get_parent_canvas.get_shadow_fill.get_colour
|
252
|
+
offset = get_parent_canvas.get_shadow_offset
|
253
|
+
|
254
|
+
move_by(offset)
|
255
|
+
draw_text_content(dc)
|
256
|
+
move_by(-offset.x, -offset.y)
|
257
|
+
|
258
|
+
@text_color = curr_color
|
259
|
+
end
|
260
|
+
|
261
|
+
# Event handler called during dragging of the left shape handle.
|
262
|
+
# The function can be overridden if necessary.
|
263
|
+
# @param [Shape::Handle] handle Reference to dragged shape handle
|
264
|
+
def on_left_handle(handle)
|
265
|
+
# HINT: overload it for custom actions...
|
266
|
+
|
267
|
+
@rect_size.x -= (handle.get_position.x - get_absolute_position.x)
|
268
|
+
end
|
269
|
+
|
270
|
+
# Event handler called during dragging of the top shape handle.
|
271
|
+
# The function can be overridden if necessary.
|
272
|
+
# @param [Shape::Handle]handle Reference to dragged shape handle
|
273
|
+
def on_top_handle(handle)
|
274
|
+
# HINT: overload it for custom actions...
|
275
|
+
|
276
|
+
@rect_size.y -= (handle.get_position.y - get_absolute_position.y)
|
277
|
+
end
|
278
|
+
|
279
|
+
# Event handler called during dragging of the right shape handle.
|
280
|
+
# The function can be overridden if neccessary.
|
281
|
+
# @param [Shape::Handle] handle Reference to dragged shape handle
|
282
|
+
def on_right_handle(handle)
|
283
|
+
# HINT: overload it for custom actions...
|
284
|
+
|
285
|
+
@rect_size.x = (handle.get_position.x - get_absolute_position.x)
|
286
|
+
end
|
287
|
+
|
288
|
+
# Event handler called during dragging of the bottom shape handle.
|
289
|
+
# The function can be overridden if neccessary.
|
290
|
+
# @param [Shape::Handle] handle Reference to dragged shape handle
|
291
|
+
def on_bottom_handle(handle)
|
292
|
+
# HINT: overload it for custom actions...
|
293
|
+
|
294
|
+
@rect_size.y = (handle.get_position.y - get_absolute_position.y)
|
295
|
+
end
|
296
|
+
|
297
|
+
# Draw text shape.
|
298
|
+
# @param [Wx::DC] dc Device context where the text shape will be drawn to
|
299
|
+
def draw_text_content(dc)
|
300
|
+
dc.with_brush(@fill) do
|
301
|
+
dc.set_background_mode(Wx::BrushStyle::BRUSHSTYLE_TRANSPARENT)
|
302
|
+
dc.set_text_foreground(@text_color)
|
303
|
+
dc.with_font(@font) do
|
304
|
+
pos = get_absolute_position
|
305
|
+
# draw all text lines
|
306
|
+
@text.split("\n").each_with_index do |line, i|
|
307
|
+
dc.draw_text(line, pos.x.to_i, pos.y.to_i + i*@line_height)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# Deserialize attributes and recalculate rectangle size afterwards.
|
314
|
+
# @param [Hash] data
|
315
|
+
# @return [self]
|
316
|
+
def from_serialized(data)
|
317
|
+
super
|
318
|
+
update_rect_size
|
319
|
+
self
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|