tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / sd / source / ui / func / fudraw.cxx
blob28e1bf7e96f3789c08c59372198113e1950bfc3d
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/ptrstyle.hxx>
24 #include <editeng/flditem.hxx>
25 #include <svx/svdogrp.hxx>
26 #include <tools/urlobj.hxx>
27 #include <vcl/help.hxx>
28 #include <svx/bmpmask.hxx>
29 #include <svx/svdotext.hxx>
30 #include <svx/ImageMapInfo.hxx>
31 #include <sfx2/dispatch.hxx>
32 #include <sfx2/bindings.hxx>
33 #include <sfx2/sfxhelp.hxx>
34 #include <svx/svdpagv.hxx>
35 #include <vcl/imapobj.hxx>
36 #include <svx/svxids.hrc>
37 #include <svx/obj3d.hxx>
38 #include <svx/scene3d.hxx>
39 #include <sfx2/viewfrm.hxx>
41 #include <strings.hrc>
44 #include <sdmod.hxx>
45 #include <fudraw.hxx>
46 #include <ViewShell.hxx>
47 #include <FrameView.hxx>
48 #include <View.hxx>
49 #include <Window.hxx>
50 #include <drawdoc.hxx>
51 #include <DrawDocShell.hxx>
52 #include <sdresid.hxx>
53 #include <fusel.hxx>
54 #include <vcl/weld.hxx>
55 #include <svx/sdrhittesthelper.hxx>
57 using namespace ::com::sun::star;
59 namespace sd {
62 /**
63 * Base-class for all drawmodul-specific functions
65 FuDraw::FuDraw(ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView,
66 SdDrawDocument* pDoc, SfxRequest& rReq)
67 : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
68 , aNewPointer(PointerStyle::Arrow)
69 , aOldPointer(PointerStyle::Arrow)
70 , bMBDown(false)
71 , bDragHelpLine(false)
72 , nHelpLine(0)
73 , bPermanent(false)
77 FuDraw::~FuDraw()
79 mpView->BrkAction();
83 /**
84 * Code shared by MouseButtonDown and MouseMove
86 void FuDraw::DoModifiers(const MouseEvent& rMEvt, bool bSnapModPressed)
88 FrameView* pFrameView = mpViewShell->GetFrameView();
89 bool bGridSnap = pFrameView->IsGridSnap();
90 bGridSnap = (bSnapModPressed != bGridSnap);
92 if (mpView->IsGridSnap() != bGridSnap)
93 mpView->SetGridSnap(bGridSnap);
95 bool bBordSnap = pFrameView->IsBordSnap();
96 bBordSnap = (bSnapModPressed != bBordSnap);
98 if (mpView->IsBordSnap() != bBordSnap)
99 mpView->SetBordSnap(bBordSnap);
101 bool bHlplSnap = pFrameView->IsHlplSnap();
102 bHlplSnap = (bSnapModPressed != bHlplSnap);
104 if (mpView->IsHlplSnap() != bHlplSnap)
105 mpView->SetHlplSnap(bHlplSnap);
107 bool bOFrmSnap = pFrameView->IsOFrmSnap();
108 bOFrmSnap = (bSnapModPressed != bOFrmSnap);
110 if (mpView->IsOFrmSnap() != bOFrmSnap)
111 mpView->SetOFrmSnap(bOFrmSnap);
113 bool bOPntSnap = pFrameView->IsOPntSnap();
114 bOPntSnap = (bSnapModPressed != bOPntSnap);
116 if (mpView->IsOPntSnap() != bOPntSnap)
117 mpView->SetOPntSnap(bOPntSnap);
119 bool bOConSnap = pFrameView->IsOConSnap();
120 bOConSnap = (bSnapModPressed != bOConSnap);
122 if (mpView->IsOConSnap() != bOConSnap)
123 mpView->SetOConSnap(bOConSnap);
125 bool bAngleSnap = rMEvt.IsShift() == !pFrameView->IsAngleSnapEnabled();
127 if (mpView->IsAngleSnapEnabled() != bAngleSnap)
128 mpView->SetAngleSnapEnabled(bAngleSnap);
130 bool bCenter = rMEvt.IsMod2();
132 if ( mpView->IsCreate1stPointAsCenter() != bCenter ||
133 mpView->IsResizeAtCenter() != bCenter )
135 mpView->SetCreate1stPointAsCenter(bCenter);
136 mpView->SetResizeAtCenter(bCenter);
141 bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt)
143 // remember button state for creation of own MouseEvents
144 SetMouseButtonCode(rMEvt.GetButtons());
146 bool bReturn = false;
147 bDragHelpLine = false;
148 aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
150 if ( rMEvt.IsLeft() )
152 FrameView* pFrameView = mpViewShell->GetFrameView();
154 bool bOrtho = false;
156 bool bRestricted = true;
158 if (mpView->IsDragObj())
160 // object is dragged (move, resize,...)
161 const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
163 if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
165 // Move
166 bRestricted = false;
170 // #i33136#
171 if(bRestricted && doConstructOrthogonal())
173 // Restrict movement:
174 // rectangle->square, ellipse->circle, etc.
175 bOrtho = !rMEvt.IsShift();
177 else
179 bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
181 if (!mpView->IsSnapEnabled())
182 mpView->SetSnapEnabled(true);
184 bool bSnapModPressed = rMEvt.IsMod1();
185 if (mpView->IsOrtho() != bOrtho)
186 mpView->SetOrtho(bOrtho);
188 DoModifiers(rMEvt, bSnapModPressed);
190 SdrPageView* pPV = nullptr;
191 sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
193 // look only for HelpLines when they are visible (!)
194 bool bHelpLine(false);
195 if(mpView->IsHlplVisible())
196 bHelpLine = mpView->PickHelpLine(aMDPos, nHitLog, *mpWindow->GetOutDev(), nHelpLine, pPV);
197 bool bHitHdl = (mpView->PickHandle(aMDPos) != nullptr);
199 if ( bHelpLine
200 && !mpView->IsCreateObj()
201 && ((mpView->GetEditMode() == SdrViewEditMode::Edit && !bHitHdl) || (rMEvt.IsShift() && bSnapModPressed)) )
203 mpWindow->CaptureMouse();
204 mpView->BegDragHelpLine(nHelpLine, pPV);
205 bDragHelpLine = mpView->IsDragHelpLine();
206 bReturn = true;
209 ForcePointer(&rMEvt);
211 return bReturn;
214 bool FuDraw::MouseMove(const MouseEvent& rMEvt)
216 FrameView* pFrameView = mpViewShell->GetFrameView();
217 Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
219 bool bOrtho = false;
220 bool bRestricted = true;
222 if (mpView->IsDragObj())
224 // object is dragged (move, resize, ...)
225 const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
227 if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
229 // Move
230 bRestricted = false;
234 if (mpView->IsAction())
236 // #i33136# and fdo#88339
237 if(bRestricted && doConstructOrthogonal())
239 // Scale proportionally by default:
240 // rectangle->square, ellipse->circle, images, etc.
241 bOrtho = !rMEvt.IsShift();
243 else
245 bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
248 bool bSnapModPressed = rMEvt.IsMod2();
249 mpView->SetDragWithCopy(rMEvt.IsMod1() && pFrameView->IsDragWithCopy());
251 if (mpView->IsOrtho() != bOrtho)
252 mpView->SetOrtho(bOrtho);
253 DoModifiers(rMEvt, bSnapModPressed);
256 if ( mpView->IsDragHelpLine() )
257 mpView->MovDragHelpLine(aPos);
260 bool bReturn = mpView->MouseMove(rMEvt, mpWindow->GetOutDev());
262 if (mpView->IsAction())
264 // Because the flag set back if necessary in MouseMove
265 if (mpView->IsOrtho() != bOrtho)
266 mpView->SetOrtho(bOrtho);
269 ForcePointer(&rMEvt);
271 return bReturn;
274 bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt)
276 if (mpView && mpView->IsDragHelpLine())
277 mpView->EndDragHelpLine();
279 if ( bDragHelpLine )
281 ::tools::Rectangle aOutputArea(Point(0,0), mpWindow->GetOutputSizePixel());
283 if (mpView && !aOutputArea.Contains(rMEvt.GetPosPixel()))
284 mpView->GetSdrPageView()->DeleteHelpLine(nHelpLine);
286 mpWindow->ReleaseMouse();
289 if (mpView)
291 FrameView* pFrameView = mpViewShell->GetFrameView();
292 mpView->SetOrtho( pFrameView->IsOrtho() );
293 mpView->SetAngleSnapEnabled( pFrameView->IsAngleSnapEnabled() );
294 mpView->SetSnapEnabled(true);
295 mpView->SetCreate1stPointAsCenter(false);
296 mpView->SetResizeAtCenter(false);
297 mpView->SetDragWithCopy(pFrameView->IsDragWithCopy());
298 mpView->SetGridSnap(pFrameView->IsGridSnap());
299 mpView->SetBordSnap(pFrameView->IsBordSnap());
300 mpView->SetHlplSnap(pFrameView->IsHlplSnap());
301 mpView->SetOFrmSnap(pFrameView->IsOFrmSnap());
302 mpView->SetOPntSnap(pFrameView->IsOPntSnap());
303 mpView->SetOConSnap(pFrameView->IsOConSnap());
306 bIsInDragMode = false;
307 ForcePointer(&rMEvt);
308 FuPoor::MouseButtonUp(rMEvt);
310 return false;
314 * Process keyboard input
315 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
317 bool FuDraw::KeyInput(const KeyEvent& rKEvt)
319 bool bReturn = false;
320 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
322 switch ( rKEvt.GetKeyCode().GetCode() )
324 case KEY_ESCAPE:
326 bReturn = FuDraw::cancel();
328 break;
330 case KEY_DELETE:
331 case KEY_BACKSPACE:
333 if (!mpDocSh->IsReadOnly())
335 if (mpView->IsPresObjSelected(false, true, false, true))
337 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(),
338 VclMessageType::Info, VclButtonsType::Ok,
339 SdResId(STR_ACTION_NOTPOSSIBLE)));
340 xInfoBox->run();
342 else
344 // wait-mousepointer while deleting object
345 weld::WaitObject aWait(mpViewShell->GetFrameWeld());
346 // delete object
347 mpView->DeleteMarked();
350 bReturn = true;
352 break;
354 case KEY_TAB:
356 vcl::KeyCode aCode = rKEvt.GetKeyCode();
358 if ( !aCode.IsMod1() && !aCode.IsMod2() )
360 // Moved next line which was a bugfix itself into
361 // the scope which really does the object selection travel
362 // and thus is allowed to call SelectionHasChanged().
364 // Switch to FuSelect.
365 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
366 SID_OBJECT_SELECT,
367 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
369 // changeover to the next object
370 if(!mpView->MarkNextObj( !aCode.IsShift() ))
372 //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj().
373 if ( mpView->HasMultipleMarkableObjects() && rMarkList.GetMarkCount() != 0 )
375 // No next object: go over open end and get first from
376 // the other side
377 mpView->UnmarkAllObj();
378 mpView->MarkNextObj(!aCode.IsShift());
382 if(rMarkList.GetMarkCount() != 0)
383 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
385 bReturn = true;
388 break;
390 case KEY_END:
392 vcl::KeyCode aCode = rKEvt.GetKeyCode();
394 if ( aCode.IsMod1() )
396 // mark last object
397 mpView->UnmarkAllObj();
398 mpView->MarkNextObj();
400 if(rMarkList.GetMarkCount() != 0)
401 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
403 bReturn = true;
406 break;
408 case KEY_HOME:
410 vcl::KeyCode aCode = rKEvt.GetKeyCode();
412 if ( aCode.IsMod1() )
414 // mark first object
415 mpView->UnmarkAllObj();
416 mpView->MarkNextObj(true);
418 if(rMarkList.GetMarkCount() != 0)
419 mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
421 bReturn = true;
424 break;
426 default:
427 break;
430 if (!bReturn)
432 bReturn = FuPoor::KeyInput(rKEvt);
434 else
436 mpWindow->ReleaseMouse();
439 return bReturn;
442 void FuDraw::Activate()
444 FuPoor::Activate();
445 ForcePointer();
449 * Toggle mouse-pointer
451 void FuDraw::ForcePointer(const MouseEvent* pMEvt)
453 Point aPnt;
454 sal_uInt16 nModifier = 0;
455 bool bLeftDown = false;
456 bool bDefPointer = true;
458 if (pMEvt)
460 aPnt = mpWindow->PixelToLogic(pMEvt->GetPosPixel());
461 nModifier = pMEvt->GetModifier();
462 bLeftDown = pMEvt->IsLeft();
464 else
466 aPnt = mpWindow->PixelToLogic(mpWindow->GetPointerPosPixel());
469 if (mpView->IsDragObj())
471 if (SdModule::get()->GetWaterCan() && !mpView->PickHandle(aPnt))
473 // water can mode
474 bDefPointer = false;
475 mpWindow->SetPointer(PointerStyle::Fill);
478 else
480 SdrHdl* pHdl = mpView->PickHandle(aPnt);
482 if (SdModule::get()->GetWaterCan() && !pHdl)
484 // water can mode
485 bDefPointer = false;
486 mpWindow->SetPointer(PointerStyle::Fill);
488 else if (!pHdl &&
489 mpViewShell->GetViewFrame()->HasChildWindow(SvxBmpMaskChildWindow::GetChildWindowId()))
491 // pipette mode
492 SfxChildWindow* pWnd = mpViewShell->GetViewFrame()->GetChildWindow(SvxBmpMaskChildWindow::GetChildWindowId());
493 SvxBmpMask* pMask = pWnd ? static_cast<SvxBmpMask*>(pWnd->GetWindow()) : nullptr;
494 if (pMask && pMask->IsEyedropping())
496 bDefPointer = false;
497 mpWindow->SetPointer(PointerStyle::RefHand);
500 else if (!mpView->IsAction())
502 SdrObject* pObj = nullptr;
503 SdrPageView* pPV = nullptr;
504 SdrViewEvent aVEvt;
505 SdrHitKind eHit = SdrHitKind::NONE;
506 SdrDragMode eDragMode = mpView->GetDragMode();
508 if (pMEvt)
510 eHit = mpView->PickAnything(*pMEvt, SdrMouseEventKind::MOVE, aVEvt);
513 if ((eDragMode == SdrDragMode::Rotate) && (eHit == SdrHitKind::MarkedObject))
515 // The goal of this request is show always the rotation arrow for 3D-objects at rotation mode
516 // Independent of the settings at Tools->Options->Draw "Objects always moveable"
517 // 2D-objects acquit in another way. Otherwise, the rotation of 3d-objects around any axes
518 // wouldn't be possible per default.
519 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
520 SdrObject* pObject = rMarkList.GetMark(0)->GetMarkedSdrObj();
521 if (DynCastE3dObject(pObject) && (rMarkList.GetMarkCount() == 1))
523 mpWindow->SetPointer(PointerStyle::Rotate);
524 bDefPointer = false; // Otherwise it'll be called Joe's routine and the mousepointer will reconfigurate again
528 if (eHit == SdrHitKind::NONE)
530 // found nothing -> look after at the masterpage
531 pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
533 else if (eHit == SdrHitKind::UnmarkedObject)
535 pObj = aVEvt.mpObj;
537 else if (eHit == SdrHitKind::TextEditObj && dynamic_cast< const FuSelection *>( this ) != nullptr)
539 SdrObjKind nSdrObjKind = aVEvt.mpObj->GetObjIdentifier();
541 if ( nSdrObjKind != SdrObjKind::Text &&
542 nSdrObjKind != SdrObjKind::TitleText &&
543 nSdrObjKind != SdrObjKind::OutlineText &&
544 aVEvt.mpObj->IsEmptyPresObj() )
546 pObj = nullptr;
547 bDefPointer = false;
548 mpWindow->SetPointer(PointerStyle::Arrow);
552 if (pObj && pMEvt && !pMEvt->IsMod2()
553 && dynamic_cast<const FuSelection*>(this) != nullptr)
555 // test for ImageMap
556 bDefPointer = !SetPointer(pObj, aPnt);
558 if (bDefPointer
559 && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr
560 || DynCastE3dScene(pObj)))
562 // take a glance into the group
563 pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV,
564 SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
565 if (pObj)
566 bDefPointer = !SetPointer(pObj, aPnt);
572 if (bDefPointer)
574 mpWindow->SetPointer(mpView->GetPreferredPointer(
575 aPnt, mpWindow->GetOutDev(), nModifier, bLeftDown));
580 * Set cursor to pointer when in clickable area of an ImageMap
582 * @return True when pointer was set
584 bool FuDraw::SetPointer(const SdrObject* pObj, const Point& rPos)
586 bool bImageMapInfo = SvxIMapInfo::GetIMapInfo(pObj) != nullptr;
588 if (!bImageMapInfo)
589 return false;
591 const SdrLayerIDSet* pVisiLayer = &mpView->GetSdrPageView()->GetVisibleLayers();
592 double fHitLog(mpWindow->PixelToLogic(Size(HITPIX, 0)).Width());
593 ::tools::Long n2HitLog(fHitLog * 2);
594 Point aHitPosR(rPos);
595 Point aHitPosL(rPos);
596 Point aHitPosT(rPos);
597 Point aHitPosB(rPos);
599 aHitPosR.AdjustX(n2HitLog);
600 aHitPosL.AdjustX(-n2HitLog);
601 aHitPosT.AdjustY(n2HitLog);
602 aHitPosB.AdjustY(-n2HitLog);
604 if (!pObj->IsClosedObj()
605 || (SdrObjectPrimitiveHit(*pObj, aHitPosR, {fHitLog, fHitLog}, *mpView->GetSdrPageView(), pVisiLayer,
606 false)
607 && SdrObjectPrimitiveHit(*pObj, aHitPosL, {fHitLog, fHitLog}, *mpView->GetSdrPageView(),
608 pVisiLayer, false)
609 && SdrObjectPrimitiveHit(*pObj, aHitPosT, {fHitLog, fHitLog}, *mpView->GetSdrPageView(),
610 pVisiLayer, false)
611 && SdrObjectPrimitiveHit(*pObj, aHitPosB, {fHitLog, fHitLog}, *mpView->GetSdrPageView(),
612 pVisiLayer, false)))
614 // hit inside the object (without margin) or open object
615 if (SvxIMapInfo::GetHitIMapObject(pObj, rPos))
617 mpWindow->SetPointer(PointerStyle::RefHand);
618 return true;
622 return false;
626 * Response of doubleclick
628 void FuDraw::DoubleClick(const MouseEvent& rMEvt)
630 sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
632 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
633 if ( rMarkList.GetMarkCount() != 0 )
635 if (rMarkList.GetMarkCount() == 1)
637 SdrMark* pMark = rMarkList.GetMark(0);
638 SdrObject* pObj = pMark->GetMarkedSdrObj();
640 SdrInventor nInv = pObj->GetObjInventor();
641 SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
643 if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::OLE2
644 && !mpDocSh->IsReadOnly())
646 // activate OLE-object
647 SfxInt16Item aItem(SID_OBJECT, 0);
648 mpViewShell->GetViewFrame()->
649 GetDispatcher()->ExecuteList(SID_OBJECT,
650 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
651 { &aItem });
653 else if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::Graphic
654 && pObj->IsEmptyPresObj() && !mpDocSh->IsReadOnly())
656 mpViewShell->GetViewFrame()->
657 GetDispatcher()->Execute( SID_INSERT_GRAPHIC,
658 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
660 else if ( ( DynCastSdrTextObj( pObj ) != nullptr || dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr ) &&
661 !SdModule::get()->GetWaterCan() &&
662 mpViewShell->GetFrameView()->IsDoubleClickTextEdit() &&
663 !mpDocSh->IsReadOnly())
665 SfxUInt16Item aItem(SID_TEXTEDIT, 2);
666 mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(
667 SID_TEXTEDIT,
668 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
669 { &aItem });
671 else if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::Group)
673 // hit group -> select subobject
674 mpView->UnMarkAll();
675 mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift(), true);
679 else
680 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
683 bool FuDraw::RequestHelp(const HelpEvent& rHEvt)
685 bool bReturn = false;
687 if (Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled())
689 SdrViewEvent aVEvt;
691 MouseEvent aMEvt(mpWindow->GetPointerPosPixel(), 1, MouseEventModifiers::NONE, MOUSE_LEFT);
693 SdrHitKind eHit = mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
695 SdrObject* pObj = aVEvt.mpObj;
697 if (eHit != SdrHitKind::NONE && pObj != nullptr)
699 Point aPosPixel = rHEvt.GetMousePosPixel();
701 bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
703 if (!bReturn && (dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr || DynCastE3dScene(pObj)))
705 // take a glance into the group
706 SdrPageView* pPV = nullptr;
708 Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(aPosPixel)));
710 pObj = mpView->PickObj(aPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
711 if (pObj)
712 bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
717 if (!bReturn)
719 bReturn = FuPoor::RequestHelp(rHEvt);
722 if (!bReturn)
723 bReturn = mpView->RequestHelp(rHEvt);
725 return bReturn;
728 bool FuDraw::SetHelpText(const SdrObject* pObj, const Point& rPosPixel, const SdrViewEvent& rVEvt)
730 OUString aHelpText;
731 Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(rPosPixel)));
732 IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(pObj, aPos);
734 if (!rVEvt.mpURLField && !pIMapObj)
735 return false;
737 OUString aURL;
738 if (rVEvt.mpURLField)
739 aURL = INetURLObject::decode(rVEvt.mpURLField->GetURL(),
740 INetURLObject::DecodeMechanism::WithCharset);
741 else if (pIMapObj)
743 aURL = pIMapObj->GetAltText() +
744 " (" +
745 INetURLObject::decode(pIMapObj->GetURL(),
746 INetURLObject::DecodeMechanism::WithCharset) +
747 ")";
749 else
750 return false;
752 aHelpText = SfxHelp::GetURLHelpText(aURL);
754 if (aHelpText.isEmpty())
755 return false;
757 ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(pObj->GetLogicRect());
758 ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()),
759 mpWindow->OutputToScreenPixel(aLogicPix.BottomRight()));
761 if (Help::IsBalloonHelpEnabled())
762 Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rPosPixel, aScreenRect, aHelpText);
763 else if (Help::IsQuickHelpEnabled())
764 Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText);
766 return true;
769 /** is called when the current function should be aborted. <p>
770 This is used when a function gets a KEY_ESCAPE but can also
771 be called directly.
773 @returns true if an active function was aborted
775 bool FuDraw::cancel()
777 bool bReturn = false;
778 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
780 if ( mpView->IsAction() )
782 mpView->BrkAction();
783 bReturn = true;
785 else if ( mpView->IsTextEdit() )
787 mpView->SdrEndTextEdit();
788 bReturn = true;
790 SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings();
791 rBindings.Invalidate( SID_DEC_INDENT );
792 rBindings.Invalidate( SID_INC_INDENT );
793 rBindings.Invalidate( SID_PARASPACE_INCREASE );
794 rBindings.Invalidate( SID_PARASPACE_DECREASE );
796 else if ( rMarkList.GetMarkCount() != 0 )
798 const SdrHdlList& rHdlList = mpView->GetHdlList();
799 SdrHdl* pHdl = rHdlList.GetFocusHdl();
801 if(pHdl)
803 const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl();
805 else
807 mpView->UnmarkAll();
810 // Switch to FuSelect.
811 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
812 SID_OBJECT_SELECT,
813 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
815 bReturn = true;
818 return bReturn;
821 } // end of namespace sd
823 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */