sprotty
Version:
A next-gen framework for graphical views
178 lines • 6.74 kB
JavaScript
;
/********************************************************************************
* Copyright (c) 2017-2018 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SShapeElementImpl = exports.findChildrenAtPosition = exports.getAbsoluteClientBounds = exports.getAbsoluteBounds = exports.isAlignable = exports.isSizeable = exports.isLayoutableChild = exports.isLayoutContainer = exports.isBoundsAware = exports.alignFeature = exports.layoutableChildFeature = exports.layoutContainerFeature = exports.boundsFeature = void 0;
const geometry_1 = require("sprotty-protocol/lib/utils/geometry");
const smodel_1 = require("../../base/model/smodel");
const smodel_utils_1 = require("../../base/model/smodel-utils");
const browser_1 = require("../../utils/browser");
exports.boundsFeature = Symbol('boundsFeature');
exports.layoutContainerFeature = Symbol('layoutContainerFeature');
exports.layoutableChildFeature = Symbol('layoutableChildFeature');
exports.alignFeature = Symbol('alignFeature');
function isBoundsAware(element) {
return 'bounds' in element;
}
exports.isBoundsAware = isBoundsAware;
function isLayoutContainer(element) {
return isBoundsAware(element)
&& element.hasFeature(exports.layoutContainerFeature)
&& 'layout' in element;
}
exports.isLayoutContainer = isLayoutContainer;
function isLayoutableChild(element) {
return isBoundsAware(element)
&& element.hasFeature(exports.layoutableChildFeature);
}
exports.isLayoutableChild = isLayoutableChild;
function isSizeable(element) {
return element.hasFeature(exports.boundsFeature) && isBoundsAware(element);
}
exports.isSizeable = isSizeable;
function isAlignable(element) {
return element.hasFeature(exports.alignFeature)
&& 'alignment' in element;
}
exports.isAlignable = isAlignable;
function getAbsoluteBounds(element) {
const boundsAware = (0, smodel_utils_1.findParentByFeature)(element, isBoundsAware);
if (boundsAware !== undefined) {
let bounds = boundsAware.bounds;
let current = boundsAware;
while (current instanceof smodel_1.SChildElementImpl) {
const parent = current.parent;
bounds = parent.localToParent(bounds);
current = parent;
}
return bounds;
}
else if (element instanceof smodel_1.SModelRootImpl) {
const canvasBounds = element.canvasBounds;
return { x: 0, y: 0, width: canvasBounds.width, height: canvasBounds.height };
}
else {
return geometry_1.Bounds.EMPTY;
}
}
exports.getAbsoluteBounds = getAbsoluteBounds;
/**
* Returns the "client-absolute" bounds of the specified `element`.
*
* The client-absolute bounds are relative to the entire browser page.
*
* @param element The element to get the bounds for.
* @param domHelper The dom helper to obtain the SVG element's id.
* @param viewerOptions The viewer options to obtain sprotty's container div id.
*/
function getAbsoluteClientBounds(element, domHelper, viewerOptions) {
let x = 0;
let y = 0;
let width = 0;
let height = 0;
const svgElementId = domHelper.createUniqueDOMElementId(element);
const svgElement = document.getElementById(svgElementId);
if (svgElement) {
const rect = svgElement.getBoundingClientRect();
const scroll = (0, browser_1.getWindowScroll)();
x = rect.left + scroll.x;
y = rect.top + scroll.y;
width = rect.width;
height = rect.height;
}
let container = document.getElementById(viewerOptions.baseDiv);
if (container) {
while (container.offsetParent instanceof HTMLElement
&& (container = container.offsetParent)) {
x -= container.offsetLeft;
y -= container.offsetTop;
}
}
return { x, y, width, height };
}
exports.getAbsoluteClientBounds = getAbsoluteClientBounds;
function findChildrenAtPosition(parent, point) {
const matches = [];
doFindChildrenAtPosition(parent, point, matches);
return matches;
}
exports.findChildrenAtPosition = findChildrenAtPosition;
function doFindChildrenAtPosition(parent, point, matches) {
parent.children.forEach(child => {
if (isBoundsAware(child) && geometry_1.Bounds.includes(child.bounds, point))
matches.push(child);
if (child instanceof smodel_1.SParentElementImpl) {
const newPoint = child.parentToLocal(point);
doFindChildrenAtPosition(child, newPoint, matches);
}
});
}
/**
* Abstract class for elements with a position and a size.
*/
class SShapeElementImpl extends smodel_1.SChildElementImpl {
constructor() {
super(...arguments);
this.position = geometry_1.Point.ORIGIN;
this.size = geometry_1.Dimension.EMPTY;
}
get bounds() {
return {
x: this.position.x,
y: this.position.y,
width: this.size.width,
height: this.size.height
};
}
set bounds(newBounds) {
this.position = {
x: newBounds.x,
y: newBounds.y
};
this.size = {
width: newBounds.width,
height: newBounds.height
};
}
localToParent(point) {
const result = {
x: point.x + this.position.x,
y: point.y + this.position.y,
width: -1,
height: -1
};
if ((0, geometry_1.isBounds)(point)) {
result.width = point.width;
result.height = point.height;
}
return result;
}
parentToLocal(point) {
const result = {
x: point.x - this.position.x,
y: point.y - this.position.y,
width: -1,
height: -1
};
if ((0, geometry_1.isBounds)(point)) {
result.width = point.width;
result.height = point.height;
}
return result;
}
}
exports.SShapeElementImpl = SShapeElementImpl;
//# sourceMappingURL=model.js.map