ReportTreeWindow.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows.Forms;
  4. using System.Drawing;
  5. using FastReport.Utils;
  6. using FastReport.Controls;
  7. namespace FastReport.Design.ToolWindows
  8. {
  9. /// <summary>
  10. /// Represents the "Report Tree" window.
  11. /// </summary>
  12. public class ReportTreeWindow : FilterableToolWindow
  13. {
  14. #region Fields
  15. //private TreeView tree;
  16. private Button collapseExpButton = new Button();
  17. private List<Base> components;
  18. private List<TreeNode> nodes;
  19. private List<TreeNode> nodesSelected;
  20. private TreeNode nodeTree;
  21. private int lastFromitem;
  22. private int lastToitem;
  23. private bool lastNeedReverse;
  24. private bool updating;
  25. private bool LastData;
  26. private bool passSelection = false;
  27. private bool cancelNextSelection = false;
  28. private bool ShiftNonSelect = false;
  29. private bool RewriteSelect = false;
  30. private bool mouseButtonRight = false;
  31. #endregion
  32. #region Private Methods
  33. protected override void UpdateTree()
  34. {
  35. // if there was no changes in the report structure, do nothing
  36. if (Designer.ActiveReport != null && tree.Nodes.Count > 0)
  37. {
  38. if (CheckChanges(Designer.ActiveReport, tree.Nodes[0]))
  39. return;
  40. }
  41. updating = true;
  42. tree.BeginUpdate();
  43. tree.Nodes.Clear();
  44. components.Clear();
  45. nodes.Clear();
  46. if (Designer.ActiveReport != null)
  47. EnumComponents(Designer.ActiveReport, tree.Nodes);
  48. tree.ExpandAll();
  49. tree.EndUpdate();
  50. updating = false;
  51. }
  52. private void UpdateSelection()
  53. {
  54. if (updating)
  55. return;
  56. if (Designer.SelectedObjects == null || Designer.SelectedObjects.Count == 0)
  57. return;
  58. Base c = Designer.SelectedObjects[Designer.SelectedObjects.Count - 1];
  59. int i = components.IndexOf(c);
  60. if (i != -1)
  61. {
  62. unpaintSelectedNodes();
  63. updating = true;
  64. tree.SelectedNode = nodes[i];
  65. nodesSelected.Clear();
  66. foreach (Base b in Designer.SelectedObjects)
  67. {
  68. nodesSelected.Add(nodes[components.IndexOf(b)]);
  69. }
  70. updating = false;
  71. paintSelectedNodes();
  72. }
  73. }
  74. void paintSelectedNodes()
  75. {
  76. Color backColor = SystemColors.Highlight;
  77. Color foreColor = SystemColors.HighlightText;
  78. foreach (TreeNode node in nodesSelected)
  79. {
  80. node.BackColor = backColor;
  81. node.ForeColor = foreColor;
  82. }
  83. }
  84. void unpaintSelectedNodes()
  85. {
  86. foreach (TreeNode node in nodesSelected)
  87. {
  88. node.BackColor = tree.BackColor;
  89. node.ForeColor = tree.ForeColor;
  90. }
  91. }
  92. private void EnumComponents(Base rootComponent, TreeNodeCollection rootNode)
  93. {
  94. string name = rootComponent is Report ?
  95. "Report - " + Designer.ActiveReportTab.ReportName : rootComponent.Name;
  96. TreeNode node = rootNode.Add(name);
  97. node.Tag = rootComponent;
  98. components.Add(rootComponent);
  99. nodes.Add(node);
  100. ObjectInfo objItem = RegisteredObjects.FindObject(rootComponent);
  101. if (objItem != null)
  102. {
  103. int imageIndex = objItem.ImageIndex;
  104. node.ImageIndex = imageIndex;
  105. node.SelectedImageIndex = imageIndex;
  106. }
  107. if (rootComponent.HasFlag(Flags.CanShowChildrenInReportTree))
  108. {
  109. foreach (Base component in rootComponent.ChildObjects)
  110. EnumComponents(component, node.Nodes);
  111. }
  112. }
  113. private bool CheckChanges(Base rootComponent, TreeNode rootNode)
  114. {
  115. if (rootNode.Tag != rootComponent)
  116. return false;
  117. if (!(rootComponent is Report))
  118. {
  119. if (rootNode.Text != rootComponent.Name)
  120. return false;
  121. }
  122. if (!rootComponent.HasFlag(Flags.CanShowChildrenInReportTree))
  123. return true;
  124. ObjectCollection childObjects = rootComponent.ChildObjects;
  125. if (childObjects.Count != rootNode.Nodes.Count)
  126. return false;
  127. for (int i = 0; i < childObjects.Count; i++)
  128. {
  129. if (!CheckChanges(childObjects[i], rootNode.Nodes[i]))
  130. return false;
  131. }
  132. return true;
  133. }
  134. private void tree_AfterSelect(object sender, TreeViewEventArgs e)
  135. {
  136. if (passSelection)
  137. return;
  138. if (updating)
  139. return;
  140. if (Designer.SelectedObjects != null)
  141. {
  142. if (Control.ModifierKeys == Keys.Control && !mouseButtonRight)
  143. {
  144. if (Designer.SelectedObjects[0] is BandBase || Designer.SelectedObjects[0] is ReportPage)
  145. {
  146. Designer.SelectedObjects.Clear();
  147. }
  148. if (Designer.SelectedObjects.Contains(e.Node.Tag as Base))
  149. {
  150. Designer.SelectedObjects.Remove(e.Node.Tag as Base);
  151. LastData = false;
  152. Designer.SelectionChanged(this);
  153. UpdateSelection();
  154. return;
  155. }
  156. else
  157. {
  158. if (e.Node.Tag is BandBase)
  159. {
  160. return;
  161. }
  162. Designer.SelectedObjects.Add(e.Node.Tag as Base);
  163. nodeTree = e.Node;
  164. LastData = false;
  165. Designer.SelectionChanged(this);
  166. UpdateSelection();
  167. return;
  168. }
  169. }
  170. Base c = e.Node.Tag as Base;
  171. if (Control.ModifierKeys == Keys.Shift)
  172. {
  173. if (nodeTree != null && isSameLevel(nodeTree, e.Node))
  174. {
  175. List<TreeNode> nodeBas = nodes;
  176. int nodeTreeIndex = getNodeIndexInNodes(nodeTree);
  177. int eNodeTreeIndex = getNodeIndexInNodes(e.Node);
  178. int from = Math.Min(nodeTreeIndex, eNodeTreeIndex);
  179. int to = Math.Max(nodeTreeIndex, eNodeTreeIndex);
  180. bool needReverse = nodeTreeIndex > eNodeTreeIndex;
  181. if (!(c is Report))
  182. Designer.ActiveReportTab.ActivePage = c.Page;
  183. if (RewriteSelect)
  184. {
  185. Designer.SelectedObjects.Clear();
  186. RewriteSelect = false;
  187. }
  188. if (from == lastFromitem && LastData)
  189. {
  190. if (to < lastToitem)
  191. {
  192. Designer.SelectedObjects.Clear();
  193. for (int i = from; i <= to; i++)
  194. {
  195. if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
  196. {
  197. continue;
  198. }
  199. Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
  200. }
  201. }
  202. else
  203. {
  204. for (int i = lastToitem + 1; i <= to; i++)
  205. {
  206. if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
  207. {
  208. continue;
  209. }
  210. Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
  211. }
  212. }
  213. }
  214. if (to == lastToitem && LastData)
  215. {
  216. if (needReverse)
  217. {
  218. if (from > lastFromitem)
  219. {
  220. Designer.SelectedObjects.Clear();
  221. for (int i = to; i >= from; i--)
  222. {
  223. if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
  224. {
  225. continue;
  226. }
  227. Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
  228. }
  229. }
  230. else
  231. {
  232. for (int i = lastFromitem - 1; i >= from; i--)
  233. {
  234. if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
  235. continue;
  236. Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
  237. }
  238. }
  239. }
  240. }
  241. if (LastData == false || lastNeedReverse != needReverse)
  242. {
  243. Designer.SelectedObjects.Clear();
  244. if (needReverse)
  245. {
  246. for (int i = to; i >= from; i--)
  247. {
  248. if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
  249. continue;
  250. Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
  251. }
  252. }
  253. else
  254. {
  255. for (int i = from; i <= to; i++)
  256. {
  257. if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report)
  258. continue;
  259. Designer.SelectedObjects.Add(nodeBas[i].Tag as Base);
  260. }
  261. }
  262. }
  263. if (Designer.SelectedObjects.Count == 0)
  264. {
  265. Designer.SelectedObjects.Add(nodeTree.Tag as Base);
  266. tree.SelectedNode = nodeTree;
  267. RewriteSelect = true;
  268. }
  269. LastData = true;
  270. lastFromitem = from;
  271. lastToitem = to;
  272. lastNeedReverse = needReverse;
  273. tree.SelectedNode = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 1]))];
  274. Designer.SelectionChanged(this);
  275. UpdateSelection();
  276. }
  277. }
  278. else
  279. {
  280. LastData = false;
  281. updating = true;
  282. if (!(c is Report))
  283. Designer.ActiveReportTab.ActivePage = c.Page;
  284. updating = false;
  285. nodeTree = e.Node;
  286. Designer.SelectedObjects.Clear();
  287. Designer.SelectedObjects.Add(c);
  288. Designer.SelectionChanged(null);
  289. }
  290. }
  291. }
  292. private int getNodeIndexInNodes(TreeNode node1)
  293. {
  294. int i = 0;
  295. foreach (TreeNode itemNode in nodes)
  296. {
  297. if (itemNode == node1)
  298. {
  299. return i;
  300. }
  301. i++;
  302. }
  303. return 0;
  304. }
  305. private bool isSameLevel(TreeNode node1, TreeNode node2)
  306. {
  307. foreach (TreeNode element in nodes)
  308. {
  309. if (element == node2)
  310. {
  311. return true;
  312. }
  313. }
  314. return false;
  315. }
  316. private void tree_ItemDrag(object sender, ItemDragEventArgs e)
  317. {
  318. SelectedObjectCollection draggedComponent = Designer.SelectedObjects;
  319. foreach (Base itemDragComp in draggedComponent)
  320. {
  321. if (itemDragComp is ComponentBase &&
  322. (itemDragComp.IsAncestor || itemDragComp.HasFlag(Flags.CanChangeParent)))
  323. {
  324. tree.DoDragDrop(draggedComponent, DragDropEffects.Move);
  325. }
  326. else
  327. {
  328. tree.DoDragDrop(draggedComponent, DragDropEffects.None);
  329. }
  330. }
  331. }
  332. private void tree_DragDrop(object sender, DragEventArgs e)
  333. {
  334. TreeNode targetNode = tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y)));
  335. Base targetComponent = targetNode.Tag as Base;
  336. // cases:
  337. // - target can contain dragged. Just change parent.
  338. // - target cannot contain dragged. Change creation order (Z-order).
  339. foreach (Base item in Designer.SelectedObjects)
  340. {
  341. if (targetComponent is IParent && (targetComponent as IParent).CanContain(item))
  342. {
  343. item.Parent = targetComponent;
  344. }
  345. else
  346. {
  347. Base parent = targetComponent.Parent;
  348. item.Parent = parent;
  349. item.ZOrder = targetComponent.ZOrder;
  350. }
  351. }
  352. // update all designer plugins (this one too)
  353. Designer.SetModified(null, "ChangeParent");
  354. Base b = Designer.SelectedObjects[Designer.SelectedObjects.Count - 1];
  355. int i = components.IndexOf(b);
  356. nodeTree = nodes[i];
  357. UpdateSelection();
  358. }
  359. private void tree_DragOver(object sender, DragEventArgs e)
  360. {
  361. List<TreeNode> draggedNode = (List<TreeNode>)e.Data.GetData(typeof(List<TreeNode>));
  362. TreeNode targetNode = (tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y))));
  363. if (targetNode == null)
  364. {
  365. return;
  366. }
  367. SelectedObjectCollection draggedComponent = Designer.SelectedObjects;
  368. Base targetComponent = targetNode.Tag as Base;
  369. // allowed moves are:
  370. // - target is not dragged
  371. // - target is not child of dragged
  372. // - target can contain dragged, or
  373. // parent of target can contain dragged
  374. foreach (Base itemDragComp in draggedComponent)
  375. {
  376. if (itemDragComp != targetComponent &&
  377. !targetComponent.HasParent(itemDragComp) &&
  378. (((targetComponent is IParent) && (targetComponent as IParent).CanContain(itemDragComp) ||
  379. (targetComponent.Parent != null && (targetComponent.Parent as IParent).CanContain(itemDragComp)))))
  380. {
  381. e.Effect = e.AllowedEffect;
  382. }
  383. else
  384. {
  385. e.Effect = DragDropEffects.None;
  386. }
  387. }
  388. // disable the Designer.OnSelectionChanged
  389. updating = true;
  390. tree.SelectedNode = targetNode;
  391. updating = false;
  392. }
  393. private void tree_KeyDown(object sender, KeyEventArgs e)
  394. {
  395. if (e.KeyCode == Keys.Delete)
  396. Designer.cmdDelete.Invoke();
  397. }
  398. private void tree_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
  399. {
  400. if (Designer.SelectedObjects.Count == 1 && Control.ModifierKeys == Keys.None)
  401. {
  402. Base c = e.Node.Tag as Base;
  403. if (c is Report)
  404. e.CancelEdit = false;
  405. }
  406. else
  407. {
  408. e.CancelEdit = true;
  409. }
  410. }
  411. private void tree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
  412. {
  413. if (Designer.SelectedObjects.Count == 1 && Control.ModifierKeys == Keys.None)
  414. {
  415. if (e.Label != null)
  416. {
  417. Base c = e.Node.Tag as Base;
  418. string saveName = c.Name;
  419. try
  420. {
  421. c.Name = e.Label;
  422. Designer.SetModified(this, "Change");
  423. }
  424. catch (Exception ex)
  425. {
  426. FRMessageBox.Error(ex.Message);
  427. e.CancelEdit = true;
  428. }
  429. }
  430. }
  431. else
  432. {
  433. e.CancelEdit = true;
  434. }
  435. }
  436. private void FTree_MouseUp(object sender, TreeNodeMouseClickEventArgs e)
  437. {
  438. if (e.Button == MouseButtons.Right)
  439. {
  440. mouseButtonRight = true;
  441. }
  442. else
  443. {
  444. mouseButtonRight = false;
  445. }
  446. if (Control.ModifierKeys == Keys.Control && e.Button != MouseButtons.Right)
  447. {
  448. if (e.Node.Tag is BandBase || e.Node.Tag is ReportPage || e.Node.Tag is Report)
  449. {
  450. ShiftNonSelect = true;
  451. Designer.SelectionChanged(this);
  452. UpdateSelection();
  453. cancelNextSelection = true;
  454. return;
  455. }
  456. if (tree.SelectedNode == e.Node && Designer.SelectedObjects.Count > 1 && Designer.SelectedObjects.Contains(e.Node.Tag as Base))
  457. {
  458. passSelection = true;
  459. tree.SelectedNode = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 2]))];
  460. nodeTree = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 2]))];
  461. LastData = false;
  462. passSelection = false;
  463. Designer.SelectedObjects.Remove(e.Node.Tag as Base);
  464. Designer.SelectionChanged(this);
  465. UpdateSelection();
  466. cancelNextSelection = true;
  467. }
  468. return;
  469. }
  470. else
  471. {
  472. if (Designer.SelectedObjects.Count > 1 && e.Node == tree.SelectedNode && e.Button != MouseButtons.Right)
  473. {
  474. Designer.SelectedObjects.Clear();
  475. Designer.SelectedObjects.Add(e.Node.Tag as Base);
  476. nodeTree = e.Node;
  477. LastData = false;
  478. Designer.SelectionChanged(null);
  479. UpdateSelection();
  480. }
  481. }
  482. if (e.Button == MouseButtons.Right)
  483. {
  484. tree.SelectedNode = tree.GetNodeAt(e.Location);
  485. if (tree.SelectedNode != null)
  486. {
  487. ContextMenuBase menu = (tree.SelectedNode.Tag as Base).GetContextMenu();
  488. if (menu != null)
  489. {
  490. menu.Show(tree, e.Location);
  491. }
  492. }
  493. }
  494. }
  495. private void tree_BeforeSelect(object sender, TreeViewCancelEventArgs e)
  496. {
  497. if (updating || passSelection)
  498. return;
  499. if (cancelNextSelection)
  500. {
  501. e.Cancel = true;
  502. cancelNextSelection = false;
  503. return;
  504. }
  505. if (Control.ModifierKeys == Keys.Control && Designer.SelectedObjects.Contains(e.Node.Tag as Base) && !ShiftNonSelect)
  506. {
  507. e.Cancel = true;
  508. Designer.SelectedObjects.Remove(e.Node.Tag as Base);
  509. Designer.SelectionChanged(null);
  510. UpdateSelection();
  511. return;
  512. }
  513. }
  514. #endregion
  515. #region Public Methods
  516. /// <inheritdoc/>
  517. public override void SelectionChanged()
  518. {
  519. UpdateSelection();
  520. }
  521. /// <inheritdoc/>
  522. public override void UpdateContent()
  523. {
  524. UpdateTree();
  525. UpdateSelection();
  526. }
  527. /// <inheritdoc/>
  528. public override void Localize()
  529. {
  530. base.Localize();
  531. Text = Res.Get("Designer,ToolWindow,ReportTree");
  532. }
  533. /// <inheritdoc/>
  534. public override void UpdateDpiDependencies()
  535. {
  536. base.UpdateDpiDependencies();
  537. Image = Designer.GetImage(189);
  538. tree.ImageList = Designer.GetImages();
  539. #if !MONO
  540. ImageIndex = 189;
  541. #endif
  542. }
  543. #endregion
  544. /// <summary>
  545. /// Initializes a new instance of the <see cref="ReportTreeWindow"/> class with default settings.
  546. /// </summary>
  547. /// <param name="designer">The report designer.</param>
  548. public ReportTreeWindow(Designer designer) : base(designer)
  549. {
  550. Name = "ReportTreeWindow";
  551. components = new List<Base>();
  552. nodes = new List<TreeNode>();
  553. nodesSelected = new List<TreeNode>();
  554. tree.ShowRootLines = false;
  555. tree.HideSelection = true;
  556. tree.LabelEdit = true;
  557. tree.AllowDrop = true;
  558. tree.AfterSelect += tree_AfterSelect;
  559. tree.BeforeSelect += tree_BeforeSelect;
  560. tree.ItemDrag += tree_ItemDrag;
  561. tree.DragOver += tree_DragOver;
  562. tree.DragDrop += tree_DragDrop;
  563. tree.KeyDown += tree_KeyDown;
  564. tree.BeforeLabelEdit += tree_BeforeLabelEdit;
  565. tree.AfterLabelEdit += tree_AfterLabelEdit;
  566. tree.NodeMouseClick += FTree_MouseUp;
  567. Localize();
  568. UpdateDpiDependencies();
  569. }
  570. }
  571. }