Skip to content

Commit 3f21103

Browse files
authored
Keyboard shortcuts are set on the top-level scaffold (flutter#3458)
1 parent d832b12 commit 3f21103

3 files changed

Lines changed: 101 additions & 48 deletions

File tree

packages/devtools_app/lib/src/debugger/debugger_screen.dart

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@ class DebuggerScreen extends Screen {
4444
@override
4545
bool showConsole(bool embed) => true;
4646

47+
@override
48+
ShortcutsConfiguration buildKeyboardShortcuts(BuildContext context) {
49+
final controller = Provider.of<DebuggerController>(context);
50+
final shortcuts = <LogicalKeySet, Intent>{
51+
goToLineNumberKeySet: GoToLineNumberIntent(context, controller),
52+
searchInFileKeySet: SearchInFileIntent(controller),
53+
escapeKeySet: EscapeIntent(controller),
54+
openFileKeySet: OpenFileIntent(controller),
55+
};
56+
final actions = <Type, Action<Intent>>{
57+
GoToLineNumberIntent: GoToLineNumberAction(),
58+
SearchInFileIntent: SearchInFileAction(),
59+
EscapeIntent: EscapeAction(),
60+
OpenFileIntent: OpenFileAction(),
61+
};
62+
return ShortcutsConfiguration(shortcuts: shortcuts, actions: actions);
63+
}
64+
4765
@override
4866
String get docPageId => screenId;
4967

@@ -161,37 +179,21 @@ class DebuggerScreenBodyState extends State<DebuggerScreenBody>
161179
},
162180
);
163181

164-
return Shortcuts(
165-
shortcuts: <LogicalKeySet, Intent>{
166-
goToLineNumberKeySet: GoToLineNumberIntent(context, controller),
167-
searchInFileKeySet: SearchInFileIntent(controller),
168-
escapeKeySet: EscapeIntent(controller),
169-
openFileKeySet: OpenFileIntent(controller),
170-
},
171-
child: Actions(
172-
actions: <Type, Action<Intent>>{
173-
GoToLineNumberIntent: GoToLineNumberAction(),
174-
SearchInFileIntent: SearchInFileAction(),
175-
EscapeIntent: EscapeAction(),
176-
OpenFileIntent: OpenFileAction(),
177-
},
178-
child: Split(
179-
axis: Axis.horizontal,
180-
initialFractions: const [0.25, 0.75],
182+
return Split(
183+
axis: Axis.horizontal,
184+
initialFractions: const [0.25, 0.75],
185+
children: [
186+
OutlineDecoration(child: debuggerPanes()),
187+
Column(
181188
children: [
182-
OutlineDecoration(child: debuggerPanes()),
183-
Column(
184-
children: [
185-
const DebuggingControls(),
186-
const SizedBox(height: denseRowSpacing),
187-
Expanded(
188-
child: codeArea,
189-
),
190-
],
189+
const DebuggingControls(),
190+
const SizedBox(height: denseRowSpacing),
191+
Expanded(
192+
child: codeArea,
191193
),
192194
],
193195
),
194-
),
196+
],
195197
);
196198
}
197199

packages/devtools_app/lib/src/scaffold.dart

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ class DevToolsScaffoldState extends State<DevToolsScaffold>
326326
],
327327
);
328328
final theme = Theme.of(context);
329+
329330
return Provider<BannerMessagesController>(
330331
create: (_) => BannerMessagesController(),
331332
child: Provider<ImportController>.value(
@@ -340,27 +341,32 @@ class DevToolsScaffoldState extends State<DevToolsScaffold>
340341
// Using theme.primaryColor matches the default behavior of the
341342
// title used by [WidgetsApp].
342343
color: theme.primaryColor,
343-
child: Scaffold(
344-
appBar: widget.embed ? null : _buildAppBar(scaffoldTitle),
345-
body: (serviceManager.connectedAppInitialized &&
346-
!offlineController.offlineMode.value &&
347-
_currentScreen.showConsole(widget.embed))
348-
? Split(
349-
axis: Axis.vertical,
350-
children: [
351-
content,
352-
Padding(
353-
padding: DevToolsScaffold.horizontalPadding,
354-
child: const DebuggerConsole(),
355-
),
356-
],
357-
splitters: [
358-
DebuggerConsole.buildHeader(),
359-
],
360-
initialFractions: const [0.8, 0.2],
361-
)
362-
: content,
363-
bottomNavigationBar: widget.embed ? null : _buildStatusLine(),
344+
child: KeyboardShortcuts(
345+
keyboardShortcuts: _currentScreen.buildKeyboardShortcuts(
346+
context,
347+
),
348+
child: Scaffold(
349+
appBar: widget.embed ? null : _buildAppBar(scaffoldTitle),
350+
body: (serviceManager.connectedAppInitialized &&
351+
!offlineController.offlineMode.value &&
352+
_currentScreen.showConsole(widget.embed))
353+
? Split(
354+
axis: Axis.vertical,
355+
children: [
356+
content,
357+
Padding(
358+
padding: DevToolsScaffold.horizontalPadding,
359+
child: const DebuggerConsole(),
360+
),
361+
],
362+
splitters: [
363+
DebuggerConsole.buildHeader(),
364+
],
365+
initialFractions: const [0.8, 0.2],
366+
)
367+
: content,
368+
bottomNavigationBar: widget.embed ? null : _buildStatusLine(),
369+
),
364370
),
365371
),
366372
);
@@ -495,6 +501,31 @@ class DevToolsScaffoldState extends State<DevToolsScaffold>
495501
}
496502
}
497503

504+
class KeyboardShortcuts extends StatelessWidget {
505+
const KeyboardShortcuts({
506+
@required this.keyboardShortcuts,
507+
@required this.child,
508+
}) : assert(keyboardShortcuts != null),
509+
assert(child != null);
510+
511+
final ShortcutsConfiguration keyboardShortcuts;
512+
final Widget child;
513+
514+
@override
515+
Widget build(BuildContext context) {
516+
if (keyboardShortcuts.isEmpty) {
517+
return child;
518+
}
519+
return Shortcuts(
520+
shortcuts: keyboardShortcuts.shortcuts,
521+
child: Actions(
522+
actions: keyboardShortcuts.actions,
523+
child: child,
524+
),
525+
);
526+
}
527+
}
528+
498529
class SimpleScreen extends Screen {
499530
const SimpleScreen(this.child)
500531
: super(

packages/devtools_app/lib/src/screen.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ abstract class Screen {
6767
/// Whether to show the console for this screen.
6868
bool showConsole(bool embed) => false;
6969

70+
/// Which keyboard shortcuts shoud be enabled for this screen.
71+
ShortcutsConfiguration buildKeyboardShortcuts(BuildContext context) =>
72+
ShortcutsConfiguration.empty();
73+
7074
final String screenId;
7175

7276
/// The user-facing name of the page.
@@ -304,3 +308,19 @@ class BadgePainter extends CustomPainter {
304308
return true;
305309
}
306310
}
311+
312+
class ShortcutsConfiguration {
313+
const ShortcutsConfiguration({
314+
@required this.shortcuts,
315+
@required this.actions,
316+
}) : assert(shortcuts.length == actions.length);
317+
318+
factory ShortcutsConfiguration.empty() {
319+
return ShortcutsConfiguration(shortcuts: {}, actions: {});
320+
}
321+
322+
final Map<ShortcutActivator, Intent> shortcuts;
323+
final Map<Type, Action<Intent>> actions;
324+
325+
bool get isEmpty => shortcuts.isEmpty && actions.isEmpty;
326+
}

0 commit comments

Comments
 (0)