UNPKG

jsroot

Version:
145 lines (116 loc) 4.23 kB
import { BIT } from '../core.mjs'; import { DrawOptions } from '../base/BasePainter.mjs'; import { ObjectPainter } from '../base/ObjectPainter.mjs'; import { ensureTCanvas } from '../gpad/TCanvasPainter.mjs'; import { addMoveHandler } from '../gui/utils.mjs'; import { assignContextMenu } from '../gui/menu.mjs'; const kLineNDC = BIT(14); /** * @summary Painter for TLine class * @private */ class TLinePainter extends ObjectPainter { #side; // side which is interactively moved /** @summary Start interactive moving */ moveStart(x, y) { const fullsize = Math.max(1, Math.sqrt((this.x1 - this.x2) ** 2 + (this.y1 - this.y2) ** 2)), sz1 = Math.sqrt((x - this.x1) ** 2 + (y - this.y1) ** 2) / fullsize, sz2 = Math.sqrt((x - this.x2) ** 2 + (y - this.y2) ** 2) / fullsize; if (sz1 > 0.9) this.#side = 1; else if (sz2 > 0.9) this.#side = -1; else this.#side = 0; } /** @summary Continue interactive moving */ moveDrag(dx, dy) { if (this.#side !== 1) { this.x1 += dx; this.y1 += dy; } if (this.#side !== -1) { this.x2 += dx; this.y2 += dy; } this.getG().select('path').attr('d', this.createPath()); } /** @summary Finish interactive moving */ moveEnd(not_changed) { if (not_changed) return; const line = this.getObject(); let exec = '', fx1 = this.svgToAxis('x', this.x1, this.isndc), fx2 = this.svgToAxis('x', this.x2, this.isndc), fy1 = this.svgToAxis('y', this.y1, this.isndc), fy2 = this.svgToAxis('y', this.y2, this.isndc); if (this.swap_xy) [fx1, fy1, fx2, fy2] = [fy1, fx1, fy2, fx2]; line.fX1 = fx1; line.fX2 = fx2; line.fY1 = fy1; line.fY2 = fy2; if (this.#side !== 1) exec += `SetX1(${fx1});;SetY1(${fy1});;`; if (this.#side !== -1) exec += `SetX2(${fx2});;SetY2(${fy2});;`; this.submitCanvExec(exec + 'Notify();;'); } /** @summary Returns object ranges * @desc Can be used for newly created canvas */ getUserRanges() { const line = this.getObject(), isndc = line.TestBit(kLineNDC); if (isndc) return null; const minx = Math.min(line.fX1, line.fX2), maxx = Math.max(line.fX1, line.fX2), miny = Math.min(line.fY1, line.fY2), maxy = Math.max(line.fY1, line.fY2); return { minx, miny, maxx, maxy }; } /** @summary Calculate line coordinates */ prepareDraw() { const line = this.getObject(); this.isndc = line.TestBit(kLineNDC); const use_frame = this.isndc ? false : new DrawOptions(this.getDrawOpt()).check('FRAME'); this.createG(use_frame ? 'frame2d' : undefined); this.swap_xy = use_frame && this.getFramePainter()?.swap_xy(); const func = this.getAxisToSvgFunc(this.isndc, true); this.x1 = func.x(line.fX1); this.y1 = func.y(line.fY1); this.x2 = func.x(line.fX2); this.y2 = func.y(line.fY2); if (this.swap_xy) [this.x1, this.y1, this.x2, this.y2] = [this.y1, this.x1, this.y2, this.x2]; this.createAttLine({ attr: line }); } /** @summary Create path */ createPath() { const x1 = Math.round(this.x1), x2 = Math.round(this.x2), y1 = Math.round(this.y1), y2 = Math.round(this.y2); return `M${x1},${y1}` + (x1 === x2 ? `V${y2}` : (y1 === y2 ? `H${x2}` : `L${x2},${y2}`)); } /** @summary Add extras - used for TArrow */ addExtras() {} /** @summary Redraw line */ redraw() { this.prepareDraw(); const elem = this.appendPath(this.createPath()) .call(this.lineatt.func); if (this.getObject()?.$do_not_draw) elem.remove(); else { this.addExtras(elem); addMoveHandler(this); assignContextMenu(this); } return this; } /** @summary Draw TLine object */ static async draw(dom, obj, opt) { const painter = new TLinePainter(dom, obj, opt); return ensureTCanvas(painter, false).then(() => painter.redraw()); } } // class TLinePainter export { TLinePainter };