Add ordered option to getDescendants and all uses.

"
This commit is contained in:
Rachel Fenichel 2018-05-16 12:51:41 -07:00
parent e91e29c8d8
commit af4060c75b
16 changed files with 83 additions and 38 deletions

View file

@ -509,12 +509,30 @@ Blockly.Block.prototype.getRootBlock = function() {
/**
* Find all the blocks that are directly nested inside this one.
* Includes value and block inputs, as well as any following statement.
* Includes value and statement inputs, as well as any following statement.
* Excludes any connection on an output tab or any preceding statement.
* Blocks are optionally sorted by position; top to bottom.
* @param {boolean} ordered Sort the list if true.
* @return {!Array.<!Blockly.Block>} Array of blocks.
*/
Blockly.Block.prototype.getChildren = function() {
return this.childBlocks_;
Blockly.Block.prototype.getChildren = function(ordered) {
if (!ordered) {
return this.childBlocks_;
}
var blocks = [];
for (var i = 0, input; input = this.inputList[i]; i++) {
if (input.connection) {
var child = input.connection.targetBlock();
if (child) {
blocks.push(child);
}
}
}
var next = this.getNextBlock();
if (next) {
blocks.push(next);
}
return blocks;
};
/**
@ -556,16 +574,20 @@ Blockly.Block.prototype.setParent = function(newParent) {
/**
* Find all the blocks that are directly or indirectly nested inside this one.
* Includes this block in the list.
* Includes value and block inputs, as well as any following statements.
* Includes value and statement inputs, as well as any following statements.
* Excludes any connection on an output tab or any preceding statements.
* Blocks are optionally sorted by position, top to bottom.
* @param {boolean} ordered Sort the list if true.
* @param {boolean=} opt_ignoreShadows If set, don't include shadow blocks.
* @return {!Array.<!Blockly.Block>} Flattened array of blocks.
*/
Blockly.Block.prototype.getDescendants = function(opt_ignoreShadows) {
Blockly.Block.prototype.getDescendants = function(ordered, opt_ignoreShadows) {
var blocks = [this];
for (var child, x = 0; child = this.childBlocks_[x]; x++) {
var childBlocks = this.getChildren(ordered);
for (var child, i = 0; child = childBlocks[i]; i++) {
if (!opt_ignoreShadows || !child.isShadow_) {
blocks.push.apply(blocks, child.getDescendants(opt_ignoreShadows));
blocks.push.apply(
blocks, child.getDescendants(ordered, opt_ignoreShadows));
}
}
return blocks;

View file

@ -135,7 +135,7 @@ Blockly.BlockDragger.prototype.dispose = function() {
Blockly.BlockDragger.initIconData_ = function(block) {
// Build a list of icons that need to be moved and where they started.
var dragIconData = [];
var descendants = block.getDescendants();
var descendants = block.getDescendants(false);
for (var i = 0, descendant; descendant = descendants[i]; i++) {
var icons = descendant.getIcons();
for (var j = 0; j < icons.length; j++) {

View file

@ -42,7 +42,6 @@ goog.require('goog.Timer');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.math.Coordinate');
goog.require('goog.userAgent');
/**
@ -551,7 +550,7 @@ Blockly.BlockSvg.prototype.setCollapsed = function(collapsed) {
var COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT';
if (collapsed) {
var icons = this.getIcons();
for (i = 0; i < icons.length; i++) {
for (var i = 0; i < icons.length; i++) {
icons[i].setVisible(false);
}
var text = this.toString(Blockly.COLLAPSE_CHARS);

View file

@ -214,12 +214,13 @@ Blockly.ContextMenu.callbackFactory = function(block, xml) {
*/
Blockly.ContextMenu.blockDeleteOption = function(block) {
// Option to delete this block but not blocks lower in the stack.
// Count the number of blocks that are nested in this block.
var descendantCount = block.getDescendants(true).length;
// Count the number of blocks that are nested in this block,
// ignoring shadows and without ordering.
var descendantCount = block.getDescendants(false, true).length;
var nextBlock = block.getNextBlock();
if (nextBlock) {
// Blocks in the current stack would survive this block's deletion.
descendantCount -= nextBlock.getDescendants(true).length;
descendantCount -= nextBlock.getDescendants(false, true).length;
}
var deleteOption = {
text: descendantCount == 1 ? Blockly.Msg.DELETE_BLOCK :

View file

@ -299,7 +299,7 @@ Blockly.Events.setGroup = function(state) {
*/
Blockly.Events.getDescendantIds_ = function(block) {
var ids = [];
var descendants = block.getDescendants();
var descendants = block.getDescendants(false);
for (var i = 0, descendant; descendant = descendants[i]; i++) {
ids[i] = descendant.id;
}
@ -368,7 +368,7 @@ Blockly.Events.disableOrphans = function(event) {
var block = workspace.getBlockById(event.blockId);
if (block) {
if (block.getParent() && !block.getParent().disabled) {
var children = block.getDescendants();
var children = block.getDescendants(false);
for (var i = 0, child; child = children[i]; i++) {
child.setDisabled(false);
}

View file

@ -328,7 +328,7 @@ Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
for (var i = 0, item; item = contents[i]; i++) {
if (item.type == 'block') {
var block = item.block;
var allBlocks = block.getDescendants();
var allBlocks = block.getDescendants(false);
for (var j = 0, child; child = allBlocks[j]; j++) {
// Mark blocks as being inside a flyout. This is used to detect and
// prevent the closure of the flyout if the user right-clicks on such a

View file

@ -437,7 +437,7 @@ Blockly.VerticalFlyout.prototype.layout_ = function(contents, gaps) {
for (var i = 0, item; item = contents[i]; i++) {
if (item.type == 'block') {
var block = item.block;
var allBlocks = block.getDescendants();
var allBlocks = block.getDescendants(false);
for (var j = 0, child; child = allBlocks[j]; j++) {
// Mark blocks as being inside a flyout. This is used to detect and
// prevent the closure of the flyout if the user right-clicks on such a

View file

@ -142,7 +142,7 @@ Blockly.Generator.prototype.prefixLines = function(text, prefix) {
*/
Blockly.Generator.prototype.allNestedComments = function(block) {
var comments = [];
var blocks = block.getDescendants();
var blocks = block.getDescendants(true);
for (var i = 0; i < blocks.length; i++) {
var comment = blocks[i].getCommentText();
if (comment) {
@ -378,9 +378,11 @@ Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) {
* Hook for code to run before code generation starts.
* Subclasses may override this, e.g. to initialise the database of variable
* names.
* @param {!Blockly.Workspace} workspace Workspace to generate code from.
* @param {!Blockly.Workspace} _workspace Workspace to generate code from.
*/
Blockly.Generator.prototype.init = undefined;
Blockly.Generator.prototype.init = function(_workspace) {
// Optionally override
};
/**
* Common tasks for generating code from blocks. This is called from
@ -388,12 +390,15 @@ Blockly.Generator.prototype.init = undefined;
* Subclasses may override this, e.g. to generate code for statements following
* the block, or to handle comments for the specified block and any connected
* value blocks.
* @param {!Blockly.Block} block The current block.
* @param {!Blockly.Block} _block The current block.
* @param {string} code The JavaScript code created for this block.
* @return {string} JavaScript code with comments and subsequent blocks added.
* @private
*/
Blockly.Generator.prototype.scrub_ = undefined;
Blockly.Generator.prototype.scrub_ = function(_block, code) {
// Optionally override
return code;
};
/**
* Hook for code to run at end of code generation.
@ -402,7 +407,10 @@ Blockly.Generator.prototype.scrub_ = undefined;
* @param {string} code Generated code.
* @return {string} Completed code.
*/
Blockly.Generator.prototype.finish = undefined;
Blockly.Generator.prototype.finish = function(code) {
// Optionally override
return code;
};
/**
* Naked values are top-level blocks with outputs that aren't plugged into
@ -412,4 +420,7 @@ Blockly.Generator.prototype.finish = undefined;
* @param {string} line Line of generated code.
* @return {string} Legal line of code.
*/
Blockly.Generator.prototype.scrubNakedValue = undefined;
Blockly.Generator.prototype.scrubNakedValue = function(line) {
// Optionally override
return line;
};

View file

@ -255,7 +255,7 @@ Blockly.Mutator.prototype.setVisible = function(visible) {
}
this.rootBlock_ = this.block_.decompose(this.workspace_);
var blocks = this.rootBlock_.getDescendants();
var blocks = this.rootBlock_.getDescendants(false);
for (var i = 0, child; child = blocks[i]; i++) {
child.render();
}

View file

@ -288,7 +288,7 @@ Blockly.Procedures.getCallers = function(name, ws, definitionRoot,
if (block.id == definitionRoot.id && !allowRecursive) {
continue;
}
allBlocks.push.apply(allBlocks, block.getDescendants());
allBlocks.push.apply(allBlocks, block.getDescendants(false));
}
var callers = [];

View file

@ -280,7 +280,7 @@ Blockly.RenderedConnection.prototype.setHidden = function(hidden) {
Blockly.RenderedConnection.prototype.hideAll = function() {
this.setHidden(true);
if (this.targetConnection) {
var blocks = this.targetBlock().getDescendants();
var blocks = this.targetBlock().getDescendants(false);
for (var i = 0; i < blocks.length; i++) {
var block = blocks[i];
// Hide all connections of all children.

View file

@ -71,7 +71,7 @@ Blockly.scratchBlocksUtils.encodeEntities = function(rawStr) {
* @package
*/
Blockly.scratchBlocksUtils.changeObscuredShadowIds = function(block) {
var blocks = block.getDescendants();
var blocks = block.getDescendants(false);
for (var i = blocks.length - 1; i >= 0; i--) {
var descendant = blocks[i];
for (var j = 0; j < descendant.inputList.length; j++) {

View file

@ -54,7 +54,7 @@ Blockly.Variables.allUsedVariables = function(root) {
var blocks;
if (root instanceof Blockly.Block) {
// Root is Block.
blocks = root.getDescendants();
blocks = root.getDescendants(false);
} else if (root instanceof Blockly.Workspace ||
root instanceof Blockly.WorkspaceSvg) {
// Root is Workspace.

View file

@ -260,19 +260,31 @@ Blockly.Workspace.prototype.getTopComments = function(ordered) {
};
/**
* Find all blocks in workspace. No particular order.
* Find all blocks in workspace. Blocks are optionally sorted
* by position; top to bottom (with slight LTR or RTL bias).
* @param {boolean} ordered Sort the list if true.
* @return {!Array.<!Blockly.Block>} Array of blocks.
*/
Blockly.Workspace.prototype.getAllBlocks = function() {
var blocks = this.getTopBlocks(false);
for (var i = 0; i < blocks.length; i++) {
blocks.push.apply(blocks, blocks[i].getChildren());
Blockly.Workspace.prototype.getAllBlocks = function(ordered) {
if (ordered) {
// Slow, but ordered.
var topBlocks = this.getTopBlocks(true);
var blocks = [];
for (var i = 0; i < topBlocks.length; i++) {
blocks.push.apply(blocks, topBlocks[i].getDescendants(true));
}
} else {
// Fast, but in no particular order.
var blocks = this.getTopBlocks(false);
for (var i = 0; i < blocks.length; i++) {
blocks.push.apply(blocks, blocks[i].getChildren(false));
}
}
return blocks;
};
/**
* Dispose of all blocks in workspace.
* Dispose of all blocks and comments in workspace.
*/
Blockly.Workspace.prototype.clear = function() {
this.isClearing = true;

View file

@ -1493,7 +1493,7 @@ Blockly.WorkspaceSvg.buildDeleteList_ = function(topBlocks) {
var deleteList = [];
function addDeletableBlocks(block) {
if (block.isDeletable()) {
deleteList = deleteList.concat(block.getDescendants());
deleteList = deleteList.concat(block.getDescendants(false));
} else {
var children = block.getChildren();
for (var i = 0; i < children.length; i++) {

View file

@ -541,7 +541,7 @@ Blockly.Xml.domToBlock = function(xmlBlock, workspace) {
try {
var topBlock = Blockly.Xml.domToBlockHeadless_(xmlBlock, workspace);
// Generate list of all blocks.
var blocks = topBlock.getDescendants();
var blocks = topBlock.getDescendants(false);
if (workspace.rendered) {
// Hide connections to speed up assembly.
topBlock.setConnectionsHidden(true);
@ -761,7 +761,7 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
}
if (xmlBlock.nodeName.toLowerCase() == 'shadow') {
// Ensure all children are also shadows.
var children = block.getChildren();
var children = block.getChildren(false);
for (var i = 0, child; child = children[i]; i++) {
goog.asserts.assert(
child.isShadow(), 'Shadow block not allowed non-shadow child.');