mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-06-05 17:34:55 -04:00
227 lines
6.4 KiB
JavaScript
227 lines
6.4 KiB
JavaScript
/**
|
|
* @license
|
|
* Visual Blocks Editor
|
|
*
|
|
* Copyright 2017 Google Inc.
|
|
* https://developers.google.com/blockly/
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview Object for configuring and updating a workspace grid in
|
|
* Blockly.
|
|
* @author fenichel@google.com (Rachel Fenichel)
|
|
*/
|
|
'use strict';
|
|
|
|
goog.provide('Blockly.Grid');
|
|
|
|
goog.require('Blockly.utils');
|
|
|
|
goog.require('goog.userAgent');
|
|
|
|
|
|
/**
|
|
* Class for a workspace's grid.
|
|
* @param {!SVGElement} pattern The grid's SVG pattern, created during injection.
|
|
* @param {!Object} options A dictionary of normalized options for the grid.
|
|
* See grid documentation:
|
|
* https://developers.google.com/blockly/guides/configure/web/grid
|
|
* @constructor
|
|
*/
|
|
Blockly.Grid = function(pattern, options) {
|
|
/**
|
|
* The grid's SVG pattern, created during injection.
|
|
* @type {!SVGElement}
|
|
* @private
|
|
*/
|
|
this.gridPattern_ = pattern;
|
|
|
|
/**
|
|
* The spacing of the grid lines (in px).
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.spacing_ = options['spacing'];
|
|
|
|
/**
|
|
* How long the grid lines should be (in px).
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.length_ = options['length'];
|
|
|
|
/**
|
|
* The horizontal grid line, if it exists.
|
|
* @type {SVGElement}
|
|
* @private
|
|
*/
|
|
this.line1_ = pattern.firstChild;
|
|
|
|
/**
|
|
* The vertical grid line, if it exists.
|
|
* @type {SVGElement}
|
|
* @private
|
|
*/
|
|
this.line2_ = this.line1_ && this.line1_.nextSibling;
|
|
|
|
/**
|
|
* Whether blocks should snap to the grid.
|
|
* @type {boolean}
|
|
* @private
|
|
*/
|
|
this.snapToGrid_ = options['snap'];
|
|
};
|
|
|
|
/**
|
|
* The scale of the grid, used to set stroke width on grid lines.
|
|
* This should always be the same as the workspace scale.
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
Blockly.Grid.prototype.scale_ = 1;
|
|
|
|
/**
|
|
* Dispose of this grid and unlink from the DOM.
|
|
* @package
|
|
*/
|
|
Blockly.Grid.prototype.dispose = function() {
|
|
this.gridPattern_ = null;
|
|
};
|
|
|
|
/**
|
|
* Whether blocks should snap to the grid, based on the initial configuration.
|
|
* @return {boolean} True if blocks should snap, false otherwise.
|
|
* @package
|
|
*/
|
|
Blockly.Grid.prototype.shouldSnap = function() {
|
|
return this.snapToGrid_;
|
|
};
|
|
|
|
/**
|
|
* Get the spacing of the grid points (in px).
|
|
* @return {number} The spacing of the grid points.
|
|
* @package
|
|
*/
|
|
Blockly.Grid.prototype.getSpacing = function() {
|
|
return this.spacing_;
|
|
};
|
|
|
|
/**
|
|
* Get the id of the pattern element, which should be randomized to avoid
|
|
* conflicts with other Blockly instances on the page.
|
|
* @return {string} The pattern ID.
|
|
* @package
|
|
*/
|
|
Blockly.Grid.prototype.getPatternId = function() {
|
|
return this.gridPattern_.id;
|
|
};
|
|
|
|
/**
|
|
* Update the grid with a new scale.
|
|
* @param {number} scale The new workspace scale.
|
|
* @package
|
|
*/
|
|
Blockly.Grid.prototype.update = function(scale) {
|
|
this.scale_ = scale;
|
|
// MSIE freaks if it sees a 0x0 pattern, so set empty patterns to 100x100.
|
|
var safeSpacing = (this.spacing_ * scale) || 100;
|
|
|
|
this.gridPattern_.setAttribute('width', safeSpacing);
|
|
this.gridPattern_.setAttribute('height', safeSpacing);
|
|
|
|
var half = Math.floor(this.spacing_ / 2) + 0.5;
|
|
var start = half - this.length_ / 2;
|
|
var end = half + this.length_ / 2;
|
|
|
|
half *= scale;
|
|
start *= scale;
|
|
end *= scale;
|
|
|
|
this.setLineAttributes_(this.line1_, scale, start, end, half, half);
|
|
this.setLineAttributes_(this.line2_, scale, half, half, start, end);
|
|
};
|
|
|
|
/**
|
|
* Set the attributes on one of the lines in the grid. Use this to update the
|
|
* length and stroke width of the grid lines.
|
|
* @param {!SVGElement} line Which line to update.
|
|
* @param {number} width The new stroke size (in px).
|
|
* @param {number} x1 The new x start position of the line (in px).
|
|
* @param {number} x2 The new x end position of the line (in px).
|
|
* @param {number} y1 The new y start position of the line (in px).
|
|
* @param {number} y2 The new y end position of the line (in px).
|
|
* @private
|
|
*/
|
|
Blockly.Grid.prototype.setLineAttributes_ = function(line, width, x1, x2, y1, y2) {
|
|
if (line) {
|
|
line.setAttribute('stroke-width', width);
|
|
line.setAttribute('x1', x1);
|
|
line.setAttribute('y1', y1);
|
|
line.setAttribute('x2', x2);
|
|
line.setAttribute('y2', y2);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Move the grid to a new x and y position, and make sure that change is visible.
|
|
* @param {number} x The new x position of the grid (in px).
|
|
* @param {number} y The new y position ofthe grid (in px).
|
|
* @package
|
|
*/
|
|
Blockly.Grid.prototype.moveTo = function(x, y) {
|
|
this.gridPattern_.setAttribute('x', x);
|
|
this.gridPattern_.setAttribute('y', y);
|
|
|
|
if (goog.userAgent.IE || goog.userAgent.EDGE) {
|
|
// IE/Edge doesn't notice that the x/y offsets have changed.
|
|
// Force an update.
|
|
this.update(this.scale_);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Create the DOM for the grid described by options.
|
|
* @param {string} rnd A random ID to append to the pattern's ID.
|
|
* @param {!Object} gridOptions The object containing grid configuration.
|
|
* @param {!SVGElement} defs The root SVG element for this workspace's defs.
|
|
* @return {!SVGElement} The SVG element for the grid pattern.
|
|
* @package
|
|
*/
|
|
Blockly.Grid.createDom = function(rnd, gridOptions, defs) {
|
|
/*
|
|
<pattern id="blocklyGridPattern837493" patternUnits="userSpaceOnUse">
|
|
<rect stroke="#888" />
|
|
<rect stroke="#888" />
|
|
</pattern>
|
|
*/
|
|
var gridPattern = Blockly.utils.createSvgElement('pattern',
|
|
{
|
|
'id': 'blocklyGridPattern' + rnd,
|
|
'patternUnits': 'userSpaceOnUse'
|
|
}, defs);
|
|
if (gridOptions['length'] > 0 && gridOptions['spacing'] > 0) {
|
|
Blockly.utils.createSvgElement('line',
|
|
{'stroke': gridOptions['colour']}, gridPattern);
|
|
if (gridOptions['length'] > 1) {
|
|
Blockly.utils.createSvgElement('line',
|
|
{'stroke': gridOptions['colour']}, gridPattern);
|
|
}
|
|
// x1, y1, x1, x2 properties will be set later in update.
|
|
} else {
|
|
// Edge 16 doesn't handle empty patterns
|
|
Blockly.utils.createSvgElement('line', {}, gridPattern);
|
|
}
|
|
return gridPattern;
|
|
};
|