@thi.ng/imgui 2.2.13 → 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.
@@ -9,60 +9,110 @@ import { dialVal } from "../behaviors/dial.js";
9
9
  import { handleSlider1Keys, isHoverSlider } from "../behaviors/slider.js";
10
10
  import { dialValueLabel } from "./textlabel.js";
11
11
  import { tooltipRaw } from "./tooltip.js";
12
- export const dial = (gui, layout, id, min, max, prec, val, label, fmt, info) => {
13
- const { x, y, w, h, ch } = isLayout(layout) ? layout.nextSquare() : layout;
14
- return dialRaw(gui, id, x, y, w, h, min, max, prec, val, gui.theme.pad, h + ch / 2 + gui.theme.baseLine, label, fmt, info);
12
+ const dial = (gui, layout, id, min, max, prec, val, label, fmt, info) => {
13
+ const { x, y, w, h, ch } = isLayout(layout) ? layout.nextSquare() : layout;
14
+ return dialRaw(
15
+ gui,
16
+ id,
17
+ x,
18
+ y,
19
+ w,
20
+ h,
21
+ min,
22
+ max,
23
+ prec,
24
+ val,
25
+ gui.theme.pad,
26
+ h + ch / 2 + gui.theme.baseLine,
27
+ label,
28
+ fmt,
29
+ info
30
+ );
15
31
  };
16
- export const dialGroup = (gui, layout, id, min, max, prec, horizontal, vals, label, fmt, info = []) => {
17
- const n = vals.length;
18
- const nested = horizontal
19
- ? layout.nest(n, [n, 1])
20
- : layout.nest(1, [1, (layout.rowsForHeight(layout.cellW) + 1) * n]);
21
- let res;
22
- let idx = -1;
23
- for (let i = 0; i < n; i++) {
24
- const v = dial(gui, nested, `${id}-${i}`, min, max, prec, vals[i], label[i], fmt, info[i]);
25
- if (v !== undefined) {
26
- res = v;
27
- idx = i;
28
- }
32
+ const dialGroup = (gui, layout, id, min, max, prec, horizontal, vals, label, fmt, info = []) => {
33
+ const n = vals.length;
34
+ const nested = horizontal ? layout.nest(n, [n, 1]) : layout.nest(1, [1, (layout.rowsForHeight(layout.cellW) + 1) * n]);
35
+ let res;
36
+ let idx = -1;
37
+ for (let i = 0; i < n; i++) {
38
+ const v = dial(
39
+ gui,
40
+ nested,
41
+ `${id}-${i}`,
42
+ min,
43
+ max,
44
+ prec,
45
+ vals[i],
46
+ label[i],
47
+ fmt,
48
+ info[i]
49
+ );
50
+ if (v !== void 0) {
51
+ res = v;
52
+ idx = i;
29
53
  }
30
- return res !== undefined ? [idx, res] : undefined;
54
+ }
55
+ return res !== void 0 ? [idx, res] : void 0;
31
56
  };
32
- export const dialRaw = (gui, id, x, y, w, h, min, max, prec, val, lx, ly, label, fmt, info) => {
33
- const r = Math.min(w, h) / 2;
34
- const pos = [x + w / 2, y + h / 2];
35
- const thetaGap = PI / 2;
36
- const startTheta = HALF_PI + thetaGap / 2;
37
- const key = hash([x, y, r]);
38
- gui.registerID(id, key);
39
- const bgShape = gui.resource(id, key, () => circle(pos, r, {}));
40
- const hover = isHoverSlider(gui, id, bgShape, "pointer");
41
- const draw = gui.draw;
42
- let v = val;
43
- let res;
44
- if (hover) {
45
- gui.hotID = id;
46
- if (gui.isMouseDown()) {
47
- gui.activeID = id;
48
- res = dialVal(gui.mouse, pos, startTheta, thetaGap, min, max, prec);
49
- }
50
- info && draw && tooltipRaw(gui, info);
57
+ const dialRaw = (gui, id, x, y, w, h, min, max, prec, val, lx, ly, label, fmt, info) => {
58
+ const r = Math.min(w, h) / 2;
59
+ const pos = [x + w / 2, y + h / 2];
60
+ const thetaGap = PI / 2;
61
+ const startTheta = HALF_PI + thetaGap / 2;
62
+ const key = hash([x, y, r]);
63
+ gui.registerID(id, key);
64
+ const bgShape = gui.resource(id, key, () => circle(pos, r, {}));
65
+ const hover = isHoverSlider(gui, id, bgShape, "pointer");
66
+ const draw = gui.draw;
67
+ let v = val;
68
+ let res;
69
+ if (hover) {
70
+ gui.hotID = id;
71
+ if (gui.isMouseDown()) {
72
+ gui.activeID = id;
73
+ res = dialVal(gui.mouse, pos, startTheta, thetaGap, min, max, prec);
51
74
  }
52
- const focused = gui.requestFocus(id);
53
- if (draw) {
54
- const valShape = gui.resource(id, v, () => line(cartesian2(null, [r, startTheta + (TAU - thetaGap) * norm(v, min, max)], pos), pos, {}));
55
- const valLabel = dialValueLabel(gui, id, key, v, x + lx, y + ly, label, fmt);
56
- bgShape.attribs.fill = gui.bgColor(hover || focused);
57
- bgShape.attribs.stroke = gui.focusColor(id);
58
- valShape.attribs.stroke = gui.fgColor(hover);
59
- valShape.attribs.weight = 2;
60
- gui.add(bgShape, valShape, valLabel);
61
- }
62
- if (focused &&
63
- (v = handleSlider1Keys(gui, min, max, prec, v)) !== undefined) {
64
- return v;
65
- }
66
- gui.lastID = id;
67
- return res;
75
+ info && draw && tooltipRaw(gui, info);
76
+ }
77
+ const focused = gui.requestFocus(id);
78
+ if (draw) {
79
+ const valShape = gui.resource(
80
+ id,
81
+ v,
82
+ () => line(
83
+ cartesian2(
84
+ null,
85
+ [r, startTheta + (TAU - thetaGap) * norm(v, min, max)],
86
+ pos
87
+ ),
88
+ pos,
89
+ {}
90
+ )
91
+ );
92
+ const valLabel = dialValueLabel(
93
+ gui,
94
+ id,
95
+ key,
96
+ v,
97
+ x + lx,
98
+ y + ly,
99
+ label,
100
+ fmt
101
+ );
102
+ bgShape.attribs.fill = gui.bgColor(hover || focused);
103
+ bgShape.attribs.stroke = gui.focusColor(id);
104
+ valShape.attribs.stroke = gui.fgColor(hover);
105
+ valShape.attribs.weight = 2;
106
+ gui.add(bgShape, valShape, valLabel);
107
+ }
108
+ if (focused && (v = handleSlider1Keys(gui, min, max, prec, v)) !== void 0) {
109
+ return v;
110
+ }
111
+ gui.lastID = id;
112
+ return res;
113
+ };
114
+ export {
115
+ dial,
116
+ dialGroup,
117
+ dialRaw
68
118
  };
@@ -5,76 +5,74 @@ import { clamp0 } from "@thi.ng/math/interval";
5
5
  import { hash } from "@thi.ng/vectors/hash";
6
6
  import { Key } from "../api.js";
7
7
  import { buttonH } from "./button.js";
8
- /**
9
- *
10
- * @param gui -
11
- * @param layout -
12
- * @param id -
13
- * @param sel -
14
- * @param items -
15
- * @param title -
16
- * @param info -
17
- */
18
- export const dropdown = (gui, layout, id, sel, items, title, info) => {
19
- const open = gui.state(id, () => false);
20
- const nested = isLayout(layout)
21
- ? layout.nest(1, [1, open ? items.length : 1])
22
- : gridLayout(layout.x, layout.y, layout.w, 1, layout.ch, layout.gap);
23
- let res;
24
- const box = nested.next();
25
- const { x, y, w, h } = box;
26
- const key = hash([x, y, w, h, ~~gui.disabled]);
27
- const tx = x + w - gui.theme.pad - 4;
28
- const ty = y + h / 2;
29
- const draw = gui.draw;
30
- if (open) {
31
- const bt = buttonH(gui, box, `${id}-title`, title);
32
- draw &&
33
- gui.add(gui.resource(id, key + 1, () => triangle(gui, tx, ty, true)));
34
- if (bt) {
35
- gui.setState(id, false);
8
+ const dropdown = (gui, layout, id, sel, items, title, info) => {
9
+ const open = gui.state(id, () => false);
10
+ const nested = isLayout(layout) ? layout.nest(1, [1, open ? items.length : 1]) : gridLayout(layout.x, layout.y, layout.w, 1, layout.ch, layout.gap);
11
+ let res;
12
+ const box = nested.next();
13
+ const { x, y, w, h } = box;
14
+ const key = hash([x, y, w, h, ~~gui.disabled]);
15
+ const tx = x + w - gui.theme.pad - 4;
16
+ const ty = y + h / 2;
17
+ const draw = gui.draw;
18
+ if (open) {
19
+ const bt = buttonH(gui, box, `${id}-title`, title);
20
+ draw && gui.add(
21
+ gui.resource(id, key + 1, () => triangle(gui, tx, ty, true))
22
+ );
23
+ if (bt) {
24
+ gui.setState(id, false);
25
+ } else {
26
+ for (let i = 0, n = items.length; i < n; i++) {
27
+ if (buttonH(gui, nested, `${id}-${i}`, items[i])) {
28
+ i !== sel && (res = i);
29
+ gui.setState(id, false);
36
30
  }
37
- else {
38
- for (let i = 0, n = items.length; i < n; i++) {
39
- if (buttonH(gui, nested, `${id}-${i}`, items[i])) {
40
- i !== sel && (res = i);
41
- gui.setState(id, false);
42
- }
43
- }
44
- if (gui.focusID.startsWith(`${id}-`)) {
45
- switch (gui.key) {
46
- case Key.ESC:
47
- gui.setState(id, false);
48
- break;
49
- case Key.UP:
50
- return update(gui, id, clamp0(sel - 1));
51
- case Key.DOWN:
52
- return update(gui, id, Math.min(items.length - 1, sel + 1));
53
- default:
54
- }
55
- }
31
+ }
32
+ if (gui.focusID.startsWith(`${id}-`)) {
33
+ switch (gui.key) {
34
+ case Key.ESC:
35
+ gui.setState(id, false);
36
+ break;
37
+ case Key.UP:
38
+ return update(gui, id, clamp0(sel - 1));
39
+ case Key.DOWN:
40
+ return update(
41
+ gui,
42
+ id,
43
+ Math.min(items.length - 1, sel + 1)
44
+ );
45
+ default:
56
46
  }
47
+ }
57
48
  }
58
- else {
59
- if (buttonH(gui, box, `${id}-${sel}`, items[sel], title, info)) {
60
- gui.setState(id, true);
61
- }
62
- draw &&
63
- gui.add(gui.resource(id, key + 2, () => triangle(gui, tx, ty, false)));
49
+ } else {
50
+ if (buttonH(gui, box, `${id}-${sel}`, items[sel], title, info)) {
51
+ gui.setState(id, true);
64
52
  }
65
- return res;
53
+ draw && gui.add(
54
+ gui.resource(id, key + 2, () => triangle(gui, tx, ty, false))
55
+ );
56
+ }
57
+ return res;
66
58
  };
67
59
  const update = (gui, id, next) => {
68
- gui.focusID = `${id}-${next}`;
69
- return next;
60
+ gui.focusID = `${id}-${next}`;
61
+ return next;
70
62
  };
71
63
  const triangle = (gui, x, y, open) => {
72
- const s = open ? 2 : -2;
73
- return polygon([
74
- [x - 4, y + s],
75
- [x + 4, y + s],
76
- [x, y - s],
77
- ], {
78
- fill: gui.textColor(false),
79
- });
64
+ const s = open ? 2 : -2;
65
+ return polygon(
66
+ [
67
+ [x - 4, y + s],
68
+ [x + 4, y + s],
69
+ [x, y - s]
70
+ ],
71
+ {
72
+ fill: gui.textColor(false)
73
+ }
74
+ );
75
+ };
76
+ export {
77
+ dropdown
80
78
  };
@@ -4,35 +4,44 @@ import { hash } from "@thi.ng/vectors/hash";
4
4
  import { mixHash } from "../hash.js";
5
5
  import { buttonRaw } from "./button.js";
6
6
  import { textLabelRaw } from "./textlabel.js";
7
- export const iconButton = (gui, layout, id, icon, iconW, iconH, label, info) => {
8
- const theme = gui.theme;
9
- const pad = theme.pad;
10
- const bodyW = label
11
- ? iconW + 3 * pad + gui.textWidth(label)
12
- : iconW + 2 * pad;
13
- const bodyH = iconH + pad;
14
- const { x, y, w, h } = isLayout(layout)
15
- ? layout.next(layout.spanForSize(bodyW, bodyH))
16
- : layout;
17
- const key = hash([x, y, w, h, ~~gui.disabled]);
18
- const mkIcon = (hover) => {
19
- const col = gui.textColor(hover);
20
- const pos = [x + pad, y + (h - iconH) / 2];
21
- return [
22
- "g",
23
- {
24
- translate: pos,
25
- fill: col,
26
- stroke: col,
27
- },
28
- icon,
29
- label
30
- ? textLabelRaw([
31
- iconW + pad,
32
- -(h - iconH) / 2 + h / 2 + theme.baseLine,
33
- ], { fill: col, stroke: "none" }, label)
34
- : undefined,
35
- ];
36
- };
37
- return buttonRaw(gui, id, gui.resource(id, key, () => rect([x, y], [w, h])), key, gui.resource(id, mixHash(key, `l${label}`), () => mkIcon(false)), gui.resource(id, mixHash(key, `lh${label}`), () => mkIcon(true)), info);
7
+ const iconButton = (gui, layout, id, icon, iconW, iconH, label, info) => {
8
+ const theme = gui.theme;
9
+ const pad = theme.pad;
10
+ const bodyW = label ? iconW + 3 * pad + gui.textWidth(label) : iconW + 2 * pad;
11
+ const bodyH = iconH + pad;
12
+ const { x, y, w, h } = isLayout(layout) ? layout.next(layout.spanForSize(bodyW, bodyH)) : layout;
13
+ const key = hash([x, y, w, h, ~~gui.disabled]);
14
+ const mkIcon = (hover) => {
15
+ const col = gui.textColor(hover);
16
+ const pos = [x + pad, y + (h - iconH) / 2];
17
+ return [
18
+ "g",
19
+ {
20
+ translate: pos,
21
+ fill: col,
22
+ stroke: col
23
+ },
24
+ icon,
25
+ label ? textLabelRaw(
26
+ [
27
+ iconW + pad,
28
+ -(h - iconH) / 2 + h / 2 + theme.baseLine
29
+ ],
30
+ { fill: col, stroke: "none" },
31
+ label
32
+ ) : void 0
33
+ ];
34
+ };
35
+ return buttonRaw(
36
+ gui,
37
+ id,
38
+ gui.resource(id, key, () => rect([x, y], [w, h])),
39
+ key,
40
+ gui.resource(id, mixHash(key, `l${label}`), () => mkIcon(false)),
41
+ gui.resource(id, mixHash(key, `lh${label}`), () => mkIcon(true)),
42
+ info
43
+ );
44
+ };
45
+ export {
46
+ iconButton
38
47
  };
@@ -10,42 +10,48 @@ import { hash } from "@thi.ng/vectors/hash";
10
10
  import { Key } from "../api.js";
11
11
  import { buttonRaw } from "./button.js";
12
12
  import { textLabelRaw } from "./textlabel.js";
13
- export const radialMenu = (gui, id, x, y, r, items, info) => {
14
- const n = items.length;
15
- const key = hash([x, y, r, n, ~~gui.disabled]);
16
- gui.registerID(id, key);
17
- const cells = gui.resource(id, key, () => [
18
- ...mapIndexed((i, pts) => {
19
- const cell = polygon(pts);
20
- const p = add2(null, [-gui.textWidth(items[i]) >> 1, gui.theme.baseLine], centroid(cell));
21
- return [
22
- cell,
23
- hash(p),
24
- textLabelRaw(p, gui.textColor(false), items[i]),
25
- textLabelRaw(p, gui.textColor(true), items[i]),
26
- ];
27
- }, triFan(vertices(circle([x, y], r), n))),
28
- ]);
29
- let res;
30
- let sel = -1;
31
- for (let i = 0; i < n; i++) {
32
- const cell = cells[i];
33
- const _id = id + i;
34
- buttonRaw(gui, _id, cell[0], cell[1], cell[2], cell[3], info[i]) &&
35
- (res = i);
36
- gui.focusID === _id && (sel = i);
13
+ const radialMenu = (gui, id, x, y, r, items, info) => {
14
+ const n = items.length;
15
+ const key = hash([x, y, r, n, ~~gui.disabled]);
16
+ gui.registerID(id, key);
17
+ const cells = gui.resource(id, key, () => [
18
+ ...mapIndexed((i, pts) => {
19
+ const cell = polygon(pts);
20
+ const p = add2(
21
+ null,
22
+ [-gui.textWidth(items[i]) >> 1, gui.theme.baseLine],
23
+ centroid(cell)
24
+ );
25
+ return [
26
+ cell,
27
+ hash(p),
28
+ textLabelRaw(p, gui.textColor(false), items[i]),
29
+ textLabelRaw(p, gui.textColor(true), items[i])
30
+ ];
31
+ }, triFan(vertices(circle([x, y], r), n)))
32
+ ]);
33
+ let res;
34
+ let sel = -1;
35
+ for (let i = 0; i < n; i++) {
36
+ const cell = cells[i];
37
+ const _id = id + i;
38
+ buttonRaw(gui, _id, cell[0], cell[1], cell[2], cell[3], info[i]) && (res = i);
39
+ gui.focusID === _id && (sel = i);
40
+ }
41
+ if (sel !== -1) {
42
+ switch (gui.key) {
43
+ case Key.UP:
44
+ case Key.RIGHT:
45
+ gui.focusID = id + mod(sel + 1, n);
46
+ break;
47
+ case Key.DOWN:
48
+ case Key.LEFT:
49
+ gui.focusID = id + mod(sel - 1, n);
50
+ default:
37
51
  }
38
- if (sel !== -1) {
39
- switch (gui.key) {
40
- case Key.UP:
41
- case Key.RIGHT:
42
- gui.focusID = id + mod(sel + 1, n);
43
- break;
44
- case Key.DOWN:
45
- case Key.LEFT:
46
- gui.focusID = id + mod(sel - 1, n);
47
- default:
48
- }
49
- }
50
- return res;
52
+ }
53
+ return res;
54
+ };
55
+ export {
56
+ radialMenu
51
57
  };
@@ -1,18 +1,23 @@
1
1
  import { isLayout } from "@thi.ng/layout/checks";
2
2
  import { gridLayout } from "@thi.ng/layout/grid-layout";
3
3
  import { toggle } from "./toggle.js";
4
- export const radio = (gui, layout, id, horizontal, sel, square, labels, info = []) => {
5
- const n = labels.length;
6
- const nested = isLayout(layout)
7
- ? horizontal
8
- ? layout.nest(n, [n, 1])
9
- : layout.nest(1, [1, n])
10
- : horizontal
11
- ? gridLayout(layout.x, layout.y, layout.w, n, layout.ch, layout.gap)
12
- : gridLayout(layout.x, layout.y, layout.w, 1, layout.ch, layout.gap);
13
- let res;
14
- for (let i = 0; i < n; i++) {
15
- toggle(gui, nested, `${id}-${i}`, sel === i, square, labels[i], info[i]) !== undefined && (res = i);
16
- }
17
- return res;
4
+ const radio = (gui, layout, id, horizontal, sel, square, labels, info = []) => {
5
+ const n = labels.length;
6
+ const nested = isLayout(layout) ? horizontal ? layout.nest(n, [n, 1]) : layout.nest(1, [1, n]) : horizontal ? gridLayout(layout.x, layout.y, layout.w, n, layout.ch, layout.gap) : gridLayout(layout.x, layout.y, layout.w, 1, layout.ch, layout.gap);
7
+ let res;
8
+ for (let i = 0; i < n; i++) {
9
+ toggle(
10
+ gui,
11
+ nested,
12
+ `${id}-${i}`,
13
+ sel === i,
14
+ square,
15
+ labels[i],
16
+ info[i]
17
+ ) !== void 0 && (res = i);
18
+ }
19
+ return res;
20
+ };
21
+ export {
22
+ radio
18
23
  };