mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-06-15 14:21:45 -04:00
Add ordered option to getDescendants and all uses.
"
This commit is contained in:
parent
e91e29c8d8
commit
af4060c75b
16 changed files with 83 additions and 38 deletions
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 = [];
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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.');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue