From 074e3238f3367cb459e5e136b9d893198342d3ce Mon Sep 17 00:00:00 2001
From: Slava Pestov <slava@slava-pestovs-macbook-pro.local>
Date: Sun, 15 Feb 2009 03:59:50 -0600
Subject: [PATCH] Scrollers: add pref-viewport-dim word that child gadgets can
 implement; clean up layout

---
 .../gadgets/scrollers/scrollers-tests.factor  | 22 ++---
 basis/ui/gadgets/scrollers/scrollers.factor   | 93 +++++++++----------
 basis/ui/gadgets/viewports/viewports.factor   | 31 +------
 3 files changed, 60 insertions(+), 86 deletions(-)

diff --git a/basis/ui/gadgets/scrollers/scrollers-tests.factor b/basis/ui/gadgets/scrollers/scrollers-tests.factor
index c05474ba5d..9a8460c90e 100644
--- a/basis/ui/gadgets/scrollers/scrollers-tests.factor
+++ b/basis/ui/gadgets/scrollers/scrollers-tests.factor
@@ -1,9 +1,9 @@
 USING: ui.gadgets ui.gadgets.scrollers namespaces tools.test
 kernel models models.compose models.range ui.gadgets.viewports
-ui.gadgets.labels ui.gadgets.grids ui.gadgets.frames
+ui.gadgets.labels ui.gadgets.grids
 ui.gadgets.sliders math math.vectors arrays sequences
 tools.test.ui math.rectangles accessors ui.gadgets.buttons
-ui.gadgets.packs ;
+ui.gadgets.packs ui.gadgets.scrollers.private ;
 IN: ui.gadgets.scrollers.tests
 
 [ ] [
@@ -28,7 +28,7 @@ IN: ui.gadgets.scrollers.tests
 "v" get [
     [ { 10 20 } ] [ "v" get model>> range-value ] unit-test
 
-    [ { 10 20 } ] [ "g" get loc>> vneg viewport-gap v+ scroller-border v+ ] unit-test
+    [ { 10 20 } ] [ "g" get loc>> vneg ] unit-test
 ] with-grafted-gadget
 
 [ ] [
@@ -41,15 +41,15 @@ IN: ui.gadgets.scrollers.tests
 [ ] [ "s" get layout ] unit-test
 
 "s" get [
-    [ { 34 34 } ] [ "s" get viewport>> dim>> ] unit-test
+    [ { 31 31 } ] [ "s" get viewport>> dim>> ] unit-test
 
-    [ { 107 107 } ] [ "s" get viewport>> viewport-dim ] unit-test
+    [ { 100 100 } ] [ "s" get viewport>> gadget-child pref-dim ] unit-test
 
     [ ] [ { 0 0 } "s" get scroll ] unit-test
 
     [ { 0 0 } ] [ "s" get model>> range-min-value ] unit-test
 
-    [ { 107 107 } ] [ "s" get model>> range-max-value ] unit-test
+    [ { 100 100 } ] [ "s" get model>> range-max-value ] unit-test
 
     [ ] [ { 10 20 } "s" get scroll ] unit-test
 
@@ -57,7 +57,7 @@ IN: ui.gadgets.scrollers.tests
 
     [ { 10 20 } ] [ "s" get viewport>> model>> range-value ] unit-test
 
-    [ { 10 20 } ] [ "g" get loc>> vneg viewport-gap v+ scroller-border v+ ] unit-test
+    [ { 10 20 } ] [ "g" get loc>> vneg ] unit-test
 ] with-grafted-gadget
 
 <gadget> { 600 400 } >>dim "g1" set
@@ -75,7 +75,7 @@ dup layout
         "g2" get scroll>gadget
         "s" get layout
         "s" get scroller-value
-    ] map [ { 3 0 } = ] all?
+    ] map [ { 0 0 } = ] all?
 ] unit-test
 
 [ ] [ "Hi" <label> dup "l" set <scroller> "s" set ] unit-test
@@ -84,8 +84,8 @@ dup layout
 [ t ] [ "l" get dup find-scroller viewport>> swap child? ] unit-test
 [ t ] [ "l" get find-scroller* "s" get eq? ] unit-test
 [ f ] [ "s" get viewport>> find-scroller* ] unit-test
-[ t ] [ "s" get @right grid-child slider? ] unit-test
-[ f ] [ "s" get @right grid-child find-scroller* ] unit-test
+[ t ] [ "s" get { 1 0 } grid-child slider? ] unit-test
+[ f ] [ "s" get { 1 0 } grid-child find-scroller* ] unit-test
 
 [ ] [
     "Click Me" [ [ scroll>gadget ] [ unparent ] bi ] <border-button>
@@ -102,7 +102,7 @@ dup layout
     swap dup quot>> call
     dup layout
     model>> dependencies>> [ range-max value>> ] map
-    viewport-padding =
+    { 0 0 } =
 ] unit-test
 
 \ <scroller> must-infer
diff --git a/basis/ui/gadgets/scrollers/scrollers.factor b/basis/ui/gadgets/scrollers/scrollers.factor
index d655cc474e..5162e2c635 100644
--- a/basis/ui/gadgets/scrollers/scrollers.factor
+++ b/basis/ui/gadgets/scrollers/scrollers.factor
@@ -9,6 +9,11 @@ IN: ui.gadgets.scrollers
 
 TUPLE: scroller < frame viewport x y follows ;
 
+! Scrollable gadget protocol; optional
+GENERIC: pref-viewport-dim ( gadget -- dim )
+
+M: gadget pref-viewport-dim pref-dim ;
+
 : find-scroller ( gadget -- scroller/f )
     [ scroller? ] find-parent ;
 
@@ -20,6 +25,8 @@ TUPLE: scroller < frame viewport x y follows ;
 
 : scroll-down-line ( scroller -- ) y>> 1 swap slide-by-line ;
 
+<PRIVATE
+
 : do-mouse-scroll ( scroller -- )
     scroll-direction get-global
     [ first swap x>> slide-by-line ]
@@ -33,33 +40,19 @@ scroller H{
 : <scroller-model> ( -- model )
     0 0 0 0 <range> 0 0 0 0 <range> 2array <compose> ;
 
-: new-scroller ( gadget class -- scroller )
-    new-frame
-        t >>root?
-        <scroller-model> >>model
-
-        dup model>> dependencies>>
-        [ first horizontal <slider> [ >>x ] [ @bottom grid-add ] bi ]
-        [ second vertical <slider> [ >>y ] [ @right grid-add ] bi ] bi
-
-        tuck model>> <viewport> [ >>viewport ] [ @center grid-add ] bi ; inline
-
-: <scroller> ( gadget -- scroller ) scroller new-scroller ;
+M: viewport pref-dim* gadget-child pref-viewport-dim ;
 
 : scroll ( value scroller -- )
     [
-        viewport>> [ dim>> { 0 0 } ] [ viewport-dim ] bi
+        viewport>> [ dim>> { 0 0 } ] [ gadget-child pref-dim ] bi
         4array flip
     ] keep
     2dup control-value = [ 2drop ] [ set-control-value ] if ;
 
-: rect-min ( rect dim -- rect' )
-    [ [ loc>> ] [ dim>> ] bi ] dip vmin <rect> ;
-
 : (scroll>rect) ( rect scroller -- )
-    [ [ loc>> ] [ dim>> { 1 1 } v+ ] bi <rect> ] dip
+    [ [ loc>> ] [ dim>> ] bi <rect> ] dip
     {
-        [ scroller-value vneg offset-rect viewport-gap offset-rect ]
+        [ scroller-value vneg offset-rect ]
         [ viewport>> dim>> rect-min ]
         [ viewport>> [ v- { 0 0 } vmin ] [ v- { 0 0 } vmax ] with-rect-extents v+ ]
         [ scroller-value v+ ]
@@ -74,14 +67,6 @@ scroller H{
     { [ nip ] [ viewport>> gadget-child swap child? ] [ nip ] }
     2&& ;
 
-: scroll>rect ( rect gadget -- ) USING: prettyprint io io.streams.c ;
-    global [ over unparse show .c flush ] bind
-    dup find-scroller* dup [
-        [ relative-scroll-rect ] keep
-        swap >>follows
-        relayout
-    ] [ 3drop ] if ;
-
 : (update-scroller) ( scroller -- )
     [ scroller-value ] keep scroll ;
 
@@ -92,22 +77,8 @@ scroller H{
         (scroll>rect)
     ] [ f >>follows (update-scroller) drop ] if ;
 
-: scroll>gadget ( gadget -- )
-    dup find-scroller* dup [
-        swap >>follows
-        relayout
-    ] [
-        2drop
-    ] if ;
-
 : (scroll>bottom) ( scroller -- )
-    [ viewport>> viewport-dim { 0 1 } v* ] keep scroll ;
-
-: scroll>bottom ( gadget -- )
-    find-scroller [ t >>follows relayout-1 ] when* ;
-
-: scroll>top ( gadget -- )
-    <zero-rect> swap scroll>rect ;
+    [ viewport>> gadget-child pref-dim { 0 1 } v* ] keep scroll ;
 
 GENERIC: update-scroller ( scroller follows -- )
 
@@ -131,12 +102,38 @@ M: scroller focusable-child*
 M: scroller model-changed
     f >>follows 2drop ;
 
-TUPLE: limited-scroller < scroller
-{ min-dim initial: { 0 0 } }
-{ max-dim initial: { 1/0. 1/0. } } ;
+PRIVATE>
 
-: <limited-scroller> ( gadget -- scroller )
-    limited-scroller new-scroller ;
+: <scroller> ( gadget -- scroller )
+    2 2 scroller new-frame
+        { 1 1 } >>gap
+        { 0 0 } >>filled-cell
+        t >>root?
+        <scroller-model> >>model
 
-M: limited-scroller pref-dim*
-    [ call-next-method ] [ min-dim>> vmax ] [ max-dim>> vmin ] tri ;
+        dup model>> dependencies>>
+        [ first horizontal <slider> [ >>x ] [ { 0 1 } grid-add ] bi ]
+        [ second vertical <slider> [ >>y ] [ { 1 0 } grid-add ] bi ] bi
+
+        tuck model>> <viewport> [ >>viewport ] [ { 0 0 } grid-add ] bi ; inline
+
+: scroll>rect ( rect gadget -- )
+    dup find-scroller* dup [
+        [ relative-scroll-rect ] keep
+        swap >>follows
+        relayout
+    ] [ 3drop ] if ;
+
+: 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 ;
diff --git a/basis/ui/gadgets/viewports/viewports.factor b/basis/ui/gadgets/viewports/viewports.factor
index 7f783e5573..d5581f2c23 100644
--- a/basis/ui/gadgets/viewports/viewports.factor
+++ b/basis/ui/gadgets/viewports/viewports.factor
@@ -5,20 +5,11 @@ kernel math namespaces sequences models math.vectors
 math.rectangles ;
 IN: ui.gadgets.viewports
 
-CONSTANT: viewport-gap { 3 3 }
-CONSTANT: scroller-border { 1 1 }
-
 TUPLE: viewport < gadget ;
 
 : find-viewport ( gadget -- viewport )
     [ viewport? ] find-parent ;
 
-: viewport-padding ( -- padding )
-    viewport-gap 2 v*n scroller-border v+ ;
-
-: viewport-dim ( viewport -- dim )
-    gadget-child pref-dim viewport-padding v+ ;
-
 : <viewport> ( content model -- viewport )
     viewport new-gadget
         swap >>model
@@ -26,33 +17,19 @@ TUPLE: viewport < gadget ;
         swap add-gadget ;
 
 M: viewport layout*
-    [ gadget-child ] [
-        [ dim>> viewport-padding v- ]
-        [ gadget-child pref-dim ]
-        bi vmax
-    ] bi >>dim drop ;
+    [ gadget-child ]
+    [ [ dim>> ] [ gadget-child pref-dim ] bi vmax ] bi >>dim drop ;
 
 M: viewport focusable-child*
     gadget-child ;
 
-M: viewport pref-dim* viewport-dim ;
-
 : scroller-value ( scroller -- loc )
     model>> range-value [ >fixnum ] map ;
 
 M: viewport model-changed
     nip
     [ relayout-1 ]
-    [
-        [ gadget-child ]
-        [
-            scroller-value vneg
-            viewport-gap v+
-            scroller-border v+
-        ] bi
-        >>loc drop
-    ] bi ;
+    [ [ gadget-child ] [ scroller-value vneg ] bi >>loc drop ] bi ;
 
 : visible-dim ( gadget -- dim )
-    dup parent>> viewport?
-    [ parent>> dim>> viewport-gap 2 v*n v- ] [ dim>> ] if ;
+    dup parent>> viewport? [ parent>> ] when dim>> ;