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

Re: start-picture/get-picture question



On Tue Jan 25 Rob Browning writes:
  I was creating a class to implement windows that will redraw themselves.

  Here's the idea:
  (Assume the window has a slot called "contents" that holds a picture.
  Also assume that the view-draw-contents method for this class clears
  the window and draws the picture in "contents" in the window)
Here are the brief responses to the questions:
> 1) Isn't it true that unless I add a without-interrupts macro around the
>    with-focused-view macro, I'll unintentially capture any
>    activation/deactivation or redraw events in the picture while "items"
>    are being drawn.
Yes. 
> 2) However, if I do add the without-interrupts macro, isn't it possible
>    that the interrupts could be disabled for too long.
The solution is to make the graphics commands faster. Avoid using
the quickdraw functions and instead use the actual traps to do what
you want. This avoids focusing and refocusing the view and recomputing
the viewing rectangle..

3) Is there a better way to do this?

Yes, use the traps and follow a method used in the contrib directory.
I've outline the process below for a standard view-draw-contents
method.

4) Are calls to start-picture, get-picture, kill-picture, and draw-picture
   particularly expensive?
The quickdraw traps calls are faster and give you more control. They
allow you to avoid duplicate calls. For example. start-picture,
and draw picture both contain (with-focused-view view. Both also
recompute the picture frame (either indirectly or from the supplied
arguments.) You're probably better off doing an unwind protect
after the #_openPicture trap call, closing the picture and removing
it when there is a failure and reinstalling the old picture. You'll
also need to add code for the "empty" picture.

You might also be interested in the a contribution available from
cambridge.apple.com by anonymous ftp: pic-window.lisp.hqx

This enables you to create a scrolling window that displays a picture.
In your code I noticed that you used the quickdraw interface calls to
1. start a new picture
2. draw the old picture
3. draw the new graphic objects
4. close the picture
It's worhthwhile to mention several points. The start-picture and
draw picture commands all assume that the size of the current
window rectangle is the drawing surface for both the
current picture and the new commands. All of the new objects must
fit within the frame, otherwise they'll be cropped. Similarly, the
code assumes that the user can't change the size of the window. If
the user makes it smaller, pieces may be lost. You're probably
better to define the rectangle for the window and store it as a slot
in the window class. Then, you can define the viewing rectangle
correctly. You can also ensure that the end-picture command is
invoked. For an example see the following code:

pic-window.lisp.hqx

(defmethod view-draw-contents ((self pic-window))
  (without-interrupts 
   (with-slots (window-picture 
                zoom-factor 
                scale-rect 
                my-scroller v-scroller h-scroller) self
     (when (view-valid-picture self window-picture)
       (let* ((topLeft (view-origin my-scroller))
              (bottomRight (add-points topLeft (view-size my-scroller)))
              (picture-bottom (rref window-picture 
:picture.picframe.BottomRight))
              (picture-top (rref window-picture :picture.picframe.topLeft)))
         (with-focused-view my-scroller
           (rlet ((r :rect :topLeft topLeft
                     :bottomRight bottomRight)
                  (clip-r :rect :topLeft topLeft
                          :bottomRight (add-points topLeft (view-size 
my-scroller))))
             (unless (point-in-rect-p r (rref clip-r :rect.bottomRight))
               (require-trap #_fillrect :ptr clip-r :ptr *light-gray-pattern*))
             (when scale-rect
               (require-trap #_eraserect :ptr scale-rect))
             (require-trap #_penNormal)
             (if scale-rect
               (view-draw-picture self window-picture scale-rect)
               (progn
                 (rset r :rect.topLeft picture-top)
                 (rset r :rect.bottomRight picture-bottom)
                 (view-draw-picture self window-picture r)))))))
     (call-next-method))))

This is an extended answer to question 3. The simple answer is. It's
better to use the #_ traps calls and to define a method for "adding"
to the window.  (e.g. (defmethod add-graphic-items ((window win) &rest commands))
Then, make sure commands are simple commands (#_moveTo etc.).

mark