LibreOffice Module sd (master) 1
MasterPageObserver.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21
22#include <algorithm>
23#include <iterator>
24#include <drawdoc.hxx>
25#include <sdpage.hxx>
26#include <set>
27#include <unordered_map>
28#include <memory>
29#include <vector>
30#include <svl/lstner.hxx>
31#include <osl/doublecheckedlocking.h>
32#include <osl/getglobalmutex.hxx>
33#include <tools/debug.hxx>
34
35namespace sd {
36
38 : public SfxListener
39{
40public:
44 void RegisterDocument (SdDrawDocument& rDocument);
45
49 void UnregisterDocument (SdDrawDocument& rDocument);
50
57 void AddEventListener (const Link<MasterPageObserverEvent&,void>& rEventListener);
58
66
67private:
68 ::std::vector<Link<MasterPageObserverEvent&,void>> maListeners;
69
70 struct DrawDocHash {
71 size_t operator()(SdDrawDocument* argument) const
72 { return reinterpret_cast<sal_uIntPtr>(argument); }
73 };
74 typedef std::unordered_map<SdDrawDocument*,
76 DrawDocHash>
79
80 virtual void Notify(
81 SfxBroadcaster& rBroadcaster,
82 const SfxHint& rHint) override;
83
84 void AnalyzeUsedMasterPages (SdDrawDocument& rDocument);
85
87};
88
89//===== MasterPageObserver ====================================================
90
92{
93 static MasterPageObserver* gInstance = []()
94 {
95 MasterPageObserver* pInstance = new MasterPageObserver ();
97 ::std::unique_ptr<SdGlobalResource>(pInstance));
98 return pInstance;
99 }();
100 return *gInstance;
101}
102
104{
105 mpImpl->RegisterDocument (rDocument);
106}
107
109{
110 mpImpl->UnregisterDocument (rDocument);
111}
112
114{
115
116 mpImpl->AddEventListener (rEventListener);
117}
118
120{
121 mpImpl->RemoveEventListener (rEventListener);
122}
123
125 : mpImpl (new Implementation)
126{}
127
129{}
130
131//===== MasterPageObserver::Implementation ====================================
132
134 SdDrawDocument& rDocument)
135{
136 // Gather the names of all the master pages in the given document.
137 MasterPageContainer::mapped_type aMasterPageSet;
138 sal_uInt16 nMasterPageCount = rDocument.GetMasterSdPageCount(PageKind::Standard);
139 for (sal_uInt16 nIndex=0; nIndex<nMasterPageCount; nIndex++)
140 {
141 SdPage* pMasterPage = rDocument.GetMasterSdPage (nIndex, PageKind::Standard);
142 if (pMasterPage != nullptr)
143 aMasterPageSet.insert (pMasterPage->GetName());
144 }
145
146 bool bAlreadyExists = maUsedMasterPages.find(&rDocument) != maUsedMasterPages.end();
147 maUsedMasterPages[&rDocument] = aMasterPageSet;
148
149 if (!bAlreadyExists)
150 StartListening (rDocument);
151}
152
154 SdDrawDocument& rDocument)
155{
156 EndListening (rDocument);
157
158 MasterPageContainer::iterator aMasterPageDescriptor(maUsedMasterPages.find(&rDocument));
159 if(aMasterPageDescriptor != maUsedMasterPages.end())
160 maUsedMasterPages.erase(aMasterPageDescriptor);
161}
162
164 const Link<MasterPageObserverEvent&,void>& rEventListener)
165{
166 if (::std::find (
167 maListeners.begin(),
168 maListeners.end(),
169 rEventListener) != maListeners.end())
170 return;
171
172 maListeners.push_back (rEventListener);
173
174 // Tell the new listener about all the master pages that are
175 // currently in use.
176 for (const auto& rDocument : maUsedMasterPages)
177 {
178 ::std::set<OUString>::reverse_iterator aNameIterator;
179 for (aNameIterator=rDocument.second.rbegin();
180 aNameIterator!=rDocument.second.rend();
181 ++aNameIterator)
182 {
185 *aNameIterator);
186 SendEvent (aEvent);
187 }
188 }
189}
190
192 const Link<MasterPageObserverEvent&,void>& rEventListener)
193{
194 maListeners.erase (
195 ::std::find (
196 maListeners.begin(),
197 maListeners.end(),
198 rEventListener));
199}
200
202 SfxBroadcaster& rBroadcaster,
203 const SfxHint& rHint)
204{
205 if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
206 return;
207 const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
208
209 switch (pSdrHint->GetKind())
210 {
211 case SdrHintKind::PageOrderChange:
212 // Process the modified set of pages only when the number of
213 // standard and notes master pages are equal. This test
214 // filters out events that are sent in between the insertion
215 // of a new standard master page and a new notes master
216 // page.
217 if (auto pDrawDocument = dynamic_cast<SdDrawDocument *>( &rBroadcaster ))
218 {
219 if (pDrawDocument->GetMasterSdPageCount(PageKind::Standard)
220 == pDrawDocument->GetMasterSdPageCount(PageKind::Notes))
221 {
222 AnalyzeUsedMasterPages (*pDrawDocument);
223 }
224 }
225 break;
226
227 default:
228 break;
229 }
230}
231
233 SdDrawDocument& rDocument)
234{
235 // Create a set of names of the master pages used by the given document.
236 sal_uInt16 nMasterPageCount = rDocument.GetMasterSdPageCount(PageKind::Standard);
237 ::std::set<OUString> aCurrentMasterPages;
238 for (sal_uInt16 nIndex=0; nIndex<nMasterPageCount; nIndex++)
239 {
240 SdPage* pMasterPage = rDocument.GetMasterSdPage (nIndex, PageKind::Standard);
241 if (pMasterPage != nullptr)
242 aCurrentMasterPages.insert (pMasterPage->GetName());
243 }
244
245 std::vector<OUString> aNewMasterPages;
246 std::vector<OUString> aRemovedMasterPages;
247 MasterPageContainer::iterator aOldMasterPagesDescriptor (
248 maUsedMasterPages.find(&rDocument));
249 if (aOldMasterPagesDescriptor == maUsedMasterPages.end())
250 return;
251
252 // Send events about the newly used master pages.
253 ::std::set_difference (
254 aCurrentMasterPages.begin(),
255 aCurrentMasterPages.end(),
256 aOldMasterPagesDescriptor->second.begin(),
257 aOldMasterPagesDescriptor->second.end(),
258 std::back_inserter(aNewMasterPages));
259 for (const auto& aNewMasterPage : aNewMasterPages)
260 {
263 aNewMasterPage);
264 SendEvent (aEvent);
265 }
266
267 // Send events about master pages that are not used any longer.
268 ::std::set_difference (
269 aOldMasterPagesDescriptor->second.begin(),
270 aOldMasterPagesDescriptor->second.end(),
271 aCurrentMasterPages.begin(),
272 aCurrentMasterPages.end(),
273 std::back_inserter(aRemovedMasterPages));
274 for (const auto& aRemovedMasterPage : aRemovedMasterPages)
275 {
278 aRemovedMasterPage);
279 SendEvent (aEvent);
280 }
281
282 // Store the new list of master pages.
283 aOldMasterPagesDescriptor->second = aCurrentMasterPages;
284}
285
288{
289 for (const auto& aLink : maListeners)
290 {
291 aLink.Call(rEvent);
292 }
293}
294
295} // end of namespace sd
296
297/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::boost::spirit::classic::rule< ScannerT > argument
AnyEventRef aEvent
sal_uInt16 GetMasterSdPageCount(PageKind ePgKind) const
Definition: drawdoc2.cxx:222
SdPage * GetMasterSdPage(sal_uInt16 nPgNum, PageKind ePgKind)
Definition: drawdoc2.cxx:217
const OUString & GetName() const
Definition: sdpage.cxx:2505
SdrHintKind GetKind() const
SfxHintId GetId() const
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
Objects of this class are sent to listeners of the MasterPageObserver singleton when the list of mast...
@ ET_MASTER_PAGE_EXISTS
Master page already exists when document is registered.
@ ET_MASTER_PAGE_ADDED
Master page has been added to a document.
@ ET_MASTER_PAGE_REMOVED
Master page has been removed from to a document.
void SendEvent(MasterPageObserverEvent &rEvent)
std::unordered_map< SdDrawDocument *, MasterPageObserver::MasterPageNameSet, DrawDocHash > MasterPageContainer
virtual void Notify(SfxBroadcaster &rBroadcaster, const SfxHint &rHint) override
void RemoveEventListener(const Link< MasterPageObserverEvent &, void > &rEventListener)
Remove the given listener from the list of listeners.
void UnregisterDocument(SdDrawDocument &rDocument)
The master page observer will stop to listen to events of this document.
void AnalyzeUsedMasterPages(SdDrawDocument &rDocument)
void AddEventListener(const Link< MasterPageObserverEvent &, void > &rEventListener)
Add a listener that is informed of master pages that are newly assigned to slides or become unassigne...
::std::vector< Link< MasterPageObserverEvent &, void > > maListeners
void RegisterDocument(SdDrawDocument &rDocument)
The master page observer will listen to events of this document and detect changes of the use of mast...
This singleton observes all registered documents for changes in the used master pages and in turn inf...
::std::unique_ptr< Implementation > mpImpl
void UnregisterDocument(SdDrawDocument &rDocument)
The master page observer will stop to listen to events of this document.
::std::set< OUString > MasterPageNameSet
void AddEventListener(const Link< MasterPageObserverEvent &, void > &rEventListener)
Add a listener that is informed of master pages that are newly assigned to slides or become unassigne...
static MasterPageObserver & Instance()
Return the single instance of this class.
virtual ~MasterPageObserver() override
void RemoveEventListener(const Link< MasterPageObserverEvent &, void > &rEventListener)
Remove the given listener from the list of listeners.
void RegisterDocument(SdDrawDocument &rDocument)
The master page observer will listen to events of this document and detect changes of the use of mast...
void AddResource(::std::unique_ptr< SdGlobalResource > pResource)
Add a resource to the container.
static SdGlobalResourceContainer & Instance()
sal_Int32 nIndex
size_t operator()(SdDrawDocument *argument) const