1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: RecentlyUsedMasterPages.cxx,v $
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"
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
;
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
;
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
)
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
)
100 class TokenComparator
102 TokenComparator(::sd::toolpanel::controls::MasterPageContainer::Token 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
>
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
;
144 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
153 RecentlyUsedMasterPages::RecentlyUsedMasterPages (void)
155 mpMasterPages(new MasterPageList()),
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()),
204 const String
sURLMemberName (OUString::createFromAscii("URL"));
205 const String
sNameMemberName (OUString::createFromAscii("Name"));
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
);
219 Any
aURL (xSetItem
->getByName(sURLMemberName
));
220 Any
aName (xSetItem
->getByName(sNameMemberName
));
223 SharedMasterPageDescriptor
pDescriptor (new MasterPageDescriptor(
224 MasterPageContainer::TEMPLATE
,
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
));
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()),
277 Sequence
<OUString
> aKeys (xSet
->getElementNames());
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"));
286 Reference
<lang::XSingleServiceFactory
> xChildFactory (
288 if ( ! xChildFactory
.is())
290 MasterPageList::const_iterator iDescriptor
;
292 for (iDescriptor
=mpMasterPages
->begin();
293 iDescriptor
!=mpMasterPages
->end();
294 ++iDescriptor
,++nIndex
)
297 OUString
sKey (OUString::createFromAscii("index_"));
298 sKey
+= OUString::valueOf(nIndex
);
299 Reference
<container::XNameReplace
> xChild(
300 xChildFactory
->createInstance(), UNO_QUERY
);
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();
327 void RecentlyUsedMasterPages::AddEventListener (const Link
& rEventListener
)
332 rEventListener
) == maListeners
.end())
334 maListeners
.push_back (rEventListener
);
341 void RecentlyUsedMasterPages::RemoveEventListener (const Link
& 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
;
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());
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
:
394 mpContainer
->GetTokenForStyleName(pEvent
->mrMasterPageName
));
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.
410 IMPL_LINK(RecentlyUsedMasterPages
, MasterPageContainerChangeListener
,
411 MasterPageContainerChangeEvent
*, pEvent
)
414 switch (pEvent
->meEventType
)
416 case MasterPageContainerChangeEvent::CHILD_ADDED
:
417 case MasterPageContainerChangeEvent::CHILD_REMOVED
:
418 case MasterPageContainerChangeEvent::INDEX_CHANGED
:
419 case MasterPageContainerChangeEvent::INDEXES_CHANGED
:
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(),
457 mpContainer
->GetURLForToken(aToken
),
458 mpContainer
->GetStyleNameForToken(aToken
)));
460 // Shorten list to maximal size.
461 while (mpMasterPages
->size() > mnMaxListSize
)
463 mpMasterPages
->pop_back ();
467 SavePersistentValues ();
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
)
491 if ( ! mpContainer
->HasToken(iDescriptor
->maToken
))
493 iDescriptor
->maToken
= MasterPageContainer::NIL_TOKEN
;
504 } } } // end of namespace ::sd::toolpanel::controls