ReportComponentBase.DesignExt.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.ComponentModel;
  5. using System.Windows.Forms;
  6. using System.Drawing.Design;
  7. using FastReport.Utils;
  8. using FastReport.TypeEditors;
  9. using FastReport.TypeConverters;
  10. using FastReport.Design.PageDesigners.Page;
  11. using System.Threading;
  12. using System.Drawing.Drawing2D;
  13. namespace FastReport
  14. {
  15. /// <summary>
  16. /// The style of the report object markers.
  17. /// </summary>
  18. public enum MarkerStyle
  19. {
  20. /// <summary>
  21. /// Rectangle marker.
  22. /// </summary>
  23. Rectangle,
  24. /// <summary>
  25. /// Small markers at the object's corners.
  26. /// </summary>
  27. Corners
  28. }
  29. partial class ReportComponentBase
  30. {
  31. #region Properties
  32. /// <inheritdoc/>
  33. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  34. public override float Left
  35. {
  36. get { return base.Left; }
  37. set { base.Left = value; }
  38. }
  39. /// <inheritdoc/>
  40. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  41. public override float Top
  42. {
  43. get { return base.Top; }
  44. set { base.Top = value; }
  45. }
  46. /// <inheritdoc/>
  47. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  48. public override float Width
  49. {
  50. get { return base.Width; }
  51. set { base.Width = value; }
  52. }
  53. /// <inheritdoc/>
  54. [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
  55. public override float Height
  56. {
  57. get { return base.Height; }
  58. set { base.Height = value; }
  59. }
  60. #endregion
  61. #region Private Methods
  62. private bool ShouldSerializeHyperlink()
  63. {
  64. return !Hyperlink.Equals(new Hyperlink(null));
  65. }
  66. private bool ShouldSerializeBorder()
  67. {
  68. return !Border.Equals(new Border());
  69. }
  70. private bool ShouldSerializeCursor()
  71. {
  72. return Cursor != Cursors.Default;
  73. }
  74. private bool ShouldSerializeFill()
  75. {
  76. return !(Fill is SolidFill) || !Fill.IsTransparent;
  77. }
  78. #endregion
  79. #region Public Methods
  80. /// <summary>
  81. /// Assigns a format from another, similar object.
  82. /// </summary>
  83. /// <param name="source">Source object to assign a format from.</param>
  84. public virtual void AssignFormat(ReportComponentBase source)
  85. {
  86. Border = source.Border.Clone();
  87. Fill = source.Fill.Clone();
  88. style = source.Style;
  89. }
  90. /// <inheritdoc/>
  91. public override void HandleMouseDown(FRMouseEventArgs e)
  92. {
  93. base.HandleMouseDown(e);
  94. // we will use FSavedBounds to keep the delta while moving the object between bands
  95. savedBounds.X = 0;
  96. savedBounds.Y = 0;
  97. }
  98. /// <inheritdoc/>
  99. public override void CheckParent(bool immediately)
  100. {
  101. if (!(Parent is ComponentBase) || !IsSelected || IsAncestor || Dock != DockStyle.None)
  102. return;
  103. if (immediately ||
  104. Left < 0 || Left > (Parent as ComponentBase).Width ||
  105. Top < 0 || Top > (Parent as ComponentBase).Height)
  106. {
  107. if (HasFlag(Flags.CanChangeParent))
  108. {
  109. ObjectCollection list = Page.AllObjects;
  110. for (int i = list.Count - 1; i >= 0; i--)
  111. {
  112. ComponentBase c = list[i] as ComponentBase;
  113. if (c == null || c == this || !(c is IParent))
  114. continue;
  115. if (c != null && (c as IParent).CanContain(this))
  116. {
  117. bool inside;
  118. int bandGap = ReportWorkspace.ClassicView && IsDesigning ? BandBase.HeaderSize : 4;
  119. if (c is BandBase)
  120. inside = AbsTop > c.AbsTop - bandGap && AbsTop < c.AbsBottom - 1;
  121. else
  122. inside = AbsLeft > c.AbsLeft - 1e-4 && AbsLeft < c.AbsRight - 1e-4 &&
  123. AbsTop > c.AbsTop - 1e-4 && AbsTop < c.AbsBottom - 1e-4;
  124. if (inside)
  125. {
  126. if (Parent != c)
  127. {
  128. float saveAbsTop = AbsTop;
  129. float saveAbsLeft = AbsLeft;
  130. // keep existing offsets if the object is not aligned to the grid
  131. float gridXOffset = Converter.DecreasePrecision(Left - (int)(Left / Page.SnapSize.Width + 1e-4) * Page.SnapSize.Width, 2);
  132. float gridYOffset = Converter.DecreasePrecision(Top - (int)(Top / Page.SnapSize.Height + 1e-4) * Page.SnapSize.Height, 2);
  133. // move the object to the new parent
  134. Left = (int)((AbsLeft - c.AbsLeft) / Page.SnapSize.Width + 1e-4) * Page.SnapSize.Width + gridXOffset;
  135. Top = (int)((AbsTop - c.AbsTop) / Page.SnapSize.Height + 1e-4) * Page.SnapSize.Height + gridYOffset;
  136. Parent = c;
  137. // correct the delta
  138. savedBounds.X += saveAbsLeft - AbsLeft;
  139. savedBounds.Y += saveAbsTop - AbsTop;
  140. // check delta
  141. if (Math.Abs(savedBounds.X) > Page.SnapSize.Width)
  142. {
  143. float delta = Math.Sign(savedBounds.X) * Page.SnapSize.Width;
  144. Left += delta;
  145. savedBounds.X -= delta;
  146. }
  147. if (Math.Abs(savedBounds.Y) > Page.SnapSize.Height)
  148. {
  149. float delta = Math.Sign(savedBounds.Y) * Page.SnapSize.Height;
  150. Top += delta;
  151. savedBounds.Y -= delta * 0.9f;
  152. }
  153. }
  154. break;
  155. }
  156. }
  157. }
  158. }
  159. else
  160. {
  161. if (Left < 0)
  162. Left = 0;
  163. if (Left > (Parent as ComponentBase).Width)
  164. Left = (Parent as ComponentBase).Width - 2;
  165. if (Top < 0)
  166. Top = 0;
  167. if (Top > (Parent as ComponentBase).Height)
  168. Top = (Parent as ComponentBase).Height - 2;
  169. }
  170. }
  171. }
  172. /// <summary>
  173. /// Draws the object's markers.
  174. /// </summary>
  175. /// <param name="e">Draw event arguments.</param>
  176. public void DrawMarkers(FRPaintEventArgs e)
  177. {
  178. if (IsDesigning && Border.Lines != BorderLines.All)
  179. DrawMarkersInternal(e);
  180. }
  181. private void DrawMarkersInternal(FRPaintEventArgs e)
  182. {
  183. DrawMarkers(e, ReportWorkspace.MarkerStyle);
  184. }
  185. /// <summary>
  186. /// Draws the object's markers.
  187. /// </summary>
  188. /// <param name="e">Draw event arguments.</param>
  189. /// <param name="style">Marker style</param>
  190. public void DrawMarkers(FRPaintEventArgs e, MarkerStyle style)
  191. {
  192. IGraphics g = e.Graphics;
  193. float _1 = 1 * e.ScaleX;
  194. float _3 = 3 * e.ScaleX;
  195. if (style == MarkerStyle.Corners)
  196. {
  197. using (Pen p = new Pen(Color.Black, _1))
  198. {
  199. int x = (int)Math.Round(AbsLeft * e.ScaleX);
  200. int y = (int)Math.Round(AbsTop * e.ScaleY);
  201. int x1 = (int)Math.Round(AbsRight * e.ScaleX);
  202. int y1 = (int)Math.Round(AbsBottom * e.ScaleY);
  203. g.DrawLine(p, x, y, x + _3, y);
  204. g.DrawLine(p, x, y, x, y + _3);
  205. g.DrawLine(p, x, y1, x + _3, y1);
  206. g.DrawLine(p, x, y1, x, y1 - _3);
  207. g.DrawLine(p, x1, y, x1 - _3, y);
  208. g.DrawLine(p, x1, y, x1, y + _3);
  209. g.DrawLine(p, x1, y1, x1 - _3, y1);
  210. g.DrawLine(p, x1, y1, x1, y1 - _3);
  211. }
  212. }
  213. else if (Math.Abs(Width) > 1 || Math.Abs(Height) > 1)
  214. {
  215. using (Pen p = new Pen(Color.Gainsboro, _1))
  216. {
  217. g.DrawRectangle(p, AbsLeft * e.ScaleX, AbsTop * e.ScaleY, Width * e.ScaleX, Height * e.ScaleY);
  218. }
  219. }
  220. }
  221. /// <summary>
  222. /// Draws the intersection indicator.
  223. /// </summary>
  224. /// <param name="e">Draw event arguments.</param>
  225. public void DrawIntersection(FRPaintEventArgs e)
  226. {
  227. RectangleF rect = new RectangleF(AbsBounds.Left * e.ScaleX, AbsBounds.Top * e.ScaleY, AbsBounds.Width * e.ScaleX, AbsBounds.Height * e.ScaleY);
  228. // normalize rect in case of diagonal lines
  229. if (rect.Width < 0)
  230. {
  231. rect.X = rect.Right;
  232. rect.Width = -rect.Width;
  233. }
  234. if (rect.Height < 0)
  235. {
  236. rect.Y = rect.Bottom;
  237. rect.Height = -rect.Height;
  238. }
  239. var backColor = (Fill is SolidFill fill) ? fill.Color : Color.Red;
  240. var contrastColor = backColor.GetBrightness() < 0.5f ? Color.White : Color.Black;
  241. using (HatchBrush brush = new HatchBrush(HatchStyle.ZigZag, Color.FromArgb(80, contrastColor), Color.Transparent))
  242. {
  243. e.Graphics.FillRectangle(brush, rect.Left, rect.Top, rect.Width, rect.Height);
  244. }
  245. }
  246. /// <inheritdoc/>
  247. public override ContextMenuBase GetContextMenu()
  248. {
  249. return new ReportComponentBaseMenu(Report.Designer);
  250. }
  251. /// <inheritdoc/>
  252. public override SizeF GetPreferredSize()
  253. {
  254. if (Page is ReportPage && (Page as ReportPage).IsImperialUnitsUsed)
  255. return new SizeF(Units.Inches * 1, Units.Inches * 0.2f);
  256. return base.GetPreferredSize();
  257. }
  258. /// <inheritdoc/>
  259. public override void OnAfterInsert(InsertFrom source)
  260. {
  261. if (this is IHasEditor && source == InsertFrom.NewObject && ReportWorkspace.EditAfterInsert)
  262. (this as IHasEditor).InvokeEditor();
  263. }
  264. #endregion
  265. }
  266. }