moel@345
|
1 |
using System;
|
moel@345
|
2 |
using System.Collections.Generic;
|
moel@345
|
3 |
using System.Text;
|
moel@345
|
4 |
using System.Drawing;
|
moel@345
|
5 |
using Aga.Controls.Properties;
|
moel@345
|
6 |
using System.Reflection;
|
moel@345
|
7 |
using System.Windows.Forms;
|
moel@345
|
8 |
using System.Windows.Forms.VisualStyles;
|
moel@345
|
9 |
using System.ComponentModel;
|
moel@345
|
10 |
|
moel@345
|
11 |
namespace Aga.Controls.Tree.NodeControls
|
moel@345
|
12 |
{
|
moel@345
|
13 |
public class NodeCheckBox : InteractiveControl
|
moel@345
|
14 |
{
|
moel@345
|
15 |
public const int ImageSize = 13;
|
moel@345
|
16 |
|
moel@345
|
17 |
private Bitmap _check;
|
moel@345
|
18 |
private Bitmap _uncheck;
|
moel@345
|
19 |
private Bitmap _unknown;
|
moel@345
|
20 |
|
moel@345
|
21 |
#region Properties
|
moel@345
|
22 |
|
moel@345
|
23 |
private bool _threeState;
|
moel@345
|
24 |
[DefaultValue(false)]
|
moel@345
|
25 |
public bool ThreeState
|
moel@345
|
26 |
{
|
moel@345
|
27 |
get { return _threeState; }
|
moel@345
|
28 |
set { _threeState = value; }
|
moel@345
|
29 |
}
|
moel@345
|
30 |
|
moel@345
|
31 |
#endregion
|
moel@345
|
32 |
|
moel@345
|
33 |
public NodeCheckBox()
|
moel@345
|
34 |
: this(string.Empty)
|
moel@345
|
35 |
{
|
moel@345
|
36 |
}
|
moel@345
|
37 |
|
moel@345
|
38 |
public NodeCheckBox(string propertyName)
|
moel@345
|
39 |
{
|
moel@345
|
40 |
_check = Resources.check;
|
moel@345
|
41 |
_uncheck = Resources.uncheck;
|
moel@345
|
42 |
_unknown = Resources.unknown;
|
moel@345
|
43 |
DataPropertyName = propertyName;
|
moel@345
|
44 |
LeftMargin = 0;
|
moel@345
|
45 |
}
|
moel@345
|
46 |
|
moel@345
|
47 |
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
|
moel@345
|
48 |
{
|
moel@345
|
49 |
return new Size(ImageSize, ImageSize);
|
moel@345
|
50 |
}
|
moel@345
|
51 |
|
moel@345
|
52 |
public override void Draw(TreeNodeAdv node, DrawContext context)
|
moel@345
|
53 |
{
|
moel@345
|
54 |
Rectangle bounds = GetBounds(node, context);
|
moel@345
|
55 |
CheckState state = GetCheckState(node);
|
moel@345
|
56 |
if (Application.RenderWithVisualStyles)
|
moel@345
|
57 |
{
|
moel@345
|
58 |
VisualStyleRenderer renderer;
|
moel@345
|
59 |
if (state == CheckState.Indeterminate)
|
moel@345
|
60 |
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.MixedNormal);
|
moel@345
|
61 |
else if (state == CheckState.Checked)
|
moel@345
|
62 |
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.CheckedNormal);
|
moel@345
|
63 |
else
|
moel@345
|
64 |
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.UncheckedNormal);
|
moel@345
|
65 |
renderer.DrawBackground(context.Graphics, new Rectangle(bounds.X, bounds.Y, ImageSize, ImageSize));
|
moel@345
|
66 |
}
|
moel@345
|
67 |
else
|
moel@345
|
68 |
{
|
moel@345
|
69 |
Image img;
|
moel@345
|
70 |
if (state == CheckState.Indeterminate)
|
moel@345
|
71 |
img = _unknown;
|
moel@345
|
72 |
else if (state == CheckState.Checked)
|
moel@345
|
73 |
img = _check;
|
moel@345
|
74 |
else
|
moel@345
|
75 |
img = _uncheck;
|
moel@345
|
76 |
context.Graphics.DrawImage(img, bounds.Location);
|
moel@345
|
77 |
}
|
moel@345
|
78 |
}
|
moel@345
|
79 |
|
moel@345
|
80 |
protected virtual CheckState GetCheckState(TreeNodeAdv node)
|
moel@345
|
81 |
{
|
moel@345
|
82 |
object obj = GetValue(node);
|
moel@345
|
83 |
if (obj is CheckState)
|
moel@345
|
84 |
return (CheckState)obj;
|
moel@345
|
85 |
else if (obj is bool)
|
moel@345
|
86 |
return (bool)obj ? CheckState.Checked : CheckState.Unchecked;
|
moel@345
|
87 |
else
|
moel@345
|
88 |
return CheckState.Unchecked;
|
moel@345
|
89 |
}
|
moel@345
|
90 |
|
moel@345
|
91 |
protected virtual void SetCheckState(TreeNodeAdv node, CheckState value)
|
moel@345
|
92 |
{
|
moel@345
|
93 |
if (VirtualMode)
|
moel@345
|
94 |
{
|
moel@345
|
95 |
SetValue(node, value);
|
moel@345
|
96 |
OnCheckStateChanged(node);
|
moel@345
|
97 |
}
|
moel@345
|
98 |
else
|
moel@345
|
99 |
{
|
moel@345
|
100 |
Type type = GetPropertyType(node);
|
moel@345
|
101 |
if (type == typeof(CheckState))
|
moel@345
|
102 |
{
|
moel@345
|
103 |
SetValue(node, value);
|
moel@345
|
104 |
OnCheckStateChanged(node);
|
moel@345
|
105 |
}
|
moel@345
|
106 |
else if (type == typeof(bool))
|
moel@345
|
107 |
{
|
moel@345
|
108 |
SetValue(node, value != CheckState.Unchecked);
|
moel@345
|
109 |
OnCheckStateChanged(node);
|
moel@345
|
110 |
}
|
moel@345
|
111 |
}
|
moel@345
|
112 |
}
|
moel@345
|
113 |
|
moel@345
|
114 |
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
|
moel@345
|
115 |
{
|
moel@345
|
116 |
if (args.Button == MouseButtons.Left && IsEditEnabled(args.Node))
|
moel@345
|
117 |
{
|
moel@345
|
118 |
DrawContext context = new DrawContext();
|
moel@345
|
119 |
context.Bounds = args.ControlBounds;
|
moel@345
|
120 |
Rectangle rect = GetBounds(args.Node, context);
|
moel@345
|
121 |
if (rect.Contains(args.ViewLocation))
|
moel@345
|
122 |
{
|
moel@345
|
123 |
CheckState state = GetCheckState(args.Node);
|
moel@345
|
124 |
state = GetNewState(state);
|
moel@345
|
125 |
SetCheckState(args.Node, state);
|
moel@345
|
126 |
Parent.UpdateView();
|
moel@345
|
127 |
args.Handled = true;
|
moel@345
|
128 |
}
|
moel@345
|
129 |
}
|
moel@345
|
130 |
}
|
moel@345
|
131 |
|
moel@345
|
132 |
public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
|
moel@345
|
133 |
{
|
moel@345
|
134 |
args.Handled = true;
|
moel@345
|
135 |
}
|
moel@345
|
136 |
|
moel@345
|
137 |
private CheckState GetNewState(CheckState state)
|
moel@345
|
138 |
{
|
moel@345
|
139 |
if (state == CheckState.Indeterminate)
|
moel@345
|
140 |
return CheckState.Unchecked;
|
moel@345
|
141 |
else if(state == CheckState.Unchecked)
|
moel@345
|
142 |
return CheckState.Checked;
|
moel@345
|
143 |
else
|
moel@345
|
144 |
return ThreeState ? CheckState.Indeterminate : CheckState.Unchecked;
|
moel@345
|
145 |
}
|
moel@345
|
146 |
|
moel@345
|
147 |
public override void KeyDown(KeyEventArgs args)
|
moel@345
|
148 |
{
|
moel@345
|
149 |
if (args.KeyCode == Keys.Space && EditEnabled)
|
moel@345
|
150 |
{
|
moel@345
|
151 |
Parent.BeginUpdate();
|
moel@345
|
152 |
try
|
moel@345
|
153 |
{
|
moel@345
|
154 |
if (Parent.CurrentNode != null)
|
moel@345
|
155 |
{
|
moel@345
|
156 |
CheckState value = GetNewState(GetCheckState(Parent.CurrentNode));
|
moel@345
|
157 |
foreach (TreeNodeAdv node in Parent.Selection)
|
moel@345
|
158 |
if (IsEditEnabled(node))
|
moel@345
|
159 |
SetCheckState(node, value);
|
moel@345
|
160 |
}
|
moel@345
|
161 |
}
|
moel@345
|
162 |
finally
|
moel@345
|
163 |
{
|
moel@345
|
164 |
Parent.EndUpdate();
|
moel@345
|
165 |
}
|
moel@345
|
166 |
args.Handled = true;
|
moel@345
|
167 |
}
|
moel@345
|
168 |
}
|
moel@345
|
169 |
|
moel@345
|
170 |
public event EventHandler<TreePathEventArgs> CheckStateChanged;
|
moel@345
|
171 |
protected void OnCheckStateChanged(TreePathEventArgs args)
|
moel@345
|
172 |
{
|
moel@345
|
173 |
if (CheckStateChanged != null)
|
moel@345
|
174 |
CheckStateChanged(this, args);
|
moel@345
|
175 |
}
|
moel@345
|
176 |
|
moel@345
|
177 |
protected void OnCheckStateChanged(TreeNodeAdv node)
|
moel@345
|
178 |
{
|
moel@345
|
179 |
TreePath path = this.Parent.GetPath(node);
|
moel@345
|
180 |
OnCheckStateChanged(new TreePathEventArgs(path));
|
moel@345
|
181 |
}
|
moel@345
|
182 |
|
moel@345
|
183 |
}
|
moel@345
|
184 |
}
|