RichObject.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7. using FastReport.Utils;
  8. using FastReport.Code;
  9. using FastReport.RichTextParser;
  10. using System.Windows.Forms;
  11. using System.Drawing.Design;
  12. #if !FRCORE
  13. using FastReport.Controls;
  14. #endif
  15. namespace FastReport
  16. {
  17. /// <summary>
  18. /// Represents a RichText object that can display formatted text.
  19. /// </summary>
  20. /// <remarks>
  21. /// Use the <see cref="Text"/> property to set the object's text. The text may include
  22. /// the RTF formatting tags.
  23. /// </remarks>
  24. public partial class RichObject : TextObjectBase
  25. {
  26. #region Fields
  27. private string dataColumn;
  28. private int actualTextStart;
  29. private int actualTextLength;
  30. private string savedText;
  31. private string savedDataColumn;
  32. private float translated_height;
  33. #if !FRCORE && !MONO
  34. private Metafile cachedMetafile;
  35. #endif
  36. private bool oldBreakStyle;
  37. private bool translateObject;
  38. private bool allowExpressionFormat;
  39. private DiffEventHandler event_handler = null;
  40. internal List<ComponentBase> TransltedObjects = new List<ComponentBase>();
  41. internal bool localVisibleStorage = false;
  42. #endregion
  43. #region Properties
  44. /// <summary>
  45. /// Gets or sets the object's text.
  46. /// </summary>
  47. /// <remarks>
  48. /// This property returns the formatted text with rtf tags.
  49. /// </remarks>
  50. [Category("Data")]
  51. [Editor("FastReport.TypeEditors.TextEditor, FastReport", typeof(UITypeEditor))]
  52. public override string Text
  53. {
  54. get { return base.Text; }
  55. set
  56. {
  57. base.Text = value;
  58. dataColumn = "";
  59. #if !FRCORE && !MONO
  60. DestroyCachedMetafile();
  61. #endif
  62. }
  63. }
  64. /// <summary>
  65. /// Gets or sets a name of the data column bound to this control.
  66. /// </summary>
  67. /// <remarks>
  68. /// Value must contain the datasource name, for example: "Datasource.Column".
  69. /// </remarks>
  70. [Category("Data")]
  71. [Editor("FastReport.TypeEditors.DataColumnEditor, FastReport", typeof(UITypeEditor))]
  72. public string DataColumn
  73. {
  74. get { return dataColumn; }
  75. set
  76. {
  77. if (!String.IsNullOrEmpty(value))
  78. {
  79. if (!String.IsNullOrEmpty(Brackets))
  80. {
  81. string[] brackets = Brackets.Split(',');
  82. Text = brackets[0] + value + brackets[1];
  83. }
  84. }
  85. dataColumn = value;
  86. }
  87. }
  88. /// <summary>
  89. /// Gets the actual text start.
  90. /// </summary>
  91. /// <remarks>
  92. /// This property is for internal use only; you should not use it in your code.
  93. /// </remarks>
  94. [Browsable(false)]
  95. public int ActualTextStart
  96. {
  97. get { return actualTextStart; }
  98. set { actualTextStart = value; }
  99. }
  100. /// <summary>
  101. /// Gets the actual text length.
  102. /// </summary>
  103. /// <remarks>
  104. /// This property is for internal use only; you should not use it in your code.
  105. /// </remarks>
  106. [Browsable(false)]
  107. public int ActualTextLength
  108. {
  109. get { return actualTextLength; }
  110. set { actualTextLength = value; }
  111. }
  112. /// <summary>
  113. /// Gets or sets the break style.
  114. /// </summary>
  115. /// <remarks>
  116. /// Set this property to true if you want editable rich text when you edit the prepared report page.
  117. /// </remarks>
  118. public bool OldBreakStyle
  119. {
  120. get { return oldBreakStyle; }
  121. set { oldBreakStyle = value; }
  122. }
  123. /// <summary>
  124. /// Experimental feature for translation of RichText into report objects
  125. /// </summary>
  126. public bool ConvertRichText
  127. {
  128. get
  129. {
  130. #if !FRCORE && !MONO
  131. return translateObject;
  132. #else
  133. return true;
  134. #endif
  135. }
  136. set { translateObject = value; }
  137. }
  138. /// <summary>
  139. /// This property not described
  140. /// </summary>
  141. public bool KeepExpressionFormat
  142. {
  143. get { return allowExpressionFormat; }
  144. set { allowExpressionFormat = value; }
  145. }
  146. #endregion
  147. #region Private Methods
  148. #if !FRCORE && !MONO
  149. private FRRichTextBox CreateRich()
  150. {
  151. FRRichTextBox rich = new FRRichTextBox();
  152. if (Text != null && Text.StartsWith(@"{\rtf"))
  153. rich.Rtf = Text;
  154. else
  155. rich.Text = Text;
  156. Color color = Color.White;
  157. if (Fill is SolidFill)
  158. color = (Fill as SolidFill).Color;
  159. if (color == Color.Transparent)
  160. color = Color.White;
  161. rich.BackColor = color;
  162. rich.DetectUrls = false;
  163. return rich;
  164. }
  165. private Metafile CreateMetafile(FRPaintEventArgs e)
  166. {
  167. Graphics measureGraphics = Report == null ? e.Graphics.Graphics :
  168. Report.PrintSettings.MeasureGraphics == null ? e.Graphics.Graphics : Report.PrintSettings.MeasureGraphics.Graphics;
  169. if (measureGraphics == null)
  170. measureGraphics = e.Graphics.Graphics;
  171. float scaleX = measureGraphics.DpiX / 96f;
  172. float scaleY = measureGraphics.DpiY / 96f;
  173. IntPtr hdc = measureGraphics.GetHdc();
  174. Metafile emf = new Metafile(hdc,
  175. new RectangleF(0, 0, (Width - Padding.Horizontal) * scaleX, (Height - Padding.Vertical) * scaleY),
  176. MetafileFrameUnit.Pixel);
  177. measureGraphics.ReleaseHdc(hdc);
  178. // create metafile canvas and draw on it
  179. using (Graphics g = Graphics.FromImage(emf))
  180. using (FRRichTextBox rich = CreateRich())
  181. {
  182. int textStart = ActualTextStart;
  183. int textLength = ActualTextLength != 0 ? ActualTextLength : rich.TextLength - textStart;
  184. rich.FormatRange(g, measureGraphics,
  185. new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical),
  186. textStart, textStart + textLength, false);
  187. }
  188. return emf;
  189. }
  190. private void DestroyCachedMetafile()
  191. {
  192. if (cachedMetafile != null)
  193. {
  194. cachedMetafile.Dispose();
  195. cachedMetafile = null;
  196. }
  197. }
  198. private void DrawRich(FRPaintEventArgs e)
  199. {
  200. // avoid GDI+ errors
  201. if (Width < Padding.Horizontal + 1 || Height < Padding.Vertical + 1)
  202. return;
  203. // draw to emf because we need to zoom the image
  204. if (cachedMetafile == null)
  205. cachedMetafile = CreateMetafile(e);
  206. if (Fill.IsTransparent == false)
  207. {
  208. e.Graphics.DrawImage(cachedMetafile,
  209. new RectangleF((AbsLeft + Padding.Left) * e.ScaleX,
  210. (AbsTop + Padding.Top) * e.ScaleY,
  211. (Width - Padding.Horizontal) * e.ScaleX,
  212. (Height - Padding.Vertical) * e.ScaleY));
  213. }
  214. else
  215. {
  216. int w = (int)Math.Floor((Width - Padding.Horizontal) * e.ScaleX);
  217. int h = (int)Math.Floor((Height - Padding.Vertical) * e.ScaleY);
  218. using (var target = new Bitmap(w, h))
  219. using (var g = Graphics.FromImage(target))
  220. {
  221. g.DrawImage(cachedMetafile, 0, 0, w, h);
  222. target.MakeTransparent(Color.White);
  223. e.Graphics.DrawImage(target, (AbsLeft + Padding.Left) * e.ScaleX, (AbsTop + Padding.Top) * e.ScaleY);
  224. }
  225. }
  226. if (IsDesigning)
  227. DestroyCachedMetafile();
  228. }
  229. private void PrintRich(FRPaintEventArgs e)
  230. {
  231. // avoid GDI+ errors
  232. if (Width < Padding.Horizontal + 1 || Height < Padding.Vertical + 1)
  233. return;
  234. if (ConvertRichText == false)
  235. {
  236. // FormatRange method uses GDI and does not respect transform settings of GDI+.
  237. RectangleF textRect = new RectangleF(
  238. (AbsLeft + Padding.Left) + e.Graphics.Transform.OffsetX / e.ScaleX,
  239. (AbsTop + Padding.Top) + e.Graphics.Transform.OffsetY / e.ScaleY,
  240. (Width - Padding.Horizontal),
  241. (Height - Padding.Vertical));
  242. IGraphics measureGraphics = Report == null ? e.Graphics : Report.PrintSettings.MeasureGraphics;
  243. if (measureGraphics == null)
  244. measureGraphics = e.Graphics;
  245. using (FRRichTextBox rich = CreateRich())
  246. {
  247. int textStart = ActualTextStart;
  248. int textLength = ActualTextLength != 0 ? ActualTextLength : rich.TextLength - textStart;
  249. rich.FormatRange(e.Graphics.Graphics, measureGraphics.Graphics, textRect, textStart, textStart + textLength, false);
  250. }
  251. return;
  252. }
  253. // draw to emf because we need to zoom the image
  254. if (cachedMetafile == null)
  255. cachedMetafile = CreateMetafile(e);
  256. if (Fill.IsTransparent == false)
  257. {
  258. e.Graphics.DrawImage(cachedMetafile,
  259. new RectangleF((AbsLeft + Padding.Left) * e.ScaleX,
  260. (AbsTop + Padding.Top) * e.ScaleY,
  261. (Width - Padding.Horizontal) * e.ScaleX,
  262. (Height - Padding.Vertical) * e.ScaleY));
  263. }
  264. else
  265. {
  266. int w = (int)Math.Floor((Width - Padding.Horizontal) * e.ScaleX);
  267. int h = (int)Math.Floor((Height - Padding.Vertical) * e.ScaleY);
  268. using (var target = new Bitmap(w, h))
  269. using (var g = Graphics.FromImage(target))
  270. {
  271. g.DrawImage(cachedMetafile, 0, 0, w, h);
  272. target.MakeTransparent(Color.White);
  273. e.Graphics.DrawImage(target, (AbsLeft + Padding.Left) * e.ScaleX, (AbsTop + Padding.Top) * e.ScaleY);
  274. }
  275. }
  276. }
  277. #endif
  278. internal float Convert2ReportObjects()
  279. {
  280. translated_height = this.Height;
  281. TransltedObjects.Clear();
  282. #region "Create background-decoration object"
  283. TextObject tob = null;
  284. #if true
  285. if (this.Border.Lines != BorderLines.None ||
  286. (this.FillColor != Color.White && this.FillColor != Color.Transparent))
  287. {
  288. tob = new TextObject();
  289. tob.Height = this.Height;
  290. tob.Border = this.Border.Clone();
  291. tob.Bounds = this.Bounds;
  292. tob.ClientSize = this.ClientSize;
  293. tob.BreakTo = this.BreakTo;
  294. // tob.Parent = this.Parent;
  295. tob.Top = 0; // this.Padding.Top;
  296. tob.Left = 0; // this.Padding.Left;
  297. tob.Fill = this.Fill.Clone();
  298. tob.FillColor = this.FillColor;
  299. tob.SetName(this.Name + "_0");
  300. if (CanGrow)
  301. {
  302. tob.CanGrow = true;
  303. tob.GrowToBottom = false;
  304. }
  305. tob.ZOrder = 0;
  306. tob.SaveState();
  307. TransltedObjects.Add(tob);
  308. }
  309. #endif
  310. using (RichText2ReportObject convertor = new RichText2ReportObject())
  311. using (RTF_DocumentParser parser = new RTF_DocumentParser())
  312. {
  313. parser.Load(Text);
  314. RichDocument rtf = parser.Document;
  315. if (tob != null)
  316. tob.FillColor = parser.GetFillColor();
  317. TransltedObjects.AddRange(convertor.RichObject2ReportObjects(this, ref rtf, out translated_height));
  318. }
  319. if(GrowToBottom /* && CanGrow */ )
  320. {
  321. }
  322. else if (CanGrow && translated_height > this.Height || CanShrink && translated_height < this.Height)
  323. {
  324. if (tob != null)
  325. tob.Height = translated_height;
  326. }
  327. else
  328. {
  329. }
  330. return translated_height;
  331. }
  332. #endregion
  333. #endregion
  334. #region Protected Methods
  335. /// <inheritdoc/>
  336. protected override void Dispose(bool disposing)
  337. {
  338. #if !FRCORE && !MONO
  339. if (disposing)
  340. DestroyCachedMetafile();
  341. #endif
  342. base.Dispose(disposing);
  343. }
  344. #endregion
  345. #region Public Methods
  346. /// <inheritdoc/>
  347. public override void Assign(Base source)
  348. {
  349. base.Assign(source);
  350. RichObject src = source as RichObject;
  351. DataColumn = src.DataColumn;
  352. ActualTextStart = src.ActualTextStart;
  353. ActualTextLength = src.ActualTextLength;
  354. OldBreakStyle = src.OldBreakStyle;
  355. ConvertRichText = src.ConvertRichText;
  356. }
  357. /// <inheritdoc/>
  358. public override void Draw(FRPaintEventArgs e)
  359. {
  360. base.Draw(e);
  361. #if !FRCORE && !MONO
  362. try
  363. {
  364. if (!this.ConvertRichText || IsDesigning)
  365. {
  366. if (IsPrinting)
  367. PrintRich(e);
  368. else
  369. DrawRich(e);
  370. }
  371. }
  372. catch (Exception ex)
  373. {
  374. e.Graphics.DrawString(ex.ToString(), DrawUtils.DefaultReportFont, Brushes.Red,
  375. new RectangleF(AbsLeft * e.ScaleX, AbsTop * e.ScaleY, Width * e.ScaleX, Height * e.ScaleY));
  376. }
  377. DrawMarkers(e);
  378. #endif
  379. Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));
  380. }
  381. #endregion
  382. #region Report Engine
  383. /// <inheritdoc/>
  384. public override void SaveState()
  385. {
  386. base.SaveState();
  387. savedText = Text;
  388. localVisibleStorage = Visible;
  389. savedDataColumn = DataColumn;
  390. }
  391. /// <inheritdoc/>
  392. public override void RestoreState()
  393. {
  394. int count = TransltedObjects.Count;
  395. if (ConvertRichText)
  396. {
  397. Report.Engine.RestoreRich(this);
  398. }
  399. base.RestoreState();
  400. base.Text = savedText;
  401. dataColumn = savedDataColumn;
  402. if (count > 0)
  403. Visible = true;
  404. }
  405. /// <inheritdoc/>
  406. public override string[] GetExpressions()
  407. {
  408. List<string> expressions = new List<string>();
  409. expressions.AddRange(base.GetExpressions());
  410. if (AllowExpressions && !String.IsNullOrEmpty(Brackets))
  411. {
  412. // collect expressions found in the text
  413. string[] brackets = Brackets.Split(',');
  414. if (ConvertRichText)
  415. {
  416. string decoded_text;
  417. using (RTF_DocumentParser parser = new RTF_DocumentParser())
  418. {
  419. parser.Load(Text);
  420. using (RTF_ToTextSaver saver = new RTF_ToTextSaver(parser.Document))
  421. decoded_text = saver.PlainText;
  422. }
  423. expressions.AddRange(CodeUtils.GetExpressions(decoded_text, brackets[0], brackets[1]));
  424. }
  425. else
  426. {
  427. #if !FRCORE && !MONO
  428. using (FRRichTextBox rich = CreateRich())
  429. {
  430. expressions.AddRange(CodeUtils.GetExpressions(rich.Text, brackets[0], brackets[1]));
  431. }
  432. #else
  433. System.Diagnostics.Trace.WriteLine("RichObject: ConvertRichText poropery must be enabled on Core and Mono systems");
  434. #endif
  435. }
  436. }
  437. if (!String.IsNullOrEmpty(DataColumn))
  438. expressions.Add(DataColumn);
  439. return expressions.ToArray();
  440. }
  441. /// <inheritdoc/>
  442. #if !FRCORE && !MONO
  443. public override void GetData()
  444. {
  445. base.GetData();
  446. #if DIAGNOSTIC
  447. System.Diagnostics.Trace.WriteLine(this.Name + " GetData() ");
  448. #endif
  449. if (!String.IsNullOrEmpty(DataColumn))
  450. {
  451. object value = Report.GetColumnValue(DataColumn);
  452. if (value is byte[])
  453. {
  454. Text = value == null ? "" : System.Text.Encoding.UTF8.GetString(value as byte[]);
  455. }
  456. else
  457. {
  458. Text = value == null ? "" : value.ToString();
  459. }
  460. }
  461. else if (AllowExpressions)
  462. {
  463. #if false //USE_ORIGINAL_RICH_EXPRESSION_CODE // Prior 20180423
  464. // process expressions
  465. if (!String.IsNullOrEmpty(Brackets))
  466. {
  467. using (FRRichTextBox rich = CreateRich())
  468. {
  469. string[] brackets = Brackets.Split(',');
  470. FindTextArgs args = new FindTextArgs();
  471. args.Text = new FastString(rich.Text);
  472. args.OpenBracket = brackets[0];
  473. args.CloseBracket = brackets[1];
  474. args.StartIndex = ActualTextStart;
  475. int expressionIndex = 0;
  476. while (args.StartIndex < args.Text.Length - 2)
  477. {
  478. string expression = CodeUtils.GetExpression(args, false);
  479. if (expression == "")
  480. break;
  481. string formattedValue = CalcAndFormatExpression(expression, expressionIndex);
  482. // strip off the "\r" characters since rich uses only "\n" for new line
  483. formattedValue = formattedValue.Replace("\r", "");
  484. args.Text = args.Text.Remove(args.StartIndex, args.EndIndex - args.StartIndex);
  485. args.Text = args.Text.Insert(args.StartIndex, formattedValue);
  486. // fix for win8.1 and later
  487. // because their Selection* properties also includes control symbols
  488. {
  489. /*rich.SelectionStart = args.StartIndex;
  490. rich.SelectionLength = args.EndIndex - args.StartIndex;
  491. rich.SelectedText = formattedValue;*/
  492. int richIndex = rich.Find(args.OpenBracket + expression + args.CloseBracket, args.StartIndex, RichTextBoxFinds.None);
  493. if (richIndex != -1)
  494. {
  495. rich.SelectedText = formattedValue;
  496. }
  497. }
  498. args.StartIndex += formattedValue.Length;
  499. expressionIndex++;
  500. }
  501. Text = rich.Rtf;
  502. }
  503. }
  504. #else // functions defined in RichText/RichObject.Ext.cs
  505. if (!ConvertRichText)
  506. CalculateExpressions();
  507. else
  508. MergeRichText();
  509. #endif
  510. }
  511. }
  512. /// <inheritdoc/>
  513. public override float CalcHeight()
  514. {
  515. using (FRRichTextBox rich = CreateRich())
  516. {
  517. int textStart = ActualTextStart;
  518. int textLength = ActualTextLength != 0 ? ActualTextLength : rich.TextLength - textStart;
  519. float h = SelectionHeight(rich, textStart, textLength);
  520. return h;
  521. }
  522. }
  523. private int SelectionHeight(FRRichTextBox rich, int start, int length)
  524. {
  525. using (Graphics g = rich.CreateGraphics())
  526. {
  527. int n1 = 0;
  528. int n2 = 100000;
  529. Graphics measureGraphics = Report == null ? g :
  530. Report.PrintSettings.MeasureGraphics == null ? g : Report.PrintSettings.MeasureGraphics.Graphics;
  531. if (measureGraphics == null)
  532. measureGraphics = g;
  533. // find the height using halfway point
  534. for (int i = 0; i < 20; i++)
  535. {
  536. int mid = (n1 + n2) / 2;
  537. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, mid);
  538. int fit = rich.FormatRange(g, measureGraphics, textRect, start, start + length, true) - start;
  539. if (fit >= length)
  540. n2 = mid;
  541. else
  542. n1 = mid;
  543. if (Math.Abs(n1 - n2) < 2)
  544. break;
  545. }
  546. int height = Math.Max(n1, n2);
  547. // workaround bug in richtext control (one-line text returns 0 height)
  548. if (rich.TextLength > 0 && height <= 2)
  549. {
  550. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, 1000000);
  551. rich.FormatRange(g, measureGraphics, textRect, start, start + length, true, out height);
  552. }
  553. return height + Padding.Vertical;
  554. }
  555. }
  556. /// <inheritdoc/>
  557. public override bool Break(BreakableComponent breakTo)
  558. {
  559. using (FRRichTextBox rich = CreateRich())
  560. using (Graphics g = rich.CreateGraphics())
  561. {
  562. // determine number of characters fit in the bounds. Set less height to prevent possible data loss.
  563. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical - 20);
  564. Graphics measureGraphics = Report == null ? g : Report.PrintSettings.MeasureGraphics.Graphics;
  565. if (measureGraphics == null)
  566. measureGraphics = g;
  567. // prevent page break when height is <= 0
  568. if (textRect.Height <= 0)
  569. return false;
  570. int textStart = ActualTextStart;
  571. int textLength = ActualTextLength != 0 ? ActualTextLength : rich.TextLength - textStart;
  572. int charsFit = rich.FormatRange(g, measureGraphics, textRect, textStart, textStart + textLength, true) - textStart;
  573. if (charsFit <= 0 || charsFit == textLength + 1)
  574. return false;
  575. // perform break
  576. if (breakTo != null)
  577. {
  578. RichObject richTo = breakTo as RichObject;
  579. if (OldBreakStyle)
  580. {
  581. // copy out-of-bounds rtf to the breakTo
  582. rich.SelectionStart = charsFit;
  583. rich.SelectionLength = rich.TextLength - charsFit;
  584. richTo.Text = rich.SelectedRtf;
  585. // leave text that fit in this object
  586. rich.SelectedText = "";
  587. Text = rich.Rtf;
  588. }
  589. else
  590. {
  591. richTo.Text = Text;
  592. richTo.ActualTextStart = textStart + charsFit;
  593. ActualTextLength = charsFit;
  594. }
  595. }
  596. return true;
  597. }
  598. }
  599. #else
  600. /// <inheritdoc/>
  601. public override float CalcHeight()
  602. {
  603. return this.SecondStageTranslation();
  604. /*
  605. // 20210713 - just calc height, do not translate object here
  606. height = Convert2ReportObjects();
  607. if (TransltedObjects.Count == 0)
  608. height = Height;
  609. else if(this.CanShrink && height < Height)
  610. height = Height;
  611. #if DEEP_DIAGNOSTIC
  612. string decoded_text;
  613. using (RTF_DocumentParser parser = new RTF_DocumentParser())
  614. {
  615. parser.Load(Text);
  616. using (RTF_ToTextSaver saver = new RTF_ToTextSaver(parser.Document))
  617. decoded_text = saver.PlainText;
  618. }
  619. System.Diagnostics.Trace.WriteLine(decoded_text);
  620. System.Diagnostics.Trace.WriteLine(height);
  621. #endif
  622. return height;
  623. */
  624. }
  625. /// <inheritdoc/>
  626. public override bool Break(BreakableComponent breakTo)
  627. {
  628. // determine number of characters fit in the bounds. Set less height to prevent possible data loss.
  629. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical - 20);
  630. // prevent page break when height is <= 0
  631. if (textRect.Height <= 0)
  632. return false;
  633. int textStart = ActualTextStart;
  634. int charsFit = 0;
  635. bool allFit = true;
  636. List<ReportComponentBase> overlap = new List<ReportComponentBase>();
  637. foreach (ReportComponentBase obj in this.ChildObjects)
  638. {
  639. if (obj.Bottom > this.Bottom)
  640. {
  641. allFit = false;
  642. if (breakTo != null)
  643. {
  644. overlap.Add(obj);
  645. continue;
  646. }
  647. break;
  648. }
  649. charsFit += (obj as TextObject).Text.Length;
  650. }
  651. if (charsFit <= 0 || allFit)
  652. return false;
  653. // perform break
  654. if (breakTo != null)
  655. {
  656. RichObject richTo = breakTo as RichObject;
  657. breakTo.Clear();
  658. foreach (ReportComponentBase obj in overlap)
  659. richTo.ChildObjects.Add(obj);
  660. richTo.ActualTextStart = textStart + charsFit;
  661. ActualTextLength = charsFit;
  662. }
  663. return true;
  664. }
  665. /// <inheritdoc/>
  666. public override void GetData()
  667. {
  668. base.GetData();
  669. if (!String.IsNullOrEmpty(DataColumn))
  670. {
  671. object value = Report.GetColumnValue(DataColumn);
  672. if (value is byte[])
  673. {
  674. Text = value == null ? "" : System.Text.Encoding.UTF8.GetString(value as byte[]);
  675. }
  676. else
  677. {
  678. Text = value == null ? "" : value.ToString();
  679. }
  680. }
  681. else if (AllowExpressions)
  682. {
  683. CalculateExpressions();
  684. }
  685. }
  686. #endif
  687. #endregion
  688. #region Serialization
  689. private void GetDiff(object sender, DiffEventArgs e)
  690. {
  691. if (Report != null)
  692. {
  693. if (e.Object is Report)
  694. e.DiffObject = Report;
  695. else if (e.Object is Base)
  696. e.DiffObject = Report.FindObject((e.Object as Base).Name);
  697. }
  698. }
  699. /// <inheritdoc/>
  700. public override void Serialize(FRWriter writer)
  701. {
  702. #if DIAGNOSTIC
  703. System.Diagnostics.Trace.WriteLine(this.Name + " Serialize to " + writer.SerializeTo.ToString());
  704. #endif
  705. if (this.Text == null)
  706. return;
  707. base.Serialize(writer);
  708. if (writer.DiffObject is RichObject)
  709. {
  710. RichObject c = writer.DiffObject as RichObject;
  711. if (ActualTextStart != c.ActualTextStart)
  712. writer.WriteInt("ActualTextStart", ActualTextStart);
  713. if (ActualTextLength != c.ActualTextLength)
  714. writer.WriteInt("ActualTextLength", ActualTextLength);
  715. if (writer.SerializeTo != SerializeTo.Preview)
  716. {
  717. if (DataColumn != c.DataColumn)
  718. writer.WriteStr("DataColumn", DataColumn);
  719. }
  720. if (OldBreakStyle != c.OldBreakStyle)
  721. writer.WriteBool("OldBreakStyle", OldBreakStyle);
  722. if (ConvertRichText != c.ConvertRichText)
  723. writer.WriteBool("ConvertRichText", ConvertRichText);
  724. if (KeepExpressionFormat != c.KeepExpressionFormat)
  725. writer.WriteBool("KeepExpressionFormat", KeepExpressionFormat);
  726. }
  727. }
  728. /// <inheritdoc/>
  729. public override void Deserialize(FRReader reader)
  730. {
  731. #if DIAGNOSTIC
  732. System.Diagnostics.Trace.WriteLine(this.Name + " Deserialize from " + reader.DeserializeFrom.ToString());
  733. #endif
  734. base.SetReport(reader.Report);
  735. base.Deserialize(reader);
  736. }
  737. #region Translated objects list
  738. /// <inheritdoc/>
  739. public bool CanContain(Base child)
  740. {
  741. return (child is ReportComponentBase);
  742. }
  743. /// <inheritdoc/>
  744. public void UpdateLayout(float dx, float dy)
  745. {
  746. }
  747. #endregion
  748. #endregion Serialization
  749. /// <summary>
  750. /// Initializes a new instance of the <see cref="RichObject"/> class with default settings.
  751. /// </summary>
  752. public RichObject()
  753. {
  754. event_handler = new DiffEventHandler(GetDiff);
  755. dataColumn = "";
  756. SetFlags(Flags.HasSmartTag, true);
  757. }
  758. }
  759. }