Show where an inspector row can be dragged and answer the pointer
After #310 rows could be dragged by their mark, but nothing said which marks take a drag, and the pointer on one changed nothing but the cursor. - A mark that drags is now a Grip: the same widget wrapped, the same size, so the value column stays where it was. Once sortBlocks takes it, it carries six faint dots at its left edge. - Marks that cannot drag stay plain: the variables of a placed object and the fields of a typed struct show no dots. - With the pointer on a grip its dots light up and the whole block that would move is washed in the accent colour, a struct with its fields. While the block is carried the wash gives way to the dimming, and the grip stays lit. - While a block is carried the other grips let the pointer pass: no lit dots, no wash. Every grip of the column shows grabbing instead of grab until the drop. - The wash first used controlHover like list rows. In the inspector it is darker than the panel and vanished next to the dark fields, so it became the accent at 15 percent, the colour of the drop line. - __gm.inspectorMark also reports the dots: none, idle or lit. Tests: - Gate on melektaus-atx: 236 files, 3576 tests (+4 in block-drag.test.ts, one of them a drag passing over another grip). - e2e 22: 40 checks (+1, sum 1740). 22f-iii reads idle dots, moves the mouse onto the mark and reads them lit. - Two counter-checks bite: no wash on hover fails 1 test, grips never made grabbable fail 3. A third: hover ignoring the drag fails 1. - Screenshots of a lit single row and a lit struct block looked at. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2c19c89878
commit
c74b6b1cab
10 files changed
+270
-23
No files matched your search
@@ -0,0 +1,63 @@
|
||||
import { Graphics } from 'pixi.js';
|
||||
import { crisp } from '../pixelGrid';
|
||||
import { Theme } from '../Theme';
|
||||
import { type Size, Widget } from '../Widget';
|
||||
|
||||
const DOT = 2;
|
||||
const DOT_GAP = 1;
|
||||
const IDLE_ALPHA = 0.5;
|
||||
|
||||
/**
|
||||
* What a row is taken hold of by to drag it to another place (#310): its mark, the same size. Once
|
||||
* `sortBlocks` makes it grabbable it carries a column of dots at its left edge, lit while the
|
||||
* pointer is on it.
|
||||
*/
|
||||
export class Grip extends Widget {
|
||||
private readonly dots = crisp(new Graphics());
|
||||
private grabbable = false;
|
||||
private lit = false;
|
||||
|
||||
constructor(readonly content: Widget) {
|
||||
super();
|
||||
// One target for over/out: moving onto the mark must not read as leaving the grip.
|
||||
this.interactiveChildren = false;
|
||||
this.addChild(this.dots, content);
|
||||
}
|
||||
|
||||
override measure(): Size {
|
||||
const size = this.content.measure();
|
||||
return { w: Math.max(this.minWidth, size.w), h: Math.max(this.minHeight, size.h) };
|
||||
}
|
||||
|
||||
override layout(): void {
|
||||
this.content.resize(this.w, this.h);
|
||||
}
|
||||
|
||||
setGrabbable(on: boolean): void {
|
||||
if (this.grabbable === on) return;
|
||||
this.grabbable = on;
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
setLit(on: boolean): void {
|
||||
if (this.lit === on) return;
|
||||
this.lit = on;
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
/** Whether the dots are drawn, and lit (test hook). */
|
||||
get dotsShown(): 'none' | 'idle' | 'lit' {
|
||||
return this.grabbable ? (this.lit ? 'lit' : 'idle') : 'none';
|
||||
}
|
||||
|
||||
override redraw(): void {
|
||||
this.dots.clear();
|
||||
if (!this.grabbable) return;
|
||||
const top = Math.round(this.h / 2 - (3 * DOT + 2 * DOT_GAP) / 2);
|
||||
for (let col = 0; col < 2; col++)
|
||||
for (let row = 0; row < 3; row++)
|
||||
this.dots.rect(col * (DOT + DOT_GAP), top + row * (DOT + DOT_GAP), DOT, DOT);
|
||||
this.dots.fill(this.lit ? Theme.colors.text : Theme.colors.textMuted);
|
||||
this.dots.alpha = this.lit ? 1 : IDLE_ALPHA;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user