mirror of
https://github.com/google/blockly.git
synced 2026-05-12 23:20:10 +02:00
9d5dcc6e46
* chore: fix circular dependencies w/ static workspace funcs * remove preserved imports that aren't currently necessary (probably) * fix circular dependency with workspaces and block using stub * fix dependency between variables and xml by moving function to utils * add stub for trashcan as well * fix line endings from rebase * fix goog/base order * add trashcan patch * fix: types of compose and decompose in block * fix: workspace naming in toolbox * chore: add jsdoc * chore: restore registry comments to better positions * chore: remove implementations in goog.js * chore: fix types of stubs * chore: remove added AnyDuringMigration casts * chore: remove modifications to xml and variables * chore: format * chore: remove event requirements in workspace comments * chore: fix circular dependency with xml and workspace comments * fixup remove ContextMenu import * chore: fix dependency between mutator and workspace * chore: break circular dependency between names and procedures * chore: get tests to run? * chore: pr comments' * chore: fix stubbing field registry fromJson * chore: fix spying on fire * chore: fix stubbing parts of connection checker * chore: fix stubbing dialog * chore: fix stubbing style * chore: fix spying on duplicate * chore: fix stubbing variables * chore: fix stubbing copy * chore: fix stubbing in workspace * chore: remove unnecessary stubs * chore: fix formatting * chore: fix other formatting * chore: add backwards compatible static properties to workspace * chore: move static type properties * chore: move and comment stubs * chore: add newlines at EOF * chore: improve errors for monkey patched functions * chore: update comment with a pointer to the doc * chore: update comment with a pointer to the doc * chore: format
223 lines
6.5 KiB
TypeScript
223 lines
6.5 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2019 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview An object that owns a block's rendering SVG elements.
|
|
*/
|
|
|
|
/**
|
|
* An object that owns a block's rendering SVG elements.
|
|
* @class
|
|
*/
|
|
import * as goog from '../../../closure/goog/goog.js';
|
|
goog.declareModuleId('Blockly.zelos.PathObject');
|
|
|
|
/* eslint-disable-next-line no-unused-vars */
|
|
// Unused import preserved for side-effects. Remove if unneeded.
|
|
// import '../../theme.js';
|
|
|
|
import type {BlockSvg} from '../../block_svg.js';
|
|
import type {Connection} from '../../connection.js';
|
|
import type {BlockStyle} from '../../theme.js';
|
|
import * as dom from '../../utils/dom.js';
|
|
import {Svg} from '../../utils/svg.js';
|
|
import {PathObject as BasePathObject} from '../common/path_object.js';
|
|
|
|
import type {ConstantProvider} from './constants.js';
|
|
|
|
|
|
/**
|
|
* An object that handles creating and setting each of the SVG elements
|
|
* used by the renderer.
|
|
* @alias Blockly.zelos.PathObject
|
|
*/
|
|
export class PathObject extends BasePathObject {
|
|
/** The selected path of the block. */
|
|
private svgPathSelected_: SVGElement|null = null;
|
|
private readonly outlines_: {[key: string]: SVGElement};
|
|
|
|
/**
|
|
* A set used to determine which outlines were used during a draw pass. The
|
|
* set is initialized with a reference to all the outlines in
|
|
* `this.outlines_`. Every time we use an outline during the draw pass, the
|
|
* reference is removed from this set.
|
|
*/
|
|
// AnyDuringMigration because: Type 'null' is not assignable to type '{ [key:
|
|
// string]: number; }'.
|
|
private remainingOutlines_: {[key: string]: number} =
|
|
null as AnyDuringMigration;
|
|
|
|
/**
|
|
* The type of block's output connection shape. This is set when a block
|
|
* with an output connection is drawn.
|
|
*/
|
|
outputShapeType = null;
|
|
|
|
/** @internal */
|
|
public override constants: ConstantProvider;
|
|
|
|
/**
|
|
* @param root The root SVG element.
|
|
* @param style The style object to use for colouring.
|
|
* @param constants The renderer's constants.
|
|
* @internal
|
|
*/
|
|
constructor(
|
|
root: SVGElement, style: BlockStyle, constants: ConstantProvider) {
|
|
super(root, style, constants);
|
|
|
|
this.constants = constants;
|
|
|
|
/** The outline paths on the block. */
|
|
this.outlines_ = Object.create(null);
|
|
}
|
|
|
|
override setPath(pathString: string) {
|
|
super.setPath(pathString);
|
|
if (this.svgPathSelected_) {
|
|
this.svgPathSelected_.setAttribute('d', pathString);
|
|
}
|
|
}
|
|
|
|
override applyColour(block: BlockSvg) {
|
|
super.applyColour(block);
|
|
// Set shadow stroke colour.
|
|
const parent = block.getParent();
|
|
if (block.isShadow() && parent) {
|
|
this.svgPath.setAttribute('stroke', parent.style.colourTertiary);
|
|
}
|
|
|
|
// Apply colour to outlines.
|
|
for (const key in this.outlines_) {
|
|
this.outlines_[key].setAttribute('fill', this.style.colourTertiary);
|
|
}
|
|
}
|
|
|
|
override flipRTL() {
|
|
super.flipRTL();
|
|
// Mirror each input outline path.
|
|
for (const key in this.outlines_) {
|
|
this.outlines_[key].setAttribute('transform', 'scale(-1 1)');
|
|
}
|
|
}
|
|
|
|
override updateSelected(enable: boolean) {
|
|
this.setClass_('blocklySelected', enable);
|
|
if (enable) {
|
|
if (!this.svgPathSelected_) {
|
|
this.svgPathSelected_ = this.svgPath.cloneNode(true) as SVGElement;
|
|
this.svgPathSelected_.setAttribute('fill', 'none');
|
|
this.svgPathSelected_.setAttribute(
|
|
'filter', 'url(#' + this.constants.selectedGlowFilterId + ')');
|
|
this.svgRoot.appendChild(this.svgPathSelected_);
|
|
}
|
|
} else {
|
|
if (this.svgPathSelected_) {
|
|
this.svgRoot.removeChild(this.svgPathSelected_);
|
|
this.svgPathSelected_ = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
override updateReplacementFade(enable: boolean) {
|
|
this.setClass_('blocklyReplaceable', enable);
|
|
if (enable) {
|
|
this.svgPath.setAttribute(
|
|
'filter', 'url(#' + this.constants.replacementGlowFilterId + ')');
|
|
} else {
|
|
this.svgPath.removeAttribute('filter');
|
|
}
|
|
}
|
|
|
|
override updateShapeForInputHighlight(conn: Connection, enable: boolean) {
|
|
const name = conn.getParentInput()!.name;
|
|
const outlinePath = this.getOutlinePath_(name);
|
|
if (!outlinePath) {
|
|
return;
|
|
}
|
|
if (enable) {
|
|
outlinePath.setAttribute(
|
|
'filter', 'url(#' + this.constants.replacementGlowFilterId + ')');
|
|
} else {
|
|
outlinePath.removeAttribute('filter');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Method that's called when the drawer is about to draw the block.
|
|
* @internal
|
|
*/
|
|
beginDrawing() {
|
|
this.remainingOutlines_ = Object.create(null);
|
|
for (const key in this.outlines_) {
|
|
// The value set here isn't used anywhere, we are just using the
|
|
// object as a Set data structure.
|
|
this.remainingOutlines_[key] = 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Method that's called when the drawer is done drawing.
|
|
* @internal
|
|
*/
|
|
endDrawing() {
|
|
// Go through all remaining outlines that were not used this draw pass, and
|
|
// remove them.
|
|
if (this.remainingOutlines_) {
|
|
for (const key in this.remainingOutlines_) {
|
|
this.removeOutlinePath_(key);
|
|
}
|
|
}
|
|
// AnyDuringMigration because: Type 'null' is not assignable to type '{
|
|
// [key: string]: number; }'.
|
|
this.remainingOutlines_ = null as AnyDuringMigration;
|
|
}
|
|
|
|
/**
|
|
* Set the path generated by the renderer for an outline path on the
|
|
* respective outline path SVG element.
|
|
* @param name The input name.
|
|
* @param pathString The path.
|
|
* @internal
|
|
*/
|
|
setOutlinePath(name: string, pathString: string) {
|
|
const outline = this.getOutlinePath_(name);
|
|
outline.setAttribute('d', pathString);
|
|
outline.setAttribute('fill', this.style.colourTertiary);
|
|
}
|
|
|
|
/**
|
|
* Create's an outline path for the specified input.
|
|
* @param name The input name.
|
|
* @return The SVG outline path.
|
|
*/
|
|
private getOutlinePath_(name: string): SVGElement {
|
|
if (!this.outlines_[name]) {
|
|
this.outlines_[name] = dom.createSvgElement(
|
|
Svg.PATH, {
|
|
'class': 'blocklyOutlinePath', // IE doesn't like paths without the
|
|
// data definition, set empty
|
|
// default
|
|
'd': '',
|
|
},
|
|
this.svgRoot);
|
|
}
|
|
if (this.remainingOutlines_) {
|
|
delete this.remainingOutlines_[name];
|
|
}
|
|
return this.outlines_[name];
|
|
}
|
|
|
|
/**
|
|
* Remove an outline path that is associated with the specified input.
|
|
* @param name The input name.
|
|
*/
|
|
private removeOutlinePath_(name: string) {
|
|
this.outlines_[name].parentNode!.removeChild(this.outlines_[name]);
|
|
delete this.outlines_[name];
|
|
}
|
|
}
|