1111 */
1212
1313import './gesture_monkey_patch' ;
14+ import './toolbox_monkey_patch' ;
1415
1516import * as Blockly from 'blockly/core' ;
1617import {
@@ -36,6 +37,16 @@ const createSerializedKey = ShortcutRegistry.registry.createSerializedKey.bind(
3637 ShortcutRegistry . registry ,
3738) ;
3839
40+ /** Represents the current focus mode of the navigation controller. */
41+ enum NAVIGATION_FOCUS_MODE {
42+ /** Indicates that no interactive elements of Blockly currently have focus. */
43+ NONE = 'none' ,
44+ /** Indicates that the toolbox currently has focus. */
45+ TOOLBOX = 'toolbox' ,
46+ /** Indicates that the main workspace currently has focus. */
47+ WORKSPACE = 'workspace' ,
48+ }
49+
3950/**
4051 * Class for registering shortcuts for keyboard navigation.
4152 */
@@ -65,7 +76,7 @@ export class NavigationController {
6576 this . canCurrentlyEdit . bind ( this ) ,
6677 ) ;
6778
68- hasNavigationFocus : boolean = false ;
79+ navigationFocus : NAVIGATION_FOCUS_MODE = NAVIGATION_FOCUS_MODE . NONE ;
6980
7081 /**
7182 * Original Toolbox.prototype.onShortcut method, saved by
@@ -156,18 +167,40 @@ export class NavigationController {
156167 }
157168
158169 /**
159- * Sets whether the navigation controller has focus. This will enable keyboard
160- * navigation if focus is now gained. Additionally, the cursor may be reset if
161- * it hasn't already been positioned in the workspace.
170+ * Sets whether the navigation controller has toolbox focus and will enable
171+ * keyboard navigation in the toolbox.
172+ *
173+ * If the workspace doesn't have a toolbox, this function is a no-op.
162174 *
163- * @param workspace the workspace that now has input focus.
175+ * @param workspace the workspace that now has toolbox input focus.
164176 * @param isFocused whether the environment has browser focus.
165177 */
166- setHasFocus ( workspace : WorkspaceSvg , isFocused : boolean ) {
167- this . hasNavigationFocus = isFocused ;
178+ updateToolboxFocus ( workspace : WorkspaceSvg , isFocused : boolean ) {
179+ if ( ! workspace . getToolbox ( ) ) return ;
180+ if ( isFocused ) {
181+ this . navigation . focusToolbox ( workspace ) ;
182+ this . navigationFocus = NAVIGATION_FOCUS_MODE . TOOLBOX ;
183+ } else {
184+ this . navigation . blurToolbox ( workspace ) ;
185+ this . navigationFocus = NAVIGATION_FOCUS_MODE . NONE ;
186+ }
187+ }
188+
189+ /**
190+ * Sets whether the navigation controller has workspace focus. This will
191+ * enable keyboard navigation within the workspace. Additionally, the cursor
192+ * may be reset if it hasn't already been positioned in the workspace.
193+ *
194+ * @param workspace the workspace that now has workspace input focus.
195+ * @param isFocused whether the environment has browser focus.
196+ */
197+ updateWorkspaceFocus ( workspace : WorkspaceSvg , isFocused : boolean ) {
168198 if ( isFocused ) {
169199 this . navigation . focusWorkspace ( workspace , true ) ;
200+ this . navigationFocus = NAVIGATION_FOCUS_MODE . WORKSPACE ;
170201 } else {
202+ this . navigationFocus = NAVIGATION_FOCUS_MODE . NONE ;
203+
171204 // Hide cursor to indicate lost focus. Also, mark the current node so that
172205 // it can be properly restored upon returning to the workspace.
173206 this . navigation . markAtCursor ( workspace ) ;
@@ -179,15 +212,26 @@ export class NavigationController {
179212 * Determines whether keyboard navigation should be allowed based on the
180213 * current state of the workspace.
181214 *
182- * A return value of 'true' generally indicates that the workspace both has
183- * enabled keyboard navigation and is currently in a state (e.g. focus) that
184- * can support keyboard navigation.
215+ * A return value of 'true' generally indicates that either the workspace or
216+ * toolbox both has enabled keyboard navigation and is currently in a state
217+ * (e.g. focus) that can support keyboard navigation.
185218 *
186219 * @param workspace the workspace in which keyboard navigation may be allowed.
187220 * @returns whether keyboard navigation is currently allowed.
188221 */
189222 private canCurrentlyNavigate ( workspace : WorkspaceSvg ) {
190- return workspace . keyboardAccessibilityMode && this . hasNavigationFocus ;
223+ return this . canCurrentlyNavigateInToolbox ( workspace ) ||
224+ this . canCurrentlyNavigateInWorkspace ( workspace ) ;
225+ }
226+
227+ private canCurrentlyNavigateInToolbox ( workspace : WorkspaceSvg ) {
228+ return workspace . keyboardAccessibilityMode &&
229+ this . navigationFocus == NAVIGATION_FOCUS_MODE . TOOLBOX ;
230+ }
231+
232+ private canCurrentlyNavigateInWorkspace ( workspace : WorkspaceSvg ) {
233+ return workspace . keyboardAccessibilityMode &&
234+ this . navigationFocus == NAVIGATION_FOCUS_MODE . WORKSPACE ;
191235 }
192236
193237 /**
0 commit comments