254 lines
8.2 KiB
TypeScript
Raw Normal View History

2021-10-04 17:05:34 -07:00
/*
2021-12-25 14:39:34 -08:00
* Copyright [2021] [wisemapping]
2021-10-04 17:05:34 -07:00
*
* 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.
*/
2021-12-03 16:11:17 -08:00
import { $assert, $defined } from '@wisemapping/core-js';
import { Workspace as Workspace2D, ElementClass as Element2D } from '@wisemapping/web2d';
2022-01-08 17:08:26 -08:00
import ScreenManager from './ScreenManager';
2022-02-03 23:07:34 -08:00
import SizeType from './SizeType';
2021-10-04 17:05:34 -07:00
2021-12-03 10:58:25 -08:00
class Workspace {
2022-01-10 12:12:15 -08:00
private _zoom: number;
2022-01-10 12:12:15 -08:00
private _screenManager: ScreenManager;
2022-01-10 12:12:15 -08:00
private _isReadOnly: boolean;
2022-02-03 23:07:34 -08:00
private _containerSize: SizeType;
2022-01-10 12:12:15 -08:00
private _workspace: Workspace2D;
2022-01-10 12:12:15 -08:00
private _eventsEnabled: boolean;
2022-02-03 23:07:34 -08:00
private _visibleAreaSize: SizeType;
2022-01-08 17:08:26 -08:00
constructor(screenManager: ScreenManager, zoom: number, isReadOnly: boolean) {
2021-10-04 17:05:34 -07:00
// Create a suitable container ...
$assert(screenManager, 'Div container can not be null');
$assert(zoom, 'zoom container can not be null');
this._zoom = zoom;
this._screenManager = screenManager;
this._isReadOnly = isReadOnly;
2021-10-04 17:05:34 -07:00
const divContainer = screenManager.getContainer();
2022-01-10 10:52:11 -08:00
this._containerSize = {
width: Number.parseInt(divContainer.css('width'), 10),
height: Number.parseInt(divContainer.css('height'), 10),
};
2021-10-04 17:05:34 -07:00
// Initialize web2d workspace.
const workspace = this._createWorkspace();
this._workspace = workspace;
// Append to the workspace...
workspace.addItAsChildTo(divContainer);
// Register drag events ...
this._registerDragEvents();
this._eventsEnabled = true;
2022-01-10 10:52:11 -08:00
// Readjust if the window is resized ...
2022-02-03 23:07:34 -08:00
window.addEventListener('resize', () => {
2022-01-10 10:52:11 -08:00
this._adjustWorkspace();
});
this.setZoom(zoom, true);
}
2022-01-10 10:52:11 -08:00
private _adjustWorkspace(): void {
this.setZoom(this._zoom, false);
}
isReadOnly(): boolean {
return this._isReadOnly;
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-02-03 23:07:34 -08:00
private _createWorkspace(): Workspace2D {
2021-10-04 17:05:34 -07:00
// Initialize workspace ...
2022-01-10 10:52:11 -08:00
const browserVisibleSize = this._screenManager.getVisibleBrowserSize();
const coordOriginX = -(browserVisibleSize.width / 2);
const coordOriginY = -(browserVisibleSize.height / 2);
2021-10-04 17:05:34 -07:00
const workspaceProfile = {
2022-01-10 10:52:11 -08:00
width: `${this._containerSize.width}px`,
height: `${this._containerSize.height}px`,
coordSizeWidth: browserVisibleSize.width,
coordSizeHeight: browserVisibleSize.height,
2021-10-04 17:05:34 -07:00
coordOriginX,
coordOriginY,
fillColor: 'transparent',
strokeWidth: 0,
};
2021-12-19 08:31:29 -08:00
return new Workspace2D(workspaceProfile);
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-02-03 23:07:34 -08:00
append(shape: Element2D): void {
2021-10-04 17:05:34 -07:00
if ($defined(shape.addToWorkspace)) {
shape.addToWorkspace(this);
} else {
this._workspace.append(shape);
}
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-02-03 23:07:34 -08:00
removeChild(shape: Element2D): void {
2021-10-04 17:05:34 -07:00
// Element is a node, not a web2d element?
if ($defined(shape.removeFromWorkspace)) {
shape.removeFromWorkspace(this);
} else {
this._workspace.removeChild(shape);
}
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-02-09 21:04:12 -08:00
addEvent(type: string, listener: (event: Event) => void): void {
2021-10-04 17:05:34 -07:00
this._workspace.addEvent(type, listener);
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-02-09 21:04:12 -08:00
removeEvent(type: string, listener: (event: Event) => void): void {
2021-10-04 17:05:34 -07:00
$assert(type, 'type can not be null');
$assert(listener, 'listener can not be null');
this._workspace.removeEvent(type, listener);
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-02-03 23:07:34 -08:00
getSize(): SizeType {
2021-10-04 17:05:34 -07:00
return this._workspace.getCoordSize();
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
setZoom(zoom: number, center = false): void {
2021-10-04 17:05:34 -07:00
this._zoom = zoom;
const workspace = this._workspace;
2022-01-10 10:52:11 -08:00
const newVisibleAreaSize = this._screenManager.getVisibleBrowserSize();
2021-10-04 17:05:34 -07:00
// Update coord scale...
const newCoordWidth = zoom * this._containerSize.width;
2022-01-10 10:52:11 -08:00
const newCoordHeight = zoom * this._containerSize.height;
2021-10-04 17:05:34 -07:00
let coordOriginX: number;
let coordOriginY: number;
2021-10-04 17:05:34 -07:00
if (center) {
2022-01-10 10:52:11 -08:00
// Center and define a new center of coordinates ...
coordOriginX = -(newVisibleAreaSize.width / 2) * zoom;
coordOriginY = -(newVisibleAreaSize.height / 2) * zoom;
2021-10-04 17:05:34 -07:00
} else {
2022-01-10 10:52:11 -08:00
const oldCoordOrigin = workspace.getCoordOrigin();
// Next coordSize is always centered in the middle of the visible area ...
const newCoordOriginX = -(newVisibleAreaSize.width / 2) * zoom;
const newCoordOriginY = -(newVisibleAreaSize.height / 2) * zoom;
2021-10-04 17:05:34 -07:00
2022-01-10 10:52:11 -08:00
// Calculate the offset with the original center to ...
const oldCenterOriginX = -(this._visibleAreaSize.width / 2) * zoom;
const oldCenterOriginY = -(this._visibleAreaSize.height / 2) * zoom;
const offsetX = oldCoordOrigin.x - oldCenterOriginX;
const offsetY = oldCoordOrigin.y - oldCenterOriginY;
// Update to new coordinate ...
coordOriginX = Math.round(newCoordOriginX + offsetX);
coordOriginY = Math.round(newCoordOriginY + offsetY);
}
2022-01-10 10:52:11 -08:00
2021-10-04 17:05:34 -07:00
workspace.setCoordOrigin(coordOriginX, coordOriginY);
2022-01-10 10:52:11 -08:00
workspace.setCoordSize(newCoordWidth, newCoordHeight);
this._visibleAreaSize = newVisibleAreaSize;
2021-10-04 17:05:34 -07:00
// Update screen.
this._screenManager.setOffset(coordOriginX, coordOriginY);
this._screenManager.setScale(zoom);
// Some changes in the screen. Let's fire an update event...
this._screenManager.fireEvent('update');
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-01-08 17:08:26 -08:00
getScreenManager(): ScreenManager {
2021-10-04 17:05:34 -07:00
return this._screenManager;
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-01-08 17:08:26 -08:00
enableWorkspaceEvents(value: boolean) {
2021-10-04 17:05:34 -07:00
this._eventsEnabled = value;
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-01-08 17:08:26 -08:00
isWorkspaceEventsEnabled(): boolean {
2021-10-04 17:05:34 -07:00
return this._eventsEnabled;
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
getSVGElement() {
return this._workspace.getSVGElement();
2021-12-03 10:58:25 -08:00
}
2021-10-04 17:05:34 -07:00
2022-01-08 17:08:26 -08:00
private _registerDragEvents() {
2021-10-04 17:05:34 -07:00
const workspace = this._workspace;
const screenManager = this._screenManager;
const mWorkspace = this;
2022-02-09 21:04:12 -08:00
const mouseDownListener = function mouseDownListener(event: MouseEvent) {
2021-10-04 17:05:34 -07:00
if (!$defined(workspace._mouseMoveListener)) {
if (mWorkspace.isWorkspaceEventsEnabled()) {
mWorkspace.enableWorkspaceEvents(false);
const mouseDownPosition = screenManager.getWorkspaceMousePosition(event);
const originalCoordOrigin = workspace.getCoordOrigin();
let wasDragged = false;
2022-02-09 21:04:12 -08:00
workspace._mouseMoveListener = (mouseMoveEvent: MouseEvent) => {
const currentMousePosition = screenManager.getWorkspaceMousePosition(mouseMoveEvent);
2021-10-04 17:05:34 -07:00
const offsetX = currentMousePosition.x - mouseDownPosition.x;
const coordOriginX = -offsetX + originalCoordOrigin.x;
const offsetY = currentMousePosition.y - mouseDownPosition.y;
const coordOriginY = -offsetY + originalCoordOrigin.y;
workspace.setCoordOrigin(coordOriginX, coordOriginY);
// Change cursor.
2021-12-23 09:56:36 -08:00
window.document.body.style.cursor = 'move';
mouseMoveEvent.preventDefault();
2021-10-04 17:05:34 -07:00
// Fire drag event ...
screenManager.fireEvent('update');
wasDragged = true;
};
screenManager.addEvent('mousemove', workspace._mouseMoveListener);
// Register mouse up listeners ...
workspace._mouseUpListener = () => {
2021-10-04 17:05:34 -07:00
screenManager.removeEvent('mousemove', workspace._mouseMoveListener);
screenManager.removeEvent('mouseup', workspace._mouseUpListener);
workspace._mouseUpListener = null;
workspace._mouseMoveListener = null;
window.document.body.style.cursor = 'default';
// Update screen manager offset.
const coordOrigin = workspace.getCoordOrigin();
screenManager.setOffset(coordOrigin.x, coordOrigin.y);
mWorkspace.enableWorkspaceEvents(true);
if (!wasDragged) {
screenManager.fireEvent('click');
}
};
screenManager.addEvent('mouseup', workspace._mouseUpListener);
}
} else {
workspace._mouseUpListener();
}
};
screenManager.addEvent('mousedown', mouseDownListener);
2021-12-03 10:58:25 -08:00
}
}
2021-10-04 17:05:34 -07:00
export default Workspace;