2005-01-31 14:02:09 -05:00
|
|
|
! Copyright (C) 2005 Slava Pestov.
|
|
|
|
! See http://factor.sf.net/license.txt for BSD license.
|
|
|
|
IN: gadgets
|
2005-02-26 02:11:25 -05:00
|
|
|
USING: generic kernel lists math namespaces sdl ;
|
2005-01-31 14:02:09 -05:00
|
|
|
|
2005-02-01 19:00:16 -05:00
|
|
|
! Shape protocol. Shapes are immutable; moving or resizing a
|
|
|
|
! shape makes a new shape.
|
2005-01-31 14:02:09 -05:00
|
|
|
|
|
|
|
! These dynamically-bound variables affect the generic word
|
|
|
|
! inside?.
|
2005-02-01 19:00:16 -05:00
|
|
|
SYMBOL: x
|
|
|
|
SYMBOL: y
|
|
|
|
|
|
|
|
GENERIC: inside? ( point shape -- ? )
|
2005-01-31 14:02:09 -05:00
|
|
|
|
|
|
|
! A shape is an object with a defined bounding
|
|
|
|
! box, and a notion of interior.
|
|
|
|
GENERIC: shape-x
|
|
|
|
GENERIC: shape-y
|
|
|
|
GENERIC: shape-w
|
|
|
|
GENERIC: shape-h
|
|
|
|
|
2005-02-02 22:00:46 -05:00
|
|
|
GENERIC: move-shape ( x y shape -- )
|
|
|
|
GENERIC: resize-shape ( w h shape -- )
|
2005-01-31 14:02:09 -05:00
|
|
|
|
2005-02-26 02:11:25 -05:00
|
|
|
: clip-w ( gadget -- )
|
|
|
|
width [ nip ( over shape-x - swap shape-w min 0 max ) ] change ;
|
|
|
|
|
|
|
|
: clip-h ( gadget -- )
|
|
|
|
height [ nip ( over shape-y - swap shape-h min 0 max ) ] change ;
|
|
|
|
|
|
|
|
: with-clip ( shape quot -- )
|
|
|
|
#! All drawing done inside the quotation is clipped to the
|
|
|
|
#! shape's bounds.
|
|
|
|
[ >r dup clip-w clip-h r> call ] with-scope ; inline
|
|
|
|
|
|
|
|
: with-trans ( shape quot -- )
|
2005-01-31 14:02:09 -05:00
|
|
|
#! All drawing done inside the quotation is translated
|
|
|
|
#! relative to the shape's origin.
|
|
|
|
[
|
|
|
|
>r dup
|
|
|
|
shape-x x [ + ] change
|
|
|
|
shape-y y [ + ] change
|
|
|
|
r> call
|
|
|
|
] with-scope ; inline
|
|
|
|
|
2005-02-02 19:50:13 -05:00
|
|
|
: max-width ( list -- n )
|
|
|
|
#! The width of the widest shape.
|
2005-02-05 22:51:41 -05:00
|
|
|
[ [ shape-w ] map [ > ] top ] [ 0 ] ifte* ;
|
2005-02-02 19:50:13 -05:00
|
|
|
|
2005-02-02 22:00:46 -05:00
|
|
|
: max-height ( list -- n )
|
|
|
|
#! The height of the tallest shape.
|
2005-02-05 22:51:41 -05:00
|
|
|
[ [ shape-h ] map [ > ] top ] [ 0 ] ifte* ;
|
2005-02-02 22:00:46 -05:00
|
|
|
|
2005-02-15 18:05:28 -05:00
|
|
|
: accumilate ( gap list -- n list )
|
|
|
|
#! The nth element of the resulting list is the sum of the
|
|
|
|
#! first n elements of the given list plus gap, n times.
|
|
|
|
[ 0 swap [ over , + over + ] each ] make-list >r swap - r> ;
|
|
|
|
|
|
|
|
: run-widths ( gap list -- w list )
|
2005-02-02 22:00:46 -05:00
|
|
|
#! Compute a list of running sums of widths of shapes.
|
2005-02-15 18:05:28 -05:00
|
|
|
[ shape-w ] map accumilate ;
|
2005-02-02 22:00:46 -05:00
|
|
|
|
2005-02-15 18:05:28 -05:00
|
|
|
: run-heights ( gap list -- h list )
|
2005-02-02 22:00:46 -05:00
|
|
|
#! Compute a list of running sums of heights of shapes.
|
2005-02-15 18:05:28 -05:00
|
|
|
[ shape-h ] map accumilate ;
|
2005-02-02 19:50:13 -05:00
|
|
|
|
2005-02-05 11:52:24 -05:00
|
|
|
! A point, represented as a complex number, is the simplest
|
|
|
|
! shape. It is not mutable and cannot be used as the delegate of
|
|
|
|
! a gadget.
|
|
|
|
: shape-pos ( shape -- pos )
|
|
|
|
dup shape-x swap shape-y rect> ;
|
2005-02-02 22:00:46 -05:00
|
|
|
|
2005-02-05 11:52:24 -05:00
|
|
|
M: number inside? ( point point -- )
|
|
|
|
>r shape-pos r> = ;
|
2005-02-02 22:00:46 -05:00
|
|
|
|
2005-02-05 11:52:24 -05:00
|
|
|
M: number shape-x real ;
|
|
|
|
M: number shape-y imaginary ;
|
|
|
|
M: number shape-w drop 0 ;
|
|
|
|
M: number shape-h drop 0 ;
|
2005-02-02 22:00:46 -05:00
|
|
|
|
|
|
|
: translate ( point shape -- point )
|
|
|
|
#! Translate a point relative to the shape.
|
2005-02-05 11:52:24 -05:00
|
|
|
swap shape-pos swap shape-pos - ;
|
2005-01-31 14:02:09 -05:00
|
|
|
|
|
|
|
! A rectangle maps trivially to the shape protocol.
|
2005-02-01 20:14:03 -05:00
|
|
|
TUPLE: rectangle x y w h ;
|
|
|
|
M: rectangle shape-x rectangle-x ;
|
|
|
|
M: rectangle shape-y rectangle-y ;
|
|
|
|
M: rectangle shape-w rectangle-w ;
|
|
|
|
M: rectangle shape-h rectangle-h ;
|
2005-01-31 14:02:09 -05:00
|
|
|
|
2005-02-07 18:27:55 -05:00
|
|
|
: rect>screen ( shape -- x1 y1 x2 y2 )
|
|
|
|
[ rectangle-x x get + ] keep
|
|
|
|
[ rectangle-y y get + ] keep
|
|
|
|
[ rectangle-w pick + ] keep
|
|
|
|
rectangle-h pick + ;
|
|
|
|
|
2005-01-31 14:02:09 -05:00
|
|
|
: fix-neg ( a b c -- a+c b -c )
|
|
|
|
dup 0 < [ neg tuck >r >r + r> r> ] when ;
|
|
|
|
|
2005-02-01 20:14:03 -05:00
|
|
|
C: rectangle ( x y w h -- rect )
|
2005-01-31 14:02:09 -05:00
|
|
|
#! We handle negative w/h for convinience.
|
|
|
|
>r fix-neg >r fix-neg r> r>
|
2005-02-01 20:14:03 -05:00
|
|
|
[ set-rectangle-h ] keep
|
|
|
|
[ set-rectangle-w ] keep
|
|
|
|
[ set-rectangle-y ] keep
|
|
|
|
[ set-rectangle-x ] keep ;
|
2005-01-31 14:02:09 -05:00
|
|
|
|
2005-02-02 22:00:46 -05:00
|
|
|
M: rectangle move-shape ( x y rect -- )
|
|
|
|
tuck set-rectangle-y set-rectangle-x ;
|
2005-02-01 19:00:16 -05:00
|
|
|
|
2005-02-02 22:00:46 -05:00
|
|
|
M: rectangle resize-shape ( w h rect -- )
|
|
|
|
tuck set-rectangle-h set-rectangle-w ;
|
2005-02-01 19:00:16 -05:00
|
|
|
|
2005-02-01 20:14:03 -05:00
|
|
|
: rectangle-x-extents ( rect -- x1 x2 )
|
2005-02-07 10:24:03 -05:00
|
|
|
dup shape-x x get + swap shape-w 1 - dupd + ;
|
2005-01-31 14:02:09 -05:00
|
|
|
|
2005-02-01 20:14:03 -05:00
|
|
|
: rectangle-y-extents ( rect -- x1 x2 )
|
2005-02-07 10:24:03 -05:00
|
|
|
dup shape-y y get + swap shape-h 1 - dupd + ;
|
2005-01-31 14:02:09 -05:00
|
|
|
|
2005-02-07 10:24:03 -05:00
|
|
|
: inside-rect? ( point rect -- ? )
|
2005-02-01 20:14:03 -05:00
|
|
|
over shape-x over rectangle-x-extents between? >r
|
|
|
|
swap shape-y swap rectangle-y-extents between? r> and ;
|
2005-02-05 22:51:41 -05:00
|
|
|
|
2005-02-07 10:24:03 -05:00
|
|
|
M: rectangle inside? ( point rect -- ? )
|
|
|
|
inside-rect? ;
|
|
|
|
|
2005-02-05 22:51:41 -05:00
|
|
|
! A line.
|
|
|
|
TUPLE: line x y w h ;
|
|
|
|
|
2005-02-07 10:24:03 -05:00
|
|
|
M: line shape-x dup line-x dup rot line-w + min ;
|
|
|
|
M: line shape-y dup line-y dup rot line-h + min ;
|
|
|
|
M: line shape-w line-w abs ;
|
|
|
|
M: line shape-h line-h abs ;
|
|
|
|
|
2005-02-07 20:10:02 -05:00
|
|
|
: line-pos ( line -- #{ x y }# )
|
|
|
|
dup line-x x get + swap line-y y get + rect> ;
|
|
|
|
|
2005-02-07 10:24:03 -05:00
|
|
|
: line-dir ( line -- #{ w h }# ) dup line-w swap line-h rect> ;
|
|
|
|
|
|
|
|
: move-line-x ( x line -- )
|
|
|
|
[ line-w dupd - max ] keep set-line-x ;
|
|
|
|
|
|
|
|
: move-line-y ( y line -- )
|
|
|
|
[ line-h dupd - max ] keep set-line-y ;
|
|
|
|
|
2005-02-05 22:51:41 -05:00
|
|
|
M: line move-shape ( x y line -- )
|
2005-02-07 10:24:03 -05:00
|
|
|
tuck move-line-y move-line-x ;
|
|
|
|
|
|
|
|
: resize-line-w ( w line -- )
|
|
|
|
dup line-w 0 >= [
|
|
|
|
set-line-w
|
|
|
|
] [
|
|
|
|
2dup
|
|
|
|
[ [ line-w + ] keep line-x + ] keep set-line-x
|
|
|
|
>r neg r> set-line-w
|
|
|
|
] ifte ;
|
|
|
|
|
|
|
|
: resize-line-h ( w line -- )
|
|
|
|
dup line-h 0 >= [
|
|
|
|
set-line-h
|
|
|
|
] [
|
|
|
|
2dup
|
|
|
|
[ [ line-h + ] keep line-y + ] keep set-line-y
|
|
|
|
>r neg r> set-line-h
|
|
|
|
] ifte ;
|
2005-02-05 22:51:41 -05:00
|
|
|
|
|
|
|
M: line resize-shape ( w h line -- )
|
2005-02-07 10:24:03 -05:00
|
|
|
tuck resize-line-h resize-line-w ;
|
|
|
|
|
2005-02-07 18:27:55 -05:00
|
|
|
: line>screen ( shape -- x1 y1 x2 y2 )
|
|
|
|
[ line-x x get + ] keep
|
|
|
|
[ line-y y get + ] keep
|
2005-02-07 20:10:02 -05:00
|
|
|
[ line-w pick + ] keep
|
|
|
|
line-h pick + ;
|
2005-02-07 18:27:55 -05:00
|
|
|
|
2005-02-07 10:24:03 -05:00
|
|
|
: line-inside? ( p d -- ? )
|
2005-02-07 20:10:02 -05:00
|
|
|
dupd proj - absq 4 < ;
|
2005-02-05 22:51:41 -05:00
|
|
|
|
|
|
|
M: line inside? ( point line -- ? )
|
2005-02-07 10:24:03 -05:00
|
|
|
2dup inside-rect? [
|
|
|
|
[ line-pos - ] keep line-dir line-inside?
|
|
|
|
] [
|
|
|
|
2drop f
|
|
|
|
] ifte ;
|
2005-02-05 22:51:41 -05:00
|
|
|
|
|
|
|
! An ellipse.
|
|
|
|
TUPLE: ellipse x y w h ;
|
|
|
|
M: ellipse shape-x ellipse-x ;
|
|
|
|
M: ellipse shape-y ellipse-y ;
|
|
|
|
M: ellipse shape-w ellipse-w ;
|
|
|
|
M: ellipse shape-h ellipse-h ;
|
|
|
|
|
|
|
|
C: ellipse ( x y w h -- line )
|
2005-02-06 00:21:26 -05:00
|
|
|
#! We handle negative w/h for convenience.
|
2005-02-05 22:51:41 -05:00
|
|
|
>r fix-neg >r fix-neg r> r>
|
|
|
|
[ set-ellipse-h ] keep
|
|
|
|
[ set-ellipse-w ] keep
|
|
|
|
[ set-ellipse-y ] keep
|
|
|
|
[ set-ellipse-x ] keep ;
|
|
|
|
|
|
|
|
M: ellipse move-shape ( x y line -- )
|
|
|
|
tuck set-ellipse-y set-ellipse-x ;
|
|
|
|
|
|
|
|
M: ellipse resize-shape ( w h line -- )
|
|
|
|
tuck set-ellipse-h set-ellipse-w ;
|
|
|
|
|
2005-02-07 10:24:03 -05:00
|
|
|
: ellipse>screen ( shape -- x y rx ry )
|
|
|
|
[ dup shape-x swap shape-w 2 /i + x get + ] keep
|
|
|
|
[ dup shape-y swap shape-h 2 /i + y get + ] keep
|
|
|
|
[ shape-w 2 /i ] keep
|
|
|
|
shape-h 2 /i ;
|
|
|
|
|
2005-02-06 00:21:26 -05:00
|
|
|
M: ellipse inside? ( point ellipse -- ? )
|
|
|
|
ellipse>screen swap sq swap sq
|
|
|
|
2dup * >r >r >r
|
|
|
|
pick shape-y - sq
|
|
|
|
>r swap shape-x - sq r>
|
|
|
|
r> * r> rot * + r> <= ;
|