PolyLineObject.DesignExt.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. using FastReport.Utils;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Drawing.Drawing2D;
  6. using System.Windows.Forms;
  7. namespace FastReport
  8. {
  9. partial class PolyLineObject : IHasEditor
  10. {
  11. //Current selected point, for move
  12. //internal PolyLineObjectToolBar toolbar; //deprecated
  13. #region Private Fields
  14. private PolyPoint currentPoint;
  15. private PolyPoint drawSelectedPointLine;
  16. private int drawSelectedPointLineNumber;
  17. private int selectedPoint;
  18. #endregion Private Fields
  19. #region Public Properties
  20. /// <inheritdoc/>
  21. public override float Height
  22. {
  23. get { return base.Height; }
  24. set
  25. {
  26. if (base.Height == 0)
  27. {
  28. base.Height = value;
  29. return;
  30. }
  31. if (IsSelected)
  32. {
  33. if (SelectionMode == PolygonSelectionMode.MoveAndScale)
  34. {
  35. float oldHeight = base.Height;
  36. if (oldHeight == value) return;
  37. if (pointsCollection.Count < 2)
  38. return;
  39. float scaleY = value / oldHeight;
  40. if (float.IsInfinity(scaleY))
  41. return;
  42. if (float.IsNaN(scaleY))
  43. return;
  44. if (scaleY == 0)
  45. return;
  46. center.Y = center.Y * scaleY;
  47. foreach (PolyPoint point in pointsCollection)
  48. {
  49. point.ScaleY(scaleY);
  50. }
  51. base.Height = value;
  52. }
  53. else
  54. RecalculateBounds();
  55. }
  56. else
  57. base.Height = value;
  58. }
  59. }
  60. /// <inheritdoc/>
  61. public override float Width
  62. {
  63. get { return base.Width; }
  64. set
  65. {
  66. if (base.Width == 0)
  67. {
  68. base.Width = value;
  69. return;
  70. }
  71. if (IsSelected)
  72. {
  73. if (SelectionMode == PolygonSelectionMode.MoveAndScale)
  74. {
  75. float oldWidth = base.Width;
  76. if (oldWidth == value) return;
  77. if (pointsCollection.Count < 2)
  78. return;
  79. float scaleX = value / oldWidth;
  80. if (float.IsInfinity(scaleX))
  81. return;
  82. if (float.IsNaN(scaleX))
  83. return;
  84. if (scaleX == 0)
  85. return;
  86. center.X = center.X * scaleX;
  87. foreach (PolyPoint point in pointsCollection)
  88. {
  89. point.ScaleX(scaleX);
  90. }
  91. base.Width = value;
  92. }
  93. else
  94. RecalculateBounds();
  95. }
  96. else
  97. base.Width = value;
  98. }
  99. }
  100. #endregion Public Properties
  101. #region Internal Properties
  102. internal PolygonSelectionMode SelectionMode
  103. {
  104. get
  105. {
  106. return polygonSelectionMode;
  107. }
  108. set
  109. {
  110. if (value != polygonSelectionMode)
  111. {
  112. polygonSelectionMode = value;
  113. try
  114. {
  115. if (IsSelected)
  116. {
  117. Report.Designer.SelectionChanged(this);
  118. }
  119. }
  120. catch
  121. {
  122. }
  123. polygonSelectionMode = value;
  124. }
  125. }
  126. }
  127. #endregion Internal Properties
  128. #region Public Methods
  129. /// <summary>
  130. /// Add point to end of polyline and recalculate bounds after add.
  131. /// Can be first point.
  132. /// Deprecated, use insert point
  133. /// </summary>
  134. /// <param name="localX">local x - relative to left-top point</param>
  135. /// <param name="localY">local y - relative to left-top point</param>
  136. [Obsolete]
  137. public void AddPointToEnd(float localX, float localY)
  138. {
  139. insertPoint(pointsCollection.Count, localX, localY, 1);
  140. if (Report != null)
  141. if (Report.Designer != null)
  142. Report.Designer.SetModified(this, "Change");
  143. }
  144. /// <summary>
  145. /// Add point to start of polyline and recalculate bounds after add
  146. /// Can be first point
  147. /// Deprecated, use insert point
  148. /// </summary>
  149. /// <param name="localX">local x - relative to left-top point</param>
  150. /// <param name="localY">local y - relative to left-top point</param>
  151. [Obsolete]
  152. public void AddPointToStart(float localX, float localY)
  153. {
  154. insertPoint(0, localX, localY, 1);
  155. if (Report != null)
  156. if (Report.Designer != null)
  157. Report.Designer.SetModified(this, "Change");
  158. }
  159. /// <inheritdoc/>
  160. public override void CheckNegativeSize(FRMouseEventArgs e)
  161. {
  162. // do nothing
  163. }
  164. /// <inheritdoc/>
  165. public override void DrawSelection(FRPaintEventArgs e)
  166. {
  167. if (SelectionMode == PolygonSelectionMode.AddToLine && drawSelectedPointLineNumber >= 0 && pointsCollection.Count > 0)
  168. {
  169. if (drawSelectedPointLine != null)
  170. {
  171. float absLeft = AbsLeft;
  172. float absTop = AbsTop;
  173. Pen p = e.Cache.GetPen(Color.DarkGray, 1, DashStyle.Solid);
  174. if (drawSelectedPointLineNumber > 0 && drawSelectedPointLineNumber - 1 < pointsCollection.Count || this is PolygonObject)
  175. {
  176. e.Graphics.DrawLine(p, GetPointF(drawSelectedPointLine, e.ScaleX, e.ScaleY, absLeft, absTop), GetPointF(drawSelectedPointLineNumber - 1, e.ScaleX, e.ScaleY, absLeft, absTop));
  177. }
  178. if (drawSelectedPointLineNumber < pointsCollection.Count || this is PolygonObject)
  179. {
  180. e.Graphics.DrawLine(p, GetPointF(drawSelectedPointLine, e.ScaleX, e.ScaleY, absLeft, absTop), GetPointF(drawSelectedPointLineNumber, e.ScaleX, e.ScaleY, absLeft, absTop));
  181. }
  182. }
  183. }
  184. if (SelectionMode == PolygonSelectionMode.MoveAndScale)
  185. {
  186. base.DrawSelection(e);
  187. }
  188. else
  189. {
  190. Pen help_p = e.Cache.GetPen(Color.Black, 1, DashStyle.Dash);
  191. if (Page == null)
  192. return;
  193. bool firstSelected = Report.Designer.SelectedObjects.IndexOf(this) == 0;
  194. Pen p = firstSelected ? Pens.Black : Pens.White;
  195. Brush b = firstSelected ? Brushes.White : Brushes.Black;
  196. SelectionPoint[] selectionPoints = GetSelectionPoints();
  197. IGraphics g = e.Graphics;
  198. SelectionPoint lastPoint = null;
  199. float m = Report.Designer.DpiMultiplier();
  200. foreach (SelectionPoint pt in selectionPoints)
  201. {
  202. switch (pt.sizingPoint)
  203. {
  204. case SizingPoint.LeftTop:
  205. {
  206. float x = pt.x * e.ScaleX;
  207. float y = pt.y * e.ScaleY;
  208. g.FillEllipse(Brushes.White, x - 5 * m, y - 5 * m, 10 * m, 10 * m);
  209. g.FillEllipse(Brushes.Red, x - 3 * m, y - 3 * m, 6 * m, 6 * m);
  210. g.DrawEllipse(Pens.Gray, x - 3 * m, y - 3 * m, 6 * m, 6 * m);
  211. lastPoint = pt;
  212. }
  213. break;
  214. case SizingPoint.RightTop:
  215. {
  216. float x = pt.x * e.ScaleX;
  217. float y = pt.y * e.ScaleY;
  218. if (lastPoint != null)
  219. {
  220. e.Graphics.DrawLine(help_p, lastPoint.x * e.ScaleX, lastPoint.y * e.ScaleY, x, y);
  221. }
  222. g.FillEllipse(Brushes.White, x - 3 * m, y - 3 * m, 6 * m, 6 * m);
  223. g.FillEllipse(Brushes.Blue, x - 2 * m, y - 2 * m, 4 * m, 4 * m);
  224. g.DrawEllipse(Pens.Gray, x - 2 * m, y - 2 * m, 4 * m, 4 * m);
  225. }
  226. break;
  227. default:
  228. lastPoint = pt;
  229. DrawSelectionPoint(e, p, b, pt.x, pt.y);
  230. break;
  231. }
  232. }
  233. }
  234. }
  235. /// <summary>
  236. /// Replace points with star
  237. /// </summary>
  238. /// <param name="spikes">Minimum value is 3</param>
  239. public void DrawStar(int spikes)
  240. {
  241. if (spikes < 3) spikes = 3;
  242. const float outerRadius = 50;
  243. const float innerRadius = 30;
  244. float rot = (float)(Math.PI / 2 * 3);
  245. const float cx = 0;
  246. const float cy = 0;
  247. float x = cx;
  248. float y = cy;
  249. float step = (float)(Math.PI / spikes);
  250. base.Width = 100;
  251. base.Height = 100;
  252. center = new PointF(50, 50);
  253. pointsCollection.Clear();
  254. pointsCollection.Add(new PolyPoint(cx, cy - outerRadius));
  255. for (int i = 0; i < spikes; i++)
  256. {
  257. x = cx + (float)Math.Cos(rot) * outerRadius;
  258. y = cy + (float)Math.Sin(rot) * outerRadius;
  259. pointsCollection.Add(new PolyPoint(x, y));
  260. rot += step;
  261. x = cx + (float)Math.Cos(rot) * innerRadius;
  262. y = cy + (float)Math.Sin(rot) * innerRadius;
  263. pointsCollection.Add(new PolyPoint(x, y));
  264. rot += step;
  265. }
  266. }
  267. /// <inheritdoc/>
  268. public override SizeF GetPreferredSize()
  269. {
  270. return new SizeF(0, 0);
  271. }
  272. /// <inheritdoc/>
  273. public override void HandleKeyDown(Control sender, KeyEventArgs e)
  274. {
  275. if (e.KeyCode == Keys.Delete)
  276. {
  277. if (SelectionMode != PolygonSelectionMode.MoveAndScale)
  278. {
  279. if (pointsCollection.Count > 0)
  280. {
  281. DeletePointByIndex(selectedPoint);
  282. selectedPoint--;
  283. Report.Designer.Refresh();
  284. e.Handled = true;
  285. }
  286. }
  287. }
  288. if (!e.Handled)
  289. base.HandleKeyDown(sender, e);
  290. }
  291. /// <inheritdoc/>
  292. public override void HandleMouseDown(FRMouseEventArgs e)
  293. {
  294. //if (toolbar.IsVisible && this.IsSelected)
  295. //{
  296. // if (toolbar.ClickPublic(new PointF(AbsLeft, AbsTop < 20 ? 20 : AbsTop), new PointF(e.x, e.y)))
  297. // {
  298. // e.handled = true;
  299. // return;
  300. // }
  301. //}
  302. if (e.button == MouseButtons.Left && currentPoint == null && this.IsSelected)
  303. {
  304. float absLeft = AbsLeft;
  305. float absTop = AbsTop;
  306. PointF mousePoint = new PointF(e.x, e.y);
  307. PointF mousePointAligned = new PointF((int)((e.x - absLeft - center.X) / Page.SnapSize.Width) * Page.SnapSize.Width, (int)((e.y - absTop - center.Y) / Page.SnapSize.Height) * Page.SnapSize.Height);
  308. switch (SelectionMode)
  309. {
  310. case PolygonSelectionMode.Normal:
  311. for (int i = 0; i < pointsCollection.Count; i++)
  312. {
  313. PolyPoint point = pointsCollection[i];
  314. if (point.LeftCurve != null && PointInSelectionPoint(absLeft + point.X + center.X + point.LeftCurve.X, absTop + point.Y + center.Y + point.LeftCurve.Y, mousePoint))
  315. {
  316. currentPoint = point.LeftCurve;
  317. e.mode = WorkspaceMode2.Custom;
  318. e.handled = true;
  319. break;
  320. }
  321. else if (point.RightCurve != null && PointInSelectionPoint(absLeft + point.X + center.X + point.RightCurve.X, absTop + point.Y + center.Y + point.RightCurve.Y, mousePoint))
  322. {
  323. currentPoint = point.RightCurve;
  324. e.mode = WorkspaceMode2.Custom;
  325. e.handled = true;
  326. break;
  327. }
  328. else if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
  329. {
  330. currentPoint = point;
  331. e.mode = WorkspaceMode2.Custom;
  332. e.handled = true;
  333. break;
  334. }
  335. }
  336. break;
  337. case PolygonSelectionMode.AddToLine:
  338. for (int i = 0; i < pointsCollection.Count; i++)
  339. {
  340. PolyPoint point = pointsCollection[i];
  341. if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
  342. {
  343. currentPoint = point;
  344. e.mode = WorkspaceMode2.Custom;
  345. e.handled = true;
  346. break;
  347. }
  348. }
  349. if (!e.handled)
  350. {
  351. e.handled = true;
  352. PolyPoint result = InsertPointByLocation(mousePointAligned.X, mousePointAligned.Y, 25);
  353. if (result != null)
  354. {
  355. e.mode = WorkspaceMode2.Custom;
  356. currentPoint = result;
  357. }
  358. }
  359. break;
  360. case PolygonSelectionMode.AddBezier:
  361. for (int i = 0; i < pointsCollection.Count; i++)
  362. {
  363. PolyPoint point = pointsCollection[i];
  364. if (point.LeftCurve != null)
  365. {
  366. if (PointInSelectionPoint(absLeft + point.X + center.X + point.LeftCurve.X, absTop + point.Y + center.Y + point.LeftCurve.Y, mousePoint))
  367. {
  368. currentPoint = point.LeftCurve;
  369. e.mode = WorkspaceMode2.Custom;
  370. e.handled = true;
  371. break;
  372. }
  373. }
  374. else if (i == selectedPoint)
  375. {
  376. if (i > 0 || (this is PolygonObject))
  377. {
  378. PolyPoint pseudoPoint = GetPseudoPoint(point, pointsCollection[i - 1]);
  379. if (PointInSelectionPoint(absLeft + pseudoPoint.X + center.X, absTop + pseudoPoint.Y + center.Y, mousePoint))
  380. {
  381. pseudoPoint.X -= point.X;
  382. pseudoPoint.Y -= point.Y;
  383. point.LeftCurve = pseudoPoint;
  384. currentPoint = pseudoPoint;
  385. e.mode = WorkspaceMode2.Custom;
  386. e.handled = true;
  387. break;
  388. }
  389. }
  390. }
  391. if (point.RightCurve != null)
  392. {
  393. if (PointInSelectionPoint(absLeft + point.X + center.X + point.RightCurve.X, absTop + point.Y + center.Y + point.RightCurve.Y, mousePoint))
  394. {
  395. currentPoint = point.RightCurve;
  396. e.mode = WorkspaceMode2.Custom;
  397. e.handled = true;
  398. break;
  399. }
  400. }
  401. else
  402. {
  403. if (i < pointsCollection.Count || (this is PolygonObject))
  404. {
  405. PolyPoint pseudoPoint = GetPseudoPoint(point, pointsCollection[i + 1]);
  406. if (PointInSelectionPoint(absLeft + pseudoPoint.X + center.X, absTop + pseudoPoint.Y + center.Y, mousePoint))
  407. {
  408. pseudoPoint.X -= point.X;
  409. pseudoPoint.Y -= point.Y;
  410. point.RightCurve = pseudoPoint;
  411. currentPoint = pseudoPoint;
  412. e.mode = WorkspaceMode2.Custom;
  413. e.handled = true;
  414. break;
  415. }
  416. }
  417. }
  418. if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
  419. {
  420. currentPoint = point;
  421. e.mode = WorkspaceMode2.Custom;
  422. e.handled = true;
  423. break;
  424. }
  425. }
  426. break;
  427. case PolygonSelectionMode.Delete:
  428. for (int i = 0; i < pointsCollection.Count; i++)
  429. {
  430. PolyPoint point = pointsCollection[i];
  431. if (point.LeftCurve != null && PointInSelectionPoint(absLeft + point.X + center.X + point.LeftCurve.X, absTop + point.Y + center.Y + point.LeftCurve.Y, mousePoint))
  432. {
  433. point.LeftCurve = null;
  434. currentPoint = null;
  435. e.mode = WorkspaceMode2.None;
  436. e.handled = true;
  437. return;
  438. }
  439. else if (point.RightCurve != null && PointInSelectionPoint(absLeft + point.X + center.X + point.RightCurve.X, absTop + point.Y + center.Y + point.RightCurve.Y, mousePoint))
  440. {
  441. point.RightCurve = null;
  442. currentPoint = null;
  443. e.mode = WorkspaceMode2.None;
  444. e.handled = true;
  445. return;
  446. }
  447. else if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
  448. {
  449. RemovePointAt(i);
  450. currentPoint = null;
  451. if (i < selectedPoint)
  452. selectedPoint--;
  453. e.mode = WorkspaceMode2.None;
  454. e.handled = true;
  455. return;
  456. }
  457. }
  458. break;
  459. case PolygonSelectionMode.MoveAndScale:
  460. if (pointsCollection.Count < 2)
  461. {
  462. for (int i = 0; i < pointsCollection.Count; i++)
  463. {
  464. PolyPoint point = pointsCollection[i];
  465. if (PointInSelectionPoint(absLeft + point.X + center.X, absTop + point.Y + center.Y, mousePoint))
  466. {
  467. currentPoint = point;
  468. e.mode = WorkspaceMode2.Custom;
  469. e.handled = true;
  470. break;
  471. }
  472. }
  473. }
  474. break;
  475. }
  476. }
  477. if (!e.handled)
  478. base.HandleMouseDown(e);
  479. }
  480. /// <inheritdoc/>
  481. public override void HandleMouseMove(FRMouseEventArgs e)
  482. {
  483. if (currentPoint != null)
  484. {
  485. currentPoint.X += e.delta.X;
  486. currentPoint.Y += e.delta.Y;
  487. //points[currentPoint] = point;
  488. RecalculateBounds();
  489. e.mode = WorkspaceMode2.Custom;
  490. e.handled = true;
  491. }
  492. if (!e.handled && SelectionMode == PolygonSelectionMode.AddToLine)
  493. {
  494. PolyPoint mousePointAligned = new PolyPoint((int)((e.x - AbsLeft - center.X) / Page.SnapSize.Width) * Page.SnapSize.Width, (int)((e.y - AbsTop - center.Y) / Page.SnapSize.Height) * Page.SnapSize.Height);
  495. drawSelectedPointLineNumber = GetBestPointPosition(mousePointAligned.X, mousePointAligned.Y);
  496. if (drawSelectedPointLine == null || !drawSelectedPointLine.Near(mousePointAligned))
  497. {
  498. drawSelectedPointLine = mousePointAligned;
  499. Report.Designer.Refresh();
  500. }
  501. }
  502. else
  503. {
  504. drawSelectedPointLineNumber = -1;
  505. }
  506. if (!e.handled)
  507. {
  508. base.HandleMouseMove(e);
  509. }
  510. if (e.handled)
  511. {
  512. e.cursor = Cursors.Cross;
  513. }
  514. if (IsSelected)
  515. {
  516. switch (SelectionMode)
  517. {
  518. case PolygonSelectionMode.AddToLine:
  519. case PolygonSelectionMode.AddBezier:
  520. e.handled = true;
  521. e.mode = WorkspaceMode2.Custom;
  522. break;
  523. }
  524. }
  525. //if (toolbar != null && toolbar.IsVisible)
  526. //{
  527. // //toolbar.MouseMove(e.x, e.y);
  528. //}
  529. }
  530. /// <inheritdoc/>
  531. public override void HandleMouseUp(FRMouseEventArgs e)
  532. {
  533. if (currentPoint != null)
  534. {
  535. RecalculateBounds();
  536. int index = pointsCollection.IndexOf(currentPoint);
  537. if (index >= 0)
  538. selectedPoint = index;
  539. currentPoint = null;
  540. if (Report != null)
  541. if (Report.Designer != null)
  542. Report.Designer.SetModified(this, "Change");
  543. }
  544. if (IsSelected)
  545. {
  546. int mode = (int)SelectionMode;
  547. if (0 < mode)
  548. {
  549. e.handled = true;
  550. }
  551. }
  552. if (!e.handled)
  553. base.HandleMouseUp(e);
  554. }
  555. /// <summary>
  556. /// Insert point to desired place of polyline
  557. /// Recalculate bounds after insert
  558. /// </summary>
  559. /// <param name="index">Index of place from zero to count</param>
  560. /// <param name="localX">local x - relative to left-top point</param>
  561. /// <param name="localY">local y - relative to left-top point</param>
  562. public void InsertPointByIndex(int index, float localX, float localY)
  563. {
  564. insertPoint(index, localX, localY, 0);
  565. if (Report != null)
  566. if (Report.Designer != null)
  567. Report.Designer.SetModified(this, "Change");
  568. }
  569. /// <summary>
  570. /// Insert point to near line
  571. /// Recalculate bounds after insert
  572. /// </summary>
  573. /// <param name="localX">local x - relative to left-top point</param>
  574. /// <param name="localY">local y - relative to left-top point</param>
  575. /// <param name="maxDistance">depricated</param>
  576. /// <returns>Index of inserted point</returns>
  577. public PolyPoint InsertPointByLocation(float localX, float localY, float maxDistance)
  578. {
  579. PolyPoint result;
  580. int pointNumber = -1;
  581. if (pointsCollection.Count == 0)
  582. {
  583. result = addPoint(0, 0, 0);
  584. pointNumber = 0;
  585. }
  586. else
  587. {
  588. pointNumber = GetBestPointPosition(localX, localY);
  589. result = insertPoint(pointNumber, localX, localY, 1);
  590. }
  591. RecalculateBounds();
  592. if (pointNumber >= 0)
  593. if (Report != null)
  594. if (Report.Designer != null)
  595. Report.Designer.SetModified(this, "Change");
  596. return result;
  597. }
  598. /// <inheritdoc/>
  599. public bool InvokeEditor()
  600. {
  601. if (IsSelected)
  602. {
  603. if (SelectionMode == PolygonSelectionMode.MoveAndScale)
  604. {
  605. Report report = Report;
  606. if (report != null)
  607. {
  608. SelectionMode = PolygonSelectionMode.Normal;
  609. }
  610. return true;
  611. }
  612. else if (SelectionMode == PolygonSelectionMode.Normal)
  613. {
  614. Report report = Report;
  615. if (report != null)
  616. {
  617. SelectionMode = PolygonSelectionMode.MoveAndScale;
  618. }
  619. return true;
  620. }
  621. }
  622. return false;
  623. }
  624. /// <inheritdoc/>
  625. public override void OnAfterInsert(InsertFrom source)
  626. {
  627. base.OnAfterInsert(source);
  628. if (Report != null)
  629. {
  630. SelectedObjectCollection selectionObjects = Report.Designer.SelectedObjects;
  631. selectionObjects.Clear();
  632. selectionObjects.Add(this);
  633. }
  634. if (pointsCollection.Count < 2)
  635. SelectionMode = PolygonSelectionMode.AddToLine;
  636. if (pointsCollection.Count > 1)
  637. SelectionMode = PolygonSelectionMode.MoveAndScale;
  638. }
  639. /// <inheritdoc/>
  640. public override void OnBeforeInsert(int flags)
  641. {
  642. float rotation = (float)((flags & 0xF) / 8.0 * Math.PI);
  643. int numberOfEdges = (flags & 0xF0) >> 4;
  644. if (numberOfEdges >= 5)
  645. {
  646. float x, y;
  647. pointsCollection.Clear();
  648. for (int i = 0; i < numberOfEdges; i++)
  649. {
  650. base.Width = 100;
  651. base.Height = 100;
  652. x = 50 + (float)(50 * Math.Cos(rotation + 2 * Math.PI * i / numberOfEdges));
  653. y = 50 + (float)(50 * Math.Sin(rotation + 2 * Math.PI * i / numberOfEdges));
  654. pointsCollection.Add(new PolyPoint(x, y));
  655. }
  656. }
  657. else
  658. {
  659. pointsCollection.Add(new PolyPoint(0, 0));
  660. Width = 5;
  661. Height = 5;
  662. }
  663. }
  664. /// <inheritdoc/>
  665. public override bool PointInObject(PointF point)
  666. {
  667. using (Pen pen = new Pen(Color.Black, 10))
  668. using (GraphicsPath path = new GraphicsPath())
  669. {
  670. float absLeft = AbsLeft;
  671. float absTop = AbsTop;
  672. if (pointsCollection.Count > 1 && currentPoint == null)
  673. for (int i = 0; i < pointsCollection.Count - 1; i++)
  674. {
  675. PolyPoint prev = pointsCollection[i];
  676. PolyPoint next = pointsCollection[i + 1];
  677. path.AddLine(absLeft + prev.X + center.X, absTop + prev.Y + center.Y, absLeft + next.X + center.X, absTop + next.Y + center.Y);
  678. }
  679. else
  680. path.AddLine(absLeft - 1 + CenterX, absTop - 1 + CenterY, AbsRight + 1 + CenterX, AbsBottom + 1 + CenterY);
  681. return path.IsOutlineVisible(point, pen);
  682. }
  683. }
  684. /// <summary>
  685. /// Delete point from polyline by index
  686. /// Recalculate bounds after remove
  687. /// </summary>
  688. /// <param name="index">Index of point in polyline</param>
  689. public void RemovePointAt(int index)
  690. {
  691. deletePoint(index);
  692. if (Report != null)
  693. if (Report.Designer != null)
  694. Report.Designer.SetModified(this, "Change");
  695. }
  696. /// <inheritdoc/>
  697. public override void SelectionChanged()
  698. {
  699. base.SelectionChanged();
  700. if (!IsSelected)
  701. SelectionMode = PolygonSelectionMode.MoveAndScale;
  702. }
  703. #endregion Public Methods
  704. #region Protected Methods
  705. /// <summary>
  706. /// Delete point from polyline by index.
  707. /// Recalculate bounds.
  708. /// </summary>
  709. /// <param name="index">Index of point in polyline</param>
  710. protected void DeletePointByIndex(int index)
  711. {
  712. pointsCollection.Remove(index);
  713. RecalculateBounds();
  714. }
  715. /// <inheritdoc/>
  716. protected override void DrawSelectionPoint(FRPaintEventArgs e, Pen p, Brush b, float x, float y)
  717. {
  718. if (SelectionMode == PolygonSelectionMode.MoveAndScale)
  719. {
  720. base.DrawSelectionPoint(e, p, b, x, y);
  721. }
  722. else
  723. {
  724. IGraphics g = e.Graphics;
  725. x = (float)Math.Round(x * e.ScaleX);
  726. y = (float)Math.Round(y * e.ScaleY);
  727. float m = Report.Designer.DpiMultiplier();
  728. RectangleF rect = new RectangleF(x - 3 * m, y - 3 * m, 6 * m, 6 * m);
  729. g.FillEllipse(b, rect);
  730. g.DrawEllipse(p, rect);
  731. }
  732. }
  733. /// <inheritdoc/>
  734. protected override SelectionPoint[] GetSelectionPoints()
  735. {
  736. List<SelectionPoint> selectionPoints = new List<SelectionPoint>();
  737. if (pointsCollection.Count == 0)
  738. {
  739. return new SelectionPoint[] {
  740. new SelectionPoint(AbsLeft + CenterX, AbsTop + CenterY,SizingPoint.None)
  741. };
  742. }
  743. if (SelectionMode == PolygonSelectionMode.MoveAndScale && pointsCollection.Count > 1)
  744. {
  745. return base.GetSelectionPoints();
  746. }
  747. if (pointsCollection.Count > 0)
  748. selectedPoint = (pointsCollection.Count + selectedPoint) % pointsCollection.Count;
  749. float absLeft = AbsLeft;
  750. float absTop = AbsTop;
  751. for (int i = 0; i < pointsCollection.Count; i++)
  752. {
  753. PolyPoint point = pointsCollection[i];
  754. selectionPoints.Add(new SelectionPoint(point.X + absLeft + center.X, point.Y + absTop + center.Y,
  755. i == selectedPoint ? SizingPoint.LeftTop : SizingPoint.RightBottom));
  756. if (SelectionMode != PolygonSelectionMode.AddToLine)
  757. {
  758. if (point.LeftCurve != null)
  759. {
  760. selectionPoints.Add(new SelectionPoint(point.X + absLeft + center.X + point.LeftCurve.X, point.Y + absTop + center.Y + point.LeftCurve.Y, SizingPoint.RightTop));
  761. }
  762. else if (SelectionMode == PolygonSelectionMode.AddBezier && i == selectedPoint)
  763. {
  764. if (i > 0 || (this is PolygonObject))
  765. {
  766. PolyPoint pseudoPoint = GetPseudoPoint(point, pointsCollection[i - 1]);
  767. selectionPoints.Add(new SelectionPoint(pseudoPoint.X + absLeft + center.X, pseudoPoint.Y + absTop + center.Y, SizingPoint.RightTop));
  768. }
  769. }
  770. if (point.RightCurve != null)
  771. {
  772. selectionPoints.Add(new SelectionPoint(point.X + absLeft + center.X + point.RightCurve.X, point.Y + absTop + center.Y + point.RightCurve.Y, SizingPoint.RightTop));
  773. }
  774. else if (SelectionMode == PolygonSelectionMode.AddBezier && i == selectedPoint)
  775. {
  776. if (i < pointsCollection.Count - 1 || (this is PolygonObject))
  777. {
  778. PolyPoint pseudoPoint = GetPseudoPoint(point, pointsCollection[i + 1]);
  779. selectionPoints.Add(new SelectionPoint(pseudoPoint.X + absLeft + center.X, pseudoPoint.Y + absTop + center.Y, SizingPoint.RightTop));
  780. }
  781. }
  782. }
  783. }
  784. return selectionPoints.ToArray();
  785. }
  786. #endregion Protected Methods
  787. #region Private Methods
  788. private void DrawDesign0(FRPaintEventArgs e)
  789. {
  790. if (IsSelected && SelectionMode == PolyLineObject.PolygonSelectionMode.MoveAndScale)
  791. {
  792. Pen pen = e.Cache.GetPen(Color.Gray, 1, DashStyle.Dot);
  793. e.Graphics.DrawRectangle(pen, AbsLeft * e.ScaleX, AbsTop * e.ScaleY, Width * e.ScaleX, Height * e.ScaleY);
  794. }
  795. }
  796. private void DrawDesign1(FRPaintEventArgs e)
  797. {
  798. }
  799. /// <summary>
  800. /// Returns best new point position based on mouse
  801. /// </summary>
  802. /// <returns></returns>
  803. private int GetBestPointPosition(float localX, float localY)
  804. {
  805. if (pointsCollection.Count > 0)
  806. {
  807. selectedPoint = (pointsCollection.Count + selectedPoint) % pointsCollection.Count;
  808. //add near select point
  809. //check if point is first or last
  810. if (selectedPoint == pointsCollection.Count - 1 && !(this is PolygonObject))
  811. {
  812. return pointsCollection.Count;
  813. }
  814. else if (selectedPoint == 0 && !(this is PolygonObject))
  815. {
  816. return 0;
  817. }
  818. else
  819. {
  820. PolyPoint local = new PolyPoint(localX, localY);
  821. PolyPoint pLeft = pointsCollection[selectedPoint - 1];
  822. PolyPoint pCenter = pointsCollection[selectedPoint];
  823. PolyPoint pRight = pointsCollection[selectedPoint + 1];
  824. //float pLeft_pLocal =
  825. // ((pLeft.X + CenterX - localX) * (pLeft.X + CenterX - localX) + (pLeft.Y + CenterY - localY) * (pLeft.Y + CenterY - localY));
  826. //float pRight_pLocal =
  827. // ((pRight.X + CenterX - localX) * (pRight.X + CenterX - localX) + (pRight.Y + CenterY - localY) * (pRight.Y + CenterY - localY));
  828. //float pLeft_pCenter = ((pLeft.X - pCenter.X) * (pLeft.X - pCenter.X) + (pLeft.Y - pCenter.Y) * (pLeft.Y - pCenter.Y));
  829. //float pRight_pCenter = ((pRight.X - pCenter.X) * (pRight.X - pCenter.X) + (pRight.Y - pCenter.Y) * (pRight.Y - pCenter.Y));
  830. //float distance1 = pLeft_pLocal/ pLeft_pCenter;
  831. //float distance2 = pRight_pLocal / pRight_pCenter;
  832. float distance1 = MATH_pnt_seg_dist(local, pLeft, pCenter);
  833. float distance2 = MATH_pnt_seg_dist(local, pCenter, pRight);
  834. if (distance1 < distance2)
  835. {
  836. return selectedPoint;
  837. }
  838. else
  839. {
  840. return selectedPoint + 1;
  841. }
  842. }
  843. }
  844. return 0;
  845. }
  846. private PointF GetPointF(int index, float scaleX, float scaleY, float absLeft, float absTop)
  847. {
  848. return GetPointF(pointsCollection[index], scaleX, scaleY, absLeft, absTop);
  849. }
  850. private PointF GetPointF(PolyPoint point, float scaleX, float scaleY, float absLeft, float absTop)
  851. {
  852. return new PointF(
  853. (point.X + absLeft + center.X) * scaleX,
  854. (point.Y + absTop + center.Y) * scaleY
  855. );
  856. }
  857. private void InitDesign()
  858. {
  859. currentPoint = null;
  860. SelectionMode = PolygonSelectionMode.MoveAndScale;
  861. //toolbar = new PolyLineObjectToolBar(this);
  862. }
  863. private float MATH_dot(float aX, float aY, float bX, float bY)
  864. {
  865. return aX * bX + aY * bY;
  866. }
  867. private float MATH_length_squared(PolyPoint a, PolyPoint b)
  868. {
  869. return (a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y);
  870. }
  871. private float MATH_pnt_seg_dist(PolyPoint p, PolyPoint v, PolyPoint w)
  872. {
  873. // Return minimum distance between line segment vw and point p
  874. float l2 = MATH_length_squared(v, w); // i.e. |w-v|^2 - avoid a sqrt
  875. if (l2 == 0.0) return MATH_length_squared(p, v); // v == w case
  876. // Consider the line extending the segment, parameterized as v + t (w - v).
  877. // We find projection of point p onto the line.
  878. // It falls where t = [(p-v) . (w-v)] / |w-v|^2
  879. // We clamp t from [0,1] to handle points outside the segment vw.
  880. float t = Math.Max(0, Math.Min(1, MATH_dot(p.X - v.X, p.Y - v.Y, w.X - v.X, w.Y - v.Y) / l2));
  881. PolyPoint projection = new PolyPoint(v.X + t * (w.X - v.X), v.Y + t * (w.Y - v.Y)); // Projection falls on the segment
  882. return MATH_length_squared(p, projection);
  883. }
  884. #endregion Private Methods
  885. }
  886. }