Action update (#3389)

Make it easier for users to create new shortcuts
This commit is contained in:
alschmiedt
2019-11-08 13:51:22 -08:00
committed by GitHub
parent 36cc9a2e89
commit b7b262efd5
5 changed files with 138 additions and 78 deletions

View File

@@ -660,8 +660,12 @@ Blockly.BlockSvg.prototype.setCollapsed = function(collapsed) {
Blockly.BlockSvg.prototype.tab = function(start, forward) {
var tabCursor = new Blockly.TabNavigateCursor();
tabCursor.setCurNode(Blockly.ASTNode.createFieldNode(start));
var action = forward ?
Blockly.navigation.ACTION_NEXT : Blockly.navigation.ACTION_PREVIOUS;
var nextNode = forward ? tabCursor.next() : tabCursor.prev();
tabCursor.onBlocklyAction(action);
var nextNode = tabCursor.getCurNode();
if (nextNode) {
var nextField = /** @type {!Blockly.Field} */ (nextNode.getLocation());
nextField.showEditor();

View File

@@ -847,3 +847,15 @@ Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) {
block.moveBy(finalOffset.x, finalOffset.y);
return block;
};
/**
* Handles the given action.
* This is only triggered when keyboard accessibility mode is enabled.
* @param {!Blockly.Action} action The action to be handled.
* @return {boolean} True if the flyout handled the action, false otherwise.
* @package
*/
Blockly.Flyout.prototype.onBlocklyAction = function(action) {
var cursor = this.workspace_.getCursor();
return cursor.onBlocklyAction(action);
};

View File

@@ -24,6 +24,7 @@
goog.provide('Blockly.Cursor');
goog.require('Blockly.navigation');
/**
* Class for a cursor.
@@ -94,10 +95,42 @@ Blockly.Cursor.prototype.hide = function() {
}
};
/**
* Handles the given action.
* This is only triggered when keyboard navigation is enabled.
* @param {!Blockly.Action} action The action to be handled.
* @return {boolean} True if the action has been handled, false otherwise.
*/
Blockly.Cursor.prototype.onBlocklyAction = function(action) {
// If we are on a field give it the option to handle the action
if (this.getCurNode() &&
this.getCurNode().getType() === Blockly.ASTNode.types.FIELD &&
this.getCurNode().getLocation().onBlocklyAction(action)) {
return true;
}
switch (action.name) {
case Blockly.navigation.actionNames.PREVIOUS:
this.prev();
return true;
case Blockly.navigation.actionNames.OUT:
this.out();
return true;
case Blockly.navigation.actionNames.NEXT:
this.next();
return true;
case Blockly.navigation.actionNames.IN:
this.in();
return true;
default:
return false;
}
};
/**
* Find the next connection, field, or block.
* @return {Blockly.ASTNode} The next element, or null if the current node is
* not set or there is no next value.
* @protected
*/
Blockly.Cursor.prototype.next = function() {
var curNode = this.getCurNode();
@@ -122,6 +155,7 @@ Blockly.Cursor.prototype.next = function() {
* Find the in connection or field.
* @return {Blockly.ASTNode} The in element, or null if the current node is
* not set or there is no in value.
* @protected
*/
Blockly.Cursor.prototype.in = function() {
var curNode = this.getCurNode();
@@ -146,6 +180,7 @@ Blockly.Cursor.prototype.in = function() {
* Find the previous connection, field, or block.
* @return {Blockly.ASTNode} The previous element, or null if the current node
* is not set or there is no previous value.
* @protected
*/
Blockly.Cursor.prototype.prev = function() {
var curNode = this.getCurNode();
@@ -170,6 +205,7 @@ Blockly.Cursor.prototype.prev = function() {
* Find the out connection, field, or block.
* @return {Blockly.ASTNode} The out element, or null if the current node is
* not set or there is no out value.
* @protected
*/
Blockly.Cursor.prototype.out = function() {
var curNode = this.getCurNode();

View File

@@ -39,6 +39,26 @@ Blockly.FlyoutCursor = function() {
};
Blockly.utils.object.inherits(Blockly.FlyoutCursor, Blockly.Cursor);
/**
* Handles the given action.
* This is only triggered when keyboard navigation is enabled.
* @param {!Blockly.Action} action The action to be handled.
* @return {boolean} True if the action has been handled, false otherwise.
* @override
*/
Blockly.FlyoutCursor.prototype.onBlocklyAction = function(action) {
switch (action.name) {
case Blockly.navigation.actionNames.PREVIOUS:
this.prev();
return true;
case Blockly.navigation.actionNames.NEXT:
this.next();
return true;
default:
return false;
}
};
/**
* Find the next connection, field, or block.
* @return {Blockly.ASTNode} The next element, or null if the current node is

View File

@@ -749,8 +749,8 @@ Blockly.navigation.onKeyPress = function(e) {
};
/**
* Execute any actions on the flyout, workspace, or toolbox that correspond to
* the given action.
* Decides which actions to handle depending on keyboard navigation and readonly
* states.
* @param {!Blockly.Action} action The current action.
* @return {boolean} True if the action has been handled, false otherwise.
*/
@@ -775,92 +775,44 @@ Blockly.navigation.onBlocklyAction = function(action) {
/**
* Handles the action or dispatches to the appropriate action handler.
* @param {!Blockly.Action} action The current action
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.handleActions_ = function(action) {
var workspace = Blockly.getMainWorkspace();
if (action.name === Blockly.navigation.actionNames.TOGGLE_KEYBOARD_NAV) {
if (action.name == Blockly.navigation.actionNames.TOOLBOX ||
Blockly.navigation.currentState_ == Blockly.navigation.STATE_TOOLBOX) {
return Blockly.navigation.toolboxOnAction_(action);
} else if (action.name == Blockly.navigation.actionNames.TOGGLE_KEYBOARD_NAV) {
Blockly.navigation.disableKeyboardAccessibility();
return true;
} else if (action.name === Blockly.navigation.actionNames.TOOLBOX) {
if (!workspace.getToolbox()) {
Blockly.navigation.focusFlyout_();
} else {
Blockly.navigation.focusToolbox_();
}
return true;
} else if (Blockly.navigation.currentState_ === Blockly.navigation.STATE_WS) {
var curNode = workspace.getCursor().getCurNode();
var actionHandled = false;
if (curNode && curNode.getType() === Blockly.ASTNode.types.FIELD) {
actionHandled = curNode.getLocation().onBlocklyAction(action);
}
if (!actionHandled) {
actionHandled = Blockly.navigation.workspaceOnAction_(action);
}
return actionHandled;
} else if (Blockly.navigation.currentState_ === Blockly.navigation.STATE_FLYOUT) {
} if (Blockly.navigation.currentState_ == Blockly.navigation.STATE_WS) {
return Blockly.navigation.workspaceOnAction_(action);
} else if (Blockly.navigation.currentState_ == Blockly.navigation.STATE_FLYOUT) {
return Blockly.navigation.flyoutOnAction_(action);
} else if (Blockly.navigation.currentState_ === Blockly.navigation.STATE_TOOLBOX) {
return Blockly.navigation.toolboxOnAction_(action);
}
return false;
};
/**
* Handle all actions performed on the workspace.
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.workspaceOnAction_ = function(action) {
var workspace = Blockly.getMainWorkspace();
switch (action.name) {
case Blockly.navigation.actionNames.PREVIOUS:
workspace.getCursor().prev();
return true;
case Blockly.navigation.actionNames.OUT:
workspace.getCursor().out();
return true;
case Blockly.navigation.actionNames.NEXT:
workspace.getCursor().next();
return true;
case Blockly.navigation.actionNames.IN:
workspace.getCursor().in();
return true;
case Blockly.navigation.actionNames.INSERT:
Blockly.navigation.modify_();
return true;
case Blockly.navigation.actionNames.MARK:
Blockly.navigation.handleEnterForWS_();
return true;
case Blockly.navigation.actionNames.DISCONNECT:
Blockly.navigation.disconnectBlocks_();
return true;
default:
return false;
}
};
/**
* Handle all actions performed on the flyout.
* Handles the given action for the flyout.
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.flyoutOnAction_ = function(action) {
var workspace = Blockly.getMainWorkspace();
var toolbox = workspace.getToolbox();
var flyout = toolbox ? toolbox.flyout_ : workspace.getFlyout();
if (flyout && flyout.onBlocklyAction(action)) {
return true;
}
switch (action.name) {
case Blockly.navigation.actionNames.PREVIOUS:
Blockly.navigation.getFlyoutCursor_().prev();
return true;
case Blockly.navigation.actionNames.OUT:
Blockly.navigation.focusToolbox_();
return true;
case Blockly.navigation.actionNames.NEXT:
Blockly.navigation.getFlyoutCursor_().next();
return true;
case Blockly.navigation.actionNames.MARK:
Blockly.navigation.insertFromFlyout();
return true;
@@ -873,24 +825,60 @@ Blockly.navigation.flyoutOnAction_ = function(action) {
};
/**
* Handle all actions performeed on the toolbox.
* Handles the given action for the toolbox.
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.toolboxOnAction_ = function(action) {
if (action.name === Blockly.navigation.actionNames.EXIT) {
Blockly.navigation.focusWorkspace_();
return true;
}
var toolbox = Blockly.getMainWorkspace().getToolbox();
var handled = toolbox.onBlocklyAction(action);
if (!handled && action.name === Blockly.navigation.actionNames.IN) {
Blockly.navigation.focusFlyout_();
var workspace = Blockly.getMainWorkspace();
var toolbox = workspace.getToolbox();
var handled = toolbox ? toolbox.onBlocklyAction(action) : false;
if (handled) {
return true;
}
return handled;
if (action.name === Blockly.navigation.actionNames.TOOLBOX) {
if (!workspace.getToolbox()) {
Blockly.navigation.focusFlyout_();
} else {
Blockly.navigation.focusToolbox_();
}
return true;
} else if (action.name === Blockly.navigation.actionNames.IN) {
Blockly.navigation.focusFlyout_();
return true;
} else if (action.name === Blockly.navigation.actionNames.EXIT) {
Blockly.navigation.focusWorkspace_();
return true;
}
return false;
};
/**
* Handles the given action for the workspace.
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.workspaceOnAction_ = function(action) {
if (Blockly.getMainWorkspace().getCursor().onBlocklyAction(action)) {
return true;
}
switch (action.name) {
case Blockly.navigation.actionNames.INSERT:
Blockly.navigation.modify_();
return true;
case Blockly.navigation.actionNames.MARK:
Blockly.navigation.handleEnterForWS_();
return true;
case Blockly.navigation.actionNames.DISCONNECT:
Blockly.navigation.disconnectBlocks_();
return true;
default:
return false;
}
};
/**