Skip to content

Commit

Permalink
feat(draw): support vector pen #WIK-15919
Browse files Browse the repository at this point in the history
  • Loading branch information
MissLixf committed Jul 4, 2024
1 parent c6029f8 commit 1cca57d
Show file tree
Hide file tree
Showing 32 changed files with 718 additions and 209 deletions.
5 changes: 5 additions & 0 deletions .changeset/thirty-dingos-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@plait/draw': minor
---

support vector pen
23 changes: 21 additions & 2 deletions packages/draw/src/constants/pointer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
import { BasicShapes, FlowchartSymbols, ArrowLineShape, SwimlaneDrawSymbols, TableSymbols, UMLSymbols } from '../interfaces';
import {
BasicShapes,
FlowchartSymbols,
ArrowLineShape,
SwimlaneDrawSymbols,
TableSymbols,
UMLSymbols,
VectorPenPointerType
} from '../interfaces';

export type DrawPointerType = BasicShapes | ArrowLineShape | FlowchartSymbols | SwimlaneDrawSymbols | TableSymbols | UMLSymbols;
export type DrawPointerType =
| BasicShapes
| ArrowLineShape
| FlowchartSymbols
| SwimlaneDrawSymbols
| TableSymbols
| UMLSymbols
| VectorPenPointerType;

export const getGeometryPointers = () => {
return [...Object.keys(BasicShapes), ...Object.keys(FlowchartSymbols), ...Object.keys(UMLSymbols)];
Expand All @@ -25,3 +40,7 @@ export const getUMLPointers = () => {
export const getArrowLinePointers = () => {
return Object.keys(ArrowLineShape);
};

export const getVectorPenPointers = () => {
return Object.keys(VectorPenPointerType);
};
17 changes: 0 additions & 17 deletions packages/draw/src/generators/arrow-line.generator.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/draw/src/generators/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './geometry-shape.generator';
export * from './arrow-line-active.generator';
export * from './line-active.generator';
export * from './arrow-line-auto-complete.generator';
export * from './single-text.generator';
export * from './text.generator';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import { PlaitBoard, Point, createG, drawRectangle, getSelectedElements } from '@plait/core';
import { ArrowLineShape, PlaitArrowLine } from '../interfaces';
import { Generator, PRIMARY_COLOR, drawFillPrimaryHandle, drawPrimaryHandle } from '@plait/common';
import { getMiddlePoints } from '../utils/arrow-line/arrow-line-basic';
import { getMiddlePoints } from '../utils/line';
import { getNextRenderPoints } from '../utils/arrow-line/elbow';
import { isUpdatedHandleIndex } from '../utils/arrow-line';
import { getHitPointIndex } from '../utils/position/arrow-line';
import { getHitPointIndex } from '../utils/position/line';
import { DefaultDrawActiveStyle } from '../constants';
import { PlaitLine } from '../interfaces/line';

export interface ActiveData {
selected: boolean;
linePoints: Point[];
}

export class ArrowLineActiveGenerator extends Generator<PlaitArrowLine, ActiveData> {
export class LineActiveGenerator extends Generator<PlaitLine, ActiveData> {
onlySelectedCurrentLine = false;

canDraw(element: PlaitArrowLine, data: ActiveData): boolean {
canDraw(element: PlaitLine, data: ActiveData): boolean {
if (data.selected) {
return true;
} else {
return false;
}
}

draw(element: PlaitArrowLine, data: ActiveData): SVGGElement {
draw(element: PlaitLine, data: ActiveData): SVGGElement {
const activeG = createG();
const selectedElements = getSelectedElements(this.board);
this.onlySelectedCurrentLine = selectedElements.length === 1;
Expand Down
24 changes: 24 additions & 0 deletions packages/draw/src/generators/line.generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { PlaitDrawElement } from '../interfaces';
import { Generator } from '@plait/common';
import { drawArrowLine } from '../utils/arrow-line/arrow-line-basic';
import { PlaitLine } from '../interfaces/line';
import { drawVectorLine } from '../utils';

export interface ShapeData {}

export class LineGenerator extends Generator<PlaitLine, ShapeData> {
canDraw(element: PlaitLine, data: ShapeData): boolean {
return true;
}

draw(element: PlaitLine, data: ShapeData) {
let lineG: SVGGElement | undefined;
if (PlaitDrawElement.isArrowLine(element)) {
lineG = drawArrowLine(this.board, element);
}
if (PlaitDrawElement.isVectorLine(element)) {
lineG = drawVectorLine(this.board, element);
}
return lineG;
}
}
3 changes: 2 additions & 1 deletion packages/draw/src/interfaces/arrow-line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Element } from 'slate';
import { StrokeStyle } from './element';
import { getConnectionPoint } from '../utils/arrow-line/arrow-line-common';
import { PlaitShapeElement } from '.';
import { PlaitLine } from './line';

export enum ArrowLineMarkerType {
arrow = 'arrow',
Expand Down Expand Up @@ -105,7 +106,7 @@ export const PlaitArrowLine = {
isBoundElementOfTarget(line: PlaitArrowLine, element: PlaitShapeElement) {
return line.target.boundId === element.id;
},
getPoints(board: PlaitBoard, line: PlaitArrowLine) {
getPoints(board: PlaitBoard, line: PlaitLine) {
let sourcePoint;
if (line.source.boundId) {
const sourceElement = getElementById<PlaitShapeElement>(board, line.source.boundId)!;
Expand Down
12 changes: 8 additions & 4 deletions packages/draw/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PlaitSwimlane, SwimlaneSymbols } from './swimlane';
import { PlaitBaseTable, PlaitTable, PlaitTableElement, TableSymbols } from './table';
import { PlaitText } from './text';
import { PlaitVectorLine } from './vector-line';
import { PlaitLine } from './line';

export * from './arrow-line';
export * from './geometry';
Expand All @@ -25,12 +26,15 @@ export const PlaitDrawElement = {
isGeometry: (value: any): value is PlaitGeometry => {
return value.type === 'geometry';
},
// isLine: (value: any): value is PlaitArrowLine => {
// return value.type === 'arrow-line' || value.type === 'line' || value.type === 'vector-line';
// },
isArrowLine: (value: any): value is PlaitArrowLine => {
return value.type === 'arrow-line' || value.type === 'line';
},
isVectorLine: (value: any): value is PlaitVectorLine => {
return value.type === 'vector-line';
},
isLine: (value: any): value is PlaitLine => {
return PlaitDrawElement.isArrowLine(value) || PlaitDrawElement.isVectorLine(value);
},
isText: (value: any): value is PlaitText => {
return value.type === 'geometry' && value.shape === BasicShapes.text;
},
Expand All @@ -43,7 +47,7 @@ export const PlaitDrawElement = {
isDrawElement: (value: any): value is PlaitDrawElement => {
if (
PlaitDrawElement.isGeometry(value) ||
PlaitDrawElement.isArrowLine(value) ||
PlaitDrawElement.isLine(value) ||
PlaitDrawElement.isImage(value) ||
PlaitDrawElement.isTable(value) ||
PlaitDrawElement.isSwimlane(value)
Expand Down
4 changes: 4 additions & 0 deletions packages/draw/src/interfaces/line.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { PlaitArrowLine } from './arrow-line';
import { PlaitVectorLine } from './vector-line';

export type PlaitLine = PlaitArrowLine | PlaitVectorLine;
13 changes: 12 additions & 1 deletion packages/draw/src/interfaces/vector-line.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import { PlaitElement, Point } from '@plait/core';
import { Path, PlaitElement, Point } from '@plait/core';
import { StrokeStyle } from './element';
import { ArrowLineShape } from './arrow-line';

export enum VectorPenPointerType {
vectorPen = 'vectorPen'
}

export enum VectorLineShape {
straight = ArrowLineShape.straight,
curve = ArrowLineShape.curve
}

export interface VectorPenRef {
start?: Point;
element?: PlaitVectorLine;
path?: Path;
shape: VectorLineShape;
}

export interface PlaitVectorLine extends PlaitElement {
type: 'vector-line';
shape: VectorLineShape;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { PlaitBoard, PlaitPluginElementContext, OnContextChanged, getElementById, createDebugGenerator, PlaitNode } from '@plait/core';
import { ArrowLineText, PlaitArrowLine, PlaitDrawElement, PlaitGeometry } from './interfaces';
import { ArrowLineShapeGenerator } from './generators/arrow-line.generator';
import { ArrowLineActiveGenerator } from './generators/arrow-line-active.generator';
import { LineActiveGenerator } from './generators/line-active.generator';
import { DrawTransforms } from './transforms';
import { GeometryThreshold, MIN_TEXT_WIDTH } from './constants';
import { CommonElementFlavour, TextManage, TextManageChangeData } from '@plait/common';
import { getArrowLinePoints, getArrowLineTextRectangle } from './utils/arrow-line/arrow-line-basic';
import { getArrowLineTextRectangle } from './utils/arrow-line/arrow-line-basic';
import { memorizeLatestText } from './utils/memorize';
import { LineGenerator } from './generators/line.generator';
import { PlaitLine } from './interfaces/line';
import { getLinePoints } from './utils';

interface BoundedElements {
source?: PlaitGeometry;
Expand All @@ -16,11 +18,10 @@ interface BoundedElements {
const debugKey = 'debug:plait:line-turning';
const debugGenerator = createDebugGenerator(debugKey);

export class ArrowLineComponent extends CommonElementFlavour<PlaitArrowLine, PlaitBoard>
implements OnContextChanged<PlaitArrowLine, PlaitBoard> {
shapeGenerator!: ArrowLineShapeGenerator;
export class LineComponent extends CommonElementFlavour<PlaitLine, PlaitBoard> implements OnContextChanged<PlaitLine, PlaitBoard> {
shapeGenerator!: LineGenerator;

activeGenerator!: ArrowLineActiveGenerator;
activeGenerator!: LineActiveGenerator;

boundedElements: BoundedElements = {};

Expand All @@ -29,23 +30,26 @@ export class ArrowLineComponent extends CommonElementFlavour<PlaitArrowLine, Pla
}

initializeGenerator() {
this.shapeGenerator = new ArrowLineShapeGenerator(this.board);
this.activeGenerator = new ArrowLineActiveGenerator(this.board);
this.initializeTextManagesByElement();
this.shapeGenerator = new LineGenerator(this.board);
this.activeGenerator = new LineActiveGenerator(this.board);
if (PlaitDrawElement.isArrowLine(this.element)) {
this.initializeTextManagesByElement();
}
}

initialize(): void {
this.initializeGenerator();
this.shapeGenerator.processDrawing(this.element, this.getElementG());
const linePoints = getArrowLinePoints(this.board, this.element);
const linePoints = getLinePoints(this.board, this.element)!;
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
selected: this.selected,
linePoints
});
super.initialize();
this.boundedElements = this.getBoundedElements();
this.drawText();

if (PlaitDrawElement.isArrowLine(this.element)) {
this.boundedElements = this.getBoundedElements();
this.drawText();
}
debugGenerator.isDebug() && debugGenerator.drawCircles(this.board, this.element.points.slice(1, -1), 4, true);
}

Expand All @@ -66,25 +70,27 @@ export class ArrowLineComponent extends CommonElementFlavour<PlaitArrowLine, Pla
return boundedElements;
}

onContextChanged(
value: PlaitPluginElementContext<PlaitArrowLine, PlaitBoard>,
previous: PlaitPluginElementContext<PlaitArrowLine, PlaitBoard>
) {
onContextChanged(value: PlaitPluginElementContext<PlaitLine, PlaitBoard>, previous: PlaitPluginElementContext<PlaitLine, PlaitBoard>) {
this.initializeWeakMap();
const boundedElements = this.getBoundedElements();
const isBoundedElementsChanged =
boundedElements.source !== this.boundedElements.source || boundedElements.target !== this.boundedElements.target;
this.boundedElements = boundedElements;
let isBoundedElementsChanged = false;
if (PlaitDrawElement.isArrowLine(this.element)) {
const boundedElements = this.getBoundedElements();
isBoundedElementsChanged =
boundedElements.source !== this.boundedElements.source || boundedElements.target !== this.boundedElements.target;
this.boundedElements = boundedElements;
}
const isChangeTheme = this.board.operations.find(op => op.type === 'set_theme');
const linePoints = getArrowLinePoints(this.board, this.element);
const linePoints = getLinePoints(this.board, this.element)!;
if (value.element !== previous.element || isChangeTheme) {
this.shapeGenerator.processDrawing(this.element, this.getElementG());
this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), {
selected: this.selected,
linePoints
});
this.updateText(previous.element.texts, value.element.texts);
this.updateTextRectangle();
if (PlaitDrawElement.isArrowLine(this.element)) {
this.updateText(previous.element.texts, value.element.texts);
this.updateTextRectangle();
}
} else {
const needUpdate = value.selected !== previous.selected || this.activeGenerator.needUpdate();
if (needUpdate) {
Expand Down Expand Up @@ -132,7 +138,7 @@ export class ArrowLineComponent extends CommonElementFlavour<PlaitArrowLine, Pla
},
onChange: (textManageChangeData: TextManageChangeData) => {
const path = PlaitBoard.findPath(this.board, this.element);
const node = PlaitNode.get(this.board, path) as PlaitArrowLine;
const node = PlaitNode.get(this.board, path) as PlaitLine;
const texts = [...node.texts];
const newWidth = textManageChangeData.width < MIN_TEXT_WIDTH ? MIN_TEXT_WIDTH : textManageChangeData.width;
texts.splice(index, 1, {
Expand Down
6 changes: 3 additions & 3 deletions packages/draw/src/plugins/with-arrow-line-bound-reaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '@plait/core';
import { ArrowLineShape, PlaitDrawElement } from '../interfaces';
import { isResizingByCondition } from '@plait/common';
import { ArrowLineResizeHandle } from '../utils/position/arrow-line';
import { LineResizeHandle } from '../utils/position/line';
import { drawBoundReaction, getHitShape, getSnappingRef } from '../utils';

export const withArrowLineBoundReaction = (board: PlaitBoard) => {
Expand All @@ -29,9 +29,9 @@ export const withArrowLineBoundReaction = (board: PlaitBoard) => {
const linePointers = Object.keys(ArrowLineShape);
const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
const isLineResizing = isResizingByCondition<PlaitElement, ArrowLineResizeHandle>(board, resizeRef => {
const isLineResizing = isResizingByCondition<PlaitElement, LineResizeHandle>(board, resizeRef => {
const { element, handle } = resizeRef;
const isSourceOrTarget = handle === ArrowLineResizeHandle.target || handle === ArrowLineResizeHandle.source;
const isSourceOrTarget = handle === LineResizeHandle.target || handle === LineResizeHandle.source;
return PlaitDrawElement.isArrowLine(element) && isSourceOrTarget;
});
if (isLinePointer || isLineResizing) {
Expand Down
Loading

0 comments on commit 1cca57d

Please sign in to comment.