Block highlighting

* Separate block selection (editing) from highlighting (execution).
* Remove add/removeDragging functions. They clutter the API for no reason.
This commit is contained in:
Neil Fraser
2016-10-26 18:39:56 -07:00
committed by GitHub
parent 6300faf85e
commit 144be4d49f
4 changed files with 63 additions and 63 deletions

View File

@@ -830,12 +830,14 @@ Blockly.BlockSvg.prototype.setDragging_ = function(adding) {
var group = this.getSvgRoot();
group.translate_ = '';
group.skew_ = '';
this.addDragging();
Blockly.draggingConnections_ =
Blockly.draggingConnections_.concat(this.getConnections_(true));
Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_),
'blocklyDragging');
} else {
this.removeDragging();
Blockly.draggingConnections_ = [];
Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),
'blocklyDragging');
}
// Recurse through all blocks attached under this one.
for (var i = 0; i < this.childBlocks_.length; i++) {
@@ -1430,6 +1432,21 @@ Blockly.BlockSvg.prototype.setDisabled = function(disabled) {
}
};
/**
* Set whether the block is highlighted or not.
* @param {boolean} highlighted True if highlighted.
*/
Blockly.BlockSvg.prototype.setHighlighted = function(highlighted) {
if (highlighted) {
this.svgPath_.setAttribute('filter',
'url(#' + this.workspace.options.embossFilterId + ')');
this.svgPathLight_.style.display = 'none';
} else {
this.svgPath_.removeAttribute('filter');
this.svgPathLight_.style.display = 'block';
}
};
/**
* Select this block. Highlight it visually.
*/
@@ -1453,23 +1470,6 @@ Blockly.BlockSvg.prototype.removeSelect = function() {
'blocklySelected');
};
/**
* Adds the dragging class to this block.
* Also disables the highlights/shadows to improve performance.
*/
Blockly.BlockSvg.prototype.addDragging = function() {
Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_),
'blocklyDragging');
};
/**
* Removes the dragging class from this block.
*/
Blockly.BlockSvg.prototype.removeDragging = function() {
Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),
'blocklyDragging');
};
// Overrides of functions on Blockly.Block that take into account whether the
// block has been rendered.

View File

@@ -104,19 +104,22 @@ Blockly.createDom_ = function(container, options) {
</defs>
*/
var defs = Blockly.createSvgElement('defs', {}, svg);
// Each filter/pattern needs a unique ID for the case of multiple Blockly
// instances on a page. Browser behaviour becomes undefined otherwise.
// https://neil.fraser.name/news/2015/11/01/
var rnd = String(Math.random()).substring(2);
/*
<filter id="blocklyEmbossFilter837493">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur"/>
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur" />
<feSpecularLighting in="blur" surfaceScale="1" specularConstant="0.5"
specularExponent="10" lighting-color="white"
result="specOut">
<fePointLight x="-5000" y="-10000" z="20000"/>
<fePointLight x="-5000" y="-10000" z="20000" />
</feSpecularLighting>
<feComposite in="specOut" in2="SourceAlpha" operator="in"
result="specOut"/>
result="specOut" />
<feComposite in="SourceGraphic" in2="specOut" operator="arithmetic"
k1="0" k2="1" k3="1" k4="0"/>
k1="0" k2="1" k3="1" k4="0" />
</filter>
*/
var embossFilter = Blockly.createSvgElement('filter',

View File

@@ -38,6 +38,7 @@ goog.require('Blockly.Workspace');
goog.require('Blockly.Xml');
goog.require('Blockly.ZoomControls');
goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.math.Coordinate');
goog.require('goog.userAgent');
@@ -65,6 +66,12 @@ Blockly.WorkspaceSvg = function(options) {
* @const
*/
this.SOUNDS_ = Object.create(null);
/**
* List of currently highlighted blocks.
* @type !Array.<!Blockly.BlockSvg>
* @private
*/
this.highlightedBlocks_ = [];
};
goog.inherits(Blockly.WorkspaceSvg, Blockly.Workspace);
@@ -260,7 +267,7 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) {
// Determine if there needs to be a category tree, or a simple list of
// blocks. This cannot be changed later, since the UI is very different.
if (this.options.hasCategories) {
/**
/**
* @type {Blockly.Toolbox}
* @private
*/
@@ -537,53 +544,43 @@ Blockly.WorkspaceSvg.prototype.render = function() {
};
/**
* Turn the visual trace functionality on or off.
* @param {boolean} armed True if the trace should be on.
* Was used back when block highlighting (for execution) and block selection
* (for editing) were the same thing.
* Any calls of this function can be deleted.
* @deprecated October 2016
*/
Blockly.WorkspaceSvg.prototype.traceOn = function(armed) {
this.traceOn_ = armed;
if (this.traceWrapper_) {
Blockly.unbindEvent_(this.traceWrapper_);
this.traceWrapper_ = null;
}
if (armed) {
this.traceWrapper_ = Blockly.bindEventWithChecks_(this.svgBlockCanvas_,
'blocklySelectChange', this, function() {this.traceOn_ = false;});
}
Blockly.WorkspaceSvg.prototype.traceOn = function() {
console.warn('Deprecated call to traceOn, delete this.');
};
/**
* Highlight a block in the workspace.
* @param {?string} id ID of block to find.
* Highlight or unhighlight a block in the workspace.
* @param {?string} id ID of block to highlight/unhighlight,
* or null for no block (used to unhighlight all blocks).
* @param {boolean=} opt_state If undefined, highlight specified block and
* automatically unhighlight all others. If true or false, manually
* highlight/unhighlight the specified block.
*/
Blockly.WorkspaceSvg.prototype.highlightBlock = function(id) {
if (this.traceOn_ && Blockly.dragMode_ != Blockly.DRAG_NONE) {
// The blocklySelectChange event normally prevents this, but sometimes
// there is a race condition on fast-executing apps.
this.traceOn(false);
}
if (!this.traceOn_) {
return;
}
var block = null;
if (id) {
block = this.getBlockById(id);
if (!block) {
return;
Blockly.WorkspaceSvg.prototype.highlightBlock = function(id, opt_state) {
if (opt_state === undefined) {
// Unhighlight all blocks.
for (var i = 0, block; block = this.highlightedBlocks_[i]; i++) {
block.setHighlighted(false);
}
this.highlightedBlocks_.length = 0;
}
// Temporary turn off the listener for selection changes, so that we don't
// trip the monitor for detecting user activity.
this.traceOn(false);
// Select the current block.
// Highlight/unhighlight the specified block.
var block = id ? this.getBlockById(id) : null;
if (block) {
block.select();
} else if (Blockly.selected) {
Blockly.selected.unselect();
var state = (opt_state === undefined) || opt_state;
// Using Set here would be great, but at the cost of IE10 support.
if (!state) {
goog.array.remove(this.highlightedBlocks_, block);
} else if (this.highlightedBlocks_.indexOf(block) == -1) {
this.highlightedBlocks_.push(block);
}
block.setHighlighted(state);
}
// Restore the monitor for user activity after the selection event has fired.
var thisWorkspace = this;
setTimeout(function() {thisWorkspace.traceOn(true);}, 1);
};
/**

View File

@@ -172,7 +172,6 @@
alert('Ready to execute this code:\n\n' + code);
document.getElementById('stepButton').disabled = '';
highlightPause = false;
workspace.traceOn(true);
workspace.highlightBlock(null);
}
@@ -183,6 +182,7 @@
if (!ok) {
// Program complete, no more code to execute.
document.getElementById('stepButton').disabled = 'disabled';
workspace.highlightBlock(null);
return;
}
}