4550 lines
147 KiB
C#
4550 lines
147 KiB
C#
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>
|
|
/// Summary description for UserControl1.
|
|
/// </summary>
|
|
[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();
|
|
/// <summary>
|
|
/// Required designer variable.
|
|
/// </summary>
|
|
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
|
|
/// <summary>
|
|
/// Occurs after the cell check box is checked.
|
|
/// </summary>
|
|
public event TreeGXCellEventHandler AfterCheck;
|
|
|
|
/// <summary>
|
|
/// Occurs after the tree node is collapsed.
|
|
/// </summary>
|
|
public event TreeGXNodeEventHandler AfterCollapse;
|
|
|
|
/// <summary>
|
|
/// Occurs before the tree node is collapsed.
|
|
/// </summary>
|
|
public event TreeGXNodeCancelEventHandler BeforeCollapse;
|
|
|
|
/// <summary>
|
|
/// Occurs after the tree node is expanded.
|
|
/// </summary>
|
|
public event TreeGXNodeEventHandler AfterExpand;
|
|
|
|
/// <summary>
|
|
/// Occurs before the tree node is expanded.
|
|
/// </summary>
|
|
public event TreeGXNodeCancelEventHandler BeforeExpand;
|
|
|
|
/// <summary>
|
|
/// Occurs when command button on node is clicked.
|
|
/// </summary>
|
|
public event CommandButtonEventHandler CommandButtonClick;
|
|
|
|
/// <summary>
|
|
/// Occurs before cell is edited. The order of the cell editing events is as follows:
|
|
/// BeforeCellEdit, CellEditEnding, AfterCellEdit.
|
|
/// </summary>
|
|
public event CellEditEventHandler BeforeCellEdit;
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public event CellEditEventHandler CellEditEnding;
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public event CellEditEventHandler AfterCellEdit;
|
|
|
|
/// <summary>
|
|
/// Occurs after Node has been selected by user or through the SelectedNode property. Event can be cancelled.
|
|
/// </summary>
|
|
public event TreeGXNodeCancelEventHandler BeforeNodeSelect;
|
|
|
|
/// <summary>
|
|
/// Occurs after node has been selected by user or through the SelectedNode property.
|
|
/// </summary>
|
|
public event TreeGXNodeEventHandler AfterNodeSelect;
|
|
|
|
/// <summary>
|
|
/// Occurs before node has been removed from its parent.
|
|
/// </summary>
|
|
public event TreeGXNodeCollectionEventHandler BeforeNodeRemove;
|
|
|
|
/// <summary>
|
|
/// Occurs after node has been removed from its parent.
|
|
/// </summary>
|
|
public event TreeGXNodeCollectionEventHandler AfterNodeRemove;
|
|
|
|
/// <summary>
|
|
/// Occurs before node is inserted or added as child node to parent node.
|
|
/// </summary>
|
|
public event TreeGXNodeCollectionEventHandler BeforeNodeInsert;
|
|
|
|
/// <summary>
|
|
/// Occurs after node is inserted or added as child node.
|
|
/// </summary>
|
|
public event TreeGXNodeCollectionEventHandler AfterNodeInsert;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public event TreeGXDragDropEventHandler BeforeNodeDrop;
|
|
|
|
/// <summary>
|
|
/// Occurs after Drag-Drop of a node is completed. This operation cannot be cancelled.
|
|
/// </summary>
|
|
public event TreeGXDragDropEventHandler AfterNodeDrop;
|
|
|
|
/// <summary>
|
|
/// Occurs when the mouse pointer is over the node and a mouse button is pressed.
|
|
/// </summary>
|
|
public event TreeGXNodeMouseEventHandler NodeMouseDown;
|
|
|
|
/// <summary>
|
|
/// Occurs when the mouse pointer is over the node and a mouse button is released.
|
|
/// </summary>
|
|
public event TreeGXNodeMouseEventHandler NodeMouseUp;
|
|
|
|
/// <summary>
|
|
/// Occurs when the mouse pointer is moved over the node.
|
|
/// </summary>
|
|
public event TreeGXNodeMouseEventHandler NodeMouseMove;
|
|
|
|
/// <summary>
|
|
/// Occurs when the mouse enters the node.
|
|
/// </summary>
|
|
public event TreeGXNodeMouseEventHandler NodeMouseEnter;
|
|
|
|
/// <summary>
|
|
/// Occurs when the mouse leaves the node.
|
|
/// </summary>
|
|
public event TreeGXNodeMouseEventHandler NodeMouseLeave;
|
|
|
|
/// <summary>
|
|
/// Occurs when the mouse hovers over the node.
|
|
/// </summary>
|
|
public event TreeGXNodeMouseEventHandler NodeMouseHover;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public event TreeGXNodeMouseEventHandler NodeClick;
|
|
|
|
/// <summary>
|
|
/// Occurs when the node is double-clicked.
|
|
/// </summary>
|
|
public event TreeGXNodeMouseEventHandler NodeDoubleClick;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>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.</para>
|
|
/// </remarks>
|
|
public event SerializeNodeEventHandler SerializeNode;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>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.</para>
|
|
/// </remarks>
|
|
public event SerializeNodeEventHandler DeserializeNode;
|
|
|
|
/// <summary>
|
|
/// Occurs when hyperlink in text-markup is clicked.
|
|
/// </summary>
|
|
public event MarkupLinkClickEventHandler MarkupLinkClick;
|
|
#endregion
|
|
|
|
#region Constructor/Dispose
|
|
/// <summary>Creates new instance of the class.</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clean up any resources being used.
|
|
/// </summary>
|
|
protected override void Dispose( bool disposing )
|
|
{
|
|
if( disposing )
|
|
{
|
|
if( components != null )
|
|
components.Dispose();
|
|
}
|
|
base.Dispose( disposing );
|
|
}
|
|
#endregion
|
|
|
|
#region Component Designer generated code
|
|
/// <summary>
|
|
/// Required method for Designer support - do not modify
|
|
/// the contents of this method with the code editor.
|
|
/// </summary>
|
|
private void InitializeComponent()
|
|
{
|
|
components = new System.ComponentModel.Container();
|
|
}
|
|
#endregion
|
|
|
|
#region Properties
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never), DefaultValue(null), Browsable(false)]
|
|
public object DotNetBarManager
|
|
{
|
|
get { return m_DotNetBarManager; }
|
|
set { m_DotNetBarManager=value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the size of the tree.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
public Size TreeSize
|
|
{
|
|
get
|
|
{
|
|
return new Size(m_NodeLayout.Width, m_NodeLayout.Height);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the style for the background of the control.
|
|
/// </summary>
|
|
[Browsable(true),Category("Appearance"),Description("Gets the style for the background of the control."),DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public ElementStyle BackgroundStyle
|
|
{
|
|
get {return m_BackgroundStyle;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the flow of nodes when Diagram layout is used. Note that this setting applies only to Diagram layout type.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the flow of nodes when Map layout is used. Note that this setting applies only to Map layout type.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the horizontal spacing in pixels between nodes. Default value is 32.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the vertical spacing in pixels between nodes. Default value is 16.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the layout type for the nodes.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether automatic drag and drop is enabled. Default value is true.
|
|
/// </summary>
|
|
[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;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether anti-alias smoothing is used while painting the tree.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the delimiter string that the tree node path uses.
|
|
/// </summary>
|
|
[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;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the collection of all column headers that appear in the tree.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>By default there are no column headers defined. In that case tree control
|
|
/// functions as regular tree control where text has unrestricted width.</para>
|
|
/// <para>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.</para>
|
|
/// </remarks>
|
|
public ColumnHeaderCollection Columns
|
|
{
|
|
get
|
|
{
|
|
return m_Columns;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the collection of all style elements created for the tree.
|
|
/// </summary>
|
|
[Browsable(true),DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public ElementStyleCollection Styles
|
|
{
|
|
get {return m_Styles;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style for the node cell.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style for the node cell when mouse is pressed.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style for the node cell when mouse is over the cell.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style for the node cell when cell is selected.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style for the node cell when cell is disabled.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style for the node when node is expanded.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style for all nodes where style is not specified
|
|
/// explicity.
|
|
/// </summary>
|
|
/// <value>
|
|
/// Name of the style assigned or null value indicating that no style is used.
|
|
/// Default value is null.
|
|
/// </value>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets or sets style for the node when node is selected. Note that this style is applied to the default node style.
|
|
/// </summary>
|
|
/// <value>
|
|
/// Reference to the style assigned or null value indicating that no style is used.
|
|
/// Default value is null.
|
|
/// </value>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets style for the node when mouse is over node. Note that this style is applied to the default node style.
|
|
/// </summary>
|
|
/// <value>
|
|
/// Reference to the style assigned or null value indicating that no style is used.
|
|
/// Default value is null.
|
|
/// </value>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gets the collection of tree nodes that are assigned to the tree view control.
|
|
/// </summary>
|
|
/// <value>
|
|
/// A <see cref="NodeCollection">NodeCollection</see> that represents the tree nodes
|
|
/// assigned to the tree control.
|
|
/// </value>
|
|
/// <remarks>
|
|
/// <para>The Nodes property holds a collection of Node objects, each of which has a
|
|
/// Nodes property that can contain its own NodeCollection.</para>
|
|
/// </remarks>
|
|
[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;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the default style class assigned to the column headers.
|
|
/// </summary>
|
|
/// <value>
|
|
/// Reference to the style assigned to the column header.
|
|
/// </value>
|
|
/// <remarks>
|
|
/// When style is not set on ColumnHeader objects then style setting from this property is used instead.
|
|
/// </remarks>
|
|
/// <seealso cref="ColumnStyleMouseDown">ColumnStyleMouseDown Property</seealso>
|
|
/// <seealso cref="ColumnStyleMouseOver">ColumnStyleMouseOver Property</seealso>
|
|
[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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style class assigned to the column which is applied when mouse
|
|
/// button is pressed over the header.
|
|
/// </summary>
|
|
/// <value>
|
|
/// Name of the style assigned to the column.
|
|
/// </value>
|
|
/// <remarks>
|
|
/// When style is not set on ColumnHeader objects then style setting from this property is used instead.
|
|
/// </remarks>
|
|
/// <seealso cref="ColumnStyleNormal">ColumnStyleNormal Property</seealso>
|
|
/// <seealso cref="ColumnStyleMouseOver">ColumnStyleMouseOver Property</seealso>
|
|
[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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets default style class assigned to the column which is applied when mouse is
|
|
/// over the column.
|
|
/// </summary>
|
|
/// <value>
|
|
/// Name of the style assigned to the column.
|
|
/// </value>
|
|
/// <remarks>
|
|
/// When style is not set on ColumnHeader objects then style setting from this property is used instead.
|
|
/// </remarks>
|
|
/// <seealso cref="ColumnStyleNormal">ColumnStyleNormal Property</seealso>
|
|
/// <seealso cref="ColumnStyleMouseDown">ColumnStyleMouseDown Property</seealso>
|
|
[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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets collection that holds definition of column headers associated with nodes.
|
|
/// </summary>
|
|
[Browsable(true),DesignerSerializationVisibility(DesignerSerializationVisibility.Content),Description("Collection that holds definition of column headers associated with nodes.")]
|
|
public HeadersCollection Headers
|
|
{
|
|
get {return m_Headers;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the tree node that is currently selected in the tree view control.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>If no <see cref="Node">Node</see> is currently selected, the
|
|
/// <b>SelectedNode</b> property is a null reference (<b>Nothing</b> in Visual
|
|
/// Basic).</para>
|
|
/// </remarks>
|
|
[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public Node SelectedNode
|
|
{
|
|
get {return m_SelectedNode;}
|
|
set
|
|
{
|
|
if(m_SelectedNode!=value)
|
|
{
|
|
SelectNode(value,eTreeAction.Code);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invalidates node bounds on canvas.
|
|
/// </summary>
|
|
/// <param name="node">Reference node.</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns reference to node layout object.
|
|
/// </summary>
|
|
internal Layout.NodeLayout NodeLayout
|
|
{
|
|
get {return m_NodeLayout;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns reference to node display object.
|
|
/// </summary>
|
|
internal NodeDisplay NodeDisplay
|
|
{
|
|
get {return m_NodeDisplay;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether layout is suspended for tree control. Layout is suspended after
|
|
/// call to <see cref="BeginUpdate">BeginUpdate</see> method and it is resumed after the
|
|
/// call to <see cref="EndUpdate">EndUpdate</see> method.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
public bool IsUpdateSuspended
|
|
{
|
|
get {return (m_UpdateSuspended>0);}
|
|
}
|
|
|
|
internal void SetPendingLayout()
|
|
{
|
|
m_PendingLayout = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
public bool SuspendPaint
|
|
{
|
|
get {return m_SuspendPaint;}
|
|
set {m_SuspendPaint=value;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the ImageList that contains the Image objects used by the tree nodes.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the image-list index value of the default image that is displayed by the tree nodes.
|
|
/// </summary>
|
|
[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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// You can use
|
|
/// <a href="TreeGX~DevComponents.Tree.Node~ParentConnector.html">Node.ParentConnector</a>
|
|
/// property to specify per node connectors.
|
|
/// </remarks>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// You can use
|
|
/// <a href="TreeGX~DevComponents.Tree.Node~ParentConnector.html">Node.ParentConnector</a>
|
|
/// property to specify per node connectors.
|
|
/// </remarks>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// You can specify cell layout on each node by using
|
|
/// <a href="TreeGX~DevComponents.Tree.Node~CellLayout.html">Node.CellLayout</a>
|
|
/// property.
|
|
/// </remarks>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// You can specify cell layout on each node by using
|
|
/// <a href="TreeGX~DevComponents.Tree.Node~CellLayout.html">Node.CellLayout</a>
|
|
/// property.
|
|
/// </remarks>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the reference to the color scheme object.
|
|
/// </summary>
|
|
internal ColorScheme ColorScheme
|
|
{
|
|
get {return m_ColorScheme;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the content of the control is centered within the bounds of control. Default value is true.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.TreeGX~NodeStyleSelected.html">NodeStyleSelected</a>
|
|
/// and
|
|
/// <a href="TreeGX~DevComponents.Tree.TreeGX~CellStyleSelected.html">CellStyleSelected</a>.
|
|
/// </summary>
|
|
/// <seealso cref="CellStyleSelected">CellStyleSelected Property</seealso>
|
|
/// <seealso cref="NodeStyleSelected">NodeStyleSelected Property</seealso>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the size/thickness in pixel of the selection box drawn around selected
|
|
/// node.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the selection box border color.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether SelectionBoxBorderColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeSelectionBoxBorderColor()
|
|
{return (m_SelectionBoxBorderColor!=GetDefaultSelectionBoxBorderColor());}
|
|
/// <summary>
|
|
/// Resets SelectionBoxBorderColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetSelectionBoxBorderColor()
|
|
{
|
|
m_SelectionBoxBorderColor=GetDefaultSelectionBoxBorderColor();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the selection box fill color.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether SelectionBoxFillColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeSelectionBoxFillColor()
|
|
{return (m_SelectionBoxFillColor!=GetDefaultSelectionBoxFillColor());}
|
|
/// <summary>
|
|
/// Resets SelectionBoxFillColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetSelectionBoxFillColor()
|
|
{
|
|
m_SelectionBoxFillColor=GetDefaultSelectionBoxFillColor();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the size of the expand button that is used to expand/collapse node. Default value is 8,8.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether SelectionBoxFillColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeExpandButtonSize()
|
|
{return (m_ExpandButtonSize!=GetDefaultExpandButtonSize());}
|
|
/// <summary>
|
|
/// Resets SelectionBoxFillColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetExpandButtonSize()
|
|
{
|
|
this.ExpandButtonSize=GetDefaultExpandButtonSize();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets expand button border color. Note that setting ExpandBorderColorSchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[Browsable(true),Category("Expand Button"),Description("Indicates expand button border color.")]
|
|
public Color ExpandBorderColor
|
|
{
|
|
get {return m_ExpandBorderColor;}
|
|
set
|
|
{
|
|
m_ExpandBorderColor=value;
|
|
this.OnExpandButtonChanged();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether ExpandBorderColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeExpandBorderColor()
|
|
{return (!m_ExpandBorderColor.IsEmpty && m_ExpandBorderColorSchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets ExpandBorderColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetExpandBorderColor()
|
|
{
|
|
this.ExpandBorderColor=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through ExpandBorderColor property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets expand button back color. Note that setting ExpandBackColorSchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[Browsable(true),Category("Expand Button"),Description("Indicates expand button back color.")]
|
|
public Color ExpandBackColor
|
|
{
|
|
get {return m_ExpandBackColor;}
|
|
set
|
|
{
|
|
m_ExpandBackColor=value;
|
|
this.OnExpandButtonChanged();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether ExpandBackColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeExpandBackColor()
|
|
{return (!m_ExpandBackColor.IsEmpty && m_ExpandBackColorSchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets ExpandBackColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetExpandBackColor()
|
|
{
|
|
this.ExpandBackColor=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through ExpandBackColor property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets expand button target gradientback color. Note that setting ExpandBackColor2SchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether ExpandBackColor2 should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeExpandBackColor2()
|
|
{return (!m_ExpandBackColor2.IsEmpty && m_ExpandBackColor2SchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets ExpandBackColor2 to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetExpandBackColor2()
|
|
{
|
|
this.ExpandBackColor2=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through ExpandBackColor2 property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets expand button line color. Note that setting ExpandLineColorSchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[Browsable(true),Category("Expand Button"),Description("Indicates expand button line color.")]
|
|
public Color ExpandLineColor
|
|
{
|
|
get {return m_ExpandLineColor;}
|
|
set
|
|
{
|
|
m_ExpandLineColor=value;
|
|
this.OnExpandButtonChanged();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether ExpandLineColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeExpandLineColor()
|
|
{return (!m_ExpandLineColor.IsEmpty && m_ExpandLineColorSchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets ExpandLineColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetExpandLineColor()
|
|
{
|
|
this.ExpandLineColor=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through ExpandLineColor property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the expand button background gradient angle.
|
|
/// </summary>
|
|
[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();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the type of the expand button used to expand/collapse nodes.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the width of the command button. Default value is 10 pixels.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets command button back color. Note that setting CommandBackColorSchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[Browsable(true),Category("Command Button"),Description("Indicates command button back color.")]
|
|
public Color CommandBackColor
|
|
{
|
|
get {return m_CommandBackColor;}
|
|
set
|
|
{
|
|
m_CommandBackColor=value;
|
|
this.OnCommandButtonChanged();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether CommandBackColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeCommandBackColor()
|
|
{return (!m_CommandBackColor.IsEmpty && m_CommandBackColorSchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets CommandBackColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetCommandBackColor()
|
|
{
|
|
this.CommandBackColor=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through CommandBackColor property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets command button target gradient back color. Note that setting CommandBackColor2SchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether CommandBackColor2 should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeCommandBackColor2()
|
|
{return (!m_CommandBackColor2.IsEmpty && m_CommandBackColor2SchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets CommandBackColor2 to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetCommandBackColor2()
|
|
{
|
|
this.CommandBackColor2=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through CommandBackColor2 property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets command button foreground color. Note that setting CommandForeColorSchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[Browsable(true),Category("Command Button"),Description("Indicates command button fore color.")]
|
|
public Color CommandForeColor
|
|
{
|
|
get {return m_CommandForeColor;}
|
|
set
|
|
{
|
|
m_CommandForeColor=value;
|
|
this.OnCommandButtonChanged();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether CommandForeColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeCommandForeColor()
|
|
{return (!m_CommandForeColor.IsEmpty && m_CommandForeColorSchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets CommandForeColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetCommandForeColor()
|
|
{
|
|
this.CommandForeColor=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through CommandForeColor property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the command button background gradient angle.
|
|
/// </summary>
|
|
[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();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets command button mouse over back color. Note that setting CommandMouseOverBackColorSchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether CommandMouseOverBackColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeCommandMouseOverBackColor()
|
|
{return (!m_CommandMouseOverBackColor.IsEmpty && m_CommandMouseOverBackColorSchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets CommandMouseOverBackColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetCommandMouseOverBackColor()
|
|
{
|
|
this.CommandMouseOverBackColor=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through CommandMouseOverBackColor property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets command button mouse over target gradient back color. Note that setting CommandMouseOverBackColor2SchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether CommandMouseOverBackColor2 should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeCommandMouseOverBackColor2()
|
|
{return (!m_CommandMouseOverBackColor2.IsEmpty && m_CommandMouseOverBackColor2SchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets CommandMouseOverBackColor2 to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetCommandMouseOverBackColor2()
|
|
{
|
|
this.CommandMouseOverBackColor2=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through CommandMouseOverBackColor2 property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets command button mouse over foreground color. Note that setting CommandMouseOverForeColorSchemePart property will override the value that you set here.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Indicates whether CommandMouseOverForeColor should be serialized. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeCommandMouseOverForeColor()
|
|
{return (!m_CommandMouseOverForeColor.IsEmpty && m_CommandMouseOverForeColorSchemePart==eColorSchemePart.None);}
|
|
/// <summary>
|
|
/// Resets CommandMouseOverForeColor to it's default value. Used by windows forms designer design-time support.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetCommandMouseOverForeColor()
|
|
{
|
|
this.CommandMouseOverForeColor=Color.Empty;
|
|
}
|
|
/// <summary>
|
|
/// 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
|
|
/// <a href="TreeGX~DevComponents.Tree.eColorSchemePart.html">eColorSchemePart.None</a> to
|
|
/// specify explicit color to use through CommandMouseOverForeColor property.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the command button mouse over background gradient angle.
|
|
/// </summary>
|
|
[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();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether the label text of the node cells can be edited. Default value is false.
|
|
/// </summary>
|
|
[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;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns whether cell editing is in progress.
|
|
/// </summary>
|
|
[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; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns color scheme part color if set otherwise returns color passed in.
|
|
/// </summary>
|
|
/// <param name="color">Color.</param>
|
|
/// <param name="p">Color scheme part.</param>
|
|
/// <returns>Color.</returns>
|
|
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
|
|
}
|
|
|
|
/// <summary>
|
|
/// Paints control to canvas. This method might be used for print output.
|
|
/// </summary>
|
|
/// <param name="g">Graphics object to paint control to.</param>
|
|
/// <param name="background">Indicates whether to paint control background.</param>
|
|
public void PaintTo(Graphics g, bool background)
|
|
{
|
|
PaintTo(g, background, Rectangle.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Paints control to canvas. This method might be used for print output.
|
|
/// </summary>
|
|
/// <param name="g">Graphics object to paint control to.</param>
|
|
/// <param name="background">Indicates whether to paint control background.</param>
|
|
/// <param name="clipRectangle">Indicates clipping rectangle. Nodes outside of clipping rectangle will not be painted. You can pass Rectangle.Empty and all nodes will be painted.</param>
|
|
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;
|
|
/// <summary>
|
|
/// Gets or sets whether cell editing is completed when control loses input focus. Default value is true.
|
|
/// </summary>
|
|
[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;
|
|
/// <summary>
|
|
/// Gets whether keyboard focus is within the control.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Selected specified node.
|
|
/// </summary>
|
|
/// <param name="node">Node to select.</param>
|
|
/// <param name="action">Action that is selecting the node.</param>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Starts editing specified cell, places the cell into the edit mode.
|
|
/// </summary>
|
|
/// <param name="cell">Cell to start editing.</param>
|
|
/// <param name="action">Action that is a cause for the edit.</param>
|
|
internal void EditCell(Cell cell, eTreeAction action)
|
|
{
|
|
EditCell(cell, action, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Starts editing specified cell, places the cell into the edit mode.
|
|
/// </summary>
|
|
/// <param name="cell">Cell to start editing.</param>
|
|
/// <param name="action">Action that is a cause for the edit.</param>
|
|
/// <param name="initialText">Specifies the text to be edited instead of the text of the cell. Passing the NULL value will edit the text of the cell.</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ends cell editing.
|
|
/// </summary>
|
|
/// <param name="action">Specifies which action is cause for end of the editing.</param>
|
|
/// <returns>Returns true if edits were applied to the cell or false otherwise.</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cancels the cell editing if it is in progress.
|
|
/// </summary>
|
|
/// <param name="action">Specifies which action is cause for canceling of editing.</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises BeforeNodeInsert event
|
|
/// </summary>
|
|
/// <param name="node">Node that is about to be inserted</param>
|
|
/// <param name="action">Source of the event</param>
|
|
internal protected virtual void InvokeBeforeNodeInsert(eTreeAction action, Node node, Node parentNode)
|
|
{
|
|
if(BeforeNodeInsert!=null)
|
|
{
|
|
TreeGXNodeCollectionEventArgs e=new TreeGXNodeCollectionEventArgs(action, node, parentNode);
|
|
BeforeNodeInsert(this, e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises AfterNodeInsert event
|
|
/// </summary>
|
|
/// <param name="node">Node that is inserted</param>
|
|
/// <param name="action">Source of the event</param>
|
|
internal protected virtual void InvokeAfterNodeInsert(eTreeAction action, Node node, Node parentNode)
|
|
{
|
|
if(AfterNodeInsert!=null)
|
|
{
|
|
TreeGXNodeCollectionEventArgs e=new TreeGXNodeCollectionEventArgs(action, node, parentNode);
|
|
AfterNodeInsert(this, e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises BeforeNodeRemove event
|
|
/// </summary>
|
|
/// <param name="node">Node that is about to be removed</param>
|
|
/// <param name="action">Source of the event</param>
|
|
internal protected virtual void InvokeBeforeNodeRemove(eTreeAction action, Node node, Node parentNode)
|
|
{
|
|
if(BeforeNodeRemove!=null)
|
|
{
|
|
TreeGXNodeCollectionEventArgs e=new TreeGXNodeCollectionEventArgs(action, node, parentNode);
|
|
BeforeNodeRemove(this, e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises AfterNodeRemove event
|
|
/// </summary>
|
|
/// <param name="node">Node that is removed</param>
|
|
/// <param name="action">Source of the event</param>
|
|
internal protected virtual void InvokeAfterNodeRemove(eTreeAction action, Node node, Node parentNode)
|
|
{
|
|
if(AfterNodeRemove!=null)
|
|
{
|
|
TreeGXNodeCollectionEventArgs e=new TreeGXNodeCollectionEventArgs(action, node, parentNode);
|
|
AfterNodeRemove(this, e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called after node has been removed
|
|
/// </summary>
|
|
/// <param name="node">Node that is removed</param>
|
|
/// <param name="action">Source of the event</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes BeforeNodeDrop event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
protected virtual void InvokeBeforeNodeDrop(TreeGXDragDropEventArgs e)
|
|
{
|
|
if(BeforeNodeDrop!=null)
|
|
BeforeNodeDrop(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes AfterNodeDrop event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
protected virtual void InvokeAfterNodeDrop(TreeGXDragDropEventArgs e)
|
|
{
|
|
if(AfterNodeDrop!=null)
|
|
AfterNodeDrop(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes NodeMouseDown event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes NodeMouseUp event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes NodeMouseMove event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes NodeClick event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
protected virtual void InvokeNodeClick(TreeGXNodeMouseEventArgs e)
|
|
{
|
|
if(e.Node!=null)
|
|
e.Node.InvokeNodeClick(this, e);
|
|
|
|
if(NodeClick!=null)
|
|
NodeClick(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes NodeDoubleClick event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
protected virtual void InvokeNodeDoubleClick(TreeGXNodeMouseEventArgs e)
|
|
{
|
|
if(e.Node!=null)
|
|
e.Node.InvokeNodeDoubleClick(this, e);
|
|
|
|
if(NodeDoubleClick!=null)
|
|
NodeDoubleClick(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes NodeMouseEnter event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
protected virtual void InvokeNodeMouseEnter(TreeGXNodeMouseEventArgs e)
|
|
{
|
|
if(e.Node!=null)
|
|
e.Node.InvokeNodeMouseEnter(this, e);
|
|
|
|
if(NodeMouseEnter!=null)
|
|
NodeMouseEnter(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes NodeMouseLeave event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
protected virtual void InvokeNodeMouseLeave(TreeGXNodeMouseEventArgs e)
|
|
{
|
|
if(e.Node!=null)
|
|
e.Node.InvokeNodeMouseLeave(this, e);
|
|
|
|
if(NodeMouseLeave!=null)
|
|
NodeMouseLeave(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes NodeMouseHover event. If overriden base implementation must be called in order for event to fire.
|
|
/// </summary>
|
|
/// <param name="e">Provides information about event</param>
|
|
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
|
|
/// <summary>
|
|
/// Save nodes to XmlDocument. New Node TreeGX is created and nodes are serialized into it.
|
|
/// </summary>
|
|
/// <param name="document">Reference to an instance of XmlDocument object</param>
|
|
public void Save(XmlDocument document)
|
|
{
|
|
TreeSerializer.Save(this, document);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves nodes to a file.
|
|
/// </summary>
|
|
/// <param name="fileName">File name to save nodes to.</param>
|
|
public void Save(string fileName)
|
|
{
|
|
TreeSerializer.Save(this, fileName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves nodes to specified stream.
|
|
/// </summary>
|
|
/// <param name="outStream">Stream to save nodes to.</param>
|
|
public void Save(Stream outStream)
|
|
{
|
|
TreeSerializer.Save(this, outStream);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves nodes to specified writer.
|
|
/// </summary>
|
|
/// <param name="writer">Writer to save nodes to.</param>
|
|
public void Save(TextWriter writer)
|
|
{
|
|
TreeSerializer.Save(this, writer);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves nodes to specified writer.
|
|
/// </summary>
|
|
/// <param name="writer">Writer to save nodes to.</param>
|
|
public void Save(XmlWriter writer)
|
|
{
|
|
TreeSerializer.Save(this, writer);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load nodes from file.
|
|
/// </summary>
|
|
/// <param name="fileName">File to load nodes from</param>
|
|
public void Load(string fileName)
|
|
{
|
|
TreeSerializer.Load(this, fileName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load nodes from stream.
|
|
/// </summary>
|
|
/// <param name="inStream">Stream to load from</param>
|
|
public void Load(Stream inStream)
|
|
{
|
|
TreeSerializer.Load(this, inStream);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load nodes from reader.
|
|
/// </summary>
|
|
/// <param name="reader">Reader to load from.</param>
|
|
public void Load(XmlReader reader)
|
|
{
|
|
TreeSerializer.Load(this, reader);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load nodes from reader.
|
|
/// </summary>
|
|
/// <param name="reader">Reader to load from.</param>
|
|
public void Load(TextReader reader)
|
|
{
|
|
TreeSerializer.Load(this, reader);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load nodes from an XmlDocument object.
|
|
/// </summary>
|
|
/// <param name="document">Document to load Nodes from.</param>
|
|
public void Load(XmlDocument document)
|
|
{
|
|
TreeSerializer.Load(this, document);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public override void Refresh()
|
|
{
|
|
if(!this.IsUpdateSuspended && !this.SuspendPaint)
|
|
base.Refresh();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>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 <strong>after</strong> the reference node to be
|
|
/// positioned Near as well.</para>
|
|
/// <para>Similarly, setting the node position to Far will cause all nodes that are in
|
|
/// collection <strong>before</strong> the reference node to be positioned Far as
|
|
/// well.</para>
|
|
/// </remarks>
|
|
/// <param name="node">Sub-root node to set layout position for.</param>
|
|
/// <param name="position">The position relative to the root node should take</param>
|
|
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<end;i++)
|
|
node.Parent.Nodes[i].SetMapSubRootPosition(position);
|
|
}
|
|
else if(position==eMapPosition.Far)
|
|
{
|
|
int start=node.Parent.Nodes.IndexOf(node);
|
|
for(int i=start;i>=0;i--)
|
|
node.Parent.Nodes[i].SetMapSubRootPosition(position);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// <see cref="EndUpdate">EndUpdate</see> method is called.
|
|
/// </summary>
|
|
public void BeginUpdate()
|
|
{
|
|
m_UpdateSuspended++;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enables the redrawing of the tree view. To maintain performance while items are
|
|
/// added one at a time to the control, call the <see cref="BeginUpdate">BeginUpdate</see>
|
|
/// method. The BeginUpdate method prevents the control from painting until the EndUpdate
|
|
/// method is called.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Call to EndUpdate will enable the layout and painting in tree control. If there
|
|
/// are any pending layouts the EndUpdate will call
|
|
/// <see cref="RecalcLayout">RecalcLayout</see> method to perform the layout and it will
|
|
/// repaint the control.
|
|
/// </remarks>
|
|
public void EndUpdate()
|
|
{
|
|
EndUpdate(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enables the redrawing of the tree view. To maintain performance while items are
|
|
/// added one at a time to the control, call the <see cref="BeginUpdate">BeginUpdate</see>
|
|
/// method. The BeginUpdate method prevents the control from painting until the EndUpdate
|
|
/// method is called.
|
|
/// </summary>
|
|
/// <param name="performLayoutAndRefresh">Gets or sets whether layout and refresh of control is performed if there are no other update blocks pending.</param>
|
|
public void EndUpdate(bool performLayoutAndRefresh)
|
|
{
|
|
if(m_UpdateSuspended>0) m_UpdateSuspended--;
|
|
if(m_UpdateSuspended==0 && performLayoutAndRefresh)
|
|
{
|
|
this.RecalcLayout();
|
|
this.Invalidate(true);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the tree node that is at the specified location.
|
|
/// </summary>
|
|
/// <returns>The Node at the specified point, in tree view coordinates.</returns>
|
|
/// <remarks>
|
|
/// <para>You can pass the MouseEventArgs.X and MouseEventArgs.Y coordinates of the
|
|
/// MouseDown event as the x and y parameters.</para>
|
|
/// </remarks>
|
|
/// <param name="p">The Point to evaluate and retrieve the node from.</param>
|
|
public Node GetNodeAt(Point p)
|
|
{
|
|
return GetNodeAt(p.X,p.Y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the tree node that is at the specified location.
|
|
/// </summary>
|
|
/// <returns>The TreeNode at the specified location, in tree view coordinates.</returns>
|
|
/// <remarks>
|
|
/// <para>You can pass the MouseEventArgs.X and MouseEventArgs.Y coordinates of the
|
|
/// MouseDown event as the x and y parameters.</para>
|
|
/// </remarks>
|
|
/// <param name="x">The X position to evaluate and retrieve the node from.</param>
|
|
/// <param name="y">The Y position to evaluate and retrieve the node from.</param>
|
|
public Node GetNodeAt(int x, int y)
|
|
{
|
|
return NodeOperations.GetNodeAt(this, x, y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the node cell that is at the specified location.
|
|
/// </summary>
|
|
/// <param name="p">The Point to evaluate and retrieve the cell from.</param>
|
|
/// <returns>The Cell at the specified point, in tree view coordinates.</returns>
|
|
public Cell GetCellAt(Point p)
|
|
{
|
|
return GetCellAt(p.X, p.Y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the node cell that is at the specified location.
|
|
/// </summary>
|
|
/// <param name="x">The X position to evaluate and retrieve the cell from.</param>
|
|
/// <param name="y">The Y position to evaluate and retrieve the cell from.</param>
|
|
/// <returns>The Cell at the specified point, in tree view coordinates.</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the reference to the node mouse is currently over or null (Nothing) if mouse is not over any node in tree.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
public Node MouseOverNode
|
|
{
|
|
get
|
|
{
|
|
return m_MouseOverNode;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Specifies the mouse cursor displayed when mouse is over the cell. Default value
|
|
/// is null which means that default control cursor is used.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// To specify cursor for each individual cell use
|
|
/// <a href="TreeGX~DevComponents.Tree.Cell~Cursor.html">Cell.Cursor</a> property.
|
|
/// </remarks>
|
|
[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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>Applies any layout changes to the tree control.</summary>
|
|
/// <remarks>
|
|
/// Layout will not be performed if BeginUpdate is called. Any calls to the
|
|
/// RecalcLayout will return without executing requested layout operation.
|
|
/// </remarks>
|
|
public void RecalcLayout()
|
|
{
|
|
if(this.IsUpdateSuspended)
|
|
{
|
|
m_PendingLayout=true;
|
|
return;
|
|
}
|
|
RecalcLayoutInternal();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets reference to array of Cell objects that have HostedControl property set.
|
|
/// </summary>
|
|
internal ArrayList HostedControlCells
|
|
{
|
|
get { return m_HostedControlCells;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This member overrides Control.WndProc.
|
|
/// </summary>
|
|
[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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recalculates layout for the tree control. Not afffected by BeginUpdate call.
|
|
/// </summary>
|
|
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.Width<this.NodeLayout.Width*zoom)
|
|
offsetX = - (this.Width - this.NodeLayout.Width)/2;
|
|
else
|
|
offsetX = (this.Width*(1.0f/zoom) - this.Width)/2;
|
|
}
|
|
|
|
if(this.Height>this.NodeLayout.Height)
|
|
{
|
|
if(this.Height<this.NodeLayout.Height*zoom)
|
|
offsetY = - (this.Height - this.NodeLayout.Height)/2;
|
|
else
|
|
offsetY = (this.Height*(1.0f/zoom) - this.Height)/2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
offsetX = (this.Width*(1.0f/zoom) - this.Width)/2;
|
|
offsetY = (this.Height*(1.0f/zoom) - this.Height)/2;
|
|
}
|
|
|
|
mx.Translate(offsetX, offsetY);
|
|
}
|
|
return mx;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <returns>Returns new instance of Matrix object.</returns>
|
|
public System.Drawing.Drawing2D.Matrix GetTranslationMatrix()
|
|
{
|
|
return GetTranslationMatrix(m_ZoomFactor);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="r">Screen rectangle</param>
|
|
/// <returns>Layout rectangle</returns>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns mouse position which is translated if control Zoom is not equal 1
|
|
/// </summary>
|
|
/// <param name="e">Mouse event arguments</param>
|
|
/// <returns>Returns translated position</returns>
|
|
protected virtual Point GetLayoutPosition(MouseEventArgs e)
|
|
{
|
|
return GetLayoutPosition(e.X, e.Y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns mouse position which is translated if control Zoom is not equal 1
|
|
/// </summary>
|
|
/// <param name="mousePosition">Mouse position</param>
|
|
/// <returns>Returns translated position</returns>
|
|
public virtual Point GetLayoutPosition(Point mousePosition)
|
|
{
|
|
return GetLayoutPosition(mousePosition.X, mousePosition.Y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns mouse position which is translated if control Zoom is not equal 1
|
|
/// </summary>
|
|
/// <param name="x">X coordinate</param>
|
|
/// <param name="y">Y coordinate</param>
|
|
/// <returns></returns>
|
|
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];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns rectangle translated to screen rectangle if Zoom is not equal 1.
|
|
/// </summary>
|
|
/// <param name="r">Rectangle to translate</param>
|
|
/// <returns>Screen Rectangle</returns>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns size translated to screen dimension if Zoom is not equal 1.
|
|
/// </summary>
|
|
/// <param name="s">Size to translate</param>
|
|
/// <returns>Screen Size</returns>
|
|
public virtual Size GetScreenSize(Size s)
|
|
{
|
|
return GetScreenRectangle(new Rectangle(Point.Empty, s)).Size;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Event Invocation
|
|
/// <summary>
|
|
/// Calls <see cref="OnAfterCheck">OnAfterCheck</see> method which fired
|
|
/// <see cref="AfterCheck">AfterCheck</see> event.
|
|
/// </summary>
|
|
/// <param name="e">Event arguments.</param>
|
|
internal void InvokeAfterCheck(TreeGXCellEventArgs e)
|
|
{
|
|
OnAfterCheck(e);
|
|
}
|
|
|
|
/// <summary>Raises the <see cref="AfterCheck">AfterCheck</see> event.</summary>
|
|
/// <param name="e">
|
|
/// A <see cref="TreeGXCellEventArgs">TreeGXEventArgs</see> that contains the event
|
|
/// data.
|
|
/// </param>
|
|
protected virtual void OnAfterCheck(TreeGXCellEventArgs e)
|
|
{
|
|
if(AfterCheck!=null)
|
|
AfterCheck(this,e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes CommandButtonClick event.
|
|
/// </summary>
|
|
/// <param name="node">Context node.</param>
|
|
/// <param name="e">Event arguments.</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes DeserializeNode event.
|
|
/// </summary>
|
|
/// <param name="e">Provides more information about the event</param>
|
|
protected virtual void OnDeserializeNode(SerializeNodeEventArgs e)
|
|
{
|
|
if(DeserializeNode!=null)
|
|
DeserializeNode(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes SerializeNode event.
|
|
/// </summary>
|
|
/// <param name="e">Provides more information about the event</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes the MarkupLinkClick evcent.
|
|
/// </summary>
|
|
/// <param name="sender">Sender of the event, usually instance Cell object.</param>
|
|
/// <param name="e">Event arguments</param>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes drag over event.
|
|
/// </summary>
|
|
/// <param name="drgevent">Drag event arguments.</param>
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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<dragNode.Cells.Count;i++)
|
|
{
|
|
if(originalNode.Cells[i].StyleNormal!=null)
|
|
{
|
|
ElementStyle cellStyle=originalNode.Cells[i].StyleNormal.Copy();
|
|
ElementStyle.SetColorsAlpha(style,alpha);
|
|
dragNode.Cells[i].StyleNormal=cellStyle;
|
|
}
|
|
else
|
|
dragNode.Cells[i].StyleNormal=style;
|
|
}
|
|
}
|
|
|
|
private bool StartDragDrop()
|
|
{
|
|
if(m_MouseOverNode==null)
|
|
return false;
|
|
|
|
return StartDragDrop(m_MouseOverNode);
|
|
}
|
|
|
|
internal bool StartDragDrop(Node node)
|
|
{
|
|
if(IsDragDropInProgress)
|
|
return false;
|
|
|
|
this.EndCellEditing(eTreeAction.Mouse);
|
|
|
|
if(node.IsMouseDown)
|
|
OnNodeMouseUp(new MouseEventArgs(Control.MouseButtons,0,0,0,0));
|
|
|
|
if(node == m_DisplayRootNode /*|| node.Parent==null*/) // Drag & drop in designer means that parent is null
|
|
return false;
|
|
|
|
Point m_MouseDownPoint=Control.MousePosition;
|
|
|
|
if(this.DesignMode)
|
|
CreateDragNode(node);
|
|
else
|
|
this.DoDragDrop(node,DragDropEffects.All);
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the display root node.
|
|
/// </summary>
|
|
/// <returns>Instance of node or null if there is no display root node.</returns>
|
|
internal Node GetDisplayRootNode()
|
|
{
|
|
if(m_DisplayRootNode!=null)
|
|
return m_DisplayRootNode;
|
|
if(this.Nodes.Count>0)
|
|
return this.Nodes[0];
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns reference to the node involved in drag-drop operation if any.
|
|
/// </summary>
|
|
/// <returns>Reference to node object or null if there is no drag node.</returns>
|
|
internal Node GetDragNode()
|
|
{
|
|
return m_DragNode;
|
|
}
|
|
#endregion
|
|
|
|
#region ISupportInitialize
|
|
/// <summary>
|
|
/// This member supports the .NET Framework infrastructure and is not intended to be
|
|
/// used directly from your code.
|
|
/// </summary>
|
|
public void BeginInit()
|
|
{
|
|
this.BeginUpdate();
|
|
}
|
|
|
|
/// <summary>
|
|
/// This member supports the .NET Framework infrastructure and is not intended to be
|
|
/// used directly from your code.
|
|
/// </summary>
|
|
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
|
|
}
|
|
}
|