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