@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.
- package/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/api.js +94 -84
- package/behaviors/button.js +26 -22
- package/behaviors/dial.js +12 -4
- package/behaviors/slider.js +46 -43
- package/behaviors/text.js +75 -70
- package/components/button.js +64 -41
- package/components/dial.js +102 -52
- package/components/dropdown.js +62 -64
- package/components/icon-button.js +40 -31
- package/components/radial-menu.js +43 -37
- package/components/radio.js +19 -14
- package/components/ring.js +123 -79
- package/components/sliderh.js +96 -46
- package/components/sliderv.js +100 -53
- package/components/textfield.js +83 -44
- package/components/textlabel.js +28 -14
- package/components/toggle.js +45 -38
- package/components/tooltip.js +16 -6
- package/components/xypad.js +89 -73
- package/events.js +36 -47
- package/gui.js +400 -415
- package/hash.js +17 -45
- package/layout.js +4 -1
- package/package.json +16 -13
package/components/ring.js
CHANGED
|
@@ -12,87 +12,131 @@ import { dialVal } from "../behaviors/dial.js";
|
|
|
12
12
|
import { handleSlider1Keys } from "../behaviors/slider.js";
|
|
13
13
|
import { dialValueLabel } from "./textlabel.js";
|
|
14
14
|
import { tooltipRaw } from "./tooltip.js";
|
|
15
|
-
const ringHeight = (w, thetaGap) =>
|
|
16
|
-
const arcVerts = (o, r, start, end, thetaRes = 12) => r > 1
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
15
|
+
const ringHeight = (w, thetaGap) => w / 2 * (1 + Math.sin(HALF_PI + thetaGap / 2));
|
|
16
|
+
const arcVerts = (o, r, start, end, thetaRes = 12) => r > 1 ? map(
|
|
17
|
+
(t) => cartesian2(null, [r, mix(start, end, t)], o),
|
|
18
|
+
normRange(
|
|
19
|
+
Math.max(1, Math.abs(end - start) / (PI / thetaRes)) | 0
|
|
20
|
+
)
|
|
21
|
+
) : [o];
|
|
22
|
+
const ring = (gui, layout, id, min, max, prec, val, thetaGap, rscale, label, fmt, info) => {
|
|
23
|
+
let h;
|
|
24
|
+
let box;
|
|
25
|
+
if (isLayout(layout)) {
|
|
26
|
+
h = ringHeight(layout.cellW, thetaGap);
|
|
27
|
+
box = layout.next([1, layout.rowsForHeight(h) + 1]);
|
|
28
|
+
} else {
|
|
29
|
+
h = ringHeight(layout.cw, thetaGap);
|
|
30
|
+
box = layout;
|
|
31
|
+
}
|
|
32
|
+
return ringRaw(
|
|
33
|
+
gui,
|
|
34
|
+
id,
|
|
35
|
+
box.x,
|
|
36
|
+
box.y,
|
|
37
|
+
box.w,
|
|
38
|
+
h,
|
|
39
|
+
min,
|
|
40
|
+
max,
|
|
41
|
+
prec,
|
|
42
|
+
val,
|
|
43
|
+
thetaGap,
|
|
44
|
+
rscale,
|
|
45
|
+
0,
|
|
46
|
+
h + box.ch / 2 + gui.theme.baseLine,
|
|
47
|
+
label,
|
|
48
|
+
fmt,
|
|
49
|
+
info
|
|
50
|
+
);
|
|
31
51
|
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
const ringGroup = (gui, layout, id, min, max, prec, horizontal, thetaGap, rscale, vals, label, fmt, info = []) => {
|
|
53
|
+
const n = vals.length;
|
|
54
|
+
const nested = horizontal ? layout.nest(n, [n, 1]) : layout.nest(1, [
|
|
55
|
+
1,
|
|
56
|
+
(layout.rowsForHeight(ringHeight(layout.cellW, thetaGap)) + 1) * n
|
|
57
|
+
]);
|
|
58
|
+
let res;
|
|
59
|
+
let idx = -1;
|
|
60
|
+
for (let i = 0; i < n; i++) {
|
|
61
|
+
const v = ring(
|
|
62
|
+
gui,
|
|
63
|
+
nested,
|
|
64
|
+
`${id}-${i}`,
|
|
65
|
+
min,
|
|
66
|
+
max,
|
|
67
|
+
prec,
|
|
68
|
+
vals[i],
|
|
69
|
+
thetaGap,
|
|
70
|
+
rscale,
|
|
71
|
+
label[i],
|
|
72
|
+
fmt,
|
|
73
|
+
info[i]
|
|
74
|
+
);
|
|
75
|
+
if (v !== void 0) {
|
|
76
|
+
res = v;
|
|
77
|
+
idx = i;
|
|
49
78
|
}
|
|
50
|
-
|
|
79
|
+
}
|
|
80
|
+
return res !== void 0 ? [idx, res] : void 0;
|
|
51
81
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
res = dialVal(gui.mouse, pos, startTheta, thetaGap, min, max, prec);
|
|
71
|
-
}
|
|
72
|
-
info && draw && tooltipRaw(gui, info);
|
|
73
|
-
}
|
|
74
|
-
const focused = gui.requestFocus(id);
|
|
75
|
-
if (draw) {
|
|
76
|
-
const valTheta = startTheta + (TAU - thetaGap) * norm(v, min, max);
|
|
77
|
-
const r2 = r * rscale;
|
|
78
|
-
// adaptive arc resolution
|
|
79
|
-
const numV = fitClamped(r, 15, 80, 12, 30);
|
|
80
|
-
const shape = (max) => () => polygon([
|
|
81
|
-
...arcVerts(pos, r, startTheta, max, numV),
|
|
82
|
-
...arcVerts(pos, r2, max, startTheta, numV),
|
|
83
|
-
], {});
|
|
84
|
-
const bgShape = gui.resource(id, key, shape(endTheta));
|
|
85
|
-
const valShape = gui.resource(id, v, shape(valTheta));
|
|
86
|
-
const valLabel = dialValueLabel(gui, id, key, v, x + lx, y + ly, label, fmt);
|
|
87
|
-
bgShape.attribs.fill = gui.bgColor(hover || focused);
|
|
88
|
-
bgShape.attribs.stroke = gui.focusColor(id);
|
|
89
|
-
valShape.attribs.fill = gui.fgColor(hover);
|
|
90
|
-
gui.add(bgShape, valShape, valLabel);
|
|
82
|
+
const ringRaw = (gui, id, x, y, w, h, min, max, prec, val, thetaGap, rscale, lx, ly, label, fmt, info) => {
|
|
83
|
+
const r = w / 2;
|
|
84
|
+
const key = hash([x, y, r]);
|
|
85
|
+
gui.registerID(id, key);
|
|
86
|
+
const pos = [x + r, y + r];
|
|
87
|
+
const startTheta = HALF_PI + thetaGap / 2;
|
|
88
|
+
const endTheta = HALF_PI + TAU - thetaGap / 2;
|
|
89
|
+
const draw = gui.draw;
|
|
90
|
+
const aid = gui.activeID;
|
|
91
|
+
const hover = !gui.disabled && (aid === id || aid === "" && pointInRect(gui.mouse, [x, y], [w, h]));
|
|
92
|
+
let v = val;
|
|
93
|
+
let res;
|
|
94
|
+
if (hover) {
|
|
95
|
+
gui.setCursor("pointer");
|
|
96
|
+
gui.hotID = id;
|
|
97
|
+
if (gui.isMouseDown()) {
|
|
98
|
+
gui.activeID = id;
|
|
99
|
+
res = dialVal(gui.mouse, pos, startTheta, thetaGap, min, max, prec);
|
|
91
100
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
info && draw && tooltipRaw(gui, info);
|
|
102
|
+
}
|
|
103
|
+
const focused = gui.requestFocus(id);
|
|
104
|
+
if (draw) {
|
|
105
|
+
const valTheta = startTheta + (TAU - thetaGap) * norm(v, min, max);
|
|
106
|
+
const r2 = r * rscale;
|
|
107
|
+
const numV = fitClamped(r, 15, 80, 12, 30);
|
|
108
|
+
const shape = (max2) => () => polygon(
|
|
109
|
+
[
|
|
110
|
+
...arcVerts(pos, r, startTheta, max2, numV),
|
|
111
|
+
...arcVerts(pos, r2, max2, startTheta, numV)
|
|
112
|
+
],
|
|
113
|
+
{}
|
|
114
|
+
);
|
|
115
|
+
const bgShape = gui.resource(id, key, shape(endTheta));
|
|
116
|
+
const valShape = gui.resource(id, v, shape(valTheta));
|
|
117
|
+
const valLabel = dialValueLabel(
|
|
118
|
+
gui,
|
|
119
|
+
id,
|
|
120
|
+
key,
|
|
121
|
+
v,
|
|
122
|
+
x + lx,
|
|
123
|
+
y + ly,
|
|
124
|
+
label,
|
|
125
|
+
fmt
|
|
126
|
+
);
|
|
127
|
+
bgShape.attribs.fill = gui.bgColor(hover || focused);
|
|
128
|
+
bgShape.attribs.stroke = gui.focusColor(id);
|
|
129
|
+
valShape.attribs.fill = gui.fgColor(hover);
|
|
130
|
+
gui.add(bgShape, valShape, valLabel);
|
|
131
|
+
}
|
|
132
|
+
if (focused && (v = handleSlider1Keys(gui, min, max, prec, v)) !== void 0) {
|
|
133
|
+
return v;
|
|
134
|
+
}
|
|
135
|
+
gui.lastID = id;
|
|
136
|
+
return res;
|
|
137
|
+
};
|
|
138
|
+
export {
|
|
139
|
+
ring,
|
|
140
|
+
ringGroup,
|
|
141
|
+
ringRaw
|
|
98
142
|
};
|
package/components/sliderh.js
CHANGED
|
@@ -1,58 +1,108 @@
|
|
|
1
1
|
import { rect } from "@thi.ng/geom/rect";
|
|
2
2
|
import { fit, norm } from "@thi.ng/math/fit";
|
|
3
3
|
import { hash } from "@thi.ng/vectors/hash";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
handleSlider1Keys,
|
|
6
|
+
isHoverSlider,
|
|
7
|
+
slider1Val
|
|
8
|
+
} from "../behaviors/slider.js";
|
|
5
9
|
import { valHash } from "../hash.js";
|
|
6
10
|
import { layoutBox } from "../layout.js";
|
|
7
11
|
import { textLabelRaw } from "./textlabel.js";
|
|
8
12
|
import { tooltipRaw } from "./tooltip.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
const sliderH = (gui, layout, id, min, max, prec, val, label, fmt, info) => {
|
|
14
|
+
const box = layoutBox(layout);
|
|
15
|
+
return sliderHRaw(
|
|
16
|
+
gui,
|
|
17
|
+
id,
|
|
18
|
+
box.x,
|
|
19
|
+
box.y,
|
|
20
|
+
box.w,
|
|
21
|
+
box.h,
|
|
22
|
+
min,
|
|
23
|
+
max,
|
|
24
|
+
prec,
|
|
25
|
+
val,
|
|
26
|
+
label,
|
|
27
|
+
fmt,
|
|
28
|
+
info
|
|
29
|
+
);
|
|
12
30
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
const sliderHGroup = (gui, layout, id, min, max, prec, horizontal, vals, label, fmt, info = []) => {
|
|
32
|
+
const n = vals.length;
|
|
33
|
+
const nested = horizontal ? layout.nest(n, [n, 1]) : layout.nest(1, [1, n]);
|
|
34
|
+
let res;
|
|
35
|
+
let idx = -1;
|
|
36
|
+
for (let i = 0; i < n; i++) {
|
|
37
|
+
const v = sliderH(
|
|
38
|
+
gui,
|
|
39
|
+
nested,
|
|
40
|
+
`${id}-${i}`,
|
|
41
|
+
min,
|
|
42
|
+
max,
|
|
43
|
+
prec,
|
|
44
|
+
vals[i],
|
|
45
|
+
label[i],
|
|
46
|
+
fmt,
|
|
47
|
+
info[i]
|
|
48
|
+
);
|
|
49
|
+
if (v !== void 0) {
|
|
50
|
+
res = v;
|
|
51
|
+
idx = i;
|
|
24
52
|
}
|
|
25
|
-
|
|
53
|
+
}
|
|
54
|
+
return res !== void 0 ? [idx, res] : void 0;
|
|
26
55
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
const sliderHRaw = (gui, id, x, y, w, h, min, max, prec, val, label, fmt, info) => {
|
|
57
|
+
const theme = gui.theme;
|
|
58
|
+
const key = hash([x, y, w, h]);
|
|
59
|
+
gui.registerID(id, key);
|
|
60
|
+
const box = gui.resource(id, key, () => rect([x, y], [w, h], {}));
|
|
61
|
+
const hover = isHoverSlider(gui, id, box);
|
|
62
|
+
const draw = gui.draw;
|
|
63
|
+
let v = val;
|
|
64
|
+
let res;
|
|
65
|
+
if (hover) {
|
|
66
|
+
if (gui.isMouseDown()) {
|
|
67
|
+
gui.activeID = id;
|
|
68
|
+
res = slider1Val(
|
|
69
|
+
fit(gui.mouse[0], x, x + w - 1, min, max),
|
|
70
|
+
min,
|
|
71
|
+
max,
|
|
72
|
+
prec
|
|
73
|
+
);
|
|
42
74
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
75
|
+
info && draw && tooltipRaw(gui, info);
|
|
76
|
+
}
|
|
77
|
+
const focused = gui.requestFocus(id);
|
|
78
|
+
if (draw) {
|
|
79
|
+
const valueBox = gui.resource(
|
|
80
|
+
id,
|
|
81
|
+
v,
|
|
82
|
+
() => rect([x, y], [1 + norm(v, min, max) * (w - 1), h], {})
|
|
83
|
+
);
|
|
84
|
+
const valLabel = gui.resource(
|
|
85
|
+
id,
|
|
86
|
+
valHash(key, v, gui.disabled),
|
|
87
|
+
() => textLabelRaw(
|
|
88
|
+
[x + theme.pad, y + h / 2 + theme.baseLine],
|
|
89
|
+
gui.textColor(false),
|
|
90
|
+
(label ? label + " " : "") + (fmt ? fmt(v) : v)
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
box.attribs.fill = gui.bgColor(hover || focused);
|
|
94
|
+
box.attribs.stroke = gui.focusColor(id);
|
|
95
|
+
valueBox.attribs.fill = gui.fgColor(hover);
|
|
96
|
+
gui.add(box, valueBox, valLabel);
|
|
97
|
+
}
|
|
98
|
+
if (focused && (v = handleSlider1Keys(gui, min, max, prec, v)) !== void 0) {
|
|
99
|
+
return v;
|
|
100
|
+
}
|
|
101
|
+
gui.lastID = id;
|
|
102
|
+
return res;
|
|
103
|
+
};
|
|
104
|
+
export {
|
|
105
|
+
sliderH,
|
|
106
|
+
sliderHGroup,
|
|
107
|
+
sliderHRaw
|
|
58
108
|
};
|
package/components/sliderv.js
CHANGED
|
@@ -2,65 +2,112 @@ import { rect } from "@thi.ng/geom/rect";
|
|
|
2
2
|
import { fit, norm } from "@thi.ng/math/fit";
|
|
3
3
|
import { ZERO2 } from "@thi.ng/vectors/api";
|
|
4
4
|
import { hash } from "@thi.ng/vectors/hash";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
handleSlider1Keys,
|
|
7
|
+
isHoverSlider,
|
|
8
|
+
slider1Val
|
|
9
|
+
} from "../behaviors/slider.js";
|
|
6
10
|
import { valHash } from "../hash.js";
|
|
7
11
|
import { layoutBox } from "../layout.js";
|
|
8
12
|
import { textLabelRaw, textTransformV } from "./textlabel.js";
|
|
9
13
|
import { tooltipRaw } from "./tooltip.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
const sliderV = (gui, layout, id, min, max, prec, val, rows, label, fmt, info) => {
|
|
15
|
+
const box = layoutBox(layout, [1, rows]);
|
|
16
|
+
return sliderVRaw(
|
|
17
|
+
gui,
|
|
18
|
+
id,
|
|
19
|
+
box.x,
|
|
20
|
+
box.y,
|
|
21
|
+
box.w,
|
|
22
|
+
box.h,
|
|
23
|
+
min,
|
|
24
|
+
max,
|
|
25
|
+
prec,
|
|
26
|
+
val,
|
|
27
|
+
label,
|
|
28
|
+
fmt,
|
|
29
|
+
info
|
|
30
|
+
);
|
|
13
31
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
const sliderVGroup = (gui, layout, id, min, max, prec, vals, rows, label, fmt, info = []) => {
|
|
33
|
+
const n = vals.length;
|
|
34
|
+
const nested = layout.nest(n, [1, rows]);
|
|
35
|
+
let res;
|
|
36
|
+
let idx = -1;
|
|
37
|
+
for (let i = 0; i < n; i++) {
|
|
38
|
+
const v = sliderV(
|
|
39
|
+
gui,
|
|
40
|
+
nested,
|
|
41
|
+
`${id}-${i}`,
|
|
42
|
+
min,
|
|
43
|
+
max,
|
|
44
|
+
prec,
|
|
45
|
+
vals[i],
|
|
46
|
+
rows,
|
|
47
|
+
label[i],
|
|
48
|
+
fmt,
|
|
49
|
+
info[i]
|
|
50
|
+
);
|
|
51
|
+
if (v !== void 0) {
|
|
52
|
+
res = v;
|
|
53
|
+
idx = i;
|
|
25
54
|
}
|
|
26
|
-
|
|
55
|
+
}
|
|
56
|
+
return res !== void 0 ? [idx, res] : void 0;
|
|
27
57
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
const sliderVRaw = (gui, id, x, y, w, h, min, max, prec, val, label, fmt, info) => {
|
|
59
|
+
const theme = gui.theme;
|
|
60
|
+
const key = hash([x, y, w, h]);
|
|
61
|
+
gui.registerID(id, key);
|
|
62
|
+
const box = gui.resource(id, key, () => rect([x, y], [w, h], {}));
|
|
63
|
+
const ymax = y + h;
|
|
64
|
+
const hover = isHoverSlider(gui, id, box, "ns-resize");
|
|
65
|
+
const draw = gui.draw;
|
|
66
|
+
let v = val;
|
|
67
|
+
let res;
|
|
68
|
+
if (hover) {
|
|
69
|
+
if (gui.isMouseDown()) {
|
|
70
|
+
gui.activeID = id;
|
|
71
|
+
res = slider1Val(
|
|
72
|
+
fit(gui.mouse[1], ymax - 1, y, min, max),
|
|
73
|
+
min,
|
|
74
|
+
max,
|
|
75
|
+
prec
|
|
76
|
+
);
|
|
44
77
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
78
|
+
info && draw && tooltipRaw(gui, info);
|
|
79
|
+
}
|
|
80
|
+
const focused = gui.requestFocus(id);
|
|
81
|
+
if (draw) {
|
|
82
|
+
const valueBox = gui.resource(id, v, () => {
|
|
83
|
+
const nh = norm(v, min, max) * (h - 1);
|
|
84
|
+
return rect([x, ymax - nh], [w, nh], {});
|
|
85
|
+
});
|
|
86
|
+
const valLabel = gui.resource(
|
|
87
|
+
id,
|
|
88
|
+
valHash(key, v, gui.disabled),
|
|
89
|
+
() => textLabelRaw(
|
|
90
|
+
ZERO2,
|
|
91
|
+
{
|
|
92
|
+
transform: textTransformV(theme, x, y, w, h),
|
|
93
|
+
fill: gui.textColor(false)
|
|
94
|
+
},
|
|
95
|
+
(label ? label + " " : "") + (fmt ? fmt(v) : v)
|
|
96
|
+
)
|
|
97
|
+
);
|
|
98
|
+
valueBox.attribs.fill = gui.fgColor(hover);
|
|
99
|
+
box.attribs.fill = gui.bgColor(hover || focused);
|
|
100
|
+
box.attribs.stroke = gui.focusColor(id);
|
|
101
|
+
gui.add(box, valueBox, valLabel);
|
|
102
|
+
}
|
|
103
|
+
if (focused && (v = handleSlider1Keys(gui, min, max, prec, v)) !== void 0) {
|
|
104
|
+
return v;
|
|
105
|
+
}
|
|
106
|
+
gui.lastID = id;
|
|
107
|
+
return res;
|
|
108
|
+
};
|
|
109
|
+
export {
|
|
110
|
+
sliderV,
|
|
111
|
+
sliderVGroup,
|
|
112
|
+
sliderVRaw
|
|
66
113
|
};
|
package/components/textfield.js
CHANGED
|
@@ -6,52 +6,91 @@ import { handleTextfieldKeys } from "../behaviors/text.js";
|
|
|
6
6
|
import { layoutBox } from "../layout.js";
|
|
7
7
|
import { textLabelRaw } from "./textlabel.js";
|
|
8
8
|
import { tooltipRaw } from "./tooltip.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const textField = (gui, layout, id, label, filter = () => true, info) => {
|
|
10
|
+
const box = layoutBox(layout);
|
|
11
|
+
return textFieldRaw(
|
|
12
|
+
gui,
|
|
13
|
+
id,
|
|
14
|
+
box.x,
|
|
15
|
+
box.y,
|
|
16
|
+
box.w,
|
|
17
|
+
box.h,
|
|
18
|
+
label,
|
|
19
|
+
filter,
|
|
20
|
+
info
|
|
21
|
+
);
|
|
12
22
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
const textFieldRaw = (gui, id, x, y, w, h, txt, filter = () => true, info) => {
|
|
24
|
+
const theme = gui.theme;
|
|
25
|
+
const cw = theme.charWidth;
|
|
26
|
+
const pad = theme.pad;
|
|
27
|
+
const maxLen = Math.max(1, (w - pad * 2) / cw | 0);
|
|
28
|
+
const txtLen = txt.length;
|
|
29
|
+
const state = gui.state(id, () => ({ cursor: 0, offset: 0 }));
|
|
30
|
+
const drawTxt = txt.substring(state.offset, state.offset + maxLen);
|
|
31
|
+
const key = hash([x, y, w, h]);
|
|
32
|
+
gui.registerID(id, key);
|
|
33
|
+
const box = gui.resource(id, key, () => rect([x, y], [w, h], {}));
|
|
34
|
+
const hover = isHoverSlider(gui, id, box, "text");
|
|
35
|
+
const draw = gui.draw;
|
|
36
|
+
if (hover) {
|
|
37
|
+
if (gui.isMouseDown()) {
|
|
38
|
+
gui.activeID = id;
|
|
39
|
+
state.cursor = Math.min(
|
|
40
|
+
Math.round(
|
|
41
|
+
fitClamped(
|
|
42
|
+
gui.mouse[0],
|
|
43
|
+
x + pad,
|
|
44
|
+
x + w - pad,
|
|
45
|
+
state.offset,
|
|
46
|
+
state.offset + maxLen
|
|
47
|
+
)
|
|
48
|
+
),
|
|
49
|
+
txtLen
|
|
50
|
+
);
|
|
32
51
|
}
|
|
33
|
-
|
|
52
|
+
info && draw && tooltipRaw(gui, info);
|
|
53
|
+
}
|
|
54
|
+
const focused = gui.requestFocus(id);
|
|
55
|
+
if (draw) {
|
|
56
|
+
box.attribs.fill = gui.bgColor(focused || hover);
|
|
57
|
+
box.attribs.stroke = gui.focusColor(id);
|
|
58
|
+
gui.add(
|
|
59
|
+
box,
|
|
60
|
+
textLabelRaw(
|
|
61
|
+
[x + pad, y + h / 2 + theme.baseLine],
|
|
62
|
+
gui.textColor(focused),
|
|
63
|
+
drawTxt
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (focused) {
|
|
68
|
+
const { cursor, offset } = state;
|
|
69
|
+
const drawCursor = Math.min(cursor - offset, maxLen);
|
|
34
70
|
if (draw) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
71
|
+
const xx = x + pad + drawCursor * cw;
|
|
72
|
+
gui.time * theme.cursorBlink % 1 < 0.5 && gui.add([
|
|
73
|
+
"line",
|
|
74
|
+
{ stroke: theme.cursor },
|
|
75
|
+
[xx, y + 4],
|
|
76
|
+
[xx, y + h - 4]
|
|
77
|
+
]);
|
|
38
78
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
gui.lastID = id;
|
|
79
|
+
const res = handleTextfieldKeys(
|
|
80
|
+
gui,
|
|
81
|
+
state,
|
|
82
|
+
filter,
|
|
83
|
+
txt,
|
|
84
|
+
cursor,
|
|
85
|
+
drawCursor,
|
|
86
|
+
maxLen
|
|
87
|
+
);
|
|
88
|
+
if (res !== void 0)
|
|
89
|
+
return res;
|
|
90
|
+
}
|
|
91
|
+
gui.lastID = id;
|
|
92
|
+
};
|
|
93
|
+
export {
|
|
94
|
+
textField,
|
|
95
|
+
textFieldRaw
|
|
57
96
|
};
|