[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Help with scrolling in dynamic windows

    Date: Fri, 29 Jan 88 05:36:24 pst
    From: saul%psyche@BOEING.COM

    In our system we have potentially long lists (several hundred to fifteen
    hundred items) that need to be displayed each on a separate line in the
    display.  We want the user to be able to scroll thru the items, but when
    we write the items out, it takes roughly 70 seconds to display them all
    in the dynamic window.  What we WANT to do is to write out only enough
    items to fill up the window, and then when the user clicks the mouse to
    scroll, write out the new appropriate items to the dynamic window.  We
    want to use dynamic windows instead of the other window types to make
    use of the easy mouse sensitivity in dynamic windows. 
    Has anyone solved this problem?

    Greg Saul 

(1) You can use redisplayable output to do this.  When you go to display
an item, determine where your viewport is using the
:visible-cursorpos-limits message to the stream.  If the item you are
displaying falls in the current viewport, then display the item as you'd
like to see it.  If the item is not in the viewport, then just display
something which takes minimal time to display (e.g. a space followed by
a terpri).

Here's a skeleton for how you might do this:

    (defun possibly-clipped-cache-value (object-top object-bottom
					 viewport-top viewport-bottom
      (if (and viewport-top
	       (or (> object-top viewport-bottom)
		   (< object-bottom viewport-top)))
	(if (or (null viewport-top)
		(and ( object-top viewport-top)
		     ( object-bottom viewport-bottom)))

;;; and in the redisplay function...
(multiple-value-bind (ignore viewport-top ignore viewport-bottom)
    (send-if-handles stream :visible-cursorpos-limits :character)
  (dw:with-redisplayable-output (:stream stream
				 :unique-id <top level unique id>
				 :cache-value <top level cache value>)
    (loop for item in items
	  as unique-id = <compute unique id for item>
	  as item-cache-value = <compute cache value for item>
	  as cache-value = (possibly-clipped-cache-value
			     line-number line-number
			     viewport-top viewport-bottom
      (if (eq cache-value :clipped)
	  (dw:with-redisplayable-output (:stream stream
					 :unique-id unique-id 
					 :cache-value cache-value )
	    (tyo #\space stream)
	    (terpri stream))
	(dw:with-redisplayable-output (:stream stream
				       :unique-id unique-id 
				       :cache-value cache-value)
	  <display the item>)))))

(2) You can put a :before method on :set-viewport-position which
determines where the viewport is and then only displays the items that
fall in that location.  Be careful about setting breakpoints in such a
method -- it can send you on a fast vacation to the cold load.  I don't
recommend this approach though.

I hope this helps.