Probably not a coincidence b/c of his posts, but I was also interacting with him on Twitter this week.
I made huge advances in the new version of Ceu this week.
I may write about it soon.
Here's a working implementation of his problem in the upcoming version of Ceu:
type Point = [_int,_int] -- [x,y] for tuples
type Dims = [_int,_int] -- no "Int" type yet, using native type
type Rect = [Point,Dims]
-- rectangle to control
var rect: Rect = [xy,wh]
where {
var xy: Point = [_10,_10]
var wh: Dims = [_5,_5]
}
-- drag and drop, or click behavior
spawn {
-- restart after each detection
loop {
-- detect the first rect click and hold the offset to its center
var dxy: Dims
{
var mouse: Point
await evt?UMouseButtonDown until isPointInsideRect[mouse,rect]
where {
set mouse = evt!UMouseButtonDown.2
}
set dxy = [ sub [rect.1.1,mouse.1], sub [rect.1.2,mouse.2] ]
}
-- either cancel, click, or drag/drop
paror {
-- cancel on any key
var orig = rect
await evt?UKeyDown -- TODO: I should detect only ESC here
set rect = orig -- move back to original position
output std _("Cancelled!"):_(char*)
} with {
-- drag/drop: must be before click (see below)
await evt?UMouseMotion
output std _("Dragging..."):_(char*)
var mouse = evt!UMouseMotion
paror {
-- abort on mouse up
await evt?UMouseButtonUp
output std _("Dropped!"):_(char*)
} with {
-- track mouse motion and move the rectangle
loop {
set rect = [pt, rect.2]
where {
var pt: Point = [ add [mouse.1,dxy.1], add [mouse.2,dxy.2] ]
}
await evt?UMouseMotion
set mouse = evt!UMouseMotion
}
}
} with {
-- click: must be the last!
-- if drag/drop starts, its mouse up must have priority over this one below
await evt?UMouseButtonUp
output std _("Clicked!"):_(char*)
}
}
}
-- redrawing behavior
spawn {
loop {
await _1 -- no Bool type, use native bool
output pico <.UClear>: TPico
output pico <.UDraw_Rect rect>: TPico
output pico <.UPresent>: TPico
}
}
call pico_loop ()