mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-06-03 01:04:31 +02:00
278 lines
7.9 KiB
TypeScript
278 lines
7.9 KiB
TypeScript
/* eslint-disable no-unused-vars */
|
|
/* eslint-disable class-methods-use-this */
|
|
/*
|
|
* 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.
|
|
*/
|
|
import { $assert, $defined } from '@wisemapping/core-js';
|
|
import SizeType from '../../SizeType';
|
|
import EventUtils from '../utils/EventUtils';
|
|
|
|
class ElementPeer {
|
|
_native: SVGElement;
|
|
private _parent: ElementPeer | null;
|
|
protected _size: SizeType;
|
|
private _changeListeners: {};
|
|
private __handlers: Map<string, any>;
|
|
private _children: ElementPeer[];
|
|
private _stokeStyle: string | null;
|
|
|
|
constructor(svgElement: SVGElement) {
|
|
this._native = svgElement;
|
|
this._size = { width: 1, height: 1 };
|
|
this._changeListeners = {};
|
|
// http://support.adobe.com/devsup/devsup.nsf/docs/50493.htm
|
|
|
|
// __handlers stores handlers references so they can be removed afterwards
|
|
this.__handlers = new Map();
|
|
this._children = [];
|
|
this._parent = null;
|
|
this._stokeStyle = null;
|
|
}
|
|
|
|
setChildren(children: ElementPeer[]): void {
|
|
this._children = children;
|
|
}
|
|
|
|
getChildren(): ElementPeer[] {
|
|
return this._children;
|
|
}
|
|
|
|
getParent(): ElementPeer | null {
|
|
return this._parent;
|
|
}
|
|
|
|
setParent(parent: ElementPeer | null): void {
|
|
this._parent = parent;
|
|
}
|
|
|
|
append(elementPeer: ElementPeer): void {
|
|
// Store parent and child relationship.
|
|
elementPeer.setParent(this);
|
|
const children = this.getChildren();
|
|
children.push(elementPeer);
|
|
|
|
// Append element as a child.
|
|
this._native.appendChild(elementPeer._native);
|
|
|
|
// Broadcast events ...
|
|
EventUtils.broadcastChangeEvent(this, 'strokeStyle');
|
|
}
|
|
|
|
removeChild(elementPeer: ElementPeer): void {
|
|
// Store parent and child relationship.
|
|
elementPeer.setParent(null);
|
|
let children = this.getChildren();
|
|
|
|
// Remove from children array ...
|
|
const oldLength = children.length;
|
|
|
|
children = children.filter((c) => c !== elementPeer);
|
|
this.setChildren(children);
|
|
|
|
$assert(children.length < oldLength, `element could not be removed:${elementPeer}`);
|
|
|
|
// Append element as a child.
|
|
this._native.removeChild(elementPeer._native);
|
|
}
|
|
|
|
/**
|
|
* http://www.w3.org/TR/DOM-Level-3-Events/events.html
|
|
* http://developer.mozilla.org/en/docs/addEvent
|
|
*/
|
|
addEvent(type: string, listener) {
|
|
// wrap it so it can be ~backward compatible with jQuery.trigger
|
|
const wrappedListener = (e) => listener(e, e.detail);
|
|
this.__handlers.set(listener, wrappedListener);
|
|
this._native.addEventListener(type, wrappedListener);
|
|
}
|
|
|
|
trigger(type: string, event) {
|
|
// TODO: check this for correctness and for real jQuery.trigger replacement
|
|
this._native.dispatchEvent(new CustomEvent(type, { detail: event }));
|
|
}
|
|
|
|
removeEvent(type: string, listener) {
|
|
this._native.removeEventListener(type, this.__handlers.get(listener));
|
|
this.__handlers.delete(listener);
|
|
}
|
|
|
|
setSize(width: number, height: number): void {
|
|
if ($defined(width) && this._size.width !== width) {
|
|
this._size.width = width;
|
|
this._native.setAttribute('width', width.toFixed(0));
|
|
}
|
|
|
|
if ($defined(height) && this._size.height !== height) {
|
|
this._size.height = height;
|
|
this._native.setAttribute('height', height.toFixed(0));
|
|
}
|
|
|
|
EventUtils.broadcastChangeEvent(this, 'strokeStyle');
|
|
}
|
|
|
|
getSize(): SizeType {
|
|
return { width: this._size.width, height: this._size.height };
|
|
}
|
|
|
|
setFill(color: string | null, opacity?: number | null) {
|
|
if (color) {
|
|
this._native.setAttribute('fill', color);
|
|
}
|
|
if ($defined(opacity)) {
|
|
this._native.setAttribute('fill-opacity', String(opacity));
|
|
}
|
|
}
|
|
|
|
getFill() {
|
|
const color = this._native.getAttribute('fill');
|
|
const opacity = this._native.getAttribute('fill-opacity');
|
|
return { color, opacity: Number(opacity) };
|
|
}
|
|
|
|
getStroke() {
|
|
const stoke = this._native;
|
|
const color = stoke.getAttribute('stroke');
|
|
const dashstyle = this._stokeStyle;
|
|
const opacity = stoke.getAttribute('stroke-opacity');
|
|
const width = stoke.getAttribute('stroke-width');
|
|
return {
|
|
color,
|
|
style: dashstyle,
|
|
opacity,
|
|
width,
|
|
};
|
|
}
|
|
|
|
setStroke(width: number | null, style?: string | null, color?: string | null, opacity?: number) {
|
|
if ($defined(width)) {
|
|
this._native.setAttribute('stroke-width', `${width}`);
|
|
}
|
|
|
|
if (color) {
|
|
this._native.setAttribute('stroke', color);
|
|
}
|
|
|
|
if (style) {
|
|
this._stokeStyle = style;
|
|
switch (style) {
|
|
case 'dash':
|
|
this._native.setAttribute('stroke-dasharray', '5 5');
|
|
this._native.setAttribute('stroke-linecap', '');
|
|
break;
|
|
case 'dot':
|
|
this._native.setAttribute('stroke-dasharray', '1 8');
|
|
this._native.setAttribute('stroke-linecap', 'round');
|
|
break;
|
|
case 'dashdot':
|
|
case 'longdash':
|
|
this._native.setAttribute('stroke-dasharray', '10 5 2');
|
|
this._native.setAttribute('stroke-linecap', 'round');
|
|
break;
|
|
case 'solid':
|
|
this._native.setAttribute('stroke-dasharray', '');
|
|
this._native.setAttribute('stroke-linecap', '');
|
|
break;
|
|
default:
|
|
throw new Error(`Unsupported style: ${style}`);
|
|
}
|
|
}
|
|
|
|
if ($defined(opacity)) {
|
|
this._native.setAttribute('stroke-opacity', String(opacity));
|
|
}
|
|
}
|
|
|
|
setVisibility(value: boolean, fade?: number) {
|
|
this._native.setAttribute('visibility', value ? 'visible' : 'hidden');
|
|
this._native.style.opacity = String(value ? 1 : 0);
|
|
if (fade) {
|
|
this._native.style.transition = `visibility ${fade}ms, opacity ${fade}ms`;
|
|
} else {
|
|
this._native.style.transition = '';
|
|
}
|
|
}
|
|
|
|
isVisible(): boolean {
|
|
const visibility = this._native.getAttribute('visibility');
|
|
return !(visibility === 'hidden');
|
|
}
|
|
|
|
updateStrokeStyle() {
|
|
const strokeStyle = this._stokeStyle;
|
|
if (this.getParent()) {
|
|
if (strokeStyle && strokeStyle !== 'solid') {
|
|
this.setStroke(null, strokeStyle);
|
|
}
|
|
}
|
|
}
|
|
|
|
attachChangeEventListener(type, listener) {
|
|
const listeners = this.getChangeEventListeners(type);
|
|
if (!$defined(listener)) {
|
|
throw new Error('Listener can not be null');
|
|
}
|
|
listeners.push(listener);
|
|
}
|
|
|
|
getChangeEventListeners(type) {
|
|
let listeners = this._changeListeners[type];
|
|
if (!$defined(listeners)) {
|
|
listeners = [];
|
|
this._changeListeners[type] = listeners;
|
|
}
|
|
return listeners;
|
|
}
|
|
|
|
/**
|
|
* Move element to the front
|
|
*/
|
|
moveToFront() {
|
|
if (!this._native.parentNode) {
|
|
throw new Error('node not connected to parent');
|
|
}
|
|
this._native.parentNode.appendChild(this._native);
|
|
}
|
|
|
|
/**
|
|
* Move element to the back
|
|
*/
|
|
moveToBack() {
|
|
if (!this._native.parentNode) {
|
|
throw new Error('node not connected to parent');
|
|
}
|
|
this._native.parentNode.insertBefore(this._native, this._native.parentNode.firstChild);
|
|
}
|
|
|
|
setCursor(type: string) {
|
|
this._native.style.cursor = type;
|
|
}
|
|
|
|
static stokeStyleToStrokDasharray() {
|
|
return {
|
|
solid: [],
|
|
dot: [1, 3],
|
|
dash: [4, 3],
|
|
longdash: [10, 2],
|
|
dashdot: [5, 3, 1, 3],
|
|
};
|
|
}
|
|
protected static svgNamespace = 'http://www.w3.org/2000/svg';
|
|
protected static linkNamespace = 'http://www.w3.org/1999/xlink';
|
|
}
|
|
|
|
export default ElementPeer;
|