diff options
Diffstat (limited to 'sw/source/uibase/ribbar')
-rw-r--r-- | sw/source/uibase/ribbar/conarc.cxx | 101 | ||||
-rw-r--r-- | sw/source/uibase/ribbar/concustomshape.cxx | 196 | ||||
-rw-r--r-- | sw/source/uibase/ribbar/conform.cxx | 112 | ||||
-rw-r--r-- | sw/source/uibase/ribbar/conpoly.cxx | 103 | ||||
-rw-r--r-- | sw/source/uibase/ribbar/conrect.cxx | 214 | ||||
-rw-r--r-- | sw/source/uibase/ribbar/drawbase.cxx | 576 | ||||
-rw-r--r-- | sw/source/uibase/ribbar/dselect.cxx | 44 | ||||
-rw-r--r-- | sw/source/uibase/ribbar/inputwin.cxx | 640 | ||||
-rw-r--r-- | sw/source/uibase/ribbar/workctrl.cxx | 900 |
9 files changed, 2886 insertions, 0 deletions
diff --git a/sw/source/uibase/ribbar/conarc.cxx b/sw/source/uibase/ribbar/conarc.cxx new file mode 100644 index 0000000000..4e55dc59ce --- /dev/null +++ b/sw/source/uibase/ribbar/conarc.cxx @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svx/svxids.hrc> +#include <vcl/event.hxx> + +#include <view.hxx> +#include <edtwin.hxx> +#include <wrtsh.hxx> +#include <drawbase.hxx> +#include <conarc.hxx> + +ConstArc::ConstArc(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView) + : SwDrawBase(pWrtShell, pEditWin, pSwView) + , m_nButtonUpCount(0) +{ +} + +bool ConstArc::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = SwDrawBase::MouseButtonDown(rMEvt); + if (bReturn && !m_nButtonUpCount) + m_aStartPoint = m_pWin->PixelToLogic(rMEvt.GetPosPixel()); + return bReturn; +} + +bool ConstArc::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = false; + + if ((m_pSh->IsDrawCreate() || m_pWin->IsDrawAction()) && rMEvt.IsLeft()) + { + Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel())); + if (!m_nButtonUpCount && aPnt == m_aStartPoint) + { + SwDrawBase::MouseButtonUp(rMEvt); + bReturn = true; + } + else + { + m_nButtonUpCount++; + + if (m_nButtonUpCount == 3) // Generating of circular arc finished + { + SwDrawBase::MouseButtonUp(rMEvt); + m_nButtonUpCount = 0; + bReturn = true; + } + else + m_pSh->EndCreate(SdrCreateCmd::NextPoint); + } + } + + return bReturn; +} + +void ConstArc::Activate(const sal_uInt16 nSlotId) +{ + switch (nSlotId) + { + case SID_DRAW_ARC: + m_pWin->SetSdrDrawMode(SdrObjKind::CircleArc); + break; + case SID_DRAW_PIE: + m_pWin->SetSdrDrawMode(SdrObjKind::CircleSection); + break; + case SID_DRAW_CIRCLECUT: + m_pWin->SetSdrDrawMode(SdrObjKind::CircleCut); + break; + default: + m_pWin->SetSdrDrawMode(SdrObjKind::NONE); + break; + } + + SwDrawBase::Activate(nSlotId); +} + +void ConstArc::Deactivate() +{ + m_nButtonUpCount = 0; + + SwDrawBase::Deactivate(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/ribbar/concustomshape.cxx b/sw/source/uibase/ribbar/concustomshape.cxx new file mode 100644 index 0000000000..56030fc42d --- /dev/null +++ b/sw/source/uibase/ribbar/concustomshape.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 <svx/svdobj.hxx> +#include <svx/sdtagitm.hxx> +#include <svx/svdview.hxx> +#include <editeng/eeitem.hxx> +#include <view.hxx> +#include <edtwin.hxx> +#include <wrtsh.hxx> +#include <drawbase.hxx> +#include <concustomshape.hxx> +#include <svx/gallery.hxx> +#include <sfx2/request.hxx> +#include <svx/fmmodel.hxx> +#include <svl/itempool.hxx> +#include <svl/stritem.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdoashp.hxx> +#include <svx/xfillit0.hxx> +#include <editeng/adjustitem.hxx> + +using namespace com::sun::star; + +ConstCustomShape::ConstCustomShape( SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView, SfxRequest const & rReq ) + : SwDrawBase( pWrtShell, pEditWin, pSwView ) +{ + m_aCustomShape = ConstCustomShape::GetShapeTypeFromRequest( rReq ); +} + +const OUString& ConstCustomShape::GetShapeType() const +{ + return m_aCustomShape; +} + +OUString ConstCustomShape::GetShapeTypeFromRequest( SfxRequest const & rReq ) +{ + OUString aRet; + const SfxItemSet* pArgs = rReq.GetArgs(); + if ( pArgs ) + { + const SfxStringItem& rItm = static_cast<const SfxStringItem&>(pArgs->Get( rReq.GetSlot() )); + aRet = rItm.GetValue(); + } + return aRet; +} + +bool ConstCustomShape::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = SwDrawBase::MouseButtonDown(rMEvt); + if ( bReturn ) + { + SdrView *pSdrView = m_pSh->GetDrawView(); + if ( pSdrView ) + { + SdrObject* pObj = pSdrView->GetCreateObj(); + if ( pObj ) + { + SetAttributes( pObj ); + bool bForceNoFillStyle = false; + if ( static_cast<SdrObjCustomShape*>(pObj)->UseNoFillStyle() ) + bForceNoFillStyle = true; + + SfxItemSet aAttr( m_pView->GetPool() ); + if ( bForceNoFillStyle ) + aAttr.Put( XFillStyleItem( drawing::FillStyle_NONE ) ); + pObj->SetMergedItemSet(aAttr); + } + } + } + return bReturn; +} + +void ConstCustomShape::Activate(const sal_uInt16 nSlotId) +{ + m_pWin->SetSdrDrawMode( SdrObjKind::CustomShape ); + + SwDrawBase::Activate(nSlotId); +} + +// applying attributes + +void ConstCustomShape::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( m_aCustomShape ) ) + { + FmFormModel aFormModel; + SfxItemPool& rPool(aFormModel.GetItemPool()); + rPool.FreezeIdRanges(); + + if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aFormModel ) ) + { + const SdrObject* pSourceObj = aFormModel.GetPage( 0 )->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 ); + Degree100 nAngle = pSourceObj->GetRotateAngle(); + if ( nAngle ) + pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle ); + bAttributesAppliedFromGallery = true; + } + } + break; + } + } + } + } + if ( !bAttributesAppliedFromGallery ) + { + pObj->SetMergedItem( SvxAdjustItem( SvxAdjust::Center, RES_PARATR_ADJUST ) ); + pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) ); + pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) ); + pObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) ); + static_cast<SdrObjCustomShape*>(pObj)->MergeDefaultAttributes( &m_aCustomShape ); + } +} + +void ConstCustomShape::CreateDefaultObject() +{ + SwDrawBase::CreateDefaultObject(); + SdrView *pSdrView = m_pSh->GetDrawView(); + if ( pSdrView ) + { + const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList(); + if ( rMarkList.GetMarkCount() == 1 ) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if ( dynamic_cast< const SdrObjCustomShape *>( pObj ) ) + SetAttributes( pObj ); + } + } +} + +void ConstCustomShape::CreateDefaultObjectAtPosWithSize(Point aPos, Size aSize) +{ + SwDrawBase::CreateDefaultObjectAtPosWithSize(aPos, aSize); + SdrView *pSdrView = m_pSh->GetDrawView(); + if ( pSdrView ) + { + const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList(); + if ( rMarkList.GetMarkCount() == 1 ) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if ( dynamic_cast< const SdrObjCustomShape *>( pObj ) ) + SetAttributes( pObj ); + } + } +} + +// #i33136# +bool ConstCustomShape::doConstructOrthogonal() const +{ + return SdrObjCustomShape::doConstructOrthogonal(m_aCustomShape); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/ribbar/conform.cxx b/sw/source/uibase/ribbar/conform.cxx new file mode 100644 index 0000000000..25cb8570d3 --- /dev/null +++ b/sw/source/uibase/ribbar/conform.cxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svx/svdview.hxx> +#include <vcl/ptrstyle.hxx> + +#include <swmodule.hxx> +#include <view.hxx> +#include <edtwin.hxx> +#include <wrtsh.hxx> +#include <drawbase.hxx> +#include <conform.hxx> + +ConstFormControl::ConstFormControl(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView, SdrObjKind eObjKind) + : SwDrawBase(pWrtShell, pEditWin, pSwView) + , m_eObjKind(eObjKind) +{ + m_bInsForm = true; +} + +bool ConstFormControl::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = false; + + SdrView *pSdrView = m_pSh->GetDrawView(); + + pSdrView->SetOrtho(rMEvt.IsShift()); + pSdrView->SetAngleSnapEnabled(rMEvt.IsShift()); + + if (rMEvt.IsMod2()) + { + pSdrView->SetCreate1stPointAsCenter(true); + pSdrView->SetResizeAtCenter(true); + } + else + { + pSdrView->SetCreate1stPointAsCenter(false); + pSdrView->SetResizeAtCenter(false); + } + + SdrViewEvent aVEvt; + SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + // Only new object; if not in base mode (or pure selection mode) + if (rMEvt.IsLeft() && !m_pWin->IsDrawAction() && + (eHit == SdrHitKind::UnmarkedObject || eHit == SdrHitKind::NONE || m_pSh->IsDrawCreate())) + { + g_bNoInterrupt = true; + m_pWin->CaptureMouse(); + + m_pWin->SetPointer(PointerStyle::DrawRect); + + m_aStartPos = m_pWin->PixelToLogic(rMEvt.GetPosPixel()); + bReturn = m_pSh->BeginCreate(m_pWin->GetSdrDrawMode(), SdrInventor::FmForm, m_aStartPos); + + if (bReturn) + m_pWin->SetDrawAction(true); + } + else + bReturn = SwDrawBase::MouseButtonDown(rMEvt); + + return bReturn; +} + +void ConstFormControl::Activate(const sal_uInt16 nSlotId) +{ + m_pWin->SetSdrDrawMode(m_eObjKind); + SwDrawBase::Activate(nSlotId); + m_pSh->GetDrawView()->SetCurrentObj(m_eObjKind); + + m_pWin->SetPointer(PointerStyle::DrawRect); +} + +void ConstFormControl::CreateDefaultObject() +{ + constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm); + constexpr tools::Long constTwips_10mm = o3tl::toTwips(10, o3tl::Length::mm); + + Point aStartPos(GetDefaultCenterPos()); + Point aEndPos(aStartPos); + aStartPos.AdjustX(-constTwips_10mm); + aStartPos.AdjustY(-constTwips_5mm); + aEndPos.AdjustX(constTwips_10mm); + aEndPos.AdjustY(constTwips_5mm); + + if(!m_pSh->HasDrawView()) + m_pSh->MakeDrawView(); + + SdrView *pSdrView = m_pSh->GetDrawView(); + pSdrView->SetDesignMode(); + m_pSh->BeginCreate(m_pWin->GetSdrDrawMode(), SdrInventor::FmForm, aStartPos); + m_pSh->MoveCreate(aEndPos); + m_pSh->EndCreate(SdrCreateCmd::ForceEnd); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/ribbar/conpoly.cxx b/sw/source/uibase/ribbar/conpoly.cxx new file mode 100644 index 0000000000..c4a245fda8 --- /dev/null +++ b/sw/source/uibase/ribbar/conpoly.cxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svx/svxids.hrc> +#include <vcl/event.hxx> + +#include <view.hxx> +#include <edtwin.hxx> +#include <wrtsh.hxx> +#include <drawbase.hxx> +#include <conpoly.hxx> + +ConstPolygon::ConstPolygon(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView) : + SwDrawBase(pWrtShell, pEditWin, pSwView) +{ +} + +bool ConstPolygon::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = false; + + if (m_pSh->IsDrawCreate()) + { + if (rMEvt.IsLeft() && rMEvt.GetClicks() == 1 && + m_pWin->GetSdrDrawMode() != SdrObjKind::FreehandLine && + m_pWin->GetSdrDrawMode() != SdrObjKind::FreehandFill) + { + if (!m_pSh->EndCreate(SdrCreateCmd::NextPoint)) + { + m_pSh->BreakCreate(); + EnterSelectMode(rMEvt); + return true; + } + } + else + { + bReturn = SwDrawBase::MouseButtonUp(rMEvt); + + // #i85045# removed double mechanism to check for AutoClose polygon + // after construction; the method here did not check for already closed and + // also worked only for a single polygon. Removing. + } + } + else + bReturn = SwDrawBase::MouseButtonUp(rMEvt); + + return bReturn; +} + +void ConstPolygon::Activate(const sal_uInt16 nSlotId) +{ + switch (nSlotId) + { + case SID_DRAW_POLYGON_NOFILL: + case SID_DRAW_XPOLYGON_NOFILL: + m_pWin->SetSdrDrawMode(SdrObjKind::PolyLine); + break; + + case SID_DRAW_POLYGON: + case SID_DRAW_XPOLYGON: + m_pWin->SetSdrDrawMode(SdrObjKind::Polygon); + break; + + case SID_DRAW_BEZIER_NOFILL: + m_pWin->SetSdrDrawMode(SdrObjKind::PathLine); + break; + + case SID_DRAW_BEZIER_FILL: + m_pWin->SetSdrDrawMode(SdrObjKind::PathFill); + break; + + case SID_DRAW_FREELINE_NOFILL: + m_pWin->SetSdrDrawMode(SdrObjKind::FreehandLine); + break; + + case SID_DRAW_FREELINE: + m_pWin->SetSdrDrawMode(SdrObjKind::FreehandFill); + break; + + default: + break; + } + + SwDrawBase::Activate(nSlotId); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/ribbar/conrect.cxx b/sw/source/uibase/ribbar/conrect.cxx new file mode 100644 index 0000000000..8d9d468a92 --- /dev/null +++ b/sw/source/uibase/ribbar/conrect.cxx @@ -0,0 +1,214 @@ +/* -*- 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/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/sdtacitm.hxx> +#include <svx/svdobj.hxx> +#include <svx/sdtagitm.hxx> +#include <svx/sdtakitm.hxx> +#include <svx/sdtaditm.hxx> +#include <svx/sdtaaitm.hxx> +#include <svx/svdview.hxx> +#include <svx/svdocapt.hxx> +#include <editeng/outlobj.hxx> +#include <cmdid.h> +#include <view.hxx> +#include <edtwin.hxx> +#include <wrtsh.hxx> +#include <drawbase.hxx> +#include <conrect.hxx> + +ConstRectangle::ConstRectangle( SwWrtShell* pWrtShell, SwEditWin* pEditWin, + SwView* pSwView ) + : SwDrawBase( pWrtShell, pEditWin, pSwView ) + , m_bMarquee(false) + , m_bCapVertical(false) + , mbVertical(false) +{ +} + +bool ConstRectangle::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = SwDrawBase::MouseButtonDown(rMEvt); + + if (bReturn) + { + if (m_pWin->GetSdrDrawMode() == SdrObjKind::Caption) + { + m_pView->NoRotate(); + if (m_pView->IsDrawSelMode()) + { + m_pView->FlipDrawSelMode(); + m_pSh->GetDrawView()->SetFrameDragSingles(m_pView->IsDrawSelMode()); + } + } + else + { + SdrObject* pObj = m_pView->GetDrawView()->GetCreateObj(); + if (pObj) + { + SfxItemSet aAttr(pObj->getSdrModelFromSdrObject().GetItemPool()); + SwFEShell::SetLineEnds(aAttr, *pObj, m_nSlotId); + pObj->SetMergedItemSet(aAttr); + } + } + } + + return bReturn; +} + +bool ConstRectangle::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bRet = SwDrawBase::MouseButtonUp(rMEvt); + if( bRet ) + { + SdrView *pSdrView = m_pSh->GetDrawView(); + const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList(); + SdrObject* pObj = rMarkList.GetMark(0) ? rMarkList.GetMark(0)->GetMarkedSdrObj() + : nullptr; + switch( m_pWin->GetSdrDrawMode() ) + { + case SdrObjKind::Text: + if( m_bMarquee ) + { + m_pSh->ChgAnchor(RndStdIds::FLY_AS_CHAR); + + if( pObj ) + { + // Set the attributes needed for scrolling + SfxItemSetFixed<SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST> + aItemSet(pSdrView->GetModel().GetItemPool()); + + aItemSet.Put( makeSdrTextAutoGrowWidthItem( false ) ); + aItemSet.Put( makeSdrTextAutoGrowHeightItem( false ) ); + aItemSet.Put( SdrTextAniKindItem( SdrTextAniKind::Scroll ) ); + aItemSet.Put( SdrTextAniDirectionItem( SdrTextAniDirection::Left ) ); + aItemSet.Put( SdrTextAniCountItem( 0 ) ); + aItemSet.Put( SdrTextAniAmountItem( + static_cast<sal_Int16>(m_pWin->PixelToLogic(Size(2,1)).Width())) ); + + pObj->SetMergedItemSetAndBroadcast(aItemSet); + } + } + else if(mbVertical) + { + if (SdrTextObj* pText = DynCastSdrTextObj(pObj)) + { + SfxItemSet aSet(pSdrView->GetModel().GetItemPool()); + + pText->SetVerticalWriting(true); + + aSet.Put(makeSdrTextAutoGrowWidthItem(true)); + aSet.Put(makeSdrTextAutoGrowHeightItem(false)); + aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); + aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); + + pText->SetMergedItemSet(aSet); + } + } + + if( pObj ) + { + SdrPageView* pPV = pSdrView->GetSdrPageView(); + m_pView->BeginTextEdit( pObj, pPV, m_pWin, true ); + } + m_pView->LeaveDrawCreate(); // Switch to selection mode + m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW); + break; + + case SdrObjKind::Caption: + { + SdrCaptionObj* pCaptObj = dynamic_cast<SdrCaptionObj*>(pObj); + if( m_bCapVertical && pCaptObj ) + { + pCaptObj->ForceOutlinerParaObject(); + OutlinerParaObject* pOPO = pCaptObj->GetOutlinerParaObject(); + if( pOPO && !pOPO->IsEffectivelyVertical() ) + pOPO->SetVertical( true ); + } + } + break; + default:; //prevent warning + } + } + return bRet; +} + +void ConstRectangle::Activate(const sal_uInt16 nSlotId) +{ + m_bMarquee = m_bCapVertical = false; + mbVertical = false; + + switch (nSlotId) + { + case SID_LINE_ARROW_END: + case SID_LINE_ARROW_CIRCLE: + case SID_LINE_ARROW_SQUARE: + case SID_LINE_ARROW_START: + case SID_LINE_CIRCLE_ARROW: + case SID_LINE_SQUARE_ARROW: + case SID_LINE_ARROWS: + case SID_DRAW_LINE: + case SID_DRAW_XLINE: + m_pWin->SetSdrDrawMode(SdrObjKind::Line); + break; + + case SID_DRAW_MEASURELINE: + m_pWin->SetSdrDrawMode(SdrObjKind::Measure); + break; + + case SID_DRAW_RECT: + m_pWin->SetSdrDrawMode(SdrObjKind::Rectangle); + break; + + case SID_DRAW_ELLIPSE: + m_pWin->SetSdrDrawMode(SdrObjKind::CircleOrEllipse); + break; + + case SID_DRAW_TEXT_MARQUEE: + m_bMarquee = true; + m_pWin->SetSdrDrawMode(SdrObjKind::Text); + break; + + case SID_DRAW_TEXT_VERTICAL: + mbVertical = true; + m_pWin->SetSdrDrawMode(SdrObjKind::Text); + break; + + case SID_DRAW_TEXT: + m_pWin->SetSdrDrawMode(SdrObjKind::Text); + break; + + case SID_DRAW_CAPTION_VERTICAL: + m_bCapVertical = true; + [[fallthrough]]; + case SID_DRAW_CAPTION: + m_pWin->SetSdrDrawMode(SdrObjKind::Caption); + break; + + default: + m_pWin->SetSdrDrawMode(SdrObjKind::NONE); + break; + } + + SwDrawBase::Activate(nSlotId); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/ribbar/drawbase.cxx b/sw/source/uibase/ribbar/drawbase.cxx new file mode 100644 index 0000000000..4e77bbc1f6 --- /dev/null +++ b/sw/source/uibase/ribbar/drawbase.cxx @@ -0,0 +1,576 @@ +/* -*- 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 <hintids.hxx> +#include <comphelper/lok.hxx> +#include <svx/svdview.hxx> +#include <svx/svdobj.hxx> +#include <svl/ptitem.hxx> +#include <editeng/sizeitem.hxx> +#include <sfx2/request.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <fmtclds.hxx> +#include <frmfmt.hxx> +#include <cmdid.h> +#include <view.hxx> +#include <wrtsh.hxx> +#include <drawbase.hxx> +#include <edtwin.hxx> +#include <swmodule.hxx> +#include <swundo.hxx> +#include <SwCapObjType.hxx> +#include <SwRewriter.hxx> +#include <strings.hrc> + +using namespace ::com::sun::star; + +SwDrawBase::SwDrawBase(SwWrtShell* pSwWrtShell, SwEditWin* pWindow, SwView* pSwView) : + m_pView(pSwView), + m_pSh(pSwWrtShell), + m_pWin(pWindow), + m_nSlotId(USHRT_MAX), + m_bCreateObj(true), + m_bInsForm(false) +{ + if ( !m_pSh->HasDrawView() ) + m_pSh->MakeDrawView(); +} + +SwDrawBase::~SwDrawBase() +{ + if (m_pView->GetWrtShellPtr()) // In the view-dtor could the wrtsh already been deleted... + m_pSh->GetDrawView()->SetEditMode(); +} + +bool SwDrawBase::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = false; + + SdrView *pSdrView = m_pSh->GetDrawView(); + + // #i33136# + pSdrView->SetOrtho(doConstructOrthogonal() ? !rMEvt.IsShift() : rMEvt.IsShift()); + pSdrView->SetAngleSnapEnabled(rMEvt.IsShift()); + + if (rMEvt.IsMod2()) + { + pSdrView->SetCreate1stPointAsCenter(true); + pSdrView->SetResizeAtCenter(true); + } + else + { + pSdrView->SetCreate1stPointAsCenter(false); + pSdrView->SetResizeAtCenter(false); + } + + SdrViewEvent aVEvt; + SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + // Only new object, if not in the basic mode (or pure selection mode). + if (rMEvt.IsLeft() && !m_pWin->IsDrawAction()) + { + if (IsCreateObj() && (eHit == SdrHitKind::UnmarkedObject || eHit == SdrHitKind::NONE || m_pSh->IsDrawCreate())) + { + g_bNoInterrupt = true; + m_pWin->CaptureMouse(); + + m_aStartPos = m_pWin->PixelToLogic(rMEvt.GetPosPixel()); + + bReturn = m_pSh->BeginCreate(m_pWin->GetSdrDrawMode(), m_aStartPos); + + SetDrawPointer(); + + if ( bReturn ) + m_pWin->SetDrawAction(true); + } + else if (!pSdrView->IsAction()) + { + // BEZIER-EDITOR + m_pWin->CaptureMouse(); + m_aStartPos = m_pWin->PixelToLogic(rMEvt.GetPosPixel()); + sal_uInt16 nEditMode = m_pWin->GetBezierMode(); + + if (eHit == SdrHitKind::Handle && aVEvt.mpHdl->GetKind() == SdrHdlKind::BezierWeight) + { + // Drag handle + g_bNoInterrupt = true; + bReturn = pSdrView->BegDragObj(m_aStartPos, nullptr, aVEvt.mpHdl); + m_pWin->SetDrawAction(true); + } + else if (eHit == SdrHitKind::MarkedObject && nEditMode == SID_BEZIER_INSERT) + { + // Insert gluepoint + g_bNoInterrupt = true; + bReturn = pSdrView->BegInsObjPoint(m_aStartPos, rMEvt.IsMod1()); + m_pWin->SetDrawAction(true); + } + else if (eHit == SdrHitKind::MarkedObject && rMEvt.IsMod1()) + { + // Select gluepoint + if (!rMEvt.IsShift()) + pSdrView->UnmarkAllPoints(); + + bReturn = pSdrView->BegMarkPoints(m_aStartPos); + m_pWin->SetDrawAction(true); + } + else if (eHit == SdrHitKind::MarkedObject && !rMEvt.IsShift() && !rMEvt.IsMod2()) + { + // Move object + return false; + } + else if (eHit == SdrHitKind::Handle) + { + // Select gluepoint + if (pSdrView->HasMarkablePoints() && (!pSdrView->IsPointMarked(*aVEvt.mpHdl) || rMEvt.IsShift())) + { + SdrHdl* pHdl = nullptr; + + if (!rMEvt.IsShift()) + { + pSdrView->UnmarkAllPoints(); + pHdl = pSdrView->PickHandle(m_aStartPos); + } + else + { + if (pSdrView->IsPointMarked(*aVEvt.mpHdl)) + { + bReturn = pSdrView->UnmarkPoint(*aVEvt.mpHdl); + pHdl = nullptr; + } + else + { + pHdl = pSdrView->PickHandle(m_aStartPos); + } + } + + if (pHdl) + { + g_bNoInterrupt = true; + pSdrView->MarkPoint(*pHdl); + } + } + } + else + { + // Select or drag object + if (m_pSh->IsObjSelectable(m_aStartPos) && eHit == SdrHitKind::UnmarkedObject) + { + if (pSdrView->HasMarkablePoints()) + pSdrView->UnmarkAllPoints(); + + g_bNoInterrupt = false; + // Use drag in edtwin + return false; + } + + g_bNoInterrupt = true; + + if (m_pSh->IsObjSelected()) + { + if (!rMEvt.IsShift()) + { + if (!pSdrView->HasMarkablePoints()) + { + bool bUnlockView = !m_pSh->IsViewLocked(); + m_pSh->LockView( true ); //lock visible section + m_pSh->SelectObj(Point(LONG_MAX, LONG_MAX)); // deselect all + if( bUnlockView ) + m_pSh->LockView( false ); + } + else + pSdrView->UnmarkAllPoints(); + } + } + if (!m_pSh->IsSelFrameMode()) + m_pSh->EnterSelFrameMode(); + + bReturn = m_pSh->BeginMark(m_aStartPos); + if( bReturn ) + m_pWin->SetDrawAction(true); + + SetDrawPointer(); + } + } + } + return bReturn; +} + +bool SwDrawBase::MouseMove(const MouseEvent& rMEvt) +{ + SdrView *pSdrView = m_pSh->GetDrawView(); + Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel())); + bool bRet = false; + + if (IsCreateObj() && !m_pWin->IsDrawSelMode() && pSdrView->IsCreateObj()) + { + // #i33136# + pSdrView->SetOrtho(doConstructOrthogonal() ? !rMEvt.IsShift() : rMEvt.IsShift()); + pSdrView->SetAngleSnapEnabled(rMEvt.IsShift()); + + m_pSh->MoveCreate(aPnt); + bRet = true; + } + else if (pSdrView->IsAction() || pSdrView->IsInsObjPoint() || pSdrView->IsMarkPoints()) + { + m_pSh->MoveMark(aPnt); + bRet = true; + } + + return bRet; +} + +bool SwDrawBase::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bReturn = false; + bool bCheckShell = false; + bool bAutoCap = false; + + Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel())); + + if (IsCreateObj() && m_pSh->IsDrawCreate() && !m_pWin->IsDrawSelMode()) + { + const SdrObjKind nDrawMode = m_pWin->GetSdrDrawMode(); + //objects with multiple point may end at the start position + bool bMultiPoint = SdrObjKind::PolyLine == nDrawMode || + SdrObjKind::Polygon == nDrawMode || + SdrObjKind::PathLine == nDrawMode || + SdrObjKind::PathFill == nDrawMode || + SdrObjKind::FreehandLine == nDrawMode || + SdrObjKind::FreehandFill == nDrawMode; + if(rMEvt.IsRight()) + { + m_pSh->BreakCreate(); + m_pView->LeaveDrawCreate(); + } + else + { + if (SdrObjKind::NewFrame == nDrawMode) + { + SwRewriter aRewriter; + + aRewriter.AddRule(UndoArg1, SwResId(STR_FRAME)); + m_pSh->StartUndo(SwUndoId::INSERT, &aRewriter); + } + + bool didCreate = m_pSh->EndCreate(SdrCreateCmd::ForceEnd); + if(!didCreate && !bMultiPoint) + { + CreateDefaultObjectAtPosWithSize(aPnt, Size(1000, 1000)); + } + + if (SdrObjKind::NewFrame == nDrawMode) // Text border inserted + { + uno::Reference< frame::XDispatchRecorder > xRecorder = + m_pSh->GetView().GetViewFrame().GetBindings().GetRecorder(); + if ( xRecorder.is() ) + { + SfxRequest aReq(m_pSh->GetView().GetViewFrame(), FN_INSERT_FRAME); + aReq .AppendItem(SfxUInt16Item( FN_INSERT_FRAME, + static_cast<sal_uInt16>(RndStdIds::FLY_AT_PARA) )); + aReq.AppendItem(SfxPointItem( FN_PARAM_1, m_pSh->GetAnchorObjDiff())); + aReq.AppendItem(SvxSizeItem( FN_PARAM_2, m_pSh->GetObjSize())); + aReq.Done(); + } + bAutoCap = true; + if(m_pWin->GetFrameColCount() > 1) + { + SfxItemSetFixed<RES_COL,RES_COL> aSet(m_pView->GetPool()); + SwFormatCol aCol(aSet.Get(RES_COL)); + aCol.Init(m_pWin->GetFrameColCount(), aCol.GetGutterWidth(), aCol.GetWishWidth()); + aSet.Put(aCol); + // Template AutoUpdate + SwFrameFormat* pFormat = m_pSh->GetSelectedFrameFormat(); + if(pFormat && pFormat->IsAutoUpdateOnDirectFormat()) + m_pSh->AutoUpdateFrame(pFormat, aSet); + else + m_pSh->SetFlyFrameAttr( aSet ); + } + } + if (m_pWin->GetSdrDrawMode() == SdrObjKind::NewFrame) + { + m_pSh->EndUndo(); + } + } + + bReturn = true; + + EnterSelectMode(rMEvt); + } + else + { + SdrView *pSdrView = m_pSh->GetDrawView(); + + if (!pSdrView->HasMarkablePoints()) + { + // NO BEZIER_EDITOR + if ((m_pSh->GetDrawView()->IsMarkObj() || m_pSh->GetDrawView()->IsMarkPoints()) + && rMEvt.IsLeft()) + { + bReturn = m_pSh->EndMark(); + + m_pWin->SetDrawAction(false); + + if (aPnt == m_aStartPos && m_pSh->IsObjSelectable(aPnt)) + { + m_pSh->SelectObj(aPnt, ( rMEvt.IsShift() && + m_pSh->IsSelFrameMode()) ? SW_ADD_SELECT : 0); + + if (!m_pSh->IsObjSelected()) + { + m_pView->LeaveDrawCreate(); // Switch to selection mode + + m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW); + + if (m_pSh->IsSelFrameMode()) + m_pSh->LeaveSelFrameMode(); + } + m_pView->NoRotate(); + + bCheckShell = true; // if necessary turn on BezierShell + } + else if (!m_pSh->IsObjSelected() && !m_pWin->IsDrawAction()) + { + if (m_pSh->IsObjSelectable(aPnt)) + m_pSh->SelectObj(aPnt, ( rMEvt.IsShift() && + m_pSh->IsSelFrameMode() ) ? SW_ADD_SELECT : 0 ); + else + { + m_pView->LeaveDrawCreate(); + if (m_pSh->IsSelFrameMode()) + m_pSh->LeaveSelFrameMode(); + } + m_pView->NoRotate(); + + bReturn = true; + } + } + } + else + { + // BEZIER_EDITOR + if ( pSdrView->IsAction() ) + { + if ( pSdrView->IsInsObjPoint() ) + bReturn = pSdrView->EndInsObjPoint(SdrCreateCmd::ForceEnd); + else if (pSdrView->IsMarkPoints() ) + bReturn = pSdrView->EndMarkPoints(); + else + { + pSdrView->EndAction(); + bReturn = true; + } + m_pWin->SetDrawAction(false); + + if (aPnt == m_aStartPos) + { + if (!m_pSh->IsObjSelectable(aPnt)) + m_pSh->SelectObj(Point(LONG_MAX, LONG_MAX)); + else if (!bReturn) + { + if (!rMEvt.IsShift()) + pSdrView->UnmarkAllPoints(); + m_pSh->SelectObj(aPnt, (rMEvt.IsShift() && + m_pSh->IsSelFrameMode()) ? SW_ADD_SELECT :0); + } + + if (!m_pSh->IsObjSelected()) + { + m_pView->LeaveDrawCreate(); // Switch to selection mode + + m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW); + + if (m_pSh->IsSelFrameMode()) + m_pSh->LeaveSelFrameMode(); + } + m_pView->NoRotate(); + + bCheckShell = true; // if necessary turn on BezierShell + } + } + + SetDrawPointer(); + + if (!m_pSh->IsObjSelected() && !m_pWin->IsDrawAction()) + { + m_pView->LeaveDrawCreate(); + if (m_pSh->IsSelFrameMode()) + m_pSh->LeaveSelFrameMode(); + + m_pView->NoRotate(); + bReturn = true; + } + } + } + + if (bCheckShell) + m_pView->AttrChangedNotify(nullptr); // if necessary turn on BezierShell + + //!!!!!!!!!! Attention suicide !!!!!!!!!!! Everything should be renewed once + if ( bAutoCap ) + m_pView->AutoCaption(FRAME_CAP); //Can currently only be FRAME, otherwise convert + // to enums + return bReturn; +} + +void SwDrawBase::Activate(const sal_uInt16 nSlot) +{ + SetSlotId(nSlot); + SdrView *pSdrView = m_pSh->GetDrawView(); + + pSdrView->SetCurrentObj(m_pWin->GetSdrDrawMode()); + pSdrView->SetEditMode(false); + + SetDrawPointer(); + m_pSh->NoEdit(); +} + +void SwDrawBase::Deactivate() +{ + SdrView *pSdrView = m_pSh->GetDrawView(); + pSdrView->SetOrtho(false); + pSdrView->SetAngleSnapEnabled(false); + + if (m_pWin->IsDrawAction() && m_pSh->IsDrawCreate()) + m_pSh->BreakCreate(); + + m_pWin->SetDrawAction(false); + + if (m_pWin->IsMouseCaptured()) + m_pWin->ReleaseMouse(); + g_bNoInterrupt = false; + + if (m_pWin->GetApplyTemplate()) + m_pWin->SetApplyTemplate(SwApplyTemplate()); + m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW); +} + +// Process keyboard events + +// If a KeyEvent is processed then the return value is true, otherwise +// false. + +void SwDrawBase::BreakCreate() +{ + m_pSh->BreakCreate(); + m_pWin->SetDrawAction(false); + m_pWin->ReleaseMouse(); + + Deactivate(); +} + +void SwDrawBase::SetDrawPointer() +{ + SdrView *pSdrView = m_pSh->GetDrawView(); + Point aPnt(m_pWin->OutputToScreenPixel(m_pWin->GetPointerPosPixel())); + aPnt = m_pWin->PixelToLogic(m_pWin->ScreenToOutputPixel(aPnt)); + PointerStyle aPointTyp = pSdrView->GetPreferredPointer(aPnt, m_pSh->GetOut()); + m_pWin->SetPointer(aPointTyp); +} + +// If necessary switch into selection mode + +void SwDrawBase::EnterSelectMode(const MouseEvent& rMEvt) +{ + m_pWin->SetDrawAction(false); + + if (m_pSh->IsObjSelected() || m_pWin->IsDrawAction()) + return; + + Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel())); + + if (m_pSh->IsObjSelectable(aPnt)) + { + m_pSh->SelectObj(aPnt); + if (rMEvt.GetModifier() == KEY_SHIFT || !m_pSh->IsObjSelected()) + { + m_pView->LeaveDrawCreate(); // Switch to selection mode + + m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW); + } + } + else + { + m_pView->LeaveDrawCreate(); + if (m_pSh->IsSelFrameMode()) + m_pSh->LeaveSelFrameMode(); + } + m_pView->NoRotate(); +} + +void SwDrawBase::CreateDefaultObject() +{ + constexpr tools::Long constTwips_3cm = o3tl::toTwips(3, o3tl::Length::cm); + + Point aStartPos = GetDefaultCenterPos(); + Point aEndPos(aStartPos); + aStartPos.AdjustX(-constTwips_3cm); + aStartPos.AdjustY(-constTwips_3cm); + aEndPos.AdjustX(constTwips_3cm); + aEndPos.AdjustY(constTwips_3cm); + tools::Rectangle aRect(aStartPos, aEndPos); + m_pSh->CreateDefaultShape(m_pWin->GetSdrDrawMode(), aRect, m_nSlotId); +} + +void SwDrawBase::CreateDefaultObjectAtPosWithSize(Point aPos, Size aSize) +{ + aPos.AdjustX(-sal_Int32(aSize.getWidth() / 2)); + aPos.AdjustY(-sal_Int32(aSize.getHeight() / 2)); + + SdrView* sdrView = m_pView->GetDrawView(); + SdrPageView *pPV = sdrView->GetSdrPageView(); + + if(sdrView->IsSnapEnabled()) + aPos = sdrView->GetSnapPos(aPos, pPV); + + ::tools::Rectangle aNewObjectRectangle(aPos, aSize); + m_pSh->CreateDefaultShape(m_pWin->GetSdrDrawMode(), aNewObjectRectangle, m_nSlotId); +} + +Point SwDrawBase::GetDefaultCenterPos() const +{ + Size aDocSz(m_pSh->GetDocSize()); + + SwRect aVisArea(m_pSh->VisArea()); + if (comphelper::LibreOfficeKit::isActive()) + { + aVisArea = SwRect(m_pSh->getLOKVisibleArea()); + aVisArea.Intersection(SwRect(Point(), aDocSz)); + } + + Point aCenter = aVisArea.Center(); + // To increase the chance that aCenter actually falls somewhere on a page (rather than on the + // background between pages), keep it centered horizontally for the "Single-page view" + // (GetViewLayoutColumns() == 1) and "Book view" (GetViewLayoutColumns() == 2) cases that + // display the pages centered on the background: + if (aVisArea.Width() > aDocSz.Width() && m_pSh->GetViewOptions()->GetViewLayoutColumns() == 0) + aCenter.setX(aDocSz.Width() / 2 + aVisArea.Left()); + if (aVisArea.Height() > aDocSz.Height()) + aCenter.setY(aDocSz.Height() / 2 + aVisArea.Top()); + + return aCenter; +} + +// #i33136# +bool SwDrawBase::doConstructOrthogonal() const +{ + return ( m_nSlotId == SID_DRAW_XPOLYGON || m_nSlotId == SID_DRAW_XPOLYGON_NOFILL || m_nSlotId == SID_DRAW_XLINE ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/ribbar/dselect.cxx b/sw/source/uibase/ribbar/dselect.cxx new file mode 100644 index 0000000000..abbebc0445 --- /dev/null +++ b/sw/source/uibase/ribbar/dselect.cxx @@ -0,0 +1,44 @@ +/* -*- 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/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <view.hxx> +#include <edtwin.hxx> +#include <wrtsh.hxx> +#include <cmdid.h> +#include <drawbase.hxx> +#include <dselect.hxx> + +DrawSelection::DrawSelection(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView) + : SwDrawBase(pWrtShell, pEditWin, pSwView) +{ + m_bCreateObj = false; +} + +void DrawSelection::Activate(const sal_uInt16 nSlotId) +{ + m_pWin->SetSdrDrawMode(SdrObjKind::NONE); + m_pWin->SetObjectSelect(true); + SwDrawBase::Activate(nSlotId); + + m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/ribbar/inputwin.cxx b/sw/source/uibase/ribbar/inputwin.cxx new file mode 100644 index 0000000000..92a9f3fb21 --- /dev/null +++ b/sw/source/uibase/ribbar/inputwin.cxx @@ -0,0 +1,640 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <sal/log.hxx> + +#include <osl/diagnose.h> +#include <comphelper/string.hxx> +#include <o3tl/safeint.hxx> +#include <officecfg/Office/Common.hxx> +#include <tools/gen.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/ruler.hxx> +#include <svl/stritem.hxx> +#include <vcl/event.hxx> +#include <vcl/weldutils.hxx> + +#include <swtypes.hxx> +#include <cmdid.h> +#include <swmodule.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <inputwin.hxx> +#include <fldbas.hxx> +#include <fldmgr.hxx> +#include <frmfmt.hxx> +#include <cellatr.hxx> +#include <edtwin.hxx> +#include <helpids.h> +#include <strings.hrc> +#include <bitmaps.hlst> + +// Only for the UpdateRange: Delete the box in which the stacked cursor is positioned. +#include <pam.hxx> + +#include <swundo.hxx> + +#include <IDocumentContentOperations.hxx> + +constexpr ToolBoxItemId ED_POS(2); +constexpr ToolBoxItemId ED_FORMULA(3); +constexpr ToolBoxItemId FN_FORMULA_CALC(FN_FORMAT + 156); /* select formula */ +constexpr ToolBoxItemId FN_FORMULA_CANCEL(FN_FORMAT + 157); /* don't apply formula */ +constexpr ToolBoxItemId FN_FORMULA_APPLY(FN_FORMAT + 158); /* apply formula */ + +SFX_IMPL_POS_CHILDWINDOW_WITHID( SwInputChild, FN_EDIT_FORMULA, SFX_OBJECTBAR_OBJECT ) + +IMPL_LINK(PosEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return ChildKeyInput(rKEvt); +} + +SwInputWindow::SwInputWindow(vcl::Window* pParent, SfxDispatcher const * pDispatcher) + : ToolBox(pParent, WB_3DLOOK|WB_BORDER) + , mxPos(VclPtr<PosEdit>::Create(this)) + , mxEdit(VclPtr<InputEdit>::Create(this)) + , m_pWrtShell(nullptr) + , m_pView(nullptr) + , m_bDoesUndo(true) + , m_bResetUndo(false) + , m_bCallUndo(false) +{ + m_bFirst = true; + m_bIsTable = m_bDelSel = false; + + InsertItem(FN_FORMULA_CALC, Image(StockImage::Yes, RID_BMP_FORMULA_CALC), + SwResId(STR_FORMULA_CALC)); + InsertItem(FN_FORMULA_CANCEL, Image(StockImage::Yes, RID_BMP_FORMULA_CANCEL), + SwResId(STR_FORMULA_CANCEL)); + InsertItem(FN_FORMULA_APPLY, Image(StockImage::Yes, RID_BMP_FORMULA_APPLY), + SwResId(STR_FORMULA_APPLY)); + + SetHelpId(FN_FORMULA_CALC, HID_TBX_FORMULA_CALC); + SetHelpId(FN_FORMULA_CANCEL, HID_TBX_FORMULA_CANCEL); + SetHelpId(FN_FORMULA_APPLY, HID_TBX_FORMULA_APPLY); + + SwView *pDispatcherView = dynamic_cast<SwView*>(pDispatcher ? pDispatcher->GetFrame()->GetViewShell() : nullptr); + SwView* pActiveView = ::GetActiveView(); + if (pDispatcherView == pActiveView) + m_pView = pActiveView; + m_pWrtShell = m_pView ? m_pView->GetWrtShellPtr() : nullptr; + + InsertWindow(ED_POS, mxPos.get(), ToolBoxItemBits::NONE, 0); + SetItemText(ED_POS, SwResId(STR_ACCESS_FORMULA_TYPE)); + mxPos->set_accessible_name(SwResId(STR_ACCESS_FORMULA_TYPE)); + SetAccessibleName(SwResId(STR_ACCESS_FORMULA_TOOLBAR)); + InsertSeparator ( 1 ); + InsertSeparator (); + InsertWindow(ED_FORMULA, mxEdit.get()); + SetItemText(ED_FORMULA, SwResId(STR_ACCESS_FORMULA_TEXT)); + mxEdit->set_accessible_name(SwResId(STR_ACCESS_FORMULA_TEXT)); + SetHelpId(ED_FORMULA, HID_EDIT_FORMULA); + + SetItemBits( FN_FORMULA_CALC, GetItemBits( FN_FORMULA_CALC ) | ToolBoxItemBits::DROPDOWNONLY ); + SetDropdownClickHdl( LINK( this, SwInputWindow, DropdownClickHdl )); + + Size aSizeTbx = CalcWindowSizePixel(); + Size aEditSize = mxEdit->GetSizePixel(); + tools::Rectangle aItemRect( GetItemRect(FN_FORMULA_CALC) ); + tools::Long nMaxHeight = std::max(aEditSize.Height(), aItemRect.GetHeight()); + if( nMaxHeight+2 > aSizeTbx.Height() ) + aSizeTbx.setHeight( nMaxHeight+2 ); + Size aSize = GetSizePixel(); + aSize.setHeight( aSizeTbx.Height() ); + SetSizePixel( aSize ); + + // align edit and item vcentered + Size aPosSize = mxPos->GetSizePixel(); + aPosSize.setHeight( nMaxHeight ); + aEditSize.setHeight( nMaxHeight ); + Point aPosPos = mxPos->GetPosPixel(); + Point aEditPos = mxEdit->GetPosPixel(); + aPosPos.setY( (aSize.Height() - nMaxHeight)/2 + 1 ); + aEditPos.setY( (aSize.Height() - nMaxHeight)/2 + 1 ); + mxPos->SetPosSizePixel( aPosPos, aPosSize ); + mxEdit->SetPosSizePixel( aEditPos, aEditSize ); +} + +SwInputWindow::~SwInputWindow() +{ + disposeOnce(); +} + +void SwInputWindow::dispose() +{ + // wake rulers + if(m_pView) + { + m_pView->GetHRuler().SetActive(); + m_pView->GetVRuler().SetActive(); + } + m_pMgr.reset(); + if(m_pWrtShell) + m_pWrtShell->EndSelTableCells(); + + CleanupUglyHackWithUndo(); + + mxPos.disposeAndClear(); + mxEdit.disposeAndClear(); + ToolBox::dispose(); +} + +void SwInputWindow::CleanupUglyHackWithUndo() +{ + if (!m_bResetUndo) + return; + + if (m_pWrtShell) + { + DelBoxContent(); + m_pWrtShell->DoUndo(m_bDoesUndo); + if (m_bCallUndo) + { + m_pWrtShell->Undo(); + } + } + m_bResetUndo = false; // #i117122# once is enough :) +} + +void SwInputWindow::Resize() +{ + ToolBox::Resize(); + + tools::Long nWidth = GetSizePixel().Width(); + tools::Long nLeft = mxEdit->GetPosPixel().X(); + Size aEditSize = mxEdit->GetSizePixel(); + + aEditSize.setWidth( std::max( static_cast<tools::Long>(nWidth - nLeft - 5), tools::Long(0) ) ); + mxEdit->SetSizePixel( aEditSize ); +} + +void SwInputWindow::ShowWin() +{ + m_bIsTable = false; + // stop rulers + if (m_pView && m_pWrtShell) + { + m_pView->GetHRuler().SetActive( false ); + m_pView->GetVRuler().SetActive( false ); + + // Cursor in table + m_bIsTable = m_pWrtShell->IsCursorInTable(); + + if( m_bFirst ) + m_pWrtShell->SelTableCells( LINK( this, SwInputWindow, + SelTableCellsNotify) ); + if( m_bIsTable ) + { + const OUString& rPos = m_pWrtShell->GetBoxNms(); + sal_Int32 nPos = 0; + short nSrch = -1; + while( (nPos = rPos.indexOf( ':',nPos + 1 ) ) != -1 ) + nSrch = static_cast<short>(nPos); + mxPos->set_text( rPos.copy( ++nSrch ) ); + m_aCurrentTableName = m_pWrtShell->GetTableFormat()->GetName(); + } + else + mxPos->set_text(SwResId(STR_TBL_FORMULA)); + + // Edit current field + OSL_ENSURE(m_pMgr == nullptr, "FieldManager not deleted"); + m_pMgr.reset(new SwFieldMgr); + + // Form should always begin with "=" , so set here + OUString sEdit('='); + if( m_pMgr->GetCurField() && SwFieldTypesEnum::Formel == m_pMgr->GetCurTypeId() ) + { + sEdit += m_pMgr->GetCurFieldPar2(); + } + else if( m_bFirst && m_bIsTable ) + { + m_bResetUndo = true; + SAL_WARN_IF( + officecfg::Office::Common::Undo::Steps::get() <= 0, + "sw", "/org.openoffice.Office.Common/Undo/Steps <= 0"); + + m_bDoesUndo = m_pWrtShell->DoesUndo(); + if( !m_bDoesUndo ) + { + m_pWrtShell->DoUndo(); + } + + if( !m_pWrtShell->SwCursorShell::HasSelection() ) + { + m_pWrtShell->MoveSection( GoCurrSection, fnSectionStart ); + m_pWrtShell->SetMark(); + m_pWrtShell->MoveSection( GoCurrSection, fnSectionEnd ); + } + if( m_pWrtShell->SwCursorShell::HasSelection() ) + { + m_pWrtShell->StartUndo( SwUndoId::DELETE ); + m_pWrtShell->Delete(false); + if( SwUndoId::EMPTY != m_pWrtShell->EndUndo( SwUndoId::DELETE )) + { + m_bCallUndo = true; + } + } + m_pWrtShell->DoUndo(false); + + SfxItemSetFixed<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA> aSet( m_pWrtShell->GetAttrPool() ); + if( m_pWrtShell->GetTableBoxFormulaAttrs( aSet )) + { + SwTableBoxFormula& rFormula + = const_cast<SwTableBoxFormula&>(aSet.Get(RES_BOXATR_FORMULA)); + // rFormula could be ANY of the table's formulas. + // GetFormula returns the "current" formula - which is basically undefined, + // so do something that encourages the current position's formula to become current. + if (m_pWrtShell->GetCursor()) + { + const SwNode* pNd = m_pWrtShell->GetCursor()->GetPointNode().FindTableNode(); + if (pNd) + { + const SwTable& rTable = static_cast<const SwTableNode*>(pNd)->GetTable(); + // get cell's external formula (for UI) by waving the magic wand. + rFormula.PtrToBoxNm(&rTable); + } + } + + sEdit += rFormula.GetFormula(); + } + } + + if( m_bFirst ) + { + // Set WrtShell flags correctly + m_pWrtShell->SttSelect(); + m_pWrtShell->EndSelect(); + } + + m_bFirst = false; + + mxEdit->connect_changed( LINK( this, SwInputWindow, ModifyHdl )); + + mxEdit->set_text( sEdit ); + m_sOldFormula = sEdit; + + // For input cut the UserInterface + + m_pView->GetEditWin().LockKeyInput(true); + m_pView->GetViewFrame().GetDispatcher()->Lock(true); + m_pWrtShell->Push(); + } + + ToolBox::Show(); + + // grab focus after ToolBox is shown so focus isn't potentially lost elsewhere + if (m_pView) + { + int nPos = mxEdit->get_text().getLength(); + mxEdit->select_region(nPos, nPos); + mxEdit->GrabFocus(); + } +} + +void SwInputWindow::MenuHdl(std::u16string_view command) +{ + if (!command.empty()) + mxEdit->replace_selection(OUString::Concat(command) + " "); +} + +IMPL_LINK_NOARG(SwInputWindow, DropdownClickHdl, ToolBox *, void) +{ + ToolBoxItemId nCurID = GetCurItemId(); + EndSelection(); // reset back CurItemId ! + if (nCurID == FN_FORMULA_CALC) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/inputwinmenu.ui")); + std::unique_ptr<weld::Menu> xPopMenu(xBuilder->weld_menu("menu")); + tools::Rectangle aRect(GetItemRect(FN_FORMULA_CALC)); + weld::Window* pParent = weld::GetPopupParent(*this, aRect); + MenuHdl(xPopMenu->popup_at_rect(pParent, aRect)); + } +} + +void SwInputWindow::Click( ) +{ + ToolBoxItemId nCurID = GetCurItemId(); + EndSelection(); // reset back CurItemId ! + if ( nCurID == FN_FORMULA_CANCEL ) + { + CancelFormula(); + } + else if (nCurID == FN_FORMULA_APPLY) + { + ApplyFormula(); + } +} + +void SwInputWindow::ApplyFormula() +{ + // in case it was created while loading the document, the active view + // wasn't initialised at that time, so ShowWin() didn't initialise anything + // either - nothing to do + if (!m_pView || !m_pWrtShell) + { + // presumably there must be an active view now since the event arrived + if (SwView* pView = GetActiveView()) + { + // this just makes the input window go away, so that the next time it works + pView->GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON); + } + return; + } + + m_pView->GetViewFrame().GetDispatcher()->Lock(false); + m_pView->GetEditWin().LockKeyInput(false); + CleanupUglyHackWithUndo(); + m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); + + // Form should always begin with "=", so remove it here again + OUString sEdit(comphelper::string::strip(mxEdit->get_text(), ' ')); + if( !sEdit.isEmpty() && '=' == sEdit[0] ) + sEdit = sEdit.copy( 1 ); + SfxStringItem aParam(FN_EDIT_FORMULA, sEdit); + + m_pWrtShell->EndSelTableCells(); + m_pView->GetEditWin().GrabFocus(); + const SfxPoolItem* aArgs[2]; + aArgs[0] = &aParam; + aArgs[1] = nullptr; + m_pView->GetViewFrame().GetBindings().Execute( FN_EDIT_FORMULA, aArgs, SfxCallMode::ASYNCHRON ); +} + +void SwInputWindow::CancelFormula() +{ + // in case it was created while loading the document, the active view + // wasn't initialised at that time, so ShowWin() didn't initialise anything + // either - nothing to do + if (!m_pView || !m_pWrtShell) + { + // presumably there must be an active view now since the event arrived + if (SwView* pView = GetActiveView()) + { + // this just makes the input window go away, so that the next time it works + pView->GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON); + } + return; + } + + m_pView->GetViewFrame().GetDispatcher()->Lock( false ); + m_pView->GetEditWin().LockKeyInput(false); + CleanupUglyHackWithUndo(); + m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); + + if( m_bDelSel ) + m_pWrtShell->EnterStdMode(); + + m_pWrtShell->EndSelTableCells(); + + m_pView->GetEditWin().GrabFocus(); + + m_pView->GetViewFrame().GetDispatcher()->Execute( FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON); +} + +const sal_Unicode CH_LRE = 0x202a; +const sal_Unicode CH_PDF = 0x202c; + +IMPL_LINK( SwInputWindow, SelTableCellsNotify, SwWrtShell&, rCaller, void ) +{ + if(m_pWrtShell && m_bIsTable) + { + SwFrameFormat* pTableFormat = rCaller.GetTableFormat(); + OUString sBoxNms( rCaller.GetBoxNms() ); + OUString sTableNm; + if( pTableFormat && m_aCurrentTableName != pTableFormat->GetName() ) + sTableNm = pTableFormat->GetName(); + + mxEdit->UpdateRange( sBoxNms, sTableNm ); + + OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text() + + OUStringChar(CH_PDF); + + if( sNew != m_sOldFormula ) + { + // The WrtShell is in the table selection, + // then cancel the table selection otherwise, the cursor is + // positioned "in the forest" and the live update does not work! + m_pWrtShell->StartAllAction(); + + SwPaM aPam( *m_pWrtShell->GetStackCursor()->GetPoint() ); + aPam.Move( fnMoveBackward, GoInSection ); + aPam.SetMark(); + aPam.Move( fnMoveForward, GoInSection ); + + IDocumentContentOperations& rIDCO = m_pWrtShell->getIDocumentContentOperations(); + rIDCO.DeleteRange( aPam ); + rIDCO.InsertString( aPam, sNew ); + m_pWrtShell->EndAllAction(); + m_sOldFormula = sNew; + } + } + else + mxEdit->GrabFocus(); +} + +void SwInputWindow::SetFormula( const OUString& rFormula ) +{ + OUString sEdit('='); + if( !rFormula.isEmpty() ) + { + if( '=' == rFormula[0] ) + sEdit = rFormula; + else + sEdit += rFormula; + } + mxEdit->set_text( sEdit ); + mxEdit->select_region(sEdit.getLength(), sEdit.getLength()); + m_bDelSel = true; +} + +IMPL_LINK_NOARG(SwInputWindow, ModifyHdl, weld::Entry&, void) +{ + if (m_pWrtShell && m_bIsTable && m_bResetUndo) + { + m_pWrtShell->StartAllAction(); + DelBoxContent(); + OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text() + + OUStringChar(CH_PDF); + m_pWrtShell->SwEditShell::Insert2( sNew ); + m_pWrtShell->EndAllAction(); + m_sOldFormula = sNew; + } +} + +void SwInputWindow::DelBoxContent() +{ + if( m_pWrtShell && m_bIsTable ) + { + m_pWrtShell->StartAllAction(); + m_pWrtShell->ClearMark(); + m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); + m_pWrtShell->Push(); + m_pWrtShell->MoveSection( GoCurrSection, fnSectionStart ); + m_pWrtShell->SetMark(); + m_pWrtShell->MoveSection( GoCurrSection, fnSectionEnd ); + m_pWrtShell->SwEditShell::Delete(false); + m_pWrtShell->EndAllAction(); + } +} + +IMPL_LINK(InputEdit, KeyInputHdl, const KeyEvent&, rEvent, bool) +{ + bool bHandled = false; + const vcl::KeyCode aCode = rEvent.GetKeyCode(); + if (aCode == KEY_RETURN || aCode == KEY_F2) + { + bHandled = ActivateHdl(*m_xWidget); + } + else if(aCode == KEY_ESCAPE ) + { + static_cast<SwInputWindow*>(GetParent())->CancelFormula(); + bHandled = true; + } + return bHandled || ChildKeyInput(rEvent); +} + +IMPL_LINK_NOARG(InputEdit, ActivateHdl, weld::Entry&, bool) +{ + static_cast<SwInputWindow*>(GetParent())->ApplyFormula(); + return true; +} + +void InputEdit::UpdateRange(std::u16string_view rBoxes, + const OUString& rName ) +{ + if( rBoxes.empty() ) + { + GrabFocus(); + return; + } + const sal_Unicode cOpen = '<', cClose = '>', + cOpenBracket = '('; + OUString aPrefix = rName; + if(!rName.isEmpty()) + aPrefix += "."; + OUString aBoxes = aPrefix + rBoxes; + + int nSelStartPos, nSelEndPos; + m_xWidget->get_selection_bounds(nSelStartPos, nSelEndPos); + + Selection aSelection(nSelStartPos, nSelEndPos); + sal_uInt16 nSel = o3tl::narrowing<sal_uInt16>(aSelection.Len()); + // OS: The following expression ensures that in the overwrite mode, + // the selected closing parenthesis will be not deleted. + if( nSel && ( nSel > 1 || + m_xWidget->get_text()[ o3tl::narrowing<sal_uInt16>(aSelection.Min()) ] != cClose )) + m_xWidget->cut_clipboard(); + else + aSelection.Max() = aSelection.Min(); + OUString aActText(m_xWidget->get_text()); + const sal_uInt16 nLen = aActText.getLength(); + if( !nLen ) + { + OUString aStr = OUStringChar(cOpen) + aBoxes + OUStringChar(cClose); + m_xWidget->set_text(aStr); + sal_Int32 nPos = aStr.indexOf( cClose ); + OSL_ENSURE(nPos != -1, "delimiter not found"); + ++nPos; + m_xWidget->select_region(nPos, nPos); + } + else + { + bool bFound = false; + sal_Unicode cCh; + sal_uInt16 nPos, nEndPos = 0, nStartPos = o3tl::narrowing<sal_uInt16>(aSelection.Min()); + if( nStartPos-- ) + { + do { + if( cOpen == (cCh = aActText[ nStartPos ] ) || + cOpenBracket == cCh ) + { + bFound = cCh == cOpen; + break; + } + } while( nStartPos-- > 0 ); + } + if( bFound ) + { + bFound = false; + nEndPos = nStartPos; + while( nEndPos < nLen ) + { + if( cClose == aActText[ nEndPos ] ) + { + bFound = true; + break; + } + ++nEndPos; + } + // Only if the current position lies in the range or right behind. + if( bFound && ( nStartPos >= o3tl::make_unsigned(aSelection.Max()) || + o3tl::narrowing<sal_uInt16>(aSelection.Max()) > nEndPos + 1 )) + bFound = false; + } + if( bFound ) + { + nPos = ++nStartPos + 1; // We want behind + aActText = aActText.replaceAt( nStartPos, nEndPos - nStartPos, aBoxes ); + nPos = nPos + aBoxes.getLength(); + } + else + { + OUString aTmp = OUStringChar(cOpen) + aBoxes + OUStringChar(cClose); + nPos = o3tl::narrowing<sal_uInt16>(aSelection.Min()); + aActText = aActText.replaceAt( nPos, 0, aTmp ); + nPos = nPos + aTmp.getLength(); + } + if( m_xWidget->get_text() != aActText ) + { + m_xWidget->set_text(aActText); + m_xWidget->select_region(nPos, nPos); + } + } + GrabFocus(); + +} + +SwInputChild::SwInputChild(vcl::Window* _pParent, + sal_uInt16 nId, + SfxBindings const * pBindings, + SfxChildWinInfo* ) : + SfxChildWindow( _pParent, nId ) +{ + m_pDispatch = pBindings->GetDispatcher(); + SetWindow(VclPtr<SwInputWindow>::Create(_pParent, m_pDispatch)); + static_cast<SwInputWindow*>(GetWindow())->ShowWin(); + SetAlignment(SfxChildAlignment::LOWESTTOP); +} + +SwInputChild::~SwInputChild() +{ + if(m_pDispatch) + m_pDispatch->Lock(false); +} + +SfxChildWinInfo SwInputChild::GetInfo() const +{ + SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); + return aInfo; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/ribbar/workctrl.cxx b/sw/source/uibase/ribbar/workctrl.cxx new file mode 100644 index 0000000000..9a9b288e14 --- /dev/null +++ b/sw/source/uibase/ribbar/workctrl.cxx @@ -0,0 +1,900 @@ +/* -*- 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 <i18nutil/unicode.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <swmodule.hxx> +#include <utility> +#include <view.hxx> +#include <initui.hxx> +#include <docsh.hxx> +#include <gloshdl.hxx> +#include <gloslst.hxx> +#include <workctrl.hxx> +#include <strings.hrc> +#include <cmdid.h> +#include <helpids.h> +#include <wrtsh.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <svl/voiditem.hxx> +#include <vcl/event.hxx> +#include <vcl/menu.hxx> +#include <vcl/settings.hxx> +#include <rtl/ustring.hxx> +#include <swabstdlg.hxx> +#include <sfx2/zoomitem.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weldutils.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <bitmaps.hlst> +#include <toolkit/helper/vclunohelper.hxx> +#include <com/sun/star/frame/XFrame.hpp> + +#include <sfx2/viewfrm.hxx> + +// Size check +#define NAVI_ENTRIES 21 + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; + +SFX_IMPL_TOOLBOX_CONTROL( SwTbxAutoTextCtrl, SfxVoidItem ); + +SwTbxAutoTextCtrl::SwTbxAutoTextCtrl( + sal_uInt16 nSlotId, + ToolBoxItemId nId, + ToolBox& rTbx ) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{ + rTbx.SetItemBits( nId, ToolBoxItemBits::DROPDOWN | rTbx.GetItemBits( nId ) ); +} + +SwTbxAutoTextCtrl::~SwTbxAutoTextCtrl() +{ +} + +void SwTbxAutoTextCtrl::CreatePopupWindow() +{ + SwView* pView = ::GetActiveView(); + if(pView && !pView->GetDocShell()->IsReadOnly() && + !pView->GetWrtShell().HasReadonlySel() ) + { + Link<Menu*,bool> aLnk = LINK(this, SwTbxAutoTextCtrl, PopupHdl); + + ScopedVclPtrInstance<PopupMenu> pPopup; + SwGlossaryList* pGlossaryList = ::GetGlossaryList(); + const size_t nGroupCount = pGlossaryList->GetGroupCount(); + o3tl::sorted_vector<OUString> titles; + for(size_t i = 1; i <= nGroupCount; ++i) + { + OUString sTitle = pGlossaryList->GetGroupTitle(i - 1); + const sal_uInt16 nBlockCount = pGlossaryList->GetBlockCount(i -1); + auto const [it, _] = titles.insert(sTitle); + size_t const menuIndex(::std::distance(titles.begin(), it)); + if(nBlockCount) + { + sal_uInt16 nIndex = o3tl::narrowing<sal_uInt16>(100*i); + // but insert without extension + pPopup->InsertItem(i, sTitle, MenuItemBits::NONE, {}, menuIndex); + VclPtrInstance<PopupMenu> pSub; + pSub->SetSelectHdl(aLnk); + pPopup->SetPopupMenu(i, pSub); + for(sal_uInt16 j = 0; j < nBlockCount; j++) + { + OUString sLongName(pGlossaryList->GetBlockLongName(i - 1, j)); + OUString sShortName(pGlossaryList->GetBlockShortName(i - 1, j)); + + OUString sEntry = sShortName + " - " + sLongName; + pSub->InsertItem(++nIndex, sEntry); + } + } + } + + ToolBox* pToolBox = &GetToolBox(); + ToolBoxItemId nId = GetId(); + pToolBox->SetItemDown( nId, true ); + + pPopup->Execute( pToolBox, pToolBox->GetItemRect( nId ), + (pToolBox->GetAlign() == WindowAlign::Top || pToolBox->GetAlign() == WindowAlign::Bottom) ? + PopupMenuFlags::ExecuteDown : PopupMenuFlags::ExecuteRight ); + + pToolBox->SetItemDown( nId, false ); + } + GetToolBox().EndSelection(); +} + +void SwTbxAutoTextCtrl::StateChangedAtToolBoxControl( sal_uInt16, + SfxItemState, + const SfxPoolItem* pState ) +{ + GetToolBox().EnableItem( GetId(), (GetItemState(pState) != SfxItemState::DISABLED) ); +} + +IMPL_STATIC_LINK(SwTbxAutoTextCtrl, PopupHdl, Menu*, pMenu, bool) +{ + sal_uInt16 nId = pMenu->GetCurItemId(); + + sal_uInt16 nBlock = nId / 100; + + SwGlossaryList* pGlossaryList = ::GetGlossaryList(); + OUString sGroup = pGlossaryList->GetGroupName(nBlock - 1); + OUString sShortName = + pGlossaryList->GetBlockShortName(nBlock - 1, nId - (100 * nBlock) - 1); + + if (SwView* pView = GetActiveView()) + { + SwGlossaryHdl* pGlosHdl = pView->GetGlosHdl(); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::GlossarySetActGroup fnSetActGroup = pFact->SetGlossaryActGroupFunc(); + if ( fnSetActGroup ) + (*fnSetActGroup)( sGroup ); + pGlosHdl->SetCurGroup(sGroup, true); + pGlosHdl->InsertGlossary(sShortName); + } + + return false; +} + +// Navigation-Popup +// determine the order of the toolbox items +static sal_uInt16 aNavigationInsertIds[ NAVI_ENTRIES ] = +{ + NID_TBL, + NID_FRM, + NID_GRF, + NID_OLE, + NID_PGE, + NID_OUTL, + NID_MARK, + NID_DRW, + NID_CTRL, + NID_REG, + NID_BKM, + NID_SEL, + NID_FTN, + NID_POSTIT, + NID_SRCH_REP, + NID_INDEX_ENTRY, + NID_TABLE_FORMULA, + NID_TABLE_FORMULA_ERROR, + NID_RECENCY, + NID_FIELD, + NID_FIELD_BYTYPE +}; + +OUString constexpr aNavigationImgIds[ NAVI_ENTRIES ] = +{ + RID_BMP_RIBBAR_TBL, + RID_BMP_RIBBAR_FRM, + RID_BMP_RIBBAR_GRF, + RID_BMP_RIBBAR_OLE, + RID_BMP_RIBBAR_PGE, + RID_BMP_RIBBAR_OUTL, + RID_BMP_RIBBAR_MARK, + RID_BMP_RIBBAR_DRW, + RID_BMP_RIBBAR_CTRL, + RID_BMP_RIBBAR_REG, + RID_BMP_RIBBAR_BKM, + RID_BMP_RIBBAR_SEL, + RID_BMP_RIBBAR_FTN, + RID_BMP_RIBBAR_POSTIT, + RID_BMP_RIBBAR_REP, + RID_BMP_RIBBAR_ENTRY, + RID_BMP_RIBBAR_FORMULA, + RID_BMP_RIBBAR_ERROR, + RID_BMP_RIBBAR_RECENCY, + RID_BMP_RIBBAR_FIELD, + RID_BMP_RIBBAR_FIELD_BYTYPE +}; + +const TranslateId aNavigationStrIds[ NAVI_ENTRIES ] = +{ + STR_CONTENT_TYPE_TABLE, + STR_CONTENT_TYPE_FRAME, + STR_CONTENT_TYPE_GRAPHIC, + STR_CONTENT_TYPE_OLE, + ST_PGE, + STR_CONTENT_TYPE_OUTLINE, + ST_MARK, + STR_CONTENT_TYPE_DRAWOBJECT, + ST_CTRL, + STR_CONTENT_TYPE_REGION, + STR_CONTENT_TYPE_BOOKMARK, + ST_SEL, + STR_CONTENT_TYPE_FOOTNOTE, + STR_CONTENT_TYPE_POSTIT, + ST_SRCH_REP, + STR_CONTENT_TYPE_INDEX, + ST_TABLE_FORMULA, + ST_TABLE_FORMULA_ERROR, + ST_RECENCY, + STR_CONTENT_TYPE_TEXTFIELD, + ST_FIELD_BYTYPE +}; + +// these are global strings +const TranslateId STR_IMGBTN_ARY[] = +{ + STR_IMGBTN_TBL_DOWN, + STR_IMGBTN_FRM_DOWN, + STR_IMGBTN_PGE_DOWN, + STR_IMGBTN_DRW_DOWN, + STR_IMGBTN_CTRL_DOWN, + STR_IMGBTN_REG_DOWN, + STR_IMGBTN_BKM_DOWN, + STR_IMGBTN_GRF_DOWN, + STR_IMGBTN_OLE_DOWN, + STR_IMGBTN_OUTL_DOWN, + STR_IMGBTN_SEL_DOWN, + STR_IMGBTN_FTN_DOWN, + STR_IMGBTN_MARK_DOWN, + STR_IMGBTN_POSTIT_DOWN, + STR_IMGBTN_SRCH_REP_DOWN, + STR_IMGBTN_INDEX_ENTRY_DOWN, + STR_IMGBTN_TBLFML_DOWN, + STR_IMGBTN_TBLFML_ERR_DOWN, + STR_IMGBTN_RECENCY_DOWN, + STR_IMGBTN_FIELD_DOWN, + STR_IMGBTN_FIELD_BYTYPE_DOWN, + STR_IMGBTN_TBL_UP, + STR_IMGBTN_FRM_UP, + STR_IMGBTN_PGE_UP, + STR_IMGBTN_DRW_UP, + STR_IMGBTN_CTRL_UP, + STR_IMGBTN_REG_UP, + STR_IMGBTN_BKM_UP, + STR_IMGBTN_GRF_UP, + STR_IMGBTN_OLE_UP, + STR_IMGBTN_OUTL_UP, + STR_IMGBTN_SEL_UP, + STR_IMGBTN_FTN_UP, + STR_IMGBTN_MARK_UP, + STR_IMGBTN_POSTIT_UP, + STR_IMGBTN_SRCH_REP_UP, + STR_IMGBTN_INDEX_ENTRY_UP, + STR_IMGBTN_TBLFML_UP, + STR_IMGBTN_TBLFML_ERR_UP, + STR_IMGBTN_RECENCY_UP, + STR_IMGBTN_FIELD_UP, + STR_IMGBTN_FIELD_BYTYPE_UP, +}; + +static OUString lcl_GetScrollToolTip(bool bNext) +{ + sal_uInt16 nResId = SwView::GetMoveType(); + OUString sToolTip = SwResId(STR_IMGBTN_ARY[(!bNext ? NID_COUNT : 0) + nResId - NID_START]); + if (nResId == NID_FIELD_BYTYPE) + { + OUString sFieldType; + SwWrtShell* pWrtSh = GetActiveWrtShell(); + if (pWrtSh) + { + SwField* pCurField = pWrtSh->GetCurField(true); + if (pCurField) + sFieldType = SwFieldType::GetTypeStr(pCurField->GetTypeId()); + } + if (!sFieldType.isEmpty()) + sToolTip = sToolTip.replaceFirst(u"%FIELDTYPE", sFieldType); + else + sToolTip = SwResId(SW_STR_NONE); + } + return sToolTip; +} + +namespace { + +class SwZoomBox_Impl final : public InterimItemWindow +{ + std::unique_ptr<weld::ComboBox> m_xWidget; + sal_uInt16 m_nSlotId; + bool m_bRelease; + + DECL_LINK(SelectHdl, weld::ComboBox&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(ActivateHdl, weld::ComboBox&, bool); + DECL_LINK(FocusOutHdl, weld::Widget&, void); + + void Select(); + + void ReleaseFocus(); + +public: + SwZoomBox_Impl(vcl::Window* pParent, sal_uInt16 nSlot); + + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + + void save_value() + { + m_xWidget->save_value(); + } + + void set_entry_text(const OUString& rText) + { + m_xWidget->set_entry_text(rText); + } + + virtual ~SwZoomBox_Impl() override + { + disposeOnce(); + } +}; + +} + +SwZoomBox_Impl::SwZoomBox_Impl(vcl::Window* pParent, sal_uInt16 nSlot) + : InterimItemWindow(pParent, "modules/swriter/ui/zoombox.ui", "ZoomBox") + , m_xWidget(m_xBuilder->weld_combo_box("zoom")) + , m_nSlotId(nSlot) + , m_bRelease(true) +{ + InitControlBase(m_xWidget.get()); + + m_xWidget->set_help_id(HID_PVIEW_ZOOM_LB); + m_xWidget->set_entry_completion(false); + m_xWidget->connect_changed(LINK(this, SwZoomBox_Impl, SelectHdl)); + m_xWidget->connect_key_press(LINK(this, SwZoomBox_Impl, KeyInputHdl)); + m_xWidget->connect_entry_activate(LINK(this, SwZoomBox_Impl, ActivateHdl)); + m_xWidget->connect_focus_out(LINK(this, SwZoomBox_Impl, FocusOutHdl)); + + const TranslateId aZoomValues[] = + { RID_SVXSTR_ZOOM_25 , RID_SVXSTR_ZOOM_50 , + RID_SVXSTR_ZOOM_75 , RID_SVXSTR_ZOOM_100 , + RID_SVXSTR_ZOOM_150 , RID_SVXSTR_ZOOM_200 , + RID_SVXSTR_ZOOM_WHOLE_PAGE, RID_SVXSTR_ZOOM_PAGE_WIDTH , + RID_SVXSTR_ZOOM_OPTIMAL_VIEW }; + for(const TranslateId& pZoomValue : aZoomValues) + { + OUString sEntry = SvxResId(pZoomValue); + m_xWidget->append_text(sEntry); + } + + int nWidth = m_xWidget->get_pixel_size(SvxResId(RID_SVXSTR_ZOOM_200)).Width(); + m_xWidget->set_entry_width_chars(std::ceil(nWidth / m_xWidget->get_approximate_digit_width())); + + SetSizePixel(m_xWidget->get_preferred_size()); +} + +IMPL_LINK(SwZoomBox_Impl, SelectHdl, weld::ComboBox&, rComboBox, void) +{ + if (rComboBox.changed_by_direct_pick()) // only when picked from the list + Select(); +} + +IMPL_LINK_NOARG(SwZoomBox_Impl, ActivateHdl, weld::ComboBox&, bool) +{ + Select(); + return true; +} + +void SwZoomBox_Impl::Select() +{ + if( FN_PREVIEW_ZOOM == m_nSlotId ) + { + bool bNonNumeric = true; + + OUString sEntry = m_xWidget->get_active_text().replaceAll("%", ""); + SvxZoomItem aZoom(SvxZoomType::PERCENT,100); + if(sEntry == SvxResId( RID_SVXSTR_ZOOM_PAGE_WIDTH ) ) + aZoom.SetType(SvxZoomType::PAGEWIDTH); + else if(sEntry == SvxResId( RID_SVXSTR_ZOOM_OPTIMAL_VIEW ) ) + aZoom.SetType(SvxZoomType::OPTIMAL); + else if(sEntry == SvxResId( RID_SVXSTR_ZOOM_WHOLE_PAGE) ) + aZoom.SetType(SvxZoomType::WHOLEPAGE); + else + { + bNonNumeric = false; + + sal_uInt16 nZoom = o3tl::narrowing<sal_uInt16>(sEntry.toInt32()); + if(nZoom < MINZOOM) + nZoom = MINZOOM; + if(nZoom > MAXZOOM) + nZoom = MAXZOOM; + aZoom.SetValue(nZoom); + } + + if (bNonNumeric) + { + // put old value back, in case its effectively the same + // as the picked option and no update to number comes + // back from writer + m_xWidget->set_entry_text(m_xWidget->get_saved_value()); + } + + if (SfxObjectShell* pCurrentShell = SfxObjectShell::Current()) + { + pCurrentShell->GetDispatcher()->ExecuteList(SID_ATTR_ZOOM, + SfxCallMode::ASYNCHRON, { &aZoom }); + } + } + ReleaseFocus(); +} + +IMPL_LINK(SwZoomBox_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + bool bHandled = false; + + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + + switch (nCode) + { + case KEY_TAB: + m_bRelease = false; + Select(); + break; + + case KEY_ESCAPE: + m_xWidget->set_entry_text(m_xWidget->get_saved_value()); + ReleaseFocus(); + bHandled = true; + break; + } + + return bHandled || ChildKeyInput(rKEvt); +} + +IMPL_LINK_NOARG(SwZoomBox_Impl, FocusOutHdl, weld::Widget&, void) +{ + if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus + m_xWidget->set_entry_text(m_xWidget->get_saved_value()); +} + +void SwZoomBox_Impl::ReleaseFocus() +{ + if ( !m_bRelease ) + { + m_bRelease = true; + return; + } + SfxViewShell* pCurSh = SfxViewShell::Current(); + + if ( pCurSh ) + { + vcl::Window* pShellWnd = pCurSh->GetWindow(); + + if ( pShellWnd ) + pShellWnd->GrabFocus(); + } +} + +SFX_IMPL_TOOLBOX_CONTROL( SwPreviewZoomControl, SfxUInt16Item); + +SwPreviewZoomControl::SwPreviewZoomControl( + sal_uInt16 nSlotId, + ToolBoxItemId nId, + ToolBox& rTbx) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SwPreviewZoomControl::~SwPreviewZoomControl() +{ +} + +void SwPreviewZoomControl::StateChangedAtToolBoxControl( sal_uInt16 /*nSID*/, + SfxItemState eState, + const SfxPoolItem* pState ) +{ + ToolBoxItemId nId = GetId(); + GetToolBox().EnableItem( nId, (GetItemState(pState) != SfxItemState::DISABLED) ); + SwZoomBox_Impl* pBox = static_cast<SwZoomBox_Impl*>(GetToolBox().GetItemWindow( GetId() )); + if(SfxItemState::DEFAULT <= eState) + { + OUString sZoom(unicode::formatPercent(static_cast<const SfxUInt16Item*>(pState)->GetValue(), + Application::GetSettings().GetUILanguageTag())); + pBox->set_entry_text(sZoom); + pBox->save_value(); + } +} + +VclPtr<InterimItemWindow> SwPreviewZoomControl::CreateItemWindow( vcl::Window *pParent ) +{ + VclPtrInstance<SwZoomBox_Impl> pRet( pParent, GetSlotId() ); + return pRet.get(); +} + +namespace { + +class SwJumpToSpecificBox_Impl final : public InterimItemWindow +{ + std::unique_ptr<weld::Entry> m_xWidget; + + sal_uInt16 m_nSlotId; + + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(SelectHdl, weld::Entry&, bool); +public: + SwJumpToSpecificBox_Impl(vcl::Window* pParent, sal_uInt16 nSlot); + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + virtual ~SwJumpToSpecificBox_Impl() override + { + disposeOnce(); + } +}; + +} + +IMPL_LINK(SwJumpToSpecificBox_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return ChildKeyInput(rKEvt); +} + +SwJumpToSpecificBox_Impl::SwJumpToSpecificBox_Impl(vcl::Window* pParent, sal_uInt16 nSlot) + : InterimItemWindow(pParent, "modules/swriter/ui/jumpposbox.ui", "JumpPosBox") + , m_xWidget(m_xBuilder->weld_entry("jumppos")) + , m_nSlotId(nSlot) +{ + InitControlBase(m_xWidget.get()); + + m_xWidget->connect_key_press(LINK(this, SwJumpToSpecificBox_Impl, KeyInputHdl)); + m_xWidget->connect_activate(LINK(this, SwJumpToSpecificBox_Impl, SelectHdl)); + + SetSizePixel(m_xWidget->get_preferred_size()); +} + +IMPL_LINK_NOARG(SwJumpToSpecificBox_Impl, SelectHdl, weld::Entry&, bool) +{ + OUString sEntry(m_xWidget->get_text()); + SfxUInt16Item aPageNum(m_nSlotId); + aPageNum.SetValue(o3tl::narrowing<sal_uInt16>(sEntry.toInt32())); + if (SfxObjectShell* pCurrentShell = SfxObjectShell::Current()) + { + pCurrentShell->GetDispatcher()->ExecuteList(m_nSlotId, SfxCallMode::ASYNCHRON, + { &aPageNum }); + } + return true; +} + +SFX_IMPL_TOOLBOX_CONTROL( SwJumpToSpecificPageControl, SfxUInt16Item); + +SwJumpToSpecificPageControl::SwJumpToSpecificPageControl( + sal_uInt16 nSlotId, + ToolBoxItemId nId, + ToolBox& rTbx) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{} + +SwJumpToSpecificPageControl::~SwJumpToSpecificPageControl() +{} + +VclPtr<InterimItemWindow> SwJumpToSpecificPageControl::CreateItemWindow( vcl::Window *pParent ) +{ + VclPtrInstance<SwJumpToSpecificBox_Impl> pRet( pParent, GetSlotId() ); + return pRet.get(); +} + +NavElementBox_Base::NavElementBox_Base(std::unique_ptr<weld::ComboBox> xComboBox, + uno::Reference<frame::XFrame> xFrame) + : m_xComboBox(std::move(xComboBox)) + ,m_xFrame(std::move(xFrame)) +{ + m_xComboBox->set_size_request(150, -1); + + m_xComboBox->make_sorted(); + m_xComboBox->freeze(); + for (sal_uInt16 i = 0; i < NID_COUNT; i++) + m_xComboBox->append(OUString::number(aNavigationInsertIds[i]), + SwResId(aNavigationStrIds[i]), aNavigationImgIds[i]); + m_xComboBox->thaw(); + + m_xComboBox->connect_changed(LINK(this, NavElementBox_Base, SelectHdl)); + m_xComboBox->connect_key_press(LINK(this, NavElementBox_Base, KeyInputHdl)); +} + +NavElementBox_Impl::NavElementBox_Impl(vcl::Window* pParent, + const uno::Reference<frame::XFrame>& xFrame) + : InterimItemWindow(pParent, "modules/swriter/ui/combobox.ui", "ComboBox") + ,NavElementBox_Base(m_xBuilder->weld_combo_box("combobox"), xFrame) +{ + SetSizePixel(m_xContainer->get_preferred_size()); +} + +void NavElementBox_Base::ReleaseFocus_Impl() +{ + if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) + m_xFrame->getContainerWindow()->setFocus(); +} + +IMPL_STATIC_LINK(NavElementBox_Base, SelectHdl, weld::ComboBox&, rComboBox, void) +{ + if (!rComboBox.changed_by_direct_pick()) // only when picked from the list + return; + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + if (!pViewFrm) + return; + SfxUInt32Item aParam(FN_NAV_ELEMENT, rComboBox.get_active_id().toUInt32()); + const SfxPoolItem* aArgs[2]; + aArgs[0] = &aParam; + aArgs[1] = nullptr; + SfxDispatcher* pDispatch = pViewFrm->GetBindings().GetDispatcher(); + pDispatch->Execute(FN_NAV_ELEMENT, SfxCallMode::SYNCHRON, aArgs); +} + +void NavElementBox_Base::UpdateBox() +{ + sal_uInt16 nMoveType = SwView::GetMoveType(); + for (size_t i = 0; i < SAL_N_ELEMENTS(aNavigationInsertIds); ++i) + { + if (nMoveType == aNavigationInsertIds[i]) + { + m_xComboBox->set_active_text(SwResId(aNavigationStrIds[i])); + break; + } + } +} + +IMPL_LINK(NavElementBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return DoKeyInput(rKEvt); +} + +bool NavElementBox_Base::DoKeyInput(const KeyEvent& /*rKEvt*/) +{ + return false; +} + +bool NavElementBox_Impl::DoKeyInput(const KeyEvent& rKEvt) +{ + if (KEY_ESCAPE == rKEvt.GetKeyCode().GetCode()) + { + ReleaseFocus_Impl(); + return true; + } + return ChildKeyInput(rKEvt); +} + +NavElementToolBoxControl::NavElementToolBoxControl( const uno::Reference< uno::XComponentContext >& rxContext ) + : NavElementToolBoxControl_Base( rxContext, + uno::Reference< frame::XFrame >(), + ".uno:NavElement" ), + m_pBox( nullptr ) +{ +} + +// XServiceInfo +sal_Bool SAL_CALL NavElementToolBoxControl::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +OUString SAL_CALL NavElementToolBoxControl::getImplementationName() +{ + return "lo.writer.NavElementToolBoxController"; +} + +uno::Sequence< OUString > SAL_CALL NavElementToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL NavElementToolBoxControl::dispose() +{ + svt::ToolboxController::dispose(); + + SolarMutexGuard aSolarMutexGuard; + m_xVclBox.disposeAndClear(); + m_xWeldBox.reset(); + m_pBox = nullptr; +} + +// XStatusListener +void SAL_CALL NavElementToolBoxControl::statusChanged( const frame::FeatureStateEvent& rEvent ) +{ + if (!m_pBox) + return; + + SolarMutexGuard aSolarMutexGuard; + if ( rEvent.FeatureURL.Path != "NavElement" ) + return; + + if ( rEvent.IsEnabled ) + { + m_pBox->set_sensitive(true); + m_pBox->UpdateBox(); + } + else + m_pBox->set_sensitive(true); + + if (SwView* pView = GetActiveView()) + { + pView->GetViewFrame().GetBindings().Invalidate(FN_SCROLL_NEXT); + pView->GetViewFrame().GetBindings().Invalidate(FN_SCROLL_PREV); + } +} + +// XToolbarController +void SAL_CALL NavElementToolBoxControl::execute( sal_Int16 /*KeyModifier*/ ) +{ +} + +void SAL_CALL NavElementToolBoxControl::click() +{ +} + +void SAL_CALL NavElementToolBoxControl::doubleClick() +{ +} + +uno::Reference< awt::XWindow > SAL_CALL NavElementToolBoxControl::createPopupWindow() +{ + return uno::Reference< awt::XWindow >(); +} + +uno::Reference< awt::XWindow > SAL_CALL NavElementToolBoxControl::createItemWindow( + const uno::Reference< awt::XWindow >& xParent ) +{ + uno::Reference< awt::XWindow > xItemWindow; + + if (m_pBuilder) + { + SolarMutexGuard aSolarMutexGuard; + + std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("NavElementWidget")); + + xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get())); + + m_xWeldBox.reset(new NavElementBox_Base(std::move(xWidget), m_xFrame)); + m_pBox = m_xWeldBox.get(); + } + else + { + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent ); + if ( pParent ) + { + SolarMutexGuard aSolarMutexGuard; + m_xVclBox = VclPtr<NavElementBox_Impl>::Create( pParent, m_xFrame ); + m_pBox = m_xVclBox.get(); + xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox); + } + } + + return xItemWindow; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_NavElementToolBoxController_get_implementation( + css::uno::XComponentContext *rxContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire( new NavElementToolBoxControl( rxContext ) ); +} + +namespace { + +typedef cppu::ImplInheritanceHelper< ::svt::ToolboxController, css::lang::XServiceInfo> PrevNextScrollToolboxController_Base; +class PrevNextScrollToolboxController : public PrevNextScrollToolboxController_Base +{ +public: + enum Type { PREVIOUS, NEXT }; + + PrevNextScrollToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext, Type eType ); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; + +private: + Type meType; +}; + +} + +PrevNextScrollToolboxController::PrevNextScrollToolboxController( const css::uno::Reference< css::uno::XComponentContext > & rxContext, Type eType ) + : PrevNextScrollToolboxController_Base( rxContext, + css::uno::Reference< css::frame::XFrame >(), + (eType == PREVIOUS) ? OUString( ".uno:ScrollToPrevious" ): OUString( ".uno:ScrollToNext" ) ), + meType( eType ) +{ + addStatusListener(".uno:NavElement"); +} + +// XServiceInfo +OUString SAL_CALL PrevNextScrollToolboxController::getImplementationName() +{ + return meType == PrevNextScrollToolboxController::PREVIOUS? + OUString( "lo.writer.PreviousScrollToolboxController" ) : + OUString( "lo.writer.NextScrollToolboxController" ); +} + +sal_Bool SAL_CALL PrevNextScrollToolboxController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL PrevNextScrollToolboxController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL PrevNextScrollToolboxController::dispose() +{ + SolarMutexGuard aSolarMutexGuard; + + svt::ToolboxController::dispose(); +} + +// XStatusListener +void SAL_CALL PrevNextScrollToolboxController::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + if (rEvent.FeatureURL.Path == "NavElement") + { + if (m_pToolbar) + m_pToolbar->set_item_tooltip_text(m_aCommandURL, lcl_GetScrollToolTip(meType != PrevNextScrollToolboxController::PREVIOUS)); + else + { + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetQuickHelpText(nId, lcl_GetScrollToolTip(meType != PrevNextScrollToolboxController::PREVIOUS)); + } + } + else if (rEvent.FeatureURL.Path == "ScrollToPrevious" || rEvent.FeatureURL.Path == "ScrollToNext") + { + if (m_pToolbar) + m_pToolbar->set_item_sensitive(m_aCommandURL, rEvent.IsEnabled); + else + { + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + pToolBox->EnableItem(nId, rEvent.IsEnabled); + } + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_PreviousScrollToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire( new PrevNextScrollToolboxController( context, PrevNextScrollToolboxController::PREVIOUS ) ); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_NextScrollToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire( new PrevNextScrollToolboxController( context, PrevNextScrollToolboxController::NEXT ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |