@itwin/core-markup
Version:
iTwin.js markup package
181 lines • 6.64 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* 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