From 9cf56b308b3e4eadd85aa0bd713725e6c8cff9e5 Mon Sep 17 00:00:00 2001 From: Eric NGUYEN Date: Fri, 17 Feb 2023 16:09:36 +0100 Subject: [PATCH] Canvas: Add symbol selector --- src/Components/Canvas/Selector.ts | 45 +++++++++----------- src/Components/Canvas/SelectorContainer.ts | 48 ++++++++++++++++++++++ src/Components/Canvas/SelectorSymbol.ts | 43 +++++++++++++++++++ src/Components/Canvas/Symbol.ts | 15 ++++--- src/Components/Viewer/Viewer.tsx | 28 +++++++++---- 5 files changed, 140 insertions(+), 39 deletions(-) create mode 100644 src/Components/Canvas/SelectorContainer.ts create mode 100644 src/Components/Canvas/SelectorSymbol.ts diff --git a/src/Components/Canvas/Selector.ts b/src/Components/Canvas/Selector.ts index c9ea814..1dc1654 100644 --- a/src/Components/Canvas/Selector.ts +++ b/src/Components/Canvas/Selector.ts @@ -1,33 +1,26 @@ -import { IContainerModel } from '../../Interfaces/IContainerModel'; import { SHOW_SELECTOR_TEXT } from '../../utils/default'; -import { GetAbsolutePosition } from '../../utils/itertools'; -import { RemoveMargin } from '../../utils/svg'; interface ISelectorProps { - containers: Map - selected?: IContainerModel - scale?: number + text: string + x: number + y: number + width: number + height: number + scale: number } -export function RenderSelector(ctx: CanvasRenderingContext2D, frameCount: number, props: ISelectorProps): void { - if (props.selected === undefined || props.selected === null) { - return; - } - - const scale = (props.scale ?? 1); - let [x, y] = GetAbsolutePosition(props.containers, props.selected); - let [width, height] = [ - props.selected.properties.width, - props.selected.properties.height - ]; - - ({ x, y, width, height } = RemoveMargin(x, y, width, height, - props.selected.properties.margin.left, - props.selected.properties.margin.bottom, - props.selected.properties.margin.top, - props.selected.properties.margin.right - )); - +export function RenderSelector( + ctx: CanvasRenderingContext2D, + frameCount: number, + { + text, + x, + y, + width, + height, + scale + }: ISelectorProps +): void { const xText = x + width / 2; const yText = y + height / 2; @@ -42,7 +35,7 @@ export function RenderSelector(ctx: CanvasRenderingContext2D, frameCount: number if (SHOW_SELECTOR_TEXT) { ctx.font = `${16 / scale}px Verdana`; ctx.textAlign = 'center'; - ctx.fillText(props.selected.properties.displayedText, xText, yText); + ctx.fillText(text, xText, yText); ctx.textAlign = 'left'; } } diff --git a/src/Components/Canvas/SelectorContainer.ts b/src/Components/Canvas/SelectorContainer.ts new file mode 100644 index 0000000..c151f6f --- /dev/null +++ b/src/Components/Canvas/SelectorContainer.ts @@ -0,0 +1,48 @@ +import { type IContainerModel } from '../../Interfaces/IContainerModel'; +import { GetAbsolutePosition } from '../../utils/itertools'; +import { RemoveMargin } from '../../utils/svg'; +import { RenderSelector } from './Selector'; + +interface ISelectorProps { + containers: Map + selected?: IContainerModel + scale?: number +} + +export function RenderContainerSelector( + ctx: CanvasRenderingContext2D, + frameCount: number, + props: ISelectorProps +): void { + if (props.selected === undefined || props.selected === null) { + return; + } + + const scale = (props.scale ?? 1); + let [x, y] = GetAbsolutePosition(props.containers, props.selected); + let [width, height] = [ + props.selected.properties.width, + props.selected.properties.height + ]; + + ({ x, y, width, height } = RemoveMargin(x, y, width, height, + props.selected.properties.margin.left, + props.selected.properties.margin.bottom, + props.selected.properties.margin.top, + props.selected.properties.margin.right + )); + + const text = props.selected.properties.displayedText; + RenderSelector( + ctx, + frameCount, + { + text, + x, + y, + width, + height, + scale + } + ); +} diff --git a/src/Components/Canvas/SelectorSymbol.ts b/src/Components/Canvas/SelectorSymbol.ts new file mode 100644 index 0000000..ddfbb29 --- /dev/null +++ b/src/Components/Canvas/SelectorSymbol.ts @@ -0,0 +1,43 @@ +import { type ISymbolModel } from '../../Interfaces/ISymbolModel'; +import { SYMBOL_MARGIN } from '../../utils/default'; +import { RenderSelector } from './Selector'; + +interface ISelectorProps { + symbols: Map + selected?: ISymbolModel + scale?: number +} + +export function RenderSymbolSelector( + ctx: CanvasRenderingContext2D, + frameCount: number, + props: ISelectorProps +): void { + if (props.selected === undefined || props.selected === null) { + return; + } + + const scale = (props.scale ?? 1); + const [width, height] = [ + props.selected.width / scale, + props.selected.height / scale + ]; + + const [x, y] = [ + props.selected.x + props.selected.width / 2, + -SYMBOL_MARGIN - height]; + + const text = props.selected.displayedText; + RenderSelector( + ctx, + frameCount, + { + text, + x, + y, + width, + height, + scale + } + ); +} diff --git a/src/Components/Canvas/Symbol.ts b/src/Components/Canvas/Symbol.ts index ced9593..c85e737 100644 --- a/src/Components/Canvas/Symbol.ts +++ b/src/Components/Canvas/Symbol.ts @@ -1,5 +1,5 @@ -import { ISymbolModel } from '../../Interfaces/ISymbolModel'; -import { DIMENSION_MARGIN } from '../../utils/default'; +import { type ISymbolModel } from '../../Interfaces/ISymbolModel'; +import { DIMENSION_MARGIN, SYMBOL_MARGIN } from '../../utils/default'; const IMAGE_CACHE = new Map(); @@ -26,6 +26,7 @@ export function RenderSymbol( DrawImage(ctx, scale, image, symbol); } + function DrawImage( ctx: CanvasRenderingContext2D, scale: number, @@ -34,12 +35,14 @@ function DrawImage( ): void { ctx.save(); ctx.fillStyle = '#000000'; + const width = symbol.width / scale; + const height = symbol.height / scale; ctx.drawImage( image, - symbol.x, - -DIMENSION_MARGIN, - symbol.width, - symbol.height + symbol.x + symbol.width / 2, + -SYMBOL_MARGIN - height, + width, + height ); ctx.restore(); } diff --git a/src/Components/Viewer/Viewer.tsx b/src/Components/Viewer/Viewer.tsx index af9dc8e..0a206ea 100644 --- a/src/Components/Viewer/Viewer.tsx +++ b/src/Components/Viewer/Viewer.tsx @@ -6,12 +6,13 @@ import { USE_EXPERIMENTAL_CANVAS_API } from '../../utils/default'; import { FindContainerById, MakeRecursionDFSIterator } from '../../utils/itertools'; import { BAR_WIDTH } from '../Bar/Bar'; import { Canvas } from '../Canvas/Canvas'; -import { RenderSelector } from '../Canvas/Selector'; +import { RenderContainerSelector } from '../Canvas/SelectorContainer'; import { SelectorMode, SVG } from '../SVG/SVG'; import { useState } from 'react'; import { type ISymbolModel } from '../../Interfaces/ISymbolModel'; import { RenderContainers, RenderContainerDimensions, RenderSymbols } from '../Canvas/Renderer'; import { RenderContainer } from '../Canvas/Container'; +import { RenderSymbolSelector } from '../Canvas/SelectorSymbol'; interface IViewerProps { className: string @@ -106,14 +107,27 @@ export function Viewer({ current.containers, leftDim, bottomDim, topDim, rightDim, scale); - // Draw selector - RenderSelector(ctx, frameCount, { - containers: current.containers, - scale, - selected: selectedContainer - }); // Draw symbols and symbol dimensions RenderSymbols(ctx, current, scale); + + // Draw selector + switch (selectorMode) { + case SelectorMode.Containers: + RenderContainerSelector(ctx, frameCount, { + containers: current.containers, + scale, + selected: selectedContainer + }); + break; + case SelectorMode.Symbols: + RenderSymbolSelector(ctx, frameCount, { + symbols: current.symbols, + scale, + selected: selectedSymbol + }); + break; + } + ctx.restore(); } return (