diff options
Diffstat (limited to '')
-rw-r--r-- | sd/source/ui/unoidl/unomodel.cxx | 3491 |
1 files changed, 3491 insertions, 0 deletions
diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx new file mode 100644 index 000000000..758ce1380 --- /dev/null +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -0,0 +1,3491 @@ +/* -*- 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 <memory> + +#include <com/sun/star/presentation/XPresentation2.hpp> + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/document/IndexedPropertyValues.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <com/sun/star/embed/Aspects.hpp> + +#include <officecfg/Office/Common.hxx> +#include <comphelper/indexedpropertyvalues.hxx> +#include <comphelper/lok.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/profilezone.hxx> + +#include <sal/log.hxx> +#include <editeng/unofield.hxx> +#include <notifydocumentevent.hxx> +#include <tpaction.hxx> +#include <unomodel.hxx> +#include "unopool.hxx" +#include <sfx2/lokhelper.hxx> +#include <sfx2/dispatch.hxx> +#include <vcl/svapp.hxx> +#include <LibreOfficeKit/LibreOfficeKitEnums.h> + +#include <editeng/UnoForbiddenCharsTable.hxx> +#include <svx/svdoutl.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <o3tl/unit_conversion.hxx> +#include <svx/UnoNamespaceMap.hxx> +#include <svx/svdlayer.hxx> +#include <svx/svdsob.hxx> +#include <svx/svdundo.hxx> +#include <svx/unoapi.hxx> +#include <svx/unofill.hxx> +#include <svx/sdrpagewindow.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <editeng/fontitem.hxx> +#include <toolkit/awt/vclxdevice.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdpagv.hxx> +#include <svtools/unoimap.hxx> +#include <svtools/slidesorterbaropt.hxx> +#include <svx/unoshape.hxx> +#include <editeng/unonrule.hxx> +#include <editeng/eeitem.hxx> +#include <unotools/datetime.hxx> +#include <xmloff/autolayout.hxx> + +// Support creation of GraphicStorageHandler and EmbeddedObjectResolver +#include <svx/xmleohlp.hxx> +#include <svx/xmlgrhlp.hxx> +#include <DrawDocShell.hxx> +#include <ViewShellBase.hxx> +#include "UnoDocumentSettings.hxx" + +#include <Annotation.hxx> +#include <drawdoc.hxx> +#include <sdmod.hxx> +#include <sdresid.hxx> +#include <sdpage.hxx> + +#include <strings.hrc> +#include <strings.hxx> +#include "unolayer.hxx" +#include <unopage.hxx> +#include "unocpres.hxx" +#include "unoobj.hxx" +#include <stlpool.hxx> +#include "unopback.hxx" +#include <unokywds.hxx> + +#include <FrameView.hxx> +#include <ClientView.hxx> +#include <DrawViewShell.hxx> +#include <ViewShell.hxx> +#include <Window.hxx> +#include <optsitem.hxx> + +#include <vcl/pdfextoutdevdata.hxx> +#include <com/sun/star/presentation/AnimationSpeed.hpp> +#include <com/sun/star/presentation/ClickAction.hpp> +#include <svx/sdr/contact/viewobjectcontact.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/sdr/contact/displayinfo.hxx> + +#include <com/sun/star/office/XAnnotation.hpp> +#include <com/sun/star/office/XAnnotationAccess.hpp> +#include <com/sun/star/office/XAnnotationEnumeration.hpp> +#include <com/sun/star/geometry/RealPoint2D.hpp> +#include <com/sun/star/util/DateTime.hpp> + +#include <drawinglayer/primitive2d/structuretagprimitive2d.hxx> + +#include <sfx2/lokcomponenthelpers.hxx> +#include <tools/gen.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <tools/json_writer.hxx> +#include <tools/UnitConversion.hxx> +#include <svx/ColorSets.hxx> + +#include <app.hrc> + +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::sd; + +TranslateId SdTPAction::GetClickActionSdResId( presentation::ClickAction eCA ) +{ + switch( eCA ) + { + case presentation::ClickAction_NONE: return STR_CLICK_ACTION_NONE; + case presentation::ClickAction_PREVPAGE: return STR_CLICK_ACTION_PREVPAGE; + case presentation::ClickAction_NEXTPAGE: return STR_CLICK_ACTION_NEXTPAGE; + case presentation::ClickAction_FIRSTPAGE: return STR_CLICK_ACTION_FIRSTPAGE; + case presentation::ClickAction_LASTPAGE: return STR_CLICK_ACTION_LASTPAGE; + case presentation::ClickAction_BOOKMARK: return STR_CLICK_ACTION_BOOKMARK; + case presentation::ClickAction_DOCUMENT: return STR_CLICK_ACTION_DOCUMENT; + case presentation::ClickAction_PROGRAM: return STR_CLICK_ACTION_PROGRAM; + case presentation::ClickAction_MACRO: return STR_CLICK_ACTION_MACRO; + case presentation::ClickAction_SOUND: return STR_CLICK_ACTION_SOUND; + case presentation::ClickAction_VERB: return STR_CLICK_ACTION_VERB; + case presentation::ClickAction_STOPPRESENTATION: return STR_CLICK_ACTION_STOPPRESENTATION; + default: OSL_FAIL( "No StringResource for ClickAction available!" ); + } + return {}; +} + +namespace { + +class SdUnoForbiddenCharsTable : public SvxUnoForbiddenCharsTable, + public SfxListener +{ +public: + explicit SdUnoForbiddenCharsTable(SdrModel* pModel); + virtual ~SdUnoForbiddenCharsTable() override; + + // SfxListener + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) noexcept override; +protected: + virtual void onChange() override; + +private: + SdrModel* mpModel; +}; + +} + +SdUnoForbiddenCharsTable::SdUnoForbiddenCharsTable( SdrModel* pModel ) +: SvxUnoForbiddenCharsTable( pModel->GetForbiddenCharsTable() ), mpModel( pModel ) +{ + StartListening( *pModel ); +} + +void SdUnoForbiddenCharsTable::onChange() +{ + if( mpModel ) + { + mpModel->ReformatAllTextObjects(); + } +} + +SdUnoForbiddenCharsTable::~SdUnoForbiddenCharsTable() +{ + SolarMutexGuard g; + + if( mpModel ) + EndListening( *mpModel ); +} + +void SdUnoForbiddenCharsTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept +{ + if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint) + return; + const SdrHint* pSdrHint = static_cast<const SdrHint*>( &rHint ); + if( SdrHintKind::ModelCleared == pSdrHint->GetKind() ) + { + mpModel = nullptr; + } +} + +const sal_uInt16 WID_MODEL_LANGUAGE = 1; +const sal_uInt16 WID_MODEL_TABSTOP = 2; +const sal_uInt16 WID_MODEL_VISAREA = 3; +const sal_uInt16 WID_MODEL_MAPUNIT = 4; +const sal_uInt16 WID_MODEL_FORBCHARS = 5; +const sal_uInt16 WID_MODEL_CONTFOCUS = 6; +const sal_uInt16 WID_MODEL_DSGNMODE = 7; +const sal_uInt16 WID_MODEL_BASICLIBS = 8; +const sal_uInt16 WID_MODEL_RUNTIMEUID = 9; +const sal_uInt16 WID_MODEL_BUILDID = 10; +const sal_uInt16 WID_MODEL_HASVALIDSIGNATURES = 11; +const sal_uInt16 WID_MODEL_DIALOGLIBS = 12; +const sal_uInt16 WID_MODEL_FONTS = 13; +const sal_uInt16 WID_MODEL_INTEROPGRABBAG = 14; +const sal_uInt16 WID_MODEL_THEME = 15; + +static const SvxItemPropertySet* ImplGetDrawModelPropertySet() +{ + // Attention: the first parameter HAS TO BE sorted!!! + const static SfxItemPropertyMapEntry aDrawModelPropertyMap_Impl[] = + { + { u"BuildId", WID_MODEL_BUILDID, ::cppu::UnoType<OUString>::get(), 0, 0}, + { sUNO_Prop_CharLocale, WID_MODEL_LANGUAGE, ::cppu::UnoType<lang::Locale>::get(), 0, 0}, + { sUNO_Prop_TabStop, WID_MODEL_TABSTOP, ::cppu::UnoType<sal_Int32>::get(), 0, 0}, + { sUNO_Prop_VisibleArea, WID_MODEL_VISAREA, ::cppu::UnoType<awt::Rectangle>::get(), 0, 0}, + { sUNO_Prop_MapUnit, WID_MODEL_MAPUNIT, ::cppu::UnoType<sal_Int16>::get(), beans::PropertyAttribute::READONLY, 0}, + { sUNO_Prop_ForbiddenCharacters, WID_MODEL_FORBCHARS, cppu::UnoType<i18n::XForbiddenCharacters>::get(), beans::PropertyAttribute::READONLY, 0}, + { sUNO_Prop_AutomContFocus, WID_MODEL_CONTFOCUS, cppu::UnoType<bool>::get(), 0, 0}, + { sUNO_Prop_ApplyFrmDsgnMode, WID_MODEL_DSGNMODE, cppu::UnoType<bool>::get(), 0, 0}, + { u"BasicLibraries", WID_MODEL_BASICLIBS, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0}, + { u"DialogLibraries", WID_MODEL_DIALOGLIBS, cppu::UnoType<script::XLibraryContainer>::get(), beans::PropertyAttribute::READONLY, 0}, + { sUNO_Prop_RuntimeUID, WID_MODEL_RUNTIMEUID, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0}, + { sUNO_Prop_HasValidSignatures, WID_MODEL_HASVALIDSIGNATURES, ::cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::READONLY, 0}, + { u"Fonts", WID_MODEL_FONTS, cppu::UnoType<uno::Sequence<uno::Any>>::get(), beans::PropertyAttribute::READONLY, 0}, + { sUNO_Prop_InteropGrabBag, WID_MODEL_INTEROPGRABBAG, cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get(), 0, 0}, + { sUNO_Prop_Theme, WID_MODEL_THEME, cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get(), 0, 0}, + { u"", 0, css::uno::Type(), 0, 0 } + }; + static SvxItemPropertySet aDrawModelPropertySet_Impl( aDrawModelPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() ); + return &aDrawModelPropertySet_Impl; +} + +// this ctor is used from the DocShell +SdXImpressDocument::SdXImpressDocument(::sd::DrawDocShell* pShell, bool bClipBoard) +: SfxBaseModel( pShell ), + mpDocShell( pShell ), + mpDoc( pShell ? pShell->GetDoc() : nullptr ), + mbDisposed(false), + mbImpressDoc( pShell && pShell->GetDoc() && pShell->GetDoc()->GetDocumentType() == DocumentType::Impress ), + mbClipBoard( bClipBoard ), + mpPropSet( ImplGetDrawModelPropertySet() ) +{ + if( mpDoc ) + { + StartListening( *mpDoc ); + } + else + { + OSL_FAIL("DocShell is invalid"); + } +} + +SdXImpressDocument::SdXImpressDocument(SdDrawDocument* pDoc, bool bClipBoard) +: SfxBaseModel( nullptr ), + mpDocShell( nullptr ), + mpDoc( pDoc ), + mbDisposed(false), + mbImpressDoc( pDoc && pDoc->GetDocumentType() == DocumentType::Impress ), + mbClipBoard( bClipBoard ), + mpPropSet( ImplGetDrawModelPropertySet() ) +{ + if( mpDoc ) + { + StartListening( *mpDoc ); + } + else + { + OSL_FAIL("SdDrawDocument is invalid"); + } +} + +/*********************************************************************** +* * +***********************************************************************/ +SdXImpressDocument::~SdXImpressDocument() noexcept +{ +} + +// XInterface +uno::Any SAL_CALL SdXImpressDocument::queryInterface( const uno::Type & rType ) +{ + uno::Any aAny; + + if (rType == cppu::UnoType<lang::XServiceInfo>::get()) + aAny <<= uno::Reference<lang::XServiceInfo>(this); + else if (rType == cppu::UnoType<beans::XPropertySet>::get()) + aAny <<= uno::Reference<beans::XPropertySet>(this); + else if (rType == cppu::UnoType<lang::XMultiServiceFactory>::get()) + aAny <<= uno::Reference<lang::XMultiServiceFactory>(this); + else if (rType == cppu::UnoType<drawing::XDrawPageDuplicator>::get()) + aAny <<= uno::Reference<drawing::XDrawPageDuplicator>(this); + else if (rType == cppu::UnoType<drawing::XLayerSupplier>::get()) + aAny <<= uno::Reference<drawing::XLayerSupplier>(this); + else if (rType == cppu::UnoType<drawing::XMasterPagesSupplier>::get()) + aAny <<= uno::Reference<drawing::XMasterPagesSupplier>(this); + else if (rType == cppu::UnoType<drawing::XDrawPagesSupplier>::get()) + aAny <<= uno::Reference<drawing::XDrawPagesSupplier>(this); + else if (rType == cppu::UnoType<presentation::XHandoutMasterSupplier>::get()) + aAny <<= uno::Reference<presentation::XHandoutMasterSupplier>(this); + else if (rType == cppu::UnoType<document::XLinkTargetSupplier>::get()) + aAny <<= uno::Reference<document::XLinkTargetSupplier>(this); + else if (rType == cppu::UnoType<style::XStyleFamiliesSupplier>::get()) + aAny <<= uno::Reference<style::XStyleFamiliesSupplier>(this); + else if (rType == cppu::UnoType<css::ucb::XAnyCompareFactory>::get()) + aAny <<= uno::Reference<css::ucb::XAnyCompareFactory>(this); + else if (rType == cppu::UnoType<view::XRenderable>::get()) + aAny <<= uno::Reference<view::XRenderable>(this); + else if (mbImpressDoc && rType == cppu::UnoType<presentation::XPresentationSupplier>::get()) + aAny <<= uno::Reference< presentation::XPresentationSupplier >(this); + else if (mbImpressDoc && rType == cppu::UnoType<presentation::XCustomPresentationSupplier>::get()) + aAny <<= uno::Reference< presentation::XCustomPresentationSupplier >(this); + else + return SfxBaseModel::queryInterface(rType); + + return aAny; +} + +void SAL_CALL SdXImpressDocument::acquire() noexcept +{ + SfxBaseModel::acquire(); +} + +void SAL_CALL SdXImpressDocument::release() noexcept +{ + if (osl_atomic_decrement( &m_refCount ) != 0) + return; + + // restore reference count: + osl_atomic_increment( &m_refCount ); + if(!mbDisposed) + { + try + { + dispose(); + } + catch (const uno::RuntimeException&) + { + // don't break throw () + TOOLS_WARN_EXCEPTION( "sd", "" ); + } + } + SfxBaseModel::release(); +} + +// XUnoTunnel +const css::uno::Sequence< sal_Int8 > & SdXImpressDocument::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theSdXImpressDocumentUnoTunnelId; + return theSdXImpressDocumentUnoTunnelId.getSeq(); +} + +sal_Int64 SAL_CALL SdXImpressDocument::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier ) +{ + if (comphelper::isUnoTunnelId<SdrModel>(rIdentifier)) + return comphelper::getSomething_cast(mpDoc); + + return comphelper::getSomethingImpl(rIdentifier, this, + comphelper::FallbackToGetSomethingOf<SfxBaseModel>{}); +} + +// XTypeProvider +uno::Sequence< uno::Type > SAL_CALL SdXImpressDocument::getTypes( ) +{ + ::SolarMutexGuard aGuard; + + if( !maTypeSequence.hasElements() ) + { + uno::Sequence< uno::Type > aTypes( SfxBaseModel::getTypes() ); + aTypes = comphelper::concatSequences(aTypes, + uno::Sequence { + cppu::UnoType<beans::XPropertySet>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XMultiServiceFactory>::get(), + cppu::UnoType<drawing::XDrawPageDuplicator>::get(), + cppu::UnoType<drawing::XLayerSupplier>::get(), + cppu::UnoType<drawing::XMasterPagesSupplier>::get(), + cppu::UnoType<drawing::XDrawPagesSupplier>::get(), + cppu::UnoType<document::XLinkTargetSupplier>::get(), + cppu::UnoType<style::XStyleFamiliesSupplier>::get(), + cppu::UnoType<css::ucb::XAnyCompareFactory>::get(), + cppu::UnoType<view::XRenderable>::get() }); + if( mbImpressDoc ) + { + aTypes = comphelper::concatSequences(aTypes, + uno::Sequence { + cppu::UnoType<presentation::XPresentationSupplier>::get(), + cppu::UnoType<presentation::XCustomPresentationSupplier>::get(), + cppu::UnoType<presentation::XHandoutMasterSupplier>::get() }); + } + maTypeSequence = aTypes; + } + + return maTypeSequence; +} + +uno::Sequence< sal_Int8 > SAL_CALL SdXImpressDocument::getImplementationId( ) +{ + return css::uno::Sequence<sal_Int8>(); +} + +/*********************************************************************** +* * +***********************************************************************/ +void SdXImpressDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if( mpDoc ) + { + if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint) + { + const SdrHint* pSdrHint = static_cast<const SdrHint*>( &rHint ); + if( hasEventListeners() ) + { + document::EventObject aEvent; + if( SvxUnoDrawMSFactory::createEvent( mpDoc, pSdrHint, aEvent ) ) + notifyEvent( aEvent ); + } + + if( pSdrHint->GetKind() == SdrHintKind::ModelCleared ) + { + if( mpDoc ) + EndListening( *mpDoc ); + mpDoc = nullptr; + mpDocShell = nullptr; + } + } + else + { + // did our SdDrawDocument just died? + if(rHint.GetId() == SfxHintId::Dying) + { + // yes, so we ask for a new one + if( mpDocShell ) + { + SdDrawDocument *pNewDoc = mpDocShell->GetDoc(); + + // is there a new one? + if( pNewDoc != mpDoc ) + { + mpDoc = pNewDoc; + if(mpDoc) + StartListening( *mpDoc ); + } + } + } + } + } + SfxBaseModel::Notify( rBC, rHint ); +} + +/****************************************************************************** +* * +******************************************************************************/ +SdPage* SdXImpressDocument::InsertSdPage( sal_uInt16 nPage, bool bDuplicate ) +{ + sal_uInt16 nPageCount = mpDoc->GetSdPageCount( PageKind::Standard ); + SdrLayerAdmin& rLayerAdmin = mpDoc->GetLayerAdmin(); + SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background); + SdrLayerID aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects); + + rtl::Reference<SdPage> pStandardPage; + + if( 0 == nPageCount ) + { + // this is only used for clipboard where we only have one page + pStandardPage = mpDoc->AllocSdPage(false); + + Size aDefSize(21000, 29700); // A4 portrait orientation + pStandardPage->SetSize( aDefSize ); + mpDoc->InsertPage(pStandardPage.get(), 0); + } + else + { + // here we determine the page after which we should insert + SdPage* pPreviousStandardPage = mpDoc->GetSdPage( std::min( static_cast<sal_uInt16>(nPageCount - 1), nPage ), PageKind::Standard ); + SdrLayerIDSet aVisibleLayers = pPreviousStandardPage->TRG_GetMasterPageVisibleLayers(); + bool bIsPageBack = aVisibleLayers.IsSet( aBckgrnd ); + bool bIsPageObj = aVisibleLayers.IsSet( aBckgrndObj ); + + // AutoLayouts must be ready + mpDoc->StopWorkStartupDelay(); + + /* First we create a standard page and then a notes page. It is + guaranteed, that after a standard page the corresponding notes page + follows. */ + + sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2; + SdPage* pPreviousNotesPage = static_cast<SdPage*>( mpDoc->GetPage( nStandardPageNum - 1 ) ); + sal_uInt16 nNotesPageNum = nStandardPageNum + 1; + + /************************************************************** + * standard page + **************************************************************/ + if( bDuplicate ) + pStandardPage = static_cast<SdPage*>( pPreviousStandardPage->CloneSdrPage(*mpDoc).get() ); + else + pStandardPage = mpDoc->AllocSdPage(false); + + pStandardPage->SetSize( pPreviousStandardPage->GetSize() ); + pStandardPage->SetBorder( pPreviousStandardPage->GetLeftBorder(), + pPreviousStandardPage->GetUpperBorder(), + pPreviousStandardPage->GetRightBorder(), + pPreviousStandardPage->GetLowerBorder() ); + pStandardPage->SetOrientation( pPreviousStandardPage->GetOrientation() ); + pStandardPage->SetName(OUString()); + + // insert page after current page + mpDoc->InsertPage(pStandardPage.get(), nStandardPageNum); + + if( !bDuplicate ) + { + // use MasterPage of the current page + pStandardPage->TRG_SetMasterPage(pPreviousStandardPage->TRG_GetMasterPage()); + pStandardPage->SetLayoutName( pPreviousStandardPage->GetLayoutName() ); + pStandardPage->SetAutoLayout(AUTOLAYOUT_NONE, true ); + } + + aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background); + aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects); + aVisibleLayers.Set(aBckgrnd, bIsPageBack); + aVisibleLayers.Set(aBckgrndObj, bIsPageObj); + pStandardPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers); + + /************************************************************** + * notes page + **************************************************************/ + rtl::Reference<SdPage> pNotesPage; + + if( bDuplicate ) + pNotesPage = static_cast<SdPage*>( pPreviousNotesPage->CloneSdrPage(*mpDoc).get() ); + else + pNotesPage = mpDoc->AllocSdPage(false); + + pNotesPage->SetSize( pPreviousNotesPage->GetSize() ); + pNotesPage->SetBorder( pPreviousNotesPage->GetLeftBorder(), + pPreviousNotesPage->GetUpperBorder(), + pPreviousNotesPage->GetRightBorder(), + pPreviousNotesPage->GetLowerBorder() ); + pNotesPage->SetOrientation( pPreviousNotesPage->GetOrientation() ); + pNotesPage->SetName(OUString()); + pNotesPage->SetPageKind(PageKind::Notes); + + // insert page after current page + mpDoc->InsertPage(pNotesPage.get(), nNotesPageNum); + + if( !bDuplicate ) + { + // use MasterPage of the current page + pNotesPage->TRG_SetMasterPage(pPreviousNotesPage->TRG_GetMasterPage()); + pNotesPage->SetLayoutName( pPreviousNotesPage->GetLayoutName() ); + pNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true ); + } + } + + SetModified(); + + return pStandardPage.get(); +} + +void SdXImpressDocument::SetModified() noexcept +{ + if( mpDoc ) + mpDoc->SetChanged(); +} + +// XModel +void SAL_CALL SdXImpressDocument::lockControllers( ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + mpDoc->setLock(true); +} + +void SAL_CALL SdXImpressDocument::unlockControllers( ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + if( mpDoc->isLocked() ) + { + mpDoc->setLock(false); + } +} + +sal_Bool SAL_CALL SdXImpressDocument::hasControllersLocked( ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + return mpDoc->isLocked(); +} + +uno::Reference < container::XIndexAccess > SAL_CALL SdXImpressDocument::getViewData() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() ); + + if( !xRet.is() ) + { + const std::vector<std::unique_ptr<sd::FrameView>> &rList = mpDoc->GetFrameViewList(); + + if( !rList.empty() ) + { + xRet = new comphelper::IndexedPropertyValuesContainer(); + + uno::Reference < container::XIndexContainer > xCont( xRet, uno::UNO_QUERY ); + DBG_ASSERT( xCont.is(), "SdXImpressDocument::getViewData() failed for OLE object" ); + if( xCont.is() ) + { + for( sal_uInt32 i = 0, n = rList.size(); i < n; i++ ) + { + ::sd::FrameView* pFrameView = rList[ i ].get(); + + uno::Sequence< beans::PropertyValue > aSeq; + pFrameView->WriteUserDataSequence( aSeq ); + xCont->insertByIndex( i, uno::Any( aSeq ) ); + } + } + } + } + + return xRet; +} + +void SAL_CALL SdXImpressDocument::setViewData( const uno::Reference < container::XIndexAccess >& xData ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + SfxBaseModel::setViewData( xData ); + if( !(mpDocShell && (mpDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED) && xData.is()) ) + return; + + const sal_Int32 nCount = xData->getCount(); + + std::vector<std::unique_ptr<sd::FrameView>> &rViews = mpDoc->GetFrameViewList(); + + rViews.clear(); + + uno::Sequence< beans::PropertyValue > aSeq; + for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + if( xData->getByIndex( nIndex ) >>= aSeq ) + { + std::unique_ptr<::sd::FrameView> pFrameView(new ::sd::FrameView( mpDoc )); + pFrameView->ReadUserDataSequence( aSeq ); + rViews.push_back( std::move(pFrameView) ); + } + } +} + +// XDrawPageDuplicator +uno::Reference< drawing::XDrawPage > SAL_CALL SdXImpressDocument::duplicate( const uno::Reference< drawing::XDrawPage >& xPage ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + // get pPage from xPage and determine the Id (nPos ) afterwards + SvxDrawPage* pSvxPage = comphelper::getFromUnoTunnel<SvxDrawPage>( xPage ); + if( pSvxPage ) + { + SdPage* pPage = static_cast<SdPage*>( pSvxPage->GetSdrPage() ); + sal_uInt16 nPos = pPage->GetPageNum(); + nPos = ( nPos - 1 ) / 2; + pPage = InsertSdPage( nPos, true ); + if( pPage ) + { + uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); + return xDrawPage; + } + } + + uno::Reference< drawing::XDrawPage > xDrawPage; + return xDrawPage; +} + +// XDrawPagesSupplier +uno::Reference< drawing::XDrawPages > SAL_CALL SdXImpressDocument::getDrawPages() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + uno::Reference< drawing::XDrawPages > xDrawPages( mxDrawPagesAccess ); + + if( !xDrawPages.is() ) + { + initializeDocument(); + mxDrawPagesAccess = xDrawPages = new SdDrawPagesAccess(*this); + } + + return xDrawPages; +} + +// XMasterPagesSupplier +uno::Reference< drawing::XDrawPages > SAL_CALL SdXImpressDocument::getMasterPages() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + uno::Reference< drawing::XDrawPages > xMasterPages( mxMasterPagesAccess ); + + if( !xMasterPages.is() ) + { + if ( !hasControllersLocked() ) + initializeDocument(); + mxMasterPagesAccess = xMasterPages = new SdMasterPagesAccess(*this); + } + + return xMasterPages; +} + +// XLayerManagerSupplier +uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getLayerManager( ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + uno::Reference< container::XNameAccess > xLayerManager( mxLayerManager ); + + if( !xLayerManager.is() ) + mxLayerManager = xLayerManager = new SdLayerManager(*this); + + return xLayerManager; +} + +// XCustomPresentationSupplier +uno::Reference< container::XNameContainer > SAL_CALL SdXImpressDocument::getCustomPresentations() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + uno::Reference< container::XNameContainer > xCustomPres( mxCustomPresentationAccess ); + + if( !xCustomPres.is() ) + mxCustomPresentationAccess = xCustomPres = new SdXCustomPresentationAccess(*this); + + return xCustomPres; +} + +// XPresentationSupplier +uno::Reference< presentation::XPresentation > SAL_CALL SdXImpressDocument::getPresentation() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + return mpDoc->getPresentation(); +} + +// XHandoutMasterSupplier +uno::Reference< drawing::XDrawPage > SAL_CALL SdXImpressDocument::getHandoutMasterPage() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + uno::Reference< drawing::XDrawPage > xPage; + + initializeDocument(); + SdPage* pPage = mpDoc->GetMasterSdPage(0, PageKind::Handout); + if (pPage) + xPage.set(pPage->getUnoPage(), uno::UNO_QUERY); + return xPage; +} + +// XMultiServiceFactory ( SvxFmMSFactory ) + +css::uno::Reference<css::uno::XInterface> SdXImpressDocument::create( + OUString const & aServiceSpecifier, OUString const & referer) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + if( aServiceSpecifier == "com.sun.star.drawing.DashTable" ) + { + if( !mxDashTable.is() ) + mxDashTable = SvxUnoDashTable_createInstance( mpDoc ); + + return mxDashTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.GradientTable" ) + { + if( !mxGradientTable.is() ) + mxGradientTable = SvxUnoGradientTable_createInstance( mpDoc ); + + return mxGradientTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.HatchTable" ) + { + if( !mxHatchTable.is() ) + mxHatchTable = SvxUnoHatchTable_createInstance( mpDoc ); + + return mxHatchTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.BitmapTable" ) + { + if( !mxBitmapTable.is() ) + mxBitmapTable = SvxUnoBitmapTable_createInstance( mpDoc ); + + return mxBitmapTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.TransparencyGradientTable" ) + { + if( !mxTransGradientTable.is() ) + mxTransGradientTable = SvxUnoTransGradientTable_createInstance( mpDoc ); + + return mxTransGradientTable; + } + if( aServiceSpecifier == "com.sun.star.drawing.MarkerTable" ) + { + if( !mxMarkerTable.is() ) + mxMarkerTable = SvxUnoMarkerTable_createInstance( mpDoc ); + + return mxMarkerTable; + } + if( aServiceSpecifier == "com.sun.star.text.NumberingRules" ) + { + return uno::Reference< uno::XInterface >( SvxCreateNumRule( mpDoc ), uno::UNO_QUERY ); + } + if( aServiceSpecifier == "com.sun.star.drawing.Background" ) + { + return uno::Reference< uno::XInterface >( + static_cast<uno::XWeak*>(new SdUnoPageBackground( mpDoc ))); + } + + if( aServiceSpecifier == "com.sun.star.drawing.Defaults" ) + { + if( !mxDrawingPool.is() ) + mxDrawingPool = SdUnoCreatePool( mpDoc ); + + return mxDrawingPool; + + } + + if ( aServiceSpecifier == sUNO_Service_ImageMapRectangleObject ) + { + return SvUnoImageMapRectangleObject_createInstance( ImplGetSupportedMacroItems() ); + } + + if ( aServiceSpecifier == sUNO_Service_ImageMapCircleObject ) + { + return SvUnoImageMapCircleObject_createInstance( ImplGetSupportedMacroItems() ); + } + + if ( aServiceSpecifier == sUNO_Service_ImageMapPolygonObject ) + { + return SvUnoImageMapPolygonObject_createInstance( ImplGetSupportedMacroItems() ); + } + + if( aServiceSpecifier == "com.sun.star.document.Settings" || + ( !mbImpressDoc && ( aServiceSpecifier == "com.sun.star.drawing.DocumentSettings" ) ) || + ( mbImpressDoc && ( aServiceSpecifier == "com.sun.star.presentation.DocumentSettings" ) ) ) + { + return sd::DocumentSettings_createInstance( this ); + } + + if( aServiceSpecifier == "com.sun.star.text.TextField.DateTime" || + aServiceSpecifier == "com.sun.star.text.textfield.DateTime" ) + { + return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::DATE )); + } + + if( aServiceSpecifier == "com.sun.star.presentation.TextField.Header" || + aServiceSpecifier == "com.sun.star.presentation.textfield.Header" ) + { + return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_HEADER )); + } + + if( aServiceSpecifier == "com.sun.star.presentation.TextField.Footer" || + aServiceSpecifier == "com.sun.star.presentation.textfield.Footer" ) + { + return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_FOOTER )); + } + + if( aServiceSpecifier == "com.sun.star.presentation.TextField.DateTime" || + aServiceSpecifier == "com.sun.star.presentation.textfield.DateTime" ) + { + return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PRESENTATION_DATE_TIME )); + } + + if( aServiceSpecifier == "com.sun.star.text.TextField.PageName" || + aServiceSpecifier == "com.sun.star.text.textfield.PageName" ) + { + return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::PAGE_NAME )); + } + + if (aServiceSpecifier == "com.sun.star.text.TextField.DocInfo.Custom" || + aServiceSpecifier == "com.sun.star.text.textfield.DocInfo.Custom") + { + return static_cast<cppu::OWeakObject *>(new SvxUnoTextField(text::textfield::Type::DOCINFO_CUSTOM)); + } + + if( aServiceSpecifier == "com.sun.star.xml.NamespaceMap" ) + { + static sal_uInt16 aWhichIds[] = { SDRATTR_XMLATTRIBUTES, EE_CHAR_XMLATTRIBS, EE_PARA_XMLATTRIBS, 0 }; + + return svx::NamespaceMap_createInstance( aWhichIds, &mpDoc->GetItemPool() ); + } + + // Support creation of GraphicStorageHandler and EmbeddedObjectResolver + if (aServiceSpecifier == "com.sun.star.document.ExportGraphicStorageHandler") + { + return static_cast<cppu::OWeakObject *>(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Write )); + } + + if (aServiceSpecifier == "com.sun.star.document.ImportGraphicStorageHandler") + { + return static_cast<cppu::OWeakObject *>(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Read )); + } + + if( aServiceSpecifier == "com.sun.star.document.ExportEmbeddedObjectResolver" ) + { + comphelper::IEmbeddedHelper* pPersist = mpDoc->GetPersist(); + if( nullptr == pPersist ) + throw lang::DisposedException(); + + return static_cast<cppu::OWeakObject *>(new SvXMLEmbeddedObjectHelper( *pPersist, SvXMLEmbeddedObjectHelperMode::Write )); + } + + if( aServiceSpecifier == "com.sun.star.document.ImportEmbeddedObjectResolver" ) + { + comphelper::IEmbeddedHelper* pPersist = mpDoc->GetPersist(); + if( nullptr == pPersist ) + throw lang::DisposedException(); + + return static_cast<cppu::OWeakObject *>(new SvXMLEmbeddedObjectHelper( *pPersist, SvXMLEmbeddedObjectHelperMode::Read )); + } + + uno::Reference< uno::XInterface > xRet; + + if( aServiceSpecifier.startsWith( "com.sun.star.presentation.") ) + { + const std::u16string_view aType( aServiceSpecifier.subView(26) ); + rtl::Reference<SvxShape> pShape; + + SdrObjKind nType = SdrObjKind::Text; + // create a shape wrapper + if( o3tl::starts_with(aType, u"TitleTextShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aType, u"OutlinerShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aType, u"SubtitleShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aType, u"GraphicObjectShape" ) ) + { + nType = SdrObjKind::Graphic; + } + else if( o3tl::starts_with(aType, u"PageShape" ) ) + { + nType = SdrObjKind::Page; + } + else if( o3tl::starts_with(aType, u"OLE2Shape" ) ) + { + nType = SdrObjKind::OLE2; + } + else if( o3tl::starts_with(aType, u"ChartShape" ) ) + { + nType = SdrObjKind::OLE2; + } + else if( o3tl::starts_with(aType, u"CalcShape" ) ) + { + nType = SdrObjKind::OLE2; + } + else if( o3tl::starts_with(aType, u"TableShape" ) ) + { + nType = SdrObjKind::Table; + } + else if( o3tl::starts_with(aType, u"OrgChartShape" ) ) + { + nType = SdrObjKind::OLE2; + } + else if( o3tl::starts_with(aType, u"NotesShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aType, u"HandoutShape" ) ) + { + nType = SdrObjKind::Page; + } + else if( o3tl::starts_with(aType, u"FooterShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aType, u"HeaderShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aType, u"SlideNumberShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aType, u"DateTimeShape" ) ) + { + nType = SdrObjKind::Text; + } + else if( o3tl::starts_with(aType, u"MediaShape" ) ) + { + nType = SdrObjKind::Media; + } + else + { + throw lang::ServiceNotRegisteredException(); + } + + // create the API wrapper + pShape = CreateSvxShapeByTypeAndInventor( nType, SdrInventor::Default, referer ); + + // set shape type + if( pShape && !mbClipBoard ) + pShape->SetShapeType(aServiceSpecifier); + + xRet = static_cast<uno::XWeak*>(pShape.get()); + } + else if ( aServiceSpecifier == "com.sun.star.drawing.TableShape" ) + { + rtl::Reference<SvxShape> pShape = CreateSvxShapeByTypeAndInventor( SdrObjKind::Table, SdrInventor::Default, referer ); + if( pShape && !mbClipBoard ) + pShape->SetShapeType(aServiceSpecifier); + + xRet = static_cast<uno::XWeak*>(pShape.get()); + } + else + { + xRet = SvxFmMSFactory::createInstance( aServiceSpecifier ); + } + + uno::Reference< drawing::XShape > xShape( xRet, uno::UNO_QUERY ); + SvxShape* pShape = xShape.is() ? comphelper::getFromUnoTunnel<SvxShape>(xShape) : nullptr; + if (pShape) + { + xRet.clear(); + new SdXShape( pShape, this ); + xRet = xShape; + xShape.clear(); + } + + return xRet; +} + +uno::Reference< uno::XInterface > SAL_CALL SdXImpressDocument::createInstance( const OUString& aServiceSpecifier ) +{ + return create(aServiceSpecifier, ""); +} + +css::uno::Reference<css::uno::XInterface> +SdXImpressDocument::createInstanceWithArguments( + OUString const & ServiceSpecifier, + css::uno::Sequence<css::uno::Any> const & Arguments) +{ + OUString arg; + if ((ServiceSpecifier == "com.sun.star.drawing.GraphicObjectShape" + || ServiceSpecifier == "com.sun.star.drawing.MediaShape" + || ServiceSpecifier == "com.sun.star.presentation.MediaShape") + && Arguments.getLength() == 1 && (Arguments[0] >>= arg)) + { + return create(ServiceSpecifier, arg); + } + return SvxFmMSFactory::createInstanceWithArguments( + ServiceSpecifier, Arguments); +} + +uno::Sequence< OUString > SAL_CALL SdXImpressDocument::getAvailableServiceNames() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + const uno::Sequence< OUString > aSNS_ORG( SvxFmMSFactory::getAvailableServiceNames() ); + + uno::Sequence< OUString > aSNS_Common{ "com.sun.star.drawing.DashTable", + "com.sun.star.drawing.GradientTable", + "com.sun.star.drawing.HatchTable", + "com.sun.star.drawing.BitmapTable", + "com.sun.star.drawing.TransparencyGradientTable", + "com.sun.star.drawing.MarkerTable", + "com.sun.star.text.NumberingRules", + "com.sun.star.drawing.Background", + "com.sun.star.document.Settings", + sUNO_Service_ImageMapRectangleObject, + sUNO_Service_ImageMapCircleObject, + sUNO_Service_ImageMapPolygonObject, + "com.sun.star.xml.NamespaceMap", + + // Support creation of GraphicStorageHandler and EmbeddedObjectResolver + "com.sun.star.document.ExportGraphicStorageHandler", + "com.sun.star.document.ImportGraphicStorageHandler", + "com.sun.star.document.ExportEmbeddedObjectResolver", + "com.sun.star.document.ImportEmbeddedObjectResolver", + "com.sun.star.drawing.TableShape" }; + + uno::Sequence< OUString > aSNS_Specific; + + if(mbImpressDoc) + aSNS_Specific = { "com.sun.star.presentation.TitleTextShape", + "com.sun.star.presentation.OutlinerShape", + "com.sun.star.presentation.SubtitleShape", + "com.sun.star.presentation.GraphicObjectShape", + "com.sun.star.presentation.ChartShape", + "com.sun.star.presentation.PageShape", + "com.sun.star.presentation.OLE2Shape", + "com.sun.star.presentation.TableShape", + "com.sun.star.presentation.OrgChartShape", + "com.sun.star.presentation.NotesShape", + "com.sun.star.presentation.HandoutShape", + "com.sun.star.presentation.DocumentSettings", + "com.sun.star.presentation.FooterShape", + "com.sun.star.presentation.HeaderShape", + "com.sun.star.presentation.SlideNumberShape", + "com.sun.star.presentation.DateTimeShape", + "com.sun.star.presentation.CalcShape", + "com.sun.star.presentation.MediaShape" }; + else + aSNS_Specific = { "com.sun.star.drawing.DocumentSettings" }; + + return comphelper::concatSequences( aSNS_ORG, aSNS_Common, aSNS_Specific ); +} + +// lang::XServiceInfo +OUString SAL_CALL SdXImpressDocument::getImplementationName() +{ + return "SdXImpressDocument"; + /* // Matching the .component information: + return mbImpressDoc + ? OUString("com.sun.star.comp.Draw.PresentationDocument") + : OUString("com.sun.star.comp.Draw.DrawingDocument"); + */ +} + +sal_Bool SAL_CALL SdXImpressDocument::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL SdXImpressDocument::getSupportedServiceNames() +{ + ::SolarMutexGuard aGuard; + + return { "com.sun.star.document.OfficeDocument", + "com.sun.star.drawing.GenericDrawingDocument", + "com.sun.star.drawing.DrawingDocumentFactory", + mbImpressDoc?OUString("com.sun.star.presentation.PresentationDocument"):OUString("com.sun.star.drawing.DrawingDocument") }; +} + +// XPropertySet +uno::Reference< beans::XPropertySetInfo > SAL_CALL SdXImpressDocument::getPropertySetInfo( ) +{ + ::SolarMutexGuard aGuard; + return mpPropSet->getPropertySetInfo(); +} + +void SAL_CALL SdXImpressDocument::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(aPropertyName); + + switch( pEntry ? pEntry->nWID : -1 ) + { + case WID_MODEL_LANGUAGE: + { + lang::Locale aLocale; + if(!(aValue >>= aLocale)) + throw lang::IllegalArgumentException(); + + mpDoc->SetLanguage( LanguageTag::convertToLanguageType(aLocale), EE_CHAR_LANGUAGE ); + break; + } + case WID_MODEL_TABSTOP: + { + sal_Int32 nValue = 0; + if(!(aValue >>= nValue) || nValue < 0 ) + throw lang::IllegalArgumentException(); + + mpDoc->SetDefaultTabulator(static_cast<sal_uInt16>(nValue)); + break; + } + case WID_MODEL_VISAREA: + { + SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh(); + if( !pEmbeddedObj ) + break; + + awt::Rectangle aVisArea; + if( !(aValue >>= aVisArea) || (aVisArea.Width < 0) || (aVisArea.Height < 0) ) + throw lang::IllegalArgumentException(); + + sal_Int32 nRight, nTop; + if (o3tl::checked_add(aVisArea.X, aVisArea.Width, nRight) || o3tl::checked_add(aVisArea.Y, aVisArea.Height, nTop)) + throw lang::IllegalArgumentException(); + + pEmbeddedObj->SetVisArea(::tools::Rectangle(aVisArea.X, aVisArea.Y, nRight, nTop)); + } + break; + case WID_MODEL_CONTFOCUS: + { + bool bFocus = false; + if( !(aValue >>= bFocus ) ) + throw lang::IllegalArgumentException(); + mpDoc->SetAutoControlFocus( bFocus ); + } + break; + case WID_MODEL_DSGNMODE: + { + bool bMode = false; + if( !(aValue >>= bMode ) ) + throw lang::IllegalArgumentException(); + mpDoc->SetOpenInDesignMode( bMode ); + } + break; + case WID_MODEL_BUILDID: + aValue >>= maBuildId; + return; + case WID_MODEL_MAPUNIT: + case WID_MODEL_BASICLIBS: + case WID_MODEL_RUNTIMEUID: // is read-only + case WID_MODEL_DIALOGLIBS: + case WID_MODEL_FONTS: + throw beans::PropertyVetoException(); + case WID_MODEL_INTEROPGRABBAG: + setGrabBagItem(aValue); + break; + case WID_MODEL_THEME: + { + SdrModel& rModel = getSdrModelFromUnoModel(); + std::unique_ptr<svx::Theme> pTheme = svx::Theme::FromAny(aValue); + rModel.SetTheme(std::move(pTheme)); + } + break; + default: + throw beans::UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this)); + } + + SetModified(); +} + +uno::Any SAL_CALL SdXImpressDocument::getPropertyValue( const OUString& PropertyName ) +{ + ::SolarMutexGuard aGuard; + + uno::Any aAny; + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(PropertyName); + + switch( pEntry ? pEntry->nWID : -1 ) + { + case WID_MODEL_LANGUAGE: + { + LanguageType eLang = mpDoc->GetLanguage( EE_CHAR_LANGUAGE ); + aAny <<= LanguageTag::convertToLocale( eLang); + break; + } + case WID_MODEL_TABSTOP: + aAny <<= static_cast<sal_Int32>(mpDoc->GetDefaultTabulator()); + break; + case WID_MODEL_VISAREA: + { + SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh(); + if( !pEmbeddedObj ) + break; + + const ::tools::Rectangle& aRect = pEmbeddedObj->GetVisArea(); + awt::Rectangle aVisArea( aRect.Left(), aRect.Top(), aRect.getWidth(), aRect.getHeight() ); + aAny <<= aVisArea; + } + break; + case WID_MODEL_MAPUNIT: + { + SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh(); + if( !pEmbeddedObj ) + break; + + sal_Int16 nMeasureUnit = 0; + SvxMapUnitToMeasureUnit( pEmbeddedObj->GetMapUnit(), nMeasureUnit ); + aAny <<= nMeasureUnit; + } + break; + case WID_MODEL_FORBCHARS: + { + aAny <<= getForbiddenCharsTable(); + } + break; + case WID_MODEL_CONTFOCUS: + aAny <<= mpDoc->GetAutoControlFocus(); + break; + case WID_MODEL_DSGNMODE: + aAny <<= mpDoc->GetOpenInDesignMode(); + break; + case WID_MODEL_BASICLIBS: + aAny <<= mpDocShell->GetBasicContainer(); + break; + case WID_MODEL_DIALOGLIBS: + aAny <<= mpDocShell->GetDialogContainer(); + break; + case WID_MODEL_RUNTIMEUID: + aAny <<= getRuntimeUID(); + break; + case WID_MODEL_BUILDID: + return uno::Any( maBuildId ); + case WID_MODEL_HASVALIDSIGNATURES: + aAny <<= hasValidSignatures(); + break; + case WID_MODEL_FONTS: + { + uno::Sequence<uno::Any> aSeq; + int nSeqIndex = 0; + + sal_uInt16 const aWhichIds[] { EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK, + EE_CHAR_FONTINFO_CTL }; + + const SfxItemPool& rPool = mpDoc->GetPool(); + + for(sal_uInt16 nWhichId : aWhichIds) + { + sal_uInt32 nItems = rPool.GetItemCount2( nWhichId ); + + aSeq.realloc( aSeq.getLength() + nItems*5 + 5 ); + auto pSeq = aSeq.getArray(); + + for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(nWhichId)) + { + const SvxFontItem *pFont = static_cast<const SvxFontItem *>(pItem); + + pSeq[nSeqIndex++] <<= pFont->GetFamilyName(); + pSeq[nSeqIndex++] <<= pFont->GetStyleName(); + pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetFamily()); + pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetPitch()); + pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetCharSet()); + } + + const SvxFontItem& rFont = static_cast<const SvxFontItem&>(rPool.GetDefaultItem( nWhichId )); + + pSeq[nSeqIndex++] <<= rFont.GetFamilyName(); + pSeq[nSeqIndex++] <<= rFont.GetStyleName(); + pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetFamily()); + pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetPitch()); + pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetCharSet()); + + } + + aSeq.realloc( nSeqIndex ); + aAny <<= aSeq; + break; + } + case WID_MODEL_INTEROPGRABBAG: + getGrabBagItem(aAny); + break; + case WID_MODEL_THEME: + { + SdrModel& rModel = getSdrModelFromUnoModel(); + svx::Theme* pTheme = rModel.GetTheme(); + if (pTheme) + { + pTheme->ToAny(aAny); + } + else + { + beans::PropertyValues aValues; + aAny <<= aValues; + } + break; + } + default: + throw beans::UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this)); + } + + return aAny; +} + +void SAL_CALL SdXImpressDocument::addPropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {} +void SAL_CALL SdXImpressDocument::removePropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {} +void SAL_CALL SdXImpressDocument::addVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {} +void SAL_CALL SdXImpressDocument::removeVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {} + +// XLinkTargetSupplier +uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getLinks() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + uno::Reference< container::XNameAccess > xLinks( mxLinks ); + if( !xLinks.is() ) + mxLinks = xLinks = new SdDocLinkTargets( *this ); + return xLinks; +} + +// XStyleFamiliesSupplier +uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getStyleFamilies( ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + uno::Reference< container::XNameAccess > xStyles( dynamic_cast< container::XNameAccess* >( mpDoc->GetStyleSheetPool()) ); + return xStyles; +} + +// XAnyCompareFactory +uno::Reference< css::ucb::XAnyCompare > SAL_CALL SdXImpressDocument::createAnyCompareByName( const OUString& ) +{ + return SvxCreateNumRuleCompare(); +} + +// XRenderable +sal_Int32 SAL_CALL SdXImpressDocument::getRendererCount( const uno::Any& rSelection, + const uno::Sequence< beans::PropertyValue >& ) +{ + ::SolarMutexGuard aGuard; + sal_Int32 nRet = 0; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + if (mpDocShell) + { + uno::Reference< frame::XModel > xModel; + + rSelection >>= xModel; + + if( xModel == mpDocShell->GetModel() ) + nRet = mpDoc->GetSdPageCount( PageKind::Standard ); + else + { + uno::Reference< drawing::XShapes > xShapes; + + rSelection >>= xShapes; + + if( xShapes.is() && xShapes->getCount() ) + nRet = 1; + } + } + return nRet; +} + +uno::Sequence< beans::PropertyValue > SAL_CALL SdXImpressDocument::getRenderer( sal_Int32 , const uno::Any& , + const uno::Sequence< beans::PropertyValue >& rxOptions ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + bool bExportNotesPages = false; + for( const auto& rOption : rxOptions ) + { + if ( rOption.Name == "ExportNotesPages" ) + rOption.Value >>= bExportNotesPages; + } + uno::Sequence< beans::PropertyValue > aRenderer; + if (mpDocShell) + { + awt::Size aPageSize; + if ( bExportNotesPages ) + { + Size aNotesPageSize = mpDoc->GetSdPage( 0, PageKind::Notes )->GetSize(); + aPageSize = awt::Size( aNotesPageSize.Width(), aNotesPageSize.Height() ); + } + else + { + const ::tools::Rectangle aVisArea( mpDocShell->GetVisArea( embed::Aspects::MSOLE_DOCPRINT ) ); + aPageSize = awt::Size( aVisArea.GetWidth(), aVisArea.GetHeight() ); + } + aRenderer = { comphelper::makePropertyValue("PageSize", aPageSize) }; + } + return aRenderer; +} + +namespace { + +class ImplRenderPaintProc : public sdr::contact::ViewObjectContactRedirector +{ + const SdrLayerAdmin& rLayerAdmin; + SdrPageView* pSdrPageView; + +public: + bool IsVisible ( const SdrObject* pObj ) const; + bool IsPrintable( const SdrObject* pObj ) const; + + ImplRenderPaintProc(const SdrLayerAdmin& rLA, SdrPageView* pView); + + // all default implementations just call the same methods at the original. To do something + // different, override the method and at least do what the method does. + virtual void createRedirectedPrimitive2DSequence( + const sdr::contact::ViewObjectContact& rOriginal, + const sdr::contact::DisplayInfo& rDisplayInfo, + drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) override; +}; + +} + +ImplRenderPaintProc::ImplRenderPaintProc(const SdrLayerAdmin& rLA, SdrPageView *const pView) + : rLayerAdmin(rLA) + , pSdrPageView(pView) +{ +} + +static sal_Int32 ImplPDFGetBookmarkPage( const OUString& rBookmark, SdDrawDocument const & rDoc ) +{ + sal_Int32 nPage = -1; + + OUString aBookmark( rBookmark ); + + if( rBookmark.startsWith("#") ) + aBookmark = rBookmark.copy( 1 ); + + // is the bookmark a page ? + bool bIsMasterPage; + sal_uInt16 nPgNum = rDoc.GetPageByName( aBookmark, bIsMasterPage ); + + if ( nPgNum == SDRPAGE_NOTFOUND ) + { + // is the bookmark an object ? + SdrObject* pObj = rDoc.GetObj( aBookmark ); + if (pObj) + nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum(); + } + if ( nPgNum != SDRPAGE_NOTFOUND ) + nPage = ( nPgNum - 1 ) / 2; + return nPage; +} + +static void ImplPDFExportComments( const uno::Reference< drawing::XDrawPage >& xPage, vcl::PDFExtOutDevData& rPDFExtOutDevData ) +{ + try + { + uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xPage, uno::UNO_QUERY_THROW ); + uno::Reference< office::XAnnotationEnumeration > xAnnotationEnumeration( xAnnotationAccess->createAnnotationEnumeration() ); + + while( xAnnotationEnumeration->hasMoreElements() ) + { + uno::Reference< office::XAnnotation > xAnnotation( xAnnotationEnumeration->nextElement() ); + + geometry::RealPoint2D aRealPoint2D( xAnnotation->getPosition() ); + uno::Reference< text::XText > xText( xAnnotation->getTextRange() ); + + vcl::PDFNote aNote; + aNote.Title = xAnnotation->getAuthor(); + aNote.Contents = xText->getString(); + aNote.maModificationDate = xAnnotation->getDateTime(); + + rPDFExtOutDevData.CreateNote( ::tools::Rectangle( Point( static_cast< ::tools::Long >( aRealPoint2D.X * 100 ), + static_cast< ::tools::Long >( aRealPoint2D.Y * 100 ) ), Size( 1000, 1000 ) ), aNote ); + } + } + catch (const uno::Exception&) + { + } +} + +static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape >& xShape, SdDrawDocument& rDoc, vcl::PDFExtOutDevData& rPDFExtOutDevData ) +{ + if ( xShape->getShapeType() == "com.sun.star.drawing.GroupShape" ) + { + uno::Reference< container::XIndexAccess > xIndexAccess( xShape, uno::UNO_QUERY ); + if ( xIndexAccess.is() ) + { + sal_Int32 i, nCount = xIndexAccess->getCount(); + for ( i = 0; i < nCount; i++ ) + { + uno::Reference< drawing::XShape > xSubShape( xIndexAccess->getByIndex( i ), uno::UNO_QUERY ); + if ( xSubShape.is() ) + ImplPDFExportShapeInteraction( xSubShape, rDoc, rPDFExtOutDevData ); + } + } + } + else + { + uno::Reference< beans::XPropertySet > xShapePropSet( xShape, uno::UNO_QUERY ); + if( xShapePropSet.is() ) + { + Size aPageSize( rDoc.GetSdPage( 0, PageKind::Standard )->GetSize() ); + Point aPoint( 0, 0 ); + ::tools::Rectangle aPageRect( aPoint, aPageSize ); + + awt::Point aShapePos( xShape->getPosition() ); + awt::Size aShapeSize( xShape->getSize() ); + ::tools::Rectangle aLinkRect( Point( aShapePos.X, aShapePos.Y ), Size( aShapeSize.Width, aShapeSize.Height ) ); + + // Handle linked videos. + if (xShape->getShapeType() == "com.sun.star.drawing.MediaShape" || xShape->getShapeType() == "com.sun.star.presentation.MediaShape") + { + OUString aMediaURL; + xShapePropSet->getPropertyValue("MediaURL") >>= aMediaURL; + if (!aMediaURL.isEmpty()) + { + sal_Int32 nScreenId = rPDFExtOutDevData.CreateScreen(aLinkRect, rPDFExtOutDevData.GetCurrentPageNumber()); + if (aMediaURL.startsWith("vnd.sun.star.Package:")) + { + OUString aTempFileURL; + xShapePropSet->getPropertyValue("PrivateTempFileURL") >>= aTempFileURL; + rPDFExtOutDevData.SetScreenStream(nScreenId, aTempFileURL); + } + else + rPDFExtOutDevData.SetScreenURL(nScreenId, aMediaURL); + } + } + + presentation::ClickAction eCa; + uno::Any aAny( xShapePropSet->getPropertyValue( "OnClick" ) ); + if ( aAny >>= eCa ) + { + OUString const actionName(SdResId(SdTPAction::GetClickActionSdResId(eCa))); + switch ( eCa ) + { + case presentation::ClickAction_LASTPAGE : + { + sal_Int32 nCount = rDoc.GetSdPageCount( PageKind::Standard ); + sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nCount - 1, vcl::PDFWriter::DestAreaType::FitRectangle ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); + rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); + } + break; + case presentation::ClickAction_FIRSTPAGE : + { + sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, 0, vcl::PDFWriter::DestAreaType::FitRectangle ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); + rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); + } + break; + case presentation::ClickAction_PREVPAGE : + { + sal_Int32 nDestPage = rPDFExtOutDevData.GetCurrentPageNumber(); + if ( nDestPage ) + nDestPage--; + sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); + rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); + } + break; + case presentation::ClickAction_NEXTPAGE : + { + sal_Int32 nDestPage = rPDFExtOutDevData.GetCurrentPageNumber() + 1; + sal_Int32 nLastPage = rDoc.GetSdPageCount( PageKind::Standard ) - 1; + if ( nDestPage > nLastPage ) + nDestPage = nLastPage; + sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); + rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); + } + break; + + case presentation::ClickAction_PROGRAM : + case presentation::ClickAction_BOOKMARK : + case presentation::ClickAction_DOCUMENT : + { + OUString aBookmark; + xShapePropSet->getPropertyValue( "Bookmark" ) >>= aBookmark; + if( !aBookmark.isEmpty() ) + { + switch( eCa ) + { + case presentation::ClickAction_DOCUMENT : + case presentation::ClickAction_PROGRAM : + { + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); + rPDFExtOutDevData.SetLinkURL( nLinkId, aBookmark ); + } + break; + case presentation::ClickAction_BOOKMARK : + { + sal_Int32 nPage = ImplPDFGetBookmarkPage( aBookmark, rDoc ); + if ( nPage != -1 ) + { + sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ); + sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); + rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); + } + } + break; + default: + break; + } + } + } + break; + + case presentation::ClickAction_STOPPRESENTATION : + case presentation::ClickAction_SOUND : + case presentation::ClickAction_INVISIBLE : + case presentation::ClickAction_VERB : + case presentation::ClickAction_VANISH : + case presentation::ClickAction_MACRO : + default : + break; + } + } + } + } +} + +void ImplRenderPaintProc::createRedirectedPrimitive2DSequence( + const sdr::contact::ViewObjectContact& rOriginal, + const sdr::contact::DisplayInfo& rDisplayInfo, + drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) +{ + SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject(); + if(!pObject) + { + // not an object, maybe a page + sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor); + return; + } + SdrPage* pSdrPage(pObject->getSdrPageFromSdrObject()); + if(!pSdrPage) + return; + if(!pSdrPage->checkVisibility(rOriginal, rDisplayInfo, false)) + return; + if(!IsVisible(pObject) || !IsPrintable(pObject)) + return; + + sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor); +} + +bool ImplRenderPaintProc::IsVisible( const SdrObject* pObj ) const +{ + bool bVisible = true; + SdrLayerID nLayerId = pObj->GetLayer(); + if( pSdrPageView ) + { + const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId ); + if ( pSdrLayer ) + { + const OUString& aLayerName = pSdrLayer->GetName(); + bVisible = pSdrPageView->IsLayerVisible( aLayerName ); + } + } + return bVisible; +} +bool ImplRenderPaintProc::IsPrintable( const SdrObject* pObj ) const +{ + bool bPrintable = true; + SdrLayerID nLayerId = pObj->GetLayer(); + if( pSdrPageView ) + { + const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId ); + if ( pSdrLayer ) + { + const OUString& aLayerName = pSdrLayer->GetName(); + bPrintable = pSdrPageView->IsLayerPrintable( aLayerName ); + } + } + return bPrintable; + +} + +namespace +{ + sal_Int16 CalcOutputPageNum(vcl::PDFExtOutDevData const * pPDFExtOutDevData, SdDrawDocument const *pDoc, sal_Int16 nPageNumber) + { + //export all pages, simple one to one case + if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportHiddenSlides()) + return nPageNumber-1; + //check all preceding pages, and only count non-hidden ones + sal_Int16 nRet = 0; + for (sal_Int16 i = 0; i < nPageNumber-1; ++i) + { + if (!pDoc->GetSdPage(i, PageKind::Standard)->IsExcluded()) + ++nRet; + } + return nRet; + } +} + +void SAL_CALL SdXImpressDocument::render( sal_Int32 nRenderer, const uno::Any& rSelection, + const uno::Sequence< beans::PropertyValue >& rxOptions ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpDoc ) + throw lang::DisposedException(); + + if (!mpDocShell) + return; + + uno::Reference< awt::XDevice > xRenderDevice; + const sal_Int32 nPageNumber = nRenderer + 1; + PageKind ePageKind = PageKind::Standard; + bool bExportNotesPages = false; + + for( const auto& rOption : rxOptions ) + { + if ( rOption.Name == "RenderDevice" ) + rOption.Value >>= xRenderDevice; + else if ( rOption.Name == "ExportNotesPages" ) + { + rOption.Value >>= bExportNotesPages; + if ( bExportNotesPages ) + ePageKind = PageKind::Notes; + } + } + + if( !(xRenderDevice.is() && nPageNumber && ( nPageNumber <= mpDoc->GetSdPageCount( ePageKind ) )) ) + return; + + VCLXDevice* pDevice = comphelper::getFromUnoTunnel<VCLXDevice>( xRenderDevice ); + VclPtr< OutputDevice> pOut = pDevice ? pDevice->GetOutputDevice() : VclPtr< OutputDevice >(); + + if( !pOut ) + return; + + vcl::PDFExtOutDevData* pPDFExtOutDevData = dynamic_cast<vcl::PDFExtOutDevData* >( pOut->GetExtOutDevData() ); + + if ( mpDoc->GetSdPage(static_cast<sal_Int16>(nPageNumber)-1, PageKind::Standard)->IsExcluded() && + !(pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportHiddenSlides()) ) + return; + + if (pPDFExtOutDevData) + { + css::lang::Locale const docLocale(Application::GetSettings().GetLanguageTag().getLocale()); + pPDFExtOutDevData->SetDocumentLocale(docLocale); + } + + ::sd::ClientView aView( mpDocShell, pOut ); + ::tools::Rectangle aVisArea( Point(), mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1, ePageKind )->GetSize() ); + vcl::Region aRegion( aVisArea ); + + ::sd::ViewShell* pOldViewSh = mpDocShell->GetViewShell(); + ::sd::View* pOldSdView = pOldViewSh ? pOldViewSh->GetView() : nullptr; + + if ( pOldSdView ) + pOldSdView->SdrEndTextEdit(); + + aView.SetHlplVisible( false ); + aView.SetGridVisible( false ); + aView.SetBordVisible( false ); + aView.SetPageVisible( false ); + aView.SetGlueVisible( false ); + + pOut->SetMapMode(MapMode(MapUnit::Map100thMM)); + pOut->IntersectClipRegion( aVisArea ); + + uno::Reference< frame::XModel > xModel; + rSelection >>= xModel; + + if( xModel == mpDocShell->GetModel() ) + { + aView.ShowSdrPage( mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1, ePageKind )); + SdrPageView* pPV = aView.GetSdrPageView(); + + if( pOldSdView ) + { + SdrPageView* pOldPV = pOldSdView->GetSdrPageView(); + if( pPV && pOldPV ) + { + pPV->SetVisibleLayers( pOldPV->GetVisibleLayers() ); + pPV->SetPrintableLayers( pOldPV->GetPrintableLayers() ); + } + } + + ImplRenderPaintProc aImplRenderPaintProc( mpDoc->GetLayerAdmin(), + pPV); + + // background color for outliner :o + SdPage* pPage = pPV ? static_cast<SdPage*>(pPV->GetPage()) : nullptr; + if( pPage ) + { + SdrOutliner& rOutl = mpDoc->GetDrawOutliner(); + bool bScreenDisplay(true); + + // #i75566# printing; suppress AutoColor BackgroundColor generation + // for visibility reasons by giving GetPageBackgroundColor() + // the needed hint + // #i75566# PDF export; suppress AutoColor BackgroundColor generation (see printing) + if (pOut && ((OUTDEV_PRINTER == pOut->GetOutDevType()) + || (OUTDEV_PDF == pOut->GetOutDevType()))) + bScreenDisplay = false; + + // #i75566# Name change GetBackgroundColor -> GetPageBackgroundColor and + // hint value if screen display. Only then the AutoColor mechanisms shall be applied + rOutl.SetBackgroundColor( pPage->GetPageBackgroundColor( pPV, bScreenDisplay ) ); + } + aView.SdrPaintView::CompleteRedraw( pOut, aRegion, &aImplRenderPaintProc ); + + if ( pPDFExtOutDevData && pPage ) + { + try + { + uno::Any aAny; + uno::Reference< drawing::XDrawPage > xPage( uno::Reference< drawing::XDrawPage >::query( pPage->getUnoPage() ) ); + if ( xPage.is() ) + { + if ( pPDFExtOutDevData->GetIsExportNotes() ) + ImplPDFExportComments( xPage, *pPDFExtOutDevData ); + uno::Reference< beans::XPropertySet > xPagePropSet( xPage, uno::UNO_QUERY ); + if( xPagePropSet.is() ) + { + // exporting object interactions to pdf + + // if necessary, the master page interactions will be exported first + bool bIsBackgroundObjectsVisible = false; // #i39428# IsBackgroundObjectsVisible not available for Draw + if ( mbImpressDoc && xPagePropSet->getPropertySetInfo()->hasPropertyByName( "IsBackgroundObjectsVisible" ) ) + xPagePropSet->getPropertyValue( "IsBackgroundObjectsVisible" ) >>= bIsBackgroundObjectsVisible; + if ( bIsBackgroundObjectsVisible && !pPDFExtOutDevData->GetIsExportNotesPages() ) + { + uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( xPage, uno::UNO_QUERY ); + if ( xMasterPageTarget.is() ) + { + uno::Reference< drawing::XDrawPage > xMasterPage = xMasterPageTarget->getMasterPage(); + if ( xMasterPage.is() ) + { + sal_Int32 i, nCount = xMasterPage->getCount(); + for ( i = 0; i < nCount; i++ ) + { + aAny = xMasterPage->getByIndex( i ); + uno::Reference< drawing::XShape > xShape; + if ( aAny >>= xShape ) + ImplPDFExportShapeInteraction( xShape, *mpDoc, *pPDFExtOutDevData ); + } + } + } + } + + // exporting slide page object interactions + sal_Int32 i, nCount = xPage->getCount(); + for ( i = 0; i < nCount; i++ ) + { + aAny = xPage->getByIndex( i ); + uno::Reference< drawing::XShape > xShape; + if ( aAny >>= xShape ) + ImplPDFExportShapeInteraction( xShape, *mpDoc, *pPDFExtOutDevData ); + } + + // exporting transition effects to pdf + if ( mbImpressDoc && !pPDFExtOutDevData->GetIsExportNotesPages() && pPDFExtOutDevData->GetIsExportTransitionEffects() ) + { + static const OUStringLiteral sEffect( u"Effect" ); + static const OUStringLiteral sSpeed ( u"Speed" ); + sal_Int32 nTime = 800; + presentation::AnimationSpeed aAs; + if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sSpeed ) ) + { + aAny = xPagePropSet->getPropertyValue( sSpeed ); + if ( aAny >>= aAs ) + { + switch( aAs ) + { + case presentation::AnimationSpeed_SLOW : nTime = 1500; break; + case presentation::AnimationSpeed_FAST : nTime = 300; break; + default: + case presentation::AnimationSpeed_MEDIUM : nTime = 800; + } + } + } + presentation::FadeEffect eFe; + vcl::PDFWriter::PageTransition eType = vcl::PDFWriter::PageTransition::Regular; + if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sEffect ) ) + { + aAny = xPagePropSet->getPropertyValue( sEffect ); + if ( aAny >>= eFe ) + { + switch( eFe ) + { + case presentation::FadeEffect_HORIZONTAL_LINES : + case presentation::FadeEffect_HORIZONTAL_CHECKERBOARD : + case presentation::FadeEffect_HORIZONTAL_STRIPES : eType = vcl::PDFWriter::PageTransition::BlindsHorizontal; break; + + case presentation::FadeEffect_VERTICAL_LINES : + case presentation::FadeEffect_VERTICAL_CHECKERBOARD : + case presentation::FadeEffect_VERTICAL_STRIPES : eType = vcl::PDFWriter::PageTransition::BlindsVertical; break; + + case presentation::FadeEffect_UNCOVER_TO_RIGHT : + case presentation::FadeEffect_UNCOVER_TO_UPPERRIGHT : + case presentation::FadeEffect_ROLL_FROM_LEFT : + case presentation::FadeEffect_FADE_FROM_UPPERLEFT : + case presentation::FadeEffect_MOVE_FROM_UPPERLEFT : + case presentation::FadeEffect_FADE_FROM_LEFT : + case presentation::FadeEffect_MOVE_FROM_LEFT : eType = vcl::PDFWriter::PageTransition::WipeLeftToRight; break; + + case presentation::FadeEffect_UNCOVER_TO_BOTTOM : + case presentation::FadeEffect_UNCOVER_TO_LOWERRIGHT : + case presentation::FadeEffect_ROLL_FROM_TOP : + case presentation::FadeEffect_FADE_FROM_UPPERRIGHT : + case presentation::FadeEffect_MOVE_FROM_UPPERRIGHT : + case presentation::FadeEffect_FADE_FROM_TOP : + case presentation::FadeEffect_MOVE_FROM_TOP : eType = vcl::PDFWriter::PageTransition::WipeTopToBottom; break; + + case presentation::FadeEffect_UNCOVER_TO_LEFT : + case presentation::FadeEffect_UNCOVER_TO_LOWERLEFT : + case presentation::FadeEffect_ROLL_FROM_RIGHT : + + case presentation::FadeEffect_FADE_FROM_LOWERRIGHT : + case presentation::FadeEffect_MOVE_FROM_LOWERRIGHT : + case presentation::FadeEffect_FADE_FROM_RIGHT : + case presentation::FadeEffect_MOVE_FROM_RIGHT : eType = vcl::PDFWriter::PageTransition::WipeRightToLeft; break; + + case presentation::FadeEffect_UNCOVER_TO_TOP : + case presentation::FadeEffect_UNCOVER_TO_UPPERLEFT : + case presentation::FadeEffect_ROLL_FROM_BOTTOM : + case presentation::FadeEffect_FADE_FROM_LOWERLEFT : + case presentation::FadeEffect_MOVE_FROM_LOWERLEFT : + case presentation::FadeEffect_FADE_FROM_BOTTOM : + case presentation::FadeEffect_MOVE_FROM_BOTTOM : eType = vcl::PDFWriter::PageTransition::WipeBottomToTop; break; + + case presentation::FadeEffect_OPEN_VERTICAL : eType = vcl::PDFWriter::PageTransition::SplitHorizontalInward; break; + case presentation::FadeEffect_CLOSE_HORIZONTAL : eType = vcl::PDFWriter::PageTransition::SplitHorizontalOutward; break; + + case presentation::FadeEffect_OPEN_HORIZONTAL : eType = vcl::PDFWriter::PageTransition::SplitVerticalInward; break; + case presentation::FadeEffect_CLOSE_VERTICAL : eType = vcl::PDFWriter::PageTransition::SplitVerticalOutward; break; + + case presentation::FadeEffect_FADE_TO_CENTER : eType = vcl::PDFWriter::PageTransition::BoxInward; break; + case presentation::FadeEffect_FADE_FROM_CENTER : eType = vcl::PDFWriter::PageTransition::BoxOutward; break; + + case presentation::FadeEffect_NONE : eType = vcl::PDFWriter::PageTransition::Regular; break; + + case presentation::FadeEffect_RANDOM : + case presentation::FadeEffect_DISSOLVE : + default: eType = vcl::PDFWriter::PageTransition::Dissolve; break; + } + } + } + + if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sEffect ) || + xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sSpeed ) ) + { + pPDFExtOutDevData->SetPageTransition( eType, nTime ); + } + } + } + } + + Size aPageSize( mpDoc->GetSdPage( 0, PageKind::Standard )->GetSize() ); + Point aPoint( 0, 0 ); + ::tools::Rectangle aPageRect( aPoint, aPageSize ); + + // resolving links found in this page by the method ImpEditEngine::Paint + std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks(); + for ( const auto& rBookmark : rBookmarks ) + { + sal_Int32 nPage = ImplPDFGetBookmarkPage( rBookmark.aBookmark, *mpDoc ); + if ( nPage != -1 ) + { + if ( rBookmark.nLinkId != -1 ) + pPDFExtOutDevData->SetLinkDest( rBookmark.nLinkId, pPDFExtOutDevData->CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ) ); + else + pPDFExtOutDevData->DescribeRegisteredDest( rBookmark.nDestId, aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ); + } + else + pPDFExtOutDevData->SetLinkURL( rBookmark.nLinkId, rBookmark.aBookmark ); + } + rBookmarks.clear(); + //---> #i56629, #i40318 + //get the page name, will be used as outline element in PDF bookmark pane + OUString aPageName = mpDoc->GetSdPage( static_cast<sal_uInt16>(nPageNumber) - 1 , PageKind::Standard )->GetName(); + if( !aPageName.isEmpty() ) + { + // Destination PageNum + const sal_Int32 nDestPageNum = CalcOutputPageNum(pPDFExtOutDevData, mpDoc, nPageNumber); + + // insert the bookmark to this page into the NamedDestinations + if( pPDFExtOutDevData->GetIsExportNamedDestinations() ) + pPDFExtOutDevData->CreateNamedDest(aPageName, aPageRect, nDestPageNum); + + // add the name to the outline, (almost) same code as in sc/source/ui/unoobj/docuno.cxx + // issue #i40318. + + if( pPDFExtOutDevData->GetIsExportBookmarks() ) + { + // Destination Export + const sal_Int32 nDestId = + pPDFExtOutDevData->CreateDest(aPageRect , nDestPageNum); + + // Create a new outline item: + pPDFExtOutDevData->CreateOutlineItem( -1 , aPageName, nDestId ); + } + } + //<--- #i56629, #i40318 + } + catch (const uno::Exception&) + { + } + + } + } + else + { + uno::Reference< drawing::XShapes > xShapes; + rSelection >>= xShapes; + + if( xShapes.is() && xShapes->getCount() ) + { + SdrPageView* pPV = nullptr; + + ImplRenderPaintProc aImplRenderPaintProc( mpDoc->GetLayerAdmin(), + pOldSdView ? pOldSdView->GetSdrPageView() : nullptr); + + for( sal_uInt32 i = 0, nCount = xShapes->getCount(); i < nCount; i++ ) + { + uno::Reference< drawing::XShape > xShape; + xShapes->getByIndex( i ) >>= xShape; + + if( xShape.is() ) + { + SdrObject* pObj = SdrObject::getSdrObjectFromXShape( xShape ); + if( pObj && pObj->getSdrPageFromSdrObject() + && aImplRenderPaintProc.IsVisible( pObj ) + && aImplRenderPaintProc.IsPrintable( pObj ) ) + { + if( !pPV ) + pPV = aView.ShowSdrPage( pObj->getSdrPageFromSdrObject() ); + + if( pPV ) + aView.MarkObj( pObj, pPV ); + } + } + } + aView.DrawMarkedObj(*pOut); + } + } +} + +DrawViewShell* SdXImpressDocument::GetViewShell() +{ + DrawViewShell* pViewSh = dynamic_cast<DrawViewShell*>(mpDocShell->GetViewShell()); + if (!pViewSh) + { + SAL_WARN("sd", "DrawViewShell not available!"); + return nullptr; + } + return pViewSh; +} + +void SdXImpressDocument::paintTile( VirtualDevice& rDevice, + int nOutputWidth, int nOutputHeight, + int nTilePosX, int nTilePosY, + ::tools::Long nTileWidth, ::tools::Long nTileHeight ) +{ + DrawViewShell* pViewSh = GetViewShell(); + if (!pViewSh) + return; + + // Setup drawing layer to work properly. Since we use a custom VirtualDevice + // for the drawing, SdrPaintView::BeginCompleteRedraw() will call FindPaintWindow() + // unsuccessfully and use a temporary window that doesn't keep state. So patch + // the existing SdrPageWindow to use a temporary, and this way the state will be kept. + // Well, at least that's how I understand it based on Writer's RenderContextGuard, + // as the drawing layer classes lack documentation. + SdrPageWindow* patchedPageWindow = nullptr; + SdrPaintWindow* previousPaintWindow = nullptr; + std::unique_ptr<SdrPaintWindow> temporaryPaintWindow; + if(SdrView* pDrawView = pViewSh->GetDrawView()) + { + if(SdrPageView* pSdrPageView = pDrawView->GetSdrPageView()) + { + patchedPageWindow = pSdrPageView->FindPageWindow(*getDocWindow()->GetOutDev()); + temporaryPaintWindow.reset(new SdrPaintWindow(*pDrawView, rDevice)); + if (patchedPageWindow) + previousPaintWindow = patchedPageWindow->patchPaintWindow(*temporaryPaintWindow); + } + } + + // Scaling. Must convert from pixels to twips. We know + // that VirtualDevices use a DPI of 96. + // We specifically calculate these scales first as we're still + // in TWIPs, and might as well minimize the number of conversions. + const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip); + Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale; + Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale; + + // svx seems to be the only component that works natively in + // 100th mm rather than TWIP. It makes most sense just to + // convert here and in getDocumentSize, and leave the tiled + // rendering API working in TWIPs. + ::tools::Long nTileWidthHMM = convertTwipToMm100( nTileWidth ); + ::tools::Long nTileHeightHMM = convertTwipToMm100( nTileHeight ); + int nTilePosXHMM = convertTwipToMm100( nTilePosX ); + int nTilePosYHMM = convertTwipToMm100( nTilePosY ); + + MapMode aMapMode = rDevice.GetMapMode(); + aMapMode.SetMapUnit( MapUnit::Map100thMM ); + aMapMode.SetOrigin( Point( -nTilePosXHMM, + -nTilePosYHMM) ); + aMapMode.SetScaleX( scaleX ); + aMapMode.SetScaleY( scaleY ); + + rDevice.SetMapMode( aMapMode ); + + rDevice.SetOutputSizePixel( Size(nOutputWidth, nOutputHeight) ); + + Point aPoint(nTilePosXHMM, nTilePosYHMM); + Size aSize(nTileWidthHMM, nTileHeightHMM); + ::tools::Rectangle aRect(aPoint, aSize); + + pViewSh->GetView()->CompleteRedraw(&rDevice, vcl::Region(aRect)); + + LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight, + nTilePosX, nTilePosY, nTileWidth, nTileHeight); + + if(patchedPageWindow != nullptr) + patchedPageWindow->unpatchPaintWindow(previousPaintWindow); +} + +void SdXImpressDocument::selectPart(int nPart, int nSelect) +{ + DrawViewShell* pViewSh = GetViewShell(); + if (!pViewSh) + return; + + pViewSh->SelectPage(nPart, nSelect); +} + +void SdXImpressDocument::moveSelectedParts(int nPosition, bool bDuplicate) +{ + // Duplicating is currently unsupported. + if (!bDuplicate) + mpDoc->MovePages(nPosition); +} + +OUString SdXImpressDocument::getPartInfo(int nPart) +{ + DrawViewShell* pViewSh = GetViewShell(); + if (!pViewSh) + return OUString(); + + const bool bIsVisible = pViewSh->IsVisible(nPart); + const bool bIsSelected = pViewSh->IsSelected(nPart); + const sal_Int16 nMasterPageCount= pViewSh->GetDoc()->GetMasterSdPageCount(pViewSh->GetPageKind()); + + OUString aPartInfo = "{ \"visible\": \"" + + OUString::number(static_cast<unsigned int>(bIsVisible)) + + "\", \"selected\": \"" + + OUString::number(static_cast<unsigned int>(bIsSelected)) + + "\", \"masterPageCount\": \"" + + OUString::number(nMasterPageCount) + + "\" }"; + return aPartInfo; +} + +void SdXImpressDocument::setPart( int nPart, bool bAllowChangeFocus ) +{ + DrawViewShell* pViewSh = GetViewShell(); + if (!pViewSh) + return; + + pViewSh->SwitchPage( nPart, bAllowChangeFocus ); +} + +int SdXImpressDocument::getParts() +{ + if (!mpDoc) + return 0; + + if (isMasterViewMode()) + return mpDoc->GetMasterSdPageCount(PageKind::Standard); + + return mpDoc->GetSdPageCount(PageKind::Standard); +} + +int SdXImpressDocument::getPart() +{ + DrawViewShell* pViewSh = GetViewShell(); + if (!pViewSh) + return 0; + + return pViewSh->GetViewShellBase().getPart(); +} + +OUString SdXImpressDocument::getPartName(int nPart) +{ + SdPage* pPage; + if (isMasterViewMode()) + pPage = mpDoc->GetMasterSdPage(nPart, PageKind::Standard); + else + pPage = mpDoc->GetSdPage(nPart, PageKind::Standard); + + if (!pPage) + { + SAL_WARN("sd", "DrawViewShell not available!"); + return OUString(); + } + + return pPage->GetName(); +} + +OUString SdXImpressDocument::getPartHash(int nPart) +{ + SdPage* pPage; + if (isMasterViewMode()) + pPage = mpDoc->GetMasterSdPage(nPart, PageKind::Standard); + else + pPage = mpDoc->GetSdPage(nPart, PageKind::Standard); + + if (!pPage) + { + SAL_WARN("sd", "DrawViewShell not available!"); + return OUString(); + } + + return OUString::number(pPage->GetHashCode()); +} + +bool SdXImpressDocument::isMasterViewMode() +{ + DrawViewShell* pViewSh = GetViewShell(); + if (!pViewSh) + return false; + + if (pViewSh->GetDispatcher()) + { + const SfxBoolItem* isMasterViewMode = nullptr; + pViewSh->GetDispatcher()->QueryState(SID_SLIDE_MASTER_MODE, isMasterViewMode); + if (isMasterViewMode && isMasterViewMode->GetValue()) + return true; + } + return false; +} + +VclPtr<vcl::Window> SdXImpressDocument::getDocWindow() +{ + SolarMutexGuard aGuard; + DrawViewShell* pViewShell = GetViewShell(); + VclPtr<vcl::Window> pWindow; + if (pViewShell) + pWindow = pViewShell->GetActiveWindow(); + + LokChartHelper aChartHelper(pViewShell->GetViewShell()); + VclPtr<vcl::Window> pChartWindow = aChartHelper.GetWindow(); + if (pChartWindow) + pWindow = pChartWindow; + + return pWindow; +} + +void SdXImpressDocument::setPartMode( int nPartMode ) +{ + DrawViewShell* pViewSh = GetViewShell(); + if (!pViewSh) + return; + + PageKind aPageKind( PageKind::Standard ); + switch ( nPartMode ) + { + case LOK_PARTMODE_SLIDES: + break; + case LOK_PARTMODE_NOTES: + aPageKind = PageKind::Notes; + break; + } + pViewSh->SetPageKind( aPageKind ); +} + +Size SdXImpressDocument::getDocumentSize() +{ + DrawViewShell* pViewSh = GetViewShell(); + if (!pViewSh) + return Size(); + + SdrView *pSdrView = pViewSh->GetView(); + if (!pSdrView) + return Size(); + + SdrPageView* pCurPageView = pSdrView->GetSdrPageView(); + if (!pCurPageView) + return Size(); + + Size aSize = pCurPageView->GetPageRect().GetSize(); + // Convert the size in 100th mm to TWIP + // See paintTile above for further info. + return o3tl::convert(aSize, o3tl::Length::mm100, o3tl::Length::twip); +} + +void SdXImpressDocument::getPostIts(::tools::JsonWriter& rJsonWriter) +{ + auto commentsNode = rJsonWriter.startNode("comments"); + // Return annotations on master pages too ? + const sal_uInt16 nMaxPages = mpDoc->GetPageCount(); + SdPage* pPage; + for (sal_uInt16 nPage = 0; nPage < nMaxPages; ++nPage) + { + pPage = static_cast<SdPage*>(mpDoc->GetPage(nPage)); + const sd::AnnotationVector& aPageAnnotations = pPage->getAnnotations(); + + for (const uno::Reference<office::XAnnotation>& xAnnotation : aPageAnnotations) + { + sal_uInt32 nID = sd::getAnnotationId(xAnnotation); + OString nodeName = "comment" + OString::number(nID); + auto commentNode = rJsonWriter.startNode(nodeName.getStr()); + rJsonWriter.put("id", nID); + rJsonWriter.put("author", xAnnotation->getAuthor()); + rJsonWriter.put("dateTime", utl::toISO8601(xAnnotation->getDateTime())); + uno::Reference<text::XText> xText(xAnnotation->getTextRange()); + rJsonWriter.put("text", xText->getString()); + rJsonWriter.put("parthash", pPage->GetHashCode()); + geometry::RealPoint2D const & rPoint = xAnnotation->getPosition(); + geometry::RealSize2D const & rSize = xAnnotation->getSize(); + ::tools::Rectangle aRectangle(Point(rPoint.X * 100.0, rPoint.Y * 100.0), Size(rSize.Width * 100.0, rSize.Height * 100.0)); + aRectangle = o3tl::toTwips(aRectangle, o3tl::Length::mm100); + OString sRectangle = aRectangle.toString(); + rJsonWriter.put("rectangle", sRectangle.getStr()); + } + } +} + +void SdXImpressDocument::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments) +{ + SolarMutexGuard aGuard; + + if (DrawViewShell* pViewShell = GetViewShell()) + { + DrawView* pDrawView = pViewShell->GetDrawView(); + for (const beans::PropertyValue& rValue : rArguments) + { + if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has<bool>()) + pDrawView->SetPageShadowVisible(rValue.Value.get<bool>()); + else if (rValue.Name == ".uno:Author" && rValue.Value.has<OUString>()) + pDrawView->SetAuthor(rValue.Value.get<OUString>()); + else if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>()) + mpDoc->SetOnlineSpell(rValue.Value.get<bool>()); + } + + // Disable comments if requested + SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType()); + pOptions->SetShowComments(comphelper::LibreOfficeKit::isTiledAnnotations()); + + pViewShell->SetRuler(false); + pViewShell->SetScrollBarsVisible(false); + + if (sd::Window* pWindow = pViewShell->GetActiveWindow()) + { + // get the full page size in pixels + pWindow->EnableMapMode(); + Size aSize(pWindow->LogicToPixel(pDrawView->GetSdrPageView()->GetPage()->GetSize())); + // Disable map mode, so that it's possible to send mouse event + // coordinates in logic units + pWindow->EnableMapMode(false); + + // arrange UI elements again with new view size + pViewShell->GetParentWindow()->SetSizePixel(aSize); + pViewShell->Resize(); + } + + // Forces all images to be swapped in synchronously, this + // ensures that images are available when paintTile is called + // (whereas with async loading images start being loaded after + // we have painted the tile, resulting in an invalidate, followed + // by the tile being rerendered - which is wasteful and ugly). + pDrawView->SetSwapAsynchron(false); + } + + // when the "This document may contain formatting or content that cannot + // be saved..." dialog appears, it is auto-cancelled with tiled rendering, + // causing 'Save' being disabled; so let's always save to the original + // format + auto xChanges = comphelper::ConfigurationChanges::create(); + officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges); + xChanges->commit(); + + if (!getenv("LO_TESTNAME")) + SvtSlideSorterBarOptions().SetVisibleImpressView(true); +} + +void SdXImpressDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode) +{ + SolarMutexGuard aGuard; + SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode); +} + +void SdXImpressDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier) +{ + SolarMutexGuard aGuard; + + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return; + + constexpr double fScale = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::px); + + // check if user hit a chart which is being edited by him + LokChartHelper aChartHelper(pViewShell->GetViewShell()); + if (aChartHelper.postMouseEvent(nType, nX, nY, + nCount, nButtons, nModifier, + fScale, fScale)) + return; + + // check if the user hit a chart which is being edited by someone else + // and, if so, skip current mouse event + if (nType != LOK_MOUSEEVENT_MOUSEMOVE) + { + if (LokChartHelper::HitAny(Point(nX, nY))) + return; + } + + const Point aPos(Point(convertTwipToMm100(nX), convertTwipToMm100(nY))); + LokMouseEventData aMouseEventData(nType, aPos, nCount, MouseEventModifiers::SIMPLECLICK, + nButtons, nModifier); + SfxLokHelper::postMouseEventAsync(pViewShell->GetActiveWindow(), aMouseEventData); +} + +void SdXImpressDocument::setTextSelection(int nType, int nX, int nY) +{ + SolarMutexGuard aGuard; + + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return; + + LokChartHelper aChartHelper(pViewShell->GetViewShell()); + if (aChartHelper.setTextSelection(nType, nX, nY)) + return; + + Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY)); + switch (nType) + { + case LOK_SETTEXTSELECTION_START: + pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/false, /*bClearMark=*/false); + break; + case LOK_SETTEXTSELECTION_END: + pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/false); + break; + case LOK_SETTEXTSELECTION_RESET: + pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/true); + break; + default: + assert(false); + break; + } +} + +uno::Reference<datatransfer::XTransferable> SdXImpressDocument::getSelection() +{ + SolarMutexGuard aGuard; + + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return uno::Reference<datatransfer::XTransferable>(); + + return pViewShell->GetSelectionTransferrable(); +} + +void SdXImpressDocument::setGraphicSelection(int nType, int nX, int nY) +{ + SolarMutexGuard aGuard; + + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return; + + constexpr double fScale = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::px); + + LokChartHelper aChartHelper(pViewShell->GetViewShell()); + if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale)) + return; + + Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY)); + switch (nType) + { + case LOK_SETGRAPHICSELECTION_START: + pViewShell->SetGraphicMm100Position(/*bStart=*/true, aPoint); + break; + case LOK_SETGRAPHICSELECTION_END: + pViewShell->SetGraphicMm100Position(/*bStart=*/false, aPoint); + break; + default: + assert(false); + break; + } +} + +void SdXImpressDocument::resetSelection() +{ + SolarMutexGuard aGuard; + + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return; + + SdrView* pSdrView = pViewShell->GetView(); + if (!pSdrView) + return; + + if (pSdrView->IsTextEdit()) + { + // Reset the editeng selection. + pSdrView->UnmarkAll(); + // Finish editing. + pSdrView->SdrEndTextEdit(); + } + // Reset graphic selection. + pSdrView->UnmarkAll(); +} + +void SdXImpressDocument::setClientVisibleArea(const ::tools::Rectangle& rRectangle) +{ + SolarMutexGuard aGuard; + + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return; + + pViewShell->GetViewShellBase().setLOKVisibleArea(rRectangle); +} + +void SdXImpressDocument::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard) +{ + SolarMutexGuard aGuard; + + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return; + + pViewShell->GetActiveWindow()->SetClipboard(xClipboard); +} + +bool SdXImpressDocument::isMimeTypeSupported() +{ + SolarMutexGuard aGuard; + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return false; + + TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(pViewShell->GetActiveWindow())); + return EditEngine::HasValidData(aDataHelper.GetTransferable()); +} + +PointerStyle SdXImpressDocument::getPointer() +{ + SolarMutexGuard aGuard; + DrawViewShell* pViewShell = GetViewShell(); + if (!pViewShell) + return PointerStyle::Arrow; + + Window* pWindow = pViewShell->GetActiveWindow(); + if (!pWindow) + return PointerStyle::Arrow; + + return pWindow->GetPointer(); +} + +uno::Reference< i18n::XForbiddenCharacters > SdXImpressDocument::getForbiddenCharsTable() +{ + uno::Reference< i18n::XForbiddenCharacters > xForb(mxForbiddenCharacters); + + if( !xForb.is() ) + mxForbiddenCharacters = xForb = new SdUnoForbiddenCharsTable( mpDoc ); + + return xForb; +} + +void SdXImpressDocument::initializeDocument() +{ + if( mbClipBoard ) + return; + + switch( mpDoc->GetPageCount() ) + { + case 1: + { + // nasty hack to detect clipboard document + mbClipBoard = true; + break; + } + case 0: + { + mpDoc->CreateFirstPages(); + mpDoc->StopWorkStartupDelay(); + break; + } + } +} + +SdrModel& SdXImpressDocument::getSdrModelFromUnoModel() const +{ + OSL_ENSURE(GetDoc(), "No SdrModel in draw/Impress, should not happen"); + return *GetDoc(); // TTTT should be reference +} + +void SAL_CALL SdXImpressDocument::dispose() +{ + if( mbDisposed ) + return; + + ::SolarMutexGuard aGuard; + + if( mpDoc ) + { + EndListening( *mpDoc ); + mpDoc = nullptr; + } + + // Call the base class dispose() before setting the mbDisposed flag + // to true. The reason for this is that if close() has not yet been + // called this is done in SfxBaseModel::dispose(). At the end of + // that dispose() is called again. It is important to forward this + // second dispose() to the base class, too. + // As a consequence the following code has to be able to be run twice. + SfxBaseModel::dispose(); + mbDisposed = true; + + uno::Reference< container::XNameAccess > xLinks( mxLinks ); + if( xLinks.is() ) + { + uno::Reference< lang::XComponent > xComp( xLinks, uno::UNO_QUERY ); + if( xComp.is() ) + xComp->dispose(); + + xLinks = nullptr; + } + + uno::Reference< drawing::XDrawPages > xDrawPagesAccess( mxDrawPagesAccess ); + if( xDrawPagesAccess.is() ) + { + uno::Reference< lang::XComponent > xComp( xDrawPagesAccess, uno::UNO_QUERY ); + if( xComp.is() ) + xComp->dispose(); + + xDrawPagesAccess = nullptr; + } + + uno::Reference< drawing::XDrawPages > xMasterPagesAccess( mxMasterPagesAccess ); + if( xDrawPagesAccess.is() ) + { + uno::Reference< lang::XComponent > xComp( xMasterPagesAccess, uno::UNO_QUERY ); + if( xComp.is() ) + xComp->dispose(); + + xDrawPagesAccess = nullptr; + } + + uno::Reference< container::XNameAccess > xLayerManager( mxLayerManager ); + if( xLayerManager.is() ) + { + uno::Reference< lang::XComponent > xComp( xLayerManager, uno::UNO_QUERY ); + if( xComp.is() ) + xComp->dispose(); + + xLayerManager = nullptr; + } + + uno::Reference< container::XNameContainer > xCustomPresentationAccess( mxCustomPresentationAccess ); + if( xCustomPresentationAccess.is() ) + { + uno::Reference< lang::XComponent > xComp( xCustomPresentationAccess, uno::UNO_QUERY ); + if( xComp.is() ) + xComp->dispose(); + + xCustomPresentationAccess = nullptr; + } + + mxDashTable = nullptr; + mxGradientTable = nullptr; + mxHatchTable = nullptr; + mxBitmapTable = nullptr; + mxTransGradientTable = nullptr; + mxMarkerTable = nullptr; + mxDrawingPool = nullptr; +} + + +SdDrawPagesAccess::SdDrawPagesAccess( SdXImpressDocument& rMyModel ) noexcept +: mpModel( &rMyModel) +{ +} + +SdDrawPagesAccess::~SdDrawPagesAccess() noexcept +{ +} + +// XIndexAccess +sal_Int32 SAL_CALL SdDrawPagesAccess::getCount() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + return mpModel->mpDoc->GetSdPageCount( PageKind::Standard ); +} + +uno::Any SAL_CALL SdDrawPagesAccess::getByIndex( sal_Int32 Index ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + uno::Any aAny; + + if( (Index < 0) || (Index >= mpModel->mpDoc->GetSdPageCount( PageKind::Standard ) ) ) + throw lang::IndexOutOfBoundsException(); + + SdPage* pPage = mpModel->mpDoc->GetSdPage( static_cast<sal_uInt16>(Index), PageKind::Standard ); + if( pPage ) + { + uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); + aAny <<= xDrawPage; + } + + return aAny; +} + +// XNameAccess +uno::Any SAL_CALL SdDrawPagesAccess::getByName( const OUString& aName ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + if( !aName.isEmpty() ) + { + const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard ); + sal_uInt16 nPage; + for( nPage = 0; nPage < nCount; nPage++ ) + { + SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard ); + if(nullptr == pPage) + continue; + + if( aName == SdDrawPage::getPageApiName( pPage ) ) + { + uno::Any aAny; + uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); + aAny <<= xDrawPage; + return aAny; + } + } + } + + throw container::NoSuchElementException(); +} + +uno::Sequence< OUString > SAL_CALL SdDrawPagesAccess::getElementNames() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard ); + uno::Sequence< OUString > aNames( nCount ); + OUString* pNames = aNames.getArray(); + + sal_uInt16 nPage; + for( nPage = 0; nPage < nCount; nPage++ ) + { + SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard ); + *pNames++ = SdDrawPage::getPageApiName( pPage ); + } + + return aNames; +} + +sal_Bool SAL_CALL SdDrawPagesAccess::hasByName( const OUString& aName ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard ); + sal_uInt16 nPage; + for( nPage = 0; nPage < nCount; nPage++ ) + { + SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard ); + if(nullptr == pPage) + continue; + + if( aName == SdDrawPage::getPageApiName( pPage ) ) + return true; + } + + return false; +} + +// XElementAccess +uno::Type SAL_CALL SdDrawPagesAccess::getElementType() +{ + return cppu::UnoType<drawing::XDrawPage>::get(); +} + +sal_Bool SAL_CALL SdDrawPagesAccess::hasElements() +{ + return getCount() > 0; +} + +// XDrawPages + +/** + * Creates a new page with model at the specified position. + * @returns corresponding SdDrawPage + */ +uno::Reference< drawing::XDrawPage > SAL_CALL SdDrawPagesAccess::insertNewByIndex( sal_Int32 nIndex ) +{ + ::SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("insertNewByIndex"); + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + if( mpModel->mpDoc ) + { + SdPage* pPage = mpModel->InsertSdPage( static_cast<sal_uInt16>(nIndex), false ); + if( pPage ) + { + uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); + return xDrawPage; + } + } + uno::Reference< drawing::XDrawPage > xDrawPage; + return xDrawPage; +} + +/** + * Removes the specified SdDrawPage from the model and the internal list. It + * only works, if there is at least one *normal* page in the model after + * removing this page. + */ +void SAL_CALL SdDrawPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel || mpModel->mpDoc == nullptr ) + throw lang::DisposedException(); + + SdDrawDocument& rDoc = *mpModel->mpDoc; + + sal_uInt16 nPageCount = rDoc.GetSdPageCount( PageKind::Standard ); + if( nPageCount > 1 ) + { + // get pPage from xPage and determine the Id (nPos ) afterwards + SdDrawPage* pSvxPage = comphelper::getFromUnoTunnel<SdDrawPage>( xPage ); + if( pSvxPage ) + { + SdPage* pPage = static_cast<SdPage*>(pSvxPage->GetSdrPage()); + if(pPage && ( pPage->GetPageKind() == PageKind::Standard ) ) + { + sal_uInt16 nPage = pPage->GetPageNum(); + + SdPage* pNotesPage = static_cast< SdPage* >( rDoc.GetPage( nPage+1 ) ); + + bool bUndo = rDoc.IsUndoEnabled(); + if( bUndo ) + { + // Add undo actions and delete the pages. The order of adding + // the undo actions is important. + rDoc.BegUndo( SdResId( STR_UNDO_DELETEPAGES ) ); + rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage)); + rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage)); + } + + rDoc.RemovePage( nPage ); // the page + rDoc.RemovePage( nPage ); // the notes page + + if( bUndo ) + { + rDoc.EndUndo(); + } + } + } + } + + mpModel->SetModified(); +} + +// XServiceInfo + +OUString SAL_CALL SdDrawPagesAccess::getImplementationName( ) +{ + return "SdDrawPagesAccess"; +} + +sal_Bool SAL_CALL SdDrawPagesAccess::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL SdDrawPagesAccess::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.DrawPages" }; +} + +// XComponent +void SAL_CALL SdDrawPagesAccess::dispose( ) +{ + mpModel = nullptr; +} + +void SAL_CALL SdDrawPagesAccess::addEventListener( const uno::Reference< lang::XEventListener >& ) +{ + OSL_FAIL( "not implemented!" ); +} + +void SAL_CALL SdDrawPagesAccess::removeEventListener( const uno::Reference< lang::XEventListener >& ) +{ + OSL_FAIL( "not implemented!" ); +} + + +SdMasterPagesAccess::SdMasterPagesAccess( SdXImpressDocument& rMyModel ) noexcept +: mpModel(&rMyModel) +{ +} + +SdMasterPagesAccess::~SdMasterPagesAccess() noexcept +{ +} + +// XComponent +void SAL_CALL SdMasterPagesAccess::dispose( ) +{ + mpModel = nullptr; +} + +void SAL_CALL SdMasterPagesAccess::addEventListener( const uno::Reference< lang::XEventListener >& ) +{ + OSL_FAIL( "not implemented!" ); +} + +void SAL_CALL SdMasterPagesAccess::removeEventListener( const uno::Reference< lang::XEventListener >& ) +{ + OSL_FAIL( "not implemented!" ); +} + +// XIndexAccess +sal_Int32 SAL_CALL SdMasterPagesAccess::getCount() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel->mpDoc ) + throw lang::DisposedException(); + + return mpModel->mpDoc->GetMasterSdPageCount(PageKind::Standard); +} + +/** + * Provides a drawing::XDrawPage interface for accessing the Masterpage at the + * specified position in the model. + */ +uno::Any SAL_CALL SdMasterPagesAccess::getByIndex( sal_Int32 Index ) +{ + ::SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("SdMasterPagesAccess::getByIndex"); + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + uno::Any aAny; + + if( (Index < 0) || (Index >= mpModel->mpDoc->GetMasterSdPageCount( PageKind::Standard ) ) ) + throw lang::IndexOutOfBoundsException(); + + SdPage* pPage = mpModel->mpDoc->GetMasterSdPage( static_cast<sal_uInt16>(Index), PageKind::Standard ); + if( pPage ) + { + uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); + aAny <<= xDrawPage; + } + + return aAny; +} + +// XElementAccess +uno::Type SAL_CALL SdMasterPagesAccess::getElementType() +{ + return cppu::UnoType<drawing::XDrawPage>::get(); +} + +sal_Bool SAL_CALL SdMasterPagesAccess::hasElements() +{ + return getCount() > 0; +} + +// XDrawPages +uno::Reference< drawing::XDrawPage > SAL_CALL SdMasterPagesAccess::insertNewByIndex( sal_Int32 nInsertPos ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + uno::Reference< drawing::XDrawPage > xDrawPage; + + SdDrawDocument* pDoc = mpModel->mpDoc; + if( pDoc ) + { + // calculate internal index and check for range errors + const sal_Int32 nMPageCount = pDoc->GetMasterPageCount(); + nInsertPos = nInsertPos * 2 + 1; + if( nInsertPos < 0 || nInsertPos > nMPageCount ) + nInsertPos = nMPageCount; + + // now generate a unique name for the new masterpage + const OUString aStdPrefix( SdResId(STR_LAYOUT_DEFAULT_NAME) ); + OUString aPrefix( aStdPrefix ); + + bool bUnique = true; + + std::vector<OUString> aPageNames; + for (sal_Int32 nMaster = 1; nMaster < nMPageCount; ++nMaster) + { + const SdPage* pPage = static_cast<const SdPage*>(pDoc->GetMasterPage(static_cast<sal_uInt16>(nMaster))); + if (!pPage) + continue; + aPageNames.push_back(pPage->GetName()); + if (aPageNames.back() == aPrefix) + bUnique = false; + } + + sal_Int32 i = 0; + while (!bUnique) + { + aPrefix = aStdPrefix + " " + OUString::number(++i); + bUnique = std::find(aPageNames.begin(), aPageNames.end(), aPrefix) == aPageNames.end(); + } + + OUString aLayoutName = aPrefix + SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE; + + // create styles + static_cast<SdStyleSheetPool*>(pDoc->GetStyleSheetPool())->CreateLayoutStyleSheets( aPrefix ); + + // get the first page for initial size and border settings + SdPage* pPage = mpModel->mpDoc->GetSdPage( sal_uInt16(0), PageKind::Standard ); + SdPage* pRefNotesPage = mpModel->mpDoc->GetSdPage( sal_uInt16(0), PageKind::Notes); + + // create and insert new draw masterpage + rtl::Reference<SdPage> pMPage = mpModel->mpDoc->AllocSdPage(true); + pMPage->SetSize( pPage->GetSize() ); + pMPage->SetBorder( pPage->GetLeftBorder(), + pPage->GetUpperBorder(), + pPage->GetRightBorder(), + pPage->GetLowerBorder() ); + pMPage->SetLayoutName( aLayoutName ); + pDoc->InsertMasterPage(pMPage.get(), static_cast<sal_uInt16>(nInsertPos)); + + { + // ensure default MasterPage fill + pMPage->EnsureMasterPageDefaultBackground(); + } + + xDrawPage.set( pMPage->getUnoPage(), uno::UNO_QUERY ); + + // create and insert new notes masterpage + rtl::Reference<SdPage> pMNotesPage = mpModel->mpDoc->AllocSdPage(true); + pMNotesPage->SetSize( pRefNotesPage->GetSize() ); + pMNotesPage->SetPageKind(PageKind::Notes); + pMNotesPage->SetBorder( pRefNotesPage->GetLeftBorder(), + pRefNotesPage->GetUpperBorder(), + pRefNotesPage->GetRightBorder(), + pRefNotesPage->GetLowerBorder() ); + pMNotesPage->SetLayoutName( aLayoutName ); + pDoc->InsertMasterPage(pMNotesPage.get(), static_cast<sal_uInt16>(nInsertPos) + 1); + pMNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true, true); + mpModel->SetModified(); + } + + return xDrawPage; +} + +/** + * Removes the specified SdMasterPage from the model and the internal list. It + * only works, if there is no *normal* page using this page as MasterPage in + * the model. + */ +void SAL_CALL SdMasterPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel || mpModel->mpDoc == nullptr ) + throw lang::DisposedException(); + + SdMasterPage* pSdPage = comphelper::getFromUnoTunnel<SdMasterPage>( xPage ); + if(pSdPage == nullptr) + return; + + SdPage* pPage = dynamic_cast< SdPage* > (pSdPage->GetSdrPage()); + + DBG_ASSERT( pPage && pPage->IsMasterPage(), "SdMasterPage is not masterpage?"); + + if( !pPage || !pPage->IsMasterPage() || (mpModel->mpDoc->GetMasterPageUserCount(pPage) > 0)) + return; //Todo: this should be excepted + + // only standard pages can be removed directly + if( pPage->GetPageKind() != PageKind::Standard ) + return; + + sal_uInt16 nPage = pPage->GetPageNum(); + + SdDrawDocument& rDoc = *mpModel->mpDoc; + + SdPage* pNotesPage = static_cast< SdPage* >( rDoc.GetMasterPage( nPage+1 ) ); + + bool bUndo = rDoc.IsUndoEnabled(); + if( bUndo ) + { + // Add undo actions and delete the pages. The order of adding + // the undo actions is important. + rDoc.BegUndo( SdResId( STR_UNDO_DELETEPAGES ) ); + rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage)); + rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage)); + } + + // remove both pages + rDoc.RemoveMasterPage( nPage ); + rDoc.RemoveMasterPage( nPage ); + + if( bUndo ) + { + rDoc.EndUndo(); + } +} + +// XServiceInfo + +OUString SAL_CALL SdMasterPagesAccess::getImplementationName( ) +{ + return "SdMasterPagesAccess"; +} + +sal_Bool SAL_CALL SdMasterPagesAccess::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL SdMasterPagesAccess::getSupportedServiceNames( ) +{ + return { "com.sun.star.drawing.MasterPages" }; +} + + +SdDocLinkTargets::SdDocLinkTargets( SdXImpressDocument& rMyModel ) noexcept +: mpModel( &rMyModel ) +{ +} + +SdDocLinkTargets::~SdDocLinkTargets() noexcept +{ +} + +// XComponent +void SAL_CALL SdDocLinkTargets::dispose( ) +{ + mpModel = nullptr; +} + +void SAL_CALL SdDocLinkTargets::addEventListener( const uno::Reference< lang::XEventListener >& ) +{ + OSL_FAIL( "not implemented!" ); +} + +void SAL_CALL SdDocLinkTargets::removeEventListener( const uno::Reference< lang::XEventListener >& ) +{ + OSL_FAIL( "not implemented!" ); +} + +// XNameAccess +uno::Any SAL_CALL SdDocLinkTargets::getByName( const OUString& aName ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + SdPage* pPage = FindPage( aName ); + + if( pPage == nullptr ) + throw container::NoSuchElementException(); + + uno::Any aAny; + + uno::Reference< beans::XPropertySet > xProps( pPage->getUnoPage(), uno::UNO_QUERY ); + if( xProps.is() ) + aAny <<= xProps; + + return aAny; +} + +uno::Sequence< OUString > SAL_CALL SdDocLinkTargets::getElementNames() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + SdDrawDocument* pDoc = mpModel->GetDoc(); + if( pDoc == nullptr ) + { + return { }; + } + + if( pDoc->GetDocumentType() == DocumentType::Draw ) + { + const sal_uInt16 nMaxPages = pDoc->GetSdPageCount( PageKind::Standard ); + const sal_uInt16 nMaxMasterPages = pDoc->GetMasterSdPageCount( PageKind::Standard ); + + uno::Sequence< OUString > aSeq( nMaxPages + nMaxMasterPages ); + OUString* pStr = aSeq.getArray(); + + sal_uInt16 nPage; + // standard pages + for( nPage = 0; nPage < nMaxPages; nPage++ ) + *pStr++ = pDoc->GetSdPage( nPage, PageKind::Standard )->GetName(); + + // master pages + for( nPage = 0; nPage < nMaxMasterPages; nPage++ ) + *pStr++ = pDoc->GetMasterSdPage( nPage, PageKind::Standard )->GetName(); + return aSeq; + } + else + { + const sal_uInt16 nMaxPages = pDoc->GetPageCount(); + const sal_uInt16 nMaxMasterPages = pDoc->GetMasterPageCount(); + + uno::Sequence< OUString > aSeq( nMaxPages + nMaxMasterPages ); + OUString* pStr = aSeq.getArray(); + + sal_uInt16 nPage; + // standard pages + for( nPage = 0; nPage < nMaxPages; nPage++ ) + *pStr++ = static_cast<SdPage*>(pDoc->GetPage( nPage ))->GetName(); + + // master pages + for( nPage = 0; nPage < nMaxMasterPages; nPage++ ) + *pStr++ = static_cast<SdPage*>(pDoc->GetMasterPage( nPage ))->GetName(); + return aSeq; + } +} + +sal_Bool SAL_CALL SdDocLinkTargets::hasByName( const OUString& aName ) +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + return FindPage( aName ) != nullptr; +} + +// container::XElementAccess +uno::Type SAL_CALL SdDocLinkTargets::getElementType() +{ + return cppu::UnoType<beans::XPropertySet>::get(); +} + +sal_Bool SAL_CALL SdDocLinkTargets::hasElements() +{ + ::SolarMutexGuard aGuard; + + if( nullptr == mpModel ) + throw lang::DisposedException(); + + return mpModel->GetDoc() != nullptr; +} + +SdPage* SdDocLinkTargets::FindPage( std::u16string_view rName ) const +{ + SdDrawDocument* pDoc = mpModel->GetDoc(); + if( pDoc == nullptr ) + return nullptr; + + const sal_uInt16 nMaxPages = pDoc->GetPageCount(); + const sal_uInt16 nMaxMasterPages = pDoc->GetMasterPageCount(); + + sal_uInt16 nPage; + SdPage* pPage; + + const bool bDraw = pDoc->GetDocumentType() == DocumentType::Draw; + + // standard pages + for( nPage = 0; nPage < nMaxPages; nPage++ ) + { + pPage = static_cast<SdPage*>(pDoc->GetPage( nPage )); + if( (pPage->GetName() == rName) && (!bDraw || (pPage->GetPageKind() == PageKind::Standard)) ) + return pPage; + } + + // master pages + for( nPage = 0; nPage < nMaxMasterPages; nPage++ ) + { + pPage = static_cast<SdPage*>(pDoc->GetMasterPage( nPage )); + if( (pPage->GetName() == rName) && (!bDraw || (pPage->GetPageKind() == PageKind::Standard)) ) + return pPage; + } + + return nullptr; +} + +// XServiceInfo +OUString SAL_CALL SdDocLinkTargets::getImplementationName() +{ + return "SdDocLinkTargets"; +} + +sal_Bool SAL_CALL SdDocLinkTargets::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +uno::Sequence< OUString > SAL_CALL SdDocLinkTargets::getSupportedServiceNames() +{ + return { "com.sun.star.document.LinkTargets" }; +} + +rtl::Reference< SdXImpressDocument > SdXImpressDocument::GetModel( SdDrawDocument const & rDocument ) +{ + rtl::Reference< SdXImpressDocument > xRet; + ::sd::DrawDocShell* pDocShell(rDocument.GetDocSh()); + if( pDocShell ) + { + uno::Reference<frame::XModel> xModel(pDocShell->GetModel()); + + xRet.set( dynamic_cast< SdXImpressDocument* >( xModel.get() ) ); + } + + return xRet; +} + +void NotifyDocumentEvent( SdDrawDocument const & rDocument, const OUString& rEventName ) +{ + rtl::Reference< SdXImpressDocument > xModel( SdXImpressDocument::GetModel( rDocument ) ); + + if( xModel.is() ) + { + uno::Reference< uno::XInterface > xSource( static_cast<uno::XWeak*>( xModel.get() ) ); + css::document::EventObject aEvent( xSource, rEventName ); + xModel->notifyEvent(aEvent ); + } +} + +void NotifyDocumentEvent( SdDrawDocument const & rDocument, const OUString& rEventName, const uno::Reference< uno::XInterface >& xSource ) +{ + rtl::Reference< SdXImpressDocument > xModel( SdXImpressDocument::GetModel( rDocument ) ); + + if( xModel.is() ) + { + css::document::EventObject aEvent( xSource, rEventName ); + xModel->notifyEvent(aEvent ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |