using System; using System.Collections.Generic; using System.Windows.Forms; using System.Drawing; using FastReport.Utils; using FastReport.Controls; namespace FastReport.Design.ToolWindows { /// /// Represents the "Report Tree" window. /// public class ReportTreeWindow : FilterableToolWindow { #region Fields //private TreeView tree; private Button collapseExpButton = new Button(); private List components; private List nodes; private List nodesSelected; private TreeNode nodeTree; private int lastFromitem; private int lastToitem; private bool lastNeedReverse; private bool updating; private bool LastData; private bool passSelection = false; private bool cancelNextSelection = false; private bool ShiftNonSelect = false; private bool RewriteSelect = false; private bool mouseButtonRight = false; #endregion #region Private Methods 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; } updating = true; tree.BeginUpdate(); tree.Nodes.Clear(); components.Clear(); nodes.Clear(); if (Designer.ActiveReport != null) EnumComponents(Designer.ActiveReport, tree.Nodes); tree.ExpandAll(); tree.EndUpdate(); updating = false; } private void UpdateSelection() { if (updating) return; if (Designer.SelectedObjects == null || Designer.SelectedObjects.Count == 0) return; Base c = Designer.SelectedObjects[Designer.SelectedObjects.Count - 1]; int i = components.IndexOf(c); if (i != -1) { unpaintSelectedNodes(); updating = true; tree.SelectedNode = nodes[i]; nodesSelected.Clear(); foreach (Base b in Designer.SelectedObjects) { nodesSelected.Add(nodes[components.IndexOf(b)]); } updating = false; paintSelectedNodes(); } } void paintSelectedNodes() { Color backColor = SystemColors.Highlight; Color foreColor = SystemColors.HighlightText; foreach (TreeNode node in nodesSelected) { node.BackColor = backColor; node.ForeColor = foreColor; } } void unpaintSelectedNodes() { foreach (TreeNode node in nodesSelected) { node.BackColor = tree.BackColor; node.ForeColor = tree.ForeColor; } } 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; components.Add(rootComponent); nodes.Add(node); ObjectInfo objItem = RegisteredObjects.FindObject(rootComponent); if (objItem != null) { int imageIndex = objItem.ImageIndex; 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_AfterSelect(object sender, TreeViewEventArgs e) { if (passSelection) return; if (updating) return; if (Designer.SelectedObjects != null) { if (Control.ModifierKeys == Keys.Control && !mouseButtonRight) { if (Designer.SelectedObjects[0] is BandBase || Designer.SelectedObjects[0] is ReportPage) { Designer.SelectedObjects.Clear(); } if (Designer.SelectedObjects.Contains(e.Node.Tag as Base)) { Designer.SelectedObjects.Remove(e.Node.Tag as Base); LastData = false; Designer.SelectionChanged(this); UpdateSelection(); return; } else { if (e.Node.Tag is BandBase) { return; } Designer.SelectedObjects.Add(e.Node.Tag as Base); nodeTree = e.Node; LastData = false; Designer.SelectionChanged(this); UpdateSelection(); return; } } Base c = e.Node.Tag as Base; if (Control.ModifierKeys == Keys.Shift) { if (nodeTree != null && isSameLevel(nodeTree, e.Node)) { List nodeBas = nodes; int nodeTreeIndex = getNodeIndexInNodes(nodeTree); int eNodeTreeIndex = getNodeIndexInNodes(e.Node); int from = Math.Min(nodeTreeIndex, eNodeTreeIndex); int to = Math.Max(nodeTreeIndex, eNodeTreeIndex); bool needReverse = nodeTreeIndex > eNodeTreeIndex; if (!(c is Report)) Designer.ActiveReportTab.ActivePage = c.Page; if (RewriteSelect) { Designer.SelectedObjects.Clear(); RewriteSelect = false; } if (from == lastFromitem && LastData) { if (to < lastToitem) { Designer.SelectedObjects.Clear(); for (int i = from; i <= to; i++) { if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report) { continue; } Designer.SelectedObjects.Add(nodeBas[i].Tag as Base); } } else { for (int i = lastToitem + 1; i <= to; i++) { if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report) { continue; } Designer.SelectedObjects.Add(nodeBas[i].Tag as Base); } } } if (to == lastToitem && LastData) { if (needReverse) { if (from > lastFromitem) { Designer.SelectedObjects.Clear(); for (int i = to; i >= from; i--) { if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report) { continue; } Designer.SelectedObjects.Add(nodeBas[i].Tag as Base); } } else { for (int i = lastFromitem - 1; i >= from; i--) { if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report) continue; Designer.SelectedObjects.Add(nodeBas[i].Tag as Base); } } } } if (LastData == false || lastNeedReverse != needReverse) { Designer.SelectedObjects.Clear(); if (needReverse) { for (int i = to; i >= from; i--) { if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report) continue; Designer.SelectedObjects.Add(nodeBas[i].Tag as Base); } } else { for (int i = from; i <= to; i++) { if (nodeBas[i].Tag is BandBase || nodeBas[i].Tag is ReportPage || nodeBas[i].Tag is Report) continue; Designer.SelectedObjects.Add(nodeBas[i].Tag as Base); } } } if (Designer.SelectedObjects.Count == 0) { Designer.SelectedObjects.Add(nodeTree.Tag as Base); tree.SelectedNode = nodeTree; RewriteSelect = true; } LastData = true; lastFromitem = from; lastToitem = to; lastNeedReverse = needReverse; tree.SelectedNode = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 1]))]; Designer.SelectionChanged(this); UpdateSelection(); } } else { LastData = false; updating = true; if (!(c is Report)) Designer.ActiveReportTab.ActivePage = c.Page; updating = false; nodeTree = e.Node; Designer.SelectedObjects.Clear(); Designer.SelectedObjects.Add(c); Designer.SelectionChanged(null); } } } private int getNodeIndexInNodes(TreeNode node1) { int i = 0; foreach (TreeNode itemNode in nodes) { if (itemNode == node1) { return i; } i++; } return 0; } private bool isSameLevel(TreeNode node1, TreeNode node2) { foreach (TreeNode element in nodes) { if (element == node2) { return true; } } return false; } private void tree_ItemDrag(object sender, ItemDragEventArgs e) { SelectedObjectCollection draggedComponent = Designer.SelectedObjects; foreach (Base itemDragComp in draggedComponent) { if (itemDragComp is ComponentBase && (itemDragComp.IsAncestor || itemDragComp.HasFlag(Flags.CanChangeParent))) { tree.DoDragDrop(draggedComponent, DragDropEffects.Move); } else { tree.DoDragDrop(draggedComponent, DragDropEffects.None); } } } private void tree_DragDrop(object sender, DragEventArgs e) { TreeNode targetNode = tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y))); Base targetComponent = targetNode.Tag as Base; // cases: // - target can contain dragged. Just change parent. // - target cannot contain dragged. Change creation order (Z-order). foreach (Base item in Designer.SelectedObjects) { if (targetComponent is IParent && (targetComponent as IParent).CanContain(item)) { item.Parent = targetComponent; } else { Base parent = targetComponent.Parent; item.Parent = parent; item.ZOrder = targetComponent.ZOrder; } } // update all designer plugins (this one too) Designer.SetModified(null, "ChangeParent"); Base b = Designer.SelectedObjects[Designer.SelectedObjects.Count - 1]; int i = components.IndexOf(b); nodeTree = nodes[i]; UpdateSelection(); } private void tree_DragOver(object sender, DragEventArgs e) { List draggedNode = (List)e.Data.GetData(typeof(List)); TreeNode targetNode = (tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y)))); if (targetNode == null) { return; } SelectedObjectCollection draggedComponent = Designer.SelectedObjects; Base targetComponent = targetNode.Tag as Base; // allowed moves are: // - target is not dragged // - target is not child of dragged // - target can contain dragged, or // parent of target can contain dragged foreach (Base itemDragComp in draggedComponent) { if (itemDragComp != targetComponent && !targetComponent.HasParent(itemDragComp) && (((targetComponent is IParent) && (targetComponent as IParent).CanContain(itemDragComp) || (targetComponent.Parent != null && (targetComponent.Parent as IParent).CanContain(itemDragComp))))) { e.Effect = e.AllowedEffect; } else { e.Effect = DragDropEffects.None; } } // disable the Designer.OnSelectionChanged updating = true; tree.SelectedNode = targetNode; updating = false; } private void tree_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Delete) Designer.cmdDelete.Invoke(); } private void tree_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e) { if (Designer.SelectedObjects.Count == 1 && Control.ModifierKeys == Keys.None) { Base c = e.Node.Tag as Base; if (c is Report) e.CancelEdit = false; } else { e.CancelEdit = true; } } private void tree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) { if (Designer.SelectedObjects.Count == 1 && Control.ModifierKeys == Keys.None) { if (e.Label != null) { Base c = e.Node.Tag as Base; string saveName = c.Name; try { c.Name = e.Label; Designer.SetModified(this, "Change"); } catch (Exception ex) { FRMessageBox.Error(ex.Message); e.CancelEdit = true; } } } else { e.CancelEdit = true; } } private void FTree_MouseUp(object sender, TreeNodeMouseClickEventArgs e) { if (e.Button == MouseButtons.Right) { mouseButtonRight = true; } else { mouseButtonRight = false; } if (Control.ModifierKeys == Keys.Control && e.Button != MouseButtons.Right) { if (e.Node.Tag is BandBase || e.Node.Tag is ReportPage || e.Node.Tag is Report) { ShiftNonSelect = true; Designer.SelectionChanged(this); UpdateSelection(); cancelNextSelection = true; return; } if (tree.SelectedNode == e.Node && Designer.SelectedObjects.Count > 1 && Designer.SelectedObjects.Contains(e.Node.Tag as Base)) { passSelection = true; tree.SelectedNode = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 2]))]; nodeTree = nodes[(components.IndexOf(Designer.SelectedObjects[Designer.SelectedObjects.Count - 2]))]; LastData = false; passSelection = false; Designer.SelectedObjects.Remove(e.Node.Tag as Base); Designer.SelectionChanged(this); UpdateSelection(); cancelNextSelection = true; } return; } else { if (Designer.SelectedObjects.Count > 1 && e.Node == tree.SelectedNode && e.Button != MouseButtons.Right) { Designer.SelectedObjects.Clear(); Designer.SelectedObjects.Add(e.Node.Tag as Base); nodeTree = e.Node; LastData = false; Designer.SelectionChanged(null); UpdateSelection(); } } if (e.Button == MouseButtons.Right) { tree.SelectedNode = tree.GetNodeAt(e.Location); if (tree.SelectedNode != null) { ContextMenuBase menu = (tree.SelectedNode.Tag as Base).GetContextMenu(); if (menu != null) { menu.Show(tree, e.Location); } } } } private void tree_BeforeSelect(object sender, TreeViewCancelEventArgs e) { if (updating || passSelection) return; if (cancelNextSelection) { e.Cancel = true; cancelNextSelection = false; return; } if (Control.ModifierKeys == Keys.Control && Designer.SelectedObjects.Contains(e.Node.Tag as Base) && !ShiftNonSelect) { e.Cancel = true; Designer.SelectedObjects.Remove(e.Node.Tag as Base); Designer.SelectionChanged(null); UpdateSelection(); return; } } #endregion #region Public Methods /// public override void SelectionChanged() { UpdateSelection(); } /// public override void UpdateContent() { UpdateTree(); UpdateSelection(); } /// public override void Localize() { base.Localize(); Text = Res.Get("Designer,ToolWindow,ReportTree"); } /// public override void UpdateDpiDependencies() { base.UpdateDpiDependencies(); Image = Designer.GetImage(189); tree.ImageList = Designer.GetImages(); #if !MONO ImageIndex = 189; #endif } #endregion /// /// Initializes a new instance of the class with default settings. /// /// The report designer. public ReportTreeWindow(Designer designer) : base(designer) { Name = "ReportTreeWindow"; components = new List(); nodes = new List(); nodesSelected = new List(); tree.ShowRootLines = false; tree.HideSelection = true; tree.LabelEdit = true; tree.AllowDrop = true; tree.AfterSelect += tree_AfterSelect; tree.BeforeSelect += tree_BeforeSelect; tree.ItemDrag += tree_ItemDrag; tree.DragOver += tree_DragOver; tree.DragDrop += tree_DragDrop; tree.KeyDown += tree_KeyDown; tree.BeforeLabelEdit += tree_BeforeLabelEdit; tree.AfterLabelEdit += tree_AfterLabelEdit; tree.NodeMouseClick += FTree_MouseUp; Localize(); UpdateDpiDependencies(); } } }