private void HandleDoubleClick() { MultiSourceTreeNode node = (MultiSourceTreeNode)GetNodeAt(lastClickX, lastClickY); if (node == null) { return; } foreach (NodeInfo info in node.InfoEntries) { foreach (NodeStateSubscriber subscriber in info.Subscriptions) { foreach (MenuDefinition def in subscriber.State.MenuDefinitions.Keys) { bool match = false; if (subscriber.State.MenuDefinitions[def]) // Will equal true if this is a default option. { match = true; if (def.MenuItemTest != null) { match = def.MenuItemTest.Invoke(node, info); } } if (match) { def.OnMenuClicked(node, info); return; } } } } if (node.IsExpanded) { node.Collapse(); } else { node.Expand(); } }
/// <summary> /// Recursively updates a node's child nodes after it has been renamed. /// </summary> void UpdateChildNodesAfterRename(MultiSourceTreeNode parentNode) { if (parentNode.ChildrenAdded) { foreach (MultiSourceTreeNode node in parentNode.Nodes) { foreach (NodeInfo info in node.InfoEntries) { if (info.NodeType.SupportsRenaming) { info.NodeType.RenameChild(info, parentNode.InfoEntries[0]); // We're only using the first InfoEntry. } } if (node.ChildrenAdded) { UpdateChildNodesAfterRename(node); } } } }
private void VerifyNode(MultiSourceTreeNode node) { if (node == null) { return; } List <NodeInfo> unmatchedEntries = new List <NodeInfo>(); foreach (NodeInfo entry in node.InfoEntries) { if (!entry.NodeType.HasChildren(entry)) { unmatchedEntries.Add(entry); } } foreach (NodeInfo entry in unmatchedEntries) { //Output.Write(OutputTypes.Debug, " - Removing entry '" + entry.NodeType.GetType() + "' from node (has no children at this path)"); RemoveNodeInfo(entry); } }
void MultiSourceTreeView_MouseMove(object sender, MouseEventArgs e) { if (MousePosition == lastMousePosition) { return; } lastMousePosition = MousePosition; // Get the node that exists at the mouse position. MultiSourceTreeNode node = GetNodeAt(PointToClient(MousePosition)) as MultiSourceTreeNode; if (node != currentNode) { currentNode = node; UseInternalTooltips = true; tooltip.HideTooltip(); ResetMouseIdleTimer(); } }
void MultiSourceTreeView_MouseDown(object sender, MouseEventArgs e) { ResetMouseIdleTimer(); if (e.Button == MouseButtons.Left) { lastClickX = e.X; lastClickY = e.Y; } if (e.Button == MouseButtons.Right) { MultiSourceTreeNode node = GetNodeAt(e.X, e.Y) as MultiSourceTreeNode; if (node == null) { return; } if (SelectedNode != node) { if (SelectedNodes.Length < 2) { SelectedNode = node; } } MultiSourceTreeNode[] selectedNodes = new MultiSourceTreeNode[SelectedNodes.Length]; for (int x = 0; x < SelectedNodes.Length; x++) { selectedNodes[x] = (MultiSourceTreeNode)SelectedNodes[x]; } UpdateContextMenu(selectedNodes); if (popupMenu.SubItems.Count > 0) { popupMenu.Popup(MousePosition); } } }
/// <summary> /// Adds a 'dummy node' to the specified MultiSourceTreeNode. /// </summary> /// <description> /// The purpose of a dummy node, is to allow a node to be expandable without /// having to actually populate it's child nodes first. This allows us to /// load child nodes on the fly - thus greatly improving performance of the TreeView. /// </description> protected static void AddDummyNode(MultiSourceTreeNode node) { node.Nodes.Add("dummy"); }
private MultiSourceTreeNode UpdateNode(NodeInfo info) { if (InvokeRequired) { return((MultiSourceTreeNode)(Invoke((NodeMethodDelegate) delegate { return UpdateNode(info); }))); } //Output.Write(OutputTypes.Debug, "Updating Node (" + info.NodeType.GetType() + "): " + info.Identifier); string treePath = info.NodeType.GetTreePath(info); if (treePath == "") { return(null); } MultiSourceTreeNode node = (MultiSourceTreeNode)GetNodeFromPath(treePath); if (node != null) { //Output.Write(OutputTypes.Debug, "Found node in the tree."); // Add Node Info to node. //Output.Write(OutputTypes.Debug, "Adding info entry."); if (!node.ContainsEntry(info)) { node.AddInfoEntry(info); } //else //Output.Write(OutputTypes.Debug, " - (Already contained)"); info.ParentSource.UpdateNode(node); // Recursively update the parent nodes. NodeInfo parentInfo = info.NodeType.GetParentNodeInfo(info); if (parentInfo != null) { if (parentInfo.Identifier != "") { //Output.Write(OutputTypes.Debug, "Updating parent node."); UpdateNode(parentInfo); } } return(node); } else { //Output.Write(OutputTypes.Debug, "The node does not exist in the tree."); NodeInfo parentInfo = info.NodeType.GetParentNodeInfo(info); MultiSourceTreeNode parentNode; if (parentInfo.Identifier != "") { //Output.Write(OutputTypes.Debug, "Updating parent node."); parentNode = UpdateNode(parentInfo); } else { // We've reached the root node, and the item does not exist. string parentTreePath = parentInfo.NodeType.GetTreePath(parentInfo); parentNode = (MultiSourceTreeNode)GetNodeFromPath(parentTreePath); } if (parentNode != null) { if (parentNode.ChildrenAdded) { //Output.Write(OutputTypes.Debug, "Parent node exists and its children have been added."); // Create the node. string nodeName = info.NodeType.GetNodeName(info.Identifier); node = info.ParentSource.CreateNode(nodeName, info, info.NodeType.HasChildren); //Output.Write(OutputTypes.Debug, "Manually add the new node (" + node.Text + ") to " + parentNode.Text + "."); AddChildNodes(parentNode, new MultiSourceTreeNode[] { node }); return(node); } } return(parentNode); } }
private void RemoveNodeInfo(NodeInfo info) { if (InvokeRequired) { Invoke(new MethodInvoker(delegate { RemoveNodeInfo(info); })); return; } // Retreive the node from the tree (if it exists). //Output.Write(OutputTypes.Debug, "Removing Node (" + info.NodeType.GetType() + "): " + info.Identifier); string treePath = info.NodeType.GetTreePath(info); MultiSourceTreeNode node = (MultiSourceTreeNode)GetNodeFromPath(treePath); if (node != null) { // Store our parent, since this will change once we remove the node from it. TreeNode parentNode = node.Parent; //Output.Write(OutputTypes.Debug, "Node exists in the tree."); // Remove the entry if it exists. NodeInfo entry = node.FindInfoEntry(info.NodeType); if (entry != null) { node.RemoveInfoEntry(entry); //Output.Write(OutputTypes.Debug, "Removed matching InfoEntry from the node."); } //else //Output.Write(OutputTypes.Debug, "Matching InfoEntry was not found!"); // Update the node if we still have entries. // DESIGN ISSUE: // ------------- // When an entry is removed, child nodes will also need updating. // The problem is, there is no way to do this without recreating the child nodes. if (node.EntryCount > 0) { info.ParentSource.UpdateNode(node); //Output.Write(OutputTypes.Debug, "Node still contains entries - updating."); } else // Remove the node (if there is a parent to remove it from) if (parentNode != null) { //Output.Write(OutputTypes.Debug, "Node contains no more entries - removing node."); parentNode.Nodes.Remove(node); if (parentNode.Nodes.Count == 0) { parentNode.Collapse(); } } // Verify the parent node. if (parentNode != null) { if (parentNode is MultiSourceTreeNode) { //Output.Write(OutputTypes.Debug, "Verifying parent node: " + parentNode.Text); VerifyNode(parentNode as MultiSourceTreeNode); } } } else { //Output.Write(OutputTypes.Debug, "Node does not exist in the tree."); // The node doesn't exist in the tree, so we don't need to remove it. // We do, however, still need to update the node's parent to ensure that // it still contains child objects of this type. // Direct parent may not exist (which was causing issues previously) // Because of that, we will need to go all the way up the tree until we // either find a node, or hit the root node. MultiSourceTreeNode parentNode = GetFirstExistingParentNode(info); if (parentNode != null) { //Output.Write(OutputTypes.Debug, "Located a parent node: " + parentNode.Text + " - Updating."); VerifyNode(parentNode); } //else //Output.Write(OutputTypes.Debug, "No parent node was found - no updates required."); } }
void MultiSourceTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { MultiSourceTreeNode node = (MultiSourceTreeNode)e.Node; LabelEdit = (node.InfoEntries[0].NodeType.SupportsRenaming); }
/// <summary> /// Creates the child nodes of the specified node. /// </summary> protected void CreateChildren(MultiSourceTreeNode node) { CreateChildren(node, false); }