Files
blockly/core/icon.ts
Maribeth Bottorff 037eb59b89 chore: Lint TsDoc. (#6353)
* chore: add linting for tsdoc

* chore: don't require types on return

* chore: remove redundant fileoverview from ts

* chore: change return to returns and add some newlines

* chore: remove license tag

* chore: don't require params/return docs

* chore: remove spurious struct tags

* Revert "chore: change return to returns and add some newlines"

This reverts commit d6d8656a45.

* chore: don't auto-add param names

* chore: disable require-param bc it breaks on this

* return to returns and add line breaks

* chore: configure additional jsdoc rules

* chore: run format

* Revert "chore: remove license tag"

This reverts commit 173455588a.

* chore: allow license tag format

* chore: only require jsdoc on exported items

* chore: add missing jsdoc or silence where needed

* chore: run format

* chore: lint fixes
2022-08-23 14:27:22 -07:00

183 lines
4.7 KiB
TypeScript

/**
* @license
* Copyright 2013 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* Object representing an icon on a block.
*
* @class
*/
import * as goog from '../closure/goog/goog.js';
goog.declareModuleId('Blockly.Icon');
import type {BlockSvg} from './block_svg.js';
import * as browserEvents from './browser_events.js';
import type {Bubble} from './bubble.js';
import {Coordinate} from './utils/coordinate.js';
import * as dom from './utils/dom.js';
import {Size} from './utils/size.js';
import {Svg} from './utils/svg.js';
import * as svgMath from './utils/svg_math.js';
/**
* Class for an icon.
*
* @alias Blockly.Icon
*/
export abstract class Icon {
protected block_: BlockSvg;
/** The icon SVG group. */
iconGroup_: SVGGElement|null = null;
/** Whether this icon gets hidden when the block is collapsed. */
collapseHidden = true;
/** Height and width of icons. */
readonly SIZE = 17;
/** Bubble UI (if visible). */
protected bubble_: Bubble|null = null;
/** Absolute coordinate of icon's center. */
protected iconXY_: Coordinate|null = null;
/** @param block The block associated with this icon. */
constructor(block: BlockSvg) {
this.block_ = block;
}
/** Create the icon on the block. */
createIcon() {
if (this.iconGroup_) {
// Icon already exists.
return;
}
/* Here's the markup that will be generated:
<g class="blocklyIconGroup">
...
</g>
*/
this.iconGroup_ =
dom.createSvgElement(Svg.G, {'class': 'blocklyIconGroup'});
if (this.block_.isInFlyout) {
dom.addClass(this.iconGroup_ as Element, 'blocklyIconGroupReadonly');
}
this.drawIcon_(this.iconGroup_);
this.block_.getSvgRoot().appendChild(this.iconGroup_);
browserEvents.conditionalBind(
this.iconGroup_, 'mouseup', this, this.iconClick_);
this.updateEditable();
}
/** Dispose of this icon. */
dispose() {
dom.removeNode(this.iconGroup_); // Dispose of and unlink the icon.
this.setVisible(false); // Dispose of and unlink the bubble.
}
/** Add or remove the UI indicating if this icon may be clicked or not. */
updateEditable() {
// No-op on the base class.
}
/**
* Is the associated bubble visible?
*
* @returns True if the bubble is visible.
*/
isVisible(): boolean {
return !!this.bubble_;
}
/**
* Clicking on the icon toggles if the bubble is visible.
*
* @param e Mouse click event.
*/
protected iconClick_(e: MouseEvent) {
if (this.block_.workspace.isDragging()) {
// Drag operation is concluding. Don't open the editor.
return;
}
if (!this.block_.isInFlyout && !browserEvents.isRightButton(e)) {
this.setVisible(!this.isVisible());
}
}
/** Change the colour of the associated bubble to match its block. */
applyColour() {
if (this.isVisible()) {
this.bubble_!.setColour(this.block_.style.colourPrimary);
}
}
/**
* Notification that the icon has moved. Update the arrow accordingly.
*
* @param xy Absolute location in workspace coordinates.
*/
setIconLocation(xy: Coordinate) {
this.iconXY_ = xy;
if (this.isVisible()) {
this.bubble_!.setAnchorLocation(xy);
}
}
/**
* Notification that the icon has moved, but we don't really know where.
* Recompute the icon's location from scratch.
*/
computeIconLocation() {
// Find coordinates for the centre of the icon and update the arrow.
const blockXY = this.block_.getRelativeToSurfaceXY();
const iconXY = svgMath.getRelativeXY(this.iconGroup_ as SVGElement);
const newXY = new Coordinate(
blockXY.x + iconXY.x + this.SIZE / 2,
blockXY.y + iconXY.y + this.SIZE / 2);
if (!Coordinate.equals(this.getIconLocation(), newXY)) {
this.setIconLocation(newXY);
}
}
/**
* Returns the center of the block's icon relative to the surface.
*
* @returns Object with x and y properties in workspace coordinates.
*/
getIconLocation(): Coordinate|null {
return this.iconXY_;
}
/**
* Get the size of the icon as used for rendering.
* This differs from the actual size of the icon, because it bulges slightly
* out of its row rather than increasing the height of its row.
*
* @returns Height and width.
*/
getCorrectedSize(): Size {
// TODO (#2562): Remove getCorrectedSize.
return new Size(this.SIZE, this.SIZE - 2);
}
/**
* Draw the icon.
*
* @param _group The icon group.
*/
protected drawIcon_(_group: Element) {}
// No-op on base class.
/**
* Show or hide the icon.
*
* @param _visible True if the icon should be visible.
*/
setVisible(_visible: boolean) {}
}
// No-op on base class