371 lines
15 KiB
C#
371 lines
15 KiB
C#
using System;
|
|
using System.Windows.Forms;
|
|
using System.Drawing;
|
|
|
|
namespace DevComponents.AdvTree
|
|
{
|
|
/// <summary>
|
|
/// Provides AdvTree Keyboard handling.
|
|
/// </summary>
|
|
internal class KeyNavigation
|
|
{
|
|
public static void KeyDown(AdvTree tree, KeyEventArgs e)
|
|
{
|
|
Node node = tree.SelectedNode;
|
|
if (node != null)
|
|
{
|
|
node.InternalKeyDown(e);
|
|
if (e.Handled) return;
|
|
}
|
|
|
|
switch(e.KeyCode)
|
|
{
|
|
case Keys.Space:
|
|
{
|
|
SpaceKeyDown(tree, e);
|
|
e.Handled = true;
|
|
break;
|
|
}
|
|
case Keys.Add:
|
|
{
|
|
e.Handled = PlusKeyDown(tree, e);
|
|
break;
|
|
}
|
|
case Keys.Subtract:
|
|
{
|
|
e.Handled = MinusKeyDown(tree, e);
|
|
break;
|
|
}
|
|
case Keys.F2:
|
|
{
|
|
F2KeyDown(tree, e);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
if (e.Control && e.KeyCode == Keys.C)
|
|
CopyKeyDown(tree, e);
|
|
else if (e.Control && e.KeyCode == Keys.V)
|
|
PasteKeyDown(tree, e);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool MinusKeyDown(AdvTree tree, KeyEventArgs e)
|
|
{
|
|
Node node = tree.SelectedNode;
|
|
if (node != null && tree.SelectedNodes.Count == 1 && node.Expanded)
|
|
{
|
|
node.Collapse();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
private static bool PlusKeyDown(AdvTree tree, KeyEventArgs e)
|
|
{
|
|
Node node = tree.SelectedNode;
|
|
if (node != null && tree.SelectedNodes.Count == 1 && !node.Expanded)
|
|
{
|
|
node.Expand();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static void PasteKeyDown(AdvTree tree, KeyEventArgs args)
|
|
{
|
|
if (tree.SelectedNode != null)
|
|
tree.SelectedNode.InvokeKeyboardPaste(args);
|
|
}
|
|
|
|
private static void CopyKeyDown(AdvTree tree, KeyEventArgs args)
|
|
{
|
|
if (tree.SelectedNode != null)
|
|
tree.SelectedNode.InvokeKeyboardCopy(args);
|
|
}
|
|
|
|
private static void F2KeyDown(AdvTree tree, KeyEventArgs e)
|
|
{
|
|
if (tree.EditSelectedCell(eTreeAction.Keyboard))
|
|
e.Handled = true;
|
|
}
|
|
|
|
public static void SpaceKeyDown(AdvTree tree, KeyEventArgs e)
|
|
{
|
|
Node node = tree.SelectedNode;
|
|
if (node != null && node.CheckBoxVisible && node.Enabled)
|
|
{
|
|
if (node.CheckBoxThreeState)
|
|
{
|
|
if (node.CheckState == CheckState.Checked)
|
|
node.SetChecked(CheckState.Indeterminate, eTreeAction.Keyboard);
|
|
else if (node.CheckState == CheckState.Unchecked)
|
|
node.SetChecked(CheckState.Checked, eTreeAction.Keyboard);
|
|
else if (node.CheckState == CheckState.Indeterminate)
|
|
node.SetChecked(CheckState.Unchecked, eTreeAction.Keyboard);
|
|
}
|
|
else
|
|
node.SetChecked(!node.Checked, eTreeAction.Keyboard);
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
public static void EnterKeyDown(AdvTree tree, KeyEventArgs e)
|
|
{
|
|
if (tree.SelectedNode != null && tree.SelectedNode.Nodes.Count > 0)
|
|
{
|
|
tree.SelectedNode.Toggle(eTreeAction.Keyboard);
|
|
}
|
|
}
|
|
|
|
public static bool NavigateKeyDown(AdvTree tree, KeyEventArgs e)
|
|
{
|
|
if(tree.SelectedNode==null)
|
|
{
|
|
if(tree.DisplayRootNode!=null)
|
|
tree.SelectNode(tree.DisplayRootNode, eTreeAction.Keyboard);
|
|
else if (tree.Nodes.Count > 0)
|
|
{
|
|
Node firstSelectable = NodeOperations.GetFirstVisibleNode(tree);
|
|
if (firstSelectable != null)
|
|
{
|
|
while (firstSelectable!=null && !firstSelectable.Selectable)
|
|
firstSelectable = NodeOperations.GetNextVisibleNode(firstSelectable);
|
|
if (firstSelectable != null)
|
|
tree.SelectNode(firstSelectable, eTreeAction.Keyboard);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Node node = tree.SelectedNode;
|
|
if (node != null && !node.IsKeyboardNavigationEnabled(e))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(e.KeyCode == Keys.Right)
|
|
{
|
|
if (node != null && node.Cells.Count > 1 && tree.SelectionPerCell && node.CellNavigationEnabled)
|
|
{
|
|
if (node.SelectedCell == null)
|
|
node.SetSelectedCell(NodeOperations.GetNextVisibleCell(node, -1), eTreeAction.Keyboard);
|
|
else
|
|
node.SetSelectedCell(NodeOperations.GetNextVisibleCell(node, node.Cells.IndexOf(node.SelectedCell)), eTreeAction.Keyboard);
|
|
return true;
|
|
}
|
|
|
|
if (tree.View == eView.Tile)
|
|
{
|
|
Node nextNode = NodeOperations.GetNextVisibleNode(node);
|
|
if (nextNode != null)
|
|
{
|
|
if (node.Expanded || !node.HasChildNodes)
|
|
tree.SelectNode(nextNode, eTreeAction.Keyboard);
|
|
else
|
|
node.Expand(eTreeAction.Keyboard);
|
|
}
|
|
else if (node != null && node.ExpandVisibility == eNodeExpandVisibility.Visible && !node.Expanded)
|
|
node.Expand(eTreeAction.Keyboard);
|
|
}
|
|
else
|
|
{
|
|
Node childNode = NodeOperations.GetFirstVisibleChildNode(node);
|
|
if (childNode != null)
|
|
{
|
|
if (node.Expanded)
|
|
tree.SelectNode(childNode, eTreeAction.Keyboard);
|
|
else
|
|
node.Expand(eTreeAction.Keyboard);
|
|
}
|
|
else if (node != null && node.ExpandVisibility == eNodeExpandVisibility.Visible && !node.Expanded)
|
|
node.Expand(eTreeAction.Keyboard);
|
|
}
|
|
}
|
|
else if(e.KeyCode == Keys.Left)
|
|
{
|
|
if (node != null && node.Cells.Count > 1 && tree.SelectionPerCell && node.CellNavigationEnabled)
|
|
{
|
|
if (node.SelectedCell == null)
|
|
node.SetSelectedCell(NodeOperations.GetPreviousVisibleCell(node, node.Cells.Count - 1), eTreeAction.Keyboard);
|
|
else
|
|
node.SetSelectedCell(NodeOperations.GetPreviousVisibleCell(node, node.Cells.IndexOf(node.SelectedCell)), eTreeAction.Keyboard);
|
|
return true;
|
|
}
|
|
|
|
if (tree.View == eView.Tile)
|
|
{
|
|
Node previousNode = NodeOperations.GetPreviousVisibleNode(node);
|
|
if (previousNode != null)
|
|
tree.SelectNode(previousNode, eTreeAction.Keyboard);
|
|
}
|
|
else
|
|
{
|
|
if (node.Expanded && node.IsSelected && NodeOperations.GetFirstVisibleChildNode(node) != null)
|
|
node.Collapse(eTreeAction.Keyboard);
|
|
else if (node.Parent != null)
|
|
tree.SelectNode(node.Parent, eTreeAction.Keyboard);
|
|
}
|
|
}
|
|
else if (e.KeyCode == Keys.End)
|
|
{
|
|
Node last = NodeOperations.GetLastVisibleNode(tree);
|
|
if (last != null)
|
|
{
|
|
if (!last.Selectable)
|
|
{
|
|
while (last != null)
|
|
{
|
|
last = NodeOperations.GetPreviousVisibleNode(last);
|
|
if (last!=null && last.Selectable) break;
|
|
}
|
|
}
|
|
if (last != null)
|
|
tree.SelectNode(last, eTreeAction.Keyboard);
|
|
}
|
|
}
|
|
else if (e.KeyCode == Keys.Home || e.KeyCode == Keys.PageDown && node == null)
|
|
{
|
|
Node first = NodeOperations.GetFirstVisibleNode(tree);
|
|
if (first != null)
|
|
{
|
|
if (!first.Selectable)
|
|
{
|
|
while (first != null)
|
|
{
|
|
first = NodeOperations.GetNextVisibleNode(first);
|
|
if (first != null && first.Selectable) break;
|
|
}
|
|
}
|
|
if (first != null)
|
|
tree.SelectNode(first, eTreeAction.Keyboard);
|
|
}
|
|
}
|
|
else if (e.KeyCode == Keys.PageDown)
|
|
{
|
|
// Find last fully rendered node
|
|
Node lastNode = NodeOperations.GetLastDisplayedNode(tree);
|
|
if (lastNode != null)
|
|
{
|
|
if (tree.SelectedNode == lastNode)
|
|
{
|
|
if (tree.VScrollBar != null && tree.AutoScroll)
|
|
{
|
|
tree.AutoScrollPosition = new Point(tree.AutoScrollPosition.X, Math.Max(tree.AutoScrollPosition.Y - tree.VScrollBar.LargeChange, -(tree.VScrollBar.Maximum - tree.VScrollBar.LargeChange)));
|
|
lastNode = NodeOperations.GetLastDisplayedNode(tree);
|
|
}
|
|
}
|
|
}
|
|
if (lastNode != null)
|
|
tree.SelectNode(lastNode, eTreeAction.Keyboard);
|
|
}
|
|
else if (e.KeyCode == Keys.PageUp)
|
|
{
|
|
// Find last fully rendered node
|
|
Node firstNode = NodeOperations.GetFirstDisplayedNode(tree);
|
|
if (firstNode != null)
|
|
{
|
|
if (tree.SelectedNode == firstNode)
|
|
{
|
|
if (tree.VScrollBar != null && tree.AutoScroll && tree.AutoScrollPosition.Y < 0)
|
|
{
|
|
tree.AutoScrollPosition = new Point(tree.AutoScrollPosition.X, Math.Min(0, tree.AutoScrollPosition.Y + tree.VScrollBar.LargeChange));
|
|
firstNode = NodeOperations.GetFirstDisplayedNode(tree);
|
|
}
|
|
}
|
|
}
|
|
if (firstNode != null)
|
|
tree.SelectNode(firstNode, eTreeAction.Keyboard);
|
|
}
|
|
else if ((e.KeyCode & Keys.Down) == Keys.Down)
|
|
{
|
|
int currentCell = 0;
|
|
|
|
if (node != null && node.SelectedCell != null) currentCell = node.Cells.IndexOf(node.SelectedCell);
|
|
|
|
Node nextNode = NodeOperations.GetNextVisibleNode(node);
|
|
|
|
// Adjust nextNode so the multi-selection is proper
|
|
if ((e.KeyData & Keys.Shift) == Keys.Shift && tree.MultiSelect && tree.SelectedNodes.Count > 1)
|
|
{
|
|
if (tree.SelectedNodes[0].Bounds.Y > tree.SelectedNodes[tree.SelectedNodes.Count - 1].Bounds.Y)
|
|
nextNode = tree.SelectedNodes[tree.SelectedNodes.Count - 1];
|
|
}
|
|
|
|
if (nextNode != null)
|
|
{
|
|
if (!nextNode.CanSelect)
|
|
{
|
|
int counter = 0;
|
|
while (nextNode != null && counter < 100)
|
|
{
|
|
nextNode = NodeOperations.GetNextVisibleNode(nextNode);
|
|
if (nextNode != null && nextNode.CanSelect) break;
|
|
}
|
|
}
|
|
if (nextNode != null)
|
|
{
|
|
if ((e.KeyData & Keys.Shift) == Keys.Shift && tree.MultiSelect && tree.SelectedNodes.Count > 0)
|
|
{
|
|
if (tree.MultiSelectRule == eMultiSelectRule.SameParent && tree.SelectedNodes[0].Parent != nextNode.Parent) return true;
|
|
|
|
if (nextNode.IsSelected)
|
|
tree.SelectedNodes.Remove(nextNode, eTreeAction.Keyboard);
|
|
else
|
|
tree.SelectedNodes.Add(nextNode, eTreeAction.Keyboard);
|
|
nextNode.EnsureVisible();
|
|
}
|
|
else
|
|
{
|
|
tree.SelectNode(nextNode, eTreeAction.Keyboard);
|
|
if (tree.SelectionPerCell && currentCell < nextNode.Cells.Count && currentCell > 0)
|
|
nextNode.SetSelectedCell(nextNode.Cells[currentCell], eTreeAction.Keyboard);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ((e.KeyCode & Keys.Up) == Keys.Up)
|
|
{
|
|
int currentCell = 0;
|
|
if (node != null && node.SelectedCell != null) currentCell = node.Cells.IndexOf(node.SelectedCell);
|
|
|
|
Node prevNode = NodeOperations.GetPreviousVisibleNode(node);
|
|
if (prevNode != null)
|
|
{
|
|
if (!prevNode.CanSelect)
|
|
{
|
|
int counter = 0;
|
|
while (prevNode != null && counter < 100)
|
|
{
|
|
prevNode = NodeOperations.GetPreviousVisibleNode(prevNode);
|
|
if (prevNode != null && prevNode.CanSelect) break;
|
|
}
|
|
}
|
|
if (prevNode != null)
|
|
{
|
|
if ((e.KeyData & Keys.Shift) == Keys.Shift && tree.MultiSelect && tree.SelectedNodes.Count > 0)
|
|
{
|
|
if (tree.MultiSelectRule == eMultiSelectRule.SameParent && tree.SelectedNodes[0].Parent != prevNode.Parent) return true;
|
|
if (prevNode.IsSelected)
|
|
{
|
|
tree.SelectedNodes.Remove(tree.SelectedNodes[tree.SelectedNodes.Count - 1], eTreeAction.Keyboard);
|
|
}
|
|
else
|
|
tree.SelectedNodes.Add(prevNode, eTreeAction.Keyboard);
|
|
prevNode.EnsureVisible();
|
|
}
|
|
else if (prevNode != null)
|
|
{
|
|
tree.SelectNode(prevNode, eTreeAction.Keyboard);
|
|
if (tree.SelectionPerCell && currentCell < prevNode.Cells.Count && currentCell > 0)
|
|
prevNode.SetSelectedCell(prevNode.Cells[currentCell], eTreeAction.Keyboard);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|