anchor.diff:  (defun translate-range-value (a mina maxa mino maxo)
     "When \arg{a} is some value in the range from \arg{mina} to \arg{maxa},
      proportionally translate the value into the range \arg{mino} to \arg{maxo}."
  -  (+ mino (* (/ (- a mina) (- maxa mina)) (- maxo mino))))
  -
  -;;; Scroll-bar's sub-regions
  -
  -(defmethod (setf scroll-bar-thumb-size) :after (new-value (sb scroll-bar-pane))
  +  (+ mino (* (/ (- a mina)
  +                (- maxa mina))          ;### avoid divide by zero here.
  +             (- maxo mino))))
  +
  +;;;; SETF :after methods
  +
  +(defmethod (setf gadget-min-value) :after (new-value (pane scroll-bar-pane))
     (declare (ignore new-value))
  -  (with-slots (inhibit-redraw-p thumb) sb
  -    #||
  -    ;;work in progress
  -    (setf (sheet-region thumb)
  -          (with-bounding-rectangle* (x1 y1 x2 y2) (scroll-bar-thumb-bed-region sb)
  -            (multiple-value-bind (minv maxv) (gadget-range* sb)
  -              (multiple-value-bind (v) (gadget-value sb)
  -                (let ((ts (scroll-bar-thumb-size sb)))
  -                  (let ((ya (translate-range-value v minv (+ maxv ts) y1 y2))
  -                        (yb (translate-range-value (+ v ts) minv (+ maxv ts) y1 y2)))
  -                    (make-rectangle* 0 0 (- x2 x1) (- yb ya))))))))
  -    ||#
  -    (unless inhibit-redraw-p
  -      (dispatch-repaint sb +everywhere+)))) ;arg...
  +  (scroll-bar/update-display pane))
  +
  +(defmethod (setf gadget-max-value) :after (new-value (pane scroll-bar-pane))
  +  (declare (ignore new-value))
  +  (scroll-bar/update-display pane))
  +
  +(defmethod (setf scroll-bar-thumb-size) :after (new-value (pane scroll-bar-pane))
  +  (declare (ignore new-value))
  +  (scroll-bar/update-display pane))
  +
  +(defmethod (setf gadget-value) :after (new-value (pane scroll-bar-pane) &key invoke-callback)
  +  (declare (ignore new-value invoke-callback))
  +  (scroll-bar/update-display pane))
  +
  +;;;; geometry
  +
  +(defparameter +minimum-thumb-size-in-pixels+ 30)
   
   (defmethod scroll-bar-up-region ((sb scroll-bar-pane))
     (with-bounding-rectangle* (minx miny maxx maxy) (transform-region (scroll-bar-transformation sb)
  
positive.code:       (cond ((region-contains-position-p (scroll-bar-up-region sb) x y)
               (scroll-up-line-callback sb (gadget-client sb) (gadget-id sb))
               (setf event-state :up-armed)
               (dispatch-repaint sb +everywhere+))
              ((region-contains-position-p (scroll-bar-down-region sb) x y)
               (scroll-down-line-callback sb (gadget-client sb) (gadget-id sb))
               (setf event-state :dn-armed)
               (dispatch-repaint sb +everywhere+))
              ((region-contains-position-p (scroll-bar-thumb-region sb) x y)
               (setf event-state :dragging
                     drag-dy (- y (bounding-rectangle-min-y (scroll-bar-thumb-region sb)))))
              ((region-contains-position-p (scroll-bar-thumb-bed-region sb) x y)
               (if (< y (bounding-rectangle-min-y (scroll-bar-thumb-region sb)))
                   (scroll-up-page-callback sb (gadget-client sb) (gadget-id sb))
                   (scroll-down-page-callback sb (gadget-client sb) (gadget-id sb))))
              (t
               nil)))))
  
  (defmethod handle-event ((sb scroll-bar-pane) (event pointer-button-release-event))
    (with-slots (event-state) sb
  
negative.code: 			      :min-width (* 3 *scrollbar-thickness*)
  			      :width (* 4 *scrollbar-thickness*))))
  
  ;;;; Redisplay
  
  (defun scroll-bar/update-display (scroll-bar)
    (with-slots (up-state dn-state tb-state tb-y1 tb-y2
                 old-up-state old-dn-state old-tb-state old-tb-y1 old-tb-y2
                 all-new-p)
        scroll-bar
      ;;
      (scroll-bar/compute-display scroll-bar)
      ;; redraw up arrow
      (unless (and (not all-new-p) (eql up-state old-up-state))
        (with-drawing-options (scroll-bar :transformation (scroll-bar-transformation scroll-bar))
          (with-bounding-rectangle* (x1 y1 x2 y2) (scroll-bar-up-region scroll-bar)
            (draw-rectangle* scroll-bar x1 y1 x2 y2 :ink *3d-inner-color*)
            (let ((pg (list (make-point (/ (+ x1 x2) 2) y1)
                            (make-point x1 y2)
                            (make-point x2 y2))))
              (case up-state
                (:armed
                 (draw-polygon scroll-bar pg :ink *3d-inner-color*)
                 (draw-bordered-polygon scroll-bar pg :style :inset :border-width 2))
                (otherwise
                 (draw-polygon scroll-bar pg :ink *3d-normal-color*)
                 (draw-bordered-polygon scroll-bar pg :style :outset :border-width 2) ))))) )
      ;; redraw dn arrow
      (unless (and (not all-new-p) (eql dn-state old-dn-state))
        (with-drawing-options (scroll-bar :transformation (scroll-bar-transformation scroll-bar))
          (with-bounding-rectangle* (x1 y1 x2 y2) (scroll-bar-down-region scroll-bar)
            (draw-rectangle* scroll-bar x1 y1 x2 y2 :ink *3d-inner-color*)
            (let ((pg (list (make-point (/ (+ x1 x2) 2) y2)
                            (make-point x1 y1)
                            (make-point x2 y1))))
              (case dn-state
                (:armed
                 (draw-polygon scroll-bar pg :ink *3d-inner-color*)
                 (draw-bordered-polygon scroll-bar pg :style :inset :border-width 2))
                (otherwise
                 (draw-polygon scroll-bar pg :ink *3d-normal-color*)
                 (draw-bordered-polygon scroll-bar pg :style :outset :border-width 2)))))))
      ;; thumb
      (unless (and (not all-new-p)
                   (and (eql tb-state old-tb-state)
                        (eql tb-y1 old-tb-y1)
                        (eql tb-y2 old-tb-y2)))
        (cond ((and (not all-new-p)
                    (eql tb-state old-tb-state)
                    (numberp tb-y1) (numberp old-tb-y1)
                    (numberp tb-y2) (numberp old-tb-y2)
                    (= (- tb-y2 tb-y1) (- old-tb-y2 old-tb-y1)))
               ;; Thumb is just moving, compute old and new region
               (multiple-value-bind (x1 ignore.1 x2 ignore.2)
                   (bounding-rectangle* (scroll-bar-thumb-bed-region scroll-bar))
                 (declare (ignore ignore.1 ignore.2))
                 ;; compute new and old region
                 (with-sheet-medium (medium scroll-bar)
                   (with-drawing-options (medium :transformation (scroll-bar-transformation scroll-bar))
                     (multiple-value-bind (ox1 oy1 ox2 oy2) (values x1 old-tb-y1 x2 old-tb-y2)
                       (multiple-value-bind (nx1 ny1 nx2 ny2) (values x1 tb-y1 x2 tb-y2)
                         (declare (ignore nx2))
                         (copy-area medium ox1 oy1 (- ox2 ox1) (- oy2 oy1) nx1 ny1)
                         ;; clear left-overs from the old region
                         (if (< oy1 ny1)
                             (draw-rectangle* medium ox1 oy1 ox2 ny1 :ink *3d-inner-color*)
                             (draw-rectangle* medium ox1 oy2 ox2 ny2 :ink *3d-inner-color*)))) ))))
               (t
                ;; redraw whole thumb bed and thumb all anew
                (with-drawing-options (scroll-bar :transformation (scroll-bar-transformation scroll-bar))
                    (with-bounding-rectangle* (bx1 by1 bx2 by2) (scroll-bar-thumb-bed-region scroll-bar)
                      (with-bounding-rectangle* (x1 y1 x2 y2) (scroll-bar-thumb-region scroll-bar)
                        (draw-rectangle* scroll-bar bx1 by1 bx2 y1 :ink *3d-inner-color*)
                        (draw-rectangle* scroll-bar bx1 y2 bx2 by2 :ink *3d-inner-color*)
                        (draw-rectangle* scroll-bar x1 y1 x2 y2 :ink *3d-normal-color*)
                        (draw-bordered-polygon scroll-bar
                                               (polygon-points (make-rectangle* x1 y1 x2 y2))
                                               :style :outset
                                               :border-width 2)
                      ;;;;;;
                        (let ((y (/ (+ y1 y2) 2)))
                          (draw-bordered-polygon scroll-bar
                                                 (polygon-points (make-rectangle* (+ x1 3) (- y 1) (- x2 3) (+ y 1)))
                                                 :style :inset
                                                 :border-width 1)
                          (draw-bordered-polygon scroll-bar
                                                 (polygon-points (make-rectangle* (+ x1 3) (- y 4) (- x2 3) (- y 2)))
                                                 :style :inset
                                                 :border-width 1)
                          (draw-bordered-polygon scroll-bar
                                                 (polygon-points (make-rectangle* (+ x1 3) (+ y 4) (- x2 3) (+ y 2)))
                                                 :style :inset
                                                 :border-width 1))))))))
      (setf old-up-state up-state
            old-dn-state dn-state
            old-tb-state tb-state
            old-tb-y1 tb-y1
            old-tb-y2 tb-y2
            all-new-p nil) ))
  
  (defun scroll-bar/compute-display (scroll-bar)
    (with-slots (up-state dn-state tb-state tb-y1 tb-y2
                          event-state) scroll-bar
      (setf up-state (if (eq event-state :up-armed) :armed nil))
      (setf dn-state (if (eq event-state :dn-armed) :armed nil))
      (setf tb-state nil)                 ;we have no armed display yet
      (with-bounding-rectangle* (x1 y1 x2 y2) (scroll-bar-thumb-region scroll-bar)
        (declare (ignore x1 x2))
        (setf tb-y1 y1
              tb-y2 y2))))
  
  ;;;; Utilities
  
  ;; We think all scroll bars as vertically oriented, therefore we have
  ;; SCROLL-BAR-TRANSFORMATION, which should make every scroll bar
  