xref: /core/sd/source/ui/func/fudraw.cxx (revision 5da4acd4)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
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>
40 
41 #include <strings.hrc>
42 
43 
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>
56 
57 using namespace ::com::sun::star;
58 
59 namespace sd {
60 
61 
62 /**
63  * Base-class for all drawmodul-specific functions
64  */
FuDraw(ViewShell * pViewSh,::sd::Window * pWin,::sd::View * pView,SdDrawDocument * pDoc,SfxRequest & rReq)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)
74 {
75 }
76 
~FuDraw()77 FuDraw::~FuDraw()
78 {
79     mpView->BrkAction();
80 }
81 
82 
83 /**
84  * Code shared by MouseButtonDown and MouseMove
85  */
DoModifiers(const MouseEvent & rMEvt,bool bSnapModPressed)86 void FuDraw::DoModifiers(const MouseEvent& rMEvt, bool bSnapModPressed)
87 {
88     FrameView* pFrameView = mpViewShell->GetFrameView();
89     bool bGridSnap = pFrameView->IsGridSnap();
90     bGridSnap = (bSnapModPressed != bGridSnap);
91 
92     if (mpView->IsGridSnap() != bGridSnap)
93         mpView->SetGridSnap(bGridSnap);
94 
95     bool bBordSnap = pFrameView->IsBordSnap();
96     bBordSnap = (bSnapModPressed != bBordSnap);
97 
98     if (mpView->IsBordSnap() != bBordSnap)
99         mpView->SetBordSnap(bBordSnap);
100 
101     bool bHlplSnap = pFrameView->IsHlplSnap();
102     bHlplSnap = (bSnapModPressed != bHlplSnap);
103 
104     if (mpView->IsHlplSnap() != bHlplSnap)
105         mpView->SetHlplSnap(bHlplSnap);
106 
107     bool bOFrmSnap = pFrameView->IsOFrmSnap();
108     bOFrmSnap = (bSnapModPressed != bOFrmSnap);
109 
110     if (mpView->IsOFrmSnap() != bOFrmSnap)
111         mpView->SetOFrmSnap(bOFrmSnap);
112 
113     bool bOPntSnap = pFrameView->IsOPntSnap();
114     bOPntSnap = (bSnapModPressed != bOPntSnap);
115 
116     if (mpView->IsOPntSnap() != bOPntSnap)
117         mpView->SetOPntSnap(bOPntSnap);
118 
119     bool bOConSnap = pFrameView->IsOConSnap();
120     bOConSnap = (bSnapModPressed != bOConSnap);
121 
122     if (mpView->IsOConSnap() != bOConSnap)
123         mpView->SetOConSnap(bOConSnap);
124 
125     bool bAngleSnap = rMEvt.IsShift() == !pFrameView->IsAngleSnapEnabled();
126 
127     if (mpView->IsAngleSnapEnabled() != bAngleSnap)
128         mpView->SetAngleSnapEnabled(bAngleSnap);
129 
130     bool bCenter = rMEvt.IsMod2();
131 
132     if ( mpView->IsCreate1stPointAsCenter() != bCenter ||
133          mpView->IsResizeAtCenter() != bCenter )
134     {
135         mpView->SetCreate1stPointAsCenter(bCenter);
136         mpView->SetResizeAtCenter(bCenter);
137     }
138 }
139 
140 
MouseButtonDown(const MouseEvent & rMEvt)141 bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt)
142 {
143     // remember button state for creation of own MouseEvents
144     SetMouseButtonCode(rMEvt.GetButtons());
145 
146     bool bReturn = false;
147     bDragHelpLine = false;
148     aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
149 
150     if ( rMEvt.IsLeft() )
151     {
152         FrameView* pFrameView = mpViewShell->GetFrameView();
153 
154         bool bOrtho = false;
155 
156         bool bRestricted = true;
157 
158         if (mpView->IsDragObj())
159         {
160             // object is dragged (move, resize,...)
161             const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
162 
163             if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
164             {
165                 // Move
166                 bRestricted = false;
167             }
168         }
169 
170         // #i33136#
171         if(bRestricted && doConstructOrthogonal())
172         {
173             // Restrict movement:
174             // rectangle->square, ellipse->circle, etc.
175             bOrtho = !rMEvt.IsShift();
176         }
177         else
178         {
179             bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
180         }
181         if (!mpView->IsSnapEnabled())
182             mpView->SetSnapEnabled(true);
183 
184         bool bSnapModPressed = rMEvt.IsMod1();
185         if (mpView->IsOrtho() != bOrtho)
186             mpView->SetOrtho(bOrtho);
187 
188         DoModifiers(rMEvt, bSnapModPressed);
189 
190         SdrPageView* pPV = nullptr;
191         sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
192 
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);
198 
199         if ( bHelpLine
200             && !mpView->IsCreateObj()
201             && ((mpView->GetEditMode() == SdrViewEditMode::Edit && !bHitHdl) || (rMEvt.IsShift() && bSnapModPressed)) )
202         {
203             mpWindow->CaptureMouse();
204             mpView->BegDragHelpLine(nHelpLine, pPV);
205             bDragHelpLine = mpView->IsDragHelpLine();
206             bReturn = true;
207         }
208     }
209     ForcePointer(&rMEvt);
210 
211     return bReturn;
212 }
213 
MouseMove(const MouseEvent & rMEvt)214 bool FuDraw::MouseMove(const MouseEvent& rMEvt)
215 {
216     FrameView* pFrameView = mpViewShell->GetFrameView();
217     Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
218 
219     bool bOrtho = false;
220     bool bRestricted = true;
221 
222     if (mpView->IsDragObj())
223     {
224         // object is dragged (move, resize, ...)
225         const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
226 
227         if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
228         {
229             // Move
230             bRestricted = false;
231         }
232     }
233 
234     if (mpView->IsAction())
235     {
236         // #i33136# and fdo#88339
237         if(bRestricted && doConstructOrthogonal())
238         {
239             // Scale proportionally by default:
240             // rectangle->square, ellipse->circle, images, etc.
241             bOrtho = !rMEvt.IsShift();
242         }
243         else
244         {
245             bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
246         }
247 
248         bool bSnapModPressed = rMEvt.IsMod2();
249         mpView->SetDragWithCopy(rMEvt.IsMod1() && pFrameView->IsDragWithCopy());
250 
251         if (mpView->IsOrtho() != bOrtho)
252             mpView->SetOrtho(bOrtho);
253         DoModifiers(rMEvt, bSnapModPressed);
254 
255 
256         if ( mpView->IsDragHelpLine() )
257             mpView->MovDragHelpLine(aPos);
258     }
259 
260     bool bReturn = mpView->MouseMove(rMEvt, mpWindow->GetOutDev());
261 
262     if (mpView->IsAction())
263     {
264         // Because the flag set back if necessary in MouseMove
265         if (mpView->IsOrtho() != bOrtho)
266             mpView->SetOrtho(bOrtho);
267     }
268 
269     ForcePointer(&rMEvt);
270 
271     return bReturn;
272 }
273 
MouseButtonUp(const MouseEvent & rMEvt)274 bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt)
275 {
276     if (mpView && mpView->IsDragHelpLine())
277         mpView->EndDragHelpLine();
278 
279     if ( bDragHelpLine )
280     {
281         ::tools::Rectangle aOutputArea(Point(0,0), mpWindow->GetOutputSizePixel());
282 
283         if (mpView && !aOutputArea.Contains(rMEvt.GetPosPixel()))
284             mpView->GetSdrPageView()->DeleteHelpLine(nHelpLine);
285 
286         mpWindow->ReleaseMouse();
287     }
288 
289     if (mpView)
290     {
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());
304     }
305 
306     bIsInDragMode = false;
307     ForcePointer(&rMEvt);
308     FuPoor::MouseButtonUp(rMEvt);
309 
310     return false;
311 }
312 
313 /**
314  * Process keyboard input
315  * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
316  */
KeyInput(const KeyEvent & rKEvt)317 bool FuDraw::KeyInput(const KeyEvent& rKEvt)
318 {
319     bool bReturn = false;
320     const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
321 
322     switch ( rKEvt.GetKeyCode().GetCode() )
323     {
324         case KEY_ESCAPE:
325         {
326             bReturn = FuDraw::cancel();
327         }
328         break;
329 
330         case KEY_DELETE:
331         case KEY_BACKSPACE:
332         {
333             if (!mpDocSh->IsReadOnly())
334             {
335                 if (mpView->IsPresObjSelected(false, true, false, true))
336                 {
337                     std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(),
338                                                                   VclMessageType::Info, VclButtonsType::Ok,
339                                                                   SdResId(STR_ACTION_NOTPOSSIBLE)));
340                     xInfoBox->run();
341                 }
342                 else
343                 {
344                     // wait-mousepointer while deleting object
345                     weld::WaitObject aWait(mpViewShell->GetFrameWeld());
346                     // delete object
347                     mpView->DeleteMarked();
348                 }
349             }
350             bReturn = true;
351         }
352         break;
353 
354         case KEY_TAB:
355         {
356             vcl::KeyCode aCode = rKEvt.GetKeyCode();
357 
358             if ( !aCode.IsMod1() && !aCode.IsMod2() )
359             {
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().
363 
364                 // Switch to FuSelect.
365                 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
366                     SID_OBJECT_SELECT,
367                     SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
368 
369                 // changeover to the next object
370                 if(!mpView->MarkNextObj( !aCode.IsShift() ))
371                 {
372                     //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj().
373                     if ( mpView->HasMultipleMarkableObjects() && rMarkList.GetMarkCount() != 0 )
374                     {
375                         // No next object: go over open end and get first from
376                         // the other side
377                         mpView->UnmarkAllObj();
378                         mpView->MarkNextObj(!aCode.IsShift());
379                     }
380                 }
381 
382                 if(rMarkList.GetMarkCount() != 0)
383                     mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
384 
385                 bReturn = true;
386             }
387         }
388         break;
389 
390         case KEY_END:
391         {
392             vcl::KeyCode aCode = rKEvt.GetKeyCode();
393 
394             if ( aCode.IsMod1() )
395             {
396                 // mark last object
397                 mpView->UnmarkAllObj();
398                 mpView->MarkNextObj();
399 
400                 if(rMarkList.GetMarkCount() != 0)
401                     mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
402 
403                 bReturn = true;
404             }
405         }
406         break;
407 
408         case KEY_HOME:
409         {
410             vcl::KeyCode aCode = rKEvt.GetKeyCode();
411 
412             if ( aCode.IsMod1() )
413             {
414                 // mark first object
415                 mpView->UnmarkAllObj();
416                 mpView->MarkNextObj(true);
417 
418                 if(rMarkList.GetMarkCount() != 0)
419                     mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
420 
421                 bReturn = true;
422             }
423         }
424         break;
425 
426         default:
427         break;
428     }
429 
430     if (!bReturn)
431     {
432         bReturn = FuPoor::KeyInput(rKEvt);
433     }
434     else
435     {
436         mpWindow->ReleaseMouse();
437     }
438 
439     return bReturn;
440 }
441 
Activate()442 void FuDraw::Activate()
443 {
444     FuPoor::Activate();
445     ForcePointer();
446 }
447 
448 /**
449  * Toggle mouse-pointer
450  */
ForcePointer(const MouseEvent * pMEvt)451 void FuDraw::ForcePointer(const MouseEvent* pMEvt)
452 {
453     Point aPnt;
454     sal_uInt16 nModifier = 0;
455     bool bLeftDown = false;
456     bool bDefPointer = true;
457 
458     if (pMEvt)
459     {
460         aPnt = mpWindow->PixelToLogic(pMEvt->GetPosPixel());
461         nModifier = pMEvt->GetModifier();
462         bLeftDown = pMEvt->IsLeft();
463     }
464     else
465     {
466         aPnt = mpWindow->PixelToLogic(mpWindow->GetPointerPosPixel());
467     }
468 
469     if (mpView->IsDragObj())
470     {
471         if (SD_MOD()->GetWaterCan() && !mpView->PickHandle(aPnt))
472         {
473             // water can mode
474             bDefPointer = false;
475             mpWindow->SetPointer(PointerStyle::Fill);
476         }
477     }
478     else
479     {
480         SdrHdl* pHdl = mpView->PickHandle(aPnt);
481 
482         if (SD_MOD()->GetWaterCan() && !pHdl)
483         {
484             // water can mode
485             bDefPointer = false;
486             mpWindow->SetPointer(PointerStyle::Fill);
487         }
488         else if (!pHdl &&
489                  mpViewShell->GetViewFrame()->HasChildWindow(SvxBmpMaskChildWindow::GetChildWindowId()))
490         {
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())
495             {
496                 bDefPointer = false;
497                 mpWindow->SetPointer(PointerStyle::RefHand);
498             }
499         }
500         else if (!mpView->IsAction())
501         {
502             SdrObject* pObj = nullptr;
503             SdrPageView* pPV = nullptr;
504             SdrViewEvent aVEvt;
505             SdrHitKind eHit = SdrHitKind::NONE;
506             SdrDragMode eDragMode = mpView->GetDragMode();
507 
508             if (pMEvt)
509             {
510                 eHit = mpView->PickAnything(*pMEvt, SdrMouseEventKind::MOVE, aVEvt);
511             }
512 
513             if ((eDragMode == SdrDragMode::Rotate) && (eHit == SdrHitKind::MarkedObject))
514             {
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))
522                 {
523                     mpWindow->SetPointer(PointerStyle::Rotate);
524                     bDefPointer = false;     // Otherwise it'll be called Joe's routine and the mousepointer will reconfigurate again
525                 }
526             }
527 
528             if (eHit == SdrHitKind::NONE)
529             {
530                 // found nothing -> look after at the masterpage
531                 pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
532             }
533             else if (eHit == SdrHitKind::UnmarkedObject)
534             {
535                 pObj = aVEvt.mpObj;
536             }
537             else if (eHit == SdrHitKind::TextEditObj && dynamic_cast< const FuSelection *>( this ) !=  nullptr)
538             {
539                 SdrObjKind nSdrObjKind = aVEvt.mpObj->GetObjIdentifier();
540 
541                 if ( nSdrObjKind != SdrObjKind::Text        &&
542                      nSdrObjKind != SdrObjKind::TitleText   &&
543                      nSdrObjKind != SdrObjKind::OutlineText &&
544                      aVEvt.mpObj->IsEmptyPresObj() )
545                 {
546                     pObj = nullptr;
547                     bDefPointer = false;
548                     mpWindow->SetPointer(PointerStyle::Arrow);
549                 }
550             }
551 
552             if (pObj && pMEvt && !pMEvt->IsMod2()
553                 && dynamic_cast<const FuSelection*>(this) != nullptr)
554             {
555                 // test for ImageMap
556                 bDefPointer = !SetPointer(pObj, aPnt);
557 
558                 if (bDefPointer
559                     && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr
560                         || DynCastE3dScene(pObj)))
561                 {
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);
567                 }
568             }
569         }
570     }
571 
572     if (bDefPointer)
573     {
574         mpWindow->SetPointer(mpView->GetPreferredPointer(
575                             aPnt, mpWindow->GetOutDev(), nModifier, bLeftDown));
576     }
577 }
578 
579 /**
580  * Set cursor to pointer when in clickable area of an ImageMap
581  *
582  * @return True when pointer was set
583  */
SetPointer(const SdrObject * pObj,const Point & rPos)584 bool FuDraw::SetPointer(const SdrObject* pObj, const Point& rPos)
585 {
586     bool bImageMapInfo = SvxIMapInfo::GetIMapInfo(pObj) != nullptr;
587 
588     if (!bImageMapInfo)
589         return false;
590 
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);
598 
599     aHitPosR.AdjustX(n2HitLog);
600     aHitPosL.AdjustX(-n2HitLog);
601     aHitPosT.AdjustY(n2HitLog);
602     aHitPosB.AdjustY(-n2HitLog);
603 
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)))
613     {
614         // hit inside the object (without margin) or open object
615         if (SvxIMapInfo::GetHitIMapObject(pObj, rPos))
616         {
617             mpWindow->SetPointer(PointerStyle::RefHand);
618             return true;
619         }
620     }
621 
622     return false;
623 }
624 
625 /**
626  * Response of doubleclick
627  */
DoubleClick(const MouseEvent & rMEvt)628 void FuDraw::DoubleClick(const MouseEvent& rMEvt)
629 {
630     sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
631 
632     const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
633     if ( rMarkList.GetMarkCount() != 0 )
634     {
635         if (rMarkList.GetMarkCount() == 1)
636         {
637             SdrMark* pMark = rMarkList.GetMark(0);
638             SdrObject* pObj = pMark->GetMarkedSdrObj();
639 
640             SdrInventor nInv = pObj->GetObjInventor();
641             SdrObjKind  nSdrObjKind = pObj->GetObjIdentifier();
642 
643             if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::OLE2)
644             {
645                 // activate OLE-object
646                 SfxInt16Item aItem(SID_OBJECT, 0);
647                 mpViewShell->GetViewFrame()->
648                     GetDispatcher()->ExecuteList(SID_OBJECT,
649                                                  SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
650                                                  { &aItem });
651             }
652             else if (nInv == SdrInventor::Default &&  nSdrObjKind == SdrObjKind::Graphic && pObj->IsEmptyPresObj() )
653             {
654                 mpViewShell->GetViewFrame()->
655                     GetDispatcher()->Execute( SID_INSERT_GRAPHIC,
656                                               SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
657             }
658             else if ( ( DynCastSdrTextObj( pObj ) != nullptr || dynamic_cast< const SdrObjGroup *>( pObj ) !=  nullptr ) &&
659                       !SD_MOD()->GetWaterCan()                            &&
660                       mpViewShell->GetFrameView()->IsDoubleClickTextEdit() &&
661                       !mpDocSh->IsReadOnly())
662             {
663                 SfxUInt16Item aItem(SID_TEXTEDIT, 2);
664                 mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(
665                         SID_TEXTEDIT,
666                         SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
667                         { &aItem });
668             }
669             else if (nInv == SdrInventor::Default &&  nSdrObjKind == SdrObjKind::Group)
670             {
671                 // hit group -> select subobject
672                 mpView->UnMarkAll();
673                 mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift(), true);
674             }
675         }
676     }
677     else
678         mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
679 }
680 
RequestHelp(const HelpEvent & rHEvt)681 bool FuDraw::RequestHelp(const HelpEvent& rHEvt)
682 {
683     bool bReturn = false;
684 
685     if (Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled())
686     {
687         SdrViewEvent aVEvt;
688 
689         MouseEvent aMEvt(mpWindow->GetPointerPosPixel(), 1, MouseEventModifiers::NONE, MOUSE_LEFT);
690 
691         SdrHitKind eHit = mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
692 
693         SdrObject* pObj = aVEvt.mpObj;
694 
695         if (eHit != SdrHitKind::NONE && pObj != nullptr)
696         {
697             Point aPosPixel = rHEvt.GetMousePosPixel();
698 
699             bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
700 
701             if (!bReturn && (dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr || DynCastE3dScene(pObj)))
702             {
703                 // take a glance into the group
704                 SdrPageView* pPV = nullptr;
705 
706                 Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(aPosPixel)));
707 
708                 pObj = mpView->PickObj(aPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
709                 if (pObj)
710                     bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
711             }
712         }
713     }
714 
715     if (!bReturn)
716     {
717         bReturn = FuPoor::RequestHelp(rHEvt);
718     }
719 
720     if (!bReturn)
721        bReturn = mpView->RequestHelp(rHEvt);
722 
723     return bReturn;
724 }
725 
SetHelpText(const SdrObject * pObj,const Point & rPosPixel,const SdrViewEvent & rVEvt)726 bool FuDraw::SetHelpText(const SdrObject* pObj, const Point& rPosPixel, const SdrViewEvent& rVEvt)
727 {
728     OUString aHelpText;
729     Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(rPosPixel)));
730     IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(pObj, aPos);
731 
732     if (!rVEvt.mpURLField && !pIMapObj)
733         return false;
734 
735     OUString aURL;
736     if (rVEvt.mpURLField)
737         aURL = INetURLObject::decode(rVEvt.mpURLField->GetURL(),
738                                      INetURLObject::DecodeMechanism::WithCharset);
739     else if (pIMapObj)
740     {
741         aURL = pIMapObj->GetAltText() +
742             " (" +
743             INetURLObject::decode(pIMapObj->GetURL(),
744                                         INetURLObject::DecodeMechanism::WithCharset) +
745             ")";
746     }
747     else
748         return false;
749 
750     aHelpText = SfxHelp::GetURLHelpText(aURL);
751 
752     if (aHelpText.isEmpty())
753         return false;
754 
755     ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(pObj->GetLogicRect());
756     ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()),
757                             mpWindow->OutputToScreenPixel(aLogicPix.BottomRight()));
758 
759     if (Help::IsBalloonHelpEnabled())
760         Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rPosPixel, aScreenRect, aHelpText);
761     else if (Help::IsQuickHelpEnabled())
762         Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText);
763 
764     return true;
765 }
766 
767 /** is called when the current function should be aborted. <p>
768     This is used when a function gets a KEY_ESCAPE but can also
769     be called directly.
770 
771     @returns true if an active function was aborted
772 */
cancel()773 bool FuDraw::cancel()
774 {
775     bool bReturn = false;
776     const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
777 
778     if ( mpView->IsAction() )
779     {
780         mpView->BrkAction();
781         bReturn = true;
782     }
783     else if ( mpView->IsTextEdit() )
784     {
785         mpView->SdrEndTextEdit();
786         bReturn = true;
787 
788         SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings();
789         rBindings.Invalidate( SID_DEC_INDENT );
790         rBindings.Invalidate( SID_INC_INDENT );
791         rBindings.Invalidate( SID_PARASPACE_INCREASE );
792         rBindings.Invalidate( SID_PARASPACE_DECREASE );
793     }
794     else if ( rMarkList.GetMarkCount() != 0 )
795     {
796         const SdrHdlList& rHdlList = mpView->GetHdlList();
797         SdrHdl* pHdl = rHdlList.GetFocusHdl();
798 
799         if(pHdl)
800         {
801             const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl();
802         }
803         else
804         {
805             mpView->UnmarkAll();
806         }
807 
808         // Switch to FuSelect.
809         mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
810             SID_OBJECT_SELECT,
811             SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
812 
813         bReturn = true;
814     }
815 
816     return bReturn;
817 }
818 
819 } // end of namespace sd
820 
821 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
822