//****************************************************************** /// <summary> /// Initializes a new instance of the TreeViewerNodeEventArgs class, /// setting the Node property to the given TreeViewerNode. The /// Handled property is also initialized to false. /// </summary> public TreeViewerNodeEventArgs(TreeViewerNode oNode) { Debug.Assert(oNode != null); moNode = oNode; mbHandled = false; }
//****************************************************************** #region [Constructor] //****************************************************************** /// <summary> /// Initializes a new instance of the TreeViewerNodeEventArgs class, /// setting the Node property to the given TreeViewerNode. The /// Handled property is also initialized to false. /// </summary> public TreeViewerNodeEventArgs(TreeViewerNode oNode) { Debug.Assert(oNode != null); moNode = oNode; mbHandled = false; }
//****************************************************************** /// <summary> /// Adds the given node to the end of the collection, then sets the /// node's ParentNode property. Returns the zero-based index of the /// added node. /// </summary> public int Add(TreeViewerNode oNode) { Debug.Assert(oNode != null); Debug.Assert(!InnerList.Contains(oNode)); int iIndex = Count; Insert(iIndex, oNode); return(iIndex); }
//****************************************************************** /// <summary> /// Displays the parse tree specified by the ParseTreeRoot property /// (or the FindPatternRoot or the DisplayPatternRoot) of the given /// TreeTransfer object. The TreeTransfer object also specifies the /// node to select (CurrentParseTreeNode property) and the nodes to /// highlight (in the MatchingNodes and ReplacedNodes collections). /// This method does not change the Modified property, raise the /// TreeChanged event or clear the undo information. /// </summary> private void PopulateRoot(TreeTransfer oTreeTransfer) { Debug.Assert(oTreeTransfer != null); //************************************************************** // Make a private copy of the FeaturesForm.FavoriteTreeFeatures // collection. This private copy will be used until the // PopulateRoot() method is called again, so this tree will // display a consistent set of features when parts of the tree // are edited (even if the FeaturesForm collection changes). FavoriteTreeFeatures.Clear(); foreach (string sName in FeaturesForm.FavoriteTreeFeatures) { FavoriteTreeFeatures.Add(sName); } //************************************************************** // Call BeginUpdate() to disable redrawing the tree, but not if // redrawing was already disabled by the calling code. bool bCallEndUpdate = false; if (! IsUpdating) { BeginUpdate(); bCallEndUpdate = true; } //************************************************************** // Get the root node that specifies the tree to display. // // Display the find-pattern tree if DisplayFindPattern is true. // Display the replace-pattern tree if DisplayReplacePattern is // true. Display the parse tree otherwise. SyntaxNode oSyntaxRoot = oTreeTransfer.ParseTreeRoot; if (DisplayFindPattern) { oSyntaxRoot = oTreeTransfer.FindPatternRoot; } if (DisplayReplacePattern) { oSyntaxRoot = oTreeTransfer.ReplacePatternRoot; } //************************************************************** // If the specified root node is null, display a blank node. if (oSyntaxRoot == null) { oSyntaxRoot = new SyntaxNode(); } //************************************************************** // Create the root TreeViewerNode and then call PopulateBranch() // to display the tree. TreeViewerNode oTreeRoot = new TreeViewerNode(); moTreeViewer.RootNode = oTreeRoot; PopulateBranch(oTreeRoot,oSyntaxRoot,oTreeTransfer); //************************************************************** // If no node is selected, select the root node. if (moTreeViewer.SelectedNode == null) { moTreeViewer.SelectedNode = moTreeViewer.RootNode; } //************************************************************** // Call EndUpdate() to redraw the tree, but not if redrawing was // already disabled by the calling code. if (bCallEndUpdate) { EndUpdate(); } }
//****************************************************************** /// <summary> /// Associates the given oTreeNode with with the indicated /// oSyntaxNode (by setting oTreeNode.Tag to oSyntaxNode). The /// oSyntaxNode features are then used to determine the text that is /// displayed by the oTreeNode. (If this node is a leaf node and /// morphology nodes are not shown, the oSyntaxNode can have child /// nodes to represent morphology. Otherwise, the given oSyntaxNode /// cannot have child nodes.) /// </summary> private void PopulateNode(TreeViewerNode oTreeNode, SyntaxNode oSyntaxNode) { Debug.Assert(oTreeNode != null); Debug.Assert(oSyntaxNode != null); //************************************************************** // The oSyntaxNode can have child nodes (representing // morphology) only if this is a leaf node and morphology nodes // are not shown. if (! oSyntaxNode.IsSyntaxLeaf) { Debug.Assert(oSyntaxNode.ChildNodes.Count == 0); } if (ShowMorphology) { Debug.Assert(oSyntaxNode.ChildNodes.Count == 0); } //************************************************************** // Set the oTreeNode.Tag to associate the displayed node with // the indicated oSyntaxNode. oTreeNode.Tag = oSyntaxNode; //************************************************************** // If this is a leaf node, display the node's text in a bold // font style. Otherwise, use a regular font style. if (oSyntaxNode.IsSyntaxLeaf) { Font oFont = Font; if (oFont.FontFamily.IsStyleAvailable(FontStyle.Bold)) { oFont = new Font(oFont,FontStyle.Bold); } oTreeNode.Font = oFont; } else { Font oFont = Font; if (oFont.FontFamily.IsStyleAvailable(FontStyle.Regular)) { oFont = new Font(oFont,FontStyle.Regular); } oTreeNode.Font = oFont; } //************************************************************** // The displayed text always starts with the node's label. string sText = oSyntaxNode.Label; //************************************************************** // If the ShowFeatures property is true, add the name and value // text for each feature. if (ShowFeatures) { //********************************************************** // For find-pattern and replace-pattern nodes, show all // features. // // For parse-tree nodes, only show the features that are // named in the FavoriteTreeFeatures collection. SyntaxNode oFilteredSyntaxNode = oSyntaxNode.CloneNode(); if ((! DisplayFindPattern) && (! DisplayReplacePattern)) { FilterFeatures(oFilteredSyntaxNode, FavoriteTreeFeatures); } //********************************************************** // Append the name and value text for each feature (except // the node-label feature, since the text already starts // with the node's label). foreach (SyntaxFeature oFeature in oFilteredSyntaxNode.Features) { if (oFeature.Name != TreeTranEngineString.NodeLabel) { string sName = oFeature.Name; string sValue = oFeature.Value; sText = sText + Environment.NewLine + sName + "=" + sValue; } } } //************************************************************** // Set the text of the displayed node. oTreeNode.Text = sText; }
//****************************************************************** /// <summary> /// Returns true if the collection contains the given node. Returns /// false otherwise. /// </summary> public bool Contains(TreeViewerNode oNode) { Debug.Assert(oNode != null); return InnerList.Contains(oNode); }
//****************************************************************** /// <summary> /// Ensures that the specified node is visible within the control, /// scrolling the contents of the control if necessary. /// </summary> public void EnsureVisible(TreeViewerNode oNode) { //************************************************************** // Validate the parameters. if (oNode == null) { string sMessage = "Invalid argument: " + "TreeViewer.EnsureVisible() requires " + "a node that is not null."; throw new Exception(sMessage); } if (RootNode == null) { string sMessage = "Invalid argument: " + "TreeViewer.EnsureVisible() requires " + "a node that is displayed in this tree."; throw new Exception(sMessage); } if (! BranchContainsNode(RootNode,oNode)) { string sMessage = "Invalid argument: " + "TreeViewer.EnsureVisible() requires " + "a node that is displayed in this tree."; throw new Exception(sMessage); } if (IsUpdating) { string sMessage = "Invalid state: " + "TreeViewer.EnsureVisible() must not be called " + "while TreeViewer.IsUpdating is true."; throw new Exception(sMessage); } //************************************************************** // Determine what the node's Left, Right, Top and Bottom values // would be if the ScrollX and ScrollY positions were both zero. int iNodeLeft = oNode.Left + ScrollX; int iNodeRight = oNode.Right + ScrollX; int iNodeTop = oNode.Top + ScrollY; int iNodeBottom = oNode.Bottom + ScrollY; //************************************************************** // Get the left and right margins as offsets from the ScrollX // position. Get the top and bottom margins as offsets from the // ScrollY position. (The ClientSize does not include the area // occupied by the vertical and horizontal scroll bars.) int iLeftMargin = AutoScrollMargin.Width; int iRightMargin = ClientSize.Width - AutoScrollMargin.Width; int iTopMargin = AutoScrollMargin.Height; int iBottomMargin = ClientSize.Height - AutoScrollMargin.Height; //************************************************************** // To ensure the node is visible, the minimum ScrollX position // places the node's right edge at the client area's right // margin: // // iMinScrollX + iRightMargin = iNodeRight // // And the maximum ScrollY position places the node's left edge // at the client area's left margin: // // iMaxScrollY + iLeftMargin = iNodeLeft int iMinScrollX = iNodeRight - iRightMargin; int iMaxScrollX = iNodeLeft - iLeftMargin; //************************************************************** // To ensure the node is visible, the minimum ScrollY position // places the node's bottom edge at the client area's bottom // margin: // // iMinScrollY + iBottomMargin = iNodeBottom // // And the maximum ScrollY position places the node's top edge // at the client area's top margin: // // iMaxScrollY + iTopMargin = iNodeTop int iMinScrollY = iNodeBottom - iBottomMargin; int iMaxScrollY = iNodeTop - iTopMargin; //************************************************************** // Change the ScrollX and ScrollY as necessary to ensure that // the node is visible. int iScrollX = ScrollX; if (iScrollX < iMinScrollX) { iScrollX = iMinScrollX; } if (iScrollX > iMaxScrollX) { iScrollX = iMaxScrollX; } ScrollX = iScrollX; int iScrollY = ScrollY; if (iScrollY < iMinScrollY) { iScrollY = iMinScrollY; } if (iScrollY > iMaxScrollY) { iScrollY = iMaxScrollY; } ScrollY = iScrollY; }
//****************************************************************** #region [Insert() and Add() Methods] //****************************************************************** /// <summary> /// Inserts the given node into the collection at the specified /// zero-based index, then sets the node's ParentNode property. /// </summary> public void Insert(int iIndex, TreeViewerNode oNode) { //************************************************************** // Validate the parameters. Debug.Assert(iIndex >= 0); Debug.Assert(iIndex <= InnerList.Count); if (oNode == null) { string sMessage = "Invalid argument: " + "TreeViewerNodeCollection " + "cannot insert a null item."; throw new Exception(sMessage); } if (InnerList.Contains(oNode)) { string sMessage = "Invalid argument: " + "TreeViewerNodeCollection " + "already contains this item."; throw new Exception(sMessage); } //************************************************************** // Call BeginUpdate() to disable redrawing the tree, but not if // redrawing was already disabled by the calling code. bool bCallEndUpdate = false; if (ParentTree != null) { if (!ParentTree.IsUpdating) { ParentTree.BeginUpdate(); bCallEndUpdate = true; } } //************************************************************** // Insert the node into the list. InnerList.Insert(iIndex, oNode); //************************************************************** // Set the node's ParentNode property. oNode.ParentNode = ParentNode; //************************************************************** // Position the node at negative coordinates off the screen (so // it will not appear until the EndUpdate() call arranges the // tree). Then add the node to the TreeViewer container. if (ParentTree != null) { oNode.Left = -oNode.Width; oNode.Top = -oNode.Height; ParentTree.Controls.Add(oNode); } //************************************************************** // Call EndUpdate() to redraw the tree, but not if redrawing was // already disabled by the calling code. if (ParentTree != null) { if (bCallEndUpdate) { ParentTree.EndUpdate(); } } }
//****************************************************************** #region [Remove(), RemoveAt() and Clear() Methods] //****************************************************************** /// <summary> /// Removes the given node from the collection, after recursively /// clearing the children of the removed node. /// </summary> public void Remove(TreeViewerNode oNode) { Debug.Assert(oNode != null); Debug.Assert(InnerList.Contains(oNode)); //************************************************************** // Call BeginUpdate() to disable redrawing the tree, but not if // redrawing was already disabled by the calling code. bool bCallEndUpdate = false; if (ParentTree != null) { if (!ParentTree.IsUpdating) { ParentTree.BeginUpdate(); bCallEndUpdate = true; } } //************************************************************** // Recursively clear the children of the indicated node. oNode.ChildNodes.Clear(); //************************************************************** // Remove the indicated node from the collection. InnerList.Remove(oNode); //************************************************************** // Set the parent of the removed node to null. oNode.ParentNode = null; //************************************************************** // Remove the indicated node from the TreeViewer container. if (ParentTree != null) { //********************************************************** // Determine if the TreeViewer contains input focus. bool bContainsFocus = ParentTree.ContainsFocus; //********************************************************** // Remove the node from the TreeViewer container. ParentTree.Controls.Remove(oNode); //********************************************************** // Set focus to the TreeViewer if it does not contain focus // now but it contained focus before the node was removed. // (The removed node contained the input focus.) if (bContainsFocus) { if (!ParentTree.ContainsFocus) { ParentTree.Focus(); } } } //************************************************************** // Call EndUpdate() to redraw the tree, but not if redrawing was // already disabled by the calling code. if (ParentTree != null) { if (bCallEndUpdate) { ParentTree.EndUpdate(); } } }
//****************************************************************** /// <summary> /// Creates a branch of SyntaxNode objects representing the nodes /// and features displayed by the given oTreeNode and its children /// (recursively). If the optional oTreeTransfer argument is given, /// its CurrentParseTreeNode is set to indicate the selected node /// (if any) in the branch, and items are added to its MatchingNodes /// and ReplacedNodes collections to indicate highlighted nodes in /// the branch. The root node of the created SyntaxNode branch is /// returned. /// </summary> private SyntaxNode CloneBranch(TreeViewerNode oTreeNode, TreeTransfer oTreeTransfer) { Debug.Assert(oTreeNode != null); Debug.Assert(oTreeTransfer != null); //************************************************************** // Clone the SyntaxNode branch associated with the given // oTreeNode. SyntaxNode oSyntaxNode = CloneNode(oTreeNode); //************************************************************** // The oTreeNode can have child nodes. Or the oSyntaxNode can // have child nodes (representing morphology nodes that were not // shown). But the oTreeNode and oSyntaxNode cannot both have // child nodes. if (oTreeNode.ChildNodes.Count > 0) { Debug.Assert(oSyntaxNode.ChildNodes.Count == 0); } if (oSyntaxNode.ChildNodes.Count > 0) { Debug.Assert(oTreeNode.ChildNodes.Count == 0); } //************************************************************** // Recursively clone each child branch of oTreeNode, and add // each cloned branch as a child of oSyntaxNode. foreach (TreeViewerNode oTreeChild in oTreeNode.ChildNodes) { SyntaxNode oSyntaxChild = CloneBranch(oTreeChild,oTreeTransfer); oSyntaxNode.ChildNodes.Add(oSyntaxChild); } //************************************************************** // If this node is the SelectedNode, set the // oTreeTransfer.CurrentParseTreeNode property to indicate this // node. if (oTreeNode == moTreeViewer.SelectedNode) { oTreeTransfer.CurrentParseTreeNode = oSyntaxNode; } //************************************************************** // If this node is highlighted as a matching node, add an item // indicating this node to the oTreeTransfer.MatchingNodes // collection. // // If this node is highlighted as a replaced node, add an item // indicating this node to the oTreeTransfer.ReplacedNodes // collection. if ((! DisplayFindPattern) && (! DisplayReplacePattern)) { if (oTreeNode.BackColor == FindPatternColor) { SyntaxNodePair oNodePair = new SyntaxNodePair(); oNodePair.ParseTreeNode = oSyntaxNode; oTreeTransfer.MatchingNodes.Push(oNodePair); } if (oTreeNode.BackColor == ReplacePatternColor) { SyntaxNodeTriple oNodeTriple = new SyntaxNodeTriple(); oNodeTriple.ParseTreeNode = oSyntaxNode; oTreeTransfer.ReplacedNodes.Push(oNodeTriple); } } //************************************************************** // Return the cloned SyntaxNode branch. return oSyntaxNode; }
//****************************************************************** /// <summary> /// Creates a branch of SyntaxNode objects representing the nodes /// and features displayed by the given oTreeNode and its children /// (recursively). If the optional oTreeTransfer argument is given, /// its CurrentParseTreeNode is set to indicate the selected node /// (if any) in the branch, and items are added to its MatchingNodes /// and ReplacedNodes collections to indicate highlighted nodes in /// the branch. The root node of the created SyntaxNode branch is /// returned. /// </summary> private SyntaxNode CloneBranch(TreeViewerNode oTreeNode) { TreeTransfer oTreeTransfer = new TreeTransfer(); return CloneBranch(oTreeNode,oTreeTransfer); }
//****************************************************************** /// <summary> /// Initializes a new instance of the TreeViewerNodeCollection /// class, using the indicated oParentNode to set the collection's /// private ParentNode property, which will be used to initialize /// the ParentNode property of each node that is added to this /// collection. /// </summary> public TreeViewerNodeCollection(TreeViewerNode oParentNode) { Debug.Assert(oParentNode != null); moParentNode = oParentNode; }
//****************************************************************** /// <summary> /// Removes the given node from the collection, after recursively /// clearing the children of the removed node. /// </summary> public void Remove(TreeViewerNode oNode) { Debug.Assert(oNode != null); Debug.Assert(InnerList.Contains(oNode)); //************************************************************** // Call BeginUpdate() to disable redrawing the tree, but not if // redrawing was already disabled by the calling code. bool bCallEndUpdate = false; if (ParentTree != null) { if (! ParentTree.IsUpdating) { ParentTree.BeginUpdate(); bCallEndUpdate = true; } } //************************************************************** // Recursively clear the children of the indicated node. oNode.ChildNodes.Clear(); //************************************************************** // Remove the indicated node from the collection. InnerList.Remove(oNode); //************************************************************** // Set the parent of the removed node to null. oNode.ParentNode = null; //************************************************************** // Remove the indicated node from the TreeViewer container. if (ParentTree != null) { //********************************************************** // Determine if the TreeViewer contains input focus. bool bContainsFocus = ParentTree.ContainsFocus; //********************************************************** // Remove the node from the TreeViewer container. ParentTree.Controls.Remove(oNode); //********************************************************** // Set focus to the TreeViewer if it does not contain focus // now but it contained focus before the node was removed. // (The removed node contained the input focus.) if (bContainsFocus) { if (! ParentTree.ContainsFocus) { ParentTree.Focus(); } } } //************************************************************** // Call EndUpdate() to redraw the tree, but not if redrawing was // already disabled by the calling code. if (ParentTree != null) { if (bCallEndUpdate) { ParentTree.EndUpdate(); } } }
//****************************************************************** /// <summary> /// Inserts the given node into the collection at the specified /// zero-based index, then sets the node's ParentNode property. /// </summary> public void Insert(int iIndex,TreeViewerNode oNode) { //************************************************************** // Validate the parameters. Debug.Assert(iIndex >= 0); Debug.Assert(iIndex <= InnerList.Count); if (oNode == null) { string sMessage = "Invalid argument: " + "TreeViewerNodeCollection " + "cannot insert a null item."; throw new Exception(sMessage); } if (InnerList.Contains(oNode)) { string sMessage = "Invalid argument: " + "TreeViewerNodeCollection " + "already contains this item."; throw new Exception(sMessage); } //************************************************************** // Call BeginUpdate() to disable redrawing the tree, but not if // redrawing was already disabled by the calling code. bool bCallEndUpdate = false; if (ParentTree != null) { if (! ParentTree.IsUpdating) { ParentTree.BeginUpdate(); bCallEndUpdate = true; } } //************************************************************** // Insert the node into the list. InnerList.Insert(iIndex,oNode); //************************************************************** // Set the node's ParentNode property. oNode.ParentNode = ParentNode; //************************************************************** // Position the node at negative coordinates off the screen (so // it will not appear until the EndUpdate() call arranges the // tree). Then add the node to the TreeViewer container. if (ParentTree != null) { oNode.Left = -oNode.Width; oNode.Top = -oNode.Height; ParentTree.Controls.Add(oNode); } //************************************************************** // Call EndUpdate() to redraw the tree, but not if redrawing was // already disabled by the calling code. if (ParentTree != null) { if (bCallEndUpdate) { ParentTree.EndUpdate(); } } }
//****************************************************************** /// <summary> /// Searches the collection for the given node. Returns the node's /// zero-based index if it was found. Returns -1 otherwise. /// </summary> public int IndexOf(TreeViewerNode oNode) { Debug.Assert(oNode != null); return InnerList.IndexOf(oNode); }
//****************************************************************** /// <summary> /// Returns true if the collection contains the given node. Returns /// false otherwise. /// </summary> public bool Contains(TreeViewerNode oNode) { Debug.Assert(oNode != null); return(InnerList.Contains(oNode)); }
//****************************************************************** /// <summary> /// Searches the collection for the given node. Returns the node's /// zero-based index if it was found. Returns -1 otherwise. /// </summary> public int IndexOf(TreeViewerNode oNode) { Debug.Assert(oNode != null); return(InnerList.IndexOf(oNode)); }
//****************************************************************** /// <summary> /// Returns a cloned copy of the SyntaxNode branch associated with /// the given oTreeNode (via the oTreeNode.Tag). If this node is a /// leaf node and morphology nodes are not shown, the returned /// SyntaxNode can have child nodes (representing morphology). /// Otherwise, the returned SyntaxNode has no child nodes. /// </summary> private SyntaxNode CloneNode(TreeViewerNode oTreeNode) { Debug.Assert(oTreeNode != null); Debug.Assert(oTreeNode.Tag != null); Debug.Assert(oTreeNode.Tag is SyntaxNode); //************************************************************** // Get the SyntaxNode associated with the given oTreeNode by // retrieving the oTreeNode.Tag (which was set by the // PopulateNode() method) and casting it back to a SyntaxNode. SyntaxNode oSyntaxNode = (SyntaxNode) oTreeNode.Tag; //************************************************************** // Return a cloned copy of the SyntaxNode branch. return oSyntaxNode.CloneBranch(); }
//****************************************************************** #region [Constructor] //****************************************************************** /// <summary> /// Initializes a new instance of the TreeViewerNodeCollection /// class, using the indicated oParentNode to set the collection's /// private ParentNode property, which will be used to initialize /// the ParentNode property of each node that is added to this /// collection. /// </summary> public TreeViewerNodeCollection(TreeViewerNode oParentNode) { Debug.Assert(oParentNode != null); moParentNode = oParentNode; }
//****************************************************************** /// <summary> /// Returns true if the given oTreeNode is null. Also returns true /// if the given oTreeNode has no children and its associated /// SyntaxNode has no features and no children. Otherwise, false is /// returned. /// </summary> private bool NodeIsNullOrEmpty(TreeViewerNode oTreeNode) { if (oTreeNode == null) { return true; } if (oTreeNode.ChildNodes.Count == 0) { SyntaxNode oSyntaxNode = CloneNode(oTreeNode); if ((oSyntaxNode.Features.Count == 0) && (oSyntaxNode.ChildNodes.Count == 0)) { return true; } } return false; }
//****************************************************************** /// <summary> /// Returns true if the indicated tree branch (dominated by oBranch) /// contains the given node (oNode). Returns false otherwise. /// </summary> private bool BranchContainsNode(TreeViewerNode oBranch, TreeViewerNode oNode) { Debug.Assert(oBranch != null); Debug.Assert(oNode != null); //************************************************************** // Search the branch recursively. if (oBranch == oNode) { return true; } foreach (TreeViewerNode oChildBranch in oBranch.ChildNodes) { if (BranchContainsNode(oChildBranch,oNode)) { return true; } } return false; }
//****************************************************************** /// <summary> /// Uses the given oTreeNode to display features of the indicated /// oSyntaxNode. Children are then recursively added to oTreeNode to /// represent the children of oSyntaxNode (unless it is a leaf node /// and morphology nodes are hidden). If the optional oTreeTransfer /// argument is given, its CurrentParseTreeNode indicates the node /// to select, and items in its MatchingNodes and ReplacedNodes /// collections indicate nodes to highlight. /// </summary> private void PopulateBranch(TreeViewerNode oTreeNode, SyntaxNode oSyntaxNode) { TreeTransfer oTreeTransfer = new TreeTransfer(); PopulateBranch(oTreeNode,oSyntaxNode,oTreeTransfer); }
//****************************************************************** /// <summary> /// Uses the given oTreeNode to display features of the indicated /// oSyntaxNode. Children are then recursively added to oTreeNode to /// represent the children of oSyntaxNode (unless it is a leaf node /// and morphology nodes are hidden). If the optional oTreeTransfer /// argument is given, its CurrentParseTreeNode indicates the node /// to select, and items in its MatchingNodes and ReplacedNodes /// collections indicate nodes to highlight. /// </summary> private void PopulateBranch(TreeViewerNode oTreeNode, SyntaxNode oSyntaxNode,TreeTransfer oTreeTransfer) { Debug.Assert(oTreeNode != null); Debug.Assert(oSyntaxNode != null); Debug.Assert(oTreeTransfer != null); //************************************************************** // The given oTreeNode should not already have children. Debug.Assert(oTreeNode.ChildNodes.Count == 0); //************************************************************** // Set the node's context menu. oTreeNode.ContextMenu = moMenu; //************************************************************** // Use the oTreeTransfer.CurrentParseTreeNode property to // determine if the node is selected. if (oSyntaxNode == oTreeTransfer.CurrentParseTreeNode) { moTreeViewer.SelectedNode = oTreeNode; } //************************************************************** // Use the oTreeTransfer.MatchingNodes and .ReplacedNodes // collections to determine the node's background color. Color oForeColor = SystemColors.WindowText; Color oBackColor = SystemColors.Window; foreach (SyntaxNodePair oNodePair in oTreeTransfer.MatchingNodes) { if (oSyntaxNode == oNodePair.ParseTreeNode) { oBackColor = FindPatternColor; } } foreach (SyntaxNodeTriple oNodeTriple in oTreeTransfer.ReplacedNodes) { if (oSyntaxNode == oNodeTriple.ParseTreeNode) { oBackColor = ReplacePatternColor; } } if (DisplayFindPattern) { oBackColor = FindPatternColor; } if (DisplayReplacePattern) { oBackColor = ReplacePatternColor; } oTreeNode.ForeColor = oForeColor; oTreeNode.BackColor = oBackColor; //************************************************************** // Determine if the node's children should be shown. // // A node's children are usually shown, but if the node is a // leaf node and ShowMorphology is false, the leaf node's // children (representing morphology) are not shown (unless the // leaf node's children are selected or highlighted). bool bShowChildNodes = true; if (oSyntaxNode.IsSyntaxLeaf) { if (! ShowMorphology) { bShowChildNodes = false; //****************************************************** // Even if ShowMorphology is false, a leaf node's // children are shown if any of the child branches // contains a selected or highlighted node. foreach (SyntaxNode oSyntaxChild in oSyntaxNode.ChildNodes) { if (BranchContainsSelectionOrHighlight( oSyntaxChild,oTreeTransfer)) { bShowChildNodes = true; } } } } //************************************************************** // Display the node (showing or hiding its children). if (bShowChildNodes) { //********************************************************** // Display the node and its children. // // Clone the oSyntaxNode (without including child nodes) and // call PopulateNode(). PopulateNode(oTreeNode,oSyntaxNode.CloneNode()); //********************************************************** // For each child node, add a new TreeViewerNode to the tree // and make a recursive call to PopulateBranch(). foreach (SyntaxNode oSyntaxChild in oSyntaxNode.ChildNodes) { TreeViewerNode oTreeChild = new TreeViewerNode(); oTreeNode.ChildNodes.Add(oTreeChild); PopulateBranch(oTreeChild,oSyntaxChild,oTreeTransfer); } } else { //********************************************************** // Display the node, but hide its children. // // Clone the entire oSyntaxNode branch (so the cloned branch // includes child nodes that represent morphology) and call // PopulateNode(). PopulateNode(oTreeNode,oSyntaxNode.CloneBranch()); } }
//****************************************************************** /// <summary> /// Adds the given node to the end of the collection, then sets the /// node's ParentNode property. Returns the zero-based index of the /// added node. /// </summary> public int Add(TreeViewerNode oNode) { Debug.Assert(oNode != null); Debug.Assert(! InnerList.Contains(oNode)); int iIndex = Count; Insert(iIndex,oNode); return iIndex; }