diff --git a/src/Components/Canvas/Canvas.tsx b/src/Components/Canvas/Canvas.tsx index 0f732a4..d7321b2 100644 --- a/src/Components/Canvas/Canvas.tsx +++ b/src/Components/Canvas/Canvas.tsx @@ -1,15 +1,79 @@ import React, { useEffect, useRef } from 'react'; import { type IPoint } from '../../Interfaces/IPoint'; import { BAR_WIDTH } from '../Bar/Bar'; +import { SelectorMode } from '../SVG/SVG'; +import { type DrawParams } from '../Viewer/Viewer'; +import { RenderContainers, RenderSymbols } from './Renderer'; +import { RenderContainerSelector } from './SelectorContainer'; +import { RenderSymbolSelector } from './SelectorSymbol'; interface ICanvasProps { + className?: string width: number height: number - draw: (context: CanvasRenderingContext2D, frameCount: number, scale: number, translatePos: IPoint) => void - className?: string style?: React.CSSProperties + drawParams: DrawParams }; +function Draw( + ctx: CanvasRenderingContext2D, + frameCount: number, + scale: number, + translatePos: IPoint, + { + mainContainer, + selectorMode, + selectedContainer, + selectedSymbol, + containers, + symbols + }: DrawParams +): void { + if (mainContainer === undefined) { + return; + } + + const topDim = mainContainer.properties.y; + const leftDim = mainContainer.properties.x; + const rightDim = mainContainer.properties.x + mainContainer.properties.width; + const bottomDim = mainContainer.properties.y + mainContainer.properties.height; + + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.save(); + ctx.setTransform(scale, 0, 0, scale, translatePos.x, translatePos.y); + ctx.fillStyle = '#000000'; + + // Draw containers and symbol dimensions + RenderContainers( + ctx, + mainContainer, + containers, + leftDim, bottomDim, topDim, rightDim, scale); + + // Draw symbols and symbol dimensions + RenderSymbols(ctx, symbols, scale); + + // Draw selector + switch (selectorMode) { + case SelectorMode.Containers: + RenderContainerSelector(ctx, frameCount, { + containers, + scale, + selected: selectedContainer + }); + break; + case SelectorMode.Symbols: + RenderSymbolSelector(ctx, frameCount, { + symbols, + scale, + selected: selectedSymbol + }); + break; + } + + ctx.restore(); +} + function UseCanvas( draw: (context: CanvasRenderingContext2D, frameCount: number, @@ -128,8 +192,21 @@ interface Viewer { viewerHeight: number } -export function Canvas({ width, height, draw, style, className }: ICanvasProps): JSX.Element { - const canvasRef = UseCanvas(draw); +export function Canvas({ + className, + width, + height, + style, + drawParams +}: ICanvasProps): JSX.Element { + const canvasRef = UseCanvas(( + ...CanvasProps + ) => { + Draw( + ...CanvasProps, + drawParams + ); + }); const [{ viewerWidth, viewerHeight }, setViewer] = React.useState({ viewerWidth: width, diff --git a/src/Components/Canvas/Renderer.ts b/src/Components/Canvas/Renderer.ts index 82f3ea1..c93e615 100644 --- a/src/Components/Canvas/Renderer.ts +++ b/src/Components/Canvas/Renderer.ts @@ -68,11 +68,11 @@ export function RenderContainerDimensions( export function RenderSymbols( ctx: CanvasRenderingContext2D, - current: IHistoryState, + symbols: Map, scale: number ): void { let count = 0; - current.symbols.forEach((symbol: ISymbolModel) => { + symbols.forEach((symbol: ISymbolModel) => { RenderSymbol(ctx, symbol, scale); if (!symbol.showDimension) { diff --git a/src/Components/SVG/SVG.tsx b/src/Components/SVG/SVG.tsx index 90bbcc8..2a99c74 100644 --- a/src/Components/SVG/SVG.tsx +++ b/src/Components/SVG/SVG.tsx @@ -1,14 +1,13 @@ import * as React from 'react'; import { ReactSVGPanZoom, type Tool, TOOL_PAN, type Value, ALIGN_CENTER } from 'react-svg-pan-zoom'; import { Container } from './Elements/Container'; -import { IContainerModel } from '../../Interfaces/IContainerModel'; import { SelectorContainer } from './Elements/SelectorContainer/SelectorContainer'; import { MAX_FRAMERATE } from '../../utils/default'; import { SymbolLayer } from './Elements/SymbolLayer'; -import { type ISymbolModel } from '../../Interfaces/ISymbolModel'; import { DimensionLayer } from './Elements/DimensionLayer'; import { SelectorSymbol } from './Elements/SelectorSymbol/SelectorSymbol'; -import { IToolbarProps, Toolbar } from './SVGReactPanZoom/ui-toolbar/toolbar'; +import { type IToolbarProps, Toolbar } from './SVGReactPanZoom/ui-toolbar/toolbar'; +import { type DrawParams } from '../Viewer/Viewer'; interface ISVGProps { className?: string @@ -16,12 +15,7 @@ interface ISVGProps { viewerHeight: number width: number height: number - containers: Map - children: IContainerModel - selectedContainer?: IContainerModel - symbols: Map - selectedSymbol?: ISymbolModel - selectorMode: SelectorMode + drawParams: DrawParams selectContainer: (containerId: string) => void } @@ -34,6 +28,14 @@ export enum SelectorMode { export const ID = 'svg'; export function SVG(props: ISVGProps): JSX.Element { + const { + mainContainer, + selectorMode, + selectedContainer, + selectedSymbol, + containers, + symbols + } = props.drawParams; const [tool, setTool] = React.useState(TOOL_PAN); // eslint-disable-next-line @typescript-eslint/consistent-type-assertions const [value, setValue] = React.useState({} as Value); @@ -59,27 +61,27 @@ export function SVG(props: ISVGProps): JSX.Element { }; const children: React.ReactNode | React.ReactNode[] = ; function Selector(): JSX.Element { - switch (props.selectorMode) { + switch (selectorMode) { case SelectorMode.Containers: return ; case SelectorMode.Symbols: return ; default: return <>; @@ -132,8 +134,13 @@ export function SVG(props: ISVGProps): JSX.Element { > {children} - - + + diff --git a/src/Components/Viewer/Viewer.tsx b/src/Components/Viewer/Viewer.tsx index 0a206ea..a29809a 100644 --- a/src/Components/Viewer/Viewer.tsx +++ b/src/Components/Viewer/Viewer.tsx @@ -1,44 +1,48 @@ import * as React from 'react'; import { type IContainerModel } from '../../Interfaces/IContainerModel'; import { type IHistoryState } from '../../Interfaces/IHistoryState'; -import { type IPoint } from '../../Interfaces/IPoint'; import { USE_EXPERIMENTAL_CANVAS_API } from '../../utils/default'; -import { FindContainerById, MakeRecursionDFSIterator } from '../../utils/itertools'; +import { FindContainerById } from '../../utils/itertools'; import { BAR_WIDTH } from '../Bar/Bar'; import { Canvas } from '../Canvas/Canvas'; -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 current: IHistoryState selectedContainer: IContainerModel | undefined - selectContainer: (containerId: string) => void selectedSymbol: ISymbolModel | undefined margin: number isComponentsOpen: boolean isSymbolsOpen: boolean + selectContainer: (containerId: string) => void +} + +export interface DrawParams { + mainContainer: IContainerModel + selectorMode: SelectorMode + selectedContainer: IContainerModel | undefined + selectedSymbol: ISymbolModel | undefined + containers: Map + symbols: Map +} + +function computeWidth(margin: number): number { + return window.innerWidth - (window.innerWidth < 768 ? BAR_WIDTH : margin); } export function Viewer({ className, current, selectedContainer, - selectContainer, selectedSymbol, margin, isComponentsOpen, - isSymbolsOpen + isSymbolsOpen, + selectContainer }: IViewerProps): JSX.Element { - function computeWidth(margin: number): number { - return window.innerWidth - (window.innerWidth < 768 ? BAR_WIDTH : margin); - } - const [windowSize, setWindowSize] = useState([ computeWidth(margin), window.innerHeight @@ -79,63 +83,22 @@ export function Viewer({ selectorMode = SelectorMode.Symbols; } + const drawParams: DrawParams = { + mainContainer, + selectorMode, + selectedContainer, + selectedSymbol, + containers: current.containers, + symbols: current.symbols + }; + if (USE_EXPERIMENTAL_CANVAS_API) { - function Draw( - ctx: CanvasRenderingContext2D, - frameCount: number, - scale: number, - translatePos: IPoint - ): void { - if (mainContainer === undefined) { - return; - } - - const topDim = mainContainer.properties.y; - const leftDim = mainContainer.properties.x; - const rightDim = mainContainer.properties.x + mainContainer.properties.width; - const bottomDim = mainContainer.properties.y + mainContainer.properties.height; - - ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); - ctx.save(); - ctx.setTransform(scale, 0, 0, scale, translatePos.x, translatePos.y); - ctx.fillStyle = '#000000'; - - // Draw containers and symbol dimensions - RenderContainers( - ctx, - mainContainer, - current.containers, - leftDim, bottomDim, topDim, rightDim, scale); - - // 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 ( ); } @@ -147,14 +110,8 @@ export function Viewer({ viewerHeight={windowSize[1]} width={mainContainer.properties.width} height={mainContainer.properties.height} - containers={current.containers} - selectedContainer={selectedContainer} - symbols={current.symbols} - selectedSymbol={selectedSymbol} - selectorMode={selectorMode} + drawParams={drawParams} selectContainer={selectContainer} - > - {mainContainer} - + /> ); }