With Resize on, the note that says how much the rounding stretches the
picture came and went every few pixels of a drag, and each time the picture
area and the rows under it jumped by a line.
- No note appears or changes while a pointer is down. A note the drag makes
untrue goes away, and the note for the new size comes once, 0.2 s after
the release. A click, a typed number or a new picture still shows its
note at once; a run of arrow clicks or a held arrow key shows the first
value and the last.
- The note has a line of its own that is there whenever Resize is on, with
text or empty, so a note that comes or goes moves nothing. The Even out
button no longer makes that line a pixel taller.
- The size line only grows while you drag: a step that comes and goes
("round to 8") no longer wraps it in and out.
- The full editor's size box and status panel show the same settled note,
and the status panel keeps its height mid-drag.
The image node and both video nodes share this code. Even out now works its
padding out at the click, because the note can be a moment behind the values.
54 lines
2.0 KiB
JavaScript
54 lines
2.0 KiB
JavaScript
// When is a run of changes over? A face asks this so that a note which
|
|
// depends on the values can wait for the hand to stop, instead of coming and
|
|
// going with every pixel of a drag. No DOM and no ComfyUI imports in here,
|
|
// so it runs under node:test (tests/settle.test.mjs).
|
|
//
|
|
// const rest = createSettle({ delay: 200, held: () => pointerIsDown, onSettle: showTheNote });
|
|
// rest.touch() a value changed. True: nothing else is going on, show it
|
|
// now. False: wait, onSettle says when.
|
|
// rest.release() the pointer came up; call it whenever held() turns false.
|
|
// rest.cancel() stop waiting (the picture or the face is gone).
|
|
//
|
|
// The rules:
|
|
// - A change with the pointer up and nothing waiting shows at once: a click,
|
|
// a typed number, a new picture.
|
|
// - While a pointer is held nothing settles, however long the hand rests.
|
|
// - Then onSettle runs once, `delay` ms after the last change or after the
|
|
// release, whichever came later. A burst of changes with no pointer (a
|
|
// held arrow key) shows its first value at once and its last one after.
|
|
export function createSettle({ delay = 200, held = () => false, onSettle = null, setTimer = setTimeout, clearTimer = clearTimeout } = {}) {
|
|
let timer = null;
|
|
// The wait ran out while a pointer was still held: release() starts it again.
|
|
let waiting = false;
|
|
// A change was held back, so onSettle has something to show.
|
|
let owed = false;
|
|
const arm = () => {
|
|
if (timer !== null) clearTimer(timer);
|
|
waiting = false;
|
|
timer = setTimer(() => {
|
|
timer = null;
|
|
if (held()) { waiting = true; return; }
|
|
if (!owed) return;
|
|
owed = false;
|
|
onSettle?.();
|
|
}, delay);
|
|
};
|
|
return {
|
|
touch() {
|
|
const now = !held() && timer === null && !waiting;
|
|
if (!now) owed = true;
|
|
arm();
|
|
return now;
|
|
},
|
|
release() {
|
|
if (timer !== null || waiting) arm();
|
|
},
|
|
cancel() {
|
|
if (timer !== null) clearTimer(timer);
|
|
timer = null;
|
|
waiting = false;
|
|
owed = false;
|
|
},
|
|
};
|
|
}
|