Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2bf116a
Merge pull request #1 from peeratham/develop
prapti-khawas Jul 13, 2018
23832a1
Adding methods for improvables
prapti-khawas Jul 16, 2018
e2e7548
Merge pull request #7 from peeratham/refactoring-support
peeratham Jan 25, 2019
1f35e25
handle hint mouseover
peeratham Feb 2, 2019
1a8b754
Merge pull request #8 from peeratham/blocks-quality-improvement-support
peeratham Feb 2, 2019
0ae8468
Merge pull request #1 from q4blocks/blocks-quality-improvement-support
thesourabh Feb 2, 2019
723b3b0
Merge pull request #2 from prapti-khawas/improvables
thesourabh Feb 3, 2019
0d711ec
Code Hint: Added mouseover and mouseout handling
thesourabh Feb 5, 2019
abe85ab
Merge pull request #9 from thesourabh/blocks-quality-improvement-support
peeratham Feb 7, 2019
da561e1
Added two-step edit procedure option for extracted procedure
thesourabh Feb 22, 2019
4a414c9
Merge pull request #10 from thesourabh/blocks-quality-improvement-sup…
peeratham Mar 4, 2019
8476a16
compact xml export
peeratham Mar 4, 2019
36baec1
Merge remote-tracking branch 'q4blocks/blocks-quality-improvement-sup…
peeratham Mar 4, 2019
bb88bfd
Added Prapti's code for highlighting a block with a fixed end block.
thesourabh Mar 5, 2019
62bd55f
Merge pull request #11 from thesourabh/blocks-quality-improvement-sup…
peeratham Mar 5, 2019
504b0ae
Merge remote-tracking branch 'q4blocks/blocks-quality-improvement-sup…
peeratham Mar 5, 2019
4cd574f
add workspace hint and positioning
peeratham Mar 6, 2019
4e30f3b
add context menu
peeratham Mar 6, 2019
14a188d
hide and show hint
peeratham Mar 6, 2019
2c676c7
use id instead of hintData.id
peeratham Mar 6, 2019
000304b
workspace hint
peeratham Mar 21, 2019
8e04f0c
Merge pull request #14 from peeratham/blocks-quality-improvement-support
peeratham Mar 21, 2019
9cb59de
improve hint highlighting
peeratham Apr 19, 2019
370a9cd
improve block highlighting when highlighting a single control block
peeratham Apr 20, 2019
cb12ae2
fix bug highlighting block
peeratham Apr 20, 2019
b5cd210
add highlighting color as options
peeratham Apr 20, 2019
2f6ce26
fix bug highlighting
peeratham Apr 22, 2019
5db6cd5
fire block events
peeratham Aug 20, 2019
84800f9
field highlighting
peeratham Aug 21, 2019
340f871
basic field (un) highlight
peeratham Aug 28, 2019
53a436b
fix bug insert after
peeratham Aug 28, 2019
af8bbde
procedure feature patch
peeratham Sep 10, 2019
ceccbdd
fix bug highlighting blocks
peeratham Oct 3, 2019
a69bbc7
fix rendering context menu options
peeratham Oct 3, 2019
4ac89f5
Merge pull request #15 from peeratham/blocks-quality-improvement-support
peeratham Oct 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion blocks_vertical/procedures.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,17 @@ Blockly.ScratchBlocks.ProcedureUtils.definitionDomToMutation = function(xmlEleme
this.procCode_ = xmlElement.getAttribute('proccode');
this.warp_ = JSON.parse(xmlElement.getAttribute('warp'));

var prevArgIds = this.argumentIds_;
var prevDisplayNames = this.displayNames_;

this.argumentIds_ = JSON.parse(xmlElement.getAttribute('argumentids'));
this.displayNames_ = JSON.parse(xmlElement.getAttribute('argumentnames'));
this.argumentDefaults_ = JSON.parse(
xmlElement.getAttribute('argumentdefaults'));
this.updateDisplay_();
if (this.updateArgumentReporterNames_) {
this.updateArgumentReporterNames_(prevArgIds, prevDisplayNames);
}
};

// End of serialization and deserialization.
Expand Down Expand Up @@ -708,6 +714,62 @@ Blockly.ScratchBlocks.ProcedureUtils.removeArgumentCallback_ = function(
}
};

/**
* Update argument reporter field values after an edit to the prototype mutation
* using previous argument ids and names.
* Because the argument reporters only store names and not which argument ids they
* are linked to, it would not be safe to update all argument reporters on the workspace
* since they may be argument reporters with the same name from a different procedure.
* Until there is a more explicit way of identifying argument reporter blocks using ids,
* be conservative and only update argument reporters that are used in the
* stack below the prototype, ie the definition.
* @param {!Array<string>} prevArgIds The previous ordering of argument ids.
* @param {!Array<string>} prevDisplayNames The previous argument names.
* @this Blockly.Block
*/
Blockly.ScratchBlocks.ProcedureUtils.updateArgumentReporterNames_ = function(prevArgIds, prevDisplayNames) {
var nameChanges = [];
var argReporters = [];
var definitionBlock = this.getParent();
if (!definitionBlock) return;

// Create a list of argument reporters that are descendants of the definition stack (see above comment)
var allBlocks = definitionBlock.getDescendants(false);
for (var i = 0; i < allBlocks.length; i++) {
var block = allBlocks[i];
if ((block.type === 'argument_reporter_string_number' ||
block.type === 'argument_reporter_boolean') &&
!block.isShadow()) { // Exclude arg reporters in the prototype block, which are shadows.
argReporters.push(block);
}
}

// Create a list of "name changes", including the new name and blocks matching the old name
// Only search over the current set of argument ids, ignore args that have been removed
for (var i = 0, id; id = this.argumentIds_[i]; i++) {
// Find the previous index of this argument id. Could be -1 if it is newly added.
var prevIndex = prevArgIds.indexOf(id);
if (prevIndex == -1) continue; // Newly added argument, no corresponding previous argument to update.
var prevName = prevDisplayNames[prevIndex];
if (prevName != this.displayNames_[i]) {
nameChanges.push({
newName: this.displayNames_[i],
blocks: argReporters.filter(function(block) {
return block.getFieldValue('VALUE') == prevName;
})
});
}
}

// Finally update the blocks for each name change.
// Do this after creating the lists to avoid cycles of renaming.
for (var j = 0, nameChange; nameChange = nameChanges[j]; j++) {
for (var k = 0, block; block = nameChange.blocks[k]; k++) {
block.setFieldValue(nameChange.newName, 'VALUE');
}
}
};

Blockly.Blocks['procedures_definition'] = {
/**
* Block for defining a procedure with no return value.
Expand Down Expand Up @@ -792,7 +854,8 @@ Blockly.Blocks['procedures_prototype'] = {
addProcedureLabel_: Blockly.ScratchBlocks.ProcedureUtils.addLabelField_,

// Only exists on procedures_prototype.
createArgumentReporter_: Blockly.ScratchBlocks.ProcedureUtils.createArgumentReporter_
createArgumentReporter_: Blockly.ScratchBlocks.ProcedureUtils.createArgumentReporter_,
updateArgumentReporterNames_: Blockly.ScratchBlocks.ProcedureUtils.updateArgumentReporterNames_
};

Blockly.Blocks['procedures_declaration'] = {
Expand Down
5 changes: 3 additions & 2 deletions core/block_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.hintId = hint.getText()||hint.getId();
this.recordUndo = false;
this.interactionType = interactionType;
};
goog.inherits(Blockly.Events.HintClick, Blockly.Events.Abstract);

Expand Down
58 changes: 56 additions & 2 deletions core/block_svg.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,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');
}
};

/**
Expand Down Expand Up @@ -391,6 +416,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.
Expand Down
39 changes: 31 additions & 8 deletions core/block_transformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,30 @@ Blockly.BlockTransformer.prototype.doTransform = function (refactorable) {
};

Blockly.BlockTransformer.prototype.executeAction = function (action) {
let result = true;
try {
this.apply(action);
result = this.apply(action);
Blockly.Events.fireNow_();
} 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) {
let varCreateJson = {
type: "var_create",
varType: "",
varName: action.name,
varId: action.id
varId: action.id,
isLocal: action.target==='_stage_'?false:true
};

let varCreateEvent = new Blockly.Events.VarCreate(null);
Expand All @@ -49,10 +52,10 @@ Blockly.BlockTransformer.prototype.VarDeclareAction = function (action) {
return true;
}

Blockly.BlockTransformer.prototype.VarRename = function (action) {
Blockly.BlockTransformer.prototype.VarRenameAction = function (action) {
let varRenameJson = {
type: "var_rename",
varId: action.id,
varId: action.var_id,
oldName: action.oldName,
newName: action.newName
};
Expand All @@ -67,15 +70,19 @@ 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) {
Blockly.Events.setGroup(true);
try {
let targetBlock = this.workspace.getBlockById(action.target_block);
let insertedBlock = this.workspace.getBlockById(action.inserted_block);
let previousBlock = targetBlock.previousConnection.targetBlock();
let previousBlock = targetBlock.previousConnection?targetBlock.previousConnection.targetBlock():null;

let moveEventJsonSpec = null;

Expand Down Expand Up @@ -206,5 +213,21 @@ Blockly.BlockTransformer.prototype.ReplaceAction = function (action) {

};

Blockly.BlockTransformer.prototype.VarDeleteAction = function (action) {
let varDeleteJson = {
type: "var_delete",
varId: action.var_id,
// var_name: action.var_name,
// target: action.target
};

let varDeleteEvent = new Blockly.Events.VarDelete(null);
varDeleteEvent.id = action.var_id;
varDeleteEvent.fromJson(varDeleteJson);
varDeleteEvent.workspaceId = this.workspace.id;
varDeleteEvent.run(true);
return true;
}

// Blockly.Workspace.prototype.createVariable
// Blockly.Workspace.prototype.deleteVariableById
1 change: 1 addition & 0 deletions core/colours.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ Blockly.Colours = {
"stackGlowSize": 4,
"stackGlowOpacity": 1,
"replacementGlow": "#FFFFFF",
"messyBlockGlow": "#ff0000",
"replacementGlowSize": 2,
"replacementGlowOpacity": 1,
"colourPickerStroke": "#FFFFFF",
Expand Down
2 changes: 1 addition & 1 deletion core/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@ Blockly.Css.CONTENT = [
'outline: none;',
'padding: 4px 0;',
'position: absolute;',
'overflow-y: auto;',
'overflow-y: hidden;',
'overflow-x: hidden;',
'z-index: 20000;', /* Arbitrary, but some apps depend on it... */
'}',
Expand Down
44 changes: 44 additions & 0 deletions core/flyout_base.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,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.<!Blockly.BlockSvg>
* @private
*/
this.highlightBoxs_ = [];

};

/**
Expand Down Expand Up @@ -921,3 +929,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<this.highlightBoxs_.length; i++ ) {
this.highlightBoxs_[i].remove();
}
};
17 changes: 17 additions & 0 deletions core/gesture.js
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ Blockly.Gesture.prototype.handleUp = function(e) {
this.doBubbleClick_();
} else if (this.isFieldClick_()) {
this.doFieldClick_();
this.startWorkspace_.setActiveFieldValue(this.startField_.sourceBlock_); //for contextualized hints
} else if (this.isBlockClick_()) {
this.doBlockClick_();
} else if (this.isWorkspaceClick_()) {
Expand Down Expand Up @@ -640,6 +641,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);
Expand Down Expand Up @@ -709,6 +712,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. */
Expand Down Expand Up @@ -818,6 +829,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.
Expand Down
Loading