moel@345: using System; moel@345: using System.Collections.Generic; moel@345: using System.Text; moel@345: using Aga.Controls.Tree.NodeControls; moel@345: using System.ComponentModel; moel@345: using System.Drawing; moel@345: using System.Windows.Forms; moel@345: moel@345: namespace Aga.Controls.Tree moel@345: { moel@345: internal class IncrementalSearch moel@345: { moel@345: private const int SearchTimeout = 300; //end of incremental search timeot in msec moel@345: moel@345: private TreeViewAdv _tree; moel@345: private TreeNodeAdv _currentNode; moel@345: private string _searchString = ""; moel@345: private DateTime _lastKeyPressed = DateTime.Now; moel@345: moel@345: public IncrementalSearch(TreeViewAdv tree) moel@345: { moel@345: _tree = tree; moel@345: } moel@345: moel@345: public void Search(Char value) moel@345: { moel@345: if (!Char.IsControl(value)) moel@345: { moel@345: Char ch = Char.ToLowerInvariant(value); moel@345: DateTime dt = DateTime.Now; moel@345: TimeSpan ts = dt - _lastKeyPressed; moel@345: _lastKeyPressed = dt; moel@345: if (ts.TotalMilliseconds < SearchTimeout) moel@345: { moel@345: if (_searchString == value.ToString()) moel@345: FirstCharSearch(ch); moel@345: else moel@345: ContinuousSearch(ch); moel@345: } moel@345: else moel@345: { moel@345: FirstCharSearch(ch); moel@345: } moel@345: } moel@345: } moel@345: moel@345: private void ContinuousSearch(Char value) moel@345: { moel@345: if (value == ' ' && String.IsNullOrEmpty(_searchString)) moel@345: return; //Ingnore leading space moel@345: moel@345: _searchString += value; moel@345: DoContinuousSearch(); moel@345: } moel@345: moel@345: private void FirstCharSearch(Char value) moel@345: { moel@345: if (value == ' ') moel@345: return; moel@345: moel@345: _searchString = value.ToString(); moel@345: TreeNodeAdv node = null; moel@345: if (_tree.SelectedNode != null) moel@345: node = _tree.SelectedNode.NextVisibleNode; moel@345: if (node == null) moel@345: node = _tree.Root.NextVisibleNode; moel@345: moel@345: if (node != null) moel@345: foreach (string label in IterateNodeLabels(node)) moel@345: { moel@345: if (label.StartsWith(_searchString)) moel@345: { moel@345: _tree.SelectedNode = _currentNode; moel@345: return; moel@345: } moel@345: } moel@345: } moel@345: moel@345: public virtual void EndSearch() moel@345: { moel@345: _currentNode = null; moel@345: _searchString = ""; moel@345: } moel@345: moel@345: protected IEnumerable IterateNodeLabels(TreeNodeAdv start) moel@345: { moel@345: _currentNode = start; moel@345: while(_currentNode != null) moel@345: { moel@345: foreach (string label in GetNodeLabels(_currentNode)) moel@345: yield return label; moel@345: moel@345: _currentNode = _currentNode.NextVisibleNode; moel@345: if (_currentNode == null) moel@345: _currentNode = _tree.Root; moel@345: moel@345: if (start == _currentNode) moel@345: break; moel@345: } moel@345: } moel@345: moel@345: private IEnumerable GetNodeLabels(TreeNodeAdv node) moel@345: { moel@345: foreach (NodeControl nc in _tree.NodeControls) moel@345: { moel@345: BindableControl bc = nc as BindableControl; moel@345: if (bc != null && bc.IncrementalSearchEnabled) moel@345: { moel@345: object obj = bc.GetValue(node); moel@345: if (obj != null) moel@345: yield return obj.ToString().ToLowerInvariant(); moel@345: } moel@345: } moel@345: } moel@345: moel@345: private bool DoContinuousSearch() moel@345: { moel@345: bool found = false; moel@345: if (!String.IsNullOrEmpty(_searchString)) moel@345: { moel@345: TreeNodeAdv node = null; moel@345: if (_tree.SelectedNode != null) moel@345: node = _tree.SelectedNode; moel@345: if (node == null) moel@345: node = _tree.Root.NextVisibleNode; moel@345: moel@345: if (!String.IsNullOrEmpty(_searchString)) moel@345: { moel@345: foreach (string label in IterateNodeLabels(node)) moel@345: { moel@345: if (label.StartsWith(_searchString)) moel@345: { moel@345: found = true; moel@345: _tree.SelectedNode = _currentNode; moel@345: break; moel@345: } moel@345: } moel@345: } moel@345: } moel@345: return found; moel@345: } moel@345: moel@345: } moel@345: }