private void control_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { Keys keyData = e.KeyData; Keys modifiers = keyData & Keys.Modifiers; keyData &= ~Keys.Modifiers; if (keyData == Keys.Up || keyData == Keys.Right || keyData == Keys.Down || keyData == Keys.Left) { TNode startElement = Adapters.As <TNode>(m_selectionContext.LastSelected); if (startElement != null) { Rectangle nearestRect; TNode nearest = FindNearestElement(startElement, keyData, out nearestRect); if (nearest != null) { var selection = new List <TNode>(m_selectionContext.SelectionCount); selection.AddRange(m_selectionContext.GetSelection <TNode>()); KeysUtil.Select <TNode>(selection, nearest, modifiers); m_selectionContext.Selection = selection.Cast <object>(); var transformAdapter = AdaptedControl.As <ITransformAdapter>(); if (transformAdapter != null) { transformAdapter.PanToRect(nearestRect); } } } } }
/// <summary> /// Handles the PreviewKeyDown event on AdaptedControl, and changes the selection /// if the user navigates using the keyboard</summary> /// <param name="sender">Sender</param> /// <param name="e">Event args</param> protected virtual void PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { Keys keyData = e.KeyData; Keys modifiers = keyData & Keys.Modifiers; keyData &= ~Keys.Modifiers; if (IsNavigationKey(keyData)) { List <TNode> oldSelection; // If the user is reversing direction of a past shift+selection, and they didn't // overshoot the beginning (i.e., the stack isn't empty), then don't search for // nodes and instead restore a past selection. if (modifiers == Keys.Shift && OppositeNavigationKeys(m_lastKeyWithShift, keyData) && m_shiftKeySelectionStack.Count > 0) { oldSelection = m_shiftKeySelectionStack.Pop(); ChangeSelection(oldSelection); return; } // We need to know the current selection now. oldSelection = new List <TNode>(m_selectionContext.SelectionCount); oldSelection.AddRange(m_selectionContext.GetSelection <TNode>()); // If the user is doing a shift+selection, then push the current selection on to the // stack. But if the user chose a new direction, clear the stack first. bool pushOldSelectionIfSelectionChanges = false; if (modifiers == Keys.Shift) { if (m_lastKeyWithShift != Keys.None && m_lastKeyWithShift != keyData) { m_lastKeyWithShift = Keys.None; m_shiftKeySelectionStack.Clear(); } pushOldSelectionIfSelectionChanges = true; } else { m_lastKeyWithShift = Keys.None; m_shiftKeySelectionStack.Clear(); } // Do a search from the existing selected nodes, looking only along wires. var connectedNodes = new HashSet <TNode>(); foreach (TNode startElement in m_selectionContext.GetSelection <TNode>()) { foreach (TNode connectedNode in FindConnectedNodes(startElement, keyData, modifiers)) { connectedNodes.Add(connectedNode); } } // If no connected nodes were found, then look for the nearest nodes. if (connectedNodes.Count == 0) { foreach (TNode startElement in m_selectionContext.GetSelection <TNode>()) { TNode nearestNode = FindNearestNode(startElement, keyData, modifiers); if (nearestNode != null) { connectedNodes.Add(nearestNode); } } } // If we have new connected nodes then change the selection. if (connectedNodes.Count > 0) { // With this keyboard navigation, the Control key doesn't seem to make sense // for toggling nodes in the selection. modifiers &= ~Keys.Control; var newSelection = new HashSet <TNode>(oldSelection); KeysUtil.Select(newSelection, connectedNodes, modifiers); if (!newSelection.SetEquals(oldSelection)) { ChangeSelection(newSelection); if (pushOldSelectionIfSelectionChanges) { m_lastKeyWithShift = keyData; m_shiftKeySelectionStack.Push(new List <TNode>(oldSelection)); } // Attempt to pan, to make sure the newly selected nodes are visible if (m_transformAdapter != null) { Rectangle boundingRect = m_pickingAdapter.GetBounds(newSelection.OfType <object>()); m_transformAdapter.PanToRect(boundingRect); } } } } }