mirror of
https://github.com/google/blockly.git
synced 2026-01-08 17:40:09 +01:00
fix: highlighting connections in zelos, also highlight connections moving (#7795)
* fix: remove zelos highlight override * feat: add isHighlighted to rendered connection * feat: add refreshing connection highlighting * chore: remove highlight and unhighlight connection APIs * chore: PR comments
This commit is contained in:
@@ -36,6 +36,7 @@ export class RenderedConnection extends Connection {
|
||||
private readonly dbOpposite: ConnectionDB;
|
||||
private readonly offsetInBlock: Coordinate;
|
||||
private trackedState: TrackedState;
|
||||
private highlighted: boolean = false;
|
||||
|
||||
/** Connection this connection connects to. Null if not connected. */
|
||||
override targetConnection: RenderedConnection | null = null;
|
||||
@@ -287,12 +288,19 @@ export class RenderedConnection extends Connection {
|
||||
|
||||
/** Add highlighting around this connection. */
|
||||
highlight() {
|
||||
this.getSourceBlock().workspace.getRenderer().highlightConnection(this);
|
||||
this.highlighted = true;
|
||||
this.getSourceBlock().queueRender();
|
||||
}
|
||||
|
||||
/** Remove the highlighting around this connection. */
|
||||
unhighlight() {
|
||||
this.getSourceBlock().workspace.getRenderer().unhighlightConnection(this);
|
||||
this.highlighted = false;
|
||||
this.getSourceBlock().queueRender();
|
||||
}
|
||||
|
||||
/** Returns true if this connection is highlighted, false otherwise. */
|
||||
isHighlighted(): boolean {
|
||||
return this.highlighted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,6 @@ import {isDynamicShape, isNotch, isPuzzleTab} from './constants.js';
|
||||
import type {ConstantProvider, Notch, PuzzleTab} from './constants.js';
|
||||
import type {RenderInfo} from './info.js';
|
||||
import * as deprecation from '../../utils/deprecation.js';
|
||||
import type {RenderedConnection} from '../../rendered_connection.js';
|
||||
import {ConnectionType} from '../../connection_type.js';
|
||||
|
||||
/**
|
||||
@@ -62,6 +61,7 @@ export class Drawer {
|
||||
draw() {
|
||||
this.drawOutline_();
|
||||
this.drawInternals_();
|
||||
this.updateConnectionHighlights();
|
||||
|
||||
this.block_.pathObject.setPath(this.outlinePath_ + '\n' + this.inlinePath_);
|
||||
if (this.info_.RTL) {
|
||||
@@ -443,13 +443,29 @@ export class Drawer {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a path to highlight the given connection. */
|
||||
drawConnectionHighlightPath(conn: RenderedConnection) {
|
||||
const measurable = this.info_.getMeasureableForConnection(conn);
|
||||
if (!measurable) {
|
||||
throw new Error('Could not find measurable for connection');
|
||||
}
|
||||
/**
|
||||
* Updates the path object to reflect which connections on the block are
|
||||
* highlighted.
|
||||
*/
|
||||
protected updateConnectionHighlights() {
|
||||
for (const row of this.info_.rows) {
|
||||
for (const elem of row.elements) {
|
||||
if (!(elem instanceof Connection)) continue;
|
||||
|
||||
if (elem.highlighted) {
|
||||
this.drawConnectionHighlightPath(elem);
|
||||
} else {
|
||||
this.block_.pathObject.removeConnectionHighlight?.(
|
||||
elem.connectionModel,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a path to highlight the given connection. */
|
||||
drawConnectionHighlightPath(measurable: Connection) {
|
||||
const conn = measurable.connectionModel;
|
||||
let path = '';
|
||||
if (
|
||||
conn.type === ConnectionType.INPUT_VALUE ||
|
||||
|
||||
@@ -40,12 +40,11 @@ export class PathObject implements IPathObject {
|
||||
constants: ConstantProvider;
|
||||
style: BlockStyle;
|
||||
|
||||
/**
|
||||
* Highlight paths associated with connections.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
connectionHighlights = new WeakMap<RenderedConnection, SVGElement>();
|
||||
/** Highlight paths associated with connections. */
|
||||
private connectionHighlights = new WeakMap<RenderedConnection, SVGElement>();
|
||||
|
||||
/** Locations of connection highlights. */
|
||||
private highlightOffsets = new WeakMap<RenderedConnection, Coordinate>();
|
||||
|
||||
/**
|
||||
* @param root The root SVG element.
|
||||
@@ -273,7 +272,13 @@ export class PathObject implements IPathObject {
|
||||
offset: Coordinate,
|
||||
rtl: boolean,
|
||||
) {
|
||||
if (this.connectionHighlights.has(connection)) return;
|
||||
if (this.connectionHighlights.has(connection)) {
|
||||
if (this.currentHighlightMatchesNew(connection, connectionPath, offset)) {
|
||||
return;
|
||||
}
|
||||
this.removeConnectionHighlight(connection);
|
||||
}
|
||||
|
||||
const highlight = dom.createSvgElement(
|
||||
Svg.PATH,
|
||||
{
|
||||
@@ -287,6 +292,18 @@ export class PathObject implements IPathObject {
|
||||
this.connectionHighlights.set(connection, highlight);
|
||||
}
|
||||
|
||||
private currentHighlightMatchesNew(
|
||||
connection: RenderedConnection,
|
||||
newPath: string,
|
||||
newOffset: Coordinate,
|
||||
): boolean {
|
||||
const currPath = this.connectionHighlights
|
||||
.get(connection)
|
||||
?.getAttribute('d');
|
||||
const currOffset = this.highlightOffsets.get(connection);
|
||||
return currPath === newPath && Coordinate.equals(currOffset, newOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any highlight associated with the given connection, if it exists.
|
||||
*/
|
||||
|
||||
@@ -257,25 +257,6 @@ export class Renderer implements IRegistrable {
|
||||
return InsertionMarkerManager.PREVIEW_TYPE.INSERTION_MARKER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visually highlights the given connection with a border, if it is not
|
||||
* already highlighted.
|
||||
*/
|
||||
highlightConnection(conn: RenderedConnection): void {
|
||||
const block = conn.getSourceBlock();
|
||||
|
||||
const info = this.makeRenderInfo_(block);
|
||||
info.measure();
|
||||
const drawer = this.makeDrawer_(block, info);
|
||||
|
||||
drawer.drawConnectionHighlightPath(conn);
|
||||
}
|
||||
|
||||
/** Visually unhighlights the given connection, if it is highlighted. */
|
||||
unhighlightConnection(conn: RenderedConnection): void {
|
||||
conn.getSourceBlock().pathObject.removeConnectionHighlight?.(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the block.
|
||||
*
|
||||
|
||||
@@ -40,6 +40,7 @@ export class Drawer extends BaseDrawer {
|
||||
override draw() {
|
||||
this.drawOutline_();
|
||||
this.drawInternals_();
|
||||
this.updateConnectionHighlights();
|
||||
|
||||
const pathObject = this.block_.pathObject as PathObject;
|
||||
pathObject.setPath(this.outlinePath_ + '\n' + this.inlinePath_);
|
||||
|
||||
@@ -20,6 +20,7 @@ import {Types} from './types.js';
|
||||
export class Connection extends Measurable {
|
||||
shape: Shape;
|
||||
isDynamicShape: boolean;
|
||||
highlighted: boolean;
|
||||
|
||||
/**
|
||||
* @param constants The rendering constants provider.
|
||||
@@ -32,9 +33,11 @@ export class Connection extends Measurable {
|
||||
) {
|
||||
super(constants);
|
||||
|
||||
this.shape = this.constants_.shapeFor(connectionModel);
|
||||
|
||||
this.isDynamicShape = 'isDynamic' in this.shape && this.shape.isDynamic;
|
||||
this.type |= Types.CONNECTION;
|
||||
|
||||
this.shape = this.constants_.shapeFor(connectionModel);
|
||||
this.isDynamicShape = 'isDynamic' in this.shape && this.shape.isDynamic;
|
||||
|
||||
this.highlighted = connectionModel.isHighlighted();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
import type {BlockSvg} from '../../block_svg.js';
|
||||
import {ConnectionType} from '../../connection_type.js';
|
||||
import {RenderedConnection} from '../../rendered_connection.js';
|
||||
import * as svgPaths from '../../utils/svg_paths.js';
|
||||
import type {BaseShape, DynamicShape, Notch} from '../common/constants.js';
|
||||
import {Drawer as BaseDrawer} from '../common/drawer.js';
|
||||
import {Connection} from '../measurables/connection.js';
|
||||
import type {InlineInput} from '../measurables/inline_input.js';
|
||||
import {OutputConnection} from '../measurables/output_connection.js';
|
||||
import type {Row} from '../measurables/row.js';
|
||||
@@ -44,6 +44,7 @@ export class Drawer extends BaseDrawer {
|
||||
pathObject.beginDrawing();
|
||||
this.drawOutline_();
|
||||
this.drawInternals_();
|
||||
this.updateConnectionHighlights();
|
||||
|
||||
pathObject.setPath(this.outlinePath_ + '\n' + this.inlinePath_);
|
||||
if (this.info_.RTL) {
|
||||
@@ -236,17 +237,14 @@ export class Drawer extends BaseDrawer {
|
||||
}
|
||||
|
||||
/** Returns a path to highlight the given connection. */
|
||||
drawConnectionHighlightPath(conn: RenderedConnection) {
|
||||
const measurable = this.info_.getMeasureableForConnection(conn);
|
||||
if (!measurable) {
|
||||
throw new Error('Could not find measurable for connection');
|
||||
}
|
||||
drawConnectionHighlightPath(measurable: Connection) {
|
||||
const conn = measurable.connectionModel;
|
||||
if (
|
||||
conn.type === ConnectionType.NEXT_STATEMENT ||
|
||||
conn.type === ConnectionType.PREVIOUS_STATEMENT ||
|
||||
(conn.type === ConnectionType.OUTPUT_VALUE && !measurable.isDynamicShape)
|
||||
) {
|
||||
super.drawConnectionHighlightPath(conn);
|
||||
super.drawConnectionHighlightPath(measurable);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
// Former goog.module ID: Blockly.zelos.Renderer
|
||||
|
||||
import type {BlockSvg} from '../../block_svg.js';
|
||||
import type {Connection} from '../../connection.js';
|
||||
import {ConnectionType} from '../../connection_type.js';
|
||||
import {InsertionMarkerManager} from '../../insertion_marker_manager.js';
|
||||
import type {Marker} from '../../keyboard_nav/marker.js';
|
||||
@@ -109,13 +108,6 @@ export class Renderer extends BaseRenderer {
|
||||
return this.constants_;
|
||||
}
|
||||
|
||||
override shouldHighlightConnection(conn: Connection) {
|
||||
return (
|
||||
conn.type !== ConnectionType.INPUT_VALUE &&
|
||||
conn.type !== ConnectionType.OUTPUT_VALUE
|
||||
);
|
||||
}
|
||||
|
||||
override getConnectionPreviewMethod(
|
||||
closest: RenderedConnection,
|
||||
local: RenderedConnection,
|
||||
|
||||
Reference in New Issue
Block a user