wisemapping-frontend/packages/mindplot/src/components/RelationshipControlPoints.ts

279 lines
8.2 KiB
TypeScript
Raw Normal View History

2022-11-26 08:47:35 -08:00
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// eslint-disable-next-line max-classes-per-file
import { Elipse, Line } from '@wisemapping/web2d';
import Shape from './util/Shape';
import ActionDispatcher from './ActionDispatcher';
import Workspace from './Workspace';
import PositionType from './PositionType';
import Relationship from './Relationship';
2022-11-27 10:22:19 -08:00
// eslint-disable-next-line no-shadow
export enum PivotType {
2022-11-26 08:47:35 -08:00
Start = 0,
End = 1,
}
class ControlPivotLine {
private _dot: Elipse;
private _line: Line;
private _pivotType: PivotType;
private _workspace: Workspace;
private _relationship: Relationship;
private _changeHander: () => void;
2022-11-27 10:22:19 -08:00
private _moveRelHandler: (controlPointPosition: PositionType) => void;
2022-11-26 08:47:35 -08:00
private _isVisible: boolean;
private _mouseMoveHandler: (e: MouseEvent) => void;
2022-11-27 10:22:19 -08:00
private _mouseUpHandler: () => void;
private _mouseDownHandler: (event: MouseEvent) => void;
2022-11-26 08:47:35 -08:00
constructor(
pivotType: PivotType,
relationship: Relationship,
2022-11-27 10:22:19 -08:00
mouseMoveHandler: (controlPointPosition: PositionType) => void,
2022-11-26 08:47:35 -08:00
changeHander: () => void,
) {
this._pivotType = pivotType;
this._changeHander = changeHander;
this._moveRelHandler = mouseMoveHandler;
this._relationship = relationship;
// Build dot controller ...
this._dot = new Elipse({
width: 6,
height: 6,
stroke: '1 solid #6589de',
fillColor: 'gray',
visibility: false,
});
this._dot.setCursor('pointer');
// Build line ...
this._line = new Line({ strokeColor: '#6589de', strokeWidth: 1, opacity: 0.3 });
const mouseClick = (event: MouseEvent): boolean => {
event.preventDefault();
event.stopPropagation();
return false;
};
this._dot.addEvent('click', mouseClick);
this._dot.addEvent('dblclick', mouseClick);
// Register handled ...
this._mouseMoveHandler = (e: MouseEvent) => this.mouseMoveHandler(e);
2022-11-27 10:22:19 -08:00
this._mouseUpHandler = () => this.mouseUpHandler();
this._mouseDownHandler = (event: MouseEvent) => this.mouseDownHandler(event);
2022-11-26 08:47:35 -08:00
}
2022-11-27 10:22:19 -08:00
private mouseDownHandler(event: MouseEvent) {
const screenManager = this.getWorkspace().getScreenManager();
screenManager.addEvent('mousemove', this._mouseMoveHandler);
screenManager.addEvent('mouseup', this._mouseUpHandler);
2022-11-26 08:47:35 -08:00
event.preventDefault();
event.stopPropagation();
}
setVisibility(value: boolean) {
2022-11-27 10:22:19 -08:00
if (this._isVisible !== value) {
const screenManager = this.getWorkspace().getScreenManager();
if (!value) {
screenManager.removeEvent('mousemove', this._mouseMoveHandler);
screenManager.removeEvent('mouseup', this._mouseUpHandler);
this._dot.removeEvent('mousedown', this._mouseDownHandler);
} else {
// Register events ...
this._dot.addEvent('mousedown', this._mouseDownHandler);
}
// Make it visible ...
this._dot.setVisibility(value);
this._line.setVisibility(value);
2022-11-26 08:47:35 -08:00
}
2022-11-27 10:22:19 -08:00
this._isVisible = value;
2022-11-26 08:47:35 -08:00
if (value) {
2022-11-27 10:22:19 -08:00
// Register events ...
2022-11-26 08:47:35 -08:00
this.redraw();
this._line.moveToFront();
this._dot.moveToFront();
}
}
getPosition(): PositionType {
const line = this._relationship.getLine();
return line.getControlPoints()[this._pivotType];
}
redraw(): void {
if (this._isVisible) {
const relationshipLine = this._relationship.getLine();
const startPosition =
2022-11-27 10:22:19 -08:00
this._pivotType === PivotType.End ? relationshipLine.getTo() : relationshipLine.getFrom();
2022-11-26 08:47:35 -08:00
const ctrPosition = relationshipLine.getControlPoints()[this._pivotType];
this._line.setFrom(startPosition.x, startPosition.y);
2022-11-27 10:22:19 -08:00
this._line.setTo(startPosition.x + ctrPosition.x - 5, startPosition.y + ctrPosition.y - 5);
2022-11-26 08:47:35 -08:00
this._dot.setPosition(
2022-11-27 10:22:19 -08:00
startPosition.x + ctrPosition.x - 8,
startPosition.y + ctrPosition.y - 8,
2022-11-26 08:47:35 -08:00
);
}
}
private mouseMoveHandler(event: MouseEvent) {
const screen = this._workspace.getScreenManager();
const mousePosition = screen.getWorkspaceMousePosition(event);
// Update relatioship position ...
2022-11-27 10:22:19 -08:00
const topic =
this._pivotType === PivotType.Start
? this._relationship.getSourceTopic()
: this._relationship.getTargetTopic();
2022-11-29 18:57:39 -08:00
let relPos = Shape.calculateRelationShipPointCoordinates(topic, mousePosition);
2022-11-27 10:22:19 -08:00
const ctlPoint = { x: mousePosition.x - relPos.x, y: mousePosition.y - relPos.y };
this._moveRelHandler(ctlPoint);
2022-11-26 08:47:35 -08:00
// Update pivot ...
2022-11-27 10:22:19 -08:00
this._dot.setPosition(mousePosition.x - 8, mousePosition.y - 8);
2022-11-26 08:47:35 -08:00
2022-11-27 10:22:19 -08:00
// Update line ...
this._line.setTo(mousePosition.x - 5, mousePosition.y - 5);
2022-11-29 18:57:39 -08:00
relPos =
this._pivotType === PivotType.Start
? this._relationship.getLine().getFrom()
: this._relationship.getLine().getTo();
2022-11-27 10:22:19 -08:00
this._line.setFrom(relPos.x, relPos.y);
2022-11-26 08:47:35 -08:00
}
2022-11-27 10:22:19 -08:00
private mouseUpHandler() {
2022-11-26 08:47:35 -08:00
const screenManager = this.getWorkspace().getScreenManager();
screenManager.removeEvent('mousemove', this._mouseMoveHandler);
screenManager.removeEvent('mouseup', this._mouseUpHandler);
this._changeHander();
}
addToWorkspace(workspace: Workspace): void {
this._workspace = workspace;
workspace.append(this._line);
workspace.append(this._dot);
}
removeFromWorkspace(workspace: Workspace) {
// Hide all elements ...
this.setVisibility(false);
// Remove elements ...
workspace.removeChild(this._line);
workspace.removeChild(this._dot);
}
private getWorkspace(): Workspace {
return this._workspace!;
}
}
class RelationshipControlPoints {
// Visual element ...
private _pivotLines: [ControlPivotLine, ControlPivotLine];
private _relationship: Relationship;
private _relationshipLinePositions: [PositionType, PositionType];
constructor(relationship: Relationship) {
this._relationship = relationship;
const startControlLine = new ControlPivotLine(
PivotType.Start,
relationship,
2022-11-27 10:22:19 -08:00
(controlPointPosition) => {
2022-11-26 08:47:35 -08:00
const line = this._relationship.getLine();
line.setSrcControlPoint(controlPointPosition);
2022-11-27 10:22:19 -08:00
relationship.redraw();
2022-11-26 08:47:35 -08:00
},
() => {
const actionDispatcher = ActionDispatcher.getInstance();
actionDispatcher.moveControlPoint(this, PivotType.Start);
relationship.setOnFocus(true);
},
);
const endControlLine = new ControlPivotLine(
PivotType.End,
relationship,
2022-11-27 10:22:19 -08:00
(controlPointPosition) => {
2022-11-26 08:47:35 -08:00
const line = this._relationship.getLine();
line.setDestControlPoint(controlPointPosition);
2022-11-27 10:22:19 -08:00
relationship.redraw();
2022-11-26 08:47:35 -08:00
},
() => {
const actionDispatcher = ActionDispatcher.getInstance();
actionDispatcher.moveControlPoint(this, PivotType.End);
relationship.setOnFocus(true);
},
);
this._pivotLines = [startControlLine, endControlLine];
}
addToWorkspace(workspace: Workspace): void {
this._pivotLines.forEach((pivot) => workspace.append(pivot));
}
removeFromWorkspace(workspace: Workspace) {
this._pivotLines.forEach((pivot) => workspace.removeChild(pivot));
}
getRelationship() {
return this._relationship;
}
redraw() {
this._pivotLines.forEach((pivot) => pivot.redraw());
}
setVisibility(value: boolean) {
this._pivotLines.forEach((pivot) => pivot.setVisibility(value));
}
getControlPointPosition(pivotType: PivotType): PositionType {
return this._pivotLines[pivotType].getPosition();
}
getRelationshipPosition(index: number): PositionType {
return { ...this._relationshipLinePositions[index] };
}
}
export default RelationshipControlPoints;