autocad 0.4.6 → 0.5

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop/minitest.yml +2 -2
  3. data/.rubocop/strict.yml +4 -4
  4. data/.rubocop.yml +36 -33
  5. data/CHANGELOG.md +5 -5
  6. data/LICENSE.txt +21 -21
  7. data/README.md +134 -39
  8. data/Rakefile +26 -10
  9. data/exe/autocad +3 -3
  10. data/gemfiles/rubocop.gemfile +2 -1
  11. data/lib/autocad/app.rb +127 -28
  12. data/lib/autocad/arc.rb +3 -0
  13. data/lib/autocad/block.rb +11 -6
  14. data/lib/autocad/block_reference.rb +33 -4
  15. data/lib/autocad/bounding_box.rb +202 -0
  16. data/lib/autocad/dim_style.rb +4 -0
  17. data/lib/autocad/drawing.rb +873 -172
  18. data/lib/autocad/element.rb +217 -25
  19. data/lib/autocad/errors.rb +9 -0
  20. data/lib/autocad/filter.rb +502 -168
  21. data/lib/autocad/layer.rb +129 -41
  22. data/lib/autocad/layout.rb +120 -0
  23. data/lib/autocad/line.rb +154 -55
  24. data/lib/autocad/message_box.rb +95 -95
  25. data/lib/autocad/model.rb +217 -89
  26. data/lib/autocad/mtext.rb +189 -110
  27. data/lib/autocad/plot.rb +45 -0
  28. data/lib/autocad/plot_configuration.rb +372 -0
  29. data/lib/autocad/point.rb +7 -0
  30. data/lib/autocad/point3d.rb +18 -11
  31. data/lib/autocad/pviewport.rb +136 -21
  32. data/lib/autocad/selection_filter.rb +358 -180
  33. data/lib/autocad/selection_set.rb +140 -61
  34. data/lib/autocad/selection_set_adapter.rb +187 -8
  35. data/lib/autocad/spline.rb +27 -0
  36. data/lib/autocad/text.rb +66 -11
  37. data/lib/autocad/text_style.rb +4 -0
  38. data/lib/autocad/version.rb +1 -1
  39. data/lib/autocad/viewport.rb +57 -0
  40. data/lib/autocad.rb +126 -30
  41. data/lib/faa/cleanup.rb +137 -0
  42. data/lib/win32ole_helper.rb +52 -0
  43. data/rbs_collection.lock.yaml +38 -18
  44. data/sig/generated/autocad/app.rbs +278 -251
  45. data/sig/generated/autocad/arc.rbs +6 -3
  46. data/sig/generated/autocad/block.rbs +8 -5
  47. data/sig/generated/autocad/block_reference.rbs +99 -59
  48. data/sig/generated/autocad/bounding_box.rbs +78 -0
  49. data/sig/generated/autocad/dim_style.rbs +6 -0
  50. data/sig/generated/autocad/drawing.rbs +597 -158
  51. data/sig/generated/autocad/element.rbs +233 -166
  52. data/sig/generated/autocad/errors.rbs +29 -23
  53. data/sig/generated/autocad/filter.rbs +388 -60
  54. data/sig/generated/autocad/layer.rbs +76 -19
  55. data/sig/generated/autocad/layout.rbs +64 -0
  56. data/sig/generated/autocad/line.rbs +128 -25
  57. data/sig/generated/autocad/message_box.rbs +81 -81
  58. data/sig/generated/autocad/model.rbs +115 -41
  59. data/sig/generated/autocad/mtext.rbs +123 -0
  60. data/sig/generated/autocad/plot.rbs +26 -0
  61. data/sig/generated/autocad/plot_configuration.rbs +176 -0
  62. data/sig/generated/autocad/point.rbs +7 -0
  63. data/sig/generated/autocad/point3d.rbs +70 -66
  64. data/sig/generated/autocad/pviewport.rbs +64 -0
  65. data/sig/generated/autocad/selection_filter.rbs +226 -50
  66. data/sig/generated/autocad/selection_set.rbs +112 -37
  67. data/sig/generated/autocad/selection_set_adapter.rbs +235 -28
  68. data/sig/generated/autocad/spline.rbs +22 -0
  69. data/sig/generated/autocad/text.rbs +66 -7
  70. data/sig/generated/autocad/text_style.rbs +6 -0
  71. data/sig/generated/autocad/viewport.rbs +19 -2
  72. data/sig/generated/autocad.rbs +140 -68
  73. data/sig/generated/faa/cleanup.rbs +53 -0
  74. data/sig/generated/win32ole_helper.rbs +9 -0
  75. data/sig/prototype/lib/autocad/app.rbs +3 -1
  76. data/sig/prototype/lib/autocad/bounding_box.rbs +15 -0
  77. data/sig/prototype/lib/autocad/drawing.rbs +6 -0
  78. data/sig/prototype/lib/autocad/layer.rbs +5 -0
  79. data/sig/prototype/lib/autocad/viewport.rbs +7 -0
  80. data/sig/prototype/lib/autocad.rbs +1 -1
  81. metadata +29 -5
  82. data/event_handler.log +0 -24
  83. data/sig/generated/autocad/text_node.rbs +0 -37
data/lib/autocad/model.rb CHANGED
@@ -1,89 +1,217 @@
1
- # require_relative 'scan/scan_trait'
2
- # require_relative "model_trait"
3
-
4
- # require_relative 'ts/tagset_trait'
5
- # require_relative 'graphics'
6
- # require_relative 'ts/instance'
7
-
8
- module Autocad
9
- module ModelTrait
10
- def each
11
- return enum_for(:each) unless block_given?
12
-
13
- @ole_obj.each do |ole|
14
- yield app.wrap(ole)
15
- end
16
- end
17
-
18
- # @rbs pt1: Autocad::Point3d
19
- # @rbs return Autocad::Line
20
- def add_line(pt1, pt2, layer: nil)
21
- pt1 = Point3d.new(pt1)
22
- pt2 = Point3d.new(pt2)
23
- ole_line = ole_obj.AddLine(pt1.to_ole, pt2.to_ole)
24
- if layer
25
- layer = app.create_layer(layer)
26
- ole_line.layer = layer.ole_obj
27
- end
28
- app.wrap(ole_line)
29
- rescue ex
30
- puts ex.message
31
- end
32
-
33
- # @rbs center: [] | Point3d -- center of circle
34
- # @rbs radius:
35
- def add_circle(center, radius)
36
- pt = Point3d(center)
37
- ole_circle = ole_obj.AddCircle(pt.to_ole, radius)
38
- app.wrap(ole_circle)
39
- rescue
40
- raise Autocad::Error.new('Error adding circle #{ex}')
41
- end
42
-
43
- def add_rectangle(upper_left, lower_right)
44
- x1, y1, _z = Point3d(upper_left).to_a
45
- x2, y2, _z2 = Point3d(lower_right)
46
- pts = [x1, y1, x2, y1, x2, y1, x2, y2]
47
- pts_variant = WIN32OLE::Variant.new(pts, WIN32OLE::VARIANT::VT_ARRAY | WIN32OLE::VARIANT::VT_R8)
48
- ole = ole_obj.AddLightweightPolyline(pts_variant)
49
- app.wrap(ole)
50
- rescue => e
51
- raise Autocad::Error.new("Error adding rectangle #{e}")
52
- end
53
-
54
- def add_spline(points)
55
- pts = Point3d.pts_to_array(points)
56
- pts_variant = Point3d.array_to_ole(pts)
57
- ole = ole_obj.AddSpline(pts_variant)
58
- puts "pts #{pts}"
59
- puts "pts_variant #{pts_variant.class} #{pts_variant}"
60
- app.wrap(ole)
61
- rescue => e
62
- raise Autocad::Error.new("Error adding spline #{e}")
63
- end
64
-
65
- def drawing
66
- @drawing ||= ::Autocad::Drawing.from_ole_obj(app, ole_obj.Document)
67
- end
68
- end
69
-
70
- class PaperSpace
71
- include ModelTrait
72
- attr_reader :app, :ole_obj
73
-
74
- def initialize(ole, app)
75
- @ole_obj = ole
76
- @app = app
77
- end
78
- end
79
-
80
- class ModelSpace
81
- include ModelTrait
82
- attr_reader :app, :ole_obj
83
-
84
- def initialize(ole, app)
85
- @ole_obj = ole
86
- @app = app
87
- end
88
- end
89
- end
1
+ # require_relative 'scan/scan_trait'
2
+ # require_relative "model_trait"
3
+
4
+ # require_relative 'ts/tagset_trait'
5
+ # require_relative 'graphics'
6
+ # require_relative 'ts/instance'
7
+
8
+ module Autocad
9
+ module ModelTrait
10
+ # Iterate through all elements in the model space
11
+ # @rbs return Enumerator[Autocad::Element]
12
+ # @rbs &: (Autocad::Element) -> void
13
+ def each
14
+ return enum_for(:each) unless block_given?
15
+
16
+ @ole_obj.each do |ole|
17
+ yield app.wrap(ole)
18
+ end
19
+ end
20
+
21
+ # Check if this model is an external reference
22
+ # @rbs return bool
23
+ def xref?
24
+ @ole_obj.IsXRef
25
+ rescue StandardError
26
+ false
27
+ end
28
+
29
+ # Attach an external reference to the model
30
+ # @rbs path: String
31
+ # @rbs name: String
32
+ # @rbs pt: Array[Numeric] | Autocad::Point3d
33
+ # @rbs x_scale: Numeric
34
+ # @rbs y_scale: Numeric
35
+ # @rbs z_scale: Numeric
36
+ # @rbs rotation: Numeric
37
+ # @rbs overlay: bool
38
+ # @rbs password: String?
39
+ # @rbs return Autocad::BlockReference?
40
+ def attach_external_reference(path, name:, pt: [0, 0, 0], x_scale: 1.0, y_scale: 1.0, z_scale: 1.0, rotation: 0.0,
41
+ overlay: false, password: nil)
42
+ windows_path = app.windows_path(path)
43
+ pt3d = Point3d.new(insertion_point)
44
+ ole_reference = ole_obj.AttachExternalReference(windows_path, name, pt3d.to_ole, x_scale, y_scale, z_scale,
45
+ rotation, overlay, password)
46
+ app.wrap(ole_reference)
47
+ rescue StandardError => e
48
+ app.error_proc.call(e, self)
49
+ end
50
+
51
+ # Add a line to the model
52
+ # @rbs pt1: Array[Numeric] | Autocad::Point3d
53
+ # @rbs pt2: Array[Numeric] | Autocad::Point3d
54
+ # @rbs layer: String?
55
+ # @rbs return Autocad::Line?
56
+ def add_line(pt1, pt2, layer: nil)
57
+ pt1 = Point3d.new(pt1)
58
+ pt2 = Point3d.new(pt2)
59
+ ole_line = ole_obj.AddLine(pt1.to_ole, pt2.to_ole)
60
+ if layer
61
+ layer_obj = create_layer(layer)
62
+ ole_line.Layer = layer_obj.name
63
+ end
64
+ app.wrap(ole_line)
65
+ rescue StandardError => e
66
+ puts e.message
67
+ nil
68
+ end
69
+
70
+ # Get the layout associated with this model
71
+ # @rbs return Autocad::Layout
72
+ def layout
73
+ ole_layout = ole_obj.Layout
74
+ app.wrap(ole_layout)
75
+ end
76
+
77
+ # Add an arc to the model
78
+ # @rbs center: Array[Numeric] | Autocad::Point3d
79
+ # @rbs radius: Numeric
80
+ # @rbs start_angle: Numeric
81
+ # @rbs end_angle: Numeric
82
+ # @rbs return Autocad::Arc
83
+ # @raise [Autocad::Error] If arc creation fails
84
+ def add_arc(center, radius, start_angle, end_angle)
85
+ pt = Point3d(center)
86
+ ole_arc = ole_obj.AddArc(pt.to_ole, radius, start_angle, end_angle)
87
+ app.wrap(ole_arc)
88
+ rescue StandardError => e
89
+ raise Autocad::Error.new("Error adding arc #{e}")
90
+ end
91
+
92
+ # Add a circle to the model
93
+ # @rbs center: Array[Numeric] | Autocad::Point3d
94
+ # @rbs radius: Numeric
95
+ # @rbs return Autocad::Circle
96
+ # @raise [Autocad::Error] If circle creation fails
97
+ def add_circle(center, radius)
98
+ pt = Point3d(center)
99
+ ole_circle = ole_obj.AddCircle(pt.to_ole, radius)
100
+ app.wrap(ole_circle)
101
+ rescue StandardError => e
102
+ raise Autocad::Error.new("Error adding circle #{e.message}")
103
+ end
104
+
105
+ # Add a rectangular polyline to the model
106
+ # @rbs lower_left: Array[Numeric] | Autocad::Point3d
107
+ # @rbs upper_right: Array[Numeric] | Autocad::Point3d
108
+ # @rbs return Autocad::Element
109
+ # @raise [Autocad::Error] If rectangle creation fails
110
+ def add_rectangle(lower_left, upper_right)
111
+ x1, y1 = Point3d(lower_left).to_xy
112
+ x2, y2 = Point3d(upper_right).to_xy
113
+ pts = [x1, y1, x2, y1, x2, y2, x1, y2, x1, y1]
114
+ pts_variant = WIN32OLE::Variant.new(pts, WIN32OLE::VARIANT::VT_ARRAY | WIN32OLE::VARIANT::VT_R8)
115
+ ole = ole_obj.AddLightweightPolyline(pts_variant)
116
+ app.wrap(ole)
117
+ rescue StandardError => e
118
+ raise Autocad::Error.new("Error adding rectangle #{e}")
119
+ end
120
+
121
+ # Add an ellipse to the model
122
+ # @rbs center: Array[Numeric] | Autocad::Point3d
123
+ # @rbs major_axis: Numeric
124
+ # @rbs radius_ratio: Numeric
125
+ # @rbs return Autocad::Ellipse
126
+ # @raise [Autocad::Error] If ellipse creation fails
127
+ def add_ellipse(center, major_axis, radius_ratio)
128
+ pt = Point3d(center)
129
+ ole_ellipse = ole_obj.AddEllipse(pt.to_ole, major_axis, radius_ratio)
130
+ app.wrap(ole_ellipse)
131
+ rescue StandardError => e
132
+ raise Autocad::Error.new("Error adding ellipse #{e}")
133
+ end
134
+
135
+ # Add a spline to the model
136
+ # @rbs points: Array[Array[Numeric] | Autocad::Point3d]
137
+ # @rbs start_tangent: Array[Numeric] | Autocad::Point3d
138
+ # @rbs end_tangent: Array[Numeric] | Autocad::Point3d
139
+ # @rbs return Autocad::Spline
140
+ # @raise [Autocad::Error] If spline creation fails
141
+ def add_spline(points, start_tangent, end_tangent)
142
+ pts = Point3d.pts_to_array(points)
143
+ pts_variant = Point3d.array_to_ole(pts)
144
+
145
+ start_tangent_ole = Point3d.new(start_tangent).to_ole
146
+ end_tangent_ole = Point3d.new(end_tangent).to_ole
147
+
148
+ ole = ole_obj.AddSpline(pts_variant, start_tangent_ole, end_tangent_ole)
149
+ app.wrap(ole)
150
+ rescue StandardError => e
151
+ raise Autocad::Error.new("Error adding spline #{e.message}")
152
+ end
153
+
154
+ # Get the parent drawing document
155
+ # @rbs return Autocad::Drawing
156
+ def drawing
157
+ @drawing ||= ::Autocad::Drawing.from_ole_obj(app, ole_obj.Document)
158
+ end
159
+
160
+ private
161
+
162
+ # Internal method to create/get a layer
163
+ # @rbs name: String
164
+ # @rbs color: Numeric | Symbol | String?
165
+ # @rbs return Autocad::Layer
166
+ def create_layer(name, color = nil)
167
+ drawing.create_layer(name, color)
168
+ end
169
+ end
170
+
171
+ # Paper space container class
172
+ class PaperSpace < Element
173
+ include ModelTrait
174
+
175
+ # Add a paper space viewport
176
+ # @rbs center: Array[Numeric] | Autocad::Point3d
177
+ # @rbs width: Numeric
178
+ # @rbs height: Numeric
179
+ # @rbs return Autocad::PViewport
180
+ # @raise [StandardError] If viewport creation fails
181
+ def add_pv_viewport(center, width:, height:)
182
+ center = Point3d(center)
183
+ ole = ole_obj.AddPViewport(center.to_ole, width.to_f, height.to_f)
184
+ if ole
185
+ ole.Display(true)
186
+ ole.ViewportOn = true
187
+ layer = drawing.create_layer('Vport', 9)
188
+ layer.Plottable = false
189
+ ole.Layer = layer.name
190
+ ole.StandardScale = ACAD::AcVpScaleToFit
191
+ app.wrap(ole)
192
+ else
193
+ nil
194
+ end
195
+ rescue StandardError => e
196
+ nil
197
+ end
198
+
199
+ # Get all paper space viewports
200
+ # @rbs return Array[Autocad::PViewport]
201
+ def pviewports
202
+ each.select { it.pviewport? }
203
+ end
204
+
205
+ # Delete all paper space viewports
206
+ # @rbs return void
207
+ def clear_pviewports
208
+ pviewports.each(&:delete)
209
+ end
210
+ end
211
+
212
+ # Model space container class
213
+ class ModelSpace < Element
214
+ include ModelTrait
215
+ # Inherits all ModelTrait functionality for model space entities
216
+ end
217
+ end
data/lib/autocad/mtext.rb CHANGED
@@ -1,110 +1,189 @@
1
- module Autocad
2
- class MText < Element
3
- attr_reader :original, :ole_obj
4
-
5
- def to_regexp
6
- Regexp.new(original.to_s)
7
- end
8
-
9
- def empty?
10
- ole_obj.TextLinesCount == 0
11
- end
12
-
13
- def mtext?
14
- true
15
- end
16
-
17
- def text?
18
- false
19
- end
20
-
21
- def size
22
- ole_obj.TextLinesCount
23
- end
24
-
25
- def read_ole(ole)
26
- ole.TextString
27
- end
28
-
29
- # def _update(text)
30
- # update_ole!(text)
31
- # @original = text
32
- # end
33
-
34
- def write_ole(text)
35
- if in_cell?
36
- write_ole_in_cell(text)
37
- else
38
- write_ole_regular(text)
39
- end
40
- end
41
-
42
- def write_ole_regular(text)
43
- ole_obj.TextString = text
44
- end
45
-
46
- def write_ole_in_cell(text)
47
- orig_ole = ole_obj
48
- new_text_ole = ole_obj.Clone
49
- new_text_ole.DeleteAllTextLines
50
- text.each_line do |line|
51
- new_text_ole.AddTextLine(line)
52
- end
53
- @ole_obj = new_text_ole
54
- rescue
55
- @ole_obj = orig_ole
56
- end
57
-
58
- def update_ole!(text)
59
- ole_obj.DeleteAllTextLines
60
- text.each_line do |line|
61
- ole_obj.AddTextLine(line)
62
- end
63
- ole_obj.Redraw Autocad::MSD::MsdDrawingModeNormal
64
- ole_obj.Rewrite
65
- end
66
-
67
- def to_s
68
- @original.to_s
69
- end
70
-
71
- def =~(reg)
72
- @original =~ reg
73
- end
74
-
75
- def template?
76
- !!(@original =~ /{{.+}}/)
77
- end
78
-
79
- def render(h = {})
80
- return self unless template?
81
-
82
- template = Liquid::Template.parse(to_s)
83
- result = template.render(h)
84
- update(result) unless result == @original
85
- self
86
- end
87
-
88
- def method_missing(meth, *, &)
89
- if /^[A-Z]/.match?(meth)
90
- ole_obj.send(meth, *)
91
- else
92
- copy = @original.dup
93
- result = copy.send(meth, *, &)
94
- update(result) unless copy == @original
95
- result
96
- end
97
- end
98
-
99
- # def method_missing2(meth,*args,&block)
100
- # if meth.to_s =~ /^[A-Z]/
101
- # ole_obj.send(meth,*args)
102
- # else
103
- # dup = @original.dup
104
- # result = dup.send(meth,*args,&block)
105
- # _update(dup) unless dup == @original
106
- # result
107
- # end
108
- # end
109
- end
110
- end
1
+ # rbs_inline: enabled
2
+
3
+ module Autocad
4
+ # Multi-line formatted text container in AutoCAD
5
+ #
6
+ # Represents a rich text entity with multiple lines and formatting.
7
+ # Supports Liquid templates, table cell awareness, and line-by-line operations.
8
+ #
9
+ # @example Create and render a template
10
+ # specs = drawing.model.add_mtext("Project: {{name}}")
11
+ # specs.render(name: "Tower A")
12
+ class MText < Element
13
+ # @rbs attr_reader original: String
14
+ # @rbs attr_reader ole_obj: WIN32OLE
15
+ attr_reader :original, :ole_obj
16
+
17
+ # Convert content to regex pattern
18
+ #
19
+ # @return [Regexp] A regular expression based on the text content
20
+ # @rbs return Regexp
21
+ def to_regexp
22
+ Regexp.new(original.to_s)
23
+ end
24
+
25
+ # Check for empty content
26
+ #
27
+ # @return [Boolean] True if the MText has no content
28
+ # @rbs return bool
29
+ def empty?
30
+ ole_obj.TextLinesCount == 0
31
+ end
32
+
33
+ # Type check for multi-line text (always true)
34
+ #
35
+ # @return [Boolean] Always returns true for MText objects
36
+ # @rbs return bool
37
+ def mtext?
38
+ true
39
+ end
40
+
41
+ # Override text type check (always false)
42
+ #
43
+ # @return [Boolean] Always returns false for MText objects
44
+ # @rbs return bool
45
+ def text?
46
+ false
47
+ end
48
+
49
+ # Get number of text lines
50
+ #
51
+ # @return [Integer] The number of lines in the MText
52
+ # @rbs return Integer
53
+ def size
54
+ ole_obj.TextLinesCount
55
+ end
56
+
57
+ # Read content from OLE object
58
+ #
59
+ # @param ole [WIN32OLE] The OLE object to read from
60
+ # @return [String] The text content
61
+ # @rbs ole: WIN32OLE -> String
62
+ def read_ole(ole)
63
+ ole.TextString
64
+ end
65
+
66
+ # Update text content with cell awareness
67
+ #
68
+ # @param text [String] The new text content
69
+ # @return [void]
70
+ # @rbs text: String -> void
71
+ def write_ole(text)
72
+ if in_cell?
73
+ write_ole_in_cell(text)
74
+ else
75
+ write_ole_regular(text)
76
+ end
77
+ end
78
+
79
+ # Update text content for regular MText
80
+ #
81
+ # @param text [String] The new text content
82
+ # @return [void]
83
+ # @rbs text: String -> void
84
+ def write_ole_regular(text)
85
+ ole_obj.TextString = text
86
+ end
87
+
88
+ # Update text content for MText in table cell
89
+ #
90
+ # @param text [String] The new text content
91
+ # @return [void]
92
+ # @rbs text: String -> void
93
+ def write_ole_in_cell(text)
94
+ orig_ole = ole_obj
95
+ new_text_ole = ole_obj.Clone
96
+ new_text_ole.DeleteAllTextLines
97
+ text.each_line do |line|
98
+ new_text_ole.AddTextLine(line)
99
+ end
100
+ @ole_obj = new_text_ole
101
+ rescue
102
+ @ole_obj = orig_ole
103
+ end
104
+
105
+ # Full content rewrite with line-by-line updates
106
+ #
107
+ # @param text [String] The new text content
108
+ # @return [void]
109
+ # @rbs text: String -> void
110
+ def update_ole!(text)
111
+ ole_obj.DeleteAllTextLines
112
+ text.each_line do |line|
113
+ ole_obj.AddTextLine(line)
114
+ end
115
+ ole_obj.Redraw Autocad::MSD::MsdDrawingModeNormal
116
+ ole_obj.Rewrite
117
+ end
118
+
119
+ # Get content as string
120
+ #
121
+ # @return [String] The text content
122
+ # @rbs return String
123
+ def to_s
124
+ @original.to_s
125
+ end
126
+
127
+ # Regex pattern matching against text content
128
+ #
129
+ # @param reg [Regexp] The regular expression to match against
130
+ # @return [Integer, nil] Match position or nil if no match
131
+ # @rbs reg: Regexp -> Integer?
132
+ def =~(reg)
133
+ @original =~ reg
134
+ end
135
+
136
+ # Check for Liquid template placeholders
137
+ #
138
+ # @return [Boolean] True if the text contains template placeholders
139
+ # @rbs return bool
140
+ def template?
141
+ !!(@original =~ /{{.+}}/)
142
+ end
143
+
144
+ # Render Liquid template with provided context
145
+ #
146
+ # @param h [Hash] The template variables
147
+ # @return [self] The MText object
148
+ # @example Render a template with variables
149
+ # mtext.render(client: "ABC Corp", floors: 42)
150
+ # @rbs h: Hash[Symbol, untyped] -> self
151
+ def render(h = {})
152
+ return self unless template?
153
+
154
+ template = Liquid::Template.parse(to_s)
155
+ result = template.render(h)
156
+ update(result) unless result == @original
157
+ self
158
+ end
159
+
160
+ # Delegate uppercase methods to OLE object, lowercase to string methods
161
+ #
162
+ # @param meth [Symbol] The method name
163
+ # @param * [Array] Method arguments
164
+ # @param & [Proc] Optional block
165
+ # @return [Object] Result of the method call
166
+ # @rbs (Symbol, *untyped) -> untyped
167
+ def method_missing(meth, *, &)
168
+ if /^[A-Z]/.match?(meth)
169
+ ole_obj.send(meth, *)
170
+ else
171
+ copy = @original.dup
172
+ result = copy.send(meth, *, &)
173
+ update(result) unless copy == @original
174
+ result
175
+ end
176
+ end
177
+
178
+ # def method_missing2(meth,*args,&block)
179
+ # if meth.to_s =~ /^[A-Z]/
180
+ # ole_obj.send(meth,*args)
181
+ # else
182
+ # dup = @original.dup
183
+ # result = dup.send(meth,*args,&block)
184
+ # _update(dup) unless dup == @original
185
+ # result
186
+ # end
187
+ # end
188
+ end
189
+ end
@@ -0,0 +1,45 @@
1
+ module Autocad
2
+ class Plot < Element
3
+ # Configure which layouts to include in the plot
4
+ # @rbs *layouts: Array[String | Autocad::Layout] | String | Autocad::Layout
5
+ # @rbs return void
6
+ def set_layouts_to_plot(*layouts)
7
+ layouts = layouts.first if layouts.size == 1 && layouts.first.is_a?(Array)
8
+ ole_layouts = layouts.map { |l| l.is_a?(Autocad::Layout) ? l.name : l.to_s }
9
+
10
+ ole_layout_values = WIN32OLE::Variant.new(
11
+ ole_layouts,
12
+ WIN32OLE::VARIANT::VT_ARRAY | WIN32OLE::VARIANT::VT_BSTR
13
+ )
14
+ ole_obj.SetLayoutsToPlot(ole_layout_values)
15
+ end
16
+
17
+ # Display full plot preview window
18
+ # @rbs return void
19
+ def plot_preview
20
+ ole_obj.DisplayPlotPreview(1) # 1 = acFullPreview
21
+ end
22
+
23
+ # Execute plot using configured device
24
+ # @rbs return void
25
+ # @raise [Autocad::Error] If device communication fails
26
+ def plot_to_device
27
+ ole_obj.PlotToDevice
28
+ rescue => e
29
+ raise Autocad::Error.new("Device plot failed: #{e.message}")
30
+ end
31
+
32
+ # Plot to file with specified configuration
33
+ # @rbs filename: String | Pathname
34
+ # @rbs plot_config: String | Autocad::PlotConfiguration?
35
+ # @rbs return void
36
+ # @raise [Autocad::Error] If file creation fails
37
+ def plot_to_file(filename, plot_config: nil)
38
+ path = app.windows_path(filename)
39
+ config_name = plot_config.respond_to?(:name) ? plot_config.name : plot_config
40
+ ole_obj.PlotToFile(path, config_name)
41
+ rescue => e
42
+ raise Autocad::Error.new("File plot failed: #{e.message}\nPath: #{path}")
43
+ end
44
+ end
45
+ end