8. Share actions and shortcuts
A named action groups an edit so a button and a shortcut perform exactly the same operation. Add this import:
dart
import 'package:flutter/services.dart';Add configuration: to the existing session constructor alongside shapeRegistry::
dart
configuration: DrawingConfiguration(
actions: [
DrawingAction(
id: 'review.grow',
isEnabled: (context) => context.shape?.type == 'tutorial.review',
execute: (context) {
final shape = context.shape!;
context.resize(width: shape.frame.width + 40,
height: shape.frame.height + 20);
},
),
],
keyBindings: const [
DrawingKeyBinding(
action: 'review.grow', key: LogicalKeyboardKey.keyG,
command: true, shift: true, scope: DrawingActionScope.selection,
),
],
),Add this method and include buildGrowButton() in the reactive toolbar:
dart
Widget buildGrowButton() {
final selection = session.selection;
final ids = selection is ElementSelection
? selection.elementIds : <String>{};
final id = ids.length == 1 ? ids.single : null;
return TextButton(
onPressed: id != null && session.canInvokeAction('review.grow', elementId: id)
? () => showDecision(session.invokeAction('review.grow', elementId: id))
: null,
child: const Text('Grow review'),
);
}Availability is rechecked at invocation. Changes staged through the action context commit together as one Undo entry. An exception or denial discards them. Use the context inside execute; do not issue independent session edits or keep the context across an await.
Here command maps to Meta on macOS and Control elsewhere. Selection-scoped bindings belong to object selection, not active text editing or a focused host text field. Choose a chord that does not collide with your application's shortcuts.
Checkpoint: select a review node and use Grow review, then Command/Ctrl+Shift+G with canvas focus. Both grow it and Undo reverses each operation. Select a diamond: Grow review disables. Action reference covers canvas/text scopes and painted regions.