-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Keyboard nav ast node #2391
Keyboard nav ast node #2391
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to refresh to pull in additional changes, so expect further comments.
* Class for an ASTNode. | ||
* @constructor | ||
* @param {!String} type This is the type of the location using | ||
* Blockly.ASTNodes.types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove s on ASTNodes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Changes can be found in cursor_ast_update branch.
Blockly.ASTNode = function(type, location, params) { | ||
|
||
/* | ||
* The type of the location. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add "One of Blockly.ASTNode.types"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Changes can be found in cursor_ast_update branch.
/** | ||
* Object holding different types for an ASTNode. | ||
*/ | ||
Blockly.ASTNode.types = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this up to the top of the file. We usually try to declare constants first so they're easy to find.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Changes can be found in cursor_ast_update branch.
Blockly.ASTNode.createConnectionNode = function(connection) { | ||
var astNode; | ||
if (!connection){return;} | ||
if (connection.type === Blockly.INPUT_VALUE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a difference between an input connection node and an input node? Do we want to enforce using Inputs for this case or silently remap it?
* block. | ||
* @private | ||
*/ | ||
Blockly.ASTNode.prototype.findOutLocationForBlock_ = function(block) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some test cases for this method with notes on how out is expected to traverse the tree.
|
||
switch (this.type_) { | ||
case Blockly.ASTNode.types.WORKSPACE: | ||
var newX = this.wsCoordinate_.x + Blockly.ASTNode.wsMove_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a TODO to limit this. The view is bounded to half a screen beyond the furthest blocks, but there's no easy way to translate that to Workspace coordinates right now (hence TODO).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Changes can be found in cursor_ast_update branch.
/** | ||
* Navigate between stacks of blocks on the workspace. | ||
* @param {?Boolean} forward True to go forward. False to go backwards. | ||
* @return {?Blockly.BlockSvg} The first block of the next stack. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency this should probably return a new ASTNode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Changes can be found in cursor_ast_update branch.
* @return {?Blockly.ASTNode} The ast node holding the next field or connection. | ||
* @private | ||
*/ | ||
Blockly.ASTNode.prototype.findNextForField_ = function(location, parentInput) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be combined with findNextForInput since in both cases you need to iterate through fields and inputs until you find a valid location or hit the end of the block. Right now your code will go from an input to a field, then get stuck on the last field in that input.
You should probably add a test that iterates across a multi-input multi-field block using next and previous to make sure all editable elements are reachable.
* @return {?Blockly.ASTNode} The ast node holding the previous input or field. | ||
* @private | ||
*/ | ||
Blockly.ASTNode.prototype.findPrevForField_ = function(location, parentInput) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto about combining this with findPrevForInput_
break; | ||
|
||
case Blockly.ASTNode.types.BLOCK: | ||
var nextConnection = this.location_.nextConnection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
next connection may not exist.
break; | ||
|
||
case Blockly.ASTNode.types.PREVIOUS: | ||
var output = this.location_.outputConnection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a previous, so there will never be an output. Also, this case should be identical to OUTPUT since in both cases next should go to the block itself.
break; | ||
|
||
case Blockly.ASTNode.types.NEXT: | ||
if (this.location_.targetBlock()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just use this.location_.targetConnection since that will either be null or the previous connection on the next block.
Blockly.ASTNode.prototype.next = function() { | ||
var newAstNode = null; | ||
|
||
switch (this.type_) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For each case in next/prev/in/out please add a comment about what you expect the returned node in the tree to be. For example, "If on a field next should return the next editable field or input connection on the block. It will not move between blocks and it will return null if this is the last valid field or input on the block."
* Find the element one level below and all the way to the left of the current | ||
* location. | ||
* @return {?Blockly.ASTNode} An ast node that wraps the next field, connection, | ||
* workspace, or block. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returns null if there is nothing below this node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Changes can be found in cursor_ast_update branch.
break; | ||
|
||
case Blockly.ASTNode.types.OUTPUT: | ||
var sourceBlock = this.location_.sourceBlock_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In our current tree diagram there is no previous from an output. you'd have to go up a level.
|
||
case Blockly.ASTNode.types.OUTPUT: | ||
var sourceBlock = this.location_.sourceBlock_; | ||
if (sourceBlock && sourceBlock.previousConnection) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A block with an output can't have a previous.
if (output) { | ||
newAstNode = Blockly.ASTNode.createConnectionNode(output); | ||
} else { | ||
var prevConnection = this.location_.previousConnection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prev may be null.
break; | ||
|
||
case Blockly.ASTNode.types.PREVIOUS: | ||
var prevBlock = this.location_.targetBlock(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
location_.targetConnection
*/ | ||
Blockly.ASTNode.prototype.prev = function() { | ||
if (!this.location_) {return null;} | ||
var newAstNode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and elsewhere you should explicitly initialize this to null. JS initializes things to undefined, which is not what we're promising to return.
The basics
The details
Resolves
Proposed Changes
Adds an AST Node for keyboard navigation. An AST Node will be able to find the next, prev, in, or out node from its current location.
Reason for Changes
To create a better keyboard navigation api.
Test Coverage
Tests are written in mocha.
Tested on:
Additional Information