diff --git a/core/block_svg.js b/core/block_svg.js index 4ea6f288d..f7727980c 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -127,6 +127,7 @@ Blockly.BlockSvg.prototype.select = function() { // Unselect any previously selected block. Blockly.selected.unselect(); } + Blockly.Events.fire(new Blockly.Events.Ui(this, 'selected', false, true)); Blockly.selected = this; this.addSelect(); Blockly.fireUiEvent(this.workspace.getCanvas(), 'blocklySelectChange'); @@ -136,6 +137,10 @@ Blockly.BlockSvg.prototype.select = function() { * Unselect this block. Remove its highlighting. */ Blockly.BlockSvg.prototype.unselect = function() { + if (Blockly.selected != this) { + return; + } + Blockly.Events.fire(new Blockly.Events.Ui(this, 'selected', true, false)); Blockly.selected = null; this.removeSelect(); Blockly.fireUiEvent(this.workspace.getCanvas(), 'blocklySelectChange'); diff --git a/core/comment.js b/core/comment.js index fd7816ac5..06c9bae77 100644 --- a/core/comment.js +++ b/core/comment.js @@ -164,6 +164,8 @@ Blockly.Comment.prototype.setVisible = function(visible) { // No change. return; } + Blockly.Events.fire( + new Blockly.Events.Ui(this.block_, 'commentOpen', !visible, visible)); if ((!this.block_.isEditable() && !this.textarea_) || goog.userAgent.IE) { // Steal the code from warnings to make an uneditable text bubble. // MSIE does not support foreignobject; textareas are impossible. diff --git a/core/events.js b/core/events.js index d532a6a5f..417d59470 100644 --- a/core/events.js +++ b/core/events.js @@ -71,6 +71,12 @@ Blockly.Events.CHANGE = 'change'; */ Blockly.Events.MOVE = 'move'; +/** + * Name of event that records a UI change. + * @const + */ +Blockly.Events.UI = 'ui'; + /** * List of events queued for firing. * @private @@ -254,6 +260,14 @@ Blockly.Events.Abstract.prototype.isNull = function() { return false; }; +/** + * Run an event. + * @param {boolean} forward True if run forward, false if run backward (undo). + */ +Blockly.Events.Abstract.prototype.run = function(forward) { + // Defined by subclasses. +}; + /** * Class for a block creation event. * @param {!Blockly.Block} block The created block. @@ -572,3 +586,47 @@ Blockly.Events.Move.prototype.run = function(forward) { } } }; + +/** + * Class for a UI event. + * @param {!Blockly.Block} block The affected block. + * @param {string} element One of 'selected', 'comment', 'mutator', etc. + * @param {string} oldValue Previous value of element. + * @param {string} newValue New value of element. + * @extends {Blockly.Events.Abstract} + * @constructor + */ +Blockly.Events.Ui = function(block, element, oldValue, newValue) { + Blockly.Events.Ui.superClass_.constructor.call(this, block); + this.element = element; + this.oldValue = oldValue; + this.newValue = newValue; + this.recordUndo = false; +}; +goog.inherits(Blockly.Events.Ui, Blockly.Events.Abstract); + +/** + * Type of this event. + * @type {string} + */ +Blockly.Events.Ui.prototype.type = Blockly.Events.UI; + +/** + * Encode the event as JSON. + * @return {!Object} JSON representation. + */ +Blockly.Events.Change.prototype.toJson = function() { + var json = Blockly.Events.Change.superClass_.toJson.call(this); + json['element'] = this.element; + json['newValue'] = this.newValue; + return json; +}; + +/** + * Does this event record any change of state? + * @return {boolean} True if something changed. + */ +Blockly.Events.Ui.prototype.isNull = function() { + return this.oldValue == this.newValue; +}; + diff --git a/core/mutator.js b/core/mutator.js index eb488e833..e8cfac42c 100644 --- a/core/mutator.js +++ b/core/mutator.js @@ -198,6 +198,8 @@ Blockly.Mutator.prototype.setVisible = function(visible) { // No change. return; } + Blockly.Events.fire( + new Blockly.Events.Ui(this.block_, 'mutatorOpen', !visible, visible)); if (visible) { // Create the bubble. this.bubble_ = new Blockly.Bubble(this.block_.workspace, diff --git a/core/warning.js b/core/warning.js index 8d990b1d2..4ec8bf771 100644 --- a/core/warning.js +++ b/core/warning.js @@ -105,6 +105,8 @@ Blockly.Warning.prototype.setVisible = function(visible) { // No change. return; } + Blockly.Events.fire( + new Blockly.Events.Ui(this.block_, 'warningOpen', !visible, visible)); if (visible) { // Create the bubble to display all warnings. var paragraph = Blockly.Warning.textToDom_(this.getText());