merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / toolpanel / controls / DocumentHelper.cxx
bloba503fa6fe0c97a61e600b0ee14adeb9704549d6c
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: DocumentHelper.cxx,v $
10 * $Revision: 1.7 $
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"
38 #include "sdpage.hxx"
39 #include "glob.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,
56 SdPage* pMasterPage)
58 SdPage* pNewMasterPage = NULL;
62 if (pMasterPage == NULL)
63 break;
65 // Check the presence of the source document.
66 SdDrawDocument* pSourceDocument = static_cast<SdDrawDocument*>(
67 pMasterPage->GetModel());
68 if (pSourceDocument == NULL)
69 break;
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;
76 break;
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
82 // page is not there.
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.
88 break;
89 USHORT nIndex = pMasterPage->GetPageNum();
90 if (nSourceMasterPageCount <= nIndex+1)
91 break;
92 // Get the slide master page.
93 if (pMasterPage != static_cast<SdPage*>(
94 pSourceDocument->GetMasterPage(nIndex)))
95 break;
96 // Get the notes master page.
97 SdPage* pNotesMasterPage = static_cast<SdPage*>(
98 pSourceDocument->GetMasterPage(nIndex+1));
99 if (pNotesMasterPage == NULL)
100 break;
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)
114 bPageExists = true;
115 pNewMasterPage = pCandidate;
116 break;
119 if (bPageExists)
120 break;
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())
126 break;
127 uno::Reference<drawing::XDrawPages> xSlides (
128 xSlideSupplier->getDrawPages(), uno::UNO_QUERY);
129 if ( ! xSlides.is())
130 break;
131 xSlides->insertNewByIndex (xSlides->getCount());
133 // Set a layout.
134 SdPage* pSlide = rTargetDocument.GetSdPage(
135 rTargetDocument.GetSdPageCount(PK_STANDARD)-1,
136 PK_STANDARD);
137 if (pSlide == NULL)
138 break;
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)
145 break;
146 SdPage* pNewNotesMasterPage
147 = AddMasterPage(rTargetDocument, pNotesMasterPage);
148 if (pNewNotesMasterPage==NULL)
149 break;
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(),
156 &rTargetDocument,
157 FALSE, // Connect the new master page with the new slide but
158 // do not modify other (master) pages.
159 TRUE);
161 while (false);
163 // We are not interested in any automatisms for our modified internal
164 // document.
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
182 // page.
183 if (pDocument!=NULL && pDocument->GetSdPageCount(PK_STANDARD) > 0)
185 // In most cases a new slide has just been inserted so start with
186 // the last page.
187 USHORT nPageIndex (pDocument->GetSdPageCount(PK_STANDARD)-1);
188 bool bFound (false);
189 while ( ! bFound)
191 pCandidate = pDocument->GetSdPage(
192 nPageIndex,
193 PK_STANDARD);
194 if (pCandidate != NULL)
196 if (static_cast<SdPage*>(&pCandidate->TRG_GetMasterPage())
197 == pMasterPage)
199 bFound = true;
200 break;
204 if (nPageIndex == 0)
205 break;
206 else
207 nPageIndex --;
210 // If no page was found that refernced the given master page reset
211 // the pointer that is returned.
212 if ( ! bFound)
213 pCandidate = NULL;
216 return pCandidate;
222 SdPage* DocumentHelper::AddMasterPage (
223 SdDrawDocument& rTargetDocument,
224 SdPage* pMasterPage)
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
245 // master page.
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");
260 catch (...)
262 pClonedMasterPage = NULL;
263 OSL_TRACE ("caught general exception");
267 return pClonedMasterPage;
273 void DocumentHelper::ProvideStyles (
274 SdDrawDocument& rSourceDocument,
275 SdDrawDocument& rTargetDocument,
276 SdPage* pPage)
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 (
289 sLayoutName,
290 *pSourceStyleSheetPool,
291 aCreatedStyles);
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 (
301 &rTargetDocument,
302 aCreatedStyles,
303 TRUE);
304 pUndoManager->AddUndoAction (pMovStyles);
312 void DocumentHelper::AssignMasterPageToPageList (
313 SdDrawDocument& rTargetDocument,
314 SdPage* pMasterPage,
315 const ::boost::shared_ptr<std::vector<SdPage*> >& rpPageList)
319 if (pMasterPage == NULL && pMasterPage->IsMasterPage())
320 break;
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())
329 break;
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);
338 if (*iPage != NULL
339 && (*iPage)->GetLayoutName().CompareTo(sFullLayoutName)!=0)
341 aCleanedList.push_back(*iPage);
344 if (aCleanedList.size() == 0)
345 break;
347 SfxUndoManager* pUndoMgr = rTargetDocument.GetDocSh()->GetUndoManager();
348 if( pUndoMgr )
349 pUndoMgr->EnterListAction(String(SdResId(STR_UNDO_SET_PRESLAYOUT)), String());
351 SdPage* pMasterPageInDocument = ProvideMasterPage(rTargetDocument,pMasterPage,rpPageList);
352 if (pMasterPageInDocument == NULL)
353 break;
355 // Assign the master pages to the given list of pages.
356 for (iPage=aCleanedList.begin();
357 iPage!=aCleanedList.end();
358 ++iPage)
360 AssignMasterPageToPage (
361 pMasterPageInDocument,
362 sBaseLayoutName,
363 *iPage);
366 if( pUndoMgr )
367 pUndoMgr->LeaveListAction();
369 while (false);
375 SdPage* DocumentHelper::AddMasterPage (
376 SdDrawDocument& rTargetDocument,
377 SdPage* pMasterPage,
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
398 // master page.
399 rTargetDocument.InsertMasterPage (pClonedMasterPage, nInsertionIndex);
401 // Adapt the size of the new master page to that of the pages in
402 // the document.
403 Size aNewSize (rTargetDocument.GetSdPage(0, pMasterPage->GetPageKind())->GetSize());
404 Rectangle aBorders (
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
423 master pages to it.
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
428 instead.
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 (
435 SdPage* pMasterPage,
436 const String& rsBaseLayoutName,
437 SdPage* pPage)
439 // Leave early when the parameters are invalid.
440 if (pPage == NULL || pMasterPage == NULL)
441 return;
442 SdDrawDocument* pDocument = dynamic_cast<SdDrawDocument*>(pPage->GetModel());
443 if (pDocument == NULL)
444 return;
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()),
453 TRUE);
454 pPage->SetBackgroundObj(NULL);
456 pDocument->SetMasterPage (
457 (pPage->GetPageNum()-1)/2,
458 rsBaseLayoutName,
459 pDocument,
460 FALSE,
461 FALSE);
463 else
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);
479 if (pSlide != NULL)
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,
485 rsBaseLayoutName,
486 pDocument,
487 FALSE,
488 FALSE);
490 else
492 // 3. Replace the master page A by a copy of the given master
493 // page B.
494 pDocument->RemoveUnnecessaryMasterPages (
495 pPage, FALSE);
503 SdPage* DocumentHelper::ProvideMasterPage (
504 SdDrawDocument& rTargetDocument,
505 SdPage* pMasterPage,
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));
536 else
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