Create fromJson for events. Add master-slave demo.

This commit is contained in:
Neil Fraser
2016-04-06 14:27:15 -07:00
parent 61b3fbfe11
commit effa81f622
5 changed files with 203 additions and 8 deletions

View File

@@ -222,7 +222,8 @@ Blockly.onMouseMove_ = function(e) {
* @private
*/
Blockly.onKeyDown_ = function(e) {
if (Blockly.isTargetInput_(e)) {
if (Blockly.mainWorkspace.options.readOnly || Blockly.isTargetInput_(e)) {
// No key actions on readonly workspaces.
// When focused on an HTML text input widget, don't trap any keys.
return;
}

View File

@@ -239,6 +239,37 @@ Blockly.Events.getDescendantIds_ = function(block) {
return ids;
};
/**
* Decode the JSON into an event.
* @param {!Object} json JSON representation.
* @param {!Blockly.Workspace} workspace Target workspace for event.
*/
Blockly.Events.fromJson = function(json, workspace) {
var event;
switch (json.type) {
case Blockly.Events.CREATE:
event = new Blockly.Events.Create(null);
break;
case Blockly.Events.DELETE:
event = new Blockly.Events.Delete(null);
break;
case Blockly.Events.CHANGE:
event = new Blockly.Events.Change(null);
break;
case Blockly.Events.MOVE:
event = new Blockly.Events.Move(null);
break;
case Blockly.Events.UI:
event = new Blockly.Events.Ui(null);
break;
default:
throw 'Unknown event type.'
}
event.fromJson(json);
event.workspaceId = workspace.id;
return event;
};
/**
* Abstract class for an event.
* @param {Blockly.Block} block The block.
@@ -260,8 +291,7 @@ Blockly.Events.Abstract = function(block) {
Blockly.Events.Abstract.prototype.toJson = function() {
var json = {
'type': this.type,
'blockId': this.blockId,
'workspaceId': this.workspaceId
'blockId': this.blockId
};
if (this.group) {
json['group'] = this.group;
@@ -269,6 +299,15 @@ Blockly.Events.Abstract.prototype.toJson = function() {
return json;
};
/**
* Decode the JSON event.
* @param {!Object} json JSON representation.
*/
Blockly.Events.Abstract.prototype.fromJson = function(json) {
this.blockId = json['blockId'];
this.group = json['group'];
};
/**
* Does this event record any change of state?
* @return {boolean} True if null, false if something changed.
@@ -287,11 +326,14 @@ Blockly.Events.Abstract.prototype.run = function(forward) {
/**
* Class for a block creation event.
* @param {!Blockly.Block} block The created block.
* @param {Blockly.Block} block The created block. Null for a blank event.
* @extends {Blockly.Events.Abstract}
* @constructor
*/
Blockly.Events.Create = function(block) {
if (!block) {
return; // Blank event to be populated by fromJson.
}
Blockly.Events.Create.superClass_.constructor.call(this, block);
this.xml = Blockly.Xml.blockToDomWithXY(block);
this.ids = Blockly.Events.getDescendantIds_(block);
@@ -315,13 +357,23 @@ Blockly.Events.Create.prototype.toJson = function() {
return json;
};
/**
* Decode the JSON event.
* @param {!Object} json JSON representation.
*/
Blockly.Events.Create.prototype.fromJson = function(json) {
Blockly.Events.Create.superClass_.fromJson.call(this, json);
this.xml = Blockly.Xml.textToDom('<xml>' + json['xml'] + '</xml>').firstChild;
this.ids = json['ids'];
};
/**
* Run a creation event.
* @param {boolean} forward True if run forward, false if run backward (undo).
*/
Blockly.Events.Create.prototype.run = function(forward) {
var workspace = Blockly.Workspace.getById(this.workspaceId);
if (forward) {
var workspace = Blockly.Workspace.getById(this.workspaceId);
var xml = goog.dom.createDom('xml');
xml.appendChild(this.xml);
Blockly.Xml.domToWorkspace(xml, workspace);
@@ -340,11 +392,14 @@ Blockly.Events.Create.prototype.run = function(forward) {
/**
* Class for a block deletion event.
* @param {!Blockly.Block} block The deleted block.
* @param {Blockly.Block} block The deleted block. Null for a blank event.
* @extends {Blockly.Events.Abstract}
* @constructor
*/
Blockly.Events.Delete = function(block) {
if (!block) {
return; // Blank event to be populated by fromJson.
}
if (block.getParent()) {
throw 'Connected blocks cannot be deleted.';
}
@@ -370,6 +425,15 @@ Blockly.Events.Delete.prototype.toJson = function() {
return json;
};
/**
* Decode the JSON event.
* @param {!Object} json JSON representation.
*/
Blockly.Events.Delete.prototype.fromJson = function(json) {
Blockly.Events.Delete.superClass_.fromJson.call(this, json);
this.ids = json['ids'];
};
/**
* Run a deletion event.
* @param {boolean} forward True if run forward, false if run backward (undo).
@@ -395,7 +459,7 @@ Blockly.Events.Delete.prototype.run = function(forward) {
/**
* Class for a block change event.
* @param {!Blockly.Block} block The changed block.
* @param {Blockly.Block} block The changed block. Null for a blank event.
* @param {string} element One of 'field', 'comment', 'disabled', etc.
* @param {?string} name Name of input or field affected, or null.
* @param {string} oldValue Previous value of element.
@@ -404,6 +468,9 @@ Blockly.Events.Delete.prototype.run = function(forward) {
* @constructor
*/
Blockly.Events.Change = function(block, element, name, oldValue, newValue) {
if (!block) {
return; // Blank event to be populated by fromJson.
}
Blockly.Events.Change.superClass_.constructor.call(this, block);
this.element = element;
this.name = name;
@@ -432,6 +499,17 @@ Blockly.Events.Change.prototype.toJson = function() {
return json;
};
/**
* Decode the JSON event.
* @param {!Object} json JSON representation.
*/
Blockly.Events.Change.prototype.fromJson = function(json) {
Blockly.Events.Change.superClass_.fromJson.call(this, json);
this.element = json['element'];
this.name = json['name'];
this.newValue = json['newValue'];
};
/**
* Does this event record any change of state?
* @return {boolean} True if something changed.
@@ -498,11 +576,14 @@ Blockly.Events.Change.prototype.run = function(forward) {
/**
* Class for a block move event. Created before the move.
* @param {!Blockly.Block} block The moved block.
* @param {Blockly.Block} block The moved block. Null for a blank event.
* @extends {Blockly.Events.Abstract}
* @constructor
*/
Blockly.Events.Move = function(block) {
if (!block) {
return; // Blank event to be populated by fromJson.
}
Blockly.Events.Move.superClass_.constructor.call(this, block);
var location = this.currentLocation_();
this.oldParentId = location.parentId;
@@ -536,6 +617,21 @@ Blockly.Events.Move.prototype.toJson = function() {
return json;
};
/**
* Decode the JSON event.
* @param {!Object} json JSON representation.
*/
Blockly.Events.Move.prototype.fromJson = function(json) {
Blockly.Events.Move.superClass_.fromJson.call(this, json);
this.newParentId = json['newParentId'];
this.newInputName = json['newInputName'];
if (json['newCoordinate']) {
var xy = json['newCoordinate'].split(',');
this.newCoordinate =
new goog.math.Coordinate(parseFloat(xy[0]), parseFloat(xy[1]));
}
};
/**
* Record the block's new location. Called after the move.
*/
@@ -662,3 +758,13 @@ Blockly.Events.Ui.prototype.toJson = function() {
}
return json;
};
/**
* Decode the JSON event.
* @param {!Object} json JSON representation.
*/
Blockly.Events.Ui.prototype.fromJson = function(json) {
Blockly.Events.Ui.superClass_.fromJson.call(this, json);
this.element = json['element'];
this.newValue = json['newValue'];
};

View File

@@ -160,6 +160,18 @@
</td>
</tr>
<tr>
<td>
<a href="mirror/index.html">
<img src="mirror/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="mirror/index.html">Mirrored Blockly</a></div>
<div>Two Blockly instances connected as master-slave.</div>
</td>
</tr>
<tr>
<td>
<a href="code/index.html">

BIN
demos/mirror/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

76
demos/mirror/index.html Normal file
View File

@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Blockly Demo: Mirrored Blockly</title>
<script src="../../blockly_compressed.js"></script>
<script src="../../blocks_compressed.js"></script>
<script src="../../msg/js/en.js"></script>
<style>
body {
background-color: #fff;
font-family: sans-serif;
}
h1 {
font-weight: normal;
font-size: 140%;
}
</style>
</head>
<body>
<h1><a href="https://developers.google.com/blockly/">Blockly</a> &gt;
<a href="../index.html">Demos</a> &gt; Mirrored Blockly</h1>
<p>This is a simple demo of a master Blockly that controls a slave Blockly.
Open the JavaScript console to see the event passing.</p>
<p>&rarr; More info on <a href="https://developers.google.com/blockly/hacking/events">events</a>&hellip;</p>
<table width="100%">
<tr>
<td>
<div id="masterDiv" style="height: 480px; width: 600px;"></div>
</td>
<td>
<div id="slaveDiv" style="height: 480px; width: 430px;"></div>
</td>
</tr>
</table>
<xml id="toolbox" style="display: none">
<block type="controls_if"></block>
<block type="logic_compare"></block>
<block type="controls_repeat_ext"></block>
<block type="math_number"></block>
<block type="math_arithmetic"></block>
<block type="text"></block>
<block type="text_print"></block>
</xml>
<script>
// Inject master workspace.
var masterWorkspace = Blockly.inject('masterDiv',
{media: '../../media/',
toolbox: document.getElementById('toolbox')});
// Inject slave workspace.
var slaveWorkspace = Blockly.inject('slaveDiv',
{media: '../../media/',
readOnly: true});
// Listen to events on master workspace.
masterWorkspace.addChangeListener(mirrorEvent);
function mirrorEvent(masterEvent) {
if (masterEvent.type == Blockly.Events.UI) {
return; // Don't mirror UI events.
}
// Convert event to JSON. This could then be transmitted across the net.
var json = masterEvent.toJson();
console.log(json);
// Convert JSON back into an event, then execute it.
var slaveEvent = Blockly.Events.fromJson(json, slaveWorkspace);
slaveEvent.run(true);
}
</script>
</body>
</html>