//namespace GraphTableSVG { import { ZVertex } from "./z_vertex" import { ZTextBox } from "./z_textbox" import { ZCalloutAttributes } from "./z_callout" import { ShapeObjectType, ConnectorType, msoDashStyle, VBAShapeType, DataName } from "../common/enums"; import * as AttributeNames from "../common/attribute_names" import * as StyleNames from "../common/style_names" import * as DefaultClassNames from "../common/default_class_names" import { Rectangle, VLine, round100 } from "../common/vline" import * as CSS from "../html/css" import * as GOptions from "./z_options" import * as ElementExtension from "../interfaces/element_extension" import * as SVGTextExtension from "../interfaces/svg_text_extension" export class ZAbstractEllipseCircle extends ZTextBox { get rx(): number { return 5; } get ry(): number { return 5; } /** 頂点の幅を返します。 */ get width(): number { return this.rx * 2; } /** 頂点の高さを返します。 */ get height(): number { return this.ry * 2; } public constructor(svgbox: SVGElement | string) { super(svgbox); } /** テキストの領域を返します。 */ /* get innerRectangle(): Rectangle { const rect = new Rectangle(); const textRect = SVGTextExtension.getVirtualRegion(this.svgText); //const rect = new Rectangle(); rect.width = this.width; rect.height = this.height; rect.x = -this.rx; rect.y = -this.ry; return rect; } */ /* public getPosition(type: ConnectorType) : [number, number]{ const centerX = (Math.sqrt(2) / 2) * this.rx; const centerY = (Math.sqrt(2) / 2) * this.ry; switch (type) { case ConnectorType.Top: return [this.cx, this.cy - this.ry]; case ConnectorType.TopRight: return [this.cx + centerX, this.cy - centerY]; case ConnectorType.Right: return [this.cx + this.rx, this.cy]; case ConnectorType.BottomRight: return [this.cx + centerX, this.cy + centerY]; case ConnectorType.Bottom: return [this.cx, this.cy + this.ry]; case ConnectorType.BottomLeft: return [this.cx - centerX, this.cy + centerY]; case ConnectorType.Left: return [this.cx - this.rx, this.cy]; case ConnectorType.TopLeft: return [this.cx - centerX, this.cy - centerY]; default: return [this.cx, this.cy - this.ry]; } } */ public getContactPosition(type: ConnectorType, x: number, y: number): [number, number] { const centerX = (Math.sqrt(2) / 2) * this.rx; const centerY = (Math.sqrt(2) / 2) * this.ry; switch (type) { case ConnectorType.Top: return [this.cx, this.cy - this.ry]; case ConnectorType.TopRight: return [this.cx + centerX, this.cy - centerY]; case ConnectorType.Right: return [this.cx + this.rx, this.cy]; case ConnectorType.BottomRight: return [this.cx + centerX, this.cy + centerY]; case ConnectorType.Bottom: return [this.cx, this.cy + this.ry]; case ConnectorType.BottomLeft: return [this.cx - centerX, this.cy + centerY]; case ConnectorType.Left: return [this.cx - this.rx, this.cy]; case ConnectorType.TopLeft: return [this.cx - centerX, this.cy - centerY]; default: const autoType = this.getContactAutoPosition(x, y); return this.getContactPosition(autoType, x, y); } } public getContactAutoPosition(x: number, y: number): ConnectorType { const centerX = (Math.sqrt(2) / 2) * this.rx; const centerY = (Math.sqrt(2) / 2) * this.ry; const lineTop = new VLine(x, y, this.cx, this.cy - centerY); const lineTopRight = new VLine(x, y, this.cx + centerX, this.cy - centerY); const lineRight = new VLine(x, y, this.cx + centerX, this.cy); const lineBottomRight = new VLine(x, y, this.cx + centerX, this.cy + centerY); const lineBottom = new VLine(x, y, this.cx, this.cy + centerY); const lineBottomLeft = new VLine(x, y, this.cx - centerX, this.cy + centerY); const lineLeft = new VLine(x, y, this.cx - centerX, this.cy); const lineTopLeft = new VLine(x, y, this.cx - centerX, this.cy - centerY); const arr: [number, ConnectorType][] = [[lineTop.distance(), ConnectorType.Top], [lineTopRight.distance(), ConnectorType.TopRight], [lineRight.distance(), ConnectorType.Right], [lineBottomRight.distance(), ConnectorType.BottomRight], [lineBottom.distance(), ConnectorType.Bottom], [lineBottomLeft.distance(), ConnectorType.BottomLeft], [lineLeft.distance(), ConnectorType.Left], [lineTopLeft.distance(), ConnectorType.TopLeft]]; const [minDis, minDir] = arr.reduce(([a, b], [c, d]) => { if (a < c) { return [a, b]; } else { return [c, d]; } }) return minDir; /* const line2 = new VLine(this.x, this.y, this.x + r, this.y - r); const b1 = line1.contains(x, y); const b2 = line2.contains(x, y); if (b1) { if (b2) { return ConnectorType.Top; } else { return ConnectorType.Right; } } else { if (b2) { return ConnectorType.Left; } else { return ConnectorType.Bottom; } } */ } public get surfaceRegion(): Rectangle { const x = -this.rx; const y = -this.ry; const w = this.width; const h = this.height return new Rectangle(x, y, w, h); } } export class ZEllipse extends ZAbstractEllipseCircle { public get svgEllipse(): SVGEllipseElement { return this._svgSurface; } public constructor(svgbox: SVGElement | string) { super(svgbox); if (this.type == ShapeObjectType.Ellipse) this.firstFunctionAfterInitialized(); } protected createSurface(svgbox: SVGElement): void { //if(option.surfaceClass === undefined) option.surfaceClass = DefaultClassNames.defaultSurfaceClass; this._svgSurface = ZEllipse.createEllipse(this.svgGroup, DefaultClassNames.defaultSurfaceClass, undefined); this.svgGroup.insertBefore(this.svgEllipse, this.svgText); } private static createEllipse(parent: SVGElement, className: string | GOptions.surfaceClassCSS, style: string | GOptions.surfaceClassCSS | undefined): SVGEllipseElement { const circle = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse'); circle.setAttribute(AttributeNames.dataNameAttribute, DataName.Surface); parent.appendChild(circle); GOptions.setClassAndStyle(circle, className, style); circle.rx.baseVal.value = AttributeNames.defaultCircleRadius; circle.ry.baseVal.value = AttributeNames.defaultCircleRadius; const radius = ElementExtension.getPropertyStyleNumberValue(circle, StyleNames.defaultRadius, null); if (radius != null) { circle.rx.baseVal.value = radius; circle.ry.baseVal.value = radius; } circle.cx.baseVal.value = 0; circle.cy.baseVal.value = 0; return circle; } /* public static constructAttributes(e: Element, removeAttributes: boolean = false, output: GOptions.ZTextBoxAttributes = {}): GOptions.ZTextBoxAttributes { ZTextBox.constructAttributes(e, removeAttributes, output); return output; } */ get width(): number { return round100(this.svgEllipse.rx.baseVal.value * 2); } get height(): number { return round100(this.svgEllipse.ry.baseVal.value * 2); } set width(value: number) { const _rx = value / 2; if (this.width != value) ElementExtension.setAttributeNumber(this.svgEllipse, "rx", _rx); } set height(value: number) { const _ry = value / 2; if (this.height != value) ElementExtension.setAttributeNumber(this.svgEllipse, "ry", _ry); //this.svgEllipse.setAttribute("ry", _ry.toString()); } get rx(): number { return round100(this.svgEllipse.rx.baseVal.value); } get ry(): number { return round100(this.svgEllipse.ry.baseVal.value); } public get type(): ShapeObjectType { return ShapeObjectType.Ellipse; } /* public getLocation(type: ConnectorPosition, x: number, y: number): [number, number] { const centerX = (Math.sqrt(2) / 2) * this.svgEllipse.rx.baseVal.value; const centerY = (Math.sqrt(2) / 2) * this.svgEllipse.ry.baseVal.value; switch (type) { case ConnectorType.Top: return [this.cx, this.cy - this.ry]; case ConnectorType.TopRight: return [this.cx + centerX, this.cy - centerY]; case ConnectorType.Right: return [this.cx + this.rx, this.cy]; case ConnectorType.BottomRight: return [this.cx + centerX, this.cy + centerY]; case ConnectorType.Bottom: return [this.cx, this.cy + this.ry]; case ConnectorType.BottomLeft: return [this.cx - centerX, this.cy + centerY]; case ConnectorType.Left: return [this.cx - this.rx, this.cy]; case ConnectorType.TopLeft: return [this.cx - centerX, this.cy - centerY]; default: const autoType = this.getAutoPosition(x, y); return this.getLocation(autoType, x, y); } } protected getAutoPosition(x: number, y: number): ConnectorPosition { const radius = this.rx; const r = (Math.sqrt(2) / 2) * radius; const line1 = new VLine(this.x, this.y, this.x + r, this.y + r); const line2 = new VLine(this.x, this.y, this.x + r, this.y - r); const b1 = line1.contains(x, y); const b2 = line2.contains(x, y); if (b1) { if (b2) { return ConnectorType.Top; } else { return ConnectorType.Right; } } else { if (b2) { return ConnectorType.Left; } else { return ConnectorType.Bottom; } } } */ public get shape(): VBAShapeType { return VBAShapeType.Oval; } /* public createVBACode(id: number): string[] { const r: string[] = []; const left = this.cx - (this.width / 2); const top = this.cy - (this.height / 2); const surface = this.surface; const shape = surface instanceof SVGRectElement ? "msoShapeRectangle" : "msoShapeOval"; r.push(`Sub create${id}(createdSlide As slide)`); r.push(` Dim shapes_ As Shapes : Set shapes_ = createdSlide.Shapes`); r.push(` Dim obj As Shape`); r.push(` Set obj = shapes_.AddShape(${shape}, ${left}, ${top}, ${this.width}, ${this.height})`); const backColor = VBATranslateFunctions.colorToVBA(surface.getPropertyStyleValueWithDefault("fill", "gray")); const lineColor = VBATranslateFunctions.colorToVBA(surface.getPropertyStyleValueWithDefault("stroke", "gray")); const lineType = GraphTableSVG.msoDashStyle.getLineType(surface); const strokeWidth = parseInt(surface.getPropertyStyleValueWithDefault("stroke-width", "4")); const visible = surface.getPropertyStyleValueWithDefault("visibility", "visible") == "visible" ? "msoTrue" : "msoFalse"; r.push(` Call EditVertexShape(obj, "${this.objectID}", ${visible}, ${backColor})`); r.push(` Call EditLine(obj.Line, ${lineColor}, ${lineType}, ${0}, ${strokeWidth}, ${visible})`); const fontSize = parseInt(this.svgText.getPropertyStyleValueWithDefault("font-size", "24")); const fontFamily = VBATranslateFunctions.ToVBAFont(this.svgText.getPropertyStyleValueWithDefault("font-family", "MS PGothic")); const fontBold = VBATranslateFunctions.ToFontBold(this.svgText.getPropertyStyleValueWithDefault("font-weight", "none")); r.push(` Call EditTextFrame(obj.TextFrame, ${0}, ${0}, ${0}, ${0}, false, ppAutoSizeNone)`); VBATranslateFunctions.TranslateSVGTextElement2(this.svgText, `obj.TextFrame.TextRange`).forEach((v)=>r.push(v)); //sub.push(` Call EditTextRange(nodes(${i}).TextFrame.TextRange, ${VBATranslateFunctions.createStringFunction(text)}, ${0}, ${0}, ${VBATranslateFunctions.colorToVBA(color)})`); r.push(` Call EditTextEffect(obj.TextEffect, ${fontSize}, "${fontFamily}")`); r.push(`End Sub`); return r; } */ } /* export type EllipseAttributes = TextBoxShapeAttributes & { speakerX? : number, speakerY? : number, } */ //}