factor/basis/ui/gadgets/scrollers/scrollers.factor

167 lines
4.5 KiB
Factor
Raw Normal View History

! Copyright (C) 2005, 2009 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-04-21 00:09:00 -04:00
USING: accessors arrays ui.gadgets ui.gadgets.viewports
2009-02-14 20:50:22 -05:00
ui.gadgets.frames ui.gadgets.grids
2008-04-21 00:09:00 -04:00
ui.gadgets.sliders ui.gestures kernel math namespaces sequences
2008-11-19 22:58:45 -05:00
models models.range models.compose combinators math.vectors
classes.tuple math.rectangles combinators.short-circuit ;
2007-09-20 18:09:08 -04:00
IN: ui.gadgets.scrollers
TUPLE: scroller < frame column-header viewport x y follows ;
2007-09-20 18:09:08 -04:00
! Scrollable gadget protocol; optional
GENERIC: pref-viewport-dim ( gadget -- dim )
M: gadget pref-viewport-dim pref-dim ;
GENERIC: viewport-column-header ( gadget -- gadget/f )
M: gadget viewport-column-header drop f ;
2007-09-20 18:09:08 -04:00
: find-scroller ( gadget -- scroller/f )
2008-08-23 00:20:49 -04:00
[ scroller? ] find-parent ;
2007-09-20 18:09:08 -04:00
2008-06-08 16:32:55 -04:00
: scroll-up-page ( scroller -- ) y>> -1 swap slide-by-page ;
2007-09-20 18:09:08 -04:00
2008-06-08 16:32:55 -04:00
: scroll-down-page ( scroller -- ) y>> 1 swap slide-by-page ;
2007-09-20 18:09:08 -04:00
2008-06-08 16:32:55 -04:00
: scroll-up-line ( scroller -- ) y>> -1 swap slide-by-line ;
2007-09-20 18:09:08 -04:00
2008-06-08 16:32:55 -04:00
: scroll-down-line ( scroller -- ) y>> 1 swap slide-by-line ;
2007-09-20 18:09:08 -04:00
<PRIVATE
2007-09-20 18:09:08 -04:00
: do-mouse-scroll ( scroller -- )
2008-11-19 22:58:45 -05:00
scroll-direction get-global
[ first swap x>> slide-by-line ]
[ second swap y>> slide-by-line ]
2bi ;
2007-09-20 18:09:08 -04:00
scroller H{
{ mouse-scroll [ do-mouse-scroll ] }
2007-09-20 18:09:08 -04:00
} set-gestures
: <scroller-model> ( -- model )
0 0 0 0 <range> 0 0 0 0 <range> 2array <compose> ;
M: viewport pref-dim* gadget-child pref-viewport-dim ;
2007-09-20 18:09:08 -04:00
: scroll ( value scroller -- )
[
viewport>> [ dim>> { 0 0 } ] [ gadget-child pref-dim ] bi
2008-11-19 22:58:45 -05:00
4array flip
2007-09-20 18:09:08 -04:00
] keep
2dup control-value = [ 2drop ] [ set-control-value ] if ;
: (scroll>rect) ( rect scroller -- )
[ [ loc>> ] [ dim>> ] bi <rect> ] dip
2008-11-19 22:58:45 -05:00
{
[ scroller-value vneg offset-rect ]
2008-11-19 22:58:45 -05:00
[ viewport>> dim>> rect-min ]
[ viewport>> [ v- { 0 0 } vmin ] [ v- { 0 0 } vmax ] with-rect-extents v+ ]
2008-11-19 22:58:45 -05:00
[ scroller-value v+ ]
[ scroll ]
} cleave ;
2007-09-20 18:09:08 -04:00
: relative-scroll-rect ( rect gadget scroller -- newrect )
2008-07-11 16:19:54 -04:00
viewport>> gadget-child relative-loc offset-rect ;
2007-09-20 18:09:08 -04:00
: find-scroller* ( gadget -- scroller/f )
dup find-scroller
2008-11-10 06:08:30 -05:00
{ [ nip ] [ viewport>> gadget-child swap child? ] [ nip ] }
2&& ;
2007-11-14 16:35:17 -05:00
2008-11-19 22:58:45 -05:00
: (update-scroller) ( scroller -- )
[ scroller-value ] keep scroll ;
2007-09-20 18:09:08 -04:00
2007-11-22 01:40:17 -05:00
: (scroll>gadget) ( gadget scroller -- )
2008-11-19 22:58:45 -05:00
2dup swap child? [
[ [ [ { 0 0 } ] dip pref-dim <rect> ] keep ] dip
2008-11-19 22:58:45 -05:00
[ relative-scroll-rect ] keep
(scroll>rect)
] [ f >>follows (update-scroller) drop ] if ;
2007-09-20 18:09:08 -04:00
: (scroll>bottom) ( scroller -- )
[ viewport>> gadget-child pref-dim { 0 1 } v* ] keep scroll ;
2007-09-20 18:09:08 -04:00
2008-07-11 16:19:54 -04:00
GENERIC: update-scroller ( scroller follows -- )
M: t update-scroller drop (scroll>bottom) ;
M: gadget update-scroller swap (scroll>gadget) ;
M: rect update-scroller swap (scroll>rect) ;
2008-11-19 22:58:45 -05:00
M: f update-scroller drop (update-scroller) ;
2007-09-20 18:09:08 -04:00
M: scroller layout*
2008-11-19 22:58:45 -05:00
[ call-next-method ] [
dup follows>>
[ update-scroller ] [ >>follows drop ] 2bi
] bi ;
2007-09-20 18:09:08 -04:00
M: scroller focusable-child*
2008-08-31 02:42:30 -04:00
viewport>> ;
2007-09-20 18:09:08 -04:00
M: scroller model-changed
2008-11-19 22:58:45 -05:00
f >>follows 2drop ;
2008-04-21 00:09:00 -04:00
: build-scroller ( scroller -- scroller )
dup x>> { 0 1 } grid-add
dup y>> { 1 0 } grid-add
dup viewport>> { 0 0 } grid-add ; inline
: <column-header-viewport> ( scroller -- viewport )
[ column-header>> ] [ model>> ] bi
<viewport> horizontal >>constraint ;
: build-header-scroller ( scroller -- scroller )
dup <column-header-viewport> { 0 0 } grid-add
dup x>> { 0 2 } grid-add
dup y>> { 1 1 } grid-add
dup viewport>> { 0 1 } grid-add ; inline
: init-scroller ( column-header scroller -- scroller )
{ 1 1 } >>gap
over { 0 1 } { 0 0 } ? >>filled-cell
t >>root?
<scroller-model> >>model
swap >>column-header ; inline
: build-children ( gadget scroller -- scroller )
dup model>> dependencies>>
[ first horizontal <slider> >>x ]
[ second vertical <slider> >>y ] bi
[ nip ] [ model>> <viewport> ] 2bi >>viewport ; inline
PRIVATE>
: <scroller> ( gadget -- scroller )
dup viewport-column-header
dup [ 2 3 ] [ 2 2 ] if scroller new-frame
init-scroller
build-children
dup column-header>>
[ build-header-scroller ] [ build-scroller ] if ;
2008-04-21 00:09:00 -04:00
: scroll>rect ( rect gadget -- )
dup find-scroller* dup [
[ relative-scroll-rect ] keep
swap >>follows
relayout
] [ 3drop ] if ;
2008-04-21 00:09:00 -04:00
: scroll>gadget ( gadget -- )
dup find-scroller* dup [
swap >>follows
relayout
] [
2drop
] if ;
: scroll>bottom ( gadget -- )
find-scroller [ t >>follows relayout-1 ] when* ;
: scroll>top ( gadget -- )
<zero-rect> swap scroll>rect ;