ComponentBase.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. using FastReport.Utils;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Drawing;
  6. using System.Drawing.Design;
  7. using System.Windows.Forms;
  8. namespace FastReport
  9. {
  10. /// <summary>
  11. /// Class that implements some object's properties such as location, size and visibility.
  12. /// </summary>
  13. public abstract partial class ComponentBase : Base
  14. {
  15. #region Fields
  16. private AnchorStyles anchor;
  17. private DockStyle dock;
  18. private int groupIndex;
  19. private float height;
  20. private float left;
  21. private string tag;
  22. private float top;
  23. private bool visible;
  24. private string visibleExpression;
  25. private bool printable;
  26. private string printableExpression;
  27. private float width;
  28. #endregion Fields
  29. #region Properties
  30. /// <summary>
  31. /// Gets the absolute bottom coordinate of the object.
  32. /// </summary>
  33. [Browsable(false)]
  34. public float AbsBottom
  35. {
  36. get { return AbsTop + Height; }
  37. }
  38. /// <summary>
  39. /// Gets the absolute bounding rectangle of the object.
  40. /// </summary>
  41. [Browsable(false)]
  42. public RectangleF AbsBounds
  43. {
  44. get { return new RectangleF(AbsLeft, AbsTop, Width, Height); }
  45. }
  46. /// <summary>
  47. /// Gets the absolute left coordinate of the object.
  48. /// </summary>
  49. [Browsable(false)]
  50. public virtual float AbsLeft
  51. {
  52. get { return (Parent is ComponentBase) ? Left + (Parent as ComponentBase).AbsLeft : Left; }
  53. }
  54. /// <summary>
  55. /// Gets the absolute right coordinate of the object.
  56. /// </summary>
  57. [Browsable(false)]
  58. public float AbsRight
  59. {
  60. get { return AbsLeft + Width; }
  61. }
  62. /// <summary>
  63. /// Gets the absolute top coordinate of the object.
  64. /// </summary>
  65. [Browsable(false)]
  66. public virtual float AbsTop
  67. {
  68. get { return (Parent is ComponentBase) ? Top + (Parent as ComponentBase).AbsTop : Top; }
  69. }
  70. /// <summary>
  71. /// Gets or sets the edges of the container to which a control is bound and determines how a control
  72. /// is resized with its parent.
  73. /// </summary>
  74. /// <remarks>
  75. /// <para>Use the Anchor property to define how a control is automatically resized as its parent control
  76. /// is resized. Anchoring a control to its parent control ensures that the anchored edges remain in the
  77. /// same position relative to the edges of the parent control when the parent control is resized.</para>
  78. /// <para>You can anchor a control to one or more edges of its container. For example, if you have a band
  79. /// with a <b>TextObject</b> whose <b>Anchor</b> property value is set to <b>Top, Bottom</b>, the <b>TextObject</b> is stretched to
  80. /// maintain the anchored distance to the top and bottom edges of the band as the height of the band
  81. /// is increased.</para>
  82. /// </remarks>
  83. [DefaultValue(AnchorStyles.Left | AnchorStyles.Top)]
  84. [Category("Layout")]
  85. public virtual AnchorStyles Anchor
  86. {
  87. get { return anchor; }
  88. set { anchor = value; }
  89. }
  90. /// <summary>
  91. /// Gets the bottom coordinate of the object in relation to its container.
  92. /// </summary>
  93. /// <remarks>
  94. /// To change the bottom coordinate, change the <see cref="Top"/> and/or <see cref="Height"/> properties.
  95. /// </remarks>
  96. [Browsable(false)]
  97. public float Bottom
  98. {
  99. get { return Top + Height; }
  100. }
  101. /// <summary>
  102. /// Gets or sets the bounding rectangle of the object.
  103. /// </summary>
  104. /// <remarks>
  105. /// Assigning a value to this property is equal to assigning values to the <see cref="Left"/>,
  106. /// <see cref="Top"/>, <see cref="Width"/>, <see cref="Height"/> properties.
  107. /// </remarks>
  108. [Browsable(false)]
  109. public RectangleF Bounds
  110. {
  111. get { return new RectangleF(Left, Top, Width, Height); }
  112. set
  113. {
  114. Left = value.Left;
  115. Top = value.Top;
  116. Width = value.Width;
  117. Height = value.Height;
  118. }
  119. }
  120. /// <summary>
  121. /// Gets or sets the size of client area of the object.
  122. /// </summary>
  123. /// <remarks>
  124. /// This property is used in the <see cref="FastReport.Dialog.DialogPage"/> class.
  125. /// </remarks>
  126. [Browsable(false)]
  127. public virtual SizeF ClientSize
  128. {
  129. get { return new SizeF(Width, Height); }
  130. set
  131. {
  132. Width = value.Width;
  133. Height = value.Height;
  134. }
  135. }
  136. /// <summary>
  137. /// Gets or sets which control borders are docked to its parent control and determines how a control
  138. /// is resized with its parent.
  139. /// </summary>
  140. /// <remarks>
  141. /// <para>Use the <b>Dock</b> property to define how a control is automatically resized as its parent control is
  142. /// resized. For example, setting Dock to <c>DockStyle.Left</c> causes the control to align itself with the
  143. /// left edges of its parent control and to resize as the parent control is resized.</para>
  144. /// <para>A control can be docked to one edge of its parent container or can be docked to all edges and
  145. /// fill the parent container.</para>
  146. /// </remarks>
  147. [DefaultValue(DockStyle.None)]
  148. [Category("Layout")]
  149. public virtual DockStyle Dock
  150. {
  151. get { return dock; }
  152. set
  153. {
  154. if (dock != value)
  155. {
  156. dock = value;
  157. if (Parent != null)
  158. (Parent as IParent).UpdateLayout(0, 0);
  159. }
  160. }
  161. }
  162. /// <summary>
  163. /// Gets or sets a group index.
  164. /// </summary>
  165. /// <remarks>
  166. /// Group index is used to group objects in the designer (using "Group" button). When you select
  167. /// any object in a group, entire group becomes selected. To reset a group, set the <b>GroupIndex</b>
  168. /// to 0 (default value).
  169. /// </remarks>
  170. [Browsable(false)]
  171. public int GroupIndex
  172. {
  173. get { return groupIndex; }
  174. set { groupIndex = value; }
  175. }
  176. /// <summary>
  177. /// Gets or sets the height of the object.
  178. /// </summary>
  179. /// <remarks>
  180. /// This property value is measured in the screen pixels. Use <see cref="Units"/> class to
  181. /// convert a value to desired units.
  182. /// </remarks>
  183. /// <example>The following example demonstrates how to convert between pixels and units:<code>
  184. /// TextObject text1;
  185. /// // set Height to 10mm
  186. /// text1.Height = Units.Millimeters * 10;
  187. /// // convert a value to millimeters
  188. /// MessageBox.Show("Height = " + (text1.Height / Units.Millimeters).ToString() + "mm");
  189. /// </code></example>
  190. [Category("Layout")]
  191. public virtual float Height
  192. {
  193. get { return height; }
  194. set
  195. {
  196. value = (float)Math.Round(value, 2);
  197. if (FloatDiff(height, value))
  198. {
  199. if (!IsDesigning || !HasRestriction(Restrictions.DontResize))
  200. {
  201. if (this is IParent)
  202. (this as IParent).UpdateLayout(0, value - height);
  203. height = value;
  204. if (Dock != DockStyle.None && Parent != null)
  205. (Parent as IParent).UpdateLayout(0, 0);
  206. }
  207. }
  208. }
  209. }
  210. /// <summary>
  211. /// Gets or sets the left coordinate of the object in relation to its container.
  212. /// </summary>
  213. /// <remarks>
  214. /// <para>
  215. /// This property value is measured in the screen pixels. Use
  216. /// <see cref="Units"/> class to convert a value to desired units.
  217. /// </para>
  218. /// <para>
  219. /// To obtain absolute coordinate, use <see cref="AbsLeft"/> property.
  220. /// </para>
  221. /// </remarks>
  222. /// <example>The following example demonstrates how to convert between pixels and units:<code>
  223. /// TextObject text1;
  224. /// // set Left to 10mm
  225. /// text1.Left = Units.Millimeters * 10;
  226. /// // convert a value to millimeters
  227. /// MessageBox.Show("Left = " + (text1.Left / Units.Millimeters).ToString() + "mm");
  228. /// </code></example>
  229. [Category("Layout")]
  230. public virtual float Left
  231. {
  232. get { return left; }
  233. set
  234. {
  235. value = (float)Math.Round(value, 2);
  236. if (!IsDesigning || !HasRestriction(Restrictions.DontMove))
  237. {
  238. left = value;
  239. if (Dock != DockStyle.None && Parent != null)
  240. (Parent as IParent).UpdateLayout(0, 0);
  241. }
  242. }
  243. }
  244. /// <summary>
  245. /// Gets the right coordinate of the object in relation to its container.
  246. /// </summary>
  247. /// <remarks>
  248. /// To change the right coordinate, change the <see cref="Left"/> and/or <see cref="Width"/> properties.
  249. /// </remarks>
  250. [Browsable(false)]
  251. public float Right
  252. {
  253. get { return Left + Width; }
  254. }
  255. /// <summary>
  256. /// Gets or sets the Tag string for this component.
  257. /// </summary>
  258. [Category("Design")]
  259. public string Tag
  260. {
  261. get { return tag; }
  262. set { tag = value; }
  263. }
  264. /// <summary>
  265. /// Gets or sets the top coordinate of the object in relation to its container.
  266. /// </summary>
  267. /// <remarks>
  268. /// <para>
  269. /// This property value is measured in the screen pixels. Use
  270. /// <see cref="Units"/> class to convert a value to desired units.
  271. /// </para>
  272. /// <para>
  273. /// To obtain absolute coordinate, use <see cref="AbsTop"/> property.
  274. /// </para>
  275. /// </remarks>
  276. /// <example>The following example demonstrates how to convert between pixels and units:<code>
  277. /// TextObject text1;
  278. /// // set Top to 10mm
  279. /// text1.Top = Units.Millimeters * 10;
  280. /// // convert a value to millimeters
  281. /// MessageBox.Show("Top = " + (text1.Top / Units.Millimeters).ToString() + "mm");
  282. /// </code></example>
  283. [Category("Layout")]
  284. public virtual float Top
  285. {
  286. get { return top; }
  287. set
  288. {
  289. value = (float)Math.Round(value, 2);
  290. if (!IsDesigning || !HasRestriction(Restrictions.DontMove))
  291. {
  292. top = value;
  293. if (Dock != DockStyle.None && Parent != null)
  294. (Parent as IParent).UpdateLayout(0, 0);
  295. }
  296. }
  297. }
  298. /// <summary>
  299. /// Gets or sets a value indicating whether the object is displayed in the preview window.
  300. /// </summary>
  301. /// <remarks>
  302. /// Setting this property to <b>false</b> will hide the object in the preview window.
  303. /// </remarks>
  304. /// <example>The following report script will control the Text1 visibility depending on the value of the
  305. /// data column:<code>
  306. /// private void Data1_BeforePrint(object sender, EventArgs e)
  307. /// {
  308. /// Text1.Visible = [Orders.Shipped] == true;
  309. /// }
  310. /// </code></example>
  311. [DefaultValue(true)]
  312. [Category("Behavior")]
  313. public virtual bool Visible
  314. {
  315. get { return visible; }
  316. set { visible = value; }
  317. }
  318. /// <summary>
  319. /// Gets or sets a string containing expression that determines should be object displayed in the preview window.
  320. /// </summary>
  321. [DefaultValue("")]
  322. [Category("Behavior")]
  323. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  324. public virtual string VisibleExpression
  325. {
  326. get { return visibleExpression; }
  327. set { visibleExpression = value; }
  328. }
  329. /// <summary>
  330. /// Gets or sets a value that determines if the object can be printed on the printer.
  331. /// </summary>
  332. /// <remarks>
  333. /// Object with Printable = <b>false</b> is still visible in the preview window, but not on the printout.
  334. /// If you want to hide an object in the preview, set the <see cref="ComponentBase.Visible"/> property to <b>false</b>.
  335. /// </remarks>
  336. [DefaultValue(true)]
  337. [Category("Behavior")]
  338. public bool Printable
  339. {
  340. get { return printable; }
  341. set { printable = value; }
  342. }
  343. /// <summary>
  344. /// Gets or sets a string containing expression that determines should be object printed on the printer.
  345. /// </summary>
  346. [DefaultValue("")]
  347. [Category("Behavior")]
  348. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  349. public string PrintableExpression
  350. {
  351. get { return printableExpression; }
  352. set { printableExpression = value; }
  353. }
  354. /// <summary>
  355. /// Gets or sets the width of the object.
  356. /// </summary>
  357. /// <remarks>
  358. /// This property value is measured in the screen pixels. Use <see cref="Units"/> class to
  359. /// convert a value to desired units.
  360. /// </remarks>
  361. /// <example>The following example demonstrates how to convert between pixels and units:<code>
  362. /// TextObject text1;
  363. /// // set Width to 10mm
  364. /// text1.Width = Units.Millimeters * 10;
  365. /// // convert a value to millimeters
  366. /// MessageBox.Show("Width = " + (text1.Width / Units.Millimeters).ToString() + "mm");
  367. /// </code></example>
  368. [Category("Layout")]
  369. public virtual float Width
  370. {
  371. get { return width; }
  372. set
  373. {
  374. value = (float)Math.Round(value, 2);
  375. if (FloatDiff(width, value))
  376. {
  377. if (!IsDesigning || !HasRestriction(Restrictions.DontResize))
  378. {
  379. if (this is IParent)
  380. (this as IParent).UpdateLayout(value - width, 0);
  381. width = value;
  382. if (Dock != DockStyle.None && Parent != null)
  383. (Parent as IParent).UpdateLayout(0, 0);
  384. }
  385. }
  386. }
  387. }
  388. #endregion Properties
  389. #region Constructors
  390. /// <summary>
  391. /// Initializes a new instance of the <see cref="ComponentBase"/> class with default settings.
  392. /// </summary>
  393. public ComponentBase()
  394. {
  395. anchor = AnchorStyles.Left | AnchorStyles.Top;
  396. visible = true;
  397. visibleExpression = "";
  398. printable = true;
  399. printableExpression = "";
  400. SetFlags(Flags.CanWriteBounds | Flags.HasGlobalName, true);
  401. tag = "";
  402. }
  403. #endregion Constructors
  404. #region Public Methods
  405. /// <inheritdoc/>
  406. public override void Assign(Base source)
  407. {
  408. base.Assign(source);
  409. ComponentBase src = source as ComponentBase;
  410. Left = src.Left;
  411. Top = src.Top;
  412. Width = src.Width;
  413. Height = src.Height;
  414. Dock = src.Dock;
  415. Anchor = src.Anchor;
  416. Visible = src.Visible;
  417. VisibleExpression = src.VisibleExpression;
  418. Printable = src.Printable;
  419. PrintableExpression = src.PrintableExpression;
  420. Tag = src.Tag;
  421. }
  422. /// <inheritdoc/>
  423. public override void Serialize(FRWriter writer)
  424. {
  425. ComponentBase c = writer.DiffObject as ComponentBase;
  426. base.Serialize(writer);
  427. if (Printable != c.Printable)
  428. writer.WriteBool("Printable", Printable);
  429. if (PrintableExpression != c.PrintableExpression)
  430. writer.WriteStr("PrintableExpression", PrintableExpression);
  431. if (HasFlag(Flags.CanWriteBounds))
  432. {
  433. if (FloatDiff(Left, c.Left))
  434. writer.WriteFloat("Left", Left);
  435. if (FloatDiff(Top, c.Top))
  436. writer.WriteFloat("Top", Top);
  437. if (FloatDiff(Width, c.Width))
  438. writer.WriteFloat("Width", Width);
  439. if (FloatDiff(Height, c.Height))
  440. writer.WriteFloat("Height", Height);
  441. }
  442. if (writer.SerializeTo != SerializeTo.Preview)
  443. {
  444. if (Dock != c.Dock)
  445. writer.WriteValue("Dock", Dock);
  446. if (Anchor != c.Anchor)
  447. writer.WriteValue("Anchor", Anchor);
  448. if (Visible != c.Visible)
  449. writer.WriteBool("Visible", Visible);
  450. if (VisibleExpression != c.VisibleExpression)
  451. writer.WriteStr("VisibleExpression", VisibleExpression);
  452. if (GroupIndex != c.GroupIndex)
  453. writer.WriteInt("GroupIndex", GroupIndex);
  454. }
  455. if (Tag != c.Tag)
  456. writer.WriteStr("Tag", Tag);
  457. }
  458. #endregion Public Methods
  459. #region Report Engine
  460. /// <inheritdoc/>
  461. public override string[] GetExpressions()
  462. {
  463. List<string> expressions = new List<string>();
  464. string[] baseExpressions = base.GetExpressions();
  465. if (baseExpressions != null)
  466. {
  467. expressions.AddRange(baseExpressions);
  468. }
  469. if (!String.IsNullOrEmpty(VisibleExpression))
  470. {
  471. string expression = Code.CodeUtils.FixExpressionWithBrackets(VisibleExpression);
  472. if (expression.ToLower() == "true" || expression.ToLower() == "false")
  473. {
  474. expression = expression.ToLower();
  475. }
  476. expressions.Add(expression);
  477. }
  478. if (!String.IsNullOrEmpty(PrintableExpression))
  479. {
  480. string expression = Code.CodeUtils.FixExpressionWithBrackets(PrintableExpression);
  481. if (expression.ToLower() == "true" || expression.ToLower() == "false")
  482. {
  483. expression = expression.ToLower();
  484. }
  485. expressions.Add(expression);
  486. }
  487. return expressions.ToArray();
  488. }
  489. /// <summary>
  490. /// Caclulates visible expression value.
  491. /// </summary>
  492. /// <param name="expression">The expression to calculate.</param>
  493. /// <returns>The result of calculation.</returns>
  494. public bool CalcVisibleExpression(string expression)
  495. {
  496. bool result = true;
  497. object expressionObj = null;
  498. // Calculate expressions with TotalPages only on FinalPass.
  499. if (!expression.Contains("TotalPages") || (Report.DoublePass && Report.Engine.FinalPass))
  500. {
  501. expressionObj = Report.Calc(Code.CodeUtils.FixExpressionWithBrackets(expression));
  502. }
  503. if (expressionObj != null && expressionObj is bool)
  504. {
  505. if (!expression.Contains("TotalPages"))
  506. {
  507. result = (bool)expressionObj;
  508. }
  509. else if (Report.Engine.FirstPass)
  510. {
  511. result = true;
  512. }
  513. else
  514. {
  515. result = (bool)expressionObj;
  516. }
  517. }
  518. return result;
  519. }
  520. #endregion Report Engine
  521. }
  522. }