bump product version to 4.1.6.2
[LibreOffice.git] / sw / inc / calbck.hxx
blob105ba9dd4aecbc6f66700b7297e2de982b1e300f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef _CALBCK_HXX
21 #define _CALBCK_HXX
23 #include <tools/rtti.hxx>
24 #include "swdllapi.h"
25 #include <boost/noncopyable.hpp>
27 class SwModify;
28 class SwClientIter;
29 class SfxPoolItem;
30 class SfxHint;
33 SwModify and SwClient cooperate in propagating attribute changes.
34 If an attribute changes, the change is notified to all dependent
35 formats and other interested objects, e.g. Nodes. The clients will detect
36 if the change affects them. It could be that the changed attribute is
37 overruled in the receiving object so that its change does not become
38 effective or that the receiver is not interested in the particular attribute
39 in general (though probably in other attributes of the SwModify object they
40 are registered in).
41 As SwModify objects are derived from SwClient, they can create a chain of SwClient
42 objects where changes can get propagated through.
43 Each SwClient can be registered at only one SwModify object, while each SwModify
44 object is connected to a list of SwClient objects. If an object derived from SwClient
45 wants to get notifications from more than one SwModify object, it must create additional
46 SwClient objects. The SwDepend class allows to handle their notifications in the same
47 notification callback as it forwards the Modify() calls it receives to a "master"
48 SwClient implementation.
49 The SwClientIter class allows to iterate over the SwClient objects registered at an
50 SwModify. For historical reasons its ability to use TypeInfo to restrict this iteration
51 to objects of a particular type created a lot of code that misuses SwClient-SwModify
52 relationships that basically should be used only for Modify() callbacks.
53 This is still subject to refactoring.
54 Until this gets resolved, new SwClientIter base code should be reduced to the absolute
55 minimum and it also should be wrapped by SwIterator templates that prevent that the
56 code gets polluted by pointer casts (see switerator.hxx).
59 // ----------
60 // SwClient
61 // ----------
63 class SW_DLLPUBLIC SwClient : ::boost::noncopyable
65 // avoids making the details of the linked list and the callback method public
66 friend class SwModify;
67 friend class SwClientIter;
69 SwClient *pLeft, *pRight; ///< double-linked list of other clients
70 SwModify *pRegisteredIn; ///< event source
72 // in general clients should not be removed when their SwModify sends out Modify()
73 // notifications; in some rare cases this is necessary, but only the concrete SwClient
74 // sub class will know that; this flag allows to make that known
75 bool mbIsAllowedToBeRemovedInModifyCall;
77 // callbacks received from SwModify (friend class - so these methods can be private)
78 // should be called only from SwModify the client is registered in
79 // mba: IMHO these methods should be pure virtual
80 virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
81 virtual void SwClientNotify( const SwModify& rModify, const SfxHint& rHint );
83 protected:
84 // single argument ctors shall be explicit.
85 explicit SwClient(SwModify *pToRegisterIn);
87 // write access to pRegisteredIn shall be granted only to the object itself (protected access)
88 SwModify* GetRegisteredInNonConst() const { return pRegisteredIn; }
89 void SetIsAllowedToBeRemovedInModifyCall( bool bSet ) { mbIsAllowedToBeRemovedInModifyCall = bSet; }
91 public:
93 inline SwClient();
94 virtual ~SwClient();
96 // in case an SwModify object is destroyed that itself is registered in another SwModify,
97 // its SwClient objects can decide to get registered to the latter instead by calling this method
98 void CheckRegistration( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue );
100 // controlled access to Modify method
101 // mba: this is still considered a hack and it should be fixed; the name makes grep-ing easier
102 void ModifyNotification( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue ) { Modify ( pOldValue, pNewValue ); }
103 void SwClientNotifyCall( const SwModify& rModify, const SfxHint& rHint ) { SwClientNotify( rModify, rHint ); }
105 const SwModify* GetRegisteredIn() const { return pRegisteredIn; }
106 bool IsLast() const { return !pLeft && !pRight; }
108 // needed for class SwClientIter
109 TYPEINFO();
111 // get information about attribute
112 virtual bool GetInfo( SfxPoolItem& ) const;
115 inline SwClient::SwClient() :
116 pLeft(0), pRight(0), pRegisteredIn(0), mbIsAllowedToBeRemovedInModifyCall(false)
119 // ----------
120 // SwModify
121 // ----------
123 // class has a doubly linked list for dependencies
124 class SW_DLLPUBLIC SwModify: public SwClient
126 SwClient* pRoot; // the start of the linked list of clients
127 bool bModifyLocked : 1; // don't broadcast changes now
128 sal_Bool bLockClientList : 1; // may be set when this instance notifies its clients
129 sal_Bool bInDocDTOR : 1; // workaround for problems when a lot of objects are destroyed
130 sal_Bool bInCache : 1;
131 sal_Bool bInSwFntCache : 1;
133 // mba: IMHO this method should be pure virtual
134 virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
136 public:
137 SwModify();
139 // broadcasting: send notifications to all clients
140 void NotifyClients( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue );
142 // the same, but without setting bModifyLocked or checking for any of the flags
143 // mba: it would be interesting to know why this is necessary
144 // also allows to limit callback to certain type (HACK)
145 void ModifyBroadcast( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue, TypeId nType = TYPE(SwClient) );
147 // a more universal broadcasting mechanism
148 void CallSwClientNotify( const SfxHint& rHint ) const;
150 // single argument ctors shall be explicit.
151 explicit SwModify( SwModify *pToRegisterIn );
152 virtual ~SwModify();
154 void Add(SwClient *pDepend);
155 SwClient* Remove(SwClient *pDepend);
156 const SwClient* GetDepends() const { return pRoot; }
158 // get information about attribute
159 virtual bool GetInfo( SfxPoolItem& ) const;
161 void LockModify() { bModifyLocked = true; }
162 void UnlockModify() { bModifyLocked = false; }
163 void SetInCache( sal_Bool bNew ) { bInCache = bNew; }
164 void SetInSwFntCache( sal_Bool bNew ) { bInSwFntCache = bNew; }
165 void SetInDocDTOR() { bInDocDTOR = sal_True; }
166 bool IsModifyLocked() const { return bModifyLocked; }
167 sal_Bool IsInDocDTOR() const { return bInDocDTOR; }
168 sal_Bool IsInCache() const { return bInCache; }
169 sal_Bool IsInSwFntCache() const { return bInSwFntCache; }
171 void CheckCaching( const sal_uInt16 nWhich );
172 bool IsLastDepend() { return pRoot && pRoot->IsLast(); }
175 // ----------
176 // SwDepend
177 // ----------
180 * Helper class for objects that need to depend on more than one SwClient
182 class SW_DLLPUBLIC SwDepend: public SwClient
184 SwClient *pToTell;
186 public:
187 SwDepend() : pToTell(0) {}
188 SwDepend(SwClient *pTellHim, SwModify *pDepend);
190 SwClient* GetToTell() { return pToTell; }
192 /** get Client information */
193 virtual bool GetInfo( SfxPoolItem & ) const;
194 protected:
195 virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNewValue );
196 virtual void SwClientNotify( const SwModify& rModify, const SfxHint& rHint );
200 class SwClientIter
202 friend SwClient* SwModify::Remove(SwClient *); ///< for pointer adjustments
203 friend void SwModify::Add(SwClient *pDepend); ///< for pointer adjustments
205 const SwModify& rRoot;
207 // the current object in an iteration
208 SwClient* pAct;
210 // in case the current object is already removed, the next object in the list
211 // is marked down to become the current object in the next step
212 // this is necessary because iteration requires access to members of the current object
213 SwClient* pDelNext;
215 // SwClientIter objects are tracked in linked list so that they can react
216 // when the current (pAct) or marked down (pDelNext) SwClient is removed
217 // from its SwModify
218 SwClientIter *pNxtIter;
220 // iterator can be limited to return only SwClient objects of a certain type
221 TypeId aSrchId;
223 public:
224 SW_DLLPUBLIC SwClientIter( const SwModify& );
225 SW_DLLPUBLIC ~SwClientIter();
227 const SwModify& GetModify() const { return rRoot; }
229 SwClient* operator++();
230 SwClient* GoStart();
231 SwClient* GoEnd();
233 // returns the current SwClient object;
234 // in case this was already removed, the object marked down to become
235 // the next current one is returned
236 SwClient* operator()() const
237 { return pDelNext == pAct ? pAct : pDelNext; }
239 // return "true" if an object was removed from a client chain in iteration
240 // adding objects to a client chain in iteration is forbidden
241 // SwModify::Add() asserts this
242 bool IsChanged() const { return pDelNext != pAct; }
244 SW_DLLPUBLIC SwClient* First( TypeId nType );
245 SW_DLLPUBLIC SwClient* Next();
246 SW_DLLPUBLIC SwClient* Last( TypeId nType );
247 SW_DLLPUBLIC SwClient* Previous();
250 #endif
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */