wxruby3-shapes 0.9.0.pre.beta.3

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