Skip to content

Instantly share code, notes, and snippets.

@rubyu
Created August 26, 2018 12:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rubyu/e084f7d84f8502b9f2135eba1f964598 to your computer and use it in GitHub Desktop.
Save rubyu/e084f7d84f8502b9f2135eba1f964598 to your computer and use it in GitHub Desktop.
// 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