xref: /core/sc/source/ui/drawfunc/fudraw.cxx (revision ec49191e)
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 <editeng/editeng.hxx>
21 #include <editeng/outlobj.hxx>
22 #include <svx/svdobj.hxx>
23 #include <svx/svdoole2.hxx>
24 #include <svx/svdouno.hxx>
25 #include <svx/ImageMapInfo.hxx>
26 #include <sfx2/dispatch.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <vcl/uitest/logger.hxx>
29 #include <vcl/uitest/eventdescription.hxx>
30 
31 #include <sc.hrc>
32 #include <fudraw.hxx>
33 #include <futext.hxx>
34 #include <tabvwsh.hxx>
35 #include <drwlayer.hxx>
36 #include <userdat.hxx>
37 #include <docsh.hxx>
38 #include <drawview.hxx>
39 #include <comphelper/lok.hxx>
40 #include <com/sun/star/embed/EmbedVerbs.hpp>
41 
42 namespace
43 {
44 
collectUIInformation(const OUString & aevent)45 void collectUIInformation( const OUString& aevent )
46 {
47     EventDescription aDescription;
48     aDescription.aID =  "grid_window";
49     aDescription.aParameters = {{ aevent ,  ""}};
50     aDescription.aAction = "COMMENT";
51     aDescription.aParent = "MainWindow";
52     aDescription.aKeyWord = "ScGridWinUIObject";
53     UITestLogger::getInstance().logEvent(aDescription);
54 }
55 
56 }
57 
58 // base class for draw module specific functions
FuDraw(ScTabViewShell & rViewSh,vcl::Window * pWin,ScDrawView * pViewP,SdrModel * pDoc,const SfxRequest & rReq)59 FuDraw::FuDraw(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
60                SdrModel* pDoc, const SfxRequest& rReq)
61     : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
62     , aNewPointer(PointerStyle::Arrow)
63     , aOldPointer(PointerStyle::Arrow)
64 {
65 }
66 
~FuDraw()67 FuDraw::~FuDraw()
68 {
69 }
70 
DoModifiers(const MouseEvent & rMEvt)71 void FuDraw::DoModifiers(const MouseEvent& rMEvt)
72 {
73     //  Shift   = Ortho and AngleSnap
74     //  Control = Snap (Toggle)
75     //  Alt     = centric
76 
77     bool bShift = rMEvt.IsShift();
78     bool bAlt   = rMEvt.IsMod2();
79 
80     bool bOrtho     = bShift;
81     bool bAngleSnap = bShift;
82     bool bCenter    = bAlt;
83 
84     // #i33136#
85     if(doConstructOrthogonal())
86     {
87         bOrtho = !bShift;
88     }
89 
90     if (pView->IsOrtho() != bOrtho)
91         pView->SetOrtho(bOrtho);
92     if (pView->IsAngleSnapEnabled() != bAngleSnap)
93         pView->SetAngleSnapEnabled(bAngleSnap);
94 
95     if (pView->IsCreate1stPointAsCenter() != bCenter)
96         pView->SetCreate1stPointAsCenter(bCenter);
97     if (pView->IsResizeAtCenter() != bCenter)
98         pView->SetResizeAtCenter(bCenter);
99 
100 }
101 
ResetModifiers()102 void FuDraw::ResetModifiers()
103 {
104     if (!pView)
105         return;
106 
107     ScViewData& rViewData = rViewShell.GetViewData();
108     const ScViewOptions& rOpt = rViewData.GetOptions();
109     const ScGridOptions& rGrid = rOpt.GetGridOptions();
110     bool bGridOpt = rGrid.GetUseGridSnap();
111 
112     if (pView->IsOrtho())
113         pView->SetOrtho(false);
114     if (pView->IsAngleSnapEnabled())
115         pView->SetAngleSnapEnabled(false);
116 
117     if (pView->IsGridSnap() != bGridOpt)
118         pView->SetGridSnap(bGridOpt);
119     if (pView->IsSnapEnabled() != bGridOpt)
120         pView->SetSnapEnabled(bGridOpt);
121 
122     if (pView->IsCreate1stPointAsCenter())
123         pView->SetCreate1stPointAsCenter(false);
124     if (pView->IsResizeAtCenter())
125         pView->SetResizeAtCenter(false);
126 }
127 
MouseButtonDown(const MouseEvent & rMEvt)128 bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt)
129 {
130     // remember button state for creation of own MouseEvents
131     SetMouseButtonCode(rMEvt.GetButtons());
132 
133     DoModifiers( rMEvt );
134     return false;
135 }
136 
MouseMove(const MouseEvent & rMEvt)137 bool FuDraw::MouseMove(const MouseEvent& rMEvt)
138 {
139     //  evaluate modifiers only if in a drawing layer action
140     //  (don't interfere with keyboard shortcut handling)
141     if (pView->IsAction())
142         DoModifiers( rMEvt );
143 
144     return false;
145 }
146 
MouseButtonUp(const MouseEvent & rMEvt)147 bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt)
148 {
149     // remember button state for creation of own MouseEvents
150     SetMouseButtonCode(rMEvt.GetButtons());
151 
152     ResetModifiers();
153     return false;
154 }
155 
156 // Process Keyboard events. Return true if an event is being handled
lcl_KeyEditMode(SdrObject * pObj,ScTabViewShell & rViewShell,const KeyEvent * pInitialKey)157 static bool lcl_KeyEditMode( SdrObject* pObj, ScTabViewShell& rViewShell, const KeyEvent* pInitialKey )
158 {
159     bool bReturn = false;
160     if ( DynCastSdrTextObj( pObj) != nullptr && dynamic_cast<const SdrUnoObj*>( pObj) ==  nullptr )
161     {
162         assert(pObj);
163         // start text edit - like FuSelection::MouseButtonUp,
164         // but with bCursorToEnd instead of mouse position
165 
166         OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
167         bool bVertical = ( pOPO && pOPO->IsEffectivelyVertical() );
168         sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
169 
170         // don't switch shells if text shell is already active
171         FuPoor* pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
172         if ( !pPoor || pPoor->GetSlotID() != nTextSlotId )
173         {
174             rViewShell.GetViewData().GetDispatcher().
175                 Execute(nTextSlotId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
176         }
177 
178         // get the resulting FuText and set in edit mode
179         pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
180         if ( pPoor && pPoor->GetSlotID() == nTextSlotId )    // no RTTI
181         {
182             FuText* pText = static_cast<FuText*>(pPoor);
183             pText->SetInEditMode( pObj, nullptr, true, pInitialKey );
184             //! set cursor to end of text
185         }
186         bReturn = true;
187     }
188     return bReturn;
189 }
190 
KeyInput(const KeyEvent & rKEvt)191 bool FuDraw::KeyInput(const KeyEvent& rKEvt)
192 {
193     bool bReturn = false;
194     ScViewData& rViewData = rViewShell.GetViewData();
195 
196     const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
197     switch ( rKEvt.GetKeyCode().GetCode() )
198     {
199         case KEY_ESCAPE:
200             if ( rViewShell.IsDrawTextShell() || aSfxRequest.GetSlot() == SID_DRAW_NOTEEDIT )
201             {
202                 collectUIInformation(u"CLOSE"_ustr);
203                 // if object selected -> normal draw-shell, else turn off drawing
204                 rViewData.GetDispatcher().Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
205                 bReturn = true;
206             }
207             else if ( rViewShell.IsDrawSelMode() )
208             {
209                 pView->UnmarkAll();
210                 rViewData.GetDispatcher().Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
211                 bReturn = true;
212             }
213             else if ( rMarkList.GetMarkCount() != 0 )
214             {
215                 // III
216                 SdrHdlList& rHdlList = const_cast< SdrHdlList& >( pView->GetHdlList() );
217                 if( rHdlList.GetFocusHdl() )
218                     rHdlList.ResetFocusHdl();
219                 else
220                     pView->UnmarkAll();
221 
222                 //  while bezier editing, object is selected
223                 if (rMarkList.GetMarkCount() == 0)
224                     rViewShell.SetDrawShell( false );
225 
226                 bReturn = true;
227             }
228             break;
229 
230         case KEY_DELETE:                    //! via accelerator
231             pView->DeleteMarked();
232             bReturn = true;
233         break;
234 
235         case KEY_RETURN:
236         {
237             if( rKEvt.GetKeyCode().GetModifier() == 0 )
238             {
239                 // activate OLE object on RETURN for selected object
240                 // put selected text object in edit mode
241                 if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() )
242                 {
243                     bool bOle = rViewShell.GetViewFrame().GetFrame().IsInPlace();
244                     SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
245                     auto pOleObj = dynamic_cast<SdrOle2Obj*>(pObj);
246                     if( pOleObj && !bOle )
247                     {
248                         rViewShell.ActivateObject(pOleObj, css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
249 
250                         // consumed
251                         bReturn = true;
252                     }
253                     else if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) )       // start text edit for suitable object
254                         bReturn = true;
255                 }
256             }
257         }
258         break;
259 
260         case KEY_F2:
261         {
262             if( rKEvt.GetKeyCode().GetModifier() == 0 )
263             {
264                 // put selected text object in edit mode
265                 // (this is not SID_SETINPUTMODE, but F2 hardcoded, like in Writer)
266                 if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() )
267                 {
268                     SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
269                     bool isMobilePhone = comphelper::LibreOfficeKit::isActive() && rViewShell.isLOKMobilePhone();
270                     // Double tapping on charts on phone may result in activating the edit mode which is not wanted.
271                     // It happens due to the delay of selection message of the object from kit to javascript
272                     // in that case F2 is sent instead of double click
273                     if (isMobilePhone && ScDocument::IsChart(pObj))
274                     {
275                         rViewShell.ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
276                         break;
277                     }
278                     if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) )            // start text edit for suitable object
279                         bReturn = true;
280                 }
281             }
282         }
283         break;
284 
285         case KEY_TAB:
286         {
287             // in calc do NOT start draw object selection using TAB/SHIFT-TAB when
288             // there is not yet an object selected
289             if(rMarkList.GetMarkCount() != 0)
290             {
291                 vcl::KeyCode aCode = rKEvt.GetKeyCode();
292 
293                 if ( !aCode.IsMod1() && !aCode.IsMod2() )
294                 {
295                     // changeover to the next object
296                     if(!pView->MarkNextObj( !aCode.IsShift() ))
297                     {
298                         //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj().
299                         if ( pView->HasMultipleMarkableObjects() && pView->HasMarkableObj() )
300                         {
301                             // No next object: go over open end and
302                             // get first from the other side
303                             pView->UnmarkAllObj();
304                             pView->MarkNextObj(!aCode.IsShift());
305                         }
306                     }
307 
308                     // II
309                     if(rMarkList.GetMarkCount() != 0)
310                         pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
311 
312                     bReturn = true;
313                 }
314 
315                 // handle Mod1 and Mod2 to get travelling running on different systems
316                 if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2())
317                 {
318                     // II do something with a selected handle?
319                     const SdrHdlList& rHdlList = pView->GetHdlList();
320                     bool bForward(!rKEvt.GetKeyCode().IsShift());
321 
322                     const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
323 
324                     // guarantee visibility of focused handle
325                     SdrHdl* pHdl = rHdlList.GetFocusHdl();
326 
327                     if(pHdl)
328                     {
329                         Point aHdlPosition(pHdl->GetPos());
330                         tools::Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200));
331                         pView->MakeVisible(aVisRect, *pWindow);
332                     }
333 
334                     // consumed
335                     bReturn = true;
336                 }
337             }
338         }
339         break;
340 
341         case KEY_END:
342         {
343             // in calc do NOT select the last draw object when
344             // there is not yet an object selected
345             if(rMarkList.GetMarkCount() != 0)
346             {
347                 vcl::KeyCode aCode = rKEvt.GetKeyCode();
348 
349                 if ( aCode.IsMod1() )
350                 {
351                     // mark last object
352                     pView->UnmarkAllObj();
353                     pView->MarkNextObj();
354 
355                     // II
356                     if(rMarkList.GetMarkCount() != 0)
357                         pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
358 
359                     bReturn = true;
360                 }
361             }
362         }
363         break;
364 
365         case KEY_HOME:
366         {
367             // in calc do NOT select the first draw object when
368             // there is not yet an object selected
369             if(rMarkList.GetMarkCount() != 0)
370             {
371                 vcl::KeyCode aCode = rKEvt.GetKeyCode();
372 
373                 if ( aCode.IsMod1() )
374                 {
375                     // mark first object
376                     pView->UnmarkAllObj();
377                     pView->MarkNextObj(true);
378 
379                     // II
380                     if(rMarkList.GetMarkCount() != 0)
381                         pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
382 
383                     bReturn = true;
384                 }
385             }
386         }
387         break;
388 
389         case KEY_UP:
390         case KEY_DOWN:
391         case KEY_LEFT:
392         case KEY_RIGHT:
393         {
394             // in calc do cursor travelling of draw objects only when
395             // there is an object selected yet
396             if(rMarkList.GetMarkCount() != 0)
397             {
398 
399                 if(rMarkList.GetMarkCount() == 1)
400                 {
401                     // disable cursor travelling on note objects as the tail connector position
402                     // must not move.
403                     SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
404                     if( ScDrawLayer::IsNoteCaption( pObj ) )
405                         break;
406                 }
407 
408                 tools::Long nX = 0;
409                 tools::Long nY = 0;
410                 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
411 
412                 if (nCode == KEY_UP)
413                 {
414                     // scroll up
415                     nX = 0;
416                     nY =-1;
417                 }
418                 else if (nCode == KEY_DOWN)
419                 {
420                     // scroll down
421                     nX = 0;
422                     nY = 1;
423                 }
424                 else if (nCode == KEY_LEFT)
425                 {
426                     // scroll left
427                     nX =-1;
428                     nY = 0;
429                 }
430                 else if (nCode == KEY_RIGHT)
431                 {
432                     // scroll right
433                     nX = 1;
434                     nY = 0;
435                 }
436 
437                 bool bReadOnly = rViewData.GetDocShell()->IsReadOnly();
438 
439                 if(!rKEvt.GetKeyCode().IsMod1() && !bReadOnly)
440                 {
441                     if(rKEvt.GetKeyCode().IsMod2())
442                     {
443                         // move in 1 pixel distance
444                         Size aLogicSizeOnePixel = pWindow ? pWindow->PixelToLogic(Size(1,1)) : Size(100, 100);
445                         nX *= aLogicSizeOnePixel.Width();
446                         nY *= aLogicSizeOnePixel.Height();
447                     }
448                     else if(rKEvt.GetKeyCode().IsShift()) // #i121236# Support for shift key in calc
449                     {
450                         nX *= 1000;
451                         nY *= 1000;
452                     }
453                     else
454                     {
455                         // old, fixed move distance
456                         nX *= 100;
457                         nY *= 100;
458                     }
459 
460                     // is there a movement to do?
461                     if(0 != nX || 0 != nY)
462                     {
463                         // II
464                         const SdrHdlList& rHdlList = pView->GetHdlList();
465                         SdrHdl* pHdl = rHdlList.GetFocusHdl();
466 
467                         if(nullptr == pHdl)
468                         {
469                             // only take action when move is allowed
470                             if(pView->IsMoveAllowed())
471                             {
472                                 // restrict movement to WorkArea
473                                 const tools::Rectangle& rWorkArea = pView->GetWorkArea();
474 
475                                 if(!rWorkArea.IsEmpty())
476                                 {
477                                     tools::Rectangle aMarkRect(pView->GetMarkedObjRect());
478                                     aMarkRect.Move(nX, nY);
479 
480                                     if(!aMarkRect.Contains(rWorkArea))
481                                     {
482                                         if(aMarkRect.Left() < rWorkArea.Left())
483                                         {
484                                             nX += rWorkArea.Left() - aMarkRect.Left();
485                                         }
486 
487                                         if(aMarkRect.Right() > rWorkArea.Right())
488                                         {
489                                             nX -= aMarkRect.Right() - rWorkArea.Right();
490                                         }
491 
492                                         if(aMarkRect.Top() < rWorkArea.Top())
493                                         {
494                                             nY += rWorkArea.Top() - aMarkRect.Top();
495                                         }
496 
497                                         if(aMarkRect.Bottom() > rWorkArea.Bottom())
498                                         {
499                                             nY -= aMarkRect.Bottom() - rWorkArea.Bottom();
500                                         }
501                                     }
502                                 }
503 
504                                 // now move the selected draw objects
505                                 pView->MoveAllMarked(Size(nX, nY));
506 
507                                 // II
508                                 pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
509 
510                                 bReturn = true;
511                             }
512                         }
513                         else
514                         {
515                             // move handle with index nHandleIndex
516                             if (nX || nY)
517                             {
518                                 // now move the Handle (nX, nY)
519                                 Point aStartPoint(pHdl->GetPos());
520                                 Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
521                                 const SdrDragStat& rDragStat = pView->GetDragStat();
522 
523                                 // start dragging
524                                 pView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
525 
526                                 if(pView->IsDragObj())
527                                 {
528                                     bool bWasNoSnap = rDragStat.IsNoSnap();
529                                     bool bWasSnapEnabled = pView->IsSnapEnabled();
530 
531                                     // switch snapping off
532                                     if(!bWasNoSnap)
533                                         const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
534                                     if(bWasSnapEnabled)
535                                         pView->SetSnapEnabled(false);
536 
537                                     pView->MovAction(aEndPoint);
538                                     pView->EndDragObj();
539 
540                                     // restore snap
541                                     if(!bWasNoSnap)
542                                         const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
543                                     if(bWasSnapEnabled)
544                                         pView->SetSnapEnabled(bWasSnapEnabled);
545                                 }
546 
547                                 // make moved handle visible
548                                 tools::Rectangle aVisRect(aEndPoint - Point(100, 100), Size(200, 200));
549                                 pView->MakeVisible(aVisRect, *pWindow);
550 
551                                 bReturn = true;
552                             }
553                         }
554                     }
555                 }
556             }
557         }
558         break;
559 
560         case KEY_SPACE:
561         {
562             // in calc do only something when draw objects are selected
563             if(rMarkList.GetMarkCount() != 0)
564             {
565                 const SdrHdlList& rHdlList = pView->GetHdlList();
566                 SdrHdl* pHdl = rHdlList.GetFocusHdl();
567 
568                 if(pHdl)
569                 {
570                     if(pHdl->GetKind() == SdrHdlKind::Poly)
571                     {
572                         // rescue ID of point with focus
573                         sal_uInt32 nPol(pHdl->GetPolyNum());
574                         sal_uInt32 nPnt(pHdl->GetPointNum());
575 
576                         if(pView->IsPointMarked(*pHdl))
577                         {
578                             if(rKEvt.GetKeyCode().IsShift())
579                             {
580                                 pView->UnmarkPoint(*pHdl);
581                             }
582                         }
583                         else
584                         {
585                             if(!rKEvt.GetKeyCode().IsShift())
586                             {
587                                 pView->UnmarkAllPoints();
588                             }
589 
590                             pView->MarkPoint(*pHdl);
591                         }
592 
593                         if(nullptr == rHdlList.GetFocusHdl())
594                         {
595                             // restore point with focus
596                             SdrHdl* pNewOne = nullptr;
597 
598                             for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a)
599                             {
600                                 SdrHdl* pAct = rHdlList.GetHdl(a);
601 
602                                 if(pAct
603                                     && pAct->GetKind() == SdrHdlKind::Poly
604                                     && pAct->GetPolyNum() == nPol
605                                     && pAct->GetPointNum() == nPnt)
606                                 {
607                                     pNewOne = pAct;
608                                 }
609                             }
610 
611                             if(pNewOne)
612                             {
613                                 const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne);
614                             }
615                         }
616 
617                         bReturn = true;
618                     }
619                 }
620             }
621         }
622         break;
623     }
624 
625     if (!bReturn)
626     {
627         bReturn = FuPoor::KeyInput(rKEvt);
628     }
629 
630     if (!bReturn)
631     {
632         // allow direct typing into a selected text object
633 
634         if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() && EditEngine::IsSimpleCharInput(rKEvt) )
635         {
636             SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
637 
638             // start text edit for suitable object, pass key event to OutlinerView
639             if ( lcl_KeyEditMode( pObj, rViewShell, &rKEvt ) )
640                 bReturn = true;
641         }
642     }
643 
644     return bReturn;
645 }
646 
647 // toggle mouse-pointer
lcl_UrlHit(const SdrView * pView,const Point & rPosPixel,const vcl::Window * pWindow)648 static bool lcl_UrlHit( const SdrView* pView, const Point& rPosPixel, const vcl::Window* pWindow )
649 {
650     SdrViewEvent aVEvt;
651     MouseEvent aMEvt( rPosPixel, 1, MouseEventModifiers::NONE, MOUSE_LEFT );
652     SdrHitKind eHit = pView->PickAnything( aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
653 
654     if (eHit != SdrHitKind::NONE && aVEvt.mpObj != nullptr)
655     {
656         if ( SvxIMapInfo::GetIMapInfo(aVEvt.mpObj) && SvxIMapInfo::GetHitIMapObject(
657                                 aVEvt.mpObj, pWindow->PixelToLogic(rPosPixel), pWindow->GetOutDev() ) )
658             return true;
659 
660         if (aVEvt.meEvent == SdrEventKind::ExecuteUrl)
661             return true;
662     }
663 
664     return false;
665 }
666 
ForcePointer(const MouseEvent * pMEvt)667 void FuDraw::ForcePointer(const MouseEvent* pMEvt)
668 {
669     if ( pView->IsAction() )
670         return;
671 
672     Point aPosPixel = pWindow->GetPointerPosPixel();
673     bool bAlt       = pMEvt && pMEvt->IsMod2();
674     Point aPnt      = pWindow->PixelToLogic( aPosPixel );
675     SdrHdl* pHdl    = pView->PickHandle(aPnt);
676     SdrPageView* pPV;
677     SdrObject* pMacroPickObj;
678 
679     ScMacroInfo* pInfo = nullptr;
680     SdrObject* pObj = pView->PickObj(aPnt, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
681     if (pObj)
682     {
683         if ( pObj->IsGroupObject() )
684         {
685             SdrObject* pHit = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
686             if (pHit)
687                 pObj = pHit;
688         }
689         pInfo = ScDrawLayer::GetMacroInfo( pObj );
690     }
691 
692     if ( pView->IsTextEdit() )
693     {
694         rViewShell.SetActivePointer(PointerStyle::Text);        // can't be ?
695     }
696     else if ( pHdl )
697     {
698         rViewShell.SetActivePointer(
699             pView->GetPreferredPointer( aPnt, pWindow->GetOutDev() ) );
700     }
701     else if ( pView->IsMarkedHit(aPnt) )
702     {
703         rViewShell.SetActivePointer( PointerStyle::Move );
704     }
705     else if ( !bAlt && ( !pMEvt || !pMEvt->GetButtons() )
706                     && lcl_UrlHit( pView, aPosPixel, pWindow ) )
707     {
708         //  could be suppressed with ALT
709         pWindow->SetPointer( PointerStyle::RefHand );          // Text-URL / ImageMap
710     }
711     else if ( !bAlt && (pMacroPickObj = pView->PickObj(aPnt, pView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO)) )
712     {
713         //  could be suppressed with ALT
714         SdrObjMacroHitRec aHitRec;  //! something missing ????
715         rViewShell.SetActivePointer(pMacroPickObj->GetMacroPointer(aHitRec));
716     }
717     else if ( !bAlt && pInfo && (!pInfo->GetMacro().isEmpty() || !pObj->getHyperlink().isEmpty()) )
718         pWindow->SetPointer( PointerStyle::RefHand );
719     else if ( IsDetectiveHit( aPnt ) )
720         rViewShell.SetActivePointer( PointerStyle::Detective );
721     else
722     {
723         const bool bIsThemed = rViewShell.GetViewData().IsThemedCursor();
724         rViewShell.SetActivePointer( bIsThemed ? PointerStyle::FatCross : PointerStyle::Arrow ); //! in Gridwin?
725     }
726 }
727 
IsEditingANote() const728 bool FuDraw::IsEditingANote() const
729 {
730     const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
731     const size_t backval=rMarkList.GetMarkCount();
732     for (size_t nlv1=0; nlv1<backval; ++nlv1)
733     {
734         SdrObject* pObj = rMarkList.GetMark( nlv1 )->GetMarkedSdrObj();
735         if ( ScDrawLayer::IsNoteCaption( pObj ) )
736         {
737             return true;
738         }
739     }
740     return false;
741 }
742 
IsSizingOrMovingNote(const MouseEvent & rMEvt) const743 bool FuDraw::IsSizingOrMovingNote( const MouseEvent& rMEvt ) const
744 {
745     bool bIsSizingOrMoving = false;
746     if ( rMEvt.IsLeft() )
747     {
748         const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
749         if(rMarkList.GetMarkCount() == 1)
750         {
751             SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
752             if ( ScDrawLayer::IsNoteCaption( pObj ) )
753             {
754                 Point aMPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
755                 bIsSizingOrMoving =
756                     pView->PickHandle( aMPos ) ||      // handles to resize the note
757                     pView->IsTextEditFrameHit( aMPos );         // frame for moving the note
758             }
759         }
760     }
761     return bIsSizingOrMoving;
762 }
763 
764 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
765