updating-output issues

Paul Werkowski pw at snoopy.qozzy.com
Fri Jan 28 18:26:50 UTC 2022


I've been revisiting a clim project from 15 years ago which was to 
provide clim graphics to Dan Corkhill's very nice GBBopen blackboard 
system. I have an initial version now working nicely on Lispworks 
clim-2.0 on Windows. It is close to running with McCLIM as well.

I have two issues, updating-output appears to work in that the 
:cache-test is respected but where Lispworks clim calls 
clear-output-record when a displayed object moves or is deleted McCLIM 
does not do so. I have attached a simple demo that shows that problem. 
Just click right or left anywhere in the pane to move the green disk 
left or right to see the problem.

The other issue is that redisplay-frame-pane (not used in the demo) 
always causes an infinite recursion that finally results in a blown 
stack. Part of the problem is with window-clear which in addition to 
using medium-clear-area, etc to clear the screen also sets window size 
to zero and then calls compose-space. I have an :around method that 
avoids that problem but the redisplay recursion persists. My workaround 
for that is to just call the display function directly but that does not 
allow updating-output to work correctly.

Paul
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/mcclim-devel/attachments/20220128/a0f19a1a/attachment.html>
-------------- next part --------------
(defpackage utest (:use :clim :clim-lisp))
(in-package :utest)

(defclass unit ()())
(define-presentation-type unit ())

(defclass test-unit (unit)
  ((x-value :initarg :x :accessor x-of)
   (y-value :initarg :y :accessor y-of)
   (color   :initarg :color
            :accessor color-of)
   (size :initform 10))
  (:default-initargs
   :x 10 :y 10 :color +green+))

(defmethod print-object ((obj test-unit) stream)
  (print-unreadable-object (obj stream :type t)
    (format stream "<~d ~d>"
            (x-of obj)(y-of obj))))

(defclass example-pane (application-pane)
  ((units :initform nil
          :initarg :units
          :accessor units-of)
   (dx :initform 10)
   (dy :initform 10))
  (:default-initargs
   :width  300
   :height 300
   :incremental-redisplay t
   :display-function 'example-pane-displayer))

(defmethod draw-unit ((pane example-pane)(unit test-unit))
  (with-slots ((x x-value) (y y-value) size color) unit
    (format *trace-output* "~&draw-unit ~a~%" unit)
    (updating-output (pane :unique-id unit
                           :cache-value (list* x y size color)
                           :cache-test #'equalp)
      (with-output-as-presentation (pane unit 'unit)
        (format *trace-output* "~&--draw-circle~%")
        (draw-circle* pane x y size :ink (color-of unit))))))

#+notyet
(define-presentation-method highlight-presentation
  ((type unit) record stream state)
  (with-bounding-rectangle* (x0 y0 xz yz) record
    (declare (ignorable xz yz))
    (let ((ink (if (eql state :highlight) +flipping-ink+ +background-ink+)))
      (draw-rectangle* stream (1- x0)(1- y0) xz yz
                       :ink ink :filled nil))))

(defmethod example-pane-displayer (frame (pane example-pane))
  (declare (ignore frame)) ; need tracking-pointer here - see plotter
  (with-bounding-rectangle* (x1 y1 x2 y2) pane
    (updating-output (pane :cache-value (list* x1 y1 x2 y2)
                           :cache-test #'equalp)
      (draw-rectangle* pane x1 y1 x2 y2 :ink +blue+ :filled nil))
    (with-first-quadrant-coordinates (pane x1 y2)
      (dolist (unit (units-of pane))
        (draw-unit pane unit))
      )))

(define-application-frame utest ()
  ((x-dim :initform 'x :initarg :x-dim)
   (y-dim :initform 'y :initarg :y-dim))
  (:menu-bar t)
  #-mcclim(:command-table t)
  #+mcclim(:command-table (utest))
  (:panes
   (p1
    (make-pane 'example-pane
               :units (list (make-instance
                             'test-unit :x 150 :y 150
                             :color +green+)
                            (make-instance
                             'test-unit :x 250 :y 50
                             :color +blue+))
               :width 300 :height 300
               :max-width +fill+
               :max-height +fill+
               )))
  (:layouts 
   (default  p1)))

(define-utest-command (com-move-unit)((which '(member :x :y))
                                      (unit 'test-unit)
                                      (pane 'example-pane)
                                      (direction '(member :up :down
                                                          :left :rignt)))
  (declare (ignorable pane))
  (with-slots (x-value y-value) unit
    (let ((incr 5.0))
      (case which
        (:x (incf x-value (case direction (:left (- incr))(:right incr))))
        (:y (incf y-value (case direction (:up incr)(:down (- incr))))))
      )))

(define-presentation-to-command-translator xlate-move-unit-l
    (blank-area com-move-unit utest
                  :pointer-documentation "Move Left"
                  :gesture :select)
    ;; object is blank-area
    (object window x y)
  (declare (ignore object x y)) (terpri *trace-output*)
  (let* ((units (units-of window))
         (unit (first units)))
    `(:x ,unit ,window :left)))

(define-presentation-to-command-translator xlate-move-unit-r
    (blank-area com-move-unit utest
                  :pointer-documentation "Move Right"
                  :gesture :menu)
    ;; object is blank-area
    (object window x y)
  (declare (ignore object x y))
  (let* ((units (units-of window))
         (unit (first units)))
    `(:x ,unit ,window :right)))

(defun testme ()
  (run-frame-top-level
   (make-application-frame 'utest
     :left 950 :top 40)))


More information about the mcclim-devel mailing list