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: DocumentHelper.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 "DocumentHelper.hxx"
36 #include "drawdoc.hxx"
37 #include "DrawDocShell.hxx"
40 #include "unmovss.hxx"
41 #include "strings.hrc"
42 #include "sdresid.hxx"
43 #include "undoback.hxx"
44 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
45 #include <com/sun/star/drawing/XDrawPages.hpp>
46 #include <com/sun/star/frame/XComponentLoader.hpp>
47 #include <com/sun/star/container/XIndexAccess.hpp>
48 #include "stlpool.hxx"
50 using namespace ::com::sun::star
;
52 namespace sd
{ namespace toolpanel
{ namespace controls
{
54 SdPage
* DocumentHelper::CopyMasterPageToLocalDocument (
55 SdDrawDocument
& rTargetDocument
,
58 SdPage
* pNewMasterPage
= NULL
;
62 if (pMasterPage
== NULL
)
65 // Check the presence of the source document.
66 SdDrawDocument
* pSourceDocument
= static_cast<SdDrawDocument
*>(
67 pMasterPage
->GetModel());
68 if (pSourceDocument
== NULL
)
71 // When the given master page already belongs to the target document
72 // then there is nothing more to do.
73 if (pSourceDocument
== &rTargetDocument
)
75 pNewMasterPage
= pMasterPage
;
79 // Test if the master pages of both the slide and its notes page are
80 // present. This is not the case when we are called during the
81 // creation of the slide master page because then the notes master
83 USHORT nSourceMasterPageCount
= pSourceDocument
->GetMasterPageCount();
84 if (nSourceMasterPageCount
%2 == 0)
85 // There should be 1 handout page + n slide masters + n notes
86 // masters = 2*n+1. An even value indicates that a new slide
87 // master but not yet the notes master has been inserted.
89 USHORT nIndex
= pMasterPage
->GetPageNum();
90 if (nSourceMasterPageCount
<= nIndex
+1)
92 // Get the slide master page.
93 if (pMasterPage
!= static_cast<SdPage
*>(
94 pSourceDocument
->GetMasterPage(nIndex
)))
96 // Get the notes master page.
97 SdPage
* pNotesMasterPage
= static_cast<SdPage
*>(
98 pSourceDocument
->GetMasterPage(nIndex
+1));
99 if (pNotesMasterPage
== NULL
)
103 // Check if a master page with the same name as that of the given
104 // master page already exists.
105 bool bPageExists (false);
106 USHORT
nMasterPageCount(rTargetDocument
.GetMasterSdPageCount(PK_STANDARD
));
107 for (USHORT nMaster
=0; nMaster
<nMasterPageCount
; nMaster
++)
109 SdPage
* pCandidate
= static_cast<SdPage
*>(
110 rTargetDocument
.GetMasterSdPage (nMaster
, PK_STANDARD
));
111 if (pMasterPage
!=NULL
112 && pCandidate
->GetName().CompareTo(pMasterPage
->GetName())==0)
115 pNewMasterPage
= pCandidate
;
122 // Create a new slide (and its notes page.)
123 uno::Reference
<drawing::XDrawPagesSupplier
> xSlideSupplier (
124 rTargetDocument
.getUnoModel(), uno::UNO_QUERY
);
125 if ( ! xSlideSupplier
.is())
127 uno::Reference
<drawing::XDrawPages
> xSlides (
128 xSlideSupplier
->getDrawPages(), uno::UNO_QUERY
);
131 xSlides
->insertNewByIndex (xSlides
->getCount());
134 SdPage
* pSlide
= rTargetDocument
.GetSdPage(
135 rTargetDocument
.GetSdPageCount(PK_STANDARD
)-1,
139 pSlide
->SetAutoLayout(AUTOLAYOUT_TITLE
, TRUE
);
141 // Create a copy of the master page and the associated notes
142 // master page and insert them into our document.
143 pNewMasterPage
= AddMasterPage(rTargetDocument
, pMasterPage
);
144 if (pNewMasterPage
==NULL
)
146 SdPage
* pNewNotesMasterPage
147 = AddMasterPage(rTargetDocument
, pNotesMasterPage
);
148 if (pNewNotesMasterPage
==NULL
)
151 // Make the connection from the new slide to the master page
152 // (and do the same for the notes page.)
153 rTargetDocument
.SetMasterPage (
154 rTargetDocument
.GetSdPageCount(PK_STANDARD
)-1,
155 pNewMasterPage
->GetName(),
157 FALSE
, // Connect the new master page with the new slide but
158 // do not modify other (master) pages.
163 // We are not interested in any automatisms for our modified internal
165 rTargetDocument
.SetChanged (sal_False
);
167 return pNewMasterPage
;
173 SdPage
* DocumentHelper::GetSlideForMasterPage (SdPage
* pMasterPage
)
175 SdPage
* pCandidate
= NULL
;
177 SdDrawDocument
* pDocument
= NULL
;
178 if (pMasterPage
!= NULL
)
179 pDocument
= dynamic_cast<SdDrawDocument
*>(pMasterPage
->GetModel());
181 // Iterate over all pages and check if it references the given master
183 if (pDocument
!=NULL
&& pDocument
->GetSdPageCount(PK_STANDARD
) > 0)
185 // In most cases a new slide has just been inserted so start with
187 USHORT
nPageIndex (pDocument
->GetSdPageCount(PK_STANDARD
)-1);
191 pCandidate
= pDocument
->GetSdPage(
194 if (pCandidate
!= NULL
)
196 if (static_cast<SdPage
*>(&pCandidate
->TRG_GetMasterPage())
210 // If no page was found that refernced the given master page reset
211 // the pointer that is returned.
222 SdPage
* DocumentHelper::AddMasterPage (
223 SdDrawDocument
& rTargetDocument
,
226 SdPage
* pClonedMasterPage
= NULL
;
228 if (pMasterPage
!=NULL
)
232 // Duplicate the master page.
233 pClonedMasterPage
= static_cast<SdPage
*>(pMasterPage
->Clone());
235 // Copy the necessary styles.
236 SdDrawDocument
* pSourceDocument
237 = static_cast<SdDrawDocument
*>(pMasterPage
->GetModel());
238 if (pSourceDocument
!= NULL
)
239 ProvideStyles (*pSourceDocument
, rTargetDocument
, pClonedMasterPage
);
241 // Copy the precious flag.
242 pClonedMasterPage
->SetPrecious(pMasterPage
->IsPrecious());
244 // Now that the styles are available we can insert the cloned
246 rTargetDocument
.InsertMasterPage (pClonedMasterPage
);
248 catch (uno::Exception
& rException
)
250 pClonedMasterPage
= NULL
;
251 OSL_TRACE("caught exception while adding master page: %s",
252 ::rtl::OUStringToOString(rException
.Message
,
253 RTL_TEXTENCODING_UTF8
).getStr());
255 catch (::std::exception rException
)
257 pClonedMasterPage
= NULL
;
258 OSL_TRACE ("caught general exception");
262 pClonedMasterPage
= NULL
;
263 OSL_TRACE ("caught general exception");
267 return pClonedMasterPage
;
273 void DocumentHelper::ProvideStyles (
274 SdDrawDocument
& rSourceDocument
,
275 SdDrawDocument
& rTargetDocument
,
278 // Get the layout name of the given page.
279 String
sLayoutName (pPage
->GetLayoutName());
280 sLayoutName
.Erase (sLayoutName
.SearchAscii (SD_LT_SEPARATOR
));
282 // Copy the style sheet from source to target document.
283 SdStyleSheetPool
* pSourceStyleSheetPool
=
284 static_cast<SdStyleSheetPool
*>(rSourceDocument
.GetStyleSheetPool());
285 SdStyleSheetPool
* pTargetStyleSheetPool
=
286 static_cast<SdStyleSheetPool
*>(rTargetDocument
.GetStyleSheetPool());
287 SdStyleSheetVector aCreatedStyles
;
288 pTargetStyleSheetPool
->CopyLayoutSheets (
290 *pSourceStyleSheetPool
,
293 // Add an undo action for the copied style sheets.
294 if( !aCreatedStyles
.empty() )
296 SfxUndoManager
* pUndoManager
= rTargetDocument
.GetDocSh()->GetUndoManager();
297 if (pUndoManager
!= NULL
)
299 SdMoveStyleSheetsUndoAction
* pMovStyles
=
300 new SdMoveStyleSheetsUndoAction (
304 pUndoManager
->AddUndoAction (pMovStyles
);
312 void DocumentHelper::AssignMasterPageToPageList (
313 SdDrawDocument
& rTargetDocument
,
315 const ::boost::shared_ptr
<std::vector
<SdPage
*> >& rpPageList
)
319 if (pMasterPage
== NULL
&& pMasterPage
->IsMasterPage())
322 // Make the layout name by stripping ouf the layout postfix from the
323 // layout name of the given master page.
324 String
sFullLayoutName (pMasterPage
->GetLayoutName());
325 String
sBaseLayoutName (sFullLayoutName
);
326 sBaseLayoutName
.Erase (sBaseLayoutName
.SearchAscii (SD_LT_SEPARATOR
));
328 if (rpPageList
->empty())
331 // Create a second list that contains only the valid pointers to
332 // pages for which an assignment is necessary.
333 ::std::vector
<SdPage
*>::const_iterator iPage
;
334 ::std::vector
<SdPage
*> aCleanedList
;
335 for (iPage
=rpPageList
->begin(); iPage
!=rpPageList
->end(); ++iPage
)
337 OSL_ASSERT(*iPage
!=NULL
&& (*iPage
)->GetModel() == &rTargetDocument
);
339 && (*iPage
)->GetLayoutName().CompareTo(sFullLayoutName
)!=0)
341 aCleanedList
.push_back(*iPage
);
344 if (aCleanedList
.size() == 0)
347 SfxUndoManager
* pUndoMgr
= rTargetDocument
.GetDocSh()->GetUndoManager();
349 pUndoMgr
->EnterListAction(String(SdResId(STR_UNDO_SET_PRESLAYOUT
)), String());
351 SdPage
* pMasterPageInDocument
= ProvideMasterPage(rTargetDocument
,pMasterPage
,rpPageList
);
352 if (pMasterPageInDocument
== NULL
)
355 // Assign the master pages to the given list of pages.
356 for (iPage
=aCleanedList
.begin();
357 iPage
!=aCleanedList
.end();
360 AssignMasterPageToPage (
361 pMasterPageInDocument
,
367 pUndoMgr
->LeaveListAction();
375 SdPage
* DocumentHelper::AddMasterPage (
376 SdDrawDocument
& rTargetDocument
,
378 USHORT nInsertionIndex
)
380 SdPage
* pClonedMasterPage
= NULL
;
382 if (pMasterPage
!=NULL
)
384 // Duplicate the master page.
385 pClonedMasterPage
= static_cast<SdPage
*>(pMasterPage
->Clone());
387 // Copy the precious flag.
388 pClonedMasterPage
->SetPrecious(pMasterPage
->IsPrecious());
390 // Copy the necessary styles.
391 SdDrawDocument
* pSourceDocument
392 = static_cast<SdDrawDocument
*>(pMasterPage
->GetModel());
393 if (pSourceDocument
!= NULL
)
395 ProvideStyles (*pSourceDocument
, rTargetDocument
, pClonedMasterPage
);
397 // Now that the styles are available we can insert the cloned
399 rTargetDocument
.InsertMasterPage (pClonedMasterPage
, nInsertionIndex
);
401 // Adapt the size of the new master page to that of the pages in
403 Size
aNewSize (rTargetDocument
.GetSdPage(0, pMasterPage
->GetPageKind())->GetSize());
405 pClonedMasterPage
->GetLftBorder(),
406 pClonedMasterPage
->GetUppBorder(),
407 pClonedMasterPage
->GetRgtBorder(),
408 pClonedMasterPage
->GetLwrBorder());
409 pClonedMasterPage
->ScaleObjects(aNewSize
, aBorders
, TRUE
);
410 pClonedMasterPage
->SetSize(aNewSize
);
411 pClonedMasterPage
->CreateTitleAndLayout(TRUE
);
415 return pClonedMasterPage
;
421 /** In here we have to handle three cases:
422 1. pPage is a normal slide. We can use SetMasterPage to assign the
424 2. pPage is a master page that is used by at least one slide. We can
425 assign the master page to these slides.
426 3. pPage is a master page that is currently not used by any slide.
427 We can delete that page and add copies of the given master pages
430 For points 2 and 3 where one master page A is assigned to another B we have
431 to keep in mind that the master page that page A has already been
432 inserted into the target document.
434 void DocumentHelper::AssignMasterPageToPage (
436 const String
& rsBaseLayoutName
,
439 // Leave early when the parameters are invalid.
440 if (pPage
== NULL
|| pMasterPage
== NULL
)
442 SdDrawDocument
* pDocument
= dynamic_cast<SdDrawDocument
*>(pPage
->GetModel());
443 if (pDocument
== NULL
)
446 if ( ! pPage
->IsMasterPage())
448 // 1. Remove the background object (so that that, if it exists, does
449 // not override the new master page) and assign the master page to
450 // the regular slide.
451 pDocument
->GetDocSh()->GetUndoManager()->AddUndoAction(
452 new SdBackgroundObjUndoAction(*pDocument
, *pPage
, pPage
->GetBackgroundObj()),
454 pPage
->SetBackgroundObj(NULL
);
456 pDocument
->SetMasterPage (
457 (pPage
->GetPageNum()-1)/2,
465 // Find first slide that uses the master page.
466 SdPage
* pSlide
= NULL
;
467 USHORT nPageCount
= pDocument
->GetSdPageCount(PK_STANDARD
);
468 for (USHORT nPage
=0; nPage
<nPageCount
&&pSlide
==NULL
; nPage
++)
470 SdrPage
* pCandidate
= pDocument
->GetSdPage(nPage
,PK_STANDARD
);
471 if (pCandidate
!= NULL
472 && pCandidate
->TRG_HasMasterPage()
473 && &(pCandidate
->TRG_GetMasterPage()) == pPage
)
475 pSlide
= static_cast<SdPage
*>(pCandidate
);
481 // 2. Assign the given master pages to the first slide that was
482 // found above that uses the master page.
483 pDocument
->SetMasterPage (
484 (pSlide
->GetPageNum()-1)/2,
492 // 3. Replace the master page A by a copy of the given master
494 pDocument
->RemoveUnnecessaryMasterPages (
503 SdPage
* DocumentHelper::ProvideMasterPage (
504 SdDrawDocument
& rTargetDocument
,
506 const ::boost::shared_ptr
<std::vector
<SdPage
*> >& rpPageList
)
508 SdPage
* pMasterPageInDocument
= NULL
;
510 // Get notes master page.
511 SdDrawDocument
* pSourceDocument
= static_cast<SdDrawDocument
*>(pMasterPage
->GetModel());
512 SdPage
* pNotesMasterPage
= static_cast<SdPage
*>(
513 pSourceDocument
->GetMasterPage (pMasterPage
->GetPageNum()+1));
514 if (pNotesMasterPage
!= NULL
)
516 // When the given master page or its associated notes master page do
517 // not already belong to the document we have to create copies of
518 // them and insert them into the document.
520 // Determine the position where the new master pages are inserted.
521 // By default they are inserted at the end. When we assign to a
522 // master page then insert after the last of the (selected) pages.
523 USHORT nInsertionIndex
= rTargetDocument
.GetMasterPageCount();
524 if (rpPageList
->front()->IsMasterPage())
526 nInsertionIndex
= rpPageList
->back()->GetPageNum();
529 if (pMasterPage
->GetModel() != &rTargetDocument
)
531 pMasterPageInDocument
= AddMasterPage (rTargetDocument
, pMasterPage
, nInsertionIndex
);
532 if( rTargetDocument
.IsUndoEnabled() )
533 rTargetDocument
.AddUndo(
534 rTargetDocument
.GetSdrUndoFactory().CreateUndoNewPage(*pMasterPageInDocument
));
537 pMasterPageInDocument
= pMasterPage
;
538 if (pNotesMasterPage
->GetModel() != &rTargetDocument
)
540 SdPage
* pClonedNotesMasterPage
541 = AddMasterPage (rTargetDocument
, pNotesMasterPage
, nInsertionIndex
+1);
542 if( rTargetDocument
.IsUndoEnabled() )
543 rTargetDocument
.AddUndo(
544 rTargetDocument
.GetSdrUndoFactory().CreateUndoNewPage(*pClonedNotesMasterPage
));
547 return pMasterPageInDocument
;
554 } } } // end of namespace ::sd::toolpanel::controls