Repository navigation
Expand file tree
/
Copy pathTextObjectBase.cs
More file actions
495 lines (452 loc) · 17.1 KB
/
Copy pathTextObjectBase.cs
File metadata and controls
495 lines (452 loc) · 17.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
using System;
using System.ComponentModel;
using FastReport.Utils;
using FastReport.Format;
using System.Windows.Forms;
using System.Drawing.Design;
namespace FastReport
{
/// <summary>
/// Specifies how to display the duplicate values.
/// </summary>
public enum Duplicates
{
/// <summary>
/// The <b>TextObject</b> can show duplicate values.
/// </summary>
Show,
/// <summary>
/// The <b>TextObject</b> with duplicate value will be hidden.
/// </summary>
Hide,
/// <summary>
/// The <b>TextObject</b> with duplicate value will be shown but with no text.
/// </summary>
Clear,
/// <summary>
/// Several <b>TextObject</b> objects with the same value will be merged into one <b>TextObject</b> object.
/// </summary>
Merge
}
/// <summary>
/// Specifies how the report engine processes the text objects.
/// </summary>
public enum ProcessAt
{
/// <summary>
/// Specifies the default process mode. The text object is processed just-in-time.
/// </summary>
Default,
/// <summary>
/// Specifies that the text object must be processed when the entire report is finished. This mode
/// can be used to print grand total value (which is normally calculated at the end of report) in the
/// report title band.
/// </summary>
ReportFinished,
/// <summary>
/// Specifies that the text object must be processed when the entire report page is finished. This mode
/// can be used if the report template consists of several report pages.
/// </summary>
ReportPageFinished,
/// <summary>
/// Specifies that the text object must be processed when any report page is finished. This mode
/// can be used to print the page total (which is normally calculated at the page footer) in the
/// page header band.
/// </summary>
PageFinished,
/// <summary>
/// Specifies that the text object must be processed when the column is finished. This mode
/// can be used to print the column total (which is normally calculated at the column footer) in the
/// column header band.
/// </summary>
ColumnFinished,
/// <summary>
/// Specifies that the text object must be processed when the data block is finished. This mode can be
/// used to print a total value in the data header (which is normally available
/// in the data footer only).
/// </summary>
DataFinished,
/// <summary>
/// Specifies that the text object must be processed when the group is finished. This mode can be
/// used to print a total value in the group header (which is normally available
/// in the group footer only).
/// </summary>
GroupFinished,
/// <summary>
/// Specifies that the text object is processed manually when you call the <b>Engine.ProcessObject</b>
/// method in the report script.
/// </summary>
Custom
}
/// <summary>
/// Base class for text objects such as <see cref="TextObject"/> and <see cref="RichObject"/>.
/// </summary>
/// <remarks>
/// This class implements common functionality of the text objects.
/// </remarks>
public partial class TextObjectBase : BreakableComponent
{
#region Fields
private string text;
private object value;
private bool allowExpressions;
private string brackets;
private Padding padding;
private bool hideZeros;
private string hideValue;
private string nullValue;
private FormatCollection formats;
private ProcessAt processAt;
private Duplicates duplicates;
private bool editable;
#endregion
#region Properties
/// <summary>
/// Gets or sets a value indicating that the object's text may contain expressions.
/// </summary>
[DefaultValue(true)]
[Category("Data")]
public bool AllowExpressions
{
get { return allowExpressions; }
set { allowExpressions = value; }
}
/// <summary>
/// Gets or sets the symbols that will be used to find expressions in the object's text.
/// </summary>
/// <remarks>
/// The default property value is "[,]". As you can see, the open and close symbols are
/// separated by the comma. You may use another symbols, for example: "<,>" or "<%,%>".
/// You should use different open and close symbols.
/// </remarks>
[Category("Data")]
public string Brackets
{
get { return brackets; }
set { brackets = value; }
}
/// <summary>
/// Gets or sets the object's text.
/// </summary>
/// <remarks>
/// Text may contain expressions and data items, for example: "Today is [Date]".
/// When report is running, all expressions are calculated and replaced with actual
/// values, so the text would be "Today is 01.01.2008".
/// </remarks>
[Category("Data")]
public virtual string Text
{
get { return text; }
set { text = value; }
}
/// <summary>
/// Gets or sets padding within the text object.
/// </summary>
[Category("Layout")]
public Padding Padding
{
get { return padding; }
set { padding = value; }
}
/// <summary>
/// Gets or sets a value indicating that zero values must be hidden.
/// </summary>
[Category("Behavior")]
[DefaultValue(false)]
public bool HideZeros
{
get { return hideZeros; }
set { hideZeros = value; }
}
/// <summary>
/// Gets or sets a value that will be hidden.
/// </summary>
/// <remarks>
/// Use this property to specify a value that you would like to hide. For example, specify "0"
/// if you want to hide zero values, or use <see cref="HideZeros"/> property to do this.
/// <para/>You also may use this property to hide default DateTime values (such as 1/1/1900).
/// In this case you need to specify a string containing both date and time, for example:
/// "1/1/1900 0:00:00".
/// <note type="caution">
/// FastReport uses the <b>ToString</b> conversion to compare the expression value with this property.
/// This conversion depends on regional settings selected in the Control Panel, so be aware of this
/// if you going to distribute your report worldwide.
/// </note>
/// </remarks>
[Category("Behavior")]
public string HideValue
{
get { return hideValue; }
set { hideValue = value; }
}
/// <summary>
/// Gets or sets a string that will be displayed instead of a null value.
/// </summary>
[Category("Behavior")]
public string NullValue
{
get { return nullValue; }
set { nullValue = value; }
}
/// <summary>
/// Gets or sets the formatter that will be used to format data in the Text object.
/// </summary>
/// <remarks>
/// The default formatter does nothing, i.e. it shows expression values with no formatting.
/// To set another formatting, create a new formatter and assign it to this property.
/// <para/>If there are several expressions in the text, use the <see cref="Formats"/> property
/// to format each expression value.
/// </remarks>
/// <example>This example shows how to set currency formatter.
/// <code>
/// TextObject text1;
/// text1.Format = new CurrencyFormat();
/// </code>
/// </example>
[Category("Data")]
[Editor("FastReport.TypeEditors.FormatEditor, FastReport", typeof(UITypeEditor))]
public FormatBase Format
{
get { return formats.Count == 0 ? new GeneralFormat() : formats[0]; }
set
{
if (value == null)
value = new GeneralFormat();
if (formats.Count == 0)
formats.Add(value);
else
formats[0] = value;
}
}
/// <summary>
/// Gets or sets a value that specifies how the report engine processes this text object.
/// </summary>
/// <remarks>
/// Use this property to perform such task as "print a total value in the group header". Normally,
/// all total values are calculated in the footers (for example, in a group footer). If you try to print
/// a total value in the group header, you will get 0. If you set this property to
/// <b>ProcessAt.DataFinished</b>, FastReport will do the following:
/// <list type="bullet">
/// <item>
/// <description>print the object (with wrong value);</description>
/// </item>
/// <item>
/// <description>print all related data rows;</description>
/// </item>
/// <item>
/// <description>calculate the correct object's value and replace old (wrong) value with the new one.</description>
/// </item>
/// </list>
/// <note type="caution">
/// This option will not work if you set the <see cref="Report.UseFileCache"/> to <b>true</b>.
/// </note>
/// </remarks>
[Category("Behavior")]
[DefaultValue(ProcessAt.Default)]
public ProcessAt ProcessAt
{
get { return processAt; }
set { processAt = value; }
}
/// <summary>
/// Gets the collection of formatters.
/// </summary>
/// <remarks>
/// This property is used to set format for each expression contained in the text.
/// For example, if the <b>TextObject</b> contains two expressions:
/// <para/><i>Today is [Date]; Page [PageN]</i>
/// <para/>you can use the following code to format these expressions separately:
/// <code>
/// text1.Formats.Clear();
/// text1.Formats.Add(new DateFormat());
/// text1.Formats.Add(new NumberFormat());
/// </code>
/// </remarks>
[Browsable(false)]
public FormatCollection Formats
{
get { return formats; }
}
/// <summary>
/// Gets or sets a value that determines how to display duplicate values.
/// </summary>
[DefaultValue(Duplicates.Show)]
[Category("Behavior")]
public Duplicates Duplicates
{
get { return duplicates; }
set { duplicates = value; }
}
/// <summary>
/// Gets a value of expression contained in the object's text.
/// </summary>
[Browsable(false)]
public object Value
{
get { return value; }
}
/// <summary>
/// Gets or sets editable for pdf export
/// </summary>
[Category("Behavior")]
[DefaultValue(false)]
public bool Editable
{
get { return editable; }
set { editable = value; }
}
#endregion
#region Protected Methods
/// <inheritdoc/>
protected override void DeserializeSubItems(FRReader reader)
{
if (String.Compare(reader.ItemName, "Formats", true) == 0)
reader.Read(Formats);
else
base.DeserializeSubItems(reader);
}
#endregion
#region Public Methods
/// <inheritdoc/>
public override void Assign(Base source)
{
base.Assign(source);
TextObjectBase src = source as TextObjectBase;
Text = src.Text;
Padding = src.Padding;
AllowExpressions = src.AllowExpressions;
Brackets = src.Brackets;
HideZeros = src.HideZeros;
HideValue = src.HideValue;
NullValue = src.NullValue;
ProcessAt = src.ProcessAt;
Formats.Assign(src.Formats);
Duplicates = src.Duplicates;
Editable = src.Editable;
}
/// <inheritdoc/>
public override void Serialize(FRWriter writer)
{
TextObjectBase c = writer.DiffObject as TextObjectBase;
base.Serialize(writer);
if (Text != c.Text)
writer.WriteStr("Text", Text);
if (Padding != c.Padding)
writer.WriteValue("Padding", Padding);
if (writer.SerializeTo != SerializeTo.Preview)
{
if (AllowExpressions != c.AllowExpressions)
writer.WriteBool("AllowExpressions", AllowExpressions);
if (Brackets != c.Brackets)
writer.WriteStr("Brackets", Brackets);
if (HideZeros != c.HideZeros)
writer.WriteBool("HideZeros", HideZeros);
if (HideValue != c.HideValue)
writer.WriteStr("HideValue", HideValue);
if (NullValue != c.NullValue)
writer.WriteStr("NullValue", NullValue);
if (ProcessAt != c.ProcessAt)
writer.WriteValue("ProcessAt", ProcessAt);
if (Duplicates != c.Duplicates)
writer.WriteValue("Duplicates", Duplicates);
}
if (Editable)
writer.WriteBool("Editable", Editable);
if (Formats.Count > 1)
writer.Write(Formats);
else
Format.Serialize(writer, "Format.", c.Format);
}
/// <inheritdoc/>
public override void ExtractMacros()
{
Text = ExtractDefaultMacros(Text);
}
internal void SetValue(object value)
{
this.value = value;
}
internal string GetTextWithBrackets(string text)
{
string[] brackets = Brackets.Split(',');
return brackets[0] + text + brackets[1];
}
internal string GetTextWithoutBrackets(string text)
{
string[] brackets = Brackets.Split(',');
if (text.StartsWith(brackets[0]))
text = text.Remove(0, brackets[0].Length);
if (text.EndsWith(brackets[1]))
text = text.Remove(text.Length - brackets[1].Length);
return text;
}
internal string FormatValue(object value)
{
return FormatValue(value, 0);
}
internal string FormatValue(object value, int formatIndex)
{
this.value = value;
string formattedValue = "";
if (value == null || value is DBNull)
{
formattedValue = NullValue;
}
else
{
if (formatIndex < Formats.Count)
formattedValue = Formats[formatIndex].FormatValue(value);
else
formattedValue = Format.FormatValue(value);
if (!String.IsNullOrEmpty(HideValue))
{
if (value.ToString() == HideValue)
formattedValue = "";
}
if (HideZeros)
{
Variant v = new Variant(value);
if ((v.IsNumeric && v == 0) || (v.IsDate && v.ToDateTime() == DateTime.MinValue))
formattedValue = "";
}
}
return formattedValue;
}
internal string CalcAndFormatExpression(string expression, int expressionIndex)
{
try
{
return FormatValue(Report.Calc(expression), expressionIndex);
}
catch (Exception e)
{
throw new Exception(Name + ": " + Res.Get("Messages,ErrorInExpression") + ": " + expression,
e.InnerException == null ? e : e.InnerException);
}
}
/// <summary>
/// Returns the text to display.
/// </summary>
/// <returns>The text to display.</returns>
/// <remarks>This method is used to display simplified DB field names in the designer. In runtime, it returns the Text property value.</remarks>
public virtual string GetDisplayText()
{
return Text;
}
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="TextObjectBase"/> class with default settings.
/// </summary>
public TextObjectBase()
{
allowExpressions = true;
brackets = "[,]";
padding = new Padding(2, 0, 2, 0);
hideValue = "";
nullValue = "";
text = "";
formats = new FormatCollection();
formats.Add(new GeneralFormat());
}
}
}