onKey method
Spec D6 Keys, F-12. Idle (nothing armed) every key bubbles.
Rturns the next placement one quarter turn counter-clockwise,Shift+Rclockwise,Mtoggles the mirror; only with no Ctrl, Meta or Alt held (Cmd/Ctrl+R is a browser reload, Ctrl+M passes through). One step per key-down; a repeat is consumed with no effect. They work armed idle and mid-press; the ghost repaints.- Mid-press:
Esccancels the press (its remaining moves and its up place nothing, Ruling R-B6-1); F and F3 with no modifier bubble (the drawing tools' rule,placement_tool.dart); every other key-down and repeat is swallowed, so undo never lands mid-placement. - Armed, not pressed: every key but R and M bubbles (the shell's
letters, undo and
Escwork). - A key-up always bubbles.
Implementation
@override
KeyEventResult onKey(KeyEvent event, ToolContext ctx) {
if (armed.value == null || event is KeyUpEvent) {
return KeyEventResult.ignored;
}
final key = event.logicalKey;
final modifier = _hasModifier();
if (!modifier &&
((key == LogicalKeyboardKey.keyR && (canRotate?.call() ?? true)) ||
(key == LogicalKeyboardKey.keyM && (canMirror?.call() ?? true)))) {
if (event is KeyDownEvent) {
if (key == LogicalKeyboardKey.keyR) {
final step = HardwareKeyboard.instance.isShiftPressed ? -1 : 1;
_quarterTurns = (_quarterTurns + step) % 4;
} else {
_mirrored = !_mirrored;
}
// Spec 09c D6, decision 5: the same pointer asks the faces again
// with the new mirror (an attached `M` mirrors in place); the
// attached transform ignores the turns, which apply off the face.
_syncAttachment(ctx);
_syncPlacement();
notifyListeners();
}
return KeyEventResult.handled;
}
if (!_pressed) return KeyEventResult.ignored;
if (event is KeyDownEvent) {
if (key == LogicalKeyboardKey.escape) {
cancel(ctx);
return KeyEventResult.handled;
}
if ((key == LogicalKeyboardKey.f3 || key == LogicalKeyboardKey.keyF) &&
!modifier) {
return KeyEventResult.ignored;
}
}
return KeyEventResult.handled;
}