Seem UBSAN doesn't like my forced reinterpret_cast to set the Idles Link in the Timer class. Now there are two possible solution: 1. convert all (DECL|IMPL).*_LINK call sites to use a Timer* or 2. split the inheritance of Idle from Timer again to maintain different Link<>s and move all common code into a TimerBase. While the 1st is more correct, the 2nd has a better indicator for Idles. This implements the first solution. And while at it, this also converts all call sites of SetTimeoutHdl and SetIdleHdl to SetInvokeHandler and gets rid of some local Link objects, which are just passed to the SetInvokeHandler call. It also introduces ClearInvokeHandler() and replaces the respective call sites of SetInvokeHandler( Link<Timer *, void>() ). Change-Id: I40c4167b1493997b7f136add4dad2f4ff5504b69
1510 lines
49 KiB
C++
1510 lines
49 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <vcl/wrkwin.hxx>
|
|
#include <vcl/settings.hxx>
|
|
|
|
#include <sfx2/printer.hxx>
|
|
#include <sfx2/app.hxx>
|
|
#include "Outliner.hxx"
|
|
#include <editeng/paperinf.hxx>
|
|
#include <svx/svdopage.hxx>
|
|
#include <svx/svdoole2.hxx>
|
|
#include <svx/svdotext.hxx>
|
|
#include <svx/svdograf.hxx>
|
|
#include <svx/svdundo.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <editeng/eeitem.hxx>
|
|
#include <editeng/langitem.hxx>
|
|
#include <svl/itempool.hxx>
|
|
#include <svx/svdpool.hxx>
|
|
#include <editeng/flditem.hxx>
|
|
|
|
#include <sfx2/linkmgr.hxx>
|
|
#include <editeng/editdata.hxx>
|
|
#include <svx/dialogs.hrc>
|
|
#include <svx/dialmgr.hxx>
|
|
|
|
#include <editeng/outliner.hxx>
|
|
#include <svx/svditer.hxx>
|
|
#include <svtools/imapobj.hxx>
|
|
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
|
|
#include <boost/property_tree/json_parser.hpp>
|
|
#include <comphelper/lok.hxx>
|
|
|
|
#include "sdresid.hxx"
|
|
#include "drawdoc.hxx"
|
|
#include "sdpage.hxx"
|
|
#include "pglink.hxx"
|
|
#include "glob.hrc"
|
|
#include "glob.hxx"
|
|
#include "stlpool.hxx"
|
|
#include "sdiocmpt.hxx"
|
|
#include "anminfo.hxx"
|
|
#include "imapinfo.hxx"
|
|
#include "cusshow.hxx"
|
|
#include "undo/undomanager.hxx"
|
|
|
|
#include "DrawDocShell.hxx"
|
|
#include "FrameView.hxx"
|
|
#include "cfgids.hxx"
|
|
#include "strings.hrc"
|
|
|
|
#include "PageListWatcher.hxx"
|
|
#include <vcl/virdev.hxx>
|
|
#include "customshowlist.hxx"
|
|
|
|
using namespace ::sd;
|
|
|
|
const long PRINT_OFFSET = 30; // see /svx/source/dialog/page.cxx
|
|
|
|
using namespace com::sun::star;
|
|
|
|
// Looks up an object by name
|
|
SdrObject* SdDrawDocument::GetObj(const OUString& rObjName) const
|
|
{
|
|
SdrObject* pObj = nullptr;
|
|
SdrObject* pObjFound = nullptr;
|
|
const SdPage* pPage = nullptr;
|
|
|
|
// First search in all pages
|
|
sal_uInt16 nPage = 0;
|
|
const sal_uInt16 nMaxPages = GetPageCount();
|
|
|
|
while (nPage < nMaxPages && !pObjFound)
|
|
{
|
|
pPage = static_cast<const SdPage*>( GetPage(nPage) );
|
|
SdrObjListIter aIter(*pPage, SdrIterMode::DeepWithGroups);
|
|
|
|
while (aIter.IsMore() && !pObjFound)
|
|
{
|
|
pObj = aIter.Next();
|
|
|
|
if( ( pObj->GetName().equals(rObjName) ) ||
|
|
( SdrInventor::Default == pObj->GetObjInventor() &&
|
|
OBJ_OLE2 == pObj->GetObjIdentifier() &&
|
|
rObjName == static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ) )
|
|
{
|
|
pObjFound = pObj;
|
|
}
|
|
}
|
|
|
|
nPage++;
|
|
}
|
|
|
|
// If it couldn't be found, look through all master pages
|
|
nPage = 0;
|
|
const sal_uInt16 nMaxMasterPages = GetMasterPageCount();
|
|
|
|
while (nPage < nMaxMasterPages && !pObjFound)
|
|
{
|
|
pPage = static_cast<const SdPage*>( GetMasterPage(nPage) );
|
|
SdrObjListIter aIter(*pPage, SdrIterMode::DeepWithGroups);
|
|
|
|
while (aIter.IsMore() && !pObjFound)
|
|
{
|
|
pObj = aIter.Next();
|
|
|
|
if( ( pObj->GetName().equals(rObjName) ) ||
|
|
( SdrInventor::Default == pObj->GetObjInventor() &&
|
|
OBJ_OLE2 == pObj->GetObjIdentifier() &&
|
|
rObjName == static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ) )
|
|
{
|
|
pObjFound = pObj;
|
|
}
|
|
}
|
|
|
|
nPage++;
|
|
}
|
|
|
|
return pObjFound;
|
|
}
|
|
|
|
// Find SdPage by name
|
|
sal_uInt16 SdDrawDocument::GetPageByName(const OUString& rPgName, bool& rbIsMasterPage) const
|
|
{
|
|
SdPage* pPage = nullptr;
|
|
sal_uInt16 nPage = 0;
|
|
const sal_uInt16 nMaxPages = GetPageCount();
|
|
sal_uInt16 nPageNum = SDRPAGE_NOTFOUND;
|
|
|
|
rbIsMasterPage = false;
|
|
|
|
// Search all regular pages and all notes pages (handout pages are
|
|
// ignored)
|
|
while (nPage < nMaxPages && nPageNum == SDRPAGE_NOTFOUND)
|
|
{
|
|
pPage = const_cast<SdPage*>(static_cast<const SdPage*>(
|
|
GetPage(nPage)));
|
|
|
|
if (pPage != nullptr
|
|
&& pPage->GetPageKind() != PageKind::Handout
|
|
&& pPage->GetName() == rPgName)
|
|
{
|
|
nPageNum = nPage;
|
|
}
|
|
|
|
nPage++;
|
|
}
|
|
|
|
// Search all master pages when not found among non-master pages
|
|
const sal_uInt16 nMaxMasterPages = GetMasterPageCount();
|
|
nPage = 0;
|
|
|
|
while (nPage < nMaxMasterPages && nPageNum == SDRPAGE_NOTFOUND)
|
|
{
|
|
pPage = const_cast<SdPage*>(static_cast<const SdPage*>(
|
|
GetMasterPage(nPage)));
|
|
|
|
if (pPage && pPage->GetName() == rPgName)
|
|
{
|
|
nPageNum = nPage;
|
|
rbIsMasterPage = true;
|
|
}
|
|
|
|
nPage++;
|
|
}
|
|
|
|
return nPageNum;
|
|
}
|
|
|
|
bool SdDrawDocument::IsPageNameUnique( const OUString& rPgName ) const
|
|
{
|
|
sal_uInt16 nCount = 0;
|
|
SdPage* pPage = nullptr;
|
|
|
|
// Search all regular pages and all notes pages (handout pages are ignored)
|
|
sal_uInt16 nPage = 0;
|
|
sal_uInt16 nMaxPages = GetPageCount();
|
|
while (nPage < nMaxPages)
|
|
{
|
|
pPage = const_cast<SdPage*>(static_cast<const SdPage*>(GetPage(nPage)));
|
|
|
|
if (pPage && pPage->GetName() == rPgName && pPage->GetPageKind() != PageKind::Handout)
|
|
nCount++;
|
|
|
|
nPage++;
|
|
}
|
|
|
|
// Search all master pages
|
|
nPage = 0;
|
|
nMaxPages = GetMasterPageCount();
|
|
while (nPage < nMaxPages)
|
|
{
|
|
pPage = const_cast<SdPage*>(static_cast<const SdPage*>(GetMasterPage(nPage)));
|
|
|
|
if (pPage && pPage->GetName() == rPgName)
|
|
nCount++;;
|
|
|
|
nPage++;
|
|
}
|
|
|
|
if (nCount == 1)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
SdPage* SdDrawDocument::GetSdPage(sal_uInt16 nPgNum, PageKind ePgKind) const
|
|
{
|
|
return mpDrawPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum));
|
|
}
|
|
|
|
sal_uInt16 SdDrawDocument::GetSdPageCount(PageKind ePgKind) const
|
|
{
|
|
return (sal_uInt16)mpDrawPageListWatcher->GetSdPageCount(ePgKind);
|
|
}
|
|
|
|
SdPage* SdDrawDocument::GetMasterSdPage(sal_uInt16 nPgNum, PageKind ePgKind)
|
|
{
|
|
return mpMasterPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum));
|
|
}
|
|
|
|
sal_uInt16 SdDrawDocument::GetMasterSdPageCount(PageKind ePgKind) const
|
|
{
|
|
return (sal_uInt16)mpMasterPageListWatcher->GetSdPageCount(ePgKind);
|
|
}
|
|
|
|
sal_uInt16 SdDrawDocument::GetActiveSdPageCount() const
|
|
{
|
|
return (sal_uInt16)mpDrawPageListWatcher->GetVisibleSdPageCount();
|
|
}
|
|
|
|
// Adapt the page numbers that are registered in the page objects of the notes
|
|
// pages
|
|
void SdDrawDocument::UpdatePageObjectsInNotes(sal_uInt16 nStartPos)
|
|
{
|
|
sal_uInt16 nPageCount = GetPageCount();
|
|
SdPage* pPage = nullptr;
|
|
|
|
for (sal_uInt16 nPage = nStartPos; nPage < nPageCount; nPage++)
|
|
{
|
|
pPage = static_cast<SdPage*>( GetPage(nPage) );
|
|
|
|
// If this is a notes page, find its page object and correct the page
|
|
// number
|
|
if (pPage && pPage->GetPageKind() == PageKind::Notes)
|
|
{
|
|
const size_t nObjCount = pPage->GetObjCount();
|
|
for (size_t nObj = 0; nObj < nObjCount; ++nObj)
|
|
{
|
|
SdrObject* pObj = pPage->GetObj(nObj);
|
|
if (pObj->GetObjIdentifier() == OBJ_PAGE &&
|
|
pObj->GetObjInventor() == SdrInventor::Default)
|
|
{
|
|
// The page object is the preceding page (drawing page)
|
|
SAL_WARN_IF(!nStartPos, "sd", "Position of notes page must not be 0.");
|
|
|
|
SAL_WARN_IF(nPage <= 1, "sd", "Page object must not be a handout.");
|
|
|
|
if (nStartPos > 0 && nPage > 1)
|
|
static_cast<SdrPageObj*>(pObj)->SetReferencedPage(GetPage(nPage - 1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdDrawDocument::UpdatePageRelativeURLs(const OUString& rOldName, const OUString& rNewName)
|
|
{
|
|
if (rNewName.isEmpty())
|
|
return;
|
|
|
|
SfxItemPool& rPool(GetPool());
|
|
sal_uInt32 nCount = rPool.GetItemCount2(EE_FEATURE_FIELD);
|
|
for (sal_uInt32 nOff = 0; nOff < nCount; nOff++)
|
|
{
|
|
const SfxPoolItem *pItem = rPool.GetItem2(EE_FEATURE_FIELD, nOff);
|
|
const SvxFieldItem* pFldItem = dynamic_cast< const SvxFieldItem * > (pItem);
|
|
|
|
if(pFldItem)
|
|
{
|
|
SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) );
|
|
|
|
if(pURLField)
|
|
{
|
|
OUString aURL = pURLField->GetURL();
|
|
|
|
if (!aURL.isEmpty() && (aURL[0] == 35) && (aURL.indexOf(rOldName, 1) == 1))
|
|
{
|
|
if (aURL.getLength() == rOldName.getLength() + 1) // standard page name
|
|
{
|
|
aURL = aURL.replaceAt(1, aURL.getLength() - 1, "");
|
|
aURL += rNewName;
|
|
pURLField->SetURL(aURL);
|
|
}
|
|
else
|
|
{
|
|
const OUString sNotes(SD_RESSTR(STR_NOTES));
|
|
if (aURL.getLength() == rOldName.getLength() + 2 + sNotes.getLength()
|
|
&& aURL.indexOf(sNotes, rOldName.getLength() + 2) == rOldName.getLength() + 2)
|
|
{
|
|
aURL = aURL.replaceAt(1, aURL.getLength() - 1, "");
|
|
aURL += rNewName + " " + sNotes;
|
|
pURLField->SetURL(aURL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdDrawDocument::UpdatePageRelativeURLs(SdPage* pPage, sal_uInt16 nPos, sal_Int32 nIncrement)
|
|
{
|
|
bool bNotes = (pPage->GetPageKind() == PageKind::Notes);
|
|
|
|
SfxItemPool& rPool(GetPool());
|
|
sal_uInt32 nCount = rPool.GetItemCount2(EE_FEATURE_FIELD);
|
|
for (sal_uInt32 nOff = 0; nOff < nCount; nOff++)
|
|
{
|
|
const SfxPoolItem *pItem = rPool.GetItem2(EE_FEATURE_FIELD, nOff);
|
|
const SvxFieldItem* pFldItem;
|
|
|
|
if ((pFldItem = dynamic_cast< const SvxFieldItem * > (pItem)) != nullptr)
|
|
{
|
|
SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) );
|
|
|
|
if(pURLField)
|
|
{
|
|
OUString aURL = pURLField->GetURL();
|
|
|
|
if (!aURL.isEmpty() && (aURL[0] == 35))
|
|
{
|
|
OUString aHashSlide("#");
|
|
aHashSlide += SD_RESSTR(STR_PAGE);
|
|
|
|
if (aURL.startsWith(aHashSlide))
|
|
{
|
|
OUString aURLCopy = aURL;
|
|
const OUString sNotes(SD_RESSTR(STR_NOTES));
|
|
|
|
aURLCopy = aURLCopy.replaceAt(0, aHashSlide.getLength(), "");
|
|
|
|
bool bNotesLink = ( aURLCopy.getLength() >= sNotes.getLength() + 3
|
|
&& aURLCopy.endsWith(sNotes) );
|
|
|
|
if (bNotesLink != bNotes)
|
|
continue; // no compatible link and page
|
|
|
|
if (bNotes)
|
|
aURLCopy = aURLCopy.replaceAt(aURLCopy.getLength() - sNotes.getLength(), sNotes.getLength(), "");
|
|
|
|
sal_Int32 number = aURLCopy.toInt32();
|
|
sal_uInt16 realPageNumber = (nPos + 1)/ 2;
|
|
|
|
if ( number >= realPageNumber )
|
|
{
|
|
// update link page number
|
|
number += nIncrement;
|
|
aURL = aURL.replaceAt(aHashSlide.getLength() + 1, aURL.getLength() - aHashSlide.getLength() - 1, "");
|
|
aURL += OUString::number(number);
|
|
if (bNotes)
|
|
{
|
|
aURL += " " + sNotes;
|
|
}
|
|
pURLField->SetURL(aURL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Move page
|
|
void SdDrawDocument::MovePage(sal_uInt16 nPgNum, sal_uInt16 nNewPos)
|
|
{
|
|
FmFormModel::MovePage(nPgNum, nNewPos);
|
|
|
|
sal_uInt16 nMin = std::min(nPgNum, nNewPos);
|
|
|
|
UpdatePageObjectsInNotes(nMin);
|
|
}
|
|
|
|
// Insert page
|
|
void SdDrawDocument::InsertPage(SdrPage* pPage, sal_uInt16 nPos)
|
|
{
|
|
bool bLast = (nPos == GetPageCount());
|
|
|
|
FmFormModel::InsertPage(pPage, nPos);
|
|
|
|
static_cast<SdPage*>(pPage)->ConnectLink();
|
|
|
|
UpdatePageObjectsInNotes(nPos);
|
|
|
|
if (!bLast)
|
|
UpdatePageRelativeURLs(static_cast<SdPage*>( pPage ), nPos, 1);
|
|
|
|
if (comphelper::LibreOfficeKit::isActive() && static_cast<SdPage*>(pPage)->GetPageKind() == PageKind::Standard)
|
|
{
|
|
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
|
|
while (pViewShell)
|
|
{
|
|
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_SIZE_CHANGED, "");
|
|
pViewShell = SfxViewShell::GetNext(*pViewShell);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Delete page
|
|
void SdDrawDocument::DeletePage(sal_uInt16 nPgNum)
|
|
{
|
|
FmFormModel::DeletePage(nPgNum);
|
|
|
|
UpdatePageObjectsInNotes(nPgNum);
|
|
}
|
|
|
|
// Remove page
|
|
SdrPage* SdDrawDocument::RemovePage(sal_uInt16 nPgNum)
|
|
{
|
|
SdrPage* pPage = FmFormModel::RemovePage(nPgNum);
|
|
|
|
bool bLast = ((nPgNum+1)/2 == (GetPageCount()+1)/2);
|
|
|
|
static_cast<SdPage*>(pPage)->DisconnectLink();
|
|
ReplacePageInCustomShows( dynamic_cast< SdPage* >( pPage ), nullptr );
|
|
UpdatePageObjectsInNotes(nPgNum);
|
|
|
|
if (!bLast)
|
|
UpdatePageRelativeURLs(static_cast<SdPage*>(pPage), nPgNum, -1);
|
|
|
|
if (comphelper::LibreOfficeKit::isActive() && static_cast<SdPage*>(pPage)->GetPageKind() == PageKind::Standard)
|
|
{
|
|
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
|
|
while (pViewShell)
|
|
{
|
|
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_SIZE_CHANGED, "");
|
|
pViewShell = SfxViewShell::GetNext(*pViewShell);
|
|
}
|
|
}
|
|
|
|
return pPage;
|
|
}
|
|
|
|
// Warning: This is not called for new master pages created from SdrModel::Merge,
|
|
// you also have to modify code in SdDrawDocument::Merge!
|
|
void SdDrawDocument::InsertMasterPage(SdrPage* pPage, sal_uInt16 nPos )
|
|
{
|
|
FmFormModel::InsertMasterPage( pPage, nPos );
|
|
if( pPage->IsMasterPage() && (static_cast<SdPage*>(pPage)->GetPageKind() == PageKind::Standard) )
|
|
{
|
|
// new master page created, add its style family
|
|
SdStyleSheetPool* pStylePool = static_cast<SdStyleSheetPool*>( GetStyleSheetPool() );
|
|
if( pStylePool )
|
|
pStylePool->AddStyleFamily( static_cast<SdPage*>(pPage) );
|
|
}
|
|
}
|
|
|
|
SdrPage* SdDrawDocument::RemoveMasterPage(sal_uInt16 nPgNum)
|
|
{
|
|
SdPage* pPage = static_cast<SdPage*>(GetMasterPage(nPgNum ));
|
|
if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PageKind::Standard) )
|
|
{
|
|
// master page removed, remove its style family
|
|
SdStyleSheetPool* pStylePool = static_cast<SdStyleSheetPool*>( GetStyleSheetPool() );
|
|
if( pStylePool )
|
|
pStylePool->RemoveStyleFamily( pPage );
|
|
}
|
|
|
|
return FmFormModel::RemoveMasterPage(nPgNum);
|
|
}
|
|
|
|
//Select pages
|
|
void SdDrawDocument::SetSelected(SdPage* pPage, bool bSelect)
|
|
{
|
|
PageKind ePageKind = pPage->GetPageKind();
|
|
|
|
if (ePageKind == PageKind::Standard)
|
|
{
|
|
pPage->SetSelected(bSelect);
|
|
|
|
const sal_uInt16 nDestPageNum(pPage->GetPageNum() + 1);
|
|
SdPage* pNotesPage = nullptr;
|
|
|
|
if(nDestPageNum < GetPageCount())
|
|
{
|
|
pNotesPage = static_cast<SdPage*>(GetPage(nDestPageNum));
|
|
}
|
|
|
|
if (pNotesPage && pNotesPage->GetPageKind() == PageKind::Notes)
|
|
{
|
|
pNotesPage->SetSelected(bSelect);
|
|
}
|
|
}
|
|
else if (ePageKind == PageKind::Notes)
|
|
{
|
|
pPage->SetSelected(bSelect);
|
|
SdPage* pStandardPage = static_cast<SdPage*>( GetPage( pPage->GetPageNum() - 1 ) );
|
|
|
|
if (pStandardPage && pStandardPage->GetPageKind() == PageKind::Standard)
|
|
pStandardPage->SetSelected(bSelect);
|
|
}
|
|
}
|
|
|
|
// If no pages exist yet, create them now
|
|
void SdDrawDocument::CreateFirstPages( SdDrawDocument* pRefDocument /* = 0 */ )
|
|
{
|
|
// If no page exists yet in the model, (File -> New), insert a page
|
|
sal_uInt16 nPageCount = GetPageCount();
|
|
|
|
if (nPageCount <= 1)
|
|
{
|
|
// #i57181# Paper size depends on Language, like in Writer
|
|
Size aDefSize = SvxPaperInfo::GetDefaultPaperSize( MapUnit::Map100thMM );
|
|
|
|
// Insert handout page
|
|
SdPage* pHandoutPage = AllocSdPage(false);
|
|
|
|
SdPage* pRefPage = nullptr;
|
|
|
|
if( pRefDocument )
|
|
pRefPage = pRefDocument->GetSdPage( 0, PageKind::Handout );
|
|
|
|
if( pRefPage )
|
|
{
|
|
pHandoutPage->SetSize(pRefPage->GetSize());
|
|
pHandoutPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() );
|
|
}
|
|
else
|
|
{
|
|
pHandoutPage->SetSize(aDefSize);
|
|
pHandoutPage->SetBorder(0, 0, 0, 0);
|
|
}
|
|
|
|
pHandoutPage->SetPageKind(PageKind::Handout);
|
|
pHandoutPage->SetName( SD_RESSTR(STR_HANDOUT) );
|
|
InsertPage(pHandoutPage, 0);
|
|
|
|
// Insert master page and register this with the handout page
|
|
SdPage* pHandoutMPage = AllocSdPage(true);
|
|
pHandoutMPage->SetSize( pHandoutPage->GetSize() );
|
|
pHandoutMPage->SetPageKind(PageKind::Handout);
|
|
pHandoutMPage->SetBorder( pHandoutPage->GetLftBorder(),
|
|
pHandoutPage->GetUppBorder(),
|
|
pHandoutPage->GetRgtBorder(),
|
|
pHandoutPage->GetLwrBorder() );
|
|
InsertMasterPage(pHandoutMPage, 0);
|
|
pHandoutPage->TRG_SetMasterPage( *pHandoutMPage );
|
|
|
|
// Insert page
|
|
// If nPageCount==1 is, the model for the clipboard was created, thus a
|
|
// default page must already exist
|
|
SdPage* pPage;
|
|
bool bClipboard = false;
|
|
|
|
if( pRefDocument )
|
|
pRefPage = pRefDocument->GetSdPage( 0, PageKind::Standard );
|
|
|
|
if (nPageCount == 0)
|
|
{
|
|
pPage = AllocSdPage(false);
|
|
|
|
if( pRefPage )
|
|
{
|
|
pPage->SetSize( pRefPage->GetSize() );
|
|
pPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() );
|
|
}
|
|
else if (meDocType == DocumentType::Draw)
|
|
{
|
|
// Draw: always use default size with margins
|
|
pPage->SetSize(aDefSize);
|
|
|
|
SfxPrinter* pPrinter = mpDocSh->GetPrinter(false);
|
|
if (pPrinter && pPrinter->IsValid())
|
|
{
|
|
Size aOutSize(pPrinter->GetOutputSize());
|
|
Point aPageOffset(pPrinter->GetPageOffset());
|
|
aPageOffset -= pPrinter->PixelToLogic( Point() );
|
|
long nOffset = !aPageOffset.X() && !aPageOffset.Y() ? 0 : PRINT_OFFSET;
|
|
|
|
sal_uLong nTop = aPageOffset.Y();
|
|
sal_uLong nLeft = aPageOffset.X();
|
|
sal_uLong nBottom = std::max((long)(aDefSize.Height() - aOutSize.Height() - nTop + nOffset), 0L);
|
|
sal_uLong nRight = std::max((long)(aDefSize.Width() - aOutSize.Width() - nLeft + nOffset), 0L);
|
|
|
|
pPage->SetBorder(nLeft, nTop, nRight, nBottom);
|
|
}
|
|
else
|
|
{
|
|
// The printer is not available. Use a border of 10mm
|
|
// on each side instead.
|
|
// This has to be kept synchronized with the border
|
|
// width set in the
|
|
// SvxPageDescPage::PaperSizeSelect_Impl callback.
|
|
pPage->SetBorder(1000, 1000, 1000, 1000);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Impress: always use screen format, landscape.
|
|
Size aSz( SvxPaperInfo::GetPaperSize(PAPER_SCREEN_4_3, MapUnit::Map100thMM) );
|
|
pPage->SetSize( Size( aSz.Height(), aSz.Width() ) );
|
|
pPage->SetBorder(0, 0, 0, 0);
|
|
}
|
|
|
|
InsertPage(pPage, 1);
|
|
}
|
|
else
|
|
{
|
|
bClipboard = true;
|
|
pPage = static_cast<SdPage*>( GetPage(1) );
|
|
}
|
|
|
|
// Insert master page, then register this with the page
|
|
SdPage* pMPage = AllocSdPage(true);
|
|
pMPage->SetSize( pPage->GetSize() );
|
|
pMPage->SetBorder( pPage->GetLftBorder(),
|
|
pPage->GetUppBorder(),
|
|
pPage->GetRgtBorder(),
|
|
pPage->GetLwrBorder() );
|
|
InsertMasterPage(pMPage, 1);
|
|
pPage->TRG_SetMasterPage( *pMPage );
|
|
if( bClipboard )
|
|
pMPage->SetLayoutName( pPage->GetLayoutName() );
|
|
|
|
// Insert notes page
|
|
SdPage* pNotesPage = AllocSdPage(false);
|
|
|
|
if( pRefDocument )
|
|
pRefPage = pRefDocument->GetSdPage( 0, PageKind::Notes );
|
|
|
|
if( pRefPage )
|
|
{
|
|
pNotesPage->SetSize( pRefPage->GetSize() );
|
|
pNotesPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() );
|
|
}
|
|
else
|
|
{
|
|
// Always use portrait format
|
|
if (aDefSize.Height() >= aDefSize.Width())
|
|
{
|
|
pNotesPage->SetSize(aDefSize);
|
|
}
|
|
else
|
|
{
|
|
pNotesPage->SetSize( Size(aDefSize.Height(), aDefSize.Width()) );
|
|
}
|
|
|
|
pNotesPage->SetBorder(0, 0, 0, 0);
|
|
}
|
|
pNotesPage->SetPageKind(PageKind::Notes);
|
|
InsertPage(pNotesPage, 2);
|
|
if( bClipboard )
|
|
pNotesPage->SetLayoutName( pPage->GetLayoutName() );
|
|
|
|
// Insert master page, then register this with the notes page
|
|
SdPage* pNotesMPage = AllocSdPage(true);
|
|
pNotesMPage->SetSize( pNotesPage->GetSize() );
|
|
pNotesMPage->SetPageKind(PageKind::Notes);
|
|
pNotesMPage->SetBorder( pNotesPage->GetLftBorder(),
|
|
pNotesPage->GetUppBorder(),
|
|
pNotesPage->GetRgtBorder(),
|
|
pNotesPage->GetLwrBorder() );
|
|
InsertMasterPage(pNotesMPage, 2);
|
|
pNotesPage->TRG_SetMasterPage( *pNotesMPage );
|
|
if( bClipboard )
|
|
pNotesMPage->SetLayoutName( pPage->GetLayoutName() );
|
|
|
|
if( !pRefPage && (meDocType != DocumentType::Draw) )
|
|
pPage->SetAutoLayout( AUTOLAYOUT_TITLE, true, true );
|
|
|
|
mpWorkStartupTimer = new Timer("DrawWorkStartupTimer");
|
|
mpWorkStartupTimer->SetInvokeHandler( LINK(this, SdDrawDocument, WorkStartupHdl) );
|
|
mpWorkStartupTimer->SetTimeout(2000);
|
|
mpWorkStartupTimer->Start();
|
|
|
|
SetChanged(false);
|
|
}
|
|
}
|
|
|
|
// Creates missing notes and handout pages (after PowerPoint import).
|
|
// We assume that at least one default page and one default master page exist.
|
|
|
|
bool SdDrawDocument::CreateMissingNotesAndHandoutPages()
|
|
{
|
|
bool bOK = false;
|
|
sal_uInt16 nPageCount = GetPageCount();
|
|
|
|
if (nPageCount != 0)
|
|
{
|
|
// Set PageKind
|
|
SdPage* pHandoutMPage = static_cast<SdPage*>( GetMasterPage(0) );
|
|
pHandoutMPage->SetPageKind(PageKind::Handout);
|
|
|
|
SdPage* pHandoutPage = static_cast<SdPage*>( GetPage(0) );
|
|
pHandoutPage->SetPageKind(PageKind::Handout);
|
|
pHandoutPage->TRG_SetMasterPage( *pHandoutMPage );
|
|
|
|
for (sal_uInt16 i = 1; i < nPageCount; i = i + 2)
|
|
{
|
|
SdPage* pPage = static_cast<SdPage*>( GetPage(i) );
|
|
|
|
if(!pPage->TRG_HasMasterPage())
|
|
{
|
|
// No master page set -> use first default master page
|
|
// (If there was no default page in the PPT)
|
|
pPage->TRG_SetMasterPage(*GetMasterPage(1));
|
|
}
|
|
|
|
SdPage* pNotesPage = static_cast<SdPage*>( GetPage(i+1) );
|
|
pNotesPage->SetPageKind(PageKind::Notes);
|
|
|
|
// Set notes master page
|
|
sal_uInt16 nMasterPageAfterPagesMasterPage = (pPage->TRG_GetMasterPage()).GetPageNum() + 1;
|
|
pNotesPage->TRG_SetMasterPage(*GetMasterPage(nMasterPageAfterPagesMasterPage));
|
|
}
|
|
|
|
bOK = true;
|
|
StopWorkStartupDelay();
|
|
SetChanged(false);
|
|
}
|
|
|
|
return bOK;
|
|
}
|
|
|
|
void SdDrawDocument::UnselectAllPages()
|
|
{
|
|
sal_uInt16 nNoOfPages = GetSdPageCount(PageKind::Standard);
|
|
for (sal_uInt16 nPage = 0; nPage < nNoOfPages; ++nPage)
|
|
{
|
|
SdPage* pPage = GetSdPage(nPage, PageKind::Standard);
|
|
pPage->SetSelected(false);
|
|
}
|
|
}
|
|
|
|
// + Move selected pages after said page
|
|
// (nTargetPage = (sal_uInt16)-1 --> move before first page)
|
|
// + Returns sal_True when the page has been moved
|
|
bool SdDrawDocument::MovePages(sal_uInt16 nTargetPage)
|
|
{
|
|
SdPage* pPage = nullptr;
|
|
sal_uInt16 nPage;
|
|
sal_uInt16 nNoOfPages = GetSdPageCount(PageKind::Standard);
|
|
bool bSomethingHappened = false;
|
|
|
|
const bool bUndo = IsUndoEnabled();
|
|
|
|
if( bUndo )
|
|
BegUndo(SD_RESSTR(STR_UNDO_MOVEPAGES));
|
|
|
|
// List of selected pages
|
|
std::vector<SdPage*> aPageList;
|
|
for (nPage = 0; nPage < nNoOfPages; nPage++)
|
|
{
|
|
pPage = GetSdPage(nPage, PageKind::Standard);
|
|
|
|
if (pPage->IsSelected()) {
|
|
aPageList.push_back(pPage);
|
|
}
|
|
}
|
|
|
|
// If necessary, look backwards, until we find a page that wasn't selected
|
|
nPage = nTargetPage;
|
|
|
|
if (nPage != (sal_uInt16)-1)
|
|
{
|
|
pPage = GetSdPage(nPage, PageKind::Standard);
|
|
while (nPage > 0 && pPage->IsSelected())
|
|
{
|
|
nPage--;
|
|
pPage = GetSdPage(nPage, PageKind::Standard);
|
|
}
|
|
|
|
if (pPage->IsSelected())
|
|
{
|
|
nPage = (sal_uInt16)-1;
|
|
}
|
|
}
|
|
|
|
// Insert before the first page
|
|
if (nPage == (sal_uInt16)-1)
|
|
{
|
|
std::vector<SdPage*>::reverse_iterator iter;
|
|
for (iter = aPageList.rbegin(); iter != aPageList.rend(); ++iter)
|
|
{
|
|
nPage = (*iter)->GetPageNum();
|
|
if (nPage != 0)
|
|
{
|
|
SdrPage* pPg = GetPage(nPage);
|
|
if( bUndo )
|
|
AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, 1));
|
|
MovePage(nPage, 1);
|
|
pPg = GetPage(nPage+1);
|
|
if( bUndo )
|
|
AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, 2));
|
|
MovePage(nPage+1, 2);
|
|
bSomethingHappened = true;
|
|
}
|
|
}
|
|
}
|
|
// Insert after <nPage>
|
|
else
|
|
{
|
|
nTargetPage = nPage;
|
|
nTargetPage = 2 * nTargetPage + 1; // PageKind::Standard --> absolute
|
|
|
|
std::vector<SdPage*>::iterator iter;
|
|
for (iter = aPageList.begin(); iter != aPageList.end(); ++iter)
|
|
{
|
|
pPage = *iter;
|
|
nPage = pPage->GetPageNum();
|
|
if (nPage > nTargetPage)
|
|
{
|
|
nTargetPage += 2; // Insert _after_ the page
|
|
|
|
if (nPage != nTargetPage)
|
|
{
|
|
SdrPage* pPg = GetPage(nPage);
|
|
if( bUndo )
|
|
AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, nTargetPage));
|
|
MovePage(nPage, nTargetPage);
|
|
pPg = GetPage(nPage+1);
|
|
if( bUndo )
|
|
AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, nTargetPage+1));
|
|
MovePage(nPage+1, nTargetPage+1);
|
|
bSomethingHappened = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (nPage != nTargetPage)
|
|
{
|
|
SdrPage* pPg = GetPage(nPage+1);
|
|
if( bUndo )
|
|
AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, nTargetPage+1));
|
|
MovePage(nPage+1, nTargetPage+1);
|
|
pPg = GetPage(nPage);
|
|
if( bUndo )
|
|
AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, nTargetPage));
|
|
MovePage(nPage, nTargetPage);
|
|
bSomethingHappened = true;
|
|
}
|
|
}
|
|
nTargetPage = pPage->GetPageNum();
|
|
}
|
|
}
|
|
|
|
if( bUndo )
|
|
EndUndo();
|
|
|
|
return bSomethingHappened;
|
|
}
|
|
|
|
// Return number of links in sfx2::LinkManager
|
|
sal_uLong SdDrawDocument::GetLinkCount()
|
|
{
|
|
return pLinkManager->GetLinks().size();
|
|
}
|
|
|
|
// Set Language
|
|
void SdDrawDocument::SetLanguage( const LanguageType eLang, const sal_uInt16 nId )
|
|
{
|
|
bool bChanged = false;
|
|
|
|
if( nId == EE_CHAR_LANGUAGE && meLanguage != eLang )
|
|
{
|
|
meLanguage = eLang;
|
|
bChanged = true;
|
|
}
|
|
else if( nId == EE_CHAR_LANGUAGE_CJK && meLanguageCJK != eLang )
|
|
{
|
|
meLanguageCJK = eLang;
|
|
bChanged = true;
|
|
}
|
|
else if( nId == EE_CHAR_LANGUAGE_CTL && meLanguageCTL != eLang )
|
|
{
|
|
meLanguageCTL = eLang;
|
|
bChanged = true;
|
|
}
|
|
|
|
if( bChanged )
|
|
{
|
|
GetDrawOutliner().SetDefaultLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
|
|
pHitTestOutliner->SetDefaultLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
|
|
pItemPool->SetPoolDefaultItem( SvxLanguageItem( eLang, nId ) );
|
|
SetChanged( bChanged );
|
|
}
|
|
}
|
|
|
|
// Return language
|
|
LanguageType SdDrawDocument::GetLanguage( const sal_uInt16 nId ) const
|
|
{
|
|
LanguageType eLangType = meLanguage;
|
|
|
|
if( nId == EE_CHAR_LANGUAGE_CJK )
|
|
eLangType = meLanguageCJK;
|
|
else if( nId == EE_CHAR_LANGUAGE_CTL )
|
|
eLangType = meLanguageCTL;
|
|
|
|
return eLangType;
|
|
}
|
|
|
|
// Initiate WorkStartup
|
|
IMPL_LINK_NOARG(SdDrawDocument, WorkStartupHdl, Timer *, void)
|
|
{
|
|
if (IsTransportContainer())
|
|
return;
|
|
|
|
if( mpDocSh )
|
|
mpDocSh->SetWaitCursor( true );
|
|
|
|
bool bChanged = IsChanged(); // remember this
|
|
|
|
// Initialize Autolayouts
|
|
SdPage* pHandoutMPage = GetMasterSdPage(0, PageKind::Handout);
|
|
|
|
if (pHandoutMPage->GetAutoLayout() == AUTOLAYOUT_NONE)
|
|
{
|
|
// No AutoLayout yet -> initialize
|
|
pHandoutMPage->SetAutoLayout(AUTOLAYOUT_HANDOUT6, true, true);
|
|
}
|
|
|
|
SdPage* pPage = GetSdPage(0, PageKind::Standard);
|
|
|
|
if (pPage->GetAutoLayout() == AUTOLAYOUT_NONE)
|
|
{
|
|
// No AutoLayout yet -> initialize
|
|
pPage->SetAutoLayout(AUTOLAYOUT_NONE, true, true);
|
|
}
|
|
|
|
SdPage* pNotesPage = GetSdPage(0, PageKind::Notes);
|
|
|
|
if (pNotesPage->GetAutoLayout() == AUTOLAYOUT_NONE)
|
|
{
|
|
// No AutoLayout yet -> initialize
|
|
pNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true, true);
|
|
}
|
|
|
|
SetChanged(bChanged);
|
|
|
|
if( mpDocSh )
|
|
mpDocSh->SetWaitCursor( false );
|
|
}
|
|
|
|
// When the WorkStartupTimer has been created (this only happens in
|
|
// SdDrawViewShell::Construct() ), the timer may be stopped and the WorkStartup
|
|
// may be initiated.
|
|
void SdDrawDocument::StopWorkStartupDelay()
|
|
{
|
|
if (mpWorkStartupTimer)
|
|
{
|
|
if ( mpWorkStartupTimer->IsActive() )
|
|
{
|
|
// Timer not yet expired -> initiate WorkStartup
|
|
mpWorkStartupTimer->Stop();
|
|
WorkStartupHdl(nullptr);
|
|
}
|
|
|
|
delete mpWorkStartupTimer;
|
|
mpWorkStartupTimer = nullptr;
|
|
}
|
|
}
|
|
|
|
// When the WorkStartupTimer has been created (this only happens in
|
|
// SdDrawViewShell::Construct() ), the timer may be stopped and the WorkStartup
|
|
// may be initiated.
|
|
SdAnimationInfo* SdDrawDocument::GetAnimationInfo(SdrObject* pObject)
|
|
{
|
|
DBG_ASSERT(pObject, "sd::SdDrawDocument::GetAnimationInfo(), invalid argument!");
|
|
if( pObject )
|
|
return GetShapeUserData( *pObject );
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
SdAnimationInfo* SdDrawDocument::GetShapeUserData(SdrObject& rObject, bool bCreate /* = false */ )
|
|
{
|
|
sal_uInt16 nUD = 0;
|
|
sal_uInt16 nUDCount = rObject.GetUserDataCount();
|
|
SdAnimationInfo* pRet = nullptr;
|
|
|
|
// Can we find animation information within the user data?
|
|
for (nUD = 0; nUD < nUDCount; nUD++)
|
|
{
|
|
SdrObjUserData* pUD = rObject.GetUserData(nUD);
|
|
if((pUD->GetInventor() == SdrInventor::StarDrawUserData) && (pUD->GetId() == SD_ANIMATIONINFO_ID))
|
|
{
|
|
pRet = dynamic_cast<SdAnimationInfo*>(pUD);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( (pRet == nullptr) && bCreate )
|
|
{
|
|
pRet = new SdAnimationInfo( rObject );
|
|
rObject.AppendUserData( pRet);
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
SdIMapInfo* SdDrawDocument::GetIMapInfo( SdrObject* pObject )
|
|
{
|
|
DBG_ASSERT(pObject, "Without an object there is no IMapInfo");
|
|
|
|
SdIMapInfo* pIMapInfo = nullptr;
|
|
sal_uInt16 nCount = pObject->GetUserDataCount();
|
|
|
|
// Can we find IMap information within the user data?
|
|
for ( sal_uInt16 i = 0; i < nCount; i++ )
|
|
{
|
|
SdrObjUserData* pUserData = pObject->GetUserData( i );
|
|
|
|
if ( ( pUserData->GetInventor() == SdrInventor::StarDrawUserData ) && ( pUserData->GetId() == SD_IMAPINFO_ID ) )
|
|
pIMapInfo = static_cast<SdIMapInfo*>(pUserData);
|
|
}
|
|
|
|
return pIMapInfo;
|
|
}
|
|
|
|
IMapObject* SdDrawDocument::GetHitIMapObject( SdrObject* pObj,
|
|
const Point& rWinPoint )
|
|
{
|
|
SdIMapInfo* pIMapInfo = GetIMapInfo( pObj );
|
|
IMapObject* pIMapObj = nullptr;
|
|
|
|
if ( pIMapInfo )
|
|
{
|
|
const MapMode aMap100( MapUnit::Map100thMM );
|
|
Size aGraphSize;
|
|
Point aRelPoint( rWinPoint );
|
|
ImageMap& rImageMap = (ImageMap&) pIMapInfo->GetImageMap();
|
|
const Rectangle& rRect = pObj->GetLogicRect();
|
|
bool bObjSupported = false;
|
|
|
|
// execute HitTest
|
|
if ( dynamic_cast< const SdrGrafObj *>( pObj ) != nullptr ) // simple graphics object
|
|
{
|
|
const SdrGrafObj* pGrafObj = static_cast<const SdrGrafObj*>(pObj);
|
|
const GeoStat& rGeo = pGrafObj->GetGeoStat();
|
|
SdrGrafObjGeoData* pGeoData = static_cast<SdrGrafObjGeoData*>( pGrafObj->GetGeoData() );
|
|
|
|
// Undo rotation
|
|
if ( rGeo.nRotationAngle )
|
|
RotatePoint( aRelPoint, rRect.TopLeft(), -rGeo.nSin, rGeo.nCos );
|
|
|
|
// Undo mirroring
|
|
if ( pGeoData->bMirrored )
|
|
aRelPoint.X() = rRect.Right() + rRect.Left() - aRelPoint.X();
|
|
|
|
// Undo shearing
|
|
if ( rGeo.nShearAngle )
|
|
ShearPoint( aRelPoint, rRect.TopLeft(), -rGeo.nTan );
|
|
|
|
if ( pGrafObj->GetGrafPrefMapMode().GetMapUnit() == MapUnit::MapPixel )
|
|
aGraphSize = Application::GetDefaultDevice()->PixelToLogic( pGrafObj->GetGrafPrefSize(), aMap100 );
|
|
else
|
|
aGraphSize = OutputDevice::LogicToLogic( pGrafObj->GetGrafPrefSize(),
|
|
pGrafObj->GetGrafPrefMapMode(), aMap100 );
|
|
|
|
delete pGeoData;
|
|
bObjSupported = true;
|
|
}
|
|
else if ( dynamic_cast<const SdrOle2Obj* >(pObj) != nullptr ) // OLE object
|
|
{
|
|
aGraphSize = static_cast<SdrOle2Obj*>( pObj )->GetOrigObjSize();
|
|
bObjSupported = true;
|
|
}
|
|
|
|
// Everything worked out well, thus execute HitTest
|
|
if ( bObjSupported )
|
|
{
|
|
// Calculate relative position of mouse cursor
|
|
aRelPoint -= rRect.TopLeft();
|
|
pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, rRect.GetSize(), aRelPoint );
|
|
|
|
// We don't care about deactivated objects
|
|
if ( pIMapObj && !pIMapObj->IsActive() )
|
|
pIMapObj = nullptr;
|
|
}
|
|
}
|
|
|
|
return pIMapObj;
|
|
}
|
|
|
|
ImageMap* SdDrawDocument::GetImageMapForObject(SdrObject* pObj)
|
|
{
|
|
SdIMapInfo* pIMapInfo = GetIMapInfo( pObj );
|
|
if ( pIMapInfo )
|
|
{
|
|
return const_cast<ImageMap*>( &(pIMapInfo->GetImageMap()) );
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/** this method enforces that the masterpages are in the correct order,
|
|
that is at position 1 is a PageKind::Standard masterpage followed by a
|
|
PageKind::Notes masterpage and so on. #
|
|
*/
|
|
void SdDrawDocument::CheckMasterPages()
|
|
{
|
|
sal_uInt16 nMaxPages = GetMasterPageCount();
|
|
|
|
// we need at least a handout master and one master page
|
|
if( nMaxPages < 2 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SdPage* pPage = nullptr;
|
|
|
|
sal_uInt16 nPage;
|
|
|
|
// first see if the page order is correct
|
|
for( nPage = 1; nPage < nMaxPages; nPage++ )
|
|
{
|
|
pPage = static_cast<SdPage*> (GetMasterPage( nPage ));
|
|
// if an odd page is not a standard page or an even page is not a notes page
|
|
if( ((1 == (nPage & 1)) && (pPage->GetPageKind() != PageKind::Standard) ) ||
|
|
((0 == (nPage & 1)) && (pPage->GetPageKind() != PageKind::Notes) ) )
|
|
break; // then we have a fatal error
|
|
}
|
|
|
|
if( nPage < nMaxPages )
|
|
{
|
|
SdPage* pNotesPage = nullptr;
|
|
|
|
// there is a fatal error in the master page order,
|
|
// we need to repair the document
|
|
bool bChanged = false;
|
|
|
|
nPage = 1;
|
|
while( nPage < nMaxPages )
|
|
{
|
|
pPage = static_cast<SdPage*> (GetMasterPage( nPage ));
|
|
if( pPage->GetPageKind() != PageKind::Standard )
|
|
{
|
|
bChanged = true;
|
|
sal_uInt16 nFound = nPage + 1;
|
|
while( nFound < nMaxPages )
|
|
{
|
|
pPage = static_cast<SdPage*>(GetMasterPage( nFound ));
|
|
if( PageKind::Standard == pPage->GetPageKind() )
|
|
{
|
|
MoveMasterPage( nFound, nPage );
|
|
pPage->SetInserted();
|
|
break;
|
|
|
|
}
|
|
|
|
nFound++;
|
|
}
|
|
|
|
// if we don't have any more standard pages, were done
|
|
if( nMaxPages == nFound )
|
|
break;
|
|
}
|
|
|
|
nPage++;
|
|
|
|
if( nPage < nMaxPages )
|
|
pNotesPage = static_cast<SdPage*>(GetMasterPage( nPage ));
|
|
else
|
|
pNotesPage = nullptr;
|
|
|
|
if( (nullptr == pNotesPage) || (pNotesPage->GetPageKind() != PageKind::Notes) || ( pPage->GetLayoutName() != pNotesPage->GetLayoutName() ) )
|
|
{
|
|
bChanged = true;
|
|
|
|
sal_uInt16 nFound = nPage + 1;
|
|
while( nFound < nMaxPages )
|
|
{
|
|
pNotesPage = static_cast<SdPage*>(GetMasterPage( nFound ));
|
|
if( (PageKind::Notes == pNotesPage->GetPageKind()) && ( pPage->GetLayoutName() == pNotesPage->GetLayoutName() ) )
|
|
{
|
|
MoveMasterPage( nFound, nPage );
|
|
pNotesPage->SetInserted();
|
|
break;
|
|
}
|
|
|
|
nFound++;
|
|
}
|
|
|
|
// looks like we lost a notes page
|
|
if( nMaxPages == nFound )
|
|
{
|
|
// so create one
|
|
|
|
// first find a reference notes page for size
|
|
SdPage* pRefNotesPage = nullptr;
|
|
nFound = 0;
|
|
while( nFound < nMaxPages )
|
|
{
|
|
pRefNotesPage = static_cast<SdPage*>(GetMasterPage( nFound ));
|
|
if( PageKind::Notes == pRefNotesPage->GetPageKind() )
|
|
break;
|
|
nFound++;
|
|
}
|
|
if( nFound == nMaxPages )
|
|
pRefNotesPage = nullptr;
|
|
|
|
SdPage* pNewNotesPage = AllocSdPage(true);
|
|
pNewNotesPage->SetPageKind(PageKind::Notes);
|
|
if( pRefNotesPage )
|
|
{
|
|
pNewNotesPage->SetSize( pRefNotesPage->GetSize() );
|
|
pNewNotesPage->SetBorder( pRefNotesPage->GetLftBorder(),
|
|
pRefNotesPage->GetUppBorder(),
|
|
pRefNotesPage->GetRgtBorder(),
|
|
pRefNotesPage->GetLwrBorder() );
|
|
}
|
|
InsertMasterPage(pNewNotesPage, nPage );
|
|
pNewNotesPage->SetLayoutName( pPage->GetLayoutName() );
|
|
pNewNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true, true );
|
|
nMaxPages++;
|
|
}
|
|
}
|
|
|
|
nPage++;
|
|
}
|
|
|
|
// now remove all remaining and unused non PageKind::Standard slides
|
|
while( nPage < nMaxPages )
|
|
{
|
|
bChanged = true;
|
|
|
|
RemoveMasterPage( nPage );
|
|
nMaxPages--;
|
|
}
|
|
|
|
if( bChanged )
|
|
{
|
|
OSL_FAIL( "master pages where in a wrong order" );
|
|
RecalcPageNums( true);
|
|
}
|
|
}
|
|
}
|
|
|
|
sal_uInt16 SdDrawDocument::CreatePage (
|
|
SdPage* pActualPage,
|
|
PageKind ePageKind,
|
|
const OUString& sStandardPageName,
|
|
const OUString& sNotesPageName,
|
|
AutoLayout eStandardLayout,
|
|
AutoLayout eNotesLayout,
|
|
bool bIsPageBack,
|
|
bool bIsPageObj,
|
|
const sal_Int32 nInsertPosition)
|
|
{
|
|
SdPage* pPreviousStandardPage;
|
|
SdPage* pPreviousNotesPage;
|
|
SdPage* pStandardPage;
|
|
SdPage* pNotesPage;
|
|
|
|
// From the given page determine the standard page and notes page of which
|
|
// to take the layout and the position where to insert the new pages.
|
|
if (ePageKind == PageKind::Notes)
|
|
{
|
|
pPreviousNotesPage = pActualPage;
|
|
sal_uInt16 nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
|
|
pPreviousStandardPage = static_cast<SdPage*>( GetPage(nNotesPageNum - 3) );
|
|
eStandardLayout = pPreviousStandardPage->GetAutoLayout();
|
|
}
|
|
else
|
|
{
|
|
pPreviousStandardPage = pActualPage;
|
|
sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
|
|
pPreviousNotesPage = static_cast<SdPage*>( GetPage(nStandardPageNum - 1) );
|
|
eNotesLayout = pPreviousNotesPage->GetAutoLayout();
|
|
}
|
|
|
|
// Create new standard page and set it up
|
|
pStandardPage = AllocSdPage(false);
|
|
|
|
// Set the size here since else the presobj autolayout
|
|
// will be wrong.
|
|
pStandardPage->SetSize( pPreviousStandardPage->GetSize() );
|
|
pStandardPage->SetBorder( pPreviousStandardPage->GetLftBorder(),
|
|
pPreviousStandardPage->GetUppBorder(),
|
|
pPreviousStandardPage->GetRgtBorder(),
|
|
pPreviousStandardPage->GetLwrBorder() );
|
|
|
|
// Use master page of current page.
|
|
pStandardPage->TRG_SetMasterPage(pPreviousStandardPage->TRG_GetMasterPage());
|
|
|
|
// User layout of current standard page
|
|
pStandardPage->SetLayoutName( pPreviousStandardPage->GetLayoutName() );
|
|
pStandardPage->SetAutoLayout(eStandardLayout, true);
|
|
pStandardPage->setHeaderFooterSettings( pPreviousStandardPage->getHeaderFooterSettings() );
|
|
|
|
// transition settings of current page
|
|
pStandardPage->setTransitionType( pPreviousStandardPage->getTransitionType() );
|
|
pStandardPage->setTransitionSubtype( pPreviousStandardPage->getTransitionSubtype() );
|
|
pStandardPage->setTransitionDirection( pPreviousStandardPage->getTransitionDirection() );
|
|
pStandardPage->setTransitionFadeColor( pPreviousStandardPage->getTransitionFadeColor() );
|
|
pStandardPage->setTransitionDuration( pPreviousStandardPage->getTransitionDuration() );
|
|
|
|
// apply previous animation timing
|
|
pStandardPage->SetPresChange( pPreviousStandardPage->GetPresChange() );
|
|
pStandardPage->SetTime( pPreviousStandardPage->GetTime() );
|
|
|
|
// Create new notes page and set it up
|
|
pNotesPage = AllocSdPage(false);
|
|
pNotesPage->SetPageKind(PageKind::Notes);
|
|
|
|
// Use master page of current page
|
|
pNotesPage->TRG_SetMasterPage(pPreviousNotesPage->TRG_GetMasterPage());
|
|
|
|
// Use layout of current notes page
|
|
pNotesPage->SetLayoutName( pPreviousNotesPage->GetLayoutName() );
|
|
pNotesPage->SetAutoLayout(eNotesLayout, true);
|
|
pNotesPage->setHeaderFooterSettings( pPreviousNotesPage->getHeaderFooterSettings() );
|
|
|
|
return InsertPageSet (
|
|
pActualPage,
|
|
ePageKind,
|
|
sStandardPageName,
|
|
sNotesPageName,
|
|
bIsPageBack,
|
|
bIsPageObj,
|
|
pStandardPage,
|
|
pNotesPage,
|
|
nInsertPosition);
|
|
}
|
|
|
|
sal_uInt16 SdDrawDocument::DuplicatePage (sal_uInt16 nPageNum)
|
|
{
|
|
PageKind ePageKind = PageKind::Standard;
|
|
|
|
// Get current page
|
|
SdPage* pActualPage = GetSdPage(nPageNum, ePageKind);
|
|
|
|
// Get background flags
|
|
SdrLayerAdmin& rLayerAdmin = GetLayerAdmin();
|
|
sal_uInt8 aBckgrnd = rLayerAdmin.GetLayerID(SD_RESSTR(STR_LAYER_BCKGRND), false);
|
|
sal_uInt8 aBckgrndObj = rLayerAdmin.GetLayerID(SD_RESSTR(STR_LAYER_BCKGRNDOBJ), false);
|
|
SetOfByte aVisibleLayers = pActualPage->TRG_GetMasterPageVisibleLayers();
|
|
|
|
return DuplicatePage (
|
|
pActualPage, ePageKind,
|
|
// No names for the new slides
|
|
OUString(), OUString(),
|
|
aVisibleLayers.IsSet(aBckgrnd),
|
|
aVisibleLayers.IsSet(aBckgrndObj), -1);
|
|
}
|
|
|
|
sal_uInt16 SdDrawDocument::DuplicatePage (
|
|
SdPage* pActualPage,
|
|
PageKind ePageKind,
|
|
const OUString& sStandardPageName,
|
|
const OUString& sNotesPageName,
|
|
bool bIsPageBack,
|
|
bool bIsPageObj,
|
|
const sal_Int32 nInsertPosition)
|
|
{
|
|
SdPage* pPreviousStandardPage;
|
|
SdPage* pPreviousNotesPage;
|
|
SdPage* pStandardPage;
|
|
SdPage* pNotesPage;
|
|
|
|
// From the given page determine the standard page and the notes page
|
|
// of which to make copies.
|
|
if (ePageKind == PageKind::Notes)
|
|
{
|
|
pPreviousNotesPage = pActualPage;
|
|
sal_uInt16 nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
|
|
pPreviousStandardPage = static_cast<SdPage*>( GetPage(nNotesPageNum - 3) );
|
|
}
|
|
else
|
|
{
|
|
pPreviousStandardPage = pActualPage;
|
|
sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
|
|
pPreviousNotesPage = static_cast<SdPage*>( GetPage(nStandardPageNum - 1) );
|
|
}
|
|
|
|
// Create duplicates of a standard page and the associated notes page
|
|
pStandardPage = static_cast<SdPage*>( pPreviousStandardPage->Clone() );
|
|
pNotesPage = static_cast<SdPage*>( pPreviousNotesPage->Clone() );
|
|
|
|
return InsertPageSet (
|
|
pActualPage,
|
|
ePageKind,
|
|
sStandardPageName,
|
|
sNotesPageName,
|
|
bIsPageBack,
|
|
bIsPageObj,
|
|
pStandardPage,
|
|
pNotesPage,
|
|
nInsertPosition);
|
|
}
|
|
|
|
sal_uInt16 SdDrawDocument::InsertPageSet (
|
|
SdPage* pActualPage,
|
|
PageKind ePageKind,
|
|
const OUString& sStandardPageName,
|
|
const OUString& sNotesPageName,
|
|
bool bIsPageBack,
|
|
bool bIsPageObj,
|
|
SdPage* pStandardPage,
|
|
SdPage* pNotesPage,
|
|
sal_Int32 nInsertPosition)
|
|
{
|
|
SdPage* pPreviousStandardPage;
|
|
SdPage* pPreviousNotesPage;
|
|
sal_uInt16 nStandardPageNum;
|
|
sal_uInt16 nNotesPageNum;
|
|
OUString aNotesPageName(sNotesPageName);
|
|
|
|
// Gather some information about the standard page and the notes page
|
|
// that are to be inserted. This makes sure that there is always one
|
|
// standard page followed by one notes page.
|
|
if (ePageKind == PageKind::Notes)
|
|
{
|
|
pPreviousNotesPage = pActualPage;
|
|
nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2;
|
|
pPreviousStandardPage = static_cast<SdPage*>( GetPage(nNotesPageNum - 3) );
|
|
nStandardPageNum = nNotesPageNum - 1;
|
|
}
|
|
else
|
|
{
|
|
pPreviousStandardPage = pActualPage;
|
|
nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2;
|
|
pPreviousNotesPage = static_cast<SdPage*>( GetPage(nStandardPageNum - 1) );
|
|
nNotesPageNum = nStandardPageNum + 1;
|
|
aNotesPageName = sStandardPageName;
|
|
}
|
|
|
|
OSL_ASSERT(nNotesPageNum==nStandardPageNum+1);
|
|
if (nInsertPosition < 0)
|
|
nInsertPosition = nStandardPageNum;
|
|
|
|
// Set up and insert the standard page
|
|
SetupNewPage (
|
|
pPreviousStandardPage,
|
|
pStandardPage,
|
|
sStandardPageName,
|
|
nInsertPosition,
|
|
bIsPageBack,
|
|
bIsPageObj);
|
|
|
|
// Set up and insert the notes page
|
|
pNotesPage->SetPageKind(PageKind::Notes);
|
|
SetupNewPage (
|
|
pPreviousNotesPage,
|
|
pNotesPage,
|
|
aNotesPageName,
|
|
nInsertPosition+1,
|
|
bIsPageBack,
|
|
bIsPageObj);
|
|
|
|
// Return an index that allows the caller to access the newly inserted
|
|
// pages by using GetSdPage()
|
|
return pStandardPage->GetPageNum() / 2;
|
|
}
|
|
|
|
void SdDrawDocument::SetupNewPage (
|
|
SdPage* pPreviousPage,
|
|
SdPage* pPage,
|
|
const OUString& sPageName,
|
|
sal_uInt16 nInsertionPoint,
|
|
bool bIsPageBack,
|
|
bool bIsPageObj)
|
|
{
|
|
if (pPreviousPage != nullptr)
|
|
{
|
|
pPage->SetSize( pPreviousPage->GetSize() );
|
|
pPage->SetBorder( pPreviousPage->GetLftBorder(),
|
|
pPreviousPage->GetUppBorder(),
|
|
pPreviousPage->GetRgtBorder(),
|
|
pPreviousPage->GetLwrBorder() );
|
|
}
|
|
pPage->SetName(sPageName);
|
|
|
|
InsertPage(pPage, nInsertionPoint);
|
|
|
|
if (pPreviousPage != nullptr)
|
|
{
|
|
SdrLayerAdmin& rLayerAdmin = GetLayerAdmin();
|
|
sal_uInt8 aBckgrnd = rLayerAdmin.GetLayerID(SD_RESSTR(STR_LAYER_BCKGRND), false);
|
|
sal_uInt8 aBckgrndObj = rLayerAdmin.GetLayerID(SD_RESSTR(STR_LAYER_BCKGRNDOBJ), false);
|
|
SetOfByte aVisibleLayers = pPreviousPage->TRG_GetMasterPageVisibleLayers();
|
|
aVisibleLayers.Set(aBckgrnd, bIsPageBack);
|
|
aVisibleLayers.Set(aBckgrndObj, bIsPageObj);
|
|
pPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
|
|
}
|
|
}
|
|
|
|
sd::UndoManager* SdDrawDocument::GetUndoManager() const
|
|
{
|
|
return mpDocSh ? dynamic_cast< sd::UndoManager* >(mpDocSh->GetUndoManager()) : nullptr;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|