@thi.ng/imgui 2.2.12 → 2.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,32 @@
1
1
  import { isPlainObject } from "@thi.ng/checks/is-plain-object";
2
2
  import { valHash } from "../hash.js";
3
3
  import { layoutBox } from "../layout.js";
4
- export const textLabel = (gui, layout, label, pad = false) => {
5
- const theme = gui.theme;
6
- const { x, y, h } = layoutBox(layout);
7
- gui.draw &&
8
- gui.add([
9
- "text",
10
- { fill: gui.textColor(false) },
11
- [x + (pad ? theme.pad : 0), y + h / 2 + theme.baseLine],
12
- label,
13
- ]);
4
+ const textLabel = (gui, layout, label, pad = false) => {
5
+ const theme = gui.theme;
6
+ const { x, y, h } = layoutBox(layout);
7
+ gui.draw && gui.add([
8
+ "text",
9
+ { fill: gui.textColor(false) },
10
+ [x + (pad ? theme.pad : 0), y + h / 2 + theme.baseLine],
11
+ label
12
+ ]);
13
+ };
14
+ const textLabelRaw = (p, attribs, label) => ["text", isPlainObject(attribs) ? attribs : { fill: attribs }, p, label];
15
+ const textTransformH = (theme, x, y, _, h) => [1, 0, 0, 1, x + theme.pad, y + h / 2 + theme.baseLine];
16
+ const textTransformV = (theme, x, y, w, h) => [0, -1, 1, 0, x + w / 2 + theme.baseLine, y + h - theme.pad];
17
+ const dialValueLabel = (gui, id, key, v, x, y, label, fmt) => gui.resource(
18
+ id,
19
+ valHash(key, v, gui.disabled),
20
+ () => textLabelRaw(
21
+ [x, y],
22
+ gui.textColor(false),
23
+ (label ? label + " " : "") + (fmt ? fmt(v) : v)
24
+ )
25
+ );
26
+ export {
27
+ dialValueLabel,
28
+ textLabel,
29
+ textLabelRaw,
30
+ textTransformH,
31
+ textTransformV
14
32
  };
15
- export const textLabelRaw = (p, attribs, label) => ["text", isPlainObject(attribs) ? attribs : { fill: attribs }, p, label];
16
- export const textTransformH = (theme, x, y, _, h) => [1, 0, 0, 1, x + theme.pad, y + h / 2 + theme.baseLine];
17
- export const textTransformV = (theme, x, y, w, h) => [0, -1, 1, 0, x + w / 2 + theme.baseLine, y + h - theme.pad];
18
- export const dialValueLabel = (gui, id, key, v, x, y, label, fmt) => gui.resource(id, valHash(key, v, gui.disabled), () => textLabelRaw([x, y], gui.textColor(false), (label ? label + " " : "") + (fmt ? fmt(v) : v)));
@@ -3,43 +3,50 @@ import { hash } from "@thi.ng/vectors/hash";
3
3
  import { handleButtonKeys, hoverButton } from "../behaviors/button.js";
4
4
  import { layoutBox } from "../layout.js";
5
5
  import { textLabelRaw } from "./textlabel.js";
6
- /**
7
- * If `square` is true, the clickable area will not fill the entire
8
- * cell, but only a left-aligned square of cell/row height.
9
- *
10
- * @param gui -
11
- * @param layout -
12
- * @param id -
13
- * @param val -
14
- * @param i -
15
- * @param square -
16
- * @param label -
17
- * @param info -
18
- */
19
- export const toggle = (gui, layout, id, val, square, label, info) => {
20
- const { x, y, w, h } = layoutBox(layout);
21
- return toggleRaw(gui, id, x, y, square ? h : w, h, square ? h : 0, val, label, info);
6
+ const toggle = (gui, layout, id, val, square, label, info) => {
7
+ const { x, y, w, h } = layoutBox(layout);
8
+ return toggleRaw(
9
+ gui,
10
+ id,
11
+ x,
12
+ y,
13
+ square ? h : w,
14
+ h,
15
+ square ? h : 0,
16
+ val,
17
+ label,
18
+ info
19
+ );
22
20
  };
23
- export const toggleRaw = (gui, id, x, y, w, h, lx, val, label, info) => {
24
- const theme = gui.theme;
25
- const key = hash([x, y, w, h]);
26
- gui.registerID(id, key);
27
- let res;
28
- const box = gui.resource(id, key, () => rect([x, y], [w, h]));
29
- const hover = hoverButton(gui, id, box, info);
30
- const focused = gui.requestFocus(id);
31
- let changed = !gui.buttons && gui.hotID === id && gui.activeID === id;
32
- focused && (changed = handleButtonKeys(gui) || changed);
33
- changed && (res = val = !val);
34
- if (gui.draw) {
35
- box.attribs = {
36
- fill: val ? gui.fgColor(hover) : gui.bgColor(hover),
37
- stroke: gui.focusColor(id),
38
- };
39
- gui.add(box);
40
- label &&
41
- gui.add(textLabelRaw([x + theme.pad + lx, y + h / 2 + theme.baseLine], gui.textColor(hover && lx > 0 && lx < w - theme.pad), label));
42
- }
43
- gui.lastID = id;
44
- return res;
21
+ const toggleRaw = (gui, id, x, y, w, h, lx, val, label, info) => {
22
+ const theme = gui.theme;
23
+ const key = hash([x, y, w, h]);
24
+ gui.registerID(id, key);
25
+ let res;
26
+ const box = gui.resource(id, key, () => rect([x, y], [w, h]));
27
+ const hover = hoverButton(gui, id, box, info);
28
+ const focused = gui.requestFocus(id);
29
+ let changed = !gui.buttons && gui.hotID === id && gui.activeID === id;
30
+ focused && (changed = handleButtonKeys(gui) || changed);
31
+ changed && (res = val = !val);
32
+ if (gui.draw) {
33
+ box.attribs = {
34
+ fill: val ? gui.fgColor(hover) : gui.bgColor(hover),
35
+ stroke: gui.focusColor(id)
36
+ };
37
+ gui.add(box);
38
+ label && gui.add(
39
+ textLabelRaw(
40
+ [x + theme.pad + lx, y + h / 2 + theme.baseLine],
41
+ gui.textColor(hover && lx > 0 && lx < w - theme.pad),
42
+ label
43
+ )
44
+ );
45
+ }
46
+ gui.lastID = id;
47
+ return res;
48
+ };
49
+ export {
50
+ toggle,
51
+ toggleRaw
45
52
  };
@@ -1,10 +1,20 @@
1
1
  import { rect } from "@thi.ng/geom/rect";
2
2
  import { add2 } from "@thi.ng/vectors/add";
3
3
  import { textLabelRaw } from "./textlabel.js";
4
- export const tooltipRaw = (gui, tooltip) => {
5
- const theme = gui.theme;
6
- const p = add2(null, [0, 10], gui.mouse);
7
- gui.addOverlay(rect(p, [tooltip.length * theme.charWidth + theme.pad, 20], {
8
- fill: theme.bgTooltip,
9
- }), textLabelRaw(add2(null, [4, 10 + theme.baseLine], p), theme.textTooltip, tooltip));
4
+ const tooltipRaw = (gui, tooltip) => {
5
+ const theme = gui.theme;
6
+ const p = add2(null, [0, 10], gui.mouse);
7
+ gui.addOverlay(
8
+ rect(p, [tooltip.length * theme.charWidth + theme.pad, 20], {
9
+ fill: theme.bgTooltip
10
+ }),
11
+ textLabelRaw(
12
+ add2(null, [4, 10 + theme.baseLine], p),
13
+ theme.textTooltip,
14
+ tooltip
15
+ )
16
+ );
17
+ };
18
+ export {
19
+ tooltipRaw
10
20
  };
@@ -2,81 +2,97 @@ import { line } from "@thi.ng/geom/line";
2
2
  import { rect } from "@thi.ng/geom/rect";
3
3
  import { fit2 } from "@thi.ng/vectors/fit";
4
4
  import { hash } from "@thi.ng/vectors/hash";
5
- import { handleSlider2Keys, isHoverSlider, slider2Val, } from "../behaviors/slider.js";
5
+ import {
6
+ handleSlider2Keys,
7
+ isHoverSlider,
8
+ slider2Val
9
+ } from "../behaviors/slider.js";
6
10
  import { textLabelRaw } from "./textlabel.js";
7
11
  import { tooltipRaw } from "./tooltip.js";
8
- /**
9
- * `mode` interpretation:
10
- *
11
- * - -2 = square
12
- * - -1 = proportional height (snapped to rows)
13
- * - >0 = fixed row height
14
- *
15
- * @param gui -
16
- * @param layout -
17
- * @param id -
18
- * @param min -
19
- * @param max -
20
- * @param prec -
21
- * @param val -
22
- * @param mode -
23
- * @param yUp -
24
- * @param label -
25
- * @param fmt -
26
- * @param info -
27
- */
28
- export const xyPad = (gui, layout, id, min, max, prec, val, mode, yUp, label, fmt, info) => {
29
- let box;
30
- const ch = layout.cellH;
31
- const gap = layout.gap;
32
- if (mode === -2) {
33
- box = layout.nextSquare();
34
- }
35
- else {
36
- let rows = (mode > 0 ? mode : layout.cellW / (ch + gap)) | 0;
37
- box = layout.next([1, rows + 1]);
38
- box.h -= ch + gap;
39
- }
40
- return xyPadRaw(gui, id, box.x, box.y, box.w, box.h, min, max, prec, val, yUp, 0, box.h + gap + ch / 2 + gui.theme.baseLine, label, fmt, info);
12
+ const xyPad = (gui, layout, id, min, max, prec, val, mode, yUp, label, fmt, info) => {
13
+ let box;
14
+ const ch = layout.cellH;
15
+ const gap = layout.gap;
16
+ if (mode === -2) {
17
+ box = layout.nextSquare();
18
+ } else {
19
+ let rows = (mode > 0 ? mode : layout.cellW / (ch + gap)) | 0;
20
+ box = layout.next([1, rows + 1]);
21
+ box.h -= ch + gap;
22
+ }
23
+ return xyPadRaw(
24
+ gui,
25
+ id,
26
+ box.x,
27
+ box.y,
28
+ box.w,
29
+ box.h,
30
+ min,
31
+ max,
32
+ prec,
33
+ val,
34
+ yUp,
35
+ 0,
36
+ box.h + gap + ch / 2 + gui.theme.baseLine,
37
+ label,
38
+ fmt,
39
+ info
40
+ );
41
41
  };
42
- export const xyPadRaw = (gui, id, x, y, w, h, min, max, prec, val, yUp = false, lx, ly, label, fmt, info) => {
43
- const maxX = x + w;
44
- const maxY = y + h;
45
- const pos = yUp ? [x, maxY] : [x, y];
46
- const maxPos = yUp ? [maxX, y] : [maxX, maxY];
47
- const key = hash([x, y, w, h]);
48
- gui.registerID(id, key);
49
- const box = gui.resource(id, key, () => rect([x, y], [w, h]));
50
- const col = gui.textColor(false);
51
- const hover = isHoverSlider(gui, id, box, "move");
52
- const draw = gui.draw;
53
- let v = val;
54
- let res;
55
- if (hover) {
56
- if (gui.isMouseDown()) {
57
- gui.activeID = id;
58
- res = slider2Val(fit2([], gui.mouse, pos, maxPos, min, max), min, max, prec);
59
- }
60
- info && draw && tooltipRaw(gui, info);
61
- }
62
- const focused = gui.requestFocus(id);
63
- if (draw) {
64
- box.attribs = {
65
- fill: gui.bgColor(hover || focused),
66
- stroke: gui.focusColor(id),
67
- };
68
- const { 0: cx, 1: cy } = fit2([], v, min, max, pos, maxPos);
69
- gui.add(box, line([x, cy], [maxX, cy], {
70
- stroke: col,
71
- }), line([cx, y], [cx, maxY], {
72
- stroke: col,
73
- }), textLabelRaw([x + lx, y + ly], col, (label ? label + " " : "") +
74
- (fmt ? fmt(val) : `${val[0] | 0}, ${val[1] | 0}`)));
42
+ const xyPadRaw = (gui, id, x, y, w, h, min, max, prec, val, yUp = false, lx, ly, label, fmt, info) => {
43
+ const maxX = x + w;
44
+ const maxY = y + h;
45
+ const pos = yUp ? [x, maxY] : [x, y];
46
+ const maxPos = yUp ? [maxX, y] : [maxX, maxY];
47
+ const key = hash([x, y, w, h]);
48
+ gui.registerID(id, key);
49
+ const box = gui.resource(id, key, () => rect([x, y], [w, h]));
50
+ const col = gui.textColor(false);
51
+ const hover = isHoverSlider(gui, id, box, "move");
52
+ const draw = gui.draw;
53
+ let v = val;
54
+ let res;
55
+ if (hover) {
56
+ if (gui.isMouseDown()) {
57
+ gui.activeID = id;
58
+ res = slider2Val(
59
+ fit2([], gui.mouse, pos, maxPos, min, max),
60
+ min,
61
+ max,
62
+ prec
63
+ );
75
64
  }
76
- if (focused &&
77
- (v = handleSlider2Keys(gui, min, max, prec, v, yUp)) !== undefined) {
78
- return v;
79
- }
80
- gui.lastID = id;
81
- return res;
65
+ info && draw && tooltipRaw(gui, info);
66
+ }
67
+ const focused = gui.requestFocus(id);
68
+ if (draw) {
69
+ box.attribs = {
70
+ fill: gui.bgColor(hover || focused),
71
+ stroke: gui.focusColor(id)
72
+ };
73
+ const { 0: cx, 1: cy } = fit2([], v, min, max, pos, maxPos);
74
+ gui.add(
75
+ box,
76
+ line([x, cy], [maxX, cy], {
77
+ stroke: col
78
+ }),
79
+ line([cx, y], [cx, maxY], {
80
+ stroke: col
81
+ }),
82
+ textLabelRaw(
83
+ [x + lx, y + ly],
84
+ col,
85
+ (label ? label + " " : "") + (fmt ? fmt(val) : `${val[0] | 0}, ${val[1] | 0}`)
86
+ )
87
+ );
88
+ }
89
+ if (focused && (v = handleSlider2Keys(gui, min, max, prec, v, yUp)) !== void 0) {
90
+ return v;
91
+ }
92
+ gui.lastID = id;
93
+ return res;
94
+ };
95
+ export {
96
+ xyPad,
97
+ xyPadRaw
82
98
  };
package/events.js CHANGED
@@ -1,49 +1,38 @@
1
1
  import { MouseButton } from "./api.js";
2
- /**
3
- * Injects default mouse & touch event handlers into `gui.attribs` and
4
- * attaches keydown/up listeners to `window`.
5
- *
6
- * This method should only be used if the IMGUI is to be updated via a
7
- * RAF loop or other non-reactive situation. For on-demand updates /
8
- * rendering event handling and IMGUI mouse/key state preparation is
9
- * left to the user.
10
- *
11
- * - {@link IMGUI.setMouse}
12
- * - {@link IMGUI.setKey}
13
- */
14
- export const useDefaultEventHandlers = (gui) => {
15
- const pos = (e) => {
16
- const b = e.target.getBoundingClientRect();
17
- const t = e.changedTouches
18
- ? e.changedTouches[0]
19
- : e;
20
- return [t.clientX - b.left, t.clientY - b.top];
21
- };
22
- const touchActive = (e) => {
23
- gui.setMouse(pos(e), MouseButton.LEFT);
24
- };
25
- const touchEnd = (e) => {
26
- gui.setMouse(pos(e), 0);
27
- };
28
- const mouseActive = (e) => {
29
- gui.setMouse(pos(e), e.buttons);
30
- };
31
- Object.assign(gui.attribs, {
32
- onmousemove: mouseActive,
33
- onmousedown: mouseActive,
34
- onmouseup: mouseActive,
35
- ontouchstart: touchActive,
36
- ontouchmove: touchActive,
37
- ontouchend: touchEnd,
38
- ontouchcancel: touchEnd,
39
- });
40
- window.addEventListener("keydown", (e) => {
41
- gui.setKey(e);
42
- if (e.key === "Tab") {
43
- e.preventDefault();
44
- }
45
- });
46
- window.addEventListener("keyup", (e) => {
47
- gui.setKey(e);
48
- });
2
+ const useDefaultEventHandlers = (gui) => {
3
+ const pos = (e) => {
4
+ const b = e.target.getBoundingClientRect();
5
+ const t = e.changedTouches ? e.changedTouches[0] : e;
6
+ return [t.clientX - b.left, t.clientY - b.top];
7
+ };
8
+ const touchActive = (e) => {
9
+ gui.setMouse(pos(e), MouseButton.LEFT);
10
+ };
11
+ const touchEnd = (e) => {
12
+ gui.setMouse(pos(e), 0);
13
+ };
14
+ const mouseActive = (e) => {
15
+ gui.setMouse(pos(e), e.buttons);
16
+ };
17
+ Object.assign(gui.attribs, {
18
+ onmousemove: mouseActive,
19
+ onmousedown: mouseActive,
20
+ onmouseup: mouseActive,
21
+ ontouchstart: touchActive,
22
+ ontouchmove: touchActive,
23
+ ontouchend: touchEnd,
24
+ ontouchcancel: touchEnd
25
+ });
26
+ window.addEventListener("keydown", (e) => {
27
+ gui.setKey(e);
28
+ if (e.key === "Tab") {
29
+ e.preventDefault();
30
+ }
31
+ });
32
+ window.addEventListener("keyup", (e) => {
33
+ gui.setKey(e);
34
+ });
35
+ };
36
+ export {
37
+ useDefaultEventHandlers
49
38
  };