pyblocks/patches/blocks/0004-display-matrix-add-Fie...

708 lines
21 KiB
Diff

From 96e9a57f0af460032f345cf0f4f5ca2ead4433e4 Mon Sep 17 00:00:00 2001
From: c0repwn3r <core@coredoes.dev>
Date: Wed, 24 May 2023 12:24:47 -0400
Subject: [PATCH] display - matrix - add FieldMatrixSingle
---
blocks_common/matrix.js | 23 +-
blocks_vertical/default_toolbox.js | 19 +
blocks_vertical/display.js | 42 +++
core/field_matrix.js | 548 ++++++++++++++++++++++++++++-
msg/messages.js | 2 +
5 files changed, 632 insertions(+), 2 deletions(-)
diff --git a/blocks_common/matrix.js b/blocks_common/matrix.js
index 8945f8b0..6af2f844 100644
--- a/blocks_common/matrix.js
+++ b/blocks_common/matrix.js
@@ -48,7 +48,28 @@ Blockly.Blocks['matrix'] = {
],
"outputShape": Blockly.OUTPUT_SHAPE_ROUND,
"output": "Number",
- "extensions": ["colours_pen"]
+ "extensions": ["colours_display"]
+ });
+ }
+};
+
+Blockly.Blocks['matrix_single'] = {
+ /**
+ * Block for matrix value.
+ * @this Blockly.Block
+ */
+ init: function() {
+ this.jsonInit({
+ "message0": "%1",
+ "args0": [
+ {
+ "type": "field_matrix_single",
+ "name": "MATRIX"
+ }
+ ],
+ "outputShape": Blockly.OUTPUT_SHAPE_ROUND,
+ "output": "Number",
+ "extensions": ["colours_display"]
});
}
};
diff --git a/blocks_vertical/default_toolbox.js b/blocks_vertical/default_toolbox.js
index 781a5f46..2807cfcd 100644
--- a/blocks_vertical/default_toolbox.js
+++ b/blocks_vertical/default_toolbox.js
@@ -51,6 +51,25 @@ Blockly.Blocks.defaultToolbox = '<xml id="toolbox-categories" style="display: no
'</value>' +
'</block>' +
'<block type="hub_display_string" id="hub_display_string"></block>' +
+ '<block type="hub_display_pixel" id="hub_display_pixel">' +
+ '<value name="PIXEL">' +
+ '<shadow type="matrix_single">' +
+ '<field name="MATRIX">0000000010000000</field>' +
+ '</shadow>' +
+ '</value>' +
+ '<value name="BRIGHTNESS">' +
+ '<shadow type="math_integer">' +
+ '<field name="NUM">100</field>' +
+ '</shadow>' +
+ '</value>' +
+ '</block>' +
+ '<block type="hub_display_icon" id="hub_display_icon">' +
+ '<value name="ICON">' +
+ '<shadow type="matrix">' +
+ '<field name="MATRIX">0101001010000001000101110</field>' +
+ '</shadow>' +
+ '</value>' +
+ '</block>' +
'</category>' +
'<category name="%{BKY_CATEGORY_INPUT}" id="input" colour="#CF63CF" secondaryColour="#3373CC">' +
'<block type="hub_input_isbuttonpressed" id="hub_input_isbuttonpressed">' +
diff --git a/blocks_vertical/display.js b/blocks_vertical/display.js
index 22338b5e..5977c46a 100644
--- a/blocks_vertical/display.js
+++ b/blocks_vertical/display.js
@@ -61,3 +61,45 @@ Blockly.Blocks['hub_display_string'] = {
});
}
};
+
+Blockly.Blocks['hub_display_pixel'] = {
+ /**
+ * @this Blockly.Block
+ */
+ init: function() {
+ this.jsonInit({
+ "message0": Blockly.Msg.HUB_DISPLAY_PIXEL,
+ "args0": [
+ {
+ "type": "input_value",
+ "name": "PIXEL"
+ },
+ {
+ "type": "input_value",
+ "name": "BRIGHTNESS"
+ }
+ ],
+ "category": Blockly.Categories.display,
+ "extensions": ["colours_display", "shape_statement"]
+ });
+ }
+};
+
+Blockly.Blocks['hub_display_icon'] = {
+ /**
+ * @this Blockly.Block
+ */
+ init: function() {
+ this.jsonInit({
+ "message0": Blockly.Msg.HUB_DISPLAY_ICON,
+ "args0": [
+ {
+ "type": "input_value",
+ "name": "ICON"
+ }
+ ],
+ "category": Blockly.Categories.display,
+ "extensions": ["colours_display", "shape_statement"]
+ });
+ }
+};
diff --git a/core/field_matrix.js b/core/field_matrix.js
index e8410e30..19c0be9c 100644
--- a/core/field_matrix.js
+++ b/core/field_matrix.js
@@ -25,7 +25,8 @@
*/
'use strict';
-goog.provide('Blockly.FieldMatrix');
+goog.provide('Blockly.FieldMatrix')
+goog.provide('Blockly.FieldMatrixSingle');
goog.require('Blockly.DropDownDiv');
@@ -563,4 +564,549 @@ Blockly.FieldMatrix.prototype.dispose_ = function() {
};
};
+/**
+ * Class for a matrix field with only one selected pixel at a time.
+ * @param {number} matrix The default matrix value represented by a 25-bit integer.
+ * @extends {Blockly.Field}
+ * @constructor
+ */
+Blockly.FieldMatrixSingle = function(matrix) {
+ Blockly.FieldMatrixSingle.superClass_.constructor.call(this, matrix);
+ this.addArgType('matrix');
+ /**
+ * Array of SVGElement<rect> for matrix thumbnail image on block field.
+ * @type {!Array<SVGElement>}
+ * @private
+ */
+ this.ledThumbNodes_ = [];
+ /**
+ * Array of SVGElement<rect> for matrix editor in dropdown menu.
+ * @type {!Array<SVGElement>}
+ * @private
+ */
+ this.ledButtons_ = [];
+ /**
+ * String for storing current matrix value.
+ * @type {!String]
+ * @private
+ */
+ this.matrix_ = '';
+ /**
+ * SVGElement for LED matrix in editor.
+ * @type {?SVGElement}
+ * @private
+ */
+ this.matrixStage_ = null;
+ /**
+ * SVG image for dropdown arrow.
+ * @type {?SVGElement}
+ * @private
+ */
+ this.arrow_ = null;
+ /**
+ * String indicating matrix paint style.
+ * value can be [null, 'fill', 'clear'].
+ * @type {?String}
+ * @private
+ */
+ this.paintStyle_ = null;
+ /**
+ * Touch event wrapper.
+ * Runs when the field is selected.
+ * @type {!Array}
+ * @private
+ */
+ this.mouseDownWrapper_ = null;
+ /**
+ * Touch event wrapper.
+ * Runs when the clear button editor button is selected.
+ * @type {!Array}
+ * @private
+ */
+ this.clearButtonWrapper_ = null;
+ /**
+ * Touch event wrapper.
+ * Runs when the fill button editor button is selected.
+ * @type {!Array}
+ * @private
+ */
+ this.fillButtonWrapper_ = null;
+ /**
+ * Touch event wrapper.
+ * Runs when the matrix editor is touched.
+ * @type {!Array}
+ * @private
+ */
+ this.matrixTouchWrapper_ = null;
+ /**
+ * Touch event wrapper.
+ * Runs when the matrix editor touch event moves.
+ * @type {!Array}
+ * @private
+ */
+ this.matrixMoveWrapper_ = null;
+ /**
+ * Touch event wrapper.
+ * Runs when the matrix editor is released.
+ * @type {!Array}
+ * @private
+ */
+ this.matrixReleaseWrapper_ = null;
+};
+goog.inherits(Blockly.FieldMatrixSingle, Blockly.Field);
+
+/**
+ * Construct a FieldMatrixSingle from a JSON arg object.
+ * @param {!Object} options A JSON object with options (matrix).
+ * @returns {!Blockly.FieldMatrixSingle} The new field instance.
+ * @package
+ * @nocollapse
+ */
+Blockly.FieldMatrixSingle.fromJson = function(options) {
+ return new Blockly.FieldMatrixSingle(options['matrix']);
+};
+
+/**
+ * Fixed size of the matrix thumbnail in the input field, in px.
+ * @type {number}
+ * @const
+ */
+Blockly.FieldMatrixSingle.THUMBNAIL_SIZE = 26;
+
+/**
+ * Fixed size of each matrix thumbnail node, in px.
+ * @type {number}
+ * @const
+ */
+Blockly.FieldMatrixSingle.THUMBNAIL_NODE_SIZE = 4;
+
+/**
+ * Fixed size of each matrix thumbnail node, in px.
+ * @type {number}
+ * @const
+ */
+Blockly.FieldMatrixSingle.THUMBNAIL_NODE_PAD = 1;
+
+/**
+ * Fixed size of arrow icon in drop down menu, in px.
+ * @type {number}
+ * @const
+ */
+Blockly.FieldMatrixSingle.ARROW_SIZE = 12;
+
+/**
+ * Fixed size of each button inside the 5x5 matrix, in px.
+ * @type {number}
+ * @const
+ */
+Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE = 18;
+
+/**
+ * Fixed corner radius for 5x5 matrix buttons, in px.
+ * @type {number}
+ * @const
+ */
+Blockly.FieldMatrixSingle.MATRIX_NODE_RADIUS = 4;
+
+/**
+ * Fixed padding for 5x5 matrix buttons, in px.
+ * @type {number}
+ * @const
+ */
+Blockly.FieldMatrixSingle.MATRIX_NODE_PAD = 5;
+
+/**
+ * String with 25 '0' chars.
+ * Used for clearing a matrix or filling an LED node array.
+ * @type {string}
+ * @const
+ */
+Blockly.FieldMatrixSingle.ZEROS = '0000000000000000000000000';
+
+/**
+ * String with 25 '1' chars.
+ * Used for filling a matrix.
+ * @type {string}
+ * @const
+ */
+Blockly.FieldMatrixSingle.ONES = '1111111111111111111111111';
+
+/**
+ * Called when the field is placed on a block.
+ * @param {Block} block The owning block.
+ */
+Blockly.FieldMatrixSingle.prototype.init = function() {
+ if (this.fieldGroup_) {
+ // Matrix menu has already been initialized once.
+ return;
+ }
+
+ // Build the DOM.
+ this.fieldGroup_ = Blockly.utils.createSvgElement('g', {}, null);
+ this.size_.width = Blockly.FieldMatrixSingle.THUMBNAIL_SIZE +
+ Blockly.FieldMatrixSingle.ARROW_SIZE + (Blockly.BlockSvg.DROPDOWN_ARROW_PADDING * 1.5);
+
+ this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_);
+
+ var thumbX = Blockly.BlockSvg.DROPDOWN_ARROW_PADDING / 2;
+ var thumbY = (this.size_.height - Blockly.FieldMatrixSingle.THUMBNAIL_SIZE) / 2;
+ var thumbnail = Blockly.utils.createSvgElement('g', {
+ 'transform': 'translate(' + thumbX + ', ' + thumbY + ')',
+ 'pointer-events': 'bounding-box', 'cursor': 'pointer'
+ }, this.fieldGroup_);
+ this.ledThumbNodes_ = [];
+ var nodeSize = Blockly.FieldMatrixSingle.THUMBNAIL_NODE_SIZE;
+ var nodePad = Blockly.FieldMatrixSingle.THUMBNAIL_NODE_PAD;
+ for (var i = 0; i < 5; i++) {
+ for (var n = 0; n < 5; n++) {
+ var attr = {
+ 'x': ((nodeSize + nodePad) * n) + nodePad,
+ 'y': ((nodeSize + nodePad) * i) + nodePad,
+ 'width': nodeSize, 'height': nodeSize,
+ 'rx': nodePad, 'ry': nodePad
+ };
+ this.ledThumbNodes_.push(
+ Blockly.utils.createSvgElement('rect', attr, thumbnail)
+ );
+ }
+ thumbnail.style.cursor = 'default';
+ this.updateMatrix_();
+ }
+
+ if (!this.arrow_) {
+ var arrowX = Blockly.FieldMatrixSingle.THUMBNAIL_SIZE +
+ Blockly.BlockSvg.DROPDOWN_ARROW_PADDING * 1.5;
+ var arrowY = (this.size_.height - Blockly.FieldMatrixSingle.ARROW_SIZE) / 2;
+ this.arrow_ = Blockly.utils.createSvgElement('image', {
+ 'height': Blockly.FieldMatrixSingle.ARROW_SIZE + 'px',
+ 'width': Blockly.FieldMatrixSingle.ARROW_SIZE + 'px',
+ 'transform': 'translate(' + arrowX + ', ' + arrowY + ')'
+ }, this.fieldGroup_);
+ this.arrow_.setAttributeNS('http://www.w3.org/1999/xlink',
+ 'xlink:href', Blockly.mainWorkspace.options.pathToMedia +
+ 'dropdown-arrow.svg');
+ this.arrow_.style.cursor = 'default';
+ }
+
+ this.mouseDownWrapper_ = Blockly.bindEventWithChecks_(
+ this.getClickTarget_(), 'mousedown', this, this.onMouseDown_);
+};
+
+/**
+ * Set the value for this matrix menu.
+ * @param {string} matrix The new matrix value represented by a 25-bit integer.
+ * @override
+ */
+Blockly.FieldMatrixSingle.prototype.setValue = function(matrix) {
+ if (!matrix || matrix === this.matrix_) {
+ return; // No change
+ }
+ if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
+ Blockly.Events.fire(new Blockly.Events.Change(
+ this.sourceBlock_, 'field', this.name, this.matrix_, matrix));
+ }
+ matrix = matrix + Blockly.FieldMatrixSingle.ZEROS.substr(0, 25 - matrix.length);
+ this.matrix_ = matrix;
+ this.updateMatrix_();
+};
+
+/**
+ * Get the value from this matrix menu.
+ * @return {string} Current matrix value.
+ */
+Blockly.FieldMatrixSingle.prototype.getValue = function() {
+ return String(this.matrix_);
+};
+
+/**
+ * Show the drop-down menu for editing this field.
+ * @private
+ */
+Blockly.FieldMatrixSingle.prototype.showEditor_ = function() {
+ // If there is an existing drop-down someone else owns, hide it immediately and clear it.
+ Blockly.DropDownDiv.hideWithoutAnimation();
+ Blockly.DropDownDiv.clearContent();
+ var div = Blockly.DropDownDiv.getContentDiv();
+ // Build the SVG DOM.
+ var matrixSize = (Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE * 5) +
+ (Blockly.FieldMatrixSingle.MATRIX_NODE_PAD * 6);
+ this.matrixStage_ = Blockly.utils.createSvgElement('svg', {
+ 'xmlns': 'http://www.w3.org/2000/svg',
+ 'xmlns:html': 'http://www.w3.org/1999/xhtml',
+ 'xmlns:xlink': 'http://www.w3.org/1999/xlink',
+ 'version': '1.1',
+ 'height': matrixSize + 'px',
+ 'width': matrixSize + 'px'
+ }, div);
+ // Create the 5x5 matrix
+ this.ledButtons_ = [];
+ for (var i = 0; i < 5; i++) {
+ for (var n = 0; n < 5; n++) {
+ var x = (Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE * n) +
+ (Blockly.FieldMatrixSingle.MATRIX_NODE_PAD * (n + 1));
+ var y = (Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE * i) +
+ (Blockly.FieldMatrixSingle.MATRIX_NODE_PAD * (i + 1));
+ var attr = {
+ 'x': x + 'px', 'y': y + 'px',
+ 'width': Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE,
+ 'height': Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE,
+ 'rx': Blockly.FieldMatrixSingle.MATRIX_NODE_RADIUS,
+ 'ry': Blockly.FieldMatrixSingle.MATRIX_NODE_RADIUS
+ };
+ var led = Blockly.utils.createSvgElement('rect', attr, this.matrixStage_);
+ this.matrixStage_.appendChild(led);
+ this.ledButtons_.push(led);
+ }
+ }
+ // Div for lower button menu
+ /*
+ var buttonDiv = document.createElement('div');
+ // Button to clear matrix
+ var clearButtonDiv = document.createElement('div');
+ clearButtonDiv.className = 'scratchMatrixButtonDiv';
+ var clearButton = this.createButton_(this.sourceBlock_.colourSecondary_);
+ clearButtonDiv.appendChild(clearButton);
+ // Button to fill matrix
+
+ var fillButtonDiv = document.createElement('div');
+ fillButtonDiv.className = 'scratchMatrixButtonDiv';
+ var fillButton = this.createButton_('#FFFFFF');
+ fillButtonDiv.appendChild(fillButton);
+
+
+
+ buttonDiv.appendChild(clearButtonDiv);
+ buttonDiv.appendChild(fillButtonDiv);
+ div.appendChild(buttonDiv);
+
+
+ */
+
+ Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(),
+ this.sourceBlock_.getColourTertiary());
+ Blockly.DropDownDiv.setCategory(this.sourceBlock_.getCategory());
+ Blockly.DropDownDiv.showPositionedByBlock(this, this.sourceBlock_);
+
+ this.matrixTouchWrapper_ =
+ Blockly.bindEvent_(this.matrixStage_, 'mousedown', this, this.onMouseDown);
+ //this.clearButtonWrapper_ =
+ // Blockly.bindEvent_(clearButton, 'click', this, this.clearMatrix_);
+ //this.fillButtonWrapper_ =
+ // Blockly.bindEvent_(fillButton, 'click', this, this.fillMatrix_);
+
+ // Update the matrix for the current value
+ this.updateMatrix_();
+
+};
+
+this.nodeCallback_ = function(e, num) {
+ console.log(num);
+};
+
+/**
+ * Make an svg object that resembles a 3x3 matrix to be used as a button.
+ * @param {string} fill The color to fill the matrix nodes.
+ * @return {SvgElement} The button svg element.
+ */
+Blockly.FieldMatrixSingle.prototype.createButton_ = function(fill) {
+ var button = Blockly.utils.createSvgElement('svg', {
+ 'xmlns': 'http://www.w3.org/2000/svg',
+ 'xmlns:html': 'http://www.w3.org/1999/xhtml',
+ 'xmlns:xlink': 'http://www.w3.org/1999/xlink',
+ 'version': '1.1',
+ 'height': Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE + 'px',
+ 'width': Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE + 'px'
+ });
+ var nodeSize = Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE / 4;
+ var nodePad = Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE / 16;
+ for (var i = 0; i < 3; i++) {
+ for (var n = 0; n < 3; n++) {
+ Blockly.utils.createSvgElement('rect', {
+ 'x': ((nodeSize + nodePad) * n) + nodePad,
+ 'y': ((nodeSize + nodePad) * i) + nodePad,
+ 'width': nodeSize, 'height': nodeSize,
+ 'rx': nodePad, 'ry': nodePad,
+ 'fill': fill
+ }, button);
+ }
+ }
+ return button;
+};
+
+/**
+ * Redraw the matrix with the current value.
+ * @private
+ */
+Blockly.FieldMatrixSingle.prototype.updateMatrix_ = function() {
+ for (var i = 0; i < this.matrix_.length; i++) {
+ if (this.matrix_[i] === '0') {
+ this.fillMatrixNode_(this.ledButtons_, i, this.sourceBlock_.colourSecondary_);
+ this.fillMatrixNode_(this.ledThumbNodes_, i, this.sourceBlock_.colour_);
+ } else {
+ this.fillMatrixNode_(this.ledButtons_, i, '#FFFFFF');
+ this.fillMatrixNode_(this.ledThumbNodes_, i, '#FFFFFF');
+ }
+ }
+};
+
+/**
+ * Clear the matrix.
+ * @param {!Event} e Mouse event.
+ */
+Blockly.FieldMatrixSingle.prototype.clearMatrix_ = function(e) {
+ if (e.button != 0) return;
+ this.setValue(Blockly.FieldMatrixSingle.ZEROS);
+};
+
+/**
+ * Fill the matrix.
+ * @param {!Event} e Mouse event.
+ */
+Blockly.FieldMatrixSingle.prototype.fillMatrix_ = function(e) {
+ if (e.button != 0) return;
+ this.setValue(Blockly.FieldMatrixSingle.ONES);
+};
+
+/**
+ * Fill matrix node with specified colour.
+ * @param {!Array<SVGElement>} node The array of matrix nodes.
+ * @param {!number} index The index of the matrix node.
+ * @param {!string} fill The fill colour in '#rrggbb' format.
+ */
+Blockly.FieldMatrixSingle.prototype.fillMatrixNode_ = function(node, index, fill) {
+ if (!node || !node[index] || !fill) return;
+ node[index].setAttribute('fill', fill);
+};
+
+Blockly.FieldMatrixSingle.prototype.setLEDNode_ = function(led, state) {
+ if (led < 0 || led > 24) return;
+ var matrix = this.matrix_.substr(0, led) + state + this.matrix_.substr(led + 1);
+ this.setValue(matrix);
+};
+
+Blockly.FieldMatrixSingle.prototype.fillLEDNode_ = function(led) {
+ if (led < 0 || led > 24) return;
+ this.setLEDNode_(led, '1');
+};
+
+Blockly.FieldMatrixSingle.prototype.clearLEDNode_ = function(led) {
+ if (led < 0 || led > 24) return;
+ this.setLEDNode_(led, '0');
+};
+
+Blockly.FieldMatrixSingle.prototype.toggleLEDNode_ = function(led, e) {
+ this.clearMatrix_(e);
+ if (led < 0 || led > 24) return;
+ if (this.matrix_.charAt(led) === '0') {
+ this.setLEDNode_(led, '1');
+ } else {
+ this.setLEDNode_(led, '0');
+ }
+};
+
+/**
+ * Toggle matrix nodes on and off.
+ * @param {!Event} e Mouse event.
+ */
+Blockly.FieldMatrixSingle.prototype.onMouseDown = function(e) {
+ this.matrixMoveWrapper_ =
+ Blockly.bindEvent_(document.body, 'mousemove', this, this.onMouseMove);
+ this.matrixReleaseWrapper_ =
+ Blockly.bindEvent_(document.body, 'mouseup', this, this.onMouseUp);
+ var ledHit = this.checkForLED_(e);
+ if (ledHit > -1) {
+ if (this.matrix_.charAt(ledHit) === '0') {
+ this.paintStyle_ = 'fill';
+ } else {
+ this.paintStyle_ = 'clear';
+ }
+ this.toggleLEDNode_(ledHit, e);
+ this.updateMatrix_();
+ } else {
+ this.paintStyle_ = null;
+ }
+};
+
+/**
+ * Unbind mouse move event and clear the paint style.
+ * @param {!Event} e Mouse move event.
+ */
+Blockly.FieldMatrixSingle.prototype.onMouseUp = function(e) {
+ Blockly.unbindEvent_(this.matrixMoveWrapper_);
+ Blockly.unbindEvent_(this.matrixReleaseWrapper_);
+ this.paintStyle_ = null;
+};
+
+/**
+ * Toggle matrix nodes on and off by dragging mouse.
+ * @param {!Event} e Mouse move event.
+ */
+Blockly.FieldMatrixSingle.prototype.onMouseMove = function(e) {
+ e.preventDefault();
+ if (this.paintStyle_) {
+ var led = this.checkForLED_(e);
+ if (led < 0) return;
+ if (this.paintStyle_ === 'clear') {
+ this.clearLEDNode_(led);
+ } else if (this.paintStyle_ === 'fill') {
+ this.clearMatrix_(e);
+ this.fillLEDNode_(led);
+ }
+ }
+};
+
+/**
+ * Check if mouse coordinates collide with a matrix node.
+ * @param {!Event} e Mouse move event.
+ * @return {number} The matching matrix node or -1 for none.
+ */
+Blockly.FieldMatrixSingle.prototype.checkForLED_ = function(e) {
+ var bBox = this.matrixStage_.getBoundingClientRect();
+ var nodeSize = Blockly.FieldMatrixSingle.MATRIX_NODE_SIZE;
+ var nodePad = Blockly.FieldMatrixSingle.MATRIX_NODE_PAD;
+ var dx = e.clientX - bBox.left;
+ var dy = e.clientY - bBox.top;
+ var min = nodePad / 2;
+ var max = bBox.width - (nodePad / 2);
+ if (dx < min || dx > max || dy < min || dy > max) {
+ return -1;
+ }
+ var xDiv = Math.trunc((dx - nodePad / 2) / (nodeSize + nodePad));
+ var yDiv = Math.trunc((dy - nodePad / 2) / (nodeSize + nodePad));
+ return xDiv + (yDiv * nodePad);
+};
+
+/**
+ * Clean up this FieldMatrixSingle, as well as the inherited Field.
+ * @return {!Function} Closure to call on destruction of the WidgetDiv.
+ * @private
+ */
+Blockly.FieldMatrixSingle.prototype.dispose_ = function() {
+ var thisField = this;
+ return function() {
+ Blockly.FieldMatrixSingle.superClass_.dispose_.call(thisField)();
+ thisField.matrixStage_ = null;
+ if (thisField.mouseDownWrapper_) {
+ Blockly.unbindEvent_(thisField.mouseDownWrapper_);
+ }
+ if (thisField.matrixTouchWrapper_) {
+ Blockly.unbindEvent_(thisField.matrixTouchWrapper_);
+ }
+ if (thisField.matrixReleaseWrapper_) {
+ Blockly.unbindEvent_(thisField.matrixReleaseWrapper_);
+ }
+ if (thisField.matrixMoveWrapper_) {
+ Blockly.unbindEvent_(thisField.matrixMoveWrapper_);
+ }
+ if (thisField.clearButtonWrapper_) {
+ Blockly.unbindEvent_(thisField.clearButtonWrapper_);
+ }
+ if (thisField.fillButtonWrapper_) {
+ Blockly.unbindEvent_(thisField.fillButtonWrapper_);
+ }
+ };
+};
+
+
Blockly.Field.register('field_matrix', Blockly.FieldMatrix);
+Blockly.Field.register('field_matrix_single', Blockly.FieldMatrixSingle);
diff --git a/msg/messages.js b/msg/messages.js
index feb70bcd..b9cd5997 100644
--- a/msg/messages.js
+++ b/msg/messages.js
@@ -375,6 +375,8 @@ Blockly.Msg.HUB_DISPLAY_OFF = 'turn display off';
Blockly.Msg.HUB_DISPLAY_NUM = 'show digits %1 on display';
Blockly.Msg.HUB_DISPLAY_CHAR = 'show char %1 on display';
Blockly.Msg.HUB_DISPLAY_STRING = 'scroll %1 across display';
+Blockly.Msg.HUB_DISPLAY_PIXEL = 'set %1 to %2 brightness';
+Blockly.Msg.HUB_DISPLAY_ICON = 'show %1 on display';
Blockly.Msg.HUB_INPUT_ISBUTTONPRESSED = 'is %1 button pressed?';
--
2.40.1