123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- using FastReport.Controls;
- using FastReport.Utils;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Windows.Forms;
- namespace FastReport.Design.ToolWindows
- {
- /// <summary>
- /// Represents the "Report Tree" window.
- /// </summary>
- public class ReportTreeWindow : FilterableToolWindow
- {
- #region Fields
- private Dictionary<Base, TreeNode> objectNodes;
- private Panel dragIndicator;
- private ToolbarButton btnSync;
- #endregion
- #region Private Methods
- private void UpdateSelection()
- {
- if (Designer.SelectedObjects == null || Designer.SelectedObjects.Count == 0)
- return;
- if (objectNodes.ContainsKey(Designer.SelectedObjects[0]))
- {
- ObjectsToSelectedNodes();
- }
- }
- private void ObjectsToSelectedNodes()
- {
- var nodes = new List<TreeNode>();
- foreach (Base b in Designer.SelectedObjects)
- nodes.Add(objectNodes[b]);
- tree.SelectedNodes = nodes;
- if (btnSync.Checked)
- tree.TrackSelection();
- }
- private void SelectedNodesToObjects()
- {
- Designer.SelectedObjects.Clear();
- foreach (var node in tree.SelectedNodes)
- Designer.SelectedObjects.Add(node.Tag as Base);
- // activate object's page
- if (Designer.SelectedObjects.Count > 0)
- {
- var c = Designer.SelectedObjects[0];
- if (!(c is Report))
- Designer.ActiveReportTab.ActivePage = c.Page;
- }
- Designer.SelectionChanged(this);
- }
- private void EnumComponents(Base rootComponent, TreeNodeCollection rootNode)
- {
- string name = rootComponent is Report ?
- "Report - " + Designer.ActiveReportTab.ReportName : rootComponent.Name;
- TreeNode node = rootNode.Add(name);
- node.Tag = rootComponent;
- objectNodes[rootComponent] = node;
- int imageIndex = rootComponent.GetImageIndex();
- if (imageIndex != -1)
- {
- node.ImageIndex = imageIndex;
- node.SelectedImageIndex = imageIndex;
- }
- if (rootComponent.HasFlag(Flags.CanShowChildrenInReportTree))
- {
- foreach (Base component in rootComponent.ChildObjects)
- EnumComponents(component, node.Nodes);
- }
- }
- private bool CheckChanges(Base rootComponent, TreeNode rootNode)
- {
- if (rootNode.Tag != rootComponent)
- return false;
- if (!(rootComponent is Report))
- {
- if (rootNode.Text != rootComponent.Name)
- return false;
- }
- if (!rootComponent.HasFlag(Flags.CanShowChildrenInReportTree))
- return true;
- ObjectCollection childObjects = rootComponent.ChildObjects;
- if (childObjects.Count != rootNode.Nodes.Count)
- return false;
- for (int i = 0; i < childObjects.Count; i++)
- {
- if (!CheckChanges(childObjects[i], rootNode.Nodes[i]))
- return false;
- }
- return true;
- }
- private void tree_SelectionChanged(object sender, EventArgs e)
- {
- SelectedNodesToObjects();
- }
- private void tree_RightMouseButtonClicked(object sender, MouseEventArgs e)
- {
- var menu = Designer.SelectedObjects[0].GetContextMenu();
- menu?.Show(tree, e.Location);
- }
- private void tree_ItemDrag(object sender, ItemDragEventArgs e)
- {
- // check if every item can be dragged
- var effect = DragDropEffects.Move;
- foreach (Base draggedItem in Designer.SelectedObjects)
- {
- if (draggedItem is ComponentBase &&
- (draggedItem.IsAncestor || draggedItem.HasFlag(Flags.CanChangeParent)))
- {
- // ok
- }
- else
- {
- effect = DragDropEffects.None;
- break;
- }
- }
- tree.DoDragDrop(e.Item, effect);
- }
- private void tree_DragOver(object sender, DragEventArgs e)
- {
- dragIndicator.Hide();
- TreeNode targetNode = (tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y))));
- if (targetNode == null || e.AllowedEffect == DragDropEffects.None)
- return;
- Base target = targetNode.Tag as Base;
- // allowed moves are:
- // - target is not dragged
- // - target is not child of dragged
- // - dragged is not child of parent
- // - target can contain dragged, or
- // parent of target can contain dragged
- int dragPos = 0;
- int allow = 0;
- foreach (Base dragged in Designer.SelectedObjects)
- {
- if (dragged == target || target.HasParent(dragged) || dragged.Parent == target)
- continue;
- bool changeParent = (target as IParent)?.CanContain(dragged) ?? false;
- bool changeOrder = (target.Parent as IParent)?.CanContain(dragged) ?? false;
- if (changeParent || changeOrder)
- {
- allow++;
- dragPos = changeParent ? targetNode.Bounds.Bottom : targetNode.Bounds.Top;
- }
- }
- if (allow == Designer.SelectedObjects.Count)
- {
- e.Effect = e.AllowedEffect;
- dragIndicator.BackColor = tree.ForeColor;
- dragIndicator.SetBounds(tree.Left + targetNode.Bounds.Left, tree.Top + dragPos, targetNode.Bounds.Width, Designer.LogicalToDevice(2));
- dragIndicator.Show();
- }
- }
- private void tree_DragDrop(object sender, DragEventArgs e)
- {
- dragIndicator.Hide();
- TreeNode targetNode = tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y)));
- Base target = targetNode.Tag as Base;
- // cases:
- // - target can contain dragged. Just change parent.
- // - target cannot contain dragged. Change creation order (Z-order).
- foreach (Base dragged in Designer.SelectedObjects)
- {
- if (target is IParent par && par.CanContain(dragged))
- {
- dragged.Parent = target;
- }
- else
- {
- Base parent = target.Parent;
- dragged.Parent = parent;
- dragged.ZOrder = target.ZOrder;
- }
- }
- // update all designer plugins (this one too)
- Designer.SetModified(null, "ChangeParent");
- }
- private void tree_DragLeave(object sender, EventArgs e)
- {
- dragIndicator.Hide();
- }
- private void tree_KeyDown(object sender, KeyEventArgs e)
- {
- if (e.KeyCode == Keys.Delete)
- Designer.cmdDelete.Invoke();
- }
- private void tree_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
- {
- Base c = e.Node.Tag as Base;
- if (c is Report)
- e.CancelEdit = true;
- }
- private void tree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
- {
- if (e.Label != null)
- {
- Base c = e.Node.Tag as Base;
- try
- {
- c.Name = e.Label;
- Designer.SetModified(this, "Change");
- }
- catch (Exception ex)
- {
- FRMessageBox.Error(ex.Message);
- e.CancelEdit = true;
- }
- }
- }
- private void btnSync_Click(object sender, EventArgs e)
- {
- tree.TrackSelection();
- }
- #endregion
- #region Protected/Public Methods
- /// <inheritdoc/>
- protected override void UpdateTree()
- {
- // if there was no changes in the report structure, do nothing
- if (Designer.ActiveReport != null && tree.Nodes.Count > 0)
- {
- if (CheckChanges(Designer.ActiveReport, tree.Nodes[0]))
- return;
- }
- tree.BeginUpdate();
- tree.Nodes.Clear();
- objectNodes.Clear();
- if (Designer.ActiveReport != null)
- EnumComponents(Designer.ActiveReport, tree.Nodes);
- tree.ExpandAll();
- tree.EndUpdate();
- }
- /// <inheritdoc/>
- public override void SelectionChanged()
- {
- Throttle.Execute(UpdateSelection);
- }
- /// <inheritdoc/>
- public override void UpdateContent()
- {
- Throttle.Execute(() =>
- {
- UpdateTree();
- UpdateSelection();
- #if !WPF
- SearchMatches();
- #endif
- });
- }
- /// <inheritdoc/>
- public override void Localize()
- {
- base.Localize();
- MyRes res = new MyRes("Designer,ToolWindow,ReportTree");
- Text = res.Get("");
- btnSync.ToolTipText = res.Get("Sync");
- }
- /// <inheritdoc/>
- public override void UpdateDpiDependencies()
- {
- base.UpdateDpiDependencies();
- Image = Designer.GetImage(189);
- tree.ImageList = Designer.GetImages();
- }
- #endregion
- /// <summary>
- /// Initializes a new instance of the <see cref="ReportTreeWindow"/> class with default settings.
- /// </summary>
- /// <param name="designer">The report designer.</param>
- public ReportTreeWindow(Designer designer) : base(designer)
- {
- Name = "ReportTreeWindow";
- objectNodes = new Dictionary<Base, TreeNode>();
- tree.LabelEdit = true;
- tree.ShowRootLines = false;
- tree.AllowDrop = true;
- tree.SelectionChanged += tree_SelectionChanged;
- tree.RightMouseButtonClicked += tree_RightMouseButtonClicked;
- tree.ItemDrag += tree_ItemDrag;
- tree.DragOver += tree_DragOver;
- tree.DragDrop += tree_DragDrop;
- tree.DragLeave += tree_DragLeave;
- tree.KeyDown += tree_KeyDown;
- tree.BeforeLabelEdit += tree_BeforeLabelEdit;
- tree.AfterLabelEdit += tree_AfterLabelEdit;
- btnSync = AddButton(81, btnSync_Click);
- btnSync.CheckOnClick = true;
- toolbar.AddItems(btnSync);
- dragIndicator = new Panel();
- dragIndicator.Visible = false;
- Controls.Add(dragIndicator);
- Controls.SetChildIndex(dragIndicator, 0);
- Localize();
- UpdateDpiDependencies();
- }
- }
- }
|