![]() | InDesign SDK 20.5 |
#include <CM2MMessageListener.h>

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 PrivateData * | SnapshotRead (const UIDRef &targetRef, IPMStream *inStream) |
Protected Member Functions inherited from CPMUnknown< IM2MMessageListener > | |
| CPMUnknown (IPMUnknown *boss) | |
Additional Inherited Members | |
Public Member Functions inherited from CPMUnknown< IM2MMessageListener > | |
| IPMUnknown * | QueryInterface (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 | |
| CPMUnknown & | operator= (const CPMUnknown &)=delete |
Protected Attributes inherited from CPMUnknown< IM2MMessageListener > | |
| HelperInterface | fHelperInterface |
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;
}
};
| 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.
| helper | Reference to helper for the class to be handled. |
| protected |
Typedef for function which returns kTrue if the SubListener can handle the specified class.
| cInfo | Pointer to IClassInfo for the class to be handled. |
| protected |
Typedef for function that which returns static pointers to the messages which the SubListener supports.
| targetM | |
| targetMSize | |
| ancestorM | |
| ancestorMSize | |
| descendentM | |
| descendentMSize | |
| unrelatedM | |
| unrelatedMSize |
| 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.
| protected |
We provide implementations for all the IM2MMessageListener methods. Constructor.
| boss | Pointer to IPMUnknown |
| inlineprotectedvirtual |
Implements IM2MMessageListener.
| protectedpure virtual |
Returns a function pointer to the nTh SubListeners CreateFor() function. Overriding classes must implement.
| n | Index of SubListener |
| protectedpure virtual |
Returns a function pointer to the nTh SubListeners GetCanHandle() function. Overriding classes must implement.
| n | Index of SubListener |
| protectedpure virtual |
Returns a function pointer to the nTh SubListeners GetMessages() function. Overriding classes must implement.
| n | Index of SubListener |
| protectedpure virtual |
Returns a function pointer to the nTh SubListeners SnapshotRead() function. Overriding classes must implement.
| n | Index of SubListener |
| protectedpure virtual |
Returns the number of SubListeners implemented the overriding class. Overriding classes must implement.
| inlineprotectedvirtual |
Implements IM2MMessageListener.
| inlineprotectedvirtual |
Implements IM2MMessageListener.