CLIM mail archive

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

Re: fancy highlighting of presentations



Thank you all for the help in highlighting presentations with a cursor
that moves along the presentation.  With a day of fiddling I managed to
make it work.  Following is the code I ended up with -- not elegant but
it works.  If there are better ways of doing things in here, feel free
to comment.
-Bill Long

;;;; ----- code follows -----

;; data structure to hold values
(defstruct (measure (:print-function
		      (lambda (measure str lev)
			(declare (ignore lev))
			(format str "<m ~A>" (measure-name measure)))))
  name
  value
  type)

;; the presentation type that's displayed as a horizontal scale
(define-presentation-type measnum ())

(defvar *arrow* (clim:make-pattern #2a((0 0 0 0 1 1 1 1 1 0 0 0 0)
				       (0 0 0 0 1 1 1 1 1 0 0 0 0)
				       (0 0 0 0 1 1 1 1 1 0 0 0 0)
				       (0 0 0 0 1 1 1 1 1 0 0 0 0)
				       (0 0 0 0 1 1 1 1 1 0 0 0 0)
				       (1 1 1 1 1 1 1 1 1 1 1 1 1)
				       (0 1 1 1 1 1 1 1 1 1 1 1 0)
				       (0 0 1 1 1 1 1 1 1 1 1 0 0)
				       (0 0 0 1 1 1 1 1 1 1 0 0 0)
				       (0 0 0 0 1 1 1 1 1 0 0 0 0)
				       (0 0 0 0 0 1 1 1 0 0 0 0 0)
				       (0 0 0 0 0 0 1 0 0 0 0 0 0)
				       )
				   (list clim:+background+ clim:+foreground+)))

(defvar *in-highlight* ()) ; the only way I can find to keep tracking-pointer from
			   ; recursively calling highlight-presentation

(define-presentation-method highlight-presentation ((type measnum) record stream state)
  (declare (ignore record))
  (when (and (eq state :highlight) ; does this do anything?
	     (not *in-highlight*))
    (setq *in-highlight* t)(highlight-scale stream)(setq *in-highlight* ())))

(defun highlight-scale (stream)
  (let (ox oy)
    (with-output-recording-options (stream :record-p nil)
      (tracking-pointer (stream :context-type 'measnum
				:transformp t ; doesn't seem to do anything
				:highlight ()) ; doesn't work, hence the *in-highlight*
        (:presentation (presentation x)
	 (with-bounding-rectangle* (left top) presentation
	   (declare (ignore left))
	   (multiple-value-bind (xr yr)
	       (convert-from-relative-to-absolute-coordinates ; copied from menu-multiple-choose
		 stream (output-record-parent presentation)) ; any reason for parent?
	     (declare (ignore xr))
	     (when ox (draw-i-beam stream ox oy))
	     (draw-i-beam stream (setq ox x)(setq oy (+ yr top 6))))))
	(:pointer-motion ()
	 (when ox (draw-i-beam stream ox oy)
	       (setq ox nil))
	 (return-from highlight-scale))
	(:presentation-button-press (event) ; if I don't include this I-beam remains and
					    ; gesture gets eaten anyway
	 (when ox (draw-i-beam stream ox oy)
	       (setq ox nil))
	 (unread-gesture event)
	 (return-from highlight-scale))))))

(define-hfcl-command (com-select-measnum) ; as command causes redisplay to show arrow
   ((meas 'measure)(val 'integer))
  (setf (measure-value meas) val))

(define-presentation-to-command-translator set-measnum
    (measnum com-select-measnum hfcl)
    (object presentation x)
  (let* ((stream (get-frame-pane *application-frame* 'input-window))
	 (xr (convert-from-relative-to-absolute-coordinates stream presentation)))
          ; with-output-as-presentation is inside with-room-for-graphics so conversion needed
      (list object (/ (- x xr) 300.0))))

;; the method that handles displaying the input pane
(defmethod display-measures ((frame hfcl) stream)
  (loop with val for meas in *measures* do
    (fresh-line stream)
    (updating-output (stream :unique-id meas :cach-value (measure-value meas))
      (with-output-as-presentation (:object meas :type 'measnam :stream stream)
	(with-text-face ((if (measure-value meas) :italic :roman) stream)
	  (format stream "~A: " (measure-name meas))))
      (cond ((eq (measure-type meas) 'scale)
	     (with-room-for-graphics (stream)
	       (with-output-as-presentation (:object meas :type 'measnum :stream stream
					     :single-box t) ; else sensitive area is just line
		 (draw-scale stream))
	       (draw-text* stream "0.0" 0 -2 :align-x :center :align-y :top)
	       (draw-text* stream "1.0" 300 -2 :align-x :center :align-y :top)
	       (if (setq val (measure-value meas))
		   (draw-icon* stream *arrow* (- (round (* 300 val)) 6) 0))))
	    ( ;; handle other types
	     )))))

(defun draw-scale (stream)
  (draw-line* stream 0 0 300 0)
  (draw-line* stream 0 0 0 12)
  (draw-line* stream 300 0 300 12))

(defun draw-i-beam (stream x y &aux (y1 (- y 8))(y2 (+ y 8))(x1 (- x 2))(x2 (+ x 2)))
  (draw-line* stream x y1 x y2 :ink +flipping-ink+)
  (draw-line* stream x1 y1 x2 y1 :ink +flipping-ink+)
  (draw-line* stream x1 y2 x2 y2 :ink +flipping-ink+))


0,,


Main Index | Thread Index