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

#include <CM2MMessageListener.h>

Inheritance diagram for CM2MMessageListener:
CPMUnknown< IM2MMessageListener >IM2MMessageListenerIPMUnknown

Classes

class  myPrivateData
 

Protected Types

typedef bool16(* funcGetCanHandle )(const IClassInfo *cInfo)
 
typedef void(* funcGetMessages )(const PMIID *&targetM, uint32 &targetMSize, const PMIID *&ancestorM, uint32 &ancestorMSize, const PMIID *&descendentM, uint32 &descendentMSize, const PMIID *&unrelatedM, uint32 &unrelatedMSize)
 
typedef myPrivateData *(* funcCreateFor )(IM2MMessageListener::MessageHelper &helper)
 
typedef myPrivateData *(* funcSnapshotRead )(const UIDRef &targetRef, IPMStream *inStream)
 

Protected Member Functions

virtual int32 GetSubListenerCount () const =0
 
virtual funcGetCanHandle GetNthSubListenerGetCanHandle (int32 n) const =0
 
virtual funcGetMessages GetNthSubListenerGetMessages (int32 n) const =0
 
virtual funcCreateFor GetNthSubListenerCreateFor (int32 n) const =0
 
virtual funcSnapshotRead GetNthSubListenerSnapshotRead (int32 n) const =0
 
 CM2MMessageListener (IPMUnknown *boss)
 
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
 
virtual void Message (MessageHelper &helper, PrivateData *data)
 
virtual PrivateDataSnapshotRead (const UIDRef &targetRef, IPMStream *inStream)
 
- Protected Member Functions inherited from CPMUnknown< IM2MMessageListener >
 CPMUnknown (IPMUnknown *boss)
 

Additional Inherited Members

- Public Types inherited from IM2MMessageListener
enum  { kDefaultIID = IID_IM2MMESSAGELISTENER }
 
enum  Relation {
  kHierAncestor = -2, kHierParent = -1, kTarget = 0, kHierChild = 1,
  kHierDescendent = 2, kUnrelated
}
 
- Public Member Functions inherited from CPMUnknown< IM2MMessageListener >
IPMUnknownQueryInterface (PMIID interfaceID) const
 
void AddRef () const
 
void Release () const
 
void PreDirty (ImplementationID prop=kInvalidImpl, bool16 allowModification=kTrue)
 
void PreDirtyNoMessage (ImplementationID prop=kInvalidImpl, bool16 allowModification=kTrue)
 
 CPMUnknown (const CPMUnknown &)=delete
 
CPMUnknownoperator= (const CPMUnknown &)=delete
 
- Protected Attributes inherited from CPMUnknown< IM2MMessageListener >
HelperInterface fHelperInterface
 

Detailed Description

The CM2MMessageListener is an attempt to simplifiy the management of PrivateData for Listeners, especially for those which would like to create SubListeners which allows a Listener to listen to more than one class and have a different policy for each.

The CM2MMessageListener enforces that important requirement that there can only be ONE SubListener per class. If you find yourselves needing to have two SubListeners for the same class, even if they are looking at different messages, you cannot do it - you will have create entirely separate Listeners.

Here's what you do:

class SubListener1 : public CM2MMessageListener::myPrivateData

{

    public:

This constructor called from our static CreatFor() method.

        SubListener1(IM2MMessageListener::MessageHelper& helper) :

            fVarSetInMessage(-1),

            fVarSetInValidate(kFalse)

            {

            }

This constructor called from CM2MMessageListener::SnapshotRead()

        SubListener1(IPMStream* inStream) :

            fVarSetInValidate(kFalse)

            {

            SnapshotReadWrite(inStream);

            }

The CM2MMessageListener::myPrivateData requires us to implement this method. We just use our common Snapshot method.

        void        SubListenerSnapshotReadWrite(IPMStream* s)

            {

            SnapshotReadWrite(s);

            }

The CM2MMessageListener::myPrivateData requires us to implement this method. We will only be called for messages that we asked for.

        void        Message(IM2MMessageListener::MessageHelper& helper)

            {

            if ((fVarSetInMessage == -1) &&

                (helper.GetChange().GetIID() == IID_ISTORYLIST))

            {

The StoryList might be changing the number of stories. Get the current count before it changes.

                ASSERT(helper.GetFromPreChange());

                ASSERT(helper.GetChange().GetOriginalWasTarget());

                InterfacePtr<const IStoryList> sl(helper.GetTarget(), UseDefaultIID());

                fVarSetInMessage = sl->GetAllTextModelCount();

            }

            }

The CM2MMessageListener::myPrivateData requires us to implement this method. We will only be called for messages that we asked for.

        void        Validate(IM2MMessageListener::ValidateHelper& helper)

            {

            IM2MMessageListener::ChangeData change;

This could fail if we signed up for and got messages from a boss other than the Target, typicall as a Descenent, which was subsequently deleted before being called here.

In this example we do not get messages from Descendents.

            bool16 success = helper.GetFirstChange(change);

            ASSERT(success);



            do

            {

                if (change.GetIID() == IID_ISTORYLIST)

                {

                    ASSERT(fVarSetInMessage != -1);

                    InterfacePtr<const IStoryList> sl(helper.GetTarget(), UseDefaultIID());

                    int32 newCount = sl->GetAllTextModelCount();



                    if (newCount != fVarSetInMessage)

                    {

The total number of TextModels in the document have changed. Let's remember that.

                        fVarSetInValidate = kTrue;

                    }

                }

            }

            while (helper.GetNextChange(changeData);

Anything interesting change? if (fVarSetInValidate) { Yes! Broadcast something, fire command, whatever... } }

These four static methods are what the CM2MMessageListener needs.

        static bool16   GetCanHandle(const IClassInfo* cInfo)

            {

The IStoryList is on the kDocBoss it is quicker to match against this rather than searching for the interface.

            if (cInfo->GetClass() != kDocBoss)

                return kFalse;



            ASSERT(cInfo->GetImplementation(IID_ISTORYLIST) != kInvalidImpl);

            return kTrue;

            }



        static void     GetMessages(const PMIID*& targetM,

                                    uint32& targetMSize,

                                    const PMIID*& ancestorM,

                                    uint32& ancestorMSize,

                                    const PMIID*& descendentM,

                                    uint32& descendentMSize,

                                    const PMIID*& unrelatedM,

                                    uint32& unrelatedMSize)

            {

We are only interested in changes/messages that originate from bosses which have the StoryList - which is the doc.

            targetM = fTargetMList;

            targetMSize = fTargetMListSize;

            }



        static myPrivateData*   CreateFor(IM2MMessageListener::MessageHelper& helper)

            {

We would not be called unless GetCanHandle() returned kTrue.

Note that you do NOT have to return anything from here.

            return new SubListener1(helper);

            }



        static myPrivateData*   SnapshotRead(const UIDRef& targetRef,

                                            IPMStream* inStream)

            { return new SubListener1(targetRef, inStream); }



    private:

Static information about the PMIID messages we are interested in. In this case we are only interested in changes that originated on the class we are interested in.

        static PMIID    fTargetMList[];

        static uint32   fTargetMListSize;

This variable is set in Message() so we have to snapshot it. In this example it contains the number of TextModels in the doc.

        int32   fVarSetInMessage;

This variable is set in Validate() so we don't snapshot it.

        bool16  fVarSetInValidate;



        void    SnapshotReadWrite(const UIDRef& targetRef, IPMStream* s)

            {

            s->XferInt32(fVarSetInMessage);

            ASSERT(!fVarSetInValidate); // must match constructor

            }



}



const PMIID  SubListener1::kTargetMList[] = { IID_ISTORYLIST };

const uint32 SubListener1::kTargetMListSize = (sizeof(kTargetMList) / sizeof(kTargetMList[0]));



class SubListener2 : public CM2MMessageListener::myPrivateData

{

Another SubListener like the one above...

};



class YourListener : public CM2MMessageListener

{

    public:

        YourListener(IPMUnknown* boss) :

            CM2MMessageListener(boss)

            { }



        int32               GetSubListenerCount() const

            { return 2; }



        funcGetCanHandle    GetNthSubListenerGetCanHandle(int32 n) const

            {

            if (n == 0)

                return SubListener1::GetCanHandle;

            else

                return SubListener2::GetCanHandle;

            }



        funcGetMessages     GetNthSubListenerGetMessages(int32 n) const

            {

            if (n == 0)

                return SubListener1::GetMessages;

            else

                return SubListener2::GetMessages;

            }



        funcCreateFor       GetNthSubListenerCreateFor(int32 n) const

            {

            if (n == 0)

                return SubListener1::CreateFor;

            else

                return SubListener2::CreateFor;

            }



        funcSnapshotRead    GetNthSubListenerSnapshotRead(int32 n) const

            {

            if (n == 0)

                return SubListener1::SnapshotRead;

            else

                return SubListener2::SnapshotRead;

            }

};

Member Typedef Documentation

typedef myPrivateData*(* CM2MMessageListener::funcCreateFor)(IM2MMessageListener::MessageHelper &helper)
protected

Typedef for function which creates an instance of myPrivateData for the object specified by the helper. The callee is free to examine the info in the helper and decide if it wants to create or not, however, typical implementations will just do it.

Parameters
helperReference to helper for the class to be handled.
Returns
Pointer to new instances of myPrivateData.
typedef bool16(* CM2MMessageListener::funcGetCanHandle)(const IClassInfo *cInfo)
protected

Typedef for function which returns kTrue if the SubListener can handle the specified class.

Parameters
cInfoPointer to IClassInfo for the class to be handled.
Returns
kTrue if the SubListener can handle the class.
typedef void(* CM2MMessageListener::funcGetMessages)(const PMIID *&targetM, uint32 &targetMSize, const PMIID *&ancestorM, uint32 &ancestorMSize, const PMIID *&descendentM, uint32 &descendentMSize, const PMIID *&unrelatedM, uint32 &unrelatedMSize)
protected

Typedef for function that which returns static pointers to the messages which the SubListener supports.

Parameters
targetM
targetMSize
ancestorM
ancestorMSize
descendentM
descendentMSize
unrelatedM
unrelatedMSize
typedef myPrivateData*(* CM2MMessageListener::funcSnapshotRead)(const UIDRef &targetRef, IPMStream *inStream)
protected

Typedef for function which will be called to snapshot read and return a return a new constructed myPrivateData and initialize from the specified stream. Callee must return an instance even it did not write anything into the snapshot.

Parameters
targetRefUIDRef to target boss
inStreamPoint to IPMStream
Returns
Pointer to new instance of myPrivateData.

Constructor & Destructor Documentation

CM2MMessageListener::CM2MMessageListener (IPMUnknownboss)
protected

We provide implementations for all the IM2MMessageListener methods. Constructor.

Parameters
bossPointer to IPMUnknown

Member Function Documentation

virtual void CM2MMessageListener::GetMessagesFor (const IClassInfocInfo,
const PMIID *& targetM,
uint32 & targetMSize,
const PMIID *& ancestorM,
uint32 & ancestorMSize,
const PMIID *& descendentM,
uint32 & descendentMSize,
const PMIID *& unrelatedM,
uint32 & unrelatedMSize 
) const
inlineprotectedvirtual
virtual funcCreateFor CM2MMessageListener::GetNthSubListenerCreateFor (int32 n) const
protectedpure virtual

Returns a function pointer to the nTh SubListeners CreateFor() function. Overriding classes must implement.

Parameters
nIndex of SubListener
Returns
Pointer to CreateFor() function
virtual funcGetCanHandle CM2MMessageListener::GetNthSubListenerGetCanHandle (int32 n) const
protectedpure virtual

Returns a function pointer to the nTh SubListeners GetCanHandle() function. Overriding classes must implement.

Parameters
nIndex of SubListener
Returns
Pointer to GetCanHandle() function
virtual funcGetMessages CM2MMessageListener::GetNthSubListenerGetMessages (int32 n) const
protectedpure virtual

Returns a function pointer to the nTh SubListeners GetMessages() function. Overriding classes must implement.

Parameters
nIndex of SubListener
Returns
Pointer to GetMessages() function
virtual funcSnapshotRead CM2MMessageListener::GetNthSubListenerSnapshotRead (int32 n) const
protectedpure virtual

Returns a function pointer to the nTh SubListeners SnapshotRead() function. Overriding classes must implement.

Parameters
nIndex of SubListener
Returns
Pointer to SnapshotRead() function
virtual int32 CM2MMessageListener::GetSubListenerCount () const
protectedpure virtual

Returns the number of SubListeners implemented the overriding class. Overriding classes must implement.

Returns
Number of SubListeners available. Must be at least one.
virtual void CM2MMessageListener::Message (MessageHelperhelper,
PrivateDatadata 
)
inlineprotectedvirtual
virtual PrivateData* CM2MMessageListener::SnapshotRead (const UIDReftargetRef,
IPMStreaminStream 
)
inlineprotectedvirtual
See Also
IM2MMessageListener::SnapshotRead(). It is important that derived classes NOT overrides this method or myPrivateData::SnapshotWrite() or else the mechanism to identify which SubListener created the myPrivateData will be lost.

Implements IM2MMessageListener.