diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sd/source/ui/func/fudraw.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sd/source/ui/func/fudraw.cxx')
-rw-r--r-- | sd/source/ui/func/fudraw.cxx | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/sd/source/ui/func/fudraw.cxx b/sd/source/ui/func/fudraw.cxx new file mode 100644 index 000000000..46988c5f4 --- /dev/null +++ b/sd/source/ui/func/fudraw.cxx @@ -0,0 +1,821 @@ +/* -*- 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 <svx/svdoole2.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->quadrat, 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, 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->quadrat, 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); + + 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.IsInside(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.pObj; + } + else if (eHit == SdrHitKind::TextEditObj && dynamic_cast< const FuSelection *>( this ) != nullptr) + { + sal_uInt16 nSdrObjKind = aVEvt.pObj->GetObjIdentifier(); + + if ( nSdrObjKind != OBJ_TEXT && + nSdrObjKind != OBJ_TITLETEXT && + nSdrObjKind != OBJ_OUTLINETEXT && + aVEvt.pObj->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, 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())); + 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(); + sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier(); + + if (nInv == SdrInventor::Default && nSdrObjKind == OBJ_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 == OBJ_GRAF && 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 == OBJ_GRUP) + { + // 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.pObj; + + 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.pURLField && !pIMapObj) + return false; + + OUString aURL; + if (rVEvt.pURLField) + aURL = INetURLObject::decode(rVEvt.pURLField->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: */ |