From 23832a18b9d3a98fe57b8518bf143aabf3afb595 Mon Sep 17 00:00:00 2001
From: Prapti Khawas
Date: Mon, 16 Jul 2018 13:13:58 -0400
Subject: [PATCH 01/23] Adding methods for improvables
---
core/block_svg.js | 58 +++++++++++-
core/colours.js | 1 +
core/flyout_base.js | 44 +++++++++
core/inject.js | 40 ++++++++
core/workspace_svg.js | 207 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 348 insertions(+), 2 deletions(-)
diff --git a/core/block_svg.js b/core/block_svg.js
index b6fe0812ef..19a7277122 100644
--- a/core/block_svg.js
+++ b/core/block_svg.js
@@ -215,9 +215,34 @@ Blockly.BlockSvg.prototype.unselect = function() {
* Glow only this particular block, to highlight it visually as if it's running.
* @param {boolean} isGlowingBlock Whether the block should glow.
*/
-Blockly.BlockSvg.prototype.setGlowBlock = function(isGlowingBlock) {
+Blockly.BlockSvg.prototype.setGlowBlock = function(isGlowingBlock, refactor=false) {
this.isGlowingBlock_ = isGlowingBlock;
- this.updateColour();
+
+ if( refactor === false ){
+ this.updateColour();
+ }
+ else{
+ // Update the applied SVG filter if the property has changed
+ var svg = this.getSvgRoot();
+ if (this.isGlowingBlock_ && !svg.hasAttribute('filter')) {
+ svg.setAttribute('filter', 'url(#blocklyMessyBlockGlowFilter)');
+ } else if (!this.isGlowingBlock_ && svg.hasAttribute('filter')) {
+ svg.removeAttribute('filter');
+ }
+ }
+}
+
+/**
+ * Set whether the block is highlighted or not.
+ * @param {boolean} highlighted True if highlighted.
+ */
+Blockly.BlockSvg.prototype.setHighlighted = function(highlighted) {
+ var svg = this.getSvgRoot();
+ if (highlighted && !svg.hasAttribute('filter')) {
+ svg.setAttribute('filter', 'url(#blocklyMessyBlockGlowFilter)');
+ } else if (svg.hasAttribute('filter')) {
+ svg.removeAttribute('filter');
+ }
};
/**
@@ -378,6 +403,35 @@ Blockly.BlockSvg.prototype.moveBy = function(dx, dy) {
this.workspace.resizeContents();
};
+/**
+ * Move a block along with its connected blocks and attach it to given parent
+ * @param {Blockly.BlockSvg} parent
+ */
+Blockly.BlockSvg.prototype.attachToParent = function(parent) {
+ goog.asserts.assert(parent, 'Parent not provided');
+ this.parentBlock_=null;
+ this.workspace.addTopBlock(this);
+ this.setParent(parent);
+};
+
+
+/**
+ * Connect block to given block
+ * Note: any block below this block will be disconnected
+ * @param {Blockly.BlockSvg} block
+ */
+Blockly.BlockSvg.prototype.connectToBlock = function(block) {
+ var previousConn = this.nextConnection;
+ if(previousConn.targetConnection) previousConn.disconnect();
+ var nextConn = block.previousConnection;
+ if(nextConn && nextConn.targetConnection) nextConn.disconnect();
+ if (previousConn.checkType_(nextConn)) {
+ // Attach the given block to this block.
+ previousConn.connect(nextConn);
+ }
+};
+
+
/**
* Transforms a block by setting the translation on the transform attribute
* of the block's SVG.
diff --git a/core/colours.js b/core/colours.js
index 4936ce6b59..3d97e7b5f8 100644
--- a/core/colours.js
+++ b/core/colours.js
@@ -99,6 +99,7 @@ Blockly.Colours = {
"stackGlowSize": 4,
"stackGlowOpacity": 1,
"replacementGlow": "#FFFFFF",
+ "messyBlockGlow": "#ff0000",
"replacementGlowSize": 2,
"replacementGlowOpacity": 1,
"colourPickerStroke": "#FFFFFF",
diff --git a/core/flyout_base.js b/core/flyout_base.js
index c297620259..92ee15e643 100644
--- a/core/flyout_base.js
+++ b/core/flyout_base.js
@@ -142,6 +142,14 @@ Blockly.Flyout = function(workspaceOptions) {
*/
this.recycleBlocks_ = [];
+ /**
+ * List of current highlight boxes drawn in flyout. Highlight boxes are often used to
+ * visually mark certain group of variables.
+ * @type !Array.
+ * @private
+ */
+ this.highlightBoxs_ = [];
+
};
/**
@@ -884,3 +892,39 @@ Blockly.Flyout.prototype.recycleBlock_ = function(block) {
block.moveBy(-xy.x, -xy.y);
this.recycleBlocks_.push(block);
};
+
+/**
+ * Display highlighting box for given variables in the workspace.
+ * @param {array} ids IDs of variables to find.
+ */
+Blockly.Flyout.prototype.drawHighlightBox = function(ids) {
+ for ( var i=0; i< ids.length; i++ ) {
+ var id = ids[i];
+ var block = null;
+ var height = 0;
+ if (id) {
+ block = this.workspace_.getBlockById(id);
+ if (!block) {
+ throw 'Tried to highlight variable that does not exist.';
+ }
+ }
+ height = block.getHeightWidth().height;
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('rect',
+ {'height': height * this.workspace_.scale,
+ 'width' : (block.getHeightWidth().width+10) * this.workspace_.scale,
+ 'style' : "fill: none;stroke-width:5;stroke:rgb(255,0,0);",
+ 'x' : (block.getBoundingRectangle().topLeft.x-5) * this.workspace_.scale,
+ 'y' : (block.getBoundingRectangle().topLeft.y-this.getScrollPos()) * this.workspace_.scale
+ },
+ this.svgGroup_));
+ }
+};
+
+/**
+ * Remove all highlighting boxes for given variables in the workspace.
+ */
+Blockly.Flyout.prototype.removeHighlightBox = function() {
+ for ( var i=0; i
+ * @private
+ */
+ this.highlightBoxs_ = [];
+
/**
* Object in charge of loading, storing, and playing audio for a workspace.
* @type {Blockly.WorkspaceAudio}
@@ -909,6 +917,76 @@ Blockly.WorkspaceSvg.prototype.glowBlock = function(id, isGlowingBlock) {
block.setGlowBlock(isGlowingBlock);
};
+/**
++ * Glow/unglow a messy block in the workspace.
++ * @param {array} ids IDs of block to find.
++ * @param {boolean} isGlowingBlock Whether to glow the block.
++ */
+Blockly.WorkspaceSvg.prototype.glowMessyBlock = function(ids, isMessyGlowingBlock) {
+
+ for ( var i=0; i< ids.length; i++ ) {
+ var id = ids[i];
+ var block = null;
+ if (id) {
+ block = this.getBlockById(id);
+ if (!block) {
+ throw 'Tried to glow block that does not exist.';
+ }
+ }
+ if(!isMessyGlowingBlock){
+ Blockly.DropDownDiv.hideWithoutAnimation();
+ }
+ block.setGlowBlock(isMessyGlowingBlock, true);
+ }
+};
+
+
+/**
+ * Display highlighting box for given block/blocks in the workspace.
+ * @param {?string} start id ID of block to find.
+ * @param {?string} (optional) end id ID of block to find.
+ */
+Blockly.WorkspaceSvg.prototype.drawHighlightBox = function(id, id2=null) {
+ var block = null;
+ var height = 0;
+ if (id) {
+ block = this.getBlockById(id);
+ if (!block) {
+ throw 'Tried to highlight block that does not exist.';
+ }
+ }
+ var lastBlock = null;
+ var block2 = null;
+ if(id2==null){
+ lastBlock = block.getNextBlock();
+ } else {
+ block2 = this.getBlockById(id2);
+ lastBlock = block2.getNextBlock();
+ }
+ if(lastBlock==null){
+ height = block.getHeightWidth().height;
+ } else {
+ height = block.getHeightWidth().height-lastBlock.getHeightWidth().height;
+ }
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('rect',
+ {'height': height,
+ 'width' : block.getHeightWidth().width+10,
+ 'style' : "fill: none;stroke-width:5;stroke:rgb(255,0,0);",
+ 'x' : block.getBoundingRectangle().topLeft.x-5,
+ 'y' : block.getBoundingRectangle().topLeft.y
+ },
+ this.svgBlockCanvas_));
+};
+
+/**
+ * Remove all highlighting boxes for given block/blocks in the workspace.
+ */
+Blockly.WorkspaceSvg.prototype.removeHighlightBox = function() {
+ for ( var i=0; i
+ *
+ *
+ *
+ *
+ */
+Blockly.WorkspaceSvg.prototype.explainHighlightBox = function(value, toPointVariables=0, noPath=0) {
+
+ var d = 'M 0 0 l -20 -20 l 0 40 z';
+ var transform = 'translate(735,300)';
+ var str = "";
+ if(toPointVariables==1){
+ d = 'M 0 0 l 20 -20 l 0 40 z';
+ transform = 'translate(295,600)';
+ }
+
+ this.drawBox(500,400);
+
+
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('image',
+ {'href':'http://research.cs.vt.edu/quality4blocks/img/quality-hound.png',
+ 'height': 180,
+ 'width' : 180,
+ 'x' : 575,
+ 'y' : 10
+ },
+ this.highlightBoxs_[this.highlightBoxs_.length-4]));
+
+ var y = 250;
+ var width = 350;
+ var lineHeight = 10;
+
+
+ if(noPath==0){
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('path',
+ {'d': d,
+ 'transform':transform
+ },
+ this.highlightBoxs_[this.highlightBoxs_.length-5]));
+ }
+
+ /**
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('text',
+ {'style' : "fill: black;font-family: 'Helvetica Neue', Helvetica, sans-serif;font-weight: bold;font-size:2rem;",
+ 'x' : 340,
+ 'y' : 200
+ },
+ this.svgGroup_));
+ var textNode1 = document.createTextNode("**sniff** **sniff**");
+ this.highlightBoxs_[this.highlightBoxs_.length - 1].appendChild(textNode1);
+ **/
+
+ /* split the words into array */
+ var words = value.split(' ');
+ var line = '';
+
+ for (var i = 0; i < words.length; i++) {
+ var testLine = line + words[i] + ' ';
+ var isNewLine = (words[i]=="\n");
+ var isLastWord = (i==words.length-1);
+ if(testLine.length>=45 || isNewLine || isLastWord){
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('text',
+ {'style' : "fill: black;font-family: 'Helvetica Neue', Helvetica, sans-serif;font-weight: bold;font-size:0.95rem;",
+ 'x' : 340,
+ 'y' : y
+ },
+ this.svgGroup_));
+ if(isLastWord) line = line + words[i];
+ var textNode = document.createTextNode(line);
+ this.highlightBoxs_[this.highlightBoxs_.length - 1].appendChild(textNode);
+ line = (isNewLine)? '' : words[i] + ' ';
+ y = (isNewLine)? y+40 : y+20;
+ } else {
+ line = line + words[i] + ' ';
+ }
+ }
+
+};
+
+/**
+ * To draw basic box for pop up with options g for adding buttons etc.
+ * Will always display to the left
+ * @param {?string} value String value to visually report.
+ *
+ *
+ *
+ *
+ */
+Blockly.WorkspaceSvg.prototype.drawBox = function(height, width){
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('g',
+ {
+ },
+ this.svgGroup_));
+
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('rect',
+ {'height': height,
+ 'width' : width,
+ 'rx' : 15,
+ 'ry' : 15,
+ 'style' : "fill: rgb(240,248,255);stroke-width:5;stroke:rgb(0,0,0);",
+ 'x' : 315,
+ 'y' : 150
+ },
+ this.highlightBoxs_[this.highlightBoxs_.length-1]));
+
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('g',
+ {'id': 'options',
+ 'transform': 'translate(350,400)'
+ },
+ this.highlightBoxs_[this.highlightBoxs_.length-2]));
+
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('g',
+ {'id': 'options2',
+ 'transform': 'translate(320,200)'
+ },
+ this.highlightBoxs_[this.highlightBoxs_.length-3]));
+}
+
+
/**
* Paste the provided block onto the workspace.
* @param {!Element} xmlBlock XML block element.
From 1f35e25ac7d32af0c3758b51ee56bcafab6d51be Mon Sep 17 00:00:00 2001
From: Peeratham Techapalokul
Date: Fri, 1 Feb 2019 21:57:46 -0500
Subject: [PATCH 02/23] handle hint mouseover
---
core/block_events.js | 3 ++-
core/hint.js | 9 ++++++++-
core/hint_bubble.js | 11 +++++++++++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/core/block_events.js b/core/block_events.js
index 9f7e0b4073..bd5155c22c 100644
--- a/core/block_events.js
+++ b/core/block_events.js
@@ -538,13 +538,14 @@ Blockly.Events.Move.prototype.run = function(forward) {
* @extends {Blockly.Events.BlockBase}
* @constructor
*/
-Blockly.Events.HintClick = function(hint) {
+Blockly.Events.HintClick = function(hint, interactionType) {
if (!hint) {
return; // Blank event to be populated by fromJson.
}
Blockly.Events.HintClick.superClass_.constructor.call(this);
this.hintId = hint.getText();
this.recordUndo = false;
+ this.interactionType = interactionType;
};
goog.inherits(Blockly.Events.HintClick, Blockly.Events.Abstract);
diff --git a/core/hint.js b/core/hint.js
index acb80f6b7f..fc888d6ef8 100644
--- a/core/hint.js
+++ b/core/hint.js
@@ -145,6 +145,7 @@ Blockly.Hint.prototype.setVisible = function(visible) {
content, this.block_.svgPath_, this.iconXY_, null, null);
// specific for hint
this.bubble_.registerContextMenuCallback(this.showContextMenu_.bind(this));
+ this.bubble_.registerMouseOverCallback(this.showCodeHint_.bind(this));
if (this.block_.RTL) {
// Right-align the paragraph.
@@ -181,6 +182,12 @@ Blockly.Hint.prototype.showContextMenu_ = function(e) {
Blockly.ContextMenu.show(e, menuOptions, this.block_.RTL);
};
+Blockly.Hint.prototype.showCodeHint_ = function(e) {
+ var event = new Blockly.Events.HintClick(this,"mouseover");
+ event.workspaceId = this.block_.workspace.id;
+ Blockly.Events.fire(event);
+}
+
/**
* Make a context menu option for action resolving the hint
* @param {!Blockly.Hint} hint The hint where the
@@ -195,7 +202,7 @@ Blockly.Hint.hintImproveOption = function(hint) {
enabled: true,
callback: function() {
console.log("Hint callback to improve get invoked");
- var event = new Blockly.Events.HintClick(hint);
+ var event = new Blockly.Events.HintClick(hint, "improve_option_click");
event.workspaceId = wsId;
Blockly.Events.fire(event);
}
diff --git a/core/hint_bubble.js b/core/hint_bubble.js
index f015e610f2..fbc85dc053 100644
--- a/core/hint_bubble.js
+++ b/core/hint_bubble.js
@@ -73,6 +73,7 @@ Blockly.HintBubble = function(workspace, content, shape, anchorXY,
this.rendered_ = true;
if (!workspace.options.readOnly) {
+ Blockly.bindEvent_(this.content_, 'mouseover', this, this.bubbleMouseOver_);
Blockly.bindEventWithChecks_(
this.content_, 'mousedown', this, this.bubbleMouseDown_);
}
@@ -87,6 +88,10 @@ Blockly.HintBubble.prototype.registerContextMenuCallback = function(callback) {
this.contextMenuCallback_ = callback;
};
+Blockly.HintBubble.prototype.registerMouseOverCallback = function(callback) {
+ this.mouseoverCallback_ = callback;
+};
+
/**
* Width of the border around the bubble.
*/
@@ -281,6 +286,12 @@ Blockly.HintBubble.prototype.showContextMenu_ = function(_e) {
}
};
+Blockly.HintBubble.prototype.bubbleMouseOver_ = function(_e){
+ if(this.mouseoverCallback_){
+ this.mouseoverCallback_(_e);
+ }
+}
+
/**
* Get whether this bubble is deletable or not.
* @return {boolean} True if deletable.
From 0d711ec2e11ce6e66245ad5d18cd13ec883d6f51 Mon Sep 17 00:00:00 2001
From: thesourabh
Date: Tue, 5 Feb 2019 13:37:09 -0500
Subject: [PATCH 03/23] Code Hint: Added mouseover and mouseout handling
---
core/hint.js | 12 +++++++++++-
core/hint_bubble.js | 15 +++++++++++++--
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/core/hint.js b/core/hint.js
index fc888d6ef8..dacd2b584a 100644
--- a/core/hint.js
+++ b/core/hint.js
@@ -146,6 +146,7 @@ Blockly.Hint.prototype.setVisible = function(visible) {
// specific for hint
this.bubble_.registerContextMenuCallback(this.showContextMenu_.bind(this));
this.bubble_.registerMouseOverCallback(this.showCodeHint_.bind(this));
+ this.bubble_.registerMouseOutCallback(this.hideCodeHint_.bind(this));
if (this.block_.RTL) {
// Right-align the paragraph.
@@ -186,7 +187,16 @@ Blockly.Hint.prototype.showCodeHint_ = function(e) {
var event = new Blockly.Events.HintClick(this,"mouseover");
event.workspaceId = this.block_.workspace.id;
Blockly.Events.fire(event);
-}
+ // this.block_.workspace.highlightBlock(this.block_.id, true);
+
+};
+Blockly.Hint.prototype.hideCodeHint_ = function(e) {
+ var event = new Blockly.Events.HintClick(this,"mouseout");
+ event.workspaceId = this.block_.workspace.id;
+ Blockly.Events.fire(event);
+ // this.block_.workspace.highlightBlock(this.block_.id, false);
+
+};
/**
* Make a context menu option for action resolving the hint
diff --git a/core/hint_bubble.js b/core/hint_bubble.js
index fbc85dc053..e4939b8b8e 100644
--- a/core/hint_bubble.js
+++ b/core/hint_bubble.js
@@ -74,6 +74,7 @@ Blockly.HintBubble = function(workspace, content, shape, anchorXY,
if (!workspace.options.readOnly) {
Blockly.bindEvent_(this.content_, 'mouseover', this, this.bubbleMouseOver_);
+ Blockly.bindEvent_(this.content_, 'mouseout', this, this.bubbleMouseOut_);
Blockly.bindEventWithChecks_(
this.content_, 'mousedown', this, this.bubbleMouseDown_);
}
@@ -92,6 +93,10 @@ Blockly.HintBubble.prototype.registerMouseOverCallback = function(callback) {
this.mouseoverCallback_ = callback;
};
+Blockly.HintBubble.prototype.registerMouseOutCallback = function(callback) {
+ this.mouseoutCallback_ = callback;
+};
+
/**
* Width of the border around the bubble.
*/
@@ -232,7 +237,7 @@ Blockly.HintBubble.prototype.createDom_ = function(content, hasResize) {
*/
this.bubbleGroup_ = Blockly.utils.createSvgElement('g', {}, null);
this.resizeGroup_ = null;
-
+
this.bubbleGroup_.appendChild(content);
return this.bubbleGroup_;
};
@@ -290,7 +295,13 @@ Blockly.HintBubble.prototype.bubbleMouseOver_ = function(_e){
if(this.mouseoverCallback_){
this.mouseoverCallback_(_e);
}
-}
+};
+
+Blockly.HintBubble.prototype.bubbleMouseOut_ = function(_e){
+ if(this.mouseoutCallback_){
+ this.mouseoutCallback_(_e);
+ }
+};
/**
* Get whether this bubble is deletable or not.
From da561e12060cfa7f8e64562731bf7c5ed7f74deb Mon Sep 17 00:00:00 2001
From: thesourabh
Date: Fri, 22 Feb 2019 17:36:35 -0500
Subject: [PATCH 04/23] Added two-step edit procedure option for extracted
procedure
---
core/block_transformer.js | 13 +++++++++----
core/hint.js | 32 ++++++++++++++++++++++++++++----
2 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/core/block_transformer.js b/core/block_transformer.js
index dfc0b186ff..74036e676e 100644
--- a/core/block_transformer.js
+++ b/core/block_transformer.js
@@ -19,19 +19,20 @@ Blockly.BlockTransformer.prototype.doTransform = function (refactorable) {
};
Blockly.BlockTransformer.prototype.executeAction = function (action) {
+ let result = true;
try {
- this.apply(action);
+ result = this.apply(action);
} catch (err) {
throw "failed to apply transformation:" +
JSON.stringify(action)
+ "\n" + err.message;
}
- return true;
+ return result;
};
Blockly.BlockTransformer.prototype.apply = function (action) {
const actionType = action.type;
- this[actionType](action);
+ return this[actionType](action);
};
Blockly.BlockTransformer.prototype.VarDeclareAction = function (action) {
@@ -67,7 +68,11 @@ Blockly.BlockTransformer.prototype.VarRename = function (action) {
Blockly.BlockTransformer.prototype.BlockCreateAction = function (action) {
let dom = Blockly.Xml.textToDom(action.block_xml).firstChild;
let block = Blockly.Xml.domToBlock(dom, this.workspace);
- return true;
+ if (block.type === "procedures_definition") {
+ return block;
+ // Blockly.Procedures.editProcedureCallback_(block);
+ }
+ return true
};
Blockly.BlockTransformer.prototype.InsertBlockAction = function (action) {
diff --git a/core/hint.js b/core/hint.js
index dacd2b584a..a2a61eb606 100644
--- a/core/hint.js
+++ b/core/hint.js
@@ -129,7 +129,7 @@ Blockly.Hint.prototype.setBubbleSize = function(width, height) {
* Show or hide the hint bubble.
* @param {boolean} visible True if the bubble should be visible.
*/
-Blockly.Hint.prototype.setVisible = function(visible) {
+Blockly.Hint.prototype.setVisible = function(visible, hintType) {
if (visible == this.isVisible()) {
// No change.
return;
@@ -144,9 +144,13 @@ Blockly.Hint.prototype.setVisible = function(visible) {
/** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace),
content, this.block_.svgPath_, this.iconXY_, null, null);
// specific for hint
- this.bubble_.registerContextMenuCallback(this.showContextMenu_.bind(this));
- this.bubble_.registerMouseOverCallback(this.showCodeHint_.bind(this));
- this.bubble_.registerMouseOutCallback(this.hideCodeHint_.bind(this));
+ if (hintType === "edit_procedure") {
+ this.bubble_.registerContextMenuCallback(this.showEditContextMenu_.bind(this));
+ } else {
+ this.bubble_.registerContextMenuCallback(this.showContextMenu_.bind(this));
+ this.bubble_.registerMouseOverCallback(this.showCodeHint_.bind(this));
+ this.bubble_.registerMouseOutCallback(this.hideCodeHint_.bind(this));
+ }
if (this.block_.RTL) {
// Right-align the paragraph.
@@ -169,6 +173,26 @@ Blockly.Hint.prototype.setVisible = function(visible) {
}
};
+/**
+ * Show the context menu for this comment's bubble.
+ * @param {!Event} e The mouse event
+ * @private
+ */
+Blockly.Hint.prototype.showEditContextMenu_ = function(e) {
+ var menuOptions = [];
+ var block = this.block_;
+ var _this = this;
+ menuOptions.push({
+ enabled: true,
+ text: Blockly.Msg.EDIT_PROCEDURE,
+ callback: function() {
+ Blockly.Procedures.editProcedureCallback_(block);
+ _this.setVisible(false, "edit_procedure");
+ }
+ });
+ Blockly.ContextMenu.show(e, menuOptions, block.RTL);
+};
+
/**
* Show the context menu for this comment's bubble.
* @param {!Event} e The mouse event
From 8476a169e127d34bd5e6b868598dc16036358588 Mon Sep 17 00:00:00 2001
From: Peeratham Techapalokul
Date: Mon, 4 Mar 2019 13:41:42 -0500
Subject: [PATCH 05/23] compact xml export
---
tests/vertical_playground_compact_xml.html | 613 +++++++++++++++++++++
1 file changed, 613 insertions(+)
create mode 100644 tests/vertical_playground_compact_xml.html
diff --git a/tests/vertical_playground_compact_xml.html b/tests/vertical_playground_compact_xml.html
new file mode 100644
index 0000000000..e2f2261a43
--- /dev/null
+++ b/tests/vertical_playground_compact_xml.html
@@ -0,0 +1,613 @@
+
+
+
+
+
+
+ Vertical Playground
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ hello
+
+
+
+
+ world
+
+
+
+
+
+
+ 1
+
+
+
+
+ world
+
+
+
+
+
+
+ world
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Vertical Blocks
+
+ Show
+ - Hide
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Log events:
+
+
+
+
+ Stress test:
+
+
+
+
+
+ Glows:
+
+
+
+
+
+
+
+ Log flyout events:
+
+
+
+
+ Enable sounds (after refresh):
+
+
+
+
+
+
+
+
+
+ Report:
+
+
+
+
+
From bb88bfdab45aeda7b6605fd572582707cab88b85 Mon Sep 17 00:00:00 2001
From: thesourabh
Date: Mon, 4 Mar 2019 19:27:51 -0500
Subject: [PATCH 06/23] Added Prapti's code for highlighting a block with a
fixed end block.
---
core/utils.js | 77 +++++++++++++++++++++++++++++++++++++++++++
core/workspace_svg.js | 38 +++++++++------------
2 files changed, 93 insertions(+), 22 deletions(-)
diff --git a/core/utils.js b/core/utils.js
index 6106df17a4..8b47816d20 100644
--- a/core/utils.js
+++ b/core/utils.js
@@ -958,3 +958,80 @@ Blockly.utils.startsWith = function(str, prefix) {
Blockly.utils.toRadians = function(angleDegrees) {
return angleDegrees * Math.PI / 180;
};
+
+/**
+ *Returns path string which bounds the blocks between block1 and block2 (inclusive)
+ */
+Blockly.utils.getBoundingPath = function(block1, block2=null){
+ if(block2 == null){
+ return block1.svgPath_.getAttribute("d");
+ }
+ var d = "";
+ var pd1 = block1.svgPath_.getAttribute("d").split(" H");
+ var pd2 = block2.svgPath_.getAttribute("d").split(" H");
+ d = d + pd1[0] + " H" + pd1[1];
+ var block2Type = block2.type.replace("control_","");
+ d = d + Blockly.utils.pathBetween(block1,block2);
+ if(["if","repeat","repeat_until","forever"].includes(block2Type)){
+ var substack = block2.inputList[1].connection ? block2.inputList[1].connection.targetConnection.getSourceBlock() : block2.inputList[2].connection.targetConnection.getSourceBlock();
+ var newTranslate = parseInt(substack.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]);
+ d = d + " H" + pd2[2] + Blockly.utils.pathBetween(substack, null, newTranslate)
+ + " H" + pd2[4];
+ d = d + " H" + pd2[6] + " H" + pd2[7];
+ } else if(block2Type == "if_else"){
+ var substack1 = block2.inputList[2].connection.targetConnection.getSourceBlock();
+ var substack2 = block2.inputList[4].connection.targetConnection.getSourceBlock();
+ var newTranslate1 = parseInt(substack1.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]);
+ var newTranslate2 = parseInt(substack2.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]);
+ d = d + " H" + pd2[2] + Blockly.utils.pathBetween(substack1, null, newTranslate1)
+ + " H" + pd2[5] + Blockly.utils.pathBetween(substack2, null, newTranslate2)
+ + " H" + pd2[7];
+ d = d + " H" + pd2[8] + " H" + pd2[9];
+ } else {
+ d = d + " H" + pd2[2];
+ d = d + " H" + pd2[3] + " H" + pd2[4];
+ }
+ return d;
+};
+
+/**
+ *Returns path string for nested blocks
+ */
+Blockly.utils.pathBetween = function(block1, block2, translate=0){
+ var d = "";
+ var block = block1;
+ while (block != null && block != block2){
+ var pd = block.svgPath_.getAttribute("d").split(" H");
+ pd[2] = pd[2].replace(pd[2].split(" ")[1],parseInt(pd[2].split(" ")[1]) + translate);
+ var blockType = block.type.replace("control_","");
+ if(["repeat","repeat_until","forever"].includes(blockType)){
+ pd[5] = pd[5].replace(pd[5].split(" ")[1],parseInt(pd[5].split(" ")[1]) + translate )
+ var substack = block.inputList[1].connection ? block.inputList[1].connection.targetConnection.getSourceBlock() : block.inputList[2].connection.targetConnection.getSourceBlock();
+ var newTranslate = parseInt(substack.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]) + translate;
+ d = d + " H" + pd[2] + Blockly.utils.pathBetween(substack, null, newTranslate)
+ + " H" + pd[5];
+ } else if(blockType == "if"){
+ pd[4] = pd[4].replace(pd[4].split(" ")[1],parseInt(pd[4].split(" ")[1]) + translate )
+ var substack = block.inputList[1].connection ? block.inputList[1].connection.targetConnection.getSourceBlock() : block.inputList[2].connection.targetConnection.getSourceBlock();
+ var newTranslate = parseInt(substack.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]) + translate;
+ d = d + " H" + pd[2] + Blockly.utils.pathBetween(substack, null, newTranslate)
+ + " H" + pd[4];
+ } else if(blockType == "if_else"){
+ pd[5] = pd[5].replace(pd[5].split(" ")[1],parseInt(pd[5].split(" ")[1]) + translate )
+ pd[7] = pd[7].replace(pd[7].split(" ")[1],parseInt(pd[7].split(" ")[1]) + translate )
+ var substack1 = block.inputList[2].connection.targetConnection.getSourceBlock();
+ var substack2 = block.inputList[4].connection.targetConnection.getSourceBlock();
+ var newTranslate1 = parseInt(substack1.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]) + translate;
+ var newTranslate2 = parseInt(substack2.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]) + translate;
+ d = d + " H" + pd[2] + Blockly.utils.pathBetween(substack1, null, newTranslate1)
+ + " H" + pd[5] + Blockly.utils.pathBetween(substack2, null, newTranslate2)
+ + " H" + pd[7];
+ } else if (block.type.includes("event_when")){
+ d = d ;
+ } else {
+ d = d + " H" + pd[2];
+ }
+ block = block.getNextBlock();
+ }
+ return d;
+};
diff --git a/core/workspace_svg.js b/core/workspace_svg.js
index 2704235c58..1433682d76 100644
--- a/core/workspace_svg.js
+++ b/core/workspace_svg.js
@@ -992,35 +992,29 @@ Blockly.WorkspaceSvg.prototype.glowMessyBlock = function(ids, isMessyGlowingBloc
* @param {?string} (optional) end id ID of block to find.
*/
Blockly.WorkspaceSvg.prototype.drawHighlightBox = function(id, id2=null) {
- var block = null;
- var height = 0;
+ var block1 = null, block2 = null;
if (id) {
- block = this.getBlockById(id);
- if (!block) {
+ block1 = this.getBlockById(id);
+ if (!block1) {
throw 'Tried to highlight block that does not exist.';
}
}
- var lastBlock = null;
- var block2 = null;
- if(id2==null){
- lastBlock = block.getNextBlock();
- } else {
+ if (id2) {
block2 = this.getBlockById(id2);
- lastBlock = block2.getNextBlock();
- }
- if(lastBlock==null){
- height = block.getHeightWidth().height;
- } else {
- height = block.getHeightWidth().height-lastBlock.getHeightWidth().height;
+ if (!block2) {
+ throw 'Tried to highlight block that does not exist.';
+ }
}
- this.highlightBoxs_.push(Blockly.utils.createSvgElement('rect',
- {'height': height,
- 'width' : block.getHeightWidth().width+10,
- 'style' : "fill: none;stroke-width:5;stroke:rgb(255,0,0);",
- 'x' : block.getBoundingRectangle().topLeft.x-5,
- 'y' : block.getBoundingRectangle().topLeft.y
+ this.highlightBoxs_.push(Blockly.utils.createSvgElement('path',
+ {
+ 'd': Blockly.utils.getBoundingPath(block1,block2),
+ 'class': 'blocklyPath blocklyBlockBackground',
+ 'stroke': 'black',
+ 'style': 'stroke-width: 5px',
+ 'fill-opacity': '0',
+ 'fill': 'black'
},
- this.svgBlockCanvas_));
+ block1.getSvgRoot()));
};
/**
From 4cd574f1ac7720dcf43c59769d62425592eeeef3 Mon Sep 17 00:00:00 2001
From: Peeratham Techapalokul
Date: Tue, 5 Mar 2019 21:15:02 -0500
Subject: [PATCH 07/23] add workspace hint and positioning
---
core/workspace.js | 8 +++-
core/workspace_hint.js | 85 ++++++++++++++++++++++++++++++++++++++++++
core/workspace_svg.js | 4 ++
3 files changed, 96 insertions(+), 1 deletion(-)
create mode 100644 core/workspace_hint.js
diff --git a/core/workspace.js b/core/workspace.js
index 3bc5f6bfcd..4e2a456d4b 100644
--- a/core/workspace.js
+++ b/core/workspace.js
@@ -32,7 +32,7 @@ goog.require('goog.array');
goog.require('goog.math');
goog.require('Blockly.BlockTransformer');
-
+goog.require('Blockly.WorkspaceHint');
/**
* Class for a workspace. This is a data structure that contains blocks.
* There is no UI, and can be created headlessly.
@@ -669,6 +669,11 @@ Blockly.Workspace.getById = function(id) {
return Blockly.Workspace.WorkspaceDB_[id] || null;
};
+Blockly.Workspace.prototype.createHint = function() {
+ this.workspaceHint_ = new Blockly.WorkspaceHint(this);
+}
+
+
// Export symbols that would otherwise be renamed by Closure compiler.
Blockly.Workspace.prototype['clear'] = Blockly.Workspace.prototype.clear;
Blockly.Workspace.prototype['clearUndo'] =
@@ -677,3 +682,4 @@ Blockly.Workspace.prototype['addChangeListener'] =
Blockly.Workspace.prototype.addChangeListener;
Blockly.Workspace.prototype['removeChangeListener'] =
Blockly.Workspace.prototype.removeChangeListener;
+
diff --git a/core/workspace_hint.js b/core/workspace_hint.js
new file mode 100644
index 0000000000..befeaebf91
--- /dev/null
+++ b/core/workspace_hint.js
@@ -0,0 +1,85 @@
+'use strict';
+
+goog.provide('Blockly.WorkspaceHint');
+
+goog.require('Blockly.Events.Ui');
+goog.require('Blockly.Icon');
+
+
+
+Blockly.WorkspaceHint = function (workspace) {
+ this.workspace_ = workspace;
+ this.createHint();
+};
+
+Blockly.WorkspaceHint.prototype.WIDTH_ = 20;
+Blockly.WorkspaceHint.prototype.HEIGHT_ = 20;
+Blockly.WorkspaceHint.prototype.MARGIN_TOP_ = 30;
+Blockly.WorkspaceHint.prototype.MARGIN_BOTTOM_ = 12;
+Blockly.WorkspaceHint.prototype.MARGIN_SIDE_ = 12;
+Blockly.WorkspaceHint.prototype.HEIGHT_ = 124;
+
+Blockly.WorkspaceHint.prototype.createHint = function () {
+ console.log("todo: create hint");
+ this.iconGroup_ = this.createHintIcon_();
+ this.workspace_.svgGroup_.appendChild(this.iconGroup_);
+ this.position();
+ Blockly.bindEventWithChecks_(
+ this.iconGroup_, 'mouseup', this,
+ function () {
+ console.log("clicked");
+ }
+ // this.iconClick_
+ );
+};
+
+Blockly.WorkspaceHint.prototype.position = function () {
+ this.bottom_ = this.MARGIN_BOTTOM_;
+ var metrics = this.workspace_.getMetrics();
+ if (!metrics) {
+ // There are no metrics available (workspace is probably not visible).
+ return;
+ }
+ if (this.workspace_.RTL) {
+ this.left_ = this.MARGIN_SIDE_ + Blockly.Scrollbar.scrollbarThickness;
+ if (metrics.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) {
+ this.left_ += metrics.flyoutWidth;
+ if (this.workspace_.toolbox_) {
+ this.left_ += metrics.absoluteLeft;
+ }
+ }
+ } else {
+ this.left_ = metrics.viewWidth + metrics.absoluteLeft -
+ this.WIDTH_ - this.MARGIN_SIDE_ - Blockly.Scrollbar.scrollbarThickness;
+
+ if (metrics.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) {
+ this.left_ -= metrics.flyoutWidth;
+ }
+ }
+
+ this.top_ = metrics.absoluteTop + this.MARGIN_TOP_;
+
+
+ this.iconGroup_.setAttribute('transform',
+ 'translate(' + this.left_ + ',' + this.top_ + ')');
+
+}
+
+Blockly.WorkspaceHint.prototype.createHintIcon_ = function () {
+ let iconGroup_ = Blockly.utils.createSvgElement('g', { 'class': 'blocklyIconGroup' }, null);
+ let WIDTH_ = 8 * Blockly.BlockSvg.GRID_UNIT;
+ let HEIGHT_ = 8 * Blockly.BlockSvg.GRID_UNIT;
+ let lightbulbSvgPath = '/icons/set-led_yellow.svg';
+ var lightbulbSvg = Blockly.utils.createSvgElement(
+ 'image',
+ {
+ 'width': WIDTH_,
+ 'height': HEIGHT_
+ },
+ iconGroup_
+ );
+ lightbulbSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',
+ this.workspace_.options.pathToMedia + lightbulbSvgPath);
+
+ return iconGroup_;
+}
diff --git a/core/workspace_svg.js b/core/workspace_svg.js
index 1433682d76..39ab1eb5d7 100644
--- a/core/workspace_svg.js
+++ b/core/workspace_svg.js
@@ -708,6 +708,10 @@ Blockly.WorkspaceSvg.prototype.resize = function() {
if (this.scrollbar) {
this.scrollbar.resize();
}
+ if (this.workspaceHint_) {
+ this.workspaceHint_.position();
+ }
+
this.updateScreenCalculations_();
};
From 4e30f3b6df32c91b87e997e5e9c25b48ec749aea Mon Sep 17 00:00:00 2001
From: Peeratham Techapalokul
Date: Tue, 5 Mar 2019 22:07:09 -0500
Subject: [PATCH 08/23] add context menu
---
core/block_events.js | 2 +-
core/gesture.js | 16 ++++++++++++++
core/workspace_hint.js | 47 ++++++++++++++++++++++++++++++++++++------
3 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/core/block_events.js b/core/block_events.js
index bd5155c22c..31b8b8a38b 100644
--- a/core/block_events.js
+++ b/core/block_events.js
@@ -543,7 +543,7 @@ Blockly.Events.HintClick = function(hint, interactionType) {
return; // Blank event to be populated by fromJson.
}
Blockly.Events.HintClick.superClass_.constructor.call(this);
- this.hintId = hint.getText();
+ this.hintId = hint.getText()||hint.getId();
this.recordUndo = false;
this.interactionType = interactionType;
};
diff --git a/core/gesture.js b/core/gesture.js
index 1e9ec9a49d..6fde8771e7 100644
--- a/core/gesture.js
+++ b/core/gesture.js
@@ -640,6 +640,8 @@ Blockly.Gesture.prototype.handleRightClick = function(e) {
this.targetBlock_.showContextMenu_(e);
} else if (this.startBubble_) {
this.startBubble_.showContextMenu_(e);
+ } else if (this.startWorkspaceHint_) {
+ this.startWorkspaceHint_.showContextMenu_(e);
} else if (this.startWorkspace_ && !this.flyout_) {
Blockly.hideChaff();
this.startWorkspace_.showContextMenu_(e);
@@ -709,6 +711,14 @@ Blockly.Gesture.prototype.handleBubbleStart = function(e, bubble) {
this.mostRecentEvent_ = e;
};
+Blockly.Gesture.prototype.handleWorkspaceHintStart = function(e, hint) {
+ goog.asserts.assert(!this.hasStarted_,
+ 'Tried to call gesture.handleWorkspaceHintStart, but the gesture had already ' +
+ 'been started.');
+ this.setStartWorkspaceHint(hint);
+ this.mostRecentEvent_ = e;
+};
+
/* Begin functions defining what actions to take to execute clicks on each type
* of target. Any developer wanting to add behaviour on clicks should modify
* only this code. */
@@ -818,6 +828,12 @@ Blockly.Gesture.prototype.setStartBubble = function(bubble) {
}
};
+Blockly.Gesture.prototype.setStartWorkspaceHint = function(hint) {
+ if (!this.startHint_) {
+ this.startWorkspaceHint_ = hint;
+ }
+};
+
/**
* Record the block that a gesture started on, and set the target block
* appropriately.
diff --git a/core/workspace_hint.js b/core/workspace_hint.js
index befeaebf91..1844e2cf1b 100644
--- a/core/workspace_hint.js
+++ b/core/workspace_hint.js
@@ -19,20 +19,25 @@ Blockly.WorkspaceHint.prototype.MARGIN_BOTTOM_ = 12;
Blockly.WorkspaceHint.prototype.MARGIN_SIDE_ = 12;
Blockly.WorkspaceHint.prototype.HEIGHT_ = 124;
+Blockly.WorkspaceHint.prototype.getId = function () {
+ return "workspaceHintId";
+}
+
+Blockly.WorkspaceHint.prototype.getText = function () {
+ return null;
+}
+
Blockly.WorkspaceHint.prototype.createHint = function () {
console.log("todo: create hint");
this.iconGroup_ = this.createHintIcon_();
this.workspace_.svgGroup_.appendChild(this.iconGroup_);
this.position();
+
Blockly.bindEventWithChecks_(
- this.iconGroup_, 'mouseup', this,
- function () {
- console.log("clicked");
- }
- // this.iconClick_
- );
+ this.iconGroup_, 'mousedown', this, this.pathMouseDown_);
};
+
Blockly.WorkspaceHint.prototype.position = function () {
this.bottom_ = this.MARGIN_BOTTOM_;
var metrics = this.workspace_.getMetrics();
@@ -65,6 +70,13 @@ Blockly.WorkspaceHint.prototype.position = function () {
}
+Blockly.WorkspaceHint.prototype.pathMouseDown_ = function(e) {
+ var gesture = this.workspace_.getGesture(e);
+ if (gesture) {
+ gesture.handleWorkspaceHintStart(e, this);
+ }
+ };
+
Blockly.WorkspaceHint.prototype.createHintIcon_ = function () {
let iconGroup_ = Blockly.utils.createSvgElement('g', { 'class': 'blocklyIconGroup' }, null);
let WIDTH_ = 8 * Blockly.BlockSvg.GRID_UNIT;
@@ -83,3 +95,26 @@ Blockly.WorkspaceHint.prototype.createHintIcon_ = function () {
return iconGroup_;
}
+
+Blockly.WorkspaceHint.hintImproveOption = function(hint) {
+ let wsId = hint.workspace_.id;
+ var hintOption = {
+ text: "Help me improve!",
+ enabled: true,
+ callback: function() {
+ console.log("Hint callback to improve get invoked");
+ var event = new Blockly.Events.HintClick(hint, "improve_option_click");
+ event.workspaceId = wsId;
+ Blockly.Events.fire(event);
+ }
+ };
+ return hintOption;
+ };
+
+Blockly.WorkspaceHint.prototype.showContextMenu_ = function (e) {
+ var menuOptions = [];
+ menuOptions.push(Blockly.WorkspaceHint.hintImproveOption(this));
+
+ Blockly.ContextMenu.show(e, menuOptions, this.workspace_.RTL);
+
+}
\ No newline at end of file
From 14a188d87e64b110a08d0e1e2cbfd6052fcd8ab1 Mon Sep 17 00:00:00 2001
From: Peeratham Techapalokul
Date: Wed, 6 Mar 2019 13:41:28 -0500
Subject: [PATCH 09/23] hide and show hint
---
core/workspace.js | 19 +++++++++++++++++--
core/workspace_hint.js | 21 ++++++++++++++++++---
2 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/core/workspace.js b/core/workspace.js
index 4e2a456d4b..bb514653c8 100644
--- a/core/workspace.js
+++ b/core/workspace.js
@@ -119,6 +119,7 @@ Blockly.Workspace = function(opt_options) {
* BlockTransformer
*/
this.blockTransformer = new Blockly.BlockTransformer(this);
+ this.workspaceHint = new Blockly.WorkspaceHint(this);
};
/**
@@ -669,10 +670,24 @@ Blockly.Workspace.getById = function(id) {
return Blockly.Workspace.WorkspaceDB_[id] || null;
};
-Blockly.Workspace.prototype.createHint = function() {
- this.workspaceHint_ = new Blockly.WorkspaceHint(this);
+
+Blockly.Workspace.prototype.setHint = function(hintData){
+ if(this.workspaceHint){
+ this.workspaceHint.setHint(hintData);
+ }
}
+Blockly.Workspace.prototype.hideHint = function(){
+ if(this.workspaceHint){
+ this.workspaceHint.setVisible(false);
+ }
+}
+
+Blockly.Workspace.prototype.showHint = function(){
+ if(this.workspaceHint){
+ this.workspaceHint.setVisible(true);
+ }
+}
// Export symbols that would otherwise be renamed by Closure compiler.
Blockly.Workspace.prototype['clear'] = Blockly.Workspace.prototype.clear;
diff --git a/core/workspace_hint.js b/core/workspace_hint.js
index 1844e2cf1b..5b997ab239 100644
--- a/core/workspace_hint.js
+++ b/core/workspace_hint.js
@@ -9,7 +9,6 @@ goog.require('Blockly.Icon');
Blockly.WorkspaceHint = function (workspace) {
this.workspace_ = workspace;
- this.createHint();
};
Blockly.WorkspaceHint.prototype.WIDTH_ = 20;
@@ -20,15 +19,20 @@ Blockly.WorkspaceHint.prototype.MARGIN_SIDE_ = 12;
Blockly.WorkspaceHint.prototype.HEIGHT_ = 124;
Blockly.WorkspaceHint.prototype.getId = function () {
- return "workspaceHintId";
+ return this.id;
}
+/**
+ * To be removed, after Blockly.Hint
+ */
Blockly.WorkspaceHint.prototype.getText = function () {
return null;
}
-Blockly.WorkspaceHint.prototype.createHint = function () {
+Blockly.WorkspaceHint.prototype.setHint = function (hintData) {
console.log("todo: create hint");
+ this.hintData = hintData;
+ this.id = hintData.id;
this.iconGroup_ = this.createHintIcon_();
this.workspace_.svgGroup_.appendChild(this.iconGroup_);
this.position();
@@ -37,6 +41,17 @@ Blockly.WorkspaceHint.prototype.createHint = function () {
this.iconGroup_, 'mousedown', this, this.pathMouseDown_);
};
+Blockly.WorkspaceHint.prototype.setVisible = function(visible){
+ if(visible){
+ if(!this.iconGroup_ && this.hintData){
+ this.setHint(this.hintData);
+ }
+ }else{
+ goog.dom.removeNode(this.iconGroup_);
+ this.iconGroup_ = null;
+ }
+}
+
Blockly.WorkspaceHint.prototype.position = function () {
this.bottom_ = this.MARGIN_BOTTOM_;
From 2c676c7fba30f1489be19c6a495cbce936399210 Mon Sep 17 00:00:00 2001
From: Peeratham Techapalokul
Date: Wed, 6 Mar 2019 13:46:38 -0500
Subject: [PATCH 10/23] use id instead of hintData.id
---
core/workspace_hint.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/core/workspace_hint.js b/core/workspace_hint.js
index 5b997ab239..11164dbcb1 100644
--- a/core/workspace_hint.js
+++ b/core/workspace_hint.js
@@ -19,7 +19,7 @@ Blockly.WorkspaceHint.prototype.MARGIN_SIDE_ = 12;
Blockly.WorkspaceHint.prototype.HEIGHT_ = 124;
Blockly.WorkspaceHint.prototype.getId = function () {
- return this.id;
+ return this.hintData.id;
}
/**
@@ -32,7 +32,6 @@ Blockly.WorkspaceHint.prototype.getText = function () {
Blockly.WorkspaceHint.prototype.setHint = function (hintData) {
console.log("todo: create hint");
this.hintData = hintData;
- this.id = hintData.id;
this.iconGroup_ = this.createHintIcon_();
this.workspace_.svgGroup_.appendChild(this.iconGroup_);
this.position();
From 000304ba1757d7f2c4f190b439b428481d4a15df Mon Sep 17 00:00:00 2001
From: Peeratham Techapalokul
Date: Wed, 20 Mar 2019 22:19:09 -0400
Subject: [PATCH 11/23] workspace hint
---
core/workspace_hint.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/core/workspace_hint.js b/core/workspace_hint.js
index 11164dbcb1..0923270952 100644
--- a/core/workspace_hint.js
+++ b/core/workspace_hint.js
@@ -13,9 +13,9 @@ Blockly.WorkspaceHint = function (workspace) {
Blockly.WorkspaceHint.prototype.WIDTH_ = 20;
Blockly.WorkspaceHint.prototype.HEIGHT_ = 20;
-Blockly.WorkspaceHint.prototype.MARGIN_TOP_ = 30;
+Blockly.WorkspaceHint.prototype.MARGIN_TOP_ = 80;
Blockly.WorkspaceHint.prototype.MARGIN_BOTTOM_ = 12;
-Blockly.WorkspaceHint.prototype.MARGIN_SIDE_ = 12;
+Blockly.WorkspaceHint.prototype.MARGIN_SIDE_ = 20;
Blockly.WorkspaceHint.prototype.HEIGHT_ = 124;
Blockly.WorkspaceHint.prototype.getId = function () {
From 9cb59de31762118a9be7d41ece11d292ba75b255 Mon Sep 17 00:00:00 2001
From: Peeratham Techapalokul
Date: Fri, 19 Apr 2019 18:28:42 -0400
Subject: [PATCH 12/23] improve hint highlighting
---
core/inject.js | 74 +++++++++++++++++++++++++++++++++++++++++++
core/workspace_svg.js | 47 +++++++++++++++++++--------
2 files changed, 107 insertions(+), 14 deletions(-)
diff --git a/core/inject.js b/core/inject.js
index 01f9d9c700..08ac391898 100644
--- a/core/inject.js
+++ b/core/inject.js
@@ -216,6 +216,80 @@ Blockly.createDom_ = function(container, options) {
// copy ends
+ // another copy
+ var focusBlocksGlowFilter = Blockly.utils.createSvgElement('filter',
+ {'id': 'blocklyFocusBlocksGlowFilter',
+ 'height': '160%',
+ 'width': '180%',
+ y: '-30%',
+ x: '-40%'
+ },
+ defs);
+
+ options.focusBlocksGlowBlur = Blockly.utils.createSvgElement('feGaussianBlur',
+ {'in': 'SourceGraphic',
+ 'stdDeviation': 1.5},
+ focusBlocksGlowFilter);
+ // Set all gaussian blur pixels to 1 opacity before applying flood
+ var componentTransfer2 = Blockly.utils.createSvgElement('feComponentTransfer', {'result': 'outBlur'}, focusBlocksGlowFilter);
+ Blockly.utils.createSvgElement('feFuncA',
+ {'type': 'table',
+ 'tableValues': '0' + goog.string.repeat(' 1', 16)},
+ componentTransfer2);
+ // Color the highlight
+ Blockly.utils.createSvgElement('feFlood',
+ {'flood-color': '#73C2FB',
+ 'flood-opacity': Blockly.Colours.stackGlowOpacity,
+ 'result': 'outColor'},
+ focusBlocksGlowFilter);
+ Blockly.utils.createSvgElement('feComposite',
+ {'in': 'outColor',
+ 'in2': 'outBlur',
+ 'operator': 'in',
+ 'result': 'outGlow'},
+ focusBlocksGlowFilter);
+ Blockly.utils.createSvgElement('feComposite',
+ {'in': 'SourceGraphic', 'in2': 'outGlow', 'operator': 'over'}, focusBlocksGlowFilter);
+ // copy end
+
+ // another copy
+ var focusBlocksStackGlowFilter = Blockly.utils.createSvgElement('filter',
+ {'id': 'focusBlocksStackGlowFilter',
+ 'height': '160%',
+ 'width': '180%',
+ y: '-30%',
+ x: '-40%'
+ },
+ defs);
+
+ options.focusBlocksStackGlowBlur = Blockly.utils.createSvgElement('feGaussianBlur',
+ {'in': 'SourceGraphic',
+ 'stdDeviation': 4},
+ focusBlocksStackGlowFilter);
+ // Set all gaussian blur pixels to 1 opacity before applying flood
+ var componentTransfer2 = Blockly.utils.createSvgElement('feComponentTransfer', {'result': 'outBlur'}, focusBlocksStackGlowFilter);
+ Blockly.utils.createSvgElement('feFuncA',
+ {'type': 'table',
+ 'tableValues': '0' + goog.string.repeat(' 1', 16)},
+ componentTransfer2);
+ // Color the highlight
+ Blockly.utils.createSvgElement('feFlood',
+ {'flood-color': '#73C2FB',
+ 'flood-opacity': Blockly.Colours.stackGlowOpacity,
+ 'result': 'outColor'},
+ focusBlocksStackGlowFilter);
+ Blockly.utils.createSvgElement('feComposite',
+ {'in': 'outColor',
+ 'in2': 'outBlur',
+ 'operator': 'in',
+ 'result': 'outGlow'},
+ focusBlocksStackGlowFilter);
+ Blockly.utils.createSvgElement('feComposite',
+ {'in': 'SourceGraphic', 'in2': 'outGlow', 'operator': 'over'}, focusBlocksStackGlowFilter);
+
+
+ // copy end
+
// Filter for replacement marker
var replacementGlowFilter = Blockly.utils.createSvgElement('filter',
diff --git a/core/workspace_svg.js b/core/workspace_svg.js
index 39ab1eb5d7..33ecc585b1 100644
--- a/core/workspace_svg.js
+++ b/core/workspace_svg.js
@@ -995,13 +995,20 @@ Blockly.WorkspaceSvg.prototype.glowMessyBlock = function(ids, isMessyGlowingBloc
* @param {?string} start id ID of block to find.
* @param {?string} (optional) end id ID of block to find.
*/
-Blockly.WorkspaceSvg.prototype.drawHighlightBox = function(id, id2=null) {
+Blockly.WorkspaceSvg.prototype.drawHighlightBox = function (id, id2 = null) {
+ var svg = null;
var block1 = null, block2 = null;
+
if (id) {
block1 = this.getBlockById(id);
if (!block1) {
throw 'Tried to highlight block that does not exist.';
}
+ if (block1.getFirstStatementConnection()) {
+ svg = block1.getSvgRoot();
+ svg.setAttribute('filter', 'url(#' + 'focusBlocksStackGlowFilter' + ')');
+ //just need to set filter as with other glow
+ }
}
if (id2) {
block2 = this.getBlockById(id2);
@@ -1009,24 +1016,36 @@ Blockly.WorkspaceSvg.prototype.drawHighlightBox = function(id, id2=null) {
throw 'Tried to highlight block that does not exist.';
}
}
- this.highlightBoxs_.push(Blockly.utils.createSvgElement('path',
- {
- 'd': Blockly.utils.getBoundingPath(block1,block2),
- 'class': 'blocklyPath blocklyBlockBackground',
- 'stroke': 'black',
- 'style': 'stroke-width: 5px',
- 'fill-opacity': '0',
- 'fill': 'black'
- },
- block1.getSvgRoot()));
+ if (!svg) {
+ svg = Blockly.utils.createSvgElement('path',
+ {
+ 'd': Blockly.utils.getBoundingPath(block1, block2),
+ 'class': 'blocklyBlockBackground',
+ 'fill': 'black',
+ 'fill-opacity': '0',
+ 'stroke': '#73C2FB',
+ // 'stroke-width': '1px',
+ },
+ block1.getSvgRoot());
+ svg.setAttribute('filter', 'url(#' + 'blocklyFocusBlocksGlowFilter' + ')');
+ }
+ this.highlightBoxs_.push(svg);
+
};
+
/**
* Remove all highlighting boxes for given block/blocks in the workspace.
*/
-Blockly.WorkspaceSvg.prototype.removeHighlightBox = function() {
- for ( var i=0; i
Date: Fri, 19 Apr 2019 23:46:33 -0400
Subject: [PATCH 13/23] improve block highlighting when highlighting a single
control block
---
core/utils.js | 64 ++++++++++++++++++++++++++++++++++
core/workspace_svg.js | 29 +++++++++------
tests/vertical_playground.html | 25 ++++++++++---
3 files changed, 104 insertions(+), 14 deletions(-)
diff --git a/core/utils.js b/core/utils.js
index 8b47816d20..64de42c49b 100644
--- a/core/utils.js
+++ b/core/utils.js
@@ -994,6 +994,70 @@ Blockly.utils.getBoundingPath = function(block1, block2=null){
return d;
};
+
+Blockly.utils.getBoundingPathForControlBlock = function(block){
+ var d = "";
+ var pd1 = block.svgPath_.getAttribute("d").split(" H");
+
+ d = d + pd1[0] + " H" + pd1[1];
+ var blockType = block.type.replace("control_","");
+ d = d + Blockly.utils.pathBetweenForControlBlock(block);
+ if(["if","repeat","repeat_until","forever"].includes(blockType)){
+ if(["if"].includes(blockType)){
+ d = d + " H" + pd1[5] + " H" + pd1[6];
+ }else if(["forever"].includes(blockType)){
+ d = d + " H" + pd1[6];
+ }else if(["repeat"].includes(blockType)){
+ d = d + " H" + pd1[6] + " H"+ pd1[7];
+ }
+ else{
+ d = d + " H" + pd1[6] + " H" + pd1[7];
+ }
+ } else if(blockType == "if_else"){
+ d = d + " H" + pd1[8] + " H" + pd1[9];
+ } else {
+
+ }
+ return d;
+};
+
+Blockly.utils.pathBetweenForControlBlock = function(block1, translate=0){
+ var d = "";
+ var block = block1;
+
+ var pd = block.svgPath_.getAttribute("d").split(" H");
+ pd[2] = pd[2].replace(pd[2].split(" ")[1],parseInt(pd[2].split(" ")[1]) + translate);
+ var blockType = block.type.replace("control_","");
+ if(["repeat","repeat_until","forever"].includes(blockType)){
+ pd[5] = pd[5].replace(pd[5].split(" ")[1],parseInt(pd[5].split(" ")[1]) + translate )
+ var substack = block.inputList[1].connection ? block.inputList[1].connection.targetConnection.getSourceBlock() : block.inputList[2].connection.targetConnection.getSourceBlock();
+ var newTranslate = parseInt(substack.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]) + translate;
+ d = d + " H" + pd[2] + Blockly.utils.pathBetweenForControlBlock(substack, newTranslate)
+ + " H" + pd[5];
+ } else if(blockType == "if"){
+ pd[4] = pd[4].replace(pd[4].split(" ")[1],parseInt(pd[4].split(" ")[1]) + translate )
+ var substack = block.inputList[1].connection ? block.inputList[1].connection.targetConnection.getSourceBlock() : block.inputList[2].connection.targetConnection.getSourceBlock();
+ var newTranslate = parseInt(substack.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]) + translate;
+ d = d + " H" + pd[2] + Blockly.utils.pathBetweenForControlBlock(substack, newTranslate)
+ + " H" + pd[4];
+ } else if(blockType == "if_else"){
+ pd[5] = pd[5].replace(pd[5].split(" ")[1],parseInt(pd[5].split(" ")[1]) + translate )
+ pd[7] = pd[7].replace(pd[7].split(" ")[1],parseInt(pd[7].split(" ")[1]) + translate )
+ var substack1 = block.inputList[2].connection.targetConnection.getSourceBlock();
+ var substack2 = block.inputList[4].connection.targetConnection.getSourceBlock();
+ var newTranslate1 = parseInt(substack1.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]) + translate;
+ var newTranslate2 = parseInt(substack2.getSvgRoot().getAttribute("transform").replace("translate(","").split(",")[0]) + translate;
+ d = d + " H" + pd[2] + Blockly.utils.pathBetweenForControlBlock(substack1, newTranslate1)
+ + " H" + pd[5] + Blockly.utils.pathBetweenForControlBlock(substack2, newTranslate2)
+ + " H" + pd[7];
+ } else {
+ d = d + " H" + pd[2];
+ }
+
+ return d;
+};
+
+
/**
*Returns path string for nested blocks
*/
diff --git a/core/workspace_svg.js b/core/workspace_svg.js
index 33ecc585b1..71c8eb9081 100644
--- a/core/workspace_svg.js
+++ b/core/workspace_svg.js
@@ -1001,14 +1001,24 @@ Blockly.WorkspaceSvg.prototype.drawHighlightBox = function (id, id2 = null) {
if (id) {
block1 = this.getBlockById(id);
+ if (block1.getFirstStatementConnection()&&!block2) {
+ svg = Blockly.utils.createSvgElement('path',
+ {
+ 'd': Blockly.utils.getBoundingPathForControlBlock(block1),
+ 'class': 'blocklyBlockBackground',
+ 'fill': 'black',
+ 'fill-opacity': '0',
+ 'stroke': '#73C2FB'
+ },
+ block1.getSvgRoot());
+ svg.setAttribute('filter', 'url(#' + 'blocklyFocusBlocksGlowFilter' + ')');
+
+ this.highlightBoxs_.push(svg);
+ return;
+ }
if (!block1) {
throw 'Tried to highlight block that does not exist.';
}
- if (block1.getFirstStatementConnection()) {
- svg = block1.getSvgRoot();
- svg.setAttribute('filter', 'url(#' + 'focusBlocksStackGlowFilter' + ')');
- //just need to set filter as with other glow
- }
}
if (id2) {
block2 = this.getBlockById(id2);
@@ -1016,19 +1026,18 @@ Blockly.WorkspaceSvg.prototype.drawHighlightBox = function (id, id2 = null) {
throw 'Tried to highlight block that does not exist.';
}
}
- if (!svg) {
+
svg = Blockly.utils.createSvgElement('path',
{
- 'd': Blockly.utils.getBoundingPath(block1, block2),
+ 'd': Blockly.utils.getBoundingPath2(block1, block2),
'class': 'blocklyBlockBackground',
'fill': 'black',
'fill-opacity': '0',
- 'stroke': '#73C2FB',
- // 'stroke-width': '1px',
+ 'stroke': '#73C2FB'
},
block1.getSvgRoot());
svg.setAttribute('filter', 'url(#' + 'blocklyFocusBlocksGlowFilter' + ')');
- }
+
this.highlightBoxs_.push(svg);
};
diff --git a/tests/vertical_playground.html b/tests/vertical_playground.html
index eb26d39024..ee20d96465 100644
--- a/tests/vertical_playground.html
+++ b/tests/vertical_playground.html
@@ -112,10 +112,23 @@
// Restore flyout event logging state.
state = sessionStorage.getItem('logFlyoutEvents');
logFlyoutEvents(Boolean(state));
- showHintSetup();
+ // showHintSetup();
+ highlightBlocksSetup();
+ svgSetup();
}
}
+ function svgSetup(){
+ var svg = document.getElementById('testSvg'); //Get svg element
+ var newElement = document.createElementNS("http://www.w3.org/2000/svg", 'path'); //Create a path in SVG's namespace
+ newElement.setAttribute("d","M 0 0 L 10 10"); //Set path's data
+ newElement.setAttribute("id", "testPath");
+ newElement.style.stroke = "#000"; //Set stroke colour
+ newElement.style.strokeWidth = "5px"; //Set stroke width
+ svg.appendChild(newElement);
+
+ }
+
function getToolboxElement() {
var match = location.search.match(/toolbox=([^&]+)/);
return document.getElementById('toolbox-' + (match ? match[1] : 'categories'));
@@ -308,9 +321,12 @@
}
}
- function showHintSetup(){
+ function highlightBlocksSetup(){
var input = document.getElementById('importExport');
- input.value = "10";
+ input.value =
+ "1010"
+ // "10_mouse_"
+ ;
fromXml();
Blockly.selected = workspace.getBlockById('*`#p/~R4kNb@uT|}iU@u');
@@ -318,7 +334,7 @@
Blockly.selected.setHintText("abc");
Blockly.selected.hint.setVisible(true);
}
-
+ workspace.drawHighlightBox('target')
}
function setLocale(locale) {
@@ -600,5 +616,6 @@ Vertical Blocks
+