Adding Blockly.Xml.appendDomToWorkspace() (#962)

This is a copy (with additional comments) of PR #822 (and also #961) by @qnoirhomme with unrelated files removed. See #822 for full review.
This commit is contained in:
Andrew n marshall
2017-03-03 08:40:00 -08:00
committed by GitHub
parent ef34ee5433
commit 6e1ffe09c2
3 changed files with 112 additions and 0 deletions

View File

@@ -279,6 +279,7 @@ Blockly.Xml.textToDom = function(text) {
* Decode an XML DOM and create blocks on the workspace.
* @param {!Element} xml XML DOM.
* @param {!Blockly.Workspace} workspace The workspace.
* @return {Array.<string>} An array containing new block ids.
*/
Blockly.Xml.domToWorkspace = function(xml, workspace) {
if (xml instanceof Blockly.Workspace) {
@@ -292,6 +293,7 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
if (workspace.RTL) {
width = workspace.getWidth();
}
var newBlockIds = []; // A list of block ids added by this call.
Blockly.Field.startCache();
// Safari 7.1.3 is known to provide node lists with extra references to
// children beyond the lists' length. Trust the length, do not use the
@@ -315,6 +317,7 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
// that means an undo is in progress. Such a block is expected
// to be moved to a nested destination in the next operation.
var block = Blockly.Xml.domToBlock(xmlChild, workspace);
newBlockIds.push(block.id);
var blockX = parseInt(xmlChild.getAttribute('x'), 10);
var blockY = parseInt(xmlChild.getAttribute('y'), 10);
if (!isNaN(blockX) && !isNaN(blockY)) {
@@ -334,6 +337,61 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
if (workspace.setResizesEnabled) {
workspace.setResizesEnabled(true);
}
return newBlockIds;
};
/**
* Decode an XML DOM and create blocks on the workspace. Position the new
* blocks immediately below prior blocks, aligned by their starting edge.
* @param {!Element} xml The XML DOM.
* @param {!Blockly.Workspace} workspace The workspace to add to.
* @return {Array.<string>} An array containing new block ids.
*/
Blockly.Xml.appendDomToWorkspace = function(xml, workspace) {
var bbox; //bounding box of the current blocks
// first check if we have a workspaceSvg otherwise the block have no shape
// and the position does not matter
if (workspace.hasOwnProperty('scale')) {
var savetab = Blockly.BlockSvg.TAB_WIDTH;
try {
Blockly.BlockSvg.TAB_WIDTH = 0;
var bbox = workspace.getBlocksBoundingBox();
} finally {
Blockly.BlockSvg.TAB_WIDTH = savetab;
}
}
// load the new blocks into the workspace and get the ids of the new blocks
var newBlockIds = Blockly.Xml.domToWorkspace(xml,workspace);
if (bbox && bbox.height) { // check if any previous block
var offsetY = 0; // offset to add to y of the new block
var offsetX = 0;
var farY = bbox.y + bbox.height; //bottom position
var topX = bbox.x; // x of bounding box
// check position of the new blocks
var newX = Infinity; // x of top corner
var newY = Infinity; // y of top corner
for (var i = 0; i < newBlockIds.length; i++) {
var blockXY = workspace.getBlockById(newBlockIds[i]).getRelativeToSurfaceXY();
if (blockXY.y < newY) {
newY = blockXY.y;
}
if (blockXY.x < newX) { //if we align also on x
newX = blockXY.x;
}
}
offsetY = farY - newY + Blockly.BlockSvg.SEP_SPACE_Y;
offsetX = topX - newX;
// move the new blocks to append them at the bottom
var width; // Not used in LTR.
if (workspace.RTL) {
width = workspace.getWidth();
}
for (var i = 0; i < newBlockIds.length; i++) {
var block = workspace.getBlockById(newBlockIds[i]);
block.moveBy(workspace.RTL ? width - offsetX : offsetX, offsetY);
}
}
return newBlockIds;
};
/**

View File

@@ -90,3 +90,34 @@ function test_domToPrettyText() {
assertEquals('Round trip', XML_TEXT.replace(/\s+/g, ''),
text.replace(/\s+/g, ''));
}
/**
* Tests the that appendDomToWorkspace works in a headless mode.
* Also see test_appendDomToWorkspace() in workspace_svg_test.js.
*/
unction test_appendDomToWorkspace() {
Blockly.Blocks.test_block = {
init: function() {
this.jsonInit({
message0: 'test',
});
}
};
try {
var dom = Blockly.Xml.textToDom(
'<xml xmlns="http://www.w3.org/1999/xhtml">' +
' <block type="test_block" inline="true" x="21" y="23">' +
' </block>' +
'</xml>');
var workspace = new Blockly.Workspace();
Blockly.Xml.appendDomToWorkspace(dom, workspace);
assertEquals('Block count', 1, workspace.getAllBlocks().length);
var newBlockIds = Blockly.Xml.appendDomToWorkspace(dom, workspace);
assertEquals('Block count', 2, workspace.getAllBlocks().length);
assertEquals('Number of new block ids',1,newBlockIds.length);
} finally {
delete Blockly.Blocks.test_block;
workspace.dispose();
}
}

View File

@@ -70,3 +70,26 @@ function test_flatWorkspace() {
workspace.dispose();
}
}
/** Tests the alignment of appendDomToWorkspace with WorkspaceSvg. */
function test_appendDomToWorkspace() {
var workspace = helper_createWorkspaceWithToolbox();
try {
var dom = Blockly.Xml.textToDom(
'<xml xmlns="http://www.w3.org/1999/xhtml">' +
' <block type="math_random_float" inline="true" x="21" y="23">' +
' </block>' +
'</xml>');
Blockly.Xml.appendDomToWorkspace(dom, workspace);
assertEquals('Block count', 1, workspace.getAllBlocks().length);
Blockly.Xml.appendDomToWorkspace(dom, workspace);
assertEquals('Block count', 2, workspace.getAllBlocks().length);
var blocks = workspace.getAllBlocks();
assertEquals('Block 1 position x',21,blocks[0].getRelativeToSurfaceXY().x);
assertEquals('Block 1 position y',23,blocks[0].getRelativeToSurfaceXY().y);
assertEquals('Block 2 position x',21,blocks[1].getRelativeToSurfaceXY().x);
assertEquals('Block 2 position y',23 + blocks[0].getHeightWidth().height + Blockly.BlockSvg.SEP_SPACE_Y,blocks[1].getRelativeToSurfaceXY().y);
} finally {
workspace.dispose();
}
}