: rect-extent ( rect -- loc ext ) rect-bounds over v+ ;
+: 2rect-extent ( rect rect -- loc1 loc2 ext1 ext2 )
+ [ rect-extent ] 2apply swapd ;
+
: |v-| ( vec vec -- vec ) v- [ 0 max ] map ;
+: <extent-rect> ( loc ext ) dupd swap |v-| <rect> ;
+
: >absolute ( rect -- rect )
rect-bounds >r origin get v+ r> <rect> ;
: (rect-intersect) ( rect rect -- array array )
- [ rect-extent ] 2apply swapd vmin >r vmax r> ;
+ 2rect-extent vmin >r vmax r> ;
: rect-intersect ( rect rect -- rect )
- (rect-intersect) dupd swap |v-| <rect> ;
+ (rect-intersect) <extent-rect> ;
: intersects? ( rect/point rect -- ? )
(rect-intersect) v- [ 0 <= ] all? ;
+: rect-union ( rect rect -- rect )
+ 2rect-extent vmax >r vmin r> <extent-rect> ;
+
! A gadget is a rectangle, a paint, a mapping of gestures to
! actions, and a reference to the gadget's parent.
TUPLE: gadget
: relative ( g1 g2 -- g2-g1 ) screen-loc swap screen-loc v- ;
+: relative-rect ( g1 g2 -- rect )
+ [ relative ] keep rect-dim <rect> ;
+
: child? ( parent child -- ? ) parents memq? ;
GENERIC: focusable-child* ( gadget -- gadget/t )
2dup over scroller-x update-slider
over scroller-y update-slider ;
-: (scroll-to) ( scroller gadget -- point )
- >r scroller-viewport gadget-child r> relative ;
+: pop-follows ( scroller -- follows )
+ dup scroller-follows f rot set-scroller-follows ;
-: update-scroller ( scroller -- )
- dup dup scroller-follows dup [
- f pick set-scroller-follows (scroll-to)
+: (do-scroll) ( gadget viewport -- point )
+ [ [ swap relative-rect ] keep rect-union ] keep
+ [ rect-extent v+ ] 2apply v- ;
+
+: do-scroll ( scroller -- delta )
+ dup pop-follows dup [
+ swap scroller-viewport (do-scroll)
] [
- drop scroller-origin
- ] if scroll ;
+ 2drop @{ 0 0 0 }@
+ ] if ;
+
+: update-scroller ( scroller -- )
+ [ dup do-scroll ] keep scroller-origin v+ scroll ;
: position-viewport ( viewport scroller -- )
scroller-origin vneg swap gadget-child set-rect-loc ;