ReportWorkspace.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using System.Windows.Forms;
  5. using System.Drawing;
  6. using System.Drawing.Drawing2D;
  7. using System.Net;
  8. using FastReport.Data;
  9. using FastReport.Utils;
  10. using FastReport.TypeConverters;
  11. using FastReport.Design.ToolWindows;
  12. namespace FastReport.Design.PageDesigners.Page
  13. {
  14. internal class ReportWorkspace : DesignWorkspaceBase
  15. {
  16. #region Fields
  17. private float zoom;
  18. private bool zoomLock = false;
  19. private EventIndicator eventIndicator;
  20. private Guides guides;
  21. private Size workspaceSize;
  22. #endregion
  23. #region Properties
  24. public float Zoom
  25. {
  26. get { return zoom; }
  27. set
  28. {
  29. DoZoom(value);
  30. }
  31. }
  32. public float ZoomDpi { get { return Zoom * this.DpiMultiplier(); } }
  33. public static Grid Grid = new Grid();
  34. public static bool ShowGrid;
  35. public static bool SnapToGrid;
  36. public static bool ShowGuides;
  37. public static bool AutoGuides;
  38. public static MarkerStyle MarkerStyle;
  39. public static bool ClassicView;
  40. public static bool EditAfterInsert;
  41. public static bool EventObjectIndicator;
  42. public static bool EventBandIndicator;
  43. public static bool EnableBacklight;
  44. public static bool SimplifyDBFields;
  45. public static bool EnableBacklightIntersectingObjects;
  46. public ReportPage Page
  47. {
  48. get { return PageDesigner.Page as ReportPage; }
  49. }
  50. public Guides Guides
  51. {
  52. get { return guides; }
  53. }
  54. public Size WorkspaceSize => workspaceSize;
  55. private RulerPanel RulerPanel
  56. {
  57. get { return (PageDesigner as ReportPageDesigner).RulerPanel; }
  58. }
  59. #endregion
  60. #region Private Methods
  61. private RectangleF GetSelectedRect()
  62. {
  63. RectangleF result = new RectangleF(100000, 100000, -100000, -100000);
  64. foreach (Base obj in Designer.SelectedObjects)
  65. {
  66. if (obj is ComponentBase)
  67. {
  68. ComponentBase c = obj as ComponentBase;
  69. if (c.Left < result.Left)
  70. result.X = c.Left;
  71. if (c.Right > result.Right)
  72. result.Width = c.Right - result.Left;
  73. float cTop = c is BandBase ? 0 : c.Top;
  74. if (cTop < result.Top)
  75. result.Y = cTop;
  76. float cBottom = c is BandBase ? c.Height : c.Bottom;
  77. if (cBottom > result.Bottom)
  78. result.Height = cBottom - result.Top;
  79. }
  80. }
  81. if (result.Top == 100000)
  82. result = new RectangleF();
  83. return result;
  84. }
  85. private void AddBand(BandBase band, BandCollection list)
  86. {
  87. if (band != null)
  88. {
  89. if (band.Child != null && band.Child.FillUnusedSpace)
  90. {
  91. AddBand(band.Child, list);
  92. list.Add(band);
  93. }
  94. else
  95. {
  96. list.Add(band);
  97. AddBand(band.Child, list);
  98. }
  99. }
  100. }
  101. private void EnumDataBand(DataBand band, BandCollection list)
  102. {
  103. if (band == null)
  104. return;
  105. AddBand(band.Header, list);
  106. AddBand(band, list);
  107. foreach (BandBase b in band.Bands)
  108. {
  109. EnumBand(b, list);
  110. }
  111. AddBand(band.Footer, list);
  112. }
  113. private void EnumGroupHeaderBand(GroupHeaderBand band, BandCollection list)
  114. {
  115. if (band == null)
  116. return;
  117. AddBand(band.Header, list);
  118. AddBand(band, list);
  119. EnumGroupHeaderBand(band.NestedGroup, list);
  120. EnumDataBand(band.Data, list);
  121. AddBand(band.GroupFooter, list);
  122. AddBand(band.Footer, list);
  123. }
  124. private void EnumBand(BandBase band, BandCollection list)
  125. {
  126. if (band is DataBand)
  127. EnumDataBand(band as DataBand, list);
  128. else if (band is GroupHeaderBand)
  129. EnumGroupHeaderBand(band as GroupHeaderBand, list);
  130. }
  131. private void EnumBands(BandCollection list)
  132. {
  133. if (Page.TitleBeforeHeader)
  134. {
  135. AddBand(Page.ReportTitle, list);
  136. AddBand(Page.PageHeader, list);
  137. }
  138. else
  139. {
  140. AddBand(Page.PageHeader, list);
  141. AddBand(Page.ReportTitle, list);
  142. }
  143. AddBand(Page.ColumnHeader, list);
  144. foreach (BandBase b in Page.Bands)
  145. {
  146. EnumBand(b, list);
  147. }
  148. AddBand(Page.ColumnFooter, list);
  149. AddBand(Page.ReportSummary, list);
  150. AddBand(Page.PageFooter, list);
  151. AddBand(Page.Overlay, list);
  152. }
  153. private void AdjustBands()
  154. {
  155. if (Page == null)
  156. return;
  157. BandCollection bands = new BandCollection();
  158. EnumBands(bands);
  159. float curY = ClassicView ? BandBase.HeaderSize : 0;
  160. float pageWidth = (Page.PaperWidth - Page.LeftMargin - Page.RightMargin) * Units.Millimeters;
  161. float columnWidth = Page.Columns.Width * Units.Millimeters;
  162. // lineup bands
  163. foreach (BandBase b in bands)
  164. {
  165. b.Left = 0;
  166. if (Page.Columns.Count > 1 && b.IsColumnDependentBand)
  167. b.Width = columnWidth;
  168. else
  169. b.Width = pageWidth;
  170. b.Top = curY;
  171. curY += b.Height + (ClassicView ? BandBase.HeaderSize : 4 / ZoomDpi);
  172. }
  173. // update size
  174. // since we are changing the size inside the OnPaint, avoid weird effects
  175. int width = (int)Math.Round(pageWidth * ZoomDpi) + 1;
  176. if (Page.ExtraDesignWidth)
  177. width *= 5;
  178. int height = (int)Math.Round(curY * ZoomDpi);
  179. if (ClassicView)
  180. height -= (int)Math.Round(BandBase.HeaderSize * ZoomDpi) - 4;
  181. workspaceSize = new Size(width, height);
  182. int _10 = this.LogicalToDevice(10);
  183. AutoScrollMinSize = new Size(width + _10 + SystemInformation.VerticalScrollBarWidth, height + _10 + SystemInformation.HorizontalScrollBarHeight);
  184. if (!mouseDown)
  185. AutoScrollPosition = AutoScrollPosition;
  186. }
  187. private void UpdateStatusBar()
  188. {
  189. RectangleF selectedRect = GetSelectedRect();
  190. bool emptyBounds = Designer.SelectedObjects.IsPageSelected || Designer.SelectedObjects.IsReportSelected ||
  191. (selectedRect.Width == 0 && selectedRect.Height == 0);
  192. #if false
  193. string location = emptyBounds ? "" :
  194. Converter.DecreasePrecision(selectedRect.Left, 2).ToString() + "; " +
  195. Converter.DecreasePrecision(selectedRect.Top, 2).ToString();
  196. string size = emptyBounds ? "" :
  197. Converter.DecreasePrecision(selectedRect.Width, 2).ToString() + "; " +
  198. Converter.DecreasePrecision(selectedRect.Height, 2).ToString();
  199. #else
  200. string location = emptyBounds ? "" :
  201. Converter.ToString(selectedRect.Left, typeof(UnitsConverter)) + "; " +
  202. Converter.ToString(selectedRect.Top, typeof(UnitsConverter));
  203. string size = emptyBounds ? "" :
  204. Converter.ToString(selectedRect.Width, typeof(UnitsConverter)) + "; " +
  205. Converter.ToString(selectedRect.Height, typeof(UnitsConverter));
  206. #endif
  207. string text = "";
  208. if (Designer.SelectedObjects.Count == 1)
  209. {
  210. Base obj = Designer.SelectedObjects[0];
  211. if (obj is TextObject)
  212. text = (obj as TextObject).Text;
  213. else if (obj is BandBase)
  214. text = (obj as BandBase).GetInfoText();
  215. }
  216. string locationRightBot = "";
  217. if (Designer.SelectedObjects.Count == 1 && Designer.SelectedObjects[0] is ReportComponentBase comp)
  218. {
  219. if (!(comp is BandBase) && comp.Parent is BandBase parentBand)
  220. locationRightBot = Converter.ToString(parentBand.Width - comp.Right, typeof(UnitsConverter)) + "; " +
  221. Converter.ToString(parentBand.Height - comp.Bottom, typeof(UnitsConverter));
  222. }
  223. Designer.ShowStatus(location, size, text, locationRightBot);
  224. }
  225. private void UpdateAutoGuides()
  226. {
  227. if (!AutoGuides)
  228. return;
  229. if (Page != null)
  230. Page.Guides.Clear();
  231. foreach (Base c in Designer.Objects)
  232. {
  233. if (c is BandBase)
  234. (c as BandBase).Guides.Clear();
  235. }
  236. foreach (Base c in Designer.Objects)
  237. {
  238. if (c is ReportComponentBase && !(c is BandBase))
  239. {
  240. ReportComponentBase obj = c as ReportComponentBase;
  241. float g = obj.AbsLeft;
  242. if (Page != null && !Page.Guides.Contains(g))
  243. Page.Guides.Add(g);
  244. g = obj.AbsRight;
  245. if (Page != null && !Page.Guides.Contains(g))
  246. Page.Guides.Add(g);
  247. BandBase band = obj.Band;
  248. if (band != null)
  249. {
  250. g = obj.AbsTop - band.AbsTop;
  251. if (!band.Guides.Contains(g))
  252. band.Guides.Add(g);
  253. g = obj.AbsBottom - band.AbsTop;
  254. if (!band.Guides.Contains(g))
  255. band.Guides.Add(g);
  256. }
  257. }
  258. }
  259. RulerPanel.HorzRuler.Refresh();
  260. RulerPanel.VertRuler.Refresh();
  261. }
  262. private void CreateTitlesForInsertedObjects(DictionaryWindow.DraggedItemCollection items)
  263. {
  264. if (items == null)
  265. return;
  266. bool changed = false;
  267. // try to create title for the inserted items
  268. for (int i = 0; i < items.Count; i++)
  269. {
  270. string text = items[i].text;
  271. Column column = items[i].obj as Column;
  272. ComponentBase insertedObject = Designer.SelectedObjects[i] as ComponentBase;
  273. if (insertedObject.Parent is DataBand)
  274. {
  275. DataBand dataBand = insertedObject.Parent as DataBand;
  276. // connect databand to data if not connected yet
  277. if (dataBand.DataSource == null && column != null)
  278. {
  279. // find a parent datasource for a column. Use the "text" which
  280. // contains full-qualified name of the column.
  281. dataBand.DataSource = DataHelper.GetDataSource(Report.Dictionary, text);
  282. changed = true;
  283. }
  284. // find a header where to insert the column title
  285. BandBase header = dataBand.Header;
  286. if (header == null)
  287. header = (dataBand.Page as ReportPage).PageHeader;
  288. if (header == null)
  289. header = (dataBand.Page as ReportPage).ColumnHeader;
  290. if (header != null)
  291. {
  292. // check for empty space on a header
  293. RectangleF newBounds = insertedObject.Bounds;
  294. newBounds.Inflate(-1, -1);
  295. newBounds.Y = 0;
  296. bool hasEmptySpace = true;
  297. foreach (ReportComponentBase obj in header.Objects)
  298. {
  299. if (obj.Bounds.IntersectsWith(newBounds))
  300. {
  301. hasEmptySpace = false;
  302. break;
  303. }
  304. }
  305. // create the title
  306. if (hasEmptySpace)
  307. {
  308. TextObject newObject = new TextObject();
  309. newObject.Bounds = insertedObject.Bounds;
  310. newObject.Top = 0;
  311. newObject.Parent = header;
  312. newObject.CreateUniqueName();
  313. if (column != null)
  314. text = column.Alias;
  315. newObject.Text = text;
  316. Designer.Objects.Add(newObject);
  317. // apply last formatting to the new object
  318. Designer.LastFormatting.SetFormatting(newObject);
  319. changed = true;
  320. }
  321. }
  322. }
  323. }
  324. if (changed)
  325. Designer.SetModified(null, "Change");
  326. }
  327. private void DrawSelectionRect(Graphics g)
  328. {
  329. RectangleF rect = NormalizeSelectionRect();
  330. Brush b = Report.GraphicCache.GetBrush(Color.FromArgb(80, SystemColors.Highlight));
  331. float scale = ZoomDpi;
  332. g.FillRectangle(b, rect.Left * scale, rect.Top * scale, rect.Width * scale, rect.Height * scale);
  333. Pen pen = Report.GraphicCache.GetPen(SystemColors.Highlight, 1, DashStyle.Dash);
  334. g.DrawRectangle(pen, rect.Left * scale, rect.Top * scale, rect.Width * scale, rect.Height * scale);
  335. }
  336. #endregion
  337. #region Protected Methods
  338. protected override float GridSnapSize
  339. {
  340. get { return Grid.SnapSize; }
  341. }
  342. protected override bool CheckGridStep()
  343. {
  344. bool al = SnapToGrid;
  345. if ((ModifierKeys & Keys.Alt) > 0)
  346. al = !al;
  347. bool result = true;
  348. float kx = eventArgs.delta.X;
  349. float ky = eventArgs.delta.Y;
  350. if (al)
  351. {
  352. result = kx >= GridSnapSize || kx <= -GridSnapSize || ky >= GridSnapSize || ky <= -GridSnapSize;
  353. if (result)
  354. {
  355. kx = (int)(kx / GridSnapSize) * GridSnapSize;
  356. ky = (int)(ky / GridSnapSize) * GridSnapSize;
  357. }
  358. }
  359. else
  360. {
  361. result = kx != 0 || ky != 0;
  362. }
  363. if (ShowGuides && !AutoGuides)
  364. Guides.CheckGuides(ref kx, ref ky);
  365. eventArgs.delta.X = kx;
  366. eventArgs.delta.Y = ky;
  367. return result;
  368. }
  369. protected override void OnPaint(PaintEventArgs e)
  370. {
  371. base.OnPaint(e);
  372. if (Locked)
  373. return;
  374. Graphics g = e.Graphics;
  375. if (Report == null)
  376. return;
  377. #if AVALONIA
  378. e.Graphics.FontScale = 1;
  379. #endif
  380. FRPaintEventArgs paintArgs = new FRPaintEventArgs(g, ZoomDpi, ZoomDpi, Report.GraphicCache);
  381. g.TranslateTransform(Offset.X, Offset.Y);
  382. g.SetClip(new Rectangle(0, 0, workspaceSize.Width, workspaceSize.Height));
  383. // check if workspace is active (in the mdi mode).
  384. ObjectCollection objects = Designer.Objects;
  385. if (Designer.ActiveReport != Report)
  386. {
  387. objects = Page.AllObjects;
  388. objects.Add(Page);
  389. }
  390. List<ReportComponentBase> intersectingObjects = new List<ReportComponentBase>();
  391. // draw bands
  392. foreach (Base obj in objects)
  393. {
  394. obj.SetDesigning(true);
  395. if (obj is BandBase band)
  396. {
  397. band.Draw(paintArgs);
  398. if (EventBandIndicator && eventIndicator.HaveToDraw(band))
  399. eventIndicator.DrawIndicator(band, paintArgs);
  400. if (EnableBacklightIntersectingObjects)
  401. {
  402. if (!mouseDown)
  403. Validator.GetIntersectingObjects(intersectingObjects, band);
  404. }
  405. }
  406. }
  407. // draw objects
  408. foreach (Base obj in objects)
  409. {
  410. if (obj is ComponentBase comp && !(obj is BandBase) && obj.HasFlag(Flags.CanDraw))
  411. {
  412. comp.Draw(paintArgs);
  413. if (EventObjectIndicator && eventIndicator.HaveToDraw(comp))
  414. eventIndicator.DrawIndicator(comp, paintArgs);
  415. }
  416. }
  417. // draw intersecting objects
  418. foreach (var obj in intersectingObjects)
  419. {
  420. obj.DrawIntersection(paintArgs);
  421. }
  422. // draw selection
  423. if (!mouseDown && Designer.ActiveReport == Report)
  424. {
  425. foreach (Base obj in Designer.SelectedObjects)
  426. {
  427. if (obj is ComponentBase comp && obj.HasFlag(Flags.CanDraw))
  428. comp.DrawSelection(paintArgs);
  429. }
  430. }
  431. // draw page margins in "ExtraDesignWidth" mode
  432. if (Page.ExtraDesignWidth)
  433. {
  434. float pageWidth = (Page.PaperWidth - Page.LeftMargin - Page.RightMargin) * Units.Millimeters * ZoomDpi;
  435. Pen pen = Report.GraphicCache.GetPen(Color.Red, 1, DashStyle.Dot);
  436. for (float x = pageWidth; x < Width; x += pageWidth)
  437. {
  438. g.DrawLine(pen, x, 0, x, Height);
  439. }
  440. }
  441. if (ShowGuides)
  442. Guides.Draw(g);
  443. virtualGuides.Draw(g);
  444. if (mode2 == WorkspaceMode2.SelectionRect)
  445. DrawSelectionRect(g);
  446. DrawToolTip(g);
  447. }
  448. protected override void ShowLocationSizeToolTip(int x, int y)
  449. {
  450. string s = "";
  451. RectangleF selectedRect = GetSelectedRect();
  452. if (eventArgs.activeObject is BandBase)
  453. selectedRect = new RectangleF(0, 0, eventArgs.activeObject.Width, eventArgs.activeObject.Height);
  454. if (mode2 == WorkspaceMode2.Move)
  455. {
  456. s = Converter.ToString(selectedRect.Left, typeof(UnitsConverter)) + "; " +
  457. Converter.ToString(selectedRect.Top, typeof(UnitsConverter));
  458. if (eventArgs != null && eventArgs.activeObject != null && eventArgs.activeObject.Parent != null && eventArgs.activeObject.Parent is BandBase)
  459. s += " | " +
  460. Converter.ToString((eventArgs.activeObject.Parent as BandBase).Width - selectedRect.Right, typeof(UnitsConverter)) + "; " +
  461. Converter.ToString((eventArgs.activeObject.Parent as BandBase).Height - selectedRect.Bottom, typeof(UnitsConverter));
  462. }
  463. else if (mode2 == WorkspaceMode2.Size)
  464. {
  465. s = Converter.ToString(selectedRect.Width, typeof(UnitsConverter)) + "; " +
  466. Converter.ToString(selectedRect.Height, typeof(UnitsConverter));
  467. }
  468. ShowToolTip(s, x, y);
  469. }
  470. protected override void Refresh1()
  471. {
  472. // if active object is band (we are resizing it), update the band structure and vertical ruler
  473. if (eventArgs.activeObject is BandBase)
  474. UpdateBands();
  475. else
  476. {
  477. Refresh();
  478. if (EnableBacklight)
  479. RulerPanel.VertRuler.Refresh();
  480. }
  481. }
  482. protected override void Refresh2()
  483. {
  484. UpdateBands();
  485. }
  486. protected override void OnKeyDown(KeyEventArgs e)
  487. {
  488. base.OnKeyDown(e);
  489. switch (e.KeyCode)
  490. {
  491. case Keys.Add:
  492. ZoomIn();
  493. break;
  494. case Keys.Subtract:
  495. ZoomOut();
  496. break;
  497. }
  498. foreach (KeyValuePair<string, Keys> shorcut in Config.Shortcuts)
  499. {
  500. if (shorcut.Value == e.KeyData)
  501. {
  502. switch (shorcut.Key)
  503. {
  504. case "Editing,Bold":
  505. if (Designer.SelectedTextObjects.Count > 0)
  506. Designer.SelectedTextObjects.ToggleFontStyle(FontStyle.Bold,
  507. !Designer.SelectedTextObjects.First.Font.Bold);
  508. break;
  509. case "Editing,Italic":
  510. if (Designer.SelectedTextObjects.Count > 0)
  511. Designer.SelectedTextObjects.ToggleFontStyle(FontStyle.Italic,
  512. !Designer.SelectedTextObjects.First.Font.Italic);
  513. break;
  514. case "Editing,Underline":
  515. if (Designer.SelectedTextObjects.Count > 0)
  516. Designer.SelectedTextObjects.ToggleFontStyle(FontStyle.Underline,
  517. !Designer.SelectedTextObjects.First.Font.Underline);
  518. break;
  519. }
  520. }
  521. }
  522. }
  523. protected override void OnMouseWheel(MouseEventArgs e)
  524. {
  525. if (Locked)
  526. return;
  527. if ((ModifierKeys & Keys.Control) != 0)
  528. {
  529. float oldZoom = zoom;
  530. if (e.Delta > 0)
  531. zoom += 0.25f;
  532. else if (e.Delta < 0)
  533. zoom -= 0.25f;
  534. if (zoom < 0.25f)
  535. zoom = 0.25f;
  536. if (zoom > 8)
  537. zoom = 8;
  538. float delta = zoom / oldZoom;
  539. AutoScrollPosition = new Point((int)((AutoScrollPosition.X - e.X) * delta) + e.X, (int)((AutoScrollPosition.Y - e.Y) * delta) + e.Y);
  540. Designer.UpdatePlugins(null);
  541. }
  542. else if (ModifierKeys == Keys.Shift)
  543. {
  544. AutoScrollPosition = new Point(AutoScrollPosition.X + e.Delta, AutoScrollPosition.Y);
  545. }
  546. else
  547. {
  548. eventArgs.wheelDelta = e.Delta;
  549. eventArgs.handled = false;
  550. // serve all objects
  551. foreach (Base c in Designer.Objects)
  552. {
  553. if (c is ComponentBase)
  554. {
  555. (c as ComponentBase).HandleMouseWheel(eventArgs);
  556. if (eventArgs.handled)
  557. {
  558. Refresh();
  559. return;
  560. }
  561. }
  562. }
  563. base.OnMouseWheel(e);
  564. #if !MONO
  565. DoMouseWheel(e);
  566. #endif
  567. }
  568. }
  569. protected override void OnDragOver(DragEventArgs drgevent)
  570. {
  571. base.OnDragOver(drgevent);
  572. if (!Designer.cmdInsert.Enabled)
  573. {
  574. drgevent.Effect = DragDropEffects.None;
  575. return;
  576. }
  577. if (mode1 != WorkspaceMode1.DragDrop)
  578. {
  579. eventArgs.dragSources = null;
  580. DictionaryWindow.DraggedItemCollection draggedItems = DictionaryWindow.DragUtils.GetAll(drgevent);
  581. if (draggedItems == null || draggedItems.Count == 0)
  582. {
  583. if (drgevent.Data.GetDataPresent(DataFormats.FileDrop))
  584. {
  585. object obj = drgevent.Data.GetData(DataFormats.FileDrop);
  586. if (obj != null)
  587. {
  588. string[] fileNames = obj as string[];
  589. string fileName = fileNames[0];
  590. string path = Path.GetExtension(fileName).ToString().ToLower();
  591. // determine type of object to insert
  592. Type objectType = null;
  593. if (path == ".txt")
  594. {
  595. objectType = typeof(TextObject);
  596. }
  597. else if (path == ".rtf")
  598. {
  599. objectType = typeof(RichObject);
  600. }
  601. else if (path == ".png" || path == ".jpg" || path == ".gif" || path == ".jpeg" || path == ".ico" ||
  602. path == ".bmp" || path == ".tif" || path == ".tiff" || path == ".emf" || path == ".wmf")
  603. {
  604. objectType = typeof(PictureObject);
  605. }
  606. if (objectType == null)
  607. {
  608. drgevent.Effect = DragDropEffects.None;
  609. return;
  610. }
  611. // do insertion
  612. Designer.InsertObject(RegisteredObjects.FindObject(objectType), InsertFrom.Dictionary);
  613. // load content from a file
  614. Base insertedObj = Designer.SelectedObjects[0];
  615. if (insertedObj is TextObject)
  616. {
  617. (insertedObj as TextObject).Text = File.ReadAllText(fileName);
  618. }
  619. else if (insertedObj is RichObject)
  620. {
  621. (insertedObj as RichObject).Text = File.ReadAllText(fileName);
  622. }
  623. else if (insertedObj is PictureObject)
  624. {
  625. try
  626. {
  627. (insertedObj as PictureObject).Image = ImageHelper.LoadFromFile(fileName);
  628. }
  629. catch (Exception ex)
  630. {
  631. FRMessageBox.Error(ex.Message);
  632. }
  633. }
  634. eventArgs.DragSource = insertedObj as ComponentBase;
  635. }
  636. else
  637. {
  638. drgevent.Effect = DragDropEffects.None;
  639. return;
  640. }
  641. }
  642. else if (drgevent.Data.GetDataPresent(DataFormats.Text))
  643. {
  644. byte[] imgData = new byte[0];
  645. string text = "";
  646. Type objectType = null;
  647. string file = (string)drgevent.Data.GetData(DataFormats.UnicodeText, false);
  648. {
  649. bool isImage = false;
  650. Uri uri = new Uri("https://www.fastreport.ru/");
  651. if (Uri.TryCreate(file, UriKind.Absolute, out uri))
  652. {
  653. // link can be not image path
  654. try
  655. {
  656. ServicePointManager.SecurityProtocol = (SecurityProtocolType)(0xc0 | 0x300 | 0xc00);
  657. using (WebClient client = new WebClient())
  658. {
  659. ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
  660. using (Stream stream = client.OpenRead(uri.AbsoluteUri))
  661. using (Bitmap bmp = new Bitmap(stream))
  662. {
  663. if (bmp != null)
  664. {
  665. using (MemoryStream tempImgStream = new MemoryStream())
  666. {
  667. bmp.Save(tempImgStream, bmp.GetImageFormat());
  668. imgData = tempImgStream.ToArray();
  669. }
  670. objectType = typeof(PictureObject);
  671. isImage = true;
  672. }
  673. }
  674. }
  675. }
  676. catch { }
  677. }
  678. if (!isImage)
  679. {
  680. text = file;
  681. objectType = typeof(TextObject);
  682. }
  683. }
  684. // do insertion
  685. Designer.InsertObject(RegisteredObjects.FindObject(objectType), InsertFrom.Dictionary);
  686. // load content from a file
  687. Base insertedObj = Designer.SelectedObjects[0];
  688. if (insertedObj is TextObject)
  689. {
  690. (insertedObj as TextObject).Text = text;
  691. }
  692. else if (insertedObj is PictureObject)
  693. {
  694. (insertedObj as PictureObject).Image = ImageHelper.Load(imgData);
  695. }
  696. eventArgs.DragSource = insertedObj as ComponentBase;
  697. }
  698. }
  699. else
  700. {
  701. ObjectInfo[] infos = new ObjectInfo[draggedItems.Count];
  702. for (int i = 0; i < draggedItems.Count; i++)
  703. {
  704. Type objType = typeof(TextObject);
  705. if (draggedItems[i].obj is Column)
  706. {
  707. Column c = draggedItems[i].obj as Column;
  708. objType = c.GetBindableControlType();
  709. }
  710. infos[i] = RegisteredObjects.FindObject(objType);
  711. }
  712. Designer.InsertObject(infos, InsertFrom.Dictionary);
  713. List<ComponentBase> dragSources = new List<ComponentBase>();
  714. if (Designer.SelectedObjects.Count == draggedItems.Count)
  715. {
  716. for (int i = 0; i < Designer.SelectedObjects.Count; i++)
  717. {
  718. ComponentBase obj = Designer.SelectedObjects[i] as ComponentBase;
  719. DictionaryWindow.DraggedItem item = draggedItems[i];
  720. if (obj == null || item == null)
  721. continue;
  722. if (obj is TextObject)
  723. {
  724. TextObject textObj = obj as TextObject;
  725. textObj.Text = textObj.GetTextWithBrackets(item.text);
  726. if (item.obj is Column)
  727. {
  728. Column c = item.obj as Column;
  729. if (c.DataType == typeof(float) || c.DataType == typeof(double) || c.DataType == typeof(decimal))
  730. {
  731. textObj.HorzAlign = HorzAlign.Right;
  732. textObj.WordWrap = false;
  733. textObj.Trimming = StringTrimming.EllipsisCharacter;
  734. }
  735. textObj.Format = c.GetFormat();
  736. }
  737. }
  738. else if (obj is PictureObject)
  739. {
  740. (obj as PictureObject).DataColumn = item.text;
  741. }
  742. else if (obj is CheckBoxObject)
  743. {
  744. (obj as CheckBoxObject).DataColumn = item.text;
  745. }
  746. dragSources.Add(obj);
  747. }
  748. }
  749. eventArgs.dragSources = dragSources.ToArray();
  750. }
  751. }
  752. if (eventArgs.dragSources == null || eventArgs.dragSources.Length == 0)
  753. {
  754. // avoid bugs when dragging from ReportTree
  755. drgevent.Effect = DragDropEffects.None;
  756. return;
  757. }
  758. mode1 = WorkspaceMode1.DragDrop;
  759. Point pt = PointToClient(new Point(drgevent.X, drgevent.Y));
  760. OnMouseMove(new MouseEventArgs(MouseButtons.Left, 0, pt.X, pt.Y, 0));
  761. drgevent.Effect = drgevent.AllowedEffect;
  762. }
  763. protected override void OnDragDrop(DragEventArgs drgevent)
  764. {
  765. base.OnDragDrop(drgevent);
  766. Point pt = PointToClient(new Point(drgevent.X, drgevent.Y));
  767. OnMouseUp(new MouseEventArgs(MouseButtons.Left, 0, pt.X, pt.Y, 0));
  768. if (eventArgs.dragSources != null && eventArgs.dragSources.Length > 0)
  769. {
  770. DictionaryWindow.DraggedItemCollection items = DictionaryWindow.DragUtils.GetAll(drgevent);
  771. if (items == null)
  772. return;
  773. CreateTitlesForInsertedObjects(items);
  774. items.Clear();
  775. }
  776. }
  777. protected override void OnDragLeave(EventArgs e)
  778. {
  779. base.OnDragLeave(e);
  780. CancelPaste();
  781. }
  782. #endregion
  783. #region Public Methods
  784. public override float GetScale()
  785. {
  786. return ZoomDpi;
  787. }
  788. protected override Base GetParentForPastedObjects()
  789. {
  790. BandCollection bands = new BandCollection();
  791. EnumBands(bands);
  792. return bands[0];
  793. }
  794. public override void Paste(ObjectCollection list, InsertFrom source)
  795. {
  796. base.Paste(list, source);
  797. // find left-top edge of pasted objects
  798. float minLeft = 100000;
  799. float minTop = 100000;
  800. foreach (Base c in list)
  801. {
  802. if (c is ComponentBase)
  803. {
  804. ComponentBase c1 = c as ComponentBase;
  805. if (c1.Left < minLeft)
  806. minLeft = c1.Left;
  807. if (c1.Top < minTop)
  808. minTop = c1.Top;
  809. }
  810. }
  811. foreach (Base c in list)
  812. {
  813. // correct the left-top
  814. if (c is ComponentBase)
  815. {
  816. ComponentBase c1 = c as ComponentBase;
  817. c1.Left -= minLeft + Grid.SnapSize * 1000;
  818. c1.Top -= minTop + Grid.SnapSize * 1000;
  819. if (c1.Width == 0 && c1.Height == 0)
  820. {
  821. SizeF preferredSize = c1.GetPreferredSize();
  822. c1.Width = preferredSize.Width;
  823. c1.Height = preferredSize.Height;
  824. if (SnapToGrid)
  825. {
  826. c1.Width = (int)Math.Round(c1.Width / Grid.SnapSize) * Grid.SnapSize;
  827. c1.Height = (int)Math.Round(c1.Height / Grid.SnapSize) * Grid.SnapSize;
  828. }
  829. }
  830. }
  831. }
  832. mode1 = WorkspaceMode1.Insert;
  833. mode2 = WorkspaceMode2.Move;
  834. eventArgs.activeObject = null;
  835. int addSize = 0;
  836. if (ClassicView)
  837. addSize = BandBase.HeaderSize;
  838. OnMouseDown(new MouseEventArgs(MouseButtons.Left, 0,
  839. 10 - (int)(Grid.SnapSize * 1000 * ZoomDpi) + Offset.X,
  840. 10 + addSize - (int)(Grid.SnapSize * 1000 * ZoomDpi) + Offset.Y, 0));
  841. }
  842. public void UpdateBands()
  843. {
  844. Refresh();
  845. RulerPanel.VertRuler.Refresh();
  846. RulerPanel.Structure.Refresh();
  847. }
  848. public override void Refresh()
  849. {
  850. // FR.Net issue with PanelX: called from constructor when PageDesigner is not set yet
  851. if (PageDesigner == null)
  852. return;
  853. AdjustBands();
  854. UpdateStatusBar();
  855. UpdateAutoGuides();
  856. base.Refresh();
  857. }
  858. public void DeleteHGuides()
  859. {
  860. foreach (Base c in Designer.Objects)
  861. {
  862. if (c is BandBase)
  863. (c as BandBase).Guides.Clear();
  864. }
  865. Refresh();
  866. RulerPanel.VertRuler.Refresh();
  867. Designer.SetModified(PageDesigner, "DeleteHGuides");
  868. }
  869. public void DeleteVGuides()
  870. {
  871. Page.Guides.Clear();
  872. Refresh();
  873. RulerPanel.HorzRuler.Refresh();
  874. Designer.SetModified(PageDesigner, "DeleteVGuides");
  875. }
  876. public void DoZoom(float zoom)
  877. {
  878. if (zoomLock)
  879. return;
  880. zoomLock = true;
  881. try
  882. {
  883. this.zoom = zoom;
  884. Designer.UpdatePlugins(null);
  885. }
  886. finally
  887. {
  888. zoomLock = false;
  889. AutoScrollPosition = AutoScrollPosition;
  890. Refresh();
  891. }
  892. }
  893. public void ZoomIn()
  894. {
  895. float zoom = Zoom;
  896. zoom += 0.25f;
  897. if (zoom > 8f)
  898. zoom = 8f;
  899. DoZoom(zoom);
  900. }
  901. public void ZoomOut()
  902. {
  903. float zoom = Zoom;
  904. zoom -= 0.25f;
  905. if (zoom < 0.25f)
  906. zoom = 0.25f;
  907. DoZoom(zoom);
  908. }
  909. public void FitPageWidth()
  910. {
  911. float actualWidth = WorkspaceSize.Width / Zoom;
  912. DoZoom((Width - 10 - SystemInformation.VerticalScrollBarWidth) / actualWidth);
  913. }
  914. public void FitWholePage()
  915. {
  916. float actualWidth = WorkspaceSize.Width / Zoom;
  917. float actualHeight = WorkspaceSize.Height / Zoom;
  918. float scaleX = (Width - 10 - SystemInformation.VerticalScrollBarWidth) / actualWidth;
  919. float scaleY = (Height - 10 - SystemInformation.HorizontalScrollBarHeight) / actualHeight;
  920. DoZoom(scaleX < scaleY ? scaleX : scaleY);
  921. }
  922. public void SelectAll()
  923. {
  924. Base parent = null;
  925. if (Designer.SelectedObjects.Count == 0)
  926. return;
  927. if (Designer.SelectedObjects[0] is Report || Designer.SelectedObjects[0] is PageBase ||
  928. Designer.SelectedObjects[0].Report == null)
  929. parent = Page;
  930. else if (Designer.SelectedObjects[0] is BandBase)
  931. parent = Designer.SelectedObjects[0];
  932. else
  933. {
  934. parent = Designer.SelectedObjects[0];
  935. while (parent != null && !(parent is BandBase))
  936. {
  937. parent = parent.Parent;
  938. }
  939. }
  940. Designer.SelectedObjects.Clear();
  941. if (parent is PageBase)
  942. {
  943. // if page is selected, select all bands on the page
  944. foreach (Base c in parent.AllObjects)
  945. {
  946. if (c is BandBase)
  947. Designer.SelectedObjects.Add(c);
  948. }
  949. }
  950. else if (parent is BandBase)
  951. {
  952. // if band is selected, select all objects on the band. Do not select sub-bands.
  953. foreach (Base c in parent.ChildObjects)
  954. {
  955. if (!(c is BandBase))
  956. Designer.SelectedObjects.Add(c);
  957. }
  958. }
  959. if (Designer.SelectedObjects.Count == 0)
  960. Designer.SelectedObjects.Add(parent);
  961. Designer.SelectionChanged(null);
  962. }
  963. #endregion
  964. internal ReportWorkspace(ReportPageDesigner pageDesigner)
  965. : base(pageDesigner)
  966. {
  967. #if AVALONIA
  968. PaintOnRenderThread = Config.AvaloniaPaintOnRenderThread;
  969. #endif
  970. guides = new Guides(this);
  971. eventIndicator = new EventIndicator();
  972. Size = new Size(1, 1);
  973. }
  974. static ReportWorkspace()
  975. {
  976. var storage = new StorageService("Designer,Report");
  977. Grid.RestoreState(storage);
  978. ShowGrid = storage.GetBool("ShowGrid", true);
  979. SnapToGrid = storage.GetBool("SnapToGrid", true);
  980. MarkerStyle = storage.GetEnum("MarkerStyle", MarkerStyle.Corners);
  981. AutoGuides = storage.GetBool("AutoGuides");
  982. ClassicView = storage.GetBool("ClassicView");
  983. EditAfterInsert = storage.GetBool("EditAfterInsert");
  984. ShowGuides = true;
  985. EventObjectIndicator = storage.GetBool("EventObjectIndicator");
  986. EventBandIndicator = storage.GetBool("EventBandIndicator");
  987. EnableBacklight = storage.GetBool("EnableBacklight");
  988. SimplifyDBFields = storage.GetBool("SimplifyDBFields");
  989. EnableBacklightIntersectingObjects = storage.GetBool("EnableBacklightIntersectingObjects");
  990. }
  991. }
  992. }