using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using DevComponents.Tree.Display;
using DevComponents.Tree.Layout;
using System.Xml;
using System.IO;
namespace DevComponents.Tree
{
///
/// Summary description for UserControl1.
///
[ToolboxItem(true),DefaultEvent("Click"),System.Runtime.InteropServices.ComVisible(false),Designer(typeof(Design.TreeGXDesigner)),ToolboxBitmap(typeof(TreeGX),"TreeGX.ico")]
public class TreeGX : System.Windows.Forms.ContainerControl, INodeNotify, ISupportInitialize
{
#region Private Variables
private ElementStyleCollection m_Styles=new ElementStyleCollection();
private ColumnHeaderCollection m_Columns=new ColumnHeaderCollection();
private NodeCollection m_Nodes=new NodeCollection();
///
/// Required designer variable.
///
private System.ComponentModel.Container components = null;
private ElementStyle m_CellStyleDefault=null;
private ElementStyle m_CellStyleMouseDown=null;
private ElementStyle m_CellStyleMouseOver=null;
private ElementStyle m_CellStyleSelected=null;
private ElementStyle m_CellStyleDisabled=null;
private ElementStyle m_NodeStyleExpanded=null;
private ElementStyle m_NodeStyle=null;
private ElementStyle m_NodeStyleSelected=null;
private ElementStyle m_NodeStyleMouseOver=null;
private ElementStyle m_ColumnStyleNormal=null;
private ElementStyle m_ColumnStyleMouseOver=null;
private ElementStyle m_ColumnStyleMouseDown=null;
private Layout.NodeLayout m_NodeLayout=null;
private NodeDisplay m_NodeDisplay=null;
private HeadersCollection m_Headers=null;
private string m_PathSeparator=System.IO.Path.PathSeparator.ToString();
private int m_UpdateSuspended=0;
private bool m_PendingLayout=false;
private bool m_SuspendPaint=false;
private Node m_SelectedNode=null;
//private Cell m_SelectedCell=null;
private Node m_MouseOverNode=null;
private Cell m_MouseOverCell=null;
private int m_CellMouseDownCounter=0;
private ImageList m_ImageList=null;
private int m_ImageIndex=-1;
private bool m_AntiAlias=true;
private NodeConnector m_RootConnector=null;
private NodeConnector m_NodesConnector=null;
private NodeConnector m_LinkConnector=null;
private NodeConnector m_SelectedPathConnector=null;
private eCellLayout m_CellLayout=eCellLayout.Default;
private eCellPartLayout m_CellPartLayout=eCellPartLayout.Default;
private Cursor m_OriginalCursor=null;
private Cursor m_DefaultCellCursor=null;
private ColorScheme m_ColorScheme=null;
private bool m_CenterContent=true;
// Selection box properties
private bool m_SelectionBox=true;
private int m_SelectionBoxSize=4;
private Color m_SelectionBoxBorderColor=Color.Empty;
private Color m_SelectionBoxFillColor=Color.Empty;
// Expand Part Properties
private Size m_DefaultExpandPartSize=new Size(9,9);
private Size m_ExpandButtonSize=Size.Empty;
private Color m_ExpandBorderColor=Color.Empty;
private eColorSchemePart m_ExpandBorderColorSchemePart=eColorSchemePart.BarDockedBorder;
private Color m_ExpandBackColor=Color.Empty;
private eColorSchemePart m_ExpandBackColorSchemePart=eColorSchemePart.None;
private Color m_ExpandBackColor2=Color.Empty;
private eColorSchemePart m_ExpandBackColor2SchemePart=eColorSchemePart.None;
private int m_ExpandBackColorGradientAngle=0;
private Color m_ExpandLineColor=Color.Empty;
private eColorSchemePart m_ExpandLineColorSchemePart=eColorSchemePart.BarDockedBorder;
private Image m_ExpandImage=null;
private Image m_ExpandImageCollapse=null;
private eExpandButtonType m_ExpandButtonType=eExpandButtonType.Ellipse;
private Node m_DisplayRootNode=null;
// Command button properties
private int m_CommandWidth=10;
private Color m_CommandBackColor=Color.Empty;
private eColorSchemePart m_CommandBackColorSchemePart=eColorSchemePart.CustomizeBackground;
private Color m_CommandBackColor2=Color.Empty;
private eColorSchemePart m_CommandBackColor2SchemePart=eColorSchemePart.CustomizeBackground2;
private Color m_CommandForeColor=Color.Empty;
private eColorSchemePart m_CommandForeColorSchemePart=eColorSchemePart.CustomizeText;
private int m_CommandBackColorGradientAngle=90;
private Color m_CommandMouseOverBackColor=Color.Empty;
private eColorSchemePart m_CommandMouseOverBackColorSchemePart=eColorSchemePart.ItemHotBackground;
private Color m_CommandMouseOverBackColor2=Color.Empty;
private eColorSchemePart m_CommandMouseOverBackColor2SchemePart=eColorSchemePart.ItemHotBackground2;
private Color m_CommandMouseOverForeColor=Color.Empty;
private eColorSchemePart m_CommandMouseOverForeColorSchemePart=eColorSchemePart.ItemHotText;
private int m_CommandMouseOverBackColorGradientAngle=90;
// Cell editing support
private bool m_CellEdit=false;
private bool m_CellEditing=false;
private Cell m_EditedCell=null;
private TextBoxEx m_EditTextBox=null;
// Drag & Drop
private bool m_DragDropEnabled=true;
private Node m_DragNode=null;
private Point m_MouseDownLocation=Point.Empty;
// Layout
private eNodeLayout m_Layout=eNodeLayout.Map;
private int m_NodeHorizontalSpacing=32;
private int m_NodeVerticalSpacing=32;
private eDiagramFlow m_DiagramLayoutFlow=eDiagramFlow.LeftToRight;
private eMapFlow m_MapLayoutFlow=eMapFlow.Spread;
private ElementStyle m_BackgroundStyle=new ElementStyle();
private eNodeRenderMode m_RenderMode=eNodeRenderMode.Default;
private NodeRenderer m_NodeRenderer=null;
private ArrayList m_HostedControlCells=new ArrayList();
private float m_ZoomFactor=1f;
private object m_DotNetBarManager=null;
#endregion
#region Events
///
/// Occurs after the cell check box is checked.
///
public event TreeGXCellEventHandler AfterCheck;
///
/// Occurs after the tree node is collapsed.
///
public event TreeGXNodeEventHandler AfterCollapse;
///
/// Occurs before the tree node is collapsed.
///
public event TreeGXNodeCancelEventHandler BeforeCollapse;
///
/// Occurs after the tree node is expanded.
///
public event TreeGXNodeEventHandler AfterExpand;
///
/// Occurs before the tree node is expanded.
///
public event TreeGXNodeCancelEventHandler BeforeExpand;
///
/// Occurs when command button on node is clicked.
///
public event CommandButtonEventHandler CommandButtonClick;
///
/// Occurs before cell is edited. The order of the cell editing events is as follows:
/// BeforeCellEdit, CellEditEnding, AfterCellEdit.
///
public event CellEditEventHandler BeforeCellEdit;
///
/// Occurs just before the cell editing is ended. The text box for editing is still visible and you can cancel
/// the exit out of editing mode at this point. The order of the cell editing events is as follows:
/// BeforeCellEdit, CellEditEnding, AfterCellEdit.
///
public event CellEditEventHandler CellEditEnding;
///
/// Occurs after cell editing has ended and before the new text entered by the user is assigned to the cell. You can abort the edits in this event.
/// The order of the cell editing events is as follows:
/// BeforeCellEdit, CellEditEnding, AfterCellEdit.
///
public event CellEditEventHandler AfterCellEdit;
///
/// Occurs after Node has been selected by user or through the SelectedNode property. Event can be cancelled.
///
public event TreeGXNodeCancelEventHandler BeforeNodeSelect;
///
/// Occurs after node has been selected by user or through the SelectedNode property.
///
public event TreeGXNodeEventHandler AfterNodeSelect;
///
/// Occurs before node has been removed from its parent.
///
public event TreeGXNodeCollectionEventHandler BeforeNodeRemove;
///
/// Occurs after node has been removed from its parent.
///
public event TreeGXNodeCollectionEventHandler AfterNodeRemove;
///
/// Occurs before node is inserted or added as child node to parent node.
///
public event TreeGXNodeCollectionEventHandler BeforeNodeInsert;
///
/// Occurs after node is inserted or added as child node.
///
public event TreeGXNodeCollectionEventHandler AfterNodeInsert;
///
/// Occurs before Drag-Drop of a node is completed and gives you information about new parent of the node that is being dragged
/// as well as opportunity to cancel the operation.
///
public event TreeGXDragDropEventHandler BeforeNodeDrop;
///
/// Occurs after Drag-Drop of a node is completed. This operation cannot be cancelled.
///
public event TreeGXDragDropEventHandler AfterNodeDrop;
///
/// Occurs when the mouse pointer is over the node and a mouse button is pressed.
///
public event TreeGXNodeMouseEventHandler NodeMouseDown;
///
/// Occurs when the mouse pointer is over the node and a mouse button is released.
///
public event TreeGXNodeMouseEventHandler NodeMouseUp;
///
/// Occurs when the mouse pointer is moved over the node.
///
public event TreeGXNodeMouseEventHandler NodeMouseMove;
///
/// Occurs when the mouse enters the node.
///
public event TreeGXNodeMouseEventHandler NodeMouseEnter;
///
/// Occurs when the mouse leaves the node.
///
public event TreeGXNodeMouseEventHandler NodeMouseLeave;
///
/// Occurs when the mouse hovers over the node.
///
public event TreeGXNodeMouseEventHandler NodeMouseHover;
///
/// Occurs when the node is clicked with left mouse button. If you need to know more information like if another mouse button is clicked etc. use
/// NodeMouseDown event.
///
public event TreeGXNodeMouseEventHandler NodeClick;
///
/// Occurs when the node is double-clicked.
///
public event TreeGXNodeMouseEventHandler NodeDoubleClick;
///
/// Occurs after an node has been serialized to XmlElement and provides you with opportunity to add any custom data
/// to serialized XML. This allows you to serialize any data associated with the node and load it back up in DeserializeNode event.
///
///
/// To serialize custom data to XML definition control creates handle this event and use CustomXmlElement
/// property on SerializeNodeEventArgs to add new nodes or set attributes with custom data you want saved.
///
public event SerializeNodeEventHandler SerializeNode;
///
/// Occurs after an node has been de-serialized (loaded) from XmlElement and provides you with opportunity to load any custom data
/// you have serialized during SerializeItem event.
///
///
/// To de-serialize custom data from XML definition handle this event and use CustomXmlElement
/// property on SerializeItemEventArgs to retrive any data you saved in SerializeNode event.
///
public event SerializeNodeEventHandler DeserializeNode;
///
/// Occurs when hyperlink in text-markup is clicked.
///
public event MarkupLinkClickEventHandler MarkupLinkClick;
#endregion
#region Constructor/Dispose
/// Creates new instance of the class.
public TreeGX()
{
ColorFunctions.Initialize();
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.Selectable, true);
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
m_BackgroundStyle.StyleChanged+=new EventHandler(ElementStyleChanged);
m_BackgroundStyle.TreeControl=this;
// Setup layout helper
//m_NodeLayout=new NodeTreeLayout(this,this.ClientRectangle);
//m_NodeLayout=new NodeListLayout(this,this.ClientRectangle);
//m_NodeLayout=new NodeDiagramLayout(this,this.ClientRectangle);
m_NodeLayout=new NodeMapLayout(this,this.ClientRectangle);
m_NodeLayout.NodeHorizontalSpacing=m_NodeHorizontalSpacing;
m_NodeLayout.NodeVerticalSpacing=m_NodeVerticalSpacing;
m_NodeLayout.LeftRight=this.RtlTranslateLeftRight(LeftRightAlignment.Left);
#if TRIAL
NodeOperations.ColorExpAlt();
#endif
// Setup display helper
m_NodeDisplay=new NodeTreeDisplay(this);
m_Headers=new HeadersCollection();
m_Nodes.TreeControl=this;
m_Styles.TreeControl=this;
m_ColorScheme=new ColorScheme(eColorSchemeStyle.Office2003);
m_SelectionBoxBorderColor=GetDefaultSelectionBoxBorderColor();
m_SelectionBoxFillColor=GetDefaultSelectionBoxFillColor();
m_ExpandButtonSize=GetDefaultExpandButtonSize();
this.AllowDrop = true;
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}
#endregion
#region Component Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
#region Properties
///
/// Gets or sets the reference to DotNetBar DotNetBarManager component which is used to provide context menu for nodes. This property
/// is automatically maintained by TreeGX.
///
[EditorBrowsable(EditorBrowsableState.Never), DefaultValue(null), Browsable(false)]
public object DotNetBarManager
{
get { return m_DotNetBarManager; }
set { m_DotNetBarManager=value; }
}
///
/// Gets or sets zoom factor for the control. Default value is 1. To zoom display of the nodes for 20% set zoom factor to 1.2
/// To zoom view 2 times set zoom factor to 2. Value must be greater than 0.
///
[Browsable(false), DefaultValue(1f), Category("Layout"), Description("Indicates zoom factor for the control.")]
public float Zoom
{
get { return m_ZoomFactor;}
set
{
if(value<=0.1)
return;
m_ZoomFactor = value;
this.RecalcLayout();
}
}
///
/// Gets the size of the tree.
///
[Browsable(false)]
public Size TreeSize
{
get
{
return new Size(m_NodeLayout.Width, m_NodeLayout.Height);
}
}
///
/// Gets or sets custom node renderer. You can set this property to your custom renderer. When set the RenderMode should be set to Custom to enable
/// your custom renderer. To choose one of the system renderer use RenderMode property. Default value is null.
///
[Browsable(false), Category("Style"), DefaultValue(null), Description("Indicates render mode used to render the node.")]
public NodeRenderer NodeRenderer
{
get { return m_NodeRenderer;}
set
{
m_NodeRenderer = value;
OnDisplayChanged();
}
}
///
/// Gets or sets the render mode used to render all nodes. Default value is eNodeRenderMode.Default which indicates that system default renderer is used.
/// Note that if you specify custom renderer you need to set TreeGX.NodeRenderer property to your custom renderer.
///
[Browsable(true), Category("Style"), DefaultValue(eNodeRenderMode.Default), Description("Indicates render mode used to render the node.")]
public eNodeRenderMode RenderMode
{
get { return m_RenderMode;}
set
{
m_RenderMode = value;
OnDisplayChanged();
}
}
///
/// Gets the style for the background of the control.
///
[Browsable(true),Category("Appearance"),Description("Gets the style for the background of the control."),DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ElementStyle BackgroundStyle
{
get {return m_BackgroundStyle;}
}
///
/// Gets or sets the flow of nodes when Diagram layout is used. Note that this setting applies only to Diagram layout type.
///
[Browsable(true),Category("Layout"),DefaultValue(eDiagramFlow.LeftToRight),Description("Indicates flow of nodes when Diagram layout is used.")]
public eDiagramFlow DiagramLayoutFlow
{
get {return m_DiagramLayoutFlow;}
set
{
m_DiagramLayoutFlow=value;
OnLayoutChanged();
}
}
///
/// Gets or sets the flow of nodes when Map layout is used. Note that this setting applies only to Map layout type.
///
[Browsable(true),Category("Layout"),DefaultValue(eMapFlow.Spread),Description("Indicates flow of nodes when Map layout is used.")]
public eMapFlow MapLayoutFlow
{
get {return m_MapLayoutFlow;}
set
{
m_MapLayoutFlow=value;
OnLayoutChanged();
}
}
///
/// Gets or sets the horizontal spacing in pixels between nodes. Default value is 32.
///
[Browsable(true),Category("Layout"),DefaultValue(32),Description("Indicates horizontal spacing in pixels between nodes.")]
public int NodeHorizontalSpacing
{
get {return m_NodeHorizontalSpacing;}
set
{
m_NodeHorizontalSpacing=value;
OnLayoutChanged();
}
}
///
/// Gets or sets the vertical spacing in pixels between nodes. Default value is 16.
///
[Browsable(true),Category("Layout"),DefaultValue(32),Description("Indicates vertical spacing in pixels between nodes.")]
public int NodeVerticalSpacing
{
get {return m_NodeVerticalSpacing;}
set
{
m_NodeVerticalSpacing=value;
OnLayoutChanged();
}
}
///
/// Gets or sets the layout type for the nodes.
///
[Browsable(true),Category("Layout"),DefaultValue(eNodeLayout.Map),Description("Indicates layout type for the nodes.")]
public eNodeLayout LayoutType
{
get {return m_Layout;}
set
{
if(m_Layout!=value)
{
SetLayout(value);
}
}
}
///
/// Gets or sets whether automatic drag and drop is enabled. Default value is true.
///
[Browsable(true),Category("Behavior"),Description("Indicates whether automatic drag and drop is enabled."),DefaultValue(true)]
public bool DragDropEnabled
{
get {return m_DragDropEnabled;}
set {m_DragDropEnabled=value;}
}
///
/// Gets or sets whether anti-alias smoothing is used while painting the tree.
///
[DefaultValue(true),Browsable(true),Category("Appearance"),Description("Gets or sets whether anti-aliasing is used while painting the tree.")]
public bool AntiAlias
{
get {return m_AntiAlias;}
set
{
if(m_AntiAlias!=value)
{
m_AntiAlias=value;
this.Refresh();
}
}
}
///
/// Gets or sets the delimiter string that the tree node path uses.
///
[DefaultValue("\\"),Browsable(false),Description("Indicates the delimiter string that the tree node path uses.")]
public string PathSeparator
{
get{return m_PathSeparator;}
set{m_PathSeparator=value;}
}
///
/// Gets the collection of all column headers that appear in the tree.
///
///
/// By default there are no column headers defined. In that case tree control
/// functions as regular tree control where text has unrestricted width.
/// If you want to restrict the horizontal width of the text but not display
/// column header you can create one column and set its width to the width desired and
/// set its Visible property to false.
///
public ColumnHeaderCollection Columns
{
get
{
return m_Columns;
}
}
///
/// Gets the collection of all style elements created for the tree.
///
[Browsable(true),DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ElementStyleCollection Styles
{
get {return m_Styles;}
}
///
/// Gets or sets default style for the node cell.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates default style for the node cell.")]
public ElementStyle CellStyleDefault
{
get {return m_CellStyleDefault;}
set
{
if(m_CellStyleDefault!=value)
{
if(m_CellStyleDefault!=null)
m_CellStyleDefault.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_CellStyleDefault=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets or sets default style for the node cell when mouse is pressed.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates default style for the node cell when mouse is pressed.")]
public ElementStyle CellStyleMouseDown
{
get {return m_CellStyleMouseDown;}
set
{
if(m_CellStyleMouseDown!=value)
{
if(m_CellStyleMouseDown!=null)
m_CellStyleMouseDown.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_CellStyleMouseDown=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets or sets default style for the node cell when mouse is over the cell.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates default style for the node cell when mouse is over the cell.")]
public ElementStyle CellStyleMouseOver
{
get {return m_CellStyleMouseOver;}
set
{
if(m_CellStyleMouseOver!=value)
{
if(m_CellStyleMouseOver!=null)
m_CellStyleMouseOver.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_CellStyleMouseOver=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets or sets default style for the node cell when cell is selected.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates default style for the node cell when cell is selected.")]
public ElementStyle CellStyleSelected
{
get {return m_CellStyleSelected;}
set
{
if(m_CellStyleSelected!=value)
{
if(m_CellStyleSelected!=null)
m_CellStyleSelected.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_CellStyleSelected=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets or sets default style for the node cell when cell is disabled.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates default style for the node cell when cell is disabled.")]
public ElementStyle CellStyleDisabled
{
get {return m_CellStyleDisabled;}
set
{
if(m_CellStyleDisabled!=value)
{
if(m_CellStyleDisabled!=null)
m_CellStyleDisabled.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_CellStyleDisabled=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets or sets default style for the node when node is expanded.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Gets or sets default style for the node cell when node that cell belongs to is expanded.")]
public ElementStyle NodeStyleExpanded
{
get {return m_NodeStyleExpanded;}
set
{
if(m_NodeStyleExpanded!=value)
{
if(m_NodeStyleExpanded!=null)
m_NodeStyleExpanded.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_NodeStyleExpanded=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets or sets default style for all nodes where style is not specified
/// explicity.
///
///
/// Name of the style assigned or null value indicating that no style is used.
/// Default value is null.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Gets or sets default style for the node.")]
public ElementStyle NodeStyle
{
get {return m_NodeStyle;}
set
{
if(m_NodeStyle!=value)
{
if(m_NodeStyle!=null)
m_NodeStyle.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_NodeStyle=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets or sets style for the node when node is selected. Note that this style is applied to the default node style.
///
///
/// Reference to the style assigned or null value indicating that no style is used.
/// Default value is null.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Gets or sets style of the node when node is selected.")]
public ElementStyle NodeStyleSelected
{
get {return m_NodeStyleSelected;}
set
{
if(m_NodeStyleSelected!=value)
{
if(m_NodeStyleSelected!=null)
m_NodeStyleSelected.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_NodeStyleSelected=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets or sets style for the node when mouse is over node. Note that this style is applied to the default node style.
///
///
/// Reference to the style assigned or null value indicating that no style is used.
/// Default value is null.
///
[Browsable(true),Category("Node Style"),DefaultValue(null),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Gets or sets style of the node when mouse is over node.")]
public ElementStyle NodeStyleMouseOver
{
get {return m_NodeStyleMouseOver;}
set
{
if(m_NodeStyleMouseOver!=value)
{
if(m_NodeStyleMouseOver!=null)
m_NodeStyleMouseOver.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_NodeStyleMouseOver=value;
this.OnCellStyleChanged();
}
}
}
///
/// Gets the collection of tree nodes that are assigned to the tree view control.
///
///
/// A NodeCollection that represents the tree nodes
/// assigned to the tree control.
///
///
/// The Nodes property holds a collection of Node objects, each of which has a
/// Nodes property that can contain its own NodeCollection.
///
[Browsable(true),DesignerSerializationVisibility(DesignerSerializationVisibility.Content),Description("Gets the collection of tree nodes that are assigned to the tree control.")]
public NodeCollection Nodes
{
get {return m_Nodes;}
}
///
/// Gets or sets the default style class assigned to the column headers.
///
///
/// Reference to the style assigned to the column header.
///
///
/// When style is not set on ColumnHeader objects then style setting from this property is used instead.
///
/// ColumnStyleMouseDown Property
/// ColumnStyleMouseOver Property
[Browsable(true),DefaultValue(null),Category("Column Header Style"),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates the style class assigned to the column.")]
public ElementStyle ColumnStyleNormal
{
get {return m_ColumnStyleNormal;}
set
{
if(m_ColumnStyleNormal!=null)
m_ColumnStyleNormal.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_ColumnStyleNormal=value;
}
}
///
/// Gets or sets default style class assigned to the column which is applied when mouse
/// button is pressed over the header.
///
///
/// Name of the style assigned to the column.
///
///
/// When style is not set on ColumnHeader objects then style setting from this property is used instead.
///
/// ColumnStyleNormal Property
/// ColumnStyleMouseOver Property
[Browsable(true),DefaultValue(null),Category("Column Header Style"),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates the style class assigned to the column when mouse is down.")]
public ElementStyle ColumnStyleMouseDown
{
get {return m_ColumnStyleMouseDown;}
set
{
if(m_ColumnStyleMouseDown!=null)
m_ColumnStyleMouseDown.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_ColumnStyleMouseDown=value;
}
}
///
/// Gets or sets default style class assigned to the column which is applied when mouse is
/// over the column.
///
///
/// Name of the style assigned to the column.
///
///
/// When style is not set on ColumnHeader objects then style setting from this property is used instead.
///
/// ColumnStyleNormal Property
/// ColumnStyleMouseDown Property
[Browsable(true),DefaultValue(null),Category("Column Header Style"),Editor(typeof(Design.ElementStyleTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates the style class assigned to the cell when mouse is over the column.")]
public ElementStyle ColumnStyleMouseOver
{
get {return m_ColumnStyleMouseOver;}
set
{
if(m_ColumnStyleMouseOver!=null)
m_ColumnStyleMouseOver.StyleChanged-=new EventHandler(this.ElementStyleChanged);
if(value!=null)
value.StyleChanged+=new EventHandler(this.ElementStyleChanged);
m_ColumnStyleMouseOver=value;
}
}
///
/// Gets collection that holds definition of column headers associated with nodes.
///
[Browsable(true),DesignerSerializationVisibility(DesignerSerializationVisibility.Content),Description("Collection that holds definition of column headers associated with nodes.")]
public HeadersCollection Headers
{
get {return m_Headers;}
}
///
/// Gets or sets the tree node that is currently selected in the tree view control.
///
///
/// If no Node is currently selected, the
/// SelectedNode property is a null reference (Nothing in Visual
/// Basic).
///
[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Node SelectedNode
{
get {return m_SelectedNode;}
set
{
if(m_SelectedNode!=value)
{
SelectNode(value,eTreeAction.Code);
}
}
}
///
/// Invalidates node bounds on canvas.
///
/// Reference node.
internal void InvalidateNode(Node node)
{
if(node==null)
return;
Rectangle r;
//if(node.Parent!=null)
if(node==m_DragNode && m_DragNode.Parent==null)
r=m_DragNode.BoundsRelative;
else
r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeContentBounds,node,m_NodeDisplay.Offset);
//else
// r=node.Bounds;
if(m_SelectionBox)
r.Inflate(m_SelectionBoxSize,m_SelectionBoxSize);
r = GetScreenRectangle(r);
this.Invalidate(r);
}
///
/// Returns reference to node layout object.
///
internal Layout.NodeLayout NodeLayout
{
get {return m_NodeLayout;}
}
///
/// Returns reference to node display object.
///
internal NodeDisplay NodeDisplay
{
get {return m_NodeDisplay;}
}
///
/// Gets whether layout is suspended for tree control. Layout is suspended after
/// call to BeginUpdate method and it is resumed after the
/// call to EndUpdate method.
///
[Browsable(false)]
public bool IsUpdateSuspended
{
get {return (m_UpdateSuspended>0);}
}
internal void SetPendingLayout()
{
m_PendingLayout = true;
}
///
/// Gets or sets whether paint operations are suspended for the control. You should use this method
/// if you need the RecalcLayout operations to proceed but you want to stop painting of the control.
///
[Browsable(false)]
public bool SuspendPaint
{
get {return m_SuspendPaint;}
set {m_SuspendPaint=value;}
}
///
/// Gets or sets the ImageList that contains the Image objects used by the tree nodes.
///
[Browsable(true),DefaultValue(null),Category("Images"),Description("Indicates the ImageList that contains the Image objects used by the tree nodes.")]
public ImageList ImageList
{
get
{
return m_ImageList;
}
set
{
if(m_ImageList!=null)
m_ImageList.Disposed-=new EventHandler(this.ImageListDisposed);
m_ImageList=value;
if(m_ImageList!=null)
m_ImageList.Disposed+=new EventHandler(this.ImageListDisposed);
}
}
///
/// Gets or sets the image-list index value of the default image that is displayed by the tree nodes.
///
[Browsable(true),Category("Images"),Description("Indicates the image-list index value of the default image that is displayed by the tree nodes."),Editor(typeof(ImageIndexEditor), typeof(System.Drawing.Design.UITypeEditor)),TypeConverter(typeof(ImageIndexConverter)),DefaultValue(-1)]
public int ImageIndex
{
get {return m_ImageIndex;}
set
{
if(m_ImageIndex!=value)
{
m_ImageIndex=value;
}
}
}
///
/// Gets or sets the NodeConnector object that describes the type of the connector used for
/// displaying connection between root node and it's nested nodes. The root node is defined as
/// the top level node i.e. which belongs directly to TreeGX.Nodes collection. Default value is null.
///
///
/// You can use
/// Node.ParentConnector
/// property to specify per node connectors.
///
[Browsable(true),Category("Connectors"),DefaultValue(null),Editor(typeof(Design.NodeConnectorTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates the root node connector.")]
public NodeConnector RootConnector
{
get {return m_RootConnector;}
set
{
if(m_RootConnector!=value)
{
if(m_RootConnector!=null)
m_RootConnector.AppearanceChanged-=new EventHandler(this.ConnectorAppearanceChanged);
if(value!=null)
value.AppearanceChanged+=new EventHandler(this.ConnectorAppearanceChanged);
m_RootConnector=value;
this.OnDisplayChanged();
}
}
}
///
/// Gets or sets the NodeConnector object that describes the type of the connector used for
/// displaying connection between nested nodes. RootConnector property specifies the connector
/// between root node and it's imidate nested nodes. This property specifies connector for all other nested levels.
/// Default value is null.
///
///
/// You can use
/// Node.ParentConnector
/// property to specify per node connectors.
///
[Browsable(true),Category("Connectors"),DefaultValue(null),Editor(typeof(Design.NodeConnectorTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates the nested nodes connector.")]
public NodeConnector NodesConnector
{
get {return m_NodesConnector;}
set
{
if(m_NodesConnector!=value)
{
if(m_NodesConnector!=null)
m_NodesConnector.AppearanceChanged-=new EventHandler(this.ConnectorAppearanceChanged);
if(value!=null)
value.AppearanceChanged+=new EventHandler(this.ConnectorAppearanceChanged);
m_NodesConnector=value;
this.OnDisplayChanged();
}
}
}
///
/// Gets or sets the NodeConnector object that describes the type of the connector used for
/// displaying connection between linked nodes. This property specifies connector for all linked nodes.
/// Default value is null.
///
[Browsable(true),Category("Connectors"),DefaultValue(null),Editor(typeof(Design.NodeConnectorTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates the linked nodes connector.")]
public NodeConnector LinkConnector
{
get {return m_LinkConnector;}
set
{
if(m_LinkConnector!=value)
{
if(m_LinkConnector!=null)
m_LinkConnector.AppearanceChanged-=new EventHandler(this.ConnectorAppearanceChanged);
if(value!=null)
value.AppearanceChanged+=new EventHandler(this.ConnectorAppearanceChanged);
m_LinkConnector=value;
this.OnDisplayChanged();
}
}
}
///
/// Gets or sets the NodeConnector object that describes the type of the connector used for
/// displaying connection between linked nodes. Connector specified here is used to display the connection
/// between nodes that are on the path to the selected node. When set you can use it to visually indicate the path to the currently selected node.
/// Default value is null.
///
[Browsable(true),Category("Connectors"),DefaultValue(null),Editor(typeof(Design.NodeConnectorTypeEditor),typeof(System.Drawing.Design.UITypeEditor)),Description("Indicates the linked nodes connector.")]
public NodeConnector SelectedPathConnector
{
get {return m_SelectedPathConnector;}
set
{
if(m_SelectedPathConnector!=value)
{
if(m_SelectedPathConnector!=null)
m_SelectedPathConnector.AppearanceChanged-=new EventHandler(this.ConnectorAppearanceChanged);
if(value!=null)
value.AppearanceChanged+=new EventHandler(this.ConnectorAppearanceChanged);
m_SelectedPathConnector=value;
this.OnDisplayChanged();
}
}
}
///
/// Gets or sets the layout of the cells inside the node. Default value is Horizontal layout which
/// means that cell are positioned horizontally next to each other.
///
///
/// You can specify cell layout on each node by using
/// Node.CellLayout
/// property.
///
[Browsable(true),DefaultValue(eCellLayout.Default),Category("Appearance"),Description("Indicates layout of the cells inside the node.")]
public eCellLayout CellLayout
{
get {return m_CellLayout;}
set
{
m_CellLayout=value;
this.RecalcLayout();
this.Refresh();
}
}
///
/// Gets or sets the layout of the cells inside the node. Default value is Horizontal layout which
/// means that cell are positioned horizontally next to each other.
///
///
/// You can specify cell layout on each node by using
/// Node.CellLayout
/// property.
///
[Browsable(true),DefaultValue(eCellPartLayout.Default),Category("Appearance"),Description("Indicates layout of the cells inside the node.")]
public eCellPartLayout CellPartLayout
{
get {return m_CellPartLayout;}
set
{
m_CellPartLayout=value;
this.RecalcLayout();
this.Refresh();
}
}
///
/// Gets or sets the color scheme style. Color scheme provides predefined colors based on popular visual styles.
/// We recommend that you use "SchemePart" color settings since they maintain consistant look that is
/// based on target system color scheme setting.
///
[Browsable(true),DefaultValue(eColorSchemeStyle.Office2003),Category("Appearance"),Description("Indicates the color scheme style.")]
public eColorSchemeStyle ColorSchemeStyle
{
get {return m_ColorScheme.Style;}
set
{
m_ColorScheme.Style=value;
if(this.DesignMode)
this.Refresh();
}
}
///
/// Gets the reference to the color scheme object.
///
internal ColorScheme ColorScheme
{
get {return m_ColorScheme;}
}
///
/// Gets or sets whether the content of the control is centered within the bounds of control. Default value is true.
///
[Browsable(true),DefaultValue(true),Description("Indicates whether the content of the control is centered within the bounds of control."),Category("Layout")]
public bool CenterContent
{
get {return m_CenterContent;}
set
{
m_CenterContent=value;
OnLayoutChanged();
}
}
///
/// Gets or sets the value that indicates whether selection box is drawn around the
/// selected node. Default value is true. Another way to provide the visual indication that
/// node is selected is by using selected state style properties like
/// NodeStyleSelected
/// and
/// CellStyleSelected.
///
/// CellStyleSelected Property
/// NodeStyleSelected Property
[Browsable(true),DefaultValue(true),Category("Selected Node"),Description("Indicates whether selection box is drawn around selected node.")]
public bool SelectionBox
{
get {return m_SelectionBox;}
set
{
if(m_SelectionBox!=value)
{
m_SelectionBox=value;
this.OnSelectionBoxChanged();
}
}
}
///
/// Gets or sets the size/thickness in pixel of the selection box drawn around selected
/// node.
///
[Browsable(true),DefaultValue(4),Category("Selected Node"),Description("Indicates the size in pixels of the selection box drawn around selected node.")]
public int SelectionBoxSize
{
get {return m_SelectionBoxSize;}
set
{
if(m_SelectionBoxSize!=value)
{
m_SelectionBoxSize=value;
this.OnSelectionBoxChanged();
}
}
}
///
/// Gets or sets the selection box border color.
///
[Browsable(true),Category("Selected Node"),Description("Indicates the selection box border color.")]
public Color SelectionBoxBorderColor
{
get {return m_SelectionBoxBorderColor;}
set
{
if(m_SelectionBoxBorderColor!=value)
{
m_SelectionBoxBorderColor=value;
this.OnSelectionBoxChanged();
}
}
}
///
/// Indicates whether SelectionBoxBorderColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeSelectionBoxBorderColor()
{return (m_SelectionBoxBorderColor!=GetDefaultSelectionBoxBorderColor());}
///
/// Resets SelectionBoxBorderColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetSelectionBoxBorderColor()
{
m_SelectionBoxBorderColor=GetDefaultSelectionBoxBorderColor();
}
///
/// Gets or sets the selection box fill color.
///
[Browsable(true),Category("Selected Node"),Description("Indicates the selection box fill color.")]
public Color SelectionBoxFillColor
{
get {return m_SelectionBoxFillColor;}
set
{
if(m_SelectionBoxFillColor!=value)
{
m_SelectionBoxFillColor=value;
this.OnSelectionBoxChanged();
}
}
}
///
/// Indicates whether SelectionBoxFillColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeSelectionBoxFillColor()
{return (m_SelectionBoxFillColor!=GetDefaultSelectionBoxFillColor());}
///
/// Resets SelectionBoxFillColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetSelectionBoxFillColor()
{
m_SelectionBoxFillColor=GetDefaultSelectionBoxFillColor();
}
///
/// Gets or sets the size of the expand button that is used to expand/collapse node. Default value is 8,8.
///
[Browsable(true),Category("Expand Button"),Description("Indicates size of the expand button that is used to expand/collapse node.")]
public Size ExpandButtonSize
{
get {return m_ExpandButtonSize;}
set
{
if(m_ExpandButtonSize!=value && !m_ExpandButtonSize.IsEmpty)
{
m_ExpandButtonSize=value;
this.OnExpandButtonChanged();
}
}
}
///
/// Indicates whether SelectionBoxFillColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeExpandButtonSize()
{return (m_ExpandButtonSize!=GetDefaultExpandButtonSize());}
///
/// Resets SelectionBoxFillColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetExpandButtonSize()
{
this.ExpandButtonSize=GetDefaultExpandButtonSize();
}
///
/// Gets or sets expand button border color. Note that setting ExpandBorderColorSchemePart property will override the value that you set here.
///
[Browsable(true),Category("Expand Button"),Description("Indicates expand button border color.")]
public Color ExpandBorderColor
{
get {return m_ExpandBorderColor;}
set
{
m_ExpandBorderColor=value;
this.OnExpandButtonChanged();
}
}
///
/// Indicates whether ExpandBorderColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeExpandBorderColor()
{return (!m_ExpandBorderColor.IsEmpty && m_ExpandBorderColorSchemePart==eColorSchemePart.None);}
///
/// Resets ExpandBorderColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetExpandBorderColor()
{
this.ExpandBorderColor=Color.Empty;
}
///
/// Gets or sets expand button color scheme border color. Setting
/// this property overrides the setting of the corresponding ExpandBorderColor property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through ExpandBorderColor property.
///
[Browsable(true),Category("Expand Button"),DefaultValue(eColorSchemePart.BarDockedBorder),Description("Indicates expand button border color.")]
public eColorSchemePart ExpandBorderColorSchemePart
{
get {return m_ExpandBorderColorSchemePart;}
set
{
m_ExpandBorderColorSchemePart=value;
this.OnExpandButtonChanged();
}
}
///
/// Gets or sets expand button back color. Note that setting ExpandBackColorSchemePart property will override the value that you set here.
///
[Browsable(true),Category("Expand Button"),Description("Indicates expand button back color.")]
public Color ExpandBackColor
{
get {return m_ExpandBackColor;}
set
{
m_ExpandBackColor=value;
this.OnExpandButtonChanged();
}
}
///
/// Indicates whether ExpandBackColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeExpandBackColor()
{return (!m_ExpandBackColor.IsEmpty && m_ExpandBackColorSchemePart==eColorSchemePart.None);}
///
/// Resets ExpandBackColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetExpandBackColor()
{
this.ExpandBackColor=Color.Empty;
}
///
/// Gets or sets expand button color scheme back color. Setting
/// this property overrides the setting of the corresponding ExpandBackColor property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through ExpandBackColor property.
///
[Browsable(true),Category("Expand Button"),DefaultValue(eColorSchemePart.None),Description("Indicates expand button back color.")]
public eColorSchemePart ExpandBackColorSchemePart
{
get {return m_ExpandBackColorSchemePart;}
set
{
m_ExpandBackColorSchemePart=value;
this.OnExpandButtonChanged();
}
}
///
/// Gets or sets expand button target gradientback color. Note that setting ExpandBackColor2SchemePart property will override the value that you set here.
///
[Browsable(true),Category("Expand Button"),Description("Indicates expand button target gradient back color.")]
public Color ExpandBackColor2
{
get {return m_ExpandBackColor2;}
set
{
m_ExpandBackColor2=value;
this.OnExpandButtonChanged();
}
}
///
/// Indicates whether ExpandBackColor2 should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeExpandBackColor2()
{return (!m_ExpandBackColor2.IsEmpty && m_ExpandBackColor2SchemePart==eColorSchemePart.None);}
///
/// Resets ExpandBackColor2 to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetExpandBackColor2()
{
this.ExpandBackColor2=Color.Empty;
}
///
/// Gets or sets expand button color scheme target gradient back color. Setting
/// this property overrides the setting of the corresponding ExpandBackColor2 property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through ExpandBackColor2 property.
///
[Browsable(true),Category("Expand Button"),DefaultValue(eColorSchemePart.None),Description("Indicates expand button target gradient back color.")]
public eColorSchemePart ExpandBackColor2SchemePart
{
get {return m_ExpandBackColor2SchemePart;}
set
{
m_ExpandBackColor2SchemePart=value;
this.OnExpandButtonChanged();
}
}
///
/// Gets or sets expand button line color. Note that setting ExpandLineColorSchemePart property will override the value that you set here.
///
[Browsable(true),Category("Expand Button"),Description("Indicates expand button line color.")]
public Color ExpandLineColor
{
get {return m_ExpandLineColor;}
set
{
m_ExpandLineColor=value;
this.OnExpandButtonChanged();
}
}
///
/// Indicates whether ExpandLineColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeExpandLineColor()
{return (!m_ExpandLineColor.IsEmpty && m_ExpandLineColorSchemePart==eColorSchemePart.None);}
///
/// Resets ExpandLineColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetExpandLineColor()
{
this.ExpandLineColor=Color.Empty;
}
///
/// Gets or sets expand button color scheme line color. Setting
/// this property overrides the setting of the corresponding ExpandLineColor property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through ExpandLineColor property.
///
[Browsable(true),Category("Expand Button"),DefaultValue(eColorSchemePart.None),Description("Indicates expand button line color.")]
public eColorSchemePart ExpandLineColorSchemePart
{
get {return m_ExpandLineColorSchemePart;}
set
{
m_ExpandLineColorSchemePart=value;
this.OnExpandButtonChanged();
}
}
///
/// Gets or sets the expand button background gradient angle.
///
[Browsable(true),Category("Expand Button"),DefaultValue(0),Description("Indicates expand button background gradient angle.")]
public int ExpandBackColorGradientAngle
{
get
{
return m_ExpandBackColorGradientAngle;
}
set
{
if(m_ExpandBackColorGradientAngle!=value)
{
m_ExpandBackColorGradientAngle=value;
this.OnExpandButtonChanged();
}
}
}
///
/// Gets or sets the expand button image which is used to indicate that node will be expanded. To use images as expand buttons you also need to set ExpandButtonType=eExpandButtonType.Image.
///
[Browsable(true),DefaultValue(null),Description("Indicates expand button image which is used to indicate that node will be expanded."),Category("Expand Button")]
public Image ExpandImage
{
get {return m_ExpandImage;}
set
{
if(m_ExpandImage!=value)
{
m_ExpandImage=value;
if(m_ExpandButtonType==eExpandButtonType.Image)
this.OnExpandButtonChanged();
}
}
}
///
/// Gets or sets the expand button image which is used to indicate that node will be collapsed. To use images as expand buttons you also need to set ExpandButtonType=eExpandButtonType.Image.
///
[Browsable(true),DefaultValue(null),Description("Indicates expand button image which is used to indicate that node will be collapsed."),Category("Expand Button")]
public Image ExpandImageCollapse
{
get {return m_ExpandImageCollapse;}
set
{
if(m_ExpandImageCollapse!=value)
{
m_ExpandImageCollapse=value;
if(m_ExpandButtonType==eExpandButtonType.Image)
this.OnExpandButtonChanged();
}
}
}
///
/// Gets or sets the type of the expand button used to expand/collapse nodes.
///
[Browsable(true),DefaultValue(eExpandButtonType.Ellipse),Category("Expand Button"),Description("Indicates type of the expand button used to expand/collapse nodes.")]
public eExpandButtonType ExpandButtonType
{
get {return m_ExpandButtonType;}
set
{
if(m_ExpandButtonType!=value)
{
m_ExpandButtonType=value;
this.OnExpandButtonChanged();
}
}
}
///
/// Gets or sets the display root node. For example in Map or Diagram layout single node
/// is always used as root node for display. Setting this property allows you to use any
/// Node as root display node. Default value is Null which means that first node from
/// TreeGX.Nodes collection is used as display root node.
///
[Browsable(true),DefaultValue(null),Category("Appearance"),Description("Indicates display root node.")]
public Node DisplayRootNode
{
get {return m_DisplayRootNode;}
set
{
if(m_DisplayRootNode!=value)
{
m_DisplayRootNode=value;
InvalidateNodesSize();
this.RecalcLayout();
this.Refresh();
}
}
}
///
/// Gets or sets the width of the command button. Default value is 10 pixels.
///
[Browsable(true),Category("Command Button"),DefaultValue(10),Description("Indicates width of the command button.")]
public int CommandWidth
{
get{return m_CommandWidth;}
set
{
m_CommandWidth=value;
OnCommandButtonChanged();
}
}
///
/// Gets or sets command button back color. Note that setting CommandBackColorSchemePart property will override the value that you set here.
///
[Browsable(true),Category("Command Button"),Description("Indicates command button back color.")]
public Color CommandBackColor
{
get {return m_CommandBackColor;}
set
{
m_CommandBackColor=value;
this.OnCommandButtonChanged();
}
}
///
/// Indicates whether CommandBackColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeCommandBackColor()
{return (!m_CommandBackColor.IsEmpty && m_CommandBackColorSchemePart==eColorSchemePart.None);}
///
/// Resets CommandBackColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetCommandBackColor()
{
this.CommandBackColor=Color.Empty;
}
///
/// Gets or sets command button color scheme back color. Setting
/// this property overrides the setting of the corresponding CommandBackColor property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through CommandBackColor property.
///
[Browsable(true),Category("Command Button"),DefaultValue(eColorSchemePart.CustomizeBackground),Description("Indicates command button back color.")]
public eColorSchemePart CommandBackColorSchemePart
{
get {return m_CommandBackColorSchemePart;}
set
{
m_CommandBackColorSchemePart=value;
this.OnCommandButtonChanged();
}
}
///
/// Gets or sets command button target gradient back color. Note that setting CommandBackColor2SchemePart property will override the value that you set here.
///
[Browsable(true),Category("Command Button"),Description("Indicates command button target gradient back color.")]
public Color CommandBackColor2
{
get {return m_CommandBackColor2;}
set
{
m_CommandBackColor2=value;
this.OnCommandButtonChanged();
}
}
///
/// Indicates whether CommandBackColor2 should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeCommandBackColor2()
{return (!m_CommandBackColor2.IsEmpty && m_CommandBackColor2SchemePart==eColorSchemePart.None);}
///
/// Resets CommandBackColor2 to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetCommandBackColor2()
{
this.CommandBackColor2=Color.Empty;
}
///
/// Gets or sets command button color scheme target gradient back color. Setting
/// this property overrides the setting of the corresponding CommandBackColor2 property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through CommandBackColor2 property.
///
[Browsable(true),Category("Command Button"),DefaultValue(eColorSchemePart.CustomizeBackground2),Description("Indicates command button target gradient back color.")]
public eColorSchemePart CommandBackColor2SchemePart
{
get {return m_CommandBackColor2SchemePart;}
set
{
m_CommandBackColor2SchemePart=value;
this.OnCommandButtonChanged();
}
}
///
/// Gets or sets command button foreground color. Note that setting CommandForeColorSchemePart property will override the value that you set here.
///
[Browsable(true),Category("Command Button"),Description("Indicates command button fore color.")]
public Color CommandForeColor
{
get {return m_CommandForeColor;}
set
{
m_CommandForeColor=value;
this.OnCommandButtonChanged();
}
}
///
/// Indicates whether CommandForeColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeCommandForeColor()
{return (!m_CommandForeColor.IsEmpty && m_CommandForeColorSchemePart==eColorSchemePart.None);}
///
/// Resets CommandForeColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetCommandForeColor()
{
this.CommandForeColor=Color.Empty;
}
///
/// Gets or sets command button color scheme foreground color. Setting
/// this property overrides the setting of the corresponding CommandForeColor property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through CommandForeColor property.
///
[Browsable(true),Category("Command Button"),DefaultValue(eColorSchemePart.CustomizeText),Description("Indicates command button foreground color.")]
public eColorSchemePart CommandForeColorSchemePart
{
get {return m_CommandForeColorSchemePart;}
set
{
m_CommandForeColorSchemePart=value;
this.OnCommandButtonChanged();
}
}
///
/// Gets or sets the command button background gradient angle.
///
[Browsable(true),Category("Expand Button"),DefaultValue(0),Description("Indicates command button background gradient angle.")]
public int CommandBackColorGradientAngle
{
get
{
return m_CommandBackColorGradientAngle;
}
set
{
if(m_CommandBackColorGradientAngle!=value)
{
m_CommandBackColorGradientAngle=value;
this.OnExpandButtonChanged();
}
}
}
///
/// Gets or sets command button mouse over back color. Note that setting CommandMouseOverBackColorSchemePart property will override the value that you set here.
///
[Browsable(true),Category("Command Button"),Description("Indicates command button mouse over back color.")]
public Color CommandMouseOverBackColor
{
get {return m_CommandMouseOverBackColor;}
set
{
m_CommandMouseOverBackColor=value;
this.OnCommandButtonChanged();
}
}
///
/// Indicates whether CommandMouseOverBackColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeCommandMouseOverBackColor()
{return (!m_CommandMouseOverBackColor.IsEmpty && m_CommandMouseOverBackColorSchemePart==eColorSchemePart.None);}
///
/// Resets CommandMouseOverBackColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetCommandMouseOverBackColor()
{
this.CommandMouseOverBackColor=Color.Empty;
}
///
/// Gets or sets command button color scheme mouse over back color. Setting
/// this property overrides the setting of the corresponding CommandMouseOverBackColor property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through CommandMouseOverBackColor property.
///
[Browsable(true),Category("Command Button"),DefaultValue(eColorSchemePart.ItemHotBackground),Description("Indicates command button mouse over back color.")]
public eColorSchemePart CommandMouseOverBackColorSchemePart
{
get {return m_CommandMouseOverBackColorSchemePart;}
set
{
m_CommandMouseOverBackColorSchemePart=value;
this.OnCommandButtonChanged();
}
}
///
/// Gets or sets command button mouse over target gradient back color. Note that setting CommandMouseOverBackColor2SchemePart property will override the value that you set here.
///
[Browsable(true),Category("Command Button"),Description("Indicates command button mouse over target gradient back color.")]
public Color CommandMouseOverBackColor2
{
get {return m_CommandMouseOverBackColor2;}
set
{
m_CommandMouseOverBackColor2=value;
this.OnCommandButtonChanged();
}
}
///
/// Indicates whether CommandMouseOverBackColor2 should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeCommandMouseOverBackColor2()
{return (!m_CommandMouseOverBackColor2.IsEmpty && m_CommandMouseOverBackColor2SchemePart==eColorSchemePart.None);}
///
/// Resets CommandMouseOverBackColor2 to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetCommandMouseOverBackColor2()
{
this.CommandMouseOverBackColor2=Color.Empty;
}
///
/// Gets or sets command button mouse over color scheme target gradient back color. Setting
/// this property overrides the setting of the corresponding CommandMouseOverBackColor2 property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through CommandMouseOverBackColor2 property.
///
[Browsable(true),Category("Command Button"),DefaultValue(eColorSchemePart.ItemPressedBackground2),Description("Indicates command button mouse over target gradient back color.")]
public eColorSchemePart CommandMouseOverBackColor2SchemePart
{
get {return m_CommandMouseOverBackColor2SchemePart;}
set
{
m_CommandMouseOverBackColor2SchemePart=value;
this.OnCommandButtonChanged();
}
}
///
/// Gets or sets command button mouse over foreground color. Note that setting CommandMouseOverForeColorSchemePart property will override the value that you set here.
///
[Browsable(true),Category("Command Button"),Description("Indicates command button mouse over fore color.")]
public Color CommandMouseOverForeColor
{
get {return m_CommandMouseOverForeColor;}
set
{
m_CommandMouseOverForeColor=value;
this.OnCommandButtonChanged();
}
}
///
/// Indicates whether CommandMouseOverForeColor should be serialized. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeCommandMouseOverForeColor()
{return (!m_CommandMouseOverForeColor.IsEmpty && m_CommandMouseOverForeColorSchemePart==eColorSchemePart.None);}
///
/// Resets CommandMouseOverForeColor to it's default value. Used by windows forms designer design-time support.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetCommandMouseOverForeColor()
{
this.CommandMouseOverForeColor=Color.Empty;
}
///
/// Gets or sets command button mouse over color scheme foreground color. Setting
/// this property overrides the setting of the corresponding CommandMouseOverForeColor property.
/// Color scheme colors are automatically managed and are based on current system colors.
/// That means if colors on the system change the color scheme will ensure that it's colors
/// are changed as well to fit in the color scheme of target system. Set this property to
/// eColorSchemePart.None to
/// specify explicit color to use through CommandMouseOverForeColor property.
///
[Browsable(true),Category("Command Button"),DefaultValue(eColorSchemePart.ItemHotText),Description("Indicates command button mouse over foreground color.")]
public eColorSchemePart CommandMouseOverForeColorSchemePart
{
get {return m_CommandMouseOverForeColorSchemePart;}
set
{
m_CommandMouseOverForeColorSchemePart=value;
this.OnCommandButtonChanged();
}
}
///
/// Gets or sets the command button mouse over background gradient angle.
///
[Browsable(true),Category("Expand Button"),DefaultValue(0),Description("Indicates command button mouse over background gradient angle.")]
public int CommandMouseOverBackColorGradientAngle
{
get
{
return m_CommandMouseOverBackColorGradientAngle;
}
set
{
if(m_CommandMouseOverBackColorGradientAngle!=value)
{
m_CommandMouseOverBackColorGradientAngle=value;
this.OnExpandButtonChanged();
}
}
}
///
/// Gets or sets a value indicating whether the label text of the node cells can be edited. Default value is false.
///
[Browsable(true),DefaultValue(false),Description("Indicates whether the label text of the node cells can be edited."),Category("Editing")]
public bool CellEdit
{
get {return m_CellEdit;}
set {m_CellEdit=value;}
}
///
/// Returns whether cell editing is in progress.
///
[Browsable(false)]
public bool IsCellEditing
{
get {return m_CellEditing;}
}
#endregion
#region Private implementation
protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
{
Dpi.SetScaling(factor);
ScaleHostedControls(factor);
this.InvalidateNodesSize();
base.ScaleControl(factor, specified);
}
private void ScaleHostedControls(SizeF factor)
{
foreach (Cell cell in m_HostedControlCells)
{
System.Windows.Forms.Control cellHostedControl = cell.HostedControl;
if (cellHostedControl == null) continue;
cellHostedControl.Scale(factor);
}
}
protected override bool ScaleChildren
{
get { return false; }
}
///
/// Returns color scheme part color if set otherwise returns color passed in.
///
/// Color.
/// Color scheme part.
/// Color.
internal Color GetColor(Color color, eColorSchemePart p)
{
if(p==eColorSchemePart.None)
return color;
ColorScheme cs=this.ColorScheme;
if(cs==null)
return color;
return (Color)cs.GetType().GetProperty(p.ToString()).GetValue(cs,null);
}
private void OnExpandButtonChanged()
{
m_NodeLayout.ExpandPartSize=m_ExpandButtonSize;
this.InvalidateNodesSize();
this.RecalcLayout();
this.Refresh();
}
private Size GetDefaultExpandButtonSize()
{
return m_DefaultExpandPartSize;
}
private void ElementStyleChanged(object sender, EventArgs e)
{
this.InvalidateNodesSize();
if(this.DesignMode)
this.RecalcLayout();
this.OnDisplayChanged();
}
private void OnDisplayChanged()
{
if(this.DesignMode)
this.Refresh();
}
private void OnLayoutChanged()
{
m_NodeLayout.NodeHorizontalSpacing=m_NodeHorizontalSpacing;
m_NodeLayout.NodeVerticalSpacing=m_NodeVerticalSpacing;
// Layout specific properties
if(m_Layout==eNodeLayout.Diagram)
{
Layout.NodeDiagramLayout nd=m_NodeLayout as Layout.NodeDiagramLayout;
nd.DiagramFlow=m_DiagramLayoutFlow;
}
else if(m_Layout==eNodeLayout.Map)
{
NodeMapLayout nd=m_NodeLayout as NodeMapLayout;
nd.MapFlow=m_MapLayoutFlow;
}
this.RecalcLayout();
OnDisplayChanged();
}
private void ConnectorAppearanceChanged(object sender, EventArgs e)
{
OnDisplayChanged();
}
private void SetLayout(eNodeLayout layout)
{
m_Layout=layout;
if(m_Layout==eNodeLayout.Map)
{
m_NodeLayout=new NodeMapLayout(this,this.ClientRectangle);
}
else if(m_Layout==eNodeLayout.Diagram)
{
m_NodeLayout=new Layout.NodeDiagramLayout(this,this.ClientRectangle);
}
InvalidateNodesSize();
OnLayoutChanged();
}
private void PaintStyleBackground(Graphics g)
{
Display.NodeRenderer renderer = this.NodeRenderer;
if(renderer!=null)
{
this.NodeRenderer.DrawTreeBackground(new TreeBackgroundRendererEventArgs(g, this));
return;
}
if(!this.BackColor.IsEmpty)
{
using(SolidBrush brush=new SolidBrush(this.BackColor))
g.FillRectangle(brush,this.DisplayRectangle);
}
ElementStyleDisplayInfo info=new ElementStyleDisplayInfo();
info.Bounds=this.DisplayRectangle;
info.Graphics=g;
info.Style=m_BackgroundStyle;
ElementStyleDisplay.Paint(info);
}
protected override void OnPaint(PaintEventArgs e)
{
if(this.SuspendPaint)
return;
if(m_PendingLayout)
{
this.RecalcLayout();
}
if(this.BackColor.A<255)
{
base.OnPaintBackground(e);
}
Graphics g=e.Graphics;
PaintStyleBackground(g);
Point offset=Point.Empty;
bool setOffset=false;
if(this.AutoScroll)
{
offset = GetAutoScrollPositionOffset();
setOffset=true;
}
if(m_AntiAlias)
{
g.SmoothingMode=System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
}
PaintTree(g, e.ClipRectangle, offset, setOffset, m_ZoomFactor);
base.OnPaint(e);
}
internal Rectangle GetInnerRectangle()
{
Rectangle r = ElementStyleLayout.GetInnerRect(this.BackgroundStyle, this.ClientRectangle);
return r;
}
internal Point GetAutoScrollPositionOffset()
{
Point p = this.AutoScrollPosition;
p.Y += this.SelectionBoxSize;
p.X += this.SelectionBoxSize;
return p;
}
private void PaintTree(Graphics g, Rectangle clipRectangle, Point offset, bool setOffset, float zoomFactor)
{
#if TRIAL
if(NodeOperations.ColorExpAlt())
{
StringFormat format=new StringFormat(StringFormat.GenericDefault);
format.Alignment=StringAlignment.Center;
format.FormatFlags=format.FormatFlags & ~(format.FormatFlags & StringFormatFlags.NoWrap);
g.DrawString("Thank you very much for trying TreeGX. Unfortunately your trial period is over. To continue using TreeGX you should purchase license at http://www.devcomponents.com",new Font(this.Font.FontFamily,12),SystemBrushes.Highlight,this.ClientRectangle,format);
format.Dispose();
return;
}
#else
if(NodeOperations.keyValidated2!=114)
{
Font trial=new Font(this.Font.FontFamily,7);
SolidBrush brushTrial = new SolidBrush(Color.FromArgb(200, SystemColors.Highlight));
StringFormat format=new StringFormat(StringFormat.GenericDefault);
format.Alignment=StringAlignment.Center;
g.DrawString("TreeGX license not found. Please purchase license at http://www.devcomponents.com",
trial, brushTrial, this.DisplayRectangle.X+this.DisplayRectangle.Width/2, this.DisplayRectangle.Bottom - 14, format);
brushTrial.Dispose();
format.Dispose();
trial.Dispose();
}
#endif
//Creates the drawing matrix with the right zoom;
if(zoomFactor!=1)
{
System.Drawing.Drawing2D.Matrix mx = GetTranslationMatrix(zoomFactor);
//use it for drawing
g.Transform=mx;
// Translate ClipRectangle
clipRectangle = GetLayoutRectangle(clipRectangle);
}
if(setOffset)
{
m_NodeDisplay.Offset = offset;
}
m_NodeDisplay.Paint(g,clipRectangle);
#if TRIAL
Font trial=new Font(this.Font.FontFamily,7);
SolidBrush brushTrial = new SolidBrush(Color.FromArgb(220, SystemColors.Highlight));
StringFormat formatTrial=new StringFormat(StringFormat.GenericDefault);
formatTrial.Alignment=StringAlignment.Center;
g.DrawString("Thank you for trying TreeGX. Please purchase license at http://www.devcomponents.com",
trial, brushTrial, this.DisplayRectangle.X+this.DisplayRectangle.Width/2, this.DisplayRectangle.Bottom - 14, formatTrial);
brushTrial.Dispose();
formatTrial.Dispose();
trial.Dispose();
#endif
}
///
/// Paints control to canvas. This method might be used for print output.
///
/// Graphics object to paint control to.
/// Indicates whether to paint control background.
public void PaintTo(Graphics g, bool background)
{
PaintTo(g, background, Rectangle.Empty);
}
///
/// Paints control to canvas. This method might be used for print output.
///
/// Graphics object to paint control to.
/// Indicates whether to paint control background.
/// Indicates clipping rectangle. Nodes outside of clipping rectangle will not be painted. You can pass Rectangle.Empty and all nodes will be painted.
public void PaintTo(Graphics g, bool background, Rectangle clipRectangle)
{
if(background)
PaintStyleBackground(g);
Point lockedOffset=m_NodeDisplay.GetLockedOffset();
Point offsetDisplay = m_NodeDisplay.Offset;
Point offset=Point.Empty;
m_NodeLayout.Graphics = g;
try
{
m_NodeLayout.PerformLayout();
}
finally
{
m_NodeLayout.Graphics = null;
}
Node displayNode=this.GetDisplayRootNode();
if(displayNode!=null)
{
if(this.NodeLayout is NodeMapLayout)
{
offset = new Point(Math.Abs(displayNode.ChildNodesBounds.Left),Math.Abs(displayNode.ChildNodesBounds.Top));
}
}
m_NodeDisplay.SetLockedOffset(offset);
try
{
PaintTree(g, clipRectangle, Point.Empty, true, 1f);
}
finally
{
m_NodeLayout.PerformLayout();
m_NodeDisplay.SetLockedOffset(lockedOffset);
if(lockedOffset.IsEmpty)
m_NodeDisplay.Offset = offsetDisplay;
}
}
protected override void OnRightToLeftChanged(EventArgs e)
{
this.RecalcLayout();
base.OnRightToLeftChanged(e);
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated (e);
#if TRIAL
if(!this.DesignMode)
{
Design.ComponentNotLicensed f = new Design.ComponentNotLicensed();
f.ShowDialog();
f.Dispose();
}
#endif
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
if(this.Size.Width==0 || this.Size.Height==0)
return;
this.RecalcLayout();
}
private bool _EndCellEditingOnLostFocus = true;
///
/// Gets or sets whether cell editing is completed when control loses input focus. Default value is true.
///
[DefaultValue(true), Category("Editing"), Description("Indicates whether cell editing is completed when control loses input focus. Default value is true.")]
public bool EndCellEditingOnLostFocus
{
get { return _EndCellEditingOnLostFocus; }
set
{
_EndCellEditingOnLostFocus = value;
}
}
protected override void OnKeyDown(KeyEventArgs e)
{
KeyNavigation.KeyDown(this, e);
base.OnKeyDown (e);
}
protected override void OnEnter(EventArgs e)
{
this.IsKeyboardFocusWithin = true;
base.OnEnter(e);
}
protected override void OnLeave(EventArgs e)
{
this.IsKeyboardFocusWithin = false;
base.OnLeave(e);
}
private bool _IsKeyboardFocusWithin = false;
///
/// Gets whether keyboard focus is within the control.
///
[Browsable(false)]
public bool IsKeyboardFocusWithin
{
get { return _IsKeyboardFocusWithin; }
#if FRAMEWORK20
internal set
#else
set
#endif
{
_IsKeyboardFocusWithin = value;
OnIsKeyboardFocusWithinChanged();
}
}
protected virtual void OnIsKeyboardFocusWithinChanged()
{
if (_IsKeyboardFocusWithin)
{
if (this.SelectedNode != null)
InvalidateNode(this.SelectedNode);
}
else
{
if (this.SelectedNode != null)
InvalidateNode(this.SelectedNode);
if (m_CellEditing && _EndCellEditingOnLostFocus)
EndCellEditing(eTreeAction.Keyboard);
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (this.IsKeyboardFocusWithin && !this.Focused)
{
foreach (Cell item in m_HostedControlCells)
{
if (item.HostedControl != null && (item.HostedControl.Focused || item.HostedControl.ContainsFocus))
return base.ProcessCmdKey(ref msg, keyData);
}
}
if(!m_CellEditing && (keyData==Keys.Left || keyData==Keys.Right || keyData==Keys.Up || keyData==Keys.Down))
{
KeyNavigation.NavigateKeyDown(this, new KeyEventArgs(keyData));
return true;
}
return base.ProcessCmdKey (ref msg, keyData);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if(!this.Focused)
this.Focus();
Point mousePos = GetLayoutPosition(e);
Node node = this.GetNodeAt(mousePos.X, mousePos.Y);
if (m_CellEditing)
{
if (node == null)
m_CellMouseDownCounter = 1;
else
m_CellMouseDownCounter =0;
if(!EndCellEditing(eTreeAction.Mouse))
return;
this.Focus();
}
if(node!=null)
OnNodeMouseDown(node,e,m_NodeDisplay.Offset);
m_MouseDownLocation=mousePos;
#if !TRIAL
if(NodeOperations.keyValidated2!=114 && !m_DialogDisplayed)
{
Design.ComponentNotLicensed f = new Design.ComponentNotLicensed();
f.ShowDialog();
f.Dispose();
m_DialogDisplayed=true;
}
#endif
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
OnNodeMouseUp(e);
}
protected override void OnClick(EventArgs e)
{
base.OnClick (e);
MouseEventArgs mouseArgs = e as MouseEventArgs;
MouseButtons mb = MouseButtons.Left;
if (mouseArgs != null)
mb = mouseArgs.Button;
OnNodeMouseClick(mb);
}
protected override void OnDoubleClick(EventArgs e)
{
base.OnDoubleClick (e);
if(this.SelectedNode!=null)
{
Point p=this.PointToClient(Control.MousePosition);
InvokeNodeDoubleClick(new TreeGXNodeMouseEventArgs(this.SelectedNode, MouseButtons.Left, 2, 0, p.X, p.Y));
}
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
if(m_MouseOverNode!=null)
this.SetMouseOverNode(null);
}
protected override void OnMouseHover(EventArgs e)
{
base.OnMouseHover (e);
if(m_MouseOverNode!=null && (FireHoverEvent || m_MouseOverNode.FireHoverEvent))
{
Point p=this.PointToClient(Control.MousePosition);
p=GetLayoutPosition(p);
InvokeNodeMouseHover(new TreeGXNodeMouseEventArgs(m_MouseOverNode, Control.MouseButtons, 0, 0, p.X, p.Y));
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
bool bUpdate=false;
Point mousePos=GetLayoutPosition(e);
if(e.Button==MouseButtons.Left && !m_CellEditing && m_DragDropEnabled && m_MouseOverNode!=null && m_DragNode==null && m_MouseOverNode.DragDropEnabled &&
(Math.Abs(m_MouseDownLocation.X-mousePos.X)>=SystemInformation.DragSize.Width || Math.Abs(m_MouseDownLocation.Y-mousePos.Y)>=SystemInformation.DragSize.Height))
{
StartDragDrop();
}
Rectangle r=Rectangle.Empty;
if(m_MouseOverNode!=null)
r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeBounds,m_MouseOverNode,m_NodeDisplay.Offset);
if(!r.IsEmpty && r.Contains(mousePos))
bUpdate=OnNodeMouseMove(m_MouseOverNode,e,m_NodeDisplay.Offset);
else
{
Node node=GetNodeAt(mousePos);
if(node!=m_MouseOverNode)
bUpdate=SetMouseOverNode(node);
if(m_MouseOverNode!=null)
bUpdate=bUpdate | OnNodeMouseMove(m_MouseOverNode,e,m_NodeDisplay.Offset);
}
if(bUpdate)
this.Update();
}
///
/// Selected specified node.
///
/// Node to select.
/// Action that is selecting the node.
public void SelectNode(Node node, eTreeAction action)
{
if (node != null && !node.Selectable && !this.DesignMode) return;
TreeGXNodeCancelEventArgs cancelArgs = new TreeGXNodeCancelEventArgs(action, node);
OnBeforeNodeSelect(cancelArgs);
if(cancelArgs.Cancel)
return;
bool bUpdate=false;
if(m_CellEditing)
{
if(!EndCellEditing(eTreeAction.Code))
return;
}
#if !TRIAL
if(NodeOperations.keyValidated2<114)
{
NodeDisplay.keyInvalid = true;
NodeOperations.keyValidated2 = NodeOperations.keyValidated2 + 124;
}
else if(NodeOperations.keyValidated2>114)
return;
#endif
if(m_SelectedNode!=null)
{
InvalidateNode(m_SelectedNode);
bUpdate=true;
if(m_SelectedNode.SelectedCell!=null)
m_SelectedNode.SelectedCell.SetSelected(false);
}
m_SelectedNode=node;
if(m_SelectedNode!=null)
{
InvalidateNode(m_SelectedNode);
bUpdate=true;
if(m_SelectedNode.SelectedCell==null)
m_SelectedNode.Cells[0].SetSelected(true);
}
if(this.SelectedPathConnector!=null)
this.Invalidate();
if(bUpdate)
this.Update();
TreeGXNodeEventArgs args = new TreeGXNodeEventArgs(action, node);
OnAfterNodeSelect(args);
}
private void OnCellStyleChanged()
{
InvalidateNodesSize();
if(this.DesignMode)
{
this.RecalcLayout();
this.Refresh();
}
}
private void SetSizeChanged(Node node)
{
node.SizeChanged=true;
foreach(Node c in node.Nodes)
SetSizeChanged(c);
}
private void InvalidateNodesSize()
{
foreach(Node node in m_Nodes)
SetSizeChanged(node);
}
private void ImageListDisposed(object sender, EventArgs e)
{
if(sender==m_ImageList)
{
this.ImageList=null;
}
}
///
/// Ensures that selected node is visible i.e. that all parents of the selected node are expanded. If not selects the first parent node not expanded.
///
internal void ValidateSelectedNode()
{
Node node = this.SelectedNode;
Node nodeSelected = node;
if (node == null)
return;
if (node.TreeControl != this)
{
nodeSelected = null;
}
else
{
while (node != null)
{
node = node.Parent;
if (node != null && !node.Expanded && node.Selectable)
nodeSelected = node;
}
}
if (nodeSelected == null || !nodeSelected.IsVisible)
{
if (!SelectFirstNode(eTreeAction.Code))
this.SelectedNode = null;
}
else
{
//if (_MultiSelect)
//{
// if (!this.SelectedNodes.Contains(nodeSelected))
// this.SelectedNode = nodeSelected;
//}
//else
{
if (this.SelectedNode != nodeSelected)
this.SelectedNode = nodeSelected;
}
}
}
internal void OnNodesCleared()
{
this.SelectedNode = null;
if (this.IsHandleCreated)
this.RecalcLayout();
else
SetPendingLayout();
}
private bool SetMouseOverCell(Cell mouseOverCell)
{
bool bUpdate=false;
if(mouseOverCell==m_MouseOverCell)
return bUpdate;
if(m_MouseOverCell!=null && m_MouseOverCell!=mouseOverCell)
{
if(this.CellStyleMouseOver!=null || m_MouseOverCell.StyleMouseOver!=null || m_RenderMode!=eNodeRenderMode.Default || m_MouseOverCell.Parent!=null && m_MouseOverCell.Parent.RenderMode!=eNodeRenderMode.Default)
bUpdate=true;
m_MouseOverCell.SetMouseOver(false);
}
m_MouseOverCell=mouseOverCell;
if(m_MouseOverCell!=null)
{
m_MouseOverCell.SetMouseOver(true);
if(this.CellStyleMouseOver!=null || m_MouseOverCell.StyleMouseOver!=null || m_RenderMode!=eNodeRenderMode.Default || m_MouseOverCell.Parent!=null && m_MouseOverCell.Parent.RenderMode!=eNodeRenderMode.Default )
bUpdate=true;
}
UpdateTreeCursor();
return bUpdate;
}
private bool SetMouseOverNode(Node mouseOverNode)
{
bool bUpdate=false;
if(m_MouseOverNode!=null)
{
bUpdate=bUpdate | SetMouseOverCell(null);
m_MouseOverNode.MouseOverNodePart=eMouseOverNodePart.None;
if(this.NodeStyleMouseOver!=null || this.CellStyleMouseOver!=null || m_MouseOverNode.StyleMouseOver!=null || this.NodeStyleMouseOver!=null ||
m_RenderMode!=eNodeRenderMode.Default || m_MouseOverNode.RenderMode!=eNodeRenderMode.Default || m_MouseOverNode.CommandButton || bUpdate)
{
InvalidateNode(m_MouseOverNode);
bUpdate=true;
}
if(m_MouseOverNode!=mouseOverNode && m_MouseOverNode!=null)
{
Point p=this.PointToClient(Control.MousePosition);
InvokeNodeMouseLeave(new TreeGXNodeMouseEventArgs(m_MouseOverNode, Control.MouseButtons, 0, 0, p.X, p.Y));
}
}
m_MouseOverNode=mouseOverNode;
if(m_MouseOverNode!=null)
{
m_MouseOverNode.MouseOverNodePart=eMouseOverNodePart.Node;
if(m_MouseOverNode.StyleMouseOver!=null || this.NodeStyleMouseOver!=null ||
m_RenderMode!=eNodeRenderMode.Default || m_MouseOverNode.RenderMode!=eNodeRenderMode.Default || m_MouseOverNode.CommandButton)
{
InvalidateNode(m_MouseOverNode);
bUpdate=true;
}
Point p=this.PointToClient(Control.MousePosition);
InvokeNodeMouseEnter(new TreeGXNodeMouseEventArgs(m_MouseOverNode, Control.MouseButtons, 0, 0, p.X, p.Y));
if(FireHoverEvent || m_MouseOverNode.FireHoverEvent)
Interop.WinApi.ResetHover(this);
}
return bUpdate;
}
private void OnNodeMouseDown(Node node, MouseEventArgs e, Point offset)
{
Point mousePos = GetLayoutPosition(e);
InvokeNodeMouseDown(new TreeGXNodeMouseEventArgs(node, e.Button, e.Clicks, e.Delta, mousePos.X, mousePos.Y));
if(e.Button==MouseButtons.Left)
{
Rectangle r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.ExpandBounds,node,offset);
if(r.Contains(mousePos))
{
m_CellMouseDownCounter=0;
node.Toggle();
return;
}
if(node.CommandButton)
{
m_CellMouseDownCounter=0;
r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.CommandBounds,node,offset);
if(r.Contains(mousePos))
{
InvokeCommandButtonClick(node,new CommandButtonEventArgs(eTreeAction.Mouse,node));
return;
}
}
r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeContentBounds,node,offset);
if(r.Contains(mousePos) && node.TreeControl!=null)
{
if(node.TreeControl.SelectedNode!=node)
m_CellMouseDownCounter=0;
if (node.Selectable)
{
SelectNode(node, eTreeAction.Mouse);
if (node.TreeControl.SelectedNode != node) // Action cancelled
return;
Cell cell = GetCellAt(node, mousePos.X, mousePos.Y, offset);
if (cell != null)
{
bool checkBoxSelection = false;
if (cell.CheckBoxVisible)
{
Rectangle rCheckBox = cell.CheckBoxBoundsRelative;
r = NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeBounds, node, offset);
rCheckBox.Offset(r.Location);
if (rCheckBox.Contains(mousePos))
{
cell.Checked = !cell.Checked;
checkBoxSelection = true;
m_CellMouseDownCounter = 0;
}
}
if (!checkBoxSelection)
m_CellMouseDownCounter++;
node.SelectedCell = cell;
cell.SetMouseDown(true);
}
}
}
else
m_CellMouseDownCounter=0;
}
else if(e.Button==MouseButtons.Right)
{
SelectNode(node, eTreeAction.Mouse);
if(node.TreeControl.SelectedNode!=node) // Action cancelled
return;
if(node.ContextMenu!=null)
{
if(node.ContextMenu is ContextMenu)
{
ContextMenu cm=node.ContextMenu as ContextMenu;
cm.Show(this, new Point(e.X, e.Y));
}
else if(node.ContextMenu.GetType().FullName=="System.Windows.Forms.ContextMenuStrip")
{
node.ContextMenu.GetType().InvokeMember("Show", System.Reflection.BindingFlags.InvokeMethod, null,
node.ContextMenu, new object[] {this, new Point(e.X, e.Y)});
}
else if(node.ContextMenu.GetType().FullName=="DevComponents.DotNetBar.ButtonItem")
{
Point p=this.PointToScreen(new Point(e.X, e.Y));
node.ContextMenu.GetType().InvokeMember("Popup", System.Reflection.BindingFlags.InvokeMethod,
null, node.ContextMenu, new object[]{p});
}
else if(node.ContextMenu.ToString().StartsWith(Design.NodeContextMenuTypeEditor.DotNetBarPrefix) && m_DotNetBarManager!=null)
{
string menuName=node.ContextMenu.ToString().Substring(Design.NodeContextMenuTypeEditor.DotNetBarPrefix.Length);
object contextMenus=m_DotNetBarManager.GetType().InvokeMember("ContextMenus",
System.Reflection.BindingFlags.GetProperty, null, m_DotNetBarManager, null);
int index=(int)contextMenus.GetType().InvokeMember("IndexOf", System.Reflection.BindingFlags.InvokeMethod,
null, contextMenus, new string[]{menuName});
if(index>=0)
{
IList list=contextMenus as IList;
object popup=list[index];
// Older version of DotNetBar do not have this method exposed so ignore the error...
try
{
popup.GetType().InvokeMember("SetSourceControl", System.Reflection.BindingFlags.InvokeMethod,
null, popup, new object[]{this});
}
catch {}
Point p=this.PointToScreen(new Point(e.X, e.Y));
popup.GetType().InvokeMember("Popup", System.Reflection.BindingFlags.InvokeMethod,
null, popup, new object[]{p});
}
}
}
}
}
private void OnNodeMouseUp(MouseEventArgs e)
{
bool bUpdate=false;
Point mousePos = GetLayoutPosition(e);
if(this.SelectedNode!=null)
{
if(this.SelectedNode.SelectedCell!=null && this.SelectedNode.SelectedCell.IsMouseDown)
{
this.SelectedNode.SelectedCell.SetMouseDown(false);
this.InvalidateNode(this.SelectedNode);
bUpdate=true;
}
}
if(bUpdate)
this.Update();
if(NodeMouseUp!=null)
{
Node node = this.GetNodeAt(mousePos);
if(node!=null)
{
InvokeNodeMouseUp(new TreeGXNodeMouseEventArgs(node, e.Button, e.Clicks, e.Delta, mousePos.X, mousePos.Y));
}
}
}
private void OnNodeMouseClick(MouseButtons mouseButton)
{
if(this.SelectedNode==null)
return;
InvokeNodeClick(new TreeGXNodeMouseEventArgs(this.SelectedNode, mouseButton, 1, 0, 0, 0));
// Start editing if allowed
if(this.CellEdit && this.SelectedNode.SelectedCell!=null && m_CellMouseDownCounter>1)
{
EditCell(this.SelectedNode.SelectedCell,eTreeAction.Mouse);
}
}
///
/// Starts editing specified cell, places the cell into the edit mode.
///
/// Cell to start editing.
/// Action that is a cause for the edit.
internal void EditCell(Cell cell, eTreeAction action)
{
EditCell(cell, action, null);
}
///
/// Starts editing specified cell, places the cell into the edit mode.
///
/// Cell to start editing.
/// Action that is a cause for the edit.
/// Specifies the text to be edited instead of the text of the cell. Passing the NULL value will edit the text of the cell.
internal void EditCell(Cell cell, eTreeAction action, string initialText)
{
if(cell==null) return;
if(m_CellEditing)
{
if(!EndCellEditing(action))
return;
}
CellEditEventArgs e = new CellEditEventArgs(cell,action,"");
OnBeforeCellEdit(e);
if(e.Cancel)
return;
TextBoxEx textBox=GetTextBox();
Rectangle rCell=NodeDisplay.GetCellRectangle(eCellRectanglePart.TextBounds, cell,m_NodeDisplay.Offset);
rCell.Inflate(Dpi.Width2, Dpi.Height2);
rCell.Height += Dpi.Height3;
rCell = GetScreenRectangle(rCell);
// It is important that text is assigned first or textbox will be resized to different size otherwise
textBox.Text=cell.Text;
textBox.EditWordWrap=cell.WordWrap;
Font font =CellDisplay.GetCellFont(this,cell);
if(m_ZoomFactor!=1 && font!=null)
{
font=new Font(font.FontFamily, font.SizeInPoints * m_ZoomFactor);
}
textBox.Font = font;
textBox.Location=rCell.Location;
textBox.Size=rCell.Size;
textBox.Visible=true;
textBox.Focus();
//if initial text is null then follow default behaviour of selecting all text
//if initial text is not null, set that as the default text and set the caret to the end of the text
if (initialText == null)
{
textBox.SelectAll();
}
else
{
textBox.Text = initialText;
textBox.Select(textBox.Text.Length, 0);
}
cell.Parent.SetEditing(true);
m_EditedCell=cell;
m_CellEditing=true;
}
///
/// Ends cell editing.
///
/// Specifies which action is cause for end of the editing.
/// Returns true if edits were applied to the cell or false otherwise.
internal bool EndCellEditing(eTreeAction action)
{
if(m_EditedCell==null || m_EditTextBox==null)
{
m_CellEditing=false;
return true;
}
TextBox textBox=m_EditTextBox;
string text=textBox.Text;
CellEditEventArgs e=new CellEditEventArgs(m_EditedCell,action,text);
InvokeCellEditEnding(e);
if(e.Cancel)
return false;
textBox.Visible=false;
text=e.NewText;
InvokeAfterCellEdit(e);
text=e.NewText;
if(!e.Cancel && m_EditedCell.Text!=text)
{
if(this.DesignMode && m_EditedCell.Parent.Cells[0]==m_EditedCell)
TypeDescriptor.GetProperties(m_EditedCell.Parent)["Text"].SetValue(m_EditedCell.Parent, text);
else
TypeDescriptor.GetProperties(m_EditedCell)["Text"].SetValue(m_EditedCell, text);
this.BeginUpdate();
this.RecalcLayout();
this.EndUpdate();
}
m_EditedCell.Parent.SetEditing(false);
m_EditedCell=null;
m_CellEditing=false;
return true;
}
///
/// Cancels the cell editing if it is in progress.
///
/// Specifies which action is cause for canceling of editing.
internal void CancelCellEdit(eTreeAction action)
{
if(m_EditedCell==null)
return;
m_EditTextBox.Text=m_EditedCell.Text;
this.EndCellEditing(action);
}
private TextBoxEx GetTextBox()
{
if(m_EditTextBox==null)
{
m_EditTextBox=new TextBoxEx();
m_EditTextBox.AutoSize=false;
this.Controls.Add(m_EditTextBox);
m_EditTextBox.EndEdit+= new EventHandler(EditTextBoxEndEdit);
m_EditTextBox.CancelEdit+=new EventHandler(EditTextBoxCancelEdit);
}
return m_EditTextBox;
}
private void EditTextBoxEndEdit(object sender, EventArgs e)
{
if(m_EditedCell==null)
return;
this.EndCellEditing(eTreeAction.Keyboard);
}
private void EditTextBoxCancelEdit(object sender, EventArgs e)
{
CancelCellEdit(eTreeAction.Keyboard);
}
private void UpdateTreeCursor()
{
if(m_MouseOverCell!=null)
{
if(m_MouseOverCell.Cursor!=null && this.Cursor!=m_MouseOverCell.Cursor)
{
if(m_OriginalCursor==null)
m_OriginalCursor=this.Cursor;
this.Cursor=m_MouseOverCell.Cursor;
}
else if(m_DefaultCellCursor!=null && this.Cursor!=m_DefaultCellCursor)
{
if(m_OriginalCursor==null)
m_OriginalCursor=this.Cursor;
this.Cursor=m_DefaultCellCursor;
}
}
else if(m_OriginalCursor!=null)
{
this.Cursor=m_OriginalCursor;
m_OriginalCursor=null;
}
}
private Cell GetCellAt(Node node, int x, int y, Point offset)
{
Cell cellAt=null;
Rectangle r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeBounds,node,offset);
foreach(Cell cell in node.Cells)
{
Rectangle rCell=cell.BoundsRelative;
rCell.Offset(r.Location);
if(rCell.Contains(x,y))
{
cellAt=cell;
break;
}
}
return cellAt;
}
private bool OnNodeMouseMove(Node node, MouseEventArgs e, Point offset)
{
Point mousePos = GetLayoutPosition(e);
InvokeNodeMouseMove(new TreeGXNodeMouseEventArgs(node, e.Button, e.Clicks, e.Delta, mousePos.X, mousePos.Y));
Rectangle r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.ExpandBounds,node,offset);
bool bUpdate=false;
if(r.Contains(mousePos))
{
node.MouseOverNodePart=eMouseOverNodePart.Expand;
if(m_MouseOverCell!=null)
{
bUpdate|=SetMouseOverCell(null);
}
bUpdate=true;
}
r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.CommandBounds,node,offset);
if(r.Contains(mousePos))
{
node.MouseOverNodePart=eMouseOverNodePart.Command;
if(m_MouseOverCell!=null)
{
bUpdate|=SetMouseOverCell(null);
}
bUpdate=true;
}
else
{
if(node.MouseOverNodePart!=eMouseOverNodePart.Node)
{
node.MouseOverNodePart=eMouseOverNodePart.Node;
bUpdate=true;
}
Cell cell=GetCellAt(node,mousePos.X,mousePos.Y,offset);
if (cell == null && node.Cells.Count == 1)
cell = node.Cells[0];
if(cell!=null)
{
bUpdate|=SetMouseOverCell(cell);
}
}
if(bUpdate)
InvalidateNode(node);
return bUpdate;
}
//
// private class MouseOverInfo
// {
// public DevComponents.Tree.Node Node=null;
// public DevComponents.Tree.Cell Cell=null;
// MouseOverInfo()
// {
// this.Node=null;
// this.Cell=null;
// }
// }
private void OnSelectionBoxChanged()
{
if(this.SelectedNode!=null)
{
InvalidateNode(this.SelectedNode);
this.Update();
}
}
private Color GetDefaultSelectionBoxBorderColor()
{
return Color.FromArgb(96,SystemColors.Highlight);
}
private Color GetDefaultSelectionBoxFillColor()
{
return Color.FromArgb(64,SystemColors.Highlight);
}
private void OnCommandButtonChanged()
{
m_NodeLayout.CommandAreaWidth=m_CommandWidth;
this.RecalcLayout();
}
private void InvokeCellEditEnding(CellEditEventArgs e)
{
if(CellEditEnding!=null)
CellEditEnding(this,e);
}
private void InvokeAfterCellEdit(CellEditEventArgs e)
{
if(AfterCellEdit!=null)
AfterCellEdit(this,e);
}
///
/// Raises BeforeNodeInsert event
///
/// Node that is about to be inserted
/// Source of the event
internal protected virtual void InvokeBeforeNodeInsert(eTreeAction action, Node node, Node parentNode)
{
if(BeforeNodeInsert!=null)
{
TreeGXNodeCollectionEventArgs e=new TreeGXNodeCollectionEventArgs(action, node, parentNode);
BeforeNodeInsert(this, e);
}
}
///
/// Raises AfterNodeInsert event
///
/// Node that is inserted
/// Source of the event
internal protected virtual void InvokeAfterNodeInsert(eTreeAction action, Node node, Node parentNode)
{
if(AfterNodeInsert!=null)
{
TreeGXNodeCollectionEventArgs e=new TreeGXNodeCollectionEventArgs(action, node, parentNode);
AfterNodeInsert(this, e);
}
}
///
/// Raises BeforeNodeRemove event
///
/// Node that is about to be removed
/// Source of the event
internal protected virtual void InvokeBeforeNodeRemove(eTreeAction action, Node node, Node parentNode)
{
if(BeforeNodeRemove!=null)
{
TreeGXNodeCollectionEventArgs e=new TreeGXNodeCollectionEventArgs(action, node, parentNode);
BeforeNodeRemove(this, e);
}
}
///
/// Raises AfterNodeRemove event
///
/// Node that is removed
/// Source of the event
internal protected virtual void InvokeAfterNodeRemove(eTreeAction action, Node node, Node parentNode)
{
if(AfterNodeRemove!=null)
{
TreeGXNodeCollectionEventArgs e=new TreeGXNodeCollectionEventArgs(action, node, parentNode);
AfterNodeRemove(this, e);
}
}
///
/// Called after node has been removed
///
/// Node that is removed
/// Source of the event
internal protected virtual void NodeRemoved(eTreeAction action, Node node, Node parentNode, int indexOfRemovedNode)
{
InvokeAfterNodeRemove(action, node, parentNode);
//if (m_NodeDisplay != null) m_NodeDisplay.PaintedNodes.Clear();
if (!this.IsDisposed)
RecalcLayout();
if (!this.IsUpdateSuspended)
{
bool updateSelection = false;
if (node.IsSelected)
updateSelection = true;
else
{
Node n = this.SelectedNode;
while (n != null)
{
if (n != null && n == node)
{
updateSelection = true;
break;
}
n = n.Parent;
}
}
if (updateSelection)
{
Node refNode = parentNode;
bool selectFirst = true;
if (parentNode != null)
{
if (parentNode.Nodes.Count > 0)
{
if (indexOfRemovedNode >= parentNode.Nodes.Count)
indexOfRemovedNode = parentNode.Nodes.Count - 1;
refNode = parentNode.Nodes[indexOfRemovedNode];
if (refNode.CanSelect)
{
this.SelectNode(refNode, action);
selectFirst = false;
refNode = null;
}
}
else
{
if (refNode.CanSelect)
{
this.SelectNode(refNode, action);
selectFirst = false;
refNode = null;
}
}
if (refNode != null)
{
while (refNode != null)
{
refNode = NodeOperations.GetPreviousVisibleNode(refNode);
if (refNode != null && refNode.CanSelect)
{
this.SelectNode(refNode, action);
selectFirst = false;
break;
}
}
}
}
else
{
int startIndex = indexOfRemovedNode;
if (this.Nodes.Count == indexOfRemovedNode) startIndex--;
if (startIndex > 0 && this.Nodes.Count > startIndex)
{
for (int i = startIndex; i >= 0; i--)
{
refNode = this.Nodes[i];
if (refNode.CanSelect && refNode.Visible && refNode.Enabled)
{
this.SelectNode(refNode, action);
selectFirst = false;
break;
}
}
}
}
if (selectFirst && !SelectFirstNode(action))
this.SelectNode(null, action);
}
this.Invalidate();
}
}
private bool SelectFirstNode(eTreeAction action)
{
bool selected = false;
foreach (Node node in this.Nodes)
{
if (node.Selectable && node.Visible && node.Enabled)
{
this.SelectNode(node, action);
if (this.SelectedNode == node)
{
return true;
}
}
}
return false;
}
///
/// Invokes BeforeNodeDrop event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeBeforeNodeDrop(TreeGXDragDropEventArgs e)
{
if(BeforeNodeDrop!=null)
BeforeNodeDrop(this, e);
}
///
/// Invokes AfterNodeDrop event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeAfterNodeDrop(TreeGXDragDropEventArgs e)
{
if(AfterNodeDrop!=null)
AfterNodeDrop(this, e);
}
///
/// Invokes NodeMouseDown event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeNodeMouseDown(TreeGXNodeMouseEventArgs e)
{
if(e.Node!=null)
e.Node.InvokeNodeMouseDown(this, new MouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta));
if(NodeMouseDown!=null)
NodeMouseDown(this, e);
}
///
/// Invokes NodeMouseUp event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeNodeMouseUp(TreeGXNodeMouseEventArgs e)
{
if(e.Node!=null)
e.Node.InvokeNodeMouseUp(this, new MouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta));
if(NodeMouseUp!=null)
NodeMouseUp(this, e);
}
///
/// Invokes NodeMouseMove event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeNodeMouseMove(TreeGXNodeMouseEventArgs e)
{
if(e.Node!=null)
e.Node.InvokeNodeMouseMove(this, new MouseEventArgs(e.Button, e.Clicks, e.X, e.Y, e.Delta));
if(NodeMouseMove!=null)
NodeMouseMove(this, e);
}
///
/// Invokes NodeClick event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeNodeClick(TreeGXNodeMouseEventArgs e)
{
if(e.Node!=null)
e.Node.InvokeNodeClick(this, e);
if(NodeClick!=null)
NodeClick(this, e);
}
///
/// Invokes NodeDoubleClick event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeNodeDoubleClick(TreeGXNodeMouseEventArgs e)
{
if(e.Node!=null)
e.Node.InvokeNodeDoubleClick(this, e);
if(NodeDoubleClick!=null)
NodeDoubleClick(this, e);
}
///
/// Invokes NodeMouseEnter event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeNodeMouseEnter(TreeGXNodeMouseEventArgs e)
{
if(e.Node!=null)
e.Node.InvokeNodeMouseEnter(this, e);
if(NodeMouseEnter!=null)
NodeMouseEnter(this, e);
}
///
/// Invokes NodeMouseLeave event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeNodeMouseLeave(TreeGXNodeMouseEventArgs e)
{
if(e.Node!=null)
e.Node.InvokeNodeMouseLeave(this, e);
if(NodeMouseLeave!=null)
NodeMouseLeave(this, e);
}
///
/// Invokes NodeMouseHover event. If overriden base implementation must be called in order for event to fire.
///
/// Provides information about event
protected virtual void InvokeNodeMouseHover(TreeGXNodeMouseEventArgs e)
{
if(e.Node!=null)
e.Node.InvokeNodeMouseHover(this, e);
if(NodeMouseHover!=null)
NodeMouseHover(this, e);
}
private bool FireHoverEvent
{
get { return NodeMouseHover!=null; }
}
#endregion
#region INodeNotify
void INodeNotify.ExpandedChanged(Node node)
{
ValidateSelectedNode();
if(!this.IsUpdateSuspended)
{
this.RecalcLayout();
this.Refresh();
}
}
#endregion
#region Public Interface
///
/// Save nodes to XmlDocument. New Node TreeGX is created and nodes are serialized into it.
///
/// Reference to an instance of XmlDocument object
public void Save(XmlDocument document)
{
TreeSerializer.Save(this, document);
}
///
/// Saves nodes to a file.
///
/// File name to save nodes to.
public void Save(string fileName)
{
TreeSerializer.Save(this, fileName);
}
///
/// Saves nodes to specified stream.
///
/// Stream to save nodes to.
public void Save(Stream outStream)
{
TreeSerializer.Save(this, outStream);
}
///
/// Saves nodes to specified writer.
///
/// Writer to save nodes to.
public void Save(TextWriter writer)
{
TreeSerializer.Save(this, writer);
}
///
/// Saves nodes to specified writer.
///
/// Writer to save nodes to.
public void Save(XmlWriter writer)
{
TreeSerializer.Save(this, writer);
}
///
/// Load nodes from file.
///
/// File to load nodes from
public void Load(string fileName)
{
TreeSerializer.Load(this, fileName);
}
///
/// Load nodes from stream.
///
/// Stream to load from
public void Load(Stream inStream)
{
TreeSerializer.Load(this, inStream);
}
///
/// Load nodes from reader.
///
/// Reader to load from.
public void Load(XmlReader reader)
{
TreeSerializer.Load(this, reader);
}
///
/// Load nodes from reader.
///
/// Reader to load from.
public void Load(TextReader reader)
{
TreeSerializer.Load(this, reader);
}
///
/// Load nodes from an XmlDocument object.
///
/// Document to load Nodes from.
public void Load(XmlDocument document)
{
TreeSerializer.Load(this, document);
}
///
/// Forces the control to invalidate its client area and immediately redraw itself
/// and any child controls. Note however that this method will node do anything if refresh
/// is suspended as result of call to BeginUpdate method without corresponding EndUpdate
/// call or if SuspendPaint property is set to true.
///
public override void Refresh()
{
if(!this.IsUpdateSuspended && !this.SuspendPaint)
base.Refresh();
}
///
/// Sets the node map position when tree is in Map layout mode. The node's position
/// can be set only for the sub-root nodes, i.e. nodes that are parented directly to
/// top-level root node. Setting map position for any other node does not have any effect.
///
///
/// Note that setting map position explicitly can change the position for other
/// nodes that are on the same level as the node that you pass into this method. Since
/// Map mode layouts the nodes clock-wise, setting the node position to Near will cause
/// all nodes that are in collection after the reference node to be
/// positioned Near as well.
/// Similarly, setting the node position to Far will cause all nodes that are in
/// collection before the reference node to be positioned Far as
/// well.
///
/// Sub-root node to set layout position for.
/// The position relative to the root node should take
public void SetNodeMapPosition(Node node, eMapPosition position)
{
if(node==null || node.Parent==null)
return;
if(position==eMapPosition.Default)
{
node.SetMapSubRootPosition(position);
}
else if(position==eMapPosition.Near)
{
int start=node.Parent.Nodes.IndexOf(node);
int end=node.Parent.Nodes.Count;
for(int i=start;i=0;i--)
node.Parent.Nodes[i].SetMapSubRootPosition(position);
}
}
///
/// Disables any redrawing of the tree control. To maintain performance while items
/// are added one at a time to the control, call the BeginUpdate method. The BeginUpdate
/// method prevents the control from painting until the
/// EndUpdate method is called.
///
public void BeginUpdate()
{
m_UpdateSuspended++;
}
///
/// Enables the redrawing of the tree view. To maintain performance while items are
/// added one at a time to the control, call the BeginUpdate
/// method. The BeginUpdate method prevents the control from painting until the EndUpdate
/// method is called.
///
///
/// Call to EndUpdate will enable the layout and painting in tree control. If there
/// are any pending layouts the EndUpdate will call
/// RecalcLayout method to perform the layout and it will
/// repaint the control.
///
public void EndUpdate()
{
EndUpdate(true);
}
///
/// Enables the redrawing of the tree view. To maintain performance while items are
/// added one at a time to the control, call the BeginUpdate
/// method. The BeginUpdate method prevents the control from painting until the EndUpdate
/// method is called.
///
/// Gets or sets whether layout and refresh of control is performed if there are no other update blocks pending.
public void EndUpdate(bool performLayoutAndRefresh)
{
if(m_UpdateSuspended>0) m_UpdateSuspended--;
if(m_UpdateSuspended==0 && performLayoutAndRefresh)
{
this.RecalcLayout();
this.Invalidate(true);
}
}
///
/// Retrieves the tree node that is at the specified location.
///
/// The Node at the specified point, in tree view coordinates.
///
/// You can pass the MouseEventArgs.X and MouseEventArgs.Y coordinates of the
/// MouseDown event as the x and y parameters.
///
/// The Point to evaluate and retrieve the node from.
public Node GetNodeAt(Point p)
{
return GetNodeAt(p.X,p.Y);
}
///
/// Retrieves the tree node that is at the specified location.
///
/// The TreeNode at the specified location, in tree view coordinates.
///
/// You can pass the MouseEventArgs.X and MouseEventArgs.Y coordinates of the
/// MouseDown event as the x and y parameters.
///
/// The X position to evaluate and retrieve the node from.
/// The Y position to evaluate and retrieve the node from.
public Node GetNodeAt(int x, int y)
{
return NodeOperations.GetNodeAt(this, x, y);
}
///
/// Retrieves the node cell that is at the specified location.
///
/// The Point to evaluate and retrieve the cell from.
/// The Cell at the specified point, in tree view coordinates.
public Cell GetCellAt(Point p)
{
return GetCellAt(p.X, p.Y);
}
///
/// Retrieves the node cell that is at the specified location.
///
/// The X position to evaluate and retrieve the cell from.
/// The Y position to evaluate and retrieve the cell from.
/// The Cell at the specified point, in tree view coordinates.
public Cell GetCellAt(int x, int y)
{
Node node = GetNodeAt(x, y);
if(node!=null)
{
return GetCellAt(node, x, y, m_NodeDisplay.Offset);
}
return null;
}
///
/// Returns the reference to the node mouse is currently over or null (Nothing) if mouse is not over any node in tree.
///
[Browsable(false)]
public Node MouseOverNode
{
get
{
return m_MouseOverNode;
}
}
///
/// Specifies the mouse cursor displayed when mouse is over the cell. Default value
/// is null which means that default control cursor is used.
///
///
/// To specify cursor for each individual cell use
/// Cell.Cursor property.
///
[Browsable(true),DefaultValue(null),Category("Appearance"),Description("Specifies the default mouse cursor displayed when mouse is over the cell.")]
public Cursor DefaultCellCursor
{
get
{
return m_DefaultCellCursor;
}
set
{
if(m_DefaultCellCursor!=value)
{
m_DefaultCellCursor=value;
}
}
}
/// Applies any layout changes to the tree control.
///
/// Layout will not be performed if BeginUpdate is called. Any calls to the
/// RecalcLayout will return without executing requested layout operation.
///
public void RecalcLayout()
{
if(this.IsUpdateSuspended)
{
m_PendingLayout=true;
return;
}
RecalcLayoutInternal();
}
///
/// Gets reference to array of Cell objects that have HostedControl property set.
///
internal ArrayList HostedControlCells
{
get { return m_HostedControlCells;}
}
///
/// This member overrides Control.WndProc.
///
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected override void WndProc(ref Message m)
{
const int WM_HSCROLL = 0x0114;
const int WM_VSCROLL = 0x115;
const int WM_MOUSEWHEEL = 0x020A;
base.WndProc(ref m);
if(this.AutoScroll)
{
if (m.Msg==WM_HSCROLL || m.Msg==WM_VSCROLL || m.Msg==WM_MOUSEWHEEL)
{
this.ActiveControl = null; // Must set to null otherwise scrolling will get reset if active control goes out of view
RepositionHostedControls(false);
this.Invalidate();
}
}
}
///
/// Recalculates layout for the tree control. Not afffected by BeginUpdate call.
///
internal void RecalcLayoutInternal()
{
Rectangle clientArea = this.ClientRectangle;
clientArea.Inflate(-this.SelectionBoxSize, -this.SelectionBoxSize);
m_NodeLayout.ClientArea = clientArea;
m_NodeLayout.LeftRight=this.RtlTranslateLeftRight(LeftRightAlignment.Left);
m_NodeLayout.PerformLayout();
m_PendingLayout=false;
float zoom = m_ZoomFactor;
Rectangle screenRect=GetScreenRectangle(new Rectangle(0,0,m_NodeLayout.Width,m_NodeLayout.Height));
Size nodeLayoutSize=screenRect.Size;
if(nodeLayoutSize.Width>this.Bounds.Width || nodeLayoutSize.Height>this.Bounds.Height)
{
Size autoScrollMinSize =nodeLayoutSize;
autoScrollMinSize.Width += this.SelectionBoxSize * 2;
autoScrollMinSize.Height += this.SelectionBoxSize * 2;
if(!this.AutoScroll)
{
this.BeginUpdate();
this.Invalidate();
this.AutoScroll=true;
this.AutoScrollMinSize = autoScrollMinSize;
this.AutoScrollPosition=m_NodeDisplay.DefaultOffset;
this.EndUpdate(false);
}
else if(this.AutoScrollMinSize!=nodeLayoutSize)
{
this.BeginUpdate();
this.AutoScrollMinSize = autoScrollMinSize;
this.EndUpdate(false);
}
}
else if(this.AutoScroll)
{
this.BeginUpdate();
this.AutoScroll=false;
m_NodeDisplay.Offset=m_NodeDisplay.DefaultOffset;
this.EndUpdate(false);
}
else
m_NodeDisplay.Offset=m_NodeDisplay.DefaultOffset;
RepositionHostedControls(true);
this.Invalidate(true);
}
private void RepositionHostedControls(bool performLayout)
{
if(m_HostedControlCells.Count>0)
{
this.SuspendLayout();
if(this.AutoScroll)
m_NodeDisplay.Offset = GetAutoScrollPositionOffset();
m_NodeDisplay.MoveHostedControls();
this.ResumeLayout(performLayout);
}
}
private System.Drawing.Drawing2D.Matrix GetTranslationMatrix(float zoom)
{
System.Drawing.Drawing2D.Matrix mx = new System.Drawing.Drawing2D.Matrix(zoom, 0, 0, zoom, 0, 0);
if(this.CenterContent)
{
float offsetX = 0, offsetY = 0;
if(this.AutoScroll)
{
if(this.Width>this.NodeLayout.Width)
{
if(this.Widththis.NodeLayout.Height)
{
if(this.Height
/// Returns translation matrix for current Zoom. Translation matrix is used to translate internal node coordinates to screen
/// coordinates when Zoom is not set to 1.
///
/// Returns new instance of Matrix object.
public System.Drawing.Drawing2D.Matrix GetTranslationMatrix()
{
return GetTranslationMatrix(m_ZoomFactor);
}
///
/// Returns layout based rectangle from screen rectangle. Layout based rectangle will be different
/// from screen rectangle when Zoom is not set to 1. This method will translate the screen rectangle enlarged by Zoom
/// to layout rectangle which does not have Zoom applied.
///
/// Screen rectangle
/// Layout rectangle
public virtual Rectangle GetLayoutRectangle(Rectangle r)
{
if(m_ZoomFactor==1)
return r;
Point[] p=new Point[] {new Point(r.X, r.Y), new Point(r.Right, r.Bottom)};
using(System.Drawing.Drawing2D.Matrix mx = GetTranslationMatrix())
{
mx.Invert();
mx.TransformPoints(p);
}
return new Rectangle(p[0].X, p[0].Y, p[1].X-p[0].X, p[1].Y-p[0].Y);
}
///
/// Returns mouse position which is translated if control Zoom is not equal 1
///
/// Mouse event arguments
/// Returns translated position
protected virtual Point GetLayoutPosition(MouseEventArgs e)
{
return GetLayoutPosition(e.X, e.Y);
}
///
/// Returns mouse position which is translated if control Zoom is not equal 1
///
/// Mouse position
/// Returns translated position
public virtual Point GetLayoutPosition(Point mousePosition)
{
return GetLayoutPosition(mousePosition.X, mousePosition.Y);
}
///
/// Returns mouse position which is translated if control Zoom is not equal 1
///
/// X coordinate
/// Y coordinate
///
public virtual Point GetLayoutPosition(int x, int y)
{
if(m_ZoomFactor==1)
return new Point(x, y);
Point[] p=new Point[] {new Point(x, y)};
using(System.Drawing.Drawing2D.Matrix mx = GetTranslationMatrix())
{
mx.Invert();
mx.TransformPoints(p);
}
return p[0];
}
///
/// Returns rectangle translated to screen rectangle if Zoom is not equal 1.
///
/// Rectangle to translate
/// Screen Rectangle
public virtual Rectangle GetScreenRectangle(Rectangle r)
{
if(m_ZoomFactor==1)
return r;
Point[] p=new Point[] {new Point(r.X, r.Y), new Point(r.Right, r.Bottom)};
using(System.Drawing.Drawing2D.Matrix mx = GetTranslationMatrix())
{
mx.TransformPoints(p);
}
return new Rectangle(p[0].X, p[0].Y, p[1].X-p[0].X, p[1].Y-p[0].Y);
}
///
/// Returns size translated to screen dimension if Zoom is not equal 1.
///
/// Size to translate
/// Screen Size
public virtual Size GetScreenSize(Size s)
{
return GetScreenRectangle(new Rectangle(Point.Empty, s)).Size;
}
#endregion
#region Event Invocation
///
/// Calls OnAfterCheck method which fired
/// AfterCheck event.
///
/// Event arguments.
internal void InvokeAfterCheck(TreeGXCellEventArgs e)
{
OnAfterCheck(e);
}
/// Raises the AfterCheck event.
///
/// A TreeGXEventArgs that contains the event
/// data.
///
protected virtual void OnAfterCheck(TreeGXCellEventArgs e)
{
if(AfterCheck!=null)
AfterCheck(this,e);
}
///
/// Invokes CommandButtonClick event.
///
/// Context node.
/// Event arguments.
internal void InvokeCommandButtonClick(Node node, CommandButtonEventArgs e)
{
if(CommandButtonClick!=null)
CommandButtonClick(node,e);
}
protected virtual void OnBeforeCellEdit(CellEditEventArgs e)
{
if(BeforeCellEdit!=null)
BeforeCellEdit(this, e);
}
void INodeNotify.OnBeforeCollapse(TreeGXNodeCancelEventArgs e)
{
if(BeforeCollapse!=null)
BeforeCollapse(this, e);
}
void INodeNotify.OnAfterCollapse(TreeGXNodeEventArgs e)
{
if(AfterCollapse!=null)
AfterCollapse(this, e);
}
void INodeNotify.OnBeforeExpand(TreeGXNodeCancelEventArgs e)
{
if(BeforeExpand!=null)
BeforeExpand(this, e);
}
void INodeNotify.OnAfterExpand(TreeGXNodeEventArgs e)
{
if(AfterExpand!=null)
AfterExpand(this, e);
}
protected virtual void OnAfterNodeSelect(TreeGXNodeEventArgs args)
{
if(AfterNodeSelect!=null)
AfterNodeSelect(this, args);
}
protected virtual void OnBeforeNodeSelect(TreeGXNodeCancelEventArgs args)
{
if(BeforeNodeSelect!=null)
BeforeNodeSelect(this,args);
}
///
/// Invokes DeserializeNode event.
///
/// Provides more information about the event
protected virtual void OnDeserializeNode(SerializeNodeEventArgs e)
{
if(DeserializeNode!=null)
DeserializeNode(this, e);
}
///
/// Invokes SerializeNode event.
///
/// Provides more information about the event
protected virtual void OnSerializeNode(SerializeNodeEventArgs e)
{
if(SerializeNode!=null)
SerializeNode(this, e);
}
internal void InvokeSerializeNode(SerializeNodeEventArgs e)
{
OnSerializeNode(e);
}
internal void InvokeDeserializeNode(SerializeNodeEventArgs e)
{
OnDeserializeNode(e);
}
internal bool HasSerializeNodeHandlers
{
get { return (SerializeNode != null);}
}
internal bool HasDeserializeNodeHandlers
{
get { return (DeserializeNode != null);}
}
internal void InvokeMarkupLinkClick(object sender, MarkupLinkClickEventArgs e)
{
OnMarkupLinkClick(sender, e);
m_CellMouseDownCounter = 0;
}
///
/// Invokes the MarkupLinkClick evcent.
///
/// Sender of the event, usually instance Cell object.
/// Event arguments
protected virtual void OnMarkupLinkClick(object sender, MarkupLinkClickEventArgs e)
{
if(MarkupLinkClick!=null)
MarkupLinkClick(sender, e);
}
#endregion
#region Drag & Drop Support
[DllImport("user32.dll", SetLastError=true)]
[return:MarshalAs(UnmanagedType.Bool)]
private static extern bool SetCursorPos(int X, int Y);
protected override void OnDragDrop(DragEventArgs drgevent)
{
base.OnDragDrop (drgevent);
InternalDragDrop(drgevent);
}
internal void InternalDragDrop(DragEventArgs drgevent)
{
ReleaseDragNode(true);
}
protected override void OnDragLeave(EventArgs e)
{
base.OnDragLeave (e);
InternalDragLeave();
}
internal void InternalDragLeave()
{
ReleaseDragNode(false);
}
protected override void OnDragOver(DragEventArgs drgevent)
{
base.OnDragOver (drgevent);
InternalDragOver(drgevent);
}
///
/// Processes drag over event.
///
/// Drag event arguments.
internal void InternalDragOver(DragEventArgs drgevent)
{
if(!m_DragDropEnabled)
return;
if(m_DragNode==null)
CreateDragNode(drgevent);
if(m_DragNode==null)
{
drgevent.Effect=DragDropEffects.None;
return;
}
drgevent.Effect=DragDropEffects.Move;
InvalidateNode(m_DragNode);
Point p=this.PointToClient(new Point(drgevent.X,drgevent.Y));
p=GetLayoutPosition(p);
TreeAreaInfo areaInfo = NodeOperations.GetTreeAreaInfo(this, p.X, p.Y);
Point insideNodeOffset=Point.Empty;
Node offsetNode=null;
bool recalcLayout=false;
//if (areaInfo == null)
// Console.WriteLine("{0} Area info null Point:{1}", DateTime.Now, p);
//else if (areaInfo.NodeAt != null)
// Console.WriteLine("{0} Area found node at: {1} Point:{2}", DateTime.Now, areaInfo.NodeAt, p);
//else
// Console.WriteLine("{0} Area found NO NODE AT: {1} Point:{2}", DateTime.Now, areaInfo.NodeAt, p);
if(areaInfo!=null && areaInfo.PreviousNode!=m_DragNode && areaInfo.NextNode!=m_DragNode &&
(areaInfo.NodeAt!=m_DragNode || m_DragNode.Parent==null))
{
if(areaInfo.NodeAt!=null && areaInfo.NodeAt!=m_DragNode.Tag && areaInfo.NodeAt!=m_DragNode)
{
if(areaInfo.NodeAt!=m_DragNode.Parent)
{
Rectangle r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeBounds,areaInfo.NodeAt,m_NodeDisplay.Offset);
insideNodeOffset=new Point(p.X-r.X,p.Y-r.Y);
recalcLayout=true;
m_DragNode.Remove(eTreeAction.Mouse);
areaInfo.NodeAt.Nodes.Add(m_DragNode, eTreeAction.Mouse);
offsetNode = areaInfo.NodeAt;
}
}
else if(areaInfo.PreviousNode!=null && areaInfo.NextNode!=null)
{
if(m_DragNode.Parent==null || !(m_DragNode.Parent==areaInfo.ParentAreaNode && areaInfo.ParentAreaNode.Nodes.IndexOf(areaInfo.NextNode)==areaInfo.ParentAreaNode.Nodes.IndexOf(m_DragNode)))
{
Rectangle r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeBounds,m_DragNode,m_NodeDisplay.Offset);
recalcLayout=true;
m_DragNode.Remove(eTreeAction.Mouse);
areaInfo.ParentAreaNode.Nodes.Insert(areaInfo.ParentAreaNode.Nodes.IndexOf(areaInfo.NextNode), m_DragNode, eTreeAction.Mouse);
insideNodeOffset=new Point(m_DragNode.BoundsRelative.Width/2,m_DragNode.BoundsRelative.Height/2);
offsetNode=m_DragNode;
}
}
else
{
if(m_DragNode.Parent!=null)
{
//System.Diagnostics.Trace.WriteLine("Floating");
Rectangle r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeBounds,m_DragNode.Parent,m_NodeDisplay.Offset);
insideNodeOffset=new Point(p.X-r.X,p.Y-r.Y);
offsetNode=m_DragNode.Parent;
recalcLayout=true;
m_DragNode.Remove(eTreeAction.Mouse);
m_DragNode.internalTreeControl=this;
}
if(m_NodeDisplay.LockOffset)
{
m_NodeDisplay.LockOffset=false;
recalcLayout=true;
}
m_DragNode.SetBounds(new Rectangle(p.X,p.Y,m_DragNode.BoundsRelative.Width,m_DragNode.BoundsRelative.Height));
}
m_DragNode.Visible=true;
if(recalcLayout)
{
this.RecalcLayout();
if(!insideNodeOffset.IsEmpty)
{
if(offsetNode!=null)
{
offsetNode.EnsureVisible();
this.Refresh();
Rectangle r=GetScreenRectangle(NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeBounds,offsetNode,m_NodeDisplay.Offset));
Point screenPos=r.Location;
screenPos.Offset((int)(insideNodeOffset.X*m_ZoomFactor), (int)(insideNodeOffset.Y*m_ZoomFactor));
screenPos=this.PointToScreen(screenPos);
SetCursorPos(screenPos.X,screenPos.Y);
}
}
this.Refresh();
}
else
{
InvalidateNode(m_DragNode);
if(this.DesignMode)
this.Refresh();
else
this.Update();
}
}
}
///
/// Gets or sets whether drag and drop operation is in progress. This member supports
/// the TreeGX infrastructure and is not intended to be used directly from your
/// code.
///
[Browsable(false)]
public bool IsDragDropInProgress
{
get {return (m_DragNode!=null);}
}
private void ReleaseDragNode(bool drop)
{
if(m_DragNode==null)
return;
this.BeginUpdate();
try
{
if(m_NodeDisplay.LockOffset)
m_NodeDisplay.LockOffset=false;
Node node=m_DragNode.Tag as Node;
node.Visible = true;
if(m_DragNode.Parent!=null)
{
int index=m_DragNode.Parent.Nodes.IndexOf(m_DragNode);
if(drop)
{
Node parent=m_DragNode.Parent;
m_DragNode.Remove(eTreeAction.Mouse);
// Fire off events and cancel processing if needed
TreeGXDragDropEventArgs e=new TreeGXDragDropEventArgs(eTreeAction.Mouse, node, node.Parent, parent);
InvokeBeforeNodeDrop(e);
if(!e.Cancel)
{
bool isCopy = e.IsCopy;
bool recursive=false;
Node test = parent;
if (!isCopy && test != null)
{
do
{
if (test.Parent == node)
{
recursive = true;
break;
}
test = test.Parent;
} while (test != null && test.Parent != null);
}
if(recursive)
{
Node rp=node.Parent;
int rpi=0;
if(node.Parent!=null)
rpi=node.Parent.Nodes.IndexOf(node);
else
rpi=this.Nodes.IndexOf(node);
Node[] na=new Node[node.Nodes.Count];
node.Nodes.CopyTo(na);
foreach(Node childNode in na)
{
if(rp==null)
{
childNode.Remove(eTreeAction.Mouse);
this.Nodes.Insert(rpi,childNode, eTreeAction.Mouse);
break;
}
childNode.Remove(eTreeAction.Mouse);
rp.Nodes.Insert(rpi,childNode, eTreeAction.Mouse);
rpi++;
}
}
if (isCopy)
{
node = node.DeepCopy();
}
else
node.Remove(eTreeAction.Mouse);
node.SizeChanged = true;
if(parent!=null && index>parent.Nodes.Count)
index=parent.Nodes.Count;
if(parent!=null)
parent.Nodes.Insert(index,node, eTreeAction.Mouse);
else
this.Nodes.Insert(index,node, eTreeAction.Mouse);
node.EnsureVisible();
InvokeAfterNodeDrop(e);
}
}
else
m_DragNode.Remove(eTreeAction.Mouse);
}
}
finally
{
m_DragNode=null;
if(!m_PendingLayout)
{
this.EndUpdate();
this.RecalcLayout();
this.Refresh();
}
else
this.EndUpdate();
}
}
private void CreateDragNode(DragEventArgs e)
{
if (e.Data != null)
{
Node node = null;
if (e.Data.GetDataPresent(typeof(Node)))
node = e.Data.GetData(typeof(Node)) as Node;
else if (e.Data.GetFormats().Length > 0)
node = e.Data.GetData(e.Data.GetFormats()[0]) as Node;
if (node != null)
CreateDragNode(node);
}
}
private void CreateDragNode(Node node)
{
m_DragNode=node.Copy();
m_DragNode.Tag=node;
PrepareDragNodeElementStyle(m_DragNode, node);
m_DragNode.Visible=false;
m_NodeLayout.PerformSingleNodeLayout(m_DragNode);
node.Visible = false;
this.RecalcLayout();
this.Refresh();
}
private void PrepareDragNodeElementStyle(Node dragNode, Node originalNode)
{
// Setup half transparent styles
int alpha=128;
ElementStyle style=null;
if(originalNode.Style!=null)
style=originalNode.Style.Copy();
else if(this.NodeStyle!=null)
style=this.NodeStyle.Copy();
else
{
style=new ElementStyle();
style.TextColorSchemePart=eColorSchemePart.ItemText;
}
ElementStyle.SetColorsAlpha(style,alpha);
dragNode.Style=style;
if(this.CellStyleDefault!=null)
style=this.CellStyleDefault.Copy();
else
style=ElementStyle.GetDefaultCellStyle(dragNode.Style);
ElementStyle.SetColorsAlpha(style,alpha);
foreach(Cell cell in dragNode.Cells)
{
cell.StyleNormal=style;
}
for(int i=0;i
/// Returns the display root node.
///
/// Instance of node or null if there is no display root node.
internal Node GetDisplayRootNode()
{
if(m_DisplayRootNode!=null)
return m_DisplayRootNode;
if(this.Nodes.Count>0)
return this.Nodes[0];
return null;
}
///
/// Returns reference to the node involved in drag-drop operation if any.
///
/// Reference to node object or null if there is no drag node.
internal Node GetDragNode()
{
return m_DragNode;
}
#endregion
#region ISupportInitialize
///
/// This member supports the .NET Framework infrastructure and is not intended to be
/// used directly from your code.
///
public void BeginInit()
{
this.BeginUpdate();
}
///
/// This member supports the .NET Framework infrastructure and is not intended to be
/// used directly from your code.
///
public void EndInit()
{
this.EndUpdate();
}
#endregion
#region Licensing
#if !TRIAL
private string m_LicenseKey="";
private bool m_DialogDisplayed=false;
[Browsable(false), DefaultValue("")]
public string LicenseKey
{
get {return m_LicenseKey;}
set
{
if(NodeOperations.ValidateLicenseKey(value))
return;
m_LicenseKey = (!NodeOperations.CheckLicenseKey(value) ? "9dsjkhds7" : value);
}
}
#endif
#endregion
}
}