first commit

This commit is contained in:
2025-04-07 07:44:27 -07:00
commit d6cde0c05e
512 changed files with 142392 additions and 0 deletions

View File

@@ -0,0 +1,314 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
public abstract class BaseTextControl : EditableControl
{
private TextFormatFlags _baseFormatFlags;
private TextFormatFlags _formatFlags;
private Pen _focusPen;
private StringFormat _format;
#region Properties
private Font _font = null;
public Font Font
{
get
{
if (_font == null)
return Control.DefaultFont;
else
return _font;
}
set
{
if (value == Control.DefaultFont)
_font = null;
else
_font = value;
}
}
protected bool ShouldSerializeFont()
{
return (_font != null);
}
private HorizontalAlignment _textAlign = HorizontalAlignment.Left;
[DefaultValue(HorizontalAlignment.Left)]
public HorizontalAlignment TextAlign
{
get { return _textAlign; }
set
{
_textAlign = value;
SetFormatFlags();
}
}
private StringTrimming _trimming = StringTrimming.None;
[DefaultValue(StringTrimming.None)]
public StringTrimming Trimming
{
get { return _trimming; }
set
{
_trimming = value;
SetFormatFlags();
}
}
private bool _displayHiddenContentInToolTip = true;
[DefaultValue(true)]
public bool DisplayHiddenContentInToolTip
{
get { return _displayHiddenContentInToolTip; }
set { _displayHiddenContentInToolTip = value; }
}
private bool _useCompatibleTextRendering = false;
[DefaultValue(false)]
public bool UseCompatibleTextRendering
{
get { return _useCompatibleTextRendering; }
set { _useCompatibleTextRendering = value; }
}
[DefaultValue(false)]
public bool TrimMultiLine
{
get;
set;
}
#endregion
protected BaseTextControl()
{
IncrementalSearchEnabled = true;
_focusPen = new Pen(Color.Black);
_focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
_format = new StringFormat(StringFormatFlags.LineLimit | StringFormatFlags.NoClip | StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces);
_baseFormatFlags = TextFormatFlags.PreserveGraphicsClipping |
TextFormatFlags.PreserveGraphicsTranslateTransform;
SetFormatFlags();
LeftMargin = 3;
}
private void SetFormatFlags()
{
_format.Alignment = TextHelper.TranslateAligment(TextAlign);
_format.Trimming = Trimming;
_formatFlags = _baseFormatFlags | TextHelper.TranslateAligmentToFlag(TextAlign)
| TextHelper.TranslateTrimmingToFlag(Trimming);
}
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
{
return GetLabelSize(node, context);
}
protected Size GetLabelSize(TreeNodeAdv node, DrawContext context)
{
return GetLabelSize(node, context, GetLabel(node));
}
protected Size GetLabelSize(TreeNodeAdv node, DrawContext context, string label)
{
PerformanceAnalyzer.Start("GetLabelSize");
CheckThread();
Font font = GetDrawingFont(node, context, label);
Size s = Size.Empty;
if (UseCompatibleTextRendering)
s = TextRenderer.MeasureText(label, font);
else
{
SizeF sf = context.Graphics.MeasureString(label, font);
s = new Size((int)Math.Ceiling(sf.Width), (int)Math.Ceiling(sf.Height));
}
PerformanceAnalyzer.Finish("GetLabelSize");
if (!s.IsEmpty)
return s;
else
return new Size(10, Font.Height);
}
protected Font GetDrawingFont(TreeNodeAdv node, DrawContext context, string label)
{
Font font = context.Font;
if (DrawTextMustBeFired(node))
{
DrawEventArgs args = new DrawEventArgs(node, this, context, label);
args.Font = context.Font;
OnDrawText(args);
font = args.Font;
}
return font;
}
protected void SetEditControlProperties(Control control, TreeNodeAdv node)
{
string label = GetLabel(node);
DrawContext context = new DrawContext();
context.Font = control.Font;
control.Font = GetDrawingFont(node, context, label);
}
public override void Draw(TreeNodeAdv node, DrawContext context)
{
if (context.CurrentEditorOwner == this && node == Parent.CurrentNode)
return;
PerformanceAnalyzer.Start("BaseTextControl.Draw");
string label = GetLabel(node);
Rectangle bounds = GetBounds(node, context);
Rectangle focusRect = new Rectangle(bounds.X, context.Bounds.Y,
bounds.Width, context.Bounds.Height);
Brush backgroundBrush;
Color textColor;
Font font;
CreateBrushes(node, context, label, out backgroundBrush, out textColor, out font, ref label);
if (backgroundBrush != null)
context.Graphics.FillRectangle(backgroundBrush, focusRect);
if (context.DrawFocus)
{
focusRect.Width--;
focusRect.Height--;
if (context.DrawSelection == DrawSelectionMode.None)
_focusPen.Color = SystemColors.ControlText;
else
_focusPen.Color = SystemColors.InactiveCaption;
context.Graphics.DrawRectangle(_focusPen, focusRect);
}
PerformanceAnalyzer.Start("BaseTextControl.DrawText");
if (UseCompatibleTextRendering)
TextRenderer.DrawText(context.Graphics, label, font, bounds, textColor, _formatFlags);
else
context.Graphics.DrawString(label, font, GetFrush(textColor), bounds, _format);
PerformanceAnalyzer.Finish("BaseTextControl.DrawText");
PerformanceAnalyzer.Finish("BaseTextControl.Draw");
}
private static Dictionary<Color, Brush> _brushes = new Dictionary<Color,Brush>();
private static Brush GetFrush(Color color)
{
Brush br;
if (_brushes.ContainsKey(color))
br = _brushes[color];
else
{
br = new SolidBrush(color);
_brushes.Add(color, br);
}
return br;
}
private void CreateBrushes(TreeNodeAdv node, DrawContext context, string text, out Brush backgroundBrush, out Color textColor, out Font font, ref string label)
{
textColor = Parent.ForeColor;
backgroundBrush = null;
font = context.Font;
if (context.DrawSelection == DrawSelectionMode.Active)
{
textColor = SystemColors.HighlightText;
backgroundBrush = SystemBrushes.Highlight;
}
else if (context.DrawSelection == DrawSelectionMode.Inactive)
{
textColor = Parent.ForeColor;
backgroundBrush = SystemBrushes.InactiveBorder;
}
else if (context.DrawSelection == DrawSelectionMode.FullRowSelect)
textColor = Parent.ForeColor;
if (!context.Enabled)
textColor = SystemColors.GrayText;
if (DrawTextMustBeFired(node))
{
DrawEventArgs args = new DrawEventArgs(node, this, context, text);
args.Text = label;
args.TextColor = textColor;
args.BackgroundBrush = backgroundBrush;
args.Font = font;
OnDrawText(args);
textColor = args.TextColor;
backgroundBrush = args.BackgroundBrush;
font = args.Font;
label = args.Text;
}
}
public string GetLabel(TreeNodeAdv node)
{
if (node != null && node.Tag != null)
{
object obj = GetValue(node);
if (obj != null)
return FormatLabel(obj);
}
return string.Empty;
}
protected virtual string FormatLabel(object obj)
{
var res = obj.ToString();
if (TrimMultiLine && res != null)
{
string[] parts = res.Split('\n');
if (parts.Length > 1)
return parts[0] + "...";
}
return res;
}
public void SetLabel(TreeNodeAdv node, string value)
{
SetValue(node, value);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_focusPen.Dispose();
_format.Dispose();
}
}
/// <summary>
/// Fires when control is going to draw a text. Can be used to change text or back color
/// </summary>
public event EventHandler<DrawEventArgs> DrawText;
protected virtual void OnDrawText(DrawEventArgs args)
{
TreeViewAdv tree = args.Node.Tree;
if (tree != null)
tree.FireDrawControl(args);
if (DrawText != null)
DrawText(this, args);
}
protected virtual bool DrawTextMustBeFired(TreeNodeAdv node)
{
return DrawText != null || (node.Tree != null && node.Tree.DrawControlMustBeFired());
}
}
}

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
public abstract class BindableControl : NodeControl
{
private struct MemberAdapter
{
private object _obj;
private PropertyInfo _pi;
private FieldInfo _fi;
public static readonly MemberAdapter Empty = new MemberAdapter();
public Type MemberType
{
get
{
if (_pi != null)
return _pi.PropertyType;
else if (_fi != null)
return _fi.FieldType;
else
return null;
}
}
public object Value
{
get
{
if (_pi != null && _pi.CanRead)
return _pi.GetValue(_obj, null);
else if (_fi != null)
return _fi.GetValue(_obj);
else
return null;
}
set
{
if (_pi != null && _pi.CanWrite)
_pi.SetValue(_obj, value, null);
else if (_fi != null)
_fi.SetValue(_obj, value);
}
}
public MemberAdapter(object obj, PropertyInfo pi)
{
_obj = obj;
_pi = pi;
_fi = null;
}
public MemberAdapter(object obj, FieldInfo fi)
{
_obj = obj;
_fi = fi;
_pi = null;
}
}
#region Properties
private bool _virtualMode = false;
[DefaultValue(false), Category("Data")]
public bool VirtualMode
{
get { return _virtualMode; }
set { _virtualMode = value; }
}
private string _propertyName = "";
[DefaultValue(""), Category("Data")]
public string DataPropertyName
{
get { return _propertyName; }
set
{
if (_propertyName == null)
_propertyName = string.Empty;
_propertyName = value;
}
}
private bool _incrementalSearchEnabled = false;
[DefaultValue(false)]
public bool IncrementalSearchEnabled
{
get { return _incrementalSearchEnabled; }
set { _incrementalSearchEnabled = value; }
}
#endregion
public virtual object GetValue(TreeNodeAdv node)
{
if (VirtualMode)
{
NodeControlValueEventArgs args = new NodeControlValueEventArgs(node);
OnValueNeeded(args);
return args.Value;
}
else
{
try
{
return GetMemberAdapter(node).Value;
}
catch (TargetInvocationException ex)
{
if (ex.InnerException != null)
throw new ArgumentException(ex.InnerException.Message, ex.InnerException);
else
throw new ArgumentException(ex.Message);
}
}
}
public virtual void SetValue(TreeNodeAdv node, object value)
{
if (VirtualMode)
{
NodeControlValueEventArgs args = new NodeControlValueEventArgs(node);
args.Value = value;
OnValuePushed(args);
}
else
{
try
{
MemberAdapter ma = GetMemberAdapter(node);
ma.Value = value;
}
catch (TargetInvocationException ex)
{
if (ex.InnerException != null)
throw new ArgumentException(ex.InnerException.Message, ex.InnerException);
else
throw new ArgumentException(ex.Message);
}
}
}
public Type GetPropertyType(TreeNodeAdv node)
{
return GetMemberAdapter(node).MemberType;
}
private MemberAdapter GetMemberAdapter(TreeNodeAdv node)
{
if (node.Tag != null && !string.IsNullOrEmpty(DataPropertyName))
{
Type type = node.Tag.GetType();
PropertyInfo pi = type.GetProperty(DataPropertyName);
if (pi != null)
return new MemberAdapter(node.Tag, pi);
else
{
FieldInfo fi = type.GetField(DataPropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (fi != null)
return new MemberAdapter(node.Tag, fi);
}
}
return MemberAdapter.Empty;
}
public override string ToString()
{
if (string.IsNullOrEmpty(DataPropertyName))
return GetType().Name;
else
return string.Format("{0} ({1})", GetType().Name, DataPropertyName);
}
public event EventHandler<NodeControlValueEventArgs> ValueNeeded;
private void OnValueNeeded(NodeControlValueEventArgs args)
{
if (ValueNeeded != null)
ValueNeeded(this, args);
}
public event EventHandler<NodeControlValueEventArgs> ValuePushed;
private void OnValuePushed(NodeControlValueEventArgs args)
{
if (ValuePushed != null)
ValuePushed(this, args);
}
}
}

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Font Name="Microsoft Sans Serif" Size="8.25" />
<Class Name="Aga.Controls.Tree.NodeControls.NodeStateIcon" Collapsed="true">
<Position X="0.5" Y="4" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeStateIcon.cs</FileName>
<HashCode>ABAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAQIAAAAAAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.BindableControl" Collapsed="true">
<Position X="2.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\BindableControl.cs</FileName>
<HashCode>FAAAAAAQIBAQCgAEAAAAIAAAAAAAAAEMAAACAAAAAAE=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodeCheckBox" Collapsed="true">
<Position X="5" Y="4" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeCheckBox.cs</FileName>
<HashCode>AAEAAAAAAAACgkQCAAAAAAigAgAAEGABAAAIAAAAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodeControl" Collapsed="true">
<Position X="1.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeControl.cs</FileName>
<HashCode>AAAAAJAAgIgBkkoQAAgAQAAwAAABEIQAAEBIAAAAAAA=</HashCode>
</TypeIdentifier>
<Compartments>
<Compartment Name="Fields" Collapsed="true" />
</Compartments>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodeIcon" Collapsed="true">
<Position X="0.5" Y="2.75" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeIcon.cs</FileName>
<HashCode>ABAAAAAAAAAAAgAAAAAAAAAgAAAAAAAAAAAAAAAAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodePlusMinus" Collapsed="true">
<Position X="0.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodePlusMinus.cs</FileName>
<HashCode>AAAAAAAAAAAAAgAAAAAAAEAgAAAAMCAAAAAIACAAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.BaseTextControl" Collapsed="true">
<Position X="3" Y="5" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\BaseTextControl.cs</FileName>
<HashCode>AAAAICBQACAAIgACBCAEAQA8AgmFoAAwAAAAACACAMA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodeTextBox" Collapsed="true">
<Position X="1" Y="6" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeTextBox.cs</FileName>
<HashCode>QQQAhAAAADAMgAAAABAAAAAAAgEAIAAAAAAAAIAAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.EditableControl" Collapsed="true">
<Position X="3" Y="4" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\EditableControl.cs</FileName>
<HashCode>QQAgAAAACGgkAMAABAEEkADAEAAUEAAABAGoAAAAAQA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodeComboBox" Collapsed="true">
<Position X="3" Y="6" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeComboBox.cs</FileName>
<HashCode>wQACAAAAAAAMAEBAAAAAAABAAAAAAAABAAAAAAAAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodeNumericUpDown" Collapsed="true">
<Position X="5" Y="6" Width="1.75" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeNumericUpDown.cs</FileName>
<HashCode>wQAAAACAAAAEAABAIAAQIAAAAAAAAAABAAAIAAAAAII=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.InteractiveControl" Collapsed="true">
<Position X="4" Y="2.75" Width="1.5" />
<TypeIdentifier>
<FileName>Tree\NodeControls\InteractiveControl.cs</FileName>
<HashCode>AAAABAAAAAAAAAAACAAAAAAAABAAAQAAAAAAAAIAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodeDecimalTextBox" Collapsed="true">
<Position X="2.5" Y="7" Width="1.75" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeDecimalTextBox.cs</FileName>
<HashCode>AQAAAAAAAACAAAACAAAAAAQAAAAAIAAAAAgAAAAAAAA=</HashCode>
</TypeIdentifier>
</Class>
<Class Name="Aga.Controls.Tree.NodeControls.NodeIntegerTextBox" Collapsed="true">
<Position X="0.5" Y="7" Width="1.75" />
<TypeIdentifier>
<FileName>Tree\NodeControls\NodeIntegerTextBox.cs</FileName>
<HashCode>AQAAAAAAAAAAAAACAAAAAAQAAAAAIAAAAAAAAAAAAAA=</HashCode>
</TypeIdentifier>
</Class>
</ClassDiagram>

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace Aga.Controls.Tree.NodeControls
{
public class DrawEventArgs : NodeEventArgs
{
private DrawContext _context;
public DrawContext Context
{
get { return _context; }
}
private Brush _textBrush;
[Obsolete("Use TextColor")]
public Brush TextBrush
{
get { return _textBrush; }
set { _textBrush = value; }
}
private Brush _backgroundBrush;
public Brush BackgroundBrush
{
get { return _backgroundBrush; }
set { _backgroundBrush = value; }
}
private Font _font;
public Font Font
{
get { return _font; }
set { _font = value; }
}
private Color _textColor;
public Color TextColor
{
get { return _textColor; }
set { _textColor = value; }
}
private string _text;
public string Text
{
get { return _text; }
set { _text = value; }
}
private EditableControl _control;
public EditableControl Control
{
get { return _control; }
}
public DrawEventArgs(TreeNodeAdv node, EditableControl control, DrawContext context, string text)
: base(node)
{
_control = control;
_context = context;
_text = text;
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace Aga.Controls.Tree.NodeControls
{
public class EditEventArgs : NodeEventArgs
{
private Control _control;
public Control Control
{
get { return _control; }
}
public EditEventArgs(TreeNodeAdv node, Control control)
: base(node)
{
_control = control;
}
}
}

View File

@@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
public abstract class EditableControl : InteractiveControl
{
private Timer _timer;
private bool _editFlag;
#region Properties
private bool _editOnClick = false;
[DefaultValue(false)]
public bool EditOnClick
{
get { return _editOnClick; }
set { _editOnClick = value; }
}
#endregion
protected EditableControl()
{
_timer = new Timer();
_timer.Interval = 500;
_timer.Tick += new EventHandler(TimerTick);
}
private void TimerTick(object sender, EventArgs e)
{
_timer.Stop();
if (_editFlag)
BeginEdit();
_editFlag = false;
}
public void SetEditorBounds(EditorContext context)
{
Size size = CalculateEditorSize(context);
context.Editor.Bounds = new Rectangle(context.Bounds.X, context.Bounds.Y,
Math.Min(size.Width, context.Bounds.Width),
Math.Min(size.Height, Parent.ClientSize.Height - context.Bounds.Y)
);
}
protected abstract Size CalculateEditorSize(EditorContext context);
protected virtual bool CanEdit(TreeNodeAdv node)
{
return (node.Tag != null) && IsEditEnabled(node);
}
public void BeginEdit()
{
if (Parent != null && Parent.CurrentNode != null && CanEdit(Parent.CurrentNode))
{
CancelEventArgs args = new CancelEventArgs();
OnEditorShowing(args);
if (!args.Cancel)
{
var editor = CreateEditor(Parent.CurrentNode);
Parent.DisplayEditor(editor, this);
}
}
}
public void EndEdit(bool applyChanges)
{
if (Parent != null)
if (Parent.HideEditor(applyChanges))
OnEditorHided();
}
public virtual void UpdateEditor(Control control)
{
}
internal void ApplyChanges(TreeNodeAdv node, Control editor)
{
DoApplyChanges(node, editor);
OnChangesApplied();
}
internal void DoDisposeEditor(Control editor)
{
DisposeEditor(editor);
}
protected abstract void DoApplyChanges(TreeNodeAdv node, Control editor);
protected abstract Control CreateEditor(TreeNodeAdv node);
protected abstract void DisposeEditor(Control editor);
public virtual void Cut(Control control)
{
}
public virtual void Copy(Control control)
{
}
public virtual void Paste(Control control)
{
}
public virtual void Delete(Control control)
{
}
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
{
_editFlag = (!EditOnClick && args.Button == MouseButtons.Left
&& args.ModifierKeys == Keys.None && args.Node.IsSelected);
}
public override void MouseUp(TreeNodeAdvMouseEventArgs args)
{
if (args.Node.IsSelected)
{
if (EditOnClick && args.Button == MouseButtons.Left && args.ModifierKeys == Keys.None)
{
Parent.ItemDragMode = false;
BeginEdit();
args.Handled = true;
}
else if (_editFlag)// && args.Node.IsSelected)
_timer.Start();
}
}
public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
{
_editFlag = false;
_timer.Stop();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
_timer.Dispose();
}
#region Events
public event CancelEventHandler EditorShowing;
protected void OnEditorShowing(CancelEventArgs args)
{
if (EditorShowing != null)
EditorShowing(this, args);
}
public event EventHandler EditorHided;
protected void OnEditorHided()
{
if (EditorHided != null)
EditorHided(this, EventArgs.Empty);
}
public event EventHandler ChangesApplied;
protected void OnChangesApplied()
{
if (ChangesApplied != null)
ChangesApplied(this, EventArgs.Empty);
}
#endregion
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
namespace Aga.Controls.Tree.NodeControls
{
/// <summary>
/// Displays an animated icon for those nodes, who are in expanding state.
/// Parent TreeView must have AsyncExpanding property set to true.
/// </summary>
public class ExpandingIcon: NodeControl
{
private static GifDecoder _gif = ResourceHelper.LoadingIcon;
private static int _index = 0;
private static volatile Thread _animatingThread;
private static object _lock = new object();
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
{
return ResourceHelper.LoadingIcon.FrameSize;
}
protected override void OnIsVisibleValueNeeded(NodeControlValueEventArgs args)
{
args.Value = args.Node.IsExpandingNow;
base.OnIsVisibleValueNeeded(args);
}
public override void Draw(TreeNodeAdv node, DrawContext context)
{
Rectangle rect = GetBounds(node, context);
Image img = _gif.GetFrame(_index).Image;
context.Graphics.DrawImage(img, rect.Location);
}
public static void Start()
{
lock (_lock)
{
if (_animatingThread == null)
{
_index = 0;
_animatingThread = new Thread(new ThreadStart(IterateIcons));
_animatingThread.IsBackground = true;
_animatingThread.Priority = ThreadPriority.Lowest;
_animatingThread.Start();
}
}
}
public static void Stop()
{
lock (_lock)
{
_index = 0;
_animatingThread = null;
}
}
private static void IterateIcons()
{
while (_animatingThread != null)
{
if (_index < _gif.FrameCount - 1)
_index++;
else
_index = 0;
if (IconChanged != null)
IconChanged(null, EventArgs.Empty);
int delay = _gif.GetFrame(_index).Delay;
Thread.Sleep(delay);
}
System.Diagnostics.Debug.WriteLine("IterateIcons Stopped");
}
public static event EventHandler IconChanged;
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
public abstract class InteractiveControl : BindableControl
{
private bool _editEnabled = false;
[DefaultValue(false)]
public bool EditEnabled
{
get { return _editEnabled; }
set { _editEnabled = value; }
}
protected bool IsEditEnabled(TreeNodeAdv node)
{
if (EditEnabled)
{
NodeControlValueEventArgs args = new NodeControlValueEventArgs(node);
args.Value = true;
OnIsEditEnabledValueNeeded(args);
return Convert.ToBoolean(args.Value);
}
else
return false;
}
public event EventHandler<NodeControlValueEventArgs> IsEditEnabledValueNeeded;
private void OnIsEditEnabledValueNeeded(NodeControlValueEventArgs args)
{
if (IsEditEnabledValueNeeded != null)
IsEditEnabledValueNeeded(this, args);
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Aga.Controls.Tree.NodeControls
{
public class LabelEventArgs : EventArgs
{
private object _subject;
public object Subject
{
get { return _subject; }
}
private string _oldLabel;
public string OldLabel
{
get { return _oldLabel; }
}
private string _newLabel;
public string NewLabel
{
get { return _newLabel; }
}
public LabelEventArgs(object subject, string oldLabel, string newLabel)
{
_subject = subject;
_oldLabel = oldLabel;
_newLabel = newLabel;
}
}
}

View File

@@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Aga.Controls.Properties;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeCheckBox : InteractiveControl
{
public const int ImageSize = 13;
private Bitmap _check;
private Bitmap _uncheck;
private Bitmap _unknown;
#region Properties
private bool _threeState;
[DefaultValue(false)]
public bool ThreeState
{
get { return _threeState; }
set { _threeState = value; }
}
#endregion
public NodeCheckBox()
: this(string.Empty)
{
}
public NodeCheckBox(string propertyName)
{
_check = Resources.check;
_uncheck = Resources.uncheck;
_unknown = Resources.unknown;
DataPropertyName = propertyName;
LeftMargin = 0;
}
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
{
int scaledX = node.Tree.GetScaledSize(ImageSize, false);
int scaledY = node.Tree.GetScaledSize(ImageSize);
return new Size(scaledX, scaledY);
}
public override void Draw(TreeNodeAdv node, DrawContext context)
{
Rectangle bounds = GetBounds(node, context);
CheckState state = GetCheckState(node);
if (TreeViewAdv.CustomCheckRenderFunc != null)
{
TreeViewAdv.CustomCheckRenderFunc(context.Graphics, bounds, state == CheckState.Checked);
}
else if (Application.RenderWithVisualStyles)
{
VisualStyleRenderer renderer;
int scaledX = node.Tree.GetScaledSize(ImageSize, false);
int scaledY = node.Tree.GetScaledSize(ImageSize);
if (state == CheckState.Indeterminate)
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.MixedNormal);
else if (state == CheckState.Checked)
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.CheckedNormal);
else
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.UncheckedNormal);
renderer.DrawBackground(context.Graphics, new Rectangle(bounds.X, bounds.Y, scaledX, scaledY));
}
else
{
Image img;
if (state == CheckState.Indeterminate)
img = _unknown;
else if (state == CheckState.Checked)
img = _check;
else
img = _uncheck;
context.Graphics.DrawImage(img, bounds.Location);
}
}
protected virtual CheckState GetCheckState(TreeNodeAdv node)
{
object obj = GetValue(node);
if (obj is CheckState)
return (CheckState)obj;
else if (obj is bool)
return (bool)obj ? CheckState.Checked : CheckState.Unchecked;
else
return CheckState.Unchecked;
}
protected virtual void SetCheckState(TreeNodeAdv node, CheckState value)
{
if (VirtualMode)
{
SetValue(node, value);
OnCheckStateChanged(node);
}
else
{
Type type = GetPropertyType(node);
if (type == typeof(CheckState))
{
SetValue(node, value);
OnCheckStateChanged(node);
}
else if (type == typeof(bool))
{
SetValue(node, value != CheckState.Unchecked);
OnCheckStateChanged(node);
}
}
}
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
{
if (args.Button == MouseButtons.Left && IsEditEnabled(args.Node))
{
DrawContext context = new DrawContext();
context.Bounds = args.ControlBounds;
Rectangle rect = GetBounds(args.Node, context);
if (rect.Contains(args.ViewLocation))
{
CheckState state = GetCheckState(args.Node);
state = GetNewState(state);
SetCheckState(args.Node, state);
Parent.UpdateView();
args.Handled = true;
}
}
}
public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
{
args.Handled = true;
}
private CheckState GetNewState(CheckState state)
{
if (state == CheckState.Indeterminate)
return CheckState.Unchecked;
else if(state == CheckState.Unchecked)
return CheckState.Checked;
else
return ThreeState ? CheckState.Indeterminate : CheckState.Unchecked;
}
public override void KeyDown(KeyEventArgs args)
{
if (args.KeyCode == Keys.Space && EditEnabled)
{
Parent.BeginUpdate();
try
{
if (Parent.CurrentNode != null)
{
CheckState value = GetNewState(GetCheckState(Parent.CurrentNode));
foreach (TreeNodeAdv node in Parent.Selection)
if (IsEditEnabled(node))
SetCheckState(node, value);
}
}
finally
{
Parent.EndUpdate();
}
args.Handled = true;
}
}
public event EventHandler<TreePathEventArgs> CheckStateChanged;
protected void OnCheckStateChanged(TreePathEventArgs args)
{
if (CheckStateChanged != null)
CheckStateChanged(this, args);
}
protected void OnCheckStateChanged(TreeNodeAdv node)
{
TreePath path = this.Parent.GetPath(node);
OnCheckStateChanged(new TreePathEventArgs(path));
}
}
}

View File

@@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using System.ComponentModel;
using System.Drawing.Design;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeComboBox : BaseTextControl
{
#region Properties
private int _editorWidth = 100;
[DefaultValue(100)]
public int EditorWidth
{
get { return _editorWidth; }
set { _editorWidth = value; }
}
private int _editorHeight = 100;
[DefaultValue(100)]
public int EditorHeight
{
get { return _editorHeight; }
set { _editorHeight = value; }
}
private List<object> _dropDownItems;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
[Editor(typeof(StringCollectionEditor), typeof(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<object> DropDownItems
{
get { return _dropDownItems; }
}
#endregion
public event EventHandler<EditEventArgs> CreatingEditor;
public NodeComboBox()
{
_dropDownItems = new List<object>();
}
protected override Size CalculateEditorSize(EditorContext context)
{
if (Parent.UseColumns)
{
if (context.Editor is CheckedListBox)
return new Size(context.Bounds.Size.Width, EditorHeight);
else
return context.Bounds.Size;
}
else
{
if (context.Editor is CheckedListBox)
return new Size(EditorWidth, EditorHeight);
else
return new Size(EditorWidth, context.Bounds.Height);
}
}
protected override Control CreateEditor(TreeNodeAdv node)
{
Control c;
object value = GetValue(node);
if (IsCheckedListBoxRequired(node))
c = CreateCheckedListBox(node);
else
c = CreateCombo(node);
OnCreatingEditor(new EditEventArgs(node, c));
return c;
}
protected override void DisposeEditor(Control editor)
{
}
protected virtual void OnCreatingEditor(EditEventArgs args)
{
if (CreatingEditor != null)
CreatingEditor(this, args);
}
protected virtual bool IsCheckedListBoxRequired(TreeNodeAdv node)
{
object value = GetValue(node);
if (value != null)
{
Type t = value.GetType();
object[] arr = t.GetCustomAttributes(typeof(FlagsAttribute), false);
return (t.IsEnum && arr.Length == 1);
}
return false;
}
private Control CreateCombo(TreeNodeAdv node)
{
ComboBox comboBox = new ComboBox();
if (DropDownItems != null)
comboBox.Items.AddRange(DropDownItems.ToArray());
comboBox.SelectedItem = GetValue(node);
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
comboBox.DropDownClosed += new EventHandler(EditorDropDownClosed);
SetEditControlProperties(comboBox, node);
return comboBox;
}
private Control CreateCheckedListBox(TreeNodeAdv node)
{
CheckedListBox listBox = new CheckedListBox();
listBox.CheckOnClick = true;
object value = GetValue(node);
Type enumType = GetEnumType(node);
foreach (object obj in Enum.GetValues(enumType))
{
object[] attributes = enumType.GetField(obj.ToString()).GetCustomAttributes(typeof(BrowsableAttribute), false);
if (attributes.Length == 0 || ((BrowsableAttribute)attributes[0]).Browsable)
listBox.Items.Add(obj, IsContain(value, obj));
}
SetEditControlProperties(listBox, node);
if (CreatingEditor != null)
CreatingEditor(this, new EditEventArgs(node, listBox));
return listBox;
}
protected virtual Type GetEnumType(TreeNodeAdv node)
{
object value = GetValue(node);
return value.GetType();
}
private bool IsContain(object value, object enumElement)
{
if (value == null || enumElement == null)
return false;
if (value.GetType().IsEnum)
{
int i1 = (int)value;
int i2 = (int)enumElement;
return (i1 & i2) == i2;
}
else
{
var arr = value as object[];
foreach (object obj in arr)
if ((int)obj == (int)enumElement)
return true;
return false;
}
}
protected override string FormatLabel(object obj)
{
var arr = obj as object[];
if (arr != null)
{
StringBuilder sb = new StringBuilder();
foreach (object t in arr)
{
if (sb.Length > 0)
sb.Append(", ");
sb.Append(t);
}
return sb.ToString();
}
else
return base.FormatLabel(obj);
}
void EditorDropDownClosed(object sender, EventArgs e)
{
EndEdit(true);
}
public override void UpdateEditor(Control control)
{
if (control is ComboBox)
(control as ComboBox).DroppedDown = true;
}
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
{
var combo = editor as ComboBox;
if (combo != null)
{
if (combo.DropDownStyle == ComboBoxStyle.DropDown)
SetValue(node, combo.Text);
else
SetValue(node, combo.SelectedItem);
}
else
{
var listBox = editor as CheckedListBox;
Type type = GetEnumType(node);
if (IsFlags(type))
{
int res = 0;
foreach (object obj in listBox.CheckedItems)
res |= (int)obj;
object val = Enum.ToObject(type, res);
SetValue(node, val);
}
else
{
List<object> list = new List<object>();
foreach (object obj in listBox.CheckedItems)
list.Add(obj);
SetValue(node, list.ToArray());
}
}
}
private bool IsFlags(Type type)
{
object[] atr = type.GetCustomAttributes(typeof(FlagsAttribute), false);
return atr.Length == 1;
}
public override void MouseUp(TreeNodeAdvMouseEventArgs args)
{
if (args.Node != null && args.Node.IsSelected) //Workaround of specific ComboBox control behavior
base.MouseUp(args);
}
}
}

View File

@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
[DesignTimeVisible(false), ToolboxItem(false)]
public abstract class NodeControl : Component
{
#region Properties
private TreeViewAdv _parent;
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public TreeViewAdv Parent
{
get { return _parent; }
set
{
if (value != _parent)
{
if (_parent != null)
_parent.NodeControls.Remove(this);
if (value != null)
value.NodeControls.Add(this);
}
}
}
private IToolTipProvider _toolTipProvider;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IToolTipProvider ToolTipProvider
{
get { return _toolTipProvider; }
set { _toolTipProvider = value; }
}
private TreeColumn _parentColumn;
public TreeColumn ParentColumn
{
get { return _parentColumn; }
set
{
_parentColumn = value;
if (_parent != null)
_parent.FullUpdate();
}
}
private VerticalAlignment _verticalAlign = VerticalAlignment.Center;
[DefaultValue(VerticalAlignment.Center)]
public VerticalAlignment VerticalAlign
{
get { return _verticalAlign; }
set
{
_verticalAlign = value;
if (_parent != null)
_parent.FullUpdate();
}
}
private int _leftMargin = 0;
public int LeftMargin
{
get { return _leftMargin; }
set
{
if (value < 0)
throw new ArgumentOutOfRangeException();
_leftMargin = value;
if (_parent != null)
_parent.FullUpdate();
}
}
#endregion
internal virtual void AssignParent(TreeViewAdv parent)
{
_parent = parent;
}
protected virtual Rectangle GetBounds(TreeNodeAdv node, DrawContext context)
{
Rectangle r = context.Bounds;
Size s = GetActualSize(node, context);
Size bs = new Size(r.Width - LeftMargin, Math.Min(r.Height, s.Height));
switch (VerticalAlign)
{
case VerticalAlignment.Top:
return new Rectangle(new Point(r.X + LeftMargin, r.Y), bs);
case VerticalAlignment.Bottom:
return new Rectangle(new Point(r.X + LeftMargin, r.Bottom - s.Height), bs);
default:
return new Rectangle(new Point(r.X + LeftMargin, r.Y + (r.Height - s.Height) / 2), bs);
}
}
protected void CheckThread()
{
if (Parent != null && Control.CheckForIllegalCrossThreadCalls)
if (Parent.InvokeRequired)
throw new InvalidOperationException("Cross-thread calls are not allowed");
}
public bool IsVisible(TreeNodeAdv node)
{
NodeControlValueEventArgs args = new NodeControlValueEventArgs(node);
args.Value = true;
OnIsVisibleValueNeeded(args);
return Convert.ToBoolean(args.Value);
}
internal Size GetActualSize(TreeNodeAdv node, DrawContext context)
{
if (IsVisible(node))
{
Size s = MeasureSize(node, context);
return new Size(s.Width + LeftMargin, s.Height);
}
else
return Size.Empty;
}
public abstract Size MeasureSize(TreeNodeAdv node, DrawContext context);
public abstract void Draw(TreeNodeAdv node, DrawContext context);
public virtual string GetToolTip(TreeNodeAdv node)
{
if (ToolTipProvider != null)
return ToolTipProvider.GetToolTip(node, this);
else
return string.Empty;
}
public virtual void MouseDown(TreeNodeAdvMouseEventArgs args)
{
}
public virtual void MouseUp(TreeNodeAdvMouseEventArgs args)
{
}
public virtual void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
{
}
public virtual void KeyDown(KeyEventArgs args)
{
}
public virtual void KeyUp(KeyEventArgs args)
{
}
public event EventHandler<NodeControlValueEventArgs> IsVisibleValueNeeded;
protected virtual void OnIsVisibleValueNeeded(NodeControlValueEventArgs args)
{
if (IsVisibleValueNeeded != null)
IsVisibleValueNeeded(this, args);
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeControlValueEventArgs : NodeEventArgs
{
private object _value;
public object Value
{
get { return _value; }
set { _value = value; }
}
public NodeControlValueEventArgs(TreeNodeAdv node)
:base(node)
{
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel.Design;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing.Design;
namespace Aga.Controls.Tree.NodeControls
{
internal class NodeControlsCollection : Collection<NodeControl>
{
private TreeViewAdv _tree;
public NodeControlsCollection(TreeViewAdv tree)
{
_tree = tree;
}
protected override void ClearItems()
{
_tree.BeginUpdate();
try
{
while (this.Count != 0)
this.RemoveAt(this.Count - 1);
}
finally
{
_tree.EndUpdate();
}
}
protected override void InsertItem(int index, NodeControl item)
{
if (item == null)
throw new ArgumentNullException("item");
if (item.Parent != _tree)
{
if (item.Parent != null)
{
item.Parent.NodeControls.Remove(item);
}
base.InsertItem(index, item);
item.AssignParent(_tree);
_tree.FullUpdate();
}
}
protected override void RemoveItem(int index)
{
NodeControl value = this[index];
value.AssignParent(null);
base.RemoveItem(index);
_tree.FullUpdate();
}
protected override void SetItem(int index, NodeControl item)
{
if (item == null)
throw new ArgumentNullException("item");
_tree.BeginUpdate();
try
{
RemoveAt(index);
InsertItem(index, item);
}
finally
{
_tree.EndUpdate();
}
}
}
internal class NodeControlCollectionEditor : CollectionEditor
{
private Type[] _types;
public NodeControlCollectionEditor(Type type)
: base(type)
{
_types = new Type[] { typeof(NodeTextBox), typeof(NodeIntegerTextBox), typeof(NodeDecimalTextBox),
typeof(NodeComboBox), typeof(NodeCheckBox),
typeof(NodeStateIcon), typeof(NodeIcon), typeof(NodeNumericUpDown), typeof(ExpandingIcon) };
}
protected override System.Type[] CreateNewItemTypes()
{
return _types;
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeDecimalTextBox : NodeTextBox
{
private bool _allowDecimalSeparator = true;
[DefaultValue(true)]
public bool AllowDecimalSeparator
{
get { return _allowDecimalSeparator; }
set { _allowDecimalSeparator = value; }
}
private bool _allowNegativeSign = true;
[DefaultValue(true)]
public bool AllowNegativeSign
{
get { return _allowNegativeSign; }
set { _allowNegativeSign = value; }
}
protected NodeDecimalTextBox()
{
}
protected override TextBox CreateTextBox()
{
NumericTextBox textBox = new NumericTextBox();
textBox.AllowDecimalSeparator = AllowDecimalSeparator;
textBox.AllowNegativeSign = AllowNegativeSign;
return textBox;
}
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
{
SetValue(node, (editor as NumericTextBox).DecimalValue);
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeEventArgs : EventArgs
{
private TreeNodeAdv _node;
public TreeNodeAdv Node
{
get { return _node; }
}
public NodeEventArgs(TreeNodeAdv node)
{
_node = node;
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Aga.Controls.Properties;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeIcon : BindableControl
{
public NodeIcon()
{
LeftMargin = 1;
}
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
{
Image image = GetIcon(node);
if (image != null)
{
int scaledX = node.Tree.GetScaledSize(image.Size.Width, false);
int scaledY = node.Tree.GetScaledSize(image.Size.Height);
return new Size(scaledX, scaledY); ;
}
else
{
return Size.Empty;
}
}
public override void Draw(TreeNodeAdv node, DrawContext context)
{
Image image = GetIcon(node);
if (image != null)
{
Rectangle r = GetBounds(node, context);
if ( image.Width > 0 && image.Height > 0 )
{
switch (_scaleMode)
{
case ImageScaleMode.Fit:
context.Graphics.DrawImage(image, r);
break;
case ImageScaleMode.ScaleDown:
{
float factor = Math.Min((float)r.Width / (float)image.Width, (float)r.Height / (float)image.Height);
if (factor < 1)
context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor);
else
context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height);
} break;
case ImageScaleMode.ScaleUp:
{
float factor = Math.Max((float)r.Width / (float)image.Width, (float)r.Height / (float)image.Height);
if (factor > 1)
context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor);
else
context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height);
} break;
case ImageScaleMode.AlwaysScale:
{
float fx = (float)r.Width / (float)image.Width;
float fy = (float)r.Height / (float)image.Height;
if (Math.Min(fx, fy) < 1)
{ //scale down
float factor = Math.Min(fx, fy);
context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor);
}
else if (Math.Max(fx, fy) > 1)
{
float factor = Math.Max(fx, fy);
context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor);
}
else
context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height);
} break;
case ImageScaleMode.Clip:
default:
context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height);
break;
}
}
}
}
protected virtual Image GetIcon(TreeNodeAdv node)
{
return GetValue(node) as Image;
}
private ImageScaleMode _scaleMode = ImageScaleMode.Clip;
[DefaultValue("Clip"), Category("Appearance")]
public ImageScaleMode ScaleMode
{
get { return _scaleMode; }
set { _scaleMode = value; }
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeIntegerTextBox : NodeTextBox
{
private bool _allowNegativeSign = true;
[DefaultValue(true)]
public bool AllowNegativeSign
{
get { return _allowNegativeSign; }
set { _allowNegativeSign = value; }
}
public NodeIntegerTextBox()
{
}
protected override TextBox CreateTextBox()
{
NumericTextBox textBox = new NumericTextBox();
textBox.AllowDecimalSeparator = false;
textBox.AllowNegativeSign = AllowNegativeSign;
return textBox;
}
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
{
SetValue(node, (editor as NumericTextBox).IntValue);
}
}
}

View File

@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using System.ComponentModel;
using System.Drawing.Design;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeNumericUpDown : BaseTextControl
{
#region Properties
private int _editorWidth = 100;
[DefaultValue(100)]
public int EditorWidth
{
get { return _editorWidth; }
set { _editorWidth = value; }
}
private int _decimalPlaces = 0;
[Category("Data"), DefaultValue(0)]
public int DecimalPlaces
{
get
{
return this._decimalPlaces;
}
set
{
this._decimalPlaces = value;
}
}
private decimal _increment = 1;
[Category("Data"), DefaultValue(1)]
public decimal Increment
{
get
{
return this._increment;
}
set
{
this._increment = value;
}
}
private decimal _minimum = 0;
[Category("Data"), DefaultValue(0)]
public decimal Minimum
{
get
{
return _minimum;
}
set
{
_minimum = value;
}
}
private decimal _maximum = 100;
[Category("Data"), DefaultValue(100)]
public decimal Maximum
{
get
{
return this._maximum;
}
set
{
this._maximum = value;
}
}
#endregion
public NodeNumericUpDown()
{
}
protected override Size CalculateEditorSize(EditorContext context)
{
if (Parent.UseColumns)
return context.Bounds.Size;
else
return new Size(EditorWidth, context.Bounds.Height);
}
protected override Control CreateEditor(TreeNodeAdv node)
{
NumericUpDown num = new NumericUpDown();
num.Increment = Increment;
num.DecimalPlaces = DecimalPlaces;
num.Minimum = Minimum;
num.Maximum = Maximum;
num.Value = (decimal)GetValue(node);
SetEditControlProperties(num, node);
return num;
}
protected override void DisposeEditor(Control editor)
{
}
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
{
SetValue(node, (editor as NumericUpDown).Value);
}
}
}

View File

@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Aga.Controls.Properties;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace Aga.Controls.Tree.NodeControls
{
internal class NodePlusMinus : NodeControl
{
public const int ImageSize = 9;
public const int Width = 16;
private Bitmap _plus;
private Bitmap _minus;
private VisualStyleRenderer _openedRenderer;
private VisualStyleRenderer OpenedRenderer
{
get
{
if (_openedRenderer == null)
_openedRenderer = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Opened);
return _openedRenderer;
}
}
private VisualStyleRenderer _closedRenderer;
private VisualStyleRenderer ClosedRenderer
{
get
{
if (_closedRenderer == null)
_closedRenderer = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Closed);
return _closedRenderer;
}
}
public NodePlusMinus()
{
_plus = Resources.plus;
_minus = Resources.minus;
}
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
{
int scaledX = node.Tree.GetScaledSize(Width, false);
int scaledY = node.Tree.GetScaledSize(Width);
return new Size(scaledX, scaledY);
}
public override void Draw(TreeNodeAdv node, DrawContext context)
{
if (node.CanExpand)
{
Rectangle r = context.Bounds;
int scaledX = node.Tree.GetScaledSize(ImageSize, false);
int scaledY = node.Tree.GetScaledSize(ImageSize);
int dy = (int)Math.Round((float)(r.Height - scaledY) / 2);
if (TreeViewAdv.CustomPlusMinusRenderFunc != null)
{
TreeViewAdv.CustomPlusMinusRenderFunc(context.Graphics, r, node.IsExpanded);
return;
}
else if (Application.RenderWithVisualStyles)
{
VisualStyleRenderer renderer;
if (node.IsExpanded)
renderer = OpenedRenderer;
else
renderer = ClosedRenderer;
renderer.DrawBackground(context.Graphics, new Rectangle(r.X, r.Y + dy, scaledX, scaledY));
}
else
{
Image img;
if (node.IsExpanded)
img = _minus;
else
img = _plus;
context.Graphics.DrawImageUnscaled(img, new Point(r.X, r.Y + dy));
}
}
}
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
{
if (args.Button == MouseButtons.Left)
{
args.Handled = true;
if (args.Node.CanExpand)
args.Node.IsExpanded = !args.Node.IsExpanded;
}
}
public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
{
args.Handled = true; // Supress expand/collapse when double click on plus/minus
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Aga.Controls.Properties;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeStateIcon: NodeIcon
{
private Image _leaf;
private Image _opened;
private Image _closed;
public NodeStateIcon()
{
_leaf = MakeTransparent(Resources.Leaf);
_opened = MakeTransparent(Resources.Folder);
_closed = MakeTransparent(Resources.FolderClosed);
}
private static Image MakeTransparent(Bitmap bitmap)
{
bitmap.MakeTransparent(bitmap.GetPixel(0,0));
return bitmap;
}
protected override Image GetIcon(TreeNodeAdv node)
{
Image icon = base.GetIcon(node);
if (icon != null)
return icon;
else if (node.IsLeaf)
return _leaf;
else if (node.CanExpand && node.IsExpanded)
return _opened;
else
return _closed;
}
}
}

View File

@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using System.ComponentModel;
namespace Aga.Controls.Tree.NodeControls
{
public class NodeTextBox : BaseTextControl
{
private const int MinTextBoxWidth = 30;
public NodeTextBox()
{
}
protected override Size CalculateEditorSize(EditorContext context)
{
if (Parent.UseColumns)
return context.Bounds.Size;
else
{
Size size = GetLabelSize(context.CurrentNode, context.DrawContext, _label);
int width = Math.Max(size.Width + Font.Height, MinTextBoxWidth); // reserve a place for new typed character
return new Size(width, size.Height);
}
}
public override void KeyDown(KeyEventArgs args)
{
if (args.KeyCode == Keys.F2 && Parent.CurrentNode != null && EditEnabled)
{
args.Handled = true;
BeginEdit();
}
}
protected override Control CreateEditor(TreeNodeAdv node)
{
TextBox textBox = CreateTextBox();
textBox.TextAlign = TextAlign;
textBox.Text = GetLabel(node);
textBox.BorderStyle = BorderStyle.FixedSingle;
textBox.TextChanged += EditorTextChanged;
textBox.KeyDown += EditorKeyDown;
_label = textBox.Text;
SetEditControlProperties(textBox, node);
return textBox;
}
protected virtual TextBox CreateTextBox()
{
return new TextBox();
}
protected override void DisposeEditor(Control editor)
{
var textBox = editor as TextBox;
textBox.TextChanged -= EditorTextChanged;
textBox.KeyDown -= EditorKeyDown;
}
private void EditorKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
EndEdit(false);
else if (e.KeyCode == Keys.Enter)
EndEdit(true);
}
private string _label;
private void EditorTextChanged(object sender, EventArgs e)
{
var textBox = sender as TextBox;
_label = textBox.Text;
Parent.UpdateEditorBounds();
}
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
{
var label = (editor as TextBox).Text;
string oldLabel = GetLabel(node);
if (oldLabel != label)
{
SetLabel(node, label);
OnLabelChanged(node.Tag, oldLabel, label);
}
}
public override void Cut(Control control)
{
(control as TextBox).Cut();
}
public override void Copy(Control control)
{
(control as TextBox).Copy();
}
public override void Paste(Control control)
{
(control as TextBox).Paste();
}
public override void Delete(Control control)
{
var textBox = control as TextBox;
int len = Math.Max(textBox.SelectionLength, 1);
if (textBox.SelectionStart < textBox.Text.Length)
{
int start = textBox.SelectionStart;
textBox.Text = textBox.Text.Remove(textBox.SelectionStart, len);
textBox.SelectionStart = start;
}
}
public event EventHandler<LabelEventArgs> LabelChanged;
protected void OnLabelChanged(object subject, string oldLabel, string newLabel)
{
if (LabelChanged != null)
LabelChanged(this, new LabelEventArgs(subject, oldLabel, newLabel));
}
}
}