Fire function events instead of DOM events.

This commit is contained in:
Neil Fraser
2016-02-11 21:40:33 -08:00
parent d310b96f84
commit 0fab13400a
9 changed files with 81 additions and 98 deletions

View File

@@ -125,6 +125,11 @@ Blockly.Block = function(workspace, prototypeName, opt_id) {
var xmlBlock = Blockly.Xml.blockToDom(this);
Blockly.Events.fire(new Blockly.Events.Create(workspace, xmlBlock));
}
// Bind an onchange function, if it exists.
if (goog.isFunction(this.onchange)) {
this.onchangeWrapper_ = this.onchange.bind(this);
this.workspace.addChangeListener(this.onchangeWrapper_);
}
};
/**
@@ -162,6 +167,10 @@ Blockly.Block.prototype.colour_ = '#000000';
* all children of this block.
*/
Blockly.Block.prototype.dispose = function(healStack) {
// Terminate onchange event calls.
if (this.onchangeWrapper_) {
this.workspace.removeChangeListener(this.onchangeWrapper_)
}
this.unplug(healStack);
if (Blockly.Events.isEnabled() && !this.isShadow()) {
Blockly.Events.fire(new Blockly.Events.Delete(this));

View File

@@ -112,11 +112,6 @@ Blockly.BlockSvg.prototype.initSvg = function() {
Blockly.bindEvent_(this.getSvgRoot(), 'touchstart', null,
function(e) {Blockly.longStart_(e, thisBlock);});
}
// Bind an onchange function, if it exists.
if (goog.isFunction(this.onchange) && !this.eventsInit_) {
this.onchangeWrapper_ = Blockly.bindEvent_(this.workspace.getCanvas(),
'blocklyWorkspaceChange', this, this.onchange);
}
this.eventsInit_ = true;
if (!this.getSvgRoot().parentNode) {
@@ -1094,11 +1089,6 @@ Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR =
*/
Blockly.BlockSvg.prototype.dispose = function(healStack, animate) {
Blockly.Field.startCache();
// Terminate onchange event calls.
if (this.onchangeWrapper_) {
Blockly.unbindEvent_(this.onchangeWrapper_);
this.onchangeWrapper_ = null;
}
// If this block is being dragged, unlink the mouse events.
if (Blockly.selected == this) {
Blockly.terminateDrag_();

View File

@@ -591,9 +591,6 @@ Blockly.Connection.prototype.closest = function(maxLimit, dx, dy) {
* @private
*/
Blockly.Connection.prototype.checkType_ = function(otherConnection) {
if (Blockly.OPPOSITE_TYPE[this.type] != otherConnection.type) {
return false;
}
// Don't split a connection where both sides are immovable.
var thisTargetBlock = this.targetBlock();
if (thisTargetBlock && !thisTargetBlock.isMovable() &&

View File

@@ -64,12 +64,6 @@ Blockly.Events.MOVE = 'move';
*/
Blockly.Events.FIRE_QUEUE_ = [];
/**
* PID of next scheduled firing.
* @private
*/
Blockly.Events.fireTask_ = null;
/**
* Create a custom event and fire it.
* @param {!Blockly.Events.Abstract} event Custom data for event.
@@ -78,10 +72,11 @@ Blockly.Events.fire = function(event) {
if (!Blockly.Events.isEnabled()) {
return;
}
Blockly.Events.FIRE_QUEUE_.push(event);
if (Blockly.Events.fireTask_ === null) {
Blockly.Events.fireTask_ = setTimeout(Blockly.Events.fireNow_, 0);
if (Blockly.Events.FIRE_QUEUE_.length == 0) {
// Schedule a firing of the event queue.
setTimeout(Blockly.Events.fireNow_, 0);
}
Blockly.Events.FIRE_QUEUE_.push(event);
};
/**
@@ -91,21 +86,10 @@ Blockly.Events.fire = function(event) {
Blockly.Events.fireNow_ = function() {
var queue = Blockly.Events.filter_(Blockly.Events.FIRE_QUEUE_);
Blockly.Events.FIRE_QUEUE_.length = 0;
Blockly.Events.fireTask_ = null;
for (var i = 0, detail; detail = queue[i]; i++) {
console.log(detail);
var workspace = Blockly.Workspace.getById(detail.workspaceId);
if (workspace && workspace.rendered) {
// Create a custom event in a browser-compatible way.
if (typeof CustomEvent == 'function') {
// W3
var evt = new CustomEvent('blocklyWorkspaceChange', {'detail': detail});
} else {
// MSIE
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(eventName, false, false, detail);
}
workspace.getCanvas().dispatchEvent(evt);
for (var i = 0, event; event = queue[i]; i++) {
var workspace = Blockly.Workspace.getById(event.workspaceId);
if (workspace) {
workspace.fireChangeListener(event);
}
}
};

View File

@@ -154,9 +154,8 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
// Bind to keyPress -- repeatedly resize when holding down a key.
htmlInput.onKeyPressWrapper_ =
Blockly.bindEvent_(htmlInput, 'keypress', this, this.onHtmlInputChange_);
htmlInput.onWorkspaceChangeWrapper_ =
Blockly.bindEvent_(workspace.getCanvas(), 'blocklyWorkspaceChange', this,
this.resizeEditor_);
htmlInput.onWorkspaceChangeWrapper_ = this.resizeEditor_.bind(this);
workspace.addChangeListener(htmlInput.onWorkspaceChangeWrapper_);
};
/**
@@ -279,7 +278,8 @@ Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
Blockly.unbindEvent_(htmlInput.onKeyDownWrapper_);
Blockly.unbindEvent_(htmlInput.onKeyUpWrapper_);
Blockly.unbindEvent_(htmlInput.onKeyPressWrapper_);
Blockly.unbindEvent_(htmlInput.onWorkspaceChangeWrapper_);
thisField.sourceBlock_.workspace.removeChangeListener(
htmlInput.onWorkspaceChangeWrapper_);
Blockly.FieldTextInput.htmlInput_ = null;
// Delete style properties.
var style = Blockly.WidgetDiv.DIV.style;

View File

@@ -155,9 +155,8 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) {
Array.prototype.push.apply(this.eventWrappers_,
Blockly.bindEvent_(this.svgGroup_, 'wheel', this, this.wheel_));
if (!this.autoClose) {
Array.prototype.push.apply(this.eventWrappers_,
Blockly.bindEvent_(this.targetWorkspace_.getCanvas(),
'blocklyWorkspaceChange', this, this.filterForCapacity_));
this.filterWrapper_ = this.filterForCapacity_.bind(this);
this.targetWorkspace_.addChangeListener(this.filterWrapper_);
}
// Dragging the flyout up and down.
Array.prototype.push.apply(this.eventWrappers_,
@@ -171,6 +170,10 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) {
Blockly.Flyout.prototype.dispose = function() {
this.hide();
Blockly.unbindEvent_(this.eventWrappers_);
if (this.filterWrapper_) {
this.targetWorkspace_.removeChangeListener(this.filterWrapper_);
this.filterWrapper_ = null;
}
if (this.scrollbar_) {
this.scrollbar_.dispose();
this.scrollbar_ = null;
@@ -345,7 +348,7 @@ Blockly.Flyout.prototype.hide = function() {
}
this.listeners_.length = 0;
if (this.reflowWrapper_) {
Blockly.unbindEvent_(this.reflowWrapper_);
this.workspace_.removeChangeListener(this.reflowWrapper_);
this.reflowWrapper_ = null;
}
// Do NOT delete the blocks here. Wait until Flyout.show.
@@ -466,8 +469,8 @@ Blockly.Flyout.prototype.show = function(xmlList) {
// Fire a resize event to update the flyout's scrollbar.
Blockly.fireUiEventNow(window, 'resize');
this.reflowWrapper_ = Blockly.bindEvent_(this.workspace_.getCanvas(),
'blocklyWorkspaceChange', this, this.reflow);
this.reflowWrapper_ = this.reflow.bind(this);
this.workspace_.addChangeListener(this.reflowWrapper_);
};
/**

View File

@@ -232,17 +232,14 @@ Blockly.Mutator.prototype.setVisible = function(visible) {
if (this.block_.saveConnections) {
var thisMutator = this;
this.block_.saveConnections(this.rootBlock_);
this.sourceListener_ = Blockly.bindEvent_(
this.block_.workspace.getCanvas(),
'blocklyWorkspaceChange', null,
function() {
thisMutator.block_.saveConnections(thisMutator.rootBlock_)
});
this.sourceListener_ = function() {
thisMutator.block_.saveConnections(thisMutator.rootBlock_)
};
this.block_.workspace.addChangeListener(this.sourceListener_);
}
this.resizeBubble_();
// When the mutator's workspace changes, update the source block.
Blockly.bindEvent_(this.workspace_.getCanvas(), 'blocklyWorkspaceChange',
this, this.workspaceChanged_);
this.workspace_.addChangeListener(this.workspaceChanged_.bind(this));
this.updateColour();
} else {
// Dispose of the bubble.
@@ -255,7 +252,7 @@ Blockly.Mutator.prototype.setVisible = function(visible) {
this.workspaceWidth_ = 0;
this.workspaceHeight_ = 0;
if (this.sourceListener_) {
Blockly.unbindEvent_(this.sourceListener_);
this.block_.workspace.removeChangeListener(this.sourceListener_);
this.sourceListener_ = null;
}
}
@@ -283,7 +280,8 @@ Blockly.Mutator.prototype.workspaceChanged_ = function() {
// When the mutator's workspace changes, update the source block.
if (this.rootBlock_.workspace == this.workspace_) {
var oldMutation = this.block_.mutationToDom();
var oldMutationDom = this.block_.mutationToDom();
var oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom);
// Switch off rendering while the source block is rebuilt.
var savedRendered = this.block_.rendered;
this.block_.rendered = false;
@@ -293,9 +291,9 @@ Blockly.Mutator.prototype.workspaceChanged_ = function() {
this.block_.rendered = savedRendered;
// Mutation may have added some elements that need initalizing.
this.block_.initSvg();
var newMutation = this.block_.mutationToDom();
if (Blockly.Xml.domToText(oldMutation) !=
Blockly.Xml.domToText(newMutation)) {
var newMutationDom = this.block_.mutationToDom();
var newMutation = newMutationDom && Blockly.Xml.domToText(newMutationDom);
if (oldMutation != newMutation) {
Blockly.Events.fire(new Blockly.Events.Change(
this.block_, 'mutation', null, oldMutation, newMutation));
goog.Timer.callOnce(

View File

@@ -45,6 +45,8 @@ Blockly.Workspace = function(opt_options) {
this.RTL = !!this.options.RTL;
/** @type {!Array.<!Blockly.Block>} */
this.topBlocks_ = [];
/** @type {!Array.<!Function>} */
this.listeners_ = [];
};
/**
@@ -58,6 +60,7 @@ Blockly.Workspace.prototype.rendered = false;
* Unlink from all DOM elements to prevent memory leaks.
*/
Blockly.Workspace.prototype.dispose = function() {
this.listeners_.length = 0;
this.clear();
// Remove from workspace database.
delete Blockly.Workspace.WorkspaceDB_[this.id];
@@ -191,6 +194,38 @@ Blockly.Workspace.prototype.remainingCapacity = function() {
return this.options.maxBlocks - this.getAllBlocks().length;
};
/**
* When something in this workspace changes, call a function.
* @param {!Function} func Function to call.
* @return {!Function} Function that can be passed to
* removeChangeListener.
*/
Blockly.Workspace.prototype.addChangeListener = function(func) {
this.listeners_.push(func);
return func;
};
/**
* Stop listening for this workspace's changes.
* @param {Function} func Function to stop calling.
*/
Blockly.Workspace.prototype.removeChangeListener = function(func) {
var i = this.listeners_.indexOf(func);
if (i != -1) {
this.listeners_.splice(i, 1);
}
};
/**
* Fire a change event.
* @param {!Blockly.Events.Abstract} event Event to fire.
*/
Blockly.Workspace.prototype.fireChangeListener = function(event) {
for (var i = 0, func; func = this.listeners_[i]; i++) {
func(event);
}
};
/**
* Database of all workspaces.
* @private
@@ -208,3 +243,7 @@ Blockly.Workspace.getById = function(id) {
// Export symbols that would otherwise be renamed by Closure compiler.
Blockly.Workspace.prototype['clear'] = Blockly.Workspace.prototype.clear;
Blockly.Workspace.prototype['addChangeListener'] =
Blockly.Workspace.prototype.addChangeListener;
Blockly.Workspace.prototype['removeChangeListener'] =
Blockly.Workspace.prototype.removeChangeListener;

View File

@@ -59,13 +59,6 @@ Blockly.WorkspaceSvg = function(options) {
* @const
*/
this.SOUNDS_ = Object.create(null);
/**
* Opaque data that can be passed to Blockly.unbindEvent_.
* @type {!Array.<!Array>}
* @private
*/
this.eventWrappers_ = [];
};
goog.inherits(Blockly.WorkspaceSvg, Blockly.Workspace);
@@ -212,7 +205,6 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) {
Blockly.WorkspaceSvg.prototype.dispose = function() {
// Stop rerendering.
this.rendered = false;
Blockly.unbindEvent_(this.eventWrappers_);
Blockly.WorkspaceSvg.superClass_.dispose.call(this);
if (this.svgGroup_) {
goog.dom.removeNode(this.svgGroup_);
@@ -904,31 +896,6 @@ Blockly.WorkspaceSvg.prototype.updateToolbox = function(tree) {
}
};
/**
* When something in this workspace changes, call a function.
* @param {!Function} func Function to call.
* @return {!Array.<!Array>} Opaque data that can be passed to
* removeChangeListener.
*/
Blockly.WorkspaceSvg.prototype.addChangeListener = function(func) {
var wrapper = Blockly.bindEvent_(this.getCanvas(),
'blocklyWorkspaceChange', null, func);
Array.prototype.push.apply(this.eventWrappers_, wrapper);
return wrapper;
};
/**
* Stop listening for this workspace's changes.
* @param {!Array.<!Array>} bindData Opaque data from addChangeListener.
*/
Blockly.WorkspaceSvg.prototype.removeChangeListener = function(bindData) {
Blockly.unbindEvent_(bindData);
var i = this.eventWrappers_.indexOf(bindData);
if (i != -1) {
this.eventWrappers_.splice(i, 1);
}
};
/**
* Mark this workspace as the currently focused main workspace.
*/
@@ -1005,7 +972,7 @@ Blockly.WorkspaceSvg.prototype.zoomCenter = function(type) {
Blockly.WorkspaceSvg.prototype.zoomToFit = function() {
var workspaceBBox = this.svgBackground_.getBBox();
var blocksBBox = this.svgBlockCanvas_.getBBox();
var workspaceWidth = workspaceBBox.width - this.toolbox_.width -
var workspaceWidth = workspaceBBox.width - this.toolbox_.width -
Blockly.Scrollbar.scrollbarThickness;
var workspaceHeight = workspaceBBox.height -
Blockly.Scrollbar.scrollbarThickness;
@@ -1106,7 +1073,3 @@ Blockly.WorkspaceSvg.prototype.updateGridPattern_ = function() {
// Export symbols that would otherwise be renamed by Closure compiler.
Blockly.WorkspaceSvg.prototype['setVisible'] =
Blockly.WorkspaceSvg.prototype.setVisible;
Blockly.WorkspaceSvg.prototype['addChangeListener'] =
Blockly.WorkspaceSvg.prototype.addChangeListener;
Blockly.WorkspaceSvg.prototype['removeChangeListener'] =
Blockly.WorkspaceSvg.prototype.removeChangeListener;