CLIM mail archive

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

Re: use of AND and Or in presentation specs



    Date: Tue, 2 Nov 1993 14:02 EST
    From: Daniel D Suthers <suthers+@pitt.edu>

    CLIM1.1

    In partial reply to my question, '(and p1 p2) works in
    with-output-as-presentation,
    but apparently not in defining commands ...

    #|-----------------------------------------------------------------------------
    -
    Using "and" presentation types ...

    Problem: we have two independent presentation hierarchies (one for a
    syntactic classification, another for an application-dependent
    semantic classification). We want to be able to draw the thing in a
    single presentation that is classified in both hierarchies.

    Confusion: The manual says presentation type names are "usually"
    symbols, but doesn't say when they aren't. It tells us about "and" and
    "or" operators for meta-presentation types but doesn't say where these
    are legal.

    Solution: The following approach appears to work (in CLIM 1.1, Lucid4.0
    and MCL2.0):

      (with-output-as-presentation
	  (:stream stream
	   :object object
	   :type (list 'and <syntactic-presentation> <semantic-presentation>))
	...)

    Then a command defined on either of the presentation types (alone) will
    highlight the conjunctive presentation.

    One apparently CANNOT use conjunctive presentation types in commands, e.g.
    one can't do:

      (define-test-window-command (BEEP-ON-AB-PRESENTATIONS :menu "Find AB's")
	  ((presentation '(and a b) :gesture :select))
	  ...)

    The error occurs at run time in both Lucid and MCL (see end).
    To see the error you need to uncomment and evaluate the "Find AB's" command.

The example below can't ever work because you have not defined
PRESENTATION-TYPEP methods for the p-types A and B.  If the presentation
types in your real application are actually CLOS classes, then your
application should work.  If, however, they are just p-types, you need
to define PRESENTATION-TYPEP methods for them.  Without the P-TYPEP
method, CLIM can't determine whether or not an object is of that type.

Later versions of CLIM have a default PRESENTATION-TYPEP method that
signals an error that tells you to define a PRESENTATION-TYPEP method.

The translators from the A and B types don't ever need to call the
PRESENTATION-TYPEP method since the types match a translator exactly
(that is, they can be compared with EQ).  The translator from (AND A B)
can't use this optimization -- it needs to use PRESENTATION-TYPEP --
so it blows out.

There was also a bug in presentation translators in CLIM 1.0 that got
fixed at some point.  With any luck, it's fixed in the CLIM you are
using and if you write P-TYPEP methods, you will win.

    ------------------------------------------------------------------------------|
    #

    (in-package :CLIM-USER)

    #+:MCL (setq CLIM::*COMMANDS-IN-MENUBAR* nil)

    (defvar *root-window* (clim:open-root-window #+:CLX :clx
						 #+:MCL :mcl
						 ))

    (define-application-frame TEST-WINDOW ()
      ;;
      ()
      (:panes (
	       (output-pane
		:application
		:scroll-bars :vertical)
	       (test-display :application
			     :display-after-commands nil
			     :display-function 'display-test
			     :scroll-bars :both)
	       (documentation :pointer-documentation)
	       (menu :command-menu)))
      (:layout ((default
		    (:column :rest
			     (test-display  17/20)
			     (output-pane   1/20)
			     (documentation 1/20)
			     (menu         :rest))))))

    (clim:define-presentation-type A ())
    (clim:define-presentation-type B ())

    ;;; This is what we want to AVOID having to do, since there
    ;;; would be too many combinations of predefined syntactic
    ;;; presentations with application-dependent semantic
    ;;; presentations.
    ;;;
    ;;; (clim:define-presentation-type AB () :inherit-from '(a b))

    (defun RUN-TEST ()
      ;;
      (let ((frame (clim:make-application-frame
		    'test-window
		    :parent *root-window*
		    :width 600
		    :height 600)))
	(clim:run-frame-top-level frame)))

    (define-test-window-command (BEEP-ON-A-PRESENTATIONS :menu "Find A's")
	((presentation 'A :gesture :select))
      (declare (ignore presentation))
      (clim:beep)
      (format *standard-output* "~%You found an A."))

    (define-test-window-command (BEEP-ON-B-PRESENTATIONS :menu "Find B's")
	((presentation 'B :gesture :select))
      (declare (ignore presentation))
      (clim:beep)
      (format *standard-output* "~%You found a B."))

    ;;; This does NOT work, see error at end ...
    #|
    (define-test-window-command (BEEP-ON-AB-PRESENTATIONS :menu "Find AB's")
	((presentation '(and a b) :gesture :select))
      (declare (ignore presentation))
      (clim:beep)
      (format *standard-output* "~%You found an AB."))
    |#

    (define-test-window-command (DONE :menu "Done") ()
      (clim:frame-exit clim:*application-frame*)
      )

    (defmethod DISPLAY-TEST ((application test-window) stream)
      (window-clear stream)
      ;;
      ;; Draw some A's
      ;;
      (with-output-as-presentation
	  (:stream stream :object 'a :type 'A)
	(surrounding-output-with-border
	 (stream :shape ':rectangle)
	 (draw-text* stream "A" 50 50)))
      (with-output-as-presentation
	  (:stream stream :object 'a :type 'A)
	(surrounding-output-with-border
	 (stream :shape ':rectangle)
	 (draw-text* stream "A" 300 200)))
      ;;
      ;; Draw some B's
      ;;
      (with-output-as-presentation
	  (:stream stream :object 'b :type 'B)
	(surrounding-output-with-border
	 (stream :shape ':rectangle)
	 (draw-text* stream "B" 450 350)))
      (with-output-as-presentation
	  (:stream stream :object 'b :type 'B)
	(surrounding-output-with-border
	 (stream :shape ':rectangle)
	 (draw-text* stream "B" 200 300)))
      ;;
      ;; Draw some AandB's.
      ;;
      ;; >>>>> THIS IS WHERE WE NEED "AND" THE MOST, especially with <<<<<
      ;; >>>>> the presentation types being determined at run time.   <<<<<
      ;;
      (with-output-as-presentation
	  (:stream stream :object 'ab :type (list 'and 'a 'b))
	(surrounding-output-with-border
	 (stream :shape ':rectangle)
	 (draw-text* stream "AandB" 110 90)))
      (with-output-as-presentation
	  (:stream stream :object 'ab :type (list 'and 'a 'b))
	(surrounding-output-with-border
	 (stream :shape ':rectangle)
	 (draw-text* stream "AandB" 280 180)))
      ;;
      #+:MCL (clim::redisplay-decorations stream))

    #|-----------------------------------------------------------------------------
    -
    ;;; For this test, uncomment & evaluate the "Find AB's" command before
    running...

    > (run-test)
    >>Error: No applicable method exists for the generic-function
    CLIM::PRESENTATION-TYPEP-METHOD when called with these arguments:
    (#<{Instance?} #X119B8266> NIL ("Find AB's" NIL (:COMMAND #)) A)

    (:GENERIC-FUNCTION NO-APPLICABLE-METHOD :|dispatch code|):
       Required arg 0 (GENERIC-FUNCTION): #<Presentation-Generic-Function
    CLIM::PRESENTATION-TYPEP-METHOD (21)>
       Rest arg 1 (ARGS): (#<{Instance?} #X119B8266> NIL ("Find AB's" NIL
    (:COMMAND #)) A)
    :C  0: Try this call again
    :A  1: Return to Test Window command level
	2: Test Window top level
	3: Exit Test Window
	4: Abort to Lisp Top Level

    -> :B
    (:GENERIC-FUNCTION NO-APPLICABLE-METHOD :|dispatch code|) <-
    (:GENERIC-FUNCTION NO-APPLICABLE-METHOD :|update trampoline|) <-
    (:GENERIC-FUNCTION CLIM::PRESENTATION-TYPEP-METHOD :|dispatch code|) <-
    PRESENTATION-TYPEP <- ...


References:

Main Index | Thread Index