Update of /project/mcclim/cvsroot/mcclim In directory clnet:/tmp/cvs-serv28193
Modified Files: frames.lisp package.lisp panes.lisp Log Message: Added some amazing hacks to pointer-documentation-panes for the notion of a "background message".
This is the beginning of extending pointer-documentation-panes into more generally useful minibuffer-like panes.
For now, this just means that the Listener shows arglists and other things for Drei commands. It's still a little flickery, though.
--- /project/mcclim/cvsroot/mcclim/frames.lisp 2008/01/22 08:51:02 1.129 +++ /project/mcclim/cvsroot/mcclim/frames.lisp 2008/01/27 22:24:07 1.130 @@ -1115,6 +1115,15 @@ (declare (ignore input-context stream)) (equal old-state new-state))
+(defun record-on-display (stream record) + "Return true if `record' is part of the output history of +`stream', false otherwise." + (labels ((worker (record) + (or (eq record (stream-output-history stream)) + (and (not (null (output-record-parent record))) + (worker (output-record-parent record)))))) + (worker record))) + (defgeneric frame-print-pointer-documentation (frame input-context stream state event))
@@ -1127,71 +1136,82 @@ (let ((x (device-event-x event)) (y (device-event-y event)) (pstream *pointer-documentation-output*)) - (loop for (button presentation translator context) - in new-translators - for name = (cadr (assoc button +button-documentation+)) - for first-one = t then nil - do (progn - (unless first-one - (write-string "; " pstream)) - (unless (zerop current-modifier) - (print-modifiers pstream current-modifier :short) - (write-string "-" pstream)) - (format pstream "~A: " name) - (document-presentation-translator translator - presentation - (input-context-type context) - *application-frame* - event - stream - x y - :stream pstream - :documentation-type - :pointer)) - finally (when new-translators - (write-char #. pstream))) + (if (null new-translators) + (when (and (background-message pstream) + (not (record-on-display pstream (background-message pstream)))) + (cond ((> (get-universal-time) + (+ (background-message-time pstream) + *background-message-minimum-lifetime*)) + (setf (background-message pstream) nil)) + (t + (setf (output-record-parent (background-message pstream)) nil) + (stream-add-output-record pstream (background-message pstream)) + (replay (background-message pstream) pstream)))) + (loop for (button presentation translator context) + in new-translators + for name = (cadr (assoc button +button-documentation+)) + for first-one = t then nil + do (progn + (unless first-one + (write-string "; " pstream)) + (unless (zerop current-modifier) + (print-modifiers pstream current-modifier :short) + (write-string "-" pstream)) + (format pstream "~A: " name) + (document-presentation-translator translator + presentation + (input-context-type context) + *application-frame* + event + stream + x y + :stream pstream + :documentation-type + :pointer)) + finally (when new-translators + (write-char #. pstream)))) ;; Wasteful to do this after doing ;; find-innermost-presentation-context above... look at doing this ;; first and then doing the innermost test. (let ((all-translators (find-applicable-translators - (stream-output-history stream) - input-context - *application-frame* - stream - x y - :for-menu t)) - (other-modifiers nil)) - (loop for (translator) in all-translators - for gesture = (gesture translator) - unless (eq gesture t) - do (loop for (name type modifier) in gesture - unless (eql modifier current-modifier) - do (pushnew modifier other-modifiers))) - (when other-modifiers - (setf other-modifiers (sort other-modifiers #'cmp-modifiers)) - (terpri pstream) - (write-string "To see other commands, press " pstream) - (loop for modifier-tail on other-modifiers - for (modifier) = modifier-tail - for count from 0 - do (progn - (if (null (cdr modifier-tail)) - (progn - (when (> count 1) - (write-char #, pstream)) - (when (> count 0) - (write-string " or " pstream))) - (when (> count 0) - (write-string ", " pstream))) - (print-modifiers pstream modifier :long))) - (write-char #. pstream)))))) + (stream-output-history stream) + input-context + *application-frame* + stream + x y + :for-menu t)) + (other-modifiers nil)) + (loop for (translator) in all-translators + for gesture = (gesture translator) + unless (eq gesture t) + do (loop for (name type modifier) in gesture + unless (eql modifier current-modifier) + do (pushnew modifier other-modifiers))) + (when other-modifiers + (setf other-modifiers (sort other-modifiers #'cmp-modifiers)) + (terpri pstream) + (write-string "To see other commands, press " pstream) + (loop for modifier-tail on other-modifiers + for (modifier) = modifier-tail + for count from 0 + do (progn + (if (null (cdr modifier-tail)) + (progn + (when (> count 1) + (write-char #, pstream)) + (when (> count 0) + (write-string " or " pstream))) + (when (> count 0) + (write-string ", " pstream))) + (print-modifiers pstream modifier :long))) + (write-char #. pstream))))))
(defmethod frame-update-pointer-documentation ((frame standard-application-frame) input-context stream event) (when *pointer-documentation-output* (with-accessors ((frame-documentation-state frame-documentation-state) (documentation-record documentation-record)) - frame + frame (setf frame-documentation-state (frame-compute-pointer-documentation-state frame input-context @@ -1206,63 +1226,55 @@ (%event% event)) (declare (special %input-context% %stream% %doc-state% %event&)) (if (and documentation-record - (output-record-parent documentation-record)) + (output-record-parent documentation-record)) (redisplay documentation-record *pointer-documentation-output*) (progn - (window-clear *pointer-documentation-output*) + (window-clear *pointer-documentation-output*) (setf documentation-record - (updating-output (*pointer-documentation-output*) - (updating-output (*pointer-documentation-output* - :cache-value %doc-state% - :cache-test - #'equal) - (frame-print-pointer-documentation frame - %input-context% - %stream% - %doc-state% - %event%)))))))))) - -#-(and) -(defmethod frame-update-pointer-documentation - ((frame standard-application-frame) input-context stream event) - (when *pointer-documentation-output* - (with-accessors ((frame-documentation-state frame-documentation-state)) - frame - (let ((new-state (frame-compute-pointer-documentation-state frame - input-context - stream - event))) - (unless (frame-compare-pointer-documentation-state - frame - input-context - stream - frame-documentation-state - new-state) - (window-clear *pointer-documentation-output*) - (frame-print-pointer-documentation frame - input-context - stream - new-state - event) - (setq frame-documentation-state new-state)))))) + (updating-output (*pointer-documentation-output*) + (updating-output (*pointer-documentation-output* + :cache-value %doc-state% + :cache-test #'equal) + (frame-print-pointer-documentation frame + %input-context% + %stream% + %doc-state% + %event%)))))))))) + +(defgeneric invoke-with-output-to-pointer-documentation (frame continuation) + (:documentation "Invoke `continuation' with a single argument - +a stream that the continuation can write to, the output of which +will be used as the background message of the pointer +documentation pane of `frame'. If the pointer-documentation of +`frame' is not a `pointer-documentation-pane', `continuation' +will not be called.")) + +(defmethod invoke-with-output-to-pointer-documentation + ((frame standard-application-frame) continuation) + (with-accessors ((pointer-documentation frame-pointer-documentation-output)) frame + (when (typep pointer-documentation 'pointer-documentation-pane) + (setf (background-message pointer-documentation) + (with-output-to-output-record (pointer-documentation) + (funcall continuation pointer-documentation)) + (background-message-time pointer-documentation) (get-universal-time))))) + +(defmacro with-output-to-pointer-documentation ((stream frame) &body body) + "Bind `stream' to the pointer-documentation pane of `frame' and +capture the output of `body' on `stream' as the background +message of the pointer documentation pane. If `frame' does not +have a `pointer-documentation-pane' as pointer documentation, +`body' will not be evaluated." + `(invoke-with-output-to-pointer-documentation + ,frame #'(lambda (,stream) + ,@body)))
;;; A hook for applications to draw random strings in the ;;; *pointer-documentation-output* without screwing up the real pointer ;;; documentation too badly.
-(defgeneric frame-display-pointer-documentation-string - (frame documentation-stream string)) - -(defmethod frame-display-pointer-documentation-string - ((frame standard-application-frame) documentation-stream string) - (when *pointer-documentation-output* - (with-accessors ((frame-documentation-state frame-documentation-state)) - frame - (unless (frame-compare-pointer-documentation-state - frame nil documentation-stream frame-documentation-state string) - (window-clear documentation-stream) - (write-string string documentation-stream) - (setq frame-documentation-state string))))) +(defun frame-display-pointer-documentation-string (frame string) + (with-output-to-pointer-documentation (stream frame) + (write-string string stream)))
(defmethod frame-input-context-track-pointer ((frame standard-application-frame) --- /project/mcclim/cvsroot/mcclim/package.lisp 2008/01/12 11:04:05 1.64 +++ /project/mcclim/cvsroot/mcclim/package.lisp 2008/01/27 22:24:07 1.65 @@ -1935,6 +1935,8 @@ #:compose-space-aux #:simple-event-loop #:pointer-motion-hint-event + #:invoke-with-output-to-pointer-documentation + #:with-output-to-pointer-documentation #:frame-display-pointer-documentation-string #:list-pane-items
--- /project/mcclim/cvsroot/mcclim/panes.lisp 2008/01/01 23:23:07 1.186 +++ /project/mcclim/cvsroot/mcclim/panes.lisp 2008/01/27 22:24:07 1.187 @@ -27,7 +27,7 @@ ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;;; Boston, MA 02111-1307 USA.
-;;; $Id: panes.lisp,v 1.186 2008/01/01 23:23:07 thenriksen Exp $ +;;; $Id: panes.lisp,v 1.187 2008/01/27 22:24:07 thenriksen Exp $
(in-package :clim-internals)
@@ -2732,9 +2732,19 @@
(defparameter *default-pointer-documentation-background* +black+) (defparameter *default-pointer-documentation-foreground* +white+) +(defvar *background-message-minimum-lifetime* 1 + "The amount of seconds a background message will be kept +alive.")
(defclass pointer-documentation-pane (clim-stream-pane) - () + ((background-message :initform nil + :accessor background-message + :documentation "An output record, or NIL, that will +be shown when there is no pointer documentation to show.") + (background-message-time :initform 0 + :accessor background-message-time + :documentation "The universal time at which the +current background message was set.")) (:default-initargs :display-time nil :scroll-bars nil @@ -2748,6 +2758,12 @@ :end-of-line-action :allow :end-of-page-action :allow))
+(defmethod stream-accept :before ((stream pointer-documentation-pane) type + &rest args) + (declare (ignore args)) + (setf (background-message stream) nil) + (redisplay-frame-pane (pane-frame stream) stream :force-p t)) + ;;; CONSTRUCTORS
(defun make-clim-stream-pane (&rest options