UNPKG

@thi.ng/imgui

Version:

Immediate mode GUI with flexible state handling & data only shape output

103 lines (102 loc) 2.48 kB
import { rect } from "@thi.ng/geom/rect"; import { fitClamped } from "@thi.ng/math/fit"; import { hash } from "@thi.ng/vectors/hash"; import { isHoverSlider } from "../behaviors/slider.js"; import { handleTextfieldKeys } from "../behaviors/text.js"; import { layoutBox } from "../layout.js"; import { textLabelRaw } from "./textlabel.js"; import { tooltipRaw } from "./tooltip.js"; const textField = ({ gui, layout, id, value, info, filter = () => true }) => { const box = layoutBox(layout); return textFieldRaw( gui, id, box.x, box.y, box.w, box.h, value, filter, info ); }; const textFieldRaw = (gui, id, x, y, w, h, txt, filter = () => true, info) => { const theme = gui.theme; const cw = theme.charWidth; const pad = theme.pad; const maxLen = Math.max(1, (w - pad * 2) / cw | 0); const txtLen = txt.length; const state = gui.state(id, () => ({ cursor: 0, offset: 0 })); const drawTxt = txt.substring(state.offset, state.offset + maxLen); const key = hash([x, y, w, h]); gui.registerID(id, key); const box = gui.resource(id, key, () => rect([x, y], [w, h], {})); const hover = isHoverSlider(gui, id, box, "text"); const draw = gui.draw; if (hover) { if (gui.isMouseDown()) { gui.activeID = id; state.cursor = Math.min( Math.round( fitClamped( gui.mouse[0], x + pad, x + w - pad, state.offset, state.offset + maxLen ) ), txtLen ); } info && draw && tooltipRaw(gui, info); } const focused = gui.requestFocus(id); if (draw) { box.attribs.fill = gui.bgColor(focused || hover); box.attribs.stroke = gui.focusColor(id); gui.add( box, textLabelRaw( [x + pad, y + h / 2 + theme.baseLine], gui.textColor(focused), drawTxt ) ); } if (focused) { const { cursor, offset } = state; const drawCursor = Math.min(cursor - offset, maxLen); if (draw) { const xx = x + pad + drawCursor * cw; gui.time * theme.cursorBlink % 1 < 0.5 && gui.add([ "line", { stroke: theme.cursor }, [xx, y + 4], [xx, y + h - 4] ]); } const res = handleTextfieldKeys( gui, state, filter, txt, cursor, drawCursor, maxLen ); if (res !== void 0) return res; } gui.lastID = id; }; export { textField, textFieldRaw };