[RTL]
[reactos.git] / reactos / tools / sysgen / TriStateTreeView / TriStateTreeViewDemo / Backup1 / TriStateTreeView.cs
1 // ---------------------------------------------------------------------------------------------
2 #region // Copyright (c) 2004-2005, SIL International. All Rights Reserved.
3 // <copyright from='2004' to='2005' company='SIL International'>
4 // Copyright (c) 2004-2005, SIL International. All Rights Reserved.
5 //
6 // Distributable under the terms of either the Common Public License or the
7 // GNU Lesser General Public License, as specified in the LICENSING.txt file.
8 // </copyright>
9 #endregion
10 //
11 // File: TriStateTreeView.cs
12 // Responsibility: Eberhard Beilharz/Tim Steenwyk
13 //
14 // <remarks>
15 // </remarks>
16 // ---------------------------------------------------------------------------------------------
17 using System;
18 using System.Collections;
19 using System.ComponentModel;
20 using System.Drawing;
21 using System.Data;
22 using System.Runtime.InteropServices;
23 using System.Windows.Forms;
24 using Skybound.VisualStyles;
25
26 namespace SIL.FieldWorks.Common.Controls
27 {
28 /// ----------------------------------------------------------------------------------------
29 /// <summary>
30 /// A tree view with tri-state check boxes
31 /// </summary>
32 /// <remarks>
33 /// REVIEW: If we want to have icons in addition to the check boxes, we probably have to
34 /// set the icons for the check boxes in a different way. The windows tree view control
35 /// can have a separate image list for states.
36 /// </remarks>
37 /// ----------------------------------------------------------------------------------------
38 public class TriStateTreeView : TreeView
39 {
40 private System.Windows.Forms.ImageList m_TriStateImages;
41 private System.ComponentModel.IContainer components;
42 /// <summary>
43 /// The check state
44 /// </summary>
45 /// <remarks>The states corresponds to image index</remarks>
46 public enum CheckState
47 {
48 /// <summary>greyed out</summary>
49 GreyChecked = 0,
50 /// <summary>Unchecked</summary>
51 Unchecked = 1,
52 /// <summary>Checked</summary>
53 Checked = 2,
54 }
55
56 #region Redefined Win-API structs and methods
57 /// <summary></summary>
58 [StructLayout(LayoutKind.Sequential, Pack=1)]
59 public struct TV_HITTESTINFO
60 {
61 /// <summary>Client coordinates of the point to test.</summary>
62 public Point pt;
63 /// <summary>Variable that receives information about the results of a hit test.</summary>
64 public TVHit flags;
65 /// <summary>Handle to the item that occupies the point.</summary>
66 public IntPtr hItem;
67 }
68
69 /// <summary>Hit tests for tree view</summary>
70 [Flags]
71 public enum TVHit
72 {
73 /// <summary>In the client area, but below the last item.</summary>
74 NoWhere = 0x0001,
75 /// <summary>On the bitmap associated with an item.</summary>
76 OnItemIcon = 0x0002,
77 /// <summary>On the label (string) associated with an item.</summary>
78 OnItemLabel = 0x0004,
79 /// <summary>In the indentation associated with an item.</summary>
80 OnItemIndent = 0x0008,
81 /// <summary>On the button associated with an item.</summary>
82 OnItemButton = 0x0010,
83 /// <summary>In the area to the right of an item. </summary>
84 OnItemRight = 0x0020,
85 /// <summary>On the state icon for a tree-view item that is in a user-defined state.</summary>
86 OnItemStateIcon = 0x0040,
87 /// <summary>On the bitmap or label associated with an item. </summary>
88 OnItem = (OnItemIcon | OnItemLabel | OnItemStateIcon),
89 /// <summary>Above the client area. </summary>
90 Above = 0x0100,
91 /// <summary>Below the client area.</summary>
92 Below = 0x0200,
93 /// <summary>To the right of the client area.</summary>
94 ToRight = 0x0400,
95 /// <summary>To the left of the client area.</summary>
96 ToLeft = 0x0800
97 }
98
99 /// <summary></summary>
100 public enum TreeViewMessages
101 {
102 /// <summary></summary>
103 TV_FIRST = 0x1100, // TreeView messages
104 /// <summary></summary>
105 TVM_HITTEST = (TV_FIRST + 17),
106 }
107
108 /// <summary></summary>
109 [DllImport("user32.dll", CharSet=CharSet.Auto)]
110 public static extern int SendMessage(IntPtr hWnd, TreeViewMessages msg, int wParam, ref TV_HITTESTINFO lParam);
111 #endregion
112
113 #region Constructor and destructor
114 /// ------------------------------------------------------------------------------------
115 /// <summary>
116 /// Initializes a new instance of the <see cref="TriStateTreeView"/> class.
117 /// </summary>
118 /// ------------------------------------------------------------------------------------
119 public TriStateTreeView()
120 {
121 // This call is required by the Windows.Forms Form Designer.
122 InitializeComponent();
123
124 if (ThemeInformation.VisualStylesEnabled)
125 {
126 Bitmap bmp = new Bitmap(m_TriStateImages.ImageSize.Width, m_TriStateImages.ImageSize.Height);
127 Rectangle rc = new Rectangle(0, 0, bmp.Width, bmp.Height);
128 Graphics graphics = Graphics.FromImage(bmp);
129
130 ThemePaint.Draw(graphics, this, ThemeClasses.Button, ThemeParts.ButtonCheckBox,
131 ThemeStates.CheckBoxCheckedDisabled, rc, rc);
132 m_TriStateImages.Images[0] = bmp;
133
134 ThemePaint.Draw(graphics, this, ThemeClasses.Button, ThemeParts.ButtonCheckBox,
135 ThemeStates.CheckBoxUncheckedNormal, rc, rc);
136 m_TriStateImages.Images[1] = bmp;
137
138 ThemePaint.Draw(graphics, this, ThemeClasses.Button, ThemeParts.ButtonCheckBox,
139 ThemeStates.CheckBoxCheckedNormal, rc, rc);
140 m_TriStateImages.Images[2] = bmp;
141 }
142
143 ImageList = m_TriStateImages;
144 ImageIndex = (int)CheckState.Unchecked;
145 SelectedImageIndex = (int)CheckState.Unchecked;
146 }
147
148 /// -----------------------------------------------------------------------------------
149 /// <summary>
150 /// Clean up any resources being used.
151 /// </summary>
152 /// <param name="disposing"><c>true</c> to release both managed and unmanaged
153 /// resources; <c>false</c> to release only unmanaged resources.
154 /// </param>
155 /// -----------------------------------------------------------------------------------
156 protected override void Dispose( bool disposing )
157 {
158 if( disposing )
159 {
160 if(components != null)
161 {
162 components.Dispose();
163 }
164 }
165 base.Dispose( disposing );
166 }
167 #endregion
168
169 #region Component Designer generated code
170 /// -----------------------------------------------------------------------------------
171 /// <summary>
172 /// Required method for Designer support - do not modify
173 /// the contents of this method with the code editor.
174 /// </summary>
175 /// -----------------------------------------------------------------------------------
176 private void InitializeComponent()
177 {
178 this.components = new System.ComponentModel.Container();
179 System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(TriStateTreeView));
180 this.m_TriStateImages = new System.Windows.Forms.ImageList(this.components);
181 //
182 // m_TriStateImages
183 //
184 this.m_TriStateImages.ImageSize = new System.Drawing.Size(16, 16);
185 this.m_TriStateImages.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("m_TriStateImages.ImageStream")));
186 this.m_TriStateImages.TransparentColor = System.Drawing.Color.Magenta;
187
188 }
189 #endregion
190
191 #region Hide no longer appropriate properties from Designer
192 /// ------------------------------------------------------------------------------------
193 /// <summary>
194 ///
195 /// </summary>
196 /// ------------------------------------------------------------------------------------
197 [Browsable(false)]
198 public new bool CheckBoxes
199 {
200 get { return base.CheckBoxes; }
201 set { base.CheckBoxes = value; }
202 }
203
204 /// ------------------------------------------------------------------------------------
205 /// <summary>
206 ///
207 /// </summary>
208 /// ------------------------------------------------------------------------------------
209 [Browsable(false)]
210 public new int ImageIndex
211 {
212 get { return base.ImageIndex; }
213 set { base.ImageIndex = value; }
214 }
215
216 /// ------------------------------------------------------------------------------------
217 /// <summary>
218 ///
219 /// </summary>
220 /// ------------------------------------------------------------------------------------
221 [Browsable(false)]
222 public new ImageList ImageList
223 {
224 get { return base.ImageList; }
225 set { base.ImageList = value; }
226 }
227
228 /// ------------------------------------------------------------------------------------
229 /// <summary>
230 ///
231 /// </summary>
232 /// ------------------------------------------------------------------------------------
233 [Browsable(false)]
234 public new int SelectedImageIndex
235 {
236 get { return base.SelectedImageIndex; }
237 set { base.SelectedImageIndex = value; }
238 }
239 #endregion
240
241 #region Overrides
242 /// ------------------------------------------------------------------------------------
243 /// <summary>
244 /// Called when the user clicks on an item
245 /// </summary>
246 /// <param name="e"></param>
247 /// ------------------------------------------------------------------------------------
248 protected override void OnClick(EventArgs e)
249 {
250 base.OnClick (e);
251
252 TV_HITTESTINFO hitTestInfo = new TV_HITTESTINFO();
253 hitTestInfo.pt = PointToClient(Control.MousePosition);
254
255 SendMessage(Handle, TreeViewMessages.TVM_HITTEST,
256 0, ref hitTestInfo);
257 if ((hitTestInfo.flags & TVHit.OnItemIcon) == TVHit.OnItemIcon)
258 {
259 TreeNode node = GetNodeAt(hitTestInfo.pt);
260 if (node != null)
261 ChangeNodeState(node);
262 }
263 }
264
265 /// ------------------------------------------------------------------------------------
266 /// <summary>
267 /// Toggle item if user presses space bar
268 /// </summary>
269 /// <param name="e"></param>
270 /// ------------------------------------------------------------------------------------
271 protected override void OnKeyDown(KeyEventArgs e)
272 {
273 base.OnKeyDown (e);
274
275 if (e.KeyCode == Keys.Space)
276 ChangeNodeState(SelectedNode);
277 }
278 #endregion
279
280 #region Private methods
281 /// ------------------------------------------------------------------------------------
282 /// <summary>
283 /// Checks or unchecks all children
284 /// </summary>
285 /// <param name="node"></param>
286 /// <param name="state"></param>
287 /// ------------------------------------------------------------------------------------
288 private void CheckNode(TreeNode node, CheckState state)
289 {
290 InternalSetChecked(node, state);
291
292 foreach (TreeNode child in node.Nodes)
293 CheckNode(child, state);
294 }
295
296 /// ------------------------------------------------------------------------------------
297 /// <summary>
298 /// Called after a node changed its state. Has to go through all direct children and
299 /// set state based on children's state.
300 /// </summary>
301 /// <param name="node">Parent node</param>
302 /// ------------------------------------------------------------------------------------
303 private void ChangeParent(TreeNode node)
304 {
305 if (node == null)
306 return;
307
308 CheckState state = GetChecked(node.FirstNode);
309 foreach (TreeNode child in node.Nodes)
310 state &= GetChecked(child);
311
312 if (InternalSetChecked(node, state))
313 ChangeParent(node.Parent);
314 }
315
316 /// ------------------------------------------------------------------------------------
317 /// <summary>
318 /// Handles changing the state of a node
319 /// </summary>
320 /// <param name="node"></param>
321 /// ------------------------------------------------------------------------------------
322 protected void ChangeNodeState(TreeNode node)
323 {
324 BeginUpdate();
325 CheckState newState;
326 if (node.ImageIndex == (int)CheckState.Unchecked || node.ImageIndex < 0)
327 newState = CheckState.Checked;
328 else
329 newState = CheckState.Unchecked;
330 CheckNode(node, newState);
331 ChangeParent(node.Parent);
332 EndUpdate();
333 }
334
335 /// ------------------------------------------------------------------------------------
336 /// <summary>
337 /// Sets the checked state of a node, but doesn't deal with children or parents
338 /// </summary>
339 /// <param name="node">Node</param>
340 /// <param name="state">The new checked state</param>
341 /// <returns><c>true</c> if checked state was set to the requested state, otherwise
342 /// <c>false</c>.</returns>
343 /// ------------------------------------------------------------------------------------
344 private bool InternalSetChecked(TreeNode node, CheckState state)
345 {
346 TreeViewCancelEventArgs args =
347 new TreeViewCancelEventArgs(node, false, TreeViewAction.Unknown);
348 OnBeforeCheck(args);
349 if (args.Cancel)
350 return false;
351
352 node.ImageIndex = (int)state;
353 node.SelectedImageIndex = (int)state;
354
355 OnAfterCheck(new TreeViewEventArgs(node, TreeViewAction.Unknown));
356 return true;
357 }
358
359 /// ------------------------------------------------------------------------------------
360 /// <summary>
361 /// Build a list of all of the tag data for checked items in the tree.
362 /// </summary>
363 /// <param name="node"></param>
364 /// <param name="list"></param>
365 /// ------------------------------------------------------------------------------------
366 private void BuildTagDataList(TreeNode node, ArrayList list)
367 {
368 if (GetChecked(node) == CheckState.Checked && node.Tag != null)
369 list.Add(node.Tag);
370
371 foreach (TreeNode child in node.Nodes)
372 BuildTagDataList(child, list);
373 }
374
375 /// ------------------------------------------------------------------------------------
376 /// <summary>
377 /// Look through the tree nodes to find the node that has given tag data and check it.
378 /// </summary>
379 /// <param name="node"></param>
380 /// <param name="tag"></param>
381 /// <param name="state"></param>
382 /// ------------------------------------------------------------------------------------
383 private void FindAndCheckNode(TreeNode node, object tag, CheckState state)
384 {
385 if (node.Tag != null && node.Tag.Equals(tag))
386 {
387 SetChecked(node, state);
388 return;
389 }
390
391 foreach (TreeNode child in node.Nodes)
392 FindAndCheckNode(child, tag, state);
393 }
394 #endregion
395
396 #region Public methods
397 /// ------------------------------------------------------------------------------------
398 /// <summary>
399 /// Gets the checked state of a node
400 /// </summary>
401 /// <param name="node">Node</param>
402 /// <returns>The checked state</returns>
403 /// ------------------------------------------------------------------------------------
404 public CheckState GetChecked(TreeNode node)
405 {
406 if (node.ImageIndex < 0)
407 return CheckState.Unchecked;
408 else
409 return (CheckState)node.ImageIndex;
410 }
411
412 /// ------------------------------------------------------------------------------------
413 /// <summary>
414 /// Sets the checked state of a node
415 /// </summary>
416 /// <param name="node">Node</param>
417 /// <param name="state">The new checked state</param>
418 /// ------------------------------------------------------------------------------------
419 public void SetChecked(TreeNode node, CheckState state)
420 {
421 if (!InternalSetChecked(node, state))
422 return;
423 CheckNode(node, state);
424 ChangeParent(node.Parent);
425 }
426
427 /// ------------------------------------------------------------------------------------
428 /// <summary>
429 /// Find a node in the tree that matches the given tag data and set its checked state
430 /// </summary>
431 /// <param name="tag"></param>
432 /// <param name="state"></param>
433 /// ------------------------------------------------------------------------------------
434 public void CheckNodeByTag(object tag, CheckState state)
435 {
436 if (tag == null)
437 return;
438 foreach (TreeNode node in Nodes)
439 FindAndCheckNode(node, tag, state);
440 }
441
442 /// ------------------------------------------------------------------------------------
443 /// <summary>
444 /// Return a list of the tag data for all of the checked items in the tree
445 /// </summary>
446 /// <returns></returns>
447 /// ------------------------------------------------------------------------------------
448 public ArrayList GetCheckedTagData()
449 {
450 ArrayList list = new ArrayList();
451
452 foreach (TreeNode node in Nodes)
453 BuildTagDataList(node, list);
454 return list;
455 }
456 #endregion
457 }
458 }