CLIM mail archive

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

Presentation typep and subtypep



    Date: Tue, 27 Oct 1992 16:21 EST
    From: Brian Anderson <bha@atc.boeing.com>

    Allegro CL 4.1
    CLIM 1.1
    SunOS 4.1.1

    I am perplexed by the behavior of presentation-typep and
    presentation-subtypep.  I guess that I just don't have a clear model
    for what is going on.  I have not been able to glean one for the
    documentation either.  I (and I'll bet others) would benefit from a
    clear description of the model.

    The following describes some problems I have had in defining a
    presentation type with parameters and the presentation-typep and
    presentation-subtypep methods.  It also includes a description of the
    behavior I have been able to glean from debugging and instrumenting my
    code and my guesses as to what the underlying model could be
    (sometimes confused and/or multiple guesses).  I would *greatly*
    appreciate any corrections to misconceptions contained herein!

    This long winded posting is an attempt to clear up these problems and
    misconceptions for me (and others?).  I would be willing to write up
    an explanation for the archive if I can obtain a good model.  Maybe
    someone (Scott?, Chris?) could hack this up so that it reflects
    reality and mail it back to me.  Then, maybe we could work up a good
    (working!) example for presentation types with parameters to place in
    the archive to go along with this description.

    If you're still with me, here it goes...

    The documentation for presentation-typep on pg 366 sez:

     "If the type name in "type" is or names a CLOS class, the method
     [presentation-typep] is called only if "object" is a member of the
     class and "type" contains parameters..."

First note that p. 366 is only talking about when PRESENTATION-TYPEP
presentation methods get called, *not* when the function
PRESENTATION-TYPEP is called.  It is true that the function
PRESENTATION-TYPEP gets called when you wave the mouse around, but this
is not guarantee that your PRESENTATION-TYPEP presentation methods will
get called.  In fact, CLIM tries hard not to call those methods when you
are just waving the mouse around.

The same goes for PRESENTATION-SUBTYPEP.

You might find it helpful to macroexpand a DEFINE-PRESENTATION-METHOD
form.  Notice that when you define a PRESENTATION-TYPEP presentation
method, the name of the generic function that gets specialized is
PRESENTATION-TYPEP-METHOD.  So, the function PRESENTATION-TYPEP might
call your PRESENTATION-TYPEP-METHOD method in the circumstances
described by the documentation.

    Well, I defined a presentation type with parameters whose name is the
    same as a CLOS class.  Then I defined a presentation-typep and
    presentation-subtypep method.  The presentation-typep method is *only*
    called when I mouse over a presentation whose type is something
    *other* than the presentation type that these methods are specialized
    for.  For example, presentation-typep is called when I mouse over a
    presentation of type clim:expression but not when I mouse over a
    presentation of my type.  This is *not* the behavior I see with
    presentation types whose name is not the name of a CLOS class.  In
    that case, the presentation-typep method is always called.

Sure.  That's because a presentation type whose name is the same as a
CLOS class comprises object whose type can be determined simply by
looking at the object - the objects will be members of the class.  For a
presentation type whose name is not a CLOS class, the type information
is not manifest in the object itself, so you must supply a
PRESENTATION-TYPEP presentation method.

CLIM did not bother calling your PRESENTATION-TYPEP method in the first
case because all CLOS objects are Lisp expressions, always.  None of
your type parameters can change this.

    From this behavior, it appears that there is an "invisible"
    presentation-typep method (behavior) for presentation types whose name
    is the same as a CLOS class.  This method determines whether the
    application object associated with the presentation the mouse is
    pointing at is a member (instance) of the CLOS class.  Only meta
    presentations (such as clim:expression) end up calling the
    presentation-type method I have defined.  For presentation types whose
    name is *not* a CLOS class, there is no "invisible" behavior.  The
    presentation types presentation-typep method is always called to
    determine the identity/associativity of the presentation type with an
    application object.

You might be better served by calling PRESENTATION-TYPEP directly rather
than relying on waving your mouse over objects in some window.  This is
also confusing you.  As I said above, CLIM tries very hard to avoid
calling *any* user code when you are waving the mouse around; it does
this in order to be as fast as possible.

    So, is the presentation-typep method supposed to say whether an object
    "has a" presentation of some type or is it to determine if the current
    input context applies with respect to the application object?  Why is
    this method not called in certain cases for CLOS classes?

PRESENTATION-TYPEP simply answers the question "is such-and-such object
of the specified (presentation) type".  For presentation types that are
the same as a CLOS class (with no parameters), PRESENTATION-TYPEP is
identical to TYPEP.  When you add parameters, you yourself must specify
how this affects type inclusion.  The same goes for p-types that are not
CLOS classes - you must specify what objects are in the class.

    If this invisible behavior is by design (and my analysis is correct),
    I question whether this is the most appropriate and consistent
    abstraction.  It would be less confusing if there wasn't this
    "invisible" behavior for CLOS classes.  If there is a default for
    presentation types whose name is the same as a CLOS class - OK, thats
    cool.  If I define a presentation-typep method, it should *override*
    this default presentation-typep method.  

I disagree.  You would then be saying that there are two types having
the same name that have different behavior.  This seems crazy, and would
simply promote bugs.

					     This is the behavior for
    non-CLOS presentation types and should be the same (IMHO) for CLOS
    presentation types too.  
			     
No.  CLOS p-types *already* have type inclusion information - the same
information used by CLOS, because CLIM just uses CLOS.  For non-CLOS
p-types, you need to specify the type inclusion rules, because there is
no way for CLIM to tell.

			     If that's what I want to do, well so be it
    (and if I get into trouble, thats my problem).  In any case, shouldn't
    the method always be called (as we shall see later)?

No.

    So, lets continue on to presentation-subtypep.  My
    presentation-subtypep method is always called whether I mouse over a
    meta presentation of a presentation of the type that the

I wouldn't know a "meta presentation" if I fell on one.

    presentation-subtypep method is specialized for.  The methods
    arguments are two presentation type "specifiers."  I call a
    presentation type specifier something like:

       name
       (name parameters)
       ((name parameters) options)

    The first argument is the presentation type specifier of the
    presentation that the mouse is currently pointing at.  It is
    guaranteed to be of the same (presentation) type (or subtype of the
    presentation type?)  as the first arguments specialized (presentation
    type) class name.  The second argument is the presentation type
    specifier for the current input context.  This is defined by the
    currently active accept or as defined in the dynamic extent of the
    with-input-context macro.

Please, just call PRESENTATION-SUBTYPEP directly, and leave ACCEPT and
WITH-INPUT-CONTEXT out of it.  Things will look much clearer.

    So, I am confused as to the appropriate roles for presentation-typep
    and presentation-subtypep.  I guess that they both are used to
    determine applicability of presentation handlers (translators or
    actions) relative to the current input context?  
						     
No, PRESENTATION-TYPEP just tells you if an object is of a specified
type, and PRESENTATION-SUBTYPEP just tells you if one type is a subtype
of another.  Don't worry about presentation "handlers" and input
contexts.  They are built on top of presentation types, but there are a
lot of other rules involved in doing handler matching.

						     I am especially
    confused because of the apparent behavior of presentation-typep not
    being called in all cases for CLOS classes.  Does presentation-typep
    define the link/identity/associativity between an object and a
    presentation type (the one that presentation-typep is specialized
    for)?  This doesn't seem correct as this relationship is held in the
    presentation object(?).  I suppose one can get into trouble though
    when some arbitrary object is presented as some presentation type (via
    with-output-as-presentation).  
				   
The consequences of presenting an object of one type as some other type
are undefined.  Right now, CLIM doesn't complain, but there is some code
in CLIM that (if it were turned on) would complain when you try to
present an object of some type as another mismatching type.

				   Or, does presentation-typep define
    presentation handler applicability between an object and the current
    input context's presentation type specifier?  Since presentation-typep
    is not called even for parameterized CLOS classes, I can't see how
    this method can determine handler applicability using the application
    object for an input context.

You might also be getting confused by a bug in CLIM 1.1 in handler
matching.  Try this:

(in-package :clim)
(defun identity-translator-applicable-p (presentation context-type)
  (let* ((type (presentation-type presentation))
	 (type-name (presentation-type-name type))
	 (object (presentation-object presentation)))
    (with-presentation-type-decoded (context-name context-parameters) context-type
      (if (eq type-name 'blank-area)
	  (eq context-name 'blank-area)
	;; Let MENU-ITEM-IDENTITY take care of pure menu items
	(unless (and (eq type-name 'menu-item)
		     (eq context-name 'menu-item))
	  ;; Either the types definitely match, or the types nominally match
	  ;; and the object must be validated.
	  (or (presentation-subtypep type context-type)
	      (and (not (null context-parameters))
		   (presentation-typep object context-type))))))))

    Should the role of the presentation-subtypep method be to examine the
    presentation parameters of the presentation that mouse is currently
    pointing at and the current input context (and any presentation
    parameters associated with it) in order to determine if the
    presentation pointed at by the mouse (its presentation type specifier)
    is really a subtype of the presentation type (according to its
    presentation type specifier) that presentation-subtypep is specialized
    for?  If so, that might necessitate obtaining access to the
    application object in order to make the determination (since the
    presentation-typep method is not called in all cases in order to make
    this determination).  How do I do this?  If not, is the role of
    presentation-subtypep method to determine if the input context
    (presentation type specifier) is a type or subtype of the presentation
    type (specifier) of the presentation we are currently pointing at?  If
    so, then it seems that presentation-typep should be determining
    handler applicability based upon the application object.

    Blah.....

I really think you should go backl and run your experiments without
recourse to ACCEPT and WITH-INPUT-CONTEXT.  Just call PRESENTATION-TYPEP
and PRESENTATION-SUBTYPEP directly.  CLIM really is 

    It occurs to me that maybe presentation-typep is supposed to determine
    applicability of the current input context presentation type specifier
    against the application object, and presentation-subtypep is supposed
    to additionally determine applicability of the current input context
    presentation type specifier against the presentation type specifier of
    the presentation we are pointing at.  I guess there is the potential
    to present something of a presentation type specifier that does not
    make sense semantically with respect to the actual state of the
    application object.

    The documentation for presentation-typep is misleading or the behavior
    for presentation types whose name is the same as a CLOS class is
    incorrect or I'm totally confused.  Well, I am confused, there is no
    doubt about that!  Also (and *very* confusing) the university example
    in the CLIM manual seems to be incorrect!  Note that in that example
    (pg. 176), even though I have a parameterized presentation type and I
    have an accept that is parameterized I can actually accept an
    application object that does not match the semantics of the accept
    (whew!).  Consider the following accept:

      (accept `(student ,(find-department "Agriculture")))

    Note that you can actually (incorrectly) accept a student that is not
    a member of the agriculture department.  I believe this is true
    because the presentation-typep method is trying enforce a subset
    relationship with the application object (and is never called as
    outlined above).  Is my analysis correct?

There is a bug in CLIM 1.1 that might cause this.  The code I supplied
above may fix it.  But note that the bug is in handler matching, not in
CLIM's type system.

    So, lets correctly fill in the following:

    presentation-typep

    Defines the identity/association between an application object and its
    presentation.

    or

    Defines the applicability of a presentation handler in a given input
    context with respect to an application object.

Neither.  It's job is to return T if an object is of the specified type,
otherwise it returns NIL.  That's all.

The job of a PRESENTATION-TYPEP presentation method is to implement the
functionality of PRESENTATION-TYPEP for a single type.

    ***NOTE - The following is really not clear in the documentation either!
	      Is this description correct?

    Note that the lexically bound names of presentation type parameters
    are the *defaults* as defined in the define-presentation-type form.
    They are *not* the actual values of the parameters of the presentation
    type specifier passed to presentation-typep!  In order to gain access
    to the values of the parameters of the presentation type specifier
    passed to presentation-type, use the macros
    with-presentation-type-decoded or with-presentation-type-parameters.

Not true.  You may be getting confused by CLIM sometimes calling your
method on a "naked" (unparameterized) type.

    Note that the same caveat is true for the bindings of presentation
    type parameters in the accept method!  The lexically bound names for
    parameters are the default values from the define-presentation-type
    form.  Once again, use either with-presentation-type-decoded or
    with-presentation-type-parameters to obtain the parameters values for
    the presentation type specifier passed to accept.

Not true, unless there is some horrible bug in CLIM under Allegro.  It
is certainly the case that I get the right bindings.

    presentation-subtypep

    Checks congruency of type specifiers between the current input
    context's presentation type specifier (as defined by accept or
    with-input-context) and the presentation type specifier of the
    presentation that the mouse is currently pointing at.  The first
    argument to presentation-subtypep is guaranteed to be a presentation
    type specifier whose presentation type is the same (or a subtype of?)
    as the specialized presentation type defined in the lambda list.
    (Probably could say this better - help?)

No.  PRESENTATION-SUBTYPEP returns (values T T), (values NIL T), or
(values NIL NIL), meaning "is a subtype of", "is definitely not a
subtypep of", or "might not be a subtype of".

The job of a PRESENTATION-SUBTYPEP presentation method is to compare the
type parameters of two presentation types of the same "base" type.

    ----

    Well, this brings up another problem!  Being able to make the
    determination if the current input context is a type or subtype of the
    presentation (that is it's type specifier) that the mouse is pointing
    at seems to assume/require that the presentation was originally
    "present"ed in the right way.  That is, it was presented with a
    presentation type specifier that *includes* parameters.  For example,
    consider the following:

       (defclass color () (<slot declarations>))

       ...

       (define-presentation-method presentation-typep
				   (object (input-context-type color))

You are inviting confusion by using INPUT-CONTEXT-TYPE as a name, since
that has nothing to do with what PRESENTATION-TYPEP does.

	<make membership determination of moused presentation's object
	   against input context's presentation type specifier?>

	...)

       (define-presentation-method presentation-subtypep
				   ((target-type color) input-context-type)

Ditto.

	<make subtype determination of moused presentation's presentation
	   type specifier against the input context's presentation type specifier?>

	...)

    The following might work since presentation-subtypep has access to the
    parameter for the red color object indicating that it is a primary
    color.

       (present *red-color-object* '(color :primary t)) 
       (accept '(color :primary t))

    will allow presentation-subtypep to work for the accept.  But the
    following will not work, as accept could still accept a color object
    even if its not a primary since the present sez that this
    presentations type specifier is essentially '(color :primary *).

       (present *red-color-object* 'color)
       (accept 'color)



0,,

Follow-Ups: References:

Main Index | Thread Index