Update ooo320-m1
[ooovba.git] / sd / source / ui / toolpanel / controls / RecentlyUsedMasterPages.cxx
blobb219428a823afed2059711ec30711621ab3d6f50
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: RecentlyUsedMasterPages.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include "RecentlyUsedMasterPages.hxx"
35 #include "MasterPageObserver.hxx"
36 #include "MasterPagesSelector.hxx"
37 #include "MasterPageDescriptor.hxx"
38 #include "tools/ConfigurationAccess.hxx"
39 #include "drawdoc.hxx"
40 #include "sdpage.hxx"
42 #include <algorithm>
43 #include <vector>
45 #include <comphelper/processfactory.hxx>
46 #include "unomodel.hxx"
47 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
48 #include <com/sun/star/drawing/XDrawPages.hpp>
49 #include <com/sun/star/frame/XComponentLoader.hpp>
50 #include <com/sun/star/container/XNameAccess.hpp>
51 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
52 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
53 #include <com/sun/star/beans/PropertyValue.hpp>
54 #include <com/sun/star/beans/PropertyState.hpp>
55 #include <tools/urlobj.hxx>
56 #include <unotools/confignode.hxx>
57 #include <osl/doublecheckedlocking.h>
58 #include <osl/getglobalmutex.hxx>
60 using namespace ::std;
61 using ::rtl::OUString;
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::uno;
66 namespace {
68 static const OUString& GetPathToImpressConfigurationRoot (void)
70 static const OUString sPathToImpressConfigurationRoot (
71 RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/"));
72 return sPathToImpressConfigurationRoot;
74 static const OUString& GetPathToSetNode (void)
76 static const OUString sPathToSetNode(
77 RTL_CONSTASCII_USTRINGPARAM(
78 "MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages"));
79 return sPathToSetNode;
83 class Descriptor
85 public:
86 ::rtl::OUString msURL;
87 ::rtl::OUString msName;
88 ::sd::toolpanel::controls::MasterPageContainer::Token maToken;
89 Descriptor (const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName)
90 : msURL(rsURL),
91 msName(rsName),
92 maToken(::sd::toolpanel::controls::MasterPageContainer::NIL_TOKEN)
94 Descriptor (::sd::toolpanel::controls::MasterPageContainer::Token aToken,
95 const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName)
96 : msURL(rsURL),
97 msName(rsName),
98 maToken(aToken)
100 class TokenComparator
101 { public:
102 TokenComparator(::sd::toolpanel::controls::MasterPageContainer::Token aToken)
103 : maToken(aToken) {}
104 bool operator () (const Descriptor& rDescriptor)
105 { return maToken==rDescriptor.maToken; }
106 private: ::sd::toolpanel::controls::MasterPageContainer::Token maToken;
110 } // end of anonymous namespace
115 namespace sd { namespace toolpanel { namespace controls {
117 class RecentlyUsedMasterPages::MasterPageList : public ::std::vector<Descriptor>
119 public:
120 MasterPageList (void) {}
124 RecentlyUsedMasterPages* RecentlyUsedMasterPages::mpInstance = NULL;
127 RecentlyUsedMasterPages& RecentlyUsedMasterPages::Instance (void)
129 if (mpInstance == NULL)
131 ::osl::GetGlobalMutex aMutexFunctor;
132 ::osl::MutexGuard aGuard (aMutexFunctor());
133 if (mpInstance == NULL)
135 RecentlyUsedMasterPages* pInstance = new RecentlyUsedMasterPages();
136 pInstance->LateInit();
137 SdGlobalResourceContainer::Instance().AddResource (
138 ::std::auto_ptr<SdGlobalResource>(pInstance));
139 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
140 mpInstance = pInstance;
143 else {
144 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
147 return *mpInstance;
153 RecentlyUsedMasterPages::RecentlyUsedMasterPages (void)
154 : maListeners(),
155 mpMasterPages(new MasterPageList()),
156 mnMaxListSize(8),
157 mpContainer(new MasterPageContainer())
164 RecentlyUsedMasterPages::~RecentlyUsedMasterPages (void)
166 Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
167 mpContainer->RemoveChangeListener(aLink);
169 MasterPageObserver::Instance().RemoveEventListener(
170 LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
176 void RecentlyUsedMasterPages::LateInit (void)
178 Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
179 mpContainer->AddChangeListener(aLink);
181 LoadPersistentValues ();
182 MasterPageObserver::Instance().AddEventListener(
183 LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
189 void RecentlyUsedMasterPages::LoadPersistentValues (void)
195 tools::ConfigurationAccess aConfiguration (
196 GetPathToImpressConfigurationRoot(),
197 tools::ConfigurationAccess::READ_ONLY);
198 Reference<container::XNameAccess> xSet (
199 aConfiguration.GetConfigurationNode(GetPathToSetNode()),
200 UNO_QUERY);
201 if ( ! xSet.is())
202 break;
204 const String sURLMemberName (OUString::createFromAscii("URL"));
205 const String sNameMemberName (OUString::createFromAscii("Name"));
206 OUString sURL;
207 OUString sName;
209 // Read the names and URLs of the master pages.
210 Sequence<OUString> aKeys (xSet->getElementNames());
211 mpMasterPages->clear();
212 mpMasterPages->reserve(aKeys.getLength());
213 for (int i=0; i<aKeys.getLength(); i++)
215 Reference<container::XNameAccess> xSetItem (
216 xSet->getByName(aKeys[i]), UNO_QUERY);
217 if (xSetItem.is())
219 Any aURL (xSetItem->getByName(sURLMemberName));
220 Any aName (xSetItem->getByName(sNameMemberName));
221 aURL >>= sURL;
222 aName >>= sName;
223 SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor(
224 MasterPageContainer::TEMPLATE,
226 sURL,
227 String(),
228 sName,
229 false,
230 ::boost::shared_ptr<PageObjectProvider>(
231 new TemplatePageObjectProvider(sURL)),
232 ::boost::shared_ptr<PreviewProvider>(
233 new TemplatePreviewProvider(sURL))));
234 // For user supplied templates we use a different
235 // preview provider: The preview in the document shows
236 // not only shapes on the master page but also shapes on
237 // the foreground. This is misleading and therefore
238 // these previews are discarded and created directly
239 // from the page objects.
240 if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER)
241 pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>(
242 new PagePreviewProvider());
243 MasterPageContainer::Token aToken (mpContainer->PutMasterPage(pDescriptor));
244 mpMasterPages->push_back(Descriptor(aToken,sURL,sName));
248 ResolveList();
250 while (false);
252 catch (Exception&)
254 // Ignore exception.
261 void RecentlyUsedMasterPages::SavePersistentValues (void)
267 tools::ConfigurationAccess aConfiguration (
268 GetPathToImpressConfigurationRoot(),
269 tools::ConfigurationAccess::READ_WRITE);
270 Reference<container::XNameContainer> xSet (
271 aConfiguration.GetConfigurationNode(GetPathToSetNode()),
272 UNO_QUERY);
273 if ( ! xSet.is())
274 break;
276 // Clear the set.
277 Sequence<OUString> aKeys (xSet->getElementNames());
278 sal_Int32 i;
279 for (i=0; i<aKeys.getLength(); i++)
280 xSet->removeByName (aKeys[i]);
282 // Fill it with the URLs of this object.
283 const String sURLMemberName (OUString::createFromAscii("URL"));
284 const String sNameMemberName (OUString::createFromAscii("Name"));
285 Any aValue;
286 Reference<lang::XSingleServiceFactory> xChildFactory (
287 xSet, UNO_QUERY);
288 if ( ! xChildFactory.is())
289 break;
290 MasterPageList::const_iterator iDescriptor;
291 sal_Int32 nIndex(0);
292 for (iDescriptor=mpMasterPages->begin();
293 iDescriptor!=mpMasterPages->end();
294 ++iDescriptor,++nIndex)
296 // Create new child.
297 OUString sKey (OUString::createFromAscii("index_"));
298 sKey += OUString::valueOf(nIndex);
299 Reference<container::XNameReplace> xChild(
300 xChildFactory->createInstance(), UNO_QUERY);
301 if (xChild.is())
303 xSet->insertByName (sKey, makeAny(xChild));
305 aValue <<= OUString(iDescriptor->msURL);
306 xChild->replaceByName (sURLMemberName, aValue);
308 aValue <<= OUString(iDescriptor->msName);
309 xChild->replaceByName (sNameMemberName, aValue);
313 // Write the data back to disk.
314 aConfiguration.CommitChanges();
316 while (false);
318 catch (Exception&)
320 // Ignore exception.
327 void RecentlyUsedMasterPages::AddEventListener (const Link& rEventListener)
329 if (::std::find (
330 maListeners.begin(),
331 maListeners.end(),
332 rEventListener) == maListeners.end())
334 maListeners.push_back (rEventListener);
341 void RecentlyUsedMasterPages::RemoveEventListener (const Link& rEventListener)
343 maListeners.erase (
344 ::std::find (
345 maListeners.begin(),
346 maListeners.end(),
347 rEventListener));
353 int RecentlyUsedMasterPages::GetMasterPageCount (void) const
355 return mpMasterPages->size();
361 MasterPageContainer::Token RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex) const
363 if(nIndex<mpMasterPages->size())
364 return (*mpMasterPages)[nIndex].maToken;
365 else
366 return MasterPageContainer::NIL_TOKEN;
372 void RecentlyUsedMasterPages::SendEvent (void)
374 ::std::vector<Link>::iterator aLink (maListeners.begin());
375 ::std::vector<Link>::iterator aEnd (maListeners.end());
376 while (aLink!=aEnd)
378 aLink->Call (NULL);
379 ++aLink;
386 IMPL_LINK(RecentlyUsedMasterPages, MasterPageChangeListener,
387 MasterPageObserverEvent*, pEvent)
389 switch (pEvent->meType)
391 case MasterPageObserverEvent::ET_MASTER_PAGE_ADDED:
392 case MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS:
393 AddMasterPage(
394 mpContainer->GetTokenForStyleName(pEvent->mrMasterPageName));
395 break;
397 case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED:
398 // Do not change the list of recently master pages (the deleted
399 // page was recently used) but tell the listeners. They may want
400 // to update their lists.
401 SendEvent();
402 break;
404 return 0;
410 IMPL_LINK(RecentlyUsedMasterPages, MasterPageContainerChangeListener,
411 MasterPageContainerChangeEvent*, pEvent)
413 if (pEvent != NULL)
414 switch (pEvent->meEventType)
416 case MasterPageContainerChangeEvent::CHILD_ADDED:
417 case MasterPageContainerChangeEvent::CHILD_REMOVED:
418 case MasterPageContainerChangeEvent::INDEX_CHANGED:
419 case MasterPageContainerChangeEvent::INDEXES_CHANGED:
420 ResolveList();
421 break;
423 default:
424 // Ignored.
425 break;
427 return 0;
433 void RecentlyUsedMasterPages::AddMasterPage (
434 MasterPageContainer::Token aToken,
435 bool bMakePersistent)
437 // For the page to be inserted the token has to be valid and the page
438 // has to have a valid URL. This excludes master pages that do not come
439 // from template files.
440 if (aToken != MasterPageContainer::NIL_TOKEN
441 && mpContainer->GetURLForToken(aToken).Len()>0)
444 MasterPageList::iterator aIterator (
445 ::std::find_if(mpMasterPages->begin(),mpMasterPages->end(),
446 Descriptor::TokenComparator(aToken)));
447 if (aIterator != mpMasterPages->end())
449 // When an entry for the given token already exists then remove
450 // it now and insert it later at the head of the list.
451 mpMasterPages->erase (aIterator);
454 mpMasterPages->insert(mpMasterPages->begin(),
455 Descriptor(
456 aToken,
457 mpContainer->GetURLForToken(aToken),
458 mpContainer->GetStyleNameForToken(aToken)));
460 // Shorten list to maximal size.
461 while (mpMasterPages->size() > mnMaxListSize)
463 mpMasterPages->pop_back ();
466 if (bMakePersistent)
467 SavePersistentValues ();
468 SendEvent();
475 void RecentlyUsedMasterPages::ResolveList (void)
477 bool bNotify (false);
479 MasterPageList::iterator iDescriptor;
480 for (iDescriptor=mpMasterPages->begin(); iDescriptor!=mpMasterPages->end(); ++iDescriptor)
482 if (iDescriptor->maToken == MasterPageContainer::NIL_TOKEN)
484 MasterPageContainer::Token aToken (mpContainer->GetTokenForURL(iDescriptor->msURL));
485 iDescriptor->maToken = aToken;
486 if (aToken != MasterPageContainer::NIL_TOKEN)
487 bNotify = true;
489 else
491 if ( ! mpContainer->HasToken(iDescriptor->maToken))
493 iDescriptor->maToken = MasterPageContainer::NIL_TOKEN;
494 bNotify = true;
499 if (bNotify)
500 SendEvent();
504 } } } // end of namespace ::sd::toolpanel::controls