Created
August 26, 2018 12:57
-
-
Save rubyu/e084f7d84f8502b9f2135eba1f964598 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Gesture status helper. | |
// | |
// Functions: | |
// - Show the state of stroke gestures (current stroke status and registered stroke gestures which can be reached from it). | |
// - Show the synopsis of gestures which could be activated from last state of GestureMachine when it timeout. | |
// | |
// Requires: | |
// Crevice >= 4.15 | |
{ | |
string StrokeSequenceToString(IEnumerable<Crevice.Core.Stroke.StrokeDirection> strokeSequence) | |
=> string.Join("", strokeSequence.Select(x => DirectionToString(x))); | |
string DirectionToString(Crevice.Core.Stroke.StrokeDirection d) | |
{ | |
switch (d) | |
{ | |
case Crevice.Core.Stroke.StrokeDirection.Up: return "⬆"; | |
case Crevice.Core.Stroke.StrokeDirection.Down: return "⬇"; | |
case Crevice.Core.Stroke.StrokeDirection.Left: return "⬅"; | |
case Crevice.Core.Stroke.StrokeDirection.Right: return "➡"; | |
default: return ""; | |
}; | |
} | |
// This variable must be cached here to prepare for the cases the profile is not the only one. | |
var profile = CurrentProfile; | |
// A string value which represents directions of the last state of gesture stroke. | |
string lastDirections = ""; | |
// The last State of GestureMachine. | |
Crevice.Core.FSM.State< | |
Crevice.GestureMachine.GestureMachineConfig, | |
Crevice.GestureMachine.ContextManager, | |
Crevice.GestureMachine.EvaluationContext, | |
Crevice.GestureMachine.ExecutionContext> | |
lastState = null; | |
// An object for locking callback invocations. | |
var lockObject = new object(); | |
Config.Callback.StateChanged += (sender, e) => | |
{ | |
lock (lockObject) | |
{ | |
if (e.CurrentState.IsStateN) | |
{ | |
lastState = e.CurrentState; | |
} | |
lastDirections = ""; | |
Tooltip(""); | |
} | |
}; | |
Config.Callback.StrokeUpdated += (sender, e) => | |
{ | |
lock (lockObject) | |
{ | |
if (lastDirections.Length == e.Strokes.Count) return; | |
var directions = StrokeSequenceToString(e.Strokes.Select(x => x.Direction)); | |
var stateN = profile.GestureMachine.CurrentState.AsStateN(); | |
if (stateN != null) | |
{ | |
if (directions.Any()) | |
{ | |
var candidates = stateN.InversedStrokeTrigger | |
.Select(p => (Key: StrokeSequenceToString(p.Key), p.Value)) | |
.Where(p => p.Key.StartsWith(directions)) | |
.ToList(); | |
if (candidates.Any()) | |
{ | |
var hasMatched = candidates.Any(p => p.Key == directions); | |
var strokes = candidates.Select(p => | |
{ | |
var header = p.Key == directions ? "✔ " : " "; | |
var descriptions = string.Join(", ", p.Value.SelectMany(x => x.DoExecutors.Where(d => d.Description.Any()).Select(d => d.Description))); | |
return header + p.Key + (descriptions.Any() ? " [" + descriptions + "]" : ""); | |
}); | |
Tooltip((hasMatched ? "" : "> " + directions + "\r\n") + string.Join("\r\n", strokes)); | |
} | |
else | |
{ | |
Tooltip("❓ " + directions); | |
} | |
} | |
} | |
lastDirections = directions; | |
} | |
}; | |
Config.Callback.GestureTimeout += (sender, e) => | |
{ | |
lock (lockObject) | |
{ | |
if (lastState == null || lastState.IsState0) return; | |
var singleThrows = lastState.AsStateN().InversedSingleThrowTrigger.Select(p => | |
{ | |
var header = "⟲ "; | |
var keyName = p.Key.LogicalKey.ToString().Substring(5); | |
var descriptions = string.Join(", ", p.Value.SelectMany(s => s.DoExecutors.Select(d => d.Description))); | |
return header + keyName + (descriptions.Any() ? " [" + descriptions + "]" : ""); | |
}); | |
var doubleThrows = lastState.AsStateN().InversedDoubleThrowTrigger.Select(p => | |
{ | |
var header = "↷ "; | |
var keyName = p.Key.LogicalKey.ToString().Substring(5); | |
var descriptions = string.Join(", ", p.Value.SelectMany(s => s.DoExecutors.Select(d => d.Description))); | |
return header + keyName + (descriptions.Any() ? " [" + descriptions + "]" : ""); | |
}); | |
var strokes = lastState.AsStateN().InversedStrokeTrigger.Select(p => | |
{ | |
var header = "↯ "; | |
var strokeDirections = StrokeSequenceToString(p.Key); | |
var descriptions = string.Join(", ", p.Value.SelectMany(x => x.DoExecutors.Where(d => d.Description.Any()).Select(d => d.Description))); | |
return header + strokeDirections + (descriptions.Any() ? " [" + descriptions + "]" : ""); | |
}); | |
Tooltip("Gesture was timeout.\r\n\r\nCandidates are:\r\n" + string.Join("\r\n", singleThrows.Concat(doubleThrows).Concat(strokes))); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment