ReportComponentBase.DesignExt.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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. namespace FastReport
  13. {
  14. /// <summary>
  15. /// The style of the report object markers.
  16. /// </summary>
  17. public enum MarkerStyle
  18. {
  19. /// <summary>
  20. /// Rectangle marker.
  21. /// </summary>
  22. Rectangle,
  23. /// <summary>
  24. /// Small markers at the object's corners.
  25. /// </summary>
  26. Corners
  27. }
  28. partial class ReportComponentBase
  29. {
  30. private CancellationTokenSource cancelToken;
  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 HandleMouseUp(FRMouseEventArgs e)
  100. {
  101. base.HandleMouseUp(e);
  102. if (e.button != MouseButtons.Left && Band != null && ReportWorkspace.EnableBacklightIntersectingObjects && IsDesigning && IsSelected)
  103. {
  104. if(cancelToken != null)
  105. cancelToken.Cancel();
  106. cancelToken = new CancellationTokenSource();
  107. Validator.ValidateIntersectionAllObjectsAsync(Band, cancelToken.Token);
  108. }
  109. }
  110. /// <inheritdoc/>
  111. public override void CheckParent(bool immediately)
  112. {
  113. if (!(Parent is ComponentBase) || !IsSelected || IsAncestor || Dock != DockStyle.None)
  114. return;
  115. if (immediately ||
  116. Left < 0 || Left > (Parent as ComponentBase).Width ||
  117. Top < 0 || Top > (Parent as ComponentBase).Height)
  118. {
  119. if (HasFlag(Flags.CanChangeParent))
  120. {
  121. ObjectCollection list = Page.AllObjects;
  122. for (int i = list.Count - 1; i >= 0; i--)
  123. {
  124. ComponentBase c = list[i] as ComponentBase;
  125. if (c == null || c == this || !(c is IParent))
  126. continue;
  127. if (c != null && (c as IParent).CanContain(this))
  128. {
  129. bool inside;
  130. int bandGap = ReportWorkspace.ClassicView && IsDesigning ? BandBase.HeaderSize : 4;
  131. if (c is BandBase)
  132. inside = AbsTop > c.AbsTop - bandGap && AbsTop < c.AbsBottom - 1;
  133. else
  134. inside = AbsLeft > c.AbsLeft - 1e-4 && AbsLeft < c.AbsRight - 1e-4 &&
  135. AbsTop > c.AbsTop - 1e-4 && AbsTop < c.AbsBottom - 1e-4;
  136. if (inside)
  137. {
  138. if (Parent != c)
  139. {
  140. float saveAbsTop = AbsTop;
  141. float saveAbsLeft = AbsLeft;
  142. // keep existing offsets if the object is not aligned to the grid
  143. float gridXOffset = Converter.DecreasePrecision(Left - (int)(Left / Page.SnapSize.Width + 1e-4) * Page.SnapSize.Width, 2);
  144. float gridYOffset = Converter.DecreasePrecision(Top - (int)(Top / Page.SnapSize.Height + 1e-4) * Page.SnapSize.Height, 2);
  145. // move the object to the new parent
  146. Left = (int)((AbsLeft - c.AbsLeft) / Page.SnapSize.Width + 1e-4) * Page.SnapSize.Width + gridXOffset;
  147. Top = (int)((AbsTop - c.AbsTop) / Page.SnapSize.Height + 1e-4) * Page.SnapSize.Height + gridYOffset;
  148. Parent = c;
  149. // correct the delta
  150. savedBounds.X += saveAbsLeft - AbsLeft;
  151. savedBounds.Y += saveAbsTop - AbsTop;
  152. // check delta
  153. if (Math.Abs(savedBounds.X) > Page.SnapSize.Width)
  154. {
  155. float delta = Math.Sign(savedBounds.X) * Page.SnapSize.Width;
  156. Left += delta;
  157. savedBounds.X -= delta;
  158. }
  159. if (Math.Abs(savedBounds.Y) > Page.SnapSize.Height)
  160. {
  161. float delta = Math.Sign(savedBounds.Y) * Page.SnapSize.Height;
  162. Top += delta;
  163. savedBounds.Y -= delta * 0.9f;
  164. }
  165. }
  166. break;
  167. }
  168. }
  169. }
  170. }
  171. else
  172. {
  173. if (Left < 0)
  174. Left = 0;
  175. if (Left > (Parent as ComponentBase).Width)
  176. Left = (Parent as ComponentBase).Width - 2;
  177. if (Top < 0)
  178. Top = 0;
  179. if (Top > (Parent as ComponentBase).Height)
  180. Top = (Parent as ComponentBase).Height - 2;
  181. }
  182. }
  183. }
  184. /// <summary>
  185. /// Draws the object's markers.
  186. /// </summary>
  187. /// <param name="e">Draw event arguments.</param>
  188. public void DrawMarkers(FRPaintEventArgs e)
  189. {
  190. if (IsDesigning && Border.Lines != BorderLines.All)
  191. DrawMarkersInternal(e);
  192. }
  193. private void DrawMarkersInternal(FRPaintEventArgs e)
  194. {
  195. DrawMarkers(e, ReportWorkspace.MarkerStyle);
  196. }
  197. /// <summary>
  198. /// Draws the object's markers.
  199. /// </summary>
  200. /// <param name="e">Draw event arguments.</param>
  201. /// <param name="style">Marker style</param>
  202. public void DrawMarkers(FRPaintEventArgs e, MarkerStyle style)
  203. {
  204. IGraphics g = e.Graphics;
  205. if (style == MarkerStyle.Corners)
  206. {
  207. Pen p = Pens.Black;
  208. int x = (int)Math.Round(AbsLeft * e.ScaleX);
  209. int y = (int)Math.Round(AbsTop * e.ScaleY);
  210. int x1 = (int)Math.Round(AbsRight * e.ScaleX);
  211. int y1 = (int)Math.Round(AbsBottom * e.ScaleY);
  212. g.DrawLine(p, x, y, x + 3, y);
  213. g.DrawLine(p, x, y, x, y + 3);
  214. g.DrawLine(p, x, y1, x + 3, y1);
  215. g.DrawLine(p, x, y1, x, y1 - 3);
  216. g.DrawLine(p, x1, y, x1 - 3, y);
  217. g.DrawLine(p, x1, y, x1, y + 3);
  218. g.DrawLine(p, x1, y1, x1 - 3, y1);
  219. g.DrawLine(p, x1, y1, x1, y1 - 3);
  220. }
  221. else if (Math.Abs(Width) > 1 || Math.Abs(Height) > 1)
  222. {
  223. g.DrawRectangle(Pens.Gainsboro, AbsLeft * e.ScaleX, AbsTop * e.ScaleY, Width * e.ScaleX, Height * e.ScaleY);
  224. }
  225. }
  226. /// <inheritdoc/>
  227. public override ContextMenuBase GetContextMenu()
  228. {
  229. return new ReportComponentBaseMenu(Report.Designer);
  230. }
  231. /// <inheritdoc/>
  232. public override SizeF GetPreferredSize()
  233. {
  234. if (Page is ReportPage && (Page as ReportPage).IsImperialUnitsUsed)
  235. return new SizeF(Units.Inches * 1, Units.Inches * 0.2f);
  236. return base.GetPreferredSize();
  237. }
  238. /// <inheritdoc/>
  239. public override void OnAfterInsert(InsertFrom source)
  240. {
  241. if (this is IHasEditor && source == InsertFrom.NewObject && ReportWorkspace.EditAfterInsert)
  242. (this as IHasEditor).InvokeEditor();
  243. }
  244. #endregion
  245. #region Proteted Method
  246. /// <summary>
  247. /// Fill background
  248. /// </summary>
  249. /// <param name="e"></param>
  250. protected bool DrawIntersectBackground(FRPaintEventArgs e)
  251. {
  252. if (IsDesigning && IsIntersectingWithOtherObject && ReportWorkspace.EnableBacklightIntersectingObjects)
  253. {
  254. RectangleF rect = new RectangleF(AbsBounds.Left * e.ScaleX, AbsBounds.Top * e.ScaleY, AbsBounds.Width * e.ScaleX, AbsBounds.Height * e.ScaleY);
  255. using (SolidBrush brush = new SolidBrush(Config.BacklightColor))
  256. {
  257. e.Graphics.FillRectangle(brush, rect.Left, rect.Top, rect.Width, rect.Height);
  258. }
  259. return true;
  260. }
  261. return false;
  262. }
  263. #endregion
  264. }
  265. }