xref: /aoo4110/main/sw/inc/calbck.hxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #ifndef _CALBCK_HXX
25*b1cdbd2cSJim Jagielski #define _CALBCK_HXX
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include <tools/rtti.hxx>
28*b1cdbd2cSJim Jagielski #include "swdllapi.h"
29*b1cdbd2cSJim Jagielski #include <boost/noncopyable.hpp>
30*b1cdbd2cSJim Jagielski 
31*b1cdbd2cSJim Jagielski class SwModify;
32*b1cdbd2cSJim Jagielski class SwClientIter;
33*b1cdbd2cSJim Jagielski class SfxPoolItem;
34*b1cdbd2cSJim Jagielski class SfxHint;
35*b1cdbd2cSJim Jagielski 
36*b1cdbd2cSJim Jagielski /*
37*b1cdbd2cSJim Jagielski     SwModify and SwClient cooperate in propagating attribute changes.
38*b1cdbd2cSJim Jagielski     If an attribute changes, the change is notified to all dependent
39*b1cdbd2cSJim Jagielski     formats and other interested objects, e.g. Nodes. The clients will detect
40*b1cdbd2cSJim Jagielski     if the change affects them. It could be that the changed attribute is
41*b1cdbd2cSJim Jagielski     overruled in the receiving object so that its change does not become
42*b1cdbd2cSJim Jagielski     effective or that the receiver is not interested in the particular attribute
43*b1cdbd2cSJim Jagielski     in general (though probably in other attributes of the SwModify object they
44*b1cdbd2cSJim Jagielski     are registered in).
45*b1cdbd2cSJim Jagielski     As SwModify objects are derived from SwClient, they can create a chain of SwClient
46*b1cdbd2cSJim Jagielski     objects where changes can get propagated through.
47*b1cdbd2cSJim Jagielski     Each SwClient can be registered at only one SwModify object, while each SwModify
48*b1cdbd2cSJim Jagielski     object is connected to a list of SwClient objects. If an object derived from SwClient
49*b1cdbd2cSJim Jagielski     wants to get notifications from more than one SwModify object, it must create additional
50*b1cdbd2cSJim Jagielski     SwClient objects. The SwDepend class allows to handle their notifications in the same
51*b1cdbd2cSJim Jagielski     notification callback as it forwards the Modify() calls it receives to a "master"
52*b1cdbd2cSJim Jagielski     SwClient implementation.
53*b1cdbd2cSJim Jagielski     The SwClientIter class allows to iterate over the SwClient objects registered at an
54*b1cdbd2cSJim Jagielski     SwModify. For historical reasons its ability to use TypeInfo to restrict this iteration
55*b1cdbd2cSJim Jagielski     to objects of a particular type created a lot of code that misuses SwClient-SwModify
56*b1cdbd2cSJim Jagielski     relationships that basically should be used only for Modify() callbacks.
57*b1cdbd2cSJim Jagielski     This is still subject to refactoring.
58*b1cdbd2cSJim Jagielski     Until this gets resolved, new SwClientIter base code should be reduced to the absolute
59*b1cdbd2cSJim Jagielski     minimum and it also should be wrapped by SwIterator templates that prevent that the
60*b1cdbd2cSJim Jagielski     code gets polluted by pointer casts (see switerator.hxx).
61*b1cdbd2cSJim Jagielski  */
62*b1cdbd2cSJim Jagielski 
63*b1cdbd2cSJim Jagielski // ----------
64*b1cdbd2cSJim Jagielski // SwClient
65*b1cdbd2cSJim Jagielski // ----------
66*b1cdbd2cSJim Jagielski 
67*b1cdbd2cSJim Jagielski class SW_DLLPUBLIC SwClient : ::boost::noncopyable
68*b1cdbd2cSJim Jagielski {
69*b1cdbd2cSJim Jagielski     // avoids making the details of the linked list and the callback method public
70*b1cdbd2cSJim Jagielski 	friend class SwModify;
71*b1cdbd2cSJim Jagielski 	friend class SwClientIter;
72*b1cdbd2cSJim Jagielski 
73*b1cdbd2cSJim Jagielski 	SwClient *pLeft, *pRight;       // double-linked list of other clients
74*b1cdbd2cSJim Jagielski 	SwModify *pRegisteredIn;        // event source
75*b1cdbd2cSJim Jagielski 
76*b1cdbd2cSJim Jagielski     // in general clients should not be removed when their SwModify sends out Modify()
77*b1cdbd2cSJim Jagielski     // notifications; in some rare cases this is necessary, but only the concrete SwClient
78*b1cdbd2cSJim Jagielski     // sub class will know that; this flag allows to make that known
79*b1cdbd2cSJim Jagielski     bool mbIsAllowedToBeRemovedInModifyCall;
80*b1cdbd2cSJim Jagielski 
81*b1cdbd2cSJim Jagielski     // callbacks received from SwModify (friend class - so these methods can be private)
82*b1cdbd2cSJim Jagielski     // should be called only from SwModify the client is registered in
83*b1cdbd2cSJim Jagielski     // mba: IMHO these methods should be pure virtual
84*b1cdbd2cSJim Jagielski     virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
85*b1cdbd2cSJim Jagielski     virtual void SwClientNotify( const SwModify& rModify, const SfxHint& rHint );
86*b1cdbd2cSJim Jagielski 
87*b1cdbd2cSJim Jagielski protected:
88*b1cdbd2cSJim Jagielski 	// single argument ctors shall be explicit.
89*b1cdbd2cSJim Jagielski 	explicit SwClient(SwModify *pToRegisterIn);
90*b1cdbd2cSJim Jagielski 
91*b1cdbd2cSJim Jagielski     // write access to pRegisteredIn shall be granted only to the object itself (protected access)
GetRegisteredInNonConst() const92*b1cdbd2cSJim Jagielski     SwModify* GetRegisteredInNonConst() const { return pRegisteredIn; }
SetIsAllowedToBeRemovedInModifyCall(bool bSet)93*b1cdbd2cSJim Jagielski     void SetIsAllowedToBeRemovedInModifyCall( bool bSet ) { mbIsAllowedToBeRemovedInModifyCall = bSet; }
94*b1cdbd2cSJim Jagielski 
95*b1cdbd2cSJim Jagielski public:
96*b1cdbd2cSJim Jagielski 
97*b1cdbd2cSJim Jagielski 	inline SwClient();
98*b1cdbd2cSJim Jagielski 	virtual ~SwClient();
99*b1cdbd2cSJim Jagielski 
100*b1cdbd2cSJim Jagielski     // in case an SwModify object is destroyed that itself is registered in another SwModify,
101*b1cdbd2cSJim Jagielski     // its SwClient objects can decide to get registered to the latter instead by calling this method
102*b1cdbd2cSJim Jagielski 	void CheckRegistration( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue );
103*b1cdbd2cSJim Jagielski 
104*b1cdbd2cSJim Jagielski     // controlled access to Modify method
105*b1cdbd2cSJim Jagielski     // mba: this is still considered a hack and it should be fixed; the name makes grep-ing easier
ModifyNotification(const SfxPoolItem * pOldValue,const SfxPoolItem * pNewValue)106*b1cdbd2cSJim Jagielski 	void ModifyNotification( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue ) { Modify ( pOldValue, pNewValue ); }
SwClientNotifyCall(const SwModify & rModify,const SfxHint & rHint)107*b1cdbd2cSJim Jagielski    void SwClientNotifyCall( const SwModify& rModify, const SfxHint& rHint ) { SwClientNotify( rModify, rHint ); }
108*b1cdbd2cSJim Jagielski 
GetRegisteredIn() const109*b1cdbd2cSJim Jagielski 	const SwModify* GetRegisteredIn() const { return pRegisteredIn; }
IsLast() const110*b1cdbd2cSJim Jagielski     bool IsLast() const { return !pLeft && !pRight; }
111*b1cdbd2cSJim Jagielski 
112*b1cdbd2cSJim Jagielski     // needed for class SwClientIter
113*b1cdbd2cSJim Jagielski 	TYPEINFO();
114*b1cdbd2cSJim Jagielski 
115*b1cdbd2cSJim Jagielski 	// get information about attribute
116*b1cdbd2cSJim Jagielski 	virtual sal_Bool GetInfo( SfxPoolItem& ) const;
117*b1cdbd2cSJim Jagielski };
118*b1cdbd2cSJim Jagielski 
SwClient()119*b1cdbd2cSJim Jagielski inline SwClient::SwClient() :
120*b1cdbd2cSJim Jagielski 	pLeft(0), pRight(0), pRegisteredIn(0), mbIsAllowedToBeRemovedInModifyCall(false)
121*b1cdbd2cSJim Jagielski {}
122*b1cdbd2cSJim Jagielski 
123*b1cdbd2cSJim Jagielski // ----------
124*b1cdbd2cSJim Jagielski // SwModify
125*b1cdbd2cSJim Jagielski // ----------
126*b1cdbd2cSJim Jagielski 
127*b1cdbd2cSJim Jagielski class SW_DLLPUBLIC SwModify: public SwClient
128*b1cdbd2cSJim Jagielski {
129*b1cdbd2cSJim Jagielski //	friend class SwClientIter;
130*b1cdbd2cSJim Jagielski 
131*b1cdbd2cSJim Jagielski 	SwClient* pRoot;                // the start of the linked list of clients
132*b1cdbd2cSJim Jagielski 	sal_Bool bModifyLocked : 1;         // don't broadcast changes now
133*b1cdbd2cSJim Jagielski 	sal_Bool bLockClientList : 1;       // may be set when this instance notifies its clients
134*b1cdbd2cSJim Jagielski 	sal_Bool bInDocDTOR	: 1;            // workaround for problems when a lot of objects are destroyed
135*b1cdbd2cSJim Jagielski 	sal_Bool bInCache	: 1;
136*b1cdbd2cSJim Jagielski 	sal_Bool bInSwFntCache : 1;
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski     // mba: IMHO this method should be pure virtual
139*b1cdbd2cSJim Jagielski     virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
140*b1cdbd2cSJim Jagielski 
141*b1cdbd2cSJim Jagielski public:
142*b1cdbd2cSJim Jagielski 	SwModify();
143*b1cdbd2cSJim Jagielski 
144*b1cdbd2cSJim Jagielski     // broadcasting: send notifications to all clients
145*b1cdbd2cSJim Jagielski 	void NotifyClients( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue );
146*b1cdbd2cSJim Jagielski 
147*b1cdbd2cSJim Jagielski     // the same, but without setting bModifyLocked or checking for any of the flags
148*b1cdbd2cSJim Jagielski     // mba: it would be interesting to know why this is necessary
149*b1cdbd2cSJim Jagielski     // also allows to limit callback to certain type (HACK)
150*b1cdbd2cSJim Jagielski 	void ModifyBroadcast( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue, TypeId nType = TYPE(SwClient) );
151*b1cdbd2cSJim Jagielski 
152*b1cdbd2cSJim Jagielski     // a more universal broadcasting mechanism
153*b1cdbd2cSJim Jagielski 	void CallSwClientNotify( const SfxHint& rHint ) const;
154*b1cdbd2cSJim Jagielski 
155*b1cdbd2cSJim Jagielski 	// single argument ctors shall be explicit.
156*b1cdbd2cSJim Jagielski 	explicit SwModify( SwModify *pToRegisterIn );
157*b1cdbd2cSJim Jagielski 	virtual ~SwModify();
158*b1cdbd2cSJim Jagielski 
159*b1cdbd2cSJim Jagielski 	void Add(SwClient *pDepend);
160*b1cdbd2cSJim Jagielski 	SwClient* Remove(SwClient *pDepend);
GetDepends() const161*b1cdbd2cSJim Jagielski 	const SwClient* GetDepends() const	{ return pRoot; }
162*b1cdbd2cSJim Jagielski 
163*b1cdbd2cSJim Jagielski 	// get information about attribute
164*b1cdbd2cSJim Jagielski 	virtual sal_Bool GetInfo( SfxPoolItem& ) const;
165*b1cdbd2cSJim Jagielski 
LockModify()166*b1cdbd2cSJim Jagielski 	void LockModify()                   { bModifyLocked = sal_True;  }
UnlockModify()167*b1cdbd2cSJim Jagielski 	void UnlockModify()  				{ bModifyLocked = sal_False; }
SetInCache(sal_Bool bNew)168*b1cdbd2cSJim Jagielski 	void SetInCache( sal_Bool bNew )		{ bInCache = bNew;		 }
SetInSwFntCache(sal_Bool bNew)169*b1cdbd2cSJim Jagielski 	void SetInSwFntCache( sal_Bool bNew ) 	{ bInSwFntCache = bNew;	 }
SetInDocDTOR()170*b1cdbd2cSJim Jagielski 	void SetInDocDTOR()                 { bInDocDTOR = sal_True; }
IsModifyLocked() const171*b1cdbd2cSJim Jagielski 	sal_Bool IsModifyLocked() const		{ return bModifyLocked;  }
IsInDocDTOR() const172*b1cdbd2cSJim Jagielski 	sal_Bool IsInDocDTOR()	  const 	{ return bInDocDTOR;	 }
IsInCache() const173*b1cdbd2cSJim Jagielski 	sal_Bool IsInCache()	  const 	{ return bInCache;		 }
IsInSwFntCache() const174*b1cdbd2cSJim Jagielski 	sal_Bool IsInSwFntCache() const     { return bInSwFntCache;	 }
175*b1cdbd2cSJim Jagielski 
176*b1cdbd2cSJim Jagielski 	void CheckCaching( const sal_uInt16 nWhich );
IsLastDepend()177*b1cdbd2cSJim Jagielski     bool IsLastDepend() { return pRoot && pRoot->IsLast(); }
178*b1cdbd2cSJim Jagielski     int GetClientCount() const;
179*b1cdbd2cSJim Jagielski };
180*b1cdbd2cSJim Jagielski 
181*b1cdbd2cSJim Jagielski // ----------
182*b1cdbd2cSJim Jagielski // SwDepend
183*b1cdbd2cSJim Jagielski // ----------
184*b1cdbd2cSJim Jagielski 
185*b1cdbd2cSJim Jagielski /*
186*b1cdbd2cSJim Jagielski  * Helper class for objects that need to depend on more than one SwClient
187*b1cdbd2cSJim Jagielski  */
188*b1cdbd2cSJim Jagielski class SW_DLLPUBLIC SwDepend: public SwClient
189*b1cdbd2cSJim Jagielski {
190*b1cdbd2cSJim Jagielski 	SwClient *pToTell;
191*b1cdbd2cSJim Jagielski 
192*b1cdbd2cSJim Jagielski public:
SwDepend()193*b1cdbd2cSJim Jagielski 	SwDepend() : pToTell(0) {}
194*b1cdbd2cSJim Jagielski 	SwDepend(SwClient *pTellHim, SwModify *pDepend);
195*b1cdbd2cSJim Jagielski 
GetToTell()196*b1cdbd2cSJim Jagielski 	SwClient* GetToTell() { return pToTell; }
197*b1cdbd2cSJim Jagielski 
198*b1cdbd2cSJim Jagielski 	virtual sal_Bool GetInfo( SfxPoolItem & ) const;
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski protected:
201*b1cdbd2cSJim Jagielski     virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNewValue );
202*b1cdbd2cSJim Jagielski     virtual void SwClientNotify( const SwModify& rModify, const SfxHint& rHint );
203*b1cdbd2cSJim Jagielski };
204*b1cdbd2cSJim Jagielski 
205*b1cdbd2cSJim Jagielski 
206*b1cdbd2cSJim Jagielski class SwClientIter
207*b1cdbd2cSJim Jagielski {
208*b1cdbd2cSJim Jagielski 	friend SwClient* SwModify::Remove(SwClient *); // for pointer adjustments
209*b1cdbd2cSJim Jagielski 	friend void SwModify::Add(SwClient *pDepend);   // for pointer adjustments
210*b1cdbd2cSJim Jagielski 
211*b1cdbd2cSJim Jagielski     const SwModify& rRoot;
212*b1cdbd2cSJim Jagielski 
213*b1cdbd2cSJim Jagielski     // the current object in an iteration
214*b1cdbd2cSJim Jagielski 	SwClient* pAct;
215*b1cdbd2cSJim Jagielski 
216*b1cdbd2cSJim Jagielski     // in case the current object is already removed, the next object in the list
217*b1cdbd2cSJim Jagielski     // is marked down to become the current object in the next step
218*b1cdbd2cSJim Jagielski     // this is necessary because iteration requires access to members of the current object
219*b1cdbd2cSJim Jagielski     SwClient* pDelNext;
220*b1cdbd2cSJim Jagielski 
221*b1cdbd2cSJim Jagielski     // SwClientIter objects are tracked in linked list so that they can react
222*b1cdbd2cSJim Jagielski     // when the current (pAct) or marked down (pDelNext) SwClient is removed
223*b1cdbd2cSJim Jagielski     // from its SwModify
224*b1cdbd2cSJim Jagielski 	SwClientIter *pNxtIter;
225*b1cdbd2cSJim Jagielski 
226*b1cdbd2cSJim Jagielski     // iterator can be limited to return only SwClient objects of a certain type
227*b1cdbd2cSJim Jagielski 	TypeId aSrchId;
228*b1cdbd2cSJim Jagielski 
229*b1cdbd2cSJim Jagielski public:
230*b1cdbd2cSJim Jagielski     SW_DLLPUBLIC SwClientIter( const SwModify& );
231*b1cdbd2cSJim Jagielski 	SW_DLLPUBLIC ~SwClientIter();
232*b1cdbd2cSJim Jagielski 
GetModify() const233*b1cdbd2cSJim Jagielski 	const SwModify& GetModify() const { return rRoot; }
234*b1cdbd2cSJim Jagielski 
235*b1cdbd2cSJim Jagielski 	SwClient* operator++();
236*b1cdbd2cSJim Jagielski 	SwClient* GoStart();
237*b1cdbd2cSJim Jagielski 	SwClient* GoEnd();
238*b1cdbd2cSJim Jagielski 
239*b1cdbd2cSJim Jagielski     // returns the current SwClient object;
240*b1cdbd2cSJim Jagielski     // in case this was already removed, the object marked down to become
241*b1cdbd2cSJim Jagielski     // the next current one is returned
operator ()() const242*b1cdbd2cSJim Jagielski 	SwClient* operator()() const
243*b1cdbd2cSJim Jagielski 		{ return pDelNext == pAct ? pAct : pDelNext; }
244*b1cdbd2cSJim Jagielski 
245*b1cdbd2cSJim Jagielski     // return "true" if an object was removed from a client chain in iteration
246*b1cdbd2cSJim Jagielski     // adding objects to a client chain in iteration is forbidden
247*b1cdbd2cSJim Jagielski     // SwModify::Add() asserts this
IsChanged() const248*b1cdbd2cSJim Jagielski 	bool IsChanged() const { return pDelNext != pAct; }
249*b1cdbd2cSJim Jagielski 
250*b1cdbd2cSJim Jagielski 	SW_DLLPUBLIC SwClient* First( TypeId nType );
251*b1cdbd2cSJim Jagielski 	SW_DLLPUBLIC SwClient* Next();
252*b1cdbd2cSJim Jagielski 	SW_DLLPUBLIC SwClient* Last( TypeId nType );
253*b1cdbd2cSJim Jagielski 	SW_DLLPUBLIC SwClient* Previous();
254*b1cdbd2cSJim Jagielski };
255*b1cdbd2cSJim Jagielski 
256*b1cdbd2cSJim Jagielski #endif
257