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