diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sd/source/ui/docshell | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | sd/source/ui/docshell/docshel2.cxx | 421 | ||||
-rw-r--r-- | sd/source/ui/docshell/docshel3.cxx | 439 | ||||
-rw-r--r-- | sd/source/ui/docshell/docshel4.cxx | 994 | ||||
-rw-r--r-- | sd/source/ui/docshell/docshell.cxx | 507 | ||||
-rw-r--r-- | sd/source/ui/docshell/grdocsh.cxx | 61 | ||||
-rw-r--r-- | sd/source/ui/docshell/sdclient.cxx | 191 |
6 files changed, 2613 insertions, 0 deletions
diff --git a/sd/source/ui/docshell/docshel2.cxx b/sd/source/ui/docshell/docshel2.cxx new file mode 100644 index 0000000000..582afec051 --- /dev/null +++ b/sd/source/ui/docshell/docshel2.cxx @@ -0,0 +1,421 @@ +/* -*- 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 <DrawDocShell.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svxdlg.hxx> +#include <o3tl/string_view.hxx> + +#include <helpids.h> +#include <ViewShell.hxx> +#include <FrameView.hxx> +#include <drawdoc.hxx> +#include <sdpage.hxx> +#include <ClientView.hxx> +#include <Window.hxx> +#include <strings.hrc> + +#include <sdresid.hxx> +#include <fupoor.hxx> +#include <vcl/svapp.hxx> +#include <vcl/virdev.hxx> +#include <rtl/character.hxx> +#include <tools/debug.hxx> + +namespace sd { + +/** + * Drawing of DocShell (with the helper class SdDrawViewShell) + */ +void DrawDocShell::Draw(OutputDevice* pOut, const JobSetup&, sal_uInt16 nAspect, bool /*bOutputForScreen*/) +{ + if (nAspect == ASPECT_THUMBNAIL) + { + // THUMBNAIL: here we may can set the draft mode + } + + std::optional<ClientView> pView( std::in_place, this, pOut ); + + pView->SetHlplVisible(false); + pView->SetGridVisible(false); + pView->SetBordVisible(false); + pView->SetPageVisible(false); + pView->SetGlueVisible(false); + + SdPage* pSelectedPage = nullptr; + + const std::vector<std::unique_ptr<sd::FrameView>> &rViews = mpDoc->GetFrameViewList(); + if( !rViews.empty() ) + { + sd::FrameView* pFrameView = rViews[0].get(); + if( pFrameView->GetPageKind() == PageKind::Standard ) + { + sal_uInt16 nSelectedPage = pFrameView->GetSelectedPage(); + pSelectedPage = mpDoc->GetSdPage(nSelectedPage, PageKind::Standard); + } + } + + if( nullptr == pSelectedPage ) + { + SdPage* pPage = nullptr; + sal_uInt16 nPageCnt = mpDoc->GetSdPageCount(PageKind::Standard); + + for (sal_uInt16 i = 0; i < nPageCnt; i++) + { + pPage = mpDoc->GetSdPage(i, PageKind::Standard); + + if ( pPage->IsSelected() ) + pSelectedPage = pPage; + } + + if( nullptr == pSelectedPage ) + pSelectedPage = mpDoc->GetSdPage(0, PageKind::Standard); + } + + ::tools::Rectangle aVisArea = GetVisArea(nAspect); + pOut->IntersectClipRegion(aVisArea); + pView->ShowSdrPage(pSelectedPage); + + if (pOut->GetOutDevType() == OUTDEV_WINDOW) + return; + + MapMode aOldMapMode = pOut->GetMapMode(); + + if (pOut->GetOutDevType() == OUTDEV_PRINTER) + { + MapMode aMapMode = aOldMapMode; + Point aOrigin = aMapMode.GetOrigin(); + aOrigin.AdjustX(1 ); + aOrigin.AdjustY(1 ); + aMapMode.SetOrigin(aOrigin); + pOut->SetMapMode(aMapMode); + } + + vcl::Region aRegion(aVisArea); + pView->CompleteRedraw(pOut, aRegion); + + if (pOut->GetOutDevType() == OUTDEV_PRINTER) + { + pOut->SetMapMode(aOldMapMode); + } +} + +::tools::Rectangle DrawDocShell::GetVisArea(sal_uInt16 nAspect) const +{ + ::tools::Rectangle aVisArea; + + if( ( ASPECT_THUMBNAIL == nAspect ) || ( ASPECT_DOCPRINT == nAspect ) ) + { + // provide size of first page + aVisArea.SetSize(mpDoc->GetSdPage(0, PageKind::Standard)->GetSize()); + } + else + { + aVisArea = SfxObjectShell::GetVisArea(nAspect); + } + + if (aVisArea.IsEmpty() && mpViewShell) + { + vcl::Window* pWin = mpViewShell->GetActiveWindow(); + + if (pWin) + { + aVisArea = pWin->PixelToLogic(::tools::Rectangle(Point(0,0), pWin->GetOutputSizePixel())); + } + } + + return aVisArea; +} + +void DrawDocShell::Connect(ViewShell* pViewSh) +{ + mpViewShell = pViewSh; +} + +void DrawDocShell::Disconnect(ViewShell const * pViewSh) +{ + if (mpViewShell == pViewSh) + { + mpViewShell = nullptr; + } +} + +FrameView* DrawDocShell::GetFrameView() +{ + FrameView* pFrameView = nullptr; + + if (mpViewShell) + { + pFrameView = mpViewShell->GetFrameView(); + } + + return pFrameView; +} + +/** + * Creates a bitmap of an arbitrary page + */ +BitmapEx DrawDocShell::GetPagePreviewBitmap(SdPage* pPage) +{ + const sal_uInt16 nMaxEdgePixel = 90; + MapMode aMapMode( MapUnit::Map100thMM ); + const Size aSize( pPage->GetSize() ); + const Point aNullPt; + ScopedVclPtrInstance< VirtualDevice > pVDev( *Application::GetDefaultDevice() ); + + pVDev->SetMapMode( aMapMode ); + + const Size aPixSize( pVDev->LogicToPixel( aSize ) ); + const sal_uLong nMaxEdgePix = std::max( aPixSize.Width(), aPixSize.Height() ); + Fraction aFrac( nMaxEdgePixel, nMaxEdgePix ); + + aMapMode.SetScaleX( aFrac ); + aMapMode.SetScaleY( aFrac ); + pVDev->SetMapMode( aMapMode ); + pVDev->SetOutputSize( aSize ); + + // that we also get the dark lines at the right and bottom page margin + aFrac = Fraction( nMaxEdgePixel - 1, nMaxEdgePix ); + aMapMode.SetScaleX( aFrac ); + aMapMode.SetScaleY( aFrac ); + pVDev->SetMapMode( aMapMode ); + + std::optional<ClientView> pView( std::in_place, this, pVDev ); + FrameView* pFrameView = GetFrameView(); + pView->ShowSdrPage( pPage ); + + if ( GetFrameView() ) + { + // initialize the drawing-(screen) attributes + pView->SetGridCoarse( pFrameView->GetGridCoarse() ); + pView->SetGridFine( pFrameView->GetGridFine() ); + pView->SetSnapGridWidth(pFrameView->GetSnapGridWidthX(), pFrameView->GetSnapGridWidthY()); + pView->SetGridVisible( pFrameView->IsGridVisible() ); + pView->SetGridFront( pFrameView->IsGridFront() ); + pView->SetSnapAngle( pFrameView->GetSnapAngle() ); + pView->SetGridSnap( pFrameView->IsGridSnap() ); + pView->SetBordSnap( pFrameView->IsBordSnap() ); + pView->SetHlplSnap( pFrameView->IsHlplSnap() ); + pView->SetOFrmSnap( pFrameView->IsOFrmSnap() ); + pView->SetOPntSnap( pFrameView->IsOPntSnap() ); + pView->SetOConSnap( pFrameView->IsOConSnap() ); + pView->SetDragStripes( pFrameView->IsDragStripes() ); + pView->SetFrameDragSingles( pFrameView->IsFrameDragSingles() ); + pView->SetSnapMagneticPixel( pFrameView->GetSnapMagneticPixel() ); + pView->SetMarkedHitMovesAlways( pFrameView->IsMarkedHitMovesAlways() ); + pView->SetMoveOnlyDragging( pFrameView->IsMoveOnlyDragging() ); + pView->SetSlantButShear( pFrameView->IsSlantButShear() ); + pView->SetNoDragXorPolys( pFrameView->IsNoDragXorPolys() ); + pView->SetCrookNoContortion( pFrameView->IsCrookNoContortion() ); + pView->SetAngleSnapEnabled( pFrameView->IsAngleSnapEnabled() ); + pView->SetBigOrtho( pFrameView->IsBigOrtho() ); + pView->SetOrtho( pFrameView->IsOrtho() ); + + SdrPageView* pPageView = pView->GetSdrPageView(); + + if (pPageView) + { + if ( pPageView->GetVisibleLayers() != pFrameView->GetVisibleLayers() ) + pPageView->SetVisibleLayers( pFrameView->GetVisibleLayers() ); + + if ( pPageView->GetPrintableLayers() != pFrameView->GetPrintableLayers() ) + pPageView->SetPrintableLayers( pFrameView->GetPrintableLayers() ); + + if ( pPageView->GetLockedLayers() != pFrameView->GetLockedLayers() ) + pPageView->SetLockedLayers( pFrameView->GetLockedLayers() ); + + pPageView->SetHelpLines( pFrameView->GetStandardHelpLines() ); + } + + if ( pView->GetActiveLayer() != pFrameView->GetActiveLayer() ) + pView->SetActiveLayer( pFrameView->GetActiveLayer() ); + } + + pView->CompleteRedraw( pVDev, vcl::Region(::tools::Rectangle(aNullPt, aSize)) ); + + // IsRedrawReady() always gives sal_True while ( !pView->IsRedrawReady() ) {} + pView.reset(); + + pVDev->SetMapMode( MapMode() ); + + BitmapEx aPreview( pVDev->GetBitmapEx( aNullPt, pVDev->GetOutputSizePixel() ) ); + + DBG_ASSERT(!aPreview.IsEmpty(), "Preview-Bitmap could not be generated"); + + return aPreview; +} + +/** + * Checks if the page exists. If so, we force the user to enter a not yet used + * name. + * @return sal_False if the user cancels the action. + */ +bool DrawDocShell::CheckPageName(weld::Window* pWin, OUString& rName) +{ + const OUString aStrForDlg( rName ); + bool bIsNameValid = IsNewPageNameValid( rName, true ); + + if( ! bIsNameValid ) + { + OUString aDesc; + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + + if (GetDocumentType() == DocumentType::Draw) + aDesc = SdResId( STR_WARN_PAGE_EXISTS_DRAW ); + else + aDesc = SdResId( STR_WARN_PAGE_EXISTS ); + + ScopedVclPtr<AbstractSvxNameDialog> aNameDlg(pFact->CreateSvxNameDialog(pWin, aStrForDlg, aDesc)); + aNameDlg->SetEditHelpId( HID_SD_NAMEDIALOG_PAGE ); + + aNameDlg->SetCheckNameHdl( LINK( this, DrawDocShell, RenameSlideHdl ) ); + + rtl::Reference<FuPoor> xFunc( mpViewShell->GetCurrentFunction() ); + if( xFunc.is() ) + xFunc->cancel(); + + if( aNameDlg->Execute() == RET_OK ) + { + aNameDlg->GetName( rName ); + bIsNameValid = IsNewPageNameValid( rName ); + } + } + + return bIsNameValid; +} + +bool DrawDocShell::IsNewPageNameValid( OUString & rInOutPageName, bool bResetStringIfStandardName /* = false */ ) +{ + bool bCanUseNewName = false; + + // check if name is something like 'Slide/Page n' + OUString aStrPage; + if (GetDoc()->GetDocumentType() == DocumentType::Draw) + aStrPage = SdResId(STR_PAGE_NAME) + " "; + else + // using the same strings as SdPage::GetName + aStrPage = SdResId(STR_PAGE) + " "; + + bool bIsStandardName = false; + + // prevent also _future_ slide names of the form "'STR_PAGE' + ' ' + '[0-9]+|[a-z]|[A-Z]|[CDILMVX]+|[cdilmvx]+'" + // (arabic, lower- and upper case single letter, lower- and upper case roman numbers) + if (rInOutPageName.startsWith(aStrPage) && + rInOutPageName.getLength() > aStrPage.getLength()) + { + sal_Int32 nIdx{ aStrPage.getLength() }; + std::u16string_view sRemainder = o3tl::getToken(rInOutPageName, 0, ' ', nIdx); + if (!sRemainder.empty() && sRemainder[0] >= '0' && sRemainder[0] <= '9') + { + // check for arabic numbering + + size_t nIndex = 1; + // skip all following numbers + while (nIndex < sRemainder.size() && + sRemainder[nIndex] >= '0' && sRemainder[nIndex] <= '9') + { + nIndex++; + } + + // EOL? Reserved name! + if (nIndex >= sRemainder.size()) + { + bIsStandardName = true; + } + } + else if (sRemainder.size() == 1 && + rtl::isAsciiLowerCase(sRemainder[0])) + { + // lower case, single character: reserved + bIsStandardName = true; + } + else if (sRemainder.size() == 1 && + rtl::isAsciiUpperCase(sRemainder[0])) + { + // upper case, single character: reserved + bIsStandardName = true; + } + else + { + // check for upper/lower case roman numbering + OUString sReserved("cdilmvx"); + + // skip all following characters contained in one reserved class + if (sReserved.indexOf(sRemainder[0]) == -1) + sReserved = sReserved.toAsciiUpperCase(); + + size_t nIndex = 0; + while (nIndex < sRemainder.size() && + sReserved.indexOf(sRemainder[nIndex]) != -1) + { + nIndex++; + } + + // EOL? Reserved name! + if (nIndex >= sRemainder.size()) + { + bIsStandardName = true; + } + } + } + + if( bIsStandardName ) + { + if( bResetStringIfStandardName ) + { + // this is for insertion of slides from other files with standard + // name. They get a new standard name, if the string is set to an + // empty one. + rInOutPageName.clear(); + bCanUseNewName = true; + } + else + bCanUseNewName = false; + } + else + { + if (!rInOutPageName.isEmpty()) + { + bool bOutDummy; + sal_uInt16 nExistingPageNum = mpDoc->GetPageByName( rInOutPageName, bOutDummy ); + bCanUseNewName = ( nExistingPageNum == SDRPAGE_NOTFOUND ); + } + else + bCanUseNewName = false; + } + + return bCanUseNewName; +} + +bool DrawDocShell::IsPageNameUnique( std::u16string_view rPageName ) const +{ + return mpDoc->IsPageNameUnique(rPageName); +} + +IMPL_LINK( DrawDocShell, RenameSlideHdl, AbstractSvxNameDialog&, rDialog, bool ) +{ + OUString aNewName; + rDialog.GetName( aNewName ); + return IsNewPageNameValid( aNewName ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/docshell/docshel3.cxx b/sd/source/ui/docshell/docshel3.cxx new file mode 100644 index 0000000000..f310ddcfc6 --- /dev/null +++ b/sd/source/ui/docshell/docshel3.cxx @@ -0,0 +1,439 @@ +/* -*- 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 <DrawDocShell.hxx> + +#include <svx/svxids.hrc> + +#include <svx/ofaitem.hxx> +#include <svl/stritem.hxx> +#include <svl/srchitem.hxx> +#include <svl/languageoptions.hxx> +#include <svtools/langtab.hxx> +#include <sfx2/request.hxx> +#include <sfx2/sfxdlg.hxx> +#include <sfx2/viewfrm.hxx> +#include <vcl/abstdlg.hxx> +#include <svx/drawitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <com/sun/star/i18n/TextConversionOption.hpp> +#include <sfx2/notebookbar/SfxNotebookBar.hxx> +#include <editeng/editeng.hxx> +#include <osl/diagnose.h> + +#include <sdmod.hxx> +#include <drawdoc.hxx> +#include <fusearch.hxx> +#include <ViewShell.hxx> +#include <slideshow.hxx> +#include <fuhhconv.hxx> +#include <memory> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + +namespace sd { + +static void lcl_setLanguageForObj( SdrObject *pObj, LanguageType nLang, bool bLanguageNone ) +{ + const sal_uInt16 aLangWhichId_EE[3] = + { + EE_CHAR_LANGUAGE, + EE_CHAR_LANGUAGE_CJK, + EE_CHAR_LANGUAGE_CTL + }; + + if( bLanguageNone ) + nLang = LANGUAGE_NONE; + + if( nLang != LANGUAGE_DONTKNOW ) + { + if( nLang == LANGUAGE_NONE ) + { + for(sal_uInt16 n : aLangWhichId_EE) + pObj->SetMergedItem( SvxLanguageItem( nLang, n ) ); + } + else + { + sal_uInt16 nLangWhichId = 0; + SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLang ); + switch (nScriptType) + { + case SvtScriptType::LATIN : nLangWhichId = EE_CHAR_LANGUAGE; break; + case SvtScriptType::ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break; + case SvtScriptType::COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; + default: + OSL_FAIL("unexpected case" ); + return; + } + pObj->SetMergedItem( SvxLanguageItem( nLang, nLangWhichId ) ); + + // Reset shape text language to default, so it inherits the shape language set above. + OutlinerParaObject* pOutliner = pObj->GetOutlinerParaObject(); + if (pOutliner) + { + EditTextObject& rEditTextObject + = const_cast<EditTextObject&>(pOutliner->GetTextObject()); + for (sal_uInt16 n : aLangWhichId_EE) + { + rEditTextObject.RemoveCharAttribs(n); + } + } + } + } + else // Reset to default + { + for(sal_uInt16 n : aLangWhichId_EE) + pObj->ClearMergedItem( n ); + } +} + +static void lcl_setLanguage( const SdDrawDocument *pDoc, std::u16string_view rLanguage, bool bLanguageNone = false ) +{ + LanguageType nLang = SvtLanguageTable::GetLanguageType( rLanguage ); + + // Do it for SdDrawDocument->SetLanguage as well? + + sal_uInt16 nPageCount = pDoc->GetPageCount(); // Pick All Pages + for( sal_uInt16 nPage = 0; nPage < nPageCount; nPage++ ) + { + const SdrPage *pPage = pDoc->GetPage( nPage ); + for (const rtl::Reference<SdrObject>& pObj : *pPage) + if (pObj->GetObjIdentifier() != SdrObjKind::Page) + lcl_setLanguageForObj( pObj.get(), nLang, bLanguageNone ); + } +} + +/** + * Handles SFX-Requests + */ +void DrawDocShell::Execute( SfxRequest& rReq ) +{ + if(mpViewShell && SlideShow::IsRunning( mpViewShell->GetViewShellBase() )) + { + // during a running presentation no slot will be executed + return; + } + + switch ( rReq.GetSlot() ) + { + case SID_SEARCH_ITEM: + { + const SfxItemSet* pReqArgs = rReq.GetArgs(); + + if (pReqArgs) + { + const SvxSearchItem & rSearchItem = pReqArgs->Get(SID_SEARCH_ITEM); + + SD_MOD()->SetSearchItem(std::unique_ptr<SvxSearchItem>(rSearchItem.Clone())); + } + + rReq.Done(); + } + break; + + case FID_SEARCH_ON: + { + // no action needed + rReq.Done(); + } + break; + + case FID_SEARCH_OFF: + { + if (mpViewShell) + { + sd::View* pView = mpViewShell->GetView(); + if (pView) + { + auto& rFunctionContext = pView->getSearchContext(); + rtl::Reference<FuSearch>& xFuSearch(rFunctionContext.getFunctionSearch()); + + if (xFuSearch.is()) + { + // End Search&Replace in all docshells + SfxObjectShell* pFirstShell = SfxObjectShell::GetFirst(); + SfxObjectShell* pShell = pFirstShell; + + while (pShell) + { + auto pDrawDocShell = dynamic_cast<DrawDocShell*>(pShell); + if (pDrawDocShell) + pDrawDocShell->CancelSearching(); + + pShell = SfxObjectShell::GetNext(*pShell); + + if (pShell == pFirstShell) + pShell = nullptr; + } + + rFunctionContext.resetSearchFunction(); + Invalidate(); + rReq.Done(); + } + } + } + } + break; + + case FID_SEARCH_NOW: + { + const SfxItemSet* pReqArgs = rReq.GetArgs(); + + if (pReqArgs && mpViewShell) + { + sd::View* pView = mpViewShell->GetView(); + if (pView) + { + rtl::Reference<FuSearch> & xFuSearch = pView->getSearchContext().getFunctionSearch(); + + if (!xFuSearch.is()) + { + xFuSearch = rtl::Reference<FuSearch>( + FuSearch::createPtr(mpViewShell, + mpViewShell->GetActiveWindow(), + pView, mpDoc, rReq)); + + pView->getSearchContext().setSearchFunction(xFuSearch); + } + + if (xFuSearch.is()) + { + const SvxSearchItem& rSearchItem = pReqArgs->Get(SID_SEARCH_ITEM); + + SD_MOD()->SetSearchItem(std::unique_ptr<SvxSearchItem>(rSearchItem.Clone())); + xFuSearch->SearchAndReplace(&rSearchItem); + } + } + } + + rReq.Done(); + } + break; + + case SID_CLOSEDOC: + { + ExecuteSlot(rReq, SfxObjectShell::GetStaticInterface()); + } + break; + + case SID_GET_COLORLIST: + { + const SvxColorListItem* pColItem = GetItem( SID_COLOR_TABLE ); + const XColorListRef& pList = pColItem->GetColorList(); + rReq.SetReturnValue( OfaXColorListItem( SID_GET_COLORLIST, pList ) ); + } + break; + + case SID_VERSION: + { + ExecuteSlot( rReq, SfxObjectShell::GetStaticInterface() ); + } + break; + + case SID_HANGUL_HANJA_CONVERSION: + { + if( mpViewShell ) + { + rtl::Reference<FuPoor> aFunc( FuHangulHanjaConversion::Create( mpViewShell, mpViewShell->GetActiveWindow(), mpViewShell->GetView(), mpDoc, rReq ) ); + static_cast< FuHangulHanjaConversion* >( aFunc.get() )->StartConversion( LANGUAGE_KOREAN, LANGUAGE_KOREAN, nullptr, i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true ); + } + } + break; + + case SID_CHINESE_CONVERSION: + { + if( mpViewShell ) + { + rtl::Reference<FuPoor> aFunc( FuHangulHanjaConversion::Create( mpViewShell, mpViewShell->GetActiveWindow(), mpViewShell->GetView(), mpDoc, rReq ) ); + static_cast< FuHangulHanjaConversion* >( aFunc.get() )->StartChineseConversion(); + } + } + break; + case SID_LANGUAGE_STATUS: + { + OUString aNewLangTxt; + const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(SID_LANGUAGE_STATUS); + if (pItem) + aNewLangTxt = pItem->GetValue(); + + if (aNewLangTxt == "*" ) + { + // open the dialog "Tools/Options/Languages and Locales - General" + if (mpViewShell) + { + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog( mpViewShell->GetFrameWeld(), SID_LANGUAGE_OPTIONS )); + pDlg->Execute(); + } + } + else + { + if( mpViewShell ) + { + // setting the new language... + if (!aNewLangTxt.isEmpty()) + { + static constexpr OUString aSelectionLangPrefix(u"Current_"_ustr); + static constexpr OUString aParagraphLangPrefix(u"Paragraph_"_ustr); + static constexpr OUString aDocumentLangPrefix(u"Default_"_ustr); + + bool bSelection = false; + bool bParagraph = false; + + SdDrawDocument* pDoc = mpViewShell->GetDoc(); + sal_Int32 nPos = -1; + if (-1 != (nPos = aNewLangTxt.indexOf( aDocumentLangPrefix ))) + { + aNewLangTxt = aNewLangTxt.replaceAt( nPos, aDocumentLangPrefix.getLength(), u"" ); + + if (aNewLangTxt == "LANGUAGE_NONE") + lcl_setLanguage( pDoc, u"", true ); + else if (aNewLangTxt == "RESET_LANGUAGES") + lcl_setLanguage( pDoc, u"" ); + else + lcl_setLanguage( pDoc, aNewLangTxt ); + } + else if (-1 != (nPos = aNewLangTxt.indexOf( aSelectionLangPrefix ))) + { + bSelection = true; + aNewLangTxt = aNewLangTxt.replaceAt( nPos, aSelectionLangPrefix.getLength(), u"" ); + } + else if (-1 != (nPos = aNewLangTxt.indexOf( aParagraphLangPrefix ))) + { + bParagraph = true; + aNewLangTxt = aNewLangTxt.replaceAt( nPos, aParagraphLangPrefix.getLength(), u"" ); + } + + if (bSelection || bParagraph) + { + SdrView* pSdrView = mpViewShell->GetDrawView(); + if (!pSdrView) + return; + + EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); + const LanguageType nLangToUse = SvtLanguageTable::GetLanguageType( aNewLangTxt ); + SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLangToUse ); + + SfxItemSet aAttrs = rEditView.GetEditEngine()->GetEmptyItemSet(); + if (nScriptType == SvtScriptType::LATIN) + aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE ) ); + if (nScriptType == SvtScriptType::COMPLEX) + aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CTL ) ); + if (nScriptType == SvtScriptType::ASIAN) + aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CJK ) ); + ESelection aOldSel; + if (bParagraph) + { + ESelection aSel = rEditView.GetSelection(); + aOldSel = aSel; + aSel.nStartPos = 0; + aSel.nEndPos = EE_TEXTPOS_ALL; + rEditView.SetSelection( aSel ); + } + + rEditView.SetAttribs( aAttrs ); + if (bParagraph) + rEditView.SetSelection( aOldSel ); + } + + if ( pDoc->GetOnlineSpell() ) + { + pDoc->StartOnlineSpelling(); + } + } + } + } + Broadcast(SfxHint(SfxHintId::LanguageChanged)); + } + break; + case SID_SPELLCHECK_IGNORE_ALL: + { + if (!mpViewShell) + return; + SdrView* pSdrView = mpViewShell->GetDrawView(); + if (!pSdrView) + return; + + EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); + OUString sIgnoreText; + const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1); + if (pItem2) + sIgnoreText = pItem2->GetValue(); + + if(sIgnoreText == "Spelling") + { + ESelection aOldSel = rEditView.GetSelection(); + rEditView.SpellIgnoreWord(); + rEditView.SetSelection( aOldSel ); + } + } + break; + case SID_SPELLCHECK_APPLY_SUGGESTION: + { + if (!mpViewShell) + return; + SdrView* pSdrView = mpViewShell->GetDrawView(); + if (!pSdrView) + return; + + EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); + OUString sApplyText; + const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1); + if (pItem2) + sApplyText = pItem2->GetValue(); + + static constexpr OUString sSpellingRule(u"Spelling_"_ustr); + sal_Int32 nPos = 0; + if(-1 != (nPos = sApplyText.indexOf( sSpellingRule ))) + { + sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), u""); + rEditView.InsertText( sApplyText ); + } + } + break; + + case SID_NOTEBOOKBAR: + { + const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR ); + + if ( mpViewShell ) + { + SfxBindings& rBindings( mpViewShell->GetFrame()->GetBindings() ); + + if ( sfx2::SfxNotebookBar::IsActive() ) + sfx2::SfxNotebookBar::ExecMethod( rBindings, pFile ? pFile->GetValue() : "" ); + else + sfx2::SfxNotebookBar::CloseMethod( rBindings ); + } + } + break; + + default: + break; + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/docshell/docshel4.cxx b/sd/source/ui/docshell/docshel4.cxx new file mode 100644 index 0000000000..742614d101 --- /dev/null +++ b/sd/source/ui/docshell/docshel4.cxx @@ -0,0 +1,994 @@ +/* -*- 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 <sal/config.h> +#include <sal/log.hxx> + +#include <memory> +#include <utility> + +#include <DrawDocShell.hxx> +#include <com/sun/star/document/PrinterIndependentLayout.hpp> +#include <editeng/outlobj.hxx> +#include <tools/urlobj.hxx> +#include <svx/compatflags.hxx> +#include <svx/svxids.hrc> +#include <editeng/editeng.hxx> +#include <editeng/editstat.hxx> +#include <editeng/flstitem.hxx> +#include <svl/flagitem.hxx> +#include <sot/storage.hxx> +#include <sfx2/dinfdlg.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/svdotext.hxx> +#include <sfx2/printer.hxx> +#include <svtools/ctrltool.hxx> +#include <comphelper/classids.hxx> +#include <sot/formats.hxx> +#include <sfx2/viewfrm.hxx> +#include <vcl/syswin.hxx> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> + +#include <app.hrc> +#include <strings.hrc> +#include <FrameView.hxx> +#include <optsitem.hxx> +#include <Outliner.hxx> +#include <sdattr.hrc> +#include <drawdoc.hxx> +#include <ViewShell.hxx> +#include <sdmod.hxx> +#include <View.hxx> +#include <EffectMigration.hxx> +#include <CustomAnimationEffect.hxx> +#include <sdpage.hxx> +#include <sdresid.hxx> +#include <DrawViewShell.hxx> +#include <ViewShellBase.hxx> +#include <OutlineView.hxx> +#include <OutlineViewShell.hxx> +#include <sdxmlwrp.hxx> +#include <sdpptwrp.hxx> +#include <sdcgmfilter.hxx> +#include <sdgrffilter.hxx> +#include <sdhtmlfilter.hxx> +#include <sdpdffilter.hxx> +#include <framework/FrameworkHelper.hxx> +#include <o3tl/string_view.hxx> + +#include <Window.hxx> +#include <svl/intitem.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::sd::framework::FrameworkHelper; + +// PowerPoint-Filter +constexpr OUStringLiteral pFilterPowerPoint97( u"MS PowerPoint 97" ); +constexpr OUStringLiteral pFilterPowerPoint97Template( u"MS PowerPoint 97 Vorlage" ); +constexpr OUStringLiteral pFilterPowerPoint97AutoPlay( u"MS PowerPoint 97 AutoPlay" ); + +namespace sd { + +/** + * Creates (if necessary) and returns a SfxPrinter + */ +SfxPrinter* DrawDocShell::GetPrinter(bool bCreate) +{ + if (bCreate && !mpPrinter) + { + // create ItemSet with special pool area + auto pSet = std::make_unique<SfxItemSetFixed< + SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN, + SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC, + ATTR_OPTIONS_PRINT, ATTR_OPTIONS_PRINT>>( GetPool() ); + // set PrintOptionsSet + SdOptionsPrintItem aPrintItem( SD_MOD()->GetSdOptions(mpDoc->GetDocumentType()) ); + SfxFlagItem aFlagItem( SID_PRINTER_CHANGESTODOC ); + SfxPrinterChangeFlags nFlags = + (aPrintItem.GetOptionsPrint().IsWarningSize() ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE) | + (aPrintItem.GetOptionsPrint().IsWarningOrientation() ? SfxPrinterChangeFlags::CHG_ORIENTATION : SfxPrinterChangeFlags::NONE); + aFlagItem.SetValue( static_cast<int>(nFlags) ); + + pSet->Put( aPrintItem ); + pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, aPrintItem.GetOptionsPrint().IsWarningPrinter() ) ); + pSet->Put( aFlagItem ); + + mpPrinter = VclPtr<SfxPrinter>::Create(std::move(pSet)); + mbOwnPrinter = true; + + // set output quality + sal_uInt16 nQuality = aPrintItem.GetOptionsPrint().GetOutputQuality(); + + DrawModeFlags nMode = DrawModeFlags::Default; + // 1 == Grayscale, 2 == Black & White (with grayscale images) + if( nQuality == 1 ) + nMode = DrawModeFlags::GrayLine | DrawModeFlags::GrayFill | DrawModeFlags::GrayText | DrawModeFlags::GrayBitmap | DrawModeFlags::GrayGradient; + else if( nQuality == 2 ) + nMode = DrawModeFlags::BlackLine | DrawModeFlags::WhiteFill | DrawModeFlags::BlackText | DrawModeFlags::GrayBitmap | DrawModeFlags::WhiteGradient; + + mpPrinter->SetDrawMode( nMode ); + + MapMode aMM (mpPrinter->GetMapMode()); + aMM.SetMapUnit(MapUnit::Map100thMM); + mpPrinter->SetMapMode(aMM); + UpdateRefDevice(); + } + return mpPrinter; +} + +/** + * Set new SfxPrinter (transfer of ownership) + */ +void DrawDocShell::SetPrinter(SfxPrinter *pNewPrinter) +{ + if ( mpViewShell ) + { + ::sd::View* pView = mpViewShell->GetView(); + if ( pView->IsTextEdit() ) + pView->SdrEndTextEdit(); + } + + if ( mpPrinter && mbOwnPrinter && (mpPrinter.get() != pNewPrinter) ) + mpPrinter.disposeAndClear(); + + mpPrinter = pNewPrinter; + mbOwnPrinter = true; + if ( mpDoc->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED ) + UpdateFontList(); + UpdateRefDevice(); +} + +void DrawDocShell::UpdateFontList() +{ + mpFontList.reset(); + OutputDevice* pRefDevice = nullptr; + if ( mpDoc->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED ) + pRefDevice = GetPrinter(true); + else + pRefDevice = SD_MOD()->GetVirtualRefDevice(); + mpFontList.reset( new FontList(pRefDevice, nullptr) ); + SvxFontListItem aFontListItem( mpFontList.get(), SID_ATTR_CHAR_FONTLIST ); + PutItem( aFontListItem ); +} + +Printer* DrawDocShell::GetDocumentPrinter() +{ + return GetPrinter(false); +} + +void DrawDocShell::OnDocumentPrinterChanged(Printer* pNewPrinter) +{ + // if we already have a printer, see if it's the same + if( mpPrinter ) + { + // easy case + if( mpPrinter == pNewPrinter ) + return; + + // compare if it's the same printer with the same job setup + if( (mpPrinter->GetName() == pNewPrinter->GetName()) && + (mpPrinter->GetJobSetup() == pNewPrinter->GetJobSetup())) + return; + } + + SfxPrinter* const pSfxPrinter = dynamic_cast<SfxPrinter*>(pNewPrinter); + if (pSfxPrinter) + { + SetPrinter(pSfxPrinter); + + // container owns printer + mbOwnPrinter = false; + } +} + +void DrawDocShell::UpdateRefDevice() +{ + if( !mpDoc ) + return; + + // Determine the device for which the output will be formatted. + VclPtr< OutputDevice > pRefDevice; + switch (mpDoc->GetPrinterIndependentLayout()) + { + case css::document::PrinterIndependentLayout::DISABLED: + pRefDevice = mpPrinter.get(); + break; + + case css::document::PrinterIndependentLayout::ENABLED: + pRefDevice = SD_MOD()->GetVirtualRefDevice(); + break; + + default: + // We are confronted with an invalid or un-implemented + // layout mode. Use the printer as formatting device + // as a fall-back. + SAL_WARN( "sd", "DrawDocShell::UpdateRefDevice(): Unexpected printer layout mode"); + + pRefDevice = mpPrinter.get(); + break; + } + mpDoc->SetRefDevice( pRefDevice.get() ); + + SdOutliner* pOutl = mpDoc->GetOutliner( false ); + + if( pOutl ) + pOutl->SetRefDevice( pRefDevice ); + + SdOutliner* pInternalOutl = mpDoc->GetInternalOutliner( false ); + + if( pInternalOutl ) + pInternalOutl->SetRefDevice( pRefDevice ); +} + +/** + * Creates new document, opens streams + */ +bool DrawDocShell::InitNew( const css::uno::Reference< css::embed::XStorage >& xStorage ) +{ + bool bRet = SfxObjectShell::InitNew( xStorage ); + + ::tools::Rectangle aVisArea( Point(0, 0), Size(14100, 10000) ); + SetVisArea(aVisArea); + + if (bRet) + { + if( !mbSdDataObj ) + mpDoc->NewOrLoadCompleted(DocCreationMode::New); // otherwise calling + // NewOrLoadCompleted(NEW_LOADED) in + // SdDrawDocument::AllocModel() + } + return bRet; +} + +/** + * loads pools and document + */ +bool DrawDocShell::Load( SfxMedium& rMedium ) +{ + // If this is an ODF file being loaded, then by default, use legacy processing + // (if required, it will be overridden in *::ReadUserDataSequence()) + if (IsOwnStorageFormat(rMedium)) + { + mpDoc->SetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy, true); // for tdf#99729 + mpDoc->SetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork, true); // for tdf#148000 + } + + bool bRet = false; + bool bStartPresentation = false; + ErrCode nError = ERRCODE_NONE; + + SfxItemSet& rSet = rMedium.GetItemSet(); + + if( ( SfxItemState::SET == rSet.GetItemState(SID_PREVIEW ) ) && rSet.Get( SID_PREVIEW ).GetValue() ) + { + mpDoc->SetStarDrawPreviewMode( true ); + } + + if( SfxItemState::SET == rSet.GetItemState(SID_DOC_STARTPRESENTATION)&& + rSet.Get( SID_DOC_STARTPRESENTATION ).GetValue() ) + { + bStartPresentation = true; + mpDoc->SetStartWithPresentation( true ); + } + + bRet = SfxObjectShell::Load( rMedium ); + if (bRet) + { + comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer(); + rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false); + bRet = SdXMLFilter( rMedium, *this, SdXMLFilterMode::Normal, SotStorage::GetVersion( rMedium.GetStorage() ) ).Import( nError ); + } + + if( bRet ) + { + // for legacy markup in OOoXML filter, convert the animations now + EffectMigration::DocumentLoaded(*GetDoc()); + UpdateTablePointers(); + + // If we're an embedded OLE object, use tight bounds + // for our visArea. No point in showing the user lots of empty + // space. Had to remove the check for empty VisArea below, + // since XML load always sets a VisArea before. + //TODO/LATER: looks a little bit strange! + if( ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED ) && SfxObjectShell::GetVisArea( ASPECT_CONTENT ).IsEmpty() ) + { + SdPage* pPage = mpDoc->GetSdPage( 0, PageKind::Standard ); + + if( pPage ) + SetVisArea( pPage->GetAllObjBoundRect() ); + } + + FinishedLoading(); + + const INetURLObject aUrl; + SfxObjectShell::SetAutoLoad( aUrl, 0, false ); + } + else + { + if( nError == ERRCODE_IO_BROKENPACKAGE ) + SetError(ERRCODE_IO_BROKENPACKAGE); + + // TODO/LATER: correct error handling?! + //pStore->SetError(SVSTREAM_WRONGVERSION); + else + SetError(ERRCODE_ABORT); + } + + // tell SFX to change viewshell when in preview mode + if( IsPreview() || bStartPresentation ) + { + GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID, bStartPresentation ? 1 : 5 ) ); + } + + return bRet; +} + +/** + * loads content for organizer + */ +bool DrawDocShell::LoadFrom( SfxMedium& rMedium ) +{ + std::unique_ptr<weld::WaitObject> pWait; + if( mpViewShell ) + pWait.reset(new weld::WaitObject(mpViewShell->GetFrameWeld())); + + mpDoc->NewOrLoadCompleted( DocCreationMode::New ); + mpDoc->CreateFirstPages(); + mpDoc->StopWorkStartupDelay(); + + // TODO/LATER: nobody is interested in the error code?! + ErrCode nError = ERRCODE_NONE; + bool bRet = SdXMLFilter( rMedium, *this, SdXMLFilterMode::Organizer, SotStorage::GetVersion( rMedium.GetStorage() ) ).Import( nError ); + + // tell SFX to change viewshell when in preview mode + if( IsPreview() ) + { + GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID, 5 ) ); + } + + return bRet; +} + +/** + * load from 3rd party format + */ +bool DrawDocShell::ImportFrom(SfxMedium &rMedium, + uno::Reference<text::XTextRange> const& xInsertPosition) +{ + const OUString aFilterName( rMedium.GetFilter()->GetFilterName() ); + if (aFilterName == "Impress MS PowerPoint 2007 XML" || + aFilterName == "Impress MS PowerPoint 2007 XML AutoPlay" || + aFilterName == "Impress MS PowerPoint 2007 XML VBA") + { + // As this is a MSFT format, we should use the "MS Compat" + // mode for spacing before and after paragraphs. + + // This is copied from what is done for .ppt import in + // ImplSdPPTImport::Import() in sd/source/filter/ppt/pptin.cxx + // in. We need to tell both the edit engine of the draw outliner, + // and the document, to do "summation of paragraphs". + SdrOutliner& rOutl = mpDoc->GetDrawOutliner(); + EEControlBits nControlWord = rOutl.GetEditEngine().GetControlWord(); + nControlWord |= EEControlBits::ULSPACESUMMATION; + const_cast<EditEngine&>(rOutl.GetEditEngine()).SetControlWord( nControlWord ); + + mpDoc->SetSummationOfParagraphs(); + } + + if (aFilterName == "Impress MS PowerPoint 2007 XML") + { + // This is a "MS Compact" mode for connectors. + // The Libreoffice uses bounding rectangle of connected shapes but + // MSO uses snap rectangle when calculate the edge track. + mpDoc->SetCompatibilityFlag(SdrCompatibilityFlag::ConnectorUseSnapRect, true); + + // compatibility flag for tdf#148966 + mpDoc->SetCompatibilityFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField, true); + } + + if (aFilterName == "Impress MS PowerPoint 2007 XML" || + aFilterName == "Impress MS PowerPoint 2007 XML AutoPlay" || + aFilterName == "Impress MS PowerPoint 2007 XML VBA" || + aFilterName == "Impress Office Open XML") + { + // We need to be able to set the default tab size for each text object. + // This is possible at the moment only for the whole document. See + // TextParagraphPropertiesContext constructor. So default tab width + // of the LibreOffice is 1270 but MSO is 2540 on general settings. + mpDoc->SetDefaultTabulator( 2540 ); + } + + const bool bRet = SfxObjectShell::ImportFrom(rMedium, xInsertPosition); + + SfxItemSet& rSet = rMedium.GetItemSet(); + if( SfxItemState::SET == rSet.GetItemState(SID_DOC_STARTPRESENTATION)&& + rSet.Get( SID_DOC_STARTPRESENTATION ).GetValue() ) + { + mpDoc->SetStartWithPresentation( true ); + + // tell SFX to change viewshell when in preview mode + if( IsPreview() ) + { + GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID, 1 ) ); + } + } + + return bRet; +} + +/** + * load from a foreign format + */ +bool DrawDocShell::ConvertFrom( SfxMedium& rMedium ) +{ + const OUString aFilterName( rMedium.GetFilter()->GetFilterName() ); + bool bRet = false; + bool bStartPresentation = false; + + SetWaitCursor( true ); + + SfxItemSet& rSet = rMedium.GetItemSet(); + if( ( SfxItemState::SET == rSet.GetItemState(SID_PREVIEW ) ) && rSet.Get( SID_PREVIEW ).GetValue() ) + { + mpDoc->SetStarDrawPreviewMode( true ); + } + + if( SfxItemState::SET == rSet.GetItemState(SID_DOC_STARTPRESENTATION)&& + rSet.Get( SID_DOC_STARTPRESENTATION ).GetValue() ) + { + bStartPresentation = true; + mpDoc->SetStartWithPresentation( true ); + } + + if( aFilterName == pFilterPowerPoint97 + || aFilterName == pFilterPowerPoint97Template + || aFilterName == pFilterPowerPoint97AutoPlay) + { + mpDoc->StopWorkStartupDelay(); + bRet = SdPPTFilter( rMedium, *this ).Import(); + } + else if (aFilterName.indexOf("impress8") >= 0 || + aFilterName.indexOf("draw8") >= 0) + { + // TODO/LATER: nobody is interested in the error code?! + mpDoc->CreateFirstPages(); + mpDoc->StopWorkStartupDelay(); + ErrCode nError = ERRCODE_NONE; + bRet = SdXMLFilter( rMedium, *this ).Import( nError ); + + } + else if (aFilterName.indexOf("StarOffice XML (Draw)") >= 0 || + aFilterName.indexOf("StarOffice XML (Impress)") >= 0) + { + // TODO/LATER: nobody is interested in the error code?! + mpDoc->CreateFirstPages(); + mpDoc->StopWorkStartupDelay(); + ErrCode nError = ERRCODE_NONE; + bRet = SdXMLFilter( rMedium, *this, SdXMLFilterMode::Normal, SOFFICE_FILEFORMAT_60 ).Import( nError ); + } + else if (aFilterName == "CGM - Computer Graphics Metafile") + { + mpDoc->CreateFirstPages(); + mpDoc->StopWorkStartupDelay(); + bRet = SdCGMFilter( rMedium, *this ).Import(); + } + else if (aFilterName == "draw_pdf_import") + { + mpDoc->CreateFirstPages(); + mpDoc->StopWorkStartupDelay(); + bRet = SdPdfFilter(rMedium, *this).Import(); + } + else + { + mpDoc->CreateFirstPages(); + mpDoc->StopWorkStartupDelay(); + bRet = SdGRFFilter( rMedium, *this ).Import(); + } + + FinishedLoading(); + + // tell SFX to change viewshell when in preview mode + if( IsPreview() ) + { + GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID, 5 ) ); + } + SetWaitCursor( false ); + + // tell SFX to change viewshell when in preview mode + if( IsPreview() || bStartPresentation ) + { + GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID, bStartPresentation ? 1 : 5 ) ); + } + + return bRet; +} + +/** + * Writes pools and document to the open streams + */ +bool DrawDocShell::Save() +{ + mpDoc->StopWorkStartupDelay(); + + //TODO/LATER: why this?! + if( GetCreateMode() == SfxObjectCreateMode::STANDARD ) + SfxObjectShell::SetVisArea( ::tools::Rectangle() ); + + bool bRet = SfxObjectShell::Save(); + + if( bRet ) + bRet = SdXMLFilter( *GetMedium(), *this, SdXMLFilterMode::Normal, SotStorage::GetVersion( GetMedium()->GetStorage() ) ).Export(); + + return bRet; +} + +/** + * Writes pools and document to the provided storage + */ +bool DrawDocShell::SaveAs( SfxMedium& rMedium ) +{ + mpDoc->setDocAccTitle(OUString()); + if (SfxViewFrame* pFrame1 = SfxViewFrame::GetFirst(this)) + { + if (vcl::Window* pSysWin = pFrame1->GetWindow().GetSystemWindow()) + { + pSysWin->SetAccessibleName(OUString()); + } + } + mpDoc->StopWorkStartupDelay(); + + //With custom animation, if Outliner is modified, update text before saving + if( mpViewShell ) + { + SdPage* pPage = mpViewShell->getCurrentPage(); + if( pPage && pPage->getMainSequence()->getCount() ) + { + SdrObject* pObj = mpViewShell->GetView()->GetTextEditObject(); + SdrOutliner* pOutl = mpViewShell->GetView()->GetTextEditOutliner(); + if( pObj && pOutl && pOutl->IsModified() ) + { + std::optional<OutlinerParaObject> pNewText = pOutl->CreateParaObject( 0, pOutl->GetParagraphCount() ); + pObj->SetOutlinerParaObject( std::move(pNewText) ); + pOutl->ClearModifyFlag(); + } + } + } + + //TODO/LATER: why this?! + if( GetCreateMode() == SfxObjectCreateMode::STANDARD ) + SfxObjectShell::SetVisArea( ::tools::Rectangle() ); + + bool bRet = SfxObjectShell::SaveAs( rMedium ); + + if( bRet ) + bRet = SdXMLFilter( rMedium, *this, SdXMLFilterMode::Normal, SotStorage::GetVersion( rMedium.GetStorage() ) ).Export(); + + if( GetErrorIgnoreWarning() == ERRCODE_NONE ) + SetError(ERRCODE_NONE); + + return bRet; +} + +/** + * save to foreign format + */ +bool DrawDocShell::ConvertTo( SfxMedium& rMedium ) +{ + bool bRet = false; + + if( mpDoc->GetPageCount() ) + { + std::shared_ptr<const SfxFilter> pMediumFilter = rMedium.GetFilter(); + const OUString aTypeName( pMediumFilter->GetTypeName() ); + std::unique_ptr<SdFilter> xFilter; + + if( aTypeName.indexOf( "graphic_HTML" ) >= 0 ) + { + xFilter = std::make_unique<SdHTMLFilter>(rMedium, *this); + } + else if( aTypeName.indexOf( "MS_PowerPoint_97" ) >= 0 ) + { + xFilter = std::make_unique<SdPPTFilter>(rMedium, *this); + static_cast<SdPPTFilter*>(xFilter.get())->PreSaveBasic(); + } + else if ( aTypeName.indexOf( "CGM_Computer_Graphics_Metafile" ) >= 0 ) + { + xFilter = std::make_unique<SdCGMFilter>(rMedium, *this); + } + else if( aTypeName.indexOf( "draw8" ) >= 0 || + aTypeName.indexOf( "impress8" ) >= 0 ) + { + xFilter = std::make_unique<SdXMLFilter>(rMedium, *this); + } + else if( aTypeName.indexOf( "StarOffice_XML_Impress" ) >= 0 || + aTypeName.indexOf( "StarOffice_XML_Draw" ) >= 0 ) + { + xFilter = std::make_unique<SdXMLFilter>(rMedium, *this, SdXMLFilterMode::Normal, SOFFICE_FILEFORMAT_60); + } + else + { + xFilter = std::make_unique<SdGRFFilter>(rMedium, *this); + } + + if (xFilter) + { + if ( mpViewShell ) + { + ::sd::View* pView = mpViewShell->GetView(); + if ( pView->IsTextEdit() ) + pView->SdrEndTextEdit(); + } + + bRet = xFilter->Export(); + } + } + + return bRet; +} + +/** + * Reopen own streams to ensure that nobody else can prevent use from opening + * them. + */ +bool DrawDocShell::SaveCompleted( const css::uno::Reference< css::embed::XStorage >& xStorage ) +{ + bool bRet = false; + + if( SfxObjectShell::SaveCompleted(xStorage) ) + { + mpDoc->NbcSetChanged( false ); + + if( mpViewShell ) + { + if( dynamic_cast< OutlineViewShell *>( mpViewShell ) != nullptr ) + static_cast<OutlineView*>(mpViewShell->GetView()) + ->GetOutliner().ClearModifyFlag(); + + SdrOutliner* pOutl = mpViewShell->GetView()->GetTextEditOutliner(); + if( pOutl ) + { + SdrObject* pObj = mpViewShell->GetView()->GetTextEditObject(); + if( pObj ) + pObj->NbcSetOutlinerParaObject( pOutl->CreateParaObject() ); + + pOutl->ClearModifyFlag(); + } + } + + bRet = true; + + SfxViewFrame* pFrame = ( mpViewShell && mpViewShell->GetViewFrame() ) ? + mpViewShell->GetViewFrame() : + SfxViewFrame::Current(); + + if( pFrame ) + pFrame->GetBindings().Invalidate( SID_NAVIGATOR_STATE, true ); + } + return bRet; +} + +SfxStyleSheetBasePool* DrawDocShell::GetStyleSheetPool() +{ + return mpDoc->GetStyleSheetPool(); +} + +void DrawDocShell::GotoBookmark(std::u16string_view rBookmark) +{ + auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ); + if (!pDrawViewShell) + return; + + ViewShellBase& rBase (mpViewShell->GetViewShellBase()); + + bool bIsMasterPage = false; + sal_uInt16 nPageNumber = SDRPAGE_NOTFOUND; + SdrObject* pObj = nullptr; + + static constexpr std::u16string_view sInteraction( u"action?" ); + if ( o3tl::starts_with(rBookmark, sInteraction ) ) + { + static constexpr std::u16string_view sJump( u"jump=" ); + if ( o3tl::starts_with(rBookmark.substr( sInteraction.size() ), sJump ) ) + { + std::u16string_view aDestination( rBookmark.substr( sInteraction.size() + sJump.size() ) ); + if ( o3tl::starts_with(aDestination, u"firstslide" ) ) + { + nPageNumber = 1; + } + else if ( o3tl::starts_with(aDestination, u"lastslide" ) ) + { + nPageNumber = mpDoc->GetPageCount() - 2; + } + else if ( o3tl::starts_with(aDestination, u"previousslide" ) ) + { + SdPage* pPage = pDrawViewShell->GetActualPage(); + nPageNumber = pPage->GetPageNum(); + nPageNumber = nPageNumber > 2 ? nPageNumber - 2 : SDRPAGE_NOTFOUND; + } + else if ( o3tl::starts_with(aDestination, u"nextslide" ) ) + { + SdPage* pPage = pDrawViewShell->GetActualPage(); + nPageNumber = pPage->GetPageNum() + 2; + if ( nPageNumber >= mpDoc->GetPageCount() ) + nPageNumber = SDRPAGE_NOTFOUND; + } + } + } + else + { + // Is the bookmark a page? + nPageNumber = mpDoc->GetPageByName( rBookmark, bIsMasterPage ); + + if (nPageNumber == SDRPAGE_NOTFOUND) + { + // Is the bookmark an object? + pObj = mpDoc->GetObj(rBookmark); + + if (pObj) + { + nPageNumber = pObj->getSdrPageFromSdrObject()->GetPageNum(); + } + } + } + if (nPageNumber != SDRPAGE_NOTFOUND) + { + // Jump to the bookmarked page. This is done in three steps. + + SdPage* pPage; + if (bIsMasterPage) + pPage = static_cast<SdPage*>( mpDoc->GetMasterPage(nPageNumber) ); + else + pPage = static_cast<SdPage*>( mpDoc->GetPage(nPageNumber) ); + + // 1.) Change the view shell to the edit view, the notes view, + // or the handout view. + PageKind eNewPageKind = pPage->GetPageKind(); + + if( (eNewPageKind != PageKind::Standard) && (mpDoc->GetDocumentType() == DocumentType::Draw) ) + return; + + if (eNewPageKind != pDrawViewShell->GetPageKind()) + { + // change work area + GetFrameView()->SetPageKind(eNewPageKind); + OUString sViewURL; + switch (eNewPageKind) + { + case PageKind::Standard: + sViewURL = FrameworkHelper::msImpressViewURL; + break; + case PageKind::Notes: + sViewURL = FrameworkHelper::msNotesViewURL; + break; + case PageKind::Handout: + sViewURL = FrameworkHelper::msHandoutViewURL; + break; + default: + break; + } + if (!sViewURL.isEmpty()) + { + std::shared_ptr<FrameworkHelper> pHelper ( + FrameworkHelper::Instance(rBase)); + pHelper->RequestView( + sViewURL, + FrameworkHelper::msCenterPaneURL); + pHelper->WaitForUpdate(); + + // Get the new DrawViewShell. + mpViewShell = pHelper->GetViewShell(FrameworkHelper::msCenterPaneURL).get(); + pDrawViewShell = dynamic_cast<sd::DrawViewShell*>(mpViewShell); + } + else + { + pDrawViewShell = nullptr; + } + } + + if (pDrawViewShell != nullptr) + { + setEditMode(pDrawViewShell, bIsMasterPage); + + // Make the bookmarked page the current page. This is done + // by using the API because this takes care of all the + // little things to be done. Especially writing the view + // data to the frame view. + sal_uInt16 nSdPgNum = (nPageNumber - 1) / 2; + Reference<drawing::XDrawView> xController (rBase.GetController(), UNO_QUERY); + if (xController.is()) + { + Reference<drawing::XDrawPage> xDrawPage (pPage->getUnoPage(), UNO_QUERY); + xController->setCurrentPage (xDrawPage); + } + else + { + // As a fall back switch to the page via the core. + DBG_ASSERT (xController.is(), + "DrawDocShell::GotoBookmark: can't switch page via API"); + pDrawViewShell->SwitchPage(nSdPgNum); + } + + // Do UnmarkAll here to stop the Navigator from reselecting the previously marked + // entry when a slide entry is selected. + pDrawViewShell->GetView()->UnmarkAll(); + if (pObj != nullptr) + { + // show and select object + if (vcl::Window* pWindow = pDrawViewShell->GetActiveWindow()) + pDrawViewShell->MakeVisible(pObj->GetSnapRect(), *pWindow); + pDrawViewShell->GetView()->MarkObj( + pObj, + pDrawViewShell->GetView()->GetSdrPageView()); + } + } + } + + if (SfxViewFrame* pViewFrame = (pDrawViewShell && pDrawViewShell->GetViewFrame()) + ? pDrawViewShell->GetViewFrame() + : SfxViewFrame::Current()) + { + SfxBindings& rBindings = pViewFrame->GetBindings(); + rBindings.Invalidate(SID_NAVIGATOR_STATE, true); + rBindings.Invalidate(SID_NAVIGATOR_PAGENAME); + } +} + +/** + * If it should become a document template. + */ +bool DrawDocShell::SaveAsOwnFormat( SfxMedium& rMedium ) +{ + + std::shared_ptr<const SfxFilter> pFilter = rMedium.GetFilter(); + + if (pFilter->IsOwnTemplateFormat()) + { + /* now the StarDraw specialty: + we assign known layout names to the layout template of the first + page, we set the layout names of the affected masterpages and pages. + We inform all text objects of the affected standard, note and + masterpages about the name change. + */ + + OUString aLayoutName; + + SfxStringItem const * pLayoutItem = rMedium.GetItemSet().GetItemIfSet(SID_TEMPLATE_NAME, false); + if( pLayoutItem ) + { + aLayoutName = pLayoutItem->GetValue(); + } + else + { + INetURLObject aURL( rMedium.GetName() ); + aURL.removeExtension(); + aLayoutName = aURL.getName(); + } + + if (aLayoutName.isEmpty()) + { + sal_uInt32 nCount = mpDoc->GetMasterSdPageCount(PageKind::Standard); + for (sal_uInt32 i = 0; i < nCount; ++i) + { + OUString aOldPageLayoutName = mpDoc->GetMasterSdPage(i, PageKind::Standard)->GetLayoutName(); + OUString aNewLayoutName = aLayoutName; + // Don't add suffix for the first master page + if( i > 0 ) + aNewLayoutName += OUString::number(i); + + mpDoc->RenameLayoutTemplate(aOldPageLayoutName, aNewLayoutName); + } + } + } + + return SfxObjectShell::SaveAsOwnFormat(rMedium); +} + +void DrawDocShell::FillClass(SvGlobalName* pClassName, + SotClipboardFormatId* pFormat, + OUString* pFullTypeName, + sal_Int32 nFileFormat, + bool bTemplate /* = false */) const +{ + if (nFileFormat == SOFFICE_FILEFORMAT_60) + { + if ( meDocType == DocumentType::Draw ) + { + *pClassName = SvGlobalName(SO3_SDRAW_CLASSID_60); + *pFormat = SotClipboardFormatId::STARDRAW_60; + *pFullTypeName = SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_60); + } + else + { + *pClassName = SvGlobalName(SO3_SIMPRESS_CLASSID_60); + *pFormat = SotClipboardFormatId::STARIMPRESS_60; + *pFullTypeName = SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_60); + } + } + else if (nFileFormat == SOFFICE_FILEFORMAT_8) + { + if ( meDocType == DocumentType::Draw ) + { + *pClassName = SvGlobalName(SO3_SDRAW_CLASSID_60); + *pFormat = bTemplate ? SotClipboardFormatId::STARDRAW_8_TEMPLATE : SotClipboardFormatId::STARDRAW_8; + *pFullTypeName = SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_80); // HACK: method will be removed with new storage API + } + else + { + *pClassName = SvGlobalName(SO3_SIMPRESS_CLASSID_60); + *pFormat = bTemplate ? SotClipboardFormatId::STARIMPRESS_8_TEMPLATE : SotClipboardFormatId::STARIMPRESS_8; + *pFullTypeName = SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_80); // HACK: method will be removed with new storage API + } + } +} + +OutputDevice* DrawDocShell::GetDocumentRefDev() +{ + OutputDevice* pReferenceDevice = SfxObjectShell::GetDocumentRefDev (); + // Only when our parent does not have a reference device then we return + // our own. + if (pReferenceDevice == nullptr && mpDoc != nullptr) + pReferenceDevice = mpDoc->GetRefDevice (); + return pReferenceDevice; +} + +/** executes the SID_OPENDOC slot to let the framework open a document + with the given URL and this document as a referer */ +void DrawDocShell::OpenBookmark( const OUString& rBookmarkURL ) +{ + SfxStringItem aStrItem( SID_FILE_NAME, rBookmarkURL ); + SfxStringItem aReferer( SID_REFERER, GetMedium()->GetName() ); + const SfxPoolItem* ppArgs[] = { &aStrItem, &aReferer, nullptr }; + if (SfxViewFrame* pFrame = mpViewShell ? mpViewShell->GetViewFrame() : SfxViewFrame::Current()) + pFrame->GetBindings().Execute( SID_OPENHYPERLINK, ppArgs ); +} + +std::shared_ptr<SfxDocumentInfoDialog> DrawDocShell::CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet &rSet) +{ + std::shared_ptr<SfxDocumentInfoDialog> xDlg = std::make_shared<SfxDocumentInfoDialog>(pParent, rSet); + DrawDocShell* pDocSh = dynamic_cast<DrawDocShell*>(SfxObjectShell::Current()); + if( pDocSh == this ) + { + xDlg->AddFontTabPage(); + } + return xDlg; +} + +void DrawDocShell::setEditMode(DrawViewShell* pDrawViewShell, bool isMasterPage) +{ + // Set the edit mode to either the normal edit mode or the + // master page mode. + EditMode eNewEditMode = EditMode::Page; + if (isMasterPage) + { + eNewEditMode = EditMode::MasterPage; + } + + if (eNewEditMode != pDrawViewShell->GetEditMode()) + { + // Set EditMode + pDrawViewShell->ChangeEditMode(eNewEditMode, false); + } +} +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/docshell/docshell.cxx b/sd/source/ui/docshell/docshell.cxx new file mode 100644 index 0000000000..5ac592f80b --- /dev/null +++ b/sd/source/ui/docshell/docshell.cxx @@ -0,0 +1,507 @@ +/* -*- 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 <DrawDocShell.hxx> + +#include <officecfg/Office/Common.hxx> +#include <unotools/configmgr.hxx> + +#include <sfx2/docfac.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/svxids.hrc> +#include <svl/srchitem.hxx> +#include <svx/srchdlg.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svditer.hxx> +#include <editeng/flstitem.hxx> +#include <editeng/eeitem.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <sfx2/printer.hxx> +#include <svx/drawitem.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/whiter.hxx> +#include <svl/itempool.hxx> +#include <svl/stritem.hxx> +#include <svtools/ctrltool.hxx> +#include <svtools/langtab.hxx> +#include <comphelper/classids.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/visitem.hxx> + +#include <app.hrc> +#include <sdmod.hxx> +#include <View.hxx> +#include <drawdoc.hxx> + +#include <ViewShell.hxx> +#include <unomodel.hxx> +#include <undo/undomanager.hxx> +#include <undo/undofactory.hxx> +#include <OutlineView.hxx> +#include <ViewShellBase.hxx> +#include <sfx2/notebookbar/SfxNotebookBar.hxx> +#include <comphelper/lok.hxx> +#include <DrawViewShell.hxx> +#include <sdpage.hxx> +#include <docmodel/theme/Theme.hxx> +#include <Outliner.hxx> + +using namespace sd; +#define ShellClass_DrawDocShell +#include <sdslots.hxx> + +SFX_IMPL_SUPERCLASS_INTERFACE(DrawDocShell, SfxObjectShell); + +void DrawDocShell::InitInterface_Impl() +{ + GetStaticInterface()->RegisterChildWindow(SvxSearchDialogWrapper::GetChildWindowId()); +} + +namespace sd { + +/** + * slotmaps and definitions of SFX + */ + +SFX_IMPL_OBJECTFACTORY( + DrawDocShell, + SvGlobalName(SO3_SIMPRESS_CLASSID), + "simpress" ) + +void DrawDocShell::Construct( bool bClipboard ) +{ + mbInDestruction = false; + SetSlotFilter(); // resets the filter + + mbOwnDocument = mpDoc == nullptr; + if( mbOwnDocument ) + mpDoc = new SdDrawDocument(meDocType, this); + + // The document has been created so we can call UpdateRefDevice() to set + // the document's ref device. + UpdateRefDevice(); + + SetBaseModel( new SdXImpressDocument( this, bClipboard ) ); + SetPool( &mpDoc->GetItemPool() ); + std::unique_ptr<sd::UndoManager> pUndoManager(new sd::UndoManager); + pUndoManager->SetDocShell(this); + mpUndoManager = std::move(pUndoManager); + + if (!utl::ConfigManager::IsFuzzing() + && officecfg::Office::Common::Undo::Steps::get() < 1) + { + mpUndoManager->EnableUndo(false); // tdf#108863 disable if 0 steps + } + mpDoc->SetSdrUndoManager( mpUndoManager.get() ); + mpDoc->SetSdrUndoFactory( new sd::UndoFactory ); + UpdateTablePointers(); + SetStyleFamily(SfxStyleFamily::Pseudo); +} + +DrawDocShell::DrawDocShell(SfxObjectCreateMode eMode, + bool bDataObject, + DocumentType eDocumentType) : + SfxObjectShell( eMode == SfxObjectCreateMode::INTERNAL ? SfxObjectCreateMode::EMBEDDED : eMode), + mpDoc(nullptr), + mpPrinter(nullptr), + mpViewShell(nullptr), + meDocType(eDocumentType), + mbSdDataObj(bDataObject), + mbOwnPrinter(false) +{ + Construct( eMode == SfxObjectCreateMode::INTERNAL ); +} + +DrawDocShell::DrawDocShell( SfxModelFlags nModelCreationFlags, bool bDataObject, DocumentType eDocumentType ) : + SfxObjectShell( nModelCreationFlags ), + mpDoc(nullptr), + mpPrinter(nullptr), + mpViewShell(nullptr), + meDocType(eDocumentType), + mbSdDataObj(bDataObject), + mbOwnPrinter(false) +{ + Construct( false ); +} + +DrawDocShell::DrawDocShell(SdDrawDocument* pDoc, SfxObjectCreateMode eMode, + bool bDataObject, + DocumentType eDocumentType) : + SfxObjectShell(eMode == SfxObjectCreateMode::INTERNAL ? SfxObjectCreateMode::EMBEDDED : eMode), + mpDoc(pDoc), + mpPrinter(nullptr), + mpViewShell(nullptr), + meDocType(eDocumentType), + mbSdDataObj(bDataObject), + mbOwnPrinter(false) +{ + Construct( eMode == SfxObjectCreateMode::INTERNAL ); +} + +DrawDocShell::~DrawDocShell() +{ + // Tell all listeners that the doc shell is about to be + // destroyed. This has been introduced for the PreviewRenderer to + // free its view (that uses the item poll of the doc shell) but + // may be useful in other places as well. + Broadcast(SfxHint(SfxHintId::Dying)); + + mbInDestruction = true; + + if (mpViewShell) + { + auto* pView = mpViewShell->GetView(); + if (pView) + { + auto & pSearchContext = pView->getSearchContext(); + pSearchContext.resetSearchFunction(); + } + } + + mpFontList.reset(); + + if( mpDoc ) + mpDoc->SetSdrUndoManager( nullptr ); + mpUndoManager.reset(); + + if (mbOwnPrinter) + mpPrinter.disposeAndClear(); + + if( mbOwnDocument ) + delete mpDoc; + + // that the navigator get informed about the disappearance of the document + SfxBoolItem aItem(SID_NAVIGATOR_INIT, true); + SfxViewFrame* pFrame = mpViewShell ? mpViewShell->GetFrame() : GetFrame(); + + if( !pFrame ) + pFrame = SfxViewFrame::GetFirst( this ); + + if( pFrame ) + { + pFrame->GetDispatcher()->ExecuteList( + SID_NAVIGATOR_INIT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aItem }); + } +} + +void DrawDocShell::GetState(SfxItemSet &rSet) +{ + + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + + while ( nWhich ) + { + sal_uInt16 nSlotId = SfxItemPool::IsWhich(nWhich) + ? GetPool().GetSlotId(nWhich) + : nWhich; + + switch ( nSlotId ) + { + case SID_ATTR_CHAR_FONTLIST: + rSet.Put( SvxFontListItem( mpFontList.get(), nSlotId ) ); + break; + + case SID_SEARCH_ITEM: + { + rSet.Put( *SD_MOD()->GetSearchItem() ); + } + break; + + case SID_CLOSEDOC: + GetSlotState(SID_CLOSEDOC, SfxObjectShell::GetInterface(), &rSet); + break; + + case SID_SEARCH_OPTIONS: + { + SearchOptionFlags nOpt = SearchOptionFlags::SEARCH | + SearchOptionFlags::WHOLE_WORDS | + SearchOptionFlags::BACKWARDS | + SearchOptionFlags::REG_EXP | + SearchOptionFlags::EXACT | + SearchOptionFlags::SIMILARITY | + SearchOptionFlags::SELECTION; + + if (!IsReadOnly()) + { + nOpt |= SearchOptionFlags::REPLACE; + nOpt |= SearchOptionFlags::REPLACE_ALL; + } + + rSet.Put(SfxUInt16Item(nWhich, static_cast<sal_uInt16>(nOpt))); + } + break; + + case SID_VERSION: + { + GetSlotState( SID_VERSION, SfxObjectShell::GetInterface(), &rSet ); + } + break; + + case SID_CHINESE_CONVERSION: + case SID_HANGUL_HANJA_CONVERSION: + { + rSet.Put(SfxVisibilityItem(nWhich, SvtCJKOptions::IsAnyEnabled())); + } + break; + case SID_LANGUAGE_STATUS: + { + SdrObject* pObj = nullptr; + bool bLanguageFound = false; + OutlinerParaObject* pParaObj = nullptr; + LanguageType eLanguage( LANGUAGE_DONTKNOW ); + sal_uInt16 nCount = mpDoc->GetPageCount(); + for ( sal_uInt16 itPage = 0; itPage < nCount && !bLanguageFound; itPage++ ) + { + SdrObjListIter aListIter(mpDoc->GetPage(itPage), SdrIterMode::DeepWithGroups); + while ( aListIter.IsMore() && !bLanguageFound ) + { + pObj = aListIter.Next(); + if ( pObj ) + { + pParaObj = pObj->GetOutlinerParaObject(); + if ( pParaObj ) + { + SdrOutliner aOutliner(&mpDoc->GetPool(), OutlinerMode::TextObject); + aOutliner.SetText(*pParaObj); + eLanguage = aOutliner.GetLanguage(0, 0); + bLanguageFound = eLanguage != LANGUAGE_DONTKNOW; + } + } + } + } + + if ( eLanguage == LANGUAGE_DONTKNOW ) + { + eLanguage = mpDoc->GetLanguage( EE_CHAR_LANGUAGE ); + } + + OUString aLanguage = SvtLanguageTable::GetLanguageString(eLanguage); + if (comphelper::LibreOfficeKit::isActive()) + { + if (eLanguage == LANGUAGE_DONTKNOW) + { + aLanguage += ";-"; + } + else + { + aLanguage += ";" + LanguageTag(eLanguage).getBcp47(false); + } + } + rSet.Put(SfxStringItem(nWhich, aLanguage)); + } + break; + + case SID_NOTEBOOKBAR: + { + if (mpViewShell) + { + bool bImpress = mpDoc->GetDocumentType() == DocumentType::Impress; + bool bVisible = false; + if(bImpress) + { + bVisible = sfx2::SfxNotebookBar::StateMethod(mpViewShell->GetFrame()->GetBindings(), + u"modules/simpress/ui/"); + } + else + { + bVisible = sfx2::SfxNotebookBar::StateMethod(mpViewShell->GetFrame()->GetBindings(), + u"modules/sdraw/ui/"); + } + rSet.Put( SfxBoolItem( SID_NOTEBOOKBAR, bVisible ) ); + } + } + break; + + default: + break; + } + nWhich = aIter.NextWhich(); + } + + if (SfxViewFrame* pFrame = SfxViewFrame::Current()) + { + if (rSet.GetItemState(SID_RELOAD) != SfxItemState::UNKNOWN) + { + pFrame->GetSlotState(SID_RELOAD, + pFrame->GetInterface(), &rSet); + } + } +} + +void DrawDocShell::Activate( bool bMDI) +{ + if (bMDI) + { + ApplySlotFilter(); + mpDoc->StartOnlineSpelling(); + } +} + +void DrawDocShell::Deactivate( bool ) +{ +} + +SfxUndoManager* DrawDocShell::GetUndoManager() +{ + return mpUndoManager.get(); +} + +void DrawDocShell::UpdateTablePointers() +{ + PutItem( SvxColorListItem( mpDoc->GetColorList(), SID_COLOR_TABLE ) ); + PutItem( SvxGradientListItem( mpDoc->GetGradientList(), SID_GRADIENT_LIST ) ); + PutItem( SvxHatchListItem( mpDoc->GetHatchList(), SID_HATCH_LIST ) ); + PutItem( SvxBitmapListItem( mpDoc->GetBitmapList(), SID_BITMAP_LIST ) ); + PutItem( SvxPatternListItem( mpDoc->GetPatternList(), SID_PATTERN_LIST ) ); + PutItem( SvxDashListItem( mpDoc->GetDashList(), SID_DASH_LIST ) ); + PutItem( SvxLineEndListItem( mpDoc->GetLineEndList(), SID_LINEEND_LIST ) ); + + UpdateFontList(); +} + +void DrawDocShell::CancelSearching() +{ + if (mpViewShell) + { + auto* pView = mpViewShell->GetView(); + if (pView) + { + auto & pSearchContext = pView->getSearchContext(); + pSearchContext.resetSearchFunction(); + } + } +} + +/** + * apply configured slot filters + */ +void DrawDocShell::ApplySlotFilter() const +{ + SfxViewShell* pTestViewShell = SfxViewShell::GetFirst(); + + while( pTestViewShell ) + { + if( pTestViewShell->GetObjectShell() == this + && pTestViewShell->GetViewFrame().GetDispatcher() ) + { + SfxDispatcher* pDispatcher = pTestViewShell->GetViewFrame().GetDispatcher(); + + if( !mpFilterSIDs.empty() ) + pDispatcher->SetSlotFilter( mbFilterEnable ? SfxSlotFilterState::ENABLED : SfxSlotFilterState::DISABLED, mpFilterSIDs ); + else + pDispatcher->SetSlotFilter(); + + if( pDispatcher->GetBindings() ) + pDispatcher->GetBindings()->InvalidateAll( true ); + } + + pTestViewShell = SfxViewShell::GetNext( *pTestViewShell ); + } +} + +void DrawDocShell::SetModified( bool bSet /* = true */ ) +{ + SfxObjectShell::SetModified( bSet ); + + // change model state, too + // only set the changed state if modification is enabled + if( IsEnableSetModified() ) + { + if ( mpDoc ) + mpDoc->NbcSetChanged( bSet ); + + Broadcast( SfxHint( SfxHintId::DocChanged ) ); + } +} + +/** + * Callback for ExecuteSpellPopup() + */ +// ExecuteSpellPopup now handled by DrawDocShell. This is necessary +// to get hands on the outliner and the text object. +IMPL_LINK(DrawDocShell, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void) +{ + SdrObject* pObj = nullptr; + SdrOutliner* pOutl = nullptr; + + if(GetViewShell()) + { + pOutl = GetViewShell()->GetView()->GetTextEditOutliner(); + pObj = GetViewShell()->GetView()->GetTextEditObject(); + } + + mpDoc->ImpOnlineSpellCallback(&rInfo, pObj, pOutl); +} + +void DrawDocShell::ClearUndoBuffer() +{ + // clear possible undo buffers of outliners + SfxViewFrame* pSfxViewFrame = SfxViewFrame::GetFirst(this, false); + while(pSfxViewFrame) + { + ViewShellBase* pViewShellBase = dynamic_cast< ViewShellBase* >( pSfxViewFrame->GetViewShell() ); + if( pViewShellBase ) + { + std::shared_ptr<ViewShell> pViewSh( pViewShellBase->GetMainViewShell() ); + if( pViewSh ) + { + ::sd::View* pView = pViewSh->GetView(); + if( pView ) + { + pView->SdrEndTextEdit(); + sd::OutlineView* pOutlView = dynamic_cast< sd::OutlineView* >( pView ); + if( pOutlView ) + { + pOutlView->GetOutliner().GetUndoManager().Clear(); + } + } + } + } + pSfxViewFrame = SfxViewFrame::GetNext(*pSfxViewFrame, this, false); + } + + SfxUndoManager* pUndoManager = GetUndoManager(); + if(pUndoManager && pUndoManager->GetUndoActionCount()) + pUndoManager->Clear(); +} + +std::shared_ptr<model::ColorSet> DrawDocShell::GetThemeColors() +{ + auto pViewShell = dynamic_cast<sd::DrawViewShell*>(GetViewShell()); + if (!pViewShell) + return {}; + + SdPage* pPage = pViewShell->getCurrentPage(); + auto pTheme = pPage->getSdrPageProperties().getTheme(); + if (!pPage->IsMasterPage()) + pTheme = pPage->TRG_GetMasterPage().getSdrPageProperties().getTheme(); + + if (!pTheme) + return {}; + + return pTheme->getColorSet(); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/docshell/grdocsh.cxx b/sd/source/ui/docshell/grdocsh.cxx new file mode 100644 index 0000000000..f0f5af9562 --- /dev/null +++ b/sd/source/ui/docshell/grdocsh.cxx @@ -0,0 +1,61 @@ +/* -*- 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 <svx/svxids.hrc> +#include <tools/globname.hxx> + +#include <comphelper/classids.hxx> + +#include <sfx2/objface.hxx> + +#include <GraphicDocShell.hxx> +#include <DrawDocShell.hxx> + +using namespace sd; +#define ShellClass_GraphicDocShell +#include <sdgslots.hxx> + +namespace sd +{ +SFX_IMPL_SUPERCLASS_INTERFACE(GraphicDocShell, SfxObjectShell) + +void GraphicDocShell::InitInterface_Impl() +{ + GetStaticInterface()->RegisterChildWindow(SID_SEARCH_DLG); +} + +SFX_IMPL_OBJECTFACTORY(GraphicDocShell, SvGlobalName(SO3_SDRAW_CLASSID_60), "sdraw") + +GraphicDocShell::GraphicDocShell(SfxObjectCreateMode eMode) + : DrawDocShell(eMode, /*bDataObject*/ true, DocumentType::Draw) +{ + SetStyleFamily(SfxStyleFamily::Para); +} + +GraphicDocShell::GraphicDocShell(SfxModelFlags nModelCreationFlags) + : DrawDocShell(nModelCreationFlags, /*bDataObject*/ false, DocumentType::Draw) +{ + SetStyleFamily(SfxStyleFamily::Para); +} + +GraphicDocShell::~GraphicDocShell() {} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/docshell/sdclient.cxx b/sd/source/ui/docshell/sdclient.cxx new file mode 100644 index 0000000000..c0b7b38edb --- /dev/null +++ b/sd/source/ui/docshell/sdclient.cxx @@ -0,0 +1,191 @@ +/* -*- 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 <Client.hxx> +#include <svx/svdoole2.hxx> +#include <tools/debug.hxx> + +#include <ViewShell.hxx> +#include <View.hxx> +#include <vcl/svapp.hxx> + +using namespace com::sun::star; + +namespace sd { + +Client::Client(SdrOle2Obj* pObj, ViewShell* pViewShell, vcl::Window* pWindow) : + SfxInPlaceClient(pViewShell->GetViewShell(), pWindow, pObj->GetAspect() ), + mpViewShell(pViewShell), + pSdrOle2Obj(pObj) +{ + SetObject( pObj->GetObjRef() ); + DBG_ASSERT( GetObject().is(), "No object connected!" ); +} + +Client::~Client() +{ +} + +/** + * If IP active, then we get this request to increase the visible section of the + * object. + */ +void Client::RequestNewObjectArea( ::tools::Rectangle& aObjRect ) +{ + ::sd::View* pView = mpViewShell->GetView(); + + bool bSizeProtect = false; + bool bPosProtect = false; + + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + { + SdrMark* pMark = rMarkList.GetMark(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + + // no need to check for changes, this method is called only if the area really changed + bSizeProtect = pObj->IsResizeProtect(); + bPosProtect = pObj->IsMoveProtect(); + } + + ::tools::Rectangle aOldRect = GetObjArea(); + if ( bPosProtect ) + aObjRect.SetPos( aOldRect.TopLeft() ); + + if ( bSizeProtect ) + aObjRect.SetSize( aOldRect.GetSize() ); + + ::tools::Rectangle aWorkArea( pView->GetWorkArea() ); + if ( aWorkArea.Contains(aObjRect) || bPosProtect || aObjRect == aOldRect ) + return; + + // correct position + Point aPos = aObjRect.TopLeft(); + Size aSize = aObjRect.GetSize(); + Point aWorkAreaTL = aWorkArea.TopLeft(); + Point aWorkAreaBR = aWorkArea.BottomRight(); + + aPos.setX( std::max(aPos.X(), aWorkAreaTL.X()) ); + aPos.setX( std::min(aPos.X(), aWorkAreaBR.X()-aSize.Width()) ); + aPos.setY( std::max(aPos.Y(), aWorkAreaTL.Y()) ); + aPos.setY( std::min(aPos.Y(), aWorkAreaBR.Y()-aSize.Height()) ); + + aObjRect.SetPos(aPos); +} + +void Client::ObjectAreaChanged() +{ + ::sd::View* pView = mpViewShell->GetView(); + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() != 1) + return; + + SdrMark* pMark = rMarkList.GetMark(0); + SdrOle2Obj* pObj = dynamic_cast< SdrOle2Obj* >(pMark->GetMarkedSdrObj()); + + if(!pObj) + return; + + // no need to check for changes, this method is called only if the area really changed + ::tools::Rectangle aNewRectangle(GetScaledObjArea()); + + // #i118524# if sheared/rotated, center to non-rotated LogicRect + pObj->setSuppressSetVisAreaSize(true); + + if(pObj->GetGeoStat().m_nRotationAngle || pObj->GetGeoStat().m_nShearAngle) + { + pObj->SetLogicRect( aNewRectangle ); + + const ::tools::Rectangle& rBoundRect = pObj->GetCurrentBoundRect(); + const Point aDelta(aNewRectangle.Center() - rBoundRect.Center()); + + aNewRectangle.Move(aDelta.X(), aDelta.Y()); + } + + pObj->SetLogicRect( aNewRectangle ); + pObj->setSuppressSetVisAreaSize(false); +} + +void Client::ViewChanged() +{ + if ( GetAspect() == embed::Aspects::MSOLE_ICON ) + { + // the iconified object seems not to need such a scaling handling + // since the replacement image and the size a completely controlled by the container + // TODO/LATER: when the icon exchange is implemented the scaling handling might be required again here + + pSdrOle2Obj->ActionChanged(); // draw needs it to remove lines in slide preview + return; + } + + //TODO/LATER: should we try to avoid the recalculation of the visareasize + //if we know that it didn't change? + if (!mpViewShell->GetActiveWindow()) + return; + + ::sd::View* pView = mpViewShell->GetView(); + if (!pView) + return; + + // Do not recalculate the visareasize if the embedded object is opening in a new window. + if (!IsObjectInPlaceActive()) + { + pSdrOle2Obj->BroadcastObjectChange(); + return; + } + + ::tools::Rectangle aLogicRect( pSdrOle2Obj->GetLogicRect() ); + Size aLogicSize( aLogicRect.GetWidth(), aLogicRect.GetHeight() ); + + if( pSdrOle2Obj->IsChart() ) + { + //charts never should be stretched see #i84323# for example + pSdrOle2Obj->SetLogicRect( ::tools::Rectangle( aLogicRect.TopLeft(), aLogicSize ) ); + pSdrOle2Obj->BroadcastObjectChange(); + return; + } + + // TODO/LEAN: maybe we can do this without requesting the VisualArea? + // working with the visual area might need running state, so the object may switch itself to this state + MapMode aMap100( MapUnit::Map100thMM ); + ::tools::Rectangle aVisArea; + Size aSize = pSdrOle2Obj->GetOrigObjSize( &aMap100 ); + + aVisArea.SetSize( aSize ); + Size aScaledSize( static_cast< ::tools::Long >( GetScaleWidth() * Fraction( aVisArea.GetWidth() ) ), + static_cast< ::tools::Long >( GetScaleHeight() * Fraction( aVisArea.GetHeight() ) ) ); + + // react to the change if the difference is bigger than one pixel + Size aPixelDiff = + Application::GetDefaultDevice()->LogicToPixel( + Size( aLogicRect.GetWidth() - aScaledSize.Width(), + aLogicRect.GetHeight() - aScaledSize.Height() ), + aMap100 ); + if( aPixelDiff.Width() || aPixelDiff.Height() ) + { + pSdrOle2Obj->SetLogicRect( ::tools::Rectangle( aLogicRect.TopLeft(), aScaledSize ) ); + pSdrOle2Obj->BroadcastObjectChange(); + } + else + pSdrOle2Obj->ActionChanged(); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |