rtf 0.1.0
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.
- data/doc/README +177 -0
- data/doc/makedoc.bat +2 -0
- data/examples/example01.rb +51 -0
- data/examples/example02.rb +45 -0
- data/examples/example03.rb +66 -0
- data/examples/example03.rtf +164 -0
- data/lib/rtf.rb +34 -0
- data/lib/rtf/colour.rb +173 -0
- data/lib/rtf/font.rb +173 -0
- data/lib/rtf/information.rb +112 -0
- data/lib/rtf/node.rb +1398 -0
- data/lib/rtf/paper.rb +55 -0
- data/lib/rtf/style.rb +305 -0
- data/test/CharacterStyleTest.rb +142 -0
- data/test/ColourTableTest.rb +98 -0
- data/test/ColourTest.rb +122 -0
- data/test/CommandNodeTest.rb +220 -0
- data/test/ContainerNodeTest.rb +70 -0
- data/test/DocumentStyleTest.rb +85 -0
- data/test/DocumentTest.rb +112 -0
- data/test/FontTableTest.rb +96 -0
- data/test/FontTest.rb +53 -0
- data/test/FooterNodeTest.rb +36 -0
- data/test/HeaderNodeTest.rb +36 -0
- data/test/InformationTest.rb +133 -0
- data/test/NodeTest.rb +31 -0
- data/test/ParagraphStyleTest.rb +87 -0
- data/test/StyleTest.rb +22 -0
- data/test/TableCellNodeTest.rb +95 -0
- data/test/TableNodeTest.rb +89 -0
- data/test/TableRowNodeTest.rb +65 -0
- data/test/TextNodeTest.rb +56 -0
- data/test/run.bat +2 -0
- data/test/unittest.bat +2 -0
- data/test/unittest.rb +21 -0
- metadata +78 -0
data/lib/rtf/node.rb
ADDED
@@ -0,0 +1,1398 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
module RTF
|
6
|
+
# This class represents an element within an RTF document. The class provides
|
7
|
+
# a base class for more specific node types.
|
8
|
+
class Node
|
9
|
+
# Attribute accessor.
|
10
|
+
attr_reader :parent
|
11
|
+
|
12
|
+
# Attribute mutator.
|
13
|
+
attr_writer :parent
|
14
|
+
|
15
|
+
|
16
|
+
# This is the constructor for the Node class.
|
17
|
+
#
|
18
|
+
# ==== Parameters
|
19
|
+
# parent:: A reference to the Node that owns the new Node. May be nil
|
20
|
+
# to indicate a base or root node.
|
21
|
+
def initialize(parent)
|
22
|
+
@parent = parent
|
23
|
+
end
|
24
|
+
|
25
|
+
# This method retrieves a Node objects previous peer node, returning nil
|
26
|
+
# if the Node has no previous peer.
|
27
|
+
def previous_node
|
28
|
+
peer = nil
|
29
|
+
if parent != nil and parent.respond_to?(:children)
|
30
|
+
index = parent.children.index(self)
|
31
|
+
peer = index > 0 ? parent.children[index - 1] : nil
|
32
|
+
end
|
33
|
+
peer
|
34
|
+
end
|
35
|
+
|
36
|
+
# This method retrieves a Node objects next peer node, returning nil
|
37
|
+
# if the Node has no previous peer.
|
38
|
+
def next_node
|
39
|
+
peer = nil
|
40
|
+
if parent != nil and parent.respond_to?(:children)
|
41
|
+
index = parent.children.index(self)
|
42
|
+
peer = parent.children[index + 1]
|
43
|
+
end
|
44
|
+
peer
|
45
|
+
end
|
46
|
+
|
47
|
+
# This method is used to determine whether a Node object represents a
|
48
|
+
# root or base element. The method returns true if the Nodes parent is
|
49
|
+
# nil, false otherwise.
|
50
|
+
def is_root?
|
51
|
+
@parent == nil
|
52
|
+
end
|
53
|
+
|
54
|
+
# This method traverses a Node tree to locate the root element.
|
55
|
+
def root
|
56
|
+
node = self
|
57
|
+
node = node.parent while node.parent != nil
|
58
|
+
node
|
59
|
+
end
|
60
|
+
end # End of the Node class.
|
61
|
+
|
62
|
+
|
63
|
+
# This class represents a specialisation of the Node class to refer to a Node
|
64
|
+
# that simply contains text.
|
65
|
+
class TextNode < Node
|
66
|
+
# Attribute accessor.
|
67
|
+
attr_reader :text
|
68
|
+
|
69
|
+
# Attribute mutator.
|
70
|
+
attr_writer :text
|
71
|
+
|
72
|
+
# This is the constructor for the TextNode class.
|
73
|
+
#
|
74
|
+
# ==== Parameters
|
75
|
+
# parent:: A reference to the Node that owns the TextNode. Must not be
|
76
|
+
# nil.
|
77
|
+
# text:: A String containing the node text. Defaults to nil.
|
78
|
+
#
|
79
|
+
# ==== Exceptions
|
80
|
+
# RTFError:: Generated whenever an nil parent object is specified to
|
81
|
+
# the method.
|
82
|
+
def initialize(parent, text=nil)
|
83
|
+
super(parent)
|
84
|
+
if parent == nil
|
85
|
+
RTFError.fire("Nil parent specified for text node.")
|
86
|
+
end
|
87
|
+
@parent = parent
|
88
|
+
@text = text
|
89
|
+
end
|
90
|
+
|
91
|
+
# This method concatenates a String on to the end of the existing text
|
92
|
+
# within a TextNode object.
|
93
|
+
#
|
94
|
+
# ==== Parameters
|
95
|
+
# text:: The String to be added to the end of the text node.
|
96
|
+
def append(text)
|
97
|
+
if @text != nil
|
98
|
+
@text = @text + text.to_s
|
99
|
+
else
|
100
|
+
@text = text.to_s
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# This method inserts a String into the existing text within a TextNode
|
105
|
+
# object. If the TextNode contains no text then it is simply set to the
|
106
|
+
# text passed in. If the offset specified is past the end of the nodes
|
107
|
+
# text then it is simply appended to the end.
|
108
|
+
#
|
109
|
+
# ==== Parameters
|
110
|
+
# text:: A String containing the text to be added.
|
111
|
+
# offset:: The numbers of characters from the first character to insert
|
112
|
+
# the new text at.
|
113
|
+
def insert(text, offset)
|
114
|
+
if @text != nil
|
115
|
+
@text = @text[0, offset] + text.to_s + @text[offset, @text.length]
|
116
|
+
else
|
117
|
+
@text = text.to_s
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# This method generates the RTF equivalent for a TextNode object. This
|
122
|
+
# method escapes any special sequences that appear in the text.
|
123
|
+
def to_rtf
|
124
|
+
@text == nil ? '' : @text.gsub("{", "\\{").gsub("}", "\\}").gsub("\\", "\\\\")
|
125
|
+
end
|
126
|
+
end # End of the TextNode class.
|
127
|
+
|
128
|
+
|
129
|
+
# This class represents a Node that can contain other Node objects. Its a
|
130
|
+
# base class for more specific Node types.
|
131
|
+
class ContainerNode < Node
|
132
|
+
include Enumerable
|
133
|
+
|
134
|
+
# Attribute accessor.
|
135
|
+
attr_reader :children
|
136
|
+
|
137
|
+
# Attribute mutator.
|
138
|
+
attr_writer :children
|
139
|
+
|
140
|
+
# This is the constructor for the ContainerNode class.
|
141
|
+
#
|
142
|
+
# ==== Parameters
|
143
|
+
# parent:: A reference to the parent node that owners the new
|
144
|
+
# ContainerNode object.
|
145
|
+
def initialize(parent)
|
146
|
+
super(parent)
|
147
|
+
@children = []
|
148
|
+
@children.concat(yield) if block_given?
|
149
|
+
end
|
150
|
+
|
151
|
+
# This method adds a new node element to the end of the list of nodes
|
152
|
+
# maintained by a ContainerNode object. Nil objects are ignored.
|
153
|
+
#
|
154
|
+
# ==== Parameters
|
155
|
+
# node:: A reference to the Node object to be added.
|
156
|
+
def store(node)
|
157
|
+
if node != nil
|
158
|
+
@children.push(node) if @children.include?(Node) == false
|
159
|
+
node.parent = self if node.parent != self
|
160
|
+
end
|
161
|
+
node
|
162
|
+
end
|
163
|
+
|
164
|
+
# This method fetches the first node child for a ContainerNode object. If
|
165
|
+
# a container contains no children this method returns nil.
|
166
|
+
def first
|
167
|
+
@children[0]
|
168
|
+
end
|
169
|
+
|
170
|
+
# This method fetches the last node child for a ContainerNode object. If
|
171
|
+
# a container contains no children this method returns nil.
|
172
|
+
def last
|
173
|
+
@children.last
|
174
|
+
end
|
175
|
+
|
176
|
+
# This method provides for iteration over the contents of a ContainerNode
|
177
|
+
# object.
|
178
|
+
def each
|
179
|
+
@children.each {|child| yield child}
|
180
|
+
end
|
181
|
+
|
182
|
+
# This method returns a count of the number of children a ContainerNode
|
183
|
+
# object contains.
|
184
|
+
def size
|
185
|
+
@children.size
|
186
|
+
end
|
187
|
+
|
188
|
+
# This method overloads the array dereference operator to allow for
|
189
|
+
# access to the child elements of a ContainerNode object.
|
190
|
+
#
|
191
|
+
# ==== Parameters
|
192
|
+
# index:: The offset from the first child of the child object to be
|
193
|
+
# returned. Negative index values work from the back of the
|
194
|
+
# list of children. An invalid index will cause a nil value
|
195
|
+
# to be returned.
|
196
|
+
def [](index)
|
197
|
+
@children[index]
|
198
|
+
end
|
199
|
+
|
200
|
+
# This method generates the RTF text for a ContainerNode object.
|
201
|
+
def to_rtf
|
202
|
+
RTFError.fire("#{self.class.name}.to_rtf method not yet implemented.")
|
203
|
+
end
|
204
|
+
end # End of the ContainerNode class.
|
205
|
+
|
206
|
+
|
207
|
+
# This class represents a RTF command element within a document. This class
|
208
|
+
# is concrete enough to be used on its own but will also be used as the
|
209
|
+
# base class for some specific command node types.
|
210
|
+
class CommandNode < ContainerNode
|
211
|
+
# Attribute accessor.
|
212
|
+
attr_reader :prefix, :suffix, :split
|
213
|
+
|
214
|
+
# Attribute mutator.
|
215
|
+
attr_writer :prefix, :suffix, :split
|
216
|
+
|
217
|
+
# This is the constructor for the CommandNode class.
|
218
|
+
#
|
219
|
+
# ==== Parameters
|
220
|
+
# parent:: A reference to the node that owns the new node.
|
221
|
+
# prefix:: A String containing the prefix text for the command.
|
222
|
+
# suffix:: A String containing the suffix text for the command. Defaults
|
223
|
+
# to nil.
|
224
|
+
# split:: A boolean to indicate whether the prefix and suffix should
|
225
|
+
# be written to separate lines whether the node is converted
|
226
|
+
# to RTF. Defaults to true.
|
227
|
+
def initialize(parent, prefix, suffix=nil, split=true)
|
228
|
+
super(parent)
|
229
|
+
@prefix = prefix
|
230
|
+
@suffix = suffix
|
231
|
+
@split = split
|
232
|
+
end
|
233
|
+
|
234
|
+
# This method adds text to a command node. If the last child node of the
|
235
|
+
# target node is a TextNode then the text is appended to that. Otherwise
|
236
|
+
# a new TextNode is created and append to the node.
|
237
|
+
#
|
238
|
+
# ==== Parameters
|
239
|
+
# text:: The String of text to be written to the node.
|
240
|
+
def <<(text)
|
241
|
+
if last != nil and last.respond_to?(:text=)
|
242
|
+
last.append(text)
|
243
|
+
else
|
244
|
+
self.store(TextNode.new(self, text))
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
# This method generates the RTF text for a CommandNode object.
|
249
|
+
def to_rtf
|
250
|
+
text = StringIO.new
|
251
|
+
separator = split? ? "\n" : " "
|
252
|
+
line = (separator == " ")
|
253
|
+
|
254
|
+
text << "{#{@prefix}"
|
255
|
+
text << separator if self.size > 0
|
256
|
+
self.each do |entry|
|
257
|
+
text << "\n" if line
|
258
|
+
line = true
|
259
|
+
text << "#{entry.to_rtf}"
|
260
|
+
end
|
261
|
+
text << "\n" if split?
|
262
|
+
text << "#{@suffix}}"
|
263
|
+
text.string
|
264
|
+
end
|
265
|
+
|
266
|
+
# This method provides a short cut means of creating a paragraph command
|
267
|
+
# node. The method accepts a block that will be passed a single parameter
|
268
|
+
# which will be a reference to the paragraph node created. After the
|
269
|
+
# block is complete the paragraph node is appended to the end of the child
|
270
|
+
# nodes on the object that the method is called against.
|
271
|
+
#
|
272
|
+
# ==== Parameters
|
273
|
+
# style:: A reference to a ParagraphStyle object that defines the style
|
274
|
+
# for the new paragraph. Defaults to nil to indicate that the
|
275
|
+
# currently applied paragraph styling should be used.
|
276
|
+
def paragraph(style=nil)
|
277
|
+
# Create the node prefix.
|
278
|
+
text = StringIO.new
|
279
|
+
text << '\pard'
|
280
|
+
text << style.prefix(nil, nil) if style != nil
|
281
|
+
|
282
|
+
node = CommandNode.new(self, text.string, '\par')
|
283
|
+
yield node if block_given?
|
284
|
+
self.store(node)
|
285
|
+
end
|
286
|
+
|
287
|
+
# This method provides a short cut means of creating a line break command
|
288
|
+
# node. This command node does not take a block and may possess no other
|
289
|
+
# content.
|
290
|
+
def line_break
|
291
|
+
self.store(CommandNode.new(self, '\line', nil, false))
|
292
|
+
nil
|
293
|
+
end
|
294
|
+
|
295
|
+
# This method inserts a footnote at the current position in a node.
|
296
|
+
#
|
297
|
+
# ==== Parameters
|
298
|
+
# text:: A string containing the text for the footnote.
|
299
|
+
def footnote(text)
|
300
|
+
if text != nil && text != ''
|
301
|
+
mark = CommandNode.new(self, '\fs16\up6\chftn', nil, false)
|
302
|
+
note = CommandNode.new(self, '\footnote {\fs16\up6\chftn}', nil, false)
|
303
|
+
note.paragraph << text
|
304
|
+
self.store(mark)
|
305
|
+
self.store(note)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
# This method provides a short cut means for applying multiple styles via
|
310
|
+
# single command node. The method accepts a block that will be passed a
|
311
|
+
# reference to the node created. Once the block is complete the new node
|
312
|
+
# will be append as the last child of the CommandNode the method is called
|
313
|
+
# on.
|
314
|
+
#
|
315
|
+
# ==== Parameters
|
316
|
+
# style:: A reference to a CharacterStyle object that contains the style
|
317
|
+
# settings to be applied.
|
318
|
+
#
|
319
|
+
# ==== Exceptions
|
320
|
+
# RTFError:: Generated whenever a non-character style is specified to
|
321
|
+
# the method.
|
322
|
+
def apply(style)
|
323
|
+
# Check the input style.
|
324
|
+
if style.is_character_style? == false
|
325
|
+
RTFError.fire("Non-character style specified to the "\
|
326
|
+
"CommandNode#apply() method.")
|
327
|
+
end
|
328
|
+
|
329
|
+
# Store fonts and colours.
|
330
|
+
root.colours << style.foreground if style.foreground != nil
|
331
|
+
root.colours << style.background if style.background != nil
|
332
|
+
root.fonts << style.font if style.font != nil
|
333
|
+
|
334
|
+
# Generate the command node.
|
335
|
+
node = CommandNode.new(self, style.prefix(root.fonts, root.colours))
|
336
|
+
yield node if block_given?
|
337
|
+
self.store(node)
|
338
|
+
end
|
339
|
+
|
340
|
+
# This method provides a short cut means of creating a bold command node.
|
341
|
+
# The method accepts a block that will be passed a single parameter which
|
342
|
+
# will be a reference to the bold node created. After the block is
|
343
|
+
# complete the bold node is appended to the end of the child nodes on
|
344
|
+
# the object that the method is call against.
|
345
|
+
def bold
|
346
|
+
style = CharacterStyle.new
|
347
|
+
style.bold = true
|
348
|
+
if block_given?
|
349
|
+
apply(style) {|node| yield node}
|
350
|
+
else
|
351
|
+
apply(style)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# This method provides a short cut means of creating an italic command
|
356
|
+
# node. The method accepts a block that will be passed a single parameter
|
357
|
+
# which will be a reference to the italic node created. After the block is
|
358
|
+
# complete the italic node is appended to the end of the child nodes on
|
359
|
+
# the object that the method is call against.
|
360
|
+
def italic
|
361
|
+
style = CharacterStyle.new
|
362
|
+
style.italic = true
|
363
|
+
if block_given?
|
364
|
+
apply(style) {|node| yield node}
|
365
|
+
else
|
366
|
+
apply(style)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# This method provides a short cut means of creating an underline command
|
371
|
+
# node. The method accepts a block that will be passed a single parameter
|
372
|
+
# which will be a reference to the underline node created. After the block
|
373
|
+
# is complete the underline node is appended to the end of the child nodes
|
374
|
+
# on the object that the method is call against.
|
375
|
+
def underline
|
376
|
+
style = CharacterStyle.new
|
377
|
+
style.underline = true
|
378
|
+
if block_given?
|
379
|
+
apply(style) {|node| yield node}
|
380
|
+
else
|
381
|
+
apply(style)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# This method provides a short cut means of creating a superscript command
|
386
|
+
# node. The method accepts a block that will be passed a single parameter
|
387
|
+
# which will be a reference to the superscript node created. After the
|
388
|
+
# block is complete the superscript node is appended to the end of the
|
389
|
+
# child nodes on the object that the method is call against.
|
390
|
+
def superscript
|
391
|
+
style = CharacterStyle.new
|
392
|
+
style.superscript = true
|
393
|
+
if block_given?
|
394
|
+
apply(style) {|node| yield node}
|
395
|
+
else
|
396
|
+
apply(style)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
# This method provides a short cut means of creating a font command node.
|
401
|
+
# The method accepts a block that will be passed a single parameter which
|
402
|
+
# will be a reference to the font node created. After the block is
|
403
|
+
# complete the font node is appended to the end of the child nodes on the
|
404
|
+
# object that the method is called against.
|
405
|
+
#
|
406
|
+
# ==== Parameters
|
407
|
+
# font:: A reference to font object that represents the font to be used
|
408
|
+
# within the node.
|
409
|
+
# size:: An integer size setting for the font. Defaults to nil to
|
410
|
+
# indicate that the current font size should be used.
|
411
|
+
def font(font, size=nil)
|
412
|
+
style = CharacterStyle.new
|
413
|
+
style.font = font
|
414
|
+
style.font_size = size
|
415
|
+
root.fonts << font
|
416
|
+
if block_given?
|
417
|
+
apply(style) {|node| yield node}
|
418
|
+
else
|
419
|
+
apply(style)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
# This method provides a short cut means of creating a foreground colour
|
424
|
+
# command node. The method accepts a block that will be passed a single
|
425
|
+
# parameter which will be a reference to the foreground colour node
|
426
|
+
# created. After the block is complete the foreground colour node is
|
427
|
+
# appended to the end of the child nodes on the object that the method
|
428
|
+
# is called against.
|
429
|
+
#
|
430
|
+
# ==== Parameters
|
431
|
+
# colour:: The foreground colour to be applied by the command.
|
432
|
+
def foreground(colour)
|
433
|
+
style = CharacterStyle.new
|
434
|
+
style.foreground = colour
|
435
|
+
root.colours << colour
|
436
|
+
if block_given?
|
437
|
+
apply(style) {|node| yield node}
|
438
|
+
else
|
439
|
+
apply(style)
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
# This method provides a short cut means of creating a background colour
|
444
|
+
# command node. The method accepts a block that will be passed a single
|
445
|
+
# parameter which will be a reference to the background colour node
|
446
|
+
# created. After the block is complete the background colour node is
|
447
|
+
# appended to the end of the child nodes on the object that the method
|
448
|
+
# is called against.
|
449
|
+
#
|
450
|
+
# ==== Parameters
|
451
|
+
# colour:: The background colour to be applied by the command.
|
452
|
+
def background(colour)
|
453
|
+
style = CharacterStyle.new
|
454
|
+
style.background = colour
|
455
|
+
root.colours << colour
|
456
|
+
if block_given?
|
457
|
+
apply(style) {|node| yield node}
|
458
|
+
else
|
459
|
+
apply(style)
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
# This method provides a short cut menas of creating a colour node that
|
464
|
+
# deals with foreground and background colours. The method accepts a
|
465
|
+
# block that will be passed a single parameter which will be a reference
|
466
|
+
# to the colour node created. After the block is complete the colour node
|
467
|
+
# is append to the end of the child nodes on the object that the method
|
468
|
+
# is called against.
|
469
|
+
#
|
470
|
+
# ==== Parameters
|
471
|
+
# fore:: The foreground colour to be applied by the command.
|
472
|
+
# back:: The background colour to be applied by the command.
|
473
|
+
def colour(fore, back)
|
474
|
+
style = CharacterStyle.new
|
475
|
+
style.foreground = fore
|
476
|
+
style.background = back
|
477
|
+
root.colours << fore
|
478
|
+
root.colours << back
|
479
|
+
if block_given?
|
480
|
+
apply(style) {|node| yield node}
|
481
|
+
else
|
482
|
+
apply(style)
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
# This method creates a new table node and returns it. The method accepts
|
487
|
+
# a block that will be passed the table as a parameter. The node is added
|
488
|
+
# to the node the method is called upon after the block is complete.
|
489
|
+
#
|
490
|
+
# ==== Parameters
|
491
|
+
# rows:: The number of rows that the table contains.
|
492
|
+
# columns:: The number of columns that the table contains.
|
493
|
+
# *widths:: One or more integers representing the widths for the table
|
494
|
+
# columns.
|
495
|
+
def table(rows, columns, *widths)
|
496
|
+
node = TableNode.new(self, rows, columns, *widths)
|
497
|
+
yield node if block_given?
|
498
|
+
store(node)
|
499
|
+
node
|
500
|
+
end
|
501
|
+
|
502
|
+
alias :write :<<
|
503
|
+
alias :color :colour
|
504
|
+
alias :split? :split
|
505
|
+
end # End of the CommandNode class.
|
506
|
+
|
507
|
+
|
508
|
+
# This class represents a table node within an RTF document. Table nodes are
|
509
|
+
# specialised container nodes that contain only TableRowNodes and have their
|
510
|
+
# size specified when they are created an cannot be resized after that.
|
511
|
+
class TableNode < ContainerNode
|
512
|
+
# Attribute accessor.
|
513
|
+
attr_reader :cell_margin
|
514
|
+
|
515
|
+
# Attribute mutator.
|
516
|
+
attr_writer :cell_margin
|
517
|
+
|
518
|
+
# This is a constructor for the TableNode class.
|
519
|
+
#
|
520
|
+
# ==== Parameters
|
521
|
+
# parent:: A reference to the node that owns the table.
|
522
|
+
# rows:: The number of rows in the tabkle.
|
523
|
+
# columns:: The number of columns in the table.
|
524
|
+
# *widths:: One or more integers specifying the widths of the table
|
525
|
+
# columns.
|
526
|
+
def initialize(parent, rows, columns, *widths)
|
527
|
+
super(parent) do
|
528
|
+
entries = []
|
529
|
+
rows.times {entries.push(TableRowNode.new(self, columns, *widths))}
|
530
|
+
entries
|
531
|
+
end
|
532
|
+
@cell_margin = 100
|
533
|
+
end
|
534
|
+
|
535
|
+
# Attribute accessor.
|
536
|
+
def rows
|
537
|
+
entries.size
|
538
|
+
end
|
539
|
+
|
540
|
+
# Attribute accessor.
|
541
|
+
def columns
|
542
|
+
entries[0].length
|
543
|
+
end
|
544
|
+
|
545
|
+
# This method assigns a border width setting to all of the sides on all
|
546
|
+
# of the cells within a table.
|
547
|
+
#
|
548
|
+
# ==== Parameters
|
549
|
+
# width:: The border width setting to apply. Negative values are ignored
|
550
|
+
# and zero switches the border off.
|
551
|
+
def border_width=(width)
|
552
|
+
self.each {|row| row.border_width = width}
|
553
|
+
end
|
554
|
+
|
555
|
+
# This method assigns a shading colour to a specified row within a
|
556
|
+
# TableNode object.
|
557
|
+
#
|
558
|
+
# ==== Parameters
|
559
|
+
# index:: The offset from the first row of the row to have shading
|
560
|
+
# applied to it.
|
561
|
+
# colour:: A reference to a Colour object representing the shading colour
|
562
|
+
# to be used. Set to nil to clear shading.
|
563
|
+
def row_shading_colour(index, colour)
|
564
|
+
row = self[index]
|
565
|
+
row.shading_colour = colour if row != nil
|
566
|
+
end
|
567
|
+
|
568
|
+
# This method assigns a shading colour to a specified column within a
|
569
|
+
# TableNode object.
|
570
|
+
#
|
571
|
+
# ==== Parameters
|
572
|
+
# index:: The offset from the first column of the column to have shading
|
573
|
+
# applied to it.
|
574
|
+
# colour:: A reference to a Colour object representing the shading colour
|
575
|
+
# to be used. Set to nil to clear shading.
|
576
|
+
def column_shading_colour(index, colour)
|
577
|
+
self.each do |row|
|
578
|
+
cell = row[index]
|
579
|
+
cell.shading_colour = colour if cell != nil
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
# This method provides a means of assigning a shading colour to a
|
584
|
+
# selection of cells within a table. The method accepts a block that
|
585
|
+
# takes three parameters - a TableCellNode representing a cell within the
|
586
|
+
# table, an integer representing the x offset of the cell and an integer
|
587
|
+
# representing the y offset of the cell. If the block returns true then
|
588
|
+
# shading will be applied to the cell.
|
589
|
+
#
|
590
|
+
# ==== Parameters
|
591
|
+
# colour:: A reference to a Colour object representing the shading colour
|
592
|
+
# to be applied. Set to nil to remove shading.
|
593
|
+
def shading_colour(colour)
|
594
|
+
if block_given?
|
595
|
+
0.upto(self.size - 1) do |x|
|
596
|
+
row = self[x]
|
597
|
+
0.upto(row.size - 1) do |y|
|
598
|
+
apply = yield row[y], x, y
|
599
|
+
row[y].shading_colour = colour if apply
|
600
|
+
end
|
601
|
+
end
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
# This method overloads the store method inherited from the ContainerNode
|
606
|
+
# class to forbid addition of further nodes.
|
607
|
+
#
|
608
|
+
# ==== Parameters
|
609
|
+
# node:: A reference to the node to be added.
|
610
|
+
def store(node)
|
611
|
+
RTFError.fire("Table nodes cannot have nodes added to.")
|
612
|
+
end
|
613
|
+
|
614
|
+
# This method generates the RTF document text for a TableCellNode object.
|
615
|
+
def to_rtf
|
616
|
+
text = StringIO.new
|
617
|
+
size = 0
|
618
|
+
|
619
|
+
self.each do |row|
|
620
|
+
if size > 0
|
621
|
+
text << "\n"
|
622
|
+
else
|
623
|
+
size = 1
|
624
|
+
end
|
625
|
+
text << row.to_rtf
|
626
|
+
end
|
627
|
+
|
628
|
+
text.string
|
629
|
+
end
|
630
|
+
|
631
|
+
alias :column_shading_color :column_shading_colour
|
632
|
+
alias :row_shading_color :row_shading_colour
|
633
|
+
alias :shading_color :shading_colour
|
634
|
+
end # End of the TableNode class.
|
635
|
+
|
636
|
+
|
637
|
+
# This class represents a row within an RTF table. The TableRowNode is a
|
638
|
+
# specialised container node that can hold only TableCellNodes and, once
|
639
|
+
# created, cannot be resized. Its also not possible to change the parent
|
640
|
+
# of a TableRowNode object.
|
641
|
+
class TableRowNode < ContainerNode
|
642
|
+
# This is the constructor for the TableRowNode class.
|
643
|
+
#
|
644
|
+
# ===== Parameters
|
645
|
+
# table:: A reference to table that owns the row.
|
646
|
+
# cells:: The number of cells that the row will contain.
|
647
|
+
# widths:: One or more integers specifying the widths for the table
|
648
|
+
# columns
|
649
|
+
def initialize(table, cells, *widths)
|
650
|
+
super(table) do
|
651
|
+
entries = []
|
652
|
+
cells.times do |index|
|
653
|
+
entries.push(TableCellNode.new(self, widths[index]))
|
654
|
+
end
|
655
|
+
entries
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
# Attrobute accessors
|
660
|
+
def length
|
661
|
+
entries.size
|
662
|
+
end
|
663
|
+
|
664
|
+
# This method assigns a border width setting to all of the sides on all
|
665
|
+
# of the cells within a table row.
|
666
|
+
#
|
667
|
+
# ==== Parameters
|
668
|
+
# width:: The border width setting to apply. Negative values are ignored
|
669
|
+
# and zero switches the border off.
|
670
|
+
def border_width=(width)
|
671
|
+
self.each {|cell| cell.border_width = width}
|
672
|
+
end
|
673
|
+
|
674
|
+
# This method overloads the parent= method inherited from the Node class
|
675
|
+
# to forbid the alteration of the cells parent.
|
676
|
+
#
|
677
|
+
# ==== Parameters
|
678
|
+
# parent:: A reference to the new node parent.
|
679
|
+
def parent=(parent)
|
680
|
+
RTFError.fire("Table row nodes cannot have their parent changed.")
|
681
|
+
end
|
682
|
+
|
683
|
+
# This method sets the shading colour for a row.
|
684
|
+
#
|
685
|
+
# ==== Parameters
|
686
|
+
# colour:: A reference to the Colour object that represents the new
|
687
|
+
# shading colour. Set to nil to switch shading off.
|
688
|
+
def shading_colour=(colour)
|
689
|
+
self.each {|cell| cell.shading_colour = colour}
|
690
|
+
end
|
691
|
+
|
692
|
+
# This method overloads the store method inherited from the ContainerNode
|
693
|
+
# class to forbid addition of further nodes.
|
694
|
+
#
|
695
|
+
# ==== Parameters
|
696
|
+
# node:: A reference to the node to be added.
|
697
|
+
#def store(node)
|
698
|
+
# RTFError.fire("Table row nodes cannot have nodes added to.")
|
699
|
+
#end
|
700
|
+
|
701
|
+
# This method generates the RTF document text for a TableCellNode object.
|
702
|
+
def to_rtf
|
703
|
+
text = StringIO.new
|
704
|
+
temp = StringIO.new
|
705
|
+
offset = 0
|
706
|
+
|
707
|
+
text << "\\trowd\\tgraph#{parent.cell_margin}"
|
708
|
+
self.each do |entry|
|
709
|
+
widths = entry.border_widths
|
710
|
+
colour = entry.shading_colour
|
711
|
+
|
712
|
+
text << "\n"
|
713
|
+
text << "\\clbrdrt\\brdrw#{widths[0]}\\brdrs" if widths[0] != 0
|
714
|
+
text << "\\clbrdrl\\brdrw#{widths[3]}\\brdrs" if widths[3] != 0
|
715
|
+
text << "\\clbrdrb\\brdrw#{widths[2]}\\brdrs" if widths[2] != 0
|
716
|
+
text << "\\clbrdrr\\brdrw#{widths[1]}\\brdrs" if widths[1] != 0
|
717
|
+
text << "\\clcbpat#{root.colours.index(colour)}" if colour != nil
|
718
|
+
text << "\\cellx#{entry.width + offset}"
|
719
|
+
temp << "\n#{entry.to_rtf}"
|
720
|
+
offset += entry.width
|
721
|
+
end
|
722
|
+
text << "#{temp.string}\n\\row"
|
723
|
+
|
724
|
+
text.string
|
725
|
+
end
|
726
|
+
end # End of the TableRowNode class.
|
727
|
+
|
728
|
+
|
729
|
+
# This class represents a cell within an RTF table. The TableCellNode is a
|
730
|
+
# specialised command node that is forbidden from creating tables or having
|
731
|
+
# its parent changed.
|
732
|
+
class TableCellNode < CommandNode
|
733
|
+
# A definition for the default width for the cell.
|
734
|
+
DEFAULT_WIDTH = 300
|
735
|
+
|
736
|
+
# Attribute accessor.
|
737
|
+
attr_reader :width, :shading_colour, :style
|
738
|
+
|
739
|
+
# Attribute mutator.
|
740
|
+
attr_writer :width, :style
|
741
|
+
|
742
|
+
# This is the constructor for the TableCellNode class.
|
743
|
+
#
|
744
|
+
# ==== Parameters
|
745
|
+
# row:: The row that the cell belongs to.
|
746
|
+
# width:: The width to be assigned to the cell. This defaults to
|
747
|
+
# TableCellNode::DEFAULT_WIDTH.
|
748
|
+
# style:: The style that is applied to the cell. This must be a
|
749
|
+
# ParagraphStyle class. Defaults to nil.
|
750
|
+
# top:: The border width for the cells top border. Defaults to nil.
|
751
|
+
# right:: The border width for the cells right hand border. Defaults to
|
752
|
+
# nil.
|
753
|
+
# bottom:: The border width for the cells bottom border. Defaults to nil.
|
754
|
+
# left:: The border width for the cells left hand border. Defaults to
|
755
|
+
# nil.
|
756
|
+
#
|
757
|
+
# ==== Exceptions
|
758
|
+
# RTFError:: Generated whenever an invalid style setting is specified.
|
759
|
+
def initialize(row, width=DEFAULT_WIDTH, style=nil, top=nil, right=nil,
|
760
|
+
bottom=nil, left=nil)
|
761
|
+
super(row, nil)
|
762
|
+
if style != nil && style.is_paragraph_style? == false
|
763
|
+
RTFError.fire("Non-paragraph style specified for TableCellNode "\
|
764
|
+
"constructor.")
|
765
|
+
end
|
766
|
+
|
767
|
+
@width = (width != nil && width > 0) ? width : DEFAULT_WIDTH
|
768
|
+
@borders = [(top != nil && top > 0) ? top : nil,
|
769
|
+
(right != nil && right > 0) ? right : nil,
|
770
|
+
(bottom != nil && bottom > 0) ? bottom : nil,
|
771
|
+
(left != nil && left > 0) ? left : nil]
|
772
|
+
@shading_colour = nil
|
773
|
+
@style = style
|
774
|
+
end
|
775
|
+
|
776
|
+
# Attribute mutator.
|
777
|
+
#
|
778
|
+
# ==== Parameters
|
779
|
+
# style:: A reference to the style object to be applied to the cell.
|
780
|
+
# Must be an instance of the ParagraphStyle class. Set to nil
|
781
|
+
# to clear style settings.
|
782
|
+
#
|
783
|
+
# ==== Exceptions
|
784
|
+
# RTFError:: Generated whenever an invalid style setting is specified.
|
785
|
+
def style=(style)
|
786
|
+
if style != nil && style.is_paragraph_style? == false
|
787
|
+
RTFError.fire("Non-paragraph style specified for TableCellNode "\
|
788
|
+
"constructor.")
|
789
|
+
end
|
790
|
+
@style = style
|
791
|
+
end
|
792
|
+
|
793
|
+
# This method assigns a width, in twips, for the borders on all sides of
|
794
|
+
# the cell. Negative widths will be ignored and a width of zero will
|
795
|
+
# switch the border off.
|
796
|
+
#
|
797
|
+
# ==== Parameters
|
798
|
+
# width:: The setting for the width of the border.
|
799
|
+
def border_width=(width)
|
800
|
+
size = width == nil ? 0 : width
|
801
|
+
if size > 0
|
802
|
+
@borders[0] = @borders[1] = @borders[2] = @borders[3] = size.to_i
|
803
|
+
else
|
804
|
+
@borders = [nil, nil, nil, nil]
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
808
|
+
# This method assigns a border width to the top side of a table cell.
|
809
|
+
# Negative values are ignored and a value of 0 switches the border off.
|
810
|
+
#
|
811
|
+
# ==== Parameters
|
812
|
+
# width:: The new border width setting.
|
813
|
+
def top_border_width=(width)
|
814
|
+
size = width == nil ? 0 : width
|
815
|
+
if size > 0
|
816
|
+
@borders[0] = size.to_i
|
817
|
+
else
|
818
|
+
@borders[0] = nil
|
819
|
+
end
|
820
|
+
end
|
821
|
+
|
822
|
+
# This method assigns a border width to the right side of a table cell.
|
823
|
+
# Negative values are ignored and a value of 0 switches the border off.
|
824
|
+
#
|
825
|
+
# ==== Parameters
|
826
|
+
# width:: The new border width setting.
|
827
|
+
def right_border_width=(width)
|
828
|
+
size = width == nil ? 0 : width
|
829
|
+
if size > 0
|
830
|
+
@borders[1] = size.to_i
|
831
|
+
else
|
832
|
+
@borders[1] = nil
|
833
|
+
end
|
834
|
+
end
|
835
|
+
|
836
|
+
# This method assigns a border width to the bottom side of a table cell.
|
837
|
+
# Negative values are ignored and a value of 0 switches the border off.
|
838
|
+
#
|
839
|
+
# ==== Parameters
|
840
|
+
# width:: The new border width setting.
|
841
|
+
def bottom_border_width=(width)
|
842
|
+
size = width == nil ? 0 : width
|
843
|
+
if size > 0
|
844
|
+
@borders[2] = size.to_i
|
845
|
+
else
|
846
|
+
@borders[2] = nil
|
847
|
+
end
|
848
|
+
end
|
849
|
+
|
850
|
+
# This method assigns a border width to the left side of a table cell.
|
851
|
+
# Negative values are ignored and a value of 0 switches the border off.
|
852
|
+
#
|
853
|
+
# ==== Parameters
|
854
|
+
# width:: The new border width setting.
|
855
|
+
def left_border_width=(width)
|
856
|
+
size = width == nil ? 0 : width
|
857
|
+
if size > 0
|
858
|
+
@borders[3] = size.to_i
|
859
|
+
else
|
860
|
+
@borders[3] = nil
|
861
|
+
end
|
862
|
+
end
|
863
|
+
|
864
|
+
# This method alters the shading colour associated with a TableCellNode
|
865
|
+
# object.
|
866
|
+
#
|
867
|
+
# ==== Parameters
|
868
|
+
# colour:: A reference to the Colour object to use in shading the cell.
|
869
|
+
# Assign nil to clear cell shading.
|
870
|
+
def shading_colour=(colour)
|
871
|
+
root.colours << colour
|
872
|
+
@shading_colour = colour
|
873
|
+
end
|
874
|
+
|
875
|
+
# This method retrieves an array with the cell border width settings.
|
876
|
+
# The values are inserted in top, right, bottom, left order.
|
877
|
+
def border_widths
|
878
|
+
widths = []
|
879
|
+
@borders.each {|entry| widths.push(entry == nil ? 0 : entry)}
|
880
|
+
widths
|
881
|
+
end
|
882
|
+
|
883
|
+
# This method fetches the width for top border of a cell.
|
884
|
+
def top_border_width
|
885
|
+
@borders[0] == nil ? 0 : @borders[0]
|
886
|
+
end
|
887
|
+
|
888
|
+
# This method fetches the width for right border of a cell.
|
889
|
+
def right_border_width
|
890
|
+
@borders[1] == nil ? 0 : @borders[1]
|
891
|
+
end
|
892
|
+
|
893
|
+
# This method fetches the width for bottom border of a cell.
|
894
|
+
def bottom_border_width
|
895
|
+
@borders[2] == nil ? 0 : @borders[2]
|
896
|
+
end
|
897
|
+
|
898
|
+
# This method fetches the width for left border of a cell.
|
899
|
+
def left_border_width
|
900
|
+
@borders[3] == nil ? 0 : @borders[3]
|
901
|
+
end
|
902
|
+
|
903
|
+
# This method overloads the paragraph method inherited from the
|
904
|
+
# ComamndNode class to forbid the creation of paragraphs.
|
905
|
+
#
|
906
|
+
# ==== Parameters
|
907
|
+
# justification:: The justification to be applied to the paragraph.
|
908
|
+
# before:: The amount of space, in twips, to be inserted before
|
909
|
+
# the paragraph. Defaults to nil.
|
910
|
+
# after:: The amount of space, in twips, to be inserted after
|
911
|
+
# the paragraph. Defaults to nil.
|
912
|
+
# left:: The amount of indentation to place on the left of the
|
913
|
+
# paragraph. Defaults to nil.
|
914
|
+
# right:: The amount of indentation to place on the right of the
|
915
|
+
# paragraph. Defaults to nil.
|
916
|
+
# first:: The amount of indentation to place on the left of the
|
917
|
+
# first line in the paragraph. Defaults to nil.
|
918
|
+
def paragraph(justification=CommandNode::LEFT_JUSTIFY, before=nil,
|
919
|
+
after=nil, left=nil, right=nil, first=nil)
|
920
|
+
RTFError.fire("TableCellNode#paragraph() called. Table cells cannot "\
|
921
|
+
"contain paragraphs.")
|
922
|
+
end
|
923
|
+
|
924
|
+
# This method overloads the parent= method inherited from the Node class
|
925
|
+
# to forbid the alteration of the cells parent.
|
926
|
+
#
|
927
|
+
# ==== Parameters
|
928
|
+
# parent:: A reference to the new node parent.
|
929
|
+
def parent=(parent)
|
930
|
+
RTFError.fire("Table cell nodes cannot have their parent changed.")
|
931
|
+
end
|
932
|
+
|
933
|
+
# This method overrides the table method inherited from CommandNode to
|
934
|
+
# forbid its use in table cells.
|
935
|
+
#
|
936
|
+
# ==== Parameters
|
937
|
+
# rows:: The number of rows for the table.
|
938
|
+
# columns:: The number of columns for the table.
|
939
|
+
# *widths:: One or more integers representing the widths for the table
|
940
|
+
# columns.
|
941
|
+
def table(rows, columns, *widths)
|
942
|
+
RTFError.fire("TableCellNode#table() called. Nested tables not allowed.")
|
943
|
+
end
|
944
|
+
|
945
|
+
# This method generates the RTF document text for a TableCellNode object.
|
946
|
+
def to_rtf
|
947
|
+
text = StringIO.new
|
948
|
+
separator = split? ? "\n" : " "
|
949
|
+
line = (separator == " ")
|
950
|
+
|
951
|
+
text << "\\pard\\intbl"
|
952
|
+
text << @style.prefix(nil, nil) if @style != nil
|
953
|
+
text << separator
|
954
|
+
self.each do |entry|
|
955
|
+
text << "\n" if line
|
956
|
+
line = true
|
957
|
+
text << entry.to_rtf
|
958
|
+
end
|
959
|
+
text << (split? ? "\n" : " ")
|
960
|
+
text << "\\cell"
|
961
|
+
|
962
|
+
text.string
|
963
|
+
end
|
964
|
+
end # End of the TableCellNode class.
|
965
|
+
|
966
|
+
|
967
|
+
# This class represents a document header.
|
968
|
+
class HeaderNode < CommandNode
|
969
|
+
# A definition for a header type.
|
970
|
+
UNIVERSAL = :header
|
971
|
+
|
972
|
+
# A definition for a header type.
|
973
|
+
LEFT_PAGE = :headerl
|
974
|
+
|
975
|
+
# A definition for a header type.
|
976
|
+
RIGHT_PAGE = :headerr
|
977
|
+
|
978
|
+
# A definition for a header type.
|
979
|
+
FIRST_PAGE = :headerf
|
980
|
+
|
981
|
+
# Attribute accessor.
|
982
|
+
attr_reader :type
|
983
|
+
|
984
|
+
# Attribute mutator.
|
985
|
+
attr_writer :type
|
986
|
+
|
987
|
+
|
988
|
+
# This is the constructor for the HeaderNode class.
|
989
|
+
#
|
990
|
+
# ==== Parameters
|
991
|
+
# document:: A reference to the Document object that will own the new
|
992
|
+
# header.
|
993
|
+
# type:: The style type for the new header. Defaults to a value of
|
994
|
+
# HeaderNode::UNIVERSAL.
|
995
|
+
def initialize(document, type=UNIVERSAL)
|
996
|
+
super(document, "\\#{type.id2name}", nil, false)
|
997
|
+
@type = type
|
998
|
+
end
|
999
|
+
|
1000
|
+
# This method overloads the footnote method inherited from the CommandNode
|
1001
|
+
# class to prevent footnotes being added to headers.
|
1002
|
+
#
|
1003
|
+
# ==== Parameters
|
1004
|
+
# text:: Not used.
|
1005
|
+
#
|
1006
|
+
# ==== Exceptions
|
1007
|
+
# RTFError:: Always generated whenever this method is called.
|
1008
|
+
def footnote(text)
|
1009
|
+
RTFError.fire("Footnotes are not permitted in page headers.")
|
1010
|
+
end
|
1011
|
+
end # End of the HeaderNode class.
|
1012
|
+
|
1013
|
+
|
1014
|
+
# This class represents a document footer.
|
1015
|
+
class FooterNode < CommandNode
|
1016
|
+
# A definition for a header type.
|
1017
|
+
UNIVERSAL = :footer
|
1018
|
+
|
1019
|
+
# A definition for a header type.
|
1020
|
+
LEFT_PAGE = :footerl
|
1021
|
+
|
1022
|
+
# A definition for a header type.
|
1023
|
+
RIGHT_PAGE = :footerr
|
1024
|
+
|
1025
|
+
# A definition for a header type.
|
1026
|
+
FIRST_PAGE = :footerf
|
1027
|
+
|
1028
|
+
# Attribute accessor.
|
1029
|
+
attr_reader :type
|
1030
|
+
|
1031
|
+
# Attribute mutator.
|
1032
|
+
attr_writer :type
|
1033
|
+
|
1034
|
+
|
1035
|
+
# This is the constructor for the FooterNode class.
|
1036
|
+
#
|
1037
|
+
# ==== Parameters
|
1038
|
+
# document:: A reference to the Document object that will own the new
|
1039
|
+
# footer.
|
1040
|
+
# type:: The style type for the new footer. Defaults to a value of
|
1041
|
+
# FooterNode::UNIVERSAL.
|
1042
|
+
def initialize(document, type=UNIVERSAL)
|
1043
|
+
super(document, "\\#{type.id2name}", nil, false)
|
1044
|
+
@type = type
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
# This method overloads the footnote method inherited from the CommandNode
|
1048
|
+
# class to prevent footnotes being added to footers.
|
1049
|
+
#
|
1050
|
+
# ==== Parameters
|
1051
|
+
# text:: Not used.
|
1052
|
+
#
|
1053
|
+
# ==== Exceptions
|
1054
|
+
# RTFError:: Always generated whenever this method is called.
|
1055
|
+
def footnote(text)
|
1056
|
+
RTFError.fire("Footnotes are not permitted in page footers.")
|
1057
|
+
end
|
1058
|
+
end # End of the FooterNode class.
|
1059
|
+
|
1060
|
+
|
1061
|
+
# This class represents an RTF document. In actuality it is just a
|
1062
|
+
# specialised Node type that cannot be assigned a parent and that holds
|
1063
|
+
# document font, colour and information tables.
|
1064
|
+
class Document < CommandNode
|
1065
|
+
# A definition for a document character set setting.
|
1066
|
+
CS_ANSI = :ansi
|
1067
|
+
|
1068
|
+
# A definition for a document character set setting.
|
1069
|
+
CS_MAC = :mac
|
1070
|
+
|
1071
|
+
# A definition for a document character set setting.
|
1072
|
+
CS_PC = :pc
|
1073
|
+
|
1074
|
+
# A definition for a document character set setting.
|
1075
|
+
CS_PCA = :pca
|
1076
|
+
|
1077
|
+
# A definition for a document language setting.
|
1078
|
+
LC_AFRIKAANS = 1078
|
1079
|
+
|
1080
|
+
# A definition for a document language setting.
|
1081
|
+
LC_ARABIC = 1025
|
1082
|
+
|
1083
|
+
# A definition for a document language setting.
|
1084
|
+
LC_CATALAN = 1027
|
1085
|
+
|
1086
|
+
# A definition for a document language setting.
|
1087
|
+
LC_CHINESE_TRADITIONAL = 1028
|
1088
|
+
|
1089
|
+
# A definition for a document language setting.
|
1090
|
+
LC_CHINESE_SIMPLIFIED = 2052
|
1091
|
+
|
1092
|
+
# A definition for a document language setting.
|
1093
|
+
LC_CZECH = 1029
|
1094
|
+
|
1095
|
+
# A definition for a document language setting.
|
1096
|
+
LC_DANISH = 1030
|
1097
|
+
|
1098
|
+
# A definition for a document language setting.
|
1099
|
+
LC_DUTCH = 1043
|
1100
|
+
|
1101
|
+
# A definition for a document language setting.
|
1102
|
+
LC_DUTCH_BELGIAN = 2067
|
1103
|
+
|
1104
|
+
# A definition for a document language setting.
|
1105
|
+
LC_ENGLISH_UK = 2057
|
1106
|
+
|
1107
|
+
# A definition for a document language setting.
|
1108
|
+
LC_ENGLISH_US = 1033
|
1109
|
+
|
1110
|
+
# A definition for a document language setting.
|
1111
|
+
LC_FINNISH = 1035
|
1112
|
+
|
1113
|
+
# A definition for a document language setting.
|
1114
|
+
LC_FRENCH = 1036
|
1115
|
+
|
1116
|
+
# A definition for a document language setting.
|
1117
|
+
LC_FRENCH_BELGIAN = 2060
|
1118
|
+
|
1119
|
+
# A definition for a document language setting.
|
1120
|
+
LC_FRENCH_CANADIAN = 3084
|
1121
|
+
|
1122
|
+
# A definition for a document language setting.
|
1123
|
+
LC_FRENCH_SWISS = 4108
|
1124
|
+
|
1125
|
+
# A definition for a document language setting.
|
1126
|
+
LC_GERMAN = 1031
|
1127
|
+
|
1128
|
+
# A definition for a document language setting.
|
1129
|
+
LC_GERMAN_SWISS = 2055
|
1130
|
+
|
1131
|
+
# A definition for a document language setting.
|
1132
|
+
LC_GREEK = 1032
|
1133
|
+
|
1134
|
+
# A definition for a document language setting.
|
1135
|
+
LC_HEBREW = 1037
|
1136
|
+
|
1137
|
+
# A definition for a document language setting.
|
1138
|
+
LC_HUNGARIAN = 1038
|
1139
|
+
|
1140
|
+
# A definition for a document language setting.
|
1141
|
+
LC_ICELANDIC = 1039
|
1142
|
+
|
1143
|
+
# A definition for a document language setting.
|
1144
|
+
LC_INDONESIAN = 1057
|
1145
|
+
|
1146
|
+
# A definition for a document language setting.
|
1147
|
+
LC_ITALIAN = 1040
|
1148
|
+
|
1149
|
+
# A definition for a document language setting.
|
1150
|
+
LC_JAPANESE = 1041
|
1151
|
+
|
1152
|
+
# A definition for a document language setting.
|
1153
|
+
LC_KOREAN = 1042
|
1154
|
+
|
1155
|
+
# A definition for a document language setting.
|
1156
|
+
LC_NORWEGIAN_BOKMAL = 1044
|
1157
|
+
|
1158
|
+
# A definition for a document language setting.
|
1159
|
+
LC_NORWEGIAN_NYNORSK = 2068
|
1160
|
+
|
1161
|
+
# A definition for a document language setting.
|
1162
|
+
LC_POLISH = 1045
|
1163
|
+
|
1164
|
+
# A definition for a document language setting.
|
1165
|
+
LC_PORTUGUESE = 2070
|
1166
|
+
|
1167
|
+
# A definition for a document language setting.
|
1168
|
+
LC_POTUGUESE_BRAZILIAN = 1046
|
1169
|
+
|
1170
|
+
# A definition for a document language setting.
|
1171
|
+
LC_ROMANIAN = 1048
|
1172
|
+
|
1173
|
+
# A definition for a document language setting.
|
1174
|
+
LC_RUSSIAN = 1049
|
1175
|
+
|
1176
|
+
# A definition for a document language setting.
|
1177
|
+
LC_SERBO_CROATIAN_CYRILLIC = 2074
|
1178
|
+
|
1179
|
+
# A definition for a document language setting.
|
1180
|
+
LC_SERBO_CROATIAN_LATIN = 1050
|
1181
|
+
|
1182
|
+
# A definition for a document language setting.
|
1183
|
+
LC_SLOVAK = 1051
|
1184
|
+
|
1185
|
+
# A definition for a document language setting.
|
1186
|
+
LC_SPANISH_CASTILLIAN = 1034
|
1187
|
+
|
1188
|
+
# A definition for a document language setting.
|
1189
|
+
LC_SPANISH_MEXICAN = 2058
|
1190
|
+
|
1191
|
+
# A definition for a document language setting.
|
1192
|
+
LC_SWAHILI = 1089
|
1193
|
+
|
1194
|
+
# A definition for a document language setting.
|
1195
|
+
LC_SWEDISH = 1053
|
1196
|
+
|
1197
|
+
# A definition for a document language setting.
|
1198
|
+
LC_THAI = 1054
|
1199
|
+
|
1200
|
+
# A definition for a document language setting.
|
1201
|
+
LC_TURKISH = 1055
|
1202
|
+
|
1203
|
+
# A definition for a document language setting.
|
1204
|
+
LC_UNKNOWN = 1024
|
1205
|
+
|
1206
|
+
# A definition for a document language setting.
|
1207
|
+
LC_VIETNAMESE = 1066
|
1208
|
+
|
1209
|
+
# Attribute accessor.
|
1210
|
+
attr_reader :fonts, :colours, :information, :character_set, :language,
|
1211
|
+
:style
|
1212
|
+
|
1213
|
+
# Attribute mutator.
|
1214
|
+
attr_writer :character_set, :language
|
1215
|
+
|
1216
|
+
|
1217
|
+
# This is a constructor for the Document class.
|
1218
|
+
#
|
1219
|
+
# ==== Parameters
|
1220
|
+
# font:: The default font to be used by the document.
|
1221
|
+
# style:: The style settings to be applied to the document. This
|
1222
|
+
# defaults to nil.
|
1223
|
+
# character:: The character set to be applied to the document. This
|
1224
|
+
# defaults to Document::CS_ANSI.
|
1225
|
+
# language:: The language setting to be applied to document. This
|
1226
|
+
# defaults to Document::LC_ENGLISH_UK.
|
1227
|
+
def initialize(font, style=nil, character=CS_ANSI, language=LC_ENGLISH_UK)
|
1228
|
+
super(nil, '\rtf1')
|
1229
|
+
@fonts = FontTable.new(font)
|
1230
|
+
@default_font = 0
|
1231
|
+
@colours = ColourTable.new
|
1232
|
+
@information = Information.new
|
1233
|
+
@character_set = character
|
1234
|
+
@language = language
|
1235
|
+
@style = style == nil ? DocumentStyle.new : style
|
1236
|
+
@headers = [nil, nil, nil, nil]
|
1237
|
+
@footers = [nil, nil, nil, nil]
|
1238
|
+
end
|
1239
|
+
|
1240
|
+
# Attribute accessor.
|
1241
|
+
def default_font
|
1242
|
+
@fonts[@default_font]
|
1243
|
+
end
|
1244
|
+
|
1245
|
+
# This method assigns a new header to a document. A Document object can
|
1246
|
+
# have up to four header - a default header, a header for left pages, a
|
1247
|
+
# header for right pages and a header for the first page. The method
|
1248
|
+
# checks the header type and stores it appropriately.
|
1249
|
+
#
|
1250
|
+
# ==== Parameters
|
1251
|
+
# header:: A reference to the header object to be stored. Existing header
|
1252
|
+
# objects are overwritten.
|
1253
|
+
def header=(header)
|
1254
|
+
if header.type == HeaderNode::UNIVERSAL
|
1255
|
+
@headers[0] = header
|
1256
|
+
elsif header.type == HeaderNode::LEFT_PAGE
|
1257
|
+
@headers[1] = header
|
1258
|
+
elsif header.type == HeaderNode::RIGHT_PAGE
|
1259
|
+
@headers[2] = header
|
1260
|
+
elsif header.type == HeaderNode::FIRST_PAGE
|
1261
|
+
@headers[3] = header
|
1262
|
+
end
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
# This method assigns a new footer to a document. A Document object can
|
1266
|
+
# have up to four footers - a default footer, a footer for left pages, a
|
1267
|
+
# footer for right pages and a footer for the first page. The method
|
1268
|
+
# checks the footer type and stores it appropriately.
|
1269
|
+
#
|
1270
|
+
# ==== Parameters
|
1271
|
+
# footer:: A reference to the footer object to be stored. Existing footer
|
1272
|
+
# objects are overwritten.
|
1273
|
+
def footer=(footer)
|
1274
|
+
if footer.type == FooterNode::UNIVERSAL
|
1275
|
+
@footers[0] = footer
|
1276
|
+
elsif footer.type == FooterNode::LEFT_PAGE
|
1277
|
+
@footers[1] = footer
|
1278
|
+
elsif footer.type == FooterNode::RIGHT_PAGE
|
1279
|
+
@footers[2] = footer
|
1280
|
+
elsif footer.type == FooterNode::FIRST_PAGE
|
1281
|
+
@footers[3] = footer
|
1282
|
+
end
|
1283
|
+
end
|
1284
|
+
|
1285
|
+
# This method fetches a header from a Document object.
|
1286
|
+
#
|
1287
|
+
# ==== Parameters
|
1288
|
+
# type:: One of the header types defined in the header class. Defaults to
|
1289
|
+
# HeaderNode::UNIVERSAL.
|
1290
|
+
def header(type=HeaderNode::UNIVERSAL)
|
1291
|
+
index = 0
|
1292
|
+
if type == HeaderNode::LEFT_PAGE
|
1293
|
+
index = 1
|
1294
|
+
elsif type == HeaderNode::RIGHT_PAGE
|
1295
|
+
index = 2
|
1296
|
+
elsif type == HeaderNode::FIRST_PAGE
|
1297
|
+
index = 3
|
1298
|
+
end
|
1299
|
+
@headers[index]
|
1300
|
+
end
|
1301
|
+
|
1302
|
+
# This method fetches a footer from a Document object.
|
1303
|
+
#
|
1304
|
+
# ==== Parameters
|
1305
|
+
# type:: One of the footer types defined in the footer class. Defaults to
|
1306
|
+
# FooterNode::UNIVERSAL.
|
1307
|
+
def footer(type=FooterNode::UNIVERSAL)
|
1308
|
+
index = 0
|
1309
|
+
if type == FooterNode::LEFT_PAGE
|
1310
|
+
index = 1
|
1311
|
+
elsif type == FooterNode::RIGHT_PAGE
|
1312
|
+
index = 2
|
1313
|
+
elsif type == FooterNode::FIRST_PAGE
|
1314
|
+
index = 3
|
1315
|
+
end
|
1316
|
+
@footers[index]
|
1317
|
+
end
|
1318
|
+
|
1319
|
+
# Attribute mutator.
|
1320
|
+
#
|
1321
|
+
# ==== Parameters
|
1322
|
+
# font:: The new default font for the Document object.
|
1323
|
+
def default_font=(font)
|
1324
|
+
@fonts << font
|
1325
|
+
@default_font = @fonts.index(font)
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
# This method provides a short cut for obtaining the Paper object
|
1329
|
+
# associated with a Document object.
|
1330
|
+
def paper
|
1331
|
+
@style.paper
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
# This method overrides the parent=() method inherited from the
|
1335
|
+
# CommandNode class to disallow setting a parent on a Document object.
|
1336
|
+
#
|
1337
|
+
# ==== Parameters
|
1338
|
+
# parent:: A reference to the new parent node for the Document object.
|
1339
|
+
#
|
1340
|
+
# ==== Exceptions
|
1341
|
+
# RTFError:: Generated whenever this method is called.
|
1342
|
+
def parent=(parent)
|
1343
|
+
RTFError.fire("Document objects may not have a parent.")
|
1344
|
+
end
|
1345
|
+
|
1346
|
+
# This method inserts a page break into a document.
|
1347
|
+
def page_break
|
1348
|
+
self.store(CommandNode.new(self, '\page', nil, false))
|
1349
|
+
nil
|
1350
|
+
end
|
1351
|
+
|
1352
|
+
# This method fetches the width of the available work area space for a
|
1353
|
+
# typical Document object page.
|
1354
|
+
def body_width
|
1355
|
+
@style.body_width
|
1356
|
+
end
|
1357
|
+
|
1358
|
+
# This method fetches the height of the available work area space for a
|
1359
|
+
# a typical Document object page.
|
1360
|
+
def body_height
|
1361
|
+
@style.body_height
|
1362
|
+
end
|
1363
|
+
|
1364
|
+
# This method generates the RTF text for a Document object.
|
1365
|
+
def to_rtf
|
1366
|
+
text = StringIO.new
|
1367
|
+
|
1368
|
+
text << "{#{prefix}\\#{@character_set.id2name}"
|
1369
|
+
text << "\\deff#{@default_font}"
|
1370
|
+
text << "\\deflang#{@language}" if @language != nil
|
1371
|
+
text << "\\plain\\fs24\\fet1"
|
1372
|
+
text << "\n#{@fonts.to_rtf}"
|
1373
|
+
text << "\n#{@colours.to_rtf}" if @colours.size > 0
|
1374
|
+
text << "\n#{@information.to_rtf}"
|
1375
|
+
if @headers.compact != []
|
1376
|
+
text << "\n#{@headers[3].to_rtf}" if @headers[3] != nil
|
1377
|
+
text << "\n#{@headers[2].to_rtf}" if @headers[2] != nil
|
1378
|
+
text << "\n#{@headers[1].to_rtf}" if @headers[1] != nil
|
1379
|
+
if @headers[1] == nil or @headers[2] == nil
|
1380
|
+
text << "\n#{@headers[0].to_rtf}"
|
1381
|
+
end
|
1382
|
+
end
|
1383
|
+
if @footers.compact != []
|
1384
|
+
text << "\n#{@footers[3].to_rtf}" if @footers[3] != nil
|
1385
|
+
text << "\n#{@footers[2].to_rtf}" if @footers[2] != nil
|
1386
|
+
text << "\n#{@footers[1].to_rtf}" if @footers[1] != nil
|
1387
|
+
if @footers[1] == nil or @footers[2] == nil
|
1388
|
+
text << "\n#{@footers[0].to_rtf}"
|
1389
|
+
end
|
1390
|
+
end
|
1391
|
+
text << "\n#{@style.prefix(self)}" if @style != nil
|
1392
|
+
self.each {|entry| text << "\n#{entry.to_rtf}"}
|
1393
|
+
text << "\n}"
|
1394
|
+
|
1395
|
+
text.string
|
1396
|
+
end
|
1397
|
+
end # End of the Document class.
|
1398
|
+
end # End of the RTF module.
|