From 799835943a7a79d0cd1488377173cdbd673eacb0 Mon Sep 17 00:00:00 2001 From: Neil Fraser Date: Tue, 6 Oct 2015 18:09:27 -0700 Subject: [PATCH] Shadow Blocks --- blockly_compressed.js | 54 ++++++------ core/block.js | 21 ++++- core/block_svg.js | 18 ++-- core/connection.js | 95 +++++++++++++++------ core/xml.js | 36 ++++++-- tests/playground.html | 194 ++++++++++++++++++++++++++++++------------ 6 files changed, 303 insertions(+), 115 deletions(-) diff --git a/blockly_compressed.js b/blockly_compressed.js index 71da84a84..889051b3d 100644 --- a/blockly_compressed.js +++ b/blockly_compressed.js @@ -879,23 +879,24 @@ this.foreignObject_.appendChild(a);Blockly.bindEvent_(this.textarea_,"mouseup",t Blockly.Comment.prototype.resizeBubble_=function(){var a=this.bubble_.getBubbleSize(),b=2*Blockly.Bubble.BORDER_WIDTH;this.foreignObject_.setAttribute("width",a.width-b);this.foreignObject_.setAttribute("height",a.height-b);this.textarea_.style.width=a.width-b-4+"px";this.textarea_.style.height=a.height-b-4+"px"}; Blockly.Comment.prototype.setVisible=function(a){if(a!=this.isVisible())if(!this.block_.isEditable()&&!this.textarea_||goog.userAgent.IE)Blockly.Warning.prototype.setVisible.call(this,a);else{var b=this.getText(),c=this.getBubbleSize();a?(this.bubble_=new Blockly.Bubble(this.block_.workspace,this.createEditor_(),this.block_.svgPath_,this.iconX_,this.iconY_,this.width_,this.height_),this.bubble_.registerResizeEvent(this,this.resizeBubble_),this.updateColour(),this.text_=null):(this.bubble_.dispose(), this.foreignObject_=this.textarea_=this.bubble_=null);this.setText(b);this.setBubbleSize(c.width,c.height)}};Blockly.Comment.prototype.textareaFocus_=function(a){this.bubble_.promote_();this.textarea_.focus()};Blockly.Comment.prototype.getBubbleSize=function(){return this.isVisible()?this.bubble_.getBubbleSize():{width:this.width_,height:this.height_}};Blockly.Comment.prototype.setBubbleSize=function(a,b){this.textarea_?this.bubble_.setBubbleSize(a,b):(this.width_=a,this.height_=b)}; -Blockly.Comment.prototype.getText=function(){return this.textarea_?this.textarea_.value:this.text_};Blockly.Comment.prototype.setText=function(a){this.textarea_?this.textarea_.value=a:this.text_=a};Blockly.Comment.prototype.dispose=function(){this.block_.comment=null;Blockly.Icon.prototype.dispose.call(this)};Blockly.Connection=function(a,b){this.sourceBlock_=a;this.type=b;this.db_=a.workspace.connectionDBList[b];this.dbOpposite_=a.workspace.connectionDBList[Blockly.OPPOSITE_TYPE[b]];this.hidden_=!this.db_};Blockly.Connection.prototype.targetConnection=null;Blockly.Connection.prototype.check_=null;Blockly.Connection.prototype.x_=0;Blockly.Connection.prototype.y_=0;Blockly.Connection.prototype.inDB_=!1; +Blockly.Comment.prototype.getText=function(){return this.textarea_?this.textarea_.value:this.text_};Blockly.Comment.prototype.setText=function(a){this.textarea_?this.textarea_.value=a:this.text_=a};Blockly.Comment.prototype.dispose=function(){this.block_.comment=null;Blockly.Icon.prototype.dispose.call(this)};Blockly.Connection=function(a,b){this.sourceBlock_=a;this.type=b;this.db_=a.workspace.connectionDBList[b];this.dbOpposite_=a.workspace.connectionDBList[Blockly.OPPOSITE_TYPE[b]];this.hidden_=!this.db_};Blockly.Connection.prototype.targetConnection=null;Blockly.Connection.prototype.check_=null;Blockly.Connection.prototype.shadowDom_=null;Blockly.Connection.prototype.x_=0;Blockly.Connection.prototype.y_=0;Blockly.Connection.prototype.inDB_=!1; Blockly.Connection.prototype.dispose=function(){if(this.targetConnection)throw"Disconnect connection before disposing of it.";this.inDB_&&this.db_.removeConnection_(this);Blockly.highlightedConnection_==this&&(Blockly.highlightedConnection_=null);Blockly.localConnection_==this&&(Blockly.localConnection_=null);this.dbOpposite_=this.db_=null};Blockly.Connection.prototype.isSuperior=function(){return this.type==Blockly.INPUT_VALUE||this.type==Blockly.NEXT_STATEMENT}; Blockly.Connection.prototype.connect=function(a){if(this.sourceBlock_==a.sourceBlock_)throw"Attempted to connect a block to itself.";if(this.sourceBlock_.workspace!==a.sourceBlock_.workspace)throw"Blocks are on different workspaces.";if(Blockly.OPPOSITE_TYPE[this.type]!=a.type)throw"Attempt to connect incompatible types.";if(this.type==Blockly.INPUT_VALUE||this.type==Blockly.OUTPUT_VALUE){if(this.targetConnection)throw"Source connection already connected (value).";if(a.targetConnection){var b=a.targetBlock(); -b.setParent(null);if(!b.outputConnection)throw"Orphan block does not have an output connection.";for(var c=this.sourceBlock_;c=Blockly.Connection.singleConnection_(c,b);)if(c.targetBlock())c=c.targetBlock();else{c.connect(b.outputConnection);b=null;break}b&&setTimeout(function(){b.outputConnection.bumpAwayFrom_(a)},Blockly.BUMP_DELAY)}}else{if(this.targetConnection)throw"Source connection already connected (block).";if(a.targetConnection){if(this.type!=Blockly.PREVIOUS_STATEMENT)throw"Can only do a mid-stack connection with the top of a block."; -b=a.targetBlock();b.setParent(null);if(!b.previousConnection)throw"Orphan block does not have a previous connection.";for(c=this.sourceBlock_;c.nextConnection;)if(c.nextConnection.targetConnection)c=c.getNextBlock();else{b.previousConnection.checkType_(c.nextConnection)&&(c.nextConnection.connect(b.previousConnection),b=null);break}b&&setTimeout(function(){b.previousConnection.bumpAwayFrom_(a)},Blockly.BUMP_DELAY)}}var d;this.isSuperior()?(c=this.sourceBlock_,d=a.sourceBlock_):(c=a.sourceBlock_,d= -this.sourceBlock_);this.targetConnection=a;a.targetConnection=this;d.setParent(c);c.rendered&&c.updateDisabled();d.rendered&&d.updateDisabled();c.rendered&&d.rendered&&(this.type==Blockly.NEXT_STATEMENT||this.type==Blockly.PREVIOUS_STATEMENT?d.render():c.render())};Blockly.Connection.singleConnection_=function(a,b){for(var c=!1,d=0;d"!=d.slice(-2)&&(b+=" ")}a=a.join("\n");a=a.replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g,"$1");return a.replace(/^\n/,"")}; Blockly.Xml.textToDom=function(a){a=(new DOMParser).parseFromString(a,"text/xml");if(!a||!a.firstChild||"xml"!=a.firstChild.nodeName.toLowerCase()||a.firstChild!==a.lastChild)throw"Blockly.Xml.textToDom did not obtain a valid XML tree.";return a.firstChild}; Blockly.Xml.domToWorkspace=function(a,b){var c;a.RTL&&(c=a.getWidth());Blockly.Field.startCache();for(var d=b.childNodes.length,e=0;ethis.workspace.scale)){var a=Blockly.getSvgXY_(this.svgGroup_,this.workspace);this.outputConnection?(a.x+=(this.RTL?3:-3)*this.workspace.scale,a.y+=13*this.workspace.scale):this.previousConnection&&(a.x+=(this.RTL?-23:23)*this.workspace.scale,a.y+=3*this.workspace.scale);a=Blockly.createSvgElement("circle",{cx:a.x,cy:a.y,r:0,fill:"none",stroke:"#888","stroke-width":10},this.workspace.options.svg);Blockly.BlockSvg.connectionUiStep_(a, new Date,this.workspace.scale)}};Blockly.BlockSvg.connectionUiStep_=function(a,b,c){var d=(new Date-b)/150;1this.workspace.scale)){var a=this.getHeightWidth().height,a=Math.atan(10/a)/Math.PI*180;this.RTL||(a*=-1);Blockly.BlockSvg.disconnectUiStep_(this.svgGroup_,a,new Date)}}; Blockly.BlockSvg.disconnectUiStep_=function(a,b,c){var d=(new Date-c)/200;1 level. It's all whitespace anyway. continue; } var input; - // Find any enclosed blocks. + // Find any enclosed blocks or shadows in this tag. var childBlockNode = null; + var childShadowNode = null; + var shadowActive = false; for (var j = 0, grandchildNode; grandchildNode = xmlChild.childNodes[j]; j++) { if (grandchildNode.nodeType == 1) { if (grandchildNode.nodeName.toLowerCase() == 'block') { childBlockNode = grandchildNode; + } else if (grandchildNode.nodeName.toLowerCase() == 'shadow') { + childShadowNode = grandchildNode; } } } + // Use the shadow block if there is no child block. + if (!childBlockNode && childShadowNode) { + childBlockNode = childShadowNode; + shadowActive = true; + } var name = xmlChild.getAttribute('name'); switch (xmlChild.nodeName.toLowerCase()) { @@ -397,6 +414,9 @@ Blockly.Xml.domToBlockHeadless_ = prototypeName); break; } + if (childShadowNode) { + input.connection.setShadowDom(childShadowNode); + } if (childBlockNode) { blockChild = Blockly.Xml.domToBlockHeadless_(workspace, childBlockNode, opt_reuseBlock); @@ -410,6 +430,9 @@ Blockly.Xml.domToBlockHeadless_ = } break; case 'next': + if (childShadowNode && block.nextConnection) { + block.nextConnection.setShadowDom(childShadowNode); + } if (childBlockNode) { if (!block.nextConnection) { throw 'Next statement does not exist.'; @@ -455,6 +478,9 @@ Blockly.Xml.domToBlockHeadless_ = if (collapsed) { block.setCollapsed(collapsed == 'true'); } + if (xmlBlock.nodeName.toLowerCase() == 'shadow') { + block.setShadow(true); + } // Give the block a chance to clean up any initial inputs. if (block.validate) { block.validate(); diff --git a/tests/playground.html b/tests/playground.html index f638d4829..849725b3e 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -233,27 +233,27 @@ h1 { - + 10 - + - + 1 - + - + 10 - + - + 1 - + @@ -261,43 +261,94 @@ h1 { - - - - - - - - + + + 1 - + + + + + 1 + - - - - - - + + + + 9 + + + + + + + 45 + + + + + + + + 0 + + + + + + 1 - + + + + + + + 3.1 + + + + + + + + 64 + + + + + 10 + + + + + + + 50 + + + + + 1 + - + 100 - + - + 1 - + - + 100 - + @@ -307,17 +358,34 @@ h1 { - + + + + + + + abc + + + + + + + + - - text + + + abc + + @@ -333,12 +401,32 @@ h1 { - - - + + + + abc + + + + + + + abc + + + + + + + abc + + + - + + abc + @@ -349,9 +437,9 @@ h1 { - + 5 - + @@ -386,9 +474,9 @@ h1 { - + , - + @@ -397,36 +485,36 @@ h1 { - + 100 - + - + 50 - + - + 0 - + - + #ff0000 - + - + #3333ff - + - + 0.5 - +