mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-08-28 22:10:31 -04:00
Refactor block_svg to share code between horizontal and vertical versionss.
This commit is contained in:
parent
9defd1ae79
commit
6ee0744b5c
11 changed files with 4493 additions and 5496 deletions
|
@ -1095,7 +1095,6 @@ c.oldCoordinate=a.dragStartXY_;c.recordNew();Blockly.Events.fire(c);a.moveConnec
|
|||
Blockly.BlockSvg.prototype.setParent=function(a){var b=this.getSvgRoot();if(this.parentBlock_&&b){var c=this.getRelativeToSurfaceXY();this.workspace.getCanvas().appendChild(b);b.setAttribute("transform","translate("+c.x+","+c.y+")")}Blockly.Field.startCache();Blockly.BlockSvg.superClass_.setParent.call(this,a);Blockly.Field.stopCache();a&&(c=this.getRelativeToSurfaceXY(),a.getSvgRoot().appendChild(b),a=this.getRelativeToSurfaceXY(),this.moveConnections_(a.x-c.x,a.y-c.y))};
|
||||
Blockly.BlockSvg.prototype.getRelativeToSurfaceXY=function(){var a=0,b=0,c=this.getSvgRoot();if(c){do var d=Blockly.getRelativeXY_(c),a=a+d.x,b=b+d.y,c=c.parentNode;while(c&&c!=this.workspace.getCanvas())}return new goog.math.Coordinate(a,b)};Blockly.BlockSvg.prototype.moveBy=function(a,b){var c=new Blockly.Events.Move(this),d=this.getRelativeToSurfaceXY();this.getSvgRoot().setAttribute("transform","translate("+(d.x+a)+","+(d.y+b)+")");this.moveConnections_(a,b);c.recordNew();Blockly.Events.fire(c)};
|
||||
Blockly.BlockSvg.prototype.snapToGrid=function(){if(this.workspace&&0==Blockly.dragMode_&&!this.getParent()&&!this.isInFlyout&&this.workspace.options.gridOptions&&this.workspace.options.gridOptions.snap){var a=this.workspace.options.gridOptions.spacing,b=a/2,c=this.getRelativeToSurfaceXY(),d=Math.round((c.x-b)/a)*a+b-c.x,a=Math.round((c.y-b)/a)*a+b-c.y,d=Math.round(d),a=Math.round(a);0==d&&0==a||this.moveBy(d,a)}};
|
||||
Blockly.BlockSvg.prototype.getHeightWidth=function(){var a=this.height,b=this.width,c=this.getNextBlock();c?(c=c.getHeightWidth(),b+=c.width,a=Math.max(a,c.height)):this.nextConnection||this.outputConnection||(a+=2);return{height:a,width:b}};
|
||||
Blockly.BlockSvg.prototype.tab=function(a,b){for(var c=[],d=0,e;e=this.inputList[d];d++){for(var f=0,g;g=e.fieldRow[f];f++)g instanceof Blockly.FieldTextInput&&c.push(g);e.connection&&(e=e.connection.targetBlock())&&c.push(e)}d=c.indexOf(a);-1==d&&(d=b?-1:c.length);(c=c[b?d+1:d-1])?c instanceof Blockly.Field?c.showEditor_():c.tab(null,b):(c=this.getParent())&&c.tab(this,b)};
|
||||
Blockly.BlockSvg.prototype.onMouseDown_=function(a){if(!this.isInFlyout)if(this.workspace.markFocused(),Blockly.svgResize(this.workspace),Blockly.terminateDrag_(),this.select(),Blockly.hideChaff(),this.workspace.recordDeleteAreas(),Blockly.isRightButton(a))this.showContextMenu_(a);else if(this.isMovable()){Blockly.Events.group=Blockly.genUid();Blockly.removeAllRanges();Blockly.Css.setCursor(Blockly.Css.Cursor.CLOSED);this.dragStartXY_=this.getRelativeToSurfaceXY();this.workspace.startDrag(a,this.dragStartXY_.x,
|
||||
this.dragStartXY_.y);Blockly.dragMode_=1;Blockly.BlockSvg.onMouseUpWrapper_=Blockly.bindEvent_(document,"mouseup",this,this.onMouseUp_);Blockly.BlockSvg.onMouseMoveWrapper_=Blockly.bindEvent_(document,"mousemove",this,this.onMouseMove_);this.draggedBubbles_=[];for(var b=this.getDescendants(),c=0,d;d=b[c];c++){d=d.getIcons();for(var e=0;e<d.length;e++){var f=d[e].getIconLocation();f.bubble=d[e];this.draggedBubbles_.push(f)}}}else return;a.stopPropagation()};
|
||||
|
@ -1109,7 +1108,17 @@ Blockly.BlockSvg.prototype.onMouseMove_=function(a){if(!("mousemove"==a.type&&1>
|
|||
b.x-this.dragStartXY_.x,b=b.y-this.dragStartXY_.y;d.translate_="translate("+c.x+","+c.y+")";d.setAttribute("transform",d.translate_+d.skew_);for(c=0;c<this.draggedBubbles_.length;c++)d=this.draggedBubbles_[c],d.bubble.setIconLocation(d.x+e,d.y+b);for(var d=this.getConnections_(!1),f=null,g=null,h=Blockly.SNAP_RADIUS,c=0;c<d.length;c++){var k=d[c],l=k.closest(h,e,b);l.connection&&(f=l.connection,g=k,h=l.radius)}Blockly.highlightedConnection_&&Blockly.highlightedConnection_!=f&&(Blockly.highlightedConnection_.unhighlight(),
|
||||
Blockly.highlightedConnection_=null,Blockly.localConnection_=null);f&&f!=Blockly.highlightedConnection_&&(f.highlight(),Blockly.highlightedConnection_=f,Blockly.localConnection_=g);this.isDeletable()&&this.workspace.isDeleteArea(a)}}a.stopPropagation()};Blockly.BlockSvg.prototype.updateMovable=function(){this.isMovable()?Blockly.addClass_(this.svgGroup_,"blocklyDraggable"):Blockly.removeClass_(this.svgGroup_,"blocklyDraggable")};
|
||||
Blockly.BlockSvg.prototype.setMovable=function(a){Blockly.BlockSvg.superClass_.setMovable.call(this,a);this.updateMovable()};Blockly.BlockSvg.prototype.setEditable=function(a){Blockly.BlockSvg.superClass_.setEditable.call(this,a);if(this.rendered)for(a=0;a<this.icons_.length;a++)this.icons_[a].updateEditable()};Blockly.BlockSvg.prototype.setShadow=function(a){Blockly.BlockSvg.superClass_.setShadow.call(this,a);this.updateColour()};Blockly.BlockSvg.prototype.getSvgRoot=function(){return this.svgGroup_};
|
||||
Blockly.BlockSvg.SEP_SPACE_X=8;Blockly.BlockSvg.SEP_SPACE_Y=8;Blockly.BlockSvg.INLINE_PADDING_Y=5;Blockly.BlockSvg.FIELD_HEIGHT=32;Blockly.BlockSvg.FIELD_WIDTH=48;Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS=16;Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS=4;Blockly.BlockSvg.MIN_BLOCK_X=40;Blockly.BlockSvg.TAB_WIDTH=8;Blockly.BlockSvg.CORNER_RADIUS=4;Blockly.BlockSvg.HAT_CORNER_RADIUS=16;Blockly.BlockSvg.NOTCH_RADIUS=2.5;Blockly.BlockSvg.NOTCH_BASE_HEIGHT=32;
|
||||
Blockly.BlockSvg.prototype.dispose=function(a,b){Blockly.Field.startCache();Blockly.selected==this&&Blockly.terminateDrag_();Blockly.ContextMenu.currentBlock==this&&Blockly.ContextMenu.hide();b&&this.rendered&&(this.unplug(a),this.disposeUiEffect());this.rendered=!1;Blockly.BlockSvg.superClass_.dispose.call(this,a);Blockly.Events.disable();for(var c=this.getIcons(),d=0;d<c.length;d++)c[d].dispose();Blockly.Events.enable();goog.dom.removeNode(this.svgGroup_);this.svgPath_=this.svgGroup_=null;Blockly.Field.stopCache()};
|
||||
Blockly.BlockSvg.prototype.disposeUiEffect=function(){this.workspace.playAudio("delete");var a=Blockly.getSvgXY_(this.svgGroup_,this.workspace),b=this.svgGroup_.cloneNode(!0);b.translateX_=a.x;b.translateY_=a.y;b.setAttribute("transform","translate("+b.translateX_+","+b.translateY_+")");this.workspace.getParentSvg().appendChild(b);b.bBox_=b.getBBox();Blockly.BlockSvg.disposeUiStep_(b,this.RTL,new Date,this.workspace.scale)};
|
||||
Blockly.BlockSvg.disposeUiStep_=function(a,b,c,d){var e=(new Date-c)/150;1<e?goog.dom.removeNode(a):(a.setAttribute("transform","translate("+(a.translateX_+(b?-1:1)*a.bBox_.width*d/2*e)+","+(a.translateY_+a.bBox_.height*d*e)+") scale("+(1-e)*d+")"),setTimeout(function(){Blockly.BlockSvg.disposeUiStep_(a,b,c,d)},10))};
|
||||
Blockly.BlockSvg.prototype.disconnectUiEffect=function(){this.workspace.playAudio("disconnect");if(!(1>this.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<d?a.skew_="":(a.skew_="skewX("+Math.round(Math.sin(d*Math.PI*3)*(1-d)*b)+")",Blockly.BlockSvg.disconnectUiStop_.group=a,Blockly.BlockSvg.disconnectUiStop_.pid=setTimeout(function(){Blockly.BlockSvg.disconnectUiStep_(a,b,c)},10));a.setAttribute("transform",a.translate_+a.skew_)};
|
||||
Blockly.BlockSvg.disconnectUiStop_=function(){if(Blockly.BlockSvg.disconnectUiStop_.group){clearTimeout(Blockly.BlockSvg.disconnectUiStop_.pid);var a=Blockly.BlockSvg.disconnectUiStop_.group;a.skew_="";a.setAttribute("transform",a.translate_);Blockly.BlockSvg.disconnectUiStop_.group=null}};Blockly.BlockSvg.disconnectUiStop_.pid=0;Blockly.BlockSvg.disconnectUiStop_.group=null;Blockly.BlockSvg.prototype.updateDisabled=function(){};
|
||||
Blockly.BlockSvg.prototype.getCommentText=function(){return this.comment?this.comment.getText().replace(/\s+$/,"").replace(/ +\n/g,"\n"):""};Blockly.BlockSvg.prototype.setCommentText=function(a){var b=!1;goog.isString(a)?(this.comment||(this.comment=new Blockly.Comment(this),b=!0),this.comment.setText(a)):this.comment&&(this.comment.dispose(),b=!0);b&&this.rendered&&(this.render(),this.bumpNeighbours_())};
|
||||
Blockly.BlockSvg.prototype.setWarningText=function(a,b){this.setWarningText.pid_||(this.setWarningText.pid_=Object.create(null));var c=b||"";if(c)this.setWarningText.pid_[c]&&(clearTimeout(this.setWarningText.pid_[c]),delete this.setWarningText.pid_[c]);else for(var d in this.setWarningText.pid_)clearTimeout(this.setWarningText.pid_[d]),delete this.setWarningText.pid_[d];if(2==Blockly.dragMode_){var e=this;this.setWarningText.pid_[c]=setTimeout(function(){e.workspace&&(delete e.setWarningText.pid_[c],
|
||||
e.setWarningText(a,c))},100)}else{this.isInFlyout&&(a=null);d=!1;if(goog.isString(a))this.warning||(this.warning=new Blockly.Warning(this),d=!0),this.warning.setText(a,c);else if(this.warning&&!c)this.warning.dispose(),d=!0;else if(this.warning){d=this.warning.getText();this.warning.setText("",c);var f=this.warning.getText();f||this.warning.dispose();d=d==f}d&&this.rendered&&(this.render(),this.bumpNeighbours_())}};
|
||||
Blockly.BlockSvg.prototype.setMutator=function(a){this.mutator&&this.mutator!==a&&this.mutator.dispose();a&&(a.block_=this,this.mutator=a,a.createIcon())};Blockly.BlockSvg.prototype.addSelect=function(){Blockly.addClass_(this.svgGroup_,"blocklySelected");this.svgGroup_.parentNode.appendChild(this.svgGroup_)};Blockly.BlockSvg.prototype.removeSelect=function(){Blockly.removeClass_(this.svgGroup_,"blocklySelected")};Blockly.BlockSvg.prototype.addDragging=function(){Blockly.addClass_(this.svgGroup_,"blocklyDragging")};
|
||||
Blockly.BlockSvg.prototype.removeDragging=function(){Blockly.removeClass_(this.svgGroup_,"blocklyDragging")};Blockly.BlockSvg.render={};Blockly.BlockSvg.SEP_SPACE_X=8;Blockly.BlockSvg.SEP_SPACE_Y=8;Blockly.BlockSvg.INLINE_PADDING_Y=5;Blockly.BlockSvg.FIELD_HEIGHT=32;Blockly.BlockSvg.FIELD_WIDTH=48;Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS=16;Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS=4;Blockly.BlockSvg.MIN_BLOCK_X=40;Blockly.BlockSvg.TAB_WIDTH=8;Blockly.BlockSvg.CORNER_RADIUS=4;Blockly.BlockSvg.HAT_CORNER_RADIUS=16;Blockly.BlockSvg.NOTCH_RADIUS=2.5;Blockly.BlockSvg.NOTCH_BASE_HEIGHT=32;
|
||||
Blockly.BlockSvg.NOTCH_HEIGHT=Blockly.BlockSvg.NOTCH_BASE_HEIGHT+Blockly.BlockSvg.NOTCH_RADIUS;Blockly.BlockSvg.NOTCH_WIDTH=Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4;
|
||||
Blockly.BlockSvg.NOTCH_PATH_DOWN="a "+-Blockly.BlockSvg.NOTCH_RADIUS+","+Blockly.BlockSvg.NOTCH_RADIUS+" 0 0 0 "+Blockly.BlockSvg.NOTCH_RADIUS/2+","+Blockly.BlockSvg.NOTCH_RADIUS+" l "+(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4-Blockly.BlockSvg.NOTCH_RADIUS)+","+(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4-Blockly.BlockSvg.NOTCH_RADIUS)+" a "+-Blockly.BlockSvg.NOTCH_RADIUS+","+Blockly.BlockSvg.NOTCH_RADIUS+" 0 0 1 "+Blockly.BlockSvg.NOTCH_RADIUS/2+","+Blockly.BlockSvg.NOTCH_RADIUS+" v "+(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/
|
||||
2-Blockly.BlockSvg.NOTCH_RADIUS)+" a "+-Blockly.BlockSvg.NOTCH_RADIUS+","+Blockly.BlockSvg.NOTCH_RADIUS+" 0 0 1 "+-Blockly.BlockSvg.NOTCH_RADIUS/2+","+Blockly.BlockSvg.NOTCH_RADIUS+" l "+(-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4+Blockly.BlockSvg.NOTCH_RADIUS)+","+(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4-Blockly.BlockSvg.NOTCH_RADIUS)+" a "+-Blockly.BlockSvg.NOTCH_RADIUS+","+Blockly.BlockSvg.NOTCH_RADIUS+" 0 0 0 "+-Blockly.BlockSvg.NOTCH_RADIUS/2+","+Blockly.BlockSvg.NOTCH_RADIUS;
|
||||
|
@ -1117,20 +1126,11 @@ Blockly.BlockSvg.NOTCH_PATH_UP="a "+Blockly.BlockSvg.NOTCH_RADIUS+","+-Blockly.B
|
|||
2-Blockly.BlockSvg.NOTCH_RADIUS)+" a "+Blockly.BlockSvg.NOTCH_RADIUS+","+-Blockly.BlockSvg.NOTCH_RADIUS+" 0 0 0 "+-Blockly.BlockSvg.NOTCH_RADIUS/2+","+-Blockly.BlockSvg.NOTCH_RADIUS+"l "+(-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4+Blockly.BlockSvg.NOTCH_RADIUS)+","+(-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4+Blockly.BlockSvg.NOTCH_RADIUS)+" a "+Blockly.BlockSvg.NOTCH_RADIUS+","+-Blockly.BlockSvg.NOTCH_RADIUS+" 0 0 1 "+-Blockly.BlockSvg.NOTCH_RADIUS/2+","+-Blockly.BlockSvg.NOTCH_RADIUS;
|
||||
Blockly.BlockSvg.TOP_LEFT_CORNER_START="m "+Blockly.BlockSvg.CORNER_RADIUS+",0";Blockly.BlockSvg.TOP_LEFT_CORNER="A "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,0 0,"+Blockly.BlockSvg.CORNER_RADIUS;Blockly.BlockSvg.HAT_TOP_LEFT_CORNER_START="m "+Blockly.BlockSvg.HAT_CORNER_RADIUS+",0";Blockly.BlockSvg.HAT_TOP_LEFT_CORNER="A "+Blockly.BlockSvg.HAT_CORNER_RADIUS+","+Blockly.BlockSvg.HAT_CORNER_RADIUS+" 0 0,0 0,"+Blockly.BlockSvg.HAT_CORNER_RADIUS;
|
||||
Blockly.BlockSvg.INNER_TOP_LEFT_CORNER=Blockly.BlockSvg.NOTCH_PATH_UP+" h -"+(Blockly.BlockSvg.NOTCH_HEIGHT-15-Blockly.BlockSvg.CORNER_RADIUS)+" h -0.5 a "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,0 -"+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS;Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER="a "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,0 "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS;
|
||||
Blockly.BlockSvg.prototype.dispose=function(a,b){Blockly.Field.startCache();Blockly.selected==this&&Blockly.terminateDrag_();Blockly.ContextMenu.currentBlock==this&&Blockly.ContextMenu.hide();b&&this.rendered&&(this.unplug(a),this.disposeUiEffect());this.rendered=!1;Blockly.BlockSvg.superClass_.dispose.call(this,a);Blockly.Events.disable();for(var c=this.getIcons(),d=0;d<c.length;d++)c[d].dispose();Blockly.Events.enable();goog.dom.removeNode(this.svgGroup_);this.svgPath_=this.svgGroup_=null;Blockly.Field.stopCache()};
|
||||
Blockly.BlockSvg.prototype.disposeUiEffect=function(){this.workspace.playAudio("delete");var a=Blockly.getSvgXY_(this.svgGroup_,this.workspace),b=this.svgGroup_.cloneNode(!0);b.translateX_=a.x;b.translateY_=a.y;b.setAttribute("transform","translate("+b.translateX_+","+b.translateY_+")");this.workspace.getParentSvg().appendChild(b);b.bBox_=b.getBBox();Blockly.BlockSvg.disposeUiStep_(b,this.RTL,new Date,this.workspace.scale)};
|
||||
Blockly.BlockSvg.disposeUiStep_=function(a,b,c,d){var e=(new Date-c)/150;1<e?goog.dom.removeNode(a):(a.setAttribute("transform","translate("+(a.translateX_+(b?-1:1)*a.bBox_.width*d/2*e)+","+(a.translateY_+a.bBox_.height*d*e)+") scale("+(1-e)*d+")"),setTimeout(function(){Blockly.BlockSvg.disposeUiStep_(a,b,c,d)},10))};
|
||||
Blockly.BlockSvg.prototype.connectionUiEffect=function(){this.workspace.playAudio("click");if(!(1>this.workspace.scale)){var a=Blockly.getSvgXY_(this.svgGroup_,this.workspace);a.x+=8*this.workspace.scale;a.y+=this.height-(2*Blockly.BlockSvg.CORNER_RADIUS+Blockly.BlockSvg.NOTCH_HEIGHT/2)-8*this.workspace.scale;a=Blockly.createSvgElement("circle",{cx:a.x,cy:a.y,r:0,fill:"none",stroke:"#EEE","stroke-width":8},this.workspace.getParentSvg());Blockly.BlockSvg.connectionUiStep_(a,new Date,this.workspace.scale)}};
|
||||
Blockly.BlockSvg.connectionUiStep_=function(a,b,c){var d=(new Date-b)/150;1<d?goog.dom.removeNode(a):(a.setAttribute("r",25*d*c),a.style.opacity=.8-d,Blockly.BlockSvg.disconnectUiStop_.pid_=setTimeout(function(){Blockly.BlockSvg.connectionUiStep_(a,b,c)},10))};
|
||||
Blockly.BlockSvg.prototype.disconnectUiEffect=function(){this.workspace.playAudio("disconnect");if(!(1>this.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<d?a.skew_="":(a.skew_="skewX("+Math.round(Math.sin(d*Math.PI*3)*(1-d)*b)+")",Blockly.BlockSvg.disconnectUiStop_.group=a,Blockly.BlockSvg.disconnectUiStop_.pid=setTimeout(function(){Blockly.BlockSvg.disconnectUiStep_(a,b,c)},10));a.setAttribute("transform",a.translate_+a.skew_)};
|
||||
Blockly.BlockSvg.disconnectUiStop_=function(){if(Blockly.BlockSvg.disconnectUiStop_.group){clearTimeout(Blockly.BlockSvg.disconnectUiStop_.pid);var a=Blockly.BlockSvg.disconnectUiStop_.group;a.skew_="";a.setAttribute("transform",a.translate_);Blockly.BlockSvg.disconnectUiStop_.group=null}};Blockly.BlockSvg.disconnectUiStop_.pid=0;Blockly.BlockSvg.disconnectUiStop_.group=null;
|
||||
Blockly.BlockSvg.prototype.updateColour=function(){var a=this.parentBlock_?this.parentBlock_.getColour():this.getColour(),b=goog.color.hexToRgb(a);this.isShadow()?this.svgPath_.setAttribute("fill","#ffffff"):this.svgPath_.setAttribute("fill",a);a=goog.color.darken(b,.1);a=goog.color.rgbArrayToHex(a);this.svgPath_.setAttribute("stroke",a);for(a=0;b=this.inputList[a];a++)for(var c=0,d;d=b.fieldRow[c];c++)d.setText(null)};Blockly.BlockSvg.prototype.updateDisabled=function(){};
|
||||
Blockly.BlockSvg.prototype.getCommentText=function(){return this.comment?this.comment.getText().replace(/\s+$/,"").replace(/ +\n/g,"\n"):""};Blockly.BlockSvg.prototype.setCommentText=function(a){var b=!1;goog.isString(a)?(this.comment||(this.comment=new Blockly.Comment(this),b=!0),this.comment.setText(a)):this.comment&&(this.comment.dispose(),b=!0);b&&this.rendered&&(this.render(),this.bumpNeighbours_())};
|
||||
Blockly.BlockSvg.prototype.setWarningText=function(a,b){this.setWarningText.pid_||(this.setWarningText.pid_=Object.create(null));var c=b||"";if(c)this.setWarningText.pid_[c]&&(clearTimeout(this.setWarningText.pid_[c]),delete this.setWarningText.pid_[c]);else for(var d in this.setWarningText.pid_)clearTimeout(this.setWarningText.pid_[d]),delete this.setWarningText.pid_[d];if(2==Blockly.dragMode_){var e=this;this.setWarningText.pid_[c]=setTimeout(function(){e.workspace&&(delete e.setWarningText.pid_[c],
|
||||
e.setWarningText(a,c))},100)}else{this.isInFlyout&&(a=null);d=!1;if(goog.isString(a))this.warning||(this.warning=new Blockly.Warning(this),d=!0),this.warning.setText(a,c);else if(this.warning&&!c)this.warning.dispose(),d=!0;else if(this.warning){d=this.warning.getText();this.warning.setText("",c);var f=this.warning.getText();f||this.warning.dispose();d=d==f}d&&this.rendered&&(this.render(),this.bumpNeighbours_())}};
|
||||
Blockly.BlockSvg.prototype.setMutator=function(a){this.mutator&&this.mutator!==a&&this.mutator.dispose();a&&(a.block_=this,this.mutator=a,a.createIcon())};Blockly.BlockSvg.prototype.addSelect=function(){Blockly.addClass_(this.svgGroup_,"blocklySelected");this.svgGroup_.parentNode.appendChild(this.svgGroup_)};Blockly.BlockSvg.prototype.removeSelect=function(){Blockly.removeClass_(this.svgGroup_,"blocklySelected")};Blockly.BlockSvg.prototype.addDragging=function(){Blockly.addClass_(this.svgGroup_,"blocklyDragging")};
|
||||
Blockly.BlockSvg.prototype.removeDragging=function(){Blockly.removeClass_(this.svgGroup_,"blocklyDragging")};Blockly.BlockSvg.prototype.render=function(a){Blockly.Field.startCache();this.rendered=!0;var b=this.renderCompute_();this.height=b.height;this.width=b.width;this.renderDraw_(b);!1!==a&&((a=this.getParent())?a.render(!0):Blockly.fireUiEvent(window,"resize"));Blockly.Field.stopCache()};
|
||||
Blockly.BlockSvg.prototype.updateColour=function(){var a=this.parentBlock_?this.parentBlock_.getColour():this.getColour(),b=goog.color.hexToRgb(a);this.isShadow()?this.svgPath_.setAttribute("fill","#ffffff"):this.svgPath_.setAttribute("fill",a);a=goog.color.darken(b,.1);a=goog.color.rgbArrayToHex(a);this.svgPath_.setAttribute("stroke",a);for(a=0;b=this.inputList[a];a++)for(var c=0,d;d=b.fieldRow[c];c++)d.setText(null)};
|
||||
Blockly.BlockSvg.prototype.getHeightWidth=function(){var a=this.height,b=this.width,c=this.getNextBlock();c?(c=c.getHeightWidth(),b+=c.width,a=Math.max(a,c.height)):this.nextConnection||this.outputConnection||(a+=2);return{height:a,width:b}};
|
||||
Blockly.BlockSvg.prototype.render=function(a){Blockly.Field.startCache();this.rendered=!0;var b=this.renderCompute_();this.height=b.height;this.width=b.width;this.renderDraw_(b);!1!==a&&((a=this.getParent())?a.render(!0):Blockly.fireUiEvent(window,"resize"));Blockly.Field.stopCache()};
|
||||
Blockly.BlockSvg.prototype.renderCompute_=function(){var a={statement:null,valueInput:null,icon:null,width:0,height:0,bayHeight:0,bayWidth:0,fieldWidth:0,fieldHeight:0,fieldRadius:0,startHat:!1,endHat:!1};this.nextConnection&&!this.previousConnection&&(a.startHat=!0);this.previousConnection&&!this.nextConnection&&(a.endHat=!0);for(var b=0,c;c=this.inputList[b];b++){if(c.type==Blockly.NEXT_STATEMENT&&(a.statement=c,a.bayHeight=Blockly.BlockSvg.NOTCH_HEIGHT+16+3*Blockly.BlockSvg.CORNER_RADIUS,a.bayWidth=
|
||||
2*Blockly.BlockSvg.NOTCH_WIDTH+Blockly.BlockSvg.MIN_BLOCK_X,c.connection&&c.connection.targetConnection)){var d=c.connection.targetBlock().getHeightWidth();a.bayHeight=Math.max(a.bayHeight,d.height);a.bayWidth=Math.max(a.bayWidth,d.width)}for(var d=0,e;e=c.fieldRow[d];d++)if(e instanceof Blockly.FieldImage&&(a.icon=e),e instanceof Blockly.FieldTextInput){var f=e.textElement_.getBBox();a.fieldWidth=f.width+Blockly.BlockSvg.SEP_SPACE_X;a.fieldHeight=f.height;a.fieldRadius="math_number"===e.sourceBlock_.type?
|
||||
Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS:Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS}}for(b=0;c=this.childBlocks_[b];b++)c.isShadow()&&(a.valueInput=c);b=a.icon?a.icon.getSize():new goog.math.Size(0,0);a.width=2*Blockly.BlockSvg.SEP_SPACE_X+b.width+a.bayWidth;a.statement&&(a.width+=2*Blockly.BlockSvg.CORNER_RADIUS+8);this.outputConnection?(a.height=Blockly.BlockSvg.FIELD_HEIGHT,a.width=Blockly.BlockSvg.FIELD_WIDTH):a.height=Math.max(2*Blockly.BlockSvg.SEP_SPACE_Y+b.height,Blockly.BlockSvg.NOTCH_HEIGHT+
|
||||
|
@ -1229,9 +1229,12 @@ this.workspace_.scale,viewTop:-this.workspace_.scrollY,viewLeft:-this.workspace_
|
|||
Blockly.Flyout.prototype.setMetrics_=function(a){var b=this.getMetrics_();b&&(!this.horizontalLayout_&&goog.isNumber(a.y)?this.workspace_.scrollY=-b.contentHeight*a.y-b.contentTop:this.horizontalLayout_&&goog.isNumber(a.x)&&(this.workspace_.scrollX=this.RTL?-b.contentWidth*a.x+b.contentLeft:-b.contentWidth*a.x-b.contentLeft),this.workspace_.translate(this.horizontalLayout_&&this.RTL?b.absoluteLeft+b.viewWidth-this.workspace_.scrollX:this.workspace_.scrollX+b.absoluteLeft,this.workspace_.scrollY+b.absoluteTop))};
|
||||
Blockly.Flyout.prototype.setVerticalOffset=function(a){this.verticalOffset_=a};
|
||||
Blockly.Flyout.prototype.position=function(){if(this.isVisible()){var a=this.targetWorkspace_.getMetrics();if(a){var b=this.horizontalLayout_?a.viewWidth:this.width_,b=b-this.CORNER_RADIUS;this.toolboxPosition_==Blockly.TOOLBOX_AT_RIGHT&&(b*=-1);this.setBackgroundPath_(b,this.horizontalLayout_?this.height_+this.verticalOffset_:a.viewHeight);b=a.absoluteLeft;this.toolboxPosition_==Blockly.TOOLBOX_AT_RIGHT&&(b+=a.viewWidth,b-=this.width_);var c=a.absoluteTop;this.toolboxPosition_==Blockly.TOOLBOX_AT_BOTTOM&&
|
||||
(c+=a.viewHeight,c-=this.height_);this.svgGroup_.setAttribute("transform","translate("+b+","+c+")");this.horizontalLayout_?this.width_=a.viewWidth:this.height_=a.viewHeight;this.scrollbar_&&this.scrollbar_.resize();this.svgGroup_.style.opacity=1}}};
|
||||
Blockly.Flyout.prototype.setBackgroundPath_=function(a,b){var c=this.toolboxPosition_==Blockly.TOOLBOX_AT_RIGHT,d=["M "+(c?this.width_:0)+",0"];d.push("h",a);d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?-this.CORNER_RADIUS:this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("v",Math.max(0,b-2*this.CORNER_RADIUS));d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?this.CORNER_RADIUS:-this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("h",-a);d.push("z");this.svgBackground_.setAttribute("d",
|
||||
d.join(" "))};Blockly.Flyout.prototype.scrollToStart=function(){this.scrollbar_.set(this.horizontalLayout_&&this.RTL?1E9:0)};Blockly.Flyout.prototype.wheel_=function(a){if(!this.horizontalLayout_){var b=a.deltaY;if(b){goog.userAgent.GECKO&&(b*=10);var c=this.getMetrics_(),b=c.viewTop+b,b=Math.min(b,c.contentHeight-c.viewHeight),b=Math.max(b,0);this.scrollbar_.set(b);a.preventDefault();a.stopPropagation()}}};Blockly.Flyout.prototype.isVisible=function(){return this.svgGroup_&&"block"==this.svgGroup_.style.display};
|
||||
(c+=a.viewHeight,c-=this.height_);this.svgGroup_.setAttribute("transform","translate("+b+","+c+")");this.horizontalLayout_?this.width_=a.viewWidth:this.height_=a.viewHeight;this.scrollbar_&&this.scrollbar_.resize();this.svgGroup_.style.opacity=1}}};Blockly.Flyout.prototype.setBackgroundPath_=function(a,b){this.horizontalLayout_?this.setBackgroundPathHorizontal_(a,b):this.setBackgroundPathVertical_(a,b)};
|
||||
Blockly.Flyout.prototype.setBackgroundPathVertical_=function(a,b){var c=this.toolboxPosition_==Blockly.TOOLBOX_AT_RIGHT,d=["M "+(c?this.width_:0)+",0"];d.push("h",a);d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?-this.CORNER_RADIUS:this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("v",Math.max(0,b-2*this.CORNER_RADIUS));d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?this.CORNER_RADIUS:-this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("h",-a);d.push("z");this.svgBackground_.setAttribute("d",
|
||||
d.join(" "))};
|
||||
Blockly.Flyout.prototype.setBackgroundPathHorizontal_=function(a,b){var c=this.toolboxPosition_==Blockly.TOOLBOX_AT_TOP,d=["M 0,"+(c?0:this.CORNER_RADIUS)];c?(d.push("h",a+this.CORNER_RADIUS),d.push("v",b),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("h",-1*(a-this.CORNER_RADIUS)),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,-this.CORNER_RADIUS)):(d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,
|
||||
-this.CORNER_RADIUS),d.push("h",a-this.CORNER_RADIUS),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("v",b-this.CORNER_RADIUS),d.push("h",-a-this.CORNER_RADIUS));d.push("z");this.svgBackground_.setAttribute("d",d.join(" "))};Blockly.Flyout.prototype.scrollToStart=function(){this.scrollbar_.set(this.horizontalLayout_&&this.RTL?1E9:0)};
|
||||
Blockly.Flyout.prototype.wheel_=function(a){if(!this.horizontalLayout_){var b=a.deltaY;if(b){goog.userAgent.GECKO&&(b*=10);var c=this.getMetrics_(),b=c.viewTop+b,b=Math.min(b,c.contentHeight-c.viewHeight),b=Math.max(b,0);this.scrollbar_.set(b);a.preventDefault();a.stopPropagation()}}};Blockly.Flyout.prototype.isVisible=function(){return this.svgGroup_&&"block"==this.svgGroup_.style.display};
|
||||
Blockly.Flyout.prototype.hide=function(){if(this.isVisible()){this.svgGroup_.style.display="none";for(var a=0,b;b=this.listeners_[a];a++)Blockly.unbindEvent_(b);this.listeners_.length=0;this.reflowWrapper_&&(this.workspace_.removeChangeListener(this.reflowWrapper_),this.reflowWrapper_=null)}};
|
||||
Blockly.Flyout.prototype.show=function(a){this.hide();for(var b=this.workspace_.getTopBlocks(!1),c=0,d;d=b[c];c++)d.workspace==this.workspace_&&d.dispose(!1,!1);for(var c=0,e;e=this.buttons_[c];c++)goog.dom.removeNode(e);this.buttons_.length=0;a==Blockly.Variables.NAME_TYPE?a=Blockly.Variables.flyoutCategory(this.workspace_.targetWorkspace):a==Blockly.Procedures.NAME_TYPE&&(a=Blockly.Procedures.flyoutCategory(this.workspace_.targetWorkspace));for(var f=this.CORNER_RADIUS,b=[],g=[],c=this.permanentlyDisabled_.length=
|
||||
0;e=a[c];c++)e.tagName&&"BLOCK"==e.tagName.toUpperCase()&&(d=Blockly.Xml.domToBlock(this.workspace_,e),d.disabled&&this.permanentlyDisabled_.push(d),b.push(d),d=parseInt(e.getAttribute("gap"),10),g.push(isNaN(d)?3*f:d));this.svgGroup_.style.opacity=0;this.svgGroup_.style.display="block";a=f/this.workspace_.scale+Blockly.BlockSvg.TAB_WIDTH;for(c=0;d=b[c];c++){e=d.getDescendants();for(var h=0,k;k=e[h];h++)k.isInFlyout=!0;d.render();h=d.getSvgRoot();e=d.getHeightWidth();d.moveBy(this.horizontalLayout_&&
|
||||
|
|
|
@ -1095,7 +1095,6 @@ c.oldCoordinate=a.dragStartXY_;c.recordNew();Blockly.Events.fire(c);a.moveConnec
|
|||
Blockly.BlockSvg.prototype.setParent=function(a){var b=this.getSvgRoot();if(this.parentBlock_&&b){var c=this.getRelativeToSurfaceXY();this.workspace.getCanvas().appendChild(b);b.setAttribute("transform","translate("+c.x+","+c.y+")")}Blockly.Field.startCache();Blockly.BlockSvg.superClass_.setParent.call(this,a);Blockly.Field.stopCache();a&&(c=this.getRelativeToSurfaceXY(),a.getSvgRoot().appendChild(b),a=this.getRelativeToSurfaceXY(),this.moveConnections_(a.x-c.x,a.y-c.y))};
|
||||
Blockly.BlockSvg.prototype.getRelativeToSurfaceXY=function(){var a=0,b=0,c=this.getSvgRoot();if(c){do var d=Blockly.getRelativeXY_(c),a=a+d.x,b=b+d.y,c=c.parentNode;while(c&&c!=this.workspace.getCanvas())}return new goog.math.Coordinate(a,b)};Blockly.BlockSvg.prototype.moveBy=function(a,b){var c=new Blockly.Events.Move(this),d=this.getRelativeToSurfaceXY();this.getSvgRoot().setAttribute("transform","translate("+(d.x+a)+","+(d.y+b)+")");this.moveConnections_(a,b);c.recordNew();Blockly.Events.fire(c)};
|
||||
Blockly.BlockSvg.prototype.snapToGrid=function(){if(this.workspace&&0==Blockly.dragMode_&&!this.getParent()&&!this.isInFlyout&&this.workspace.options.gridOptions&&this.workspace.options.gridOptions.snap){var a=this.workspace.options.gridOptions.spacing,b=a/2,c=this.getRelativeToSurfaceXY(),d=Math.round((c.x-b)/a)*a+b-c.x,a=Math.round((c.y-b)/a)*a+b-c.y,d=Math.round(d),a=Math.round(a);0==d&&0==a||this.moveBy(d,a)}};
|
||||
Blockly.BlockSvg.prototype.getHeightWidth=function(){var a=this.height,b=this.width,c=this.getNextBlock();c?(c=c.getHeightWidth(),a+=c.height-4,b=Math.max(b,c.width)):this.nextConnection||this.outputConnection||(a+=2);return{height:a,width:b}};
|
||||
Blockly.BlockSvg.prototype.tab=function(a,b){for(var c=[],d=0,e;e=this.inputList[d];d++){for(var f=0,g;g=e.fieldRow[f];f++)g instanceof Blockly.FieldTextInput&&c.push(g);e.connection&&(e=e.connection.targetBlock())&&c.push(e)}d=c.indexOf(a);-1==d&&(d=b?-1:c.length);(c=c[b?d+1:d-1])?c instanceof Blockly.Field?c.showEditor_():c.tab(null,b):(c=this.getParent())&&c.tab(this,b)};
|
||||
Blockly.BlockSvg.prototype.onMouseDown_=function(a){if(!this.isInFlyout)if(this.workspace.markFocused(),Blockly.svgResize(this.workspace),Blockly.terminateDrag_(),this.select(),Blockly.hideChaff(),this.workspace.recordDeleteAreas(),Blockly.isRightButton(a))this.showContextMenu_(a);else if(this.isMovable()){Blockly.Events.group=Blockly.genUid();Blockly.removeAllRanges();Blockly.Css.setCursor(Blockly.Css.Cursor.CLOSED);this.dragStartXY_=this.getRelativeToSurfaceXY();this.workspace.startDrag(a,this.dragStartXY_.x,
|
||||
this.dragStartXY_.y);Blockly.dragMode_=1;Blockly.BlockSvg.onMouseUpWrapper_=Blockly.bindEvent_(document,"mouseup",this,this.onMouseUp_);Blockly.BlockSvg.onMouseMoveWrapper_=Blockly.bindEvent_(document,"mousemove",this,this.onMouseMove_);this.draggedBubbles_=[];for(var b=this.getDescendants(),c=0,d;d=b[c];c++){d=d.getIcons();for(var e=0;e<d.length;e++){var f=d[e].getIconLocation();f.bubble=d[e];this.draggedBubbles_.push(f)}}}else return;a.stopPropagation()};
|
||||
|
@ -1109,23 +1108,23 @@ Blockly.BlockSvg.prototype.onMouseMove_=function(a){if(!("mousemove"==a.type&&1>
|
|||
b.x-this.dragStartXY_.x,b=b.y-this.dragStartXY_.y;d.translate_="translate("+c.x+","+c.y+")";d.setAttribute("transform",d.translate_+d.skew_);for(c=0;c<this.draggedBubbles_.length;c++)d=this.draggedBubbles_[c],d.bubble.setIconLocation(d.x+e,d.y+b);for(var d=this.getConnections_(!1),f=null,g=null,h=Blockly.SNAP_RADIUS,c=0;c<d.length;c++){var k=d[c],m=k.closest(h,e,b);m.connection&&(f=m.connection,g=k,h=m.radius)}Blockly.highlightedConnection_&&Blockly.highlightedConnection_!=f&&(Blockly.highlightedConnection_.unhighlight(),
|
||||
Blockly.highlightedConnection_=null,Blockly.localConnection_=null);f&&f!=Blockly.highlightedConnection_&&(f.highlight(),Blockly.highlightedConnection_=f,Blockly.localConnection_=g);this.isDeletable()&&this.workspace.isDeleteArea(a)}}a.stopPropagation()};Blockly.BlockSvg.prototype.updateMovable=function(){this.isMovable()?Blockly.addClass_(this.svgGroup_,"blocklyDraggable"):Blockly.removeClass_(this.svgGroup_,"blocklyDraggable")};
|
||||
Blockly.BlockSvg.prototype.setMovable=function(a){Blockly.BlockSvg.superClass_.setMovable.call(this,a);this.updateMovable()};Blockly.BlockSvg.prototype.setEditable=function(a){Blockly.BlockSvg.superClass_.setEditable.call(this,a);if(this.rendered)for(a=0;a<this.icons_.length;a++)this.icons_[a].updateEditable()};Blockly.BlockSvg.prototype.setShadow=function(a){Blockly.BlockSvg.superClass_.setShadow.call(this,a);this.updateColour()};Blockly.BlockSvg.prototype.getSvgRoot=function(){return this.svgGroup_};
|
||||
Blockly.BlockSvg.SEP_SPACE_X=10;Blockly.BlockSvg.SEP_SPACE_Y=10;Blockly.BlockSvg.INLINE_PADDING_Y=5;Blockly.BlockSvg.MIN_BLOCK_Y=25;Blockly.BlockSvg.TAB_HEIGHT=20;Blockly.BlockSvg.TAB_WIDTH=8;Blockly.BlockSvg.NOTCH_WIDTH=30;Blockly.BlockSvg.CORNER_RADIUS=4;Blockly.BlockSvg.START_HAT=!0;Blockly.BlockSvg.START_HAT_PATH="c 30,-15 70,-15 100,0";Blockly.BlockSvg.NOTCH_PATH_LEFT="l 6,4 3,0 6,-4";Blockly.BlockSvg.NOTCH_PATH_RIGHT="l -6,4 -3,0 -6,-4";
|
||||
Blockly.BlockSvg.TAB_PATH_DOWN="v 5 c 0,10 -"+Blockly.BlockSvg.TAB_WIDTH+",-8 -"+Blockly.BlockSvg.TAB_WIDTH+",7.5 s "+Blockly.BlockSvg.TAB_WIDTH+",-2.5 "+Blockly.BlockSvg.TAB_WIDTH+",7.5";Blockly.BlockSvg.TOP_LEFT_CORNER_START="m 0,"+Blockly.BlockSvg.CORNER_RADIUS;Blockly.BlockSvg.TOP_LEFT_CORNER="A "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,1 "+Blockly.BlockSvg.CORNER_RADIUS+",0";
|
||||
Blockly.BlockSvg.INNER_TOP_LEFT_CORNER=Blockly.BlockSvg.NOTCH_PATH_RIGHT+" h -"+(Blockly.BlockSvg.NOTCH_WIDTH-15-Blockly.BlockSvg.CORNER_RADIUS)+" a "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,0 -"+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS;Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER="a "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,0 "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS;
|
||||
Blockly.BlockSvg.prototype.dispose=function(a,b){Blockly.Field.startCache();Blockly.selected==this&&Blockly.terminateDrag_();Blockly.ContextMenu.currentBlock==this&&Blockly.ContextMenu.hide();b&&this.rendered&&(this.unplug(a),this.disposeUiEffect());this.rendered=!1;Blockly.BlockSvg.superClass_.dispose.call(this,a);Blockly.Events.disable();for(var c=this.getIcons(),d=0;d<c.length;d++)c[d].dispose();Blockly.Events.enable();goog.dom.removeNode(this.svgGroup_);this.svgPath_=this.svgGroup_=null;Blockly.Field.stopCache()};
|
||||
Blockly.BlockSvg.prototype.disposeUiEffect=function(){this.workspace.playAudio("delete");var a=Blockly.getSvgXY_(this.svgGroup_,this.workspace),b=this.svgGroup_.cloneNode(!0);b.translateX_=a.x;b.translateY_=a.y;b.setAttribute("transform","translate("+b.translateX_+","+b.translateY_+")");this.workspace.getParentSvg().appendChild(b);b.bBox_=b.getBBox();Blockly.BlockSvg.disposeUiStep_(b,this.RTL,new Date,this.workspace.scale)};
|
||||
Blockly.BlockSvg.disposeUiStep_=function(a,b,c,d){var e=(new Date-c)/150;1<e?goog.dom.removeNode(a):(a.setAttribute("transform","translate("+(a.translateX_+(b?-1:1)*a.bBox_.width*d/2*e)+","+(a.translateY_+a.bBox_.height*d*e)+") scale("+(1-e)*d+")"),setTimeout(function(){Blockly.BlockSvg.disposeUiStep_(a,b,c,d)},10))};
|
||||
Blockly.BlockSvg.prototype.connectionUiEffect=function(){this.workspace.playAudio("click");if(!(1>this.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.getParentSvg());
|
||||
Blockly.BlockSvg.connectionUiStep_(a,new Date,this.workspace.scale)}};Blockly.BlockSvg.connectionUiStep_=function(a,b,c){var d=(new Date-b)/150;1<d?goog.dom.removeNode(a):(a.setAttribute("r",25*d*c),a.style.opacity=1-d,Blockly.BlockSvg.disconnectUiStop_.pid_=setTimeout(function(){Blockly.BlockSvg.connectionUiStep_(a,b,c)},10))};
|
||||
Blockly.BlockSvg.prototype.disconnectUiEffect=function(){this.workspace.playAudio("disconnect");if(!(1>this.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<d?a.skew_="":(a.skew_="skewX("+Math.round(Math.sin(d*Math.PI*3)*(1-d)*b)+")",Blockly.BlockSvg.disconnectUiStop_.group=a,Blockly.BlockSvg.disconnectUiStop_.pid=setTimeout(function(){Blockly.BlockSvg.disconnectUiStep_(a,b,c)},10));a.setAttribute("transform",a.translate_+a.skew_)};
|
||||
Blockly.BlockSvg.disconnectUiStop_=function(){if(Blockly.BlockSvg.disconnectUiStop_.group){clearTimeout(Blockly.BlockSvg.disconnectUiStop_.pid);var a=Blockly.BlockSvg.disconnectUiStop_.group;a.skew_="";a.setAttribute("transform",a.translate_);Blockly.BlockSvg.disconnectUiStop_.group=null}};Blockly.BlockSvg.disconnectUiStop_.pid=0;Blockly.BlockSvg.disconnectUiStop_.group=null;
|
||||
Blockly.BlockSvg.prototype.updateColour=function(){var a=this.getColour(),b=goog.color.hexToRgb(a);this.isShadow()&&(b=goog.color.lighten(b,.6),a=goog.color.rgbArrayToHex(b));this.svgPath_.setAttribute("fill",a);a=goog.color.darken(b,.1);a=goog.color.rgbArrayToHex(a);this.svgPath_.setAttribute("stroke",a);a=this.getIcons();for(b=0;b<a.length;b++)a[b].updateColour();for(a=0;b=this.inputList[a];a++)for(var c=0,d;d=b.fieldRow[c];c++)d.setText(null)};Blockly.BlockSvg.prototype.updateDisabled=function(){};
|
||||
Blockly.BlockSvg.disconnectUiStop_=function(){if(Blockly.BlockSvg.disconnectUiStop_.group){clearTimeout(Blockly.BlockSvg.disconnectUiStop_.pid);var a=Blockly.BlockSvg.disconnectUiStop_.group;a.skew_="";a.setAttribute("transform",a.translate_);Blockly.BlockSvg.disconnectUiStop_.group=null}};Blockly.BlockSvg.disconnectUiStop_.pid=0;Blockly.BlockSvg.disconnectUiStop_.group=null;Blockly.BlockSvg.prototype.updateDisabled=function(){};
|
||||
Blockly.BlockSvg.prototype.getCommentText=function(){return this.comment?this.comment.getText().replace(/\s+$/,"").replace(/ +\n/g,"\n"):""};Blockly.BlockSvg.prototype.setCommentText=function(a){var b=!1;goog.isString(a)?(this.comment||(this.comment=new Blockly.Comment(this),b=!0),this.comment.setText(a)):this.comment&&(this.comment.dispose(),b=!0);b&&this.rendered&&(this.render(),this.bumpNeighbours_())};
|
||||
Blockly.BlockSvg.prototype.setWarningText=function(a,b){this.setWarningText.pid_||(this.setWarningText.pid_=Object.create(null));var c=b||"";if(c)this.setWarningText.pid_[c]&&(clearTimeout(this.setWarningText.pid_[c]),delete this.setWarningText.pid_[c]);else for(var d in this.setWarningText.pid_)clearTimeout(this.setWarningText.pid_[d]),delete this.setWarningText.pid_[d];if(2==Blockly.dragMode_){var e=this;this.setWarningText.pid_[c]=setTimeout(function(){e.workspace&&(delete e.setWarningText.pid_[c],
|
||||
e.setWarningText(a,c))},100)}else{this.isInFlyout&&(a=null);d=!1;if(goog.isString(a))this.warning||(this.warning=new Blockly.Warning(this),d=!0),this.warning.setText(a,c);else if(this.warning&&!c)this.warning.dispose(),d=!0;else if(this.warning){d=this.warning.getText();this.warning.setText("",c);var f=this.warning.getText();f||this.warning.dispose();d=d==f}d&&this.rendered&&(this.render(),this.bumpNeighbours_())}};
|
||||
Blockly.BlockSvg.prototype.setMutator=function(a){this.mutator&&this.mutator!==a&&this.mutator.dispose();a&&(a.block_=this,this.mutator=a,a.createIcon())};Blockly.BlockSvg.prototype.addSelect=function(){Blockly.addClass_(this.svgGroup_,"blocklySelected");this.svgGroup_.parentNode.appendChild(this.svgGroup_)};Blockly.BlockSvg.prototype.removeSelect=function(){Blockly.removeClass_(this.svgGroup_,"blocklySelected")};Blockly.BlockSvg.prototype.addDragging=function(){Blockly.addClass_(this.svgGroup_,"blocklyDragging")};
|
||||
Blockly.BlockSvg.prototype.removeDragging=function(){Blockly.removeClass_(this.svgGroup_,"blocklyDragging")};
|
||||
Blockly.BlockSvg.prototype.removeDragging=function(){Blockly.removeClass_(this.svgGroup_,"blocklyDragging")};Blockly.BlockSvg.render={};Blockly.BlockSvg.SEP_SPACE_X=10;Blockly.BlockSvg.SEP_SPACE_Y=10;Blockly.BlockSvg.INLINE_PADDING_Y=5;Blockly.BlockSvg.MIN_BLOCK_Y=25;Blockly.BlockSvg.TAB_HEIGHT=20;Blockly.BlockSvg.TAB_WIDTH=8;Blockly.BlockSvg.NOTCH_WIDTH=30;Blockly.BlockSvg.CORNER_RADIUS=4;Blockly.BlockSvg.START_HAT=!0;Blockly.BlockSvg.START_HAT_PATH="c 30,-15 70,-15 100,0";Blockly.BlockSvg.NOTCH_PATH_LEFT="l 6,4 3,0 6,-4";Blockly.BlockSvg.NOTCH_PATH_RIGHT="l -6,4 -3,0 -6,-4";
|
||||
Blockly.BlockSvg.TAB_PATH_DOWN="v 5 c 0,10 -"+Blockly.BlockSvg.TAB_WIDTH+",-8 -"+Blockly.BlockSvg.TAB_WIDTH+",7.5 s "+Blockly.BlockSvg.TAB_WIDTH+",-2.5 "+Blockly.BlockSvg.TAB_WIDTH+",7.5";Blockly.BlockSvg.TOP_LEFT_CORNER_START="m 0,"+Blockly.BlockSvg.CORNER_RADIUS;Blockly.BlockSvg.TOP_LEFT_CORNER="A "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,1 "+Blockly.BlockSvg.CORNER_RADIUS+",0";
|
||||
Blockly.BlockSvg.INNER_TOP_LEFT_CORNER=Blockly.BlockSvg.NOTCH_PATH_RIGHT+" h -"+(Blockly.BlockSvg.NOTCH_WIDTH-15-Blockly.BlockSvg.CORNER_RADIUS)+" a "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,0 -"+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS;Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER="a "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS+" 0 0,0 "+Blockly.BlockSvg.CORNER_RADIUS+","+Blockly.BlockSvg.CORNER_RADIUS;
|
||||
Blockly.BlockSvg.prototype.connectionUiEffect=function(){this.workspace.playAudio("click");if(!(1>this.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.getParentSvg());
|
||||
Blockly.BlockSvg.connectionUiStep_(a,new Date,this.workspace.scale)}};Blockly.BlockSvg.connectionUiStep_=function(a,b,c){var d=(new Date-b)/150;1<d?goog.dom.removeNode(a):(a.setAttribute("r",25*d*c),a.style.opacity=1-d,Blockly.BlockSvg.disconnectUiStop_.pid_=setTimeout(function(){Blockly.BlockSvg.connectionUiStep_(a,b,c)},10))};
|
||||
Blockly.BlockSvg.prototype.updateColour=function(){var a=this.getColour(),b=goog.color.hexToRgb(a);this.isShadow()&&(b=goog.color.lighten(b,.6),a=goog.color.rgbArrayToHex(b));this.svgPath_.setAttribute("fill",a);a=goog.color.darken(b,.1);a=goog.color.rgbArrayToHex(a);this.svgPath_.setAttribute("stroke",a);a=this.getIcons();for(b=0;b<a.length;b++)a[b].updateColour();for(a=0;b=this.inputList[a];a++)for(var c=0,d;d=b.fieldRow[c];c++)d.setText(null)};
|
||||
Blockly.BlockSvg.prototype.getHeightWidth=function(){var a=this.height,b=this.width,c=this.getNextBlock();c?(c=c.getHeightWidth(),a+=c.height-4,b=Math.max(b,c.width)):this.nextConnection||this.outputConnection||(a+=2);return{height:a,width:b}};
|
||||
Blockly.BlockSvg.prototype.render=function(a){Blockly.Field.startCache();this.rendered=!0;var b=Blockly.BlockSvg.SEP_SPACE_X;this.RTL&&(b=-b);for(var c=this.getIcons(),d=0;d<c.length;d++)b=c[d].renderIcon(b);b+=this.RTL?Blockly.BlockSvg.SEP_SPACE_X:-Blockly.BlockSvg.SEP_SPACE_X;c=this.renderCompute_(b);this.renderDraw_(b,c);!1!==a&&((a=this.getParent())?a.render(!0):Blockly.fireUiEvent(window,"resize"));Blockly.Field.stopCache()};
|
||||
Blockly.BlockSvg.prototype.renderFields_=function(a,b,c){c+=Blockly.BlockSvg.INLINE_PADDING_Y;this.RTL&&(b=-b);for(var d=0,e;e=a[d];d++){var f=e.getSvgRoot();f&&(this.RTL?(b-=e.renderSep+e.renderWidth,f.setAttribute("transform","translate("+b+","+c+")"),e.renderWidth&&(b-=Blockly.BlockSvg.SEP_SPACE_X)):(f.setAttribute("transform","translate("+(b+e.renderSep)+","+c+")"),e.renderWidth&&(b+=e.renderSep+e.renderWidth+Blockly.BlockSvg.SEP_SPACE_X)))}return this.RTL?-b:b};
|
||||
Blockly.BlockSvg.prototype.renderCompute_=function(a){var b=this.inputList,c=[];c.rightEdge=a+2*Blockly.BlockSvg.SEP_SPACE_X;if(this.previousConnection||this.nextConnection)c.rightEdge=Math.max(c.rightEdge,Blockly.BlockSvg.NOTCH_WIDTH+Blockly.BlockSvg.SEP_SPACE_X);for(var d=0,e=0,f=!1,g=!1,h=!1,k=void 0,m=0,n;n=b[m];m++)if(n.isVisible()){var l;k&&k!=Blockly.NEXT_STATEMENT&&n.type!=Blockly.NEXT_STATEMENT?l=c[c.length-1]:(k=n.type,l=[],l.type=n.type!=Blockly.NEXT_STATEMENT?Blockly.BlockSvg.INLINE:n.type,
|
||||
|
@ -1226,9 +1225,12 @@ this.workspace_.scale,viewTop:-this.workspace_.scrollY,viewLeft:-this.workspace_
|
|||
Blockly.Flyout.prototype.setMetrics_=function(a){var b=this.getMetrics_();b&&(!this.horizontalLayout_&&goog.isNumber(a.y)?this.workspace_.scrollY=-b.contentHeight*a.y-b.contentTop:this.horizontalLayout_&&goog.isNumber(a.x)&&(this.workspace_.scrollX=this.RTL?-b.contentWidth*a.x+b.contentLeft:-b.contentWidth*a.x-b.contentLeft),this.workspace_.translate(this.horizontalLayout_&&this.RTL?b.absoluteLeft+b.viewWidth-this.workspace_.scrollX:this.workspace_.scrollX+b.absoluteLeft,this.workspace_.scrollY+b.absoluteTop))};
|
||||
Blockly.Flyout.prototype.setVerticalOffset=function(a){this.verticalOffset_=a};
|
||||
Blockly.Flyout.prototype.position=function(){if(this.isVisible()){var a=this.targetWorkspace_.getMetrics();if(a){var b=this.horizontalLayout_?a.viewWidth:this.width_,b=b-this.CORNER_RADIUS;this.toolboxPosition_==Blockly.TOOLBOX_AT_RIGHT&&(b*=-1);this.setBackgroundPath_(b,this.horizontalLayout_?this.height_+this.verticalOffset_:a.viewHeight);b=a.absoluteLeft;this.toolboxPosition_==Blockly.TOOLBOX_AT_RIGHT&&(b+=a.viewWidth,b-=this.width_);var c=a.absoluteTop;this.toolboxPosition_==Blockly.TOOLBOX_AT_BOTTOM&&
|
||||
(c+=a.viewHeight,c-=this.height_);this.svgGroup_.setAttribute("transform","translate("+b+","+c+")");this.horizontalLayout_?this.width_=a.viewWidth:this.height_=a.viewHeight;this.scrollbar_&&this.scrollbar_.resize();this.svgGroup_.style.opacity=1}}};
|
||||
Blockly.Flyout.prototype.setBackgroundPath_=function(a,b){var c=this.toolboxPosition_==Blockly.TOOLBOX_AT_RIGHT,d=["M "+(c?this.width_:0)+",0"];d.push("h",a);d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?-this.CORNER_RADIUS:this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("v",Math.max(0,b-2*this.CORNER_RADIUS));d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?this.CORNER_RADIUS:-this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("h",-a);d.push("z");this.svgBackground_.setAttribute("d",
|
||||
d.join(" "))};Blockly.Flyout.prototype.scrollToStart=function(){this.scrollbar_.set(this.horizontalLayout_&&this.RTL?1E9:0)};Blockly.Flyout.prototype.wheel_=function(a){if(!this.horizontalLayout_){var b=a.deltaY;if(b){goog.userAgent.GECKO&&(b*=10);var c=this.getMetrics_(),b=c.viewTop+b,b=Math.min(b,c.contentHeight-c.viewHeight),b=Math.max(b,0);this.scrollbar_.set(b);a.preventDefault();a.stopPropagation()}}};Blockly.Flyout.prototype.isVisible=function(){return this.svgGroup_&&"block"==this.svgGroup_.style.display};
|
||||
(c+=a.viewHeight,c-=this.height_);this.svgGroup_.setAttribute("transform","translate("+b+","+c+")");this.horizontalLayout_?this.width_=a.viewWidth:this.height_=a.viewHeight;this.scrollbar_&&this.scrollbar_.resize();this.svgGroup_.style.opacity=1}}};Blockly.Flyout.prototype.setBackgroundPath_=function(a,b){this.horizontalLayout_?this.setBackgroundPathHorizontal_(a,b):this.setBackgroundPathVertical_(a,b)};
|
||||
Blockly.Flyout.prototype.setBackgroundPathVertical_=function(a,b){var c=this.toolboxPosition_==Blockly.TOOLBOX_AT_RIGHT,d=["M "+(c?this.width_:0)+",0"];d.push("h",a);d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?-this.CORNER_RADIUS:this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("v",Math.max(0,b-2*this.CORNER_RADIUS));d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,c?0:1,c?this.CORNER_RADIUS:-this.CORNER_RADIUS,this.CORNER_RADIUS);d.push("h",-a);d.push("z");this.svgBackground_.setAttribute("d",
|
||||
d.join(" "))};
|
||||
Blockly.Flyout.prototype.setBackgroundPathHorizontal_=function(a,b){var c=this.toolboxPosition_==Blockly.TOOLBOX_AT_TOP,d=["M 0,"+(c?0:this.CORNER_RADIUS)];c?(d.push("h",a+this.CORNER_RADIUS),d.push("v",b),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("h",-1*(a-this.CORNER_RADIUS)),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,-this.CORNER_RADIUS,-this.CORNER_RADIUS)):(d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,
|
||||
-this.CORNER_RADIUS),d.push("h",a-this.CORNER_RADIUS),d.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,1,this.CORNER_RADIUS,this.CORNER_RADIUS),d.push("v",b-this.CORNER_RADIUS),d.push("h",-a-this.CORNER_RADIUS));d.push("z");this.svgBackground_.setAttribute("d",d.join(" "))};Blockly.Flyout.prototype.scrollToStart=function(){this.scrollbar_.set(this.horizontalLayout_&&this.RTL?1E9:0)};
|
||||
Blockly.Flyout.prototype.wheel_=function(a){if(!this.horizontalLayout_){var b=a.deltaY;if(b){goog.userAgent.GECKO&&(b*=10);var c=this.getMetrics_(),b=c.viewTop+b,b=Math.min(b,c.contentHeight-c.viewHeight),b=Math.max(b,0);this.scrollbar_.set(b);a.preventDefault();a.stopPropagation()}}};Blockly.Flyout.prototype.isVisible=function(){return this.svgGroup_&&"block"==this.svgGroup_.style.display};
|
||||
Blockly.Flyout.prototype.hide=function(){if(this.isVisible()){this.svgGroup_.style.display="none";for(var a=0,b;b=this.listeners_[a];a++)Blockly.unbindEvent_(b);this.listeners_.length=0;this.reflowWrapper_&&(this.workspace_.removeChangeListener(this.reflowWrapper_),this.reflowWrapper_=null)}};
|
||||
Blockly.Flyout.prototype.show=function(a){this.hide();for(var b=this.workspace_.getTopBlocks(!1),c=0,d;d=b[c];c++)d.workspace==this.workspace_&&d.dispose(!1,!1);for(var c=0,e;e=this.buttons_[c];c++)goog.dom.removeNode(e);this.buttons_.length=0;a==Blockly.Variables.NAME_TYPE?a=Blockly.Variables.flyoutCategory(this.workspace_.targetWorkspace):a==Blockly.Procedures.NAME_TYPE&&(a=Blockly.Procedures.flyoutCategory(this.workspace_.targetWorkspace));for(var f=this.CORNER_RADIUS,b=[],g=[],c=this.permanentlyDisabled_.length=
|
||||
0;e=a[c];c++)e.tagName&&"BLOCK"==e.tagName.toUpperCase()&&(d=Blockly.Xml.domToBlock(this.workspace_,e),d.disabled&&this.permanentlyDisabled_.push(d),b.push(d),d=parseInt(e.getAttribute("gap"),10),g.push(isNaN(d)?3*f:d));this.svgGroup_.style.opacity=0;this.svgGroup_.style.display="block";a=f/this.workspace_.scale+Blockly.BlockSvg.TAB_WIDTH;for(c=0;d=b[c];c++){e=d.getDescendants();for(var h=0,k;k=e[h];h++)k.isInFlyout=!0;d.render();h=d.getSvgRoot();e=d.getHeightWidth();d.moveBy(this.horizontalLayout_&&
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
build.py
4
build.py
|
@ -439,10 +439,10 @@ class Gen_langfiles(threading.Thread):
|
|||
print("FAILED to create " + f)
|
||||
|
||||
def exclude_vertical(item):
|
||||
return not item.endswith("block_vertical_scratch.js")
|
||||
return not item.endswith("block_render_svg_vertical.js")
|
||||
|
||||
def exclude_horizontal(item):
|
||||
return not item.endswith("block_svg.js")
|
||||
return not item.endswith("block_render_svg_horizontal.js")
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
|
|
661
core/block_render_svg_horizontal.js
Normal file
661
core/block_render_svg_horizontal.js
Normal file
|
@ -0,0 +1,661 @@
|
|||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2012 Google Inc.
|
||||
* https://developers.google.com/blockly/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Methods for graphically rendering a block as SVG.
|
||||
* @author fraser@google.com (Neil Fraser)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.BlockSvg.render');
|
||||
|
||||
goog.require('Blockly.BlockSvg');
|
||||
|
||||
// UI constants for rendering blocks.
|
||||
/**
|
||||
* Horizontal space between elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.SEP_SPACE_X = 8;
|
||||
/**
|
||||
* Vertical space between elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.SEP_SPACE_Y = 8;
|
||||
/**
|
||||
* Vertical padding around inline elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INLINE_PADDING_Y = 5;
|
||||
/**
|
||||
* Height of user inputs
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.FIELD_HEIGHT = 32;
|
||||
/**
|
||||
* Width of user inputs
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.FIELD_WIDTH = 48;
|
||||
/**
|
||||
* Corner radius of number inputs
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS = 16;
|
||||
/**
|
||||
* Corner radius of text inputs
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS = 4;
|
||||
/**
|
||||
* Minimum width of a block.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.MIN_BLOCK_X = 40;
|
||||
/**
|
||||
* Width of horizontal puzzle tab.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TAB_WIDTH = 8;
|
||||
/**
|
||||
* Rounded corner radius.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.CORNER_RADIUS = 4;
|
||||
/**
|
||||
* Rounded corner radius.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS = 16;
|
||||
/**
|
||||
* Rounded notch radius.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_RADIUS = 2.5;
|
||||
/**
|
||||
* Height of connector notch, not including rounded corner at top and bottom.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_BASE_HEIGHT = 32;
|
||||
/**
|
||||
* Full height of connector notch including rounded corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_HEIGHT = Blockly.BlockSvg.NOTCH_BASE_HEIGHT + Blockly.BlockSvg.NOTCH_RADIUS;
|
||||
/**
|
||||
* Width of connector notch
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_WIDTH = Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4;
|
||||
/**
|
||||
* SVG path for drawing next/previous notch from top to bottom.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_PATH_DOWN =
|
||||
'a ' + -Blockly.BlockSvg.NOTCH_RADIUS + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 0 ' + Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'l ' + (Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ',' +
|
||||
(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + -Blockly.BlockSvg.NOTCH_RADIUS + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 1 ' + Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'v ' + (Blockly.BlockSvg.NOTCH_BASE_HEIGHT/2 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + -Blockly.BlockSvg.NOTCH_RADIUS + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 1 ' + -Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'l ' + (-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 + Blockly.BlockSvg.NOTCH_RADIUS) + ',' +
|
||||
(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + -Blockly.BlockSvg.NOTCH_RADIUS + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 0 ' + -Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + Blockly.BlockSvg.NOTCH_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing next/previous notch from bottom to top.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_PATH_UP =
|
||||
'a ' + Blockly.BlockSvg.NOTCH_RADIUS + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 1 ' + Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'l ' + (Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ',' +
|
||||
-1*(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + Blockly.BlockSvg.NOTCH_RADIUS + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 0 ' + Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'v ' + -1*(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/2 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + Blockly.BlockSvg.NOTCH_RADIUS + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 0 ' + -Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + -Blockly.BlockSvg.NOTCH_RADIUS +
|
||||
'l ' + (-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 + Blockly.BlockSvg.NOTCH_RADIUS) + ',' +
|
||||
(-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 + Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + Blockly.BlockSvg.NOTCH_RADIUS + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 1 ' + -Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + -Blockly.BlockSvg.NOTCH_RADIUS;
|
||||
/**
|
||||
* SVG start point for drawing the top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TOP_LEFT_CORNER_START =
|
||||
'm ' + Blockly.BlockSvg.CORNER_RADIUS + ',0';
|
||||
/**
|
||||
* SVG path for drawing the rounded top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TOP_LEFT_CORNER =
|
||||
'A ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
'0,' + Blockly.BlockSvg.CORNER_RADIUS;
|
||||
/**
|
||||
* SVG start point for drawing the top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.HAT_TOP_LEFT_CORNER_START =
|
||||
'm ' + Blockly.BlockSvg.HAT_CORNER_RADIUS + ',0';
|
||||
/**
|
||||
* SVG path for drawing the rounded top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.HAT_TOP_LEFT_CORNER =
|
||||
'A ' + Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ' 0 0,0 ' +
|
||||
'0,' + Blockly.BlockSvg.HAT_CORNER_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing the top-left corner of a statement input.
|
||||
* Includes the top notch, a horizontal space, and the rounded inside corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INNER_TOP_LEFT_CORNER =
|
||||
Blockly.BlockSvg.NOTCH_PATH_UP + ' h -' +
|
||||
(Blockly.BlockSvg.NOTCH_HEIGHT - 15 - Blockly.BlockSvg.CORNER_RADIUS) +
|
||||
' h -0.5 a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 -' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing the bottom-left corner of a statement input.
|
||||
* Includes the rounded inside corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER =
|
||||
'a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS;
|
||||
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, ripple) after a connection has been established.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.connectionUiEffect = function() {
|
||||
this.workspace.playAudio('click');
|
||||
if (this.workspace.scale < 1) {
|
||||
return; // Too small to care about visual effects.
|
||||
}
|
||||
// Determine the absolute coordinates of the inferior block.
|
||||
var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_),
|
||||
this.workspace);
|
||||
// Offset the coordinates based on the two connection types, fix scale.
|
||||
xy.x += 8 * this.workspace.scale;
|
||||
xy.y += this.height - (Blockly.BlockSvg.CORNER_RADIUS * 2 + Blockly.BlockSvg.NOTCH_HEIGHT / 2) - 8 * this.workspace.scale;
|
||||
|
||||
var ripple = Blockly.createSvgElement('circle',
|
||||
{'cx': xy.x, 'cy': xy.y, 'r': 0, 'fill': 'none',
|
||||
'stroke': '#EEE', 'stroke-width': 8},
|
||||
this.workspace.getParentSvg());
|
||||
|
||||
// Start the animation.
|
||||
Blockly.BlockSvg.connectionUiStep_(ripple, new Date(), this.workspace.scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand a ripple around a connection.
|
||||
* @param {!Element} ripple Element to animate.
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @param {number} workspaceScale Scale of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.connectionUiStep_ = function(ripple, start, workspaceScale) {
|
||||
var ms = (new Date()) - start;
|
||||
var percent = ms / 150;
|
||||
if (percent > 1) {
|
||||
goog.dom.removeNode(ripple);
|
||||
} else {
|
||||
ripple.setAttribute('r', percent * 25 * workspaceScale);
|
||||
ripple.style.opacity = 0.8 - percent;
|
||||
var closure = function() {
|
||||
Blockly.BlockSvg.connectionUiStep_(ripple, start, workspaceScale);
|
||||
};
|
||||
Blockly.BlockSvg.disconnectUiStop_.pid_ = setTimeout(closure, 10);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the colour of a block.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.updateColour = function() {
|
||||
// Render block fill
|
||||
var hexColour = this.parentBlock_ ? this.parentBlock_.getColour() : this.getColour();
|
||||
var rgb = goog.color.hexToRgb(hexColour);
|
||||
if (this.isShadow()) {
|
||||
this.svgPath_.setAttribute('fill', '#ffffff');
|
||||
} else {
|
||||
this.svgPath_.setAttribute('fill', hexColour);
|
||||
}
|
||||
|
||||
// Render block stroke
|
||||
var colorShift = goog.color.darken(rgb, 0.1);
|
||||
var strokeColor = goog.color.rgbArrayToHex(colorShift);
|
||||
this.svgPath_.setAttribute('stroke', strokeColor);
|
||||
|
||||
// Bump every dropdown to change its colour.
|
||||
for (var x = 0, input; input = this.inputList[x]; x++) {
|
||||
for (var y = 0, field; field = input.fieldRow[y]; y++) {
|
||||
field.setText(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a bounding box describing the dimensions of this block
|
||||
* and any blocks stacked below it.
|
||||
* @return {!{height: number, width: number}} Object with height and width properties.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.getHeightWidth = function() {
|
||||
var height = this.height;
|
||||
var width = this.width;
|
||||
// Recursively add size of subsequent blocks.
|
||||
var nextBlock = this.getNextBlock();
|
||||
if (nextBlock) {
|
||||
var nextHeightWidth = nextBlock.getHeightWidth();
|
||||
width += nextHeightWidth.width;
|
||||
height = Math.max(height, nextHeightWidth.height);
|
||||
} else if (!this.nextConnection && !this.outputConnection) {
|
||||
// Add a bit of margin under blocks with no bottom tab.
|
||||
height += 2;
|
||||
}
|
||||
return {height: height, width: width};
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the block.
|
||||
* Lays out and reflows a block based on its contents and settings.
|
||||
* @param {boolean=} opt_bubble If false, just render this block.
|
||||
* If true, also render block's parent, grandparent, etc. Defaults to true.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.render = function(opt_bubble) {
|
||||
Blockly.Field.startCache();
|
||||
this.rendered = true;
|
||||
|
||||
var metrics = this.renderCompute_();
|
||||
this.height = metrics.height;
|
||||
this.width = metrics.width;
|
||||
this.renderDraw_(metrics);
|
||||
|
||||
if (opt_bubble !== false) {
|
||||
// Render all blocks above this one (propagate a reflow).
|
||||
var parentBlock = this.getParent();
|
||||
if (parentBlock) {
|
||||
parentBlock.render(true);
|
||||
} else {
|
||||
// Top-most block. Fire an event to allow scrollbars to resize.
|
||||
Blockly.fireUiEvent(window, 'resize');
|
||||
}
|
||||
}
|
||||
Blockly.Field.stopCache();
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the height and widths for each row and field.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @return {!Array.<!Array.<!Object>>} 2D array of objects, each containing
|
||||
* position information.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderCompute_ = function() {
|
||||
var metrics = {
|
||||
statement: null,
|
||||
valueInput: null,
|
||||
icon: null,
|
||||
width: 0,
|
||||
height: 0,
|
||||
bayHeight: 0,
|
||||
bayWidth: 0,
|
||||
fieldWidth: 0,
|
||||
fieldHeight: 0,
|
||||
fieldRadius: 0,
|
||||
startHat: false,
|
||||
endHat: false
|
||||
};
|
||||
|
||||
if (this.nextConnection && !this.previousConnection) {
|
||||
metrics.startHat = true;
|
||||
}
|
||||
if (this.previousConnection && !this.nextConnection) {
|
||||
metrics.endHat = true;
|
||||
}
|
||||
|
||||
// Does block have a statement?
|
||||
for (var i = 0, input; input = this.inputList[i]; i++) {
|
||||
if (input.type == Blockly.NEXT_STATEMENT) {
|
||||
metrics.statement = input;
|
||||
// Compute minimum input size.
|
||||
// @todo Why 3?
|
||||
metrics.bayHeight = Blockly.BlockSvg.NOTCH_HEIGHT + 16 +
|
||||
Blockly.BlockSvg.CORNER_RADIUS * 3;
|
||||
metrics.bayWidth = Blockly.BlockSvg.NOTCH_WIDTH * 2 +
|
||||
Blockly.BlockSvg.MIN_BLOCK_X;
|
||||
// Expand input size if there is a connection.
|
||||
if (input.connection && input.connection.targetConnection) {
|
||||
var linkedBlock = input.connection.targetBlock();
|
||||
var bBox = linkedBlock.getHeightWidth();
|
||||
metrics.bayHeight = Math.max(metrics.bayHeight, bBox.height);
|
||||
metrics.bayWidth = Math.max(metrics.bayWidth, bBox.width);
|
||||
}
|
||||
}
|
||||
|
||||
// Find icon
|
||||
for (var j = 0, field; field = input.fieldRow[j]; j++) {
|
||||
if (field instanceof Blockly.FieldImage) {
|
||||
metrics.icon = field;
|
||||
}
|
||||
if (field instanceof Blockly.FieldTextInput) {
|
||||
var fieldBBox = field.textElement_.getBBox();
|
||||
metrics.fieldWidth = fieldBBox.width + Blockly.BlockSvg.SEP_SPACE_X;
|
||||
metrics.fieldHeight = fieldBBox.height;
|
||||
if (field.sourceBlock_.type === 'math_number') {
|
||||
metrics.fieldRadius = Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS;
|
||||
} else {
|
||||
metrics.fieldRadius = Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0, child; child = this.childBlocks_[i]; i++) {
|
||||
if (child.isShadow()) {
|
||||
metrics.valueInput = child;
|
||||
}
|
||||
}
|
||||
|
||||
var iconSize = (metrics.icon) ? metrics.icon.getSize() : new goog.math.Size(0,0);
|
||||
metrics.width =
|
||||
Blockly.BlockSvg.SEP_SPACE_X * 2 + iconSize.width + metrics.bayWidth;
|
||||
if (metrics.statement) {
|
||||
metrics.width += 2 * Blockly.BlockSvg.CORNER_RADIUS + 8;
|
||||
}
|
||||
if (this.outputConnection) {
|
||||
metrics.height = Blockly.BlockSvg.FIELD_HEIGHT;
|
||||
metrics.width = Blockly.BlockSvg.FIELD_WIDTH;
|
||||
} else {
|
||||
metrics.height = Math.max(
|
||||
Blockly.BlockSvg.SEP_SPACE_Y * 2 + iconSize.height,
|
||||
Blockly.BlockSvg.NOTCH_HEIGHT + 16 + Blockly.BlockSvg.CORNER_RADIUS * 2,
|
||||
metrics.bayHeight + Blockly.BlockSvg.SEP_SPACE_Y
|
||||
);
|
||||
}
|
||||
return metrics;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Draw the path of the block.
|
||||
* Move the fields to the correct locations.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each
|
||||
* containing position information.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDraw_ = function(metrics) {
|
||||
// Fetch the block's coordinates on the surface for use in anchoring
|
||||
// the connections.
|
||||
var connectionsXY = this.getRelativeToSurfaceXY();
|
||||
|
||||
// Assemble the block's path.
|
||||
var steps = [];
|
||||
|
||||
this.renderDrawLeft_(steps, connectionsXY, metrics);
|
||||
this.renderDrawBottom_(steps, connectionsXY, metrics);
|
||||
this.renderDrawRight_(steps, connectionsXY, metrics);
|
||||
this.renderDrawTop_(steps, connectionsXY, metrics);
|
||||
|
||||
var pathString = steps.join(' ');
|
||||
this.svgPath_.setAttribute('d', pathString);
|
||||
|
||||
if (this.RTL) {
|
||||
// Mirror the block's path.
|
||||
// This is awesome.
|
||||
this.svgPath_.setAttribute('transform', 'scale(-1 1)');
|
||||
}
|
||||
|
||||
// Position icon
|
||||
if (metrics.icon) {
|
||||
var icon = metrics.icon.getSvgRoot();
|
||||
var iconSize = metrics.icon.getSize();
|
||||
icon.setAttribute('transform',
|
||||
'translate(' + (metrics.width - iconSize.width - Blockly.BlockSvg.SEP_SPACE_X / 2) + ',' +
|
||||
(metrics.height - iconSize.height - Blockly.BlockSvg.SEP_SPACE_Y) + ')');
|
||||
// @todo RTL
|
||||
}
|
||||
|
||||
// Position value input
|
||||
if (metrics.valueInput) {
|
||||
var input = metrics.valueInput.getSvgRoot();
|
||||
var inputBBox = input.getBBox();
|
||||
var transformation = 'translate(' +
|
||||
(Blockly.BlockSvg.NOTCH_WIDTH + (metrics.bayWidth ? 8 + Blockly.BlockSvg.NOTCH_WIDTH*2 : 0) + metrics.bayWidth) + ',' +
|
||||
(metrics.height - 8) + ')';
|
||||
input.setAttribute('transform', transformation);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the left edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} rightEdge Minimum width of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawLeft_ =
|
||||
function(steps, connectionsXY, metrics) {
|
||||
|
||||
// Top edge.
|
||||
if (metrics.startHat) {
|
||||
// Hat block
|
||||
// Position the cursor at the top-left starting point.
|
||||
steps.push(Blockly.BlockSvg.HAT_TOP_LEFT_CORNER_START);
|
||||
// Top-left rounded corner.
|
||||
steps.push(Blockly.BlockSvg.HAT_TOP_LEFT_CORNER);
|
||||
steps.push('V', metrics.height - Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.previousConnection) {
|
||||
// Regular block
|
||||
// Position the cursor at the top-left starting point.
|
||||
steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER_START);
|
||||
// Top-left rounded corner.
|
||||
steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER);
|
||||
var cursorY = metrics.height - Blockly.BlockSvg.CORNER_RADIUS - 8 - Blockly.BlockSvg.NOTCH_HEIGHT;
|
||||
steps.push('V', cursorY);
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_DOWN);
|
||||
// Create previous block connection.
|
||||
var connectionX = connectionsXY.x;
|
||||
var connectionY = connectionsXY.y + metrics.height - Blockly.BlockSvg.CORNER_RADIUS * 2;
|
||||
this.previousConnection.moveTo(connectionX, connectionY);
|
||||
// This connection will be tightened when the parent renders.
|
||||
steps.push('V', metrics.height - Blockly.BlockSvg.CORNER_RADIUS);
|
||||
} else {
|
||||
// Input
|
||||
// Position the cursor at the top-left starting point.
|
||||
steps.push('m', metrics.fieldRadius + ',0');
|
||||
// Top-left rounded corner.
|
||||
steps.push(
|
||||
'A', metrics.fieldRadius + ',' + metrics.fieldRadius,
|
||||
'0', '0,0', '0,' + metrics.fieldRadius);
|
||||
steps.push(
|
||||
'V', metrics.height - metrics.fieldRadius);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the bottom edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each
|
||||
* containing position information.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @return {number} Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawBottom_ = function(steps,
|
||||
connectionsXY, metrics) {
|
||||
|
||||
if (metrics.startHat) {
|
||||
steps.push('a', Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.previousConnection) {
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
} else {
|
||||
// Input
|
||||
steps.push(
|
||||
'a', metrics.fieldRadius + ',' + metrics.fieldRadius,
|
||||
'0', '0,0', metrics.fieldRadius + ',' + metrics.fieldRadius);
|
||||
}
|
||||
|
||||
// Has statement
|
||||
if (metrics.statement) {
|
||||
steps.push('h', 8);
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('v', -8);
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_UP);
|
||||
// @todo Why 3?
|
||||
steps.push('v', -metrics.bayHeight + (Blockly.BlockSvg.CORNER_RADIUS * 3) + Blockly.BlockSvg.NOTCH_HEIGHT + 8);
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('h', metrics.bayWidth - (Blockly.BlockSvg.CORNER_RADIUS * 2));
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('v', metrics.bayHeight - (Blockly.BlockSvg.CORNER_RADIUS * 3) - Blockly.BlockSvg.NOTCH_HEIGHT - 8);
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_DOWN);
|
||||
steps.push('v', 8);
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
|
||||
// Create statement connection.
|
||||
// @todo RTL
|
||||
// var connectionX = connectionsXY.x + (this.RTL ? -cursorX : cursorX + 1);
|
||||
var connectionX = connectionsXY.x + Blockly.BlockSvg.CORNER_RADIUS * 2 + 8;
|
||||
var connectionY = connectionsXY.y + metrics.height - Blockly.BlockSvg.CORNER_RADIUS * 2;
|
||||
metrics.statement.connection.moveTo(connectionX, connectionY);
|
||||
if (metrics.statement.connection.targetConnection) {
|
||||
metrics.statement.connection.tighten_();
|
||||
}
|
||||
}
|
||||
|
||||
if (metrics.endHat) {
|
||||
steps.push('H', metrics.width - Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.nextConnection) {
|
||||
steps.push('H', metrics.width - Blockly.BlockSvg.CORNER_RADIUS);
|
||||
} else {
|
||||
// input
|
||||
steps.push('H', metrics.width - metrics.fieldRadius);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the right edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} cursorY Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawRight_ =
|
||||
function(steps, connectionsXY, metrics) {
|
||||
if (metrics.endHat) {
|
||||
steps.push('a', Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
steps.push('v', -8);
|
||||
} else if (this.nextConnection) {
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('v', -8);
|
||||
} else {
|
||||
// Input
|
||||
steps.push(
|
||||
'a', metrics.fieldRadius + ',' + metrics.fieldRadius,
|
||||
'0', '0,0', metrics.fieldRadius + ',' + -1*metrics.fieldRadius);
|
||||
steps.push('v', -1*(metrics.height - metrics.fieldRadius*2));
|
||||
}
|
||||
|
||||
if (metrics.endHat) {
|
||||
steps.push('V', Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.nextConnection) {
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_UP);
|
||||
|
||||
// Create next block connection.
|
||||
var connectionX;
|
||||
if (this.RTL) {
|
||||
connectionX = connectionsXY.x + metrics.width;
|
||||
} else {
|
||||
connectionX = connectionsXY.x + metrics.width;
|
||||
}
|
||||
var connectionY = connectionsXY.y + metrics.height - Blockly.BlockSvg.CORNER_RADIUS * 2;
|
||||
this.nextConnection.moveTo(connectionX, connectionY);
|
||||
if (this.nextConnection.targetConnection) {
|
||||
this.nextConnection.tighten_();
|
||||
}
|
||||
this.height += 4; // Height of tab.
|
||||
steps.push('V', Blockly.BlockSvg.CORNER_RADIUS);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the top edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} cursorY Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawTop_ =
|
||||
function(steps, connectionsXY, metrics) {
|
||||
if (metrics.endHat) {
|
||||
steps.push('a', Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ' 0 0,0 -' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.nextConnection) {
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 -' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
} else {
|
||||
steps.push(
|
||||
'a', metrics.fieldRadius + ',' + metrics.fieldRadius,
|
||||
'0', '0,0', '-' + metrics.fieldRadius + ',-' + metrics.fieldRadius);
|
||||
}
|
||||
steps.push('z');
|
||||
};
|
751
core/block_render_svg_vertical.js
Normal file
751
core/block_render_svg_vertical.js
Normal file
|
@ -0,0 +1,751 @@
|
|||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2012 Google Inc.
|
||||
* https://developers.google.com/blockly/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Methods for graphically rendering a block as SVG.
|
||||
* @author fraser@google.com (Neil Fraser)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.BlockSvg.render');
|
||||
|
||||
goog.require('Blockly.BlockSvg');
|
||||
|
||||
|
||||
// UI constants for rendering blocks.
|
||||
/**
|
||||
* Horizontal space between elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.SEP_SPACE_X = 10;
|
||||
/**
|
||||
* Vertical space between elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.SEP_SPACE_Y = 10;
|
||||
/**
|
||||
* Vertical padding around inline elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INLINE_PADDING_Y = 5;
|
||||
/**
|
||||
* Minimum height of a block.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.MIN_BLOCK_Y = 25;
|
||||
/**
|
||||
* Height of horizontal puzzle tab.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TAB_HEIGHT = 20;
|
||||
/**
|
||||
* Width of horizontal puzzle tab.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TAB_WIDTH = 8;
|
||||
/**
|
||||
* Width of vertical tab (inc left margin).
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_WIDTH = 30;
|
||||
/**
|
||||
* Rounded corner radius.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.CORNER_RADIUS = 4;
|
||||
/**
|
||||
* Do blocks with no previous or output connections have a 'hat' on top?
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.START_HAT = true;
|
||||
/**
|
||||
* Path of the top hat's curve.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.START_HAT_PATH = 'c 30,-15 70,-15 100,0';
|
||||
/**
|
||||
* SVG path for drawing next/previous notch from left to right.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_PATH_LEFT = 'l 6,4 3,0 6,-4';
|
||||
/**
|
||||
* SVG path for drawing next/previous notch from right to left.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_PATH_RIGHT = 'l -6,4 -3,0 -6,-4';
|
||||
/**
|
||||
* SVG path for drawing a horizontal puzzle tab from top to bottom.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TAB_PATH_DOWN = 'v 5 c 0,10 -' + Blockly.BlockSvg.TAB_WIDTH +
|
||||
',-8 -' + Blockly.BlockSvg.TAB_WIDTH + ',7.5 s ' +
|
||||
Blockly.BlockSvg.TAB_WIDTH + ',-2.5 ' + Blockly.BlockSvg.TAB_WIDTH + ',7.5';
|
||||
/**
|
||||
* SVG start point for drawing the top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TOP_LEFT_CORNER_START =
|
||||
'm 0,' + Blockly.BlockSvg.CORNER_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing the rounded top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TOP_LEFT_CORNER =
|
||||
'A ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',0';
|
||||
/**
|
||||
* SVG path for drawing the top-left corner of a statement input.
|
||||
* Includes the top notch, a horizontal space, and the rounded inside corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INNER_TOP_LEFT_CORNER =
|
||||
Blockly.BlockSvg.NOTCH_PATH_RIGHT + ' h -' +
|
||||
(Blockly.BlockSvg.NOTCH_WIDTH - 15 - Blockly.BlockSvg.CORNER_RADIUS) +
|
||||
' a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 -' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing the bottom-left corner of a statement input.
|
||||
* Includes the rounded inside corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER =
|
||||
'a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS;
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, ripple) after a connection has been established.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.connectionUiEffect = function() {
|
||||
this.workspace.playAudio('click');
|
||||
if (this.workspace.scale < 1) {
|
||||
return; // Too small to care about visual effects.
|
||||
}
|
||||
// Determine the absolute coordinates of the inferior block.
|
||||
var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_),
|
||||
this.workspace);
|
||||
// Offset the coordinates based on the two connection types, fix scale.
|
||||
if (this.outputConnection) {
|
||||
xy.x += (this.RTL ? 3 : -3) * this.workspace.scale;
|
||||
xy.y += 13 * this.workspace.scale;
|
||||
} else if (this.previousConnection) {
|
||||
xy.x += (this.RTL ? -23 : 23) * this.workspace.scale;
|
||||
xy.y += 3 * this.workspace.scale;
|
||||
}
|
||||
var ripple = Blockly.createSvgElement('circle',
|
||||
{'cx': xy.x, 'cy': xy.y, 'r': 0, 'fill': 'none',
|
||||
'stroke': '#888', 'stroke-width': 10},
|
||||
this.workspace.getParentSvg());
|
||||
// Start the animation.
|
||||
Blockly.BlockSvg.connectionUiStep_(ripple, new Date(), this.workspace.scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand a ripple around a connection.
|
||||
* @param {!Element} ripple Element to animate.
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @param {number} workspaceScale Scale of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.connectionUiStep_ = function(ripple, start, workspaceScale) {
|
||||
var ms = (new Date()) - start;
|
||||
var percent = ms / 150;
|
||||
if (percent > 1) {
|
||||
goog.dom.removeNode(ripple);
|
||||
} else {
|
||||
ripple.setAttribute('r', percent * 25 * workspaceScale);
|
||||
ripple.style.opacity = 1 - percent;
|
||||
var closure = function() {
|
||||
Blockly.BlockSvg.connectionUiStep_(ripple, start, workspaceScale);
|
||||
};
|
||||
Blockly.BlockSvg.disconnectUiStop_.pid_ = setTimeout(closure, 10);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the colour of a block.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.updateColour = function() {
|
||||
// Render block fill
|
||||
var hexColour = this.getColour();
|
||||
var rgb = goog.color.hexToRgb(hexColour);
|
||||
if (this.isShadow()) {
|
||||
rgb = goog.color.lighten(rgb, 0.6);
|
||||
hexColour = goog.color.rgbArrayToHex(rgb);
|
||||
}
|
||||
this.svgPath_.setAttribute('fill', hexColour);
|
||||
|
||||
// Render block stroke
|
||||
var colorShift = goog.color.darken(rgb, 0.1);
|
||||
var strokeColor = goog.color.rgbArrayToHex(colorShift);
|
||||
this.svgPath_.setAttribute('stroke', strokeColor);
|
||||
|
||||
// Render icon(s) if applicable
|
||||
var icons = this.getIcons();
|
||||
for (var i = 0; i < icons.length; i++) {
|
||||
icons[i].updateColour();
|
||||
}
|
||||
|
||||
// Bump every dropdown to change its colour.
|
||||
for (var x = 0, input; input = this.inputList[x]; x++) {
|
||||
for (var y = 0, field; field = input.fieldRow[y]; y++) {
|
||||
field.setText(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a bounding box describing the dimensions of this block
|
||||
* and any blocks stacked below it.
|
||||
* @return {!{height: number, width: number}} Object with height and width properties.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.getHeightWidth = function() {
|
||||
var height = this.height;
|
||||
var width = this.width;
|
||||
// Recursively add size of subsequent blocks.
|
||||
var nextBlock = this.getNextBlock();
|
||||
if (nextBlock) {
|
||||
var nextHeightWidth = nextBlock.getHeightWidth();
|
||||
height += nextHeightWidth.height - 4; // Height of tab.
|
||||
width = Math.max(width, nextHeightWidth.width);
|
||||
} else if (!this.nextConnection && !this.outputConnection) {
|
||||
// Add a bit of margin under blocks with no bottom tab.
|
||||
height += 2;
|
||||
}
|
||||
return {height: height, width: width};
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the block.
|
||||
* Lays out and reflows a block based on its contents and settings.
|
||||
* @param {boolean=} opt_bubble If false, just render this block.
|
||||
* If true, also render block's parent, grandparent, etc. Defaults to true.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.render = function(opt_bubble) {
|
||||
Blockly.Field.startCache();
|
||||
this.rendered = true;
|
||||
|
||||
var cursorX = Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (this.RTL) {
|
||||
cursorX = -cursorX;
|
||||
}
|
||||
// Move the icons into position.
|
||||
var icons = this.getIcons();
|
||||
for (var i = 0; i < icons.length; i++) {
|
||||
cursorX = icons[i].renderIcon(cursorX);
|
||||
}
|
||||
cursorX += this.RTL ?
|
||||
Blockly.BlockSvg.SEP_SPACE_X : -Blockly.BlockSvg.SEP_SPACE_X;
|
||||
// If there are no icons, cursorX will be 0, otherwise it will be the
|
||||
// width that the first label needs to move over by.
|
||||
|
||||
var inputRows = this.renderCompute_(cursorX);
|
||||
this.renderDraw_(cursorX, inputRows);
|
||||
|
||||
if (opt_bubble !== false) {
|
||||
// Render all blocks above this one (propagate a reflow).
|
||||
var parentBlock = this.getParent();
|
||||
if (parentBlock) {
|
||||
parentBlock.render(true);
|
||||
} else {
|
||||
// Top-most block. Fire an event to allow scrollbars to resize.
|
||||
Blockly.fireUiEvent(window, 'resize');
|
||||
}
|
||||
}
|
||||
Blockly.Field.stopCache();
|
||||
};
|
||||
|
||||
/**
|
||||
* Render a list of fields starting at the specified location.
|
||||
* @param {!Array.<!Blockly.Field>} fieldList List of fields.
|
||||
* @param {number} cursorX X-coordinate to start the fields.
|
||||
* @param {number} cursorY Y-coordinate to start the fields.
|
||||
* @return {number} X-coordinate of the end of the field row (plus a gap).
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderFields_ =
|
||||
function(fieldList, cursorX, cursorY) {
|
||||
cursorY += Blockly.BlockSvg.INLINE_PADDING_Y;
|
||||
if (this.RTL) {
|
||||
cursorX = -cursorX;
|
||||
}
|
||||
for (var t = 0, field; field = fieldList[t]; t++) {
|
||||
var root = field.getSvgRoot();
|
||||
if (!root) {
|
||||
continue;
|
||||
}
|
||||
if (this.RTL) {
|
||||
cursorX -= field.renderSep + field.renderWidth;
|
||||
root.setAttribute('transform',
|
||||
'translate(' + cursorX + ',' + cursorY + ')');
|
||||
if (field.renderWidth) {
|
||||
cursorX -= Blockly.BlockSvg.SEP_SPACE_X;
|
||||
}
|
||||
} else {
|
||||
root.setAttribute('transform',
|
||||
'translate(' + (cursorX + field.renderSep) + ',' + cursorY + ')');
|
||||
if (field.renderWidth) {
|
||||
cursorX += field.renderSep + field.renderWidth +
|
||||
Blockly.BlockSvg.SEP_SPACE_X;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.RTL ? -cursorX : cursorX;
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the height and widths for each row and field.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @return {!Array.<!Array.<!Object>>} 2D array of objects, each containing
|
||||
* position information.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderCompute_ = function(iconWidth) {
|
||||
var inputList = this.inputList;
|
||||
var inputRows = [];
|
||||
inputRows.rightEdge = iconWidth + Blockly.BlockSvg.SEP_SPACE_X * 2;
|
||||
if (this.previousConnection || this.nextConnection) {
|
||||
inputRows.rightEdge = Math.max(inputRows.rightEdge,
|
||||
Blockly.BlockSvg.NOTCH_WIDTH + Blockly.BlockSvg.SEP_SPACE_X);
|
||||
}
|
||||
var fieldValueWidth = 0; // Width of longest external value field.
|
||||
var fieldStatementWidth = 0; // Width of longest statement field.
|
||||
var hasValue = false;
|
||||
var hasStatement = false;
|
||||
var hasDummy = false;
|
||||
var lastType = undefined;
|
||||
|
||||
for (var i = 0, input; input = inputList[i]; i++) {
|
||||
if (!input.isVisible()) {
|
||||
continue;
|
||||
}
|
||||
var row;
|
||||
if (!lastType ||
|
||||
lastType == Blockly.NEXT_STATEMENT ||
|
||||
input.type == Blockly.NEXT_STATEMENT) {
|
||||
// Create new row.
|
||||
lastType = input.type;
|
||||
row = [];
|
||||
if (input.type != Blockly.NEXT_STATEMENT) {
|
||||
row.type = Blockly.BlockSvg.INLINE;
|
||||
} else {
|
||||
row.type = input.type;
|
||||
}
|
||||
row.height = 0;
|
||||
inputRows.push(row);
|
||||
} else {
|
||||
row = inputRows[inputRows.length - 1];
|
||||
}
|
||||
row.push(input);
|
||||
|
||||
// Compute minimum input size.
|
||||
input.renderHeight = Blockly.BlockSvg.MIN_BLOCK_Y;
|
||||
// The width is currently only needed for inline value inputs.
|
||||
if (input.type == Blockly.INPUT_VALUE) {
|
||||
input.renderWidth = Blockly.BlockSvg.TAB_WIDTH +
|
||||
Blockly.BlockSvg.SEP_SPACE_X * 1.25;
|
||||
} else {
|
||||
input.renderWidth = 0;
|
||||
}
|
||||
// Expand input size if there is a connection.
|
||||
if (input.connection && input.connection.targetConnection) {
|
||||
var linkedBlock = input.connection.targetBlock();
|
||||
var bBox = linkedBlock.getHeightWidth();
|
||||
input.renderHeight = Math.max(input.renderHeight, bBox.height);
|
||||
input.renderWidth = Math.max(input.renderWidth, bBox.width);
|
||||
}
|
||||
// Blocks have a one pixel shadow that should sometimes overhang.
|
||||
if (i == inputList.length - 1) {
|
||||
// Last value input should overhang.
|
||||
input.renderHeight--;
|
||||
} else if (input.type == Blockly.INPUT_VALUE &&
|
||||
inputList[i + 1] && inputList[i + 1].type == Blockly.NEXT_STATEMENT) {
|
||||
// Value input above statement input should overhang.
|
||||
input.renderHeight--;
|
||||
}
|
||||
|
||||
row.height = Math.max(row.height, input.renderHeight);
|
||||
input.fieldWidth = 0;
|
||||
if (inputRows.length == 1) {
|
||||
// The first row gets shifted to accommodate any icons.
|
||||
input.fieldWidth += this.RTL ? -iconWidth : iconWidth;
|
||||
}
|
||||
var previousFieldEditable = false;
|
||||
for (var j = 0, field; field = input.fieldRow[j]; j++) {
|
||||
if (j != 0) {
|
||||
input.fieldWidth += Blockly.BlockSvg.SEP_SPACE_X;
|
||||
}
|
||||
// Get the dimensions of the field.
|
||||
var fieldSize = field.getSize();
|
||||
field.renderWidth = fieldSize.width;
|
||||
field.renderSep = (previousFieldEditable && field.EDITABLE) ?
|
||||
Blockly.BlockSvg.SEP_SPACE_X : 0;
|
||||
input.fieldWidth += field.renderWidth + field.renderSep;
|
||||
row.height = Math.max(row.height, fieldSize.height);
|
||||
previousFieldEditable = field.EDITABLE;
|
||||
}
|
||||
|
||||
if (row.type != Blockly.BlockSvg.INLINE) {
|
||||
if (row.type == Blockly.NEXT_STATEMENT) {
|
||||
hasStatement = true;
|
||||
fieldStatementWidth = Math.max(fieldStatementWidth, input.fieldWidth);
|
||||
} else {
|
||||
if (row.type == Blockly.INPUT_VALUE) {
|
||||
hasValue = true;
|
||||
} else if (row.type == Blockly.DUMMY_INPUT) {
|
||||
hasDummy = true;
|
||||
}
|
||||
fieldValueWidth = Math.max(fieldValueWidth, input.fieldWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make inline rows a bit thicker in order to enclose the values.
|
||||
for (var y = 0, row; row = inputRows[y]; y++) {
|
||||
row.thicker = false;
|
||||
if (row.type == Blockly.BlockSvg.INLINE) {
|
||||
for (var z = 0, input; input = row[z]; z++) {
|
||||
if (input.type == Blockly.INPUT_VALUE) {
|
||||
row.height += 2 * Blockly.BlockSvg.INLINE_PADDING_Y;
|
||||
row.thicker = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the statement edge.
|
||||
// This is the width of a block where statements are nested.
|
||||
inputRows.statementEdge = 2 * Blockly.BlockSvg.SEP_SPACE_X +
|
||||
fieldStatementWidth;
|
||||
// Compute the preferred right edge. Inline blocks may extend beyond.
|
||||
// This is the width of the block where external inputs connect.
|
||||
if (hasStatement) {
|
||||
inputRows.rightEdge = Math.max(inputRows.rightEdge,
|
||||
inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH);
|
||||
}
|
||||
if (hasValue) {
|
||||
inputRows.rightEdge = Math.max(inputRows.rightEdge, fieldValueWidth +
|
||||
Blockly.BlockSvg.SEP_SPACE_X * 2 + Blockly.BlockSvg.TAB_WIDTH);
|
||||
} else if (hasDummy) {
|
||||
inputRows.rightEdge = Math.max(inputRows.rightEdge, fieldValueWidth +
|
||||
Blockly.BlockSvg.SEP_SPACE_X * 2);
|
||||
}
|
||||
|
||||
inputRows.hasValue = hasValue;
|
||||
inputRows.hasStatement = hasStatement;
|
||||
inputRows.hasDummy = hasDummy;
|
||||
return inputRows;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Draw the path of the block.
|
||||
* Move the fields to the correct locations.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each
|
||||
* containing position information.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDraw_ = function(iconWidth, inputRows) {
|
||||
this.startHat_ = false;
|
||||
// Should the top and bottom left corners be rounded or square?
|
||||
if (this.outputConnection) {
|
||||
this.squareTopLeftCorner_ = true;
|
||||
this.squareBottomLeftCorner_ = true;
|
||||
} else {
|
||||
this.squareTopLeftCorner_ = false;
|
||||
this.squareBottomLeftCorner_ = false;
|
||||
// If this block is in the middle of a stack, square the corners.
|
||||
if (this.previousConnection) {
|
||||
var prevBlock = this.previousConnection.targetBlock();
|
||||
if (prevBlock && prevBlock.getNextBlock() == this) {
|
||||
this.squareTopLeftCorner_ = true;
|
||||
}
|
||||
} else if (Blockly.BlockSvg.START_HAT) {
|
||||
// No output or previous connection.
|
||||
this.squareTopLeftCorner_ = true;
|
||||
this.startHat_ = true;
|
||||
inputRows.rightEdge = Math.max(inputRows.rightEdge, 100);
|
||||
}
|
||||
var nextBlock = this.getNextBlock();
|
||||
if (nextBlock) {
|
||||
this.squareBottomLeftCorner_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the block's coordinates on the surface for use in anchoring
|
||||
// the connections.
|
||||
var connectionsXY = this.getRelativeToSurfaceXY();
|
||||
|
||||
// Assemble the block's path.
|
||||
var steps = [];
|
||||
|
||||
this.renderDrawTop_(steps, connectionsXY,
|
||||
inputRows.rightEdge);
|
||||
var cursorY = this.renderDrawRight_(steps,
|
||||
connectionsXY, inputRows, iconWidth);
|
||||
this.renderDrawBottom_(steps, connectionsXY, cursorY);
|
||||
this.renderDrawLeft_(steps, connectionsXY, cursorY);
|
||||
|
||||
var pathString = steps.join(' ');
|
||||
this.svgPath_.setAttribute('d', pathString);
|
||||
|
||||
if (this.RTL) {
|
||||
// Mirror the block's path.
|
||||
// This is awesome.
|
||||
this.svgPath_.setAttribute('transform', 'scale(-1 1)');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the top edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} rightEdge Minimum width of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawTop_ =
|
||||
function(steps, connectionsXY, rightEdge) {
|
||||
// Position the cursor at the top-left starting point.
|
||||
if (this.squareTopLeftCorner_) {
|
||||
steps.push('m 0,0');
|
||||
if (this.startHat_) {
|
||||
steps.push(Blockly.BlockSvg.START_HAT_PATH);
|
||||
}
|
||||
} else {
|
||||
steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER_START);
|
||||
// Top-left rounded corner.
|
||||
steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER);
|
||||
}
|
||||
|
||||
// Top edge.
|
||||
if (this.previousConnection) {
|
||||
steps.push('H', Blockly.BlockSvg.NOTCH_WIDTH - 15);
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_LEFT);
|
||||
// Create previous block connection.
|
||||
var connectionX = connectionsXY.x + (this.RTL ?
|
||||
-Blockly.BlockSvg.NOTCH_WIDTH : Blockly.BlockSvg.NOTCH_WIDTH);
|
||||
var connectionY = connectionsXY.y;
|
||||
this.previousConnection.moveTo(connectionX, connectionY);
|
||||
// This connection will be tightened when the parent renders.
|
||||
}
|
||||
steps.push('H', rightEdge);
|
||||
this.width = rightEdge;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the right edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each
|
||||
* containing position information.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @return {number} Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawRight_ = function(steps,
|
||||
connectionsXY, inputRows, iconWidth) {
|
||||
var cursorX;
|
||||
var cursorY = 0;
|
||||
var connectionX, connectionY;
|
||||
for (var y = 0, row; row = inputRows[y]; y++) {
|
||||
cursorX = Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (y == 0) {
|
||||
cursorX += this.RTL ? -iconWidth : iconWidth;
|
||||
}
|
||||
|
||||
if (row.type == Blockly.BlockSvg.INLINE) {
|
||||
// Inline inputs.
|
||||
for (var x = 0, input; input = row[x]; x++) {
|
||||
var fieldX = cursorX;
|
||||
var fieldY = cursorY;
|
||||
if (row.thicker) {
|
||||
// Lower the field slightly.
|
||||
fieldY += Blockly.BlockSvg.INLINE_PADDING_Y;
|
||||
}
|
||||
// TODO: Align inline field rows (left/right/centre).
|
||||
cursorX = this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
if (input.type != Blockly.DUMMY_INPUT) {
|
||||
cursorX += input.renderWidth + Blockly.BlockSvg.SEP_SPACE_X;
|
||||
}
|
||||
if (input.type == Blockly.INPUT_VALUE) {
|
||||
// Create inline input connection.
|
||||
if (this.RTL) {
|
||||
connectionX = connectionsXY.x - cursorX -
|
||||
Blockly.BlockSvg.TAB_WIDTH + Blockly.BlockSvg.SEP_SPACE_X +
|
||||
input.renderWidth + 1;
|
||||
} else {
|
||||
connectionX = connectionsXY.x + cursorX +
|
||||
Blockly.BlockSvg.TAB_WIDTH - Blockly.BlockSvg.SEP_SPACE_X -
|
||||
input.renderWidth - 1;
|
||||
}
|
||||
connectionY = connectionsXY.y + cursorY +
|
||||
Blockly.BlockSvg.INLINE_PADDING_Y + 1;
|
||||
input.connection.moveTo(connectionX, connectionY);
|
||||
if (input.connection.targetConnection) {
|
||||
input.connection.tighten_();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cursorX = Math.max(cursorX, inputRows.rightEdge);
|
||||
this.width = Math.max(this.width, cursorX);
|
||||
steps.push('H', cursorX);
|
||||
steps.push('v', row.height);
|
||||
} else if (row.type == Blockly.DUMMY_INPUT) {
|
||||
// External naked field.
|
||||
var input = row[0];
|
||||
var fieldX = cursorX;
|
||||
var fieldY = cursorY;
|
||||
if (input.align != Blockly.ALIGN_LEFT) {
|
||||
var fieldRightX = inputRows.rightEdge - input.fieldWidth -
|
||||
2 * Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (inputRows.hasValue) {
|
||||
fieldRightX -= Blockly.BlockSvg.TAB_WIDTH;
|
||||
}
|
||||
if (input.align == Blockly.ALIGN_RIGHT) {
|
||||
fieldX += fieldRightX;
|
||||
} else if (input.align == Blockly.ALIGN_CENTRE) {
|
||||
fieldX += fieldRightX / 2;
|
||||
}
|
||||
}
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
steps.push('v', row.height);
|
||||
} else if (row.type == Blockly.NEXT_STATEMENT) {
|
||||
// Nested statement.
|
||||
var input = row[0];
|
||||
if (y == 0) {
|
||||
// If the first input is a statement stack, add a small row on top.
|
||||
steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y);
|
||||
cursorY += Blockly.BlockSvg.SEP_SPACE_Y;
|
||||
}
|
||||
var fieldX = cursorX;
|
||||
var fieldY = cursorY;
|
||||
if (input.align != Blockly.ALIGN_LEFT) {
|
||||
var fieldRightX = inputRows.statementEdge - input.fieldWidth -
|
||||
2 * Blockly.BlockSvg.SEP_SPACE_X;
|
||||
if (input.align == Blockly.ALIGN_RIGHT) {
|
||||
fieldX += fieldRightX;
|
||||
} else if (input.align == Blockly.ALIGN_CENTRE) {
|
||||
fieldX += fieldRightX / 2;
|
||||
}
|
||||
}
|
||||
this.renderFields_(input.fieldRow, fieldX, fieldY);
|
||||
cursorX = inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH;
|
||||
steps.push('H', cursorX);
|
||||
steps.push(Blockly.BlockSvg.INNER_TOP_LEFT_CORNER);
|
||||
steps.push('v', row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push(Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER);
|
||||
steps.push('H', inputRows.rightEdge);
|
||||
|
||||
// Create statement connection.
|
||||
connectionX = connectionsXY.x + (this.RTL ? -cursorX : cursorX + 1);
|
||||
connectionY = connectionsXY.y + cursorY + 1;
|
||||
input.connection.moveTo(connectionX, connectionY);
|
||||
if (input.connection.targetConnection) {
|
||||
input.connection.tighten_();
|
||||
this.width = Math.max(this.width, inputRows.statementEdge +
|
||||
input.connection.targetBlock().getHeightWidth().width);
|
||||
}
|
||||
if (y == inputRows.length - 1 ||
|
||||
inputRows[y + 1].type == Blockly.NEXT_STATEMENT) {
|
||||
// If the final input is a statement stack, add a small row underneath.
|
||||
// Consecutive statement stacks are also separated by a small divider.
|
||||
steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y);
|
||||
cursorY += Blockly.BlockSvg.SEP_SPACE_Y;
|
||||
}
|
||||
}
|
||||
cursorY += row.height;
|
||||
}
|
||||
if (!inputRows.length) {
|
||||
cursorY = Blockly.BlockSvg.MIN_BLOCK_Y;
|
||||
steps.push('V', cursorY);
|
||||
}
|
||||
return cursorY;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the bottom edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} cursorY Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawBottom_ =
|
||||
function(steps, connectionsXY, cursorY) {
|
||||
this.height = cursorY + 1; // Add one for the shadow.
|
||||
if (this.nextConnection) {
|
||||
steps.push('H', (Blockly.BlockSvg.NOTCH_WIDTH + (this.RTL ? 0.5 : - 0.5)) +
|
||||
' ' + Blockly.BlockSvg.NOTCH_PATH_RIGHT);
|
||||
// Create next block connection.
|
||||
var connectionX;
|
||||
if (this.RTL) {
|
||||
connectionX = connectionsXY.x - Blockly.BlockSvg.NOTCH_WIDTH;
|
||||
} else {
|
||||
connectionX = connectionsXY.x + Blockly.BlockSvg.NOTCH_WIDTH;
|
||||
}
|
||||
var connectionY = connectionsXY.y + cursorY + 1;
|
||||
this.nextConnection.moveTo(connectionX, connectionY);
|
||||
if (this.nextConnection.targetConnection) {
|
||||
this.nextConnection.tighten_();
|
||||
}
|
||||
this.height += 4; // Height of tab.
|
||||
}
|
||||
|
||||
// Should the bottom-left corner be rounded or square?
|
||||
if (this.squareBottomLeftCorner_) {
|
||||
steps.push('H 0');
|
||||
} else {
|
||||
steps.push('H', Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 -' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the left edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} cursorY Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawLeft_ =
|
||||
function(steps, connectionsXY, cursorY) {
|
||||
if (this.outputConnection) {
|
||||
// Create output connection.
|
||||
this.outputConnection.moveTo(connectionsXY.x, connectionsXY.y);
|
||||
// This connection will be tightened when the parent renders.
|
||||
if (this.outputConnection.getOutputShape() === Blockly.Connection.NUMBER) {
|
||||
steps.push('V', Blockly.BlockSvg.TAB_HEIGHT);
|
||||
steps.push('c 0,-10 -' + Blockly.BlockSvg.TAB_WIDTH + ',8 -' +
|
||||
Blockly.BlockSvg.TAB_WIDTH + ',-7.5 s ' + Blockly.BlockSvg.TAB_WIDTH +
|
||||
',2.5 ' + Blockly.BlockSvg.TAB_WIDTH + ',-7.5');
|
||||
this.width += Blockly.BlockSvg.TAB_WIDTH;
|
||||
}
|
||||
}
|
||||
steps.push('z');
|
||||
};
|
|
@ -320,27 +320,6 @@ Blockly.BlockSvg.prototype.snapToGrid = function() {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a bounding box describing the dimensions of this block
|
||||
* and any blocks stacked below it.
|
||||
* @return {!{height: number, width: number}} Object with height and width properties.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.getHeightWidth = function() {
|
||||
var height = this.height;
|
||||
var width = this.width;
|
||||
// Recursively add size of subsequent blocks.
|
||||
var nextBlock = this.getNextBlock();
|
||||
if (nextBlock) {
|
||||
var nextHeightWidth = nextBlock.getHeightWidth();
|
||||
width += nextHeightWidth.width;
|
||||
height = Math.max(height, nextHeightWidth.height);
|
||||
} else if (!this.nextConnection && !this.outputConnection) {
|
||||
// Add a bit of margin under blocks with no bottom tab.
|
||||
height += 2;
|
||||
}
|
||||
return {height: height, width: width};
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the next (or previous) FieldTextInput.
|
||||
* @param {Blockly.Field|Blockly.Block} start Current location.
|
||||
|
@ -763,169 +742,6 @@ Blockly.BlockSvg.prototype.getSvgRoot = function() {
|
|||
return this.svgGroup_;
|
||||
};
|
||||
|
||||
// UI constants for rendering blocks.
|
||||
/**
|
||||
* Horizontal space between elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.SEP_SPACE_X = 8;
|
||||
/**
|
||||
* Vertical space between elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.SEP_SPACE_Y = 8;
|
||||
/**
|
||||
* Vertical padding around inline elements.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INLINE_PADDING_Y = 5;
|
||||
/**
|
||||
* Height of user inputs
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.FIELD_HEIGHT = 32;
|
||||
/**
|
||||
* Width of user inputs
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.FIELD_WIDTH = 48;
|
||||
/**
|
||||
* Corner radius of number inputs
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS = 16;
|
||||
/**
|
||||
* Corner radius of text inputs
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS = 4;
|
||||
/**
|
||||
* Minimum width of a block.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.MIN_BLOCK_X = 40;
|
||||
/**
|
||||
* Width of horizontal puzzle tab.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TAB_WIDTH = 8;
|
||||
/**
|
||||
* Rounded corner radius.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.CORNER_RADIUS = 4;
|
||||
/**
|
||||
* Rounded corner radius.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS = 16;
|
||||
/**
|
||||
* Rounded notch radius.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_RADIUS = 2.5;
|
||||
/**
|
||||
* Height of connector notch, not including rounded corner at top and bottom.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_BASE_HEIGHT = 32;
|
||||
/**
|
||||
* Full height of connector notch including rounded corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_HEIGHT = Blockly.BlockSvg.NOTCH_BASE_HEIGHT + Blockly.BlockSvg.NOTCH_RADIUS;
|
||||
/**
|
||||
* Width of connector notch
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_WIDTH = Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4;
|
||||
/**
|
||||
* SVG path for drawing next/previous notch from top to bottom.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_PATH_DOWN =
|
||||
'a ' + -Blockly.BlockSvg.NOTCH_RADIUS + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 0 ' + Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'l ' + (Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ',' +
|
||||
(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + -Blockly.BlockSvg.NOTCH_RADIUS + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 1 ' + Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'v ' + (Blockly.BlockSvg.NOTCH_BASE_HEIGHT/2 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + -Blockly.BlockSvg.NOTCH_RADIUS + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 1 ' + -Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'l ' + (-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 + Blockly.BlockSvg.NOTCH_RADIUS) + ',' +
|
||||
(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + -Blockly.BlockSvg.NOTCH_RADIUS + ',' + Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 0 ' + -Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + Blockly.BlockSvg.NOTCH_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing next/previous notch from bottom to top.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.NOTCH_PATH_UP =
|
||||
'a ' + Blockly.BlockSvg.NOTCH_RADIUS + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 1 ' + Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'l ' + (Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ',' +
|
||||
-1*(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + Blockly.BlockSvg.NOTCH_RADIUS + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 0 ' + Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'v ' + -1*(Blockly.BlockSvg.NOTCH_BASE_HEIGHT/2 - Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + Blockly.BlockSvg.NOTCH_RADIUS + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 0 ' + -Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + -Blockly.BlockSvg.NOTCH_RADIUS +
|
||||
'l ' + (-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 + Blockly.BlockSvg.NOTCH_RADIUS) + ',' +
|
||||
(-Blockly.BlockSvg.NOTCH_BASE_HEIGHT/4 + Blockly.BlockSvg.NOTCH_RADIUS) + ' ' +
|
||||
'a ' + Blockly.BlockSvg.NOTCH_RADIUS + ',' + -Blockly.BlockSvg.NOTCH_RADIUS + ' ' +
|
||||
'0 0 1 ' + -Blockly.BlockSvg.NOTCH_RADIUS/2 + ',' + -Blockly.BlockSvg.NOTCH_RADIUS;
|
||||
/**
|
||||
* SVG start point for drawing the top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TOP_LEFT_CORNER_START =
|
||||
'm ' + Blockly.BlockSvg.CORNER_RADIUS + ',0';
|
||||
/**
|
||||
* SVG path for drawing the rounded top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.TOP_LEFT_CORNER =
|
||||
'A ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
'0,' + Blockly.BlockSvg.CORNER_RADIUS;
|
||||
/**
|
||||
* SVG start point for drawing the top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.HAT_TOP_LEFT_CORNER_START =
|
||||
'm ' + Blockly.BlockSvg.HAT_CORNER_RADIUS + ',0';
|
||||
/**
|
||||
* SVG path for drawing the rounded top-left corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.HAT_TOP_LEFT_CORNER =
|
||||
'A ' + Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ' 0 0,0 ' +
|
||||
'0,' + Blockly.BlockSvg.HAT_CORNER_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing the top-left corner of a statement input.
|
||||
* Includes the top notch, a horizontal space, and the rounded inside corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INNER_TOP_LEFT_CORNER =
|
||||
Blockly.BlockSvg.NOTCH_PATH_UP + ' h -' +
|
||||
(Blockly.BlockSvg.NOTCH_HEIGHT - 15 - Blockly.BlockSvg.CORNER_RADIUS) +
|
||||
' h -0.5 a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 -' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS;
|
||||
/**
|
||||
* SVG path for drawing the bottom-left corner of a statement input.
|
||||
* Includes the rounded inside corner.
|
||||
* @const
|
||||
*/
|
||||
Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER =
|
||||
'a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS;
|
||||
|
||||
/**
|
||||
* Dispose of this block.
|
||||
* @param {boolean} healStack If true, then try to heal any gap by connecting
|
||||
|
@ -1016,52 +832,6 @@ Blockly.BlockSvg.disposeUiStep_ = function(clone, rtl, start, workspaceScale) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, ripple) after a connection has been established.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.connectionUiEffect = function() {
|
||||
this.workspace.playAudio('click');
|
||||
if (this.workspace.scale < 1) {
|
||||
return; // Too small to care about visual effects.
|
||||
}
|
||||
// Determine the absolute coordinates of the inferior block.
|
||||
var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_),
|
||||
this.workspace);
|
||||
// Offset the coordinates based on the two connection types, fix scale.
|
||||
xy.x += 8 * this.workspace.scale;
|
||||
xy.y += this.height - (Blockly.BlockSvg.CORNER_RADIUS * 2 + Blockly.BlockSvg.NOTCH_HEIGHT / 2) - 8 * this.workspace.scale;
|
||||
|
||||
var ripple = Blockly.createSvgElement('circle',
|
||||
{'cx': xy.x, 'cy': xy.y, 'r': 0, 'fill': 'none',
|
||||
'stroke': '#EEE', 'stroke-width': 8},
|
||||
this.workspace.getParentSvg());
|
||||
|
||||
// Start the animation.
|
||||
Blockly.BlockSvg.connectionUiStep_(ripple, new Date(), this.workspace.scale);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand a ripple around a connection.
|
||||
* @param {!Element} ripple Element to animate.
|
||||
* @param {!Date} start Date of animation's start.
|
||||
* @param {number} workspaceScale Scale of workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.connectionUiStep_ = function(ripple, start, workspaceScale) {
|
||||
var ms = (new Date()) - start;
|
||||
var percent = ms / 150;
|
||||
if (percent > 1) {
|
||||
goog.dom.removeNode(ripple);
|
||||
} else {
|
||||
ripple.setAttribute('r', percent * 25 * workspaceScale);
|
||||
ripple.style.opacity = 0.8 - percent;
|
||||
var closure = function() {
|
||||
Blockly.BlockSvg.connectionUiStep_(ripple, start, workspaceScale);
|
||||
};
|
||||
Blockly.BlockSvg.disconnectUiStop_.pid_ = setTimeout(closure, 10);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Play some UI effects (sound, animation) when disconnecting a block.
|
||||
*/
|
||||
|
@ -1137,32 +907,6 @@ Blockly.BlockSvg.disconnectUiStop_.pid = 0;
|
|||
*/
|
||||
Blockly.BlockSvg.disconnectUiStop_.group = null;
|
||||
|
||||
/**
|
||||
* Change the colour of a block.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.updateColour = function() {
|
||||
// Render block fill
|
||||
var hexColour = this.parentBlock_ ? this.parentBlock_.getColour() : this.getColour();
|
||||
var rgb = goog.color.hexToRgb(hexColour);
|
||||
if (this.isShadow()) {
|
||||
this.svgPath_.setAttribute('fill', '#ffffff');
|
||||
} else {
|
||||
this.svgPath_.setAttribute('fill', hexColour);
|
||||
}
|
||||
|
||||
// Render block stroke
|
||||
var colorShift = goog.color.darken(rgb, 0.1);
|
||||
var strokeColor = goog.color.rgbArrayToHex(colorShift);
|
||||
this.svgPath_.setAttribute('stroke', strokeColor);
|
||||
|
||||
// Bump every dropdown to change its colour.
|
||||
for (var x = 0, input; input = this.inputList[x]; x++) {
|
||||
for (var y = 0, field; field = input.fieldRow[y]; y++) {
|
||||
field.setText(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Enable or disable a block.
|
||||
*/
|
||||
|
@ -1326,378 +1070,3 @@ Blockly.BlockSvg.prototype.removeDragging = function() {
|
|||
Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),
|
||||
'blocklyDragging');
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the block.
|
||||
* Lays out and reflows a block based on its contents and settings.
|
||||
* @param {boolean=} opt_bubble If false, just render this block.
|
||||
* If true, also render block's parent, grandparent, etc. Defaults to true.
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.render = function(opt_bubble) {
|
||||
Blockly.Field.startCache();
|
||||
this.rendered = true;
|
||||
|
||||
var metrics = this.renderCompute_();
|
||||
this.height = metrics.height;
|
||||
this.width = metrics.width;
|
||||
this.renderDraw_(metrics);
|
||||
|
||||
if (opt_bubble !== false) {
|
||||
// Render all blocks above this one (propagate a reflow).
|
||||
var parentBlock = this.getParent();
|
||||
if (parentBlock) {
|
||||
parentBlock.render(true);
|
||||
} else {
|
||||
// Top-most block. Fire an event to allow scrollbars to resize.
|
||||
Blockly.fireUiEvent(window, 'resize');
|
||||
}
|
||||
}
|
||||
Blockly.Field.stopCache();
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the height and widths for each row and field.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @return {!Array.<!Array.<!Object>>} 2D array of objects, each containing
|
||||
* position information.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderCompute_ = function() {
|
||||
var metrics = {
|
||||
statement: null,
|
||||
valueInput: null,
|
||||
icon: null,
|
||||
width: 0,
|
||||
height: 0,
|
||||
bayHeight: 0,
|
||||
bayWidth: 0,
|
||||
fieldWidth: 0,
|
||||
fieldHeight: 0,
|
||||
fieldRadius: 0,
|
||||
startHat: false,
|
||||
endHat: false
|
||||
};
|
||||
|
||||
if (this.nextConnection && !this.previousConnection) {
|
||||
metrics.startHat = true;
|
||||
}
|
||||
if (this.previousConnection && !this.nextConnection) {
|
||||
metrics.endHat = true;
|
||||
}
|
||||
|
||||
// Does block have a statement?
|
||||
for (var i = 0, input; input = this.inputList[i]; i++) {
|
||||
if (input.type == Blockly.NEXT_STATEMENT) {
|
||||
metrics.statement = input;
|
||||
// Compute minimum input size.
|
||||
// @todo Why 3?
|
||||
metrics.bayHeight = Blockly.BlockSvg.NOTCH_HEIGHT + 16 +
|
||||
Blockly.BlockSvg.CORNER_RADIUS * 3;
|
||||
metrics.bayWidth = Blockly.BlockSvg.NOTCH_WIDTH * 2 +
|
||||
Blockly.BlockSvg.MIN_BLOCK_X;
|
||||
// Expand input size if there is a connection.
|
||||
if (input.connection && input.connection.targetConnection) {
|
||||
var linkedBlock = input.connection.targetBlock();
|
||||
var bBox = linkedBlock.getHeightWidth();
|
||||
metrics.bayHeight = Math.max(metrics.bayHeight, bBox.height);
|
||||
metrics.bayWidth = Math.max(metrics.bayWidth, bBox.width);
|
||||
}
|
||||
}
|
||||
|
||||
// Find icon
|
||||
for (var j = 0, field; field = input.fieldRow[j]; j++) {
|
||||
if (field instanceof Blockly.FieldImage) {
|
||||
metrics.icon = field;
|
||||
}
|
||||
if (field instanceof Blockly.FieldTextInput) {
|
||||
var fieldBBox = field.textElement_.getBBox();
|
||||
metrics.fieldWidth = fieldBBox.width + Blockly.BlockSvg.SEP_SPACE_X;
|
||||
metrics.fieldHeight = fieldBBox.height;
|
||||
if (field.sourceBlock_.type === 'math_number') {
|
||||
metrics.fieldRadius = Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS;
|
||||
} else {
|
||||
metrics.fieldRadius = Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0, child; child = this.childBlocks_[i]; i++) {
|
||||
if (child.isShadow()) {
|
||||
metrics.valueInput = child;
|
||||
}
|
||||
}
|
||||
|
||||
var iconSize = (metrics.icon) ? metrics.icon.getSize() : new goog.math.Size(0,0);
|
||||
metrics.width =
|
||||
Blockly.BlockSvg.SEP_SPACE_X * 2 + iconSize.width + metrics.bayWidth;
|
||||
if (metrics.statement) {
|
||||
metrics.width += 2 * Blockly.BlockSvg.CORNER_RADIUS + 8;
|
||||
}
|
||||
if (this.outputConnection) {
|
||||
metrics.height = Blockly.BlockSvg.FIELD_HEIGHT;
|
||||
metrics.width = Blockly.BlockSvg.FIELD_WIDTH;
|
||||
} else {
|
||||
metrics.height = Math.max(
|
||||
Blockly.BlockSvg.SEP_SPACE_Y * 2 + iconSize.height,
|
||||
Blockly.BlockSvg.NOTCH_HEIGHT + 16 + Blockly.BlockSvg.CORNER_RADIUS * 2,
|
||||
metrics.bayHeight + Blockly.BlockSvg.SEP_SPACE_Y
|
||||
);
|
||||
}
|
||||
return metrics;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Draw the path of the block.
|
||||
* Move the fields to the correct locations.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each
|
||||
* containing position information.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDraw_ = function(metrics) {
|
||||
// Fetch the block's coordinates on the surface for use in anchoring
|
||||
// the connections.
|
||||
var connectionsXY = this.getRelativeToSurfaceXY();
|
||||
|
||||
// Assemble the block's path.
|
||||
var steps = [];
|
||||
|
||||
this.renderDrawLeft_(steps, connectionsXY, metrics);
|
||||
this.renderDrawBottom_(steps, connectionsXY, metrics);
|
||||
this.renderDrawRight_(steps, connectionsXY, metrics);
|
||||
this.renderDrawTop_(steps, connectionsXY, metrics);
|
||||
|
||||
var pathString = steps.join(' ');
|
||||
this.svgPath_.setAttribute('d', pathString);
|
||||
|
||||
if (this.RTL) {
|
||||
// Mirror the block's path.
|
||||
// This is awesome.
|
||||
this.svgPath_.setAttribute('transform', 'scale(-1 1)');
|
||||
}
|
||||
|
||||
// Position icon
|
||||
if (metrics.icon) {
|
||||
var icon = metrics.icon.getSvgRoot();
|
||||
var iconSize = metrics.icon.getSize();
|
||||
icon.setAttribute('transform',
|
||||
'translate(' + (metrics.width - iconSize.width - Blockly.BlockSvg.SEP_SPACE_X / 2) + ',' +
|
||||
(metrics.height - iconSize.height - Blockly.BlockSvg.SEP_SPACE_Y) + ')');
|
||||
// @todo RTL
|
||||
}
|
||||
|
||||
// Position value input
|
||||
if (metrics.valueInput) {
|
||||
var input = metrics.valueInput.getSvgRoot();
|
||||
var inputBBox = input.getBBox();
|
||||
var transformation = 'translate(' +
|
||||
(Blockly.BlockSvg.NOTCH_WIDTH + (metrics.bayWidth ? 8 + Blockly.BlockSvg.NOTCH_WIDTH*2 : 0) + metrics.bayWidth) + ',' +
|
||||
(metrics.height - 8) + ')';
|
||||
input.setAttribute('transform', transformation);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the left edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} rightEdge Minimum width of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawLeft_ =
|
||||
function(steps, connectionsXY, metrics) {
|
||||
|
||||
// Top edge.
|
||||
if (metrics.startHat) {
|
||||
// Hat block
|
||||
// Position the cursor at the top-left starting point.
|
||||
steps.push(Blockly.BlockSvg.HAT_TOP_LEFT_CORNER_START);
|
||||
// Top-left rounded corner.
|
||||
steps.push(Blockly.BlockSvg.HAT_TOP_LEFT_CORNER);
|
||||
steps.push('V', metrics.height - Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.previousConnection) {
|
||||
// Regular block
|
||||
// Position the cursor at the top-left starting point.
|
||||
steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER_START);
|
||||
// Top-left rounded corner.
|
||||
steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER);
|
||||
var cursorY = metrics.height - Blockly.BlockSvg.CORNER_RADIUS - 8 - Blockly.BlockSvg.NOTCH_HEIGHT;
|
||||
steps.push('V', cursorY);
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_DOWN);
|
||||
// Create previous block connection.
|
||||
var connectionX = connectionsXY.x;
|
||||
var connectionY = connectionsXY.y + metrics.height - Blockly.BlockSvg.CORNER_RADIUS * 2;
|
||||
this.previousConnection.moveTo(connectionX, connectionY);
|
||||
// This connection will be tightened when the parent renders.
|
||||
steps.push('V', metrics.height - Blockly.BlockSvg.CORNER_RADIUS);
|
||||
} else {
|
||||
// Input
|
||||
// Position the cursor at the top-left starting point.
|
||||
steps.push('m', metrics.fieldRadius + ',0');
|
||||
// Top-left rounded corner.
|
||||
steps.push(
|
||||
'A', metrics.fieldRadius + ',' + metrics.fieldRadius,
|
||||
'0', '0,0', '0,' + metrics.fieldRadius);
|
||||
steps.push(
|
||||
'V', metrics.height - metrics.fieldRadius);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the bottom edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each
|
||||
* containing position information.
|
||||
* @param {number} iconWidth Offset of first row due to icons.
|
||||
* @return {number} Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawBottom_ = function(steps,
|
||||
connectionsXY, metrics) {
|
||||
|
||||
if (metrics.startHat) {
|
||||
steps.push('a', Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.previousConnection) {
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
} else {
|
||||
// Input
|
||||
steps.push(
|
||||
'a', metrics.fieldRadius + ',' + metrics.fieldRadius,
|
||||
'0', '0,0', metrics.fieldRadius + ',' + metrics.fieldRadius);
|
||||
}
|
||||
|
||||
// Has statement
|
||||
if (metrics.statement) {
|
||||
steps.push('h', 8);
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('v', -8);
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_UP);
|
||||
// @todo Why 3?
|
||||
steps.push('v', -metrics.bayHeight + (Blockly.BlockSvg.CORNER_RADIUS * 3) + Blockly.BlockSvg.NOTCH_HEIGHT + 8);
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('h', metrics.bayWidth - (Blockly.BlockSvg.CORNER_RADIUS * 2));
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('v', metrics.bayHeight - (Blockly.BlockSvg.CORNER_RADIUS * 3) - Blockly.BlockSvg.NOTCH_HEIGHT - 8);
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_DOWN);
|
||||
steps.push('v', 8);
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
|
||||
// Create statement connection.
|
||||
// @todo RTL
|
||||
// var connectionX = connectionsXY.x + (this.RTL ? -cursorX : cursorX + 1);
|
||||
var connectionX = connectionsXY.x + Blockly.BlockSvg.CORNER_RADIUS * 2 + 8;
|
||||
var connectionY = connectionsXY.y + metrics.height - Blockly.BlockSvg.CORNER_RADIUS * 2;
|
||||
metrics.statement.connection.moveTo(connectionX, connectionY);
|
||||
if (metrics.statement.connection.targetConnection) {
|
||||
metrics.statement.connection.tighten_();
|
||||
}
|
||||
}
|
||||
|
||||
if (metrics.endHat) {
|
||||
steps.push('H', metrics.width - Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.nextConnection) {
|
||||
steps.push('H', metrics.width - Blockly.BlockSvg.CORNER_RADIUS);
|
||||
} else {
|
||||
// input
|
||||
steps.push('H', metrics.width - metrics.fieldRadius);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the right edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} cursorY Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawRight_ =
|
||||
function(steps, connectionsXY, metrics) {
|
||||
if (metrics.endHat) {
|
||||
steps.push('a', Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
steps.push('v', -8);
|
||||
} else if (this.nextConnection) {
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
steps.push('v', -8);
|
||||
} else {
|
||||
// Input
|
||||
steps.push(
|
||||
'a', metrics.fieldRadius + ',' + metrics.fieldRadius,
|
||||
'0', '0,0', metrics.fieldRadius + ',' + -1*metrics.fieldRadius);
|
||||
steps.push('v', -1*(metrics.height - metrics.fieldRadius*2));
|
||||
}
|
||||
|
||||
if (metrics.endHat) {
|
||||
steps.push('V', Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.nextConnection) {
|
||||
steps.push(Blockly.BlockSvg.NOTCH_PATH_UP);
|
||||
|
||||
// Create next block connection.
|
||||
var connectionX;
|
||||
if (this.RTL) {
|
||||
connectionX = connectionsXY.x + metrics.width;
|
||||
} else {
|
||||
connectionX = connectionsXY.x + metrics.width;
|
||||
}
|
||||
var connectionY = connectionsXY.y + metrics.height - Blockly.BlockSvg.CORNER_RADIUS * 2;
|
||||
this.nextConnection.moveTo(connectionX, connectionY);
|
||||
if (this.nextConnection.targetConnection) {
|
||||
this.nextConnection.tighten_();
|
||||
}
|
||||
this.height += 4; // Height of tab.
|
||||
steps.push('V', Blockly.BlockSvg.CORNER_RADIUS);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the top edge of the block.
|
||||
* @param {!Array.<string>} steps Path of block outline.
|
||||
* @param {!Object} connectionsXY Location of block.
|
||||
* @param {number} cursorY Height of block.
|
||||
* @private
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.renderDrawTop_ =
|
||||
function(steps, connectionsXY, metrics) {
|
||||
if (metrics.endHat) {
|
||||
steps.push('a', Blockly.BlockSvg.HAT_CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ' 0 0,0 -' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.HAT_CORNER_RADIUS);
|
||||
} else if (this.nextConnection) {
|
||||
steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 -' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS + ',-' +
|
||||
Blockly.BlockSvg.CORNER_RADIUS);
|
||||
} else {
|
||||
steps.push(
|
||||
'a', metrics.fieldRadius + ',' + metrics.fieldRadius,
|
||||
'0', '0,0', '-' + metrics.fieldRadius + ',-' + metrics.fieldRadius);
|
||||
}
|
||||
steps.push('z');
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,7 @@
|
|||
// Top level object for Blockly.
|
||||
goog.provide('Blockly');
|
||||
|
||||
goog.require('Blockly.BlockSvg');
|
||||
goog.require('Blockly.BlockSvg.render');
|
||||
goog.require('Blockly.Events');
|
||||
goog.require('Blockly.FieldAngle');
|
||||
goog.require('Blockly.FieldCheckbox');
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
goog.provide('Blockly.FieldTextInput');
|
||||
|
||||
goog.require('Blockly.BlockSvg');
|
||||
goog.require('Blockly.BlockSvg.render');
|
||||
goog.require('Blockly.Field');
|
||||
goog.require('Blockly.Msg');
|
||||
goog.require('goog.asserts');
|
||||
|
@ -228,7 +228,7 @@ Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
|
|||
var bBox = this.fieldGroup_.getBBox();
|
||||
var height = bBox.height * this.sourceBlock_.workspace.scale;
|
||||
var width = Math.max(
|
||||
bBox.width, Blockly.BlockSvg.FIELD_WIDTH-Blockly.BlockSvg.SEP_SPACE_X) *
|
||||
bBox.width, Blockly.BlockSvg.FIELD_WIDTH-Blockly.BlockSvg.SEP_SPACE_X) *
|
||||
this.sourceBlock_.workspace.scale
|
||||
div.style.width = width + 'px';
|
||||
div.style.height = height + 'px';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue