Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support multiple keybindings for some actions #2884

Merged
merged 2 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 52 additions & 18 deletions pkgs/sketch_pad/lib/keys.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ import 'theme.dart';
bool get _mac => defaultTargetPlatform == TargetPlatform.macOS;
bool get _nonMac => defaultTargetPlatform != TargetPlatform.macOS;

// key activators
// ## Key activators

final ShortcutActivator reloadKeyActivator = SingleActivator(
LogicalKeyboardKey.keyS,
final ShortcutActivator runKeyActivator1 = SingleActivator(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to make sure we're following best-practices for shortcuts and actions: https://docs.flutter.dev/ui/interactivity/actions-and-shortcuts

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 - I filed #2913 to track this

LogicalKeyboardKey.keyR,
meta: _mac,
control: _nonMac,
);
final ShortcutActivator runKeyActivator2 = SingleActivator(
LogicalKeyboardKey.enter,
meta: _mac,
control: _nonMac,
);

final ShortcutActivator findKeyActivator = SingleActivator(
LogicalKeyboardKey.keyF,
meta: _mac,
Expand All @@ -28,30 +34,45 @@ final ShortcutActivator findNextKeyActivator = SingleActivator(
meta: _mac,
control: _nonMac,
);

final ShortcutActivator formatKeyActivator1 = SingleActivator(
LogicalKeyboardKey.keyS,
meta: _mac,
control: _nonMac,
);
const ShortcutActivator formatKeyActivator2 = SingleActivator(
LogicalKeyboardKey.keyF,
shift: true,
alt: true,
);

const ShortcutActivator codeCompletionKeyActivator = SingleActivator(
LogicalKeyboardKey.space,
control: true,
);
final ShortcutActivator quickFixKeyActivator = SingleActivator(

final ShortcutActivator quickFixKeyActivator1 = SingleActivator(
LogicalKeyboardKey.period,
meta: _mac,
control: _nonMac,
);
const ShortcutActivator quickFixKeyActivator2 = SingleActivator(
LogicalKeyboardKey.enter,
alt: true,
);

// map of key activator names
// ## Map of key activator names

final List<(String, ShortcutActivator)> keyBindings = [
('Code completion', codeCompletionKeyActivator),
('Find', findKeyActivator),
('Find next', findNextKeyActivator),
('Quick fixes', quickFixKeyActivator),
('Reload', reloadKeyActivator),
final List<(String, List<ShortcutActivator>)> keyBindings = [
('Code completion', [codeCompletionKeyActivator]),
('Find', [findKeyActivator]),
('Find next', [findNextKeyActivator]),
('Format', [formatKeyActivator1, formatKeyActivator2]),
('Quick fixes', [quickFixKeyActivator1, quickFixKeyActivator2]),
('Run', [runKeyActivator1, runKeyActivator2]),
];

extension SingleActivatorExtension on SingleActivator {
// Note that this only works in debug mode.
String get describe => debugDescribeKeys();

Widget renderToWidget(BuildContext context) {
var text = trigger.keyLabel;
if (trigger == LogicalKeyboardKey.space) {
Expand All @@ -60,17 +81,30 @@ extension SingleActivatorExtension on SingleActivator {

return Container(
decoration: BoxDecoration(
border: Border.fromBorderSide(
Divider.createBorderSide(context, width: 1.0, color: subtleColor),
),
borderRadius: const BorderRadius.all(Radius.circular(4))),
border: Border.fromBorderSide(
Divider.createBorderSide(context, width: 1.0, color: subtleColor),
),
borderRadius: const BorderRadius.all(Radius.circular(4)),
),
padding: const EdgeInsets.symmetric(
vertical: 2,
horizontal: 6,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (shift)
const Icon(
Icons.arrow_upward,
size: 16,
color: subtleColor,
),
if (alt)
Icon(
_mac ? Icons.keyboard_option_key : Icons.keyboard_alt,
size: 16,
color: subtleColor,
),
if (control)
const Icon(
Icons.keyboard_control_key,
Expand Down
48 changes: 33 additions & 15 deletions pkgs/sketch_pad/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ import 'utils.dart';
import 'versions.dart';
import 'widgets.dart';

// TODO: show documentation on hover

// TODO: implement find / find next

const appName = 'DartPad';
const smallScreenWidth = 720;

Expand Down Expand Up @@ -439,10 +435,11 @@ class _DartPadMainPageState extends State<DartPadMainPage>
value: appModel,
child: CallbackShortcuts(
bindings: <ShortcutActivator, VoidCallback>{
keys.reloadKeyActivator: () {
if (!appModel.compilingBusy.value) {
_performCompileAndRun();
}
keys.runKeyActivator1: () {
if (!appModel.compilingBusy.value) _performCompileAndRun();
},
keys.runKeyActivator2: () {
if (!appModel.compilingBusy.value) _performCompileAndRun();
},
keys.findKeyActivator: () {
// TODO:
Expand All @@ -452,10 +449,19 @@ class _DartPadMainPageState extends State<DartPadMainPage>
// TODO:
unimplemented(context, 'find next');
},
keys.formatKeyActivator1: () {
if (!appModel.formattingBusy.value) _handleFormatting();
},
keys.formatKeyActivator2: () {
if (!appModel.formattingBusy.value) _handleFormatting();
},
keys.codeCompletionKeyActivator: () {
appServices.editorService?.showCompletions();
},
keys.quickFixKeyActivator: () {
keys.quickFixKeyActivator1: () {
appServices.editorService?.showQuickFixes();
},
keys.quickFixKeyActivator2: () {
appServices.editorService?.showQuickFixes();
},
},
Expand Down Expand Up @@ -1056,7 +1062,7 @@ class OverflowMenu extends StatelessWidget {
}

class KeyBindingsTable extends StatelessWidget {
final List<(String, ShortcutActivator)> bindings;
final List<(String, List<ShortcutActivator>)> bindings;

const KeyBindingsTable({
required this.bindings,
Expand All @@ -1070,7 +1076,7 @@ class KeyBindingsTable extends StatelessWidget {
children: [
const Divider(),
Expanded(
child: VTable<(String, ShortcutActivator)>(
child: VTable<(String, List<ShortcutActivator>)>(
showToolbar: false,
showHeaders: false,
startsSorted: true,
Expand All @@ -1087,12 +1093,24 @@ class KeyBindingsTable extends StatelessWidget {
width: 100,
grow: 0.5,
alignment: Alignment.centerRight,
transformFunction: (binding) =>
(binding.$2 as SingleActivator).describe,
styleFunction: (binding) => subtleText,
renderFunction: (context, binding, _) {
return (binding.$2 as SingleActivator)
.renderToWidget(context);
final children = <Widget>[];
var first = true;
for (final shortcut in binding.$2) {
if (!first) {
children.add(
const Padding(
padding: EdgeInsets.only(left: 4, right: 8),
child: Text(','),
),
);
}
first = false;
children.add(
(shortcut as SingleActivator).renderToWidget(context));
}
return Row(children: children);
},
),
],
Expand Down
Loading