bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / func / fudraw.cxx
blob45a5629609bd6848b58c01617b7b022e28f3c789
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <vcl/svapp.hxx>
23 #include <vcl/waitobj.hxx>
24 #include <vcl/ptrstyle.hxx>
25 #include <editeng/flditem.hxx>
26 #include <svx/svdogrp.hxx>
27 #include <svx/svdoole2.hxx>
28 #include <tools/urlobj.hxx>
29 #include <vcl/help.hxx>
30 #include <svx/bmpmask.hxx>
31 #include <svx/svdotext.hxx>
32 #include <sfx2/app.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include <sfx2/bindings.hxx>
35 #include <svx/svdpagv.hxx>
36 #include <vcl/imapobj.hxx>
37 #include <svx/svxids.hrc>
38 #include <svx/obj3d.hxx>
39 #include <svx/scene3d.hxx>
40 #include <sfx2/viewfrm.hxx>
42 #include <anminfo.hxx>
43 #include <strings.hrc>
46 #include <sdmod.hxx>
47 #include <GraphicDocShell.hxx>
48 #include <fudraw.hxx>
49 #include <ViewShell.hxx>
50 #include <FrameView.hxx>
51 #include <View.hxx>
52 #include <Window.hxx>
53 #include <drawdoc.hxx>
54 #include <DrawDocShell.hxx>
55 #include <sdresid.hxx>
56 #include <drawview.hxx>
57 #include <fusel.hxx>
58 #include <vcl/weld.hxx>
59 #include <slideshow.hxx>
60 #include <svx/sdrhittesthelper.hxx>
61 #include <unotools/securityoptions.hxx>
63 using namespace ::com::sun::star;
65 namespace sd {
68 /**
69 * Base-class for all drawmodul-specific functions
71 FuDraw::FuDraw(ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView,
72 SdDrawDocument* pDoc, SfxRequest& rReq)
73 : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
74 , aNewPointer(PointerStyle::Arrow)
75 , aOldPointer(PointerStyle::Arrow)
76 , bMBDown(false)
77 , bDragHelpLine(false)
78 , nHelpLine(0)
79 , bPermanent(false)
83 FuDraw::~FuDraw()
85 mpView->BrkAction();
89 /**
90 * Code shared by MouseButtonDown and MouseMove
92 void FuDraw::DoModifiers(const MouseEvent& rMEvt, bool bSnapModPressed)
94 FrameView* pFrameView = mpViewShell->GetFrameView();
95 bool bGridSnap = pFrameView->IsGridSnap();
96 bGridSnap = (bSnapModPressed != bGridSnap);
98 if (mpView->IsGridSnap() != bGridSnap)
99 mpView->SetGridSnap(bGridSnap);
101 bool bBordSnap = pFrameView->IsBordSnap();
102 bBordSnap = (bSnapModPressed != bBordSnap);
104 if (mpView->IsBordSnap() != bBordSnap)
105 mpView->SetBordSnap(bBordSnap);
107 bool bHlplSnap = pFrameView->IsHlplSnap();
108 bHlplSnap = (bSnapModPressed != bHlplSnap);
110 if (mpView->IsHlplSnap() != bHlplSnap)
111 mpView->SetHlplSnap(bHlplSnap);
113 bool bOFrmSnap = pFrameView->IsOFrmSnap();
114 bOFrmSnap = (bSnapModPressed != bOFrmSnap);
116 if (mpView->IsOFrmSnap() != bOFrmSnap)
117 mpView->SetOFrmSnap(bOFrmSnap);
119 bool bOPntSnap = pFrameView->IsOPntSnap();
120 bOPntSnap = (bSnapModPressed != bOPntSnap);
122 if (mpView->IsOPntSnap() != bOPntSnap)
123 mpView->SetOPntSnap(bOPntSnap);
125 bool bOConSnap = pFrameView->IsOConSnap();
126 bOConSnap = (bSnapModPressed != bOConSnap);
128 if (mpView->IsOConSnap() != bOConSnap)
129 mpView->SetOConSnap(bOConSnap);
131 bool bAngleSnap = rMEvt.IsShift() == !pFrameView->IsAngleSnapEnabled();
133 if (mpView->IsAngleSnapEnabled() != bAngleSnap)
134 mpView->SetAngleSnapEnabled(bAngleSnap);
136 bool bCenter = rMEvt.IsMod2();
138 if ( mpView->IsCreate1stPointAsCenter() != bCenter ||
139 mpView->IsResizeAtCenter() != bCenter )
141 mpView->SetCreate1stPointAsCenter(bCenter);
142 mpView->SetResizeAtCenter(bCenter);
147 bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt)
149 // remember button state for creation of own MouseEvents
150 SetMouseButtonCode(rMEvt.GetButtons());
152 bool bReturn = false;
153 bDragHelpLine = false;
154 aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
156 if ( rMEvt.IsLeft() )
158 FrameView* pFrameView = mpViewShell->GetFrameView();
160 bool bOrtho = false;
162 bool bRestricted = true;
164 if (mpView->IsDragObj())
166 // object is dragged (move, resize,...)
167 const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
169 if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
171 // Move
172 bRestricted = false;
176 // #i33136#
177 if(bRestricted && doConstructOrthogonal())
179 // Restrict movement:
180 // rectangle->quadrat, ellipse->circle etc.
181 bOrtho = !rMEvt.IsShift();
183 else
185 bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
187 if (!mpView->IsSnapEnabled())
188 mpView->SetSnapEnabled(true);
190 bool bSnapModPressed = rMEvt.IsMod1();
191 if (mpView->IsOrtho() != bOrtho)
192 mpView->SetOrtho(bOrtho);
194 DoModifiers(rMEvt, bSnapModPressed);
196 SdrPageView* pPV = nullptr;
197 sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
199 // look only for HelpLines when they are visible (!)
200 bool bHelpLine(false);
201 if(mpView->IsHlplVisible())
202 bHelpLine = mpView->PickHelpLine(aMDPos, nHitLog, *mpWindow, nHelpLine, pPV);
203 bool bHitHdl = (mpView->PickHandle(aMDPos) != nullptr);
205 if ( bHelpLine
206 && !mpView->IsCreateObj()
207 && ((mpView->GetEditMode() == SdrViewEditMode::Edit && !bHitHdl) || (rMEvt.IsShift() && bSnapModPressed)) )
209 mpWindow->CaptureMouse();
210 mpView->BegDragHelpLine(nHelpLine, pPV);
211 bDragHelpLine = mpView->IsDragHelpLine();
212 bReturn = true;
215 ForcePointer(&rMEvt);
217 return bReturn;
220 bool FuDraw::MouseMove(const MouseEvent& rMEvt)
222 FrameView* pFrameView = mpViewShell->GetFrameView();
223 Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
225 bool bOrtho = false;
226 bool bRestricted = true;
228 if (mpView->IsDragObj())
230 // object is dragged (move, resize, ...)
231 const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
233 if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
235 // Move
236 bRestricted = false;
240 if (mpView->IsAction())
242 // #i33136# and fdo#88339
243 if(bRestricted && doConstructOrthogonal())
245 // Scale proportionally by default:
246 // rectangle->quadrat, ellipse->circle, Images etc.
247 bOrtho = !rMEvt.IsShift();
249 else
251 bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
254 bool bSnapModPressed = rMEvt.IsMod2();
255 mpView->SetDragWithCopy(rMEvt.IsMod1() && pFrameView->IsDragWithCopy());
257 if (mpView->IsOrtho() != bOrtho)
258 mpView->SetOrtho(bOrtho);
259 DoModifiers(rMEvt, bSnapModPressed);
262 if ( mpView->IsDragHelpLine() )
263 mpView->MovDragHelpLine(aPos);
266 bool bReturn = mpView->MouseMove(rMEvt, mpWindow);
268 if (mpView->IsAction())
270 // Because the flag set back if necessary in MouseMove
271 if (mpView->IsOrtho() != bOrtho)
272 mpView->SetOrtho(bOrtho);
275 ForcePointer(&rMEvt);
277 return bReturn;
280 bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt)
282 if (mpView && mpView->IsDragHelpLine())
283 mpView->EndDragHelpLine();
285 if ( bDragHelpLine )
287 ::tools::Rectangle aOutputArea(Point(0,0), mpWindow->GetOutputSizePixel());
289 if (mpView && !aOutputArea.IsInside(rMEvt.GetPosPixel()))
290 mpView->GetSdrPageView()->DeleteHelpLine(nHelpLine);
292 mpWindow->ReleaseMouse();
295 if (mpView)
297 FrameView* pFrameView = mpViewShell->GetFrameView();
298 mpView->SetOrtho( pFrameView->IsOrtho() );
299 mpView->SetAngleSnapEnabled( pFrameView->IsAngleSnapEnabled() );
300 mpView->SetSnapEnabled(true);
301 mpView->SetCreate1stPointAsCenter(false);
302 mpView->SetResizeAtCenter(false);
303 mpView->SetDragWithCopy(pFrameView->IsDragWithCopy());
304 mpView->SetGridSnap(pFrameView->IsGridSnap());
305 mpView->SetBordSnap(pFrameView->IsBordSnap());
306 mpView->SetHlplSnap(pFrameView->IsHlplSnap());
307 mpView->SetOFrmSnap(pFrameView->IsOFrmSnap());
308 mpView->SetOPntSnap(pFrameView->IsOPntSnap());
309 mpView->SetOConSnap(pFrameView->IsOConSnap());
312 bIsInDragMode = false;
313 ForcePointer(&rMEvt);
314 FuPoor::MouseButtonUp(rMEvt);
316 return false;
320 * Process keyboard input
321 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
323 bool FuDraw::KeyInput(const KeyEvent& rKEvt)
325 bool bReturn = false;
327 switch ( rKEvt.GetKeyCode().GetCode() )
329 case KEY_ESCAPE:
331 bReturn = FuDraw::cancel();
333 break;
335 case KEY_DELETE:
336 case KEY_BACKSPACE:
338 if (!mpDocSh->IsReadOnly())
340 if (mpView->IsPresObjSelected(false, true, false, true))
342 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(),
343 VclMessageType::Info, VclButtonsType::Ok,
344 SdResId(STR_ACTION_NOTPOSSIBLE)));
345 xInfoBox->run();
347 else
349 // wait-mousepointer while deleting object
350 WaitObject aWait( static_cast<vcl::Window*>(mpViewShell->GetActiveWindow()) );
351 // delete object
352 mpView->DeleteMarked();
355 bReturn = true;
357 break;
359 case KEY_TAB:
361 vcl::KeyCode aCode = rKEvt.GetKeyCode();
363 if ( !aCode.IsMod1() && !aCode.IsMod2() )
365 // Moved next line which was a bugfix itself into
366 // the scope which really does the object selection travel
367 // and thus is allowed to call SelectionHasChanged().
369 // Switch to FuSelect.
370 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
371 SID_OBJECT_SELECT,
372 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
374 // changeover to the next object
375 if(!mpView->MarkNextObj( !aCode.IsShift() ))
377 //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj().
378 if ( mpView->HasMultipleMarkableObjects() && mpView->AreObjectsMarked() )
380 // No next object: go over open end and get first from
381 // the other side
382 mpView->UnmarkAllObj();
383 mpView->MarkNextObj(!aCode.IsShift());
387 if(mpView->AreObjectsMarked())
388 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
390 bReturn = true;
393 break;
395 case KEY_END:
397 vcl::KeyCode aCode = rKEvt.GetKeyCode();
399 if ( aCode.IsMod1() )
401 // mark last object
402 mpView->UnmarkAllObj();
403 mpView->MarkNextObj();
405 if(mpView->AreObjectsMarked())
406 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
408 bReturn = true;
411 break;
413 case KEY_HOME:
415 vcl::KeyCode aCode = rKEvt.GetKeyCode();
417 if ( aCode.IsMod1() )
419 // mark first object
420 mpView->UnmarkAllObj();
421 mpView->MarkNextObj(true);
423 if(mpView->AreObjectsMarked())
424 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
426 bReturn = true;
429 break;
431 default:
432 break;
435 if (!bReturn)
437 bReturn = FuPoor::KeyInput(rKEvt);
439 else
441 mpWindow->ReleaseMouse();
444 return bReturn;
447 void FuDraw::Activate()
449 FuPoor::Activate();
450 ForcePointer();
454 * Toggle mouse-pointer
456 void FuDraw::ForcePointer(const MouseEvent* pMEvt)
458 Point aPnt;
459 sal_uInt16 nModifier = 0;
460 bool bLeftDown = false;
461 bool bDefPointer = true;
463 if (pMEvt)
465 aPnt = mpWindow->PixelToLogic(pMEvt->GetPosPixel());
466 nModifier = pMEvt->GetModifier();
467 bLeftDown = pMEvt->IsLeft();
469 else
471 aPnt = mpWindow->PixelToLogic(mpWindow->GetPointerPosPixel());
474 if (mpView->IsDragObj())
476 if (SD_MOD()->GetWaterCan() && !mpView->PickHandle(aPnt))
478 // water can mode
479 bDefPointer = false;
480 mpWindow->SetPointer(PointerStyle::Fill);
483 else
485 SdrHdl* pHdl = mpView->PickHandle(aPnt);
487 if (SD_MOD()->GetWaterCan() && !pHdl)
489 // water can mode
490 bDefPointer = false;
491 mpWindow->SetPointer(PointerStyle::Fill);
493 else if (!pHdl &&
494 mpViewShell->GetViewFrame()->HasChildWindow(SvxBmpMaskChildWindow::GetChildWindowId()))
496 // pipette mode
497 SfxChildWindow* pWnd = mpViewShell->GetViewFrame()->GetChildWindow(SvxBmpMaskChildWindow::GetChildWindowId());
498 SvxBmpMask* pMask = pWnd ? static_cast<SvxBmpMask*>(pWnd->GetWindow()) : nullptr;
499 if (pMask && pMask->IsEyedropping())
501 bDefPointer = false;
502 mpWindow->SetPointer(PointerStyle::RefHand);
505 else if (!mpView->IsAction())
507 SdrObject* pObj = nullptr;
508 SdrPageView* pPV = nullptr;
509 SdrViewEvent aVEvt;
510 SdrHitKind eHit = SdrHitKind::NONE;
511 SdrDragMode eDragMode = mpView->GetDragMode();
513 if (pMEvt)
515 eHit = mpView->PickAnything(*pMEvt, SdrMouseEventKind::MOVE, aVEvt);
518 if ((eDragMode == SdrDragMode::Rotate) && (eHit == SdrHitKind::MarkedObject))
520 // The goal of this request is show always the rotation arrow for 3D-objects at rotation mode
521 // Independent of the settings at Tools->Options->Draw "Objects always moveable"
522 // 2D-objects acquit in another way. Otherwise, the rotation of 3d-objects around any axes
523 // wouldn't be possible per default.
524 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
525 SdrObject* pObject = rMarkList.GetMark(0)->GetMarkedSdrObj();
526 if ((dynamic_cast<const E3dObject* >(pObject) != nullptr) && (rMarkList.GetMarkCount() == 1))
528 mpWindow->SetPointer(PointerStyle::Rotate);
529 bDefPointer = false; // Otherwise it'll be called Joe's routine and the mousepointer will reconfigurate again
533 if (eHit == SdrHitKind::NONE)
535 // found nothing -> look after at the masterpage
536 pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
538 else if (eHit == SdrHitKind::UnmarkedObject)
540 pObj = aVEvt.pObj;
542 else if (eHit == SdrHitKind::TextEditObj && dynamic_cast< const FuSelection *>( this ) != nullptr)
544 sal_uInt16 nSdrObjKind = aVEvt.pObj->GetObjIdentifier();
546 if ( nSdrObjKind != OBJ_TEXT &&
547 nSdrObjKind != OBJ_TITLETEXT &&
548 nSdrObjKind != OBJ_OUTLINETEXT &&
549 aVEvt.pObj->IsEmptyPresObj() )
551 pObj = nullptr;
552 bDefPointer = false;
553 mpWindow->SetPointer(PointerStyle::Arrow);
557 if (pObj && pMEvt && !pMEvt->IsMod2() && dynamic_cast< const FuSelection *>( this ) != nullptr)
559 // test for animation or ImageMap
560 bDefPointer = !SetPointer(pObj, aPnt);
562 if (bDefPointer && (dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr || dynamic_cast< const E3dScene* >(pObj) != nullptr))
564 // take a glance into the group
565 pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
566 if (pObj)
567 bDefPointer = !SetPointer(pObj, aPnt);
573 if (bDefPointer)
575 mpWindow->SetPointer(mpView->GetPreferredPointer(
576 aPnt, mpWindow, nModifier, bLeftDown));
581 * Set cursor for animation or imagemap
583 bool FuDraw::SetPointer(SdrObject* pObj, const Point& rPos)
585 bool bSet = false;
587 bool bAnimationInfo = dynamic_cast< const GraphicDocShell *>( mpDocSh ) == nullptr &&
588 SdDrawDocument::GetAnimationInfo(pObj);
590 bool bImageMapInfo = false;
592 if (!bAnimationInfo)
593 bImageMapInfo = SdDrawDocument::GetIMapInfo(pObj) != nullptr;
595 if (bAnimationInfo || bImageMapInfo)
597 const SdrLayerIDSet* pVisiLayer = &mpView->GetSdrPageView()->GetVisibleLayers();
598 sal_uInt16 nHitLog(sal_uInt16 (mpWindow->PixelToLogic(Size(HITPIX,0)).Width()));
599 long n2HitLog(nHitLog * 2);
600 Point aHitPosR(rPos);
601 Point aHitPosL(rPos);
602 Point aHitPosT(rPos);
603 Point aHitPosB(rPos);
605 aHitPosR.AdjustX(n2HitLog );
606 aHitPosL.AdjustX( -n2HitLog );
607 aHitPosT.AdjustY(n2HitLog );
608 aHitPosB.AdjustY( -n2HitLog );
610 if ( !pObj->IsClosedObj() ||
611 ( SdrObjectPrimitiveHit(*pObj, aHitPosR, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, false) &&
612 SdrObjectPrimitiveHit(*pObj, aHitPosL, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, false) &&
613 SdrObjectPrimitiveHit(*pObj, aHitPosT, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, false) &&
614 SdrObjectPrimitiveHit(*pObj, aHitPosB, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, false)))
616 /**********************************************************
617 * hit inside the object (without margin) or open object
618 ********************************************************/
620 if (bAnimationInfo)
622 /******************************************************
623 * Click-Action
624 ******************************************************/
625 SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo(pObj);
627 if(( dynamic_cast< const DrawView *>( mpView ) != nullptr &&
628 (pInfo->meClickAction == presentation::ClickAction_BOOKMARK ||
629 pInfo->meClickAction == presentation::ClickAction_DOCUMENT ||
630 pInfo->meClickAction == presentation::ClickAction_PREVPAGE ||
631 pInfo->meClickAction == presentation::ClickAction_NEXTPAGE ||
632 pInfo->meClickAction == presentation::ClickAction_FIRSTPAGE ||
633 pInfo->meClickAction == presentation::ClickAction_LASTPAGE ||
634 pInfo->meClickAction == presentation::ClickAction_VERB ||
635 pInfo->meClickAction == presentation::ClickAction_PROGRAM ||
636 pInfo->meClickAction == presentation::ClickAction_MACRO ||
637 pInfo->meClickAction == presentation::ClickAction_SOUND))
639 ( dynamic_cast< const DrawView *>( mpView ) != nullptr &&
640 SlideShow::IsRunning( mpViewShell->GetViewShellBase() ) &&
641 (pInfo->meClickAction == presentation::ClickAction_VANISH ||
642 pInfo->meClickAction == presentation::ClickAction_INVISIBLE ||
643 pInfo->meClickAction == presentation::ClickAction_STOPPRESENTATION ||
644 (pInfo->mbActive &&
645 ( pInfo->meEffect != presentation::AnimationEffect_NONE ||
646 pInfo->meTextEffect != presentation::AnimationEffect_NONE )))))
648 // Animation object
649 bSet = true;
650 mpWindow->SetPointer(PointerStyle::RefHand);
653 else if (bImageMapInfo &&
654 SdDrawDocument::GetHitIMapObject(pObj, rPos))
656 /******************************************************
657 * ImageMap
658 ******************************************************/
659 bSet = true;
660 mpWindow->SetPointer(PointerStyle::RefHand);
665 return bSet;
669 * Response of doubleclick
671 void FuDraw::DoubleClick(const MouseEvent& rMEvt)
673 sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
675 if ( mpView->AreObjectsMarked() )
677 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
679 if (rMarkList.GetMarkCount() == 1)
681 SdrMark* pMark = rMarkList.GetMark(0);
682 SdrObject* pObj = pMark->GetMarkedSdrObj();
684 SdrInventor nInv = pObj->GetObjInventor();
685 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
687 if (nInv == SdrInventor::Default && nSdrObjKind == OBJ_OLE2)
689 DrawDocShell* pDocSh = mpDoc->GetDocSh();
691 if ( !pDocSh->IsUIActive() )
693 /**********************************************************
694 * activate OLE-object
695 **********************************************************/
696 mpViewShell->ActivateObject( static_cast<SdrOle2Obj*>(pObj), 0);
699 else if (nInv == SdrInventor::Default && nSdrObjKind == OBJ_GRAF && pObj->IsEmptyPresObj() )
701 mpViewShell->GetViewFrame()->
702 GetDispatcher()->Execute( SID_INSERT_GRAPHIC,
703 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
705 else if ( ( dynamic_cast< const SdrTextObj *>( pObj ) != nullptr || dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr ) &&
706 !SD_MOD()->GetWaterCan() &&
707 mpViewShell->GetFrameView()->IsDoubleClickTextEdit() &&
708 !mpDocSh->IsReadOnly())
710 SfxUInt16Item aItem(SID_TEXTEDIT, 2);
711 mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(
712 SID_TEXTEDIT,
713 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
714 { &aItem });
716 else if (nInv == SdrInventor::Default && nSdrObjKind == OBJ_GRUP)
718 // hit group -> select subobject
719 mpView->UnMarkAll();
720 mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift(), true);
724 else
725 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
728 bool FuDraw::RequestHelp(const HelpEvent& rHEvt)
730 bool bReturn = false;
732 if (Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled())
734 SdrViewEvent aVEvt;
736 MouseEvent aMEvt(mpWindow->GetPointerPosPixel(), 1, MouseEventModifiers::NONE, MOUSE_LEFT);
738 SdrHitKind eHit = mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
740 SdrObject* pObj = aVEvt.pObj;
742 if (eHit != SdrHitKind::NONE && pObj != nullptr)
744 Point aPosPixel = rHEvt.GetMousePosPixel();
746 bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
748 if (!bReturn && (dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr || dynamic_cast< const E3dScene* >(pObj) != nullptr))
750 // take a glance into the group
751 SdrPageView* pPV = nullptr;
753 Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(aPosPixel)));
755 pObj = mpView->PickObj(aPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
756 if (pObj)
757 bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
762 if (!bReturn)
764 bReturn = FuPoor::RequestHelp(rHEvt);
767 if (!bReturn)
768 bReturn = mpView->RequestHelp(rHEvt);
770 return bReturn;
773 bool FuDraw::SetHelpText(SdrObject* pObj, const Point& rPosPixel, const SdrViewEvent& rVEvt)
775 bool bSet = false;
776 OUString aHelpText;
777 Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(rPosPixel)));
779 // URL for IMapObject underneath pointer is help text
780 if ( SdDrawDocument::GetIMapInfo(pObj) )
782 IMapObject* pIMapObj = SdDrawDocument::GetHitIMapObject(pObj, aPos);
784 if ( pIMapObj )
786 // show name
787 aHelpText = pIMapObj->GetAltText();
789 if (aHelpText.isEmpty())
791 // show url if no name is available
792 aHelpText = INetURLObject::decode( pIMapObj->GetURL(), INetURLObject::DecodeMechanism::WithCharset );
796 else if (rVEvt.pURLField)
798 /**************************************************************
799 * URL-Field
800 **************************************************************/
801 OUString aURL = INetURLObject::decode(rVEvt.pURLField->GetURL(), INetURLObject::DecodeMechanism::WithCharset);
803 SvtSecurityOptions aSecOpt;
804 if (aSecOpt.IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink))
806 // Hint about Ctrl-click to open hyperlink, but need to detect "Ctrl" key for MacOs
807 vcl::KeyCode aCode(KEY_SPACE);
808 vcl::KeyCode aModifiedCode(KEY_SPACE, KEY_MOD1);
809 OUString aModStr(aModifiedCode.GetName());
810 aModStr = aModStr.replaceFirst(aCode.GetName(), "");
811 aModStr = aModStr.replaceAll("+", "");
813 OUString aCtrlClickHlinkStr = SdResId(STR_CTRLCLICKHYPERLINK);
815 aCtrlClickHlinkStr = aCtrlClickHlinkStr.replaceAll("%s", aModStr);
817 aHelpText = aCtrlClickHlinkStr + aURL;
819 else
821 // Hint about just clicking hyperlink
822 aHelpText = SdResId(STR_CLICKHYPERLINK) + aURL;
825 else if (dynamic_cast< GraphicDocShell *>( mpDocSh ) == nullptr && SdDrawDocument::GetAnimationInfo(pObj))
827 SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo(pObj);
829 switch (pInfo->meClickAction)
831 case presentation::ClickAction_PREVPAGE:
833 // jump to the prior page
834 aHelpText = SdResId(STR_CLICK_ACTION_PREVPAGE);
836 break;
838 case presentation::ClickAction_NEXTPAGE:
840 // jump to the next page
841 aHelpText = SdResId(STR_CLICK_ACTION_NEXTPAGE);
843 break;
845 case presentation::ClickAction_FIRSTPAGE:
847 // jump to the first page
848 aHelpText = SdResId(STR_CLICK_ACTION_FIRSTPAGE);
850 break;
852 case presentation::ClickAction_LASTPAGE:
854 // jump to the last page
855 aHelpText = SdResId(STR_CLICK_ACTION_LASTPAGE);
857 break;
859 case presentation::ClickAction_BOOKMARK:
861 // jump to object/page
862 aHelpText = SdResId(STR_CLICK_ACTION_BOOKMARK)
863 + ": "
864 + INetURLObject::decode( pInfo->GetBookmark(), INetURLObject::DecodeMechanism::WithCharset );
866 break;
868 case presentation::ClickAction_DOCUMENT:
870 // jump to document (object/page)
871 aHelpText = SdResId(STR_CLICK_ACTION_DOCUMENT)
872 + ": "
873 + INetURLObject::decode( pInfo->GetBookmark(), INetURLObject::DecodeMechanism::WithCharset );
875 break;
877 case presentation::ClickAction_PROGRAM:
879 // execute program
880 aHelpText = SdResId(STR_CLICK_ACTION_PROGRAM)
881 + ": "
882 + INetURLObject::decode( pInfo->GetBookmark(), INetURLObject::DecodeMechanism::WithCharset );
884 break;
886 case presentation::ClickAction_MACRO:
888 // execute program
889 aHelpText = SdResId(STR_CLICK_ACTION_MACRO) + ": ";
891 if ( SfxApplication::IsXScriptURL( pInfo->GetBookmark() ) )
893 aHelpText += pInfo->GetBookmark();
895 else
897 OUString sBookmark( pInfo->GetBookmark() );
898 sal_Int32 nIdx{ 0 };
899 const OUString s0{ sBookmark.getToken( 0, '.', nIdx ) };
900 const OUString s1{ sBookmark.getToken( 0, '.', nIdx ) };
901 const OUString s2{ sBookmark.getToken( 0, '.', nIdx ) };
902 aHelpText += s2 + "." + s1 + "." + s0;
905 break;
907 case presentation::ClickAction_SOUND:
909 // play-back sound
910 aHelpText = SdResId(STR_CLICK_ACTION_SOUND);
912 break;
914 case presentation::ClickAction_VERB:
916 // execute OLE-verb
917 aHelpText = SdResId(STR_CLICK_ACTION_VERB);
919 break;
921 case presentation::ClickAction_STOPPRESENTATION:
923 // quit presentation
924 aHelpText = SdResId(STR_CLICK_ACTION_STOPPRESENTATION);
926 break;
927 default:
928 break;
932 if (!aHelpText.isEmpty())
934 bSet = true;
935 ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(pObj->GetLogicRect());
936 ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()),
937 mpWindow->OutputToScreenPixel(aLogicPix.BottomRight()));
939 if (Help::IsBalloonHelpEnabled())
940 Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rPosPixel, aScreenRect, aHelpText);
941 else if (Help::IsQuickHelpEnabled())
942 Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText);
945 return bSet;
948 /** is called when the current function should be aborted. <p>
949 This is used when a function gets a KEY_ESCAPE but can also
950 be called directly.
952 @returns true if a active function was aborted
954 bool FuDraw::cancel()
956 bool bReturn = false;
958 if ( mpView->IsAction() )
960 mpView->BrkAction();
961 bReturn = true;
963 else if ( mpView->IsTextEdit() )
965 mpView->SdrEndTextEdit();
966 bReturn = true;
968 SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings();
969 rBindings.Invalidate( SID_DEC_INDENT );
970 rBindings.Invalidate( SID_INC_INDENT );
971 rBindings.Invalidate( SID_PARASPACE_INCREASE );
972 rBindings.Invalidate( SID_PARASPACE_DECREASE );
974 else if ( mpView->AreObjectsMarked() )
976 const SdrHdlList& rHdlList = mpView->GetHdlList();
977 SdrHdl* pHdl = rHdlList.GetFocusHdl();
979 if(pHdl)
981 const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl();
983 else
985 mpView->UnmarkAll();
988 // Switch to FuSelect.
989 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
990 SID_OBJECT_SELECT,
991 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
993 bReturn = true;
996 return bReturn;
999 } // end of namespace sd
1001 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */