diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sd/source/ui/func | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sd/source/ui/func')
59 files changed, 19197 insertions, 0 deletions
diff --git a/sd/source/ui/func/bulmaper.cxx b/sd/source/ui/func/bulmaper.cxx new file mode 100644 index 000000000..67a667891 --- /dev/null +++ b/sd/source/ui/func/bulmaper.cxx @@ -0,0 +1,104 @@ +/* -*- 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 <editeng/editids.hrc> + +//-> Fonts & Items +#include <vcl/font.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/contouritem.hxx> +#include <editeng/shdditem.hxx> + +//<- Fonts & Items +#include <svl/itemset.hxx> +#include <svl/itempool.hxx> +#include <editeng/numitem.hxx> + +#include <bulmaper.hxx> + +#define GetWhich(nSlot) rSet.GetPool()->GetWhich( nSlot ) + +void SdBulletMapper::MapFontsInNumRule( SvxNumRule& aNumRule, const SfxItemSet& rSet ) +{ + const sal_uInt16 nCount = aNumRule.GetLevelCount(); + for( sal_uInt16 nLevel = 0; nLevel < nCount; nLevel++ ) + { + const SvxNumberFormat& rSrcLevel = aNumRule.GetLevel(nLevel); + SvxNumberFormat aNewLevel( rSrcLevel ); + + if(rSrcLevel.GetNumberingType() != css::style::NumberingType::CHAR_SPECIAL && + rSrcLevel.GetNumberingType() != css::style::NumberingType::NUMBER_NONE ) + { + // if enumeration instead bullet is chosen, adjust bullet font to template font + + // to be implemented if module supports CJK + + vcl::Font aMyFont; + const SvxFontItem& rFItem = + static_cast<const SvxFontItem&>(rSet.Get(GetWhich( sal_uInt16(SID_ATTR_CHAR_FONT) ))); + aMyFont.SetFamily(rFItem.GetFamily()); + aMyFont.SetFamilyName(rFItem.GetFamilyName()); + aMyFont.SetCharSet(rFItem.GetCharSet()); + aMyFont.SetPitch(rFItem.GetPitch()); + + const SvxFontHeightItem& rFHItem = + static_cast<const SvxFontHeightItem&>(rSet.Get(GetWhich( sal_uInt16(SID_ATTR_CHAR_FONTHEIGHT) ))); + aMyFont.SetFontSize(Size(0, rFHItem.GetHeight())); + + const SvxWeightItem& rWItem = + static_cast<const SvxWeightItem&>(rSet.Get(GetWhich( sal_uInt16(SID_ATTR_CHAR_WEIGHT) ))); + aMyFont.SetWeight(rWItem.GetWeight()); + + const SvxPostureItem& rPItem = + static_cast<const SvxPostureItem&>(rSet.Get(GetWhich( sal_uInt16(SID_ATTR_CHAR_POSTURE) ))); + aMyFont.SetItalic(rPItem.GetPosture()); + + const SvxUnderlineItem& rUItem = rSet.Get(GetWhich(SID_ATTR_CHAR_UNDERLINE)); + aMyFont.SetUnderline(rUItem.GetLineStyle()); + + const SvxOverlineItem& rOItem = static_cast<const SvxOverlineItem&>(rSet.Get(GetWhich(SID_ATTR_CHAR_OVERLINE))); + aMyFont.SetOverline(rOItem.GetLineStyle()); + + const SvxCrossedOutItem& rCOItem = static_cast<const SvxCrossedOutItem&>(rSet.Get(GetWhich(SID_ATTR_CHAR_STRIKEOUT))); + aMyFont.SetStrikeout(rCOItem.GetStrikeout()); + + const SvxContourItem& rCItem = static_cast<const SvxContourItem&>(rSet.Get(GetWhich(SID_ATTR_CHAR_CONTOUR))); + aMyFont.SetOutline(rCItem.GetValue()); + + const SvxShadowedItem& rSItem = static_cast<const SvxShadowedItem&>(rSet.Get(GetWhich(SID_ATTR_CHAR_SHADOWED))); + aMyFont.SetShadow(rSItem.GetValue()); + + aNewLevel.SetBulletFont(&aMyFont); + aNumRule.SetLevel(nLevel, aNewLevel ); + } + else if( rSrcLevel.GetNumberingType() == css::style::NumberingType::CHAR_SPECIAL ) + { + aNewLevel.SetPrefix(""); + aNewLevel.SetSuffix(""); + aNumRule.SetLevel(nLevel, aNewLevel ); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuarea.cxx b/sd/source/ui/func/fuarea.cxx new file mode 100644 index 000000000..8dd7543e3 --- /dev/null +++ b/sd/source/ui/func/fuarea.cxx @@ -0,0 +1,99 @@ +/* -*- 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 <fuarea.hxx> + +#include <svx/svxids.hrc> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <ViewShell.hxx> + +#include <drawdoc.hxx> +#include <View.hxx> +#include <svx/svxdlg.hxx> + +namespace sd { + +FuArea::FuArea( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* _pView, SdDrawDocument* pDoc, SfxRequest& rReq) +: FuPoor(pViewSh, pWin, _pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuArea::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* _pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuArea( pViewSh, pWin, _pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuArea::DoExecute( SfxRequest& rReq ) +{ + rReq.Ignore (); + + const SfxItemSet* pArgs = rReq.GetArgs(); + if (pArgs) + return; + + SfxItemSet aNewAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aNewAttr ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + bool bHasSlideBackground = mpViewShell->GetDoc()->GetDocumentType() == DocumentType::Impress; + VclPtr<AbstractSvxAreaTabDialog> pDlg( + pFact->CreateSvxAreaTabDialog(mpViewShell->GetFrameWeld(), &aNewAttr, mpDoc, true, bHasSlideBackground)); + + pDlg->StartExecuteAsync([pDlg, pView = this->mpView, pViewShell = this->mpViewShell](sal_Int32 nResult){ + if (nResult == RET_OK) + { + pView->SetAttributes (*(pDlg->GetOutputItemSet ())); + + // attributes changed, update Listboxes in Objectbars + static const sal_uInt16 SidArray[] = { + SID_ATTR_FILL_STYLE, + SID_ATTR_FILL_COLOR, + SID_ATTR_FILL_GRADIENT, + SID_ATTR_FILL_HATCH, + SID_ATTR_FILL_BITMAP, + SID_ATTR_FILL_TRANSPARENCE, + SID_ATTR_FILL_FLOATTRANSPARENCE, + SID_ATTR_FILL_USE_SLIDE_BACKGROUND, + 0 }; + + pViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); + } + + // deferred until the dialog ends + pViewShell->Cancel(); + + pDlg->disposeOnce(); + }); +} + +void FuArea::Activate() +{ +} + +void FuArea::Deactivate() +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fubullet.cxx b/sd/source/ui/func/fubullet.cxx new file mode 100644 index 000000000..ab0cf7de8 --- /dev/null +++ b/sd/source/ui/func/fubullet.cxx @@ -0,0 +1,330 @@ +/* -*- 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 <fubullet.hxx> + +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <editeng/eeitem.hxx> +#include <svl/poolitem.hxx> +#include <editeng/fontitem.hxx> +#include <OutlineView.hxx> +#include <OutlineViewShell.hxx> +#include <DrawViewShell.hxx> +#include <ViewShellBase.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> +#include <strings.hrc> +#include <sdresid.hxx> +#include <svx/svdoutl.hxx> +#include <sfx2/request.hxx> +#include <svl/ctloptions.hxx> +#include <svl/stritem.hxx> +#include <tools/debug.hxx> + +#include <svx/svxdlg.hxx> +#include <svx/svxids.hrc> + +namespace sd { + +const sal_Unicode CHAR_HARDBLANK = u'\x00A0'; +const sal_Unicode CHAR_HARDHYPHEN = u'\x2011'; +const sal_Unicode CHAR_SOFTHYPHEN = u'\x00AD'; +const sal_Unicode CHAR_RLM = u'\x200F'; +const sal_Unicode CHAR_LRM = u'\x200E'; +const sal_Unicode CHAR_ZWSP = u'\x200B'; +const sal_Unicode CHAR_WJ = u'\x2060'; +const sal_Unicode CHAR_NNBSP = u'\x202F'; //NARROW NO-BREAK SPACE + + +FuBullet::FuBullet ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* _pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, _pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuBullet::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuBullet( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuBullet::DoExecute( SfxRequest& rReq ) +{ + if( rReq.GetSlot() == SID_CHARMAP ) + InsertSpecialCharacter(rReq); + else + { + sal_Unicode cMark = 0; + switch( rReq.GetSlot() ) + { + case FN_INSERT_SOFT_HYPHEN: cMark = CHAR_SOFTHYPHEN ; break; + case FN_INSERT_HARDHYPHEN: cMark = CHAR_HARDHYPHEN ; break; + case FN_INSERT_HARD_SPACE: cMark = CHAR_HARDBLANK ; break; + case FN_INSERT_NNBSP: cMark = CHAR_NNBSP ; break; + case SID_INSERT_RLM : cMark = CHAR_RLM ; break; + case SID_INSERT_LRM : cMark = CHAR_LRM ; break; + case SID_INSERT_ZWSP : cMark = CHAR_ZWSP ; break; + case SID_INSERT_WJ: cMark = CHAR_WJ; break; + } + + DBG_ASSERT( cMark != 0, "FuBullet::FuBullet(), illegal slot used!" ); + + if( cMark ) + InsertFormattingMark( cMark ); + } + +} + +void FuBullet::InsertFormattingMark( sal_Unicode cMark ) +{ + OutlinerView* pOV = nullptr; + ::Outliner* pOL = nullptr; + + // depending on ViewShell set Outliner and OutlinerView + if( dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr) + { + pOV = mpView->GetTextEditOutlinerView(); + if (pOV) + pOL = mpView->GetTextEditOutliner(); + } + else if( dynamic_cast< const OutlineViewShell *>( mpViewShell ) != nullptr) + { + pOL = &static_cast<OutlineView*>(mpView)->GetOutliner(); + pOV = static_cast<OutlineView*>(mpView)->GetViewByWindow( + mpViewShell->GetActiveWindow()); + } + + // insert string + if(!(pOV && pOL)) + return; + + // prevent flickering + pOV->HideCursor(); + pOL->SetUpdateLayout(false); + + // remove old selected text + pOV->InsertText( "" ); + + // prepare undo + SfxUndoManager& rUndoMgr = pOL->GetUndoManager(); + rUndoMgr.EnterListAction(SdResId(STR_UNDO_INSERT_SPECCHAR), + "", 0, mpViewShell->GetViewShellBase().GetViewShellId() ); + + // insert given text + OUString aStr( cMark ); + pOV->InsertText( aStr, true); + + ESelection aSel = pOV->GetSelection(); + aSel.nStartPara = aSel.nEndPara; + aSel.nStartPos = aSel.nEndPos; + pOV->SetSelection(aSel); + + rUndoMgr.LeaveListAction(); + + // restart repainting + pOL->SetUpdateLayout(true); + pOV->ShowCursor(); +} + +void FuBullet::InsertSpecialCharacter( SfxRequest const & rReq ) +{ + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxStringItem* pItem = nullptr; + if( pArgs ) + pItem = pArgs->GetItemIfSet(SID_CHARMAP, false); + + OUString aChars; + vcl::Font aFont; + if ( pItem ) + { + aChars = pItem->GetValue(); + const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_ATTR_SPECIALCHAR, false ); + if ( pFontItem ) + { + const OUString& aFontName = pFontItem->GetValue(); + aFont = vcl::Font( aFontName, Size(1,1) ); + } + else + { + SfxItemSet aFontAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aFontAttr ); + const SvxFontItem* pFItem = aFontAttr.GetItem( SID_ATTR_CHAR_FONT ); + if( pFItem ) + aFont = vcl::Font( pFItem->GetFamilyName(), pFItem->GetStyleName(), Size( 1, 1 ) ); + } + } + + if (aChars.isEmpty()) + { + SfxAllItemSet aSet( mpDoc->GetPool() ); + aSet.Put( SfxBoolItem( FN_PARAM_1, false ) ); + + SfxItemSet aFontAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aFontAttr ); + const SvxFontItem* pFontItem = aFontAttr.GetItem( SID_ATTR_CHAR_FONT ); + if( pFontItem ) + aSet.Put( *pFontItem ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + auto xFrame = mpViewShell ? mpViewShell->GetFrame()->GetFrame().GetFrameInterface() : nullptr; + ScopedVclPtr<SfxAbstractDialog> pDlg( pFact->CreateCharMapDialog(mpView->GetViewShell()->GetFrameWeld(), aSet, + xFrame) ); + + // If a character is selected, it can be shown + // pDLg->SetFont( ); + // pDlg->SetChar( ); + pDlg->Execute(); + return; + } + + if (aChars.isEmpty()) + return; + + OutlinerView* pOV = nullptr; + ::Outliner* pOL = nullptr; + + // determine depending on ViewShell Outliner and OutlinerView + if(dynamic_cast< const DrawViewShell *>( mpViewShell )) + { + pOV = mpView->GetTextEditOutlinerView(); + if (pOV) + { + pOL = mpView->GetTextEditOutliner(); + } + } + else if(dynamic_cast< const OutlineViewShell *>( mpViewShell )) + { + pOL = &static_cast<OutlineView*>(mpView)->GetOutliner(); + pOV = static_cast<OutlineView*>(mpView)->GetViewByWindow( + mpViewShell->GetActiveWindow()); + } + + // insert special character + if (!pOV) + return; + + // prevent flicker + pOV->HideCursor(); + pOL->SetUpdateLayout(false); + + /* remember old attributes: + To do that, remove selected area before (it has to go anyway). + With that, we get unique attributes (and since there is no + DeleteSelected() in OutlinerView, it is deleted by inserting an + empty string). */ + pOV->InsertText( "" ); + + SfxItemSetFixed<EE_CHAR_FONTINFO, EE_CHAR_FONTINFO> aOldSet( mpDoc->GetPool() ); + aOldSet.Put( pOV->GetAttribs() ); + + SfxUndoManager& rUndoMgr = pOL->GetUndoManager(); + ViewShellId nViewShellId = mpViewShell ? mpViewShell->GetViewShellBase().GetViewShellId() : ViewShellId(-1); + rUndoMgr.EnterListAction(SdResId(STR_UNDO_INSERT_SPECCHAR), + "", 0, nViewShellId ); + pOV->InsertText(aChars, true); + + // set attributes (set font) + SfxItemSet aSet(pOL->GetEmptyItemSet()); + SvxFontItem aFontItem (aFont.GetFamilyType(), aFont.GetFamilyName(), + aFont.GetStyleName(), aFont.GetPitch(), + aFont.GetCharSet(), + EE_CHAR_FONTINFO); + aSet.Put(aFontItem); + aFontItem.SetWhich(EE_CHAR_FONTINFO_CJK); + aSet.Put(aFontItem); + aFontItem.SetWhich(EE_CHAR_FONTINFO_CTL); + aSet.Put(aFontItem); + pOV->SetAttribs(aSet); + + ESelection aSel = pOV->GetSelection(); + aSel.nStartPara = aSel.nEndPara; + aSel.nStartPos = aSel.nEndPos; + pOV->SetSelection(aSel); + + // do not go ahead with setting attributes of special characters + pOV->GetOutliner()->QuickSetAttribs(aOldSet, aSel); + + rUndoMgr.LeaveListAction(); + + // show it again + pOL->SetUpdateLayout(true); + pOV->ShowCursor(); +} + +void FuBullet::GetSlotState( SfxItemSet& rSet, ViewShell const * pViewShell, SfxViewFrame* pViewFrame ) +{ + if( !(SfxItemState::DEFAULT == rSet.GetItemState( SID_CHARMAP ) || + SfxItemState::DEFAULT == rSet.GetItemState( SID_CHARMAP_CONTROL ) || + SfxItemState::DEFAULT == rSet.GetItemState( FN_INSERT_SOFT_HYPHEN ) || + SfxItemState::DEFAULT == rSet.GetItemState( FN_INSERT_HARDHYPHEN ) || + SfxItemState::DEFAULT == rSet.GetItemState( FN_INSERT_HARD_SPACE ) || + SfxItemState::DEFAULT == rSet.GetItemState( FN_INSERT_NNBSP ) || + SfxItemState::DEFAULT == rSet.GetItemState( SID_INSERT_RLM ) || + SfxItemState::DEFAULT == rSet.GetItemState( SID_INSERT_LRM ) || + SfxItemState::DEFAULT == rSet.GetItemState( SID_INSERT_WJ ) || + SfxItemState::DEFAULT == rSet.GetItemState( SID_INSERT_ZWSP ))) + return; + + ::sd::View* pView = pViewShell ? pViewShell->GetView() : nullptr; + OutlinerView* pOLV = pView ? pView->GetTextEditOutlinerView() : nullptr; + + const bool bTextEdit = pOLV; + + SvtCTLOptions aCTLOptions; + const bool bCtlEnabled = aCTLOptions.IsCTLFontEnabled(); + + if(!bTextEdit ) + { + rSet.DisableItem(FN_INSERT_SOFT_HYPHEN); + rSet.DisableItem(FN_INSERT_HARDHYPHEN); + rSet.DisableItem(FN_INSERT_HARD_SPACE); + rSet.DisableItem(FN_INSERT_NNBSP); + rSet.DisableItem(SID_INSERT_WJ); + rSet.DisableItem(SID_INSERT_ZWSP); + } + + if( !bTextEdit && (dynamic_cast<OutlineViewShell const *>( pViewShell ) == nullptr) ) + { + rSet.DisableItem(SID_CHARMAP); + rSet.DisableItem(SID_CHARMAP_CONTROL); + } + + if(!bTextEdit || !bCtlEnabled ) + { + rSet.DisableItem(SID_INSERT_RLM); + rSet.DisableItem(SID_INSERT_LRM); + } + + if( pViewFrame ) + { + SfxBindings& rBindings = pViewFrame->GetBindings(); + + rBindings.SetVisibleState( SID_INSERT_RLM, bCtlEnabled ); + rBindings.SetVisibleState( SID_INSERT_LRM, bCtlEnabled ); + } +} +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuchar.cxx b/sd/source/ui/func/fuchar.cxx new file mode 100644 index 000000000..3935f64a1 --- /dev/null +++ b/sd/source/ui/func/fuchar.cxx @@ -0,0 +1,139 @@ +/* -*- 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 <fuchar.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/sfxdlg.hxx> + +#include <svx/svxids.hrc> +#include <editeng/eeitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/brushitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <View.hxx> +#include <drawdoc.hxx> +#include <ViewShell.hxx> +#include <DrawDocShell.hxx> +#include <sdabstdlg.hxx> + +namespace sd { + + +FuChar::FuChar ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuChar::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuChar( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuChar::DoExecute( SfxRequest& rReq ) +{ + const SfxItemSet* pArgs = rReq.GetArgs(); + + if( !pArgs ) + { + SfxItemSet aEditAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aEditAttr ); + + SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLCOLOR, EE_ITEMS_START, EE_ITEMS_END> aNewAttr(mpViewShell->GetPool()); + aNewAttr.Put( aEditAttr, false ); + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractTabDialog> pDlg( pFact->CreateSdTabCharDialog(mpViewShell->GetFrameWeld(), &aNewAttr, mpDoc->GetDocSh() ) ); + if (rReq.GetSlot() == SID_CHAR_DLG_EFFECT) + { + pDlg->SetCurPageId("RID_SVXPAGE_CHAR_EFFECTS"); + } + + sal_uInt16 nResult = pDlg->Execute(); + + if( nResult != RET_OK ) + return; + + const SfxItemSet* pOutputSet = pDlg->GetOutputItemSet(); + SfxItemSet aOtherSet( *pOutputSet ); + + // and now the reverse process + const SvxBrushItem* pBrushItem = aOtherSet.GetItem<SvxBrushItem>( SID_ATTR_BRUSH_CHAR ); + + if ( pBrushItem ) + { + SvxColorItem aBackColorItem( pBrushItem->GetColor(), EE_CHAR_BKGCOLOR ); + aOtherSet.ClearItem( SID_ATTR_BRUSH_CHAR ); + aOtherSet.Put( aBackColorItem ); + } + + rReq.Done( aOtherSet ); + pArgs = rReq.GetArgs(); + } + mpView->SetAttributes(*pArgs); + + // invalidate the Slots which are in DrTxtObjBar + static const sal_uInt16 SidArray[] = { + SID_ATTR_CHAR_FONT, + SID_ATTR_CHAR_POSTURE, + SID_ATTR_CHAR_WEIGHT, + SID_ATTR_CHAR_SHADOWED, + SID_ATTR_CHAR_STRIKEOUT, + SID_ATTR_CHAR_UNDERLINE, + SID_ATTR_CHAR_FONTHEIGHT, + SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_KERNING, + SID_ATTR_CHAR_CASEMAP, + SID_SET_SUPER_SCRIPT, + SID_SET_SUB_SCRIPT, + SID_ATTR_CHAR_BACK_COLOR, + 0 }; + + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); + + if( mpDoc->GetOnlineSpell() ) + { + if( SfxItemState::SET == pArgs->GetItemState(EE_CHAR_LANGUAGE, false ) || + SfxItemState::SET == pArgs->GetItemState(EE_CHAR_LANGUAGE_CJK, false ) || + SfxItemState::SET == pArgs->GetItemState(EE_CHAR_LANGUAGE_CTL, false ) ) + { + mpDoc->StopOnlineSpelling(); + mpDoc->StartOnlineSpelling(); + } + } +} + +void FuChar::Activate() +{ +} + +void FuChar::Deactivate() +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fucon3d.cxx b/sd/source/ui/func/fucon3d.cxx new file mode 100644 index 000000000..fb844548f --- /dev/null +++ b/sd/source/ui/func/fucon3d.cxx @@ -0,0 +1,474 @@ +/* -*- 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 <fucon3d.hxx> + +#include <svx/svxids.hrc> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <tools/poly.hxx> + +#include <svx/xlineit0.hxx> +#include <svx/scene3d.hxx> +#include <svx/sphere3d.hxx> +#include <svx/cube3d.hxx> +#include <svx/lathe3d.hxx> +#include <svx/camera3d.hxx> + +#include <vcl/weld.hxx> + +#include <app.hrc> + +#include <View.hxx> +#include <Window.hxx> +#include <ViewShell.hxx> +#include <drawdoc.hxx> +#include <ViewShellBase.hxx> +#include <ToolBarManager.hxx> +#include <svx/svx3ditems.hxx> + +#include <basegfx/polygon/b2dpolygontools.hxx> + +using namespace com::sun::star; + +namespace sd { + + +FuConstruct3dObject::FuConstruct3dObject ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuConstruct(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuConstruct3dObject::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent ) +{ + FuConstruct3dObject* pFunc; + rtl::Reference<FuPoor> xFunc( pFunc = new FuConstruct3dObject( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + pFunc->SetPermanent(bPermanent); + return xFunc; +} + +void FuConstruct3dObject::DoExecute( SfxRequest& rReq ) +{ + FuConstruct::DoExecute( rReq ); + mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBar( + ToolBarManager::ToolBarGroup::Function, + ToolBarManager::msDrawingObjectToolBar); +} + +E3dCompoundObject* FuConstruct3dObject::ImpCreateBasic3DShape() +{ + E3dCompoundObject* p3DObj = nullptr; + + switch (nSlotId) + { + default: + case SID_3D_CUBE: + { + p3DObj = new E3dCubeObj( + mpView->getSdrModelFromSdrView(), + mpView->Get3DDefaultAttributes(), + ::basegfx::B3DPoint(-2500, -2500, -2500), + ::basegfx::B3DVector(5000, 5000, 5000)); + break; + } + + case SID_3D_SPHERE: + { + p3DObj = new E3dSphereObj( + mpView->getSdrModelFromSdrView(), + mpView->Get3DDefaultAttributes(), + ::basegfx::B3DPoint(0, 0, 0), + ::basegfx::B3DVector(5000, 5000, 5000)); + break; + } + + case SID_3D_SHELL: + { + XPolygon aXPoly(Point (0, 1250), 2500, 2500, 0_deg100, 9000_deg100, false); + aXPoly.Scale(5.0, 5.0); + + ::basegfx::B2DPolygon aB2DPolygon(aXPoly.getB2DPolygon()); + if(aB2DPolygon.areControlPointsUsed()) + { + aB2DPolygon = ::basegfx::utils::adaptiveSubdivideByAngle(aB2DPolygon); + } + p3DObj = new E3dLatheObj( + mpView->getSdrModelFromSdrView(), + mpView->Get3DDefaultAttributes(), + ::basegfx::B2DPolyPolygon(aB2DPolygon)); + + /* this is an open object, therefore it has to be handled double- + sided by default */ + p3DObj->SetMergedItem(makeSvx3DDoubleSidedItem(true)); + break; + } + + case SID_3D_HALF_SPHERE: + { + XPolygon aXPoly(Point (0, 1250), 2500, 2500, 0_deg100, 9000_deg100, false); + aXPoly.Scale(5.0, 5.0); + + aXPoly.Insert(0, Point (2400*5, 1250*5), PolyFlags::Normal); + aXPoly.Insert(0, Point (2000*5, 1250*5), PolyFlags::Normal); + aXPoly.Insert(0, Point (1500*5, 1250*5), PolyFlags::Normal); + aXPoly.Insert(0, Point (1000*5, 1250*5), PolyFlags::Normal); + aXPoly.Insert(0, Point (500*5, 1250*5), PolyFlags::Normal); + aXPoly.Insert(0, Point (250*5, 1250*5), PolyFlags::Normal); + aXPoly.Insert(0, Point (50*5, 1250*5), PolyFlags::Normal); + aXPoly.Insert(0, Point (0, 1250*5), PolyFlags::Normal); + + ::basegfx::B2DPolygon aB2DPolygon(aXPoly.getB2DPolygon()); + if(aB2DPolygon.areControlPointsUsed()) + { + aB2DPolygon = ::basegfx::utils::adaptiveSubdivideByAngle(aB2DPolygon); + } + p3DObj = new E3dLatheObj( + mpView->getSdrModelFromSdrView(), + mpView->Get3DDefaultAttributes(), + ::basegfx::B2DPolyPolygon(aB2DPolygon)); + break; + } + + case SID_3D_TORUS: + { + ::basegfx::B2DPolygon aB2DPolygon(::basegfx::utils::createPolygonFromCircle(::basegfx::B2DPoint(1000.0, 0.0), 500.0)); + if(aB2DPolygon.areControlPointsUsed()) + { + aB2DPolygon = ::basegfx::utils::adaptiveSubdivideByAngle(aB2DPolygon); + } + p3DObj = new E3dLatheObj( + mpView->getSdrModelFromSdrView(), + mpView->Get3DDefaultAttributes(), + ::basegfx::B2DPolyPolygon(aB2DPolygon)); + break; + } + + case SID_3D_CYLINDER: + { + ::basegfx::B2DPolygon aInnerPoly; + + aInnerPoly.append(::basegfx::B2DPoint(0, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(50*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(100*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(200*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(300*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(400*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(450*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(500*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(500*5, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(450*5, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(400*5, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(300*5, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(200*5, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(100*5, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(50*5, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(0, -1000*5)); + aInnerPoly.setClosed(true); + + p3DObj = new E3dLatheObj( + mpView->getSdrModelFromSdrView(), + mpView->Get3DDefaultAttributes(), + ::basegfx::B2DPolyPolygon(aInnerPoly)); + break; + } + + case SID_3D_CONE: + { + ::basegfx::B2DPolygon aInnerPoly; + + aInnerPoly.append(::basegfx::B2DPoint(0, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(25*5, -900*5)); + aInnerPoly.append(::basegfx::B2DPoint(50*5, -800*5)); + aInnerPoly.append(::basegfx::B2DPoint(100*5, -600*5)); + aInnerPoly.append(::basegfx::B2DPoint(200*5, -200*5)); + aInnerPoly.append(::basegfx::B2DPoint(300*5, 200*5)); + aInnerPoly.append(::basegfx::B2DPoint(400*5, 600*5)); + aInnerPoly.append(::basegfx::B2DPoint(500*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(400*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(300*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(200*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(100*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(50*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(0, 1000*5)); + aInnerPoly.setClosed(true); + + p3DObj = new E3dLatheObj( + mpView->getSdrModelFromSdrView(), + mpView->Get3DDefaultAttributes(), + ::basegfx::B2DPolyPolygon(aInnerPoly)); + break; + } + + case SID_3D_PYRAMID: + { + ::basegfx::B2DPolygon aInnerPoly; + + aInnerPoly.append(::basegfx::B2DPoint(0, -1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(25*5, -900*5)); + aInnerPoly.append(::basegfx::B2DPoint(50*5, -800*5)); + aInnerPoly.append(::basegfx::B2DPoint(100*5, -600*5)); + aInnerPoly.append(::basegfx::B2DPoint(200*5, -200*5)); + aInnerPoly.append(::basegfx::B2DPoint(300*5, 200*5)); + aInnerPoly.append(::basegfx::B2DPoint(400*5, 600*5)); + aInnerPoly.append(::basegfx::B2DPoint(500*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(400*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(300*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(200*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(100*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(50*5, 1000*5)); + aInnerPoly.append(::basegfx::B2DPoint(0, 1000*5)); + aInnerPoly.setClosed(true); + + p3DObj = new E3dLatheObj( + mpView->getSdrModelFromSdrView(), + mpView->Get3DDefaultAttributes(), + ::basegfx::B2DPolyPolygon(aInnerPoly)); + p3DObj->SetMergedItem(makeSvx3DHorizontalSegmentsItem(4)); + break; + } + } + + return p3DObj; +} + +void FuConstruct3dObject::ImpPrepareBasic3DShape(E3dCompoundObject const * p3DObj, E3dScene *pScene) +{ + Camera3D aCamera = pScene->GetCamera (); + + // get transformed BoundVolume of the new object + basegfx::B3DRange aBoundVol; + basegfx::B3DRange aObjVol(p3DObj->GetBoundVolume()); + aObjVol.transform(p3DObj->GetTransform()); + aBoundVol.expand(aObjVol); + double fDeepth(aBoundVol.getDepth()); + + aCamera.SetPRP(::basegfx::B3DPoint(0.0, 0.0, 1000.0)); + aCamera.SetPosition(::basegfx::B3DPoint(0.0, 0.0, mpView->GetDefaultCamPosZ() + fDeepth / 2)); + aCamera.SetFocalLength(mpView->GetDefaultCamFocal()); + pScene->SetCamera(aCamera); + basegfx::B3DHomMatrix aTransformation; + + switch (nSlotId) + { + case SID_3D_CUBE: + { + aTransformation.rotate(basegfx::deg2rad(20), 0.0, 0.0); + } + break; + + case SID_3D_SPHERE: + { + } + break; + + case SID_3D_SHELL: + case SID_3D_HALF_SPHERE: + { + aTransformation.rotate(basegfx::deg2rad(200), 0.0, 0.0); + } + break; + + case SID_3D_CYLINDER: + case SID_3D_CONE: + case SID_3D_PYRAMID: + { + } + break; + + case SID_3D_TORUS: + { + aTransformation.rotate(basegfx::deg2rad(90), 0.0, 0.0); + } + break; + + default: + { + } + break; + } + + pScene->SetTransform(aTransformation * pScene->GetTransform()); + + SfxItemSet aAttr (mpViewShell->GetPool()); + pScene->SetMergedItemSetAndBroadcast(aAttr); +} + +bool FuConstruct3dObject::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = FuConstruct::MouseButtonDown(rMEvt); + + if ( rMEvt.IsLeft() && !mpView->IsAction() ) + { + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + + mpWindow->CaptureMouse(); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + + weld::WaitObject aWait(mpViewShell->GetFrameWeld()); + + E3dCompoundObject* p3DObj = ImpCreateBasic3DShape(); + E3dScene* pScene = mpView->SetCurrent3DObj(p3DObj); + + ImpPrepareBasic3DShape(p3DObj, pScene); + bReturn = mpView->BegCreatePreparedObject(aPnt, nDrgLog, pScene); + + SdrObject* pObj = mpView->GetCreateObj(); + + if (pObj) + { + SfxItemSet aAttr(mpDoc->GetPool()); + SetStyleSheet(aAttr, pObj); + + // extract LineStyle + aAttr.Put(XLineStyleItem (drawing::LineStyle_NONE)); + + pObj->SetMergedItemSet(aAttr); + } + } + + return bReturn; +} + +bool FuConstruct3dObject::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = false; + + if ( mpView->IsCreateObj() && rMEvt.IsLeft() ) + { + if( mpView->EndCreateObj( SdrCreateCmd::ForceEnd ) ) + { + bReturn = true; + } + else + { + //Drag was too small to create object, so insert default object at click pos + Point aClickPos(mpWindow->PixelToLogic(rMEvt.GetPosPixel())); + sal_uInt32 nDefaultObjectSize(1000); + sal_Int32 nCenterOffset(-sal_Int32(nDefaultObjectSize / 2)); + aClickPos.AdjustX(nCenterOffset); + aClickPos.AdjustY(nCenterOffset); + + SdrPageView *pPV = mpView->GetSdrPageView(); + + if(mpView->IsSnapEnabled()) + aClickPos = mpView->GetSnapPos(aClickPos, pPV); + + ::tools::Rectangle aNewObjectRectangle(aClickPos, Size(nDefaultObjectSize, nDefaultObjectSize)); + SdrObjectUniquePtr pObjDefault = CreateDefaultObject(nSlotId, aNewObjectRectangle); + + bReturn = mpView->InsertObjectAtView(pObjDefault.release(), *pPV); + } + } + bReturn = FuConstruct::MouseButtonUp(rMEvt) || bReturn; + + if (!bPermanent) + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + + return bReturn; +} + +void FuConstruct3dObject::Activate() +{ + mpView->SetCurrentObj(SdrObjKind::NONE); + + FuConstruct::Activate(); +} + +SdrObjectUniquePtr FuConstruct3dObject::CreateDefaultObject(const sal_uInt16 nID, const ::tools::Rectangle& rRectangle) +{ + + E3dCompoundObject* p3DObj = ImpCreateBasic3DShape(); + + // E3dView::SetCurrent3DObj part + // get transformed BoundVolume of the object + basegfx::B3DRange aObjVol(p3DObj->GetBoundVolume()); + aObjVol.transform(p3DObj->GetTransform()); + basegfx::B3DRange aVolume(aObjVol); + double fW(aVolume.getWidth()); + double fH(aVolume.getHeight()); + ::tools::Rectangle a3DRect(0, 0, static_cast<::tools::Long>(fW), static_cast<::tools::Long>(fH)); + std::unique_ptr< E3dScene, SdrObjectFreeOp > pScene(new E3dScene(*mpDoc)); + + // copied code from E3dView::InitScene + double fCamZ(aVolume.getMaxZ() + ((fW + fH) / 4.0)); + Camera3D aCam(pScene->GetCamera()); + aCam.SetAutoAdjustProjection(false); + aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH); + ::basegfx::B3DPoint aLookAt; + double fDefaultCamPosZ = mpView->GetDefaultCamPosZ(); + ::basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ); + aCam.SetPosAndLookAt(aCamPos, aLookAt); + aCam.SetFocalLength(mpView->GetDefaultCamFocal()); + pScene->SetCamera(aCam); + pScene->InsertObject(p3DObj); + pScene->NbcSetSnapRect(a3DRect); + ImpPrepareBasic3DShape(p3DObj, pScene.get()); + SfxItemSet aAttr(mpDoc->GetPool()); + SetStyleSheet(aAttr, p3DObj); + aAttr.Put(XLineStyleItem (drawing::LineStyle_NONE)); + p3DObj->SetMergedItemSet(aAttr); + + // make object interactive at once + pScene->SetBoundAndSnapRectsDirty(); + + // Take care of restrictions for the rectangle + ::tools::Rectangle aRect(rRectangle); + + switch(nID) + { + case SID_3D_CUBE: + case SID_3D_SPHERE: + case SID_3D_TORUS: + { + // force quadratic + ImpForceQuadratic(aRect); + break; + } + + case SID_3D_SHELL: + case SID_3D_HALF_SPHERE: + { + // force horizontal layout + break; + } + + case SID_3D_CYLINDER: + case SID_3D_CONE: + case SID_3D_PYRAMID: + { + // force vertical layout + break; + } + } + + // use changed rectangle, not original one + pScene->SetLogicRect(aRect); + + return SdrObjectUniquePtr(pScene.release()); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuconarc.cxx b/sd/source/ui/func/fuconarc.cxx new file mode 100644 index 000000000..b5be93f9b --- /dev/null +++ b/sd/source/ui/func/fuconarc.cxx @@ -0,0 +1,254 @@ +/* -*- 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 <fuconarc.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdocirc.hxx> +#include <sfx2/request.hxx> +#include <svl/intitem.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/svdobj.hxx> +#include <sfx2/viewfrm.hxx> +#include <osl/diagnose.h> + +#include <svx/svxids.hrc> + +#include <Window.hxx> +#include <drawdoc.hxx> + +#include <View.hxx> +#include <ViewShell.hxx> +#include <ViewShellBase.hxx> +#include <ToolBarManager.hxx> + +#include <svx/sxciaitm.hxx> +#include <svx/xfillit0.hxx> + +using namespace com::sun::star; + +namespace sd { + + +FuConstructArc::FuConstructArc ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq ) + : FuConstruct( pViewSh, pWin, pView, pDoc, rReq ) +{ +} + +rtl::Reference<FuPoor> FuConstructArc::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent ) +{ + FuConstructArc* pFunc; + rtl::Reference<FuPoor> xFunc( pFunc = new FuConstructArc( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + pFunc->SetPermanent(bPermanent); + return xFunc; +} + +void FuConstructArc::DoExecute( SfxRequest& rReq ) +{ + FuConstruct::DoExecute( rReq ); + + mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBar( + ToolBarManager::ToolBarGroup::Function, + ToolBarManager::msDrawingObjectToolBar); + + const SfxItemSet *pArgs = rReq.GetArgs (); + + if (!pArgs) + return; + + const SfxUInt32Item* pCenterX = rReq.GetArg<SfxUInt32Item>(ID_VAL_CENTER_X); + const SfxUInt32Item* pCenterY = rReq.GetArg<SfxUInt32Item>(ID_VAL_CENTER_Y); + const SfxUInt32Item* pAxisX = rReq.GetArg<SfxUInt32Item>(ID_VAL_AXIS_X); + const SfxUInt32Item* pAxisY = rReq.GetArg<SfxUInt32Item>(ID_VAL_AXIS_Y); + const SfxUInt32Item* pPhiStart = rReq.GetArg<SfxUInt32Item>(ID_VAL_ANGLESTART); + const SfxUInt32Item* pPhiEnd = rReq.GetArg<SfxUInt32Item>(ID_VAL_ANGLEEND); + + ::tools::Rectangle aNewRectangle (pCenterX->GetValue () - pAxisX->GetValue () / 2, + pCenterY->GetValue () - pAxisY->GetValue () / 2, + pCenterX->GetValue () + pAxisX->GetValue () / 2, + pCenterY->GetValue () + pAxisY->GetValue () / 2); + + Activate(); // sets aObjKind + SdrCircObj* pNewCircle = + new SdrCircObj( + mpView->getSdrModelFromSdrView(), + ToSdrCircKind(mpView->GetCurrentObjIdentifier()), + aNewRectangle, + Degree100(pPhiStart->GetValue() * 10), + Degree100(pPhiEnd->GetValue() * 10)); + SdrPageView *pPV = mpView->GetSdrPageView(); + + mpView->InsertObjectAtView(pNewCircle, *pPV, SdrInsertFlags::SETDEFLAYER); +} + +bool FuConstructArc::MouseButtonDown( const MouseEvent& rMEvt ) +{ + bool bReturn = FuConstruct::MouseButtonDown( rMEvt ); + + if ( rMEvt.IsLeft() && !mpView->IsAction() ) + { + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + mpWindow->CaptureMouse(); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + mpView->BegCreateObj(aPnt, nullptr, nDrgLog); + + SdrObject* pObj = mpView->GetCreateObj(); + + if (pObj) + { + SfxItemSet aAttr(mpDoc->GetPool()); + SetStyleSheet(aAttr, pObj); + + pObj->SetMergedItemSet(aAttr); + } + + bReturn = true; + } + return bReturn; +} + +bool FuConstructArc::MouseButtonUp( const MouseEvent& rMEvt ) +{ + bool bReturn = false; + bool bCreated = false; + + if ( mpView->IsCreateObj() && rMEvt.IsLeft() ) + { + const size_t nCount = mpView->GetSdrPageView()->GetObjList()->GetObjCount(); + + if (mpView->EndCreateObj(SdrCreateCmd::NextPoint) ) + { + if (nCount != mpView->GetSdrPageView()->GetObjList()->GetObjCount()) + { + bCreated = true; + } + } + + bReturn = true; + } + + bReturn = FuConstruct::MouseButtonUp (rMEvt) || bReturn; + + if (!bPermanent && bCreated) + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + + return bReturn; +} + +void FuConstructArc::Activate() +{ + SdrObjKind aObjKind; + + switch( nSlotId ) + { + case SID_DRAW_ARC : + case SID_DRAW_CIRCLEARC: + { + aObjKind = SdrObjKind::CircleArc; + } + break; + + case SID_DRAW_PIE : + case SID_DRAW_PIE_NOFILL : + case SID_DRAW_CIRCLEPIE : + case SID_DRAW_CIRCLEPIE_NOFILL: + { + aObjKind = SdrObjKind::CircleSection; + } + break; + + case SID_DRAW_ELLIPSECUT : + case SID_DRAW_ELLIPSECUT_NOFILL: + case SID_DRAW_CIRCLECUT : + case SID_DRAW_CIRCLECUT_NOFILL : + { + aObjKind = SdrObjKind::CircleCut; + } + break; + + default: + { + aObjKind = SdrObjKind::CircleArc; + } + break; + } + + mpView->SetCurrentObj(aObjKind); + + FuConstruct::Activate(); +} + +SdrObjectUniquePtr FuConstructArc::CreateDefaultObject(const sal_uInt16 nID, const ::tools::Rectangle& rRectangle) +{ + + SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject( + mpView->getSdrModelFromSdrView(), + mpView->GetCurrentObjInventor(), + mpView->GetCurrentObjIdentifier())); + + if(pObj) + { + if( dynamic_cast< const SdrCircObj *>( pObj.get() ) != nullptr) + { + ::tools::Rectangle aRect(rRectangle); + + if(SID_DRAW_ARC == nID || + SID_DRAW_CIRCLEARC == nID || + SID_DRAW_CIRCLEPIE == nID || + SID_DRAW_CIRCLEPIE_NOFILL == nID || + SID_DRAW_CIRCLECUT == nID || + SID_DRAW_CIRCLECUT_NOFILL == nID) + { + // force quadratic + ImpForceQuadratic(aRect); + } + + pObj->SetLogicRect(aRect); + + SfxItemSet aAttr(mpDoc->GetPool()); + aAttr.Put(makeSdrCircStartAngleItem(9000_deg100)); + aAttr.Put(makeSdrCircEndAngleItem(0_deg100)); + + if(SID_DRAW_PIE_NOFILL == nID || + SID_DRAW_CIRCLEPIE_NOFILL == nID || + SID_DRAW_ELLIPSECUT_NOFILL == nID || + SID_DRAW_CIRCLECUT_NOFILL == nID) + { + aAttr.Put(XFillStyleItem(drawing::FillStyle_NONE)); + } + + pObj->SetMergedItemSet(aAttr); + } + else + { + OSL_FAIL("Object is NO circle object"); + } + } + + return pObj; +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuconbez.cxx b/sd/source/ui/func/fuconbez.cxx new file mode 100644 index 000000000..b123e9c2d --- /dev/null +++ b/sd/source/ui/func/fuconbez.cxx @@ -0,0 +1,556 @@ +/* -*- 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 <com/sun/star/presentation/EffectNodeType.hpp> + +#include <fuconbez.hxx> +#include <svx/svdopath.hxx> +#include <svl/intitem.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/svdobj.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <osl/diagnose.h> + +#include <svx/svxids.hrc> +#include <svx/svdpagv.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xlnwtit.hxx> + +#include <app.hrc> +#include <ViewShell.hxx> +#include <ViewShellBase.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <ToolBarManager.hxx> +#include <drawdoc.hxx> +#include <sdpage.hxx> + +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +#include <CustomAnimationEffect.hxx> + +using namespace ::com::sun::star::uno; + +namespace sd { + +/*//Extra attributes coming from parameters + sal_uInt16 mnTransparence; // Default: 0 + OUString msColor; // Default: "" + sal_uInt16 mnWidth; // Default: 0 + OUString msShapeName; // Default: ""*/ +FuConstructBezierPolygon::FuConstructBezierPolygon ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuConstruct(pViewSh, pWin, pView, pDoc, rReq), + nEditMode(SID_BEZIER_MOVE), + mnTransparence(0), + mnWidth(0) +{ +} + +namespace{ + +/// Checks to see if the request has a parameter of IsSticky:bool=true +/// It means that the selected command/button will stay selected after use +bool isSticky(const SfxRequest& rReq) +{ + const SfxItemSet *pArgs = rReq.GetArgs (); + if (pArgs) + { + const SfxBoolItem* pIsSticky = rReq.GetArg<SfxBoolItem>(FN_PARAM_4); + if (pIsSticky && pIsSticky->GetValue()) + return true; + } + + return false; +} + +} + +rtl::Reference<FuPoor> FuConstructBezierPolygon::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent ) +{ + FuConstructBezierPolygon* pFunc; + rtl::Reference<FuPoor> xFunc( pFunc = new FuConstructBezierPolygon( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + pFunc->SetPermanent(bPermanent || isSticky(rReq)); + return xFunc; +} + +void FuConstructBezierPolygon::DoExecute( SfxRequest& rReq ) +{ + FuConstruct::DoExecute( rReq ); + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if( !pArgs ) + return; + + const SfxUnoAnyItem* pPoolItem = pArgs->GetItemIfSet( SID_ADD_MOTION_PATH ); + if( pPoolItem ) + maTargets = pPoolItem->GetValue(); + + if (nSlotId != SID_DRAW_FREELINE_NOFILL) + return; + + const SfxUInt16Item* pTransparence = rReq.GetArg<SfxUInt16Item>(FN_PARAM_1); + const SfxStringItem* pColor = rReq.GetArg<SfxStringItem>(FN_PARAM_2); + const SfxUInt16Item* pWidth = rReq.GetArg<SfxUInt16Item>(FN_PARAM_3); + const SfxStringItem* pShapeName = rReq.GetArg<SfxStringItem>(SID_SHAPE_NAME); + + if (pTransparence && pTransparence->GetValue() > 0) + { + mnTransparence = pTransparence->GetValue(); + } + if (pColor && !pColor->GetValue().isEmpty()) + { + msColor = pColor->GetValue(); + } + if (pWidth && pWidth->GetValue() > 0) + { + mnWidth = pWidth->GetValue(); + } + if (pShapeName && !pShapeName->GetValue().isEmpty()) + { + msShapeName = pShapeName->GetValue(); + } +} + +bool FuConstructBezierPolygon::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = FuConstruct::MouseButtonDown(rMEvt); + + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::Handle || rMEvt.IsMod1()) + { + mpView->SetEditMode(SdrViewEditMode::Edit); + } + else + { + mpView->SetEditMode(SdrViewEditMode::Create); + } + + if (aVEvt.meEvent == SdrEventKind::BeginTextEdit) + { + // here, we do not allow text input + aVEvt.meEvent = SdrEventKind::BeginDragObj; + mpView->EnableExtendedMouseEventDispatcher(false); + } + else + { + mpView->EnableExtendedMouseEventDispatcher(true); + } + + if (eHit == SdrHitKind::MarkedObject && nEditMode == SID_BEZIER_INSERT) + { + // insert gluepoint + mpView->BegInsObjPoint(aMDPos, rMEvt.IsMod1()); + } + else + { + mpView->MouseButtonDown(rMEvt, mpWindow->GetOutDev()); + + SdrObject* pObj = mpView->GetCreateObj(); + + if (pObj) + { + SfxItemSet aAttr(mpDoc->GetPool()); + SetStyleSheet(aAttr, pObj); + SetAttributes(aAttr, pObj); + pObj->SetMergedItemSet(aAttr); + } + } + + return bReturn; +} + +bool FuConstructBezierPolygon::MouseButtonUp(const MouseEvent& rMEvt ) +{ + bool bReturn = false; + bool bCreated = false; + + SdrViewEvent aVEvt; + mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONUP, aVEvt); + + const size_t nCount = mpView->GetSdrPageView()->GetObjList()->GetObjCount(); + + if (mpView->IsInsObjPoint()) + { + mpView->EndInsObjPoint(SdrCreateCmd::ForceEnd); + } + else + { + mpView->MouseButtonUp(rMEvt, mpWindow->GetOutDev()); + } + + if (aVEvt.meEvent == SdrEventKind::EndCreate) + { + bReturn = true; + + if (nCount+1 == mpView->GetSdrPageView()->GetObjList()->GetObjCount()) + { + bCreated = true; + } + + // trick to suppress FuDraw::DoubleClick + bMBDown = false; + + } + + bReturn = FuConstruct::MouseButtonUp(rMEvt) || bReturn; + + bool bDeleted = false; + if( bCreated && maTargets.hasValue() ) + { + SdrPathObj* pPathObj = dynamic_cast< SdrPathObj* >( mpView->GetSdrPageView()->GetObjList()->GetObj( nCount ) ); + SdPage* pPage = dynamic_cast< SdPage* >( pPathObj ? pPathObj->getSdrPageFromSdrObject() : nullptr ); + if( pPage ) + { + std::shared_ptr< sd::MainSequence > pMainSequence( pPage->getMainSequence() ); + if( pMainSequence ) + { + Sequence< Any > aTargets; + maTargets >>= aTargets; + + sal_Int32 nTCount = aTargets.getLength(); + if( nTCount > 1 ) + { + const Any* pTarget = aTargets.getConstArray(); + double fDuration = 0.0; + *pTarget++ >>= fDuration; + bool bFirst = true; + + OUString sPresetId; + switch(nSlotId) + { + case SID_DRAW_BEZIER_NOFILL: + sPresetId = "libo-motionpath-curve"; + break; + case SID_DRAW_POLYGON_NOFILL: + sPresetId = "libo-motionpath-polygon"; + break; + case SID_DRAW_FREELINE_NOFILL: + sPresetId = "libo-motionpath-freeform-line"; + break; + } + + while( --nTCount ) + { + CustomAnimationEffectPtr pCreated( pMainSequence->append( *pPathObj, *pTarget++, fDuration, sPresetId) ); + if( bFirst ) + bFirst = false; + else + pCreated->setNodeType( css::presentation::EffectNodeType::WITH_PREVIOUS ); + } + } + } + } + mpView->DeleteMarked(); + bDeleted = true; + } + + if ((!bPermanent && bCreated) || bDeleted) + { + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + } + + return bReturn; +} + +void FuConstructBezierPolygon::Activate() +{ + mpView->EnableExtendedMouseEventDispatcher(true); + + SdrObjKind eKind; + + switch (nSlotId) + { + case SID_DRAW_POLYGON_NOFILL: + case SID_DRAW_XPOLYGON_NOFILL: + { + eKind = SdrObjKind::PolyLine; + } + break; + + case SID_DRAW_POLYGON: + case SID_DRAW_XPOLYGON: + { + eKind = SdrObjKind::Polygon; + } + break; + + case SID_DRAW_BEZIER_NOFILL: + { + eKind = SdrObjKind::PathLine; + } + break; + + case SID_DRAW_BEZIER_FILL: + { + eKind = SdrObjKind::PathFill; + } + break; + + case SID_DRAW_FREELINE_NOFILL: + { + eKind = SdrObjKind::FreehandLine; + } + break; + + case SID_DRAW_FREELINE: + { + eKind = SdrObjKind::FreehandFill; + } + break; + + default: + { + eKind = SdrObjKind::PathLine; + } + break; + } + + mpView->SetCurrentObj(eKind); + + FuConstruct::Activate(); +} + +void FuConstructBezierPolygon::Deactivate() +{ + mpView->EnableExtendedMouseEventDispatcher(false); + + FuConstruct::Deactivate(); +} + +void FuConstructBezierPolygon::SelectionHasChanged() +{ + FuDraw::SelectionHasChanged(); + + mpViewShell->GetViewShellBase().GetToolBarManager()->SelectionHasChanged( + *mpViewShell, + *mpView); +} + +namespace { +/// Returns the color based on the color names listed in core/include/tools/color.hxx +/// Feel free to extend with more color names from color.hxx +Color strToColor(std::u16string_view sColor) +{ + Color aColor = COL_AUTO; + + if (sColor == u"COL_GRAY") + aColor = COL_GRAY; + else if (sColor == u"COL_GRAY3") + aColor = COL_GRAY3; + else if (sColor == u"COL_GRAY7") + aColor = COL_GRAY7; + + return aColor; +} +} + +void FuConstructBezierPolygon::SetAttributes(SfxItemSet& rAttr, SdrObject *pObj) +{ + if (nSlotId == SID_DRAW_FREELINE_NOFILL) + { + if (mnTransparence > 0 && mnTransparence <= 100) + rAttr.Put(XLineTransparenceItem(mnTransparence)); + if (!msColor.isEmpty()) + rAttr.Put(XLineColorItem(OUString(), strToColor(msColor))); + if (mnWidth > 0) + rAttr.Put(XLineWidthItem(mnWidth)); + if (!msShapeName.isEmpty()) + pObj->SetName(msShapeName); + } +} + +/** + * Set current bezier edit mode + */ +void FuConstructBezierPolygon::SetEditMode(sal_uInt16 nMode) +{ + nEditMode = nMode; + ForcePointer(); + + SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings(); + rBindings.Invalidate(SID_BEZIER_MOVE); + rBindings.Invalidate(SID_BEZIER_INSERT); +} + +SdrObjectUniquePtr FuConstructBezierPolygon::CreateDefaultObject(const sal_uInt16 nID, const ::tools::Rectangle& rRectangle) +{ + // case SID_DRAW_POLYGON: + // case SID_DRAW_POLYGON_NOFILL: + // case SID_DRAW_XPOLYGON: + // case SID_DRAW_XPOLYGON_NOFILL: + // case SID_DRAW_FREELINE: + // case SID_DRAW_FREELINE_NOFILL: + // case SID_DRAW_BEZIER_FILL: // BASIC + // case SID_DRAW_BEZIER_NOFILL: // BASIC + + SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject( + mpView->getSdrModelFromSdrView(), + mpView->GetCurrentObjInventor(), + mpView->GetCurrentObjIdentifier())); + + if(pObj) + { + if( auto pPathObj = dynamic_cast< SdrPathObj *>( pObj.get() ) ) + { + basegfx::B2DPolyPolygon aPoly; + + switch(nID) + { + case SID_DRAW_BEZIER_FILL: + { + const sal_Int32 nWdt(rRectangle.GetWidth() / 2); + const sal_Int32 nHgt(rRectangle.GetHeight() / 2); + const basegfx::B2DPolygon aInnerPoly(basegfx::utils::createPolygonFromEllipse(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y()), nWdt, nHgt)); + + aPoly.append(aInnerPoly); + break; + } + case SID_DRAW_BEZIER_NOFILL: + { + basegfx::B2DPolygon aInnerPoly; + + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom())); + + const basegfx::B2DPoint aCenterBottom(rRectangle.Center().X(), rRectangle.Bottom()); + aInnerPoly.appendBezierSegment( + aCenterBottom, + aCenterBottom, + basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y())); + + const basegfx::B2DPoint aCenterTop(rRectangle.Center().X(), rRectangle.Top()); + aInnerPoly.appendBezierSegment( + aCenterTop, + aCenterTop, + basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top())); + + aPoly.append(aInnerPoly); + break; + } + case SID_DRAW_FREELINE: + case SID_DRAW_FREELINE_NOFILL: + { + basegfx::B2DPolygon aInnerPoly; + + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom())); + + aInnerPoly.appendBezierSegment( + basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top()), + basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Top()), + basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y())); + + aInnerPoly.appendBezierSegment( + basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Bottom()), + basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom()), + basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top())); + + if(SID_DRAW_FREELINE == nID) + { + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom())); + } + else + { + aInnerPoly.setClosed(true); + } + + aPoly.append(aInnerPoly); + break; + } + case SID_DRAW_XPOLYGON: + case SID_DRAW_XPOLYGON_NOFILL: + { + basegfx::B2DPolygon aInnerPoly; + + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom())); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top())); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Top())); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Center().Y())); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Center().Y())); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom())); + + if(SID_DRAW_XPOLYGON_NOFILL == nID) + { + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Bottom())); + } + else + { + aInnerPoly.setClosed(true); + } + + aPoly.append(aInnerPoly); + break; + } + case SID_DRAW_POLYGON: + case SID_DRAW_POLYGON_NOFILL: + { + basegfx::B2DPolygon aInnerPoly; + const sal_Int32 nWdt(rRectangle.GetWidth()); + const sal_Int32 nHgt(rRectangle.GetHeight()); + + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom())); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 30) / 100, rRectangle.Top() + (nHgt * 70) / 100)); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top() + (nHgt * 15) / 100)); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 65) / 100, rRectangle.Top())); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + nWdt, rRectangle.Top() + (nHgt * 30) / 100)); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 80) / 100, rRectangle.Top() + (nHgt * 50) / 100)); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Left() + (nWdt * 80) / 100, rRectangle.Top() + (nHgt * 75) / 100)); + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Bottom(), rRectangle.Right())); + + if(SID_DRAW_POLYGON_NOFILL == nID) + { + aInnerPoly.append(basegfx::B2DPoint(rRectangle.Center().X(), rRectangle.Bottom())); + } + else + { + aInnerPoly.setClosed(true); + } + + aPoly.append(aInnerPoly); + break; + } + } + + pPathObj->SetPathPoly(aPoly); + } + else + { + OSL_FAIL("Object is NO path object"); + } + + pObj->SetLogicRect(rRectangle); + } + + return pObj; +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuconcs.cxx b/sd/source/ui/func/fuconcs.cxx new file mode 100644 index 000000000..806960dd2 --- /dev/null +++ b/sd/source/ui/func/fuconcs.cxx @@ -0,0 +1,261 @@ +/* -*- 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 <fuconcs.hxx> +#include <rtl/ustring.hxx> + +#include <svx/svxids.hrc> + +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/request.hxx> +#include <editeng/adjustitem.hxx> +#include <editeng/eeitem.hxx> +#include <svx/svdoashp.hxx> +#include <svx/sdtagitm.hxx> + +#include <ViewShell.hxx> +#include <ViewShellBase.hxx> +#include <ToolBarManager.hxx> +#include <svx/gallery.hxx> +#include <svx/sdooitm.hxx> +#include <svl/itempool.hxx> +#include <svl/stritem.hxx> + +#include <View.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> + +namespace sd { + + +FuConstructCustomShape::FuConstructCustomShape ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq ) : + FuConstruct(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuConstructCustomShape::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent ) +{ + FuConstructCustomShape* pFunc; + rtl::Reference<FuPoor> xFunc( pFunc = new FuConstructCustomShape( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + pFunc->SetPermanent( bPermanent ); + return xFunc; +} + +void FuConstructCustomShape::DoExecute( SfxRequest& rReq ) +{ + FuConstruct::DoExecute( rReq ); + + const SfxItemSet* pArgs = rReq.GetArgs(); + if ( pArgs ) + { + const SfxStringItem& rItm = static_cast<const SfxStringItem&>(pArgs->Get( rReq.GetSlot() )); + aCustomShape = rItm.GetValue(); + } + + mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBar( + ToolBarManager::ToolBarGroup::Function, + ToolBarManager::msDrawingObjectToolBar); +} + +bool FuConstructCustomShape::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = FuConstruct::MouseButtonDown(rMEvt); + + if ( rMEvt.IsLeft() && !mpView->IsAction() ) + { + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + + mpWindow->CaptureMouse(); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + + mpView->BegCreateObj(aPnt, nullptr, nDrgLog); + + SdrObject* pObj = mpView->GetCreateObj(); + if ( pObj ) + { + SetAttributes( pObj ); + bool bForceFillStyle = true; + bool bForceNoFillStyle = false; + if ( static_cast<SdrObjCustomShape*>(pObj)->UseNoFillStyle() ) + { + bForceFillStyle = false; + bForceNoFillStyle = true; + } + SfxItemSet aAttr(mpDoc->GetPool()); + SetStyleSheet( aAttr, pObj, bForceFillStyle, bForceNoFillStyle ); + pObj->SetMergedItemSet(aAttr); + } + } + + return bReturn; +} + +bool FuConstructCustomShape::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn(false); + + if(mpView->IsCreateObj() && rMEvt.IsLeft()) + { + SdrObject* pObj = mpView->GetCreateObj(); + if( pObj && mpView->EndCreateObj( SdrCreateCmd::ForceEnd ) ) + { + bReturn = true; + } + else + { + //Drag was too small to create object, so insert default object at click pos + Point aClickPos(mpWindow->PixelToLogic(rMEvt.GetPosPixel())); + sal_uInt32 nDefaultObjectSize(1000); + sal_Int32 nCenterOffset(-sal_Int32(nDefaultObjectSize / 2)); + aClickPos.AdjustX(nCenterOffset); + aClickPos.AdjustY(nCenterOffset); + + SdrPageView *pPV = mpView->GetSdrPageView(); + if(mpView->IsSnapEnabled()) + aClickPos = mpView->GetSnapPos(aClickPos, pPV); + + ::tools::Rectangle aNewObjectRectangle(aClickPos, Size(nDefaultObjectSize, nDefaultObjectSize)); + SdrObjectUniquePtr pObjDefault = CreateDefaultObject(nSlotId, aNewObjectRectangle); + + bReturn = mpView->InsertObjectAtView(pObjDefault.release(), *pPV); + } + } + bReturn = FuConstruct::MouseButtonUp (rMEvt) || bReturn; + + if (!bPermanent) + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + + return bReturn; +} + +void FuConstructCustomShape::Activate() +{ + mpView->SetCurrentObj( SdrObjKind::CustomShape ); + FuConstruct::Activate(); +} + +/** + * set attribute for the object to be created + */ +void FuConstructCustomShape::SetAttributes( SdrObject* pObj ) +{ + bool bAttributesAppliedFromGallery = false; + + if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT ) ) + { + std::vector< OUString > aObjList; + if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT, aObjList ) ) + { + for ( std::vector<OUString>::size_type i = 0; i < aObjList.size(); i++ ) + { + if ( aObjList[ i ].equalsIgnoreAsciiCase( aCustomShape ) ) + { + FmFormModel aFormModel; + SfxItemPool& rPool(aFormModel.GetItemPool()); + rPool.FreezeIdRanges(); + + if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aFormModel ) ) + { + const SdrPage* pPage = aFormModel.GetPage( 0 ); + if ( pPage ) + { + const SdrObject* pSourceObj = pPage->GetObj( 0 ); + if( pSourceObj ) + { + const SfxItemSet& rSource = pSourceObj->GetMergedItemSet(); + SfxItemSetFixed< + // Ranges from SdrAttrObj: + SDRATTR_START, SDRATTR_SHADOW_LAST, + SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST, + SDRATTR_TEXTDIRECTION, + SDRATTR_TEXTDIRECTION, + // Graphic attributes, 3D properties, + // CustomShape properties: + SDRATTR_GRAF_FIRST, + SDRATTR_CUSTOMSHAPE_LAST, + // Range from SdrTextObj: + EE_ITEMS_START, EE_ITEMS_END> aDest(pObj->getSdrModelFromSdrObject().GetItemPool()); + aDest.Set( rSource ); + pObj->SetMergedItemSet( aDest ); + // Enables Word-wrap by default (tdf#134369) + pObj->SetMergedItem( SdrOnOffItem( SDRATTR_TEXT_WORDWRAP, true ) ); + Degree100 nAngle = pSourceObj->GetRotateAngle(); + if ( nAngle ) + pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle ); + bAttributesAppliedFromGallery = true; + } + } + } + break; + } + } + } + } + if ( !bAttributesAppliedFromGallery ) + { + pObj->SetMergedItem( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST ) ); + pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) ); + pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) ); + pObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) ); + static_cast<SdrObjCustomShape*>(pObj)->MergeDefaultAttributes( &aCustomShape ); + } +} + +const OUString& FuConstructCustomShape::GetShapeType() const +{ + return aCustomShape; +} + +SdrObjectUniquePtr FuConstructCustomShape::CreateDefaultObject(const sal_uInt16, const ::tools::Rectangle& rRectangle) +{ + SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject( + mpView->getSdrModelFromSdrView(), + mpView->GetCurrentObjInventor(), + mpView->GetCurrentObjIdentifier())); + + if( pObj ) + { + ::tools::Rectangle aRect( rRectangle ); + if ( doConstructOrthogonal() ) + ImpForceQuadratic( aRect ); + pObj->SetLogicRect( aRect ); + SetAttributes( pObj.get() ); + SfxItemSet aAttr(mpDoc->GetPool()); + SetStyleSheet(aAttr, pObj.get()); + pObj->SetMergedItemSet(aAttr); + } + return pObj; +} + +// #i33136# +bool FuConstructCustomShape::doConstructOrthogonal() const +{ + return SdrObjCustomShape::doConstructOrthogonal(aCustomShape); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuconnct.cxx b/sd/source/ui/func/fuconnct.cxx new file mode 100644 index 000000000..fc95b4907 --- /dev/null +++ b/sd/source/ui/func/fuconnct.cxx @@ -0,0 +1,71 @@ +/* -*- 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 <fuconnct.hxx> +#include <sfx2/request.hxx> +#include <View.hxx> +#include <drawdoc.hxx> +#include <svx/svxdlg.hxx> +#include <svx/dialogs.hrc> + +namespace sd { + + +FuConnectionDlg::FuConnectionDlg ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuConnectionDlg::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuConnectionDlg( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuConnectionDlg::DoExecute( SfxRequest& rReq ) +{ + SfxItemSet aNewAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aNewAttr ); + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if( !pArgs ) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSfxDialog(rReq.GetFrameWeld(), aNewAttr, mpView, RID_SVXPAGE_CONNECTION)); + + if( pDlg->Execute() == RET_OK ) + { + rReq.Done( *pDlg->GetOutputItemSet() ); + pArgs = rReq.GetArgs(); + } + } + if( pArgs ) + mpView->SetAttributes( *pArgs ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuconrec.cxx b/sd/source/ui/func/fuconrec.cxx new file mode 100644 index 000000000..d93ef2849 --- /dev/null +++ b/sd/source/ui/func/fuconrec.cxx @@ -0,0 +1,1096 @@ +/* -*- 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 <fuconrec.hxx> +#include <svx/svdpagv.hxx> + +#include <svx/svxids.hrc> +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> + +#include <app.hrc> +#include <svl/itemset.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnwtit.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/sdtmfitm.hxx> +#include <svx/sxekitm.hxx> +#include <svx/sderitm.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdocirc.hxx> +#include <svl/intitem.hxx> +#include <sfx2/request.hxx> +#include <editeng/adjustitem.hxx> +#include <editeng/eeitem.hxx> +#include <svx/xtable.hxx> +#include <svx/xfltrit.hxx> +#include <svx/xflclit.hxx> +#include <svx/sdtagitm.hxx> +#include <svx/sdtditm.hxx> + +#include <svx/svdocapt.hxx> + +#include <svx/svdomeas.hxx> +#include <ViewShell.hxx> +#include <ViewShellBase.hxx> +#include <ToolBarManager.hxx> +#include <editeng/writingmodeitem.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <svx/xfillit0.hxx> +#include <svx/signaturelinehelper.hxx> +#include <osl/diagnose.h> + +#include <sdresid.hxx> +#include <View.hxx> +#include <sdpage.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> +#include <unokywds.hxx> + +#include <strings.hrc> + +using namespace com::sun::star; + +namespace sd { + + +FuConstructRectangle::FuConstructRectangle ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuConstruct(pViewSh, pWin, pView, pDoc, rReq) + , mnFillTransparence(0) + , mnLineStyle(SAL_MAX_UINT16) +{ +} + +namespace{ + +/// Checks to see if the request has a parameter of IsSticky:bool=true +/// It means that the selected command/button will stay selected after use +bool isSticky(const SfxRequest& rReq) +{ + const SfxItemSet *pArgs = rReq.GetArgs (); + if (pArgs) + { + const SfxBoolItem* pIsSticky = rReq.GetArg<SfxBoolItem>(FN_PARAM_4); + if (pIsSticky && pIsSticky->GetValue()) + return true; + } + + return false; +} + +} + +rtl::Reference<FuPoor> FuConstructRectangle::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent ) +{ + FuConstructRectangle* pFunc; + rtl::Reference<FuPoor> xFunc( pFunc = new FuConstructRectangle( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + pFunc->SetPermanent(bPermanent || isSticky(rReq)); + return xFunc; +} + +void FuConstructRectangle::DoExecute( SfxRequest& rReq ) +{ + FuConstruct::DoExecute( rReq ); + + mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBar( + ToolBarManager::ToolBarGroup::Function, + ToolBarManager::msDrawingObjectToolBar); + + const SfxItemSet *pArgs = rReq.GetArgs (); + + if (pArgs) + { + switch (nSlotId) + { + case SID_DRAW_ELLIPSE : + { + const SfxUInt32Item* pCenterX = rReq.GetArg<SfxUInt32Item>(ID_VAL_CENTER_X); + const SfxUInt32Item* pCenterY = rReq.GetArg<SfxUInt32Item>(ID_VAL_CENTER_Y); + const SfxUInt32Item* pAxisX = rReq.GetArg<SfxUInt32Item>(ID_VAL_AXIS_X); + const SfxUInt32Item* pAxisY = rReq.GetArg<SfxUInt32Item>(ID_VAL_AXIS_Y); + + if (!pCenterX || !pCenterY || !pAxisX || !pAxisY) + break; + + ::tools::Rectangle aNewRectangle (pCenterX->GetValue () - pAxisX->GetValue () / 2, + pCenterY->GetValue () - pAxisY->GetValue () / 2, + pCenterX->GetValue () + pAxisX->GetValue () / 2, + pCenterY->GetValue () + pAxisY->GetValue () / 2); + SdrCircObj *pNewCircle = new SdrCircObj( + mpView->getSdrModelFromSdrView(), + SdrCircKind::Full, + aNewRectangle); + SdrPageView *pPV = mpView->GetSdrPageView(); + + mpView->InsertObjectAtView(pNewCircle, *pPV, SdrInsertFlags::SETDEFLAYER | SdrInsertFlags::SETDEFATTR); + } + break; + + case SID_DRAW_RECT : + { + const SfxUInt32Item* pMouseStartX = rReq.GetArg<SfxUInt32Item>(ID_VAL_MOUSESTART_X); + const SfxUInt32Item* pMouseStartY = rReq.GetArg<SfxUInt32Item>(ID_VAL_MOUSESTART_Y); + const SfxUInt32Item* pMouseEndX = rReq.GetArg<SfxUInt32Item>(ID_VAL_MOUSEEND_X); + const SfxUInt32Item* pMouseEndY = rReq.GetArg<SfxUInt32Item>(ID_VAL_MOUSEEND_Y); + const SfxUInt16Item* pFillTransparence = rReq.GetArg<SfxUInt16Item>(FN_PARAM_1); + const SfxStringItem* pFillColor = rReq.GetArg<SfxStringItem>(FN_PARAM_2); + const SfxUInt16Item* pLineStyle = rReq.GetArg<SfxUInt16Item>(FN_PARAM_3); + const SfxStringItem* pShapeName = rReq.GetArg<SfxStringItem>(SID_SHAPE_NAME); + + if (pFillTransparence && pFillTransparence->GetValue() > 0) + { + mnFillTransparence = pFillTransparence->GetValue(); + } + if (pFillColor && !pFillColor->GetValue().isEmpty()) + { + msFillColor = pFillColor->GetValue(); + } + if (pLineStyle) + { + mnLineStyle = pLineStyle->GetValue(); + } + if (pShapeName && !pShapeName->GetValue().isEmpty()) + { + msShapeName = pShapeName->GetValue(); + } + + if (!pMouseStartX || !pMouseStartY || !pMouseEndX || !pMouseEndY) + break; + + ::tools::Rectangle aNewRectangle (pMouseStartX->GetValue (), + pMouseStartY->GetValue (), + pMouseEndX->GetValue (), + pMouseEndY->GetValue ()); + SdrRectObj *pNewRect = new SdrRectObj( + mpView->getSdrModelFromSdrView(), + aNewRectangle); + SdrPageView *pPV = mpView->GetSdrPageView(); + + mpView->InsertObjectAtView(pNewRect, *pPV, SdrInsertFlags::SETDEFLAYER | SdrInsertFlags::SETDEFATTR); + } + break; + } + } + + if (nSlotId == SID_TOOL_CONNECTOR || + nSlotId == SID_CONNECTOR_ARROW_START || + nSlotId == SID_CONNECTOR_ARROW_END || + nSlotId == SID_CONNECTOR_ARROWS || + nSlotId == SID_CONNECTOR_CIRCLE_START || + nSlotId == SID_CONNECTOR_CIRCLE_END || + nSlotId == SID_CONNECTOR_CIRCLES || + nSlotId == SID_CONNECTOR_LINE || + nSlotId == SID_CONNECTOR_LINE_ARROW_START || + nSlotId == SID_CONNECTOR_LINE_ARROW_END || + nSlotId == SID_CONNECTOR_LINE_ARROWS || + nSlotId == SID_CONNECTOR_LINE_CIRCLE_START || + nSlotId == SID_CONNECTOR_LINE_CIRCLE_END || + nSlotId == SID_CONNECTOR_LINE_CIRCLES || + nSlotId == SID_CONNECTOR_CURVE || + nSlotId == SID_CONNECTOR_CURVE_ARROW_START || + nSlotId == SID_CONNECTOR_CURVE_ARROW_END || + nSlotId == SID_CONNECTOR_CURVE_ARROWS || + nSlotId == SID_CONNECTOR_CURVE_CIRCLE_START || + nSlotId == SID_CONNECTOR_CURVE_CIRCLE_END || + nSlotId == SID_CONNECTOR_CURVE_CIRCLES || + nSlotId == SID_CONNECTOR_LINES || + nSlotId == SID_CONNECTOR_LINES_ARROW_START || + nSlotId == SID_CONNECTOR_LINES_ARROW_END || + nSlotId == SID_CONNECTOR_LINES_ARROWS || + nSlotId == SID_CONNECTOR_LINES_CIRCLE_START || + nSlotId == SID_CONNECTOR_LINES_CIRCLE_END || + nSlotId == SID_CONNECTOR_LINES_CIRCLES || + nSlotId == SID_LINE_ARROW_START || + nSlotId == SID_LINE_ARROW_END || + nSlotId == SID_LINE_ARROWS || + nSlotId == SID_LINE_ARROW_CIRCLE || + nSlotId == SID_LINE_CIRCLE_ARROW || + nSlotId == SID_LINE_ARROW_SQUARE || + nSlotId == SID_LINE_SQUARE_ARROW ) + { + mpView->UnmarkAll(); + } +} + +bool FuConstructRectangle::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = FuConstruct::MouseButtonDown(rMEvt); + + if ( rMEvt.IsLeft() && !mpView->IsAction() ) + { + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + + mpWindow->CaptureMouse(); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + + if (mpView->GetCurrentObjIdentifier() == SdrObjKind::Caption) + { + Size aCaptionSize(846, 846); // (4x2)cm + bReturn = mpView->BegCreateCaptionObj(aPnt, aCaptionSize, + nullptr, nDrgLog); + } + else + { + mpView->BegCreateObj(aPnt, nullptr, nDrgLog); + } + + SdrObject* pObj = mpView->GetCreateObj(); + + if (pObj) + { + SfxItemSet aAttr(mpDoc->GetPool()); + SetStyleSheet(aAttr, pObj); + SetAttributes(aAttr, pObj); + SetLineEnds(aAttr, *pObj); + pObj->SetMergedItemSet(aAttr); + + if( nSlotId == SID_DRAW_CAPTION_VERTICAL ) + static_cast<SdrTextObj*>(pObj)->SetVerticalWriting( true ); + } + } + return bReturn; +} + +bool FuConstructRectangle::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn(false); + + if(mpView->IsCreateObj() && rMEvt.IsLeft()) + { + SdrObject* pObj = mpView->GetCreateObj(); + + if(pObj && mpView->EndCreateObj(SdrCreateCmd::ForceEnd)) + { + if(SID_DRAW_MEASURELINE == nSlotId) + { + SdrLayerAdmin& rAdmin = mpDoc->GetLayerAdmin(); + pObj->SetLayer(rAdmin.GetLayerID(sUNO_LayerName_measurelines)); + } + + // init text position when vertical caption object is created + if( dynamic_cast< const SdrCaptionObj *>( pObj ) != nullptr && SID_DRAW_CAPTION_VERTICAL == nSlotId) + { + // draw text object, needs to be initialized when vertical text is used + SfxItemSet aSet(pObj->GetMergedItemSet()); + + aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + + // Correct the value of SDRATTR_TEXTDIRECTION to avoid SetItemSet + // calling SetVerticalWriting() again since this item may not yet + // be set at the object and thus may differ from vertical state of + // the object. + aSet.Put(SvxWritingModeItem(css::text::WritingMode_TB_RL, SDRATTR_TEXTDIRECTION)); + pObj->SetMergedItemSet(aSet); + } + + bReturn = true; + } + else + { + //Drag was too small to create object, so insert default object at click pos + Point aClickPos(mpWindow->PixelToLogic(rMEvt.GetPosPixel())); + sal_uInt32 nDefaultObjectSize(1500); + sal_Int32 nCenterOffset(-sal_Int32(nDefaultObjectSize / 2)); + aClickPos.AdjustX(nCenterOffset); + aClickPos.AdjustY(nCenterOffset); + + SdrPageView *pPV = mpView->GetSdrPageView(); + if(mpView->IsSnapEnabled()) + aClickPos = mpView->GetSnapPos(aClickPos, pPV); + + ::tools::Rectangle aNewObjectRectangle(aClickPos, Size(nDefaultObjectSize, nDefaultObjectSize)); + SdrObjectUniquePtr pObjDefault = CreateDefaultObject(nSlotId, aNewObjectRectangle); + + bReturn = mpView->InsertObjectAtView(pObjDefault.release(), *pPV); + } + } + + bReturn = FuConstruct::MouseButtonUp (rMEvt) || bReturn; + + if (!bPermanent) + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + + return bReturn; +} + +void FuConstructRectangle::Activate() +{ + SdrObjKind aObjKind; + + switch (nSlotId) + { + case SID_LINE_ARROW_START: + case SID_LINE_ARROW_END: + case SID_LINE_ARROWS: + case SID_LINE_ARROW_CIRCLE: + case SID_LINE_CIRCLE_ARROW: + case SID_LINE_ARROW_SQUARE: + case SID_LINE_SQUARE_ARROW: + mpView->SetGlueVisible(); + [[fallthrough]]; + case SID_DRAW_LINE : + case SID_DRAW_XLINE: + aObjKind = SdrObjKind::Line; + break; + + case SID_DRAW_MEASURELINE: + { + aObjKind = SdrObjKind::Measure; + } + break; + + case SID_DRAW_RECT : + case SID_DRAW_RECT_NOFILL : + case SID_DRAW_RECT_ROUND : + case SID_DRAW_RECT_ROUND_NOFILL: + case SID_DRAW_SQUARE : + case SID_DRAW_SQUARE_NOFILL : + case SID_DRAW_SQUARE_ROUND : + case SID_DRAW_SQUARE_ROUND_NOFILL: + { + aObjKind = SdrObjKind::Rectangle; + } + break; + + case SID_DRAW_ELLIPSE : + case SID_DRAW_ELLIPSE_NOFILL: + case SID_DRAW_CIRCLE : + case SID_DRAW_CIRCLE_NOFILL : + { + aObjKind = SdrObjKind::CircleOrEllipse; + } + break; + + case SID_DRAW_CAPTION: + case SID_DRAW_CAPTION_VERTICAL: + { + aObjKind = SdrObjKind::Caption; + } + break; + + case SID_TOOL_CONNECTOR: + case SID_CONNECTOR_ARROW_START: + case SID_CONNECTOR_ARROW_END: + case SID_CONNECTOR_ARROWS: + case SID_CONNECTOR_CIRCLE_START: + case SID_CONNECTOR_CIRCLE_END: + case SID_CONNECTOR_CIRCLES: + case SID_CONNECTOR_LINE: + case SID_CONNECTOR_LINE_ARROW_START: + case SID_CONNECTOR_LINE_ARROW_END: + case SID_CONNECTOR_LINE_ARROWS: + case SID_CONNECTOR_LINE_CIRCLE_START: + case SID_CONNECTOR_LINE_CIRCLE_END: + case SID_CONNECTOR_LINE_CIRCLES: + case SID_CONNECTOR_CURVE: + case SID_CONNECTOR_CURVE_ARROW_START: + case SID_CONNECTOR_CURVE_ARROW_END: + case SID_CONNECTOR_CURVE_ARROWS: + case SID_CONNECTOR_CURVE_CIRCLE_START: + case SID_CONNECTOR_CURVE_CIRCLE_END: + case SID_CONNECTOR_CURVE_CIRCLES: + case SID_CONNECTOR_LINES: + case SID_CONNECTOR_LINES_ARROW_START: + case SID_CONNECTOR_LINES_ARROW_END: + case SID_CONNECTOR_LINES_ARROWS: + case SID_CONNECTOR_LINES_CIRCLE_START: + case SID_CONNECTOR_LINES_CIRCLE_END: + case SID_CONNECTOR_LINES_CIRCLES: + { + aObjKind = SdrObjKind::Edge; + mpView->SetGlueVisible(); + } + break; + case SID_INSERT_SIGNATURELINE: + { + aObjKind = SdrObjKind::Graphic; + } + break; + + default: + { + aObjKind = SdrObjKind::Rectangle; + } + break; + } + + mpView->SetCurrentObj(aObjKind); + + FuConstruct::Activate(); +} + +void FuConstructRectangle::Deactivate() +{ + if( nSlotId == SID_TOOL_CONNECTOR || + nSlotId == SID_CONNECTOR_ARROW_START || + nSlotId == SID_CONNECTOR_ARROW_END || + nSlotId == SID_CONNECTOR_ARROWS || + nSlotId == SID_CONNECTOR_CIRCLE_START || + nSlotId == SID_CONNECTOR_CIRCLE_END || + nSlotId == SID_CONNECTOR_CIRCLES || + nSlotId == SID_CONNECTOR_LINE || + nSlotId == SID_CONNECTOR_LINE_ARROW_START || + nSlotId == SID_CONNECTOR_LINE_ARROW_END || + nSlotId == SID_CONNECTOR_LINE_ARROWS || + nSlotId == SID_CONNECTOR_LINE_CIRCLE_START || + nSlotId == SID_CONNECTOR_LINE_CIRCLE_END || + nSlotId == SID_CONNECTOR_LINE_CIRCLES || + nSlotId == SID_CONNECTOR_CURVE || + nSlotId == SID_CONNECTOR_CURVE_ARROW_START || + nSlotId == SID_CONNECTOR_CURVE_ARROW_END || + nSlotId == SID_CONNECTOR_CURVE_ARROWS || + nSlotId == SID_CONNECTOR_CURVE_CIRCLE_START || + nSlotId == SID_CONNECTOR_CURVE_CIRCLE_END || + nSlotId == SID_CONNECTOR_CURVE_CIRCLES || + nSlotId == SID_CONNECTOR_LINES || + nSlotId == SID_CONNECTOR_LINES_ARROW_START || + nSlotId == SID_CONNECTOR_LINES_ARROW_END || + nSlotId == SID_CONNECTOR_LINES_ARROWS || + nSlotId == SID_CONNECTOR_LINES_CIRCLE_START || + nSlotId == SID_CONNECTOR_LINES_CIRCLE_END || + nSlotId == SID_CONNECTOR_LINES_CIRCLES || + nSlotId == SID_LINE_ARROW_START || + nSlotId == SID_LINE_ARROW_END || + nSlotId == SID_LINE_ARROWS || + nSlotId == SID_LINE_ARROW_CIRCLE || + nSlotId == SID_LINE_CIRCLE_ARROW || + nSlotId == SID_LINE_ARROW_SQUARE || + nSlotId == SID_LINE_SQUARE_ARROW ) + { + mpView->SetGlueVisible( false ); + } + FuConstruct::Deactivate(); + + if (nSlotId != SID_INSERT_SIGNATURELINE) + { + return; + } + + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() < 1) + { + // Just switching pages, no signature rectangle yet. + return; + } + + // Finished drawing a signature rectangle, now set it up. + if (!mpViewShell) + { + return; + } + + uno::Reference<security::XCertificate> xCertificate + = svx::SignatureLineHelper::getSignatureCertificate(mpViewShell->GetObjectShell(), + mpViewShell->GetFrameWeld()); + if (!xCertificate.is()) + { + return; + } + + svx::SignatureLineHelper::setShapeCertificate(mpView, xCertificate); + + // Update infobar to offer "finish signing". + SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); + if (pFrame && pFrame->HasInfoBarWithID(u"readonly")) + { + pFrame->RemoveInfoBar(u"readonly"); + pFrame->AppendReadOnlyInfobar(); + } +} + +namespace { +/// Returns the color based on the color names listed in core/include/tools/color.hxx +/// Feel free to extend with more color names from color.hxx +Color strToColor(std::u16string_view sColor) +{ + Color aColor = COL_AUTO; + + if (sColor == u"COL_GRAY") + aColor = COL_GRAY; + else if (sColor == u"COL_GRAY3") + aColor = COL_GRAY3; + else if (sColor == u"COL_GRAY7") + aColor = COL_GRAY7; + + return aColor; +} +} + +/** + * set attribute for the object to be created + */ +void FuConstructRectangle::SetAttributes(SfxItemSet& rAttr, SdrObject* pObj) +{ + if (nSlotId == SID_DRAW_RECT_ROUND || + nSlotId == SID_DRAW_RECT_ROUND_NOFILL || + nSlotId == SID_DRAW_SQUARE_ROUND || + nSlotId == SID_DRAW_SQUARE_ROUND_NOFILL) + { + // round corner + rAttr.Put(makeSdrEckenradiusItem(500)); + } + else if (nSlotId == SID_CONNECTOR_LINE || + nSlotId == SID_CONNECTOR_LINE_ARROW_START || + nSlotId == SID_CONNECTOR_LINE_ARROW_END || + nSlotId == SID_CONNECTOR_LINE_ARROWS || + nSlotId == SID_CONNECTOR_LINE_CIRCLE_START || + nSlotId == SID_CONNECTOR_LINE_CIRCLE_END || + nSlotId == SID_CONNECTOR_LINE_CIRCLES) + { + // direct connector + rAttr.Put(SdrEdgeKindItem(SdrEdgeKind::OneLine)); + } + else if (nSlotId == SID_CONNECTOR_LINES || + nSlotId == SID_CONNECTOR_LINES_ARROW_START || + nSlotId == SID_CONNECTOR_LINES_ARROW_END || + nSlotId == SID_CONNECTOR_LINES_ARROWS || + nSlotId == SID_CONNECTOR_LINES_CIRCLE_START || + nSlotId == SID_CONNECTOR_LINES_CIRCLE_END || + nSlotId == SID_CONNECTOR_LINES_CIRCLES) + { + // line connector + rAttr.Put(SdrEdgeKindItem(SdrEdgeKind::ThreeLines)); + } + else if (nSlotId == SID_CONNECTOR_CURVE || + nSlotId == SID_CONNECTOR_CURVE_ARROW_START || + nSlotId == SID_CONNECTOR_CURVE_ARROW_END || + nSlotId == SID_CONNECTOR_CURVE_ARROWS || + nSlotId == SID_CONNECTOR_CURVE_CIRCLE_START || + nSlotId == SID_CONNECTOR_CURVE_CIRCLE_END || + nSlotId == SID_CONNECTOR_CURVE_CIRCLES) + { + // curve connector + rAttr.Put(SdrEdgeKindItem(SdrEdgeKind::Bezier)); + } + else if ( nSlotId == SID_DRAW_CAPTION || nSlotId == SID_DRAW_CAPTION_VERTICAL ) + { + // legend object + Size aSize(pObj->GetLogicRect().GetSize()); + rAttr.Put( makeSdrTextMinFrameHeightItem( aSize.Height() ) ); + rAttr.Put( makeSdrTextMinFrameWidthItem( aSize.Width() ) ); + rAttr.Put( makeSdrTextAutoGrowHeightItem( true ) ); + rAttr.Put( makeSdrTextAutoGrowWidthItem( true ) ); + + // Support full with for vertical caption objects, too + if(SID_DRAW_CAPTION == nSlotId) + rAttr.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) ); + else + rAttr.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_BLOCK ) ); + + rAttr.Put( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST ) ); + rAttr.Put( makeSdrTextLeftDistItem( 100 ) ); + rAttr.Put( makeSdrTextRightDistItem( 100 ) ); + rAttr.Put( makeSdrTextUpperDistItem( 100 ) ); + rAttr.Put( makeSdrTextLowerDistItem( 100 ) ); + } + else if (nSlotId == SID_DRAW_MEASURELINE) + { + // dimension line + SdPage* pPage = static_cast<SdPage*>( mpView->GetSdrPageView()->GetPage() ); + OUString aName(SdResId(STR_POOLSHEET_MEASURE)); + SfxStyleSheet* pSheet( + static_cast< SfxStyleSheet* >( + pPage->getSdrModelFromSdrPage().GetStyleSheetPool()->Find(aName, SfxStyleFamily::Para))); + DBG_ASSERT(pSheet, "StyleSheet missing"); + + if (pSheet) + { + pObj->SetStyleSheet(pSheet, false); + } + + SdrLayerAdmin& rAdmin = mpDoc->GetLayerAdmin(); + pObj->SetLayer(rAdmin.GetLayerID(sUNO_LayerName_measurelines)); + } + else if (nSlotId == SID_DRAW_RECT) + { + if (mnFillTransparence > 0 && mnFillTransparence <= 100) + rAttr.Put(XFillTransparenceItem(mnFillTransparence)); + if (!msFillColor.isEmpty()) + rAttr.Put(XFillColorItem(OUString(), strToColor(msFillColor))); + if (!msShapeName.isEmpty()) + pObj->SetName(msShapeName); + + switch(mnLineStyle) + { + case 0: + rAttr.Put( XLineStyleItem(css::drawing::LineStyle_NONE ) ); + break; + case 1: + rAttr.Put( XLineStyleItem(css::drawing::LineStyle_SOLID ) ); + break; + case 2: + rAttr.Put( XLineStyleItem(css::drawing::LineStyle_DASH ) ); + break; + default: + // Leave it to the defaults + break; + } + } + else if (nSlotId == SID_INSERT_SIGNATURELINE) + { + // Avoid the default solid fill and line, we'll set a graphic instead. + rAttr.Put(XFillStyleItem(drawing::FillStyle_NONE)); + rAttr.Put(XLineStyleItem(drawing::LineStyle_NONE)); + } +} + +/** + * set line starts and ends for the object to be created + */ +static ::basegfx::B2DPolyPolygon getPolygon(TranslateId pResId, const SdrModel& rModel) +{ + ::basegfx::B2DPolyPolygon aRetval; + XLineEndListRef pLineEndList(rModel.GetLineEndList()); + + if( pLineEndList.is() ) + { + OUString aArrowName(SvxResId(pResId)); + ::tools::Long nCount = pLineEndList->Count(); + ::tools::Long nIndex; + for( nIndex = 0; nIndex < nCount; nIndex++ ) + { + const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nIndex); + if( pEntry->GetName() == aArrowName ) + { + aRetval = pEntry->GetLineEnd(); + break; + } + } + } + + return aRetval; +} + +void FuConstructRectangle::SetLineEnds(SfxItemSet& rAttr, SdrObject const & rObj) +{ + if ( !((rObj.GetObjIdentifier() == SdrObjKind::Edge && + nSlotId != SID_TOOL_CONNECTOR && + nSlotId != SID_CONNECTOR_LINE && + nSlotId != SID_CONNECTOR_LINES && + nSlotId != SID_CONNECTOR_CURVE) || + nSlotId == SID_LINE_ARROW_START || + nSlotId == SID_LINE_ARROW_END || + nSlotId == SID_LINE_ARROWS || + nSlotId == SID_LINE_ARROW_CIRCLE || + nSlotId == SID_LINE_CIRCLE_ARROW || + nSlotId == SID_LINE_ARROW_SQUARE || + nSlotId == SID_LINE_SQUARE_ARROW) ) + return; + + // set attributes of line start and ends + SdrModel& rModel(rObj.getSdrModelFromSdrObject()); + + // arrowhead + ::basegfx::B2DPolyPolygon aArrow( getPolygon( RID_SVXSTR_ARROW, rModel ) ); + if( !aArrow.count() ) + { + ::basegfx::B2DPolygon aNewArrow; + aNewArrow.append(::basegfx::B2DPoint(10.0, 0.0)); + aNewArrow.append(::basegfx::B2DPoint(0.0, 30.0)); + aNewArrow.append(::basegfx::B2DPoint(20.0, 30.0)); + aNewArrow.setClosed(true); + aArrow.append(aNewArrow); + } + + // Circles + ::basegfx::B2DPolyPolygon aCircle( getPolygon( RID_SVXSTR_CIRCLE, rModel ) ); + if( !aCircle.count() ) + { + ::basegfx::B2DPolygon aNewCircle = ::basegfx::utils::createPolygonFromEllipse(::basegfx::B2DPoint(0.0, 0.0), 250.0, 250.0); + aNewCircle.setClosed(true); + aCircle.append(aNewCircle); + } + + // Square + ::basegfx::B2DPolyPolygon aSquare( getPolygon( RID_SVXSTR_SQUARE, rModel ) ); + if( !aSquare.count() ) + { + ::basegfx::B2DPolygon aNewSquare; + aNewSquare.append(::basegfx::B2DPoint(0.0, 0.0)); + aNewSquare.append(::basegfx::B2DPoint(10.0, 0.0)); + aNewSquare.append(::basegfx::B2DPoint(10.0, 10.0)); + aNewSquare.append(::basegfx::B2DPoint(0.0, 10.0)); + aNewSquare.setClosed(true); + aSquare.append(aNewSquare); + } + + SfxItemSet aSet( mpDoc->GetPool() ); + mpView->GetAttributes( aSet ); + + // #i3908# Here, the default Line Start/End width for arrow construction is + // set. To have the same value in all situations (construction) in i3908 + // it was decided to change the default to 0.03 cm for all situations. + ::tools::Long nWidth = 300; // (1/100th mm) + + // determine line width and calculate with it the line end width + if( aSet.GetItemState( XATTR_LINEWIDTH ) != SfxItemState::DONTCARE ) + { + ::tools::Long nValue = aSet.Get( XATTR_LINEWIDTH ).GetValue(); + if( nValue > 0 ) + nWidth = nValue * 3; + } + + switch (nSlotId) + { + case SID_CONNECTOR_ARROWS: + case SID_CONNECTOR_LINE_ARROWS: + case SID_CONNECTOR_LINES_ARROWS: + case SID_CONNECTOR_CURVE_ARROWS: + case SID_LINE_ARROWS: + { + // connector with arrow ends + rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROW), aArrow)); + rAttr.Put(XLineStartWidthItem(nWidth)); + rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROW), aArrow)); + rAttr.Put(XLineEndWidthItem(nWidth)); + } + break; + + case SID_CONNECTOR_ARROW_START: + case SID_CONNECTOR_LINE_ARROW_START: + case SID_CONNECTOR_LINES_ARROW_START: + case SID_CONNECTOR_CURVE_ARROW_START: + case SID_LINE_ARROW_START: + case SID_LINE_ARROW_CIRCLE: + case SID_LINE_ARROW_SQUARE: + { + // connector with arrow start + rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_ARROW), aArrow)); + rAttr.Put(XLineStartWidthItem(nWidth)); + } + break; + + case SID_CONNECTOR_ARROW_END: + case SID_CONNECTOR_LINE_ARROW_END: + case SID_CONNECTOR_LINES_ARROW_END: + case SID_CONNECTOR_CURVE_ARROW_END: + case SID_LINE_ARROW_END: + case SID_LINE_CIRCLE_ARROW: + case SID_LINE_SQUARE_ARROW: + { + // connector with arrow end + rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_ARROW), aArrow)); + rAttr.Put(XLineEndWidthItem(nWidth)); + } + break; + + case SID_CONNECTOR_CIRCLES: + case SID_CONNECTOR_LINE_CIRCLES: + case SID_CONNECTOR_LINES_CIRCLES: + case SID_CONNECTOR_CURVE_CIRCLES: + { + // connector with circle ends + rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle)); + rAttr.Put(XLineStartWidthItem(nWidth)); + rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle)); + rAttr.Put(XLineEndWidthItem(nWidth)); + } + break; + + case SID_CONNECTOR_CIRCLE_START: + case SID_CONNECTOR_LINE_CIRCLE_START: + case SID_CONNECTOR_LINES_CIRCLE_START: + case SID_CONNECTOR_CURVE_CIRCLE_START: + { + // connector with circle start + rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle)); + rAttr.Put(XLineStartWidthItem(nWidth)); + } + break; + + case SID_CONNECTOR_CIRCLE_END: + case SID_CONNECTOR_LINE_CIRCLE_END: + case SID_CONNECTOR_LINES_CIRCLE_END: + case SID_CONNECTOR_CURVE_CIRCLE_END: + { + // connector with circle ends + rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle)); + rAttr.Put(XLineEndWidthItem(nWidth)); + } + break; + } + + // and again, for the still missing ends + switch (nSlotId) + { + case SID_LINE_ARROW_CIRCLE: + { + // circle end + rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle)); + rAttr.Put(XLineEndWidthItem(nWidth)); + } + break; + + case SID_LINE_CIRCLE_ARROW: + { + // circle start + rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_CIRCLE), aCircle)); + rAttr.Put(XLineStartWidthItem(nWidth)); + } + break; + + case SID_LINE_ARROW_SQUARE: + { + // square end + rAttr.Put(XLineEndItem(SvxResId(RID_SVXSTR_SQUARE), aSquare)); + rAttr.Put(XLineEndWidthItem(nWidth)); + } + break; + + case SID_LINE_SQUARE_ARROW: + { + // square start + rAttr.Put(XLineStartItem(SvxResId(RID_SVXSTR_SQUARE), aSquare)); + rAttr.Put(XLineStartWidthItem(nWidth)); + } + break; + } +} + +SdrObjectUniquePtr FuConstructRectangle::CreateDefaultObject(const sal_uInt16 nID, const ::tools::Rectangle& rRectangle) +{ + DBG_ASSERT( (nID != SID_DRAW_FONTWORK) && (nID != SID_DRAW_FONTWORK_VERTICAL ), "FuConstRectangle::CreateDefaultObject can not create Fontwork shapes!" ); + + // case SID_DRAW_LINE: + // case SID_DRAW_XLINE: + // case SID_DRAW_MEASURELINE: + // case SID_LINE_ARROW_START: + // case SID_LINE_ARROW_END: + // case SID_LINE_ARROWS: + // case SID_LINE_ARROW_CIRCLE: + // case SID_LINE_CIRCLE_ARROW: + // case SID_LINE_ARROW_SQUARE: + // case SID_LINE_SQUARE_ARROW: + // case SID_DRAW_RECT: + // case SID_DRAW_RECT_NOFILL: + // case SID_DRAW_RECT_ROUND: + // case SID_DRAW_RECT_ROUND_NOFILL: + // case SID_DRAW_SQUARE: + // case SID_DRAW_SQUARE_NOFILL: + // case SID_DRAW_SQUARE_ROUND: + // case SID_DRAW_SQUARE_ROUND_NOFILL: + // case SID_DRAW_ELLIPSE: + // case SID_DRAW_ELLIPSE_NOFILL: + // case SID_DRAW_CIRCLE: + // case SID_DRAW_CIRCLE_NOFILL: + // case SID_DRAW_CAPTION: + // case SID_DRAW_CAPTION_VERTICAL: + // case SID_TOOL_CONNECTOR: + // case SID_CONNECTOR_ARROW_START: + // case SID_CONNECTOR_ARROW_END: + // case SID_CONNECTOR_ARROWS: + // case SID_CONNECTOR_CIRCLE_START: + // case SID_CONNECTOR_CIRCLE_END: + // case SID_CONNECTOR_CIRCLES: + // case SID_CONNECTOR_LINE: + // case SID_CONNECTOR_LINE_ARROW_START: + // case SID_CONNECTOR_LINE_ARROW_END: + // case SID_CONNECTOR_LINE_ARROWS: + // case SID_CONNECTOR_LINE_CIRCLE_START: + // case SID_CONNECTOR_LINE_CIRCLE_END: + // case SID_CONNECTOR_LINE_CIRCLES: + // case SID_CONNECTOR_CURVE: + // case SID_CONNECTOR_CURVE_ARROW_START: + // case SID_CONNECTOR_CURVE_ARROW_END: + // case SID_CONNECTOR_CURVE_ARROWS: + // case SID_CONNECTOR_CURVE_CIRCLE_START: + // case SID_CONNECTOR_CURVE_CIRCLE_END: + // case SID_CONNECTOR_CURVE_CIRCLES: + // case SID_CONNECTOR_LINES: + // case SID_CONNECTOR_LINES_ARROW_START: + // case SID_CONNECTOR_LINES_ARROW_END: + // case SID_CONNECTOR_LINES_ARROWS: + // case SID_CONNECTOR_LINES_CIRCLE_START: + // case SID_CONNECTOR_LINES_CIRCLE_END: + // case SID_CONNECTOR_LINES_CIRCLES: + + SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject( + mpView->getSdrModelFromSdrView(), + mpView->GetCurrentObjInventor(), + mpView->GetCurrentObjIdentifier())); + + if(pObj) + { + ::tools::Rectangle aRect(rRectangle); + + if(SID_DRAW_SQUARE == nID || + SID_DRAW_SQUARE_NOFILL == nID || + SID_DRAW_SQUARE_ROUND == nID || + SID_DRAW_SQUARE_ROUND_NOFILL == nID || + SID_DRAW_CIRCLE == nID || + SID_DRAW_CIRCLE_NOFILL == nID) + { + // force quadratic + ImpForceQuadratic(aRect); + } + + Point aStart = aRect.TopLeft(); + Point aEnd = aRect.BottomRight(); + + switch(nID) + { + case SID_DRAW_LINE: + case SID_DRAW_XLINE: + case SID_LINE_ARROW_START: + case SID_LINE_ARROW_END: + case SID_LINE_ARROWS: + case SID_LINE_ARROW_CIRCLE: + case SID_LINE_CIRCLE_ARROW: + case SID_LINE_ARROW_SQUARE: + case SID_LINE_SQUARE_ARROW: + { + if( auto pPathObj = dynamic_cast<SdrPathObj *>( pObj.get() ) ) + { + sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2); + + ::basegfx::B2DPolygon aB2DPolygon; + aB2DPolygon.append(::basegfx::B2DPoint(aStart.X(), nYMiddle)); + aB2DPolygon.append(::basegfx::B2DPoint(aEnd.X(), nYMiddle)); + pPathObj->SetPathPoly(::basegfx::B2DPolyPolygon(aB2DPolygon)); + } + else + { + OSL_FAIL("Object is NO line object"); + } + + break; + } + + case SID_DRAW_MEASURELINE: + { + if( auto pMeasureObj = dynamic_cast< SdrMeasureObj *>( pObj.get() ) ) + { + sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2); + pMeasureObj->SetPoint(Point(aStart.X(), nYMiddle), 0); + pMeasureObj->SetPoint(Point(aEnd.X(), nYMiddle), 1); + } + else + { + OSL_FAIL("Object is NO measure object"); + } + + break; + } + + case SID_TOOL_CONNECTOR: + case SID_CONNECTOR_ARROW_START: + case SID_CONNECTOR_ARROW_END: + case SID_CONNECTOR_ARROWS: + case SID_CONNECTOR_CIRCLE_START: + case SID_CONNECTOR_CIRCLE_END: + case SID_CONNECTOR_CIRCLES: + case SID_CONNECTOR_LINE: + case SID_CONNECTOR_LINE_ARROW_START: + case SID_CONNECTOR_LINE_ARROW_END: + case SID_CONNECTOR_LINE_ARROWS: + case SID_CONNECTOR_LINE_CIRCLE_START: + case SID_CONNECTOR_LINE_CIRCLE_END: + case SID_CONNECTOR_LINE_CIRCLES: + case SID_CONNECTOR_CURVE: + case SID_CONNECTOR_CURVE_ARROW_START: + case SID_CONNECTOR_CURVE_ARROW_END: + case SID_CONNECTOR_CURVE_ARROWS: + case SID_CONNECTOR_CURVE_CIRCLE_START: + case SID_CONNECTOR_CURVE_CIRCLE_END: + case SID_CONNECTOR_CURVE_CIRCLES: + case SID_CONNECTOR_LINES: + case SID_CONNECTOR_LINES_ARROW_START: + case SID_CONNECTOR_LINES_ARROW_END: + case SID_CONNECTOR_LINES_ARROWS: + case SID_CONNECTOR_LINES_CIRCLE_START: + case SID_CONNECTOR_LINES_CIRCLE_END: + case SID_CONNECTOR_LINES_CIRCLES: + { + if( auto pEdgeObj = dynamic_cast< SdrEdgeObj *>( pObj.get() ) ) + { + pEdgeObj->SetTailPoint(false, aStart); + pEdgeObj->SetTailPoint(true, aEnd); + } + else + { + OSL_FAIL("Object is NO connector object"); + } + + break; + } + case SID_DRAW_CAPTION: + case SID_DRAW_CAPTION_VERTICAL: + { + if( auto pCaptionObj = dynamic_cast< SdrCaptionObj *>( pObj.get() ) ) + { + bool bIsVertical(SID_DRAW_CAPTION_VERTICAL == nID); + + pCaptionObj->SetVerticalWriting(bIsVertical); + + if(bIsVertical) + { + SfxItemSet aSet(pObj->GetMergedItemSet()); + aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + pObj->SetMergedItemSet(aSet); + } + + // The default text is not inserted anymore. + + pCaptionObj->SetLogicRect(aRect); + pCaptionObj->SetTailPos( + aRect.TopLeft() - Point(aRect.GetWidth() / 2, aRect.GetHeight() / 2)); + } + else + { + OSL_FAIL("Object is NO caption object"); + } + + break; + } + + default: + { + pObj->SetLogicRect(aRect); + + break; + } + } + + SfxItemSet aAttr(mpDoc->GetPool()); + SetStyleSheet(aAttr, pObj.get()); + SetAttributes(aAttr, pObj.get()); + SetLineEnds(aAttr, *pObj); + pObj->SetMergedItemSet(aAttr); + } + + return pObj; +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuconstr.cxx b/sd/source/ui/func/fuconstr.cxx new file mode 100644 index 000000000..9d6f36320 --- /dev/null +++ b/sd/source/ui/func/fuconstr.cxx @@ -0,0 +1,414 @@ +/* -*- 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 <fuconstr.hxx> + +#include <svx/svxids.hrc> +#include <svx/svdpagv.hxx> +#include <svx/xdef.hxx> +#include <svx/xfillit0.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <tools/debug.hxx> +#include <svx/xflclit.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnclit.hxx> + +#include <app.hrc> +#include <strings.hrc> +#include <strings.hxx> +#include <fudraw.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <ViewShell.hxx> +#include <drawdoc.hxx> +#include <FrameView.hxx> +#include <sdpage.hxx> +#include <sdresid.hxx> +#include <glob.hxx> +#include <comphelper/lok.hxx> + +using namespace com::sun::star; + +namespace sd { + + +FuConstruct::FuConstruct ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuDraw(pViewSh, pWin, pView, pDoc, rReq), + bSelectionChanged(false) +{ +} + +bool FuConstruct::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = FuDraw::MouseButtonDown(rMEvt); + + bMBDown = true; + bSelectionChanged = false; + + if ( mpView->IsAction() ) + { + return true; + } + + bFirstMouseMove = true; + aDragTimer.Start(); + + aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() ); + sal_uInt16 nHitLog = sal_uInt16 (mpWindow->PixelToLogic(Size(HITPIX,0)).Width()); + + if (rMEvt.IsLeft() && mpView->IsExtendedMouseEventDispatcherEnabled()) + { + mpWindow->CaptureMouse(); + + SdrHdl* pHdl = mpView->PickHandle(aMDPos); + + if ( pHdl != nullptr || mpView->IsMarkedHit(aMDPos, nHitLog) ) + { + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); + bReturn = true; + } + else if ( mpView->AreObjectsMarked() ) + { + mpView->UnmarkAll(); + bReturn = true; + } + } + + return bReturn; +} + +bool FuConstruct::MouseMove(const MouseEvent& rMEvt) +{ + FuDraw::MouseMove(rMEvt); + + if (aDragTimer.IsActive() ) + { + if( bFirstMouseMove ) + bFirstMouseMove = false; + else + aDragTimer.Stop(); + } + + Point aPix(rMEvt.GetPosPixel()); + Point aPnt( mpWindow->PixelToLogic(aPix) ); + + if ( mpView->IsAction() ) + { + ForceScroll(aPix); + mpView->MovAction(aPnt); + } + + return true; +} + +bool FuConstruct::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = true; + + if (aDragTimer.IsActive() ) + { + aDragTimer.Stop(); + bIsInDragMode = false; + } + + FuDraw::MouseButtonUp(rMEvt); + + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + + if ( mpView && mpView->IsDragObj() ) + { + FrameView* pFrameView = mpViewShell->GetFrameView(); + bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); + + if (bDragWithCopy) + { + bDragWithCopy = !mpView->IsPresObjSelected(false); + } + + mpView->SetDragWithCopy(bDragWithCopy); + mpView->EndDragObj( mpView->IsDragWithCopy() ); + } + else if ( mpView && mpView->IsMarkObj() ) + { + mpView->EndMarkObj(); + } + else + { + bReturn = false; + } + + if ( mpView && !mpView->IsAction() ) + { + mpWindow->ReleaseMouse(); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + + if ( !mpView->AreObjectsMarked() ) + { + SdrPageView* pPV; + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + + SdrObject* pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV); + if (!pObj) + { + mpView->MarkObj(aPnt, nHitLog); + } + + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + } + else if (rMEvt.IsLeft() && !rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() && + !bSelectionChanged && + std::abs(aPnt.X() - aMDPos.X()) < nDrgLog && + std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) + { + // toggle between selection and rotation + SdrObject* pSingleObj = nullptr; + + if (mpView->GetMarkedObjectList().GetMarkCount()==1) + { + pSingleObj = mpView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + } + + const bool bTiledRendering = comphelper::LibreOfficeKit::isActive(); + if (!bTiledRendering && (mpView->GetDragMode() == SdrDragMode::Move && mpView->IsRotateAllowed() && + (mpViewShell->GetFrameView()->IsClickChangeRotation() || + (pSingleObj && pSingleObj->GetObjInventor()==SdrInventor::E3d)))) + { + mpView->SetDragMode(SdrDragMode::Rotate); + } + else + { + mpView->SetDragMode(SdrDragMode::Move); + } + } + } + + sal_uInt16 nClicks = rMEvt.GetClicks(); + + if (nClicks == 2 && rMEvt.IsLeft() && bMBDown && + !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift() ) + { + DoubleClick(rMEvt); + } + bMBDown = false; + + return bReturn; +} + +void FuConstruct::Activate() +{ + mpView->SetEditMode(SdrViewEditMode::Create); + FuDraw::Activate(); +} + +void FuConstruct::Deactivate() +{ + FuDraw::Deactivate(); + mpView->SetEditMode(SdrViewEditMode::Edit); +} + +/** + * set style sheet for the object to be created + */ +void FuConstruct::SetStyleSheet(SfxItemSet& rAttr, SdrObject* pObj) +{ + bool bUseFillStyle, bUseNoFillStyle; + bUseFillStyle = bUseNoFillStyle = false; + + switch( nSlotId ) + { + case SID_DRAW_RECT: + case SID_DRAW_RECT_ROUND: + case SID_DRAW_SQUARE: + case SID_DRAW_SQUARE_ROUND: + case SID_DRAW_ELLIPSE: + case SID_DRAW_PIE: + case SID_DRAW_ELLIPSECUT: + case SID_DRAW_CIRCLE: + case SID_DRAW_CIRCLEPIE: + case SID_DRAW_CIRCLECUT: + case SID_DRAW_POLYGON: + case SID_DRAW_XPOLYGON: + case SID_DRAW_FREELINE: + case SID_DRAW_BEZIER_FILL: + { + bUseFillStyle = true; + break; + } + case SID_DRAW_RECT_NOFILL: + case SID_DRAW_RECT_ROUND_NOFILL: + case SID_DRAW_SQUARE_NOFILL: + case SID_DRAW_SQUARE_ROUND_NOFILL: + case SID_DRAW_ELLIPSE_NOFILL: + case SID_DRAW_PIE_NOFILL: + case SID_DRAW_ELLIPSECUT_NOFILL: + case SID_DRAW_CIRCLE_NOFILL: + case SID_DRAW_CIRCLEPIE_NOFILL: + case SID_DRAW_CIRCLECUT_NOFILL: + case SID_DRAW_POLYGON_NOFILL: + case SID_DRAW_XPOLYGON_NOFILL: + case SID_DRAW_FREELINE_NOFILL: + case SID_DRAW_LINE: + case SID_DRAW_XLINE: + case SID_CONNECTOR_ARROW_START: + case SID_CONNECTOR_ARROW_END: + case SID_CONNECTOR_ARROWS: + case SID_CONNECTOR_CIRCLE_START: + case SID_CONNECTOR_CIRCLE_END: + case SID_CONNECTOR_CIRCLES: + case SID_CONNECTOR_LINE: + case SID_CONNECTOR_LINE_ARROW_START: + case SID_CONNECTOR_LINE_ARROW_END: + case SID_CONNECTOR_LINE_ARROWS: + case SID_CONNECTOR_LINE_CIRCLE_START: + case SID_CONNECTOR_LINE_CIRCLE_END: + case SID_CONNECTOR_LINE_CIRCLES: + case SID_CONNECTOR_CURVE: + case SID_CONNECTOR_CURVE_ARROW_START: + case SID_CONNECTOR_CURVE_ARROW_END: + case SID_CONNECTOR_CURVE_ARROWS: + case SID_CONNECTOR_CURVE_CIRCLE_START: + case SID_CONNECTOR_CURVE_CIRCLE_END: + case SID_CONNECTOR_CURVE_CIRCLES: + case SID_CONNECTOR_LINES: + case SID_CONNECTOR_LINES_ARROW_START: + case SID_CONNECTOR_LINES_ARROW_END: + case SID_CONNECTOR_LINES_ARROWS: + case SID_CONNECTOR_LINES_CIRCLE_START: + case SID_CONNECTOR_LINES_CIRCLE_END: + case SID_CONNECTOR_LINES_CIRCLES: + case SID_DRAW_BEZIER_NOFILL: + case SID_LINE_ARROW_END: + { + bUseNoFillStyle = true; + break; + } + } + SetStyleSheet( rAttr, pObj, bUseFillStyle, bUseNoFillStyle ); +} + +void FuConstruct::SetStyleSheet( SfxItemSet& rAttr, SdrObject* pObj, + const bool bForceFillStyle, const bool bForceNoFillStyle ) +{ + SdPage* pPage = static_cast<SdPage*>(mpView->GetSdrPageView()->GetPage()); + if ( pPage->IsMasterPage() && pPage->GetPageKind() == PageKind::Standard && + mpDoc->GetDocumentType() == DocumentType::Impress ) + { + /********************************************** + * Objects was created on the slide master page + ***********************************************/ + OUString aName( pPage->GetLayoutName() ); + sal_Int32 n = aName.indexOf(SD_LT_SEPARATOR) + SD_LT_SEPARATOR.getLength(); + aName = OUString::Concat(aName.subView(0, n)) + STR_LAYOUT_BACKGROUNDOBJECTS; + SfxStyleSheet* pSheet( + static_cast< SfxStyleSheet* >( + pPage->getSdrModelFromSdrPage().GetStyleSheetPool()->Find(aName, SfxStyleFamily::Page))); + DBG_ASSERT(pSheet, "StyleSheet missing"); + if (pSheet) + { + // applying style sheet for background objects + pObj->SetStyleSheet(pSheet, false); + SfxItemSet& rSet = pSheet->GetItemSet(); + const XFillStyleItem& rFillStyle = rSet.Get(XATTR_FILLSTYLE); + if ( bForceFillStyle ) + { + if (rFillStyle.GetValue() == drawing::FillStyle_NONE) + rAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID)); + } + else if ( bForceNoFillStyle ) + { + if (rFillStyle.GetValue() != drawing::FillStyle_NONE) + rAttr.Put(XFillStyleItem(drawing::FillStyle_NONE)); + } + } + } + else + { + /*********************************** + * object was created on normal page + ************************************/ + if ( bForceNoFillStyle ) + { + OUString aName(SdResId(STR_POOLSHEET_OBJWITHOUTFILL)); + SfxStyleSheet* pSheet( + static_cast< SfxStyleSheet* >( + pPage->getSdrModelFromSdrPage().GetStyleSheetPool()->Find(aName, SfxStyleFamily::Para))); + DBG_ASSERT(pSheet, "Stylesheet missing"); + if (pSheet) + { + pObj->SetStyleSheet(pSheet, false); + SfxItemSet aAttr(mpView->GetDefaultAttr()); + aAttr.Put(pSheet->GetItemSet().Get(XATTR_FILLSTYLE)); + pObj->SetMergedItemSet(aAttr); + } + else + { + SfxItemSet aAttr(mpView->GetDefaultAttr()); + rAttr.Put(XFillStyleItem(drawing::FillStyle_NONE)); + pObj->SetMergedItemSet(aAttr); + } + } + else + { + // Creating an object with fill. + SdrPage* pThemePage = pPage; + if (pThemePage->TRG_HasMasterPage()) + { + pThemePage = &pThemePage->TRG_GetMasterPage(); + } + + svx::Theme* pTheme = pThemePage->getSdrPageProperties().GetTheme(); + if (pTheme) + { + // We construct an object on a page where the master page has a theme. Take the + // accent1 color from that theme, make sure it has priority over the shape's + // document-global style. + SfxItemSet aAttr(mpView->GetDefaultAttr()); + + aAttr.Put(XFillStyleItem(css::drawing::FillStyle_SOLID)); + + svx::ThemeColorType eColorType = svx::ThemeColorType::ACCENT1; + Color aColor = pTheme->GetColor(eColorType); + XFillColorItem aFillColorItem("", aColor); + aFillColorItem.GetThemeColor().SetThemeIndex(static_cast<sal_Int16>(eColorType)); + aAttr.Put(aFillColorItem); + + aAttr.Put(XLineStyleItem(css::drawing::LineStyle_SOLID)); + + // Line color is 50% darker than the fill color. + aColor.ApplyTintOrShade(-5000); + XLineColorItem aLineColorItem("", aColor); + // TODO no theme or theme effect for line colors yet. + aAttr.Put(aLineColorItem); + + pObj->SetMergedItemSet(aAttr); + } + } + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuconuno.cxx b/sd/source/ui/func/fuconuno.cxx new file mode 100644 index 000000000..afa4523c6 --- /dev/null +++ b/sd/source/ui/func/fuconuno.cxx @@ -0,0 +1,150 @@ +/* -*- 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 <fuconuno.hxx> +#include <rtl/ustring.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/request.hxx> +#include <svl/intitem.hxx> +#include <svx/svxids.hrc> +#include <vcl/ptrstyle.hxx> + +#include <ViewShell.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <ViewShellBase.hxx> +#include <ToolBarManager.hxx> +#include <unokywds.hxx> + + +namespace sd { + + +FuConstructUnoControl::FuConstructUnoControl ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuConstruct(pViewSh, pWin, pView, pDoc, rReq) + , nInventor(SdrInventor::Unknown) + , nIdentifier(SdrObjKind::NONE) +{ +} + +rtl::Reference<FuPoor> FuConstructUnoControl::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent ) +{ + FuConstructUnoControl* pFunc; + rtl::Reference<FuPoor> xFunc( pFunc = new FuConstructUnoControl( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + pFunc->SetPermanent(bPermanent); + return xFunc; +} + +void FuConstructUnoControl::DoExecute( SfxRequest& rReq ) +{ + FuConstruct::DoExecute( rReq ); + + const SfxUInt32Item* pInventorItem = rReq.GetArg<SfxUInt32Item>(SID_FM_CONTROL_INVENTOR); + const SfxUInt16Item* pIdentifierItem = rReq.GetArg<SfxUInt16Item>(SID_FM_CONTROL_IDENTIFIER); + if( pInventorItem ) + nInventor = static_cast<SdrInventor>(pInventorItem->GetValue()); + if( pIdentifierItem ) + nIdentifier = static_cast<SdrObjKind>(pIdentifierItem->GetValue()); + + mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBar( + ToolBarManager::ToolBarGroup::Function, + ToolBarManager::msDrawingObjectToolBar); +} + +bool FuConstructUnoControl::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = FuConstruct::MouseButtonDown(rMEvt); + + if ( rMEvt.IsLeft() && !mpView->IsAction() ) + { + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + mpWindow->CaptureMouse(); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + mpView->BegCreateObj(aPnt, nullptr, nDrgLog); + bReturn = true; + } + return bReturn; +} + +bool FuConstructUnoControl::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = false; + + if ( mpView->IsCreateObj() && rMEvt.IsLeft() ) + { + mpView->EndCreateObj(SdrCreateCmd::ForceEnd); + bReturn = true; + } + + bReturn = (FuConstruct::MouseButtonUp(rMEvt) || bReturn); + + if (!bPermanent) + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + + return bReturn; +} + +void FuConstructUnoControl::Activate() +{ + mpView->SetCurrentObj( nIdentifier, nInventor ); + + aNewPointer = PointerStyle::DrawRect; + aOldPointer = mpWindow->GetPointer(); + mpWindow->SetPointer( aNewPointer ); + + aOldLayer = mpView->GetActiveLayer(); + mpView->SetActiveLayer(sUNO_LayerName_controls); + + FuConstruct::Activate(); +} + +void FuConstructUnoControl::Deactivate() +{ + FuConstruct::Deactivate(); + mpView->SetActiveLayer( aOldLayer ); + mpWindow->SetPointer( aOldPointer ); +} + +SdrObjectUniquePtr FuConstructUnoControl::CreateDefaultObject(const sal_uInt16, const ::tools::Rectangle& rRectangle) +{ + // case SID_FM_CREATE_CONTROL: + + SdrObjectUniquePtr pObj(SdrObjFactory::MakeNewObject( + mpView->getSdrModelFromSdrView(), + mpView->GetCurrentObjInventor(), + mpView->GetCurrentObjIdentifier())); + + if(pObj) + { + pObj->SetLogicRect(rRectangle); + } + + return pObj; +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fucopy.cxx b/sd/source/ui/func/fucopy.cxx new file mode 100644 index 000000000..99e5f7b87 --- /dev/null +++ b/sd/source/ui/func/fucopy.cxx @@ -0,0 +1,288 @@ +/* -*- 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 <fucopy.hxx> +#include <sfx2/progress.hxx> +#include <svl/intitem.hxx> + +#include <sdattr.hrc> +#include <sdresid.hxx> +#include <strings.hrc> +#include <ViewShell.hxx> +#include <View.hxx> +#include <drawdoc.hxx> +#include <DrawDocShell.hxx> +#include <svx/svdobj.hxx> +#include <svx/xcolit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xdef.hxx> +#include <svx/xfillit0.hxx> +#include <svx/sdangitm.hxx> +#include <sfx2/request.hxx> +#include <sdabstdlg.hxx> +#include <memory> + +using namespace com::sun::star; + +namespace sd { + + +FuCopy::FuCopy ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuCopy::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuCopy( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuCopy::DoExecute( SfxRequest& rReq ) +{ + if( !mpView->AreObjectsMarked() ) + return; + + // Undo + OUString aString = mpView->GetDescriptionOfMarkedObjects() + + " " + SdResId( STR_UNDO_COPYOBJECTS ); + mpView->BegUndo( aString ); + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if( !pArgs ) + { + SfxItemSetFixed<ATTR_COPY_START, ATTR_COPY_END> aSet( mpViewShell->GetPool() ); + + // indicate color attribute + SfxItemSet aAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aAttr ); + + if( const XFillStyleItem* pFillStyleItem = aAttr.GetItemIfSet( XATTR_FILLSTYLE ) ) + { + drawing::FillStyle eStyle = pFillStyleItem->GetValue(); + + const XFillColorItem* pFillColorItem; + if( eStyle == drawing::FillStyle_SOLID && + (pFillColorItem = aAttr.GetItemIfSet( XATTR_FILLCOLOR )) ) + { + XColorItem aXColorItem( ATTR_COPY_START_COLOR, pFillColorItem->GetName(), + pFillColorItem->GetColorValue() ); + aSet.Put( aXColorItem ); + + } + } + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractCopyDlg> pDlg(pFact->CreateCopyDlg(mpViewShell->GetFrameWeld(), aSet, mpView )); + + sal_uInt16 nResult = pDlg->Execute(); + + switch( nResult ) + { + case RET_OK: + pDlg->GetAttr( aSet ); + rReq.Done( aSet ); + pArgs = rReq.GetArgs(); + break; + + default: + { + pDlg.disposeAndClear(); + mpView->EndUndo(); + return; // Cancel + } + } + } + + ::tools::Rectangle aRect; + sal_Int32 lWidth = 0, lHeight = 0, lSizeX = 0, lSizeY = 0; + Degree100 lAngle(0); + sal_uInt16 nNumber = 0; + Color aStartColor, aEndColor; + bool bColor = false; + + if (pArgs) + { + // Count + if( const SfxUInt16Item* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_NUMBER ) ) + nNumber = pPoolItem->GetValue(); + + // translation + if( const SfxInt32Item* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_MOVE_X ) ) + lSizeX = pPoolItem->GetValue(); + if( const SfxInt32Item* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_MOVE_Y ) ) + lSizeY = pPoolItem->GetValue(); + if( const SdrAngleItem* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_ANGLE ) ) + lAngle = pPoolItem->GetValue(); + + // scale + if( const SfxInt32Item* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_WIDTH ) ) + lWidth = pPoolItem->GetValue(); + if( const SfxInt32Item* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_HEIGHT ) ) + lHeight = pPoolItem->GetValue(); + + // start/end color + if( const XColorItem* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_START_COLOR ) ) + { + aStartColor = pPoolItem->GetColorValue(); + bColor = true; + } + if( const XColorItem* pPoolItem = pArgs->GetItemIfSet( ATTR_COPY_END_COLOR ) ) + { + aEndColor = pPoolItem->GetColorValue(); + if( aStartColor == aEndColor ) + bColor = false; + } + } + + // remove handles + //HMHmpView->HideMarkHdl(); + + std::unique_ptr<SfxProgress> pProgress; + bool bWaiting = false; + + if( nNumber > 1 ) + { + OUString aStr = SdResId( STR_OBJECTS ) + + " " + SdResId( STR_UNDO_COPYOBJECTS ); + + pProgress.reset(new SfxProgress( mpDocSh, aStr, nNumber )); + mpDocSh->SetWaitCursor( true ); + bWaiting = true; + } + + const SdrMarkList aMarkList( mpView->GetMarkedObjectList() ); + const size_t nMarkCount = aMarkList.GetMarkCount(); + SdrObject* pObj = nullptr; + + // calculate number of possible copies + aRect = mpView->GetAllMarkedRect(); + + if( lWidth < 0 ) + { + ::tools::Long nTmp = ( aRect.Right() - aRect.Left() ) / -lWidth; + nNumber = static_cast<sal_uInt16>(std::min( nTmp, static_cast<::tools::Long>(nNumber) )); + } + + if( lHeight < 0 ) + { + ::tools::Long nTmp = ( aRect.Bottom() - aRect.Top() ) / -lHeight; + nNumber = static_cast<sal_uInt16>(std::min( nTmp, static_cast<::tools::Long>(nNumber) )); + } + + for( sal_uInt16 i = 1; i <= nNumber; i++ ) + { + if( pProgress ) + pProgress->SetState( i ); + + aRect = mpView->GetAllMarkedRect(); + + if( ( 1 == i ) && bColor ) + { + SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLCOLOR> aNewSet( mpViewShell->GetPool() ); + aNewSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); + aNewSet.Put( XFillColorItem( OUString(), aStartColor ) ); + mpView->SetAttributes( aNewSet ); + } + + // make a copy of selected objects + mpView->CopyMarked(); + + // get newly selected objects + SdrMarkList aCopyMarkList( mpView->GetMarkedObjectList() ); + const size_t nCopyMarkCount = aMarkList.GetMarkCount(); + + // set protection flags at marked copies to null + for( size_t j = 0; j < nCopyMarkCount; ++j ) + { + pObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj(); + + if( pObj ) + { + pObj->SetMoveProtect( false ); + pObj->SetResizeProtect( false ); + } + } + + Fraction aWidth( aRect.Right() - aRect.Left() + lWidth, aRect.Right() - aRect.Left() ); + Fraction aHeight( aRect.Bottom() - aRect.Top() + lHeight, aRect.Bottom() - aRect.Top() ); + + if( mpView->IsResizeAllowed() ) + mpView->ResizeAllMarked( aRect.TopLeft(), aWidth, aHeight ); + + if( mpView->IsRotateAllowed() ) + mpView->RotateAllMarked( aRect.Center(), lAngle ); + + if( mpView->IsMoveAllowed() ) + mpView->MoveAllMarked( Size( lSizeX, lSizeY ) ); + + // set protection flags at marked copies to original values + if( nMarkCount == nCopyMarkCount ) + { + for( size_t j = 0; j < nMarkCount; ++j ) + { + SdrObject* pSrcObj = aMarkList.GetMark( j )->GetMarkedSdrObj(); + SdrObject* pDstObj = aCopyMarkList.GetMark( j )->GetMarkedSdrObj(); + + if( pSrcObj && pDstObj && + ( pSrcObj->GetObjInventor() == pDstObj->GetObjInventor() ) && + ( pSrcObj->GetObjIdentifier() == pDstObj->GetObjIdentifier() ) ) + { + pDstObj->SetMoveProtect( pSrcObj->IsMoveProtect() ); + pDstObj->SetResizeProtect( pSrcObj->IsResizeProtect() ); + } + } + } + + if( bColor ) + { + // probably room for optimizations, but may can lead to rounding errors + sal_uInt8 nRed = aStartColor.GetRed() + static_cast<sal_uInt8>( ( static_cast<::tools::Long>(aEndColor.GetRed()) - static_cast<::tools::Long>(aStartColor.GetRed()) ) * static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber) ); + sal_uInt8 nGreen = aStartColor.GetGreen() + static_cast<sal_uInt8>( ( static_cast<::tools::Long>(aEndColor.GetGreen()) - static_cast<::tools::Long>(aStartColor.GetGreen()) ) * static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber) ); + sal_uInt8 nBlue = aStartColor.GetBlue() + static_cast<sal_uInt8>( ( static_cast<::tools::Long>(aEndColor.GetBlue()) - static_cast<::tools::Long>(aStartColor.GetBlue()) ) * static_cast<::tools::Long>(i) / static_cast<::tools::Long>(nNumber) ); + Color aNewColor( nRed, nGreen, nBlue ); + SfxItemSetFixed<XATTR_FILLSTYLE, XATTR_FILLCOLOR> aNewSet( mpViewShell->GetPool() ); + aNewSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); + aNewSet.Put( XFillColorItem( OUString(), aNewColor ) ); + mpView->SetAttributes( aNewSet ); + } + } + + pProgress.reset(); + + if ( bWaiting ) + mpDocSh->SetWaitCursor( false ); + + // show handles + mpView->AdjustMarkHdl(); //HMH sal_True ); + //HMHpView->ShowMarkHdl(); + + mpView->EndUndo(); +} + +} // end of namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fucushow.cxx b/sd/source/ui/func/fucushow.cxx new file mode 100644 index 000000000..eb3b12211 --- /dev/null +++ b/sd/source/ui/func/fucushow.cxx @@ -0,0 +1,91 @@ +/* -*- 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 <fucushow.hxx> + +#include <svx/svxids.hrc> + +#include <ViewShell.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> + +#include <sdabstdlg.hxx> + +namespace sd { + + +FuCustomShowDlg::FuCustomShowDlg ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor( pViewSh, pWin, pView, pDoc, rReq ) +{ +} + +rtl::Reference<FuPoor> FuCustomShowDlg::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuCustomShowDlg( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuCustomShowDlg::DoExecute( SfxRequest& ) +{ + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + vcl::Window* pWin = mpViewShell->GetActiveWindow(); + ScopedVclPtr<AbstractSdCustomShowDlg> pDlg( pFact->CreateSdCustomShowDlg(pWin ? pWin->GetFrameWeld() : nullptr, *mpDoc) ); + sal_uInt16 nRet = pDlg->Execute(); + mpDoc->SetChanged(); + sd::PresentationSettings& rSettings = mpDoc->getPresentationSettings(); + + if( nRet == RET_YES ) + { + // If the custom show is not set by default + if (!rSettings.mbCustomShow) + { + rSettings.mbStartCustomShow = true; + rSettings.mbCustomShow = pDlg->IsCustomShow(); + } + + mpViewShell->SetStartShowWithDialog(true); + + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_PRESENTATION, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); + } + if (nRet == RET_OK) + { + if (mpDoc->GetCustomShowList()) + { + if (!pDlg->IsCustomShow()) + { + rSettings.mbCustomShow = false; + rSettings.mbAll = true; + } + } + } + pDlg.disposeAndClear(); +} + +} // end of namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fudraw.cxx b/sd/source/ui/func/fudraw.cxx new file mode 100644 index 000000000..8beb753f6 --- /dev/null +++ b/sd/source/ui/func/fudraw.cxx @@ -0,0 +1,820 @@ +/* -*- 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 <vcl/svapp.hxx> +#include <vcl/ptrstyle.hxx> +#include <editeng/flditem.hxx> +#include <svx/svdogrp.hxx> +#include <tools/urlobj.hxx> +#include <vcl/help.hxx> +#include <svx/bmpmask.hxx> +#include <svx/svdotext.hxx> +#include <svx/ImageMapInfo.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/sfxhelp.hxx> +#include <svx/svdpagv.hxx> +#include <vcl/imapobj.hxx> +#include <svx/svxids.hrc> +#include <svx/obj3d.hxx> +#include <svx/scene3d.hxx> +#include <sfx2/viewfrm.hxx> + +#include <strings.hrc> + + +#include <sdmod.hxx> +#include <fudraw.hxx> +#include <ViewShell.hxx> +#include <FrameView.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> +#include <DrawDocShell.hxx> +#include <sdresid.hxx> +#include <fusel.hxx> +#include <vcl/weld.hxx> +#include <svx/sdrhittesthelper.hxx> + +using namespace ::com::sun::star; + +namespace sd { + + +/** + * Base-class for all drawmodul-specific functions + */ +FuDraw::FuDraw(ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, + SdDrawDocument* pDoc, SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) + , aNewPointer(PointerStyle::Arrow) + , aOldPointer(PointerStyle::Arrow) + , bMBDown(false) + , bDragHelpLine(false) + , nHelpLine(0) + , bPermanent(false) +{ +} + +FuDraw::~FuDraw() +{ + mpView->BrkAction(); +} + + +/** + * Code shared by MouseButtonDown and MouseMove + */ +void FuDraw::DoModifiers(const MouseEvent& rMEvt, bool bSnapModPressed) +{ + FrameView* pFrameView = mpViewShell->GetFrameView(); + bool bGridSnap = pFrameView->IsGridSnap(); + bGridSnap = (bSnapModPressed != bGridSnap); + + if (mpView->IsGridSnap() != bGridSnap) + mpView->SetGridSnap(bGridSnap); + + bool bBordSnap = pFrameView->IsBordSnap(); + bBordSnap = (bSnapModPressed != bBordSnap); + + if (mpView->IsBordSnap() != bBordSnap) + mpView->SetBordSnap(bBordSnap); + + bool bHlplSnap = pFrameView->IsHlplSnap(); + bHlplSnap = (bSnapModPressed != bHlplSnap); + + if (mpView->IsHlplSnap() != bHlplSnap) + mpView->SetHlplSnap(bHlplSnap); + + bool bOFrmSnap = pFrameView->IsOFrmSnap(); + bOFrmSnap = (bSnapModPressed != bOFrmSnap); + + if (mpView->IsOFrmSnap() != bOFrmSnap) + mpView->SetOFrmSnap(bOFrmSnap); + + bool bOPntSnap = pFrameView->IsOPntSnap(); + bOPntSnap = (bSnapModPressed != bOPntSnap); + + if (mpView->IsOPntSnap() != bOPntSnap) + mpView->SetOPntSnap(bOPntSnap); + + bool bOConSnap = pFrameView->IsOConSnap(); + bOConSnap = (bSnapModPressed != bOConSnap); + + if (mpView->IsOConSnap() != bOConSnap) + mpView->SetOConSnap(bOConSnap); + + bool bAngleSnap = rMEvt.IsShift() == !pFrameView->IsAngleSnapEnabled(); + + if (mpView->IsAngleSnapEnabled() != bAngleSnap) + mpView->SetAngleSnapEnabled(bAngleSnap); + + bool bCenter = rMEvt.IsMod2(); + + if ( mpView->IsCreate1stPointAsCenter() != bCenter || + mpView->IsResizeAtCenter() != bCenter ) + { + mpView->SetCreate1stPointAsCenter(bCenter); + mpView->SetResizeAtCenter(bCenter); + } +} + + +bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt) +{ + // remember button state for creation of own MouseEvents + SetMouseButtonCode(rMEvt.GetButtons()); + + bool bReturn = false; + bDragHelpLine = false; + aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() ); + + if ( rMEvt.IsLeft() ) + { + FrameView* pFrameView = mpViewShell->GetFrameView(); + + bool bOrtho = false; + + bool bRestricted = true; + + if (mpView->IsDragObj()) + { + // object is dragged (move, resize,...) + const SdrHdl* pHdl = mpView->GetDragStat().GetHdl(); + + if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl())) + { + // Move + bRestricted = false; + } + } + + // #i33136# + if(bRestricted && doConstructOrthogonal()) + { + // Restrict movement: + // rectangle->square, ellipse->circle, etc. + bOrtho = !rMEvt.IsShift(); + } + else + { + bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho(); + } + if (!mpView->IsSnapEnabled()) + mpView->SetSnapEnabled(true); + + bool bSnapModPressed = rMEvt.IsMod1(); + if (mpView->IsOrtho() != bOrtho) + mpView->SetOrtho(bOrtho); + + DoModifiers(rMEvt, bSnapModPressed); + + SdrPageView* pPV = nullptr; + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + + // look only for HelpLines when they are visible (!) + bool bHelpLine(false); + if(mpView->IsHlplVisible()) + bHelpLine = mpView->PickHelpLine(aMDPos, nHitLog, *mpWindow->GetOutDev(), nHelpLine, pPV); + bool bHitHdl = (mpView->PickHandle(aMDPos) != nullptr); + + if ( bHelpLine + && !mpView->IsCreateObj() + && ((mpView->GetEditMode() == SdrViewEditMode::Edit && !bHitHdl) || (rMEvt.IsShift() && bSnapModPressed)) ) + { + mpWindow->CaptureMouse(); + mpView->BegDragHelpLine(nHelpLine, pPV); + bDragHelpLine = mpView->IsDragHelpLine(); + bReturn = true; + } + } + ForcePointer(&rMEvt); + + return bReturn; +} + +bool FuDraw::MouseMove(const MouseEvent& rMEvt) +{ + FrameView* pFrameView = mpViewShell->GetFrameView(); + Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() ); + + bool bOrtho = false; + bool bRestricted = true; + + if (mpView->IsDragObj()) + { + // object is dragged (move, resize, ...) + const SdrHdl* pHdl = mpView->GetDragStat().GetHdl(); + + if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl())) + { + // Move + bRestricted = false; + } + } + + if (mpView->IsAction()) + { + // #i33136# and fdo#88339 + if(bRestricted && doConstructOrthogonal()) + { + // Scale proportionally by default: + // rectangle->square, ellipse->circle, images, etc. + bOrtho = !rMEvt.IsShift(); + } + else + { + bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho(); + } + + bool bSnapModPressed = rMEvt.IsMod2(); + mpView->SetDragWithCopy(rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); + + if (mpView->IsOrtho() != bOrtho) + mpView->SetOrtho(bOrtho); + DoModifiers(rMEvt, bSnapModPressed); + + + if ( mpView->IsDragHelpLine() ) + mpView->MovDragHelpLine(aPos); + } + + bool bReturn = mpView->MouseMove(rMEvt, mpWindow->GetOutDev()); + + if (mpView->IsAction()) + { + // Because the flag set back if necessary in MouseMove + if (mpView->IsOrtho() != bOrtho) + mpView->SetOrtho(bOrtho); + } + + ForcePointer(&rMEvt); + + return bReturn; +} + +bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt) +{ + if (mpView && mpView->IsDragHelpLine()) + mpView->EndDragHelpLine(); + + if ( bDragHelpLine ) + { + ::tools::Rectangle aOutputArea(Point(0,0), mpWindow->GetOutputSizePixel()); + + if (mpView && !aOutputArea.Contains(rMEvt.GetPosPixel())) + mpView->GetSdrPageView()->DeleteHelpLine(nHelpLine); + + mpWindow->ReleaseMouse(); + } + + if (mpView) + { + FrameView* pFrameView = mpViewShell->GetFrameView(); + mpView->SetOrtho( pFrameView->IsOrtho() ); + mpView->SetAngleSnapEnabled( pFrameView->IsAngleSnapEnabled() ); + mpView->SetSnapEnabled(true); + mpView->SetCreate1stPointAsCenter(false); + mpView->SetResizeAtCenter(false); + mpView->SetDragWithCopy(pFrameView->IsDragWithCopy()); + mpView->SetGridSnap(pFrameView->IsGridSnap()); + mpView->SetBordSnap(pFrameView->IsBordSnap()); + mpView->SetHlplSnap(pFrameView->IsHlplSnap()); + mpView->SetOFrmSnap(pFrameView->IsOFrmSnap()); + mpView->SetOPntSnap(pFrameView->IsOPntSnap()); + mpView->SetOConSnap(pFrameView->IsOConSnap()); + } + + bIsInDragMode = false; + ForcePointer(&rMEvt); + FuPoor::MouseButtonUp(rMEvt); + + return false; +} + +/** + * Process keyboard input + * @returns sal_True if a KeyEvent is being processed, sal_False otherwise + */ +bool FuDraw::KeyInput(const KeyEvent& rKEvt) +{ + bool bReturn = false; + + switch ( rKEvt.GetKeyCode().GetCode() ) + { + case KEY_ESCAPE: + { + bReturn = FuDraw::cancel(); + } + break; + + case KEY_DELETE: + case KEY_BACKSPACE: + { + if (!mpDocSh->IsReadOnly()) + { + if (mpView->IsPresObjSelected(false, true, false, true)) + { + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(), + VclMessageType::Info, VclButtonsType::Ok, + SdResId(STR_ACTION_NOTPOSSIBLE))); + xInfoBox->run(); + } + else + { + // wait-mousepointer while deleting object + weld::WaitObject aWait(mpViewShell->GetFrameWeld()); + // delete object + mpView->DeleteMarked(); + } + } + bReturn = true; + } + break; + + case KEY_TAB: + { + vcl::KeyCode aCode = rKEvt.GetKeyCode(); + + if ( !aCode.IsMod1() && !aCode.IsMod2() ) + { + // Moved next line which was a bugfix itself into + // the scope which really does the object selection travel + // and thus is allowed to call SelectionHasChanged(). + + // Switch to FuSelect. + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( + SID_OBJECT_SELECT, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + + // changeover to the next object + if(!mpView->MarkNextObj( !aCode.IsShift() )) + { + //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj(). + if ( mpView->HasMultipleMarkableObjects() && mpView->AreObjectsMarked() ) + { + // No next object: go over open end and get first from + // the other side + mpView->UnmarkAllObj(); + mpView->MarkNextObj(!aCode.IsShift()); + } + } + + if(mpView->AreObjectsMarked()) + mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow); + + bReturn = true; + } + } + break; + + case KEY_END: + { + vcl::KeyCode aCode = rKEvt.GetKeyCode(); + + if ( aCode.IsMod1() ) + { + // mark last object + mpView->UnmarkAllObj(); + mpView->MarkNextObj(); + + if(mpView->AreObjectsMarked()) + mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow); + + bReturn = true; + } + } + break; + + case KEY_HOME: + { + vcl::KeyCode aCode = rKEvt.GetKeyCode(); + + if ( aCode.IsMod1() ) + { + // mark first object + mpView->UnmarkAllObj(); + mpView->MarkNextObj(true); + + if(mpView->AreObjectsMarked()) + mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow); + + bReturn = true; + } + } + break; + + default: + break; + } + + if (!bReturn) + { + bReturn = FuPoor::KeyInput(rKEvt); + } + else + { + mpWindow->ReleaseMouse(); + } + + return bReturn; +} + +void FuDraw::Activate() +{ + FuPoor::Activate(); + ForcePointer(); +} + +/** + * Toggle mouse-pointer + */ +void FuDraw::ForcePointer(const MouseEvent* pMEvt) +{ + Point aPnt; + sal_uInt16 nModifier = 0; + bool bLeftDown = false; + bool bDefPointer = true; + + if (pMEvt) + { + aPnt = mpWindow->PixelToLogic(pMEvt->GetPosPixel()); + nModifier = pMEvt->GetModifier(); + bLeftDown = pMEvt->IsLeft(); + } + else + { + aPnt = mpWindow->PixelToLogic(mpWindow->GetPointerPosPixel()); + } + + if (mpView->IsDragObj()) + { + if (SD_MOD()->GetWaterCan() && !mpView->PickHandle(aPnt)) + { + // water can mode + bDefPointer = false; + mpWindow->SetPointer(PointerStyle::Fill); + } + } + else + { + SdrHdl* pHdl = mpView->PickHandle(aPnt); + + if (SD_MOD()->GetWaterCan() && !pHdl) + { + // water can mode + bDefPointer = false; + mpWindow->SetPointer(PointerStyle::Fill); + } + else if (!pHdl && + mpViewShell->GetViewFrame()->HasChildWindow(SvxBmpMaskChildWindow::GetChildWindowId())) + { + // pipette mode + SfxChildWindow* pWnd = mpViewShell->GetViewFrame()->GetChildWindow(SvxBmpMaskChildWindow::GetChildWindowId()); + SvxBmpMask* pMask = pWnd ? static_cast<SvxBmpMask*>(pWnd->GetWindow()) : nullptr; + if (pMask && pMask->IsEyedropping()) + { + bDefPointer = false; + mpWindow->SetPointer(PointerStyle::RefHand); + } + } + else if (!mpView->IsAction()) + { + SdrObject* pObj = nullptr; + SdrPageView* pPV = nullptr; + SdrViewEvent aVEvt; + SdrHitKind eHit = SdrHitKind::NONE; + SdrDragMode eDragMode = mpView->GetDragMode(); + + if (pMEvt) + { + eHit = mpView->PickAnything(*pMEvt, SdrMouseEventKind::MOVE, aVEvt); + } + + if ((eDragMode == SdrDragMode::Rotate) && (eHit == SdrHitKind::MarkedObject)) + { + // The goal of this request is show always the rotation arrow for 3D-objects at rotation mode + // Independent of the settings at Tools->Options->Draw "Objects always moveable" + // 2D-objects acquit in another way. Otherwise, the rotation of 3d-objects around any axes + // wouldn't be possible per default. + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + SdrObject* pObject = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if ((dynamic_cast<const E3dObject* >(pObject) != nullptr) && (rMarkList.GetMarkCount() == 1)) + { + mpWindow->SetPointer(PointerStyle::Rotate); + bDefPointer = false; // Otherwise it'll be called Joe's routine and the mousepointer will reconfigurate again + } + } + + if (eHit == SdrHitKind::NONE) + { + // found nothing -> look after at the masterpage + pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER); + } + else if (eHit == SdrHitKind::UnmarkedObject) + { + pObj = aVEvt.mpObj; + } + else if (eHit == SdrHitKind::TextEditObj && dynamic_cast< const FuSelection *>( this ) != nullptr) + { + SdrObjKind nSdrObjKind = aVEvt.mpObj->GetObjIdentifier(); + + if ( nSdrObjKind != SdrObjKind::Text && + nSdrObjKind != SdrObjKind::TitleText && + nSdrObjKind != SdrObjKind::OutlineText && + aVEvt.mpObj->IsEmptyPresObj() ) + { + pObj = nullptr; + bDefPointer = false; + mpWindow->SetPointer(PointerStyle::Arrow); + } + } + + if (pObj && pMEvt && !pMEvt->IsMod2() + && dynamic_cast<const FuSelection*>(this) != nullptr) + { + // test for ImageMap + bDefPointer = !SetPointer(pObj, aPnt); + + if (bDefPointer + && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr + || dynamic_cast<const E3dScene*>(pObj) != nullptr)) + { + // take a glance into the group + pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, + SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP); + if (pObj) + bDefPointer = !SetPointer(pObj, aPnt); + } + } + } + } + + if (bDefPointer) + { + mpWindow->SetPointer(mpView->GetPreferredPointer( + aPnt, mpWindow->GetOutDev(), nModifier, bLeftDown)); + } +} + +/** + * Set cursor to pointer when in clickable area of an ImageMap + * + * @return True when pointer was set + */ +bool FuDraw::SetPointer(const SdrObject* pObj, const Point& rPos) +{ + bool bImageMapInfo = SvxIMapInfo::GetIMapInfo(pObj) != nullptr; + + if (!bImageMapInfo) + return false; + + const SdrLayerIDSet* pVisiLayer = &mpView->GetSdrPageView()->GetVisibleLayers(); + sal_uInt16 nHitLog(sal_uInt16(mpWindow->PixelToLogic(Size(HITPIX, 0)).Width())); + ::tools::Long n2HitLog(nHitLog * 2); + Point aHitPosR(rPos); + Point aHitPosL(rPos); + Point aHitPosT(rPos); + Point aHitPosB(rPos); + + aHitPosR.AdjustX(n2HitLog); + aHitPosL.AdjustX(-n2HitLog); + aHitPosT.AdjustY(n2HitLog); + aHitPosB.AdjustY(-n2HitLog); + + if (!pObj->IsClosedObj() + || (SdrObjectPrimitiveHit(*pObj, aHitPosR, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, + false) + && SdrObjectPrimitiveHit(*pObj, aHitPosL, nHitLog, *mpView->GetSdrPageView(), + pVisiLayer, false) + && SdrObjectPrimitiveHit(*pObj, aHitPosT, nHitLog, *mpView->GetSdrPageView(), + pVisiLayer, false) + && SdrObjectPrimitiveHit(*pObj, aHitPosB, nHitLog, *mpView->GetSdrPageView(), + pVisiLayer, false))) + { + // hit inside the object (without margin) or open object + if (SvxIMapInfo::GetHitIMapObject(pObj, rPos)) + { + mpWindow->SetPointer(PointerStyle::RefHand); + return true; + } + } + + return false; +} + +/** + * Response of doubleclick + */ +void FuDraw::DoubleClick(const MouseEvent& rMEvt) +{ + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + + if ( mpView->AreObjectsMarked() ) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if (rMarkList.GetMarkCount() == 1) + { + SdrMark* pMark = rMarkList.GetMark(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + + SdrInventor nInv = pObj->GetObjInventor(); + SdrObjKind nSdrObjKind = pObj->GetObjIdentifier(); + + if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::OLE2) + { + // activate OLE-object + SfxInt16Item aItem(SID_OBJECT, 0); + mpViewShell->GetViewFrame()-> + GetDispatcher()->ExecuteList(SID_OBJECT, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aItem }); + } + else if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::Graphic && pObj->IsEmptyPresObj() ) + { + mpViewShell->GetViewFrame()-> + GetDispatcher()->Execute( SID_INSERT_GRAPHIC, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); + } + else if ( ( dynamic_cast< const SdrTextObj *>( pObj ) != nullptr || dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr ) && + !SD_MOD()->GetWaterCan() && + mpViewShell->GetFrameView()->IsDoubleClickTextEdit() && + !mpDocSh->IsReadOnly()) + { + SfxUInt16Item aItem(SID_TEXTEDIT, 2); + mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_TEXTEDIT, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aItem }); + } + else if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::Group) + { + // hit group -> select subobject + mpView->UnMarkAll(); + mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift(), true); + } + } + } + else + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); +} + +bool FuDraw::RequestHelp(const HelpEvent& rHEvt) +{ + bool bReturn = false; + + if (Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled()) + { + SdrViewEvent aVEvt; + + MouseEvent aMEvt(mpWindow->GetPointerPosPixel(), 1, MouseEventModifiers::NONE, MOUSE_LEFT); + + SdrHitKind eHit = mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + SdrObject* pObj = aVEvt.mpObj; + + if (eHit != SdrHitKind::NONE && pObj != nullptr) + { + Point aPosPixel = rHEvt.GetMousePosPixel(); + + bReturn = SetHelpText(pObj, aPosPixel, aVEvt); + + if (!bReturn && (dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr || dynamic_cast< const E3dScene* >(pObj) != nullptr)) + { + // take a glance into the group + SdrPageView* pPV = nullptr; + + Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(aPosPixel))); + + pObj = mpView->PickObj(aPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP); + if (pObj) + bReturn = SetHelpText(pObj, aPosPixel, aVEvt); + } + } + } + + if (!bReturn) + { + bReturn = FuPoor::RequestHelp(rHEvt); + } + + if (!bReturn) + bReturn = mpView->RequestHelp(rHEvt); + + return bReturn; +} + +bool FuDraw::SetHelpText(const SdrObject* pObj, const Point& rPosPixel, const SdrViewEvent& rVEvt) +{ + OUString aHelpText; + Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(rPosPixel))); + IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(pObj, aPos); + + if (!rVEvt.mpURLField && !pIMapObj) + return false; + + OUString aURL; + if (rVEvt.mpURLField) + aURL = INetURLObject::decode(rVEvt.mpURLField->GetURL(), + INetURLObject::DecodeMechanism::WithCharset); + else if (pIMapObj) + { + aURL = pIMapObj->GetAltText() + + " (" + + INetURLObject::decode(pIMapObj->GetURL(), + INetURLObject::DecodeMechanism::WithCharset) + + ")"; + } + else + return false; + + aHelpText = SfxHelp::GetURLHelpText(aURL); + + if (aHelpText.isEmpty()) + return false; + + ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(pObj->GetLogicRect()); + ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()), + mpWindow->OutputToScreenPixel(aLogicPix.BottomRight())); + + if (Help::IsBalloonHelpEnabled()) + Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rPosPixel, aScreenRect, aHelpText); + else if (Help::IsQuickHelpEnabled()) + Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText); + + return true; +} + +/** is called when the current function should be aborted. <p> + This is used when a function gets a KEY_ESCAPE but can also + be called directly. + + @returns true if an active function was aborted +*/ +bool FuDraw::cancel() +{ + bool bReturn = false; + + if ( mpView->IsAction() ) + { + mpView->BrkAction(); + bReturn = true; + } + else if ( mpView->IsTextEdit() ) + { + mpView->SdrEndTextEdit(); + bReturn = true; + + SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings(); + rBindings.Invalidate( SID_DEC_INDENT ); + rBindings.Invalidate( SID_INC_INDENT ); + rBindings.Invalidate( SID_PARASPACE_INCREASE ); + rBindings.Invalidate( SID_PARASPACE_DECREASE ); + } + else if ( mpView->AreObjectsMarked() ) + { + const SdrHdlList& rHdlList = mpView->GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + + if(pHdl) + { + const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl(); + } + else + { + mpView->UnmarkAll(); + } + + // Switch to FuSelect. + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( + SID_OBJECT_SELECT, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + + bReturn = true; + } + + return bReturn; +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fudspord.cxx b/sd/source/ui/func/fudspord.cxx new file mode 100644 index 000000000..f129c523c --- /dev/null +++ b/sd/source/ui/func/fudspord.cxx @@ -0,0 +1,131 @@ +/* -*- 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 <fudspord.hxx> + +#include <vcl/ptrstyle.hxx> + +#include <app.hrc> +#include <fupoor.hxx> +#include <ViewShell.hxx> +#include <View.hxx> +#include <Window.hxx> + +namespace sd { + + +FuDisplayOrder::FuDisplayOrder( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq) +: FuPoor(pViewSh, pWin, pView, pDoc, rReq) +, maPtr(PointerStyle::Arrow) +, mpRefObj(nullptr) +{ +} + +FuDisplayOrder::~FuDisplayOrder() +{ +} + +void FuDisplayOrder::implClearOverlay() +{ + mpOverlay.reset(); +} + +rtl::Reference<FuPoor> FuDisplayOrder::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuDisplayOrder( pViewSh, pWin, pView, pDoc, rReq ) ); + return xFunc; +} + +bool FuDisplayOrder::MouseButtonDown(const MouseEvent& rMEvt) +{ + // remember button state for creation of own MouseEvents + SetMouseButtonCode(rMEvt.GetButtons()); + + return true; +} + +bool FuDisplayOrder::MouseMove(const MouseEvent& rMEvt) +{ + SdrPageView* pPV; + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + + SdrObject* pPickObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV); + if (pPickObj) + { + if (mpRefObj != pPickObj) + { + // delete current overlay + implClearOverlay(); + + // create new one + mpOverlay.reset( new SdrDropMarkerOverlay(*mpView, *pPickObj) ); + + // remember referenced object + mpRefObj = pPickObj; + } + } + else + { + mpRefObj = nullptr; + implClearOverlay(); + } + + return true; +} + +bool FuDisplayOrder::MouseButtonUp(const MouseEvent& rMEvt) +{ + // remember button state for creation of own MouseEvents + SetMouseButtonCode(rMEvt.GetButtons()); + + SdrPageView* pPV = nullptr; + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + + mpRefObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV); + if (mpRefObj) + { + if (nSlotId == SID_BEFORE_OBJ) + { + mpView->PutMarkedInFrontOfObj(mpRefObj); + } + else + { + mpView->PutMarkedBehindObj(mpRefObj); + } + } + + mpViewShell->Cancel(); + + return true; +} + +void FuDisplayOrder::Activate() +{ + maPtr = mpWindow->GetPointer(); + mpWindow->SetPointer( PointerStyle::RefHand ); +} + +void FuDisplayOrder::Deactivate() +{ + mpWindow->SetPointer( maPtr ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuediglu.cxx b/sd/source/ui/func/fuediglu.cxx new file mode 100644 index 000000000..5d9d61447 --- /dev/null +++ b/sd/source/ui/func/fuediglu.cxx @@ -0,0 +1,471 @@ +/* -*- 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 <fuediglu.hxx> +#include <svl/eitem.hxx> +#include <svx/svdglue.hxx> +#include <sfx2/request.hxx> + +#include <app.hrc> + +#include <Window.hxx> +#include <View.hxx> +#include <ViewShell.hxx> +#include <ViewShellBase.hxx> +#include <ToolBarManager.hxx> + +namespace sd { + + +FuEditGluePoints::FuEditGluePoints ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuDraw(pViewSh, pWin, pView, pDoc, rReq) + //Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point, + //and SHIFT+ENTER key to decide the position and draw the new insert point + ,bBeginInsertPoint(false), + oldPoint(0,0) +{ +} + +rtl::Reference<FuPoor> FuEditGluePoints::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent ) +{ + FuEditGluePoints* pFunc; + rtl::Reference<FuPoor> xFunc( pFunc = new FuEditGluePoints( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + pFunc->SetPermanent( bPermanent ); + return xFunc; +} + +void FuEditGluePoints::DoExecute( SfxRequest& rReq ) +{ + FuDraw::DoExecute( rReq ); + mpView->SetInsGluePointMode(false); + mpViewShell->GetViewShellBase().GetToolBarManager()->AddToolBar( + ToolBarManager::ToolBarGroup::Function, + ToolBarManager::msGluePointsToolBar); +} + +FuEditGluePoints::~FuEditGluePoints() +{ + mpView->BrkAction(); + mpView->UnmarkAllGluePoints(); + mpView->SetInsGluePointMode(false); +} + +bool FuEditGluePoints::MouseButtonDown(const MouseEvent& rMEvt) +{ + mpView->SetActualWin( mpWindow->GetOutDev() ); + + bool bReturn = FuDraw::MouseButtonDown(rMEvt); + + if (mpView->IsAction()) + { + if (rMEvt.IsRight()) + mpView->BckAction(); + + return true; + } + + if (rMEvt.IsLeft()) + { + bReturn = true; + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + mpWindow->CaptureMouse(); + + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::Handle) + { + // drag handle + SdrHdl* pHdl = aVEvt.mpHdl; + + if (mpView->IsGluePointMarked(aVEvt.mpObj, aVEvt.mnGlueId) && rMEvt.IsShift()) + { + mpView->UnmarkGluePoint(aVEvt.mpObj, aVEvt.mnGlueId); + pHdl = nullptr; + } + + if (pHdl) + { + // drag handle + mpView->BegDragObj(aMDPos, nullptr, aVEvt.mpHdl, nDrgLog); + } + } + else if (eHit == SdrHitKind::MarkedObject && mpView->IsInsGluePointMode()) + { + // insert gluepoints + mpView->BegInsGluePoint(aMDPos); + } + else if (eHit == SdrHitKind::MarkedObject && rMEvt.IsMod1()) + { + // select gluepoints + if (!rMEvt.IsShift()) + mpView->UnmarkAllGluePoints(); + + mpView->BegMarkGluePoints(aMDPos); + } + else if (eHit == SdrHitKind::MarkedObject && !rMEvt.IsShift() && !rMEvt.IsMod2()) + { + // move object + mpView->BegDragObj(aMDPos, nullptr, nullptr, nDrgLog); + } + else if (eHit == SdrHitKind::Gluepoint) + { + // select gluepoints + if (!rMEvt.IsShift()) + mpView->UnmarkAllGluePoints(); + + mpView->MarkGluePoint(aVEvt.mpObj, aVEvt.mnGlueId, false); + SdrHdl* pHdl = mpView->GetGluePointHdl(aVEvt.mpObj, aVEvt.mnGlueId); + + if (pHdl) + { + mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); + } + } + else + { + // select or drag object + if (!rMEvt.IsShift() && !rMEvt.IsMod2() && eHit == SdrHitKind::UnmarkedObject) + { + mpView->UnmarkAllObj(); + } + + bool bMarked = false; + + if (!rMEvt.IsMod1()) + { + if (rMEvt.IsMod2()) + { + bMarked = mpView->MarkNextObj(aMDPos, nHitLog, rMEvt.IsShift()); + } + else + { + bMarked = mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift()); + } + } + + if (bMarked && + (!rMEvt.IsShift() || eHit == SdrHitKind::MarkedObject)) + { + // move object + mpView->BegDragObj(aMDPos, nullptr, aVEvt.mpHdl, nDrgLog); + } + else if (mpView->AreObjectsMarked()) + { + // select gluepoint + if (!rMEvt.IsShift()) + mpView->UnmarkAllGluePoints(); + + mpView->BegMarkGluePoints(aMDPos); + } + else + { + // select object + mpView->BegMarkObj(aMDPos); + } + } + + ForcePointer(&rMEvt); + } + + return bReturn; +} + +bool FuEditGluePoints::MouseMove(const MouseEvent& rMEvt) +{ + mpView->SetActualWin( mpWindow->GetOutDev() ); + + FuDraw::MouseMove(rMEvt); + + if (mpView->IsAction()) + { + Point aPix(rMEvt.GetPosPixel()); + Point aPnt( mpWindow->PixelToLogic(aPix) ); + ForceScroll(aPix); + mpView->MovAction(aPnt); + } + + ForcePointer(&rMEvt); + + return true; +} + +bool FuEditGluePoints::MouseButtonUp(const MouseEvent& rMEvt) +{ + mpView->SetActualWin( mpWindow->GetOutDev() ); + + bool bReturn = false; + + if (mpView->IsAction()) + { + bReturn = true; + mpView->EndAction(); + } + + FuDraw::MouseButtonUp(rMEvt); + + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() ); + + if (std::abs(aMDPos.X() - aPos.X()) < nDrgLog && + std::abs(aMDPos.Y() - aPos.Y()) < nDrgLog && + !rMEvt.IsShift() && !rMEvt.IsMod2()) + { + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::NONE) + { + // click on position: deselect + mpView->UnmarkAllObj(); + } + } + + mpWindow->ReleaseMouse(); + + return bReturn; +} + +/** + * Process keyboard input + * @returns sal_True if a KeyEvent is being processed, sal_False otherwise + */ +bool FuEditGluePoints::KeyInput(const KeyEvent& rKEvt) +{ + mpView->SetActualWin( mpWindow->GetOutDev() ); + + //Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point, + //and SHIFT+ENTER key to decide the position and draw the new insert point + + bool bReturn = false; + + switch (rKEvt.GetKeyCode().GetCode()) + { + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + { + if(rKEvt.GetKeyCode().IsShift()&& mpView->IsInsGluePointMode() ){ + ::tools::Long nX = 0; + ::tools::Long nY = 0; + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + if (nCode == KEY_UP) + { + // scroll up + nX = 0; + nY =-1; + } + else if (nCode == KEY_DOWN) + { + // scroll down + nX = 0; + nY = 1; + } + else if (nCode == KEY_LEFT) + { + // scroll left + nX =-1; + nY = 0; + } + else if (nCode == KEY_RIGHT) + { + // scroll right + nX = 1; + nY = 0; + } + Point centerPoint; + ::tools::Rectangle rect = mpView->GetMarkedObjRect(); + centerPoint = mpWindow->LogicToPixel(rect.Center()); + Point aPoint = bBeginInsertPoint? oldPoint:centerPoint; + Point ePoint = aPoint + Point(nX,nY); + mpWindow->SetPointerPosPixel(ePoint); + //simulate mouse move action + MouseEvent eMevt(ePoint, 1, MouseEventModifiers::DRAGMOVE, MOUSE_LEFT, 0); + MouseMove(eMevt); + oldPoint = ePoint; + bBeginInsertPoint = true; + bReturn = true; + } + } + break; + case KEY_RETURN: + if(rKEvt.GetKeyCode().IsShift() && mpView->IsInsGluePointMode() ) + { + if(bBeginInsertPoint) + { + mpWindow->SetPointerPosPixel(oldPoint); + //simulate mouse button down action + MouseEvent aMevt(oldPoint, 1, + MouseEventModifiers::SIMPLEMOVE | MouseEventModifiers::DRAGMOVE, + MOUSE_LEFT, KEY_SHIFT); + // MT IA2: Not used? + // sal_uInt16 ubuttons = aMevt.GetButtons(); + // sal_uInt16 uMod = aMevt.GetModifier(); + MouseButtonDown(aMevt); + mpWindow->CaptureMouse(); + //simulate mouse button up action + MouseEvent rMEvt(oldPoint+Point(0,0), 1, + MouseEventModifiers::SIMPLEMOVE | MouseEventModifiers::ENTERWINDOW, + MOUSE_LEFT, KEY_SHIFT); + MouseButtonUp(rMEvt); + bReturn= true; + } + } + break; + } + + if(!bReturn) + bReturn = FuDraw::KeyInput(rKEvt); + + return bReturn; +} + +//Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point, and +//SHIFT+ENTER key to decide the position and draw the new insert point +void FuEditGluePoints::ForcePointer(const MouseEvent* pMEvt) +{ + if(bBeginInsertPoint && pMEvt) + { + MouseEvent aMEvt(pMEvt->GetPosPixel(), pMEvt->GetClicks(), + pMEvt->GetMode(), pMEvt->GetButtons(), pMEvt->GetModifier() & ~KEY_SHIFT); + FuDraw::ForcePointer(&aMEvt); + } + else + { + FuDraw::ForcePointer(pMEvt); + } +} + +bool FuEditGluePoints::Command(const CommandEvent& rCEvt) +{ + mpView->SetActualWin( mpWindow->GetOutDev() ); + return FuPoor::Command( rCEvt ); +} + +void FuEditGluePoints::Activate() +{ + mpView->SetGluePointEditMode(); + FuDraw::Activate(); +} + +void FuEditGluePoints::Deactivate() +{ + mpView->SetGluePointEditMode( false ); + FuDraw::Deactivate(); +} + +void FuEditGluePoints::ReceiveRequest(SfxRequest& rReq) +{ + switch (rReq.GetSlot()) + { + case SID_GLUE_INSERT_POINT: + { + mpView->SetInsGluePointMode(!mpView->IsInsGluePointMode()); + } + break; + + case SID_GLUE_ESCDIR_LEFT: + { + mpView->SetMarkedGluePointsEscDir( SdrEscapeDirection::LEFT, + !mpView->IsMarkedGluePointsEscDir( SdrEscapeDirection::LEFT ) ); + } + break; + + case SID_GLUE_ESCDIR_RIGHT: + { + mpView->SetMarkedGluePointsEscDir( SdrEscapeDirection::RIGHT, + !mpView->IsMarkedGluePointsEscDir( SdrEscapeDirection::RIGHT ) ); + } + break; + + case SID_GLUE_ESCDIR_TOP: + { + mpView->SetMarkedGluePointsEscDir( SdrEscapeDirection::TOP, + !mpView->IsMarkedGluePointsEscDir( SdrEscapeDirection::TOP ) ); + } + break; + + case SID_GLUE_ESCDIR_BOTTOM: + { + mpView->SetMarkedGluePointsEscDir( SdrEscapeDirection::BOTTOM, + !mpView->IsMarkedGluePointsEscDir( SdrEscapeDirection::BOTTOM ) ); + } + break; + + case SID_GLUE_PERCENT: + { + const SfxItemSet* pSet = rReq.GetArgs(); + const SfxPoolItem& rItem = pSet->Get(SID_GLUE_PERCENT); + bool bPercent = static_cast<const SfxBoolItem&>(rItem).GetValue(); + mpView->SetMarkedGluePointsPercent(bPercent); + } + break; + + case SID_GLUE_HORZALIGN_CENTER: + { + mpView->SetMarkedGluePointsAlign(false, SdrAlign::HORZ_CENTER); + } + break; + + case SID_GLUE_HORZALIGN_LEFT: + { + mpView->SetMarkedGluePointsAlign(false, SdrAlign::HORZ_LEFT); + } + break; + + case SID_GLUE_HORZALIGN_RIGHT: + { + mpView->SetMarkedGluePointsAlign(false, SdrAlign::HORZ_RIGHT); + } + break; + + case SID_GLUE_VERTALIGN_CENTER: + { + mpView->SetMarkedGluePointsAlign(true, SdrAlign::VERT_CENTER); + } + break; + + case SID_GLUE_VERTALIGN_TOP: + { + mpView->SetMarkedGluePointsAlign(true, SdrAlign::VERT_TOP); + } + break; + + case SID_GLUE_VERTALIGN_BOTTOM: + { + mpView->SetMarkedGluePointsAlign(true, SdrAlign::VERT_BOTTOM); + } + break; + } + + // at the end, call base class + FuPoor::ReceiveRequest(rReq); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuexecuteinteraction.cxx b/sd/source/ui/func/fuexecuteinteraction.cxx new file mode 100644 index 000000000..d1956fcf5 --- /dev/null +++ b/sd/source/ui/func/fuexecuteinteraction.cxx @@ -0,0 +1,237 @@ +/* -*- 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 <fuexecuteinteraction.hxx> + +#include <app.hrc> +#include <config_features.h> +#include <avmedia/mediawindow.hxx> +#include <basic/sbstar.hxx> +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/viewfrm.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svl/urihelper.hxx> +#include <tools/urlobj.hxx> +#include <o3tl/string_view.hxx> + +#include <DrawViewShell.hxx> +#include <GraphicDocShell.hxx> +#include <ViewShell.hxx> +#include <anminfo.hxx> +#include <drawdoc.hxx> +#include <drawview.hxx> +#include <pgjump.hxx> + +#include <com/sun/star/media/XPlayer.hpp> + +using namespace css; + +namespace sd +{ +FuExecuteInteraction::FuExecuteInteraction(ViewShell* pViewSh, ::sd::Window* pWin, + ::sd::View* pView, SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuExecuteInteraction::Create(ViewShell* pViewSh, ::sd::Window* pWin, + ::sd::View* pView, SdDrawDocument* pDoc, + SfxRequest& rReq) +{ + rtl::Reference<FuPoor> xFunc(new FuExecuteInteraction(pViewSh, pWin, pView, pDoc, rReq)); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuExecuteInteraction::DoExecute(SfxRequest&) +{ + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if (rMarkList.GetMarkCount() != 1) + return; + + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + + if (dynamic_cast<const GraphicDocShell*>(mpDocSh) != nullptr + || dynamic_cast<const DrawView*>(mpView) == nullptr) + return; + + SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo(pObj); + if (!pInfo) + return; + + switch (pInfo->meClickAction) + { + case presentation::ClickAction_BOOKMARK: + { + // Jump to Bookmark (Page or Object) + SfxStringItem aItem(SID_NAVIGATOR_OBJECT, pInfo->GetBookmark()); + mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_NAVIGATOR_OBJECT, SfxCallMode::SLOT | SfxCallMode::RECORD, { &aItem }); + } + break; + + case presentation::ClickAction_DOCUMENT: + { + OUString sBookmark(pInfo->GetBookmark()); + // Jump to document + if (!sBookmark.isEmpty()) + { + SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName()); + SfxStringItem aStrItem(SID_FILE_NAME, sBookmark); + SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); + SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame); + SfxBoolItem aBrowseItem(SID_BROWSE, true); + pFrame->GetDispatcher()->ExecuteList( + SID_OPENDOC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aStrItem, &aFrameItem, &aBrowseItem, &aReferer }); + } + } + break; + + case presentation::ClickAction_PREVPAGE: + { + // Jump to the previous page + SfxUInt16Item aItem(SID_NAVIGATOR_PAGE, PAGE_PREVIOUS); + mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_NAVIGATOR_PAGE, SfxCallMode::SLOT | SfxCallMode::RECORD, { &aItem }); + } + break; + + case presentation::ClickAction_NEXTPAGE: + { + // Jump to the next page + SfxUInt16Item aItem(SID_NAVIGATOR_PAGE, PAGE_NEXT); + mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_NAVIGATOR_PAGE, SfxCallMode::SLOT | SfxCallMode::RECORD, { &aItem }); + } + break; + + case presentation::ClickAction_FIRSTPAGE: + { + // Jump to the first page + SfxUInt16Item aItem(SID_NAVIGATOR_PAGE, PAGE_FIRST); + mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_NAVIGATOR_PAGE, SfxCallMode::SLOT | SfxCallMode::RECORD, { &aItem }); + } + break; + + case presentation::ClickAction_LASTPAGE: + { + // Jump to the last page + SfxUInt16Item aItem(SID_NAVIGATOR_PAGE, PAGE_LAST); + mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_NAVIGATOR_PAGE, SfxCallMode::SLOT | SfxCallMode::RECORD, { &aItem }); + } + break; + + case presentation::ClickAction_SOUND: + { +#if HAVE_FEATURE_AVMEDIA + try + { + mxPlayer.set(avmedia::MediaWindow::createPlayer(pInfo->GetBookmark(), "" /*TODO?*/), + uno::UNO_SET_THROW); + mxPlayer->start(); + } + catch (uno::Exception&) + { + } +#endif + } + break; + + case presentation::ClickAction_VERB: + { + // Assign verb + mpView->UnmarkAll(); + mpView->MarkObj(pObj, mpView->GetSdrPageView()); + DrawViewShell* pDrViewSh = static_cast<DrawViewShell*>(mpViewShell); + pDrViewSh->DoVerb(static_cast<sal_Int16>(pInfo->mnVerb)); + } + break; + + case presentation::ClickAction_PROGRAM: + { + OUString aBaseURL = GetDocSh()->GetMedium()->GetBaseURL(); + INetURLObject aURL(::URIHelper::SmartRel2Abs( + INetURLObject(aBaseURL), pInfo->GetBookmark(), URIHelper::GetMaybeFileHdl(), true, + false, INetURLObject::EncodeMechanism::WasEncoded, + INetURLObject::DecodeMechanism::Unambiguous)); + + if (INetProtocol::File == aURL.GetProtocol()) + { + SfxStringItem aUrl(SID_FILE_NAME, + aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE)); + SfxBoolItem aBrowsing(SID_BROWSE, true); + + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + if (pViewFrm) + pViewFrm->GetDispatcher()->ExecuteList( + SID_OPENDOC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aUrl, &aBrowsing }); + } + } + break; + +#if HAVE_FEATURE_SCRIPTING + case presentation::ClickAction_MACRO: + { + // Execute macro + OUString aMacro = pInfo->GetBookmark(); + + if (SfxApplication::IsXScriptURL(aMacro)) + { + uno::Any aRet; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aParams; + uno::Sequence<uno::Any> aOutArgs; + + mpDocSh->CallXScript(aMacro, aParams, aRet, aOutArgsIndex, aOutArgs); + } + else + { + // aMacro has got following format: + // "Macroname.Modulname.Libname.Documentname" or + // "Macroname.Modulname.Libname.Applicationname" + sal_Int32 nIdx{ 0 }; + const std::u16string_view aMacroName = o3tl::getToken(aMacro, 0, '.', nIdx); + const std::u16string_view aModulName = o3tl::getToken(aMacro, 0, '.', nIdx); + + // Currently the "Call" method only resolves modulename+macroname + mpDocSh->GetBasic()->Call(OUString::Concat(aModulName) + "." + aMacroName); + } + } + break; +#endif + + default: + break; + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuexpand.cxx b/sd/source/ui/func/fuexpand.cxx new file mode 100644 index 000000000..822174ed9 --- /dev/null +++ b/sd/source/ui/func/fuexpand.cxx @@ -0,0 +1,256 @@ +/* -*- 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 <fuexpand.hxx> + +#include <sfx2/viewfrm.hxx> +#include <svx/svdotext.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xlineit0.hxx> +#include <svx/svdundo.hxx> +#include <editeng/outlobj.hxx> +#include <svx/svdetc.hxx> +#include <xmloff/autolayout.hxx> +#include <sal/log.hxx> + +#include <app.hrc> +#include <strings.hrc> +#include <pres.hxx> +#include <View.hxx> +#include <sdpage.hxx> +#include <Outliner.hxx> +#include <drawdoc.hxx> +#include <ViewShell.hxx> +#include <sdresid.hxx> +#include <sdmod.hxx> +#include <sfx2/dispatch.hxx> +#include <editeng/eeitem.hxx> + +using namespace com::sun::star; + +namespace sd { + + +FuExpandPage::FuExpandPage ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuExpandPage::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuExpandPage( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuExpandPage::DoExecute( SfxRequest& ) +{ + if ( mpView && mpView->IsTextEdit() ) + mpView->SdrEndTextEdit(); + + // find selected page (only standard pages) + SdPage* pActualPage = nullptr; + sal_uInt16 i = 0; + sal_uInt16 nCount = mpDoc->GetSdPageCount(PageKind::Standard); + + while (!pActualPage && i < nCount) + { + if (mpDoc->GetSdPage(i, PageKind::Standard)->IsSelected()) + { + pActualPage = mpDoc->GetSdPage(i, PageKind::Standard); + } + + i++; + } + + if (!pActualPage) + return; + + SdOutliner aOutliner( mpDoc, OutlinerMode::OutlineObject ); + aOutliner.SetUpdateLayout(false); + aOutliner.EnableUndo(false); + + if (mpDocSh) + aOutliner.SetRefDevice( SD_MOD()->GetVirtualRefDevice() ); + + aOutliner.SetDefTab( mpDoc->GetDefaultTabulator() ); + aOutliner.SetStyleSheetPool(static_cast<SfxStyleSheetPool*>(mpDoc->GetStyleSheetPool())); + + SdrLayerIDSet aVisibleLayers = pActualPage->TRG_GetMasterPageVisibleLayers(); + sal_uInt16 nActualPageNum = pActualPage->GetPageNum(); + SdPage* pActualNotesPage = static_cast<SdPage*>(mpDoc->GetPage(nActualPageNum + 1)); + SdrTextObj* pActualOutline = static_cast<SdrTextObj*>(pActualPage->GetPresObj(PresObjKind::Outline)); + + if (pActualOutline) + { + const bool bUndo = mpView->IsUndoEnabled(); + + if( bUndo ) + mpView->BegUndo(SdResId(STR_UNDO_EXPAND_PAGE)); + + // set current structuring-object into outliner + OutlinerParaObject* pParaObj = pActualOutline->GetOutlinerParaObject(); + aOutliner.SetText(*pParaObj); + + // remove hard paragraph- and character attributes + SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END> aEmptyEEAttr(mpDoc->GetPool()); + sal_Int32 nParaCount1 = aOutliner.GetParagraphCount(); + + for (sal_Int32 nPara = 0; nPara < nParaCount1; nPara++) + { + aOutliner.RemoveCharAttribs(nPara); + aOutliner.SetParaAttribs(nPara, aEmptyEEAttr); + } + + sal_uInt16 nPos = 2; + Paragraph* pPara = aOutliner.GetParagraph( 0 ); + + while (pPara) + { + sal_Int32 nParaPos = aOutliner.GetAbsPos( pPara ); + sal_Int16 nDepth = aOutliner.GetDepth( nParaPos ); + if ( nDepth == 0 ) + { + // page with title & structuring! + rtl::Reference<SdPage> pPage = mpDoc->AllocSdPage(false); + pPage->SetSize(pActualPage->GetSize() ); + pPage->SetBorder(pActualPage->GetLeftBorder(), + pActualPage->GetUpperBorder(), + pActualPage->GetRightBorder(), + pActualPage->GetLowerBorder() ); + pPage->SetName(OUString()); + + // insert page after current page + mpDoc->InsertPage(pPage.get(), nActualPageNum + nPos); + nPos++; + + if( bUndo ) + mpView->AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoNewPage(*pPage)); + + // use MasterPage of the current page + pPage->TRG_SetMasterPage(pActualPage->TRG_GetMasterPage()); + pPage->SetLayoutName(pActualPage->GetLayoutName()); + pPage->SetAutoLayout(AUTOLAYOUT_TITLE_CONTENT, true); + pPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers); + + // notes-page + rtl::Reference<SdPage> pNotesPage = mpDoc->AllocSdPage(false); + pNotesPage->SetSize(pActualNotesPage->GetSize()); + pNotesPage->SetBorder(pActualNotesPage->GetLeftBorder(), + pActualNotesPage->GetUpperBorder(), + pActualNotesPage->GetRightBorder(), + pActualNotesPage->GetLowerBorder() ); + pNotesPage->SetPageKind(PageKind::Notes); + pNotesPage->SetName(OUString()); + + // insert page after current page + mpDoc->InsertPage(pNotesPage.get(), nActualPageNum + nPos); + nPos++; + + if( bUndo ) + mpView->AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoNewPage(*pNotesPage)); + + // use MasterPage of the current page + pNotesPage->TRG_SetMasterPage(pActualNotesPage->TRG_GetMasterPage()); + pNotesPage->SetLayoutName(pActualNotesPage->GetLayoutName()); + pNotesPage->SetAutoLayout(pActualNotesPage->GetAutoLayout(), true); + pNotesPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers); + + // create title text objects + SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pPage->GetPresObj(PresObjKind::Title)); + SAL_WARN_IF(!pTextObj, "sd.core", "worrying lack of PresObjKind::Title object"); + if (!pTextObj) + continue; + + std::optional<OutlinerParaObject> pOutlinerParaObject = aOutliner.CreateParaObject( nParaPos, 1); + pOutlinerParaObject->SetOutlinerMode(OutlinerMode::TitleObject); + + if( pOutlinerParaObject->GetDepth(0) != -1 ) + { + std::unique_ptr<SdrOutliner> pTempOutl = SdrMakeOutliner(OutlinerMode::TitleObject, *mpDoc); + + pTempOutl->SetText( *pOutlinerParaObject ); + + pOutlinerParaObject.reset(); + + pTempOutl->SetDepth( pTempOutl->GetParagraph( 0 ), -1 ); + + pOutlinerParaObject = pTempOutl->CreateParaObject(); + } + + pTextObj->SetOutlinerParaObject(std::move(pOutlinerParaObject)); + + pTextObj->SetEmptyPresObj(false); + + SfxStyleSheet* pSheet = pPage->GetStyleSheetForPresObj(PresObjKind::Title); + pTextObj->NbcSetStyleSheet(pSheet, false); + + SdrTextObj* pOutlineObj = nullptr; + sal_Int32 nChildCount = aOutliner.GetChildCount(pPara); + if (nChildCount > 0) + pOutlineObj = static_cast<SdrTextObj*>( pPage->GetPresObj(PresObjKind::Outline) ); + if (pOutlineObj) + { + // create structuring text objects + std::optional<OutlinerParaObject> pOPO = aOutliner.CreateParaObject(++nParaPos, nChildCount); + + std::unique_ptr<SdrOutliner> pTempOutl = SdrMakeOutliner(OutlinerMode::OutlineObject, *mpDoc); + pTempOutl->SetText( *pOPO ); + + sal_Int32 nParaCount2 = pTempOutl->GetParagraphCount(); + sal_Int32 nPara; + for( nPara = 0; nPara < nParaCount2; nPara++ ) + { + pTempOutl->SetDepth ( + pTempOutl->GetParagraph( nPara ), + pTempOutl->GetDepth( nPara ) - 1); + } + + pOPO = pTempOutl->CreateParaObject(); + pTempOutl.reset(); + + pOutlineObj->SetOutlinerParaObject( std::move(pOPO) ); + pOutlineObj->SetEmptyPresObj(false); + + // remove hard attributes (Flag to sal_True) + SfxItemSet aAttr(mpDoc->GetPool()); + aAttr.Put(XLineStyleItem(drawing::LineStyle_NONE)); + aAttr.Put(XFillStyleItem(drawing::FillStyle_NONE)); + pOutlineObj->SetMergedItemSet(aAttr); + } + } + + pPara = aOutliner.GetParagraph( ++nParaPos ); + } + + if( bUndo ) + mpView->EndUndo(); + } + + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_DELETE_PAGE, SfxCallMode::SYNCHRON | SfxCallMode::RECORD); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuformatpaintbrush.cxx b/sd/source/ui/func/fuformatpaintbrush.cxx new file mode 100644 index 000000000..40bde764f --- /dev/null +++ b/sd/source/ui/func/fuformatpaintbrush.cxx @@ -0,0 +1,276 @@ +/* -*- 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 <sfx2/request.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> + +#include <svx/svxids.hrc> +#include <svx/svdotable.hxx> +#include <svx/svdundo.hxx> +#include <editeng/outliner.hxx> +#include <vcl/ptrstyle.hxx> + +#include <fuformatpaintbrush.hxx> +#include <drawview.hxx> +#include <DrawViewShell.hxx> +#include <FrameView.hxx> +#include <drawdoc.hxx> +#include <ViewShellBase.hxx> + +#include <Window.hxx> + +namespace sd { + + +FuFormatPaintBrush::FuFormatPaintBrush( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +: FuText(pViewSh, pWin, pView, pDoc, rReq) +, mbPermanent( false ) +, mbOldIsQuickTextEditMode( true ) +{ +} + +rtl::Reference<FuPoor> FuFormatPaintBrush::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuFormatPaintBrush( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute( rReq ); + return xFunc; +} + +void FuFormatPaintBrush::DoExecute( SfxRequest& rReq ) +{ + const SfxItemSet *pArgs = rReq.GetArgs(); + if( pArgs && pArgs->Count() >= 1 ) + { + mbPermanent = pArgs->Get(SID_FORMATPAINTBRUSH).GetValue(); + } + + if( mpView ) + { + mpView->TakeFormatPaintBrush( mxItemSet ); + } +} + +void FuFormatPaintBrush::implcancel() +{ + if( mpViewShell && mpViewShell->GetViewFrame() ) + { + SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame(); + pViewFrame->GetBindings().Invalidate(SID_FORMATPAINTBRUSH); + pViewFrame->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + } +} + +static void unmarkimpl( SdrView* pView ) +{ + pView->SdrEndTextEdit(); + pView->UnMarkAll(); +} + +bool FuFormatPaintBrush::MouseButtonDown(const MouseEvent& rMEvt) +{ + if(mpView&&mpWindow) + { + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if( (eHit == SdrHitKind::TextEdit) || (eHit == SdrHitKind::TextEditObj && ( mpViewShell->GetFrameView()->IsQuickEdit() || dynamic_cast<sdr::table::SdrTableObj*>(aVEvt.mpObj) != nullptr ) )) + { + SdrPageView* pPV=nullptr; + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + SdrObject* pPickObj = mpView->PickObj(mpWindow->PixelToLogic(rMEvt.GetPosPixel()),nHitLog, pPV, SdrSearchOptions::PICKMARKABLE); + if( (pPickObj != nullptr) && !pPickObj->IsEmptyPresObj() ) + { + // if we text hit another shape than the one currently selected, unselect the old one now + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + if( rMarkList.GetMarkCount() > 0 ) + { + if( rMarkList.GetMarkCount() == 1 ) + { + if( rMarkList.GetMark(0)->GetMarkedSdrObj() != pPickObj ) + { + + // if current selected shape is not that of the hit text edit, deselect it + unmarkimpl( mpView ); + } + } + else + { + // more than one shape selected, deselect all of them + unmarkimpl( mpView ); + } + } + MouseEvent aMEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), 0 ); + return FuText::MouseButtonDown(aMEvt); + } + + if (aVEvt.mpObj == nullptr) + aVEvt.mpObj = pPickObj; + } + + unmarkimpl( mpView ); + + if (aVEvt.mpObj) + { + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + mpView->MarkObj(mpWindow->PixelToLogic( rMEvt.GetPosPixel() ), nHitLog, false/*bToggle*/); + return true; + } + } + return false; +} + +bool FuFormatPaintBrush::MouseMove(const MouseEvent& rMEvt) +{ + bool bReturn = false; + if( mpWindow && mpView ) + { + if ( mpView->IsTextEdit() ) + { + bReturn = FuText::MouseMove( rMEvt ); + mpWindow->SetPointer(PointerStyle::Fill); + } + else + { + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + SdrPageView* pPV=nullptr; + SdrObject* pObj = mpView->PickObj(mpWindow->PixelToLogic( rMEvt.GetPosPixel() ),nHitLog, pPV, SdrSearchOptions::PICKMARKABLE); + if (pObj && HasContentForThisType(pObj->GetObjInventor(),pObj->GetObjIdentifier()) ) + mpWindow->SetPointer(PointerStyle::Fill); + else + mpWindow->SetPointer(PointerStyle::Arrow); + } + } + return bReturn; +} + +bool FuFormatPaintBrush::MouseButtonUp(const MouseEvent& rMEvt) +{ + if( mxItemSet && mpView && mpView->AreObjectsMarked() ) + { + bool bNoCharacterFormats = false; + bool bNoParagraphFormats = false; + { + if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) ) + bNoCharacterFormats = true; + else if( rMEvt.GetModifier() & KEY_MOD1 ) + bNoParagraphFormats = true; + } + + OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); + if( pOLV ) + pOLV->MouseButtonUp(rMEvt); + + Paste( bNoCharacterFormats, bNoParagraphFormats ); + if(mpViewShell) + mpViewShell->GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH); + + if( mbPermanent ) + return true; + } + + implcancel(); + return true; +} + +bool FuFormatPaintBrush::KeyInput(const KeyEvent& rKEvt) +{ + if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE) + { + implcancel(); + return true; + } + return FuPoor::KeyInput(rKEvt); +} + +void FuFormatPaintBrush::Activate() +{ + mbOldIsQuickTextEditMode = mpViewShell->GetFrameView()->IsQuickEdit(); + if( !mbOldIsQuickTextEditMode ) + { + mpViewShell->GetFrameView()->SetQuickEdit(true); + mpView->SetQuickTextEditMode(true); + } +} + +void FuFormatPaintBrush::Deactivate() +{ + if( !mbOldIsQuickTextEditMode ) + { + mpViewShell->GetFrameView()->SetQuickEdit(false); + mpView->SetQuickTextEditMode(false); + } +} + +bool FuFormatPaintBrush::HasContentForThisType( SdrInventor nObjectInventor, SdrObjKind nObjectIdentifier ) const +{ + if (mxItemSet == nullptr) + return false; + if( !mpView || (!SdrObjEditView::SupportsFormatPaintbrush( nObjectInventor, nObjectIdentifier) ) ) + return false; + return true; +} + +void FuFormatPaintBrush::Paste( bool bNoCharacterFormats, bool bNoParagraphFormats ) +{ + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + if( !(mxItemSet && ( rMarkList.GetMarkCount() == 1 )) ) + return; + + SdrObject* pObj( nullptr ); + bool bUndo = mpDoc->IsUndoEnabled(); + + if( bUndo && !mpView->GetTextEditOutlinerView() ) + pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + + // n685123: ApplyFormatPaintBrush itself would store undo information + // except in a few cases (?) + if( pObj ) + { + OUString sLabel( mpViewShell->GetViewShellBase().RetrieveLabelFromCommand(".uno:FormatPaintbrush" ) ); + mpDoc->BegUndo( sLabel ); + if (dynamic_cast< sdr::table::SdrTableObj* >( pObj ) == nullptr) + mpDoc->AddUndo( mpDoc->GetSdrUndoFactory().CreateUndoAttrObject( *pObj, false, true ) ); + } + + mpView->ApplyFormatPaintBrush( *mxItemSet, bNoCharacterFormats, bNoParagraphFormats ); + + if( pObj ) + { + mpDoc->EndUndo(); + } +} + +/* static */ void FuFormatPaintBrush::GetMenuState( DrawViewShell const & rDrawViewShell, SfxItemSet &rSet ) +{ + const SdrMarkList& rMarkList = rDrawViewShell.GetDrawView()->GetMarkedObjectList(); + + if( rMarkList.GetMarkCount() == 1 ) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if( pObj && SdrObjEditView::SupportsFormatPaintbrush(pObj->GetObjInventor(),pObj->GetObjIdentifier()) ) + return; + } + rSet.DisableItem( SID_FORMATPAINTBRUSH ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuhhconv.cxx b/sd/source/ui/func/fuhhconv.cxx new file mode 100644 index 000000000..a312439bb --- /dev/null +++ b/sd/source/ui/func/fuhhconv.cxx @@ -0,0 +1,256 @@ +/* -*- 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 <com/sun/star/i18n/TextConversionOption.hpp> + +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <comphelper/propertysequence.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <svl/style.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/fontitem.hxx> + +#include <fuhhconv.hxx> +#include <drawdoc.hxx> +#include <Outliner.hxx> +#include <DrawViewShell.hxx> +#include <OutlineViewShell.hxx> +#include <Window.hxx> +#include <ViewShellBase.hxx> + +#include <sdresid.hxx> +#include <strings.hrc> + +class SfxRequest; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + +namespace sd { + + +FuHangulHanjaConversion::FuHangulHanjaConversion ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDocument, + SfxRequest& rReq ) + : FuPoor(pViewSh, pWin, pView, pDocument, rReq), + pSdOutliner(nullptr), + bOwnOutliner(false) +{ + if ( dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr ) + { + bOwnOutliner = true; + pSdOutliner = new SdOutliner( mpDoc, OutlinerMode::TextObject ); + } + else if ( dynamic_cast< const OutlineViewShell *>( mpViewShell ) != nullptr ) + { + bOwnOutliner = false; + pSdOutliner = mpDoc->GetOutliner(); + } + + if (pSdOutliner) + pSdOutliner->PrepareSpelling(); +} + +FuHangulHanjaConversion::~FuHangulHanjaConversion() +{ + if (pSdOutliner) + pSdOutliner->EndConversion(); + + if (bOwnOutliner) + delete pSdOutliner; +} + +rtl::Reference<FuPoor> FuHangulHanjaConversion::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuHangulHanjaConversion( pViewSh, pWin, pView, pDoc, rReq ) ); + return xFunc; +} + +/** + * Search and replace + */ +void FuHangulHanjaConversion::StartConversion( LanguageType nSourceLanguage, LanguageType nTargetLanguage, + const vcl::Font *pTargetFont, sal_Int32 nOptions, bool bIsInteractive ) +{ + + mpView->BegUndo(SdResId(STR_UNDO_HANGULHANJACONVERSION)); + + ViewShellBase* pBase = dynamic_cast<ViewShellBase*>( SfxViewShell::Current() ); + if (pBase != nullptr) + mpViewShell = pBase->GetMainViewShell().get(); + + if( mpViewShell ) + { + if ( pSdOutliner && dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr && !bOwnOutliner ) + { + pSdOutliner->EndConversion(); + + bOwnOutliner = true; + pSdOutliner = new SdOutliner( mpDoc, OutlinerMode::TextObject ); + pSdOutliner->BeginConversion(); + } + else if ( pSdOutliner && dynamic_cast< const OutlineViewShell *>( mpViewShell ) != nullptr && bOwnOutliner ) + { + pSdOutliner->EndConversion(); + delete pSdOutliner; + + bOwnOutliner = false; + pSdOutliner = mpDoc->GetOutliner(); + pSdOutliner->BeginConversion(); + } + + if (pSdOutliner) + pSdOutliner->StartConversion(nSourceLanguage, nTargetLanguage, pTargetFont, nOptions, bIsInteractive ); + } + + // Due to changing between edit mode, notes mode, and handout mode the + // view has most likely changed. Get the new one. + mpViewShell = pBase ? pBase->GetMainViewShell().get() : nullptr; + if (mpViewShell != nullptr) + { + mpView = mpViewShell->GetView(); + mpWindow = mpViewShell->GetActiveWindow(); + } + else + { + mpView = nullptr; + mpWindow = nullptr; + } + + if (mpView != nullptr) + mpView->EndUndo(); +} + +void FuHangulHanjaConversion::ConvertStyles( LanguageType nTargetLanguage, const vcl::Font *pTargetFont ) +{ + if( !mpDoc ) + return; + + SfxStyleSheetBasePool* pStyleSheetPool = mpDoc->GetStyleSheetPool(); + if( !pStyleSheetPool ) + return; + + SfxStyleSheetBase* pStyle = pStyleSheetPool->First(SfxStyleFamily::All); + while( pStyle ) + { + SfxItemSet& rSet = pStyle->GetItemSet(); + + const bool bHasParent = !pStyle->GetParent().isEmpty(); + + if( !bHasParent || rSet.GetItemState( EE_CHAR_LANGUAGE_CJK, false ) == SfxItemState::SET ) + rSet.Put( SvxLanguageItem( nTargetLanguage, EE_CHAR_LANGUAGE_CJK ) ); + + if( pTargetFont && + ( !bHasParent || rSet.GetItemState( EE_CHAR_FONTINFO_CJK, false ) == SfxItemState::SET ) ) + { + // set new font attribute + SvxFontItem aFontItem( rSet.Get( EE_CHAR_FONTINFO_CJK ) ); + aFontItem.SetFamilyName( pTargetFont->GetFamilyName()); + aFontItem.SetFamily( pTargetFont->GetFamilyType()); + aFontItem.SetStyleName( pTargetFont->GetStyleName()); + aFontItem.SetPitch( pTargetFont->GetPitch()); + aFontItem.SetCharSet( pTargetFont->GetCharSet()); + rSet.Put( aFontItem ); + } + + pStyle = pStyleSheetPool->Next(); + } + + mpDoc->SetLanguage( nTargetLanguage, EE_CHAR_LANGUAGE_CJK ); +} + +void FuHangulHanjaConversion::StartChineseConversion() +{ + //open ChineseTranslationDialog + Reference< XComponentContext > xContext( + ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one + if(!xContext.is()) + return; + + Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() ); + if(!xMCF.is()) + return; + + Reference< ui::dialogs::XExecutableDialog > xDialog( + xMCF->createInstanceWithContext("com.sun.star.linguistic2.ChineseTranslationDialog" + , xContext), UNO_QUERY); + Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY ); + if( xInit.is() ) + { + // initialize dialog + Reference< awt::XWindow > xDialogParentWindow; + Sequence<Any> aSeq(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", uno::Any(xDialogParentWindow)} + })); + xInit->initialize( aSeq ); + + //execute dialog + sal_Int16 nDialogRet = xDialog->execute(); + if( RET_OK == nDialogRet ) + { + //get some parameters from the dialog + bool bToSimplified = true; + bool bUseVariants = true; + bool bCommonTerms = true; + Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY ); + if( xProp.is() ) + { + try + { + xProp->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified; + xProp->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants; + xProp->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms; + } + catch( Exception& ) + { + } + } + + //execute translation + LanguageType nSourceLang = bToSimplified ? LANGUAGE_CHINESE_TRADITIONAL : LANGUAGE_CHINESE_SIMPLIFIED; + LanguageType nTargetLang = bToSimplified ? LANGUAGE_CHINESE_SIMPLIFIED : LANGUAGE_CHINESE_TRADITIONAL; + sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0; + if( !bCommonTerms ) + nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER; + + vcl::Font aTargetFont = OutputDevice::GetDefaultFont( + DefaultFontType::CJK_PRESENTATION, + nTargetLang, GetDefaultFontFlags::OnlyOne ); + + StartConversion( nSourceLang, nTargetLang, &aTargetFont, nOptions, false ); + ConvertStyles( nTargetLang, &aTargetFont ); + } + } + Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY ); + if( xComponent.is() ) + xComponent->dispose(); +} +} // end of namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuinsert.cxx b/sd/source/ui/func/fuinsert.cxx new file mode 100644 index 000000000..919814d56 --- /dev/null +++ b/sd/source/ui/func/fuinsert.cxx @@ -0,0 +1,767 @@ +/* -*- 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 <config_features.h> + +#include <fuinsert.hxx> +#include <comphelper/storagehelper.hxx> +#include <comphelper/propertysequence.hxx> +#include <editeng/sizeitem.hxx> +#include <officecfg/Office/Common.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <svx/svxdlg.hxx> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/embed/EmbedVerbs.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/media/XPlayer.hpp> + +#include <svl/stritem.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/msgpool.hxx> +#include <sfx2/msg.hxx> +#include <svtools/insdlg.hxx> +#include <sfx2/request.hxx> +#include <svl/globalnameitem.hxx> +#include <svtools/embedhlp.hxx> +#include <svx/linkwarn.hxx> +#include <avmedia/mediawindow.hxx> +#include <comphelper/classids.hxx> +#include <svtools/sfxecode.hxx> +#include <vcl/transfer.hxx> +#include <svl/urlbmk.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdoole2.hxx> +#include <sot/formats.hxx> +#include <svx/svdpagv.hxx> +#include <sfx2/opengrf.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/charthelper.hxx> +#include <svx/svxids.hrc> + +#include <sdresid.hxx> +#include <View.hxx> +#include <sdmod.hxx> +#include <Window.hxx> +#include <DrawViewShell.hxx> +#include <DrawDocShell.hxx> +#include <GraphicDocShell.hxx> +#include <strings.hrc> +#include <drawdoc.hxx> +#include <sdpage.hxx> +#include <sdgrffilter.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <vcl/errinf.hxx> +#include <vcl/graphicfilter.hxx> + +#include <vcl/GraphicNativeTransform.hxx> +#include <vcl/GraphicNativeMetadata.hxx> + +#include <comphelper/lok.hxx> + +using namespace com::sun::star; + +namespace sd { + + +FuInsertGraphic::FuInsertGraphic ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq, + bool replaceExistingImage) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq), + mbReplaceExistingImage(replaceExistingImage) +{ +} + +rtl::Reference<FuPoor> FuInsertGraphic::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, + SdDrawDocument* pDoc, SfxRequest& rReq, bool replaceExistingImage ) +{ + rtl::Reference<FuPoor> xFunc( new FuInsertGraphic( pViewSh, pWin, pView, pDoc, rReq, replaceExistingImage ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuInsertGraphic::DoExecute( SfxRequest& rReq ) +{ + OUString aFileName; + Graphic aGraphic; + + bool bAsLink = false; + ErrCode nError = ERRCODE_GRFILTER_OPENERROR; + + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + + if ( pArgs && + pArgs->GetItemState( SID_INSERT_GRAPHIC, true, &pItem ) == SfxItemState::SET ) + { + aFileName = static_cast<const SfxStringItem*>(pItem)->GetValue(); + + OUString aFilterName; + if ( const SfxStringItem* pFilterItem = pArgs->GetItemIfSet( FN_PARAM_FILTER ) ) + aFilterName = pFilterItem->GetValue(); + + if ( pArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET ) + bAsLink = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + + nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() ); + } + else + { + SvxOpenGraphicDialog aDlg(SdResId(STR_INSERTGRAPHIC), mpWindow ? mpWindow->GetFrameWeld() : nullptr); + + if( aDlg.Execute() != ERRCODE_NONE ) + return; // cancel dialog + + nError = aDlg.GetGraphic(aGraphic); + bAsLink = aDlg.IsAsLink(); + aFileName = aDlg.GetPath(); + } + + if( nError == ERRCODE_NONE ) + { + GraphicNativeMetadata aMetadata; + if ( aMetadata.read(aGraphic) ) + { + const Degree10 aRotation = aMetadata.getRotation(); + if (aRotation) + { + GraphicNativeTransform aTransform( aGraphic ); + aTransform.rotate( aRotation ); + } + } + if( dynamic_cast< DrawViewShell *>( mpViewShell ) ) + { + sal_Int8 nAction = DND_ACTION_COPY; + SdrObject* pPickObj = nullptr; + if (mbReplaceExistingImage) + pPickObj = mpView->GetSelectedSingleObject( mpView->GetPage() ); + if (pPickObj) + nAction = DND_ACTION_LINK; + else + { + pPickObj = mpView->GetEmptyPresentationObject( PresObjKind::Graphic ); + if (pPickObj) + nAction = DND_ACTION_LINK; + } + + Point aPos = mpWindow->GetVisibleCenter(); + SdrGrafObj* pGrafObj = mpView->InsertGraphic(aGraphic, nAction, aPos, pPickObj, nullptr); + + if(pGrafObj && bAsLink ) + { + // really store as link only? + if( officecfg::Office::Common::Misc::ShowLinkWarningDialog::get() ) + { + SvxLinkWarningDialog aWarnDlg(mpWindow->GetFrameWeld(), aFileName); + if (aWarnDlg.run() != RET_OK) + return; // don't store as link + } + + // store as link + pGrafObj->SetGraphicLink(aFileName); + } + } + } + else + { + SdGRFFilter::HandleGraphicFilterError( nError, GraphicFilter::GetGraphicFilter().GetLastError() ); + } +} + +FuInsertClipboard::FuInsertClipboard ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuInsertClipboard::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuInsertClipboard( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuInsertClipboard::DoExecute( SfxRequest& ) +{ + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mpWindow ) ); + SotClipboardFormatId nFormatId; + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(mpViewShell->GetFrameWeld())); + pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, OUString() ); + pDlg->Insert( SotClipboardFormatId::LINK_SOURCE, OUString() ); + pDlg->Insert( SotClipboardFormatId::DRAWING, OUString() ); + pDlg->Insert( SotClipboardFormatId::SVXB, OUString() ); + pDlg->Insert( SotClipboardFormatId::GDIMETAFILE, OUString() ); + pDlg->Insert( SotClipboardFormatId::BITMAP, OUString() ); + pDlg->Insert( SotClipboardFormatId::NETSCAPE_BOOKMARK, OUString() ); + pDlg->Insert( SotClipboardFormatId::STRING, OUString() ); + pDlg->Insert( SotClipboardFormatId::HTML, OUString() ); + pDlg->Insert( SotClipboardFormatId::RTF, OUString() ); + pDlg->Insert( SotClipboardFormatId::RICHTEXT, OUString() ); + pDlg->Insert( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT, OUString() ); + + //TODO/MBA: testing + nFormatId = pDlg->GetFormat( aDataHelper ); + if( nFormatId == SotClipboardFormatId::NONE || !aDataHelper.GetTransferable().is() ) + return; + + sal_Int8 nAction = DND_ACTION_COPY; + DrawViewShell* pDrViewSh = nullptr; + + if (!mpView->InsertData( aDataHelper, + mpWindow->PixelToLogic( ::tools::Rectangle( Point(), mpWindow->GetOutputSizePixel() ).Center() ), + nAction, false, nFormatId )) + { + pDrViewSh = dynamic_cast<DrawViewShell*>(mpViewShell); + } + + if (!pDrViewSh) + return; + + INetBookmark aINetBookmark( "", "" ); + + if( ( aDataHelper.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK ) && + aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) ) || + ( aDataHelper.HasFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR ) && + aDataHelper.GetINetBookmark( SotClipboardFormatId::FILEGRPDESCRIPTOR, aINetBookmark ) ) || + ( aDataHelper.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) && + aDataHelper.GetINetBookmark( SotClipboardFormatId::UNIFORMRESOURCELOCATOR, aINetBookmark ) ) ) + { + pDrViewSh->InsertURLField( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), "" ); + } +} + +FuInsertOLE::FuInsertOLE ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuInsertOLE::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuInsertOLE( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuInsertOLE::DoExecute( SfxRequest& rReq ) +{ + if ( nSlotId == SID_ATTR_TABLE || + nSlotId == SID_INSERT_DIAGRAM || + nSlotId == SID_INSERT_MATH ) + { + PresObjKind ePresObjKind = (nSlotId == SID_INSERT_DIAGRAM) ? PresObjKind::Chart : PresObjKind::Object; + + SdrObject* pPickObj = mpView->GetEmptyPresentationObject( ePresObjKind ); + + // insert diagram or Calc table + OUString aObjName; + SvGlobalName aName; + if (nSlotId == SID_INSERT_DIAGRAM) + aName = SvGlobalName( SO3_SCH_CLASSID); + else if (nSlotId == SID_ATTR_TABLE) + aName = SvGlobalName(SO3_SC_CLASSID); + else if (nSlotId == SID_INSERT_MATH) + aName = SvGlobalName(SO3_SM_CLASSID); + + uno::Reference < embed::XEmbeddedObject > xObj = mpViewShell->GetViewFrame()->GetObjectShell()-> + GetEmbeddedObjectContainer().CreateEmbeddedObject( aName.GetByteSequence(), aObjName ); + if ( xObj.is() ) + { + // Create default chart type. + uno::Reference<chart2::XChartDocument> xChartDoc(xObj->getComponent(), uno::UNO_QUERY); + if (xChartDoc.is()) + xChartDoc->createDefaultChart(); + + sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; + + MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) ); + + ::tools::Rectangle aRect; + if( pPickObj ) + { + aRect = pPickObj->GetLogicRect(); + + awt::Size aSz; + aSz.Width = aRect.GetWidth(); + aSz.Height = aRect.GetHeight(); + xObj->setVisualAreaSize( nAspect, aSz ); + } + else + { + awt::Size aSz; + try + { + aSz = xObj->getVisualAreaSize( nAspect ); + } + catch ( embed::NoVisualAreaSizeException& ) + { + // the default size will be set later + } + + Size aSize( aSz.Width, aSz.Height ); + + if (aSize.IsEmpty()) + { + // rectangle with balanced edge ratio + aSize.setWidth( 14100 ); + aSize.setHeight( 10000 ); + Size aTmp = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(aUnit)); + aSz.Width = aTmp.Width(); + aSz.Height = aTmp.Height(); + xObj->setVisualAreaSize( nAspect, aSz ); + } + else + { + aSize = OutputDevice::LogicToLogic(aSize, MapMode(aUnit), MapMode(MapUnit::Map100thMM)); + } + + Point aPos = mpWindow->GetVisibleCenter(); + aPos.AdjustX( -(aSize.Width() / 2) ); + aPos.AdjustY( -(aSize.Height() / 2) ); + aRect = ::tools::Rectangle(aPos, aSize); + } + + SdrOle2Obj* pOleObj = new SdrOle2Obj( + mpView->getSdrModelFromSdrView(), + svt::EmbeddedObjectRef( xObj, nAspect ), + aObjName, + aRect); + SdrPageView* pPV = mpView->GetSdrPageView(); + + // if we have a pick obj we need to make this new ole a pres obj replacing the current pick obj + if( pPickObj ) + { + SdPage* pPage = static_cast< SdPage* >(pPickObj->getSdrPageFromSdrObject()); + if(pPage && pPage->IsPresObj(pPickObj)) + { + pPage->InsertPresObj( pOleObj, ePresObjKind ); + pOleObj->SetUserCall(pPickObj->GetUserCall()); + } + + // #i123468# we need to end text edit before replacing the object. There cannot yet + // being text typed (else it would not be an EmptyPresObj anymore), but it may be + // in text edit mode + if (mpView->IsTextEdit()) + { + mpView->SdrEndTextEdit(); + } + } + + bool bRet = true; + if( pPickObj ) + mpView->ReplaceObjectAtView(pPickObj, *pPV, pOleObj ); + else + bRet = mpView->InsertObjectAtView(pOleObj, *pPV, SdrInsertFlags::SETDEFLAYER); + + if (bRet && !comphelper::LibreOfficeKit::isActive()) + { + // Let the chart be activated after the inserting (unless + // via LibreOfficeKit) + if (nSlotId == SID_INSERT_DIAGRAM) + { + pOleObj->SetProgName( "StarChart"); + } + else if (nSlotId == SID_ATTR_TABLE) + { + pOleObj->SetProgName( "StarCalc" ); + } + else if (nSlotId == SID_INSERT_MATH) + { + pOleObj->SetProgName( "StarMath" ); + } + + pOleObj->SetLogicRect(aRect); + Size aTmp( OutputDevice::LogicToLogic(aRect.GetSize(), MapMode(MapUnit::Map100thMM), MapMode(aUnit)) ); + awt::Size aVisualSize; + aVisualSize.Width = aTmp.Width(); + aVisualSize.Height = aTmp.Height(); + xObj->setVisualAreaSize( nAspect, aVisualSize ); + mpViewShell->ActivateObject(pOleObj, embed::EmbedVerbs::MS_OLEVERB_SHOW); + + if (nSlotId == SID_INSERT_DIAGRAM) + { + // note, that this call modified the chart model which + // results in a change notification. So call this after + // everything else is finished. + ChartHelper::AdaptDefaultsForChart( xObj ); + } + } + } + else + { + ErrorHandler::HandleError(* new StringErrorInfo(ERRCODE_SFX_OLEGENERAL, + "" ) ); + } + } + else + { + // insert object + sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; + bool bCreateNew = false; + uno::Reference < embed::XEmbeddedObject > xObj; + uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage(); + SvObjectServerList aServerLst; + OUString aName; + + OUString aIconMediaType; + uno::Reference< io::XInputStream > xIconMetaFile; + + const SfxGlobalNameItem* pNameItem = rReq.GetArg<SfxGlobalNameItem>(SID_INSERT_OBJECT); + if ( nSlotId == SID_INSERT_OBJECT && pNameItem ) + { + const SvGlobalName& aClassName = pNameItem->GetValue(); + xObj = mpViewShell->GetViewFrame()->GetObjectShell()-> + GetEmbeddedObjectContainer().CreateEmbeddedObject( aClassName.GetByteSequence(), aName ); + } + else + { + switch ( nSlotId ) + { + case SID_INSERT_OBJECT : + { + aServerLst.FillInsertObjects(); + if (mpDoc->GetDocumentType() == DocumentType::Draw) + { + aServerLst.Remove( GraphicDocShell::Factory().GetClassId() ); + } + else + { + aServerLst.Remove( DrawDocShell::Factory().GetClassId() ); + } + + [[fallthrough]]; + } + case SID_INSERT_FLOATINGFRAME : + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg( + pFact->CreateInsertObjectDialog( mpViewShell->GetFrameWeld(), SD_MOD()->GetSlotPool()->GetSlot(nSlotId)->GetCommandString(), + xStorage, &aServerLst )); + pDlg->Execute(); + bCreateNew = pDlg->IsCreateNew(); + xObj = pDlg->GetObject(); + + xIconMetaFile = pDlg->GetIconIfIconified( &aIconMediaType ); + if ( xIconMetaFile.is() ) + nAspect = embed::Aspects::MSOLE_ICON; + + if ( xObj.is() ) + mpViewShell->GetObjectShell()->GetEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aName ); + + break; + } + } + } + + try + { + if (xObj.is()) + { + bool bInsertNewObject = true; + + Size aSize; + MapUnit aMapUnit = MapUnit::Map100thMM; + if ( nAspect != embed::Aspects::MSOLE_ICON ) + { + awt::Size aSz; + try + { + aSz = xObj->getVisualAreaSize( nAspect ); + } + catch( embed::NoVisualAreaSizeException& ) + { + // the default size will be set later + } + + aSize =Size( aSz.Width, aSz.Height ); + + aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) ); + if (aSize.IsEmpty()) + { + // rectangle with balanced edge ratio + aSize.setWidth( 14100 ); + aSize.setHeight( 10000 ); + Size aTmp = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(aMapUnit)); + aSz.Width = aTmp.Width(); + aSz.Height = aTmp.Height(); + xObj->setVisualAreaSize( nAspect, aSz ); + } + else + { + aSize = OutputDevice::LogicToLogic(aSize, MapMode(aMapUnit), MapMode(MapUnit::Map100thMM)); + } + } + + if ( mpView->AreObjectsMarked() ) + { + // as an empty OLE object available? + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if (rMarkList.GetMarkCount() == 1) + { + SdrMark* pMark = rMarkList.GetMark(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + + if (pObj->GetObjInventor() == SdrInventor::Default && + pObj->GetObjIdentifier() == SdrObjKind::OLE2) + { + if ( !static_cast<SdrOle2Obj*>(pObj)->GetObjRef().is() ) + { + // the empty OLE object gets a new IPObj + bInsertNewObject = false; + pObj->SetEmptyPresObj(false); + static_cast<SdrOle2Obj*>(pObj)->SetOutlinerParaObject(std::nullopt); + static_cast<SdrOle2Obj*>(pObj)->SetObjRef(xObj); + static_cast<SdrOle2Obj*>(pObj)->SetPersistName(aName); + static_cast<SdrOle2Obj*>(pObj)->SetName(aName); + static_cast<SdrOle2Obj*>(pObj)->SetAspect(nAspect); + ::tools::Rectangle aRect = static_cast<SdrOle2Obj*>(pObj)->GetLogicRect(); + + if ( nAspect == embed::Aspects::MSOLE_ICON ) + { + if( xIconMetaFile.is() ) + static_cast<SdrOle2Obj*>(pObj)->SetGraphicToObj( xIconMetaFile, aIconMediaType ); + } + else + { + Size aTmp = OutputDevice::LogicToLogic(aRect.GetSize(), MapMode(MapUnit::Map100thMM), MapMode(aMapUnit)); + awt::Size aSz( aTmp.Width(), aTmp.Height() ); + xObj->setVisualAreaSize( nAspect, aSz ); + } + } + } + } + } + + if (bInsertNewObject) + { + // we create a new OLE object + SdrPageView* pPV = mpView->GetSdrPageView(); + Size aPageSize = pPV->GetPage()->GetSize(); + + // get the size from the iconified object + ::svt::EmbeddedObjectRef aObjRef( xObj, nAspect ); + if ( nAspect == embed::Aspects::MSOLE_ICON ) + { + aObjRef.SetGraphicStream( xIconMetaFile, aIconMediaType ); + MapMode aMapMode( MapUnit::Map100thMM ); + aSize = aObjRef.GetSize( &aMapMode ); + } + + Point aPnt ((aPageSize.Width() - aSize.Width()) / 2, + (aPageSize.Height() - aSize.Height()) / 2); + ::tools::Rectangle aRect (aPnt, aSize); + SdrOle2Obj* pObj = new SdrOle2Obj( + mpView->getSdrModelFromSdrView(), + aObjRef, + aName, + aRect); + + if( mpView->InsertObjectAtView(pObj, *pPV, SdrInsertFlags::SETDEFLAYER) ) + { + // Math objects change their object size during InsertObject. + // New size must be set in SdrObject, or a wrong scale will be set at + // ActivateObject. + + if ( nAspect != embed::Aspects::MSOLE_ICON ) + { + try + { + awt::Size aSz = xObj->getVisualAreaSize( nAspect ); + + Size aNewSize = OutputDevice::LogicToLogic( Size( aSz.Width, aSz.Height ), + MapMode( aMapUnit ), MapMode( MapUnit::Map100thMM ) ); + if ( aNewSize != aSize ) + { + aRect.SetSize( aNewSize ); + pObj->SetLogicRect( aRect ); + } + } + catch( embed::NoVisualAreaSizeException& ) + {} + } + + if (bCreateNew) + { + pObj->SetLogicRect(aRect); + + if ( nAspect != embed::Aspects::MSOLE_ICON ) + { + Size aTmp = OutputDevice::LogicToLogic(aRect.GetSize(), MapMode(MapUnit::Map100thMM), MapMode(aMapUnit)); + awt::Size aSz( aTmp.Width(), aTmp.Height() ); + xObj->setVisualAreaSize( nAspect, aSz ); + } + + mpViewShell->ActivateObject(pObj, embed::EmbedVerbs::MS_OLEVERB_SHOW); + } + + Size aVisSizePixel = mpWindow->GetOutputSizePixel(); + ::tools::Rectangle aVisAreaWin = mpWindow->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) ); + mpViewShell->VisAreaChanged(aVisAreaWin); + mpDocSh->SetVisArea(aVisAreaWin); + } + } + } + } + catch (uno::Exception&) + { + // For some reason the object can not be inserted. For example + // because it is password protected and is not properly unlocked. + } + } +} + +FuInsertAVMedia::FuInsertAVMedia( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuInsertAVMedia::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuInsertAVMedia( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuInsertAVMedia::DoExecute( SfxRequest& rReq ) +{ +#if HAVE_FEATURE_AVMEDIA + OUString aURL; + const SfxItemSet* pReqArgs = rReq.GetArgs(); + bool bAPI = false; + + const SvxSizeItem* pSizeItem = rReq.GetArg<SvxSizeItem>(FN_PARAM_1); + const SfxBoolItem* pLinkItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_2); + const bool bSizeUnknown = !pSizeItem; + Size aPrefSize; + + if( pReqArgs ) + { + const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( &pReqArgs->Get( rReq.GetSlot() ) ); + + if( pStringItem ) + { + aURL = pStringItem->GetValue(); + bAPI = !aURL.isEmpty(); + } + } + + bool bLink(pLinkItem ? pLinkItem->GetValue() : true); + if (!(bAPI + || ::avmedia::MediaWindow::executeMediaURLDialog(mpWindow ? mpWindow->GetFrameWeld() : nullptr, aURL, & bLink) + )) + return; + + if (!bSizeUnknown) + { + aPrefSize = pSizeItem->GetSize(); + } + else + { + // If we don't have a size then try and find that out, the resulted might be deliver async, so dispatch a follow up + // effort to insert the video, this time with a size. + if( mpWindow ) + mpWindow->EnterWait(); + + css::uno::Reference<css::frame::XDispatchProvider> xDispatchProvider(mpViewShell->GetViewFrame()->GetFrame().GetFrameInterface(), css::uno::UNO_QUERY); + + rtl::Reference<avmedia::PlayerListener> xPlayerListener(new avmedia::PlayerListener( + [xDispatchProvider, aURL, bLink](const css::uno::Reference<css::media::XPlayer>& rPlayer){ + css::awt::Size aSize = rPlayer->getPreferredPlayerWindowSize(); + avmedia::MediaWindow::dispatchInsertAVMedia(xDispatchProvider, aSize, aURL, bLink); + })); + + const bool bIsMediaURL = ::avmedia::MediaWindow::isMediaURL(aURL, "", true, xPlayerListener); + + if( mpWindow ) + mpWindow->LeaveWait(); + + if (!bIsMediaURL && !bAPI) + ::avmedia::MediaWindow::executeFormatErrorBox(mpWindow->GetFrameWeld()); + + return; + } + + InsertMediaURL(aURL, aPrefSize, bLink); + +#else + (void)rReq; +#endif +} + +#if HAVE_FEATURE_AVMEDIA +void FuInsertAVMedia::InsertMediaURL(const OUString& rURL, const Size& rPrefSize, bool bLink) +{ + if( mpWindow ) + mpWindow->EnterWait(); + + Point aPos; + Size aSize; + sal_Int8 nAction = DND_ACTION_COPY; + + if (rPrefSize.Width() && rPrefSize.Height()) + { + if( mpWindow ) + aSize = mpWindow->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM)); + else + aSize = Application::GetDefaultDevice()->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM)); + } + else + aSize = Size( 5000, 5000 ); + + if( mpWindow ) + { + aPos = mpWindow->PixelToLogic( ::tools::Rectangle( aPos, mpWindow->GetOutputSizePixel() ).Center() ); + aPos.AdjustX( -(aSize.Width() >> 1) ); + aPos.AdjustY( -(aSize.Height() >> 1) ); + } + + mpView->InsertMediaURL(rURL, nAction, aPos, aSize, bLink); + + if( mpWindow ) + mpWindow->LeaveWait(); +} +#endif + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuinsfil.cxx b/sd/source/ui/func/fuinsfil.cxx new file mode 100644 index 000000000..6569514cf --- /dev/null +++ b/sd/source/ui/func/fuinsfil.cxx @@ -0,0 +1,725 @@ +/* -*- 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 <fuinsfil.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/progress.hxx> +#include <editeng/outliner.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editeng.hxx> +#include <svl/stritem.hxx> +#include <sfx2/request.hxx> +#include <sfx2/app.hxx> +#include <vcl/weld.hxx> +#include <svx/svdorect.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdoutl.hxx> +#include <sfx2/filedlghelper.hxx> +#include <sot/formats.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/fcontnr.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svxids.hrc> +#include <tools/debug.hxx> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker3.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> + +#include <sdresid.hxx> +#include <drawdoc.hxx> +#include <Window.hxx> +#include <View.hxx> +#include <strings.hrc> +#include <sdmod.hxx> +#include <sdpage.hxx> +#include <ViewShellBase.hxx> +#include <DrawViewShell.hxx> +#include <OutlineView.hxx> +#include <DrawDocShell.hxx> +#include <GraphicDocShell.hxx> +#include <app.hrc> +#include <Outliner.hxx> +#include <sdabstdlg.hxx> +#include <memory> + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star; + +typedef ::std::pair< OUString, OUString > FilterDesc; + +namespace +{ + +OUString lcl_GetExtensionsList ( ::std::vector< FilterDesc > const& rFilterDescList ) +{ + OUStringBuffer aExtensions; + + for (const auto& rFilterDesc : rFilterDescList) + { + OUString sWildcard = rFilterDesc.second; + + if ( aExtensions.indexOf( sWildcard ) == -1 ) + { + if ( !aExtensions.isEmpty() ) + aExtensions.append(";"); + aExtensions.append(sWildcard); + } + + } + + return aExtensions.makeStringAndClear(); +} + +void lcl_AddFilter ( ::std::vector< FilterDesc >& rFilterDescList, + const std::shared_ptr<const SfxFilter>& pFilter ) +{ + if (pFilter) + rFilterDescList.emplace_back( pFilter->GetUIName(), pFilter->GetDefaultExtension() ); +} + +} + +namespace sd { + + +FuInsertFile::FuInsertFile ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuInsertFile::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuInsertFile( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuInsertFile::DoExecute( SfxRequest& rReq ) +{ + SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher(); + ::std::vector< FilterDesc > aFilterVector; + ::std::vector< OUString > aOtherFilterVector; + const SfxItemSet* pArgs = rReq.GetArgs (); + + FuInsertFile::GetSupportedFilterVector( aOtherFilterVector ); + + if (!pArgs) + { + sfx2::FileDialogHelper aFileDialog( + ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::Insert, mpWindow ? mpWindow->GetFrameWeld() : nullptr); + aFileDialog.SetContext(sfx2::FileDialogHelper::DrawImpressInsertFile); + Reference< XFilePicker > xFilePicker( aFileDialog.GetFilePicker() ); + Reference< XFilterManager > xFilterManager( xFilePicker, UNO_QUERY ); + OUString aOwnCont; + OUString aOtherCont; + + aFileDialog.SetTitle( SdResId(STR_DLG_INSERT_PAGES_FROM_FILE) ); + + if( mpDoc->GetDocumentType() == DocumentType::Impress ) + { + aOwnCont = "simpress"; + aOtherCont = "sdraw"; + } + else + { + aOtherCont = "simpress"; + aOwnCont = "sdraw" ; + } + + SfxFilterMatcher aMatch( aOwnCont ); + + if( xFilterManager.is() ) + { + // Get filter for current format + try + { + // Get main filter + std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetDefaultFilterFromFactory( aOwnCont ); + lcl_AddFilter( aFilterVector, pFilter ); + + // get template filter + if( mpDoc->GetDocumentType() == DocumentType::Impress ) + pFilter = DrawDocShell::Factory().GetTemplateFilter(); + else + pFilter = GraphicDocShell::Factory().GetTemplateFilter(); + lcl_AddFilter( aFilterVector, pFilter ); + + // get cross filter + pFilter = SfxFilter::GetDefaultFilterFromFactory( aOtherCont ); + lcl_AddFilter( aFilterVector, pFilter ); + + // get Powerpoint filter + pFilter = aMatch.GetFilter4Extension( ".ppt" ); + lcl_AddFilter( aFilterVector, pFilter ); + + // Get other draw/impress filters + pFilter = aMatch.GetFilter4ClipBoardId( SotClipboardFormatId::STARIMPRESS_60, SfxFilterFlags::IMPORT, SfxFilterFlags::TEMPLATEPATH ); + lcl_AddFilter( aFilterVector, pFilter ); + + pFilter = aMatch.GetFilter4ClipBoardId( SotClipboardFormatId::STARIMPRESS_60, SfxFilterFlags::TEMPLATEPATH ); + lcl_AddFilter( aFilterVector, pFilter ); + + pFilter = aMatch.GetFilter4ClipBoardId( SotClipboardFormatId::STARDRAW_60, SfxFilterFlags::IMPORT, SfxFilterFlags::TEMPLATEPATH ); + lcl_AddFilter( aFilterVector, pFilter ); + + pFilter = aMatch.GetFilter4ClipBoardId( SotClipboardFormatId::STARDRAW_60, SfxFilterFlags::TEMPLATEPATH ); + lcl_AddFilter( aFilterVector, pFilter ); + + pFilter = aMatch.GetFilter4ClipBoardId( SotClipboardFormatId::STARDRAW, SfxFilterFlags::IMPORT, SfxFilterFlags::TEMPLATEPATH ); + lcl_AddFilter( aFilterVector, pFilter ); + + pFilter = aMatch.GetFilter4ClipBoardId( SotClipboardFormatId::STARDRAW, SfxFilterFlags::TEMPLATEPATH ); + lcl_AddFilter( aFilterVector, pFilter ); + + // add additional supported filters + for( const auto& rOtherFilter : aOtherFilterVector ) + { + if( ( pFilter = rMatcher.GetFilter4Mime( rOtherFilter ) ) != nullptr ) + lcl_AddFilter( aFilterVector, pFilter ); + } + + // set "All supported formats" as the default filter + OUString aAllSpec( SdResId( STR_ALL_SUPPORTED_FORMATS ) ); + OUString aExtensions = lcl_GetExtensionsList( aFilterVector ); + OUString aGUIName = aAllSpec + " (" + aExtensions + ")"; + + xFilterManager->appendFilter( aGUIName, aExtensions ); + xFilterManager->setCurrentFilter( aAllSpec ); + + // append individual filters + for( const auto& rFilter : aFilterVector ) + { + xFilterManager->appendFilter( rFilter.first, rFilter.second ); + } + + // end with "All files" as fallback + xFilterManager->appendFilter( SdResId( STR_ALL_FILES ), "*.*" ); + } + catch (const IllegalArgumentException&) + { + } + } + + if( aFileDialog.Execute() != ERRCODE_NONE ) + return; + else + { + aFilterName = aFileDialog.GetCurrentFilter(); + aFile = aFileDialog.GetPath(); + } + } + else + { + const SfxStringItem* pFileName = rReq.GetArg<SfxStringItem>(ID_VAL_DUMMY0); + const SfxStringItem* pFilterName = rReq.GetArg<SfxStringItem>(ID_VAL_DUMMY1); + + aFile = pFileName->GetValue (); + + if( pFilterName ) + aFilterName = pFilterName->GetValue (); + } + + mpDocSh->SetWaitCursor( true ); + + std::unique_ptr<SfxMedium> xMedium(new SfxMedium(aFile, StreamMode::READ | StreamMode::NOCREATE)); + std::shared_ptr<const SfxFilter> pFilter; + + SfxGetpApp()->GetFilterMatcher().GuessFilter(*xMedium, pFilter); + + bool bDrawMode = dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr; + bool bInserted = false; + + if( pFilter ) + { + xMedium->SetFilter( pFilter ); + aFilterName = pFilter->GetFilterName(); + + if( xMedium->IsStorage() || ( xMedium->GetInStream() && SotStorage::IsStorageFile( xMedium->GetInStream() ) ) ) + { + if ( pFilter->GetServiceName() == "com.sun.star.presentation.PresentationDocument" || + pFilter->GetServiceName() == "com.sun.star.drawing.DrawingDocument" ) + { + // Draw, Impress or PowerPoint document + // the ownership of the Medium is transferred + if( bDrawMode ) + InsSDDinDrMode(xMedium.release()); + else + InsSDDinOlMode(xMedium.release()); + + // ownership of pMedium has changed in this case + bInserted = true; + } + } + else + { + bool bFound = ( ::std::find( aOtherFilterVector.begin(), aOtherFilterVector.end(), pFilter->GetMimeType() ) != aOtherFilterVector.end() ); + if( !bFound && + ( aFilterName.indexOf( "Text" ) != -1 || + aFilterName.indexOf( "Rich" ) != -1 || + aFilterName.indexOf( "RTF" ) != -1 || + aFilterName.indexOf( "HTML" ) != -1 ) ) + { + bFound = true; + } + + if( bFound ) + { + if( bDrawMode ) + InsTextOrRTFinDrMode(xMedium.get()); + else + InsTextOrRTFinOlMode(xMedium.get()); + + bInserted = true; + xMedium.reset(); + } + } + } + + mpDocSh->SetWaitCursor( false ); + + if( !bInserted ) + { + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_READ_DATA_ERROR))); + xErrorBox->run(); + } +} + +bool FuInsertFile::InsSDDinDrMode(SfxMedium* pMedium) +{ + bool bOK = false; + + mpDocSh->SetWaitCursor( false ); + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + weld::Window* pParent = mpViewShell ? mpViewShell->GetFrameWeld() : nullptr; + ScopedVclPtr<AbstractSdInsertPagesObjsDlg> pDlg( pFact->CreateSdInsertPagesObjsDlg(pParent, mpDoc, pMedium, aFile) ); + + sal_uInt16 nRet = pDlg->Execute(); + + mpDocSh->SetWaitCursor( true ); + + if( nRet == RET_OK ) + { + /* list with page names (if NULL, then all pages) + First, insert pages */ + std::vector<OUString> aBookmarkList = pDlg->GetList( 1 ); // pages + bool bLink = pDlg->IsLink(); + SdPage* pPage = nullptr; + ::sd::View* pView = mpViewShell ? mpViewShell->GetView() : nullptr; + + if (pView) + { + if( auto pOutlineView = dynamic_cast<OutlineView *>( pView )) + { + pPage = pOutlineView->GetActualPage(); + } + else + { + pPage = static_cast<SdPage*>(pView->GetSdrPageView()->GetPage()); + } + } + + sal_uInt16 nPos = 0xFFFF; + + if (pPage && !pPage->IsMasterPage()) + { + if (pPage->GetPageKind() == PageKind::Standard) + { + nPos = pPage->GetPageNum() + 2; + } + else if (pPage->GetPageKind() == PageKind::Notes) + { + nPos = pPage->GetPageNum() + 1; + } + } + + bool bNameOK; + std::vector<OUString> aExchangeList; + std::vector<OUString> aObjectBookmarkList = pDlg->GetList( 2 ); // objects + + /* if pBookmarkList is NULL, we insert selected pages, and/or selected + objects or everything. */ + if( !aBookmarkList.empty() || aObjectBookmarkList.empty() ) + { + /* To ensure that all page names are unique, we check the ones we + want to insert and insert them into a substitution list if + necessary. + bNameOK is sal_False if the user has canceled. */ + bNameOK = mpView->GetExchangeList( aExchangeList, aBookmarkList, 0 ); + + if( bNameOK ) + bOK = mpDoc->InsertBookmarkAsPage( aBookmarkList, &aExchangeList, + bLink, false/*bReplace*/, nPos, + false, nullptr, true, true, false ); + + aBookmarkList.clear(); + aExchangeList.clear(); + } + + // to ensure ... (see above) + bNameOK = mpView->GetExchangeList( aExchangeList, aObjectBookmarkList, 1 ); + + if( bNameOK ) + bOK = mpDoc->InsertBookmarkAsObject( aObjectBookmarkList, aExchangeList, + nullptr, nullptr, false ); + + if( pDlg->IsRemoveUnnecessaryMasterPages() ) + mpDoc->RemoveUnnecessaryMasterPages(); + } + + return bOK; +} + +void FuInsertFile::InsTextOrRTFinDrMode(SfxMedium* pMedium) +{ + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSdInsertPagesObjsDlg> pDlg( pFact->CreateSdInsertPagesObjsDlg(mpViewShell->GetFrameWeld(), mpDoc, nullptr, aFile) ); + + mpDocSh->SetWaitCursor( false ); + + sal_uInt16 nRet = pDlg->Execute(); + mpDocSh->SetWaitCursor( true ); + + if( nRet != RET_OK ) + return; + + // selected file format: text, RTF or HTML (default is text) + EETextFormat nFormat = EETextFormat::Text; + + if( aFilterName.indexOf( "Rich") != -1 ) + nFormat = EETextFormat::Rtf; + else if( aFilterName.indexOf( "HTML" ) != -1 ) + nFormat = EETextFormat::Html; + + /* create our own outline since: + - it is possible that the document outliner is actually used in the + structuring mode + - the draw outliner of the drawing engine has to draw something in + between + - the global outliner could be used in SdPage::CreatePresObj */ + SdOutliner aOutliner( mpDoc, OutlinerMode::TextObject ); + + // set reference device + aOutliner.SetRefDevice( SD_MOD()->GetVirtualRefDevice() ); + + SdPage* pPage = static_cast<DrawViewShell*>(mpViewShell)->GetActualPage(); + aLayoutName = pPage->GetLayoutName(); + sal_Int32 nIndex = aLayoutName.indexOf(SD_LT_SEPARATOR); + if( nIndex != -1 ) + aLayoutName = aLayoutName.copy(0, nIndex); + + aOutliner.SetPaperSize(pPage->GetSize()); + + SvStream* pStream = pMedium->GetInStream(); + assert(pStream && "No InStream!"); + pStream->Seek( 0 ); + + ErrCode nErr = aOutliner.Read( *pStream, pMedium->GetBaseURL(), nFormat, mpDocSh->GetHeaderAttributes() ); + + if (nErr || aOutliner.GetEditEngine().GetText().isEmpty()) + { + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_READ_DATA_ERROR))); + xErrorBox->run(); + } + else + { + // is it a master page? + if (static_cast<DrawViewShell*>(mpViewShell)->GetEditMode() == EditMode::MasterPage && + !pPage->IsMasterPage()) + { + pPage = static_cast<SdPage*>(&(pPage->TRG_GetMasterPage())); + } + + assert(pPage && "page not found"); + + // if editing is going on right now, let it flow into this text object + OutlinerView* pOutlinerView = mpView->GetTextEditOutlinerView(); + if( pOutlinerView ) + { + SdrObject* pObj = mpView->GetTextEditObject(); + if( pObj && + pObj->GetObjInventor() == SdrInventor::Default && + pObj->GetObjIdentifier() == SdrObjKind::TitleText && + aOutliner.GetParagraphCount() > 1 ) + { + // in title objects, only one paragraph is allowed + while ( aOutliner.GetParagraphCount() > 1 ) + { + Paragraph* pPara = aOutliner.GetParagraph( 0 ); + sal_uLong nLen = aOutliner.GetText( pPara ).getLength(); + aOutliner.QuickDelete( ESelection( 0, nLen, 1, 0 ) ); + aOutliner.QuickInsertLineBreak( ESelection( 0, nLen, 0, nLen ) ); + } + } + } + + std::optional<OutlinerParaObject> pOPO = aOutliner.CreateParaObject(); + + if (pOutlinerView) + { + pOutlinerView->InsertText(*pOPO); + } + else + { + SdrRectObj* pTO = new SdrRectObj( + mpView->getSdrModelFromSdrView(), + SdrObjKind::Text); + pTO->SetOutlinerParaObject(std::move(pOPO)); + + const bool bUndo = mpView->IsUndoEnabled(); + if( bUndo ) + mpView->BegUndo(SdResId(STR_UNDO_INSERT_TEXTFRAME)); + pPage->InsertObject(pTO); + + /* can be bigger as the maximal allowed size: + limit object size if necessary */ + Size aSize(aOutliner.CalcTextSize()); + Size aMaxSize = mpDoc->GetMaxObjSize(); + aSize.setHeight( std::min(aSize.Height(), aMaxSize.Height()) ); + aSize.setWidth( std::min(aSize.Width(), aMaxSize.Width()) ); + aSize = mpWindow->LogicToPixel(aSize); + + // put it at the center of the window + Size aTemp(mpWindow->GetOutputSizePixel()); + Point aPos(aTemp.Width() / 2, aTemp.Height() / 2); + aPos.AdjustX( -(aSize.Width() / 2) ); + aPos.AdjustY( -(aSize.Height() / 2) ); + aSize = mpWindow->PixelToLogic(aSize); + aPos = mpWindow->PixelToLogic(aPos); + pTO->SetLogicRect(::tools::Rectangle(aPos, aSize)); + + if (pDlg->IsLink()) + { + pTO->SetTextLink(aFile, aFilterName ); + } + + if( bUndo ) + { + mpView->AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoInsertObject(*pTO)); + mpView->EndUndo(); + } + } + } +} + +void FuInsertFile::InsTextOrRTFinOlMode(SfxMedium* pMedium) +{ + // selected file format: text, RTF or HTML (default is text) + EETextFormat nFormat = EETextFormat::Text; + + if( aFilterName.indexOf( "Rich") != -1 ) + nFormat = EETextFormat::Rtf; + else if( aFilterName.indexOf( "HTML" ) != -1 ) + nFormat = EETextFormat::Html; + + ::Outliner& rDocliner = static_cast<OutlineView*>(mpView)->GetOutliner(); + + std::vector<Paragraph*> aSelList; + rDocliner.GetView(0)->CreateSelectionList(aSelList); + + Paragraph* pPara = aSelList.empty() ? nullptr : *(aSelList.begin()); + + // what should we insert? + while (pPara && !Outliner::HasParaFlag(pPara, ParaFlag::ISPAGE)) + pPara = rDocliner.GetParent(pPara); + + sal_Int32 nTargetPos = rDocliner.GetAbsPos(pPara) + 1; + + // apply layout of predecessor page + sal_uInt16 nPage = 0; + pPara = rDocliner.GetParagraph( rDocliner.GetAbsPos( pPara ) - 1 ); + while (pPara) + { + sal_Int32 nPos = rDocliner.GetAbsPos( pPara ); + if ( Outliner::HasParaFlag( pPara, ParaFlag::ISPAGE ) ) + nPage++; + pPara = rDocliner.GetParagraph( nPos - 1 ); + } + SdPage* pPage = mpDoc->GetSdPage(nPage, PageKind::Standard); + aLayoutName = pPage->GetLayoutName(); + sal_Int32 nIndex = aLayoutName.indexOf(SD_LT_SEPARATOR); + if( nIndex != -1 ) + aLayoutName = aLayoutName.copy(0, nIndex); + + /* create our own outline since: + - it is possible that the document outliner is actually used in the + structuring mode + - the draw outliner of the drawing engine has to draw something in + between + - the global outliner could be used in SdPage::CreatePresObj */ + ::Outliner aOutliner( &mpDoc->GetItemPool(), OutlinerMode::OutlineObject ); + aOutliner.SetStyleSheetPool(static_cast<SfxStyleSheetPool*>(mpDoc->GetStyleSheetPool())); + + // set reference device + aOutliner.SetRefDevice(SD_MOD()->GetVirtualRefDevice()); + aOutliner.SetPaperSize(Size(0x7fffffff, 0x7fffffff)); + + SvStream* pStream = pMedium->GetInStream(); + DBG_ASSERT( pStream, "No InStream!" ); + pStream->Seek( 0 ); + + ErrCode nErr = aOutliner.Read(*pStream, pMedium->GetBaseURL(), nFormat, mpDocSh->GetHeaderAttributes()); + + if (nErr || aOutliner.GetEditEngine().GetText().isEmpty()) + { + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_READ_DATA_ERROR))); + xErrorBox->run(); + } + else + { + sal_Int32 nParaCount = aOutliner.GetParagraphCount(); + + // for progress bar: number of level-0-paragraphs + sal_uInt16 nNewPages = 0; + pPara = aOutliner.GetParagraph( 0 ); + while (pPara) + { + sal_Int32 nPos = aOutliner.GetAbsPos( pPara ); + if( Outliner::HasParaFlag( pPara, ParaFlag::ISPAGE ) ) + nNewPages++; + pPara = aOutliner.GetParagraph( ++nPos ); + } + + mpDocSh->SetWaitCursor( false ); + + std::optional<SfxProgress> pProgress( std::in_place, mpDocSh, SdResId(STR_CREATE_PAGES), nNewPages); + pProgress->SetState( 0, 100 ); + + nNewPages = 0; + + ViewShellId nViewShellId = mpViewShell ? mpViewShell->GetViewShellBase().GetViewShellId() : ViewShellId(-1); + rDocliner.GetUndoManager().EnterListAction( + SdResId(STR_UNDO_INSERT_FILE), OUString(), 0, nViewShellId ); + + sal_Int32 nSourcePos = 0; + SfxStyleSheet* pStyleSheet = pPage->GetStyleSheetForPresObj( PresObjKind::Outline ); + Paragraph* pSourcePara = aOutliner.GetParagraph( 0 ); + while (pSourcePara) + { + sal_Int32 nPos = aOutliner.GetAbsPos( pSourcePara ); + sal_Int16 nDepth = aOutliner.GetDepth( nPos ); + + // only take the last paragraph if it is filled + if (nSourcePos < nParaCount - 1 || + !aOutliner.GetText(pSourcePara).isEmpty()) + { + rDocliner.Insert( aOutliner.GetText(pSourcePara), nTargetPos, nDepth ); + OUString aStyleSheetName( pStyleSheet->GetName() ); + aStyleSheetName = aStyleSheetName.subView( 0, aStyleSheetName.getLength()-1 ) + + OUString::number( nDepth <= 0 ? 1 : nDepth+1 ); + SfxStyleSheetBasePool* pStylePool = mpDoc->GetStyleSheetPool(); + SfxStyleSheet* pOutlStyle = static_cast<SfxStyleSheet*>( pStylePool->Find( aStyleSheetName, pStyleSheet->GetFamily() ) ); + rDocliner.SetStyleSheet( nTargetPos, pOutlStyle ); + } + + if( Outliner::HasParaFlag( pSourcePara, ParaFlag::ISPAGE ) ) + { + nNewPages++; + pProgress->SetState( nNewPages ); + } + + pSourcePara = aOutliner.GetParagraph( ++nPos ); + nTargetPos++; + nSourcePos++; + } + + rDocliner.GetUndoManager().LeaveListAction(); + + pProgress.reset(); + + mpDocSh->SetWaitCursor( true ); + } +} + +bool FuInsertFile::InsSDDinOlMode(SfxMedium* pMedium) +{ + OutlineView* pOlView = static_cast<OutlineView*>(mpView); + + // transfer Outliner content to SdDrawDocument + pOlView->PrepareClose(); + + // read in like in the character mode + if (InsSDDinDrMode(pMedium)) + { + ::Outliner* pOutliner = pOlView->GetViewByWindow(mpWindow)->GetOutliner(); + + // cut notification links temporarily + Link<Outliner::ParagraphHdlParam,void> aOldParagraphInsertedHdl = pOutliner->GetParaInsertedHdl(); + pOutliner->SetParaInsertedHdl( Link<Outliner::ParagraphHdlParam,void>()); + Link<Outliner::ParagraphHdlParam,void> aOldParagraphRemovingHdl = pOutliner->GetParaRemovingHdl(); + pOutliner->SetParaRemovingHdl( Link<Outliner::ParagraphHdlParam,void>()); + Link<Outliner::DepthChangeHdlParam,void> aOldDepthChangedHdl = pOutliner->GetDepthChangedHdl(); + pOutliner->SetDepthChangedHdl( Link<::Outliner::DepthChangeHdlParam,void>()); + Link<::Outliner*,void> aOldBeginMovingHdl = pOutliner->GetBeginMovingHdl(); + pOutliner->SetBeginMovingHdl( Link<::Outliner*,void>()); + Link<::Outliner*,void> aOldEndMovingHdl = pOutliner->GetEndMovingHdl(); + pOutliner->SetEndMovingHdl( Link<::Outliner*,void>()); + + Link<EditStatus&,void> aOldStatusEventHdl = pOutliner->GetStatusEventHdl(); + pOutliner->SetStatusEventHdl(Link<EditStatus&,void>()); + + pOutliner->Clear(); + pOlView->FillOutliner(); + + // set links again + pOutliner->SetParaInsertedHdl(aOldParagraphInsertedHdl); + pOutliner->SetParaRemovingHdl(aOldParagraphRemovingHdl); + pOutliner->SetDepthChangedHdl(aOldDepthChangedHdl); + pOutliner->SetBeginMovingHdl(aOldBeginMovingHdl); + pOutliner->SetEndMovingHdl(aOldEndMovingHdl); + pOutliner->SetStatusEventHdl(aOldStatusEventHdl); + + return true; + } + else + return false; +} + +void FuInsertFile::GetSupportedFilterVector( ::std::vector< OUString >& rFilterVector ) +{ + SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher(); + std::shared_ptr<const SfxFilter> pSearchFilter; + + rFilterVector.clear(); + + if( ( pSearchFilter = rMatcher.GetFilter4Mime( "text/plain" )) != nullptr ) + rFilterVector.push_back( pSearchFilter->GetMimeType() ); + + if( ( pSearchFilter = rMatcher.GetFilter4Mime( "application/rtf" ) ) != nullptr ) + rFilterVector.push_back( pSearchFilter->GetMimeType() ); + + if( ( pSearchFilter = rMatcher.GetFilter4Mime( "text/html" ) ) != nullptr ) + rFilterVector.push_back( pSearchFilter->GetMimeType() ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuline.cxx b/sd/source/ui/func/fuline.cxx new file mode 100644 index 000000000..da9cc795f --- /dev/null +++ b/sd/source/ui/func/fuline.cxx @@ -0,0 +1,109 @@ +/* -*- 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 <fuline.hxx> + +#include <svx/svxids.hrc> +#include <sfx2/request.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <ViewShell.hxx> +#include <View.hxx> +#include <drawdoc.hxx> +#include <svx/svxdlg.hxx> + +namespace sd { + + +FuLine::FuLine ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuLine::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuLine( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuLine::DoExecute( SfxRequest& rReq ) +{ + rReq.Ignore(); + + const SfxItemSet* pArgs = rReq.GetArgs(); + if (pArgs) + return; + + const SdrObject* pObj = nullptr; + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + if( rMarkList.GetMarkCount() == 1 ) + pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + + SfxItemSet aNewAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aNewAttr ); + + bool bHasMarked = mpView->AreObjectsMarked(); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + VclPtr<SfxAbstractTabDialog> pDlg( pFact->CreateSvxLineTabDialog(mpViewShell->GetFrameWeld(), &aNewAttr, mpDoc, pObj, bHasMarked) ); + + pDlg->StartExecuteAsync([pDlg, this](sal_Int32 nResult){ + if (nResult == RET_OK) + { + mpView->SetAttributes (*(pDlg->GetOutputItemSet ())); + + // some attributes are changed, we have to update the listboxes in the objectbars + static const sal_uInt16 SidArray[] = { + SID_ATTR_LINE_STYLE, // ( SID_SVX_START + 169 ) + SID_ATTR_LINE_DASH, // ( SID_SVX_START + 170 ) + SID_ATTR_LINE_WIDTH, // ( SID_SVX_START + 171 ) + SID_ATTR_LINE_COLOR, // ( SID_SVX_START + 172 ) + SID_ATTR_LINE_START, // ( SID_SVX_START + 173 ) + SID_ATTR_LINE_END, // ( SID_SVX_START + 174 ) + SID_ATTR_LINE_TRANSPARENCE, // (SID_SVX_START+1107) + SID_ATTR_LINE_JOINT, // (SID_SVX_START+1110) + SID_ATTR_LINE_CAP, // (SID_SVX_START+1111) + 0 }; + + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); + } + + // deferred until the dialog ends + mpViewShell->Cancel(); + + pDlg->disposeOnce(); + }); +} + +void FuLine::Activate() +{ +} + +void FuLine::Deactivate() +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fulinend.cxx b/sd/source/ui/func/fulinend.cxx new file mode 100644 index 000000000..34fe63161 --- /dev/null +++ b/sd/source/ui/func/fulinend.cxx @@ -0,0 +1,154 @@ +/* -*- 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 <fulinend.hxx> +#include <svx/xtable.hxx> +#include <svx/svxdlg.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdopath.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +#include <strings.hrc> +#include <helpids.h> +#include <sdresid.hxx> +#include <drawdoc.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <memory> + +namespace sd { + + +FuLineEnd::FuLineEnd(ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, + SdDrawDocument* pDoc, SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuLineEnd::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuLineEnd( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuLineEnd::DoExecute( SfxRequest& ) +{ + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if( rMarkList.GetMarkCount() != 1 ) + return; + + const SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + const SdrObject* pNewObj; + SdrObjectUniquePtr pConvPolyObj; + + if( dynamic_cast< const SdrPathObj *>( pObj ) != nullptr ) + { + pNewObj = pObj; + } + else + { + SdrObjTransformInfoRec aInfoRec; + pObj->TakeObjInfo( aInfoRec ); + + if( aInfoRec.bCanConvToPath && + pObj->GetObjInventor() == SdrInventor::Default && + pObj->GetObjIdentifier() != SdrObjKind::Group ) + // bCanConvToPath is sal_True for group objects, + // but it crashes on ConvertToPathObj()! + { + pConvPolyObj = pObj->ConvertToPolyObj( true, false ); + pNewObj = pConvPolyObj.get(); + + if( !pNewObj || dynamic_cast< const SdrPathObj *>( pNewObj ) == nullptr ) + return; // Cancel, additional security, but it does not help + // for group objects + } + else return; // Cancel + } + + const ::basegfx::B2DPolyPolygon aPolyPolygon = static_cast<const SdrPathObj*>(pNewObj)->GetPathPoly(); + + // Delete the created poly-object + pConvPolyObj.reset(); + + XLineEndListRef pLineEndList = mpDoc->GetLineEndList(); + + OUString aNewName( SdResId( STR_LINEEND ) ); + OUString aDesc( SdResId( STR_DESC_LINEEND ) ); + OUString aName; + + ::tools::Long nCount = pLineEndList->Count(); + ::tools::Long j = 1; + bool bDifferent = false; + + while( !bDifferent ) + { + aName = aNewName + " " + OUString::number(j++); + bDifferent = true; + for( ::tools::Long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + } + } + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxNameDialog> pDlg( pFact->CreateSvxNameDialog( nullptr, aName, aDesc ) ); + + pDlg->SetEditHelpId( HID_SD_NAMEDIALOG_LINEEND ); + + if( pDlg->Execute() != RET_OK ) + return; + + pDlg->GetName( aName ); + bDifferent = true; + + for( ::tools::Long i = 0; i < nCount && bDifferent; i++ ) + { + if( aName == pLineEndList->GetLineEnd( i )->GetName() ) + bDifferent = false; + } + + if( bDifferent ) + { + pLineEndList->Insert(std::make_unique<XLineEndEntry>(aPolyPolygon, aName)); + } + else + { + std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(mpWindow ? mpWindow->GetFrameWeld() : nullptr, + VclMessageType::Warning, VclButtonsType::Ok, + SdResId(STR_WARN_NAME_DUPLICATE))); + xWarn->run(); + } +} + +void FuLineEnd::Activate() +{ +} + +void FuLineEnd::Deactivate() +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fulink.cxx b/sd/source/ui/func/fulink.cxx new file mode 100644 index 000000000..8a6d726de --- /dev/null +++ b/sd/source/ui/func/fulink.cxx @@ -0,0 +1,65 @@ +/* -*- 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 <fulink.hxx> + +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> + +#include <svx/svxdlg.hxx> + +#include <drawdoc.hxx> +#include <ViewShell.hxx> +#include <app.hrc> + +class SfxRequest; + +namespace sd { + + +FuLink::FuLink ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq ) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuLink::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuLink( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuLink::DoExecute( SfxRequest& ) +{ + sfx2::LinkManager* pLinkManager = mpDoc->GetLinkManager(); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractLinksDialog> pDlg(pFact->CreateLinksDialog(mpViewShell->GetFrameWeld(), pLinkManager)); + pDlg->Execute(); + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_MANAGE_LINKS ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fumeasur.cxx b/sd/source/ui/func/fumeasur.cxx new file mode 100644 index 000000000..27afd0f7a --- /dev/null +++ b/sd/source/ui/func/fumeasur.cxx @@ -0,0 +1,72 @@ +/* -*- 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 <fumeasur.hxx> +#include <sfx2/request.hxx> +#include <View.hxx> +#include <drawdoc.hxx> +#include <svx/svxdlg.hxx> +#include <svx/dialogs.hrc> + +namespace sd { + + +FuMeasureDlg::FuMeasureDlg ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuMeasureDlg::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuMeasureDlg( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuMeasureDlg::DoExecute( SfxRequest& rReq ) +{ + SfxItemSet aNewAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aNewAttr ); + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if( !pArgs ) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSfxDialog(rReq.GetFrameWeld(), aNewAttr, mpView, RID_SVXPAGE_MEASURE)); + + if( pDlg->Execute() == RET_OK ) + { + rReq.Done( *pDlg->GetOutputItemSet() ); + pArgs = rReq.GetArgs(); + } + } + + if( pArgs ) + mpView->SetAttributes( *pArgs ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fumorph.cxx b/sd/source/ui/func/fumorph.cxx new file mode 100644 index 000000000..c2f94b440 --- /dev/null +++ b/sd/source/ui/func/fumorph.cxx @@ -0,0 +1,508 @@ +/* -*- 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 <fumorph.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xflclit.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdogrp.hxx> +#include <editeng/eeitem.hxx> + +#include <View.hxx> +#include <Window.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +#include <strings.hrc> +#include <sdresid.hxx> + +#include <sdabstdlg.hxx> + +#include <svx/svditer.hxx> + +#include <basegfx/color/bcolor.hxx> +#include <com/sun/star/drawing/LineStyle.hpp> + +using namespace com::sun::star; + +namespace sd { + +FuMorph::FuMorph ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq ) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuMorph::Create( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq +) +{ + rtl::Reference<FuPoor> xFunc( new FuMorph( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuMorph::DoExecute( SfxRequest& ) +{ + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if(rMarkList.GetMarkCount() != 2) + return; + + // create clones + SdrObject* pObj1 = rMarkList.GetMark(0)->GetMarkedSdrObj(); + SdrObject* pObj2 = rMarkList.GetMark(1)->GetMarkedSdrObj(); + SdrObject* pCloneObj1(pObj1->CloneSdrObject(pObj1->getSdrModelFromSdrObject())); + SdrObject* pCloneObj2(pObj2->CloneSdrObject(pObj2->getSdrModelFromSdrObject())); + + // delete text at clone, otherwise we do not get a correct PathObj + pCloneObj1->SetOutlinerParaObject(std::nullopt); + pCloneObj2->SetOutlinerParaObject(std::nullopt); + + // create path objects + SdrObjectUniquePtr pPolyObj1 = pCloneObj1->ConvertToPolyObj(false, false); + SdrObjectUniquePtr pPolyObj2 = pCloneObj2->ConvertToPolyObj(false, false); + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractMorphDlg> pDlg( pFact->CreateMorphDlg(mpWindow ? mpWindow->GetFrameWeld() : nullptr, pObj1, pObj2) ); + if(pPolyObj1 && pPolyObj2 && (pDlg->Execute() == RET_OK)) + { + B2DPolyPolygonList_impl aPolyPolyList; + ::basegfx::B2DPolyPolygon aPolyPoly1; + ::basegfx::B2DPolyPolygon aPolyPoly2; + + pDlg->SaveSettings(); + + // #i48168# Not always is the pPolyObj1/pPolyObj2 a SdrPathObj, it may also be a group object + // containing SdrPathObjs. To get the polygons, I add two iters here + SdrObjListIter aIter1(*pPolyObj1); + SdrObjListIter aIter2(*pPolyObj2); + + while(aIter1.IsMore()) + { + SdrObject* pObj = aIter1.Next(); + if(auto pPathObj = dynamic_cast< SdrPathObj *>( pObj )) + aPolyPoly1.append(pPathObj->GetPathPoly()); + } + + while(aIter2.IsMore()) + { + SdrObject* pObj = aIter2.Next(); + if(auto pPathObj = dynamic_cast< SdrPathObj *>( pObj )) + aPolyPoly2.append(pPathObj->GetPathPoly()); + } + + // perform morphing + if(aPolyPoly1.count() && aPolyPoly2.count()) + { + aPolyPoly1 = ::basegfx::utils::correctOrientations(aPolyPoly1); + aPolyPoly1.removeDoublePoints(); + ::basegfx::B2VectorOrientation eIsClockwise1(::basegfx::utils::getOrientation(aPolyPoly1.getB2DPolygon(0))); + + aPolyPoly2 = ::basegfx::utils::correctOrientations(aPolyPoly2); + aPolyPoly2.removeDoublePoints(); + ::basegfx::B2VectorOrientation eIsClockwise2(::basegfx::utils::getOrientation(aPolyPoly2.getB2DPolygon(0))); + + // set same orientation + if(eIsClockwise1 != eIsClockwise2) + aPolyPoly2.flip(); + + // force same poly count + if(aPolyPoly1.count() < aPolyPoly2.count()) + ImpAddPolys(aPolyPoly1, aPolyPoly2); + else if(aPolyPoly2.count() < aPolyPoly1.count()) + ImpAddPolys(aPolyPoly2, aPolyPoly1); + + // use orientation flag from dialog + if(!pDlg->IsOrientationFade()) + aPolyPoly2.flip(); + + // force same point counts + for( sal_uInt32 a(0); a < aPolyPoly1.count(); a++ ) + { + ::basegfx::B2DPolygon aSub1(aPolyPoly1.getB2DPolygon(a)); + ::basegfx::B2DPolygon aSub2(aPolyPoly2.getB2DPolygon(a)); + + if(aSub1.count() < aSub2.count()) + ImpEqualizePolyPointCount(aSub1, aSub2); + else if(aSub2.count() < aSub1.count()) + ImpEqualizePolyPointCount(aSub2, aSub1); + + aPolyPoly1.setB2DPolygon(a, aSub1); + aPolyPoly2.setB2DPolygon(a, aSub2); + } + + ImpMorphPolygons(aPolyPoly1, aPolyPoly2, pDlg->GetFadeSteps(), aPolyPolyList); + + OUString aString = mpView->GetDescriptionOfMarkedObjects() + + " " + SdResId(STR_UNDO_MORPHING); + + mpView->BegUndo(aString); + ImpInsertPolygons(aPolyPolyList, pDlg->IsAttributeFade(), pObj1, pObj2); + mpView->EndUndo(); + } + } + SdrObject::Free( pCloneObj1 ); + SdrObject::Free( pCloneObj2 ); +} + +static ::basegfx::B2DPolygon ImpGetExpandedPolygon( + const ::basegfx::B2DPolygon& rCandidate, + sal_uInt32 nNum +) +{ + if(rCandidate.count() && nNum && rCandidate.count() != nNum) + { + // length of step in dest poly + ::basegfx::B2DPolygon aRetval; + const double fStep(::basegfx::utils::getLength(rCandidate) / static_cast<double>(rCandidate.isClosed() ? nNum : nNum - 1)); + double fDestPos(0.0); + double fSrcPos(0.0); + sal_uInt32 nSrcPos(0); + sal_uInt32 nSrcPosNext((nSrcPos + 1 == rCandidate.count()) ? 0 : nSrcPos + 1); + double fNextSrcLen(::basegfx::B2DVector(rCandidate.getB2DPoint(nSrcPos) - rCandidate.getB2DPoint(nSrcPosNext)).getLength()); + + for(sal_uInt32 b(0); b < nNum; b++) + { + // calc fDestPos in source + while(fSrcPos + fNextSrcLen < fDestPos) + { + fSrcPos += fNextSrcLen; + nSrcPos++; + nSrcPosNext = (nSrcPos + 1 == rCandidate.count()) ? 0 : nSrcPos + 1; + fNextSrcLen = ::basegfx::B2DVector(rCandidate.getB2DPoint(nSrcPos) - rCandidate.getB2DPoint(nSrcPosNext)).getLength(); + } + + // fDestPos is between fSrcPos and (fSrcPos + fNextSrcLen) + const double fLenA((fDestPos - fSrcPos) / fNextSrcLen); + const ::basegfx::B2DPoint aOld1(rCandidate.getB2DPoint(nSrcPos)); + const ::basegfx::B2DPoint aOld2(rCandidate.getB2DPoint(nSrcPosNext)); + ::basegfx::B2DPoint aNewPoint(basegfx::interpolate(aOld1, aOld2, fLenA)); + aRetval.append(aNewPoint); + + // next step + fDestPos += fStep; + } + + if(aRetval.count() >= 3) + { + aRetval.setClosed(rCandidate.isClosed()); + } + + return aRetval; + } + else + { + return rCandidate; + } +} + +/** + * make the point count of the polygons equal in adding points + */ +void FuMorph::ImpEqualizePolyPointCount( + ::basegfx::B2DPolygon& rSmall, + const ::basegfx::B2DPolygon& rBig +) +{ + // create poly with equal point count + const sal_uInt32 nCnt(rBig.count()); + ::basegfx::B2DPolygon aPoly1(ImpGetExpandedPolygon(rSmall, nCnt)); + + // create transformation for rBig to do the compare + const ::basegfx::B2DRange aSrcSize(::basegfx::utils::getRange(rBig)); + const ::basegfx::B2DPoint aSrcPos(aSrcSize.getCenter()); + const ::basegfx::B2DRange aDstSize(::basegfx::utils::getRange(rSmall)); + const ::basegfx::B2DPoint aDstPos(aDstSize.getCenter()); + + basegfx::B2DHomMatrix aTrans(basegfx::utils::createTranslateB2DHomMatrix(-aSrcPos.getX(), -aSrcPos.getY())); + aTrans.scale(aDstSize.getWidth() / aSrcSize.getWidth(), aDstSize.getHeight() / aSrcSize.getHeight()); + aTrans.translate(aDstPos.getX(), aDstPos.getY()); + + // transpose points to have smooth linear blending + ::basegfx::B2DPolygon aPoly2; + aPoly2.append(::basegfx::B2DPoint(), nCnt); + sal_uInt32 nInd(ImpGetNearestIndex(aPoly1, aTrans * rBig.getB2DPoint(0))); + + for(sal_uInt32 a(0); a < nCnt; a++) + { + aPoly2.setB2DPoint((a + nCnt - nInd) % nCnt, aPoly1.getB2DPoint(a)); + } + + aPoly2.setClosed(rBig.isClosed()); + rSmall = aPoly2; +} + +sal_uInt32 FuMorph::ImpGetNearestIndex( + const ::basegfx::B2DPolygon& rPoly, + const ::basegfx::B2DPoint& rPos +) +{ + double fMinDist = 0.0; + sal_uInt32 nActInd = 0; + + for(sal_uInt32 a(0); a < rPoly.count(); a++) + { + double fNewDist(::basegfx::B2DVector(rPoly.getB2DPoint(a) - rPos).getLength()); + + if(!a || fNewDist < fMinDist) + { + fMinDist = fNewDist; + nActInd = a; + } + } + + return nActInd; +} + +/** + * add to a point reduced polys until count is same + */ +void FuMorph::ImpAddPolys( + ::basegfx::B2DPolyPolygon& rSmaller, + const ::basegfx::B2DPolyPolygon& rBigger +) +{ + while(rSmaller.count() < rBigger.count()) + { + const ::basegfx::B2DPolygon& aToBeCopied(rBigger.getB2DPolygon(rSmaller.count())); + const ::basegfx::B2DRange aToBeCopiedPolySize(::basegfx::utils::getRange(aToBeCopied)); + ::basegfx::B2DPoint aNewPoint(aToBeCopiedPolySize.getCenter()); + ::basegfx::B2DPolygon aNewPoly; + + const ::basegfx::B2DRange aSrcSize(::basegfx::utils::getRange(rBigger.getB2DPolygon(0))); + const ::basegfx::B2DPoint aSrcPos(aSrcSize.getCenter()); + const ::basegfx::B2DRange aDstSize(::basegfx::utils::getRange(rSmaller.getB2DPolygon(0))); + const ::basegfx::B2DPoint aDstPos(aDstSize.getCenter()); + aNewPoint = aNewPoint - aSrcPos + aDstPos; + + for(sal_uInt32 a(0); a < aToBeCopied.count(); a++) + { + aNewPoly.append(aNewPoint); + } + + rSmaller.append(aNewPoly); + } +} + +/** + * create group object with morphed polygons + */ +void FuMorph::ImpInsertPolygons( + B2DPolyPolygonList_impl& rPolyPolyList3D, + bool bAttributeFade, + const SdrObject* pObj1, + const SdrObject* pObj2 +) +{ + Color aStartFillCol; + Color aEndFillCol; + Color aStartLineCol; + Color aEndLineCol; + ::tools::Long nStartLineWidth = 0; + ::tools::Long nEndLineWidth = 0; + SdrPageView* pPageView = mpView->GetSdrPageView(); + SfxItemPool & rPool = pObj1->GetObjectItemPool(); + SfxItemSetFixed<SDRATTR_START,SDRATTR_NOTPERSIST_FIRST-1,EE_ITEMS_START,EE_ITEMS_END> aSet1( rPool ); + SfxItemSet aSet2( aSet1 ); + bool bLineColor = false; + bool bFillColor = false; + bool bLineWidth = false; + bool bIgnoreLine = false; + bool bIgnoreFill = false; + + aSet1.Put(pObj1->GetMergedItemSet()); + aSet2.Put(pObj2->GetMergedItemSet()); + + const drawing::LineStyle eLineStyle1 = aSet1.Get(XATTR_LINESTYLE).GetValue(); + const drawing::LineStyle eLineStyle2 = aSet2.Get(XATTR_LINESTYLE).GetValue(); + const drawing::FillStyle eFillStyle1 = aSet1.Get(XATTR_FILLSTYLE).GetValue(); + const drawing::FillStyle eFillStyle2 = aSet2.Get(XATTR_FILLSTYLE).GetValue(); + + if ( bAttributeFade ) + { + if ( ( eLineStyle1 != drawing::LineStyle_NONE ) && ( eLineStyle2 != drawing::LineStyle_NONE ) ) + { + bLineWidth = bLineColor = true; + + aStartLineCol = aSet1.Get(XATTR_LINECOLOR).GetColorValue(); + aEndLineCol = aSet2.Get(XATTR_LINECOLOR).GetColorValue(); + + nStartLineWidth = aSet1.Get(XATTR_LINEWIDTH).GetValue(); + nEndLineWidth = aSet2.Get(XATTR_LINEWIDTH).GetValue(); + } + else if ( ( eLineStyle1 == drawing::LineStyle_NONE ) && ( eLineStyle2 == drawing::LineStyle_NONE ) ) + bIgnoreLine = true; + + if ( ( eFillStyle1 == drawing::FillStyle_SOLID ) && ( eFillStyle2 == drawing::FillStyle_SOLID ) ) + { + bFillColor = true; + aStartFillCol = aSet1.Get(XATTR_FILLCOLOR).GetColorValue(); + aEndFillCol = aSet2.Get(XATTR_FILLCOLOR).GetColorValue(); + } + else if ( ( eFillStyle1 == drawing::FillStyle_NONE ) && ( eFillStyle2 == drawing::FillStyle_NONE ) ) + bIgnoreFill = true; + } + + if ( !pPageView ) + return; + + SfxItemSet aSet( aSet1 ); + std::unique_ptr<SdrObjGroup, SdrObjectFreeOp> xObjGroup(new SdrObjGroup(mpView->getSdrModelFromSdrView())); + SdrObjList* pObjList = xObjGroup->GetSubList(); + const size_t nCount = rPolyPolyList3D.size(); + const double fStep = 1. / ( nCount + 1 ); + const double fDelta = nEndLineWidth - nStartLineWidth; + double fFactor = fStep; + + aSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) ); + aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) ); + + for ( size_t i = 0; i < nCount; i++, fFactor += fStep ) + { + const ::basegfx::B2DPolyPolygon& rPolyPoly3D = rPolyPolyList3D[ i ]; + SdrPathObj* pNewObj = new SdrPathObj( + mpView->getSdrModelFromSdrView(), + SdrObjKind::Polygon, + rPolyPoly3D); + + // line color + if ( bLineColor ) + { + const basegfx::BColor aLineColor(basegfx::interpolate(aStartLineCol.getBColor(), aEndLineCol.getBColor(), fFactor)); + aSet.Put( XLineColorItem( "", Color(aLineColor))); + } + else if ( bIgnoreLine ) + aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) ); + + // fill color + if ( bFillColor ) + { + const basegfx::BColor aFillColor(basegfx::interpolate(aStartFillCol.getBColor(), aEndFillCol.getBColor(), fFactor)); + aSet.Put( XFillColorItem( "", Color(aFillColor))); + } + else if ( bIgnoreFill ) + aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) ); + + // line width + if ( bLineWidth ) + aSet.Put( XLineWidthItem( nStartLineWidth + static_cast<::tools::Long>( fFactor * fDelta + 0.5 ) ) ); + + pNewObj->SetMergedItemSetAndBroadcast(aSet); + + pObjList->InsertObject( pNewObj ); + } + + if ( nCount ) + { + pObjList->InsertObject( + pObj1->CloneSdrObject(pObj1->getSdrModelFromSdrObject()), + 0 ); + pObjList->InsertObject( + pObj2->CloneSdrObject(pObj2->getSdrModelFromSdrObject()) ); + + mpView->DeleteMarked(); + mpView->InsertObjectAtView(xObjGroup.release(), *pPageView, SdrInsertFlags:: SETDEFLAYER); + } +} + +/** + * create single morphed PolyPolygon + */ +::basegfx::B2DPolyPolygon FuMorph::ImpCreateMorphedPolygon( + const ::basegfx::B2DPolyPolygon& rPolyPolyStart, + const ::basegfx::B2DPolyPolygon& rPolyPolyEnd, + double fMorphingFactor +) +{ + ::basegfx::B2DPolyPolygon aNewPolyPolygon; + const double fFactor = 1.0 - fMorphingFactor; + + for(sal_uInt32 a(0); a < rPolyPolyStart.count(); a++) + { + const ::basegfx::B2DPolygon& aPolyStart(rPolyPolyStart.getB2DPolygon(a)); + const ::basegfx::B2DPolygon& aPolyEnd(rPolyPolyEnd.getB2DPolygon(a)); + const sal_uInt32 nCount(aPolyStart.count()); + ::basegfx::B2DPolygon aNewPolygon; + + for(sal_uInt32 b(0); b < nCount; b++) + { + const ::basegfx::B2DPoint& aPtStart(aPolyStart.getB2DPoint(b)); + const ::basegfx::B2DPoint& aPtEnd(aPolyEnd.getB2DPoint(b)); + aNewPolygon.append(aPtEnd + ((aPtStart - aPtEnd) * fFactor)); + } + + aNewPolygon.setClosed(aPolyStart.isClosed() && aPolyEnd.isClosed()); + aNewPolyPolygon.append(aNewPolygon); + } + + return aNewPolyPolygon; +} + +/** + * create morphed PolyPolygons + */ +void FuMorph::ImpMorphPolygons( + const ::basegfx::B2DPolyPolygon& rPolyPoly1, + const ::basegfx::B2DPolyPolygon& rPolyPoly2, + const sal_uInt16 nSteps, + B2DPolyPolygonList_impl& rPolyPolyList3D +) +{ + if(!nSteps) + return; + + const ::basegfx::B2DRange aStartPolySize(::basegfx::utils::getRange(rPolyPoly1)); + const ::basegfx::B2DPoint aStartCenter(aStartPolySize.getCenter()); + const ::basegfx::B2DRange aEndPolySize(::basegfx::utils::getRange(rPolyPoly2)); + const ::basegfx::B2DPoint aEndCenter(aEndPolySize.getCenter()); + const ::basegfx::B2DPoint aDelta(aEndCenter - aStartCenter); + const double fFactor(1.0 / (nSteps + 1)); + double fValue(0.0); + + for(sal_uInt16 i(0); i < nSteps; i++) + { + fValue += fFactor; + ::basegfx::B2DPolyPolygon aNewPolyPoly2D = ImpCreateMorphedPolygon(rPolyPoly1, rPolyPoly2, fValue); + + const ::basegfx::B2DRange aNewPolySize(::basegfx::utils::getRange(aNewPolyPoly2D)); + const ::basegfx::B2DPoint aNewS(aNewPolySize.getCenter()); + const ::basegfx::B2DPoint aRealS(aStartCenter + (aDelta * fValue)); + const ::basegfx::B2DPoint aDiff(aRealS - aNewS); + + aNewPolyPoly2D.transform(basegfx::utils::createTranslateB2DHomMatrix(aDiff)); + rPolyPolyList3D.push_back( std::move(aNewPolyPoly2D) ); + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/funavig.cxx b/sd/source/ui/func/funavig.cxx new file mode 100644 index 000000000..bd0cdb7c3 --- /dev/null +++ b/sd/source/ui/func/funavig.cxx @@ -0,0 +1,154 @@ +/* -*- 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 <funavig.hxx> +#include <sfx2/viewfrm.hxx> + +#include <app.hrc> +#include <sdpage.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <drawdoc.hxx> +#include <DrawViewShell.hxx> +#include <ViewShell.hxx> +#include <slideshow.hxx> + +namespace sd { + + +FuNavigation::FuNavigation ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuNavigation::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuNavigation( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuNavigation::DoExecute( SfxRequest& rReq ) +{ + bool bSlideShow = SlideShow::IsRunning( mpViewShell->GetViewShellBase() ); + + switch ( rReq.GetSlot() ) + { + case SID_GO_TO_FIRST_PAGE: + { + if (!mpView->IsTextEdit() + && dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr + && !bSlideShow) + { + // jump to first page + static_cast<DrawViewShell*>(mpViewShell)->SwitchPage(0); + } + } + break; + + case SID_GO_TO_PREVIOUS_PAGE: + { + if( !bSlideShow) + if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ) ) + { + // With no modifier pressed we move to the previous + // slide. + mpView->SdrEndTextEdit(); + + // Previous page. + SdPage* pPage = pDrawViewShell->GetActualPage(); + sal_uInt16 nSdPage = (pPage->GetPageNum() - 1) / 2; + + if (nSdPage > 0) + { + // Switch the page and send events regarding + // deactivation the old page and activating the new + // one. + TabControl& rPageTabControl = + static_cast<DrawViewShell*>(mpViewShell) + ->GetPageTabControl(); + if (rPageTabControl.IsReallyShown()) + rPageTabControl.SendDeactivatePageEvent (); + static_cast<DrawViewShell*>(mpViewShell)->SwitchPage(nSdPage - 1); + if (rPageTabControl.IsReallyShown()) + rPageTabControl.SendActivatePageEvent (); + } + } + } + break; + + case SID_GO_TO_NEXT_PAGE: + { + if( !bSlideShow) + if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell )) + { + // With no modifier pressed we move to the next slide. + mpView->SdrEndTextEdit(); + + // Next page. + SdPage* pPage = pDrawViewShell->GetActualPage(); + sal_uInt16 nSdPage = (pPage->GetPageNum() - 1) / 2; + + if (nSdPage < mpDoc->GetSdPageCount(pPage->GetPageKind()) - 1) + { + // Switch the page and send events regarding + // deactivation the old page and activating the new + // one. + TabControl& rPageTabControl = + static_cast<DrawViewShell*>(mpViewShell)->GetPageTabControl(); + if (rPageTabControl.IsReallyShown()) + rPageTabControl.SendDeactivatePageEvent (); + static_cast<DrawViewShell*>(mpViewShell)->SwitchPage(nSdPage + 1); + if (rPageTabControl.IsReallyShown()) + rPageTabControl.SendActivatePageEvent (); + } + } + } + break; + + case SID_GO_TO_LAST_PAGE: + { + if (!mpView->IsTextEdit() && !bSlideShow) + if (auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell )) + { + // jump to last page + SdPage* pPage = pDrawViewShell->GetActualPage(); + pDrawViewShell->SwitchPage(mpDoc->GetSdPageCount( + pPage->GetPageKind()) - 1); + } + } + break; + } + // Refresh toolbar icons + SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings(); + rBindings.Invalidate(SID_GO_TO_FIRST_PAGE); + rBindings.Invalidate(SID_GO_TO_PREVIOUS_PAGE); + rBindings.Invalidate(SID_GO_TO_NEXT_PAGE); + rBindings.Invalidate(SID_GO_TO_LAST_PAGE); +} + + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuoaprms.cxx b/sd/source/ui/func/fuoaprms.cxx new file mode 100644 index 000000000..0feaabfb4 --- /dev/null +++ b/sd/source/ui/func/fuoaprms.cxx @@ -0,0 +1,800 @@ +/* -*- 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 <fuoaprms.hxx> +#include <sdattr.hrc> + +#include <editeng/colritem.hxx> +#include <svx/svdundo.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/sfxdlg.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svx/svdopath.hxx> +#include <tools/debug.hxx> + +#include <strings.hrc> +#include <drawdoc.hxx> +#include <ViewShell.hxx> +#include <ViewShellBase.hxx> +#include <anminfo.hxx> +#include <unoaprms.hxx> +#include <sdundogr.hxx> +#include <View.hxx> +#include <sdabstdlg.hxx> +#include <sdresid.hxx> +#include <tools/helpers.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <memory> + +using namespace ::com::sun::star; + +namespace sd { + + +#define ATTR_MISSING 0 ///< Attribute missing +#define ATTR_MIXED 1 ///< Attribute ambiguous (on multi-selection) +#define ATTR_SET 2 ///< Attribute unique + +FuObjectAnimationParameters::FuObjectAnimationParameters ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuObjectAnimationParameters::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuObjectAnimationParameters( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuObjectAnimationParameters::DoExecute( SfxRequest& rReq ) +{ + SfxUndoManager* pUndoMgr = mpViewShell->GetViewFrame()->GetObjectShell()->GetUndoManager(); + + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + const size_t nCount = rMarkList.GetMarkCount(); + + short nAnimationSet = ATTR_MISSING; + short nEffectSet = ATTR_MISSING; + short nTextEffectSet = ATTR_MISSING; + short nSpeedSet = ATTR_MISSING; + short nFadeColorSet = ATTR_MISSING; + short nFadeOutSet = ATTR_MISSING; + short nInvisibleSet = ATTR_MISSING; + short nSoundOnSet = ATTR_MISSING; + short nSoundFileSet = ATTR_MISSING; + short nPlayFullSet = ATTR_MISSING; + short nClickActionSet = ATTR_MISSING; + short nBookmarkSet = ATTR_MISSING; + + short nSecondEffectSet = ATTR_MISSING; + short nSecondSpeedSet = ATTR_MISSING; + short nSecondSoundOnSet = ATTR_MISSING; + short nSecondPlayFullSet = ATTR_MISSING; + + // defaults (for Undo-Action) + presentation::AnimationEffect eEffect = presentation::AnimationEffect_NONE; + presentation::AnimationEffect eTextEffect = presentation::AnimationEffect_NONE; + presentation::AnimationSpeed eSpeed = presentation::AnimationSpeed_MEDIUM; + bool bActive = false; + bool bFadeOut = false; + Color aFadeColor = COL_LIGHTGRAY; + bool bInvisible = false; + bool bSoundOn = false; + OUString aSound; + bool bPlayFull = false; + presentation::ClickAction eClickAction = presentation::ClickAction_NONE; + OUString aBookmark; + + presentation::AnimationEffect eSecondEffect = presentation::AnimationEffect_NONE; + presentation::AnimationSpeed eSecondSpeed = presentation::AnimationSpeed_MEDIUM; + bool bSecondSoundOn = false; + bool bSecondPlayFull = false; + + SdAnimationInfo* pInfo; + SdrMark* pMark; + + // inspect first object + pMark = rMarkList.GetMark(0); + pInfo = SdDrawDocument::GetAnimationInfo(pMark->GetMarkedSdrObj()); + if( pInfo ) + { + bActive = pInfo->mbActive; + nAnimationSet = ATTR_SET; + + eEffect = pInfo->meEffect; + nEffectSet = ATTR_SET; + + eTextEffect = pInfo->meTextEffect; + nTextEffectSet = ATTR_SET; + + eSpeed = pInfo->meSpeed; + nSpeedSet = ATTR_SET; + + bFadeOut = pInfo->mbDimPrevious; + nFadeOutSet = ATTR_SET; + + aFadeColor = pInfo->maDimColor; + nFadeColorSet = ATTR_SET; + + bInvisible = pInfo->mbDimHide; + nInvisibleSet = ATTR_SET; + + bSoundOn = pInfo->mbSoundOn; + nSoundOnSet = ATTR_SET; + + aSound = pInfo->maSoundFile; + nSoundFileSet = ATTR_SET; + + bPlayFull = pInfo->mbPlayFull; + nPlayFullSet = ATTR_SET; + + eClickAction = pInfo->meClickAction; + nClickActionSet = ATTR_SET; + + aBookmark = pInfo->GetBookmark(); + nBookmarkSet = ATTR_SET; + + eSecondEffect = pInfo->meSecondEffect; + nSecondEffectSet = ATTR_SET; + + eSecondSpeed = pInfo->meSecondSpeed; + nSecondSpeedSet = ATTR_SET; + + bSecondSoundOn = pInfo->mbSecondSoundOn; + nSecondSoundOnSet = ATTR_SET; + + bSecondPlayFull = pInfo->mbSecondPlayFull; + nSecondPlayFullSet = ATTR_SET; + } + + // if necessary, inspect more objects + for( size_t nObject = 1; nObject < nCount; ++nObject ) + { + pMark = rMarkList.GetMark( nObject ); + SdrObject* pObject = pMark->GetMarkedSdrObj(); + pInfo = SdDrawDocument::GetAnimationInfo(pObject); + if( pInfo ) + { + if( bActive != pInfo->mbActive ) + nAnimationSet = ATTR_MIXED; + + if( eEffect != pInfo->meEffect ) + nEffectSet = ATTR_MIXED; + + if( eTextEffect != pInfo->meTextEffect ) + nTextEffectSet = ATTR_MIXED; + + if( eSpeed != pInfo->meSpeed ) + nSpeedSet = ATTR_MIXED; + + if( bFadeOut != pInfo->mbDimPrevious ) + nFadeOutSet = ATTR_MIXED; + + if( aFadeColor != pInfo->maDimColor ) + nFadeColorSet = ATTR_MIXED; + + if( bInvisible != pInfo->mbDimHide ) + nInvisibleSet = ATTR_MIXED; + + if( bSoundOn != pInfo->mbSoundOn ) + nSoundOnSet = ATTR_MIXED; + + if( aSound != pInfo->maSoundFile ) + nSoundFileSet = ATTR_MIXED; + + if( bPlayFull != pInfo->mbPlayFull ) + nPlayFullSet = ATTR_MIXED; + + if( eClickAction != pInfo->meClickAction ) + nClickActionSet = ATTR_MIXED; + + if( aBookmark != pInfo->GetBookmark() ) + nBookmarkSet = ATTR_MIXED; + + if( eSecondEffect != pInfo->meSecondEffect ) + nSecondEffectSet = ATTR_MIXED; + + if( eSecondSpeed != pInfo->meSecondSpeed ) + nSecondSpeedSet = ATTR_MIXED; + + if( bSecondSoundOn != pInfo->mbSecondSoundOn ) + nSecondSoundOnSet = ATTR_MIXED; + + if( bSecondPlayFull != pInfo->mbSecondPlayFull ) + nSecondPlayFullSet = ATTR_MIXED; + } + else + { + if (nAnimationSet == ATTR_SET && bActive) + nAnimationSet = ATTR_MIXED; + + if (nEffectSet == ATTR_SET && eEffect != presentation::AnimationEffect_NONE) + nEffectSet = ATTR_MIXED; + + if (nTextEffectSet == ATTR_SET && eTextEffect != presentation::AnimationEffect_NONE) + nTextEffectSet = ATTR_MIXED; + + if (nSpeedSet == ATTR_SET) + nSpeedSet = ATTR_MIXED; + + if (nFadeOutSet == ATTR_SET && bFadeOut) + nFadeOutSet = ATTR_MIXED; + + if (nFadeColorSet == ATTR_SET) + nFadeColorSet = ATTR_MIXED; + + if (nInvisibleSet == ATTR_SET && bInvisible) + nInvisibleSet = ATTR_MIXED; + + if (nSoundOnSet == ATTR_SET && bSoundOn) + nSoundOnSet = ATTR_MIXED; + + if (nSoundFileSet == ATTR_SET) + nSoundFileSet = ATTR_MIXED; + + if (nPlayFullSet == ATTR_SET && bPlayFull) + nPlayFullSet = ATTR_MIXED; + + if (nClickActionSet == ATTR_SET && eClickAction != presentation::ClickAction_NONE) + nClickActionSet = ATTR_MIXED; + + if (nBookmarkSet == ATTR_SET) + nBookmarkSet = ATTR_MIXED; + + if (nSecondEffectSet == ATTR_SET && eSecondEffect != presentation::AnimationEffect_NONE) + nSecondEffectSet = ATTR_MIXED; + + if (nSecondSpeedSet == ATTR_SET) + nSecondSpeedSet = ATTR_MIXED; + + if (nSecondSoundOnSet == ATTR_SET && bSecondSoundOn) + nSecondSoundOnSet = ATTR_MIXED; + + if (nSecondPlayFullSet == ATTR_SET && bSecondPlayFull) + nSecondPlayFullSet = ATTR_MIXED; + } + } + + /* Exactly two objects with path effect? + Then, only the animation info at the moved object is valid. */ + if (nCount == 2) + { + SdrObject* pObject1 = rMarkList.GetMark(0)->GetMarkedSdrObj(); + SdrObject* pObject2 = rMarkList.GetMark(1)->GetMarkedSdrObj(); + SdrObjKind eKind1 = pObject1->GetObjIdentifier(); + SdrObjKind eKind2 = pObject2->GetObjIdentifier(); + SdAnimationInfo* pInfo1 = SdDrawDocument::GetAnimationInfo(pObject1); + SdAnimationInfo* pInfo2 = SdDrawDocument::GetAnimationInfo(pObject2); + pInfo = nullptr; + + if (pObject1->GetObjInventor() == SdrInventor::Default && + ((eKind1 == SdrObjKind::Line) || // 2 point line + (eKind1 == SdrObjKind::PolyLine) || // Polygon + (eKind1 == SdrObjKind::PathLine)) && // Bezier curve + (pInfo2 && pInfo2->meEffect == presentation::AnimationEffect_PATH)) + { + pInfo = pInfo2; + } + + if (pObject2->GetObjInventor() == SdrInventor::Default && + ((eKind2 == SdrObjKind::Line) || // 2 point line + (eKind2 == SdrObjKind::PolyLine) || // Polygon + (eKind2 == SdrObjKind::PathLine)) && // Bezier curve + (pInfo1 && pInfo1->meEffect == presentation::AnimationEffect_PATH)) + { + pInfo = pInfo1; + } + + if (pInfo) + { + bActive = pInfo->mbActive; nAnimationSet = ATTR_SET; + eEffect = pInfo->meEffect; nEffectSet = ATTR_SET; + eTextEffect = pInfo->meTextEffect; nTextEffectSet = ATTR_SET; + eSpeed = pInfo->meSpeed; nSpeedSet = ATTR_SET; + bFadeOut = pInfo->mbDimPrevious; nFadeOutSet = ATTR_SET; + aFadeColor = pInfo->maDimColor; nFadeColorSet = ATTR_SET; + bInvisible = pInfo->mbDimHide; nInvisibleSet = ATTR_SET; + bSoundOn = pInfo->mbSoundOn; nSoundOnSet = ATTR_SET; + aSound = pInfo->maSoundFile; nSoundFileSet = ATTR_SET; + bPlayFull = pInfo->mbPlayFull; nPlayFullSet = ATTR_SET; + eClickAction = pInfo->meClickAction; nClickActionSet = ATTR_SET; + aBookmark = pInfo->GetBookmark(); nBookmarkSet = ATTR_SET; + eSecondEffect = pInfo->meSecondEffect; nSecondEffectSet = ATTR_SET; + eSecondSpeed = pInfo->meSecondSpeed; nSecondSpeedSet = ATTR_SET; + bSecondSoundOn = pInfo->mbSecondSoundOn; nSecondSoundOnSet = ATTR_SET; + bSecondPlayFull = pInfo->mbSecondPlayFull; nSecondPlayFullSet = ATTR_SET; + } + } + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if(!pArgs) + { + // fill ItemSet for dialog + SfxItemSetFixed<ATTR_ANIMATION_START, ATTR_ACTION_END> aSet(mpDoc->GetPool()); + + // fill the set + if (nAnimationSet == ATTR_SET) + aSet.Put( SfxBoolItem( ATTR_ANIMATION_ACTIVE, bActive)); + else if (nAnimationSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ANIMATION_ACTIVE); + else + aSet.Put(SfxBoolItem(ATTR_ANIMATION_ACTIVE, false)); + + if (nEffectSet == ATTR_SET) + aSet.Put(SfxUInt16Item(ATTR_ANIMATION_EFFECT, static_cast<sal_uInt16>(eEffect))); + else if (nEffectSet == ATTR_MIXED) + aSet.InvalidateItem( ATTR_ANIMATION_EFFECT ); + else + aSet.Put(SfxUInt16Item(ATTR_ANIMATION_EFFECT, sal_uInt16(presentation::AnimationEffect_NONE))); + + if (nTextEffectSet == ATTR_SET) + aSet.Put(SfxUInt16Item(ATTR_ANIMATION_TEXTEFFECT, static_cast<sal_uInt16>(eTextEffect))); + else if (nTextEffectSet == ATTR_MIXED) + aSet.InvalidateItem( ATTR_ANIMATION_TEXTEFFECT ); + else + aSet.Put(SfxUInt16Item(ATTR_ANIMATION_TEXTEFFECT, sal_uInt16(presentation::AnimationEffect_NONE))); + + if (nSpeedSet == ATTR_SET) + aSet.Put(SfxUInt16Item(ATTR_ANIMATION_SPEED, static_cast<sal_uInt16>(eSpeed))); + else + aSet.InvalidateItem(ATTR_ANIMATION_SPEED); + + if (nFadeOutSet == ATTR_SET) + aSet.Put(SfxBoolItem(ATTR_ANIMATION_FADEOUT, bFadeOut)); + else if (nFadeOutSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ANIMATION_FADEOUT); + else + aSet.Put(SfxBoolItem(ATTR_ANIMATION_FADEOUT, false)); + + if (nFadeColorSet == ATTR_SET) + aSet.Put(SvxColorItem(aFadeColor, ATTR_ANIMATION_COLOR)); + else if (nFadeColorSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ANIMATION_COLOR); + else + aSet.Put(SvxColorItem(COL_LIGHTGRAY, ATTR_ANIMATION_COLOR)); + + if (nInvisibleSet == ATTR_SET) + aSet.Put(SfxBoolItem(ATTR_ANIMATION_INVISIBLE, bInvisible)); + else if (nInvisibleSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ANIMATION_INVISIBLE); + else + aSet.Put(SfxBoolItem(ATTR_ANIMATION_INVISIBLE, false)); + + if (nSoundOnSet == ATTR_SET) + aSet.Put(SfxBoolItem(ATTR_ANIMATION_SOUNDON, bSoundOn)); + else if (nSoundOnSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ANIMATION_SOUNDON); + else + aSet.Put(SfxBoolItem(ATTR_ANIMATION_SOUNDON, false)); + + if (nSoundFileSet == ATTR_SET) + aSet.Put(SfxStringItem(ATTR_ANIMATION_SOUNDFILE, aSound)); + else + aSet.InvalidateItem(ATTR_ANIMATION_SOUNDFILE); + + if (nPlayFullSet == ATTR_SET) + aSet.Put(SfxBoolItem(ATTR_ANIMATION_PLAYFULL, bPlayFull)); + else if (nPlayFullSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ANIMATION_PLAYFULL); + else + aSet.Put(SfxBoolItem(ATTR_ANIMATION_PLAYFULL, false)); + + if (nClickActionSet == ATTR_SET) + aSet.Put(SfxUInt16Item(ATTR_ACTION, static_cast<sal_uInt16>(eClickAction))); + else if (nClickActionSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ACTION); + else + aSet.Put(SfxUInt16Item(ATTR_ACTION, sal_uInt16(presentation::ClickAction_NONE))); + + if (nBookmarkSet == ATTR_SET) + aSet.Put(SfxStringItem(ATTR_ACTION_FILENAME, aBookmark)); + else + aSet.InvalidateItem(ATTR_ACTION_FILENAME); + + if (nSecondEffectSet == ATTR_SET) + aSet.Put(SfxUInt16Item(ATTR_ACTION_EFFECT, static_cast<sal_uInt16>(eSecondEffect))); + else if (nSecondEffectSet == ATTR_MIXED) + aSet.InvalidateItem( ATTR_ACTION_EFFECT ); + else + aSet.Put(SfxUInt16Item(ATTR_ACTION_EFFECT, sal_uInt16(presentation::AnimationEffect_NONE))); + + if (nSecondSpeedSet == ATTR_SET) + aSet.Put(SfxUInt16Item(ATTR_ACTION_EFFECTSPEED, static_cast<sal_uInt16>(eSecondSpeed))); + else + aSet.InvalidateItem(ATTR_ACTION_EFFECTSPEED); + + if (nSecondSoundOnSet == ATTR_SET) + aSet.Put(SfxBoolItem(ATTR_ACTION_SOUNDON, bSecondSoundOn)); + else if (nSecondSoundOnSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ACTION_SOUNDON); + else + aSet.Put(SfxBoolItem(ATTR_ACTION_SOUNDON, false)); + + if (nSecondPlayFullSet == ATTR_SET) + aSet.Put(SfxBoolItem(ATTR_ACTION_PLAYFULL, bSecondPlayFull)); + else if (nSecondPlayFullSet == ATTR_MIXED) + aSet.InvalidateItem(ATTR_ACTION_PLAYFULL); + else + aSet.Put(SfxBoolItem(ATTR_ACTION_PLAYFULL, false)); + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractDialog> pDlg( pFact->CreatSdActionDialog(mpViewShell->GetFrameWeld(), &aSet, mpView) ); + + short nResult = pDlg->Execute(); + + if( nResult != RET_OK ) + return; + + rReq.Done( *( pDlg->GetOutputItemSet() ) ); + pArgs = rReq.GetArgs(); + } + + // evaluation of the ItemSets + if (pArgs->GetItemState(ATTR_ANIMATION_ACTIVE) == SfxItemState::SET) + { + bActive = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_ANIMATION_ACTIVE)).GetValue(); + nAnimationSet = ATTR_SET; + } + else + nAnimationSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_EFFECT) == SfxItemState::SET) + { + eEffect = static_cast<presentation::AnimationEffect>(static_cast<const SfxUInt16Item&>( pArgs-> + Get(ATTR_ANIMATION_EFFECT)).GetValue()); + nEffectSet = ATTR_SET; + } + else + nEffectSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_TEXTEFFECT) == SfxItemState::SET) + { + eTextEffect = static_cast<presentation::AnimationEffect>(static_cast<const SfxUInt16Item&>( pArgs-> + Get(ATTR_ANIMATION_TEXTEFFECT)).GetValue()); + nTextEffectSet = ATTR_SET; + } + else + nTextEffectSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_SPEED) == SfxItemState::SET) + { + eSpeed = static_cast<presentation::AnimationSpeed>(static_cast<const SfxUInt16Item&>( pArgs-> + Get(ATTR_ANIMATION_SPEED)).GetValue()); + nSpeedSet = ATTR_SET; + } + else + nSpeedSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_FADEOUT) == SfxItemState::SET) + { + bFadeOut = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_ANIMATION_FADEOUT)).GetValue(); + nFadeOutSet = ATTR_SET; + } + else + nFadeOutSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_INVISIBLE) == SfxItemState::SET) + { + bInvisible = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_ANIMATION_INVISIBLE)).GetValue(); + nInvisibleSet = ATTR_SET; + } + else + nInvisibleSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_SOUNDON) == SfxItemState::SET) + { + bSoundOn = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_ANIMATION_SOUNDON)).GetValue(); + nSoundOnSet = ATTR_SET; + } + else + nSoundOnSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_SOUNDFILE) == SfxItemState::SET) + { + aSound = static_cast<const SfxStringItem&>(pArgs->Get(ATTR_ANIMATION_SOUNDFILE)).GetValue(); + nSoundFileSet = ATTR_SET; + } + else + nSoundFileSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_COLOR) == SfxItemState::SET) + { + aFadeColor = static_cast<const SvxColorItem&>(pArgs->Get(ATTR_ANIMATION_COLOR)).GetValue(); + nFadeColorSet = ATTR_SET; + } + else + nFadeColorSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ANIMATION_PLAYFULL) == SfxItemState::SET) + { + bPlayFull = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_ANIMATION_PLAYFULL)).GetValue(); + nPlayFullSet = ATTR_SET; + } + else + nPlayFullSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ACTION) == SfxItemState::SET) + { + eClickAction = static_cast<presentation::ClickAction>(static_cast<const SfxUInt16Item&>(pArgs-> + Get(ATTR_ACTION)).GetValue()); + nClickActionSet = ATTR_SET; + } + else + nClickActionSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ACTION_FILENAME) == SfxItemState::SET) + { + aBookmark = static_cast<const SfxStringItem&>(pArgs-> + Get(ATTR_ACTION_FILENAME)).GetValue(); + nBookmarkSet = ATTR_SET; + } + else + nBookmarkSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ACTION_EFFECT) == SfxItemState::SET) + { + eSecondEffect = static_cast<presentation::AnimationEffect>(static_cast<const SfxUInt16Item&>( pArgs-> + Get(ATTR_ACTION_EFFECT)).GetValue()); + nSecondEffectSet = ATTR_SET; + } + else + nSecondEffectSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ACTION_EFFECTSPEED) == SfxItemState::SET) + { + eSecondSpeed = static_cast<presentation::AnimationSpeed>(static_cast<const SfxUInt16Item&>( pArgs-> + Get(ATTR_ACTION_EFFECTSPEED)).GetValue()); + nSecondSpeedSet = ATTR_SET; + } + else + nSecondSpeedSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ACTION_SOUNDON) == SfxItemState::SET) + { + bSecondSoundOn = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_ACTION_SOUNDON)).GetValue(); + nSecondSoundOnSet = ATTR_SET; + } + else + nSecondSoundOnSet = ATTR_MISSING; + + if (pArgs->GetItemState(ATTR_ACTION_PLAYFULL) == SfxItemState::SET) + { + bSecondPlayFull = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_ACTION_PLAYFULL)).GetValue(); + nSecondPlayFullSet = ATTR_SET; + } + else + nSecondPlayFullSet = ATTR_MISSING; + + // if any attribute is chosen + if (!(nEffectSet == ATTR_SET || + nTextEffectSet == ATTR_SET || + nSpeedSet == ATTR_SET || + nAnimationSet == ATTR_SET || + nFadeOutSet == ATTR_SET || + nFadeColorSet == ATTR_SET || + nInvisibleSet == ATTR_SET || + nSoundOnSet == ATTR_SET || + nSoundFileSet == ATTR_SET || + nPlayFullSet == ATTR_SET || + nClickActionSet == ATTR_SET || + nBookmarkSet == ATTR_SET || + nSecondEffectSet == ATTR_SET || + nSecondSpeedSet == ATTR_SET || + nSecondSoundOnSet == ATTR_SET || + nSecondPlayFullSet == ATTR_SET)) + return; + + // String for undo-group and list-action + OUString aComment(SdResId(STR_UNDO_ANIMATION)); + + // with 'following curves', we have an additional UndoAction + // therefore cling? here + pUndoMgr->EnterListAction(aComment, aComment, 0, mpViewShell->GetViewShellBase().GetViewShellId()); + + // create undo group + std::unique_ptr<SdUndoGroup> pUndoGroup(new SdUndoGroup(mpDoc)); + pUndoGroup->SetComment(aComment); + + // for the path effect, remember some stuff + SdrPathObj* pPath = nullptr; + if (eEffect == presentation::AnimationEffect_PATH && nEffectSet == ATTR_SET) + { + DBG_ASSERT(nCount == 2, "This effect expects two selected objects"); + SdrObject* pObject1 = rMarkList.GetMark(0)->GetMarkedSdrObj(); + SdrObject* pObject2 = rMarkList.GetMark(1)->GetMarkedSdrObj(); + SdrObjKind eKind1 = pObject1->GetObjIdentifier(); + SdrObjKind eKind2 = pObject2->GetObjIdentifier(); + SdrObject* pRunningObj = nullptr; + + if (pObject1->GetObjInventor() == SdrInventor::Default && + ((eKind1 == SdrObjKind::Line) || // 2 point line + (eKind1 == SdrObjKind::PolyLine) || // Polygon + (eKind1 == SdrObjKind::PathLine))) // Bezier curve + { + pPath = static_cast<SdrPathObj*>(pObject1); + pRunningObj = pObject2; + } + + if (pObject2->GetObjInventor() == SdrInventor::Default && + ((eKind2 == SdrObjKind::Line) || // 2 point line + (eKind2 == SdrObjKind::PolyLine) || // Polygon + (eKind2 == SdrObjKind::PathLine))) // Bezier curve + { + pPath = static_cast<SdrPathObj*>(pObject2); + pRunningObj = pObject1; + } + + assert(pRunningObj && pPath && "no curve found"); + + // push the running object to the end of the curve + if (pRunningObj) + { + ::tools::Rectangle aCurRect(pRunningObj->GetLogicRect()); + Point aCurCenter(aCurRect.Center()); + const ::basegfx::B2DPolyPolygon& rPolyPolygon = pPath->GetPathPoly(); + sal_uInt32 nNoOfPolygons(rPolyPolygon.count()); + const ::basegfx::B2DPolygon& aPolygon(rPolyPolygon.getB2DPolygon(nNoOfPolygons - 1)); + sal_uInt32 nPoints(aPolygon.count()); + const ::basegfx::B2DPoint aNewB2DCenter(aPolygon.getB2DPoint(nPoints - 1)); + const Point aNewCenter(FRound(aNewB2DCenter.getX()), FRound(aNewB2DCenter.getY())); + Size aDistance(aNewCenter.X() - aCurCenter.X(), aNewCenter.Y() - aCurCenter.Y()); + pRunningObj->Move(aDistance); + + pUndoMgr->AddUndoAction(mpDoc->GetSdrUndoFactory().CreateUndoMoveObject( *pRunningObj, aDistance)); + } + } + + for (size_t nObject = 0; nObject < nCount; ++nObject) + { + SdrObject* pObject = rMarkList.GetMark(nObject)->GetMarkedSdrObj(); + + pInfo = SdDrawDocument::GetAnimationInfo(pObject); + + bool bCreated = false; + if( !pInfo ) + { + pInfo = SdDrawDocument::GetShapeUserData(*pObject,true); + bCreated = true; + } + + // path object for 'following curves'? + if (eEffect == presentation::AnimationEffect_PATH && pObject == pPath) + { + SdAnimationPrmsUndoAction* pAction = new SdAnimationPrmsUndoAction + (mpDoc, pObject, bCreated); + pAction->SetActive(pInfo->mbActive, pInfo->mbActive); + pAction->SetEffect(pInfo->meEffect, pInfo->meEffect); + pAction->SetTextEffect(pInfo->meTextEffect, pInfo->meTextEffect); + pAction->SetSpeed(pInfo->meSpeed, pInfo->meSpeed); + pAction->SetDim(pInfo->mbDimPrevious, pInfo->mbDimPrevious); + pAction->SetDimColor(pInfo->maDimColor, pInfo->maDimColor); + pAction->SetDimHide(pInfo->mbDimHide, pInfo->mbDimHide); + pAction->SetSoundOn(pInfo->mbSoundOn, pInfo->mbSoundOn); + pAction->SetSound(pInfo->maSoundFile, pInfo->maSoundFile); + pAction->SetPlayFull(pInfo->mbPlayFull, pInfo->mbPlayFull); + pAction->SetClickAction(pInfo->meClickAction, pInfo->meClickAction); + pAction->SetBookmark(pInfo->GetBookmark(), pInfo->GetBookmark()); + pAction->SetVerb(pInfo->mnVerb, pInfo->mnVerb); + pAction->SetSecondEffect(pInfo->meSecondEffect, pInfo->meSecondEffect); + pAction->SetSecondSpeed(pInfo->meSecondSpeed, pInfo->meSecondSpeed); + pAction->SetSecondSoundOn(pInfo->mbSecondSoundOn, pInfo->mbSecondSoundOn); + pAction->SetSecondPlayFull(pInfo->mbSecondPlayFull, pInfo->mbSecondPlayFull); + pUndoGroup->AddAction(pAction); + + } + else + { + + // create undo action with old and new sizes + SdAnimationPrmsUndoAction* pAction = new SdAnimationPrmsUndoAction + (mpDoc, pObject, bCreated); + pAction->SetActive(pInfo->mbActive, bActive); + pAction->SetEffect(pInfo->meEffect, eEffect); + pAction->SetTextEffect(pInfo->meTextEffect, eTextEffect); + pAction->SetSpeed(pInfo->meSpeed, eSpeed); + pAction->SetDim(pInfo->mbDimPrevious, bFadeOut); + pAction->SetDimColor(pInfo->maDimColor, aFadeColor); + pAction->SetDimHide(pInfo->mbDimHide, bInvisible); + pAction->SetSoundOn(pInfo->mbSoundOn, bSoundOn); + pAction->SetSound(pInfo->maSoundFile, aSound); + pAction->SetPlayFull(pInfo->mbPlayFull, bPlayFull); + pAction->SetClickAction(pInfo->meClickAction, eClickAction); + pAction->SetBookmark(pInfo->GetBookmark(), aBookmark); + pAction->SetVerb(pInfo->mnVerb, static_cast<sal_uInt16>(pInfo->GetBookmark().toInt32()) ); + pAction->SetSecondEffect(pInfo->meSecondEffect, eSecondEffect); + pAction->SetSecondSpeed(pInfo->meSecondSpeed, eSecondSpeed); + pAction->SetSecondSoundOn(pInfo->mbSecondSoundOn, bSecondSoundOn); + pAction->SetSecondPlayFull(pInfo->mbSecondPlayFull,bSecondPlayFull); + pUndoGroup->AddAction(pAction); + + // insert new values at info block of the object + if (nAnimationSet == ATTR_SET) + pInfo->mbActive = bActive; + + if (nEffectSet == ATTR_SET) + pInfo->meEffect = eEffect; + + if (nTextEffectSet == ATTR_SET) + pInfo->meTextEffect = eTextEffect; + + if (nSpeedSet == ATTR_SET) + pInfo->meSpeed = eSpeed; + + if (nFadeOutSet == ATTR_SET) + pInfo->mbDimPrevious = bFadeOut; + + if (nFadeColorSet == ATTR_SET) + pInfo->maDimColor = aFadeColor; + + if (nInvisibleSet == ATTR_SET) + pInfo->mbDimHide = bInvisible; + + if (nSoundOnSet == ATTR_SET) + pInfo->mbSoundOn = bSoundOn; + + if (nSoundFileSet == ATTR_SET) + pInfo->maSoundFile = aSound; + + if (nPlayFullSet == ATTR_SET) + pInfo->mbPlayFull = bPlayFull; + + if (nClickActionSet == ATTR_SET) + pInfo->meClickAction = eClickAction; + + if (nBookmarkSet == ATTR_SET) + pInfo->SetBookmark( aBookmark ); + + if (nSecondEffectSet == ATTR_SET) + pInfo->meSecondEffect = eSecondEffect; + + if (nSecondSpeedSet == ATTR_SET) + pInfo->meSecondSpeed = eSecondSpeed; + + if (nSecondSoundOnSet == ATTR_SET) + pInfo->mbSecondSoundOn = bSecondSoundOn; + + if (nSecondPlayFullSet == ATTR_SET) + pInfo->mbSecondPlayFull = bSecondPlayFull; + + if (eClickAction == presentation::ClickAction_VERB) + pInfo->mnVerb = static_cast<sal_uInt16>(aBookmark.toInt32()); + } + } + // Set the Undo Group in of the Undo Manager + pUndoMgr->AddUndoAction(std::move(pUndoGroup)); + pUndoMgr->LeaveListAction(); + + // Model changed + mpDoc->SetChanged(); + // not seen, therefore we do not need to invalidate at the bindings +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuolbull.cxx b/sd/source/ui/func/fuolbull.cxx new file mode 100644 index 000000000..beb57db5b --- /dev/null +++ b/sd/source/ui/func/fuolbull.cxx @@ -0,0 +1,340 @@ +/* -*- 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 <fuolbull.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <editeng/outliner.hxx> +#include <editeng/eeitem.hxx> +#include <sfx2/request.hxx> +#include <editeng/numitem.hxx> +#include <strings.hxx> + +#include <svx/svxids.hrc> +#include <OutlineView.hxx> +#include <DrawDocShell.hxx> +#include <DrawViewShell.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> +#include <sdabstdlg.hxx> +#include <svx/nbdtmg.hxx> +#include <svx/nbdtmgfact.hxx> +#include <svx/svdoutl.hxx> +#include <memory> + +using namespace svx::sidebar; +namespace sd { + +FuBulletAndPosition::FuBulletAndPosition(ViewShell* pViewShell, ::sd::Window* pWindow, + ::sd::View* pView, SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewShell, pWindow, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuBulletAndPosition::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuBulletAndPosition( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuBulletAndPosition::DoExecute( SfxRequest& rReq ) +{ + const sal_uInt16 nSId = rReq.GetSlot(); + if ( nSId == FN_SVX_SET_BULLET || nSId == FN_SVX_SET_NUMBER ) + { + SetCurrentBulletsNumbering(rReq); + return; + } + + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxStringItem* pPageItem = SfxItemSet::GetItem<SfxStringItem>(pArgs, FN_PARAM_1, false); + + if ( pArgs && !pPageItem ) + { + /* not direct to pOlView; therefore, SdDrawView::SetAttributes can catch + changes to master page and redirect to a template */ + mpView->SetAttributes(*pArgs); + return; + } + + // fill ItemSet for Dialog + SfxItemSet aEditAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aEditAttr ); + + SfxItemSetFixed<EE_PARA_NUMBULLET, EE_PARA_BULLET> aNewAttr( mpViewShell->GetPool() ); + aNewAttr.Put( aEditAttr, false ); + + auto pView = mpView; + + // create and execute dialog + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxBulletAndPositionDlg> pDlg(pFact->CreateSvxBulletAndPositionDlg(mpViewShell->GetFrameWeld(), &aNewAttr, mpView)); + sal_uInt16 nResult = pDlg->Execute(); + + if( nResult == RET_OK ) + { + OutlinerView* pOLV = pView->GetTextEditOutlinerView(); + + std::unique_ptr<OutlineViewModelChangeGuard, o3tl::default_delete<OutlineViewModelChangeGuard>> aGuard; + + if (OutlineView* pOutlineView = dynamic_cast<OutlineView*>(pView)) + { + pOLV = pOutlineView->GetViewByWindow(mpViewShell->GetActiveWindow()); + aGuard.reset(new OutlineViewModelChangeGuard(*pOutlineView)); + } + + if( pOLV ) + pOLV->EnsureNumberingIsOn(); + + const SfxItemSet pOutputSet( *pDlg->GetOutputItemSet( &aNewAttr ) ); + pView->SetAttributes(pOutputSet, /*bReplaceAll=*/false, /*bSlide*/ pDlg->IsSlideScope(), /*bMaster=*/pDlg->IsApplyToMaster()); + } + + rReq.Done(); +} + +void FuBulletAndPosition::SetCurrentBulletsNumbering(SfxRequest& rReq) +{ + if (!mpDoc || !mpView) + return; + + const sal_uInt16 nSId = rReq.GetSlot(); + if ( nSId != FN_SVX_SET_BULLET && nSId != FN_SVX_SET_NUMBER ) + { + // unexpected SfxRequest + return; + } + + const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nSId); + if ( !pItem ) + { + rReq.Done(); + return; + } + + SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END> aNewAttr( mpViewShell->GetPool() ); + { + SfxItemSet aEditAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aEditAttr ); + aNewAttr.Put( aEditAttr, false ); + } + + const DrawViewShell* pDrawViewShell = dynamic_cast< DrawViewShell* >(mpViewShell); + //Init bullet level in "Customize" tab page in bullet dialog in master page view + const bool bInMasterView = pDrawViewShell && pDrawViewShell->GetEditMode() == EditMode::MasterPage; + if ( bInMasterView ) + { + SdrObject* pObj = mpView->GetTextEditObject(); + if( pObj && pObj->GetObjIdentifier() == SdrObjKind::OutlineText ) + { + const sal_uInt16 nLevel = mpView->GetSelectionLevel(); + if( nLevel != 0xFFFF ) + { + //save the itemset value + SfxItemSet aStoreSet( aNewAttr ); + aNewAttr.ClearItem(); + //extend range + aNewAttr.MergeRange( SID_PARAM_NUM_PRESET, SID_PARAM_CUR_NUM_LEVEL ); + aNewAttr.Put( aStoreSet ); + //put current level user selected + aNewAttr.Put( SfxUInt16Item( SID_PARAM_CUR_NUM_LEVEL, nLevel ) ); + } + } + } + + sal_uInt16 nIdx = pItem->GetValue(); + bool bToggle = false; + if( nIdx == sal_uInt16(0xFFFF) ) + { + // If the nIdx is (sal_uInt16)0xFFFF, means set bullet status to on/off + nIdx = 1; + bToggle = true; + } + nIdx--; + + TypedWhichId<SvxNumBulletItem> nNumItemId = SID_ATTR_NUMBERING_RULE; + const SfxPoolItem* pTmpItem = GetNumBulletItem( aNewAttr, nNumItemId ); + std::unique_ptr<SvxNumRule> pNumRule; + if ( pTmpItem ) + { + pNumRule.reset(new SvxNumRule(static_cast<const SvxNumBulletItem*>(pTmpItem)->GetNumRule())); + + // get numbering rule corresponding to <nIdx> and apply the needed number formats to <pNumRule> + NBOTypeMgrBase* pNumRuleMgr = + NBOutlineTypeMgrFact::CreateInstance( + nSId == FN_SVX_SET_BULLET ? NBOType::Bullets : NBOType::Numbering ); + if ( pNumRuleMgr ) + { + sal_uInt16 nActNumLvl = sal_uInt16(0xFFFF); + if(const SfxUInt16Item* pNumLevelItem = aNewAttr.GetItemIfSet(SID_PARAM_CUR_NUM_LEVEL, false)) + nActNumLvl = pNumLevelItem->GetValue(); + + pNumRuleMgr->SetItems(&aNewAttr); + SvxNumRule aTmpRule( *pNumRule ); + if ( nSId == FN_SVX_SET_BULLET && bToggle && nIdx==0 ) + { + // for toggling bullets get default numbering rule + pNumRuleMgr->ApplyNumRule( aTmpRule, nIdx, nActNumLvl, true ); + } + else + { + pNumRuleMgr->ApplyNumRule( aTmpRule, nIdx, nActNumLvl ); + } + + sal_uInt16 nMask = 1; + for(sal_uInt16 i = 0; i < pNumRule->GetLevelCount(); i++) + { + if(nActNumLvl & nMask) + { + const SvxNumberFormat& aFmt(aTmpRule.GetLevel(i)); + pNumRule->SetLevel(i, aFmt); + } + nMask <<= 1; + } + } + } + + OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); + std::unique_ptr<OutlineViewModelChangeGuard, o3tl::default_delete<OutlineViewModelChangeGuard>> aGuard; + if (OutlineView* pView = dynamic_cast<OutlineView*>(mpView)) + { + pOLV = pView->GetViewByWindow(mpViewShell->GetActiveWindow()); + aGuard.reset(new OutlineViewModelChangeGuard(*pView)); + } + + SdrOutliner* pOwner = bInMasterView ? mpView->GetTextEditOutliner() : nullptr; + const bool bOutlinerUndoEnabled = pOwner && !pOwner->IsInUndo() && pOwner->IsUndoEnabled(); + SdrModel* pSdrModel = bInMasterView ? mpView->GetModel() : nullptr; + const bool bModelUndoEnabled = pSdrModel && pSdrModel->IsUndoEnabled(); + + if ( bOutlinerUndoEnabled ) + { + pOwner->UndoActionStart( OLUNDO_ATTR ); + } + else if ( bModelUndoEnabled ) + { + pSdrModel->BegUndo(); + } + + if ( pOLV ) + { + pOLV->ToggleBulletsNumbering( bToggle, nSId == FN_SVX_SET_BULLET, bInMasterView ? nullptr : pNumRule.get() ); + } + else + { + mpView->ChangeMarkedObjectsBulletsNumbering( bToggle, nSId == FN_SVX_SET_BULLET, bInMasterView ? nullptr : pNumRule.get() ); + } + + if (bInMasterView && pNumRule) + { + SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END> aSetAttr( mpViewShell->GetPool() ); + aSetAttr.Put(SvxNumBulletItem( *pNumRule, nNumItemId )); + mpView->SetAttributes(aSetAttr); + } + + if( bOutlinerUndoEnabled ) + { + pOwner->UndoActionEnd(); + } + else if ( bModelUndoEnabled ) + { + pSdrModel->EndUndo(); + } + + pNumRule.reset(); + rReq.Done(); +} + +const SvxNumBulletItem* FuBulletAndPosition::GetNumBulletItem(SfxItemSet& aNewAttr, TypedWhichId<SvxNumBulletItem>& nNumItemId) +{ + const SvxNumBulletItem* pTmpItem = aNewAttr.GetItemIfSet(nNumItemId, false); + + if(pTmpItem) + return pTmpItem; + + nNumItemId = aNewAttr.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE); + pTmpItem = aNewAttr.GetItemIfSet(nNumItemId, false); + if (pTmpItem) + return pTmpItem; + + bool bOutliner = false; + bool bTitle = false; + + if( mpView ) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + const size_t nCount = rMarkList.GetMarkCount(); + + for(size_t nNum = 0; nNum < nCount; ++nNum) + { + SdrObject* pObj = rMarkList.GetMark(nNum)->GetMarkedSdrObj(); + if( pObj->GetObjInventor() == SdrInventor::Default ) + { + switch(pObj->GetObjIdentifier()) + { + case SdrObjKind::TitleText: + bTitle = true; + break; + case SdrObjKind::OutlineText: + bOutliner = true; + break; + default: + break; + } + } + } + } + + const SvxNumBulletItem *pItem = nullptr; + if(bOutliner) + { + SfxStyleSheetBasePool* pSSPool = mpView->GetDocSh()->GetStyleSheetPool(); + SfxStyleSheetBase* pFirstStyleSheet = pSSPool->Find( STR_LAYOUT_OUTLINE + " 1", SfxStyleFamily::Pseudo); + if( pFirstStyleSheet ) + pItem = pFirstStyleSheet->GetItemSet().GetItemIfSet(EE_PARA_NUMBULLET, false); + } + + if( pItem == nullptr ) + pItem = aNewAttr.GetPool()->GetSecondaryPool()->GetPoolDefaultItem(EE_PARA_NUMBULLET); + + //DBG_ASSERT( pItem, "No EE_PARA_NUMBULLET in the Pool!" ); + + aNewAttr.Put(pItem->CloneSetWhich(EE_PARA_NUMBULLET)); + + if(bTitle && aNewAttr.GetItemState(EE_PARA_NUMBULLET) == SfxItemState::SET ) + { + const SvxNumBulletItem* pBulletItem = aNewAttr.GetItem(EE_PARA_NUMBULLET); + const SvxNumRule& rLclRule = pBulletItem->GetNumRule(); + SvxNumRule aNewRule( rLclRule ); + aNewRule.SetFeatureFlag( SvxNumRuleFlags::NO_NUMBERS ); + + SvxNumBulletItem aNewItem( std::move(aNewRule), EE_PARA_NUMBULLET ); + aNewAttr.Put(aNewItem); + } + + pTmpItem = aNewAttr.GetItemIfSet(nNumItemId, false); + return pTmpItem; +} + + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuoltext.cxx b/sd/source/ui/func/fuoltext.cxx new file mode 100644 index 000000000..fe64cac47 --- /dev/null +++ b/sd/source/ui/func/fuoltext.cxx @@ -0,0 +1,305 @@ +/* -*- 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 <fuoltext.hxx> + +#include <sfx2/viewfrm.hxx> +#include <editeng/outliner.hxx> +#include <editeng/flditem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/dispatch.hxx> +#include <tools/debug.hxx> +#include <svl/stritem.hxx> + +#include <svx/svxids.hrc> +#include <app.hrc> +#include <OutlineView.hxx> +#include <Window.hxx> +#include <DrawDocShell.hxx> +#include <ViewShell.hxx> +#include <OutlineViewShell.hxx> + +#include <memory> + +namespace sd { + +const sal_uInt16 SidArray[] = { + SID_STYLE_FAMILY2, + SID_STYLE_FAMILY3, + SID_STYLE_FAMILY5, + SID_STYLE_UPDATE_BY_EXAMPLE, + SID_CUT, + SID_COPY, + SID_PASTE, + SID_SELECTALL, + SID_ATTR_CHAR_FONT, + SID_ATTR_CHAR_POSTURE, + SID_ATTR_CHAR_WEIGHT, + SID_ATTR_CHAR_SHADOWED, + SID_ATTR_CHAR_STRIKEOUT, + SID_ATTR_CHAR_UNDERLINE, + SID_ATTR_CHAR_FONTHEIGHT, + SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_KERNING, + SID_OUTLINE_UP, + SID_OUTLINE_DOWN, + SID_OUTLINE_LEFT, + SID_OUTLINE_RIGHT, + //SID_OUTLINE_FORMAT, + SID_OUTLINE_COLLAPSE_ALL, + //SID_OUTLINE_BULLET, + SID_OUTLINE_COLLAPSE, + SID_OUTLINE_EXPAND_ALL, + SID_OUTLINE_EXPAND, + SID_SET_SUPER_SCRIPT, + SID_SET_SUB_SCRIPT, + SID_HYPERLINK_GETLINK, + SID_DEC_INDENT, + SID_INC_INDENT, + SID_PARASPACE_INCREASE, + SID_PARASPACE_DECREASE, + SID_SCALE, + SID_STATUS_PAGE, + SID_STATUS_LAYOUT, + SID_EXPAND_PAGE, + SID_SUMMARY_PAGE, + 0 }; + + +FuOutlineText::FuOutlineText(ViewShell* pViewShell, ::sd::Window* pWindow, + ::sd::View* pView, SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewShell, pWindow, pView, pDoc, rReq), + pOutlineViewShell (static_cast<OutlineViewShell*>(pViewShell)), + pOutlineView (static_cast<OutlineView*>(pView)) +{ +} + +/** + * forward to OutlinerView + */ +bool FuOutlineText::Command(const CommandEvent& rCEvt) +{ + bool bResult = false; + + OutlinerView* pOlView = + static_cast<OutlineView*>(mpView)->GetViewByWindow(mpWindow); + DBG_ASSERT (pOlView, "no OutlineView found"); + + if (pOlView) + { + pOlView->Command(rCEvt); // unfortunately, we do not get a return value + bResult = true; + } + return bResult; +} + + +rtl::Reference<FuPoor> FuOutlineText::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuOutlineText( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute( rReq ); + return xFunc; +} + +bool FuOutlineText::MouseButtonDown(const MouseEvent& rMEvt) +{ + mpWindow->GrabFocus(); + + bool bReturn = pOutlineView->GetViewByWindow(mpWindow)->MouseButtonDown(rMEvt); + + if (bReturn) + { + // Now the attributes of the current text position can be different + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); + } + else + { + bReturn = FuPoor::MouseButtonDown(rMEvt); + } + + return bReturn; +} + +bool FuOutlineText::MouseMove(const MouseEvent& rMEvt) +{ + bool bReturn = pOutlineView->GetViewByWindow(mpWindow)->MouseMove(rMEvt); + + if (!bReturn) + { + bReturn = FuPoor::MouseMove(rMEvt); + } + + return bReturn; +} + +bool FuOutlineText::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = pOutlineView->GetViewByWindow(mpWindow)->MouseButtonUp(rMEvt); + + if (bReturn) + { + // Now the attributes of the current text position can be different + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); + } + else + { + const SvxFieldItem* pFieldItem = pOutlineView->GetViewByWindow( mpWindow )->GetFieldUnderMousePointer(); + if( pFieldItem ) + { + const SvxFieldData* pField = pFieldItem->GetField(); + + if( auto pURLField = dynamic_cast< const SvxURLField *>( pField ) ) + { + bReturn = true; + mpWindow->ReleaseMouse(); + SfxStringItem aStrItem( SID_FILE_NAME, pURLField->GetURL() ); + SfxStringItem aReferer( SID_REFERER, mpDocSh->GetMedium()->GetName() ); + SfxBoolItem aBrowseItem( SID_BROWSE, true ); + SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); + + if ( rMEvt.IsMod1() ) + { + // open in new frame + pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aStrItem, &aBrowseItem, &aReferer }); + } + else + { + // open in current frame + SfxFrameItem aFrameItem( SID_DOCFRAME, pFrame ); + pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aStrItem, &aFrameItem, &aBrowseItem, &aReferer }); + } + } + } + } + + if( !bReturn ) + bReturn = FuPoor::MouseButtonUp(rMEvt); + + return bReturn; +} + +/** + * Process keyboard input + * @returns sal_True if a KeyEvent is being processed, sal_False otherwise + */ +bool FuOutlineText::KeyInput(const KeyEvent& rKEvt) +{ + bool bReturn = false; + + sal_uInt16 nKeyGroup = rKEvt.GetKeyCode().GetGroup(); + if( !mpDocSh->IsReadOnly() || nKeyGroup == KEYGROUP_CURSOR ) + { + mpWindow->GrabFocus(); + + std::unique_ptr<OutlineViewModelChangeGuard, o3tl::default_delete<OutlineViewModelChangeGuard>> aGuard; + if( (nKeyGroup != KEYGROUP_CURSOR) && (nKeyGroup != KEYGROUP_FKEYS) ) + aGuard.reset( new OutlineViewModelChangeGuard( *pOutlineView ) ); + + bReturn = pOutlineView->GetViewByWindow(mpWindow)->PostKeyEvent(rKEvt); + + if (bReturn) + { + UpdateForKeyPress (rKEvt); + } + else + { + bReturn = FuPoor::KeyInput(rKEvt); + } + } + + return bReturn; +} + +void FuOutlineText::UpdateForKeyPress (const KeyEvent& rEvent) +{ + // Attributes at the current text position may have changed. + mpViewShell->GetViewFrame()->GetBindings().Invalidate(SidArray); + + bool bUpdatePreview = true; + switch (rEvent.GetKeyCode().GetCode()) + { + // When just the cursor has been moved the preview only changes when + // it moved to entries of another page. To prevent unnecessary + // updates we check this here. This is an early rejection test, so + // missing a key is not a problem. + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + case KEY_HOME: + case KEY_END: + case KEY_PAGEUP: + case KEY_PAGEDOWN: + { + SdPage* pCurrentPage = pOutlineViewShell->GetActualPage(); + bUpdatePreview = (pCurrentPage != pOutlineViewShell->GetActualPage()); + } + break; + } + if (bUpdatePreview) + pOutlineViewShell->UpdatePreview (pOutlineViewShell->GetActualPage()); +} + +/** + * Cut object to clipboard + */ +void FuOutlineText::DoCut() +{ + pOutlineView->GetViewByWindow(mpWindow)->Cut(); +} + +/** + * Copy object to clipboard + */ +void FuOutlineText::DoCopy() +{ + pOutlineView->GetViewByWindow(mpWindow)->Copy(); +} + +/** + * Paste object from clipboard + */ +void FuOutlineText::DoPaste() +{ + pOutlineView->GetViewByWindow(mpWindow)->PasteSpecial(); +} + +/** + * Paste object as unformatted text from clipboard + */ +void FuOutlineText::DoPasteUnformatted() +{ + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mpViewShell->GetActiveWindow() ) ); + if (aDataHelper.GetTransferable().is()) + { + OUString aText; + if (aDataHelper.GetString(SotClipboardFormatId::STRING, aText)) + pOutlineView->GetViewByWindow(mpWindow)->InsertText(aText); + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fupage.cxx b/sd/source/ui/func/fupage.cxx new file mode 100644 index 000000000..5427e6b7d --- /dev/null +++ b/sd/source/ui/func/fupage.cxx @@ -0,0 +1,648 @@ +/* -*- 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 <fupage.hxx> + +// arrange Tab-Page + +#include <sfx2/sfxdlg.hxx> +#include <svx/pageitem.hxx> +#include <svx/svxids.hrc> +#include <svl/itempool.hxx> +#include <svl/grabbagitem.hxx> +#include <sfx2/request.hxx> +#include <vcl/prntypes.hxx> +#include <vcl/graphicfilter.hxx> +#include <stlsheet.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <svx/graphichelper.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflbstit.hxx> +#include <svx/xflbmtit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/lrspitem.hxx> +#include <svx/sdr/properties/properties.hxx> +#include <editeng/shaditem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/sizeitem.hxx> +#include <editeng/pbinitem.hxx> +#include <sfx2/opengrf.hxx> +#include <sal/log.hxx> + +#include <strings.hrc> +#include <sdpage.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <pres.hxx> +#include <drawdoc.hxx> +#include <DrawDocShell.hxx> +#include <ViewShell.hxx> +#include <DrawViewShell.hxx> +#include <app.hrc> +#include <unchss.hxx> +#include <undoback.hxx> +#include <sdabstdlg.hxx> +#include <sdresid.hxx> + +#include <memory> + +using namespace com::sun::star; + +namespace sd { + +// 50 cm 28350 +// adapted from writer +#define MAXHEIGHT 28350 +#define MAXWIDTH 28350 + + +static void mergeItemSetsImpl( SfxItemSet& rTarget, const SfxItemSet& rSource ) +{ + const WhichRangesContainer& rRanges = rSource.GetRanges(); + sal_uInt16 p1, p2; + for (sal_Int32 i = 0; i < rRanges.size(); ++i) + { + p1 = rRanges[i].first; + p2 = rRanges[i].second; + + // make ranges discrete + while(i < rRanges.size()-1 && (rRanges[i+1].first - p2 == 1)) + { + p2 = rRanges[i+1].second; + ++i; + } + rTarget.MergeRange( p1, p2 ); + } + + rTarget.Put(rSource); +} + +FuPage::FuPage( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, + SdDrawDocument* pDoc, SfxRequest& rReq ) +: FuPoor(pViewSh, pWin, pView, pDoc, rReq), + mrReq(rReq), + mpArgs( rReq.GetArgs() ), + mbPageBckgrdDeleted( false ), + mbMasterPage( false ), + mbDisplayBackgroundTabPage( true ), + mpPage(nullptr), + mpDrawViewShell(nullptr) +{ +} + +rtl::Reference<FuPoor> FuPage::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuPage( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuPage::DoExecute(SfxRequest& rReq) +{ + mpDrawViewShell = dynamic_cast<DrawViewShell*>(mpViewShell); + DBG_ASSERT( mpDrawViewShell, "sd::FuPage::FuPage(), called without a current DrawViewShell!" ); + + if( mpDrawViewShell ) + { + mbMasterPage = mpDrawViewShell->GetEditMode() == EditMode::MasterPage; + // we don't really want to format page background with SID_ATTR_PAGE[_SIZE] slots + mbDisplayBackgroundTabPage = ( mpDrawViewShell->GetPageKind() == PageKind::Standard) && + ( nSlotId != SID_ATTR_PAGE_SIZE) && ( nSlotId != SID_ATTR_PAGE ); + mpPage = mpDrawViewShell->getCurrentPage(); + } + + if( !mpPage ) + return; + + // if there are no arguments given, open the dialog + if (!mpArgs || mpArgs->GetItemState(SID_SELECT_BACKGROUND) == SfxItemState::SET) + { + mpView->SdrEndTextEdit(); + mpArgs = ExecuteDialog(mpWindow ? mpWindow->GetFrameWeld() : nullptr, rReq); + } + + // if we now have arguments, apply them to current page + if( mpArgs ) + { + ApplyItemSet( mpArgs ); + } +} + +FuPage::~FuPage() +{ +} + +void FuPage::Activate() +{ +} + +void FuPage::Deactivate() +{ +} + +void MergePageBackgroundFilling(SdPage *pPage, SdStyleSheet *pStyleSheet, bool bMasterPage, SfxItemSet& rMergedAttr) +{ + if (bMasterPage) + { + if (pStyleSheet) + mergeItemSetsImpl(rMergedAttr, pStyleSheet->GetItemSet()); + } + else + { + // Only this page, get attributes for background fill + const SfxItemSet& rBackgroundAttributes = pPage->getSdrPageProperties().GetItemSet(); + + if(drawing::FillStyle_NONE != rBackgroundAttributes.Get(XATTR_FILLSTYLE).GetValue()) + { + // page attributes are used, take them + rMergedAttr.Put(rBackgroundAttributes); + } + else + { + if(pStyleSheet + && drawing::FillStyle_NONE != pStyleSheet->GetItemSet().Get(XATTR_FILLSTYLE).GetValue()) + { + // if the page has no fill style, use the settings from the + // background stylesheet (if used) + mergeItemSetsImpl(rMergedAttr, pStyleSheet->GetItemSet()); + } + else + { + // no fill style from page, start with no fill style + rMergedAttr.Put(XFillStyleItem(drawing::FillStyle_NONE)); + } + } + } +} + +const SfxItemSet* FuPage::ExecuteDialog(weld::Window* pParent, const SfxRequest& rReq) +{ + if (!mpDrawViewShell) + return nullptr; + + SfxItemSetFixed< + XATTR_FILL_FIRST, XATTR_FILL_LAST, + EE_PARA_WRITINGDIR, EE_PARA_WRITINGDIR, + SID_ATTR_BORDER_OUTER, SID_ATTR_BORDER_OUTER, + SID_ATTR_BORDER_SHADOW, SID_ATTR_BORDER_SHADOW, + SID_ATTR_PAGE, SID_ATTR_PAGE_SHARED, + SID_ATTR_CHAR_GRABBAG, SID_ATTR_CHAR_GRABBAG, + SID_ATTR_PAGE_COLOR, SID_ATTR_PAGE_FILLSTYLE + > aNewAttr(mpDoc->GetPool()); + // Keep it sorted + aNewAttr.MergeRange(mpDoc->GetPool().GetWhich(SID_ATTR_LRSPACE), + mpDoc->GetPool().GetWhich(SID_ATTR_ULSPACE)); + + // Retrieve additional data for dialog + + SvxShadowItem aShadowItem(SID_ATTR_BORDER_SHADOW); + aNewAttr.Put( aShadowItem ); + SvxBoxItem aBoxItem( SID_ATTR_BORDER_OUTER ); + aNewAttr.Put( aBoxItem ); + + aNewAttr.Put( SvxFrameDirectionItem( + mpDoc->GetDefaultWritingMode() == css::text::WritingMode_RL_TB ? SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB, + EE_PARA_WRITINGDIR ) ); + + // Retrieve page-data for dialog + + SvxPageItem aPageItem( SID_ATTR_PAGE ); + aPageItem.SetDescName( mpPage->GetName() ); + aPageItem.SetPageUsage( SvxPageUsage::All ); + aPageItem.SetLandscape( mpPage->GetOrientation() == Orientation::Landscape ); + aPageItem.SetNumType( mpDoc->GetPageNumType() ); + aNewAttr.Put( aPageItem ); + + // size + maSize = mpPage->GetSize(); + SvxSizeItem aSizeItem( SID_ATTR_PAGE_SIZE, maSize ); + aNewAttr.Put( aSizeItem ); + + // Max size + SvxSizeItem aMaxSizeItem( SID_ATTR_PAGE_MAXSIZE, Size( MAXWIDTH, MAXHEIGHT ) ); + aNewAttr.Put( aMaxSizeItem ); + + // paperbin + SvxPaperBinItem aPaperBinItem( SID_ATTR_PAGE_PAPERBIN, static_cast<sal_uInt8>(mpPage->GetPaperBin()) ); + aNewAttr.Put( aPaperBinItem ); + + SvxLRSpaceItem aLRSpaceItem( static_cast<sal_uInt16>(mpPage->GetLeftBorder()), static_cast<sal_uInt16>(mpPage->GetRightBorder()), 0, 0, mpDoc->GetPool().GetWhich(SID_ATTR_LRSPACE)); + aNewAttr.Put( aLRSpaceItem ); + + SvxULSpaceItem aULSpaceItem( static_cast<sal_uInt16>(mpPage->GetUpperBorder()), static_cast<sal_uInt16>(mpPage->GetLowerBorder()), mpDoc->GetPool().GetWhich(SID_ATTR_ULSPACE)); + aNewAttr.Put( aULSpaceItem ); + + // Application + bool bScale = mpDoc->GetDocumentType() != DocumentType::Draw; + aNewAttr.Put( SfxBoolItem( SID_ATTR_PAGE_EXT1, bScale ) ); + + bool bFullSize = mpPage->IsMasterPage() ? + mpPage->IsBackgroundFullSize() : static_cast<SdPage&>(mpPage->TRG_GetMasterPage()).IsBackgroundFullSize(); + + SfxGrabBagItem grabBag(SID_ATTR_CHAR_GRABBAG); + grabBag.GetGrabBag()["BackgroundFullSize"] <<= bFullSize; + + if (mpDoc->GetDocumentType() == DocumentType::Impress && mpPage->IsMasterPage()) + { + // A master slide may have a theme. + svx::Theme* pTheme = mpPage->getSdrPageProperties().GetTheme(); + if (pTheme) + { + uno::Any aTheme; + pTheme->ToAny(aTheme); + grabBag.GetGrabBag()["Theme"] = aTheme; + } + } + + aNewAttr.Put(grabBag); + + // Merge ItemSet for dialog + + const WhichRangesContainer& rRanges = aNewAttr.GetRanges(); + sal_uInt16 p1 = rRanges[0].first, p2 = rRanges[0].second; + sal_Int32 idx = 1; + while(idx < rRanges.size() && (rRanges[idx].first - p2 == 1)) + { + p2 = rRanges[idx].second; + ++idx; + } + SfxItemSet aMergedAttr( *aNewAttr.GetPool(), p1, p2 ); + + mergeItemSetsImpl( aMergedAttr, aNewAttr ); + + SdStyleSheet* pStyleSheet = mpPage->getPresentationStyle(HID_PSEUDOSHEET_BACKGROUND); + + // merge page background filling to the dialogs input set + if( mbDisplayBackgroundTabPage ) + { + MergePageBackgroundFilling(mpPage, pStyleSheet, mbMasterPage, aMergedAttr); + } + + std::optional< SfxItemSet > pTempSet; + + const sal_uInt16 nId = GetSlotID(); + if (nId == SID_SAVE_BACKGROUND) + { + const XFillStyleItem& rStyleItem = aMergedAttr.Get(XATTR_FILLSTYLE); + if (drawing::FillStyle_BITMAP == rStyleItem.GetValue()) + { + const XFillBitmapItem& rBitmap = aMergedAttr.Get(XATTR_FILLBITMAP); + const GraphicObject& rGraphicObj = rBitmap.GetGraphicObject(); + GraphicHelper::ExportGraphic(pParent, rGraphicObj.GetGraphic(), ""); + } + } + else if (nId == SID_SELECT_BACKGROUND) + { + Graphic aGraphic; + ErrCode nError = ERRCODE_GRFILTER_OPENERROR; + + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + + if (pArgs && pArgs->GetItemState(SID_SELECT_BACKGROUND, true, &pItem) == SfxItemState::SET) + { + OUString aFileName(static_cast<const SfxStringItem*>(pItem)->GetValue()); + OUString aFilterName; + + if (const SfxStringItem* pFilterItem = pArgs->GetItemIfSet(FN_PARAM_FILTER)) + aFilterName = pFilterItem->GetValue(); + + nError = GraphicFilter::LoadGraphic(aFileName, aFilterName, aGraphic, + &GraphicFilter::GetGraphicFilter()); + } + else + { + SvxOpenGraphicDialog aDlg(SdResId(STR_SET_BACKGROUND_PICTURE), pParent); + + nError = aDlg.Execute(); + if (nError == ERRCODE_NONE) + { + nError = aDlg.GetGraphic(aGraphic); + } + } + + if (nError == ERRCODE_NONE) + { + pTempSet.emplace( mpDoc->GetPool(), svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST> ); + + pTempSet->Put( XFillStyleItem( drawing::FillStyle_BITMAP ) ); + + // MigrateItemSet makes sure the XFillBitmapItem will have a unique name + SfxItemSetFixed<XATTR_FILLBITMAP, XATTR_FILLBITMAP> aMigrateSet( mpDoc->GetPool() ); + aMigrateSet.Put(XFillBitmapItem("background", aGraphic)); + SdrModel::MigrateItemSet( &aMigrateSet, &*pTempSet, mpDoc ); + + pTempSet->Put( XFillBmpStretchItem( true )); + pTempSet->Put( XFillBmpTileItem( false )); + } + } + + else + { + bool bIsImpressDoc = mpDrawViewShell->GetDoc()->GetDocumentType() == DocumentType::Impress; + + // create the dialog + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractTabDialog> pDlg( pFact->CreateSdTabPageDialog(mpViewShell->GetFrameWeld(), &aMergedAttr, mpDocSh, mbDisplayBackgroundTabPage, bIsImpressDoc, mbMasterPage) ); + if( pDlg->Execute() == RET_OK ) + pTempSet.emplace( *pDlg->GetOutputItemSet() ); + } + + if (pTempSet && pStyleSheet) + { + pStyleSheet->AdjustToFontHeight(*pTempSet); + + if( mbDisplayBackgroundTabPage ) + { + // if some fillstyle-items are not set in the dialog, then + // try to use the items before + bool bChanges = false; + for( sal_uInt16 i=XATTR_FILL_FIRST; i<XATTR_FILL_LAST; i++ ) + { + if( aMergedAttr.GetItemState( i ) != SfxItemState::DEFAULT ) + { + if( pTempSet->GetItemState( i ) == SfxItemState::DEFAULT ) + pTempSet->Put( aMergedAttr.Get( i ) ); + else + if( aMergedAttr.GetItem( i ) != pTempSet->GetItem( i ) ) + bChanges = true; + } + } + + // if the background for this page was set to invisible, the background-object has to be deleted, too. + const XFillStyleItem* pTempFillStyleItem = pTempSet->GetItem<XFillStyleItem>(XATTR_FILLSTYLE); + assert(pTempFillStyleItem); + if (pTempFillStyleItem->GetValue() == drawing::FillStyle_NONE) + mbPageBckgrdDeleted = true; + else + { + if (pTempSet->GetItemState(XATTR_FILLSTYLE) == SfxItemState::DEFAULT) + { + const XFillStyleItem* pMergedFillStyleItem = aMergedAttr.GetItem<XFillStyleItem>(XATTR_FILLSTYLE); + assert(pMergedFillStyleItem); + if (pMergedFillStyleItem->GetValue() == drawing::FillStyle_NONE) + mbPageBckgrdDeleted = true; + } + } + + const XFillGradientItem* pTempGradItem = pTempSet->GetItem<XFillGradientItem>(XATTR_FILLGRADIENT); + if (pTempGradItem && pTempGradItem->GetName().isEmpty()) + { + // MigrateItemSet guarantees unique gradient names + SfxItemSetFixed<XATTR_FILLGRADIENT, XATTR_FILLGRADIENT> aMigrateSet( mpDoc->GetPool() ); + aMigrateSet.Put( XFillGradientItem("gradient", pTempGradItem->GetGradientValue()) ); + SdrModel::MigrateItemSet( &aMigrateSet, &*pTempSet, mpDoc); + } + + const XFillHatchItem* pTempHatchItem = pTempSet->GetItem<XFillHatchItem>(XATTR_FILLHATCH); + if (pTempHatchItem && pTempHatchItem->GetName().isEmpty()) + { + // MigrateItemSet guarantees unique hatch names + SfxItemSetFixed<XATTR_FILLHATCH, XATTR_FILLHATCH> aMigrateSet( mpDoc->GetPool() ); + aMigrateSet.Put( XFillHatchItem("hatch", pTempHatchItem->GetHatchValue()) ); + SdrModel::MigrateItemSet( &aMigrateSet, &*pTempSet, mpDoc); + } + + if( !mbMasterPage && bChanges && mbPageBckgrdDeleted ) + { + mpBackgroundObjUndoAction.reset( new SdBackgroundObjUndoAction( + *mpDoc, *mpPage, mpPage->getSdrPageProperties().GetItemSet()) ); + + if(!mpPage->IsMasterPage()) + { + // on normal pages, switch off fill attribute usage + SdrPageProperties& rPageProperties = mpPage->getSdrPageProperties(); + rPageProperties.ClearItem( XATTR_FILLBITMAP ); + rPageProperties.ClearItem( XATTR_FILLGRADIENT ); + rPageProperties.ClearItem( XATTR_FILLHATCH ); + rPageProperties.PutItem(XFillStyleItem(drawing::FillStyle_NONE)); + } + } + + + /* Special treatment: reset the INVALIDS to + NULL-Pointer (otherwise INVALIDs or pointer point + to DefaultItems in the template; both would + prevent the attribute inheritance) */ + pTempSet->ClearInvalidItems(); + + if( mbMasterPage ) + { + mpDocSh->GetUndoManager()->AddUndoAction(std::make_unique<StyleSheetUndoAction>( + mpDoc, static_cast<SfxStyleSheet*>(pStyleSheet), &(*pTempSet))); + pStyleSheet->GetItemSet().Put( *pTempSet ); + sdr::properties::CleanupFillProperties( pStyleSheet->GetItemSet() ); + pStyleSheet->Broadcast(SfxHint(SfxHintId::DataChanged)); + } + + // if background filling is set to master pages then clear from page set + if( mbMasterPage ) + { + for( sal_uInt16 nWhich = XATTR_FILL_FIRST; nWhich <= XATTR_FILL_LAST; nWhich++ ) + { + pTempSet->ClearItem( nWhich ); + } + pTempSet->Put(XFillStyleItem(drawing::FillStyle_NONE)); + } + + if( const SvxFrameDirectionItem* pItem = pTempSet->GetItemIfSet( EE_PARA_WRITINGDIR, false ) ) + { + SvxFrameDirection nVal = pItem->GetValue(); + mpDoc->SetDefaultWritingMode( nVal == SvxFrameDirection::Horizontal_RL_TB ? css::text::WritingMode_RL_TB : css::text::WritingMode_LR_TB ); + } + + mpDoc->SetChanged(); + + // BackgroundFill of Masterpage: no hard attributes allowed + SdrPage& rUsedMasterPage = mpPage->IsMasterPage() ? *mpPage : mpPage->TRG_GetMasterPage(); + OSL_ENSURE(rUsedMasterPage.IsMasterPage(), "No MasterPage (!)"); + rUsedMasterPage.getSdrPageProperties().ClearItem(); + OSL_ENSURE(nullptr != rUsedMasterPage.getSdrPageProperties().GetStyleSheet(), + "MasterPage without StyleSheet detected (!)"); + } + + aNewAttr.Put(*pTempSet); + mrReq.Done( aNewAttr ); + + return mrReq.GetArgs(); + } + else + { + return nullptr; + } +} + +void FuPage::ApplyItemSet( const SfxItemSet* pArgs ) +{ + if (!pArgs || !mpDrawViewShell) + return; + + // Set new page-attributes + PageKind ePageKind = mpDrawViewShell->GetPageKind(); + const SfxPoolItem* pPoolItem; + bool bSetPageSizeAndBorder = false; + Size aNewSize(maSize); + sal_Int32 nLeft = -1, nRight = -1, nUpper = -1, nLower = -1; + bool bScaleAll = true; + Orientation eOrientation = mpPage->GetOrientation(); + SdPage* pMasterPage = mpPage->IsMasterPage() ? mpPage : &static_cast<SdPage&>(mpPage->TRG_GetMasterPage()); + bool bFullSize = pMasterPage->IsBackgroundFullSize(); + sal_uInt16 nPaperBin = mpPage->GetPaperBin(); + + if( pArgs->GetItemState(SID_ATTR_PAGE, true, &pPoolItem) == SfxItemState::SET ) + { + mpDoc->SetPageNumType(static_cast<const SvxPageItem*>(pPoolItem)->GetNumType()); + + eOrientation = static_cast<const SvxPageItem*>(pPoolItem)->IsLandscape() ? + Orientation::Landscape : Orientation::Portrait; + + if( mpPage->GetOrientation() != eOrientation ) + bSetPageSizeAndBorder = true; + + mpDrawViewShell->ResetActualPage(); + } + + if( pArgs->GetItemState(SID_ATTR_PAGE_SIZE, true, &pPoolItem) == SfxItemState::SET ) + { + aNewSize = static_cast<const SvxSizeItem*>(pPoolItem)->GetSize(); + + if( mpPage->GetSize() != aNewSize ) + bSetPageSizeAndBorder = true; + } + + if( pArgs->GetItemState(mpDoc->GetPool().GetWhich(SID_ATTR_LRSPACE), + true, &pPoolItem) == SfxItemState::SET ) + { + nLeft = static_cast<const SvxLRSpaceItem*>(pPoolItem)->GetLeft(); + nRight = static_cast<const SvxLRSpaceItem*>(pPoolItem)->GetRight(); + + if( mpPage->GetLeftBorder() != nLeft || mpPage->GetRightBorder() != nRight ) + bSetPageSizeAndBorder = true; + + } + + if( pArgs->GetItemState(mpDoc->GetPool().GetWhich(SID_ATTR_ULSPACE), + true, &pPoolItem) == SfxItemState::SET ) + { + nUpper = static_cast<const SvxULSpaceItem*>(pPoolItem)->GetUpper(); + nLower = static_cast<const SvxULSpaceItem*>(pPoolItem)->GetLower(); + + if( mpPage->GetUpperBorder() != nUpper || mpPage->GetLowerBorder() != nLower ) + bSetPageSizeAndBorder = true; + } + + if( pArgs->GetItemState(mpDoc->GetPool().GetWhich(SID_ATTR_PAGE_EXT1), true, &pPoolItem) == SfxItemState::SET ) + { + bScaleAll = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue(); + } + + if (SfxItemState::SET == pArgs->GetItemState(SID_ATTR_CHAR_GRABBAG, true, &pPoolItem)) + { + SfxGrabBagItem const*const pGrabBag(static_cast<SfxGrabBagItem const*>(pPoolItem)); + if (pGrabBag->GetGrabBag().find("BackgroundFullSize")->second >>= bFullSize) + { + if (pMasterPage->IsBackgroundFullSize() != bFullSize) + { + bSetPageSizeAndBorder = true; + } + } + + if (mpDoc->GetDocumentType() == DocumentType::Impress && mpPage->IsMasterPage()) + { + // The item set may have a theme. + auto it = pGrabBag->GetGrabBag().find("Theme"); + if (it != pGrabBag->GetGrabBag().end()) + { + std::unique_ptr<svx::Theme> pTheme = svx::Theme::FromAny(it->second); + pMasterPage->getSdrPageProperties().SetTheme(std::move(pTheme)); + } + else + { + SAL_WARN("sd.ui", "FuPage::ApplyItemSet: got no theme"); + } + } + } + + // Paper Bin + if( pArgs->GetItemState(mpDoc->GetPool().GetWhich(SID_ATTR_PAGE_PAPERBIN), true, &pPoolItem) == SfxItemState::SET ) + { + nPaperBin = static_cast<const SvxPaperBinItem*>(pPoolItem)->GetValue(); + + if( mpPage->GetPaperBin() != nPaperBin ) + bSetPageSizeAndBorder = true; + } + + if (nLeft == -1 && nUpper != -1) + { + bSetPageSizeAndBorder = true; + nLeft = mpPage->GetLeftBorder(); + nRight = mpPage->GetRightBorder(); + } + else if (nLeft != -1 && nUpper == -1) + { + bSetPageSizeAndBorder = true; + nUpper = mpPage->GetUpperBorder(); + nLower = mpPage->GetLowerBorder(); + } + + if( bSetPageSizeAndBorder || !mbMasterPage ) + mpDrawViewShell->SetPageSizeAndBorder(ePageKind, aNewSize, nLeft, nRight, nUpper, nLower, bScaleAll, eOrientation, nPaperBin, bFullSize ); + + // if bMasterPage==sal_False then create a background-object for this page with the + // properties set in the dialog before, but if mbPageBckgrdDeleted==sal_True then + // the background of this page was set to invisible, so it would be a mistake + // to create a new background-object for this page ! + + if( mbDisplayBackgroundTabPage ) + { + if( !mbMasterPage && !mbPageBckgrdDeleted ) + { + // Only this page + mpBackgroundObjUndoAction.reset( new SdBackgroundObjUndoAction( + *mpDoc, *mpPage, mpPage->getSdrPageProperties().GetItemSet()) ); + SfxItemSet aSet( *pArgs ); + sdr::properties::CleanupFillProperties(aSet); + mpPage->getSdrPageProperties().ClearItem(); + mpPage->getSdrPageProperties().PutItemSet(aSet); + } + } + + // add undo action for background object + if( mpBackgroundObjUndoAction ) + { + // set merge flag, because a SdUndoGroupAction could have been inserted before + mpDocSh->GetUndoManager()->AddUndoAction( std::move(mpBackgroundObjUndoAction), true ); + } + + // Objects can not be bigger than ViewSize + Size aPageSize = mpDoc->GetSdPage(0, ePageKind)->GetSize(); + Size aViewSize(aPageSize.Width() * 3, aPageSize.Height() * 2); + mpDoc->SetMaxObjSize(aViewSize); + + // if necessary, we tell Preview the new context + mpDrawViewShell->UpdatePreview( mpDrawViewShell->GetActualPage() ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuparagr.cxx b/sd/source/ui/func/fuparagr.cxx new file mode 100644 index 000000000..ac5d87636 --- /dev/null +++ b/sd/source/ui/func/fuparagr.cxx @@ -0,0 +1,162 @@ +/* -*- 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 <fuparagr.hxx> +#include <editeng/eeitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/sfxdlg.hxx> +#include <svx/svxids.hrc> +#include <editeng/editdata.hxx> +#include <editeng/lrspitem.hxx> +#include <svx/svdoutl.hxx> +#include <svl/intitem.hxx> + +#include <View.hxx> +#include <ViewShell.hxx> +#include <drawdoc.hxx> +#include <sdabstdlg.hxx> +#include <sdattr.hrc> + +namespace sd { + + +FuParagraph::FuParagraph ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuParagraph::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuParagraph( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuParagraph::DoExecute( SfxRequest& rReq ) +{ + const SfxItemSet* pArgs = rReq.GetArgs(); + + OutlinerView* pOutlView = mpView->GetTextEditOutlinerView(); + ::Outliner* pOutliner = mpView->GetTextEditOutliner(); + + if( !pArgs ) + { + SfxItemSet aEditAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aEditAttr ); + SfxItemPool *pPool = aEditAttr.GetPool(); + SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END, + SID_ATTR_TABSTOP_OFFSET, SID_ATTR_TABSTOP_OFFSET, + ATTR_PARANUMBERING_START, ATTR_PARANUMBERING_END> aNewAttr( *pPool ); + + aNewAttr.Put( aEditAttr ); + + // left border is offset + const ::tools::Long nOff = aNewAttr.Get( EE_PARA_LRSPACE ).GetTextLeft(); + // conversion since TabulatorTabPage always uses Twips! + SfxInt32Item aOff( SID_ATTR_TABSTOP_OFFSET, nOff ); + aNewAttr.Put( aOff ); + + if( pOutlView && pOutliner ) + { + ESelection eSelection = pOutlView->GetSelection(); + aNewAttr.Put( SfxInt16Item( ATTR_NUMBER_NEWSTART_AT, pOutliner->GetNumberingStartValue( eSelection.nStartPara ) ) ); + aNewAttr.Put( SfxBoolItem( ATTR_NUMBER_NEWSTART, pOutliner->IsParaIsNumberingRestart( eSelection.nStartPara ) ) ); + } + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSdParagraphTabDlg(mpViewShell->GetFrameWeld(), &aNewAttr)); + + sal_uInt16 nResult = pDlg->Execute(); + + switch( nResult ) + { + case RET_OK: + { + rReq.Done( *( pDlg->GetOutputItemSet() ) ); + + pArgs = rReq.GetArgs(); + } + break; + + default: + return; // Cancel + } + } + mpView->SetAttributes( *pArgs ); + + if( pOutlView && pOutliner ) + { + ESelection eSelection = pOutlView->GetSelection(); + + if( const SfxBoolItem* pItem = pArgs->GetItemIfSet( ATTR_NUMBER_NEWSTART, false ) ) + { + const bool bNewStart = pItem->GetValue(); + pOutliner->SetParaIsNumberingRestart( eSelection.nStartPara, bNewStart ); + } + + if( const SfxInt16Item* pItem = pArgs->GetItemIfSet( ATTR_NUMBER_NEWSTART_AT, false ) ) + { + const sal_Int16 nStartAt = pItem->GetValue(); + pOutliner->SetNumberingStartValue( eSelection.nStartPara, nStartAt ); + } + } + + // invalidate slots + static const sal_uInt16 SidArray[] = { + SID_ATTR_TABSTOP, + SID_ATTR_PARA_ADJUST_LEFT, + SID_ATTR_PARA_ADJUST_RIGHT, + SID_ATTR_PARA_ADJUST_CENTER, + SID_ATTR_PARA_ADJUST_BLOCK, + SID_ATTR_PARA_LINESPACE, + SID_ATTR_PARA_LINESPACE_10, + SID_ATTR_PARA_LINESPACE_15, + SID_ATTR_PARA_LINESPACE_20, + SID_ATTR_PARA_ULSPACE, + SID_ATTR_PARA_LRSPACE, + SID_DEC_INDENT, + SID_INC_INDENT, + SID_ATTR_PARA_LEFT_TO_RIGHT, + SID_ATTR_PARA_RIGHT_TO_LEFT, + SID_RULER_TEXT_RIGHT_TO_LEFT, + SID_PARASPACE_INCREASE, + SID_PARASPACE_DECREASE, + 0 }; + + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); +} + +void FuParagraph::Activate() +{ +} + +void FuParagraph::Deactivate() +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fupoor.cxx b/sd/source/ui/func/fupoor.cxx new file mode 100644 index 000000000..e901d07a6 --- /dev/null +++ b/sd/source/ui/func/fupoor.cxx @@ -0,0 +1,1135 @@ +/* -*- 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 <fupoor.hxx> + +#include <svx/svxids.hrc> +#include <svx/svdpagv.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdograf.hxx> +#include <vcl/seleng.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <svl/stritem.hxx> + +#include <app.hrc> +#include <fusel.hxx> +#include <sdpage.hxx> +#include <DrawViewShell.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> +#include <DrawDocShell.hxx> +#include <zoomlist.hxx> +#include <slideshow.hxx> +#include <LayerTabBar.hxx> + +#include <com/sun/star/embed/EmbedVerbs.hpp> + +#include <sfx2/viewfrm.hxx> + +#include <svx/svditer.hxx> + +#include <editeng/editeng.hxx> + +using namespace ::com::sun::star; + +namespace sd { + + +FuPoor::FuPoor ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDrDoc, + SfxRequest& rReq) + : mpView(pView), + mpViewShell(pViewSh), + mpWindow(pWin), + mpDocSh( pDrDoc->GetDocSh() ), + mpDoc(pDrDoc), + nSlotId( rReq.GetSlot() ), + aScrollTimer("sd FuPoor aScrollTimer"), + aDragTimer("sd FuPoor aDragTimer"), + bIsInDragMode(false), + bNoScrollUntilInside (true), + aDelayToScrollTimer("sd FuPoor aDelayToScrollTimer"), + bScrollable (false), + bDelayActive (false), + bFirstMouseMove (false), + // remember MouseButton state + mnCode(0) +{ + ReceiveRequest(rReq); + + aScrollTimer.SetInvokeHandler( LINK(this, FuPoor, ScrollHdl) ); + aScrollTimer.SetTimeout(SELENG_AUTOREPEAT_INTERVAL); + + aDragTimer.SetInvokeHandler( LINK(this, FuPoor, DragHdl) ); + aDragTimer.SetTimeout(SELENG_DRAGDROP_TIMEOUT); + + aDelayToScrollTimer.SetInvokeHandler( LINK(this, FuPoor, DelayHdl) ); + aDelayToScrollTimer.SetTimeout(2000); +} + +FuPoor::~FuPoor() +{ + aDragTimer.Stop(); + aScrollTimer.Stop(); + aDelayToScrollTimer.Stop(); +} + +void FuPoor::Activate() +{ +} + +void FuPoor::Deactivate() +{ + aDragTimer.Stop(); + aScrollTimer.Stop(); + aDelayToScrollTimer.Stop (); + bScrollable = bDelayActive = false; + + if (mpWindow && mpWindow->IsMouseCaptured()) + mpWindow->ReleaseMouse(); +} + +void FuPoor::SetWindow(::sd::Window* pWin) +{ + mpWindow = pWin; +} + +/** + * scroll when approached the border of the window; is called by MouseMove + */ +void FuPoor::ForceScroll(const Point& aPixPos) +{ + aScrollTimer.Stop(); + + if ( mpView->IsDragHelpLine() || mpView->IsSetPageOrg() || + SlideShow::IsRunning( mpViewShell->GetViewShellBase() ) ) + return; + + Point aPos = mpWindow->OutputToScreenPixel(aPixPos); + const ::tools::Rectangle& rRect = mpViewShell->GetAllWindowRect(); + + if ( bNoScrollUntilInside ) + { + if ( rRect.Contains(aPos) ) + bNoScrollUntilInside = false; + } + else + { + short dx = 0, dy = 0; + + if ( aPos.X() <= rRect.Left() ) dx = -1; + if ( aPos.X() >= rRect.Right() ) dx = 1; + if ( aPos.Y() <= rRect.Top() ) dy = -1; + if ( aPos.Y() >= rRect.Bottom() ) dy = 1; + + if ( dx != 0 || dy != 0 ) + { + if (bScrollable) + { + // scroll action in derived class + mpViewShell->ScrollLines(dx, dy); + aScrollTimer.Start(); + } + else if (! bDelayActive) StartDelayToScrollTimer (); + } + } +} + +/** + * timer handler for window scrolling + */ +IMPL_LINK_NOARG(FuPoor, ScrollHdl, Timer *, void) +{ + Point aPnt(mpWindow->GetPointerPosPixel()); + + // use remembered MouseButton state to create correct + // MouseEvents for this artificial MouseMove. + MouseMove(MouseEvent(aPnt, 1, MouseEventModifiers::NONE, GetMouseButtonCode())); +} + +/** + * handle keyboard events + * @returns sal_True if the event was handled, sal_False otherwise + */ +bool FuPoor::KeyInput(const KeyEvent& rKEvt) +{ + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + bool bReturn = false; + bool bSlideShow = SlideShow::IsRunning( mpViewShell->GetViewShellBase() ); + + switch (nCode) + { + case KEY_RETURN: + { + if(rKEvt.GetKeyCode().IsMod1()) + { + if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell )) + { + SdPage* pActualPage = pDrawViewShell->GetActualPage(); + SdrTextObj* pCandidate = nullptr; + + if(pActualPage) + { + SdrObjListIter aIter(pActualPage, SdrIterMode::DeepNoGroups); + + while(aIter.IsMore() && !pCandidate) + { + SdrObject* pObj = aIter.Next(); + + if(auto pTextObj = dynamic_cast<SdrTextObj *>( pObj )) + { + SdrInventor nInv(pObj->GetObjInventor()); + SdrObjKind nKnd(pObj->GetObjIdentifier()); + + if(SdrInventor::Default == nInv && + (SdrObjKind::TitleText == nKnd || SdrObjKind::OutlineText == nKnd || SdrObjKind::Text == nKnd)) + { + pCandidate = pTextObj; + } + } + } + } + + if(pCandidate) + { + mpView->UnMarkAll(); + mpView->MarkObj(pCandidate, mpView->GetSdrPageView()); + + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( + SID_ATTR_CHAR, SfxCallMode::ASYNCHRON); + } + else + { + // insert a new page with the same page layout + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( + SID_INSERTPAGE_QUICK, SfxCallMode::ASYNCHRON); + } + + // consumed + bReturn = true; + } + } + else + { + // activate OLE object on RETURN for selected object + // activate text edit on RETURN for selected object + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if( !mpView->IsTextEdit() && 1 == rMarkList.GetMarkCount() ) + { + SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + + if( dynamic_cast< const SdrOle2Obj* >( pObj ) && !mpDocSh->IsUIActive() ) + { + //HMHmpView->HideMarkHdl(); + mpViewShell->ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY); + } + else if( pObj && pObj->IsEmptyPresObj() && dynamic_cast< const SdrGrafObj *>( pObj ) != nullptr ) + { + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_INSERT_GRAPHIC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); + } + else + { + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_ATTR_CHAR, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); + } + + // consumed + bReturn = true; + } + } + } + break; + + case KEY_TAB: + { + // handle Mod1 and Mod2 to get travelling running on different systems + if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2()) + { + // do something with a selected handle? + const SdrHdlList& rHdlList = mpView->GetHdlList(); + bool bForward(!rKEvt.GetKeyCode().IsShift()); + + const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward); + + // guarantee visibility of focused handle + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + + if(pHdl) + { + Point aHdlPosition(pHdl->GetPos()); + ::tools::Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200)); + mpView->MakeVisible(aVisRect, *mpWindow); + } + + // consumed + bReturn = true; + } + } + break; + + case KEY_ESCAPE: + { + bReturn = FuPoor::cancel(); + } + break; + + case KEY_ADD: + { + if (!mpView->IsTextEdit() && !bSlideShow && !mpDocSh->IsUIActive()) + { + // increase zoom + mpViewShell->SetZoom(mpWindow->GetZoom() * 3 / 2); + + if( auto pViewShell = dynamic_cast<DrawViewShell *>( mpViewShell )) + pViewShell->SetZoomOnPage(false); + + bReturn = true; + } + } + break; + + case KEY_SUBTRACT: + { + if (!mpView->IsTextEdit() && !bSlideShow && !mpDocSh->IsUIActive()) + { + // decrease zoom + mpViewShell->SetZoom(mpWindow->GetZoom() * 2 / 3); + + if( auto pViewShell = dynamic_cast<DrawViewShell *>( mpViewShell )) + pViewShell->SetZoomOnPage(false); + + bReturn = true; + } + } + break; + + case KEY_MULTIPLY: + { + if (!mpView->IsTextEdit() && !bSlideShow) + { + // zoom to page + mpViewShell->GetViewFrame()->GetDispatcher()-> + Execute(SID_SIZE_PAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + bReturn = true; + } + } + break; + + case KEY_DIVIDE: + { + if (!mpView->IsTextEdit() && !bSlideShow) + { + // zoom to selected objects + mpViewShell->GetViewFrame()->GetDispatcher()-> + Execute(SID_SIZE_OPTIMAL, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + bReturn = true; + } + } + break; + + case KEY_POINT: + { + ZoomList* pZoomList = mpViewShell->GetZoomList(); + + if (!mpView->IsTextEdit() && pZoomList->IsNextPossible() && !bSlideShow && !mpDocSh->IsUIActive()) + { + // use next ZoomRect + mpViewShell->SetZoomRect(pZoomList->GetNextZoomRect()); + bReturn = true; + } + } + break; + + case KEY_COMMA: + { + ZoomList* pZoomList = mpViewShell->GetZoomList(); + + if (!mpView->IsTextEdit() && pZoomList->IsPreviousPossible() && !bSlideShow && !mpDocSh->IsUIActive()) + { + // use previous ZoomRect + mpViewShell->SetZoomRect(pZoomList->GetPreviousZoomRect()); + bReturn = true; + } + } + break; + + case KEY_HOME: + { + if (!mpView->IsTextEdit() && !bSlideShow) + if (auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell )) + { + // jump to first page + pDrawViewShell->SwitchPage(0); + bReturn = true; + } + } + break; + + case KEY_END: + { + if (!mpView->IsTextEdit() && !bSlideShow) + if (auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell )) + { + // jump to last page + SdPage* pPage = pDrawViewShell->GetActualPage(); + pDrawViewShell->SwitchPage(mpDoc->GetSdPageCount( + pPage->GetPageKind()) - 1); + bReturn = true; + } + } + break; + + case KEY_PAGEUP: + { + if( rKEvt.GetKeyCode().IsMod1() && rKEvt.GetKeyCode().IsMod2() ) + break; + if( bSlideShow) + break; + + if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ) ) + { + // The page-up key switches layers or pages depending on the + // modifier key. + if ( ! rKEvt.GetKeyCode().GetModifier()) + { + // With no modifier pressed we move to the previous + // slide. + mpView->SdrEndTextEdit(); + + // Previous page. + bReturn = true; + SdPage* pPage = pDrawViewShell->GetActualPage(); + sal_uInt16 nSdPage = (pPage->GetPageNum() - 1) / 2; + + if (nSdPage > 0) + { + // Switch the page and send events regarding + // deactivation the old page and activating the new + // one. + TabControl& rPageTabControl = + pDrawViewShell->GetPageTabControl(); + if (rPageTabControl.IsReallyShown()) + rPageTabControl.SendDeactivatePageEvent (); + pDrawViewShell->SwitchPage(nSdPage - 1); + if (rPageTabControl.IsReallyShown()) + rPageTabControl.SendActivatePageEvent (); + } + } + else if (rKEvt.GetKeyCode().IsMod1()) + { + // With the CONTROL modifier we switch layers. + if (pDrawViewShell->IsLayerModeActive()) + { + // Moves to the previous layer. + SwitchLayer (-1); + } + } + } + } + break; + + case KEY_PAGEDOWN: + { + if( rKEvt.GetKeyCode().IsMod1() && rKEvt.GetKeyCode().IsMod2() ) + break; + if(dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr && !bSlideShow) + { + // The page-down key switches layers or pages depending on the + // modifier key. + if ( ! rKEvt.GetKeyCode().GetModifier()) + { + // With no modifier pressed we move to the next slide. + mpView->SdrEndTextEdit(); + + // Next page. + bReturn = true; + SdPage* pPage = static_cast<DrawViewShell*>(mpViewShell)->GetActualPage(); + sal_uInt16 nSdPage = (pPage->GetPageNum() - 1) / 2; + + if (nSdPage < mpDoc->GetSdPageCount(pPage->GetPageKind()) - 1) + { + // Switch the page and send events regarding + // deactivation the old page and activating the new + // one. + TabControl& rPageTabControl = + static_cast<DrawViewShell*>(mpViewShell)->GetPageTabControl(); + if (rPageTabControl.IsReallyShown()) + rPageTabControl.SendDeactivatePageEvent (); + static_cast<DrawViewShell*>(mpViewShell)->SwitchPage(nSdPage + 1); + if (rPageTabControl.IsReallyShown()) + rPageTabControl.SendActivatePageEvent (); + } + } + else if (rKEvt.GetKeyCode().IsMod1()) + { + // With the CONTROL modifier we switch layers. + if (static_cast<DrawViewShell*>(mpViewShell)->IsLayerModeActive()) + { + // With the layer mode active pressing page-down + // moves to the next layer. + SwitchLayer (+1); + } + } + } + } + break; + + // change select state when focus is on poly point + case KEY_SPACE: + { + const SdrHdlList& rHdlList = mpView->GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + + if(pHdl) + { + if(pHdl->GetKind() == SdrHdlKind::Poly) + { + // rescue ID of point with focus + sal_uInt32 nPol(pHdl->GetPolyNum()); + sal_uInt32 nPnt(pHdl->GetPointNum()); + + if(mpView->IsPointMarked(*pHdl)) + { + if(rKEvt.GetKeyCode().IsShift()) + { + mpView->UnmarkPoint(*pHdl); + } + } + else + { + if(!rKEvt.GetKeyCode().IsShift()) + { + mpView->UnmarkAllPoints(); + } + + mpView->MarkPoint(*pHdl); + } + + if(nullptr == rHdlList.GetFocusHdl()) + { + // restore point with focus + SdrHdl* pNewOne = nullptr; + + for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a) + { + SdrHdl* pAct = rHdlList.GetHdl(a); + + if(pAct + && pAct->GetKind() == SdrHdlKind::Poly + && pAct->GetPolyNum() == nPol + && pAct->GetPointNum() == nPnt) + { + pNewOne = pAct; + } + } + + if(pNewOne) + { + const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne); + } + } + + bReturn = true; + } + } + } + break; + + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + { + if (!mpView->IsTextEdit() && !bSlideShow) + { + ::tools::Long nX = 0; + ::tools::Long nY = 0; + + if (nCode == KEY_UP) + { + // scroll up + nX = 0; + nY =-1; + } + else if (nCode == KEY_DOWN) + { + // scroll down + nX = 0; + nY = 1; + } + else if (nCode == KEY_LEFT) + { + // scroll left + nX =-1; + nY = 0; + } + else if (nCode == KEY_RIGHT) + { + // scroll right + nX = 1; + nY = 0; + } + + if (mpView->AreObjectsMarked() && !rKEvt.GetKeyCode().IsMod1() && + !mpDocSh->IsReadOnly()) + { + const SdrHdlList& rHdlList = mpView->GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + + bool bIsMoveOfConnectedHandle(false); + bool bOldSuppress = false; + SdrEdgeObj* pEdgeObj = nullptr; + if(pHdl) + pEdgeObj = dynamic_cast<SdrEdgeObj *>( pHdl->GetObj() ); + + if(pEdgeObj && 0 == pHdl->GetPolyNum()) + { + if(0 == pHdl->GetPointNum()) + { + if(pEdgeObj->GetConnection(true).GetObject()) + { + bIsMoveOfConnectedHandle = true; + } + } + if(1 == pHdl->GetPointNum()) + { + if(pEdgeObj->GetConnection(false).GetObject()) + { + bIsMoveOfConnectedHandle = true; + } + } + } + + if(pEdgeObj) + { + // Suppress default connects to inside object and object center + bOldSuppress = pEdgeObj->GetSuppressDefaultConnect(); + pEdgeObj->SetSuppressDefaultConnect(true); + } + + if(bIsMoveOfConnectedHandle) + { + sal_uInt16 nMarkHdSiz(mpView->GetMarkHdlSizePixel()); + Size aHalfConSiz(nMarkHdSiz + 1, nMarkHdSiz + 1); + aHalfConSiz = mpWindow->PixelToLogic(aHalfConSiz); + + if(100 < aHalfConSiz.Width()) + nX *= aHalfConSiz.Width(); + else + nX *= 100; + + if(100 < aHalfConSiz.Height()) + nY *= aHalfConSiz.Height(); + else + nY *= 100; + } + else if(rKEvt.GetKeyCode().IsMod2()) + { + // move in 1 pixel distance + Size aLogicSizeOnePixel = mpWindow->PixelToLogic(Size(1,1)); + nX *= aLogicSizeOnePixel.Width(); + nY *= aLogicSizeOnePixel.Height(); + } + else if(rKEvt.GetKeyCode().IsShift()) + { + nX *= 1000; + nY *= 1000; + } + else + { + // old, fixed move distance + nX *= 100; + nY *= 100; + } + + if(nullptr == pHdl) + { + // only take action when move is allowed + if(mpView->IsMoveAllowed()) + { + // restrict movement to WorkArea + const ::tools::Rectangle& rWorkArea = mpView->GetWorkArea(); + + if(!rWorkArea.IsEmpty()) + { + ::tools::Rectangle aMarkRect(mpView->GetMarkedObjRect()); + aMarkRect.Move(nX, nY); + + if(!aMarkRect.Contains(rWorkArea)) + { + if(aMarkRect.Left() < rWorkArea.Left()) + { + nX += rWorkArea.Left() - aMarkRect.Left(); + } + + if(aMarkRect.Right() > rWorkArea.Right()) + { + nX -= aMarkRect.Right() - rWorkArea.Right(); + } + + if(aMarkRect.Top() < rWorkArea.Top()) + { + nY += rWorkArea.Top() - aMarkRect.Top(); + } + + if(aMarkRect.Bottom() > rWorkArea.Bottom()) + { + nY -= aMarkRect.Bottom() - rWorkArea.Bottom(); + } + } + } + + // no handle selected + if(0 != nX || 0 != nY) + { + mpView->MoveAllMarked(Size(nX, nY)); + + mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow); + } + } + } + else + { + // move handle with index nHandleIndex + if (nX || nY) + { + // now move the Handle (nX, nY) + Point aStartPoint(pHdl->GetPos()); + Point aEndPoint(pHdl->GetPos() + Point(nX, nY)); + const SdrDragStat& rDragStat = mpView->GetDragStat(); + + // start dragging + mpView->BegDragObj(aStartPoint, nullptr, pHdl, 0); + + if(mpView->IsDragObj()) + { + bool bWasNoSnap = rDragStat.IsNoSnap(); + bool bWasSnapEnabled = mpView->IsSnapEnabled(); + + // switch snapping off + if(!bWasNoSnap) + const_cast<SdrDragStat&>(rDragStat).SetNoSnap(); + if(bWasSnapEnabled) + mpView->SetSnapEnabled(false); + + mpView->MovAction(aEndPoint); + mpView->EndDragObj(); + + // restore snap + if(!bWasNoSnap) + const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap); + if(bWasSnapEnabled) + mpView->SetSnapEnabled(bWasSnapEnabled); + } + + // make moved handle visible + ::tools::Rectangle aVisRect(aEndPoint - Point(100, 100), Size(200, 200)); + mpView->MakeVisible(aVisRect, *mpWindow); + } + } + + if(pEdgeObj) + { + // Restore original suppress value + pEdgeObj->SetSuppressDefaultConnect(bOldSuppress); + } + } + else + { + // scroll page + mpViewShell->ScrollLines(nX, nY); + } + + bReturn = true; + } + } + break; + } + + if (bReturn) + { + mpWindow->ReleaseMouse(); + } + + // when a text-editable object is selected and the + // input character is printable, activate text edit on that object + // and feed character to object + if(!bReturn && !mpDocSh->IsReadOnly()) + { + if (!mpView->IsTextEdit()) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if(1 == rMarkList.GetMarkCount()) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + + // #i118485# allow TextInput for OLEs, too + if( dynamic_cast< const SdrTextObj *>( pObj ) != nullptr && pObj->HasTextEdit()) + { + // use common IsSimpleCharInput from the EditEngine. + bool bPrintable(EditEngine::IsSimpleCharInput(rKEvt)); + + if(bPrintable) + { + // try to activate textedit mode for the selected object + SfxStringItem aInputString(SID_ATTR_CHAR, OUString(rKEvt.GetCharCode())); + + mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_ATTR_CHAR, + SfxCallMode::ASYNCHRON, + { &aInputString }); + + // consumed + bReturn = true; + } + } + } + else + { + // test if there is a title object there. If yes, try to + // set it to edit mode and start typing... + DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(mpViewShell); + if (pDrawViewShell && EditEngine::IsSimpleCharInput(rKEvt)) + { + SdPage* pActualPage = pDrawViewShell->GetActualPage(); + SdrTextObj* pCandidate = nullptr; + + if(pActualPage) + { + SdrObjListIter aIter(pActualPage, SdrIterMode::DeepNoGroups); + + while(aIter.IsMore() && !pCandidate) + { + SdrObject* pObj = aIter.Next(); + + if(auto pTextObj = dynamic_cast< SdrTextObj *>( pObj )) + { + SdrInventor nInv(pObj->GetObjInventor()); + SdrObjKind nKnd(pObj->GetObjIdentifier()); + + if(SdrInventor::Default == nInv && SdrObjKind::TitleText == nKnd) + { + pCandidate = pTextObj; + } + } + } + } + + // when candidate found and candidate is untouched, start editing text... + if(pCandidate && pCandidate->IsEmptyPresObj()) + { + mpView->UnMarkAll(); + mpView->MarkObj(pCandidate, mpView->GetSdrPageView()); + SfxStringItem aInputString(SID_ATTR_CHAR, OUString(rKEvt.GetCharCode())); + + mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_ATTR_CHAR, + SfxCallMode::ASYNCHRON, + { &aInputString }); + + // consumed + bReturn = true; + } + } + } + } + } + + return bReturn; +} + +bool FuPoor::MouseMove(const MouseEvent& ) +{ + return false; +} + +void FuPoor::SelectionHasChanged() +{ + const SdrHdlList& rHdlList = mpView->GetHdlList(); + const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl(); +} + +/** + * Cut object to clipboard + */ +void FuPoor::DoCut() +{ + if (mpView) + { + mpView->DoCut(); + } +} + +/** + * Copy object to clipboard + */ +void FuPoor::DoCopy() +{ + if (mpView) + { + mpView->DoCopy(); + } +} + +/** + * Paste object from clipboard + */ +void FuPoor::DoPaste() +{ + if (mpView) + { + mpView->DoPaste(mpWindow); + } +} + +/** + * Paste unformatted text from clipboard + */ +void FuPoor::DoPasteUnformatted() +{ + if (mpView) + { + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mpViewShell->GetActiveWindow() ) ); + if (aDataHelper.GetTransferable().is()) + { + sal_Int8 nAction = DND_ACTION_COPY; + mpView->InsertData( aDataHelper, + mpWindow->PixelToLogic( ::tools::Rectangle( Point(), mpWindow->GetOutputSizePixel() ).Center() ), + nAction, false, SotClipboardFormatId::STRING); + } + } +} + +/** + * Timer handler for Drag&Drop + */ +IMPL_LINK_NOARG(FuPoor, DragHdl, Timer *, void) +{ + if( !mpView ) + return; + + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + SdrHdl* pHdl = mpView->PickHandle(aMDPos); + + if ( pHdl==nullptr && mpView->IsMarkedHit(aMDPos, nHitLog) + && !mpView->IsPresObjSelected(false) ) + { + mpWindow->ReleaseMouse(); + bIsInDragMode = true; + mpView->StartDrag( aMDPos, mpWindow ); + } +} + +bool FuPoor::Command(const CommandEvent& rCEvt) +{ + return mpView->Command(rCEvt,mpWindow); +} + +/** + * Timer handler for window scrolling + */ +IMPL_LINK_NOARG(FuPoor, DelayHdl, Timer *, void) +{ + aDelayToScrollTimer.Stop (); + bScrollable = true; + + Point aPnt(mpWindow->GetPointerPosPixel()); + + // use remembered MouseButton state to create correct + // MouseEvents for this artificial MouseMove. + MouseMove(MouseEvent(aPnt, 1, MouseEventModifiers::NONE, GetMouseButtonCode())); +} + +bool FuPoor::MouseButtonUp (const MouseEvent& rMEvt) +{ + // remember button state for creation of own MouseEvents + SetMouseButtonCode(rMEvt.GetButtons()); + + aDelayToScrollTimer.Stop (); + bScrollable = bDelayActive = false; + return bScrollable; +} + +bool FuPoor::MouseButtonDown(const MouseEvent& rMEvt) +{ + // remember button state for creation of own MouseEvents + SetMouseButtonCode(rMEvt.GetButtons()); + + return false; +} + +void FuPoor::StartDelayToScrollTimer () +{ + bDelayActive = true; + aDelayToScrollTimer.Start (); +} + +bool FuPoor::RequestHelp(const HelpEvent& rHEvt) +{ + bool bReturn = false; + + SdrPageView* pPV = mpView->GetSdrPageView(); + + if (pPV) + { + SdPage* pPage = static_cast<SdPage*>( pPV->GetPage() ); + + if (pPage) + { + bReturn = FmFormPage::RequestHelp(mpWindow, mpView, rHEvt); + } + } + + return bReturn; +} + +void FuPoor::ReceiveRequest(SfxRequest& /*rReq*/) +{ +} + +SdrObjectUniquePtr FuPoor::CreateDefaultObject(const sal_uInt16, const ::tools::Rectangle& ) +{ + // empty base implementation + return nullptr; +} + +void FuPoor::ImpForceQuadratic(::tools::Rectangle& rRect) +{ + if(rRect.GetWidth() > rRect.GetHeight()) + { + rRect = ::tools::Rectangle( + Point(rRect.Left() + ((rRect.GetWidth() - rRect.GetHeight()) / 2), rRect.Top()), + Size(rRect.GetHeight(), rRect.GetHeight())); + } + else + { + rRect = ::tools::Rectangle( + Point(rRect.Left(), rRect.Top() + ((rRect.GetHeight() - rRect.GetWidth()) / 2)), + Size(rRect.GetWidth(), rRect.GetWidth())); + } +} + +void FuPoor::SwitchLayer (sal_Int32 nOffset) +{ + auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ); + if(!pDrawViewShell) + return; + + // Calculate the new index. + sal_Int32 nIndex = pDrawViewShell->GetActiveTabLayerIndex() + nOffset; + + // Make sure the new index lies inside the range of valid indices. + if (nIndex < 0) + nIndex = 0; + else if (nIndex >= pDrawViewShell->GetTabLayerCount ()) + nIndex = pDrawViewShell->GetTabLayerCount() - 1; + + // Set the new active layer. + if (nIndex != pDrawViewShell->GetActiveTabLayerIndex ()) + { + LayerTabBar* pLayerTabControl = + static_cast<DrawViewShell*>(mpViewShell)->GetLayerTabControl(); + if (pLayerTabControl != nullptr) + pLayerTabControl->SendDeactivatePageEvent (); + + pDrawViewShell->SetActiveTabLayerIndex (nIndex); + + if (pLayerTabControl != nullptr) + pLayerTabControl->SendActivatePageEvent (); + } +} + +/** is called when the current function should be aborted. <p> + This is used when a function gets a KEY_ESCAPE but can also + be called directly. + + @returns true if an active function was aborted +*/ +bool FuPoor::cancel() +{ + if ( dynamic_cast< const FuSelection *>( this ) == nullptr ) + { + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); + return true; + } + + return false; +} + +// #i33136# +bool FuPoor::doConstructOrthogonal() const +{ + // Check whether a media object is selected + bool bResizeKeepRatio = false; + // tdf#89758 Avoid interactive crop preview from being proportionally scaled by default. + if (mpView->AreObjectsMarked() && mpView->GetDragMode() != SdrDragMode::Crop) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + { + SdrObjKind aObjIdentifier = rMarkList.GetMark(0)->GetMarkedSdrObj()->GetObjIdentifier(); + bResizeKeepRatio = aObjIdentifier == SdrObjKind::Graphic || + aObjIdentifier == SdrObjKind::Media || + aObjIdentifier == SdrObjKind::OLE2; + } + } + SdrHdl* pHdl = mpView->PickHandle(aMDPos); + // Resize proportionally when media is selected and the user drags on a corner + if (pHdl) + bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl(); + + return ( + bResizeKeepRatio || + SID_DRAW_XLINE == nSlotId || + SID_DRAW_CIRCLEARC == nSlotId || + SID_DRAW_SQUARE == nSlotId || + SID_DRAW_SQUARE_NOFILL == nSlotId || + SID_DRAW_SQUARE_ROUND == nSlotId || + SID_DRAW_SQUARE_ROUND_NOFILL == nSlotId || + SID_DRAW_CIRCLE == nSlotId || + SID_DRAW_CIRCLE_NOFILL == nSlotId || + SID_DRAW_CIRCLEPIE == nSlotId || + SID_DRAW_CIRCLEPIE_NOFILL == nSlotId || + SID_DRAW_CIRCLECUT == nSlotId || + SID_DRAW_CIRCLECUT_NOFILL == nSlotId || + SID_DRAW_XPOLYGON == nSlotId || + SID_DRAW_XPOLYGON_NOFILL == nSlotId || + SID_3D_CUBE == nSlotId || + SID_3D_SPHERE == nSlotId || + SID_3D_SHELL == nSlotId || + SID_3D_HALF_SPHERE == nSlotId || + SID_3D_TORUS == nSlotId || + SID_3D_CYLINDER == nSlotId || + SID_3D_CONE == nSlotId || + SID_3D_PYRAMID == nSlotId); +} + +void FuPoor::DoExecute( SfxRequest& ) +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuprlout.cxx b/sd/source/ui/func/fuprlout.cxx new file mode 100644 index 000000000..c436b78f0 --- /dev/null +++ b/sd/source/ui/func/fuprlout.cxx @@ -0,0 +1,277 @@ +/* -*- 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 <fuprlout.hxx> +#include <sfx2/dispatch.hxx> + +#include <sfx2/viewfrm.hxx> +#include <sfx2/request.hxx> +#include <svl/stritem.hxx> + +#include <sdattr.hrc> +#include <drawdoc.hxx> +#include <sdpage.hxx> +#include <pres.hxx> +#include <DrawViewShell.hxx> +#include <View.hxx> +#include <glob.hxx> +#include <app.hrc> +#include <DrawDocShell.hxx> +#include <SlideSorterViewShell.hxx> +#include <Window.hxx> +#include <drawview.hxx> +#include <sdabstdlg.hxx> +#include <memory> + +namespace sd +{ + + +#define DOCUMENT_TOKEN '#' + +FuPresentationLayout::FuPresentationLayout ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuPresentationLayout::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuPresentationLayout( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuPresentationLayout::DoExecute( SfxRequest& rReq ) +{ + // prevent selected objects or objects which are under editing from disappearing + mpView->SdrEndTextEdit(); + + if(mpView->GetSdrPageView()) + { + mpView->UnmarkAll(); + } + + bool bError = false; + + /* if we are on a master page, the changes apply for all pages and notes- + pages who are using the relevant layout */ + bool bOnMaster = false; + if (DrawViewShell *pShell = dynamic_cast<DrawViewShell*>(mpViewShell)) + { + EditMode eEditMode = pShell->GetEditMode(); + if (eEditMode == EditMode::MasterPage) + bOnMaster = true; + } + + std::vector<SdPage*> aUnselect; + if (!bOnMaster) + { + //We later rely on IsSelected, so transfer the selection here + //into the document + slidesorter::SlideSorterViewShell* pSlideSorterViewShell + = slidesorter::SlideSorterViewShell::GetSlideSorter(mpViewShell->GetViewShellBase()); + if (pSlideSorterViewShell) + { + std::shared_ptr<slidesorter::SlideSorterViewShell::PageSelection> xSelection( + pSlideSorterViewShell->GetPageSelection()); + if (xSelection) + { + for (SdPage *pPage : *xSelection) + { + if (pPage->IsSelected() || pPage->GetPageKind() != PageKind::Standard) + continue; + mpDoc->SetSelected(pPage, true); + aUnselect.push_back(pPage); + } + } + } + } + + std::vector<SdPage*> aSelectedPages; + std::vector<sal_uInt16> aSelectedPageNums; + // determine the active pages + for (sal_uInt16 nPage = 0; nPage < mpDoc->GetSdPageCount(PageKind::Standard); nPage++) + { + SdPage* pPage = mpDoc->GetSdPage(nPage, PageKind::Standard); + if (pPage->IsSelected()) + { + aSelectedPages.push_back(pPage); + aSelectedPageNums.push_back(nPage); + } + } + + bool bMasterPage = bOnMaster; + bool bCheckMasters = false; + + // call dialog + bool bLoad = false; // appear the new master pages? + OUString aFile; + + SfxItemSetFixed<ATTR_PRESLAYOUT_START, ATTR_PRESLAYOUT_END> aSet(mpDoc->GetPool() ); + + aSet.Put( SfxBoolItem( ATTR_PRESLAYOUT_LOAD, bLoad)); + aSet.Put( SfxBoolItem( ATTR_PRESLAYOUT_MASTER_PAGE, bMasterPage ) ); + aSet.Put( SfxBoolItem( ATTR_PRESLAYOUT_CHECK_MASTERS, bCheckMasters ) ); + + if (!aSelectedPages.empty()) + { + OUString aOldLayoutName(aSelectedPages.back()->GetLayoutName()); + sal_Int32 nPos = aOldLayoutName.indexOf(SD_LT_SEPARATOR); + if (nPos != -1) + aOldLayoutName = aOldLayoutName.copy(0, nPos); + aSet.Put(SfxStringItem(ATTR_PRESLAYOUT_NAME, aOldLayoutName)); + } + + const SfxItemSet *pArgs = rReq.GetArgs (); + + if (pArgs) + { + if (pArgs->GetItemState(ATTR_PRESLAYOUT_LOAD) == SfxItemState::SET) + bLoad = static_cast<const SfxBoolItem&>(pArgs->Get(ATTR_PRESLAYOUT_LOAD)).GetValue(); + if( pArgs->GetItemState( ATTR_PRESLAYOUT_MASTER_PAGE ) == SfxItemState::SET ) + bMasterPage = pArgs->Get( ATTR_PRESLAYOUT_MASTER_PAGE ).GetValue(); + if( pArgs->GetItemState( ATTR_PRESLAYOUT_CHECK_MASTERS ) == SfxItemState::SET ) + bCheckMasters = static_cast<const SfxBoolItem&>( pArgs->Get( ATTR_PRESLAYOUT_CHECK_MASTERS ) ).GetValue(); + if (pArgs->GetItemState(ATTR_PRESLAYOUT_NAME) == SfxItemState::SET) + aFile = pArgs->Get(ATTR_PRESLAYOUT_NAME).GetValue(); + } + else + { + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSdPresLayoutDlg> pDlg(pFact->CreateSdPresLayoutDlg(mpWindow ? mpWindow->GetFrameWeld() : nullptr, mpDocSh, aSet)); + + sal_uInt16 nResult = pDlg->Execute(); + + switch (nResult) + { + case RET_OK: + { + pDlg->GetAttr(aSet); + if (aSet.GetItemState(ATTR_PRESLAYOUT_LOAD) == SfxItemState::SET) + bLoad = static_cast<const SfxBoolItem&>(aSet.Get(ATTR_PRESLAYOUT_LOAD)).GetValue(); + if( aSet.GetItemState( ATTR_PRESLAYOUT_MASTER_PAGE ) == SfxItemState::SET ) + bMasterPage = aSet.Get( ATTR_PRESLAYOUT_MASTER_PAGE ).GetValue(); + if( aSet.GetItemState( ATTR_PRESLAYOUT_CHECK_MASTERS ) == SfxItemState::SET ) + bCheckMasters = static_cast<const SfxBoolItem&>(aSet.Get( ATTR_PRESLAYOUT_CHECK_MASTERS ) ).GetValue(); + if (aSet.GetItemState(ATTR_PRESLAYOUT_NAME) == SfxItemState::SET) + aFile = aSet.Get(ATTR_PRESLAYOUT_NAME).GetValue(); + } + break; + + default: + bError = true; + } + } + + if (bError) + return; + + mpDocSh->SetWaitCursor( true ); + + /* Here, we only exchange masterpages, therefore the current page + remains the current page. To prevent calling PageOrderChangedHint + during insertion and extraction of the masterpages, we block. */ + /* That isn't quite right. If the masterpageview is active and you are + removing a masterpage, it's possible that you are removing the + current masterpage. So you have to call ResetActualPage ! */ + if( dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr && !bCheckMasters ) + static_cast<DrawView*>(mpView)->BlockPageOrderChangedHint(true); + + if (bLoad) + { + sal_Int32 nIdx{ 0 }; + OUString aFileName = aFile.getToken(0, DOCUMENT_TOKEN, nIdx); + SdDrawDocument* pTempDoc = mpDoc->OpenBookmarkDoc( aFileName ); + + // #69581: If I chose the standard-template I got no filename and so I get no + // SdDrawDocument-Pointer. But the method SetMasterPage is able to handle + // a NULL-pointer as a Standard-template ( look at SdDrawDocument::SetMasterPage ) + OUString aLayoutName; + if( pTempDoc ) + aLayoutName = aFile.getToken(0, DOCUMENT_TOKEN, nIdx); + for (auto nSelectedPage : aSelectedPageNums) + mpDoc->SetMasterPage(nSelectedPage, aLayoutName, pTempDoc, bMasterPage, bCheckMasters); + mpDoc->CloseBookmarkDoc(); + } + else + { + // use master page with the layout name aFile from current Doc + for (auto nSelectedPage : aSelectedPageNums) + mpDoc->SetMasterPage(nSelectedPage, aFile, mpDoc, bMasterPage, bCheckMasters); + } + + // remove blocking + if( dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr && !bCheckMasters ) + static_cast<DrawView*>(mpView)->BlockPageOrderChangedHint(false); + + // if the master page was visible, show it again + if (!aSelectedPages.empty()) + { + if (bOnMaster) + { + if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell )) + { + ::sd::View* pView = pDrawViewShell->GetView(); + for (auto pSelectedPage : aSelectedPages) + { + sal_uInt16 nPgNum = pSelectedPage->TRG_GetMasterPage().GetPageNum(); + + if (static_cast<DrawViewShell*>(mpViewShell)->GetPageKind() == PageKind::Notes) + nPgNum++; + + pView->HideSdrPage(); + pView->ShowSdrPage(pView->GetModel()->GetMasterPage(nPgNum)); + } + } + + // force update of TabBar + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_MASTERPAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + } + else + { + for (auto pSelectedPage : aSelectedPages) + pSelectedPage->SetAutoLayout(pSelectedPage->GetAutoLayout()); + } + } + + //Undo transfer to document selection + for (auto pPage : aUnselect) + mpDoc->SetSelected(pPage, false); + + + // fake a mode change to repaint the page tab bar + if( auto pDrawViewSh = dynamic_cast<DrawViewShell *>( mpViewShell ) ) + { + EditMode eMode = pDrawViewSh->GetEditMode(); + bool bLayer = pDrawViewSh->IsLayerModeActive(); + pDrawViewSh->ChangeEditMode( eMode, !bLayer ); + pDrawViewSh->ChangeEditMode( eMode, bLayer ); + } + + mpDocSh->SetWaitCursor( false ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuprobjs.cxx b/sd/source/ui/func/fuprobjs.cxx new file mode 100644 index 000000000..6042d1fbc --- /dev/null +++ b/sd/source/ui/func/fuprobjs.cxx @@ -0,0 +1,154 @@ +/* -*- 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 <fuprobjs.hxx> + +#include <svl/stritem.hxx> +#include <svl/style.hxx> +#include <editeng/outliner.hxx> +#include <svl/hint.hxx> +#include <tools/debug.hxx> + +#include <app.hrc> + +#include <strings.hxx> + +#include <drawdoc.hxx> +#include <sfx2/sfxdlg.hxx> +#include <DrawDocShell.hxx> +#include <OutlineView.hxx> +#include <OutlineViewShell.hxx> +#include <ViewShell.hxx> +#include <Window.hxx> +#include <glob.hxx> +#include <prlayout.hxx> +#include <unchss.hxx> +#include <sdabstdlg.hxx> +#include <memory> + +namespace sd { + + +FuPresentationObjects::FuPresentationObjects ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuPresentationObjects::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuPresentationObjects( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuPresentationObjects::DoExecute( SfxRequest& ) +{ + OutlineViewShell* pOutlineViewShell = dynamic_cast< OutlineViewShell* >( mpViewShell ); + DBG_ASSERT( pOutlineViewShell, "sd::FuPresentationObjects::DoExecute(), does not work without an OutlineViewShell!"); + if( !pOutlineViewShell ) + return; + + /* does the selections end in a unique presentation layout? + if not, it is not allowed to edit the templates */ + SfxItemSetFixed<SID_STATUS_LAYOUT, SID_STATUS_LAYOUT> aSet(mpDoc->GetItemPool() ); + pOutlineViewShell->GetStatusBarState( aSet ); + OUString aLayoutName = static_cast<const SfxStringItem&>(aSet.Get(SID_STATUS_LAYOUT)).GetValue(); + DBG_ASSERT(!aLayoutName.isEmpty(), "Layout not defined"); + + bool bUnique = false; + sal_Int16 nDepth, nTmp; + OutlineView* pOlView = static_cast<OutlineView*>(pOutlineViewShell->GetView()); + OutlinerView* pOutlinerView = pOlView->GetViewByWindow( static_cast<Window*>(mpWindow) ); + ::Outliner* pOutl = pOutlinerView->GetOutliner(); + + std::vector<Paragraph*> aSelList; + pOutlinerView->CreateSelectionList(aSelList); + + Paragraph* pPara = aSelList.empty() ? nullptr : aSelList.front(); + + nDepth = pOutl->GetDepth(pOutl->GetAbsPos( pPara ) ); + bool bPage = ::Outliner::HasParaFlag( pPara, ParaFlag::ISPAGE ); + + for( const auto& rpPara : aSelList ) + { + nTmp = pOutl->GetDepth( pOutl->GetAbsPos( rpPara ) ); + + if( nDepth != nTmp ) + { + bUnique = false; + break; + } + + if( ::Outliner::HasParaFlag( rpPara, ParaFlag::ISPAGE ) != bPage ) + { + bUnique = false; + break; + } + bUnique = true; + } + + if( !bUnique ) + return; + + OUString aStyleName = aLayoutName + SD_LT_SEPARATOR; + PresentationObjects ePO; + + if( bPage ) + { + ePO = PresentationObjects::Title; + aStyleName += STR_LAYOUT_TITLE; + } + else + { + ePO = static_cast<PresentationObjects>( static_cast<int>(PresentationObjects::Outline_1) + nDepth - 1 ); + aStyleName += STR_LAYOUT_OUTLINE + " " + OUString::number(nDepth); + } + + SfxStyleSheetBasePool* pStyleSheetPool = mpDocSh->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStyleSheetPool->Find( aStyleName, SfxStyleFamily::Page ); + DBG_ASSERT(pStyleSheet, "StyleSheet missing"); + + if( !pStyleSheet ) + return; + + SfxStyleSheetBase& rStyleSheet = *pStyleSheet; + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateSdPresLayoutTemplateDlg(mpDocSh, mpViewShell->GetFrameWeld(), + false, rStyleSheet, ePO, pStyleSheetPool)); + if( pDlg->Execute() == RET_OK ) + { + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + // Undo-Action + mpDocSh->GetUndoManager()->AddUndoAction( + std::make_unique<StyleSheetUndoAction>(mpDoc, static_cast<SfxStyleSheet*>(pStyleSheet), pOutSet)); + + pStyleSheet->GetItemSet().Put( *pOutSet ); + static_cast<SfxStyleSheet*>( pStyleSheet )->Broadcast( SfxHint( SfxHintId::DataChanged ) ); + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuscale.cxx b/sd/source/ui/func/fuscale.cxx new file mode 100644 index 000000000..d4730b243 --- /dev/null +++ b/sd/source/ui/func/fuscale.cxx @@ -0,0 +1,179 @@ +/* -*- 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 <fuscale.hxx> + +#include <svx/svxids.hrc> + +#include <app.hrc> +#include <View.hxx> +#include <Window.hxx> +#include <OutlineViewShell.hxx> +#include <drawdoc.hxx> +#include <DrawViewShell.hxx> +#include <ViewShell.hxx> +#include <fuzoom.hxx> + +#include <svx/svdpagv.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/zoomitem.hxx> +#include <sfx2/request.hxx> +#include <svx/svxdlg.hxx> +#include <memory> + +namespace sd { + + +FuScale::FuScale ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuScale::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuScale( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuScale::DoExecute( SfxRequest& rReq ) +{ + sal_Int16 nValue; + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if( !pArgs ) + { + SfxItemSetFixed<SID_ATTR_ZOOM, SID_ATTR_ZOOM> aNewAttr( mpDoc->GetPool() ); + std::unique_ptr<SvxZoomItem> pZoomItem; + SvxZoomEnableFlags nZoomValues = SvxZoomEnableFlags::ALL; + + nValue = static_cast<sal_Int16>(mpWindow->GetZoom()); + + // zoom on page size? + if( dynamic_cast< DrawViewShell *>( mpViewShell ) && + static_cast<DrawViewShell*>(mpViewShell)->IsZoomOnPage() ) + { + pZoomItem.reset(new SvxZoomItem( SvxZoomType::WHOLEPAGE, nValue )); + } + else + { + pZoomItem.reset(new SvxZoomItem( SvxZoomType::PERCENT, nValue )); + } + + // limit range + if( mpViewShell ) + { + if( dynamic_cast< DrawViewShell *>( mpViewShell ) != nullptr ) + { + SdrPageView* pPageView = mpView->GetSdrPageView(); + if( pPageView && pPageView->GetObjList()->GetObjCount() == 0 ) + { + nZoomValues &= ~SvxZoomEnableFlags::OPTIMAL; + } + } + else if( dynamic_cast< OutlineViewShell *>( mpViewShell ) != nullptr ) + { + nZoomValues &= ~SvxZoomEnableFlags::OPTIMAL; + nZoomValues &= ~SvxZoomEnableFlags::WHOLEPAGE; + nZoomValues &= ~SvxZoomEnableFlags::PAGEWIDTH; + } + } + + pZoomItem->SetValueSet( nZoomValues ); + aNewAttr.Put( std::move(pZoomItem) ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSvxZoomDialog> pDlg(pFact->CreateSvxZoomDialog(rReq.GetFrameWeld(), aNewAttr)); + pDlg->SetLimits( static_cast<sal_uInt16>(mpWindow->GetMinZoom()), static_cast<sal_uInt16>(mpWindow->GetMaxZoom()) ); + sal_uInt16 nResult = pDlg->Execute(); + switch( nResult ) + { + case RET_CANCEL: + { + rReq.Ignore (); + return; // Cancel + } + default: + { + rReq.Ignore (); + } + break; + } + + const SfxItemSet aArgs (*(pDlg->GetOutputItemSet ())); + + pDlg.disposeAndClear(); + + if (!mpViewShell) + return; + + switch ( aArgs.Get (SID_ATTR_ZOOM).GetType ()) + { + case SvxZoomType::PERCENT: + { + nValue = aArgs.Get (SID_ATTR_ZOOM).GetValue (); + + mpViewShell->SetZoom( nValue ); + + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArrayZoom ); + } + break; + + case SvxZoomType::OPTIMAL: + { + if( dynamic_cast< DrawViewShell *>( mpViewShell ) != nullptr ) + { + // name confusion: SID_SIZE_ALL -> zoom onto all objects + // --> the program offers it as optimal + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_SIZE_ALL, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + } + } + break; + + case SvxZoomType::PAGEWIDTH: + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_SIZE_PAGE_WIDTH, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + break; + + case SvxZoomType::WHOLEPAGE: + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_SIZE_PAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + break; + default: + break; + } + } + else if(mpViewShell && (pArgs->Count () == 1)) + { + const SfxUInt32Item* pScale = rReq.GetArg<SfxUInt32Item>(ID_VAL_ZOOM); + mpViewShell->SetZoom (pScale->GetValue ()); + + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArrayZoom ); + } + +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fusearch.cxx b/sd/source/ui/func/fusearch.cxx new file mode 100644 index 000000000..73a112bf4 --- /dev/null +++ b/sd/source/ui/func/fusearch.cxx @@ -0,0 +1,140 @@ +/* -*- 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 <fusearch.hxx> + +#include <sfx2/viewfrm.hxx> + +#include <sfx2/bindings.hxx> +#include <fupoor.hxx> +#include <drawdoc.hxx> +#include <app.hrc> +#include <Outliner.hxx> +#include <DrawDocShell.hxx> +#include <DrawViewShell.hxx> +#include <OutlineViewShell.hxx> +#include <ViewShellBase.hxx> + +class SfxRequest; + +namespace sd { + +const sal_uInt16 SidArraySpell[] = { + SID_DRAWINGMODE, + SID_OUTLINE_MODE, + SID_SLIDE_SORTER_MODE, + SID_NOTES_MODE, + SID_HANDOUT_MASTER_MODE, + SID_SLIDE_MASTER_MODE, + SID_NOTES_MASTER_MODE, + 0 }; + +FuSearch::FuSearch ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq ) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq), + m_pSdOutliner(nullptr), + m_bOwnOutliner(false) +{ +} + +FuSearch* FuSearch::createPtr(ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq) +{ + FuSearch* xFunc( new FuSearch( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuSearch::DoExecute( SfxRequest& ) +{ + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArraySpell ); + + if ( dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr ) + { + m_bOwnOutliner = true; + m_pSdOutliner = new SdOutliner( mpDoc, OutlinerMode::TextObject ); + } + else if ( dynamic_cast< const OutlineViewShell *>( mpViewShell ) != nullptr ) + { + m_bOwnOutliner = false; + m_pSdOutliner = mpDoc->GetOutliner(); + } + + if (m_pSdOutliner) + m_pSdOutliner->PrepareSpelling(); +} + +FuSearch::~FuSearch() +{ + if ( ! mpDocSh->IsInDestruction() && mpDocSh->GetViewShell()!=nullptr) + mpDocSh->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SidArraySpell ); + + if (m_pSdOutliner) + m_pSdOutliner->EndSpelling(); + + if (m_bOwnOutliner) + delete m_pSdOutliner; +} + +void FuSearch::SearchAndReplace( const SvxSearchItem* pSearchItem ) +{ + ViewShellBase* pBase = dynamic_cast<ViewShellBase*>( SfxViewShell::Current() ); + ViewShell* pViewShell = nullptr; + if (pBase != nullptr) + pViewShell = pBase->GetMainViewShell().get(); + + if (pViewShell == nullptr) + return; + + if (m_pSdOutliner && dynamic_cast<const DrawViewShell*>(pViewShell) && !m_bOwnOutliner) + { + m_pSdOutliner->EndSpelling(); + + m_bOwnOutliner = true; + m_pSdOutliner = new SdOutliner(mpDoc, OutlinerMode::TextObject); + m_pSdOutliner->PrepareSpelling(); + } + else if (m_pSdOutliner && dynamic_cast<const OutlineViewShell*>(pViewShell) && m_bOwnOutliner) + { + m_pSdOutliner->EndSpelling(); + delete m_pSdOutliner; + + m_bOwnOutliner = false; + m_pSdOutliner = mpDoc->GetOutliner(); + m_pSdOutliner->PrepareSpelling(); + } + + if (m_pSdOutliner) + { + bool bEndSpelling = m_pSdOutliner->StartSearchAndReplace(pSearchItem); + + if (bEndSpelling) + { + m_pSdOutliner->EndSpelling(); + m_pSdOutliner->PrepareSpelling(); + } + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fusel.cxx b/sd/source/ui/func/fusel.cxx new file mode 100644 index 000000000..a525f3bfc --- /dev/null +++ b/sd/source/ui/func/fusel.cxx @@ -0,0 +1,1328 @@ +/* -*- 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 <fusel.hxx> +#include <svx/svddrgmt.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdogrp.hxx> +#include <svx/scene3d.hxx> +#include <vcl/imapobj.hxx> +#include <unotools/securityoptions.hxx> +#include <svx/svxids.hrc> +#include <svx/xfillit0.hxx> +#include <svx/ImageMapInfo.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <editeng/flditem.hxx> + +#include <svx/svdotable.hxx> + +#include <app.hrc> + +#include <sdmod.hxx> +#include <DrawDocShell.hxx> +#include <stlpool.hxx> +#include <fudraw.hxx> +#include <ViewShell.hxx> +#include <ViewShellBase.hxx> +#include <FrameView.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> +#include <DrawViewShell.hxx> +#include <ToolBarManager.hxx> +#include <Client.hxx> + +#include <svx/svdundo.hxx> + +#include <svx/sdrhittesthelper.hxx> +#include <svx/diagram/IDiagramHelper.hxx> + +#include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <comphelper/lok.hxx> + +using namespace ::com::sun::star; + +namespace sd { + +FuSelection::FuSelection ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuDraw(pViewSh, pWin, pView, pDoc, rReq), + bTempRotation(false), + bSelectionChanged(false), + pHdl(nullptr), + bSuppressChangesOfSelection(false), + bMirrorSide0(false), + nEditMode(SID_BEZIER_MOVE), + pWaterCanCandidate(nullptr) + //Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point, + //and SHIFT+ENTER key to decide the position and draw the new insert point + ,bBeginInsertPoint(false), + oldPoint(0,0) + ,bMovedToCenterPoint(false) +{ +} + +rtl::Reference<FuPoor> FuSelection::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuSelection( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuSelection::DoExecute( SfxRequest& rReq ) +{ + FuDraw::DoExecute( rReq ); + + // Select object bar + SelectionHasChanged(); +} + +FuSelection::~FuSelection() +{ + mpView->UnmarkAllPoints(); + mpView->ResetCreationActive(); + + if ( mpView->GetDragMode() != SdrDragMode::Move ) + { + mpView->SetDragMode(SdrDragMode::Move); + } +} + +namespace { + bool lcl_followHyperlinkAllowed(const MouseEvent& rMEvt) { + if (!rMEvt.IsMod1() && SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink)) + return false; + if (rMEvt.IsMod1() && !SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink)) + return false; + return true; + } +} + +bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt) +{ + pHdl = nullptr; + bool bReturn = FuDraw::MouseButtonDown(rMEvt); + bool bWaterCan = SD_MOD()->GetWaterCan(); + const bool bReadOnly = mpDocSh->IsReadOnly(); + // When the right mouse button is pressed then only select objects + // (and deselect others) as a preparation for showing the context + // menu. + const bool bSelectionOnly = rMEvt.IsRight(); + + bMBDown = true; + bSelectionChanged = false; + + if ( mpView->IsAction() ) + { + if ( rMEvt.IsRight() ) + mpView->BckAction(); + return true; + } + + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + + if (comphelper::LibreOfficeKit::isActive()) + { + // When tiled rendering, we always work in logic units, use the non-pixel constants. + nDrgLog = DRGLOG; + nHitLog = HITLOG; + } + + // The following code is executed for right clicks as well as for left + // clicks in order to modify the selection for the right button as a + // preparation for the context menu. The functions BegMarkObject() and + // BegDragObject(), however, are not called for right clicks because a) + // it makes no sense and b) to have IsAction() return sal_False when called + // from Command() which is a prerequisite for the context menu. + if ((rMEvt.IsLeft() || rMEvt.IsRight()) + && !mpView->IsAction() + && (mpView->IsFrameDragSingles() || !mpView->HasMarkablePoints())) + { + /****************************************************************** + * NO BEZIER_EDITOR + ******************************************************************/ + mpWindow->CaptureMouse(); + pHdl = mpView->PickHandle(aMDPos); + + Degree100 nAngle0 = GetAngle(aMDPos - mpView->GetRef1()); + nAngle0 -= 27000_deg100; + nAngle0 = NormAngle36000(nAngle0); + bMirrorSide0 = nAngle0 < 18000_deg100; + + if (!pHdl && mpView->Is3DRotationCreationActive()) + { + /****************************************************************** + * If 3D-rotation bodies are about to be created, + * end creation now. + ******************************************************************/ + bSuppressChangesOfSelection = true; + mpWindow->EnterWait(); + mpView->End3DCreation(); + bSuppressChangesOfSelection = false; + mpView->ResetCreationActive(); + mpWindow->LeaveWait(); + } + + bool bTextEdit = false; + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::TextEditObj && (mpViewShell->GetFrameView()->IsQuickEdit() || dynamic_cast< sdr::table::SdrTableObj* >(aVEvt.mpObj) != nullptr)) + { + bTextEdit = true; + } + + // When clicking into a URl field, also go to text edit mode (when not following the link) + if (!bTextEdit && eHit == SdrHitKind::UrlField && !rMEvt.IsMod2() && !lcl_followHyperlinkAllowed(rMEvt)) + bTextEdit = true; + + bool bPreventModify = mpDocSh->IsReadOnly(); + if (bPreventModify && mpDocSh->GetSignPDFCertificate().is()) + { + // If the just added signature line shape is selected, allow moving / resizing it. + bPreventModify = false; + } + + if(!bTextEdit + && !bPreventModify + && ((mpView->IsMarkedHit(aMDPos, nHitLog) && !rMEvt.IsShift() && !rMEvt.IsMod2()) || pHdl != nullptr) + && (rMEvt.GetClicks() != 2) + ) + { + if (!pHdl && mpView->Is3DRotationCreationActive()) + { + // Switch between 3D-rotation body -> selection + mpView->ResetCreationActive(); + } + else if (bWaterCan) + { + // Remember the selected object for proper handling in + // MouseButtonUp(). + pWaterCanCandidate = pickObject (aMDPos); + } + else + { + // hit handle or marked object + bFirstMouseMove = true; + aDragTimer.Start(); + } + + if ( ! rMEvt.IsRight()) + if (mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog)) + mpView->GetDragMethod()->SetShiftPressed( rMEvt.IsShift() ); + bReturn = true; + } + else + { + SdrPageView* pPV = nullptr; + SdrObject* pObj = !rMEvt.IsMod2() ? mpView->PickObj(aMDPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) : nullptr; + if (pObj) + { + mpView->BegMacroObj(aMDPos, nHitLog, pObj, pPV, mpWindow); + bReturn = true; + } + else if ( bTextEdit ) + { + SdrObjKind nSdrObjKind = aVEvt.mpObj->GetObjIdentifier(); + + if (aVEvt.mpObj->GetObjInventor() == SdrInventor::Default && + (nSdrObjKind == SdrObjKind::Text || + nSdrObjKind == SdrObjKind::TitleText || + nSdrObjKind == SdrObjKind::OutlineText || + !aVEvt.mpObj->IsEmptyPresObj())) + { + // Seamless Editing: branch to text input + if (!rMEvt.IsShift()) + mpView->UnmarkAll(); + + SfxUInt16Item aItem(SID_TEXTEDIT, 1); + mpViewShell->GetViewFrame()->GetDispatcher()-> + ExecuteList(SID_TEXTEDIT, + SfxCallMode::SYNCHRON | SfxCallMode::RECORD, + { &aItem }); + return bReturn; // CAUTION, due to the synchronous slot the object is deleted now + } + } + else if ( !rMEvt.IsMod2() && rMEvt.GetClicks() == 1 && + aVEvt.meEvent == SdrEventKind::ExecuteUrl ) + { + mpWindow->ReleaseMouse(); + + // If tiled rendering, let client handles URL execution and early returns. + if (comphelper::LibreOfficeKit::isActive()) + { + SfxViewShell& rSfxViewShell = mpViewShell->GetViewShellBase(); + rSfxViewShell.libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED, aVEvt.mpURLField->GetURL().toUtf8().getStr()); + return true; + } + + if (!lcl_followHyperlinkAllowed(rMEvt)) + return true; + + SfxStringItem aStrItem(SID_FILE_NAME, aVEvt.mpURLField->GetURL()); + SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName()); + SfxBoolItem aBrowseItem( SID_BROWSE, true ); + SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); + mpWindow->ReleaseMouse(); + + if (rMEvt.IsMod1()) + { + // Open in new frame + pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aStrItem, &aBrowseItem, &aReferer }); + } + else + { + // Open in current frame + SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame); + pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aStrItem, &aFrameItem, &aBrowseItem, &aReferer }); + } + + bReturn = true; + } + else if(!rMEvt.IsMod2() + && dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr + ) + { + pObj = mpView->PickObj(aMDPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER); + if (pObj) + { + // Handle ImageMap click when not just selecting + if (!bSelectionOnly) + { + if (lcl_followHyperlinkAllowed(rMEvt)) + bReturn = HandleImageMapClick(pObj, aMDPos); + } + + if (!bReturn + && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr + || dynamic_cast<const E3dScene*>(pObj) != nullptr)) + { + if (rMEvt.GetClicks() == 1) + { + // Look into the group + pObj = mpView->PickObj(aMDPos, mpView->getHitTolLog(), pPV, + SdrSearchOptions::ALSOONMASTER + | SdrSearchOptions::DEEP); + if (pObj && lcl_followHyperlinkAllowed(rMEvt)) + bReturn = HandleImageMapClick(pObj, aMDPos); + } + else if (!bReadOnly && rMEvt.GetClicks() == 2) + { + // New: double click on selected Group object + // enter group + if (!bSelectionOnly + && pObj->getSdrPageFromSdrObject() == pPV->GetPage()) + bReturn = pPV->EnterGroup(pObj); + } + } + } + + // #i71727# replaced else here with two possibilities, once the original else (!pObj) + // and also ignoring the found object when it's on a masterpage + if(!pObj || (pObj->getSdrPageFromSdrObject() && pObj->getSdrPageFromSdrObject()->IsMasterPage())) + { + if(mpView->IsGroupEntered() && 2 == rMEvt.GetClicks()) + { + // New: double click on empty space/on obj on MasterPage, leave group + mpView->LeaveOneGroup(); + bReturn = true; + } + } + } + + if (!bReturn) + { + if (bWaterCan) + { + if ( ! (rMEvt.IsShift() || rMEvt.IsMod2())) + { + // Find the object under the current mouse position + // and store it for the MouseButtonUp() method to + // evaluate. + pWaterCanCandidate = pickObject (aMDPos); + } + } + else + { + bReturn = true; + bool bDeactivateOLE = false; + + if ( !rMEvt.IsShift() && !rMEvt.IsMod2() ) + { + OSL_ASSERT (mpViewShell->GetViewShell()!=nullptr); + Client* pIPClient = static_cast<Client*>( + mpViewShell->GetViewShell()->GetIPClient()); + + if (pIPClient && pIPClient->IsObjectInPlaceActive()) + { + // OLE-object gets deactivated in subsequent UnmarkAll() + bDeactivateOLE = true; + } + + mpView->UnmarkAll(); + } + + bool bMarked = false; + + if ( !rMEvt.IsMod1() && !bDeactivateOLE) + { + if ( rMEvt.IsMod2() ) + { + bMarked = mpView->MarkNextObj(aMDPos, nHitLog, rMEvt.IsShift() ); + } + else + { + bool bToggle = false; + + if (rMEvt.IsShift() && mpView->GetMarkedObjectList().GetMarkCount() > 1) + { + // No Toggle on single selection + bToggle = true; + } + + bMarked = mpView->MarkObj(aMDPos, nHitLog, bToggle); + } + } + + if( !bDeactivateOLE ) + { + if ( !bReadOnly && + bMarked && + (!rMEvt.IsShift() || mpView->IsMarkedHit(aMDPos, nHitLog))) + { + /********************************************************** + * Move object + **********************************************************/ + aDragTimer.Start(); + + pHdl=mpView->PickHandle(aMDPos); + if ( ! rMEvt.IsRight()) + mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); + } + else + { + /********************************************************** + * Select object + **********************************************************/ + if ( ! rMEvt.IsRight()) + mpView->BegMarkObj(aMDPos); + } + } + + if( bMarked && bTempRotation && (nSlotId == SID_OBJECT_ROTATE) && !rMEvt.IsShift() && (rMEvt.GetClicks() != 2) ) + { + nSlotId = SID_OBJECT_SELECT; + Activate(); + } + } + } + } + } + else if ( !bReadOnly + && (rMEvt.IsLeft() || rMEvt.IsRight()) + && !mpView->IsAction()) + { + /********************************************************************** + * BEZIER-EDITOR + **********************************************************************/ + mpWindow->CaptureMouse(); + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::Handle && aVEvt.mpHdl->GetKind() == SdrHdlKind::BezierWeight) + { + /****************************************************************** + * Drag Handle + ******************************************************************/ + if ( ! rMEvt.IsRight()) + mpView->BegDragObj(aMDPos, nullptr, aVEvt.mpHdl, nDrgLog); + } + else if (eHit == SdrHitKind::MarkedObject && nEditMode == SID_BEZIER_INSERT) + { + /****************************************************************** + * Insert gluepoint + ******************************************************************/ + mpView->BegInsObjPoint(aMDPos, rMEvt.IsMod1()); + } + else if (eHit == SdrHitKind::MarkedObject && rMEvt.IsMod1()) + { + /****************************************************************** + * Select gluepoint + ******************************************************************/ + if (!rMEvt.IsShift()) + mpView->UnmarkAllPoints(); + + if ( ! rMEvt.IsRight()) + mpView->BegMarkPoints(aMDPos); + } + else if (eHit == SdrHitKind::MarkedObject && !rMEvt.IsShift() && !rMEvt.IsMod2()) + { + /****************************************************************** + * Move object + ******************************************************************/ + if ( ! rMEvt.IsRight()) + mpView->BegDragObj(aMDPos, nullptr, nullptr, nDrgLog); + } + else if (eHit == SdrHitKind::Handle) + { + /****************************************************************** + * Select gluepoint + ******************************************************************/ + if (!mpView->IsPointMarked(*aVEvt.mpHdl) || rMEvt.IsShift()) + { + if (!rMEvt.IsShift()) + { + mpView->UnmarkAllPoints(); + pHdl = mpView->PickHandle(aMDPos); + } + else + { + if (mpView->IsPointMarked(*aVEvt.mpHdl)) + { + mpView->UnmarkPoint(*aVEvt.mpHdl); + pHdl = nullptr; + } + else + { + pHdl = mpView->PickHandle(aMDPos); + } + } + + if (pHdl) + { + mpView->MarkPoint(*pHdl); + if ( ! rMEvt.IsRight()) + mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); + + } + } + else + { + // Point IS marked and NO shift is pressed. Start + // dragging of selected point(s) + pHdl = mpView->PickHandle(aMDPos); + if(pHdl && ! rMEvt.IsRight()) + mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); + } + } + else + { + /****************************************************************** + * Select or drag object + ******************************************************************/ + if (!rMEvt.IsShift() && !rMEvt.IsMod2() && eHit == SdrHitKind::UnmarkedObject) + { + mpView->UnmarkAllObj(); + } + + bool bMarked = false; + + if (!rMEvt.IsMod1()) + { + if (rMEvt.IsMod2()) + { + bMarked = mpView->MarkNextObj(aMDPos, nHitLog, rMEvt.IsShift()); + } + else + { + bMarked = mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift()); + } + } + + if (bMarked && + (!rMEvt.IsShift() || eHit == SdrHitKind::MarkedObject)) + { + // Move object + if ( ! rMEvt.IsRight()) + mpView->BegDragObj(aMDPos, nullptr, aVEvt.mpHdl, nDrgLog); + } + else if (mpView->AreObjectsMarked()) + { + /************************************************************** + * Select gluepoint + **************************************************************/ + if (!rMEvt.IsShift()) + mpView->UnmarkAllPoints(); + + if ( ! rMEvt.IsRight()) + mpView->BegMarkPoints(aMDPos); + } + else + { + /************************************************************** + * Select object + **************************************************************/ + if ( ! rMEvt.IsRight()) + mpView->BegMarkObj(aMDPos); + } + + ForcePointer(&rMEvt); + } + } + + if (!bIsInDragMode) + { + ForcePointer(&rMEvt); + } + + return bReturn; +} + +bool FuSelection::MouseMove(const MouseEvent& rMEvt) +{ + bool bReturn = FuDraw::MouseMove(rMEvt); + + if (aDragTimer.IsActive()) + { + if(bFirstMouseMove) + { + bFirstMouseMove = false; + } + else + { + aDragTimer.Stop(); + } + } + + if (mpView->IsAction()) + { + Point aPix(rMEvt.GetPosPixel()); + Point aPnt(mpWindow->PixelToLogic(aPix)); + + ForceScroll(aPix); + + if (mpView->IsInsObjPoint()) + { + mpView->MovInsObjPoint(aPnt); + } + else + { + mpView->MovAction(aPnt); + } + } + + ForcePointer(&rMEvt); + + return bReturn; +} + +bool FuSelection::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = false; + // When the right mouse button is pressed then only select objects + // (and deselect others) as a preparation for showing the context + // menu. + const bool bSelectionOnly = rMEvt.IsRight(); + + if (aDragTimer.IsActive() ) + { + aDragTimer.Stop(); + bIsInDragMode = false; + } + + if( !mpView ) + return false; + + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + + if (mpView->IsFrameDragSingles() || !mpView->HasMarkablePoints()) + { + /********************************************************************** + * NO BEZIER_EDITOR + **********************************************************************/ + if ( mpView->IsDragObj() ) + { + /****************************************************************** + * Object was moved + ******************************************************************/ + FrameView* pFrameView = mpViewShell->GetFrameView(); + bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); + + if (bDragWithCopy) + { + bDragWithCopy = !mpView->IsPresObjSelected(false); + } + + mpView->SetDragWithCopy(bDragWithCopy); + bool bWasDragged(mpView->EndDragObj( mpView->IsDragWithCopy() )); + + mpView->ForceMarkedToAnotherPage(); + + if (!rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() && + !bSelectionChanged && + std::abs(aPnt.X() - aMDPos.X()) < nDrgLog && + std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) + { + /************************************************************* + * If a user wants to click on an object in front of a marked + * one, he releases the mouse button immediately + **************************************************************/ + SdrPageView* pPV; + SdrObject* pObj = mpView->PickObj(aMDPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK); + if (pObj && pPV->IsObjMarkable(pObj)) + { + mpView->UnmarkAllObj(); + mpView->MarkObj(pObj,pPV); + return true; + } + + // check for single object selected + SdrObject* pSingleObj = nullptr; + + if (mpView->GetMarkedObjectList().GetMarkCount()==1) + { + pSingleObj = mpView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + } + + // Check for click on svx::diagram::DiagramFrameHdl + // - if we hit a SdrHdl + // - if it was not moved + // - if single object is selected + // - and it is a Diagram + if(pHdl && !bWasDragged && nullptr != pSingleObj && pSingleObj->isDiagram()) + { + svx::diagram::DiagramFrameHdl* pDiagramFrameHdl(dynamic_cast<svx::diagram::DiagramFrameHdl*>(pHdl)); + if(nullptr != pDiagramFrameHdl) + { + // let the DiagramFrameHdl decide what to do + svx::diagram::DiagramFrameHdl::clicked(aPnt); + } + } + + /************************************************************** + * Toggle between selection and rotation + **************************************************************/ + if (nSlotId == SID_OBJECT_SELECT + && !comphelper::LibreOfficeKit::isActive() + && mpView->IsRotateAllowed() + + && (rMEvt.GetClicks() != 2) + && (mpViewShell->GetFrameView()->IsClickChangeRotation() + || (pSingleObj + && pSingleObj->GetObjInventor()==SdrInventor::E3d)) + && ! bSelectionOnly) + + { + bTempRotation = true; + nSlotId = SID_OBJECT_ROTATE; + Activate(); + } + else if (nSlotId == SID_OBJECT_ROTATE) + { + nSlotId = SID_OBJECT_SELECT; + Activate(); + } + } + else if (nSlotId == SID_CONVERT_TO_3D_LATHE) + { + if (!pHdl) + { + bSuppressChangesOfSelection = true; + mpView->Start3DCreation(); + bSuppressChangesOfSelection = false; + } + else if (pHdl->GetKind() != SdrHdlKind::MirrorAxis && + pHdl->GetKind() != SdrHdlKind::Ref1 && + pHdl->GetKind() != SdrHdlKind::Ref2 && mpView->Is3DRotationCreationActive()) + { + /********************************************************* + * If 3D-rotation bodies are about to be created, + * end creation now + **********************************************************/ + Degree100 nAngle1 = GetAngle(aPnt - mpView->GetRef1()); + nAngle1 -= 27000_deg100; + nAngle1 = NormAngle36000(nAngle1); + bool bMirrorSide1 = nAngle1 < 18000_deg100; + + if (bMirrorSide0 != bMirrorSide1) + { + bSuppressChangesOfSelection = true; + mpWindow->EnterWait(); + mpView->End3DCreation(); + bSuppressChangesOfSelection = false; + nSlotId = SID_OBJECT_SELECT; + mpWindow->LeaveWait(); + Activate(); + } + } + } + } + else if (rMEvt.IsMod1() + && !rMEvt.IsMod2() + && std::abs(aPnt.X() - aMDPos.X()) < nDrgLog + && std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) + { + // Enter group + mpView->MarkObj(aPnt, nHitLog, rMEvt.IsShift(), rMEvt.IsMod1()); + } + + if (mpView->IsAction() ) + { + mpView->EndAction(); + } + + if( SD_MOD()->GetWaterCan() ) + { + if( rMEvt.IsRight() ) + { + // In watering-can mode, on press onto right mouse button, an undo is executed + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_UNDO, SfxCallMode::ASYNCHRON ); + } + else if (pWaterCanCandidate != nullptr) + { + // Is the candidate object still under the mouse? + if (pickObject (aPnt) == pWaterCanCandidate) + { + SdStyleSheetPool* pPool = static_cast<SdStyleSheetPool*>( + mpDocSh->GetStyleSheetPool()); + if (pPool != nullptr) + { + SfxStyleSheet* pStyleSheet = static_cast<SfxStyleSheet*>( + pPool->GetActualStyleSheet()); + if (pStyleSheet != nullptr && mpView->IsUndoEnabled() ) + { + // Added UNDOs for the WaterCan mode. This was never done in + // the past, thus it was missing all the time. + std::unique_ptr<SdrUndoAction> pUndoAttr = mpDoc->GetSdrUndoFactory().CreateUndoAttrObject(*pWaterCanCandidate, true, true); + mpView->BegUndo(pUndoAttr->GetComment()); + mpView->AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoGeoObject(*pWaterCanCandidate)); + mpView->AddUndo(std::move(pUndoAttr)); + + pWaterCanCandidate->SetStyleSheet (pStyleSheet, false); + + mpView->EndUndo(); + } + } + } + } + // else when there has been no object under the mouse when the + // button was pressed then nothing happens even when there is + // one now. + } + + sal_uInt16 nClicks = rMEvt.GetClicks(); + + if (nClicks == 2 && rMEvt.IsLeft() && bMBDown && + !rMEvt.IsMod1() && !rMEvt.IsShift() ) + { + DoubleClick(rMEvt); + } + + bMBDown = false; + + ForcePointer(&rMEvt); + pHdl = nullptr; + mpWindow->ReleaseMouse(); + SdrObject* pSingleObj = nullptr; + const size_t nMarkCount = mpView->GetMarkedObjectList().GetMarkCount(); + + if (nMarkCount==1) + { + pSingleObj = mpView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + } + + if ( (nSlotId != SID_OBJECT_SELECT && nMarkCount==0) || + ( mpView->GetDragMode() == SdrDragMode::Crook && + !mpView->IsCrookAllowed( mpView->IsCrookNoContortion() ) ) || + ( mpView->GetDragMode() == SdrDragMode::Shear && + !mpView->IsShearAllowed() && !mpView->IsDistortAllowed() ) || + ( nSlotId==SID_CONVERT_TO_3D_LATHE && pSingleObj && + (pSingleObj->GetObjInventor() != SdrInventor::Default || + pSingleObj->GetObjIdentifier() == SdrObjKind::Measure) ) ) + { + bReturn = true; + ForcePointer(&rMEvt); + pHdl = nullptr; + mpWindow->ReleaseMouse(); + FuDraw::MouseButtonUp(rMEvt); + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::SYNCHRON); + return bReturn; // CAUTION, due to the synchronous slot, the object is deleted now. + } + + FuDraw::MouseButtonUp(rMEvt); + } + else + { + /********************************************************************** + * BEZIER_EDITOR + **********************************************************************/ + if ( mpView->IsAction() ) + { + if ( mpView->IsInsObjPoint() ) + { + mpView->EndInsObjPoint(SdrCreateCmd::ForceEnd); + } + else if ( mpView->IsDragObj() ) + { + FrameView* pFrameView = mpViewShell->GetFrameView(); + bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); + + if (bDragWithCopy) + { + bDragWithCopy = !mpView->IsPresObjSelected(false); + } + + mpView->SetDragWithCopy(bDragWithCopy); + mpView->EndDragObj( mpView->IsDragWithCopy() ); + } + else + { + mpView->EndAction(); + + sal_uInt16 nDrgLog2 = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() ); + + if (std::abs(aMDPos.X() - aPos.X()) < nDrgLog2 && + std::abs(aMDPos.Y() - aPos.Y()) < nDrgLog2 && + !rMEvt.IsShift() && !rMEvt.IsMod2()) + { + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::NONE) + { + // Click on the same place - unselect + mpView->UnmarkAllObj(); + } + } + } + } + else if (!rMEvt.IsShift() && rMEvt.IsMod1() && !rMEvt.IsMod2() && + std::abs(aPnt.X() - aMDPos.X()) < nDrgLog && + std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) + { + // Enter group + mpView->MarkObj(aPnt, nHitLog, false, rMEvt.IsMod1()); + } + + ForcePointer(&rMEvt); + pHdl = nullptr; + mpWindow->ReleaseMouse(); + + FuDraw::MouseButtonUp(rMEvt); + } + + return bReturn; +} + +/** + * Process keyboard input + * @returns sal_True if a KeyEvent is being processed, sal_False otherwise + */ +bool FuSelection::KeyInput(const KeyEvent& rKEvt) +{ + bool bReturn = false; + + switch (rKEvt.GetKeyCode().GetCode()) + { + case KEY_ESCAPE: + { + bReturn = FuSelection::cancel(); + } + break; + //add keyboard operation for insert points in drawing curve + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + { + if(rKEvt.GetKeyCode().IsShift()&&(nEditMode == SID_BEZIER_INSERT)){ + ::tools::Long nX = 0; + ::tools::Long nY = 0; + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + if (nCode == KEY_UP) + { + // scroll up + nX = 0; + nY =-1; + } + else if (nCode == KEY_DOWN) + { + // scroll down + nX = 0; + nY = 1; + } + else if (nCode == KEY_LEFT) + { + // scroll left + nX =-1; + nY = 0; + } + else if (nCode == KEY_RIGHT) + { + // scroll right + nX = 1; + nY = 0; + } + + Point centerPoint; + ::tools::Rectangle rect = mpView->GetMarkedObjRect(); + centerPoint = mpWindow->LogicToPixel(rect.Center()); + Point aPoint = bMovedToCenterPoint? oldPoint:centerPoint; + Point ePoint = aPoint + Point(nX,nY); + mpWindow->SetPointerPosPixel(ePoint); + //simulate mouse move action + MouseEvent eMevt(ePoint, 1, MouseEventModifiers::DRAGMOVE, MOUSE_LEFT, 0); + MouseMove(eMevt); + oldPoint = ePoint; + bMovedToCenterPoint = true; + bReturn = true; + } + } + break; + case KEY_RETURN: + if(rKEvt.GetKeyCode().IsShift()&&(nEditMode == SID_BEZIER_INSERT)) + { + if(!bBeginInsertPoint) + { + //simulate mouse button down action + MouseEvent aMevt(oldPoint, 1, + MouseEventModifiers::SIMPLEMOVE | MouseEventModifiers::DRAGMOVE, + MOUSE_LEFT, KEY_SHIFT); + MouseButtonDown(aMevt); + mpWindow->CaptureMouse(); + bBeginInsertPoint = true; + } + else + { + //simulate mouse button up action + MouseEvent rMEvt(oldPoint, 1, + MouseEventModifiers::SIMPLEMOVE | MouseEventModifiers::ENTERWINDOW, + MOUSE_LEFT, KEY_SHIFT); + MouseButtonUp(rMEvt); + bBeginInsertPoint = false; + } + bReturn= true; + } + break; + } + if (!bReturn) + { + bReturn = FuDraw::KeyInput(rKEvt); + + if(mpView->GetMarkedObjectList().GetMarkCount() == 0) + { + mpView->ResetCreationActive(); + + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + } + } + + return bReturn; + +} + +void FuSelection::Activate() +{ + SdrDragMode eMode; + mpView->ResetCreationActive(); + mpView->SetEditMode(SdrViewEditMode::Edit); + + switch( nSlotId ) + { + case SID_OBJECT_ROTATE: + { + eMode = SdrDragMode::Rotate; + + if ( mpView->GetDragMode() != eMode ) + mpView->SetDragMode(eMode); + } + break; + + case SID_OBJECT_MIRROR: + { + eMode = SdrDragMode::Mirror; + + if ( mpView->GetDragMode() != eMode ) + mpView->SetDragMode(eMode); + } + break; + + case SID_OBJECT_CROP: + { + eMode = SdrDragMode::Crop; + + if ( mpView->GetDragMode() != eMode ) + mpView->SetDragMode(eMode); + } + break; + + case SID_OBJECT_TRANSPARENCE: + { + eMode = SdrDragMode::Transparence; + + if ( mpView->GetDragMode() != eMode ) + mpView->SetDragMode(eMode); + } + break; + + case SID_OBJECT_GRADIENT: + { + eMode = SdrDragMode::Gradient; + + if ( mpView->GetDragMode() != eMode ) + mpView->SetDragMode(eMode); + } + break; + + case SID_OBJECT_SHEAR: + { + eMode = SdrDragMode::Shear; + + if ( mpView->GetDragMode() != eMode ) + mpView->SetDragMode(eMode); + } + break; + + case SID_OBJECT_CROOK_ROTATE: + { + eMode = SdrDragMode::Crook; + + if ( mpView->GetDragMode() != eMode ) + { + mpView->SetDragMode(eMode); + mpView->SetCrookMode(SdrCrookMode::Rotate); + } + } + break; + + case SID_OBJECT_CROOK_SLANT: + { + eMode = SdrDragMode::Crook; + + if ( mpView->GetDragMode() != eMode ) + { + mpView->SetDragMode(eMode); + mpView->SetCrookMode(SdrCrookMode::Slant); + } + } + break; + + case SID_OBJECT_CROOK_STRETCH: + { + eMode = SdrDragMode::Crook; + + if ( mpView->GetDragMode() != eMode ) + { + mpView->SetDragMode(eMode); + mpView->SetCrookMode(SdrCrookMode::Stretch); + } + } + break; + + case SID_CONVERT_TO_3D_LATHE: + { + eMode = SdrDragMode::Mirror; + bSuppressChangesOfSelection = true; + + if ( mpView->GetDragMode() != eMode ) + mpView->SetDragMode(eMode); + + if (!mpView->Is3DRotationCreationActive()) + mpView->Start3DCreation(); + + bSuppressChangesOfSelection = false; + } + break; + + default: + { + eMode = SdrDragMode::Move; + + if ( mpView->GetDragMode() != eMode ) + mpView->SetDragMode(eMode); + } + break; + } + + if (nSlotId != SID_OBJECT_ROTATE) + { + bTempRotation = false; + } + + FuDraw::Activate(); +} + +void FuSelection::SelectionHasChanged() +{ + bSelectionChanged = true; + + FuDraw::SelectionHasChanged(); + + if (mpView->Is3DRotationCreationActive() && !bSuppressChangesOfSelection) + { + // Switch rotation body -> selection + mpView->ResetCreationActive(); + nSlotId = SID_OBJECT_SELECT; + Activate(); + } + + // Activate the right tool bar for the current context of the view. + mpViewShell->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(*mpViewShell, *mpView); +} + +/** + * Set current bezier edit mode + */ +void FuSelection::SetEditMode(sal_uInt16 nMode) +{ + nEditMode = nMode; + + if (nEditMode == SID_BEZIER_INSERT) + { + mpView->SetInsObjPointMode(true); + } + else + { + mpView->SetInsObjPointMode(false); + } + + ForcePointer(); + + SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings(); + rBindings.Invalidate(SID_BEZIER_MOVE); + rBindings.Invalidate(SID_BEZIER_INSERT); +} + +/** + * Execute ImageMap interaction + */ +bool FuSelection::HandleImageMapClick(const SdrObject* pObj, const Point& rPos) +{ + bool bClosed = pObj->IsClosedObj(); + bool bFilled = false; + + if (bClosed) + { + SfxItemSet aSet(mpDoc->GetPool()); + + aSet.Put(pObj->GetMergedItemSet()); + + const XFillStyleItem& rFillStyle = aSet.Get(XATTR_FILLSTYLE); + bFilled = rFillStyle.GetValue() != drawing::FillStyle_NONE; + } + + const SdrLayerIDSet* pVisiLayer = &mpView->GetSdrPageView()->GetVisibleLayers(); + sal_uInt16 nHitLog = sal_uInt16(mpWindow->PixelToLogic(Size(HITPIX, 0)).Width()); + const ::tools::Long n2HitLog = nHitLog * 2; + Point aHitPosR(rPos); + Point aHitPosL(rPos); + Point aHitPosT(rPos); + Point aHitPosB(rPos); + + aHitPosR.AdjustX(n2HitLog); + aHitPosL.AdjustX(-n2HitLog); + aHitPosT.AdjustY(n2HitLog); + aHitPosB.AdjustY(-n2HitLog); + + if (!bClosed || !bFilled + || (SdrObjectPrimitiveHit(*pObj, aHitPosR, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, + false) + && SdrObjectPrimitiveHit(*pObj, aHitPosL, nHitLog, *mpView->GetSdrPageView(), + pVisiLayer, false) + && SdrObjectPrimitiveHit(*pObj, aHitPosT, nHitLog, *mpView->GetSdrPageView(), + pVisiLayer, false) + && SdrObjectPrimitiveHit(*pObj, aHitPosB, nHitLog, *mpView->GetSdrPageView(), + pVisiLayer, false))) + { + if (SvxIMapInfo::GetIMapInfo(pObj)) + { + const IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(pObj, rPos); + + if (pIMapObj && !pIMapObj->GetURL().isEmpty()) + { + // Jump to Document + mpWindow->ReleaseMouse(); + SfxStringItem aStrItem(SID_FILE_NAME, pIMapObj->GetURL()); + SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName()); + SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); + SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame); + SfxBoolItem aBrowseItem(SID_BROWSE, true); + mpWindow->ReleaseMouse(); + pFrame->GetDispatcher()->ExecuteList( + SID_OPENDOC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aStrItem, &aFrameItem, &aBrowseItem, &aReferer }); + + return true; + } + } + } + + return false; +} + +/** is called when the current function should be aborted. <p> + This is used when a function gets a KEY_ESCAPE but can also + be called directly. + + @returns true if an active function was aborted +*/ +bool FuSelection::cancel() +{ + if (mpView->Is3DRotationCreationActive()) + { + mpView->ResetCreationActive(); + mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + return true; + } + else + { + return false; + } +} + +SdrObject* FuSelection::pickObject (const Point& rTestPoint) +{ + SdrPageView* pPageView; + sal_uInt16 nHitLog = sal_uInt16 (mpWindow->PixelToLogic(Size(HITPIX,0)).Width()); + return mpView->PickObj(rTestPoint, nHitLog, pPageView, SdrSearchOptions::PICKMARKABLE); +} + +void FuSelection::ForcePointer(const MouseEvent* pMEvt) +{ + if(bMovedToCenterPoint && !bBeginInsertPoint && pMEvt) + { + MouseEvent aMEvt(pMEvt->GetPosPixel(), pMEvt->GetClicks(), + pMEvt->GetMode(), pMEvt->GetButtons(), pMEvt->GetModifier() & ~KEY_SHIFT); + FuDraw::ForcePointer(&aMEvt); + } + else + { + FuDraw::ForcePointer(pMEvt); + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fusldlg.cxx b/sd/source/ui/func/fusldlg.cxx new file mode 100644 index 000000000..c0269b08a --- /dev/null +++ b/sd/source/ui/func/fusldlg.cxx @@ -0,0 +1,226 @@ +/* -*- 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 <fusldlg.hxx> +#include <svl/eitem.hxx> +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> + +#include <drawdoc.hxx> +#include <sdpage.hxx> +#include <sdresid.hxx> +#include <strings.hrc> +#include <sdattr.hrc> +#include <sdmod.hxx> +#include <Window.hxx> +#include <optsitem.hxx> +#include <sdabstdlg.hxx> + +namespace sd { + +#define ITEMVALUE(ItemSet,Id,Cast) static_cast<const Cast&>((ItemSet).Get(Id)).GetValue() + + +FuSlideShowDlg::FuSlideShowDlg ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor( pViewSh, pWin, pView, pDoc, rReq ) +{ +} + +rtl::Reference<FuPoor> FuSlideShowDlg::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuSlideShowDlg( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuSlideShowDlg::DoExecute( SfxRequest& ) +{ + PresentationSettings& rPresentationSettings = mpDoc->getPresentationSettings(); + + SfxItemSetFixed<ATTR_PRESENT_START, ATTR_PRESENT_END> aDlgSet( mpDoc->GetPool() ); + std::vector<OUString> aPageNameList(mpDoc->GetSdPageCount( PageKind::Standard )); + const OUString& rPresPage = rPresentationSettings.maPresPage; + OUString aFirstPage; + SdPage* pPage = nullptr; + ::tools::Long nPage; + + for( nPage = mpDoc->GetSdPageCount( PageKind::Standard ) - 1; nPage >= 0; nPage-- ) + { + pPage = mpDoc->GetSdPage( static_cast<sal_uInt16>(nPage), PageKind::Standard ); + OUString aStr( pPage->GetName() ); + + if ( aStr.isEmpty() ) + { + aStr = SdResId( STR_PAGE ) + OUString::number( nPage + 1 ); + } + + aPageNameList[ nPage ] = aStr; + + // is this our (existing) first page? + if ( rPresPage == aStr ) + aFirstPage = rPresPage; + else if ( pPage->IsSelected() && aFirstPage.isEmpty() ) + aFirstPage = aStr; + } + SdCustomShowList* pCustomShowList = mpDoc->GetCustomShowList(); // No Create + + if( aFirstPage.isEmpty() && pPage ) + aFirstPage = pPage->GetName(); + + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_ALL, rPresentationSettings.mbAll ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_CUSTOMSHOW, rPresentationSettings.mbCustomShow ) ); + aDlgSet.Put( SfxStringItem( ATTR_PRESENT_DIANAME, aFirstPage ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_ENDLESS, rPresentationSettings.mbEndless ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_MANUEL, rPresentationSettings.mbManual ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_MOUSE, rPresentationSettings.mbMouseVisible ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_PEN, rPresentationSettings.mbMouseAsPen ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_ANIMATION_ALLOWED, rPresentationSettings.mbAnimationAllowed ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_CHANGE_PAGE, !rPresentationSettings.mbLockedPages ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_ALWAYS_ON_TOP, rPresentationSettings.mbAlwaysOnTop ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_FULLSCREEN, rPresentationSettings.mbFullScreen ) ); + aDlgSet.Put( SfxUInt32Item( ATTR_PRESENT_PAUSE_TIMEOUT, rPresentationSettings.mnPauseTimeout ) ); + aDlgSet.Put( SfxBoolItem( ATTR_PRESENT_SHOW_PAUSELOGO, rPresentationSettings.mbShowPauseLogo ) ); + + SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress); + aDlgSet.Put( SfxInt32Item( ATTR_PRESENT_DISPLAY, pOptions->GetDisplay() ) ); + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSdStartPresDlg> pDlg( pFact->CreateSdStartPresentationDlg(mpWindow ? mpWindow->GetFrameWeld() : nullptr, aDlgSet, aPageNameList, pCustomShowList) ); + if( pDlg->Execute() != RET_OK ) + return; + + ::tools::Long nValue32; + bool bValue; + bool bValuesChanged = false; + + pDlg->GetAttr( aDlgSet ); + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_ALL, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbAll ) + { + bValuesChanged = true; + rPresentationSettings.mbAll = bValue; + // remove any previous existing slide + rPresentationSettings.maPresPage.clear(); + } + + if (!rPresentationSettings.mbAll) + { + OUString aPage = ITEMVALUE( aDlgSet, ATTR_PRESENT_DIANAME, SfxStringItem ); + if( aPage != rPresentationSettings.maPresPage ) + { + bValuesChanged = true; + rPresentationSettings.maPresPage = aPage; + } + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_CUSTOMSHOW, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbCustomShow ) + { + bValuesChanged = true; + rPresentationSettings.mbCustomShow = bValue; + rPresentationSettings.mbStartCustomShow = false; + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_ENDLESS, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbEndless ) + { + bValuesChanged = true; + rPresentationSettings.mbEndless = bValue; + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_MANUEL, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbManual ) + { + bValuesChanged = true; + rPresentationSettings.mbManual = bValue; + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_MOUSE, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbMouseVisible ) + { + bValuesChanged = true; + rPresentationSettings.mbMouseVisible = bValue; + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_PEN, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbMouseAsPen ) + { + bValuesChanged = true; + rPresentationSettings.mbMouseAsPen = bValue; + } + + bValue = !ITEMVALUE( aDlgSet, ATTR_PRESENT_CHANGE_PAGE, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbLockedPages ) + { + bValuesChanged = true; + rPresentationSettings.mbLockedPages = bValue; + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_ANIMATION_ALLOWED, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbAnimationAllowed ) + { + bValuesChanged = true; + rPresentationSettings.mbAnimationAllowed = bValue; + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_ALWAYS_ON_TOP, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbAlwaysOnTop ) + { + bValuesChanged = true; + rPresentationSettings.mbAlwaysOnTop = bValue; + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_FULLSCREEN, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbFullScreen ) + { + bValuesChanged = true; + rPresentationSettings.mbFullScreen = bValue; + } + + nValue32 = ITEMVALUE( aDlgSet, ATTR_PRESENT_PAUSE_TIMEOUT, SfxUInt32Item ); + if( nValue32 != rPresentationSettings.mnPauseTimeout ) + { + bValuesChanged = true; + rPresentationSettings.mnPauseTimeout = nValue32; + } + + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_SHOW_PAUSELOGO, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbShowPauseLogo ) + { + bValuesChanged = true; + rPresentationSettings.mbShowPauseLogo = bValue; + } + + pOptions->SetDisplay( ITEMVALUE( aDlgSet, ATTR_PRESENT_DISPLAY, SfxInt32Item ) ); + + // is something has changed, we set the modified flag + if ( bValuesChanged ) + mpDoc->SetChanged(); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fusnapln.cxx b/sd/source/ui/func/fusnapln.cxx new file mode 100644 index 000000000..ee51d78ce --- /dev/null +++ b/sd/source/ui/func/fusnapln.cxx @@ -0,0 +1,196 @@ +/* -*- 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 <fusnapln.hxx> +#include <svl/intitem.hxx> +#include <sfx2/request.hxx> +#include <svx/svxids.hrc> + +#include <strings.hrc> +#include <sdattr.hrc> + +#include <View.hxx> +#include <ViewShell.hxx> +#include <DrawViewShell.hxx> +#include <Window.hxx> +#include <sdenumdef.hxx> +#include <sdresid.hxx> +#include <sdabstdlg.hxx> +#include <svx/svdpagv.hxx> + +namespace sd { + + +FuSnapLine::FuSnapLine(ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, + SdDrawDocument* pDoc, SfxRequest& rReq) : + FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuSnapLine::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuSnapLine( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuSnapLine::DoExecute( SfxRequest& rReq ) +{ + const SfxItemSet* pArgs = rReq.GetArgs(); + sal_uInt16 nHelpLine = 0; + bool bCreateNew = true; + + // Get index of snap line or snap point from the request. + const SfxUInt32Item* pHelpLineIndex = rReq.GetArg<SfxUInt32Item>(ID_VAL_INDEX); + if (pHelpLineIndex != nullptr) + { + nHelpLine = static_cast<sal_uInt16>(pHelpLineIndex->GetValue()); + // Reset the argument pointer to trigger the display of the dialog. + pArgs = nullptr; + } + + SdrPageView* pPV = mpView->GetSdrPageView(); + + if (!pArgs) + { + SfxItemSetFixed<ATTR_SNAPLINE_START, ATTR_SNAPLINE_END> aNewAttr(mpViewShell->GetPool()); + bool bLineExist (false); + Point aLinePos; + + if (pHelpLineIndex == nullptr) + { + // The index of the snap line is not provided as argument to the + // request. Determine it from the mouse position. + + aLinePos = static_cast<DrawViewShell*>(mpViewShell)->GetMousePos(); + + if ( aLinePos.X() >= 0 ) + { + aLinePos = mpWindow->PixelToLogic(aLinePos); + sal_uInt16 nHitLog = static_cast<sal_uInt16>(mpWindow->PixelToLogic(Size(HITPIX,0)).Width()); + bLineExist = mpView->PickHelpLine(aLinePos, nHitLog, *mpWindow->GetOutDev(), nHelpLine, pPV); + if ( bLineExist ) + aLinePos = (pPV->GetHelpLines())[nHelpLine].GetPos(); + else + pPV = mpView->GetSdrPageView(); + + pPV->LogicToPagePos(aLinePos); + } + else + aLinePos = Point(0,0); + } + else + { + assert(pPV!=nullptr); + aLinePos = (pPV->GetHelpLines())[nHelpLine].GetPos(); + pPV->LogicToPagePos(aLinePos); + bLineExist = true; + } + aNewAttr.Put(SfxInt32Item(ATTR_SNAPLINE_X, aLinePos.X())); + aNewAttr.Put(SfxInt32Item(ATTR_SNAPLINE_Y, aLinePos.Y())); + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + vcl::Window* pWin = mpViewShell->GetActiveWindow(); + ScopedVclPtr<AbstractSdSnapLineDlg> pDlg( pFact->CreateSdSnapLineDlg(pWin ? pWin->GetFrameWeld() : nullptr, aNewAttr, mpView) ); + + if ( bLineExist ) + { + pDlg->HideRadioGroup(); + + const SdrHelpLine& rHelpLine = (pPV->GetHelpLines())[nHelpLine]; + + if ( rHelpLine.GetKind() == SdrHelpLineKind::Point ) + { + pDlg->SetText(SdResId(STR_SNAPDLG_SETPOINT)); + pDlg->SetInputFields(true, true); + } + else + { + pDlg->SetText(SdResId(STR_SNAPDLG_SETLINE)); + + if ( rHelpLine.GetKind() == SdrHelpLineKind::Vertical ) + pDlg->SetInputFields(true, false); + else + pDlg->SetInputFields(false, true); + } + bCreateNew = false; + } + else + pDlg->HideDeleteBtn(); + + sal_uInt16 nResult = pDlg->Execute(); + + pDlg->GetAttr(aNewAttr); + pDlg.disposeAndClear(); + + switch( nResult ) + { + case RET_OK: + rReq.Done(aNewAttr); + pArgs = rReq.GetArgs(); + break; + + case RET_SNAP_DELETE: + // delete snap object + if ( !bCreateNew ) + pPV->DeleteHelpLine(nHelpLine); + [[fallthrough]]; + default: + return; + } + } + Point aHlpPos; + + aHlpPos.setX( static_cast<const SfxInt32Item&>( pArgs->Get(ATTR_SNAPLINE_X)).GetValue() ); + aHlpPos.setY( static_cast<const SfxInt32Item&>( pArgs->Get(ATTR_SNAPLINE_Y)).GetValue() ); + pPV->PagePosToLogic(aHlpPos); + + if ( bCreateNew ) + { + SdrHelpLineKind eKind; + + pPV = mpView->GetSdrPageView(); + + switch ( static_cast<SnapKind>(static_cast<const SfxUInt16Item&>( + pArgs->Get(ATTR_SNAPLINE_KIND)).GetValue()) ) + { + case SnapKind::Horizontal : eKind = SdrHelpLineKind::Horizontal; break; + case SnapKind::Vertical : eKind = SdrHelpLineKind::Vertical; break; + default : eKind = SdrHelpLineKind::Point; break; + } + pPV->InsertHelpLine(SdrHelpLine(eKind, aHlpPos)); + } + else + { + const SdrHelpLine& rHelpLine = (pPV->GetHelpLines())[nHelpLine]; + pPV->SetHelpLine(nHelpLine, SdrHelpLine(rHelpLine.GetKind(), aHlpPos)); + } +} + +void FuSnapLine::Activate() +{ +} + +void FuSnapLine::Deactivate() +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fusumry.cxx b/sd/source/ui/func/fusumry.cxx new file mode 100644 index 000000000..9b160099c --- /dev/null +++ b/sd/source/ui/func/fusumry.cxx @@ -0,0 +1,229 @@ +/* -*- 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 <fusumry.hxx> +#include <editeng/eeitem.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdundo.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xlineit0.hxx> +#include <editeng/outlobj.hxx> +#include <xmloff/autolayout.hxx> + +#include <strings.hrc> + +#include <pres.hxx> +#include <View.hxx> +#include <sdpage.hxx> +#include <Outliner.hxx> +#include <drawdoc.hxx> +#include <ViewShell.hxx> +#include <sdmod.hxx> +#include <sdresid.hxx> +#include <DrawViewShell.hxx> + +using namespace com::sun::star; + +namespace sd { + + +FuSummaryPage::FuSummaryPage ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuSummaryPage::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuSummaryPage( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuSummaryPage::DoExecute( SfxRequest& ) +{ + std::unique_ptr<SdOutliner> pOutl; + rtl::Reference<SdPage> pSummaryPage; + sal_uInt16 i = 0; + sal_uInt16 nFirstPage = SDRPAGE_NOTFOUND; + sal_uInt16 nSelectedPages = 0; + sal_uInt16 nCount = mpDoc->GetSdPageCount(PageKind::Standard); + + while (i < nCount && nSelectedPages <= 1) + { + /* How many pages are selected? + exactly one: pool everything from this page + otherwise: only pool the selected pages */ + SdPage* pActualPage = mpDoc->GetSdPage(i, PageKind::Standard); + + if (pActualPage->IsSelected()) + { + if (nFirstPage == SDRPAGE_NOTFOUND) + { + nFirstPage = i; + } + + nSelectedPages++; + } + + i++; + } + + bool bBegUndo = false; + + SfxStyleSheet* pStyle = nullptr; + + for (i = nFirstPage; i < nCount; i++) + { + SdPage* pActualPage = mpDoc->GetSdPage(i, PageKind::Standard); + + if (nSelectedPages <= 1 || pActualPage->IsSelected()) + { + SdPage* pActualNotesPage = mpDoc->GetSdPage(i, PageKind::Notes); + SdrTextObj* pTextObj = static_cast<SdrTextObj*>( pActualPage->GetPresObj(PresObjKind::Title) ); + + if (pTextObj && !pTextObj->IsEmptyPresObj()) + { + if (!pSummaryPage) + { + // insert "table of content"-page and create outliner + const bool bUndo = mpView->IsUndoEnabled(); + + if( bUndo ) + { + mpView->BegUndo(SdResId(STR_UNDO_SUMMARY_PAGE)); + bBegUndo = true; + } + + SdrLayerIDSet aVisibleLayers = pActualPage->TRG_GetMasterPageVisibleLayers(); + + // page with title & structuring! + pSummaryPage = mpDoc->AllocSdPage(false); + pSummaryPage->SetSize(pActualPage->GetSize() ); + pSummaryPage->SetBorder(pActualPage->GetLeftBorder(), + pActualPage->GetUpperBorder(), + pActualPage->GetRightBorder(), + pActualPage->GetLowerBorder() ); + + // insert page at the back + mpDoc->InsertPage(pSummaryPage.get(), nCount * 2 + 1); + if( bUndo ) + mpView->AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoNewPage(*pSummaryPage)); + + // use MasterPage of the current page + pSummaryPage->TRG_SetMasterPage(pActualPage->TRG_GetMasterPage()); + pSummaryPage->SetLayoutName(pActualPage->GetLayoutName()); + pSummaryPage->SetAutoLayout(AUTOLAYOUT_TITLE_CONTENT, true); + pSummaryPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers); + pSummaryPage->setHeaderFooterSettings(pActualPage->getHeaderFooterSettings()); + + // notes-page + rtl::Reference<SdPage> pNotesPage = mpDoc->AllocSdPage(false); + pNotesPage->SetSize(pActualNotesPage->GetSize()); + pNotesPage->SetBorder(pActualNotesPage->GetLeftBorder(), + pActualNotesPage->GetUpperBorder(), + pActualNotesPage->GetRightBorder(), + pActualNotesPage->GetLowerBorder() ); + pNotesPage->SetPageKind(PageKind::Notes); + + // insert page at the back + mpDoc->InsertPage(pNotesPage.get(), nCount * 2 + 2); + + if( bUndo ) + mpView->AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoNewPage(*pNotesPage)); + + // use MasterPage of the current page + pNotesPage->TRG_SetMasterPage(pActualNotesPage->TRG_GetMasterPage()); + pNotesPage->SetLayoutName(pActualNotesPage->GetLayoutName()); + pNotesPage->SetAutoLayout(pActualNotesPage->GetAutoLayout(), true); + pNotesPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers); + pNotesPage->setHeaderFooterSettings(pActualNotesPage->getHeaderFooterSettings()); + + pOutl.reset(new SdOutliner( mpDoc, OutlinerMode::OutlineObject )); + pOutl->SetUpdateLayout(false); + pOutl->EnableUndo(false); + + if (mpDocSh) + pOutl->SetRefDevice(SD_MOD()->GetVirtualRefDevice()); + + pOutl->SetDefTab( mpDoc->GetDefaultTabulator() ); + pOutl->SetStyleSheetPool(static_cast<SfxStyleSheetPool*>(mpDoc->GetStyleSheetPool())); + pStyle = pSummaryPage->GetStyleSheetForPresObj( PresObjKind::Outline ); + pOutl->SetStyleSheet( 0, pStyle ); + } + + // add text + OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject(); + // #118876#, check if the OutlinerParaObject is created successfully + if( pParaObj ) + { + pParaObj->SetOutlinerMode( OutlinerMode::OutlineObject ); + pOutl->AddText(*pParaObj); + } + } + } + } + + if (!pSummaryPage) + return; + + SdrTextObj* pTextObj = static_cast<SdrTextObj*>( pSummaryPage->GetPresObj(PresObjKind::Outline) ); + + if (!pTextObj) + return; + + // remove hard break- and character attributes + SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END> aEmptyEEAttr(mpDoc->GetPool()); + sal_Int32 nParaCount = pOutl->GetParagraphCount(); + + for (sal_Int32 nPara = 0; nPara < nParaCount; nPara++) + { + pOutl->SetStyleSheet( nPara, pStyle ); + pOutl->RemoveCharAttribs(nPara); + pOutl->SetParaAttribs(nPara, aEmptyEEAttr); + pOutl->SetDepth(pOutl->GetParagraph(nPara), 0); + } + + pTextObj->SetOutlinerParaObject( pOutl->CreateParaObject() ); + pTextObj->SetEmptyPresObj(false); + + // remove hard attributes (Flag to sal_True) + SfxItemSet aAttr(mpDoc->GetPool()); + aAttr.Put(XLineStyleItem(drawing::LineStyle_NONE)); + aAttr.Put(XFillStyleItem(drawing::FillStyle_NONE)); + pTextObj->SetMergedItemSet(aAttr); + + if( bBegUndo ) + mpView->EndUndo(); + pOutl.reset(); + + DrawViewShell* pDrawViewShell= dynamic_cast< DrawViewShell* >( mpViewShell ); + if(pDrawViewShell) + { + pDrawViewShell->SwitchPage( (pSummaryPage->GetPageNum() - 1) / 2); + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/futempl.cxx b/sd/source/ui/func/futempl.cxx new file mode 100644 index 000000000..2c0c22ecd --- /dev/null +++ b/sd/source/ui/func/futempl.cxx @@ -0,0 +1,638 @@ +/* -*- 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 <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/frame/XModel.hpp> + +#include <futempl.hxx> + +#include <svx/svxids.hrc> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <editeng/eeitem.hxx> +#include <sfx2/request.hxx> +#include <sfx2/sfxdlg.hxx> +#include <editeng/numitem.hxx> +#include <svx/svdopage.hxx> +#include <editeng/colritem.hxx> +#include <editeng/brushitem.hxx> +#include <svx/svditer.hxx> +#include <svx/sdr/properties/properties.hxx> +#include <svl/intitem.hxx> + +#include <sfx2/viewfrm.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xflhtit.hxx> +#include <o3tl/string_view.hxx> +#include <app.hrc> +#include <stlsheet.hxx> +#include <sdpage.hxx> +#include <stlpool.hxx> +#include <sdmod.hxx> +#include <View.hxx> +#include <drawdoc.hxx> +#include <DrawDocShell.hxx> +#include <DrawViewShell.hxx> +#include <ViewShell.hxx> + +#include <strings.hrc> +#include <prlayout.hxx> +#include <sdresid.hxx> +#include <OutlineView.hxx> +#include <sdabstdlg.hxx> +#include <memory> + +using namespace com::sun::star::uno; +using namespace com::sun::star::container; +using namespace com::sun::star::beans; +using namespace com::sun::star::style; + +namespace sd +{ + + +FuTemplate::FuTemplate ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq ) + : FuPoor( pViewSh, pWin, pView, pDoc, rReq ) +{ +} + +rtl::Reference<FuPoor> FuTemplate::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuTemplate( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuTemplate::DoExecute( SfxRequest& rReq ) +{ + const SfxItemSet* pArgs = rReq.GetArgs(); + sal_uInt16 nSId = rReq.GetSlot(); + + // get StyleSheet parameter + SfxStyleSheetBasePool* pSSPool = mpDoc->GetDocSh()->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = nullptr; + + const SfxPoolItem* pItem; + SfxStyleFamily nFamily = SfxStyleFamily(USHRT_MAX); + if( pArgs && SfxItemState::SET == pArgs->GetItemState( SID_STYLE_FAMILY, + false, &pItem )) + { + nFamily = static_cast<SfxStyleFamily>( pArgs->Get( SID_STYLE_FAMILY ).GetValue()); + } + else if( pArgs && SfxItemState::SET == pArgs->GetItemState( SID_STYLE_FAMILYNAME, + false, &pItem )) + { + OUString sFamily = pArgs->Get( SID_STYLE_FAMILYNAME ).GetValue(); + if (sFamily == "graphics") + nFamily = SfxStyleFamily::Para; + else + nFamily = SfxStyleFamily::Pseudo; + } + + OUString aStyleName; + sal_uInt16 nRetMask = static_cast<sal_uInt16>(SfxStyleSearchBits::All); + + switch( nSId ) + { + case SID_STYLE_APPLY: + case SID_STYLE_EDIT: + case SID_STYLE_DELETE: + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + case SID_STYLE_FAMILY: + case SID_STYLE_NEW_BY_EXAMPLE: + { + const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(SID_APPLY_STYLE); + const SfxStringItem* pFamilyItem = rReq.GetArg<SfxStringItem>(SID_STYLE_FAMILYNAME); + if ( pFamilyItem && pNameItem ) + { + try + { + Reference< XStyleFamiliesSupplier > xModel(mpDoc->GetDocSh()->GetModel(), UNO_QUERY_THROW ); + Reference< XNameAccess > xCont( xModel->getStyleFamilies() ); + Reference< XNameAccess > xStyles( xCont->getByName(pFamilyItem->GetValue()), UNO_QUERY_THROW ); + Reference< XPropertySet > xInfo( xStyles->getByName( pNameItem->GetValue() ), UNO_QUERY_THROW ); + + OUString aUIName; + xInfo->getPropertyValue( "DisplayName" ) >>= aUIName; + if ( !aUIName.isEmpty() ) + rReq.AppendItem( SfxStringItem( nSId, aUIName ) ); + } + catch( Exception& ) + { + } + } + + if (pArgs && pArgs->GetItemState(nSId) == SfxItemState::SET) + aStyleName = static_cast<const SfxStringItem &>( pArgs->Get( nSId ) ).GetValue(); + } + } + + switch( nSId ) + { + case SID_STYLE_NEW: + { + SfxStyleSheetBase *p = pSSPool->Find(aStyleName, nFamily ); + if(p) + { + pSSPool->Remove(p); + p = nullptr; + } + pStyleSheet = &pSSPool->Make( aStyleName, nFamily, SfxStyleSearchBits::UserDefined ); + + if (pArgs && pArgs->GetItemState(SID_STYLE_REFERENCE) == SfxItemState::SET) + { + OUString aParentName( pArgs->Get(SID_STYLE_REFERENCE).GetValue()); + pStyleSheet->SetParent(aParentName); + } + else + { + pStyleSheet->SetParent(SdResId(STR_STANDARD_STYLESHEET_NAME)); + } + } + break; + + case SID_STYLE_NEW_BY_EXAMPLE: + { + // at the moment, the dialog to enter the name of the template is still opened + SfxStyleSheetBase *p = pSSPool->Find(aStyleName, nFamily ); + if(p) + { + pSSPool->Remove(p); + p = nullptr; + } + pStyleSheet = &pSSPool->Make( aStyleName, nFamily, SfxStyleSearchBits::UserDefined ); + pStyleSheet->SetParent(SdResId(STR_STANDARD_STYLESHEET_NAME)); + } + break; + + case SID_STYLE_EDIT: + pStyleSheet = pSSPool->Find( aStyleName, nFamily); + break; + + case SID_STYLE_DELETE: + pStyleSheet = pSSPool->Find( aStyleName, nFamily); + if( pStyleSheet ) + { + pSSPool->Remove( pStyleSheet ); + nRetMask = sal_uInt16(true); + mpDoc->SetChanged(); + } + else + { + nRetMask = sal_uInt16(false); + } + break; + + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + pStyleSheet = pSSPool->Find( aStyleName, nFamily); + pStyleSheet->SetHidden( nSId == SID_STYLE_HIDE ); + nRetMask = sal_uInt16(true); + break; + + case SID_STYLE_APPLY: + // apply the template to the document + pStyleSheet = pSSPool->Find( aStyleName, nFamily); + + // do not set presentation styles, they will be set implicit + if ( pStyleSheet && pStyleSheet->GetFamily() != SfxStyleFamily::Pseudo ) + { + SfxStyleSheet* pOldStyleSheet = mpView->GetStyleSheet(); + OUString aStr; + + if( // if the object had no style sheet, allow all + !pOldStyleSheet || + + // allow if old and new style sheet has same family + pStyleSheet->GetFamily() == pOldStyleSheet->GetFamily() || + + // allow if old was background objects and new is graphics + (pStyleSheet->GetFamily() == SfxStyleFamily::Para && pOldStyleSheet->GetHelpId( aStr ) == HID_PSEUDOSHEET_BACKGROUNDOBJECTS) || + + // allow if old was presentation and we are a drawing document + (pOldStyleSheet->GetFamily() == SfxStyleFamily::Page && mpDoc->GetDocumentType() == DocumentType::Draw) ) + { + mpView->SetStyleSheet( static_cast<SfxStyleSheet*>(pStyleSheet)); + mpDoc->SetChanged(); + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_STYLE_FAMILY2 ); + } + } + break; + + case SID_STYLE_WATERCAN: + { + if( !SD_MOD()->GetWaterCan() ) + { + if (pArgs && pArgs->GetItemState( nSId ) == SfxItemState::SET) + { + aStyleName = static_cast<const SfxStringItem &>( pArgs->Get( nSId ) ).GetValue(); + SD_MOD()->SetWaterCan( true ); + pStyleSheet = pSSPool->Find( aStyleName, nFamily); + } + // no presentation object templates, they are only allowed implicitly + if( pStyleSheet && pStyleSheet->GetFamily() != SfxStyleFamily::Pseudo ) + { + static_cast<SdStyleSheetPool*>( pSSPool )->SetActualStyleSheet( pStyleSheet ); + + // we switch explicitly into selection mode + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_OBJECT_SELECT, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); + + } + else + SD_MOD()->SetWaterCan( false ); + } + else + { + SD_MOD()->SetWaterCan( false ); + // we have to re-enable to tools-bar + mpViewShell->Invalidate(); + } + } + break; + + default: + break; + } + + switch( nSId ) + { + case SID_STYLE_NEW: + case SID_STYLE_EDIT: + { + PresentationObjects ePO = PresentationObjects::Outline_1; + + if( pStyleSheet ) + { + ScopedVclPtr<SfxAbstractTabDialog> pStdDlg; + ScopedVclPtr<SfxAbstractTabDialog> pPresDlg; + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + + SfxStyleFamily eFamily = pStyleSheet->GetFamily(); + + if (eFamily == SfxStyleFamily::Para) + { + pStdDlg.disposeAndReset(pFact ? pFact->CreateSdTabTemplateDlg(mpViewShell->GetFrameWeld(), mpDoc->GetDocSh(), *pStyleSheet, mpDoc, mpView) : nullptr); + } + else if (eFamily == SfxStyleFamily::Pseudo) + { + OUString aName(pStyleSheet->GetName()); + bool bBackground = false; + bool bOldDocInOtherLanguage = false; + + if (aName == SdResId(STR_PSEUDOSHEET_TITLE)) + { + ePO = PresentationObjects::Title; + } + else if (aName == SdResId(STR_PSEUDOSHEET_SUBTITLE)) + { + ePO = PresentationObjects::Subtitle; + } + else if (aName == + SdResId(STR_PSEUDOSHEET_BACKGROUND)) + { + bBackground = true; + ePO = PresentationObjects::Background; + } + else if (aName == + SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS)) + { + ePO = PresentationObjects::BackgroundObjects; + } + else if (aName == + SdResId(STR_PSEUDOSHEET_NOTES)) + { + ePO = PresentationObjects::Notes; + } + else if(aName.indexOf(SdResId(STR_PSEUDOSHEET_OUTLINE)) != -1) + { + OUString aOutlineStr(SdResId(STR_PSEUDOSHEET_OUTLINE)); + // determine number, mind the blank between name and number + std::u16string_view aNumStr(aName.subView(aOutlineStr.getLength() + 1)); + sal_uInt16 nLevel = static_cast<sal_uInt16>(o3tl::toInt32(aNumStr)); + switch (nLevel) + { + case 1: ePO = PresentationObjects::Outline_1; break; + case 2: ePO = PresentationObjects::Outline_2; break; + case 3: ePO = PresentationObjects::Outline_3; break; + case 4: ePO = PresentationObjects::Outline_4; break; + case 5: ePO = PresentationObjects::Outline_5; break; + case 6: ePO = PresentationObjects::Outline_6; break; + case 7: ePO = PresentationObjects::Outline_7; break; + case 8: ePO = PresentationObjects::Outline_8; break; + case 9: ePO = PresentationObjects::Outline_9; break; + } + } + else + { + OSL_FAIL("StyleSheet from older version with different language"); + bOldDocInOtherLanguage = true; + } + + if( !bOldDocInOtherLanguage ) + { + pPresDlg.disposeAndReset(pFact ? pFact->CreateSdPresLayoutTemplateDlg(mpDocSh, mpViewShell->GetFrameWeld(), bBackground, *pStyleSheet, ePO, pSSPool ) : nullptr); + } + } + + sal_uInt16 nResult = RET_CANCEL; + const SfxItemSet* pOutSet = nullptr; + if (pStdDlg) + { + nResult = pStdDlg->Execute(); + pOutSet = pStdDlg->GetOutputItemSet(); + } + else if( pPresDlg ) + { + nResult = pPresDlg->Execute(); + pOutSet = pPresDlg->GetOutputItemSet(); + } + + switch( nResult ) + { + case RET_OK: + { + nRetMask = static_cast<sal_uInt16>(pStyleSheet->GetMask()); + + if (eFamily == SfxStyleFamily::Pseudo) + { + SfxItemSet aTempSet(*pOutSet); + /* Extract SvxBrushItem out of set and insert SvxColorItem */ + const SvxBrushItem* pBrushItem = aTempSet.GetItem<SvxBrushItem>( SID_ATTR_BRUSH_CHAR ); + + if ( pBrushItem ) + { + SvxColorItem aBackColorItem(pBrushItem->GetColor(), EE_CHAR_BKGCOLOR); + aTempSet.ClearItem( EE_CHAR_BKGCOLOR ); + aTempSet.Put( aBackColorItem ); + } + static_cast<SdStyleSheet*>(pStyleSheet)->AdjustToFontHeight(aTempSet); + + /* Special treatment: reset the INVALIDS to + NULL-Pointer (otherwise INVALIDs or pointer point + to DefaultItems in the template; both would + prevent the attribute inheritance) */ + aTempSet.ClearInvalidItems(); + + // EE_PARA_NUMBULLET item is only valid in first outline template + if( (ePO >= PresentationObjects::Outline_2) && (ePO <= PresentationObjects::Outline_9) ) + { + if (aTempSet.GetItemState(EE_PARA_NUMBULLET) == SfxItemState::SET) + { + SvxNumRule aRule(aTempSet.GetItem<SvxNumBulletItem>(EE_PARA_NUMBULLET)->GetNumRule()); + + OUString sStyleName(SdResId(STR_PSEUDOSHEET_OUTLINE) + " 1"); + SfxStyleSheetBase* pFirstStyleSheet = pSSPool->Find( sStyleName, SfxStyleFamily::Pseudo); + + if(pFirstStyleSheet) + { + pFirstStyleSheet->GetItemSet().Put( SvxNumBulletItem( aRule, EE_PARA_NUMBULLET )); + SdStyleSheet* pRealSheet = static_cast<SdStyleSheet*>(pFirstStyleSheet)->GetRealStyleSheet(); + pRealSheet->Broadcast(SfxHint(SfxHintId::DataChanged)); + } + + aTempSet.ClearItem( EE_PARA_NUMBULLET ); + } + } + + pStyleSheet->GetItemSet().Put(aTempSet); + SdStyleSheet::BroadcastSdStyleSheetChange(pStyleSheet, ePO, pSSPool); + } + + SfxItemSet& rAttr = pStyleSheet->GetItemSet(); + + sdr::properties::CleanupFillProperties( rAttr ); + + // check for unique names of named items for xml + if( rAttr.GetItemState( XATTR_FILLBITMAP ) == SfxItemState::SET ) + { + const SfxPoolItem* pOldItem = rAttr.GetItem( XATTR_FILLBITMAP ); + std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XFillBitmapItem*>(pOldItem)->checkForUniqueItem( mpDoc ); + if( pNewItem ) + { + rAttr.Put( std::move(pNewItem) ); + } + } + if( rAttr.GetItemState( XATTR_LINEDASH ) == SfxItemState::SET ) + { + const SfxPoolItem* pOldItem = rAttr.GetItem( XATTR_LINEDASH ); + std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XLineDashItem*>(pOldItem)->checkForUniqueItem( mpDoc ); + if( pNewItem ) + { + rAttr.Put( std::move(pNewItem) ); + } + } + if( rAttr.GetItemState( XATTR_LINESTART ) == SfxItemState::SET ) + { + const SfxPoolItem* pOldItem = rAttr.GetItem( XATTR_LINESTART ); + std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XLineStartItem*>(pOldItem)->checkForUniqueItem( mpDoc ); + if( pNewItem ) + { + rAttr.Put( std::move(pNewItem) ); + } + } + if( rAttr.GetItemState( XATTR_LINEEND ) == SfxItemState::SET ) + { + const SfxPoolItem* pOldItem = rAttr.GetItem( XATTR_LINEEND ); + std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XLineEndItem*>(pOldItem)->checkForUniqueItem( mpDoc ); + if( pNewItem ) + { + rAttr.Put( std::move(pNewItem) ); + } + } + if( rAttr.GetItemState( XATTR_FILLGRADIENT ) == SfxItemState::SET ) + { + const SfxPoolItem* pOldItem = rAttr.GetItem( XATTR_FILLGRADIENT ); + std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XFillGradientItem*>(pOldItem)->checkForUniqueItem( mpDoc ); + if( pNewItem ) + { + rAttr.Put( std::move(pNewItem) ); + } + } + if( rAttr.GetItemState( XATTR_FILLFLOATTRANSPARENCE ) == SfxItemState::SET ) + { + const SfxPoolItem* pOldItem = rAttr.GetItem( XATTR_FILLFLOATTRANSPARENCE ); + std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XFillFloatTransparenceItem*>(pOldItem)->checkForUniqueItem( mpDoc ); + if( pNewItem ) + { + rAttr.Put( std::move(pNewItem) ); + } + } + if( rAttr.GetItemState( XATTR_FILLHATCH ) == SfxItemState::SET ) + { + const SfxPoolItem* pOldItem = rAttr.GetItem( XATTR_FILLHATCH ); + std::unique_ptr<SfxPoolItem> pNewItem = static_cast<const XFillHatchItem*>(pOldItem)->checkForUniqueItem( mpDoc ); + if( pNewItem ) + { + rAttr.Put( std::move(pNewItem) ); + } + } + + static_cast<SfxStyleSheet*>( pStyleSheet )->Broadcast( SfxHint( SfxHintId::DataChanged ) ); + + DrawViewShell* pDrawViewShell = dynamic_cast< DrawViewShell* >( mpViewShell ); + if( pDrawViewShell ) + { + PageKind ePageKind = pDrawViewShell->GetPageKind(); + if( ePageKind == PageKind::Notes || ePageKind == PageKind::Handout ) + { + SdPage* pPage = mpViewShell->GetActualPage(); + + if(pDrawViewShell->GetEditMode() == EditMode::MasterPage) + { + pPage = static_cast<SdPage*>((&(pPage->TRG_GetMasterPage()))); + } + + if( pPage ) + { + SdrObjListIter aIter( pPage ); + while( aIter.IsMore() ) + { + SdrObject* pObj = aIter.Next(); + if( dynamic_cast< const SdrPageObj *>( pObj ) != nullptr ) + { + // repaint only + pObj->ActionChanged(); + // pObj->SendRepaintBroadcast(); + } + } + } + } + } + + if( mpDoc->GetOnlineSpell() ) + { + if( SfxItemState::SET == rAttr.GetItemState(EE_CHAR_LANGUAGE, false ) || + SfxItemState::SET == rAttr.GetItemState(EE_CHAR_LANGUAGE_CJK, false ) || + SfxItemState::SET == rAttr.GetItemState(EE_CHAR_LANGUAGE_CTL, false ) ) + { + mpDoc->StopOnlineSpelling(); + mpDoc->StartOnlineSpelling(); + } + } + + mpDoc->SetChanged(); + } + break; + + default: + { + if( nSId == SID_STYLE_NEW ) + pSSPool->Remove( pStyleSheet ); + } + return; // Cancel + } + } + } + break; + + case SID_STYLE_NEW_BY_EXAMPLE: + { + if( pStyleSheet ) + { + nRetMask = static_cast<sal_uInt16>(pStyleSheet->GetMask()); + SfxItemSet aCoreSet( mpDoc->GetPool() ); + mpView->GetAttributes( aCoreSet, true ); + + // if the object had a template, this becomes parent of the new template + SfxStyleSheet* pOldStyle = mpView->GetStyleSheet(); + + // if pOldStyle == pStyleSheet -> recursion + if( pOldStyle != pStyleSheet ) + { + if (pOldStyle) + { + pStyleSheet->SetParent(pOldStyle->GetName()); + } + + SfxItemSet* pStyleSet = &pStyleSheet->GetItemSet(); + pStyleSet->Put(aCoreSet); + + /* apply template (but not when somebody is editing a text. + To do this, the edit engine had to be capable to use + templates on a character level. */ + if (!mpView->GetTextEditObject()) + { + mpView->SetStyleSheet( static_cast<SfxStyleSheet*>(pStyleSheet)); + } + + static_cast<SfxStyleSheet*>( pStyleSheet )->Broadcast( SfxHint( SfxHintId::DataChanged ) ); + mpDoc->SetChanged(); + + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_STYLE_FAMILY2 ); + } + } + } + break; + + case SID_STYLE_UPDATE_BY_EXAMPLE: + { + if ((mpView->AreObjectsMarked() && mpView->GetMarkedObjectList().GetMarkCount() == 1) || + dynamic_cast< const OutlineView *>( mpView ) != nullptr) + { + pStyleSheet = mpView->GetStyleSheet(); + + if( pStyleSheet ) + { + nRetMask = static_cast<sal_uInt16>(pStyleSheet->GetMask()); + SfxItemSet aCoreSet( mpDoc->GetPool() ); + mpView->GetAttributes( aCoreSet ); + + SfxItemSet* pStyleSet = &pStyleSheet->GetItemSet(); + pStyleSet->Put( aCoreSet ); + + mpView->SetStyleSheet( static_cast<SfxStyleSheet*>(pStyleSheet)); + + static_cast<SfxStyleSheet*>( pStyleSheet )->Broadcast( SfxHint( SfxHintId::DataChanged ) ); + mpDoc->SetChanged(); + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_STYLE_FAMILY2 ); + } + } + } + break; + + } + if( nRetMask != static_cast<sal_uInt16>(SfxStyleSearchBits::All) ) + rReq.SetReturnValue( SfxUInt16Item( nSId, nRetMask ) ); +} + +void FuTemplate::Activate() +{ +} + +void FuTemplate::Deactivate() +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/futext.cxx b/sd/source/ui/func/futext.cxx new file mode 100644 index 000000000..725bf96e1 --- /dev/null +++ b/sd/source/ui/func/futext.cxx @@ -0,0 +1,1464 @@ +/* -*- 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 <futext.hxx> +#include <editeng/eeitem.hxx> +#include <svx/sdrpagewindow.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <tools/urlobj.hxx> +#include <vcl/help.hxx> +#include <editeng/fhgtitem.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svx/svdotext.hxx> +#include <editeng/flditem.hxx> +#include <svl/style.hxx> +#include <svx/svdpagv.hxx> +#include <svx/sdtmfitm.hxx> +#include <svx/sdtagitm.hxx> +#include <svx/sdtfsitm.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <editeng/editeng.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svxids.hrc> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <sfx2/docfile.hxx> +#include <editeng/outlobj.hxx> +#include <osl/diagnose.h> + +#include <editeng/frmdiritem.hxx> + +#include <svx/svdetc.hxx> +#include <editeng/editview.hxx> + +#include <sdresid.hxx> +#include <app.hrc> + +#include <ViewShell.hxx> +#include <ViewShellBase.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <drawdoc.hxx> +#include <sdpage.hxx> +#include <FrameView.hxx> +#include <ToolBarManager.hxx> +#include <DrawDocShell.hxx> +#include <strings.hrc> +#include <pres.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::linguistic2; + +namespace sd { + +const sal_uInt16 SidArray[] = { + SID_STYLE_FAMILY2, // 5542 + SID_STYLE_FAMILY5, // 5545 + SID_REDO, // 5700 + SID_UNDO, // 5701 + SID_CUT, // 5710 + SID_COPY, // 5711 + SID_ATTR_TABSTOP, // 10002 + SID_ATTR_CHAR_FONT, // 10007 + SID_ATTR_CHAR_POSTURE, // 10008 + SID_ATTR_CHAR_WEIGHT, // 10009 + SID_ATTR_CHAR_SHADOWED, // 10010 + SID_ATTR_CHAR_STRIKEOUT, // 10013 + SID_ATTR_CHAR_UNDERLINE, // 10014 + SID_ATTR_CHAR_FONTHEIGHT, // 10015 + SID_ATTR_CHAR_COLOR, // 10017 + SID_ATTR_CHAR_KERNING, // 10018 + SID_ATTR_CHAR_CASEMAP, // 10019 + SID_ATTR_PARA_ADJUST_LEFT, // 10028 + SID_ATTR_PARA_ADJUST_RIGHT, // 10029 + SID_ATTR_PARA_ADJUST_CENTER, // 10030 + SID_ATTR_PARA_ADJUST_BLOCK, // 10031 + SID_ATTR_PARA_LINESPACE_10, // 10034 + SID_ATTR_PARA_LINESPACE_15, // 10035 + SID_ATTR_PARA_LINESPACE_20, // 10036 + SID_ATTR_PARA_ULSPACE, // 10042 + SID_ATTR_PARA_LRSPACE, // 10043 + SID_ATTR_TRANSFORM_POS_X, // 10088 + SID_ATTR_TRANSFORM_POS_Y, // 10089 + SID_ATTR_TRANSFORM_WIDTH, // 10090 + SID_ATTR_TRANSFORM_HEIGHT, // 10091 + SID_ATTR_TRANSFORM_ROT_X, // 10093 + SID_ATTR_TRANSFORM_ROT_Y, // 10094 + SID_ATTR_TRANSFORM_ANGLE, // 10095 //Added + SID_OUTLINE_UP, // 10150 + SID_OUTLINE_DOWN, // 10151 + SID_OUTLINE_LEFT, // 10152 + SID_OUTLINE_RIGHT, // 10153 + SID_ATTR_TRANSFORM_PROTECT_POS, // 10236 + SID_ATTR_TRANSFORM_PROTECT_SIZE, // 10237 //Added + SID_FORMTEXT_STYLE, // 10257 + SID_SET_SUPER_SCRIPT, // 10294 + SID_SET_SUB_SCRIPT, // 10295 + SID_ATTR_TRANSFORM_AUTOWIDTH, // 10310 + SID_ATTR_TRANSFORM_AUTOHEIGHT, // 10311 //Added + SID_HYPERLINK_GETLINK, // 10361 + SID_DEC_INDENT, // 10461 + SID_INC_INDENT, // 10462 + SID_CHARMAP, // 10503 + SID_TEXTDIRECTION_LEFT_TO_RIGHT, // 10907 + SID_TEXTDIRECTION_TOP_TO_BOTTOM, // 10908 + SID_ATTR_PARA_LEFT_TO_RIGHT, // 10950 + SID_ATTR_PARA_RIGHT_TO_LEFT, // 10951 + SID_PARASPACE_INCREASE, // 11145 + SID_PARASPACE_DECREASE, // 11146 + FN_NUM_BULLET_ON, // 20138 + 0 }; + + +/** + * base class for text functions + */ +FuText::FuText( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +: FuConstruct(pViewSh, pWin, pView, pDoc, rReq) +, bFirstObjCreated(false) +, bJustEndedEdit(false) +, rRequest (rReq) +{ +} + +rtl::Reference<FuPoor> FuText::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuText( pViewSh, pWin, pView, pDoc, rReq ) ); + return xFunc; +} + +void FuText::disposing() +{ + if(mpView) + { + if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted) + mxTextObj.reset(nullptr); + + // reset the RequestHandler of the used Outliner to the handler of the document + ::Outliner* pOutliner = mpView->GetTextEditOutliner(); + + if (pOutliner) + pOutliner->SetStyleSheetPool(static_cast<SfxStyleSheetPool*>(mpDoc->GetStyleSheetPool())); + } +} + +/************************************************************************* +|* +|* Execute functionality of this class: +|* +|* #71422: Start the functionality of this class in this method +|* and not in the ctor. +|* If you construct an object of this class and you put the +|* address of this object to pFuActual you've got a problem, +|* because some methods inside DoExecute use the pFuActual-Pointer. +|* If the code inside DoExecute is executed inside the ctor, +|* the value of pFuActual is not right. And the value will not +|* be right until the ctor finished !!! +|* +\************************************************************************/ +void FuText::DoExecute( SfxRequest& ) +{ + mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBarShell( + ToolBarManager::ToolBarGroup::Function, + ToolbarId::Draw_Text_Toolbox_Sd); + + mpView->SetCurrentObj(SdrObjKind::Text); + mpView->SetEditMode(SdrViewEditMode::Edit); + + MouseEvent aMEvt(mpWindow->GetPointerPosPixel()); + + if (nSlotId == SID_TEXTEDIT) + { + // Try to select an object + SdrPageView* pPV = mpView->GetSdrPageView(); + SdrViewEvent aVEvt; + mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + mpView->MarkObj(aVEvt.mpRootObj, pPV); + + mxTextObj.reset( dynamic_cast< SdrTextObj* >( aVEvt.mpObj ) ); + } + else if (mpView->AreObjectsMarked()) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if (rMarkList.GetMarkCount() == 1) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + mxTextObj.reset( dynamic_cast< SdrTextObj* >( pObj ) ); + } + } + + // check for table + if (mpView->AreObjectsMarked()) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if (rMarkList.GetMarkCount() == 1) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if( pObj && (pObj->GetObjInventor() == SdrInventor::Default ) && (pObj->GetObjIdentifier() == SdrObjKind::Table) ) + { + mpViewShell->GetViewShellBase().GetToolBarManager()->AddToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Draw_Table_Toolbox); + } + } + } + + bool bQuickDrag = true; + + const SfxItemSet* pArgs = rRequest.GetArgs(); + + if (pArgs + + // test for type before using + && SID_TEXTEDIT == nSlotId + && SfxItemState::SET == pArgs->GetItemState(SID_TEXTEDIT) + + && static_cast<const SfxUInt16Item&>(pArgs->Get(SID_TEXTEDIT)).GetValue() == 2) + { + // Selection by doubleclick -> don't allow QuickDrag + bQuickDrag = false; + } + + SetInEditMode(aMEvt, bQuickDrag); +} + +bool FuText::MouseButtonDown(const MouseEvent& rMEvt) +{ + bMBDown = true; + bJustEndedEdit = false; + + bool bReturn = FuDraw::MouseButtonDown(rMEvt); + + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + // handle URL also during the text editing + if (rMEvt.GetClicks() == 1 && rMEvt.IsLeft() && rMEvt.IsMod1()) + { + OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); + + if (mxTextObj.is() && pOLV && pOLV->GetFieldUnderMousePointer()) + { + const SvxFieldItem* pFieldItem = pOLV->GetFieldUnderMousePointer(); + if (pFieldItem) + { + const SvxFieldData* pField = pFieldItem->GetField(); + + if (auto pURLField = dynamic_cast< const SvxURLField *>( pField )) + { + eHit = SdrHitKind::MarkedObject; + aVEvt.meEvent = SdrEventKind::ExecuteUrl; + aVEvt.mpURLField = pURLField; + } + } + } + } + + if (eHit == SdrHitKind::TextEdit) + { + // hit text -> SdrView handles event + if (mpView->MouseButtonDown(rMEvt, mpWindow->GetOutDev())) + return true; + } + + if (rMEvt.GetClicks() == 1) + { + if (mpView->IsTextEdit() && eHit != SdrHitKind::MarkedObject && eHit != SdrHitKind::Handle) + { + // finish text input + if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted) + { + /* Bugfix from MBA: during a double click onto the unused? area + in text mode, we get with the second click eHit = + SdrHitKind::TextEditObj since it goes to the TextObject which was + created with the first click. But this is removed by + SdrEndTextEdit since it is empty. But it is still in the mark + list. The call MarkObj further below accesses then the dead + object. As a simple fix, we determine eHit after + SdrEndTextEdit again, this returns then SdrHitKind::NONE. */ + mxTextObj.reset(nullptr); + eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + } + + mpView->SetCurrentObj(SdrObjKind::Text); + mpView->SetEditMode(SdrViewEditMode::Edit); + } + + if (rMEvt.IsLeft() || rMEvt.IsRight()) + { + mpWindow->CaptureMouse(); + SdrPageView* pPV = mpView->GetSdrPageView(); + + if (eHit == SdrHitKind::TextEdit) + { + SetInEditMode(rMEvt, false); + } + else + { + // Don't remark table when clicking in it, mark change triggers a lot of updating + bool bMarkChanges = true; + rtl::Reference< sdr::SelectionController > xSelectionController(mpView->getSelectionController()); + if (eHit == SdrHitKind::TextEditObj && xSelectionController.is()) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1 && rMarkList.GetMark(0)->GetMarkedSdrObj() == aVEvt.mpRootObj) + bMarkChanges = false; + } + + if (eHit != SdrHitKind::Handle) + { + // deselect selection + if (!rMEvt.IsShift() && eHit == SdrHitKind::TextEditObj) + { + if(bMarkChanges) + { + mpView->UnmarkAll(); + mpView->SetDragMode(SdrDragMode::Move); + } + } + } + + if ( aVEvt.meEvent == SdrEventKind::ExecuteUrl || + eHit == SdrHitKind::Handle || + eHit == SdrHitKind::MarkedObject || + eHit == SdrHitKind::TextEditObj || + ( eHit == SdrHitKind::UnmarkedObject && bFirstObjCreated && + !bPermanent ) ) + { + // Handle, hit marked or unmarked object + if (eHit == SdrHitKind::TextEditObj) + { + /* hit text of unmarked object: + select object and set to EditMode */ + if (bMarkChanges) + mpView->MarkObj(aVEvt.mpRootObj, pPV); + + if (auto pSdrTextObj = dynamic_cast<SdrTextObj*>(aVEvt.mpObj)) + { + mxTextObj.reset( pSdrTextObj ); + } + + SetInEditMode(rMEvt, true); + } + else if (aVEvt.meEvent == SdrEventKind::ExecuteUrl && !rMEvt.IsMod2()) + { + // execute URL + mpWindow->ReleaseMouse(); + SfxStringItem aStrItem(SID_FILE_NAME, aVEvt.mpURLField->GetURL()); + SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName()); + SfxBoolItem aBrowseItem( SID_BROWSE, true ); + SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); + mpWindow->ReleaseMouse(); + + if (rMEvt.IsMod1()) + { + // open in new frame + pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aStrItem, &aBrowseItem, &aReferer }); + } + else + { + // open in current frame + SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame); + pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, + { &aStrItem, &aFrameItem, &aBrowseItem, &aReferer }); + } + } + else + { + // drag object or handle + + // #i78748# + // do the EndTextEdit first, it will delete the handles and force a + // recreation. This will make aVEvt.mpHdl to point to a deleted handle, + // thus it is necessary to reset it and to get it again. + + // #i112855# + // cl: I'm not sure why we checked here also for mxTextObj->GetOutlinerParaObject + // this caused SdrEndTextEdit() to be called also when not in text editing and + // this does not make sense and caused troubles. (see issue 112855) + + if( mpView->IsTextEdit() ) + { + mpView->SdrEndTextEdit(); + bJustEndedEdit = true; + + if(aVEvt.mpHdl) + { + // force new handle identification, the pointer will be dead here + // since SdrEndTextEdit has reset (deleted) the handles. + aVEvt.mpHdl = nullptr; + mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + } + } + + if (!aVEvt.mpHdl) + { + if( eHit == SdrHitKind::UnmarkedObject ) + { + if ( !rMEvt.IsShift() ) + mpView->UnmarkAll(); + + mpView->MarkObj(aVEvt.mpRootObj, pPV); + } + + // Drag object + bFirstMouseMove = true; + aDragTimer.Start(); + } + + if ( ! rMEvt.IsRight()) + { + // we need to pick again since SdrEndTextEdit can rebuild the handles list + eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + if( (eHit == SdrHitKind::Handle) || (eHit == SdrHitKind::MarkedObject) ) + { + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + mpView->BegDragObj(aMDPos, nullptr, aVEvt.mpHdl, nDrgLog); + } + } + bReturn = true; + } + } + else if ( nSlotId != SID_TEXTEDIT && + (bPermanent || !bFirstObjCreated) ) + { + // create object + mpView->SetCurrentObj(SdrObjKind::Text); + mpView->SetEditMode(SdrViewEditMode::Create); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + mpView->BegCreateObj(aMDPos, nullptr, nDrgLog); + } + else + { + // select + if( !rMEvt.IsShift() ) + mpView->UnmarkAll(); + + mpView->BegMarkObj( aMDPos ); + } + } + } + } + else if ( rMEvt.GetClicks() == 2 && !mpView->IsTextEdit() ) + { + MouseEvent aMEvt( mpWindow->GetPointerPosPixel() ); + SetInEditMode( aMEvt, false ); + } + + if (!bIsInDragMode) + { + ForcePointer(&rMEvt); + mpViewShell->GetViewFrame()->GetBindings().Invalidate(SidArray); + } + + return bReturn; +} + +bool FuText::MouseMove(const MouseEvent& rMEvt) +{ + bool bReturn = FuDraw::MouseMove(rMEvt); + + if (aDragTimer.IsActive() ) + { + if( bFirstMouseMove ) + bFirstMouseMove = false; + else + aDragTimer.Stop(); + } + + if (!bReturn && mpView->IsAction() && !mpDocSh->IsReadOnly()) + { + Point aPix(rMEvt.GetPosPixel()); + Point aPnt(mpWindow->PixelToLogic(aPix)); + + ForceScroll(aPix); + mpView->MovAction(aPnt); + } + + ForcePointer(&rMEvt); + + return bReturn; +} + +void FuText::ImpSetAttributesForNewTextObject(SdrTextObj* pTxtObj) +{ + if(mpDoc->GetDocumentType() == DocumentType::Impress) + { + if( nSlotId == SID_ATTR_CHAR ) + { + /* Create Impress text object (rescales to line height) + We get the correct height during the subsequent creation of the + object, otherwise we draw too much */ + SfxItemSet aSet(mpViewShell->GetPool()); + aSet.Put(makeSdrTextMinFrameHeightItem(0)); + aSet.Put(makeSdrTextAutoGrowWidthItem(false)); + aSet.Put(makeSdrTextAutoGrowHeightItem(true)); + pTxtObj->SetMergedItemSet(aSet); + pTxtObj->AdjustTextFrameWidthAndHeight(); + aSet.Put(makeSdrTextMaxFrameHeightItem(pTxtObj->GetLogicRect().GetSize().Height())); + pTxtObj->SetMergedItemSet(aSet); + const SfxViewShell* pCurrentViewShell = SfxViewShell::Current(); + if (pCurrentViewShell && (pCurrentViewShell->isLOKMobilePhone() || pCurrentViewShell->isLOKTablet())) + pTxtObj->SetText(SdResId(STR_PRESOBJ_TEXT_EDIT_MOBILE)); + } + else if( nSlotId == SID_ATTR_CHAR_VERTICAL ) + { + SfxItemSet aSet(mpViewShell->GetPool()); + aSet.Put(makeSdrTextMinFrameWidthItem(0)); + aSet.Put(makeSdrTextAutoGrowWidthItem(true)); + aSet.Put(makeSdrTextAutoGrowHeightItem(false)); + + // Needs to be set since default is SDRTEXTHORZADJUST_BLOCK + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + pTxtObj->SetMergedItemSet(aSet); + pTxtObj->AdjustTextFrameWidthAndHeight(); + aSet.Put(makeSdrTextMaxFrameWidthItem(pTxtObj->GetLogicRect().GetSize().Width())); + pTxtObj->SetMergedItemSet(aSet); + } + } + else + { + if( nSlotId == SID_ATTR_CHAR_VERTICAL ) + { + // draw text object, needs to be initialized when vertical text is used + SfxItemSet aSet(mpViewShell->GetPool()); + + aSet.Put(makeSdrTextAutoGrowWidthItem(true)); + aSet.Put(makeSdrTextAutoGrowHeightItem(false)); + + // Set defaults for vertical click-n'drag text object, pool defaults are: + // SdrTextVertAdjustItem: SDRTEXTVERTADJUST_TOP + // SdrTextHorzAdjustItem: SDRTEXTHORZADJUST_BLOCK + // Analog to that: + aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + + pTxtObj->SetMergedItemSet(aSet); + } + } +} + +void FuText::ImpSetAttributesFitToSize(SdrTextObj* pTxtObj) +{ + // FitToSize (fit to frame) + SfxItemSetFixed<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWWIDTH> aSet(mpViewShell->GetPool()); + aSet.Put(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_PROPORTIONAL)); + aSet.Put(makeSdrTextAutoGrowHeightItem(false)); + aSet.Put(makeSdrTextAutoGrowWidthItem(false)); + pTxtObj->SetMergedItemSet(aSet); + pTxtObj->AdjustTextFrameWidthAndHeight(); +} + +void FuText::ImpSetAttributesFitToSizeVertical(SdrTextObj* pTxtObj) +{ + SfxItemSetFixed<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWWIDTH> aSet(mpViewShell->GetPool()); + aSet.Put(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_PROPORTIONAL)); + aSet.Put(makeSdrTextAutoGrowHeightItem(false)); + aSet.Put(makeSdrTextAutoGrowWidthItem(false)); + pTxtObj->SetMergedItemSet(aSet); + pTxtObj->AdjustTextFrameWidthAndHeight(); +} + +void FuText::ImpSetAttributesFitCommon(SdrTextObj* pTxtObj) +{ + // Normal Textobject + if (mpDoc->GetDocumentType() != DocumentType::Impress) + return; + + if( nSlotId == SID_ATTR_CHAR ) + { + // Impress text object (rescales to line height) + SfxItemSet aSet(mpViewShell->GetPool()); + aSet.Put(makeSdrTextMinFrameHeightItem(0)); + aSet.Put(makeSdrTextMaxFrameHeightItem(0)); + aSet.Put(makeSdrTextAutoGrowHeightItem(true)); + aSet.Put(makeSdrTextAutoGrowWidthItem(false)); + pTxtObj->SetMergedItemSet(aSet); + } + else if( nSlotId == SID_ATTR_CHAR_VERTICAL ) + { + SfxItemSet aSet(mpViewShell->GetPool()); + aSet.Put(makeSdrTextMinFrameWidthItem(0)); + aSet.Put(makeSdrTextMaxFrameWidthItem(0)); + aSet.Put(makeSdrTextAutoGrowWidthItem(true)); + aSet.Put(makeSdrTextAutoGrowHeightItem(false)); + pTxtObj->SetMergedItemSet(aSet); + } + + pTxtObj->AdjustTextFrameWidthAndHeight(); +} + +bool FuText::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = false; + if (aDragTimer.IsActive()) + { + aDragTimer.Stop(); + bIsInDragMode = false; + } + + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); + + Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + + if( (mpView && mpView->MouseButtonUp(rMEvt, mpWindow->GetOutDev())) || rMEvt.GetClicks() == 2 ) + return true; // handle event from SdrView + + bool bEmptyTextObj = false; + + if (mxTextObj.is()) + { + bool bReset = true; + + if (mpView) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if (rMarkList.GetMarkCount() == 1 + && ( rMarkList.GetMark(0)->GetMarkedSdrObj() == mxTextObj.get()) ) + { + if( mxTextObj.is() && !GetTextObj()->GetOutlinerParaObject() ) + bEmptyTextObj = true; + else + bFirstObjCreated = true; + bReset = false; + } + } + + if (bReset) + { + mxTextObj.reset(nullptr); + } + } + + if( mpView && mpView->IsDragObj()) + { + // object was moved + FrameView* pFrameView = mpViewShell->GetFrameView(); + bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); + + if (bDragWithCopy) + { + bDragWithCopy = !mpView->IsPresObjSelected(false); + } + + mpView->SetDragWithCopy(bDragWithCopy); + mpView->EndDragObj( mpView->IsDragWithCopy() ); + mpView->ForceMarkedToAnotherPage(); + mpView->SetCurrentObj(SdrObjKind::Text); + + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + + if (bJustEndedEdit) + { + bJustEndedEdit = false; + FuPoor::cancel(); + } + if ((rMEvt.GetClicks() != 2) && + !rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsRight() && + std::abs(aPnt.X() - aMDPos.X()) < nDrgLog && + std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) + { + /************************************************************* + * From text mode, you don't want to rotate immediately. + **************************************************************/ + SdrPageView* pPV; + SdrObject* pObj = mpView->PickObj(aMDPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK); + if (pObj && pPV->IsObjMarkable(pObj)) + { + mpView->UnmarkAllObj(); + mpView->MarkObj(pObj,pPV); + return bReturn; + } + } + } + else if( mpView && mpView->IsCreateObj() && rMEvt.IsLeft()) + { + // object was created + mxTextObj.reset( dynamic_cast< SdrTextObj* >( mpView->GetCreateObj() ) ); + + if( mxTextObj.is() ) + { + //AW outliner needs to be set to vertical when there is no + // outliner object up to now; also it needs to be set back to not + // vertical when there was a vertical one used last time. + OutlinerParaObject* pOPO = GetTextObj()->GetOutlinerParaObject(); + SdrOutliner& rOutl(mxTextObj->getSdrModelFromSdrObject().GetDrawOutliner(GetTextObj())); + bool bVertical((pOPO && pOPO->IsEffectivelyVertical()) + || nSlotId == SID_ATTR_CHAR_VERTICAL + || nSlotId == SID_TEXT_FITTOSIZE_VERTICAL); + rOutl.SetVertical(bVertical); + + // Before ImpSetAttributesForNewTextObject the vertical writing mode + // needs to be set at the object. This is done here at the OutlinerParaObject + // directly to not mirror the layout text items involved. These items will be set + // from ImpSetAttributesForNewTextObject and below. + OutlinerParaObject* pPara = GetTextObj()->GetOutlinerParaObject(); + + if(!pPara) + { + GetTextObj()->ForceOutlinerParaObject(); + pPara = GetTextObj()->GetOutlinerParaObject(); + } + + if(pPara && bVertical != pPara->IsEffectivelyVertical()) + { + // set ParaObject orientation accordingly + pPara->SetVertical(bVertical); + } + + ImpSetAttributesForNewTextObject(GetTextObj()); + } + + if (!mpView->EndCreateObj(SdrCreateCmd::ForceEnd)) + { + // it was not possible to create text object + mxTextObj.reset(nullptr); + } + else if (nSlotId == SID_TEXT_FITTOSIZE) + { + ImpSetAttributesFitToSize(GetTextObj()); + + SetInEditMode(rMEvt, false); + } + else if ( nSlotId == SID_TEXT_FITTOSIZE_VERTICAL ) + { + ImpSetAttributesFitToSizeVertical(GetTextObj()); + + SetInEditMode(rMEvt, false); + } + else + { + ImpSetAttributesFitCommon(GetTextObj()); + + // thereby the handles and the gray frame are correct + mpView->AdjustMarkHdl(); + mpView->PickHandle(aPnt); + SetInEditMode(rMEvt, false); + } + } + else if ( mpView && mpView->IsAction()) + { + mpView->EndAction(); + } + + ForcePointer(&rMEvt); + mpWindow->ReleaseMouse(); + sal_uInt16 nDrgLog1 = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + + if ( mpView && !mpView->AreObjectsMarked() && + std::abs(aMDPos.X() - aPnt.X()) < nDrgLog1 && + std::abs(aMDPos.Y() - aPnt.Y()) < nDrgLog1 && + !rMEvt.IsShift() && !rMEvt.IsMod2() ) + { + SdrPageView* pPV2 = mpView->GetSdrPageView(); + SdrViewEvent aVEvt; + mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + mpView->MarkObj(aVEvt.mpRootObj, pPV2); + } + + if ( !mxTextObj.is() && mpView ) + { + if ( ( (!bEmptyTextObj && bPermanent) || + (!bFirstObjCreated && !bPermanent) ) && + !mpDocSh->IsReadOnly() && + nSlotId != SID_TEXTEDIT ) + { + // text body (left-justified AutoGrow) + mpView->SetCurrentObj(SdrObjKind::Text); + mpView->SetEditMode(SdrViewEditMode::Create); + sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); + mpView->BegCreateObj(aMDPos, nullptr, nDrgLog); + + bool bSnapEnabled = mpView->IsSnapEnabled(); + + if (bSnapEnabled) + mpView->SetSnapEnabled(false); + + aPnt.AdjustX(nDrgLog + nDrgLog ); + aPnt.AdjustY(nDrgLog + nDrgLog ); + mpView->MovAction(aPnt); + + mxTextObj.reset( dynamic_cast< SdrTextObj* >( mpView->GetCreateObj() ) ); + + if(mxTextObj.is()) + { + GetTextObj()->SetDisableAutoWidthOnDragging(true); + } + + if(!mpView->EndCreateObj(SdrCreateCmd::ForceEnd)) + { + mxTextObj.reset(nullptr); + } + + if(bSnapEnabled) + mpView->SetSnapEnabled(bSnapEnabled); + + if(mxTextObj.is()) + { + SfxItemSet aSet(mpViewShell->GetPool()); + aSet.Put(makeSdrTextMinFrameHeightItem(0)); + aSet.Put(makeSdrTextMinFrameWidthItem(0)); + aSet.Put(makeSdrTextAutoGrowHeightItem(true)); + aSet.Put(makeSdrTextAutoGrowWidthItem(true)); + + if(nSlotId == SID_ATTR_CHAR_VERTICAL) + { + // Here, all items which need to be different from pool default need to be set + // again on the newly created text object. + // Since this is a simple click text object, it is first created, then SetVertical() + // is used, then ImpSetAttributesForNewTextObject is called and then the object is + // deleted again since not the minimum drag distance was travelled. Then, a new + // click text object is created and thus all that stuff needs to be set again here. + + // Before using the new object the vertical writing mode + // needs to be set. This is done here at the OutlinerParaObject + // directly to not mirror the layout text items involved. These items will be set + // below. + OutlinerParaObject* pPara = GetTextObj()->GetOutlinerParaObject(); + + if(!pPara) + { + GetTextObj()->ForceOutlinerParaObject(); + pPara = GetTextObj()->GetOutlinerParaObject(); + } + + if(pPara && !pPara->IsEffectivelyVertical()) + { + // set ParaObject orientation accordingly + pPara->SetVertical(true); + } + + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + + // Analog to the else case below, for vertical simple click texts + // one of the default set items from ImpSetAttributesForNewTextObject + // needs to be adapted to non-block mode. + const SfxItemSet& rSet = mpView->GetDefaultAttr(); + SvxFrameDirection eDirection = rSet.Get(EE_PARA_WRITINGDIR).GetValue(); + + if(SvxFrameDirection::Horizontal_RL_TB == eDirection || SvxFrameDirection::Vertical_RL_TB == eDirection) + { + aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); + } + else + { + aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); + } + } + else + { + // This is for Format/Page settings. Since this also leads + // to the object defaults to be changed, i think this code can be + // removed. CL. wanted to take a look before adding this. + + // Look in the object defaults if left-to-right is wanted. If + // yes, set text anchoring to right to let the box grow to left. + const SfxItemSet& rSet = mpView->GetDefaultAttr(); + SvxFrameDirection eDirection = rSet.Get(EE_PARA_WRITINGDIR).GetValue(); + + if(SvxFrameDirection::Horizontal_RL_TB == eDirection) + { + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + } + else + { + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); + } + } + + GetTextObj()->SetMergedItemSet(aSet); + GetTextObj()->SetDisableAutoWidthOnDragging(true); + SetInEditMode(rMEvt, false); + } + + bFirstObjCreated = true; + } + else + { + // switch to selection + if (mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted) + { + mxTextObj.reset(nullptr); + } + + mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_OBJECT_SELECT, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); + } + } + if (bJustEndedEdit) + { + bJustEndedEdit = false; + FuPoor::cancel(); + } + bMBDown = false; + FuConstruct::MouseButtonUp(rMEvt); + return bReturn; +} + +/** + * handle keyboard events + * @returns sal_True if the event was handled, sal_False otherwise + */ +bool FuText::KeyInput(const KeyEvent& rKEvt) +{ + bool bReturn = false; + + vcl::KeyCode nCode = rKEvt.GetKeyCode(); + bool bShift = nCode.IsShift(); + + if(mxTextObj.is()) + { + // maybe object is deleted, test if it's equal to the selected object + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + SdrObject* pSelectedObj = nullptr; + + if(1 == rMarkList.GetMarkCount()) + { + SdrMark* pMark = rMarkList.GetMark(0); + pSelectedObj = pMark->GetMarkedSdrObj(); + } + + if(mxTextObj.get() != pSelectedObj) + { + mxTextObj.reset(nullptr); + } + } + + if ( mxTextObj.is() && mxTextObj->GetObjInventor() == SdrInventor::Default && mxTextObj->GetObjIdentifier() == SdrObjKind::TitleText && rKEvt.GetKeyCode().GetCode() == KEY_RETURN ) + { + // title text object: always soft breaks + bShift = true; + } + + sal_uInt16 nKey = nCode.GetCode(); + vcl::KeyCode aKeyCode (nKey, bShift, nCode.IsMod1(), nCode.IsMod2(), nCode.IsMod3() ); + KeyEvent aKEvt(rKEvt.GetCharCode(), aKeyCode); + + bool bOK = true; + + if (mpDocSh->IsReadOnly()) + { + bOK = !EditEngine::DoesKeyChangeText(aKEvt); + } + if( aKeyCode.GetCode() == KEY_PAGEUP || aKeyCode.GetCode() == KEY_PAGEDOWN ) + { + bOK = false; // default handling in base class + } + + if (bOK && mpView->KeyInput(aKEvt, mpWindow) ) + { + bReturn = true; + + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); + + } + else if (aKeyCode == KEY_ESCAPE) + { + bReturn = cancel(); + } + + if( bPermanent ) + { + mpView->SetCurrentObj(SdrObjKind::Text); + mpView->SetEditMode(SdrViewEditMode::Create); + } + + if (!bReturn) + { + bReturn = FuDraw::KeyInput(aKEvt); + } + + return bReturn; +} + +void FuText::Activate() +{ + mpView->SetQuickTextEditMode(mpViewShell->GetFrameView()->IsQuickEdit()); + + // #i89661# it's no longer necessary to make it so big here, it's fine tuned + // for text objects in SdrMarkView::CheckSingleSdrObjectHit + mpView->SetHitTolerancePixel( 2 * HITPIX ); + + OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); + + if (pOLV) + pOLV->ShowCursor(/*bGotoCursor=*/true, /*bActivate=*/true); + + FuConstruct::Activate(); + + if( pOLV ) + mpView->SetEditMode(SdrViewEditMode::Edit); +} + +void FuText::Deactivate() +{ + OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); + + if (pOLV) + pOLV->HideCursor(/*bDeactivate=*/true); + + mpView->SetHitTolerancePixel( HITPIX ); + + FuConstruct::Deactivate(); +} + +/** + * Sets the object into the edit mode. + */ +void FuText::SetInEditMode(const MouseEvent& rMEvt, bool bQuickDrag) +{ + SdrPageView* pPV = mpView->GetSdrPageView(); + if( mxTextObj.is() && (mxTextObj->getSdrPageFromSdrObject() == pPV->GetPage()) ) + { + mpView->SetCurrentObj(SdrObjKind::Text); + + if( bPermanent ) + mpView->SetEditMode(SdrViewEditMode::Create); + else + mpView->SetEditMode(SdrViewEditMode::Edit); + + bool bEmptyOutliner = false; + + if (!GetTextObj()->GetOutlinerParaObject() && mpView->GetTextEditOutliner()) + { + ::Outliner* pOutl = mpView->GetTextEditOutliner(); + sal_Int32 nParagraphCnt = pOutl->GetParagraphCount(); + Paragraph* p1stPara = pOutl->GetParagraph( 0 ); + + if (nParagraphCnt==1 && p1stPara) + { + // with only one paragraph + if (pOutl->GetText(p1stPara).isEmpty()) + { + bEmptyOutliner = true; + } + } + } + + if (GetTextObj() != mpView->GetTextEditObject() || bEmptyOutliner) + { + SdrInventor nInv = mxTextObj->GetObjInventor(); + SdrObjKind nSdrObjKind = mxTextObj->GetObjIdentifier(); + + if (nInv == SdrInventor::Default && GetTextObj()->HasTextEdit() && + (nSdrObjKind == SdrObjKind::Text || + nSdrObjKind == SdrObjKind::TitleText || + nSdrObjKind == SdrObjKind::OutlineText || !mxTextObj->IsEmptyPresObj() ) ) + { + // create new outliner (owned by SdrObjEditView) + std::unique_ptr<SdrOutliner> pOutl = SdrMakeOutliner(OutlinerMode::OutlineObject, *mpDoc); + + if (bEmptyOutliner) + mpView->SdrEndTextEdit(true); + + SdrTextObj* pTextObj = GetTextObj(); + if( pTextObj ) + { + OutlinerParaObject* pOPO = pTextObj->GetOutlinerParaObject(); + if( pOPO && pOPO->IsEffectivelyVertical() ) + { + pOutl->SetVertical(pOPO->GetVertical()); + pOutl->SetRotation(pOPO->GetRotation()); + } + else if (nSlotId == SID_ATTR_CHAR_VERTICAL || nSlotId == SID_TEXT_FITTOSIZE_VERTICAL) + pOutl->SetVertical( true ); + + if( pTextObj->getTextCount() > 1 ) + { + Point aPix(rMEvt.GetPosPixel()); + Point aPnt(mpWindow->PixelToLogic(aPix)); + pTextObj->setActiveText( pTextObj->CheckTextHit(aPnt ) ); + } + + if (mpView->SdrBeginTextEdit(pTextObj, pPV, mpWindow, true, pOutl.release()) && mxTextObj->GetObjInventor() == SdrInventor::Default) + { + //tdf#102293 flush overlay before going on to pass clicks down to + //the outline view which will want to paint selections + for (sal_uInt32 b = 0; b < pPV->PageWindowCount(); ++b) + { + const SdrPageWindow& rPageWindow = *pPV->GetPageWindow(b); + if (!rPageWindow.GetPaintWindow().OutputToWindow()) + continue; + const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); + if (!xManager.is()) + continue; + xManager->flush(); + } + + bFirstObjCreated = true; + DeleteDefaultText(); + + OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); + + nSdrObjKind = mxTextObj->GetObjIdentifier(); + + SdrViewEvent aVEvt; + SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (eHit == SdrHitKind::TextEdit) + { + // hit text + if (nSdrObjKind == SdrObjKind::Text || + nSdrObjKind == SdrObjKind::TitleText || + nSdrObjKind == SdrObjKind::OutlineText || + nSdrObjKind == SdrObjKind::Table || + nSlotId == SID_TEXTEDIT || + !bQuickDrag) + { + pOLV->MouseButtonDown(rMEvt); + pOLV->MouseMove(rMEvt); + pOLV->MouseButtonUp(rMEvt); + } + + if (mpViewShell->GetFrameView()->IsQuickEdit() && bQuickDrag && GetTextObj()->GetOutlinerParaObject()) + { + pOLV->MouseButtonDown(rMEvt); + } + } + else + { + // Move cursor to end of text + ESelection aNewSelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND); + if (pOLV != nullptr) + pOLV->SetSelection(aNewSelection); + } + } + else + { + mpView->RestoreDefaultText( mxTextObj.get() ); + } + } + } + } + } + else + { + mxTextObj.reset(nullptr); + } +} + +/** + * Text entry is started, if necessary delete the default text. + */ +void FuText::DeleteDefaultText() +{ + if ( !(mxTextObj.is() && mxTextObj->IsEmptyPresObj()) ) + return; + + SdPage* pPage = static_cast<SdPage*>( mxTextObj->getSdrPageFromSdrObject() ); + + if (!pPage) + return; + + PresObjKind ePresObjKind = pPage->GetPresObjKind(mxTextObj.get()); + + if ( !(ePresObjKind == PresObjKind::Title || + ePresObjKind == PresObjKind::Outline || + ePresObjKind == PresObjKind::Notes || + ePresObjKind == PresObjKind::Text ) || + pPage->IsMasterPage() ) + return; + + ::Outliner* pOutliner = mpView->GetTextEditOutliner(); + SfxStyleSheet* pSheet = pOutliner->GetStyleSheet( 0 ); + bool bIsUndoEnabled = pOutliner->IsUndoEnabled(); + if( bIsUndoEnabled ) + pOutliner->EnableUndo(false); + + pOutliner->SetText( OUString(), pOutliner->GetParagraph( 0 ) ); + + if( bIsUndoEnabled ) + pOutliner->EnableUndo(true); + + if (pSheet && + (ePresObjKind == PresObjKind::Notes || ePresObjKind == PresObjKind::Text)) + pOutliner->SetStyleSheet(0, pSheet); + + mxTextObj->SetEmptyPresObj(true); +} + +bool FuText::RequestHelp(const HelpEvent& rHEvt) +{ + bool bReturn = false; + + OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); + + if ((Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled()) && + mxTextObj.is() && pOLV && pOLV->GetFieldUnderMousePointer()) + { + OUString aHelpText; + const SvxFieldItem* pFieldItem = pOLV->GetFieldUnderMousePointer(); + const SvxFieldData* pField = pFieldItem->GetField(); + + if (auto pURLField = dynamic_cast< const SvxURLField *>( pField )) + { + // URL-Field + aHelpText = INetURLObject::decode( pURLField->GetURL(), INetURLObject::DecodeMechanism::WithCharset ); + } + if (!aHelpText.isEmpty()) + { + ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(mxTextObj->GetLogicRect()); + ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()), + mpWindow->OutputToScreenPixel(aLogicPix.BottomRight())); + + if (Help::IsBalloonHelpEnabled()) + { + Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rHEvt.GetMousePosPixel(), aScreenRect, aHelpText); + bReturn = true; + } + else if (Help::IsQuickHelpEnabled()) + { + Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText); + bReturn = true; + } + } + } + + if (!bReturn) + { + bReturn = FuConstruct::RequestHelp(rHEvt); + } + + return bReturn; +} + +void FuText::ReceiveRequest(SfxRequest& rReq) +{ + nSlotId = rReq.GetSlot(); + + // then we call the base class (besides others, nSlotId is NOT set there) + FuPoor::ReceiveRequest(rReq); + + if (!(nSlotId == SID_TEXTEDIT || mpViewShell->GetFrameView()->IsQuickEdit() || SID_ATTR_CHAR == nSlotId)) + return; + + MouseEvent aMEvt(mpWindow->GetPointerPosPixel()); + + mxTextObj.reset(nullptr); + + if (nSlotId == SID_TEXTEDIT) + { + // are we currently editing? + mxTextObj.reset( mpView->GetTextEditObject() ); + + if (!mxTextObj.is()) + { + // Try to select an object + SdrPageView* pPV = mpView->GetSdrPageView(); + SdrViewEvent aVEvt; + mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + mpView->MarkObj(aVEvt.mpRootObj, pPV); + + if (auto pSdrTextObj = dynamic_cast<SdrTextObj*>(aVEvt.mpObj)) + { + mxTextObj.reset( pSdrTextObj ); + } + } + } + else if (mpView->AreObjectsMarked()) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if (rMarkList.GetMarkCount() == 1) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + + if( auto pTextObj = dynamic_cast<SdrTextObj *>( pObj )) + { + mxTextObj.reset( pTextObj ); + } + } + } + + bool bQuickDrag = true; + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if (pArgs + + // test for type before using + && SID_TEXTEDIT == nSlotId + && SfxItemState::SET == pArgs->GetItemState(SID_TEXTEDIT) + + && static_cast<const SfxUInt16Item&>( pArgs->Get(SID_TEXTEDIT)).GetValue() == 2) + { + // selection with double click -> do not allow QuickDrag + bQuickDrag = false; + } + + SetInEditMode(aMEvt, bQuickDrag); +} + +void FuText::DoubleClick(const MouseEvent& ) +{ + // Nothing to do +} + +/** Removed the insertion of default text and putting a new text + object directly into edit mode. +*/ +SdrObjectUniquePtr FuText::CreateDefaultObject(const sal_uInt16 nID, const ::tools::Rectangle& rRectangle) +{ + SdrObjectUniquePtr pObj( SdrObjFactory::MakeNewObject( + mpView->getSdrModelFromSdrView(), + mpView->GetCurrentObjInventor(), + mpView->GetCurrentObjIdentifier(), + nullptr) ); + + if(pObj) + { + if( auto pText = dynamic_cast< SdrTextObj *>( pObj.get() ) ) + { + pText->SetLogicRect(rRectangle); + + bool bVertical = (SID_ATTR_CHAR_VERTICAL == nID || SID_TEXT_FITTOSIZE_VERTICAL == nID); + pText->SetVerticalWriting(bVertical); + + ImpSetAttributesForNewTextObject(pText); + + if (nSlotId == SID_TEXT_FITTOSIZE) + { + ImpSetAttributesFitToSize(pText); + } + else if ( nSlotId == SID_TEXT_FITTOSIZE_VERTICAL ) + { + ImpSetAttributesFitToSizeVertical(pText); + } + else + { + ImpSetAttributesFitCommon(pText); + } + + // Put text object into edit mode. + SdrPageView* pPV = mpView->GetSdrPageView(); + mpView->SdrBeginTextEdit(pText, pPV); + } + else + { + OSL_FAIL("Object is NO text object"); + } + } + + return pObj; +} + +/** is called when the current function should be aborted. <p> + This is used when a function gets a KEY_ESCAPE but can also + be called directly. + + @returns true if an active function was aborted +*/ +bool FuText::cancel() +{ + if ( mpView->IsTextEdit() ) + { + if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted) + mxTextObj.reset(nullptr); + + mpView->SetCurrentObj(SdrObjKind::Text); + mpView->SetEditMode(SdrViewEditMode::Edit); + return true; + } + else + { + return false; + } +} + +void FuText::ChangeFontSize( bool bGrow, OutlinerView* pOLV, const FontList* pFontList, ::sd::View* pView ) +{ + if( !pFontList || !pView ) + return; + + if( pOLV ) + { + pOLV->GetEditView().ChangeFontSize( bGrow, pFontList ); + } + else + { + + pView->BegUndo(SdResId(bGrow ? STR_GROW_FONT_SIZE : STR_SHRINK_FONT_SIZE)); + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + for( size_t nMark = 0; nMark < rMarkList.GetMarkCount(); ++nMark ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( rMarkList.GetMark(nMark)->GetMarkedSdrObj() ); + if( pTextObj ) + { + rtl::Reference<sdr::SelectionController> xSelectionController(pView->getSelectionController()); + if (xSelectionController.is() && xSelectionController->ChangeFontSize(bGrow, pFontList)) + { + continue; + } + for( sal_Int32 nText = 0; nText < pTextObj->getTextCount(); nText++ ) + { + pTextObj->setActiveText( nText ); + + // Put text object into edit mode. + SdrPageView* pPV = pView->GetSdrPageView(); + pView->SdrBeginTextEdit(pTextObj, pPV); + + pOLV = pView->GetTextEditOutlinerView(); + if( pOLV ) + { + EditEngine* pEditEngine = pOLV->GetEditView().GetEditEngine(); + if( pEditEngine ) + { + ESelection aSel; + aSel.nEndPara = pEditEngine->GetParagraphCount()-1; + aSel.nEndPos = pEditEngine->GetTextLen(aSel.nEndPara); + pOLV->SetSelection(aSel); + } + + ChangeFontSize( bGrow, pOLV, pFontList, pView ); + } + + pView->SdrEndTextEdit(); + } + + SfxItemSet aShapeSet( pTextObj->GetMergedItemSet() ); + if( EditView::ChangeFontSize( bGrow, aShapeSet, pFontList ) ) + { + pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT ) ); + pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT_CJK ) ); + pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT_CTL ) ); + } + } + } + pView->EndUndo(); + } +} + +void FuText::InvalidateBindings() +{ + mpViewShell->GetViewFrame()->GetBindings().Invalidate(SidArray); +} + + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/futhes.cxx b/sd/source/ui/func/futhes.cxx new file mode 100644 index 000000000..78d2ae693 --- /dev/null +++ b/sd/source/ui/func/futhes.cxx @@ -0,0 +1,132 @@ +/* -*- 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 <futhes.hxx> + +#include <editeng/outliner.hxx> +#include <sfx2/request.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdotext.hxx> +#include <editeng/eeitem.hxx> +#include <tools/debug.hxx> + +#include <svx/svxerr.hxx> +#include <svx/dialmgr.hxx> +#include <editeng/unolingu.hxx> +#include <vcl/weld.hxx> +#include <drawdoc.hxx> +#include <View.hxx> +#include <Outliner.hxx> +#include <DrawViewShell.hxx> +#include <OutlineViewShell.hxx> +#include <Window.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::linguistic2; + +class SfxRequest; + +namespace sd { + + +FuThesaurus::FuThesaurus( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, + SdDrawDocument* pDoc, SfxRequest& rReq ) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuThesaurus::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuThesaurus( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuThesaurus::DoExecute(SfxRequest& rReq) +{ + SfxErrorContext aContext(ERRCTX_SVX_LINGU_THESAURUS, OUString(), + mpWindow->GetFrameWeld(), RID_SVXERRCTX, SvxResLocale()); + + if (dynamic_cast< DrawViewShell *>( mpViewShell )) + { + SdrTextObj* pTextObj = nullptr; + + if ( mpView->AreObjectsMarked() ) + { + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if ( rMarkList.GetMarkCount() == 1 ) + { + SdrMark* pMark = rMarkList.GetMark(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + + pTextObj = dynamic_cast<SdrTextObj *>( pObj ); + } + } + + ::Outliner* pOutliner = mpView->GetTextEditOutliner(); + const OutlinerView* pOutlView = mpView->GetTextEditOutlinerView(); + + if ( pTextObj && pOutliner && pOutlView ) + { + if ( !pOutliner->GetSpeller().is() ) + { + Reference< XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() ); + if ( xSpellChecker.is() ) + pOutliner->SetSpeller( xSpellChecker ); + + Reference< XHyphenator > xHyphenator( LinguMgr::GetHyphenator() ); + if( xHyphenator.is() ) + pOutliner->SetHyphenator( xHyphenator ); + + pOutliner->SetDefaultLanguage( mpDoc->GetLanguage( EE_CHAR_LANGUAGE ) ); + } + + EESpellState eState = const_cast<OutlinerView*>(pOutlView)->StartThesaurus(rReq.GetFrameWeld()); + DBG_ASSERT(eState != EESpellState::NoSpeller, "No SpellChecker"); + } + } + else if (dynamic_cast< OutlineViewShell *>( mpViewShell )) + { + Outliner* pOutliner = mpDoc->GetOutliner(); + OutlinerView* pOutlView = pOutliner->GetView(0); + + if ( !pOutliner->GetSpeller().is() ) + { + Reference< XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() ); + if ( xSpellChecker.is() ) + pOutliner->SetSpeller( xSpellChecker ); + + Reference< XHyphenator > xHyphenator( LinguMgr::GetHyphenator() ); + if( xHyphenator.is() ) + pOutliner->SetHyphenator( xHyphenator ); + + pOutliner->SetDefaultLanguage( mpDoc->GetLanguage( EE_CHAR_LANGUAGE ) ); + } + + EESpellState eState = pOutlView->StartThesaurus(rReq.GetFrameWeld()); + DBG_ASSERT(eState != EESpellState::NoSpeller, "No SpellChecker"); + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/futransf.cxx b/sd/source/ui/func/futransf.cxx new file mode 100644 index 000000000..8c565a3b8 --- /dev/null +++ b/sd/source/ui/func/futransf.cxx @@ -0,0 +1,132 @@ +/* -*- 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 <futransf.hxx> + +#include <svx/svxids.hrc> +#include <sfx2/request.hxx> + +#include <strings.hrc> +#include <ViewShell.hxx> +#include <View.hxx> +#include <sdresid.hxx> +#include <drawdoc.hxx> +#include <svx/svxdlg.hxx> +#include <comphelper/lok.hxx> + +#include <memory> + +using namespace sd; + +FuTransform::FuTransform(ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, + SdDrawDocument* pDoc, SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuTransform::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuTransform( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +namespace { + +void setUndo(::sd::View* pView, const SfxItemSet* pArgs, bool addPageMargin) +{ + // Undo + OUString aString = pView->GetDescriptionOfMarkedObjects() + + " " + SdResId(STR_TRANSFORM); + pView->BegUndo(aString); + pView->SetGeoAttrToMarked(*pArgs, addPageMargin); + pView->SetAttributes(*pArgs); + pView->EndUndo(); +} + +} + +void FuTransform::DoExecute( SfxRequest& rReq ) +{ + if (!mpView->AreObjectsMarked()) + return; + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if (pArgs) + { + // If this comes from LOK, that means the shape is moved by mouse + // only then pArgs is pre-set. + setUndo(mpView, pArgs, comphelper::LibreOfficeKit::isActive()); + return; + } + + // --------- itemset for size and position -------- + SfxItemSet aSet( mpView->GetGeoAttrFromMarked() ); + VclPtr<SfxAbstractTabDialog> pDlg; + + bool bWelded = false; + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if( rMarkList.GetMarkCount() == 1 && + pObj->GetObjInventor() == SdrInventor::Default && + pObj->GetObjIdentifier() == SdrObjKind::Caption ) + { + // --------- itemset for caption -------- + SfxItemSet aNewAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aNewAttr ); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + pDlg.reset(pFact->CreateCaptionDialog(mpViewShell->GetFrameWeld(), mpView)); + + const WhichRangesContainer& pRange = pDlg->GetInputRanges( *aNewAttr.GetPool() ); + SfxItemSet aCombSet( *aNewAttr.GetPool(), pRange ); + aCombSet.Put( aNewAttr ); + aCombSet.Put( aSet ); + pDlg->SetInputSet( &aCombSet ); + } + else + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + pDlg.reset(pFact->CreateSvxTransformTabDialog(mpViewShell->GetFrameWeld(), &aSet, mpView)); + bWelded = true; + } + + assert(pDlg && "there must be a dialog at this point"); + + auto pRequest = std::make_shared<SfxRequest>(rReq); + rReq.Ignore(); // the 'old' request is not relevant any more + + pDlg->StartExecuteAsync([bWelded, pDlg, pRequest, this](sal_Int32 nResult){ + if (nResult == RET_OK) + { + pRequest->Done(*(pDlg->GetOutputItemSet())); + // Page margin is already calculated at this point. + setUndo(mpView, pRequest->GetArgs(), false); + } + + // deferred until the dialog ends + mpViewShell->Invalidate(SID_RULER_OBJECT); + mpViewShell->Cancel(); + if (bWelded) + pDlg->disposeOnce(); + }); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/futxtatt.cxx b/sd/source/ui/func/futxtatt.cxx new file mode 100644 index 000000000..56f8c2569 --- /dev/null +++ b/sd/source/ui/func/futxtatt.cxx @@ -0,0 +1,80 @@ +/* -*- 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 <futxtatt.hxx> +#include <sfx2/request.hxx> + +#include <svx/svxdlg.hxx> +#include <View.hxx> +#include <drawdoc.hxx> + +namespace sd { + + +FuTextAttrDlg::FuTextAttrDlg ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuTextAttrDlg::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuTextAttrDlg( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuTextAttrDlg::DoExecute( SfxRequest& rReq ) +{ + SfxItemSet aNewAttr( mpDoc->GetPool() ); + mpView->GetAttributes( aNewAttr ); + + const SfxItemSet* pArgs = rReq.GetArgs(); + + if( !pArgs ) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateTextTabDialog(rReq.GetFrameWeld(), &aNewAttr, mpView)); + + sal_uInt16 nResult = pDlg->Execute(); + + switch( nResult ) + { + case RET_OK: + { + rReq.Done( *( pDlg->GetOutputItemSet() ) ); + + pArgs = rReq.GetArgs(); + } + break; + + default: + return; // Cancel + } + } + mpView->SetAttributes( *pArgs ); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuvect.cxx b/sd/source/ui/func/fuvect.cxx new file mode 100644 index 000000000..64840810c --- /dev/null +++ b/sd/source/ui/func/fuvect.cxx @@ -0,0 +1,87 @@ +/* -*- 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 <fuvect.hxx> +#include <svx/svdograf.hxx> + +#include <View.hxx> +#include <Window.hxx> +#include <strings.hrc> +#include <sdresid.hxx> +#include <sdabstdlg.hxx> + +namespace sd +{ + + +FuVectorize::FuVectorize ( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor (pViewSh, pWin, pView, pDoc, rReq) +{ +} + +rtl::Reference<FuPoor> FuVectorize::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuVectorize( pViewSh, pWin, pView, pDoc, rReq ) ); + xFunc->DoExecute(rReq); + return xFunc; +} + +void FuVectorize::DoExecute( SfxRequest& ) +{ + const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); + + if( rMarkList.GetMarkCount() != 1 ) + return; + + SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + + auto pSdrGrafObj = dynamic_cast< const SdrGrafObj *>( pObj ); + if( !pSdrGrafObj ) + return; + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSdVectorizeDlg> pDlg( + pFact->CreateSdVectorizeDlg(mpWindow ? mpWindow->GetFrameWeld() : nullptr, + pSdrGrafObj->GetGraphic().GetBitmapEx().GetBitmap(), mpDocSh ) ); + if( pDlg->Execute() != RET_OK ) + return; + + const GDIMetaFile& rMtf = pDlg->GetGDIMetaFile(); + SdrPageView* pPageView = mpView->GetSdrPageView(); + + if( pPageView && rMtf.GetActionSize() ) + { + SdrGrafObj* pVectObj = static_cast<SdrGrafObj*>( pObj->CloneSdrObject(pObj->getSdrModelFromSdrObject()) ); + OUString aStr = mpView->GetDescriptionOfMarkedObjects() + + " " + SdResId( STR_UNDO_VECTORIZE ); + mpView->BegUndo( aStr ); + pVectObj->SetGraphic( rMtf ); + mpView->ReplaceObjectAtView( pObj, *pPageView, pVectObj ); + mpView->EndUndo(); + } +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/fuzoom.cxx b/sd/source/ui/func/fuzoom.cxx new file mode 100644 index 000000000..871d594d3 --- /dev/null +++ b/sd/source/ui/func/fuzoom.cxx @@ -0,0 +1,219 @@ +/* -*- 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 <fuzoom.hxx> + +#include <svx/svxids.hrc> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <app.hrc> +#include <svx/svdpagv.hxx> +#include <vcl/ptrstyle.hxx> + +#include <ViewShell.hxx> +#include <View.hxx> +#include <Window.hxx> +#include <zoomlist.hxx> + +namespace sd { + +const sal_uInt16 SidArrayZoom[] = { + SID_ATTR_ZOOM, + SID_ZOOM_OUT, + SID_ZOOM_IN, + 0 }; + + +FuZoom::FuZoom( + ViewShell* pViewSh, + ::sd::Window* pWin, + ::sd::View* pView, + SdDrawDocument* pDoc, + SfxRequest& rReq) + : FuPoor(pViewSh, pWin, pView, pDoc, rReq), + bVisible(false), + bStartDrag(false), + aPtr(PointerStyle::Arrow) +{ +} + +FuZoom::~FuZoom() +{ + if (bVisible) + { + // Hide ZoomRect + mpViewShell->DrawMarkRect(aZoomRect); + + bVisible = false; + bStartDrag = false; + } +} + +rtl::Reference<FuPoor> FuZoom::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) +{ + rtl::Reference<FuPoor> xFunc( new FuZoom( pViewSh, pWin, pView, pDoc, rReq ) ); + return xFunc; +} + +bool FuZoom::MouseButtonDown(const MouseEvent& rMEvt) +{ + // remember button state for creation of own MouseEvents + SetMouseButtonCode(rMEvt.GetButtons()); + + mpWindow->CaptureMouse(); + bStartDrag = true; + + aBeginPosPix = rMEvt.GetPosPixel(); + aBeginPos = mpWindow->PixelToLogic(aBeginPosPix); + aZoomRect.SetSize( Size( 0, 0 ) ); + aZoomRect.SetPos( aBeginPos ); + + return true; +} + +bool FuZoom::MouseMove(const MouseEvent& rMEvt) +{ + if (rMEvt.IsShift()) + mpWindow->SetPointer(PointerStyle::Hand); + else if (nSlotId != SID_ZOOM_PANNING) + mpWindow->SetPointer(PointerStyle::Magnify); + + if (bStartDrag) + { + if (bVisible) + { + mpViewShell->DrawMarkRect(aZoomRect); + } + + Point aPosPix = rMEvt.GetPosPixel(); + ForceScroll(aPosPix); + + aEndPos = mpWindow->PixelToLogic(aPosPix); + aBeginPos = mpWindow->PixelToLogic(aBeginPosPix); + + if (nSlotId == SID_ZOOM_PANNING || (rMEvt.IsShift() && !bVisible) ) + { + // Panning + + Point aScroll = aBeginPos - aEndPos; + + if (aScroll.X() != 0 || aScroll.Y() != 0) + { + Size aWorkSize = mpView->GetWorkArea().GetSize(); + Size aPageSize = mpView->GetSdrPageView()->GetPage()->GetSize(); + if (aWorkSize.Width() != 0 && aWorkSize.Height() != 0 && + aPageSize.Width() != 0 && aPageSize.Height() != 0) + { + aScroll.setX( aScroll.X() / ( aWorkSize.Width() / aPageSize.Width()) ); + aScroll.setY( aScroll.Y() / ( aWorkSize.Height() / aPageSize.Height()) ); + mpViewShell->Scroll(aScroll.X(), aScroll.Y()); + aBeginPosPix = aPosPix; + } + } + } + else + { + ::tools::Rectangle aRect(aBeginPos, aEndPos); + aZoomRect = aRect; + aZoomRect.Justify(); + mpViewShell->DrawMarkRect(aZoomRect); + bVisible = true; + } + } + + return bStartDrag; +} + +bool FuZoom::MouseButtonUp(const MouseEvent& rMEvt) +{ + // remember button state for creation of own MouseEvents + SetMouseButtonCode(rMEvt.GetButtons()); + + if (bVisible) + { + // Hide ZoomRect + mpViewShell->DrawMarkRect(aZoomRect); + bVisible = false; + } + + Point aPosPix = rMEvt.GetPosPixel(); + + if(SID_ZOOM_PANNING != nSlotId && !rMEvt.IsShift()) + { + // Zoom + Size aZoomSizePixel = mpWindow->LogicToPixel(aZoomRect).GetSize(); + sal_uLong nTol = DRGPIX + DRGPIX; + + if ( ( aZoomSizePixel.Width() < static_cast<::tools::Long>(nTol) && aZoomSizePixel.Height() < static_cast<::tools::Long>(nTol) ) || rMEvt.IsMod1() ) + { + // click at place: double zoom factor + Point aPos = mpWindow->PixelToLogic(aPosPix); + Size aSize = mpWindow->PixelToLogic(mpWindow->GetOutputSizePixel()); + if ( rMEvt.IsMod1() ) + { + aSize.setWidth( aSize.Width() * 2 ); + aSize.setHeight( aSize.Height() * 2 ); + } + else + { + aSize.setWidth( aSize.Width() / 2 ); + aSize.setHeight( aSize.Height() / 2 ); + } + aPos.AdjustX( -(aSize.Width() / 2) ); + aPos.AdjustY( -(aSize.Height() / 2) ); + aZoomRect.SetPos(aPos); + aZoomRect.SetSize(aSize); + } + + mpViewShell->SetZoomRect(aZoomRect); + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArrayZoom ); + } + + ::tools::Rectangle aVisAreaWin = mpWindow->PixelToLogic(::tools::Rectangle(Point(0,0), + mpWindow->GetOutputSizePixel())); + mpViewShell->GetZoomList()->InsertZoomRect(aVisAreaWin); + + bStartDrag = false; + mpWindow->ReleaseMouse(); + + return true; +} + +void FuZoom::Activate() +{ + aPtr = mpWindow->GetPointer(); + + if (nSlotId == SID_ZOOM_PANNING) + { + mpWindow->SetPointer(PointerStyle::Hand); + } + else + { + mpWindow->SetPointer(PointerStyle::Magnify); + } +} + +void FuZoom::Deactivate() +{ + mpWindow->SetPointer( aPtr ); + mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArrayZoom ); +} +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/sdundogr.cxx b/sd/source/ui/func/sdundogr.cxx new file mode 100644 index 000000000..a2e97386d --- /dev/null +++ b/sd/source/ui/func/sdundogr.cxx @@ -0,0 +1,66 @@ +/* -*- 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 <sdundogr.hxx> +#include <tools/long.hxx> + +SdUndoGroup::~SdUndoGroup() = default; + +bool SdUndoGroup::Merge(SfxUndoAction* pNextAction) +{ + bool bRet = false; + + if (auto pSdUndoAction = dynamic_cast<SdUndoAction*>(pNextAction)) + { + SdUndoAction* pClone = pSdUndoAction->Clone(); + + if (pClone) + { + AddAction(pClone); + bRet = true; + } + } + + return bRet; +} + +/** + * Undo, reverse order of execution + */ +void SdUndoGroup::Undo() +{ + ::tools::Long nLast = aCtn.size(); + for (::tools::Long nAction = nLast - 1; nAction >= 0; nAction--) + { + aCtn[nAction]->Undo(); + } +} + +void SdUndoGroup::Redo() +{ + size_t nLast = aCtn.size(); + for (size_t nAction = 0; nAction < nLast; nAction++) + { + aCtn[nAction]->Redo(); + } +} + +void SdUndoGroup::AddAction(SdUndoAction* pAction) { aCtn.emplace_back(pAction); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/smarttag.cxx b/sd/source/ui/func/smarttag.cxx new file mode 100644 index 000000000..ff5382116 --- /dev/null +++ b/sd/source/ui/func/smarttag.cxx @@ -0,0 +1,333 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/commandevent.hxx> + +#include <ViewShell.hxx> +#include <smarttag.hxx> +#include <Window.hxx> +#include <View.hxx> + +namespace sd +{ + +SmartTag::SmartTag( ::sd::View& rView ) +: mrView( rView ) +, mbSelected( false ) +{ + SmartTagReference xThis( this ); + mrView.getSmartTags().add( xThis ); +} + +SmartTag::~SmartTag() +{ +} + +bool SmartTag::MouseButtonDown( const MouseEvent&, SmartHdl& ) +{ + return false; +} + +/** returns true if the SmartTag consumes this event. */ +bool SmartTag::KeyInput( const KeyEvent& /*rKEvt*/ ) +{ + return false; +} + +/** returns true if the SmartTag consumes this event. */ +bool SmartTag::Command( const CommandEvent& /*rCEvt*/ ) +{ + return false; +} + +void SmartTag::addCustomHandles( SdrHdlList& /*rHandlerList*/ ) +{ +} + +void SmartTag::select() +{ + mbSelected = true; +} + +void SmartTag::deselect() +{ + mbSelected = false; +} + +void SmartTag::disposing() +{ + SmartTagReference xThis( this ); + mrView.getSmartTags().remove( xThis ); +} + +bool SmartTag::getContext( SdrViewContext& /*rContext*/ ) +{ + return false; +} + +sal_Int32 SmartTag::GetMarkablePointCount() const +{ + return 0; +} + +sal_Int32 SmartTag::GetMarkedPointCount() const +{ + return 0; +} + +bool SmartTag::MarkPoint(SdrHdl& /*rHdl*/, bool /*bUnmark*/ ) +{ + return false; +} + +bool SmartTag::MarkPoints(const ::tools::Rectangle* /*pRect*/, bool /*bUnmark*/ ) +{ + return false; +} + +void SmartTag::CheckPossibilities() +{ +} + +SmartTagSet::SmartTagSet( View& rView ) +: mrView( rView ) +{ +} + +SmartTagSet::~SmartTagSet() +{ +} + +void SmartTagSet::add( const SmartTagReference& xTag ) +{ + maSet.insert( xTag ); + mrView.InvalidateAllWin(); + + if( xTag == mxMouseOverTag ) + mxMouseOverTag.clear(); + + if( xTag == mxSelectedTag ) + mxSelectedTag.clear(); +} + +void SmartTagSet::remove( const SmartTagReference& xTag ) +{ + std::set< SmartTagReference >::iterator aIter( maSet.find( xTag ) ); + if( aIter != maSet.end() ) + maSet.erase( aIter ); + mrView.InvalidateAllWin(); + + if( xTag == mxMouseOverTag ) + mxMouseOverTag.clear(); + + if( xTag == mxSelectedTag ) + mxSelectedTag.clear(); +} + +void SmartTagSet::Dispose() +{ + std::set< SmartTagReference > aSet; + aSet.swap( maSet ); + for( auto& rxItem : aSet ) + rxItem->Dispose(); + mrView.InvalidateAllWin(); + mxMouseOverTag.clear(); + mxSelectedTag.clear(); +} + +void SmartTagSet::select( const SmartTagReference& xTag ) +{ + if( mxSelectedTag == xTag ) + return; + + if( mxSelectedTag.is() ) + mxSelectedTag->deselect(); + + mxSelectedTag = xTag; + mxSelectedTag->select(); + mrView.SetPossibilitiesDirty(); + if( mrView.GetMarkedObjectCount() > 0 ) + mrView.UnmarkAllObj(); + else + mrView.updateHandles(); +} + +void SmartTagSet::deselect() +{ + if( mxSelectedTag.is() ) + { + mxSelectedTag->deselect(); + mxSelectedTag.clear(); + mrView.SetPossibilitiesDirty(); + mrView.updateHandles(); + } +} + +bool SmartTagSet::MouseButtonDown( const MouseEvent& rMEvt ) +{ + Point aMDPos( mrView.GetViewShell()->GetActiveWindow()->PixelToLogic( rMEvt.GetPosPixel() ) ); + SdrHdl* pHdl = mrView.PickHandle(aMDPos); + + // check if a smart tag is selected and no handle is hit + if( mxSelectedTag.is() && !pHdl ) + { + // deselect smart tag + deselect(); + return false; + } + + // if a smart tag handle is hit, forward event to its smart tag + SmartHdl* pSmartHdl = dynamic_cast< SmartHdl* >( pHdl ); + if(pSmartHdl && pSmartHdl->getTag().is() ) + { + SmartTagReference xTag( pSmartHdl->getTag() ); + return xTag->MouseButtonDown( rMEvt, *pSmartHdl ); + } + + return false; +} + +bool SmartTagSet::KeyInput( const KeyEvent& rKEvt ) +{ + if( mxSelectedTag.is() ) + return mxSelectedTag->KeyInput( rKEvt ); + else if( rKEvt.GetKeyCode().GetCode() == KEY_SPACE ) + { + SmartHdl* pSmartHdl = dynamic_cast< SmartHdl* >( mrView.GetHdlList().GetFocusHdl() ); + if( pSmartHdl ) + { + const_cast< SdrHdlList& >( mrView.GetHdlList() ).ResetFocusHdl(); + const SmartTagReference& xTag( pSmartHdl->getTag() ); + select( xTag ); + return true; + } + } + + return false; +} + +/** returns true if the SmartTag consumes this event. */ +bool SmartTagSet::Command( const CommandEvent& rCEvt ) +{ + if( rCEvt.IsMouseEvent() ) + { + Point aMDPos( mrView.GetViewShell()->GetActiveWindow()->PixelToLogic( rCEvt.GetMousePosPixel() ) ); + SdrHdl* pHdl = mrView.PickHandle(aMDPos); + + if( pHdl ) + { + // if a smart tag handle is hit, forward event to its smart tag + SmartHdl* pSmartHdl = dynamic_cast< SmartHdl* >( pHdl ); + if(pSmartHdl && pSmartHdl->getTag().is() ) + { + const SmartTagReference& xTag( pSmartHdl->getTag() ); + return xTag->Command( rCEvt ); + } + } + } + else + { + if( mxSelectedTag.is() ) + return mxSelectedTag->Command( rCEvt ); + + } + + return false; +} + +void SmartTagSet::addCustomHandles( SdrHdlList& rHandlerList ) +{ + for( auto& rxItem : maSet ) + rxItem->addCustomHandles( rHandlerList ); +} + +/** returns true if the currently selected smart tag has + a special context, returned in rContext. */ +bool SmartTagSet::getContext( SdrViewContext& rContext ) const +{ + if( mxSelectedTag.is() ) + return mxSelectedTag->getContext( rContext ); + else + return false; +} + +// support point editing + +bool SmartTagSet::HasMarkablePoints() const +{ + return GetMarkablePointCount() != 0; +} + +sal_uLong SmartTagSet::GetMarkablePointCount() const +{ + if( mxSelectedTag.is() ) + return mxSelectedTag->GetMarkablePointCount(); + return 0; +} + +bool SmartTagSet::HasMarkedPoints() const +{ + return GetMarkedPointCount() != 0; +} + +sal_uLong SmartTagSet::GetMarkedPointCount() const +{ + if( mxSelectedTag.is() ) + return mxSelectedTag->GetMarkedPointCount(); + else + return 0; +} + +bool SmartTagSet::MarkPoint(SdrHdl& rHdl, bool bUnmark ) +{ + if( mxSelectedTag.is() ) + return mxSelectedTag->MarkPoint( rHdl, bUnmark ); + + return false; +} + +bool SmartTagSet::MarkPoints(const ::tools::Rectangle* pRect, bool bUnmark) +{ + if( mxSelectedTag.is() ) + return mxSelectedTag->MarkPoints( pRect, bUnmark ); + return false; +} + +void SmartTagSet::CheckPossibilities() +{ + if( mxSelectedTag.is() ) + mxSelectedTag->CheckPossibilities(); +} + +SmartHdl::SmartHdl( const SmartTagReference& xTag, SdrObject* pObject, const Point& rPnt, SdrHdlKind eNewKind /*=SdrHdlKind::Move*/ ) +: SdrHdl( rPnt, eNewKind ) +, mxSmartTag( xTag ) +{ + SetObj( pObject ); +} + +SmartHdl::SmartHdl( const SmartTagReference& xTag, const Point& rPnt, SdrHdlKind eNewKind /*=SdrHdlKind::Move*/ ) +: SdrHdl( rPnt, eNewKind ) +, mxSmartTag( xTag ) +{ +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/undoback.cxx b/sd/source/ui/func/undoback.cxx new file mode 100644 index 000000000..768ca2ec2 --- /dev/null +++ b/sd/source/ui/func/undoback.cxx @@ -0,0 +1,105 @@ +/* -*- 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 <undoback.hxx> + +#include <sdpage.hxx> +#include <sdresid.hxx> +#include <strings.hrc> + +#include <com/sun/star/drawing/FillStyle.hpp> + +#include <svl/itemset.hxx> + +#include <svx/xdef.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xbtmpit.hxx> + +SdBackgroundObjUndoAction::SdBackgroundObjUndoAction( + SdDrawDocument& rDoc, + SdPage& rPage, + const SfxItemSet& rItemSet) +: SdUndoAction(&rDoc), + mrPage(rPage), + mpItemSet(std::make_unique<SfxItemSet>(rItemSet)), + mbHasFillBitmap(false) +{ + OUString aString( SdResId( STR_UNDO_CHANGE_PAGEFORMAT ) ); + SetComment( aString ); + saveFillBitmap(*mpItemSet); +} + +void SdBackgroundObjUndoAction::ImplRestoreBackgroundObj() +{ + std::unique_ptr<SfxItemSet> pNew = std::make_unique<SfxItemSet>(mrPage.getSdrPageProperties().GetItemSet()); + mrPage.getSdrPageProperties().ClearItem(); + if (bool(mpFillBitmapItem)) + restoreFillBitmap(*mpItemSet); + mpFillBitmapItem.reset(); + mbHasFillBitmap = false; + mrPage.getSdrPageProperties().PutItemSet(*mpItemSet); + mpItemSet = std::move(pNew); + saveFillBitmap(*mpItemSet); + + // tell the page that it's visualization has changed + mrPage.ActionChanged(); +} + +void SdBackgroundObjUndoAction::Undo() +{ + ImplRestoreBackgroundObj(); +} + +void SdBackgroundObjUndoAction::Redo() +{ + ImplRestoreBackgroundObj(); +} + +SdUndoAction* SdBackgroundObjUndoAction::Clone() const +{ + std::unique_ptr<SdBackgroundObjUndoAction> pCopy = std::make_unique<SdBackgroundObjUndoAction>(*mpDoc, mrPage, *mpItemSet); + if (mpFillBitmapItem) + pCopy->mpFillBitmapItem.reset(mpFillBitmapItem->Clone()); + pCopy->mbHasFillBitmap = mbHasFillBitmap; + return pCopy.release(); +} + +void SdBackgroundObjUndoAction::saveFillBitmap(SfxItemSet &rItemSet) +{ + if (const XFillBitmapItem *pItem = rItemSet.GetItemIfSet(XATTR_FILLBITMAP, false)) + mpFillBitmapItem.reset(pItem->Clone()); + if (bool(mpFillBitmapItem)) + { + if (const XFillStyleItem* pItem = rItemSet.GetItemIfSet(XATTR_FILLSTYLE, false)) + mbHasFillBitmap = pItem->GetValue() == css::drawing::FillStyle_BITMAP; + rItemSet.ClearItem(XATTR_FILLBITMAP); + if (mbHasFillBitmap) + rItemSet.ClearItem(XATTR_FILLSTYLE); + } +} + +void SdBackgroundObjUndoAction::restoreFillBitmap(SfxItemSet &rItemSet) +{ + rItemSet.Put(*mpFillBitmapItem); + if (mbHasFillBitmap) + rItemSet.Put(XFillStyleItem(css::drawing::FillStyle_BITMAP)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/undoheaderfooter.cxx b/sd/source/ui/func/undoheaderfooter.cxx new file mode 100644 index 000000000..e0183dac3 --- /dev/null +++ b/sd/source/ui/func/undoheaderfooter.cxx @@ -0,0 +1,53 @@ +/* -*- 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 <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> + +#include <app.hrc> +#include <undoheaderfooter.hxx> + + +SdHeaderFooterUndoAction::SdHeaderFooterUndoAction( SdDrawDocument* pDoc, SdPage* pPage, const sd::HeaderFooterSettings& rNewSettings ) +: SdUndoAction(pDoc), + mpPage(pPage), + maOldSettings(pPage->getHeaderFooterSettings()), + maNewSettings(rNewSettings) +{ +} + +SdHeaderFooterUndoAction::~SdHeaderFooterUndoAction() +{ +} + +void SdHeaderFooterUndoAction::Undo() +{ + mpPage->setHeaderFooterSettings( maOldSettings ); + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetDispatcher()->Execute( SID_SWITCHPAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); +} + +void SdHeaderFooterUndoAction::Redo() +{ + mpPage->setHeaderFooterSettings( maNewSettings ); + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetDispatcher()->Execute( SID_SWITCHPAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/undolayer.cxx b/sd/source/ui/func/undolayer.cxx new file mode 100644 index 000000000..b29142ee8 --- /dev/null +++ b/sd/source/ui/func/undolayer.cxx @@ -0,0 +1,78 @@ +/* -*- 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 <undolayer.hxx> + +#include <DrawDocShell.hxx> +#include <drawdoc.hxx> +#include <DrawViewShell.hxx> +#include <strings.hrc> +#include <sdresid.hxx> + + +SdLayerModifyUndoAction::SdLayerModifyUndoAction( + SdDrawDocument* _pDoc, SdrLayer* pLayer, + const OUString& rOldLayerName, const OUString& rOldLayerTitle, const OUString& rOldLayerDesc, bool bOldIsVisible, bool bOldIsLocked, bool bOldIsPrintable, + const OUString& rNewLayerName, const OUString& rNewLayerTitle, const OUString& rNewLayerDesc, bool bNewIsVisible, bool bNewIsLocked, bool bNewIsPrintable ) +: SdUndoAction( _pDoc ), + mpLayer( pLayer ), + maOldLayerName( rOldLayerName ), + maOldLayerTitle( rOldLayerTitle ), + maOldLayerDesc( rOldLayerDesc ), + mbOldIsVisible( bOldIsVisible ), + mbOldIsLocked( bOldIsLocked ), + mbOldIsPrintable( bOldIsPrintable ), + maNewLayerName( rNewLayerName ), + maNewLayerTitle( rNewLayerTitle ), + maNewLayerDesc( rNewLayerDesc ), + mbNewIsVisible( bNewIsVisible ), + mbNewIsLocked( bNewIsLocked ), + mbNewIsPrintable( bNewIsPrintable ) +{ + OUString aString(SdResId(STR_MODIFYLAYER)); + SetComment(aString); +} + +void SdLayerModifyUndoAction::Undo() +{ + ::sd::DrawDocShell* pDocSh = mpDoc->GetDocSh(); + if( pDocSh ) + { + ::sd::DrawViewShell* pDrViewSh = dynamic_cast< ::sd::DrawViewShell*> ( pDocSh->GetViewShell() ); + if( pDrViewSh ) + { + pDrViewSh->ModifyLayer( mpLayer, maOldLayerName, maOldLayerTitle, maOldLayerDesc, mbOldIsVisible, mbOldIsLocked, mbOldIsPrintable ); + } + } +} + +void SdLayerModifyUndoAction::Redo() +{ + ::sd::DrawDocShell* pDocSh = mpDoc->GetDocSh(); + if( pDocSh ) + { + ::sd::DrawViewShell* pDrViewSh = dynamic_cast< ::sd::DrawViewShell* >( pDocSh->GetViewShell() ); + if( pDrViewSh ) + { + pDrViewSh->ModifyLayer( mpLayer, maNewLayerName, maNewLayerTitle, maNewLayerDesc, mbNewIsVisible, mbNewIsLocked, mbNewIsPrintable ); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/undopage.cxx b/sd/source/ui/func/undopage.cxx new file mode 100644 index 000000000..174747bf6 --- /dev/null +++ b/sd/source/ui/func/undopage.cxx @@ -0,0 +1,99 @@ +/* -*- 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 <undopage.hxx> +#include <sdpage.hxx> + + +SdPageFormatUndoAction::~SdPageFormatUndoAction() +{ +} + +void SdPageFormatUndoAction::Undo() +{ + ::tools::Rectangle aOldBorderRect(mnOldLeft, mnOldUpper, mnOldRight, mnOldLower); + mpPage->ScaleObjects(maOldSize, aOldBorderRect, mbNewScale); + mpPage->SetSize(maOldSize); + mpPage->SetLeftBorder(mnOldLeft); + mpPage->SetRightBorder(mnOldRight); + mpPage->SetUpperBorder(mnOldUpper); + mpPage->SetLowerBorder(mnOldLower); + mpPage->SetOrientation(meOldOrientation); + mpPage->SetPaperBin( mnOldPaperBin ); + + mpPage->SetBackgroundFullSize( mbOldFullSize ); + if( !mpPage->IsMasterPage() ) + static_cast<SdPage&>( mpPage->TRG_GetMasterPage() ).SetBackgroundFullSize( mbOldFullSize ); + +} + +void SdPageFormatUndoAction::Redo() +{ + ::tools::Rectangle aNewBorderRect(mnNewLeft, mnNewUpper, mnNewRight, mnNewLower); + mpPage->ScaleObjects(maNewSize, aNewBorderRect, mbNewScale); + mpPage->SetSize(maNewSize); + mpPage->SetLeftBorder(mnNewLeft); + mpPage->SetRightBorder(mnNewRight); + mpPage->SetUpperBorder(mnNewUpper); + mpPage->SetLowerBorder(mnNewLower); + mpPage->SetOrientation(meNewOrientation); + mpPage->SetPaperBin( mnNewPaperBin ); + + mpPage->SetBackgroundFullSize( mbNewFullSize ); + if( !mpPage->IsMasterPage() ) + static_cast<SdPage&>( mpPage->TRG_GetMasterPage() ).SetBackgroundFullSize( mbNewFullSize ); + +} + +SdPageLRUndoAction::~SdPageLRUndoAction() +{ +} + +void SdPageLRUndoAction::Undo() +{ + mpPage->SetLeftBorder(mnOldLeft); + mpPage->SetRightBorder(mnOldRight); +} + +void SdPageLRUndoAction::Redo() +{ + mpPage->SetLeftBorder(mnNewLeft); + mpPage->SetRightBorder(mnNewRight); +} + +SdPageULUndoAction::~SdPageULUndoAction() +{ +} + +void SdPageULUndoAction::Undo() +{ + mpPage->SetUpperBorder(mnOldUpper); + mpPage->SetLowerBorder(mnOldLower); +} + +/** + * UL-Redo() + */ +void SdPageULUndoAction::Redo() +{ + mpPage->SetUpperBorder(mnNewUpper); + mpPage->SetLowerBorder(mnNewLower); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/unmovss.cxx b/sd/source/ui/func/unmovss.cxx new file mode 100644 index 000000000..d21f83b39 --- /dev/null +++ b/sd/source/ui/func/unmovss.cxx @@ -0,0 +1,95 @@ +/* -*- 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 <unmovss.hxx> +#include <drawdoc.hxx> +#include <stlsheet.hxx> +#include <stlpool.hxx> + +SdMoveStyleSheetsUndoAction::SdMoveStyleSheetsUndoAction( SdDrawDocument* pTheDoc, StyleSheetCopyResultVector& rTheStyles, bool bInserted) +: SdUndoAction(pTheDoc) +, mbMySheets( !bInserted ) +{ + maStyles.swap( rTheStyles ); + + maListOfChildLists.resize( maStyles.size() ); + // create list with lists of style sheet children + std::size_t i = 0; + for (const auto& a : maStyles) + { + maListOfChildLists[i++] = SdStyleSheetPool::CreateChildList(a.m_xStyleSheet.get()); + } +} + +void SdMoveStyleSheetsUndoAction::Undo() +{ + SfxStyleSheetBasePool* pPool = mpDoc->GetStyleSheetPool(); + + if (mbMySheets) + { + // the styles have to be inserted in the pool + + // first insert all styles to the pool + for (auto& a : maStyles) + { + if (!a.m_bCreatedByCopy) // tdf#119259, existed before this action, so leave it alone + continue; + pPool->Insert(a.m_xStyleSheet.get()); + } + + // now assign the children again + std::vector< SdStyleSheetVector >::iterator childlistiter( maListOfChildLists.begin() ); + for (const auto& a : maStyles) + { + OUString aParent(a.m_xStyleSheet->GetName()); + for( auto& rxChild : *childlistiter ) + { + rxChild->SetParent(aParent); + } + ++childlistiter; + } + } + else + { + // remove the styles again from the pool + for (auto& a : maStyles) + { + if (!a.m_bCreatedByCopy) // tdf#119259, existed before this action, so leave it alone + continue; + pPool->Remove(a.m_xStyleSheet.get()); + } + } + mbMySheets = !mbMySheets; +} + +void SdMoveStyleSheetsUndoAction::Redo() +{ + Undo(); +} + +SdMoveStyleSheetsUndoAction::~SdMoveStyleSheetsUndoAction() +{ +} + +OUString SdMoveStyleSheetsUndoAction::GetComment() const +{ + return OUString(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/unoaprms.cxx b/sd/source/ui/func/unoaprms.cxx new file mode 100644 index 000000000..3bf7d98a6 --- /dev/null +++ b/sd/source/ui/func/unoaprms.cxx @@ -0,0 +1,96 @@ +/* -*- 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 <drawdoc.hxx> +#include <unoaprms.hxx> +#include <anminfo.hxx> + + +void SdAnimationPrmsUndoAction::Undo() +{ + // no new info created: restore data + if (!bInfoCreated) + { + SdDrawDocument* pDoc(dynamic_cast< SdDrawDocument* >(&pObject->getSdrModelFromSdrObject())); + SdAnimationInfo* pInfo = pDoc ? SdDrawDocument::GetAnimationInfo(pObject) : nullptr; + if (pInfo) + { + pInfo->mbActive = bOldActive; + pInfo->meEffect = eOldEffect; + pInfo->meTextEffect = eOldTextEffect; + pInfo->meSpeed = eOldSpeed; + pInfo->mbDimPrevious = bOldDimPrevious; + pInfo->maDimColor = aOldDimColor; + pInfo->mbDimHide = bOldDimHide; + pInfo->mbSoundOn = bOldSoundOn; + pInfo->maSoundFile = aOldSoundFile; + pInfo->mbPlayFull = bOldPlayFull; + pInfo->meClickAction = eOldClickAction; + pInfo->SetBookmark( aOldBookmark ); + pInfo->mnVerb = nOldVerb; + + pInfo->meSecondEffect = eOldSecondEffect; + pInfo->meSecondSpeed = eOldSecondSpeed; + pInfo->mbSecondSoundOn = bOldSecondSoundOn; + pInfo->mbSecondPlayFull = bOldSecondPlayFull; + } + } + // info was created by action: delete info + else + { + pObject->DeleteUserData(0); + } + // force ModelHasChanged() in order to update effect window (animation order) + pObject->SetChanged(); + pObject->BroadcastObjectChange(); +} + +void SdAnimationPrmsUndoAction::Redo() +{ + SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(*pObject,true); + + pInfo->mbActive = bNewActive; + pInfo->meEffect = eNewEffect; + pInfo->meTextEffect = eNewTextEffect; + pInfo->meSpeed = eNewSpeed; + pInfo->mbDimPrevious = bNewDimPrevious; + pInfo->maDimColor = aNewDimColor; + pInfo->mbDimHide = bNewDimHide; + pInfo->mbSoundOn = bNewSoundOn; + pInfo->maSoundFile = aNewSoundFile; + pInfo->mbPlayFull = bNewPlayFull; + pInfo->meClickAction = eNewClickAction; + pInfo->SetBookmark( aNewBookmark ); + pInfo->mnVerb = nNewVerb; + + pInfo->meSecondEffect = eNewSecondEffect; + pInfo->meSecondSpeed = eNewSecondSpeed; + pInfo->mbSecondSoundOn = bNewSecondSoundOn; + pInfo->mbSecondPlayFull = bNewSecondPlayFull; + + // force ModelHasChanged() in order to update effect window (animation order) + pObject->SetChanged(); + pObject->BroadcastObjectChange(); +} + +SdAnimationPrmsUndoAction::~SdAnimationPrmsUndoAction() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/func/unprlout.cxx b/sd/source/ui/func/unprlout.cxx new file mode 100644 index 000000000..218883349 --- /dev/null +++ b/sd/source/ui/func/unprlout.cxx @@ -0,0 +1,73 @@ +/* -*- 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 <tools/debug.hxx> + +#include <unprlout.hxx> + +#include <strings.hrc> +#include <sdpage.hxx> +#include <sdresid.hxx> + + +SdPresentationLayoutUndoAction::SdPresentationLayoutUndoAction( + SdDrawDocument* pTheDoc, + const OUString& aTheOldLayoutName, + const OUString& aTheNewLayoutName, + AutoLayout eTheOldAutoLayout, + AutoLayout eTheNewAutoLayout, + bool bSet, + SdPage* pThePage): + SdUndoAction(pTheDoc) +{ + aOldLayoutName = aTheOldLayoutName; + aNewLayoutName = aTheNewLayoutName; + eOldAutoLayout = eTheOldAutoLayout; + eNewAutoLayout = eTheNewAutoLayout; + bSetAutoLayout = bSet; + + DBG_ASSERT(pThePage, "No Page set!"); + pPage = pThePage; + aComment = SdResId(STR_UNDO_SET_PRESLAYOUT); +} + +void SdPresentationLayoutUndoAction::Undo() +{ + pPage->SetPresentationLayout(aOldLayoutName, true, true, true); + if (bSetAutoLayout) + pPage->SetAutoLayout(eOldAutoLayout, true); +} + +void SdPresentationLayoutUndoAction::Redo() +{ + pPage->SetPresentationLayout(aNewLayoutName); + if (bSetAutoLayout) + pPage->SetAutoLayout(eNewAutoLayout, true); +} + +SdPresentationLayoutUndoAction::~SdPresentationLayoutUndoAction() +{ +} + +OUString SdPresentationLayoutUndoAction::GetComment() const +{ + return aComment; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |