moel@345
|
1 |
using System;
|
moel@345
|
2 |
using System.Collections.Generic;
|
moel@345
|
3 |
using System.Text;
|
moel@345
|
4 |
using Aga.Controls.Tree.NodeControls;
|
moel@345
|
5 |
using System.ComponentModel;
|
moel@345
|
6 |
using System.Drawing;
|
moel@345
|
7 |
using System.Windows.Forms;
|
moel@345
|
8 |
|
moel@345
|
9 |
namespace Aga.Controls.Tree
|
moel@345
|
10 |
{
|
moel@345
|
11 |
internal class IncrementalSearch
|
moel@345
|
12 |
{
|
moel@345
|
13 |
private const int SearchTimeout = 300; //end of incremental search timeot in msec
|
moel@345
|
14 |
|
moel@345
|
15 |
private TreeViewAdv _tree;
|
moel@345
|
16 |
private TreeNodeAdv _currentNode;
|
moel@345
|
17 |
private string _searchString = "";
|
moel@345
|
18 |
private DateTime _lastKeyPressed = DateTime.Now;
|
moel@345
|
19 |
|
moel@345
|
20 |
public IncrementalSearch(TreeViewAdv tree)
|
moel@345
|
21 |
{
|
moel@345
|
22 |
_tree = tree;
|
moel@345
|
23 |
}
|
moel@345
|
24 |
|
moel@345
|
25 |
public void Search(Char value)
|
moel@345
|
26 |
{
|
moel@345
|
27 |
if (!Char.IsControl(value))
|
moel@345
|
28 |
{
|
moel@345
|
29 |
Char ch = Char.ToLowerInvariant(value);
|
moel@345
|
30 |
DateTime dt = DateTime.Now;
|
moel@345
|
31 |
TimeSpan ts = dt - _lastKeyPressed;
|
moel@345
|
32 |
_lastKeyPressed = dt;
|
moel@345
|
33 |
if (ts.TotalMilliseconds < SearchTimeout)
|
moel@345
|
34 |
{
|
moel@345
|
35 |
if (_searchString == value.ToString())
|
moel@345
|
36 |
FirstCharSearch(ch);
|
moel@345
|
37 |
else
|
moel@345
|
38 |
ContinuousSearch(ch);
|
moel@345
|
39 |
}
|
moel@345
|
40 |
else
|
moel@345
|
41 |
{
|
moel@345
|
42 |
FirstCharSearch(ch);
|
moel@345
|
43 |
}
|
moel@345
|
44 |
}
|
moel@345
|
45 |
}
|
moel@345
|
46 |
|
moel@345
|
47 |
private void ContinuousSearch(Char value)
|
moel@345
|
48 |
{
|
moel@345
|
49 |
if (value == ' ' && String.IsNullOrEmpty(_searchString))
|
moel@345
|
50 |
return; //Ingnore leading space
|
moel@345
|
51 |
|
moel@345
|
52 |
_searchString += value;
|
moel@345
|
53 |
DoContinuousSearch();
|
moel@345
|
54 |
}
|
moel@345
|
55 |
|
moel@345
|
56 |
private void FirstCharSearch(Char value)
|
moel@345
|
57 |
{
|
moel@345
|
58 |
if (value == ' ')
|
moel@345
|
59 |
return;
|
moel@345
|
60 |
|
moel@345
|
61 |
_searchString = value.ToString();
|
moel@345
|
62 |
TreeNodeAdv node = null;
|
moel@345
|
63 |
if (_tree.SelectedNode != null)
|
moel@345
|
64 |
node = _tree.SelectedNode.NextVisibleNode;
|
moel@345
|
65 |
if (node == null)
|
moel@345
|
66 |
node = _tree.Root.NextVisibleNode;
|
moel@345
|
67 |
|
moel@345
|
68 |
if (node != null)
|
moel@345
|
69 |
foreach (string label in IterateNodeLabels(node))
|
moel@345
|
70 |
{
|
moel@345
|
71 |
if (label.StartsWith(_searchString))
|
moel@345
|
72 |
{
|
moel@345
|
73 |
_tree.SelectedNode = _currentNode;
|
moel@345
|
74 |
return;
|
moel@345
|
75 |
}
|
moel@345
|
76 |
}
|
moel@345
|
77 |
}
|
moel@345
|
78 |
|
moel@345
|
79 |
public virtual void EndSearch()
|
moel@345
|
80 |
{
|
moel@345
|
81 |
_currentNode = null;
|
moel@345
|
82 |
_searchString = "";
|
moel@345
|
83 |
}
|
moel@345
|
84 |
|
moel@345
|
85 |
protected IEnumerable<string> IterateNodeLabels(TreeNodeAdv start)
|
moel@345
|
86 |
{
|
moel@345
|
87 |
_currentNode = start;
|
moel@345
|
88 |
while(_currentNode != null)
|
moel@345
|
89 |
{
|
moel@345
|
90 |
foreach (string label in GetNodeLabels(_currentNode))
|
moel@345
|
91 |
yield return label;
|
moel@345
|
92 |
|
moel@345
|
93 |
_currentNode = _currentNode.NextVisibleNode;
|
moel@345
|
94 |
if (_currentNode == null)
|
moel@345
|
95 |
_currentNode = _tree.Root;
|
moel@345
|
96 |
|
moel@345
|
97 |
if (start == _currentNode)
|
moel@345
|
98 |
break;
|
moel@345
|
99 |
}
|
moel@345
|
100 |
}
|
moel@345
|
101 |
|
moel@345
|
102 |
private IEnumerable<string> GetNodeLabels(TreeNodeAdv node)
|
moel@345
|
103 |
{
|
moel@345
|
104 |
foreach (NodeControl nc in _tree.NodeControls)
|
moel@345
|
105 |
{
|
moel@345
|
106 |
BindableControl bc = nc as BindableControl;
|
moel@345
|
107 |
if (bc != null && bc.IncrementalSearchEnabled)
|
moel@345
|
108 |
{
|
moel@345
|
109 |
object obj = bc.GetValue(node);
|
moel@345
|
110 |
if (obj != null)
|
moel@345
|
111 |
yield return obj.ToString().ToLowerInvariant();
|
moel@345
|
112 |
}
|
moel@345
|
113 |
}
|
moel@345
|
114 |
}
|
moel@345
|
115 |
|
moel@345
|
116 |
private bool DoContinuousSearch()
|
moel@345
|
117 |
{
|
moel@345
|
118 |
bool found = false;
|
moel@345
|
119 |
if (!String.IsNullOrEmpty(_searchString))
|
moel@345
|
120 |
{
|
moel@345
|
121 |
TreeNodeAdv node = null;
|
moel@345
|
122 |
if (_tree.SelectedNode != null)
|
moel@345
|
123 |
node = _tree.SelectedNode;
|
moel@345
|
124 |
if (node == null)
|
moel@345
|
125 |
node = _tree.Root.NextVisibleNode;
|
moel@345
|
126 |
|
moel@345
|
127 |
if (!String.IsNullOrEmpty(_searchString))
|
moel@345
|
128 |
{
|
moel@345
|
129 |
foreach (string label in IterateNodeLabels(node))
|
moel@345
|
130 |
{
|
moel@345
|
131 |
if (label.StartsWith(_searchString))
|
moel@345
|
132 |
{
|
moel@345
|
133 |
found = true;
|
moel@345
|
134 |
_tree.SelectedNode = _currentNode;
|
moel@345
|
135 |
break;
|
moel@345
|
136 |
}
|
moel@345
|
137 |
}
|
moel@345
|
138 |
}
|
moel@345
|
139 |
}
|
moel@345
|
140 |
return found;
|
moel@345
|
141 |
}
|
moel@345
|
142 |
|
moel@345
|
143 |
}
|
moel@345
|
144 |
}
|