scripts/screen/FrameManager_ops.js
"use strict";
import cconst from '../config/const.js';
import * as util from '../path-controller/util/util.js';
import * as vectormath from '../path-controller/util/vectormath.js';
import * as ui_base from '../core/ui_base.js';
import * as simple_toolsys from '../path-controller/toolsys/toolsys.js';
import {ToolTip} from "../widgets/ui_widgets2.js";
/*
why am I using a toolstack here at all? time to remove!
*/
let toolstack_getter = function () {
throw new Error("must pass a toolstack getter to registerToolStackGetter")
}
export function registerToolStackGetter(func) {
toolstack_getter = func;
}
let Vector2 = vectormath.Vector2,
Vector3 = vectormath.Vector3,
UndoFlags = simple_toolsys.UndoFlags,
ToolFlags = simple_toolsys.ToolFlags;
import {pushModalLight, popModalLight, keymap, pushPointerModal} from "../util/simple_events.js";
//import {keymap} from './events';
export class ToolBase extends simple_toolsys.ToolOp {
constructor(screen) {
super();
this.screen = screen;
//super();
this._finished = false;
}
start(elem, pointerId) {
//toolstack_getter().execTool(this);
this.modalStart(undefined, elem, pointerId);
}
cancel() {
this.finish();
}
finish() {
this._finished = true;
this.popModal(this.screen);
}
popModal() {
this.overdraw.end();
popModalLight(this.modaldata);
this.modaldata = undefined;
}
modalStart(ctx, elem, pointerId) {
this.ctx = ctx;
if (this.modaldata !== undefined) {
console.log("Error, modaldata was not undefined");
popModalLight(this.modaldata);
}
this.overdraw = ui_base.UIBase.createElement("overdraw-x");
this.overdraw.start(this.screen);
let handlers = {};
let keys = Object.getOwnPropertyNames(this);
for (let k in this.__proto__) {
keys.push(k);
}
for (let k of Object.getOwnPropertyNames(this.__proto__)) {
keys.push(k);
}
for (let k in this) {
keys.push(k);
}
for (let k of keys) {
if (k.startsWith("on")) {
handlers[k] = this[k].bind(this);
}
}
//window.setTimeout(() => {
if (pointerId !== undefined) {
handlers.on_pointerdown = handlers.on_mousedown;
handlers.on_pointermove = handlers.on_mousemove;
handlers.on_pointerup = handlers.on_mouseup;
handlers.on_pointercancel = handlers.on_mouseup;
handlers.on_pointerend = handlers.on_mouseup;
this.modaldata = pushPointerModal(handlers, elem, pointerId);
} else {
this.modaldata = pushModalLight(handlers);
}
//console.log("HANDLERS", this.modaldata.handlers);
//}, 100);
//window.addEventListener("touchmove", (e) => {
// console.log("touchmove");
//}, {passive : false});
}
on_mousemove(e) {
}
on_mouseup(e) {
this.finish();
}
on_keydown(e) {
console.log("s", e.keyCode);
switch (e.keyCode) {
case keymap.Escape: //esc
this.cancel();
break;
case keymap.Space: //space
case keymap.Enter: //return
this.finish();
break;
}
}
}
export class AreaResizeTool extends ToolBase {
constructor(screen, border, mpos) {
if (screen === undefined) screen = _appstate.screen; //XXX hackish!
super(screen);
this.start_mpos = new Vector2(mpos);
this.sarea = border.sareas[0];
if (!this.sarea || border.dead) {
console.log(border.dead, border);
throw new Error("border corruption");
}
this.screen = screen;
this.side = this.sarea._side(border);
}
get border() {
return this.sarea._borders[this.side];
}
static tooldef() {
return {
uiname : "Resize Area",
toolpath : "screen.area.resize",
icon : ui_base.Icons.RESIZE,
description: "change size of area",
is_modal : true,
undoflag : UndoFlags.NO_UNDO,
flag : 0,
inputs : {}, //tool properties
outputs : {} //tool properties
}
}
getBorders() {
let horiz = this.border.horiz;
let ret = [];
let visit = new Set();
let rec = (v) => {
if (visit.has(v._id)) {
return;
}
visit.add(v._id);
for (let border of v.borders) {
if (border.horiz == horiz && !visit.has(border._id)) {
visit.add(border._id);
ret.push(border);
rec(border.otherVertex(v));
}
}
}
rec(this.border.v1);
rec(this.border.v2);
return ret;
}
on_mouseup(e) {
this.finish();
}
finish() {
super.finish();
this.screen.snapScreenVerts();
this.screen.regenBorders();
this.screen.snapScreenVerts();
this.screen.loadFromVerts();
}
on_keydown(e) {
switch (e.keyCode) {
case keymap["Escape"]:
case keymap["Enter"]:
case keymap["Space"]:
this.finish();
break;
}
}
on_mousemove(e) {
let mpos = new Vector2([e.x, e.y]);
mpos.sub(this.start_mpos);
let axis = this.border.horiz ? 1 : 0;
//console.log(this.border.horiz);
this.overdraw.clear();
let visit = new Set();
let borders = this.getBorders();
let color = cconst.DEBUG.screenborders ? "rgba(1.0, 0.5, 0.0, 0.1)" : "rgba(1.0, 0.5, 0.0, 1.0)";
let bad = false;
for (let border of borders) {
bad = bad || !this.screen.isBorderMovable(border);
border.oldv1 = new Vector2(border.v1);
border.oldv2 = new Vector2(border.v2);
}
if (bad) {
console.log("border is not movable");
return;
}
let check = () => {
let count = 0;
for (let sarea of this.screen.sareas) {
if (sarea.size[0] < 15 || sarea.size[1] < 15) {
count++;
}
}
return count;
};
let badcount = check();
let snapMode = true;
let df = mpos[axis];
let border = this.border;
this.screen.moveBorder(border, df, false);
for (let border of borders) {
//if false, stead of forcing areas to fit within screen bounds
//in snapScreenVerts the screen bounds will be modified instead.
if (border.outer) {
snapMode = false;
}
this.overdraw.line(border.v1, border.v2, color);
}
this.start_mpos[0] = e.x;
this.start_mpos[1] = e.y;
this.screen.loadFromVerts();
this.screen.setCSS();
if (check() != badcount) {
console.log("bad");
for (let border of borders) {
border.v1.load(border.oldv1);
border.v2.load(border.oldv2);
}
}
this.screen.snapScreenVerts(snapMode);
this.screen.loadFromVerts();
this.screen.solveAreaConstraints(snapMode);
this.screen.setCSS();
this.screen.updateDebugBoxes();
this.screen._fireResizeCB();
}
}
//controller.registerTool(AreaResizeTool);
export class SplitTool extends ToolBase {
constructor(screen) {
if (screen === undefined) screen = _appstate.screen; //XXX hackish!
super(screen);
this.done = false;
this.screen = screen;
this.ctx = screen.ctx;
this.sarea = undefined;
this.t = undefined;
this.started = false;
}
static tooldef() {
return {
uiname : "Split Area",
toolpath : "screen.area.split",
icon : ui_base.Icons.SMALL_PLUS,
description: "split an area in two",
is_modal : true,
undoflag : UndoFlags.NO_UNDO,
flag : 0,
inputs : {}, //tool properties
outputs : {} //tool properties
}
}
modalStart(ctx) {
if (this.started) {
console.trace("double call to modalStart()");
return;
}
this.overdraw = ui_base.UIBase.createElement("overdraw-x");
this.overdraw.start(this.screen);
super.modalStart(ctx);
}
cancel() {
return this.finish(true);
}
finish(canceled = false) {
if (this.done) {
return;
}
this.done = true;
this.overdraw.end();
this.popModal(this.screen);
if (canceled || !this.sarea) {
return;
}
let sarea = this.sarea, screen = this.screen;
let t = this.t;
screen.splitArea(sarea, t, this.horiz);
screen._internalRegenAll();
}
on_mousemove(e) {
let x = e.x, y = e.y;
let screen = this.screen;
let sarea = screen.findScreenArea(x, y);
this.overdraw.clear();
if (sarea !== undefined) {
//x -= sarea.pos[0];
//y -= sarea.pos[1];
x = (x - sarea.pos[0])/(sarea.size[0]);
y = (y - sarea.pos[1])/(sarea.size[1]);
let dx = 1.0 - Math.abs(x - 0.5);
let dy = 1.0 - Math.abs(y - 0.5);
this.sarea = sarea;
let horiz = this.horiz = dx < dy;
if (horiz) {
this.t = y;
this.overdraw.line([sarea.pos[0], e.y], [sarea.pos[0] + sarea.size[0], e.y]);
} else {
this.t = x;
this.overdraw.line([e.x, sarea.pos[1]], [e.x, sarea.pos[1] + sarea.size[1]]);
}
}
//console.warn("sarea:", sarea);
//let sarea = this.
//console.log(e.x, e.y);
//this.overdraw.clear();
//this.overdraw.line([e.x, e.y-200], [e.x, e.y+200], "grey");
}
on_mousedown(e) {
}
on_mouseup(e) {
this.finish();
if (e.button) {
this.stopPropagation();
this.preventDefault();
}
}
on_keydown(e) {
console.log("s", e.keyCode);
switch (e.keyCode) {
case keymap.Escape: //esc
this.cancel();
break;
case keymap.Space: //space
case keymap.Enter: //return
this.finish();
break;
}
}
}
export class RemoveAreaTool extends ToolBase {
constructor(screen, border) {
if (screen === undefined) screen = _appstate.screen; //XXX hackish!
super(screen);
this.border = border;
this.done = false;
this.screen = screen;
this.ctx = screen.ctx;
this.sarea = undefined;
this.t = undefined;
this.started = false;
}
static tooldef() {
return {
uiname : "Remove Area",
toolpath : "screen.area.pick_remove",
icon : ui_base.Icons.SMALL_PLUS,
description: "Collapse a window",
is_modal : true,
undoflag : UndoFlags.NO_UNDO,
flag : 0,
inputs : {}, //tool properties
outputs : {} //tool properties
}
}
modalStart(ctx) {
if (this.started) {
console.trace("double call to modalStart()");
return;
}
this.overdraw = ui_base.UIBase.createElement("overdraw-x");
this.overdraw.start(this.screen);
super.modalStart(ctx);
}
cancel() {
return this.finish(true);
}
finish(canceled = false) {
if (this.done) {
return;
}
this.done = true;
this.overdraw.end();
this.popModal(this.screen);
if (canceled || !this.sarea) {
return;
}
let sarea = this.sarea, screen = this.screen;
let t = this.t;
if (sarea) {
screen.collapseArea(sarea, this.border);
screen._internalRegenAll();
}
}
on_mousemove(e) {
let x = e.x, y = e.y;
let screen = this.screen;
let sarea = screen.findScreenArea(x, y);
this.overdraw.clear();
if (sarea !== undefined) {
this.sarea = sarea;
this.overdraw.rect(sarea.pos, sarea.size, "rgba(0,0,0,0.1)");
}
//console.warn("sarea:", sarea);
//let sarea = this.
//console.log(e.x, e.y);
//this.overdraw.clear();
//this.overdraw.line([e.x, e.y-200], [e.x, e.y+200], "grey");
}
on_mousedown(e) {
}
on_mouseup(e) {
this.finish();
if (e.button) {
this.stopPropagation();
this.preventDefault();
}
}
on_keydown(e) {
console.log("s", e.keyCode);
switch (e.keyCode) {
case keymap.Escape: //esc
this.cancel();
break;
case keymap.Space: //space
case keymap.Enter: //return
this.finish();
break;
}
}
}
//controller.registerTool(SplitTool);
export class AreaDragTool extends ToolBase {
constructor(screen, sarea, mpos) {
if (screen === undefined) screen = _appstate.screen; //XXX hackish!
super(screen);
this.dropArea = false;
this.excludeAreas = new Set();
this.cursorbox = undefined;
this.boxes = [];
this.boxes.active = undefined;
this.sarea = sarea;
this.start_mpos = new Vector2(mpos);
this.screen = screen;
}
static tooldef() {
return {
uiname : "Drag Area",
toolpath : "screen.area.drag",
icon : ui_base.Icons.TRANSLATE,
description: "move or duplicate area",
is_modal : true,
undoflag : UndoFlags.NO_UNDO,
flag : 0,
inputs : {}, //tool properties
outputs : {} //tool properties
}
}
finish() {
super.finish();
this.screen.regenBorders();
this.screen.solveAreaConstraints();
this.screen.snapScreenVerts();
this.screen._recalcAABB();
}
getBoxRect(b) {
let sa = b.sarea;
let pos, size;
if (b.horiz == -1) {
//replacement mode
pos = sa.pos;
size = sa.size;
} else if (b.horiz) {
if (b.side == 'b') {
pos = [sa.pos[0], sa.pos[1] + sa.size[1]*b.t]
size = [sa.size[0], sa.size[1]*(1.0 - b.t)]
} else {
pos = [sa.pos[0], sa.pos[1]];
size = [sa.size[0], sa.size[1]*b.t]
}
} else {
if (b.side == 'r') {
pos = [sa.pos[0] + sa.size[0]*b.t, sa.pos[1]]
size = [sa.size[0]*(1.0 - b.t), sa.size[1]]
} else {
pos = [sa.pos[0], sa.pos[1]];
size = [sa.size[0]*b.t, sa.size[1]]
}
}
let color = "rgba(100, 100, 100, 0.2)";
let ret = this.overdraw.rect(pos, size, color);
ret.style["pointer-events"] = "none";
return ret;
}
doSplit(b) {
if (this.sarea) {
return this.doSplitDrop(b);
}
let src = this.sarea, dst = b.sarea;
let screen = this.screen;
let t = b.t;
screen.splitArea(dst, t, b.horiz);
screen._internalRegenAll();
}
doSplitDrop(b) {
//first check if there was no change
if (b.horiz === -1 && b.sarea === this.sarea) {
return;
}
let can_rip = false;
let sa = this.sarea;
let screen = this.screen;
//rip conditions
can_rip = sa.size[0] === screen.size[0] || sa.size[1] === screen.size[1];
can_rip = can_rip || this.sarea.floating;
can_rip = can_rip && b.sarea !== sa;
can_rip = can_rip && (b.horiz === -1 || !screen.areasBorder(sa, b.sarea));
let expand = b.horiz === -1 && b.sarea !== sa && screen.areasBorder(b.sarea, sa);
can_rip = can_rip || expand;
console.log("can_rip:", can_rip, expand);
if (can_rip) {
screen.removeArea(sa);
screen.snapScreenVerts();
}
if (b.horiz === -1) {
//replacement
let src = this.sarea, dst = b.sarea;
if (can_rip && src !== dst) {
let mm;
//handle case of one area "consuming" another
if (expand) {
mm = screen.minmaxArea(src);
screen.minmaxArea(dst, mm);
}
console.log("replacing. . .", expand);
if (src.floating) {
let old = dst.editors;
dst.editors = [];
dst.editormap = {};
if (dst.area && !(dst.area.constructor.define().areaname in src.editormap)) {
dst.area.push_ctx_active();
dst.area.on_area_inactive();
dst.area.remove();
dst.area.pop_ctx_active();
}
for (let editor of old) {
let def = editor.constructor.define();
let bad = false;
//bad = !(def.areaname in src.editormap);
for (let editor2 of src.editors) {
if (editor.constructor === editor2.constructor) {
bad = true;
break;
}
}
if (!bad) {
dst.editors.push(editor);
dst.editormap[def.areaname] = editor;
}
}
for (let editor of src.editors) {
let def = editor.constructor.define();
dst.editormap[def.areaname] = editor;
dst.editors.push(editor);
if (editor.owning_sarea) {
editor.owning_sarea = dst;
}
if (editor.parentWidget) {
editor.parentWidget = dst;
}
}
if (cconst.useAreaTabSwitcher) {
for (let editor of dst.editors) {
if (editor.switcher) {
editor.switcher.flagUpdate();
}
}
}
dst.area = src.area;
dst.shadow.appendChild(src.area);
src.area = undefined;
src.editors = [];
src.editormap = {};
dst.on_resize(dst.size, dst.size);
dst.flushSetCSS();
dst.flushUpdate();
screen.removeArea(src);
screen.snapScreenVerts();
return;
} else {
screen.replaceArea(dst, src);
}
if (expand) {
console.log("\nEXPANDING:", src.size[0], src.size[1]);
src.pos[0] = mm.min[0];
src.pos[1] = mm.min[1];
src.size[0] = mm.max[0] - mm.min[0];
src.size[1] = mm.max[1] - mm.min[1];
src.loadFromPosSize();
screen._internalRegenAll();
}
} else {
//console.log("copying. . .");
screen.replaceArea(dst, src.copy());
screen._internalRegenAll();
}
} else {
let src = this.sarea, dst = b.sarea;
let t = b.t;
let nsa = screen.splitArea(dst, t, b.horiz);
if (b.side === 'l' || b.side === 't') {
nsa = dst;
}
if (can_rip) {
//console.log("replacing");
screen.replaceArea(nsa, src);
} else {
//console.log("copying");
screen.replaceArea(nsa, src.copy());
}
screen._internalRegenAll();
}
}
makeBoxes(sa) {
let sz = util.isMobile() ? 100 : 40;
let cx = sa.pos[0] + sa.size[0]*0.5;
let cy = sa.pos[1] + sa.size[1]*0.5;
let color = this.color = "rgba(200, 200, 200, 0.55)";
let hcolor = this.hcolor = "rgba(230, 230, 230, 0.75)";
let idgen = 0;
let boxes = this.boxes;
let box = (x, y, sz, horiz, t, side) => {
//console.log(x, y, sz);
let b = this.overdraw.rect([x - sz[0]*0.5, y - sz[1]*0.5], sz, color);
b.style["border-radius"] = "14px";
boxes.push(b);
b.sarea = sa;
let style = document.createElement("style")
let cls = `mybox_${idgen++}`;
b.horiz = horiz;
b.t = t;
b.side = side;
b.setAttribute("class", cls);
b.setAttribute("is_box", true);
b.addEventListener("mousemove", this.on_mousemove.bind(this));
let onclick = b.onclick = (e) => {
let type = e.type.toLowerCase();
if ((e.type === "mousedown" || e.type === "mouseup") && e.button !== 0) {
return; //another handler will cancel
}
console.log("split click");
if (!this._finished) {
this.finish();
this.doSplit(b);
e.preventDefault();
e.stopPropagation();
}
}
b.addEventListener("click", onclick);
b.addEventListener("mousedown", onclick);
b.addEventListener("mouseup", onclick);
b.addEventListener("mouseenter", (e) => {
if (this.curbox !== undefined) {
if (this.curbox.rect) {
this.curbox.rect.remove()
this.curbox.rect = undefined;
}
}
if (b.rect !== undefined) {
b.rect.remove();
b.rect = undefined;
}
b.rect = this.getBoxRect(b);
this.curbox = b;
b.setColor(hcolor);
//b.style["background-color"] = hcolor;
})
b.addEventListener("mouseleave", (e) => {
if (b.rect) {
b.rect.remove();
b.rect = undefined;
}
if (this.curbox === b) {
this.curbox = undefined;
}
b.setColor(color);
//b.style["background-color"] = color;
})
style.textContent = `
.${cls}:hover {
background-color : orange;
fill:orange;stroke-width:2
}
`
//console.log(style.textContent);
b.appendChild(style);
b.setAttribute("class", cls);
return b;
}
let pad = 5;
if (this.sarea) {
box(cx, cy, [sz, sz], -1, -1, -1);
}
box(cx - sz*0.75 - pad, cy, [sz*0.5, sz], false, 0.5, 'l');
box(cx - sz*1.2 - pad, cy, [sz*0.25, sz], false, 0.3, 'l');
box(cx + sz*0.75 + pad, cy, [sz*0.5, sz], false, 0.5, 'r');
box(cx + sz*1.2 + pad, cy, [sz*0.25, sz], false, 0.7, 'r');
box(cx, cy - sz*0.75 - pad, [sz, sz*0.5], true, 0.5, 't');
box(cx, cy - sz*1.2 - pad, [sz, sz*0.25], true, 0.3, 't');
box(cx, cy + sz*0.75 + pad, [sz, sz*0.5], true, 0.5, 'b');
box(cx, cy + sz*1.2 + pad, [sz, sz*0.25], true, 0.7, 'b');
}
getActiveBox(x, y) {
for (let n of this.boxes) {
if (n.hasAttribute && n.hasAttribute("is_box")) {
let rect = n.getClientRects()[0];
//console.log(rect.x, rect.y);
if (x >= rect.x && y >= rect.y && x < rect.x + rect.width && y < rect.y + rect.height) {
//console.log("found rect");
return n;
}
}
}
}
on_drag(e) {
this.on_mousemove(e);
}
on_dragend(e) {
this.on_mouseup(e);
}
on_mousemove(e) {
let wid = 55;
let color = "rgb(200, 200, 200, 0.7)";
//console.trace("mouse move!", e.x, e.y, this.sarea);
/*
manually feed events to boxes so as to work right
with touch events; note that pushModalLight routes
touch to mouse events (if no touch handlers are present).
*/
let n = this.getActiveBox(e.x, e.y);
if (n !== undefined) {
n.setColor(this.hcolor); //"rgba(250, 250, 250, 0.75)");
}
//console.log("mouse move", n);
if (this.boxes.active !== undefined && this.boxes.active !== n) {
this.boxes.active.setColor(this.color);
this.boxes.active.dispatchEvent(new MouseEvent("mouseleave", e));
}
if (n !== undefined) {
n.dispatchEvent(new MouseEvent("mouseenter", e));
}
this.boxes.active = n;
/*
let rec = (n) => {
if (n.hasAttribute && n.hasAttribute("is_box")) {
let rect = n.getClientRects()[0];
console.log(rect.x, rect.y);
if (x >= rect.x && x >= rect.y && x < rect.x+rect.width && y < rect.y+rect.height) {
console.log("found rect");
n.dispatchEvent("mouseenter", new MouseEvent("mouseenter", e));
}
}
if (n === undefined || n.childNodes === undefined) {
return;
}
for (let n2 of n.childNodes) {
rec(n2);
}
if (n.shadow) {
for (let n2 of n.shadow.childNodes) {
rec(n2);
}
}
};
rec(this.overdraw);
//*/
if (this.sarea === undefined) {
return;
}
if (this.cursorbox === undefined) {
wid = 25;
this.cursorbox = this.overdraw.rect([e.x - wid*0.5, e.y - wid*0.5], [wid, wid], color);
this.cursorbox.style["pointer-events"] = "none";
} else {
this.cursorbox.style["x"] = (e.x - wid*0.5) + "px";
this.cursorbox.style["y"] = (e.y - wid*0.5) + "px";
}
}
on_pointerup(e) {
this.on_mouseup(e);
}
on_mouseup(e) {
console.log("e.button", e.button, e, e.x, e.y, this.getActiveBox(e.x, e.y));
if (e.button) {
e.stopPropagation();
e.preventDefault();
} else {
let box = this.getActiveBox(e.x, e.y);
if (box !== undefined) {
box.onclick(e);
}
}
this.finish();
}
modalStart(ctx) {
super.modalStart(...arguments);
let screen = this.screen;
this.overdraw.clear();
if (this.sarea && !this.excludeAreas.has(this.sarea)) {
let sa = this.sarea;
let box = this.overdraw.rect(sa.pos, sa.size, "rgba(100, 100, 100, 0.5)");
box.style["pointer-events"] = "none";
}
for (let sa of screen.sareas) {
if (this.excludeAreas.has(sa)) {
continue;
}
this.makeBoxes(sa);
}
}
on_keydown(e) {
switch (e.keyCode){
case keymap["Escape"]:
case keymap["Enter"]:
case keymap["Space"]:
this.finish();
break;
}
}
}
export class AreaMoveAttachTool extends AreaDragTool {
constructor(screen, sarea, mpos) {
super(screen, sarea, mpos);
this.excludeAreas = new Set([sarea]);
this.dropArea = true;
this.first = true;
this.sarea = sarea;
this.mpos = new Vector2(mpos);
this.start_mpos2 = new Vector2(mpos);
this.start_pos = new Vector2(sarea.pos);
}
on_mousemove(e) {
let dx = e.x - this.start_mpos2[0];
let dy = e.y - this.start_mpos2[1];
let sarea = this.sarea;
if (this.first) {
this.start_mpos2 = new Vector2([e.x, e.y]);
this.first = false;
return;
}
sarea.pos[0] = this.start_pos[0] + dx;
sarea.pos[1] = this.start_pos[1] + dy;
sarea.loadFromPosSize();
this.mpos.loadXY(e.x, e.y);
super.on_mousemove(e);
}
on_mouseup(e) {
super.on_mouseup(e);
}
on_mousedown(e) {
super.on_mousedown(e);
}
on_keydown(e) {
super.on_keydown(e);
}
}
//controller.registerTool(AreaDragTool);
export class ToolTipViewer extends ToolBase {
constructor(screen) {
super(screen);
this.tooltip = undefined;
this.element = undefined;
}
static tooldef() {
return {
uiname : "Help Tool",
toolpath : "screen.help_picker",
icon : ui_base.Icons.HELP,
description: "view tooltips",
is_modal : true,
undoflag : UndoFlags.NO_UNDO,
flag : 0,
inputs : {}, //tool properties
outputs : {} //tool properties
}
}
on_mousemove(e) {
this.pick(e);
}
on_mousedown(e) {
this.pick(e);
}
on_mouseup(e) {
this.finish();
}
finish() {
super.finish();
}
on_keydown(e) {
switch (e.keyCode) {
case keymap.Escape:
case keymap.Enter:
case Keymap.Space:
if (this.tooltip) {
this.tooltip.end();
}
this.finish();
break;
}
}
pick(e) {
let x = e.x, y = e.y;
let ele = this.screen.pickElement(x, y);
console.log(ele ? ele.tagName : ele);
if (ele !== undefined && ele !== this.element && ele.title) {
if (this.tooltip) {
this.tooltip.end();
}
this.element = ele;
let tip = ele.title;
this.tooltip = ToolTip.show(tip, this.screen, x, y);
}
e.preventDefault();
e.stopPropagation();
}
}