0dc2548d0b
* Optimize simulator for light mode. * Add user-select none.
141 lines
4.2 KiB
TypeScript
141 lines
4.2 KiB
TypeScript
namespace pxsim.visuals {
|
|
export function normalizeId(prefix: string, svgId: string) {
|
|
return `${prefix}-${svgId}`;
|
|
}
|
|
|
|
export function normalizeXml(prefix: string, xml: string): string {
|
|
xml = xml.replace(/id=\"(.*?)\"/g, (m: string, id: string) => {
|
|
return `id="${normalizeId(prefix, id)}"`;
|
|
});
|
|
xml = xml.replace(/url\(#(.*?)\)/g, (m: string, id: string) => {
|
|
return `url(#${normalizeId(prefix, id)})`;
|
|
});
|
|
xml = xml.replace(/xlink:href=\"#(.*?)\"/g, (m: string, id: string) => {
|
|
return `xlink:href="#${normalizeId(prefix, id)}"`;
|
|
});
|
|
return xml;
|
|
}
|
|
|
|
export class ModuleView extends View implements LayoutElement {
|
|
protected content: SVGSVGElement;
|
|
|
|
protected controlShown: boolean;
|
|
|
|
protected opacity: number;
|
|
|
|
constructor(protected xml: string, protected prefix: string, protected id: NodeType, protected port: NodeType) {
|
|
super();
|
|
this.xml = normalizeXml(this.prefix, xml);
|
|
}
|
|
|
|
private normalizeXml(xml: string) {
|
|
return pxsim.visuals.normalizeXml(this.prefix, xml);
|
|
}
|
|
|
|
protected normalizeId(svgId: string) {
|
|
return `${this.prefix}-${svgId}`;
|
|
}
|
|
|
|
public getId() {
|
|
return this.id;
|
|
}
|
|
|
|
public getPort() {
|
|
return this.port;
|
|
}
|
|
|
|
public getPaddingRatio() {
|
|
return 0;
|
|
}
|
|
|
|
public getWiringRatio() {
|
|
return 0.5;
|
|
}
|
|
|
|
protected buildDom(): SVGElement {
|
|
this.content = svg.parseString(this.xml);
|
|
this.buildDomCore();
|
|
if (pxsim.inLightMode()) this.optimizeForLightMode();
|
|
this.attachEvents();
|
|
if (this.hasClick())
|
|
this.content.style.cursor = "pointer";
|
|
return this.content;
|
|
}
|
|
|
|
protected buildDomCore() {
|
|
|
|
}
|
|
|
|
protected optimizeForLightMode() {
|
|
|
|
}
|
|
|
|
public getInnerHeight() {
|
|
if (!this.content) {
|
|
return 0;
|
|
}
|
|
if (!this.content.hasAttribute("viewBox")) {
|
|
return parseFloat(this.content.getAttribute("height"));
|
|
}
|
|
return parseFloat(this.content.getAttribute("viewBox").split(" ")[3]);
|
|
}
|
|
|
|
public getInnerWidth() {
|
|
if (!this.content) {
|
|
return 0;
|
|
}
|
|
if (!this.content.hasAttribute("viewBox")) {
|
|
return parseFloat(this.content.getAttribute("width"));
|
|
}
|
|
return parseFloat(this.content.getAttribute("viewBox").split(" ")[2]);
|
|
}
|
|
|
|
public attachEvents() {
|
|
}
|
|
|
|
public resize(width: number, height: number) {
|
|
super.resize(width, height);
|
|
this.updateDimensions(width, height);
|
|
}
|
|
|
|
private updateDimensions(width: number, height: number) {
|
|
if (this.content) {
|
|
const currentWidth = this.getInnerWidth();
|
|
const currentHeight = this.getInnerHeight();
|
|
const newHeight = currentHeight / currentWidth * width;
|
|
const newWidth = currentWidth / currentHeight * height;
|
|
this.content.setAttribute('width', `${width}`);
|
|
this.content.setAttribute('height', `${newHeight}`);
|
|
}
|
|
}
|
|
|
|
public hasClick() {
|
|
return true;
|
|
}
|
|
|
|
public setSelected(selected: boolean) {
|
|
super.setSelected(selected);
|
|
this.updateOpacity();
|
|
}
|
|
|
|
public updateState() {
|
|
this.updateOpacity();
|
|
}
|
|
|
|
protected updateOpacity() {
|
|
if (this.rendered) {
|
|
const opacity = this.selected ? 0.2 : 1;
|
|
if (this.hasClick() && this.opacity != opacity) {
|
|
this.opacity = opacity;
|
|
this.setOpacity(this.opacity);
|
|
if (this.selected) this.content.style.cursor = "";
|
|
else this.content.style.cursor = "pointer";
|
|
}
|
|
}
|
|
}
|
|
|
|
protected setOpacity(opacity: number) {
|
|
this.element.setAttribute("opacity", `${opacity}`);
|
|
}
|
|
}
|
|
} |