Add project files.
This commit is contained in:
12
Nodify/Interactivity/Gestures/AllGestures.cs
Normal file
12
Nodify/Interactivity/Gestures/AllGestures.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify.Interactivity
|
||||
{
|
||||
/// <inheritdoc cref="MultiGesture.Match.All" />
|
||||
public sealed class AllGestures : MultiGesture
|
||||
{
|
||||
public AllGestures(params InputGesture[] gestures) : base(Match.All, gestures)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Nodify/Interactivity/Gestures/AnyGesture.cs
Normal file
12
Nodify/Interactivity/Gestures/AnyGesture.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify.Interactivity
|
||||
{
|
||||
/// <inheritdoc cref="MultiGesture.Match.Any" />
|
||||
public sealed class AnyGesture : MultiGesture
|
||||
{
|
||||
public AnyGesture(params InputGesture[] gestures) : base(Match.Any, gestures)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
653
Nodify/Interactivity/Gestures/EditorGestures.cs
Normal file
653
Nodify/Interactivity/Gestures/EditorGestures.cs
Normal file
@@ -0,0 +1,653 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify.Interactivity
|
||||
{
|
||||
/// <summary>Gestures used by built-in controls inside the <see cref="NodifyEditor"/>.</summary>
|
||||
public class EditorGestures
|
||||
{
|
||||
public static readonly EditorGestures Mappings = new EditorGestures();
|
||||
|
||||
/// <summary>Gestures for the selection.</summary>
|
||||
public class SelectionGestures
|
||||
{
|
||||
/// <summary>Disable selection gestures.</summary>
|
||||
public static readonly SelectionGestures None = new SelectionGestures(MouseAction.None);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SelectionGestures"/> class with specified mouse action
|
||||
/// and a flag indicating whether modifier keys should be ignored when releasing the mouse button.
|
||||
/// </summary>
|
||||
/// <param name="mouseAction">The mouse action to trigger the gestures.</param>
|
||||
/// <param name="ignoreModifierKeysOnRelease">
|
||||
/// A value indicating whether modifier keys (Alt, Shift, Control) should be ignored when the mouse button is released.
|
||||
/// </param>
|
||||
public SelectionGestures(MouseAction mouseAction, bool ignoreModifierKeysOnRelease)
|
||||
{
|
||||
Replace = new MouseGesture(mouseAction);
|
||||
Remove = new MouseGesture(mouseAction, ModifierKeys.Alt, ignoreModifierKeysOnRelease);
|
||||
Append = new MouseGesture(mouseAction, ModifierKeys.Shift, ignoreModifierKeysOnRelease);
|
||||
Invert = new MouseGesture(mouseAction, ModifierKeys.Control, ignoreModifierKeysOnRelease);
|
||||
Select = new AnyGesture(Replace, Remove, Append, Invert);
|
||||
Cancel = new KeyGesture(Key.Escape);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SelectionGestures"/> class with a specified mouse action.
|
||||
/// Modifier keys will be ignored when releasing the mouse button.
|
||||
/// </summary>
|
||||
/// <param name="mouseAction">The mouse action to trigger the gestures.</param>
|
||||
public SelectionGestures(MouseAction mouseAction)
|
||||
: this(mouseAction, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SelectionGestures"/> class with a flag indicating
|
||||
/// whether modifier keys should be ignored when releasing the mouse button.
|
||||
/// The default mouse action is <see cref="MouseAction.LeftClick"/>.
|
||||
/// </summary>
|
||||
/// <param name="ignoreModifierKeysOnRelease">
|
||||
/// A value indicating whether modifier keys (Alt, Shift, Control) should be ignored when the mouse button is released.
|
||||
/// </param>
|
||||
public SelectionGestures(bool ignoreModifierKeysOnRelease)
|
||||
: this(MouseAction.LeftClick, ignoreModifierKeysOnRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SelectionGestures"/> class with default values:
|
||||
/// the mouse action is <see cref="MouseAction.LeftClick"/>, and modifier keys are ignored when releasing the mouse button.
|
||||
/// </summary>
|
||||
public SelectionGestures() : this(true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Gesture to replace previous selection with the selected items.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.LeftClick"/>.</remarks>
|
||||
public InputGestureRef Replace { get; }
|
||||
|
||||
/// <summary>Gesture to remove the selected items from the previous selection.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Alt"/>+<see cref="MouseAction.LeftClick"/>.</remarks>
|
||||
public InputGestureRef Remove { get; }
|
||||
|
||||
/// <summary>Gesture to add the new selected items to the previous selection.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Shift"/>+<see cref="MouseAction.LeftClick"/>.</remarks>
|
||||
public InputGestureRef Append { get; }
|
||||
|
||||
/// <summary>Gesture to invert the selected items.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Control"/>+<see cref="MouseAction.LeftClick"/>.</remarks>
|
||||
public InputGestureRef Invert { get; }
|
||||
|
||||
/// <summary>Cancel the current selection operation reverting to the previous selection.</summary>
|
||||
/// <remarks>Defaults to <see cref="Key.Escape"/>.</remarks>
|
||||
public InputGestureRef Cancel { get; }
|
||||
|
||||
/// <summary>Gesture used to start selecting using a <see cref="SelectionGestures"/> strategy.</summary>
|
||||
public InputGestureRef Select { get; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(SelectionGestures gestures)
|
||||
{
|
||||
Replace.Value = gestures.Replace.Value;
|
||||
Remove.Value = gestures.Remove.Value;
|
||||
Append.Value = gestures.Append.Value;
|
||||
Invert.Value = gestures.Invert.Value;
|
||||
Select.Value = gestures.Select.Value;
|
||||
Cancel.Value = gestures.Cancel.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds the all the gestures used for selection.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
=> Apply(None);
|
||||
}
|
||||
|
||||
/// <summary>Gestures for the item containers.</summary>
|
||||
public class ItemContainerGestures
|
||||
{
|
||||
public ItemContainerGestures()
|
||||
{
|
||||
Selection = new SelectionGestures();
|
||||
Selection.Select.Value = new AnyGesture(
|
||||
Selection.Replace,
|
||||
Selection.Remove,
|
||||
Selection.Append,
|
||||
Selection.Invert);
|
||||
|
||||
Drag = new AnyGesture(Selection.Replace, Selection.Remove, Selection.Append, Selection.Invert);
|
||||
CancelAction = new AnyGesture(new MouseGesture(MouseAction.RightClick), new KeyGesture(Key.Escape));
|
||||
}
|
||||
|
||||
/// <summary>Gesture to select the container using a <see cref="SelectionGestures"/> strategy.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.LeftClick"/> or any of the <see cref="SelectionGestures"/> gestures.</remarks>
|
||||
public SelectionGestures Selection { get; }
|
||||
|
||||
/// <summary>Gesture to start and complete a dragging operation.</summary>
|
||||
/// <remarks>Using a <see cref="Selection"/> strategy to drag from a new selection.
|
||||
/// <br /> Defaults to any of the <see cref="Selection"/> gestures.
|
||||
/// </remarks>
|
||||
public InputGestureRef Drag { get; }
|
||||
|
||||
/// <summary>Gesture to cancel the dragging operation.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.RightClick"/> or <see cref="Key.Escape"/>.</remarks>
|
||||
public InputGestureRef CancelAction { get; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(ItemContainerGestures gestures)
|
||||
{
|
||||
Selection.Apply(gestures.Selection);
|
||||
Drag.Value = gestures.Drag.Value;
|
||||
CancelAction.Value = gestures.CancelAction.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
Selection.Unbind();
|
||||
Drag.Unbind();
|
||||
CancelAction.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keyboard gestures used for navigating the editor and moving selected items.
|
||||
/// </summary>
|
||||
public class DirectionalNavigationGestures
|
||||
{
|
||||
public DirectionalNavigationGestures(ModifierKeys modifierKeys = ModifierKeys.None)
|
||||
{
|
||||
Up = new KeyGesture(Key.Up, modifierKeys);
|
||||
Left = new KeyGesture(Key.Left, modifierKeys);
|
||||
Down = new KeyGesture(Key.Down, modifierKeys);
|
||||
Right = new KeyGesture(Key.Right, modifierKeys);
|
||||
}
|
||||
|
||||
public DirectionalNavigationGestures(Key triggerKey, ModifierKeys modifierKeys = ModifierKeys.None, bool repeated = false)
|
||||
{
|
||||
Up = new KeyComboGesture(triggerKey, Key.Up, modifierKeys) { AllowRepeatingComboKey = repeated };
|
||||
Left = new KeyComboGesture(triggerKey, Key.Left, modifierKeys) { AllowRepeatingComboKey = repeated };
|
||||
Down = new KeyComboGesture(triggerKey, Key.Down, modifierKeys) { AllowRepeatingComboKey = repeated };
|
||||
Right = new KeyComboGesture(triggerKey, Key.Right, modifierKeys) { AllowRepeatingComboKey = repeated };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gesture used for navigating or moving upward.
|
||||
/// </summary>
|
||||
public InputGestureRef Up { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gesture used for navigating or moving left.
|
||||
/// </summary>
|
||||
public InputGestureRef Left { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gesture used for navigating or moving downward.
|
||||
/// </summary>
|
||||
public InputGestureRef Down { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gesture used for navigating or moving right.
|
||||
/// </summary>
|
||||
public InputGestureRef Right { get; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(DirectionalNavigationGestures gestures)
|
||||
{
|
||||
Up.Value = gestures.Up.Value;
|
||||
Left.Value = gestures.Left.Value;
|
||||
Down.Value = gestures.Down.Value;
|
||||
Right.Value = gestures.Right.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
Up.Unbind();
|
||||
Left.Unbind();
|
||||
Down.Unbind();
|
||||
Right.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gestures for the editor.</summary>
|
||||
public class NodifyEditorGestures
|
||||
{
|
||||
/// <summary>
|
||||
/// Keyboard gestures used for navigation, selection, and manipulation in the editor.
|
||||
/// </summary>
|
||||
public class KeyboardGestures
|
||||
{
|
||||
public KeyboardGestures()
|
||||
{
|
||||
Pan = new DirectionalNavigationGestures(Key.Space, repeated: true);
|
||||
DragSelection = new DirectionalNavigationGestures(ModifierKeys.Control);
|
||||
NavigateSelection = new DirectionalNavigationGestures(ModifierKeys.None);
|
||||
ToggleSelected = new AnyGesture(new KeyGesture(Key.Space), new KeyGesture(Key.Enter));
|
||||
DeselectAll = new KeyGesture(Key.Escape);
|
||||
NextNavigationLayer = new KeyGesture(Key.OemCloseBrackets, ModifierKeys.Control);
|
||||
PrevNavigationLayer = new KeyGesture(Key.OemOpenBrackets, ModifierKeys.Control);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Directional gestures used for panning the viewport.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to <see cref="Key.Space"/>+arrow keys.</remarks>
|
||||
public DirectionalNavigationGestures Pan { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Directional gestures used for dragging the selected items.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Control"/>+arrow keys.</remarks>
|
||||
public DirectionalNavigationGestures DragSelection { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Directional gestures used to navigate the selection focus (e.g., between nodes).
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to arrow keys.</remarks>
|
||||
public DirectionalNavigationGestures NavigateSelection { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gesture used to toggle the selected state of the currently focused item.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to <see cref="Key.Space"/></remarks>
|
||||
public InputGestureRef ToggleSelected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gesture used to clear the current selection.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to <see cref="Key.Escape"/>.</remarks>
|
||||
public InputGestureRef DeselectAll { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gesture used to activate the previous keyboard navigation layer.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="ModifierKeys.Control"/>+<see cref="Key.OemCloseBrackets"/>.</remarks>
|
||||
public InputGestureRef NextNavigationLayer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gesture used to activate the next keyboard navigation layer.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="ModifierKeys.Control"/>+<see cref="Key.OemOpenBrackets"/>.</remarks>
|
||||
public InputGestureRef PrevNavigationLayer { get; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(KeyboardGestures gestures)
|
||||
{
|
||||
Pan.Apply(gestures.Pan);
|
||||
DragSelection.Apply(gestures.DragSelection);
|
||||
NavigateSelection.Apply(gestures.NavigateSelection);
|
||||
ToggleSelected.Value = gestures.ToggleSelected.Value;
|
||||
DeselectAll.Value = gestures.DeselectAll.Value;
|
||||
NextNavigationLayer.Value = gestures.NextNavigationLayer.Value;
|
||||
PrevNavigationLayer.Value = gestures.PrevNavigationLayer.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
Pan.Unbind();
|
||||
DragSelection.Unbind();
|
||||
NavigateSelection.Unbind();
|
||||
ToggleSelected.Unbind();
|
||||
DeselectAll.Unbind();
|
||||
NextNavigationLayer.Unbind();
|
||||
PrevNavigationLayer.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
public NodifyEditorGestures()
|
||||
{
|
||||
Keyboard = new KeyboardGestures();
|
||||
Selection = new SelectionGestures();
|
||||
SelectAll = ApplicationCommands.SelectAll.InputGestures[0].AsRef();
|
||||
Cutting = new MouseGesture(MouseAction.LeftClick, ModifierKeys.Alt | ModifierKeys.Shift, true);
|
||||
PushItems = new MouseGesture(MouseAction.LeftClick, ModifierKeys.Control | ModifierKeys.Shift, true);
|
||||
Pan = new AnyGesture(new MouseGesture(MouseAction.RightClick), new MouseGesture(MouseAction.MiddleClick));
|
||||
ZoomModifierKey = ModifierKeys.None;
|
||||
ZoomIn = new AnyGesture(new KeyGesture(Key.OemPlus, ModifierKeys.Control), new KeyGesture(Key.Add, ModifierKeys.Control));
|
||||
ZoomOut = new AnyGesture(new KeyGesture(Key.OemMinus, ModifierKeys.Control), new KeyGesture(Key.Subtract, ModifierKeys.Control));
|
||||
ResetViewport = new KeyGesture(Key.Home);
|
||||
FitToScreen = new KeyGesture(Key.Home, ModifierKeys.Shift);
|
||||
CancelAction = new AnyGesture(new MouseGesture(MouseAction.RightClick), new KeyGesture(Key.Escape));
|
||||
PanWithMouseWheel = false;
|
||||
PanHorizontalModifierKey = ModifierKeys.Shift;
|
||||
PanVerticalModifierKey = ModifierKeys.None;
|
||||
}
|
||||
|
||||
public KeyboardGestures Keyboard { get; }
|
||||
|
||||
/// <summary>Gesture used to start selecting using a <see cref="SelectionGestures"/> strategy.</summary>
|
||||
public SelectionGestures Selection { get; }
|
||||
|
||||
/// <summary>Gesture used to select all <see cref="Nodify.ItemContainer"/>s in the editor.</summary>
|
||||
public InputGestureRef SelectAll { get; }
|
||||
|
||||
/// <summary>Gesture used to start cutting connections.</summary>
|
||||
public InputGestureRef Cutting { get; }
|
||||
|
||||
/// <summary>Gesture used to start panning.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.RightClick"/> or <see cref="MouseAction.MiddleClick"/>.</remarks>
|
||||
public InputGestureRef Pan { get; }
|
||||
|
||||
/// <summary>Whether panning using mouse wheel is allowed.</summary>
|
||||
/// <remarks>Set the <see cref="ZoomModifierKey"/> to allow zooming using the mouse wheel.</remarks>
|
||||
public bool PanWithMouseWheel { get; set; }
|
||||
|
||||
/// <summary>The modifier key required to start panning vertically with the mouse wheel (see <see cref="PanWithMouseWheel"/>)</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.None"/>.</remarks>
|
||||
public ModifierKeys PanVerticalModifierKey { get; set; }
|
||||
|
||||
/// <summary>The modifier key required to start panning horizontally with the mouse wheel (see <see cref="PanWithMouseWheel"/>)</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Shift"/>.</remarks>
|
||||
public ModifierKeys PanHorizontalModifierKey { get; set; }
|
||||
|
||||
/// <summary>Gesture used to start pushing.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Control"/>+<see cref="ModifierKeys.Shift"/>+<see cref="MouseAction.LeftClick"/>.</remarks>
|
||||
public InputGestureRef PushItems { get; }
|
||||
|
||||
/// <summary>The key modifier required to start zooming by mouse wheel.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.None"/>.</remarks>
|
||||
public ModifierKeys ZoomModifierKey { get; set; }
|
||||
|
||||
/// <summary>Gesture used to zoom in.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Control"/>+<see cref="Key.OemPlus"/>.</remarks>
|
||||
public InputGestureRef ZoomIn { get; }
|
||||
|
||||
/// <summary>Gesture used to zoom out.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Control"/>+<see cref="Key.OemMinus"/>.</remarks>
|
||||
public InputGestureRef ZoomOut { get; }
|
||||
|
||||
/// <summary>Gesture used to move the editor's viewport location to (0, 0) and set the zoom to 1.</summary>
|
||||
/// <remarks>Defaults to <see cref="Key.Home"/>.</remarks>
|
||||
public InputGestureRef ResetViewport { get; }
|
||||
|
||||
/// <summary>Gesture used to fit as many containers as possible into the viewport.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Shift"/>+<see cref="Key.Home"/>.</remarks>
|
||||
public InputGestureRef FitToScreen { get; }
|
||||
|
||||
/// <summary>Gesture to cancel the current operation.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.RightClick"/> or <see cref="Key.Escape"/>.</remarks>
|
||||
public InputGestureRef CancelAction { get; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(NodifyEditorGestures gestures)
|
||||
{
|
||||
Keyboard.Apply(gestures.Keyboard);
|
||||
Selection.Apply(gestures.Selection);
|
||||
SelectAll.Value = gestures.SelectAll.Value;
|
||||
Cutting.Value = gestures.Cutting.Value;
|
||||
PushItems.Value = gestures.PushItems.Value;
|
||||
Pan.Value = gestures.Pan.Value;
|
||||
ZoomModifierKey = gestures.ZoomModifierKey;
|
||||
ZoomIn.Value = gestures.ZoomIn.Value;
|
||||
ZoomOut.Value = gestures.ZoomOut.Value;
|
||||
ResetViewport.Value = gestures.ResetViewport.Value;
|
||||
FitToScreen.Value = gestures.FitToScreen.Value;
|
||||
CancelAction.Value = gestures.CancelAction.Value;
|
||||
PanWithMouseWheel = gestures.PanWithMouseWheel;
|
||||
PanHorizontalModifierKey = gestures.PanHorizontalModifierKey;
|
||||
PanVerticalModifierKey = gestures.PanVerticalModifierKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
Keyboard.Unbind();
|
||||
Selection.Unbind();
|
||||
SelectAll.Unbind();
|
||||
Cutting.Unbind();
|
||||
Pan.Unbind();
|
||||
PushItems.Unbind();
|
||||
ZoomIn.Unbind();
|
||||
ZoomOut.Unbind();
|
||||
ResetViewport.Unbind();
|
||||
FitToScreen.Unbind();
|
||||
CancelAction.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gestures used by the <see cref="Connector"/>.</summary>
|
||||
public class ConnectorGestures
|
||||
{
|
||||
public ConnectorGestures()
|
||||
{
|
||||
Disconnect = new AnyGesture(new MouseGesture(MouseAction.LeftClick, ModifierKeys.Alt), new KeyGesture(Key.Delete));
|
||||
Connect = new AnyGesture(new MouseGesture(MouseAction.LeftClick), new KeyGesture(Key.Space));
|
||||
CancelAction = new AnyGesture(new MouseGesture(MouseAction.RightClick), new KeyGesture(Key.Escape));
|
||||
}
|
||||
|
||||
/// <summary>Gesture to call the <see cref="Connector.DisconnectCommand"/>.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Alt"/>+<see cref="MouseAction.LeftClick"/> or <see cref="Key.Delete"/>.</remarks>
|
||||
public InputGestureRef Disconnect { get; }
|
||||
|
||||
/// <summary>Gesture to start and complete a pending connection.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.LeftClick"/>.</remarks>
|
||||
public InputGestureRef Connect { get; }
|
||||
|
||||
/// <summary>Gesture to cancel the pending connection.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.RightClick"/> or <see cref="Key.Escape"/>.</remarks>
|
||||
public InputGestureRef CancelAction { get; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(ConnectorGestures gestures)
|
||||
{
|
||||
Disconnect.Value = gestures.Disconnect.Value;
|
||||
Connect.Value = gestures.Connect.Value;
|
||||
CancelAction.Value = gestures.CancelAction.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
Disconnect.Unbind();
|
||||
Connect.Unbind();
|
||||
CancelAction.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gestures used by the <see cref="BaseConnection"/>.</summary>
|
||||
public class ConnectionGestures
|
||||
{
|
||||
public ConnectionGestures()
|
||||
{
|
||||
Split = new MouseGesture(MouseAction.LeftDoubleClick);
|
||||
Selection = new SelectionGestures(MouseAction.LeftClick);
|
||||
Disconnect = new MouseGesture(MouseAction.LeftClick, ModifierKeys.Alt);
|
||||
}
|
||||
|
||||
/// <summary>Gesture to call the <see cref="BaseConnection.SplitCommand"/> command.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.LeftDoubleClick"/>.</remarks>
|
||||
public InputGestureRef Split { get; }
|
||||
|
||||
/// <summary>Gesture used to start selecting using a <see cref="SelectionGestures"/> strategy.</summary>
|
||||
public SelectionGestures Selection { get; }
|
||||
|
||||
/// <summary>Gesture to call the <see cref="BaseConnection.DisconnectCommand"/> command.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Alt"/>+<see cref="MouseAction.LeftClick"/>.</remarks>
|
||||
public InputGestureRef Disconnect { get; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(ConnectionGestures gestures)
|
||||
{
|
||||
Split.Value = gestures.Split.Value;
|
||||
Disconnect.Value = gestures.Disconnect.Value;
|
||||
Selection.Apply(gestures.Selection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
Split.Unbind();
|
||||
Selection.Unbind();
|
||||
Disconnect.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gestures for the <see cref="GroupingNode"/>.</summary>
|
||||
public class GroupingNodeGestures
|
||||
{
|
||||
public GroupingNodeGestures()
|
||||
{
|
||||
SwitchMovementMode = ModifierKeys.Shift;
|
||||
ToggleContentSelection = new AnyGesture(new KeyGesture(Key.Space, ModifierKeys.Control), new KeyGesture(Key.Enter, ModifierKeys.Control));
|
||||
}
|
||||
|
||||
/// <summary>The key modifier that will toggle between <see cref="GroupingMovementMode"/>s.</summary>
|
||||
/// <remarks>The modifier must be allowed by the <see cref="ItemContainer.Drag"/> gesture.
|
||||
/// <br /> Defaults to <see cref="ModifierKeys.Shift"/>.
|
||||
/// </remarks>
|
||||
public ModifierKeys SwitchMovementMode { get; set; }
|
||||
|
||||
/// <summary>Gesture to toggle the content selection of the <see cref="GroupingNode"/> when it is selected.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Control"/>+<see cref="Key.Space"/>.</remarks>
|
||||
public InputGestureRef ToggleContentSelection { get; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(GroupingNodeGestures gestures)
|
||||
{
|
||||
SwitchMovementMode = gestures.SwitchMovementMode;
|
||||
ToggleContentSelection.Value = gestures.ToggleContentSelection.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
ToggleContentSelection.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gestures used by the <see cref="Nodify.Minimap"/> control.</summary>
|
||||
public class MinimapGestures
|
||||
{
|
||||
public MinimapGestures()
|
||||
{
|
||||
Pan = new DirectionalNavigationGestures();
|
||||
DragViewport = new MouseGesture(MouseAction.LeftClick);
|
||||
ResetViewport = new KeyGesture(Key.Home);
|
||||
CancelAction = new AnyGesture(new MouseGesture(MouseAction.RightClick), new KeyGesture(Key.Escape));
|
||||
ZoomIn = new AnyGesture(new KeyGesture(Key.OemPlus, ModifierKeys.Control), new KeyGesture(Key.Add, ModifierKeys.Control));
|
||||
ZoomOut = new AnyGesture(new KeyGesture(Key.OemMinus, ModifierKeys.Control), new KeyGesture(Key.Subtract, ModifierKeys.Control));
|
||||
ZoomModifierKey = ModifierKeys.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Directional gestures used for panning the viewport.
|
||||
/// </summary>
|
||||
/// <remarks>Defaults to <see cref="Key.Space"/>+arrow keys.</remarks>
|
||||
public DirectionalNavigationGestures Pan { get; }
|
||||
|
||||
/// <summary>Gesture to move the viewport inside the <see cref="Minimap" />.</summary>
|
||||
public InputGestureRef DragViewport { get; }
|
||||
|
||||
/// <summary>Gesture to move the viewport inside the <see cref="Minimap" />.</summary>
|
||||
public InputGestureRef ResetViewport { get; }
|
||||
|
||||
/// <summary>Gesture to cancel the panning operation.</summary>
|
||||
/// <remarks>Defaults to <see cref="MouseAction.RightClick"/> or <see cref="Key.Escape"/>.</remarks>
|
||||
public InputGestureRef CancelAction { get; }
|
||||
|
||||
/// <summary>Gesture used to zoom in.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Control"/>+<see cref="Key.OemPlus"/>.</remarks>
|
||||
public InputGestureRef ZoomIn { get; }
|
||||
|
||||
/// <summary>Gesture used to zoom out.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.Control"/>+<see cref="Key.OemMinus"/>.</remarks>
|
||||
public InputGestureRef ZoomOut { get; }
|
||||
|
||||
/// <summary>The key modifier required to start zooming by mouse wheel.</summary>
|
||||
/// <remarks>Defaults to <see cref="ModifierKeys.None"/>.</remarks>
|
||||
public ModifierKeys ZoomModifierKey { get; set; }
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(MinimapGestures gestures)
|
||||
{
|
||||
Pan.Apply(gestures.Pan);
|
||||
ZoomIn.Value = gestures.ZoomIn.Value;
|
||||
ZoomOut.Value = gestures.ZoomOut.Value;
|
||||
ResetViewport.Value = gestures.ResetViewport.Value;
|
||||
DragViewport.Value = gestures.DragViewport.Value;
|
||||
CancelAction.Value = gestures.CancelAction.Value;
|
||||
ZoomModifierKey = gestures.ZoomModifierKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
Pan.Unbind();
|
||||
ZoomIn.Unbind();
|
||||
ZoomOut.Unbind();
|
||||
ResetViewport.Unbind();
|
||||
DragViewport.Unbind();
|
||||
CancelAction.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gestures for the editor.</summary>
|
||||
public NodifyEditorGestures Editor { get; } = new NodifyEditorGestures();
|
||||
|
||||
/// <summary>Gestures for the item container.</summary>
|
||||
public ItemContainerGestures ItemContainer { get; } = new ItemContainerGestures();
|
||||
|
||||
/// <summary>Gestures for the connector.</summary>
|
||||
public ConnectorGestures Connector { get; } = new ConnectorGestures();
|
||||
|
||||
/// <summary>Gestures for the connection.</summary>
|
||||
public ConnectionGestures Connection { get; } = new ConnectionGestures();
|
||||
|
||||
/// <summary>Gestures for the grouping node.</summary>
|
||||
public GroupingNodeGestures GroupingNode { get; } = new GroupingNodeGestures();
|
||||
|
||||
/// <summary>Gestures for the minimap.</summary>
|
||||
public MinimapGestures Minimap { get; } = new MinimapGestures();
|
||||
|
||||
/// <summary>Copies from the specified gestures.</summary>
|
||||
/// <param name="gestures">The gestures to copy.</param>
|
||||
public void Apply(EditorGestures gestures)
|
||||
{
|
||||
Editor.Apply(gestures.Editor);
|
||||
ItemContainer.Apply(gestures.ItemContainer);
|
||||
Connector.Apply(gestures.Connector);
|
||||
Connection.Apply(gestures.Connection);
|
||||
GroupingNode.Apply(gestures.GroupingNode);
|
||||
Minimap.Apply(gestures.Minimap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds all the gestures used by the editor and its controls.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
{
|
||||
Editor.Unbind();
|
||||
ItemContainer.Unbind();
|
||||
Connector.Unbind();
|
||||
Connection.Unbind();
|
||||
Minimap.Unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Nodify/Interactivity/Gestures/InputGestureRef.cs
Normal file
58
Nodify/Interactivity/Gestures/InputGestureRef.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify.Interactivity
|
||||
{
|
||||
/// <summary>
|
||||
/// An input gesture that allows changing its logic at runtime without changing its reference.
|
||||
/// Useful for classes that capture the object reference without the posibility of updating it. (e.g. <see cref="EditorCommands"/>)
|
||||
/// </summary>
|
||||
public sealed class InputGestureRef : InputGesture
|
||||
{
|
||||
/// <summary>The referenced gesture.</summary>
|
||||
public InputGesture Value { get; set; } = MultiGesture.None;
|
||||
|
||||
private InputGestureRef() { }
|
||||
|
||||
internal InputGestureRef(InputGesture gesture)
|
||||
{
|
||||
Value = gesture;
|
||||
}
|
||||
|
||||
public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
|
||||
{
|
||||
return Value.Matches(targetElement, inputEventArgs);
|
||||
}
|
||||
|
||||
public static implicit operator InputGestureRef(MouseGesture gesture)
|
||||
=> new InputGestureRef { Value = gesture };
|
||||
|
||||
public static implicit operator InputGestureRef(System.Windows.Input.MouseGesture gesture)
|
||||
=> new InputGestureRef { Value = gesture };
|
||||
|
||||
public static implicit operator InputGestureRef(KeyGesture gesture)
|
||||
=> new InputGestureRef { Value = gesture };
|
||||
|
||||
public static implicit operator InputGestureRef(MultiGesture gesture)
|
||||
=> new InputGestureRef { Value = gesture };
|
||||
|
||||
/// <summary>
|
||||
/// Unbinds the current gesture.
|
||||
/// </summary>
|
||||
public void Unbind()
|
||||
=> Value = MultiGesture.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for the <see cref="InputGestureRef"/> class.
|
||||
/// </summary>
|
||||
public static class InputGestureRefExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="InputGestureRef"/> from the specified gesture.
|
||||
/// </summary>
|
||||
public static InputGestureRef AsRef(this InputGesture gesture)
|
||||
{
|
||||
return new InputGestureRef(gesture);
|
||||
}
|
||||
}
|
||||
}
|
||||
131
Nodify/Interactivity/Gestures/KeyComboGesture.cs
Normal file
131
Nodify/Interactivity/Gestures/KeyComboGesture.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify.Interactivity
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a keyboard gesture that requires a trigger key to be held down
|
||||
/// before pressing a combo key. For example, press and hold Space, then press Left arrow.
|
||||
/// </summary>
|
||||
public class KeyComboGesture : KeyGesture
|
||||
{
|
||||
private static readonly WeakReferenceCollection<KeyComboGesture> _allCombos = new WeakReferenceCollection<KeyComboGesture>(16);
|
||||
|
||||
private bool _isTriggerDown;
|
||||
private int _comboCounter;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the combo gesture has been performed at least once.
|
||||
/// </summary>
|
||||
private bool HasBeenPerformedAtLeastOnce => _comboCounter > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the key that must be pressed first to activate this combo gesture.
|
||||
/// </summary>
|
||||
public Key TriggerKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the combo key can be repeatedly triggered
|
||||
/// without releasing the trigger key.
|
||||
/// </summary>
|
||||
public bool AllowRepeatingComboKey { get; set; }
|
||||
|
||||
static KeyComboGesture()
|
||||
{
|
||||
EventManager.RegisterClassHandler(typeof(UIElement), UIElement.PreviewKeyUpEvent, new KeyEventHandler(HandleKeyUp), true);
|
||||
EventManager.RegisterClassHandler(typeof(UIElement), UIElement.LostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(HandleFocusLost), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="KeyComboGesture"/> class with the specified trigger and combo keys.
|
||||
/// </summary>
|
||||
/// <param name="triggerKey">The key that must be pressed first.</param>
|
||||
/// <param name="comboKey">The combo key pressed while the trigger key is held.</param>
|
||||
public KeyComboGesture(Key triggerKey, Key comboKey) : this(triggerKey, comboKey, ModifierKeys.None, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="KeyComboGesture"/> class with the specified trigger and combo keys and modifiers.
|
||||
/// </summary>
|
||||
/// <param name="triggerKey">The key that must be pressed first.</param>
|
||||
/// <param name="comboKey">The combo key pressed while the trigger key is held.</param>
|
||||
/// <param name="modifiers">Any modifier keys required for the combo key.</param>
|
||||
public KeyComboGesture(Key triggerKey, Key comboKey, ModifierKeys modifiers) : this(triggerKey, comboKey, modifiers, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="KeyComboGesture"/> class with the specified trigger key,
|
||||
/// combo key, modifiers, and display string.
|
||||
/// </summary>
|
||||
/// <param name="triggerKey">The key that must be pressed first.</param>
|
||||
/// <param name="comboKey">The combo key pressed while the trigger key is held.</param>
|
||||
/// <param name="modifiers">Any modifier keys required for the combo key.</param>
|
||||
/// <param name="displayString">The display string representing the gesture.</param>
|
||||
public KeyComboGesture(Key triggerKey, Key comboKey, ModifierKeys modifiers, string displayString) : base(comboKey, modifiers, displayString)
|
||||
{
|
||||
TriggerKey = triggerKey;
|
||||
_allCombos.Add(this);
|
||||
}
|
||||
|
||||
private static void HandleFocusLost(object sender, KeyboardFocusChangedEventArgs e)
|
||||
{
|
||||
foreach (var combo in _allCombos)
|
||||
{
|
||||
combo.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleKeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
foreach (var combo in _allCombos)
|
||||
{
|
||||
if (e.Key == combo.TriggerKey)
|
||||
{
|
||||
// We don't want to handle the event if only the trigger key was pressed.
|
||||
if (combo.HasBeenPerformedAtLeastOnce)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
combo.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
_isTriggerDown = false;
|
||||
_comboCounter = 0;
|
||||
}
|
||||
|
||||
public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
|
||||
{
|
||||
if (inputEventArgs is KeyEventArgs { IsDown: true } keyArgs)
|
||||
{
|
||||
if (keyArgs.Key == TriggerKey)
|
||||
{
|
||||
_isTriggerDown = true;
|
||||
}
|
||||
|
||||
// The combo key only triggers the combo on key down
|
||||
bool matches = _isTriggerDown && base.Matches(targetElement, inputEventArgs);
|
||||
if (!matches)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_comboCounter++;
|
||||
|
||||
if (!AllowRepeatingComboKey)
|
||||
{
|
||||
_isTriggerDown = false;
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
153
Nodify/Interactivity/Gestures/MouseGesture.cs
Normal file
153
Nodify/Interactivity/Gestures/MouseGesture.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify.Interactivity
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a mouse gesture that optionally includes a specific key press as part of the gesture.
|
||||
/// </summary>
|
||||
public sealed class MouseGesture : System.Windows.Input.MouseGesture
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the key that must be pressed to match this gesture.
|
||||
/// </summary>
|
||||
public Key Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to ignore modifier keys when releasing the mouse button.
|
||||
/// </summary>
|
||||
public bool IgnoreModifierKeysOnRelease { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MouseGesture"/> class with the specified mouse action, modifier keys, and a specific key.
|
||||
/// </summary>
|
||||
/// <param name="action">The action associated with this gesture.</param>
|
||||
/// <param name="modifiers">The modifiers associated with this gesture.</param>
|
||||
/// <param name="key">The key required to match the gesture.</param>
|
||||
public MouseGesture(MouseAction action, ModifierKeys modifiers, Key key) : base(action, modifiers)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MouseGesture"/> class with the specified mouse action and key.
|
||||
/// </summary>
|
||||
/// <param name="action">The action associated with this gesture.</param>
|
||||
/// <param name="key">The key required to match the gesture.</param>
|
||||
public MouseGesture(MouseAction action, Key key) : base(action)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MouseGesture(MouseAction action, ModifierKeys modifiers)
|
||||
: base(action, modifiers)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MouseGesture"/> class with the specified mouse action and modifier keys.
|
||||
/// </summary>
|
||||
/// <param name="action">The action associated with this gesture.</param>
|
||||
/// <param name="modifiers">The modifiers required to match the gesture.</param>
|
||||
/// <param name="ignoreModifierKeysOnRelease">Whether to ignore modifiers when releasing the mouse button.</param>
|
||||
public MouseGesture(MouseAction action, ModifierKeys modifiers, bool ignoreModifierKeysOnRelease)
|
||||
: base(action, modifiers)
|
||||
{
|
||||
IgnoreModifierKeysOnRelease = ignoreModifierKeysOnRelease;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MouseGesture(MouseAction action) : base(action)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MouseGesture()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
|
||||
{
|
||||
if (inputEventArgs is MouseButtonEventArgs || inputEventArgs is MouseWheelEventArgs)
|
||||
{
|
||||
bool matches = base.Matches(targetElement, inputEventArgs);
|
||||
|
||||
if (IgnoreModifierKeysOnRelease && IsButtonReleased(inputEventArgs))
|
||||
{
|
||||
ModifierKeys prevModifiers = Modifiers;
|
||||
Modifiers = ModifierKeys.None;
|
||||
matches |= base.Matches(targetElement, inputEventArgs);
|
||||
Modifiers = prevModifiers;
|
||||
}
|
||||
|
||||
return matches && MatchesKeyboard();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the required key is pressed or no keys are pressed when <see cref="Key"/> is <see cref="Key.None"/>.
|
||||
/// </summary>
|
||||
private bool MatchesKeyboard()
|
||||
{
|
||||
if (Key is Key.None)
|
||||
{
|
||||
return !IsAnyKeyPressed();
|
||||
}
|
||||
|
||||
return Keyboard.IsKeyDown(Key);
|
||||
}
|
||||
|
||||
private static readonly Key[] _allKeys = new[]
|
||||
{
|
||||
// Alphanumeric
|
||||
Key.A, Key.B, Key.C, Key.D, Key.E, Key.F, Key.G, Key.H, Key.I, Key.J,
|
||||
Key.K, Key.L, Key.M, Key.N, Key.O, Key.P, Key.Q, Key.R, Key.S, Key.T,
|
||||
Key.U, Key.V, Key.W, Key.X, Key.Y, Key.Z,
|
||||
Key.D0, Key.D1, Key.D2, Key.D3, Key.D4, Key.D5, Key.D6, Key.D7, Key.D8, Key.D9,
|
||||
|
||||
// Punctuation and symbols
|
||||
Key.Oem3, Key.OemMinus, Key.OemPlus, Key.OemOpenBrackets, Key.OemCloseBrackets,
|
||||
Key.Oem5, Key.Oem1, Key.OemQuotes, Key.OemComma, Key.OemPeriod, Key.Oem2,
|
||||
|
||||
// Function keys
|
||||
Key.F1, Key.F2, Key.F3, Key.F4, Key.F5, Key.F6, Key.F7, Key.F8,
|
||||
Key.F9, Key.F10, Key.F11, Key.F12,
|
||||
|
||||
// Navigation
|
||||
Key.Left, Key.Right, Key.Up, Key.Down,
|
||||
Key.PageUp, Key.PageDown, Key.Home, Key.End,
|
||||
|
||||
// Editing
|
||||
Key.Back, Key.Delete, Key.Insert,
|
||||
|
||||
// Special
|
||||
Key.Space, Key.Return, Key.Escape, Key.Tab,
|
||||
|
||||
// Numeric keypad
|
||||
Key.NumPad0, Key.NumPad1, Key.NumPad2, Key.NumPad3, Key.NumPad4,
|
||||
Key.NumPad5, Key.NumPad6, Key.NumPad7, Key.NumPad8, Key.NumPad9,
|
||||
Key.Multiply, Key.Add, Key.Subtract, Key.Divide, Key.Decimal
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether any key (excluding modifiers) is currently pressed.
|
||||
/// </summary>
|
||||
private static bool IsAnyKeyPressed()
|
||||
=> _allKeys.Any(Keyboard.IsKeyDown);
|
||||
|
||||
private static bool IsButtonReleased(InputEventArgs e)
|
||||
{
|
||||
if (e is MouseButtonEventArgs mbe && mbe.ButtonState == MouseButtonState.Released)
|
||||
return true;
|
||||
|
||||
if (e is MouseWheelEventArgs mwe && mwe.MiddleButton == MouseButtonState.Released)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
Nodify/Interactivity/Gestures/MultiGesture.cs
Normal file
68
Nodify/Interactivity/Gestures/MultiGesture.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify.Interactivity
|
||||
{
|
||||
/// <summary>Combines multiple input gestures.</summary>
|
||||
public class MultiGesture : InputGesture
|
||||
{
|
||||
public static readonly MultiGesture None = new MultiGesture(Match.Any);
|
||||
|
||||
/// <summary>The strategy used by <see cref="Matches(object, InputEventArgs)"/>.</summary>
|
||||
public enum Match
|
||||
{
|
||||
/// <summary>At least one gesture must match.</summary>
|
||||
Any,
|
||||
/// <summary>All gestures must match.</summary>
|
||||
All
|
||||
}
|
||||
|
||||
private readonly InputGesture[] _gestures;
|
||||
private readonly Match _match;
|
||||
|
||||
/// <summary>Constructs an instance of a <see cref="MultiGesture"/>.</summary>
|
||||
/// <param name="match">The matching strategy.</param>
|
||||
/// <param name="gestures">The input gestures.</param>
|
||||
public MultiGesture(Match match, params InputGesture[] gestures)
|
||||
{
|
||||
_gestures = gestures;
|
||||
_match = match;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
|
||||
{
|
||||
if (_match == Match.Any)
|
||||
{
|
||||
return MatchesAny(targetElement, inputEventArgs);
|
||||
}
|
||||
|
||||
return MatchesAll(targetElement, inputEventArgs);
|
||||
}
|
||||
|
||||
private bool MatchesAll(object targetElement, InputEventArgs inputEventArgs)
|
||||
{
|
||||
for (int i = 0; i < _gestures.Length; i++)
|
||||
{
|
||||
if (!_gestures[i].Matches(targetElement, inputEventArgs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool MatchesAny(object targetElement, InputEventArgs inputEventArgs)
|
||||
{
|
||||
for (int i = 0; i < _gestures.Length; i++)
|
||||
{
|
||||
if (_gestures[i].Matches(targetElement, inputEventArgs))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user