2017-01-16 20:59:50 +01:00
/ * Copyright ( c ) Citrix Systems , Inc .
2013-06-24 13:41:48 +02:00
* All rights reserved .
*
* Redistribution and use in source and binary forms ,
* with or without modification , are permitted provided
* that the following conditions are met :
*
* * Redistributions of source code must retain the above
* copyright notice , this list of conditions and the
* following disclaimer .
* * Redistributions in binary form must reproduce the above
* copyright notice , this list of conditions and the
* following disclaimer in the documentation and / or other
* materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ,
* INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY ,
* WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
* /
using System ;
using System.Collections.Generic ;
using System.Text ;
using System.Windows.Forms ;
using System.Drawing ;
using System.ComponentModel ;
using System.Reflection ;
namespace XenAdmin.Controls
{
/// <summary>
/// This interface is used to hide these members from general use.
/// </summary>
internal interface IMultiSelectTreeNode
{
void SetSelected ( bool selected ) ;
void SetEnabled ( bool enabled ) ;
}
public class MultiSelectTreeNode : TreeNode , IMultiSelectTreeNodeCollectionOwner , IMultiSelectTreeNode
{
private readonly MultiSelectTreeNodeCollection _nodes ;
private Color _backColor ;
private Color _foreColor ;
private bool _selected ;
private bool _enabled ;
private Color _highlightForeColor = SystemColors . HighlightText ;
private Color _highlightBackColor = SystemColors . Highlight ;
private bool _showCheckBox ;
public MultiSelectTreeNode ( )
: this ( string . Empty )
{
}
public MultiSelectTreeNode ( string text )
: base ( text )
{
_nodes = new MultiSelectTreeNodeCollection ( this ) ;
_backColor = BackColor ;
_foreColor = ForeColor ;
}
/// <summary>
/// Gets or sets the back-color of the treeNode from the base class. If this is done by setting the BackColor of the base class, then
/// the entire treeview is invalidated which can cause flicker. It is therefore achieved by setting the internal propbag and then invalidating
/// just this node.
/// </summary>
private Color BaseBackColor
{
get
{
return base . BackColor ;
}
set
{
if ( value ! = base . BackColor )
{
if ( TreeView ! = null & & PropBag ! = null & & TreeView . IsHandleCreated )
{
PropBag . BackColor = value ;
TreeView . Invalidate ( Bounds ) ;
}
else
{
base . BackColor = value ;
}
}
}
}
/// <summary>
/// Gets or sets the fore-color of the treeNode from the base class. If this is done by setting the BackColor of the base class, then
/// the entire treeview is invalidated which can cause flicker. It is therefore achieved by setting the internal propbag and then invalidating
/// just this node.
/// </summary>
private Color BaseForeColor
{
get
{
return base . ForeColor ;
}
set
{
if ( value ! = base . ForeColor )
{
if ( TreeView ! = null & & PropBag ! = null & & TreeView . IsHandleCreated )
{
PropBag . ForeColor = value ;
TreeView . Invalidate ( Bounds ) ;
}
else
{
base . ForeColor = value ;
}
}
}
}
/// <summary>
/// Gets the internal prop bag for this node. Users of this property should always check for null after calling this property.
/// </summary>
private OwnerDrawPropertyBag PropBag
{
get
{
FieldInfo fieldInfo = GetType ( ) . GetField ( "propBag" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
if ( fieldInfo ! = null )
{
return ( OwnerDrawPropertyBag ) fieldInfo . GetValue ( this ) ;
}
return null ;
}
}
private void UpdateColors ( )
{
if ( _enabled & & _selected )
{
BaseBackColor = _highlightBackColor ;
BaseForeColor = _highlightForeColor ;
}
else
{
BaseBackColor = _backColor ;
BaseForeColor = _foreColor ;
}
}
public new Color BackColor
{
get
{
return _backColor ;
}
set
{
_backColor = value ;
if ( ! _selected )
{
BaseBackColor = value ;
}
}
}
public new Color ForeColor
{
get
{
return _foreColor ;
}
set
{
_foreColor = value ;
if ( ! _selected )
{
BaseForeColor = value ;
}
}
}
public Color HighlightForeColor
{
get
{
return _highlightForeColor ;
}
set
{
_highlightForeColor = value ;
UpdateColors ( ) ;
}
}
public Color HighlightBackColor
{
get
{
return _highlightBackColor ;
}
set
{
_highlightBackColor = value ;
UpdateColors ( ) ;
}
}
public new MultiSelectTreeNode NextVisibleNode
{
get
{
return ( MultiSelectTreeNode ) base . NextVisibleNode ;
}
}
public new MultiSelectTreeNode PrevVisibleNode
{
get
{
return ( MultiSelectTreeNode ) base . PrevVisibleNode ;
}
}
public new MultiSelectTreeNode Parent
{
get
{
return ( MultiSelectTreeNode ) base . Parent ;
}
}
private bool IsTreeViewEnabled ( )
{
// iterate through ancestors to find treeview as this node might have only just been
// added and therefore the TreeView property will still return null.
MultiSelectTreeNode node = this ;
while ( node ! = null )
{
if ( node . TreeView ! = null )
{
return node . TreeView . Enabled ;
}
node = node . Parent ;
}
return true ;
}
/// <summary>
/// Gets a value indicating whether the tree node is in the selected state.
/// </summary>
/// <value></value>
/// <returns>true if the tree node is in the selected state; otherwise, false.
/// </returns>
public new bool IsSelected
{
get
{
return _selected ;
}
}
/// <summary>
/// Gets or sets a value indicating whether a CheckBox should be shown on this node. This
/// only takes effect if TreeView.ShowCheckBoxes is set to true.
/// </summary>
public bool ShowCheckBox
{
get
{
return _showCheckBox ;
}
set
{
if ( _showCheckBox ! = value )
{
_showCheckBox = value ;
if ( TreeView ! = null )
{
TreeView . UpdateCheckboxVisibility ( this ) ;
}
}
}
}
/// <summary>
/// Iterates through all the descendants of this <see cref="VirtualTreeNode"/>.
/// </summary>
public IEnumerable < MultiSelectTreeNode > Descendants
{
get
{
foreach ( MultiSelectTreeNode node in Nodes )
{
yield return node ;
foreach ( MultiSelectTreeNode n in node . Descendants )
{
yield return n ;
}
}
}
}
/// <summary>
/// Gets the parent tree view that the tree node is assigned to.
/// </summary>
/// <value></value>
/// <returns>
/// A <see cref="MultiSelectTreeView"/> that represents the parent tree view that the tree node is assigned to, or null if the node has not been assigned to a tree view.
/// </returns>
public new MultiSelectTreeView TreeView
{
get
{
return ( MultiSelectTreeView ) base . TreeView ;
}
}
#region IMultiSelectTreeNodeCollectionOwner Members
public new MultiSelectTreeNodeCollection Nodes
{
get { return _nodes ; }
}
#endregion
#region IMultiSelectTreeNode Members
void IMultiSelectTreeNode . SetSelected ( bool selected )
{
_enabled = IsTreeViewEnabled ( ) ;
_selected = selected ;
UpdateColors ( ) ;
}
void IMultiSelectTreeNode . SetEnabled ( bool enabled )
{
_enabled = enabled ;
UpdateColors ( ) ;
}
#endregion
}
}