UNPKG

@itwin/core-markup

Version:
181 lines • 6.64 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module MarkupApp */ import { Transform } from "@itwin/core-geometry"; import { Box, extend, G, Element as MarkupElement, Matrix, nodeOrNew, Rect, register, Text } from "@svgdotjs/svg.js"; import { MarkupApp } from "./Markup"; const OLDCOLOR = "Color"; /** this is the SVG.js way of adding methods to classes */ extend(MarkupElement, { forElementsOfGroup(fn) { const me = this; if (me instanceof G) me.each((i, children) => { const child = children[i]; if (child instanceof MarkupElement) fn(child); }, false); }, cloneMarkup() { const me = this; const cloned = me.clone(); cloned.node.removeAttribute("id"); cloned.resetColor(); return cloned; }, overrideColor(color) { const me = this; me.forElementsOfGroup((child) => child.overrideColor(color)); // Do children first, getComputedStyle will inherit from group for unspecified values... let oldColor = me.data(OLDCOLOR); if (undefined === oldColor) { const css = window.getComputedStyle(me.node); const colorOrNone = (c) => (c && c !== "none") ? c : "none"; oldColor = { fill: colorOrNone(css.fill), stroke: colorOrNone(css.stroke) }; me.data(OLDCOLOR, oldColor); } const toColor = (val) => (!val || val === "none") ? "none" : color; me.css({ fill: toColor(oldColor.fill), stroke: toColor(oldColor.stroke) }); }, resetColor() { const me = this; const oldColor = me.data(OLDCOLOR); if (undefined !== oldColor) me.css(oldColor).data(OLDCOLOR, null); // change to old color and remove data object me.forElementsOfGroup((child) => child.resetColor()); }, hilite() { const me = this; if (!me.inSelection) { me.overrideColor(MarkupApp.props.hilite.color); me.inSelection = true; } }, unHilite() { const me = this; if (me.inSelection) { me.resetColor(); me.inSelection = undefined; } }, flash() { const me = this; if (!me.inSelection) me.overrideColor(MarkupApp.props.hilite.flash); }, unFlash() { const me = this; if (!me.inSelection) me.resetColor(); }, markupStretch(w, h, x, y, _mtx) { const me = this; me.size(w, h).move(x, y); }, isChildOf(svg) { const parent = this.parent(); return (parent === svg) ? true : (parent instanceof MarkupElement) ? parent.isChildOf(svg) : false; }, getChildOrGroupOf(svg) { const me = this; const parents = me.parents(svg.parent()); if (0 === parents.length || parents[parents.length - 1].node !== svg.node) return undefined; if (parents.length > 1) { for (let index = parents.length - 2; index >= 0; --index) if (parents[index] instanceof G || parents[index] instanceof Text) return parents[index]; } return me; }, getNpcToVp() { const me = this; const bb = me.bbox(); return new Matrix().scaleO(bb.w, bb.h).translateO(bb.x, bb.y).lmultiplyO(me.matrixify()); }, getOutline(expand) { const me = this; const box = me.bbox(); if (expand === undefined) expand = 0; return new Rect().move(box.x - expand, box.y - expand).size(box.w + (expand * 2), box.h + (expand * 2)).transform(me.matrixify()); }, }); extend(G, { markupStretch(_w, _h, _x, _y, mtx) { this.attr("transform", mtx); }, }); extend(Text, { getFontSize() { const me = this; return parseFloat(window.getComputedStyle(me.node).fontSize); }, markupStretch(_w, _h, _x, _y, mtx) { this.attr("transform", mtx); }, getMarkup() { const node = this.node; let text = ""; node.childNodes.forEach((child) => { if (child.nodeName === "tspan" || child.nodeName === "#text") { if (text.length !== 0) text += "\n"; text += child.textContent; } }); return text; }, createMarkup(val, spacing) { spacing = spacing ? spacing : 1; const me = this; me.clear(); if (val === "") return; const lines = val.split("\n"); me.plain(lines[0]); const x = me.attr("x"); me.build(true); for (let i = 1; i < lines.length; ++i) { const tspan = me.tspan(lines[i]); tspan.dy(spacing); tspan.x(x); } me.build(false); me.dom = {}; }, // override for Text so that empty text will return a size getOutline(expand) { const me = this; const node = me.node; const content = node.textContent; if (content !== null && content.length > 0) return MarkupElement.prototype.getOutline.call(me, expand); node.textContent = "M"; const outline = MarkupElement.prototype.getOutline.call(me, expand); node.textContent = content; return outline; }, writeDataToDom() { const me = this; const dom = me.dom; // strip off useless "leading" data me.dom = {}; MarkupElement.prototype.writeDataToDom.call(me); me.dom = dom; return me; }, }); extend(Matrix, { toIModelTransform() { const m = this; return Transform.createRowValues(m.a, m.c, 0, m.e, m.b, m.d, 0, m.f, 0, 0, 1, 0); }, fromIModelTransform(t) { const m = this; const o = t.origin; const mtx = t.matrix; m.a = mtx.coffs[0]; m.b = mtx.coffs[3]; m.c = mtx.coffs[1]; m.d = mtx.coffs[4]; m.e = o.x; m.f = o.y; return this; }, }); /** Dummy class so a <title> inside a <g> will work. * @internal */ export class Title extends MarkupElement { constructor(node) { super(nodeOrNew("title", node)); } scale() { return this; } size() { return this; } move() { return this; } dmove() { return this; } bbox() { return new Box(); } screenCTM() { return new Matrix(); } } register(Title, "Title"); /** only for tests * @internal */ export function initSvgExt() { } //# sourceMappingURL=SvgJsExt.js.map