Commit for development environment setup
This commit is contained in:
@@ -0,0 +1,439 @@
|
||||
/*********************************************************************************************
|
||||
* Copyright 2005 - Volian Enterprises, Inc. All rights reserved.
|
||||
* Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
|
||||
* ------------------------------------------------------------------------------
|
||||
* $Workfile: TreeViewMultiSelect.cs $ $Revision: 1 $
|
||||
* $Author: Kathy $ $Date: 3/08/05 1:45p $
|
||||
*
|
||||
* $History: TreeViewMultiSelect.cs $
|
||||
*
|
||||
* ***************** Version 1 *****************
|
||||
* User: Kathy Date: 3/08/05 Time: 1:45p
|
||||
* Created in $/LibSource/GUI_Utils
|
||||
* Approval
|
||||
*
|
||||
* ***************** Version 1 *****************
|
||||
* User: Kathy Date: 3/08/05 Time: 1:40p
|
||||
* Created in $/LibSource/GUI_Utils/GUI_Utils
|
||||
*
|
||||
* ***************** Version 1 *****************
|
||||
* User: Kathy Date: 3/08/05 Time: 1:33p
|
||||
* Created in $/LibSource/GUI_Utils/GUI_Utils
|
||||
*
|
||||
* ***************** Version 1 *****************
|
||||
* User: Kathy Date: 3/08/05 Time: 1:32p
|
||||
* Created in $/LibSource/GUI_Utils/GUI_Utils
|
||||
*
|
||||
* ***************** Version 1 *****************
|
||||
* User: Kathy Date: 3/08/05 Time: 1:30p
|
||||
* Created in $/GUI_Utils/GUI_Utils
|
||||
*********************************************************************************************/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MultiSelectTreeView
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for MultiSelectTreeView.
|
||||
/// The MultiSelectTreeView inherits from System.Windows.Forms.TreeView to
|
||||
/// allow user to select multiple nodes.
|
||||
/// The underlying comctl32 TreeView doesn't support multiple selection.
|
||||
/// Hence this MultiSelectTreeView listens for the BeforeSelect && AfterSelect
|
||||
/// events to dynamically change the BackColor of the individual treenodes to
|
||||
/// denote selection.
|
||||
/// It then adds the TreeNode to the internal arraylist of currently
|
||||
/// selectedNodes after validation checks.
|
||||
///
|
||||
/// The MultiSelectTreeView supports
|
||||
/// 1) Select + Control will add the current node to list of SelectedNodes
|
||||
/// 2) Select + Shift will add the current node and all the nodes between the two
|
||||
/// (if the start node and end node is at the same level)
|
||||
/// 3) Control + A when the MultiSelectTreeView has focus will select all Nodes.
|
||||
///
|
||||
///
|
||||
/// </summary>
|
||||
public class MultiSelectTreeView : System.Windows.Forms.TreeView
|
||||
{
|
||||
/// <summary>
|
||||
/// This is private member which caches the last treenode user clicked
|
||||
/// </summary>
|
||||
private TreeNode lastNode;
|
||||
private TreeNode ParentNode;
|
||||
private int SelectNodes_ImageId;
|
||||
|
||||
/// <summary>
|
||||
/// This is private member stores the list of SelectedNodes
|
||||
/// </summary>
|
||||
private ArrayList selectedNodes;
|
||||
|
||||
/// <summary>
|
||||
/// This is private member which caches the first treenode user clicked
|
||||
/// </summary>
|
||||
private TreeNode firstNode;
|
||||
|
||||
/// <summary>
|
||||
/// The constructor which initialises the MultiSelectTreeView.
|
||||
/// </summary>
|
||||
public MultiSelectTreeView(int imgid)
|
||||
{
|
||||
SelectNodes_ImageId=imgid;
|
||||
selectedNodes = new ArrayList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor which initialises the MultiSelectTreeView.
|
||||
/// </summary>
|
||||
[
|
||||
Category("Selection"),
|
||||
Description("Gets or sets the selected nodes as ArrayList")
|
||||
]
|
||||
public ArrayList SelectedNodes
|
||||
{
|
||||
get
|
||||
{
|
||||
return selectedNodes;
|
||||
}
|
||||
set
|
||||
{
|
||||
DeselectNodes();
|
||||
selectedNodes.Clear();
|
||||
selectedNodes = value;
|
||||
SelectNodes();
|
||||
}
|
||||
}
|
||||
|
||||
#region overrides
|
||||
/// <summary>
|
||||
/// If the user has pressed "Control+A" keys then select all nodes.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnKeyUp(KeyEventArgs e)
|
||||
{
|
||||
base.OnKeyDown (e);
|
||||
bool Pressed = (e.Control && ((e.KeyData & Keys.A) == Keys.A));
|
||||
if (Pressed)
|
||||
{
|
||||
// SelectAllNodes(this.Nodes); //we won't allow selection of all.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This Function starts the multiple selection.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnBeforeSelect(TreeViewCancelEventArgs e)
|
||||
{
|
||||
base.OnBeforeSelect(e);
|
||||
|
||||
//if (e.Node.SelectedImageIndex!=SelectNodes_ImageId)return;
|
||||
//if (selectedNodes.Count>1 && e.Node.Parent != ParentNode) return;
|
||||
//ParentNode=e.Node.Parent;
|
||||
|
||||
//Check for the current keys press..
|
||||
bool isControlPressed = (ModifierKeys==Keys.Control);
|
||||
bool isShiftPressed = (ModifierKeys==Keys.Shift);
|
||||
bool isRightMouse = (Control.MouseButtons==MouseButtons.Right);
|
||||
|
||||
if (isRightMouse)return;
|
||||
|
||||
//If control is pressed and the selectedNodes contains current Node
|
||||
//Deselect that node...
|
||||
//Remove from the selectedNodes Collection...
|
||||
if (isControlPressed && selectedNodes.Contains(e.Node))
|
||||
{
|
||||
DeselectNodes();
|
||||
selectedNodes.Remove( e.Node );
|
||||
SelectNodes();
|
||||
//MultiSelectTreeView has handled this event ....
|
||||
//Windows.Forms.TreeView should eat this event.
|
||||
e.Cancel = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//else (if Shift key is pressed)
|
||||
//Start the multiselection ...
|
||||
//Since Shift is pressed we would "SELECT"
|
||||
///all nodes from first node - to last node
|
||||
lastNode = e.Node;
|
||||
|
||||
//If Shift not pressed...
|
||||
//Remember this Node to be the Start Node .. in case user presses Shift to
|
||||
//select multiple nodes.
|
||||
if (!isShiftPressed&&!isControlPressed&&(e.Node.ImageIndex==this.SelectNodes_ImageId))
|
||||
firstNode = e.Node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function ends the multi selection. Also adds and removes the node to
|
||||
/// the selectedNodes depending upon the keys pressed.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnAfterSelect(TreeViewEventArgs e)
|
||||
{
|
||||
base.OnAfterSelect(e);
|
||||
//if (e.Node.SelectedImageIndex!=SelectNodes_ImageId)return;
|
||||
//if (selectedNodes.Count>1 && e.Node.Parent != ParentNode) return;
|
||||
ParentNode=e.Node.Parent;
|
||||
//Check for the current keys press..
|
||||
bool isControlPressed = (ModifierKeys==Keys.Control);
|
||||
bool isShiftPressed = (ModifierKeys==Keys.Shift);
|
||||
bool isRightMouse = (Control.MouseButtons==MouseButtons.Right);
|
||||
|
||||
if (isRightMouse)return;
|
||||
if (isControlPressed)
|
||||
{
|
||||
if ((!selectedNodes.Contains(e.Node ))&& (e.Node.SelectedImageIndex==SelectNodes_ImageId) && (selectedNodes.Count==0 || e.Node.Parent == ParentNode))
|
||||
{
|
||||
//This is a new Node, so add it to the list.
|
||||
selectedNodes.Add(e.Node);
|
||||
ParentNode = e.Node.Parent;
|
||||
SelectNodes();
|
||||
}
|
||||
else if (selectedNodes.Contains(e.Node))
|
||||
{
|
||||
//If control is pressed and the selectedNodes contains current Node
|
||||
//Deselect that node...
|
||||
//Remove from the selectedNodes Collection...
|
||||
DeselectNodes();
|
||||
selectedNodes.Remove( e.Node );
|
||||
if (selectedNodes.Count==0)ParentNode=null;
|
||||
SelectNodes();
|
||||
}
|
||||
else
|
||||
{
|
||||
//If control is pressed and this is not at the level of multi
|
||||
// select, clear selectetdNodes.
|
||||
if (selectedNodes!=null && selectedNodes.Count>0)
|
||||
{
|
||||
DeselectNodes();
|
||||
selectedNodes.Clear();
|
||||
ParentNode=null;
|
||||
}
|
||||
selectedNodes.Add( e.Node );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// SHIFT is pressed
|
||||
|
||||
if (isShiftPressed && e.Node.SelectedImageIndex==SelectNodes_ImageId)
|
||||
{
|
||||
if (firstNode==null)
|
||||
firstNode=e.Node;
|
||||
else
|
||||
{
|
||||
//Start Looking for the start and end nodes to select all the nodes between them.
|
||||
TreeNode uppernode = firstNode;
|
||||
TreeNode bottomnode = e.Node;
|
||||
//Check Parenting Upper ---> Bottom
|
||||
//Is Upper Node parent (direct or indirect) of Bottom Node
|
||||
bool bParent = CheckIfParent(uppernode, bottomnode);
|
||||
if (!bParent)
|
||||
{
|
||||
//Check Parenting the other way round
|
||||
bParent = CheckIfParent(bottomnode, uppernode);
|
||||
if (bParent) // SWAPPING
|
||||
{
|
||||
TreeNode temp = uppernode;
|
||||
uppernode = bottomnode;
|
||||
bottomnode = temp;
|
||||
}
|
||||
}
|
||||
if (bParent)
|
||||
{
|
||||
TreeNode n = bottomnode;
|
||||
while ( n != uppernode.Parent)
|
||||
{
|
||||
if ( !selectedNodes.Contains( n ) )
|
||||
selectedNodes.Add( n );
|
||||
n = n.Parent;
|
||||
}
|
||||
}
|
||||
// Parenting Fails ... but check if the NODES are on the same LEVEL.
|
||||
else
|
||||
{
|
||||
if ( (uppernode.Parent==null && bottomnode.Parent==null) || (uppernode.Parent!=null && uppernode.Parent.Nodes.Contains( bottomnode )) ) // are they siblings ?
|
||||
{
|
||||
int nIndexUpper = uppernode.Index;
|
||||
int nIndexBottom = bottomnode.Index;
|
||||
//Need to SWAP if the order is reversed...
|
||||
if (nIndexBottom < nIndexUpper)
|
||||
{
|
||||
TreeNode temp = uppernode;
|
||||
uppernode = bottomnode;
|
||||
bottomnode = temp;
|
||||
nIndexUpper = uppernode.Index;
|
||||
nIndexBottom = bottomnode.Index;
|
||||
}
|
||||
|
||||
TreeNode n = uppernode;
|
||||
selectedNodes.Clear();
|
||||
while (nIndexUpper < nIndexBottom)
|
||||
{
|
||||
//Add all the nodes if nodes not present in the current
|
||||
//SelectedNodes list...
|
||||
|
||||
if (!selectedNodes.Contains( n ))
|
||||
{
|
||||
selectedNodes.Add(n);
|
||||
SelectAllNodesInNode(n.Nodes, n);
|
||||
}
|
||||
n = n.NextNode;
|
||||
nIndexUpper++;
|
||||
}
|
||||
//Add the Last Node.
|
||||
selectedNodes.Add(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !selectedNodes.Contains( uppernode ) ) selectedNodes.Add( uppernode );
|
||||
if ( !selectedNodes.Contains( bottomnode ) )selectedNodes.Add( bottomnode );
|
||||
}
|
||||
}
|
||||
ParentNode = e.Node.Parent;
|
||||
SelectNodes();
|
||||
//Reset the firstNode counter for subsequent "SHIFT" keys.
|
||||
firstNode = e.Node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If Normal selection then add this to SelectedNodes Collection.
|
||||
if (selectedNodes!=null && selectedNodes.Count>0)
|
||||
{
|
||||
DeselectNodes();
|
||||
selectedNodes.Clear();
|
||||
}
|
||||
selectedNodes.Add( e.Node );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overriden OnLostFocus to mimic TreeView's behavior of de-selecting nodes.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnLostFocus(EventArgs e)
|
||||
{
|
||||
base.OnLostFocus (e);
|
||||
DeselectNodes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overriden OnGotFocus to mimic TreeView's behavior of selecting nodes.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnGotFocus(EventArgs e)
|
||||
{
|
||||
base.OnGotFocus (e);
|
||||
SelectNodes();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion overrides
|
||||
|
||||
/// <summary>
|
||||
/// Private function to check the parenting of the two nodes passed.
|
||||
/// </summary>
|
||||
/// <param name="parentNode"></param>
|
||||
/// <param name="childNode"></param>
|
||||
/// <returns></returns>
|
||||
private bool CheckIfParent(TreeNode parentNode, TreeNode childNode)
|
||||
{
|
||||
if (parentNode == childNode)
|
||||
return true;
|
||||
|
||||
TreeNode node = childNode;
|
||||
bool parentFound = false;
|
||||
while (!parentFound && node != null)
|
||||
{
|
||||
node = node.Parent;
|
||||
parentFound = (node == parentNode);
|
||||
}
|
||||
return parentFound;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function provides the user feedback that the node is selected
|
||||
/// Basically the BackColor and the ForeColor is changed for all
|
||||
/// the nodes in the selectedNodes collection.
|
||||
/// </summary>
|
||||
private void SelectNodes()
|
||||
{
|
||||
foreach ( TreeNode n in selectedNodes )
|
||||
{
|
||||
n.BackColor = SystemColors.Highlight;
|
||||
n.ForeColor = SystemColors.HighlightText;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function provides the user feedback that the node is de-selected
|
||||
/// Basically the BackColor and the ForeColor is changed for all
|
||||
/// the nodes in the selectedNodes collection.
|
||||
/// </summary>
|
||||
private void DeselectNodes()
|
||||
{
|
||||
if (selectedNodes.Count==0) return;
|
||||
|
||||
TreeNode node = (TreeNode) selectedNodes[0];
|
||||
if (node.TreeView==null) return; // on dispose, at end of program
|
||||
|
||||
Color backColor = node.TreeView.BackColor;
|
||||
Color foreColor= node.TreeView.ForeColor;
|
||||
|
||||
foreach ( TreeNode n in selectedNodes )
|
||||
{
|
||||
n.BackColor = backColor;
|
||||
n.ForeColor = foreColor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function selects all the Nodes in the MultiSelectTreeView..
|
||||
/// </summary>
|
||||
private void SelectAllNodes(TreeNodeCollection nodes)
|
||||
{
|
||||
foreach (TreeNode n in this.Nodes)
|
||||
{
|
||||
selectedNodes.Add(n);
|
||||
if (n.Nodes.Count > 1)
|
||||
{
|
||||
SelectAllNodesInNode(n.Nodes, n);
|
||||
}
|
||||
|
||||
}
|
||||
SelectNodes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive function selects all the Nodes in the MultiSelectTreeView's Node
|
||||
/// </summary>
|
||||
private void SelectAllNodesInNode(TreeNodeCollection nodes, TreeNode node)
|
||||
{
|
||||
foreach (TreeNode n in node.Nodes)
|
||||
{
|
||||
selectedNodes.Add(n);
|
||||
if (n.Nodes.Count > 1)
|
||||
{
|
||||
SelectAllNodesInNode(n.Nodes, n);
|
||||
}
|
||||
}
|
||||
SelectNodes();
|
||||
}
|
||||
|
||||
public bool MultiSelectActive()
|
||||
{
|
||||
if (selectedNodes.Count>1)return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user