InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
IM2MMessageListener Class Referenceabstract

#include <IM2MMessageListener.h>

Inheritance diagram for IM2MMessageListener:
IPMUnknownCPMUnknown< IM2MMessageListener >CM2MMessageListener

Classes

class  ChangeData
 
class  MessageHelper
 
class  PrivateData
 

Public Types

enum  { kDefaultIID = IID_IM2MMESSAGELISTENER }
 
enum  Relation {
  kHierAncestor = -2, kHierParent = -1, kTarget = 0, kHierChild = 1,
  kHierDescendent = 2, kUnrelated
}
 

Public Member Functions

virtual void GetMessagesFor (const IClassInfo *cInfo, const PMIID *&targetM, uint32 &targetMSize, const PMIID *&ancestorM, uint32 &ancestorMSize, const PMIID *&descendentM, uint32 &descendentMSize, const PMIID *&unrelatedM, uint32 &unrelatedMSize) const =0
 
virtual void Message (MessageHelper &helper, PrivateData *data)=0
 
virtual PrivateDataSnapshotRead (const UIDRef &targetRef, IPMStream *inStream)=0
 
- Public Member Functions inherited from IPMUnknown
virtual IPMUnknownQueryInterface (PMIID interfaceID) const =0
 
virtual void AddRef () const =0
 
virtual void Release () const =0
 

Detailed Description

Model To Model Listeners are a low level mechanism to "listen to" (vs Subject/Observer) changes to persistent objects in a database. It was used internally in CS4 to revise the way TextWrap and TextFrames detect changes to the the myriad number of properties and objects they depend on.

For example, MultiColumnTextFrames are dependent on their parent Spline for its stroke, stroke alignment, text inset, movement relative to the spread, etc.

Any changes to these properties requires explict action by the MCF to manage its size and/or text content.

Listeners are registered with K2 service providers thus:


Class

{

    kFooListenerServiceBoss,

    kInvalidClass,

    {

        IID_IK2SERVICEPROVIDER, kM2MMessageListenerServiceProviderImpl,

        IID_IM2MMESSAGELISTENER, kFooListenerImpl,

    }

}

    

Listeners can be attached to any persistent objects in the system and this attachment is determined by the M2MMessageManager on the first change to a persistent instance of a class by calling all the Listeners on their GetMessagesFor() method. A Listener which wishes to receive further notifcation of changes to any instance of the specified class must return a list of "messages" in the form of PMIIDs associated with the class.

The next time any implementation which implement one of the specified IIDs on that class changes the Listener will be called at its Message() method.

Listeners which use the MessageHelper::AddPrivateData() method to add PrivateData will be called back on their Validate() method when the Command Stack goes empty, typically, but not exclusively.

In Validate() they can fire commands (or make direct model changes) which will be associated with the same transaction as the command that is just finishing.

Listeners have several advantages over the traditional Subject/Observer mechanism:

  1. Listeners do not need to know or rely on known Commands or Protocols in order to find out about changes to any class it is listening to.
  1. Listeners are typically called immediately before the implementation it is listening to changes - allowing it to take read and save (in PrivateData) the state of the implementation and compare it to the final state at Validate() time. This allows detailed understanding of the actual change that took place on the particular boss.
  1. Listeners can listen to many changes and defer their reaction until Validate() at which time they can decide how to proceed. This improves performance, and in some cases correctness, because the Listener does not have to react to every change as an Observer has to.
  1. Listeners can listen to messages in the context of their place in the IHierarchy (Ancestor, Descendent) without having to explicitly listen to the parent or descendent objects. This quite useful when changes to Ancestor, such as a transform, effectively changes position of the object being listened to but without and explit change to any of it's interfaces.

See CM2MMessageListener for a simplified way to implement Listeners which wish to have PrivateData (as most will).

Member Enumeration Documentation

The Relation enum describes the relationship in IHierarchy terms between the boss the Listener is listening to, specified by MessageHelper::GetTarget() and ValidateHelper::GetTarget(), and the boss the message was originated from.

Note that messages of Relation other than kTarget are by definition the result of a explit call by another Listener to forward the message from a boss that they are listening to to another boss. MessageHelper::Forward() is one way to do this.
Enumerator
kHierAncestor 

The message is from a boss that is an ancestor to, but NOT the parent of, the boss the Listener is listening to.

kHierParent 

The message is from a boss that is the parent of the boss the Listener is listening to.

kTarget 

The message is from the boss that Listener is listening to.

kHierChild 

The message is from a boss that is the child of the boss the Listener is listening to.

kHierDescendent 

The message is from a boss that is the descendent of, but NOT the child of, the boss the Listener is listening to.

kUnrelated 

The message is from a boss that is unrelated by IHierarchy to the boss the Listener is listening to.

Member Function Documentation

virtual void IM2MMessageListener::GetMessagesFor (const IClassInfocInfo,
const PMIID *& targetM,
uint32 & targetMSize,
const PMIID *& ancestorM,
uint32 & ancestorMSize,
const PMIID *& descendentM,
uint32 & descendentMSize,
const PMIID *& unrelatedM,
uint32 & unrelatedMSize 
) const
pure virtual

Return a pointer to the vector of PMIID messages that the Listener is interested in about the specified Class. If the Listener is not interested in the class then it should return nil.

Implemented in CM2MMessageListener.

virtual void IM2MMessageListener::Message (MessageHelperhelper,
PrivateDatadata 
)
pure virtual

Notification that a message has been sent to a boss listened to by the callee Listener. It is ASSERT()able that the only messages that a Listener will see are part of the set returned by what was returned from GetMessagesFor().

Listeners may only do direct modifications to data in this context (do not fire commands) and keep their work to a minimum in the interest of performance.

Those Listeners which need to do major work, such as firing commands, must create PrivateData and defer this work to a PrivateData::Validate() method.

Parameters
helperReference to ChangingHelper boss.
dataReference to PrivateData class created in a previous call in the same M2MMessageManager 'transaction'. See MessageHelper::AddPrivateData().

Implemented in CM2MMessageListener.

virtual PrivateData* IM2MMessageListener::SnapshotRead (const UIDReftargetRef,
IPMStreaminStream 
)
pure virtual

A Listener which has previously created PrivateData is being called to create a new instance of PrivateData and initialize it from the snapshot (possibly) created by a previous call to PrivateData::SnapshotWrite().

Note that a Listener which does not change any state of their PrivateData during calls to Message() does not need to write anything out when called for SnapshotWrite(). However, the Listener will still be called at this method and will need to construct and return a new instance of their PrivateData().

Parameters
targetRefUIDRef to object the Listener is associated with
inStreamPointer to IPMStream input stream positioned at the snapshot data (if any) previously written in a call to PrivateData::SnapshotWrite()

Implemented in CM2MMessageListener.