RichObject.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  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, ITranslatable
  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.Border = this.Border.Clone();
  290. tob.BreakTo = this.BreakTo;
  291. // tob.Parent = this.Parent;
  292. tob.Fill = this.Fill.Clone();
  293. tob.FillColor = this.FillColor;
  294. tob.SetName(this.Name + "_0");
  295. // background object must have the height of the original object
  296. tob.Height = this.Height;
  297. tob.Bounds = this.Bounds;
  298. tob.ClientSize = this.ClientSize;
  299. tob.Top = 0; // this.Padding.Top;
  300. tob.Left = Left; // this.Padding.Left;
  301. tob.CanGrow = CanGrow;
  302. tob.GrowToBottom = GrowToBottom;
  303. tob.ZOrder = 0;
  304. tob.SaveState();
  305. TransltedObjects.Add(tob);
  306. }
  307. #endif
  308. using (RichText2ReportObject convertor = new RichText2ReportObject())
  309. using (RTF_DocumentParser parser = new RTF_DocumentParser())
  310. {
  311. parser.Load(Text);
  312. RichDocument rtf = parser.Document;
  313. if (tob != null)
  314. // tob.FillColor = parser.GetFillColor();
  315. tob.FillColor = Color.Transparent;
  316. TransltedObjects.AddRange(convertor.RichObject2ReportObjects(this, ref rtf, out translated_height));
  317. }
  318. if (CanGrow && translated_height > this.Height || CanShrink && translated_height < this.Height)
  319. {
  320. // shrinking of the background object occurs here
  321. if (tob != null)
  322. tob.Height = translated_height;
  323. }
  324. return translated_height;
  325. }
  326. #endregion
  327. #endregion
  328. #region Protected Methods
  329. /// <inheritdoc/>
  330. protected override void Dispose(bool disposing)
  331. {
  332. #if !FRCORE && !MONO
  333. if (disposing)
  334. DestroyCachedMetafile();
  335. #endif
  336. base.Dispose(disposing);
  337. }
  338. #endregion
  339. #region Public Methods
  340. /// <inheritdoc/>
  341. public override void Assign(Base source)
  342. {
  343. base.Assign(source);
  344. RichObject src = source as RichObject;
  345. DataColumn = src.DataColumn;
  346. ActualTextStart = src.ActualTextStart;
  347. ActualTextLength = src.ActualTextLength;
  348. OldBreakStyle = src.OldBreakStyle;
  349. ConvertRichText = src.ConvertRichText;
  350. TransltedObjects = src.TransltedObjects;
  351. }
  352. /// <inheritdoc/>
  353. public override void Draw(FRPaintEventArgs e)
  354. {
  355. base.Draw(e);
  356. #if !FRCORE && !MONO
  357. try
  358. {
  359. if (!this.ConvertRichText || IsDesigning)
  360. {
  361. if (IsPrinting)
  362. PrintRich(e);
  363. else
  364. DrawRich(e);
  365. }
  366. }
  367. catch (Exception ex)
  368. {
  369. e.Graphics.DrawString(ex.ToString(), DrawUtils.DefaultReportFont, Brushes.Red,
  370. new RectangleF(AbsLeft * e.ScaleX, AbsTop * e.ScaleY, Width * e.ScaleX, Height * e.ScaleY));
  371. }
  372. #endif
  373. #if !FRCORE
  374. DrawDesign(e);
  375. #endif
  376. Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));
  377. }
  378. #endregion
  379. #region Report Engine
  380. /// <inheritdoc/>
  381. public override void SaveState()
  382. {
  383. base.SaveState();
  384. savedText = Text;
  385. localVisibleStorage = Visible;
  386. savedDataColumn = DataColumn;
  387. }
  388. /// <inheritdoc/>
  389. public override void RestoreState()
  390. {
  391. int count = TransltedObjects.Count;
  392. if (ConvertRichText)
  393. {
  394. Report.Engine.RestoreRich(this);
  395. }
  396. base.RestoreState();
  397. base.Text = savedText;
  398. dataColumn = savedDataColumn;
  399. if (count > 0)
  400. Visible = true;
  401. }
  402. /// <inheritdoc/>
  403. public override string[] GetExpressions()
  404. {
  405. List<string> expressions = new List<string>();
  406. expressions.AddRange(base.GetExpressions());
  407. if (AllowExpressions && !String.IsNullOrEmpty(Brackets))
  408. {
  409. // collect expressions found in the text
  410. string[] brackets = Brackets.Split(',');
  411. if (ConvertRichText)
  412. {
  413. string decoded_text;
  414. using (RTF_DocumentParser parser = new RTF_DocumentParser())
  415. {
  416. parser.Load(Text);
  417. using (RTF_ToTextSaver saver = new RTF_ToTextSaver(parser.Document))
  418. decoded_text = saver.PlainText;
  419. }
  420. expressions.AddRange(CodeUtils.GetExpressions(decoded_text, brackets[0], brackets[1]));
  421. }
  422. else
  423. {
  424. #if !FRCORE && !MONO
  425. using (FRRichTextBox rich = CreateRich())
  426. {
  427. expressions.AddRange(CodeUtils.GetExpressions(rich.Text, brackets[0], brackets[1]));
  428. }
  429. #else
  430. System.Diagnostics.Trace.WriteLine("RichObject: ConvertRichText poropery must be enabled on Core and Mono systems");
  431. #endif
  432. }
  433. }
  434. if (!String.IsNullOrEmpty(DataColumn))
  435. expressions.Add(DataColumn);
  436. return expressions.ToArray();
  437. }
  438. /// <inheritdoc/>
  439. #if !FRCORE && !MONO
  440. public override void GetData()
  441. {
  442. base.GetData();
  443. #if DIAGNOSTIC
  444. System.Diagnostics.Trace.WriteLine(this.Name + " GetData() ");
  445. #endif
  446. if (!String.IsNullOrEmpty(DataColumn))
  447. {
  448. object value = Report.GetColumnValue(DataColumn);
  449. if (value is byte[])
  450. {
  451. Text = value == null ? "" : System.Text.Encoding.UTF8.GetString(value as byte[]);
  452. }
  453. else
  454. {
  455. Text = value == null ? "" : value.ToString();
  456. }
  457. }
  458. else if (AllowExpressions)
  459. {
  460. #if false //USE_ORIGINAL_RICH_EXPRESSION_CODE // Prior 20180423
  461. // process expressions
  462. if (!String.IsNullOrEmpty(Brackets))
  463. {
  464. using (FRRichTextBox rich = CreateRich())
  465. {
  466. string[] brackets = Brackets.Split(',');
  467. FindTextArgs args = new FindTextArgs();
  468. args.Text = new FastString(rich.Text);
  469. args.OpenBracket = brackets[0];
  470. args.CloseBracket = brackets[1];
  471. args.StartIndex = ActualTextStart;
  472. int expressionIndex = 0;
  473. while (args.StartIndex < args.Text.Length - 2)
  474. {
  475. string expression = CodeUtils.GetExpression(args, false);
  476. if (expression == "")
  477. break;
  478. string formattedValue = CalcAndFormatExpression(expression, expressionIndex);
  479. // strip off the "\r" characters since rich uses only "\n" for new line
  480. formattedValue = formattedValue.Replace("\r", "");
  481. args.Text = args.Text.Remove(args.StartIndex, args.EndIndex - args.StartIndex);
  482. args.Text = args.Text.Insert(args.StartIndex, formattedValue);
  483. // fix for win8.1 and later
  484. // because their Selection* properties also includes control symbols
  485. {
  486. /*rich.SelectionStart = args.StartIndex;
  487. rich.SelectionLength = args.EndIndex - args.StartIndex;
  488. rich.SelectedText = formattedValue;*/
  489. int richIndex = rich.Find(args.OpenBracket + expression + args.CloseBracket, args.StartIndex, RichTextBoxFinds.None);
  490. if (richIndex != -1)
  491. {
  492. rich.SelectedText = formattedValue;
  493. }
  494. }
  495. args.StartIndex += formattedValue.Length;
  496. expressionIndex++;
  497. }
  498. Text = rich.Rtf;
  499. }
  500. }
  501. #else // functions defined in RichText/RichObject.Ext.cs
  502. if (!ConvertRichText)
  503. CalculateExpressions();
  504. else
  505. MergeRichText();
  506. #endif
  507. }
  508. }
  509. /// <inheritdoc/>
  510. public override float CalcHeight()
  511. {
  512. using (FRRichTextBox rich = CreateRich())
  513. {
  514. int textStart = ActualTextStart;
  515. int textLength = ActualTextLength != 0 ? ActualTextLength : rich.TextLength - textStart;
  516. if (textLength <= 0)
  517. return 0;
  518. float h = SelectionHeight(rich, textStart, textLength);
  519. return h;
  520. }
  521. }
  522. private int SelectionHeight(FRRichTextBox rich, int start, int length)
  523. {
  524. using (Graphics g = rich.CreateGraphics())
  525. {
  526. int n1 = 0;
  527. int n2 = 100000;
  528. Graphics measureGraphics = Report == null ? g :
  529. Report.PrintSettings.MeasureGraphics == null ? g : Report.PrintSettings.MeasureGraphics.Graphics;
  530. if (measureGraphics == null)
  531. measureGraphics = g;
  532. // find the height using halfway point
  533. for (int i = 0; i < 20; i++)
  534. {
  535. int mid = (n1 + n2) / 2;
  536. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, mid);
  537. int fit = rich.FormatRange(g, measureGraphics, textRect, start, start + length, true) - start;
  538. if (fit >= length)
  539. n2 = mid;
  540. else
  541. n1 = mid;
  542. if (Math.Abs(n1 - n2) < 2)
  543. break;
  544. }
  545. int height = Math.Max(n1, n2);
  546. // workaround bug in richtext control (one-line text returns 0 height)
  547. if (rich.TextLength > 0 && height <= 2)
  548. {
  549. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, 1000000);
  550. rich.FormatRange(g, measureGraphics, textRect, start, start + length, true, out height);
  551. }
  552. return height + Padding.Vertical;
  553. }
  554. }
  555. /// <inheritdoc/>
  556. public override bool Break(BreakableComponent breakTo)
  557. {
  558. using (FRRichTextBox rich = CreateRich())
  559. using (Graphics g = rich.CreateGraphics())
  560. {
  561. // determine number of characters fit in the bounds. Set less height to prevent possible data loss.
  562. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical - 20);
  563. Graphics measureGraphics = g;
  564. if (Report != null && Report.PrintSettings != null && Report.PrintSettings.MeasureGraphics != null
  565. && Report.PrintSettings.MeasureGraphics.Graphics != null)
  566. measureGraphics = Report.PrintSettings.MeasureGraphics.Graphics;
  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. // check the height of the content, because we don't need to split an object that contains half of the image.
  574. int tempLength = ActualTextLength;
  575. ActualTextLength = charsFit;
  576. float height = CalcHeight();
  577. ActualTextLength = tempLength;
  578. // if we can print the contents, we can break this object
  579. if (charsFit <= 0 || Height < height)
  580. return false;
  581. // perform break
  582. if (breakTo != null)
  583. {
  584. RichObject richTo = breakTo as RichObject;
  585. if (OldBreakStyle)
  586. {
  587. // copy out-of-bounds rtf to the breakTo
  588. rich.SelectionStart = charsFit;
  589. rich.SelectionLength = rich.TextLength - charsFit;
  590. richTo.Text = rich.SelectedRtf;
  591. // leave text that fit in this object
  592. rich.SelectedText = "";
  593. Text = rich.Rtf;
  594. }
  595. else
  596. {
  597. richTo.Text = Text;
  598. richTo.ActualTextStart = textStart + charsFit;
  599. ActualTextLength = charsFit;
  600. }
  601. }
  602. return true;
  603. }
  604. }
  605. #else
  606. /// <inheritdoc/>
  607. public override float CalcHeight()
  608. {
  609. float bottom = 0;
  610. foreach (ReportComponentBase c in TransltedObjects)
  611. {
  612. bottom = Math.Max(bottom, c.Bottom);
  613. }
  614. return bottom - this.Top;
  615. /*
  616. // 20210713 - just calc height, do not translate object here
  617. height = Convert2ReportObjects();
  618. if (TransltedObjects.Count == 0)
  619. height = Height;
  620. else if(this.CanShrink && height < Height)
  621. height = Height;
  622. #if DEEP_DIAGNOSTIC
  623. string decoded_text;
  624. using (RTF_DocumentParser parser = new RTF_DocumentParser())
  625. {
  626. parser.Load(Text);
  627. using (RTF_ToTextSaver saver = new RTF_ToTextSaver(parser.Document))
  628. decoded_text = saver.PlainText;
  629. }
  630. System.Diagnostics.Trace.WriteLine(decoded_text);
  631. System.Diagnostics.Trace.WriteLine(height);
  632. #endif
  633. return height;
  634. */
  635. }
  636. /// <inheritdoc/>
  637. public override bool Break(BreakableComponent breakTo)
  638. {
  639. // determine number of characters fit in the bounds. Set less height to prevent possible data loss.
  640. RectangleF textRect = new RectangleF(0, 0, Width - Padding.Horizontal, Height - Padding.Vertical - 20);
  641. // prevent page break when height is <= 0
  642. if (textRect.Height <= 0)
  643. return false;
  644. int textStart = ActualTextStart;
  645. int charsFit = 0;
  646. List<ReportComponentBase> overlap = new List<ReportComponentBase>();
  647. foreach (ReportComponentBase obj in this.TransltedObjects)
  648. {
  649. if (obj.Bottom > this.Bottom && obj != TransltedObjects[0])
  650. {
  651. if (breakTo != null)
  652. {
  653. overlap.Add(obj);
  654. continue;
  655. }
  656. break;
  657. }
  658. charsFit += (obj as TextObject).Text.Length;
  659. }
  660. //if we can print the contents, we can break this object
  661. if (charsFit <= 0)
  662. return false;
  663. // perform break
  664. if (breakTo != null)
  665. {
  666. RichObject richTo = breakTo as RichObject;
  667. breakTo.Clear();
  668. foreach (ReportComponentBase obj in overlap)
  669. richTo.TransltedObjects.Add(obj);
  670. richTo.ActualTextStart = textStart + charsFit;
  671. ActualTextLength = charsFit;
  672. }
  673. return true;
  674. }
  675. /// <inheritdoc/>
  676. public override void GetData()
  677. {
  678. base.GetData();
  679. if (!String.IsNullOrEmpty(DataColumn))
  680. {
  681. object value = Report.GetColumnValue(DataColumn);
  682. if (value is byte[])
  683. {
  684. Text = value == null ? "" : System.Text.Encoding.UTF8.GetString(value as byte[]);
  685. }
  686. else
  687. {
  688. Text = value == null ? "" : value.ToString();
  689. }
  690. }
  691. else if (AllowExpressions)
  692. {
  693. CalculateExpressions();
  694. }
  695. }
  696. #endif
  697. #endregion
  698. #region Serialization
  699. private void GetDiff(object sender, DiffEventArgs e)
  700. {
  701. if (Report != null)
  702. {
  703. if (e.Object is Report)
  704. e.DiffObject = Report;
  705. else if (e.Object is Base)
  706. e.DiffObject = Report.FindObject((e.Object as Base).Name);
  707. }
  708. }
  709. /// <inheritdoc/>
  710. public override void Serialize(FRWriter writer)
  711. {
  712. #if DIAGNOSTIC
  713. System.Diagnostics.Trace.WriteLine(this.Name + " Serialize to " + writer.SerializeTo.ToString());
  714. #endif
  715. if (this.Text == null)
  716. return;
  717. base.Serialize(writer);
  718. if (writer.DiffObject is RichObject)
  719. {
  720. RichObject c = writer.DiffObject as RichObject;
  721. if (ActualTextStart != c.ActualTextStart)
  722. writer.WriteInt("ActualTextStart", ActualTextStart);
  723. if (ActualTextLength != c.ActualTextLength)
  724. writer.WriteInt("ActualTextLength", ActualTextLength);
  725. if (writer.SerializeTo != SerializeTo.Preview)
  726. {
  727. if (DataColumn != c.DataColumn)
  728. writer.WriteStr("DataColumn", DataColumn);
  729. }
  730. if (OldBreakStyle != c.OldBreakStyle)
  731. writer.WriteBool("OldBreakStyle", OldBreakStyle);
  732. if (ConvertRichText != c.ConvertRichText)
  733. writer.WriteBool("ConvertRichText", ConvertRichText);
  734. if (KeepExpressionFormat != c.KeepExpressionFormat)
  735. writer.WriteBool("KeepExpressionFormat", KeepExpressionFormat);
  736. }
  737. }
  738. /// <inheritdoc/>
  739. public override void Deserialize(FRReader reader)
  740. {
  741. #if DIAGNOSTIC
  742. System.Diagnostics.Trace.WriteLine(this.Name + " Deserialize from " + reader.DeserializeFrom.ToString());
  743. #endif
  744. base.SetReport(reader.Report);
  745. base.Deserialize(reader);
  746. }
  747. #region Translated objects list
  748. /// <inheritdoc/>
  749. public bool CanContain(Base child)
  750. {
  751. return (child is ReportComponentBase);
  752. }
  753. /// <inheritdoc/>
  754. public void UpdateLayout(float dx, float dy)
  755. {
  756. }
  757. void ITranslatable.ConvertToReportObjects()
  758. {
  759. Convert2ReportObjects();
  760. SecondStageTranslation();
  761. }
  762. #endregion
  763. #endregion Serialization
  764. /// <summary>
  765. /// Initializes a new instance of the <see cref="RichObject"/> class with default settings.
  766. /// </summary>
  767. public RichObject()
  768. {
  769. event_handler = new DiffEventHandler(GetDiff);
  770. dataColumn = "";
  771. SetFlags(Flags.HasSmartTag, true);
  772. }
  773. }
  774. }