1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <svx/svddrgmt.hxx>
22 #include <svx/svdpagv.hxx>
23 #include <svx/svdogrp.hxx>
24 #include <svx/scene3d.hxx>
25 #include <vcl/imapobj.hxx>
26 #include <unotools/securityoptions.hxx>
27 #include <svx/svxids.hrc>
28 #include <svx/xfillit0.hxx>
29 #include <svx/ImageMapInfo.hxx>
30 #include <sfx2/viewfrm.hxx>
31 #include <svl/stritem.hxx>
32 #include <svl/intitem.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <editeng/flditem.hxx>
37 #include <svx/svdotable.hxx>
42 #include <DrawDocShell.hxx>
43 #include <stlpool.hxx>
45 #include <ViewShell.hxx>
46 #include <ViewShellBase.hxx>
47 #include <FrameView.hxx>
50 #include <drawdoc.hxx>
51 #include <DrawViewShell.hxx>
52 #include <ToolBarManager.hxx>
54 #include <annotationmanager.hxx>
56 #include <svx/svdundo.hxx>
58 #include <svx/sdrhittesthelper.hxx>
59 #include <svx/diagram/IDiagramHelper.hxx>
60 #include <svx/annotation/ObjectAnnotationData.hxx>
62 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
63 #include <comphelper/lok.hxx>
65 using namespace ::com::sun::star
;
69 FuSelection::FuSelection (
75 : FuDraw(pViewSh
, pWin
, pView
, pDoc
, rReq
),
77 bSelectionChanged(false),
79 bSuppressChangesOfSelection(false),
81 nEditMode(SID_BEZIER_MOVE
),
82 pWaterCanCandidate(nullptr)
83 //Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point,
84 //and SHIFT+ENTER key to decide the position and draw the new insert point
85 ,bBeginInsertPoint(false),
87 ,bMovedToCenterPoint(false)
91 rtl::Reference
<FuPoor
> FuSelection::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
)
93 rtl::Reference
<FuPoor
> xFunc( new FuSelection( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
94 xFunc
->DoExecute(rReq
);
98 void FuSelection::DoExecute( SfxRequest
& rReq
)
100 FuDraw::DoExecute( rReq
);
103 SelectionHasChanged();
106 FuSelection::~FuSelection()
108 mpView
->UnmarkAllPoints();
109 mpView
->ResetCreationActive();
111 if ( mpView
->GetDragMode() != SdrDragMode::Move
)
113 mpView
->SetDragMode(SdrDragMode::Move
);
118 bool lcl_followHyperlinkAllowed(const MouseEvent
& rMEvt
) {
119 if (!rMEvt
.IsMod1() && SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink
))
121 if (rMEvt
.IsMod1() && !SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink
))
127 bool FuSelection::MouseButtonDown(const MouseEvent
& rMEvt
)
130 bool bReturn
= FuDraw::MouseButtonDown(rMEvt
);
131 bool bWaterCan
= SdModule::get()->GetWaterCan();
132 const bool bReadOnly
= mpDocSh
->IsReadOnly();
133 // When the right mouse button is pressed then only select objects
134 // (and deselect others) as a preparation for showing the context
136 const bool bSelectionOnly
= rMEvt
.IsRight();
139 bSelectionChanged
= false;
141 if ( mpView
->IsAction() )
143 if ( rMEvt
.IsRight() )
148 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(mpView
->GetDragThresholdPixels(),0)).Width() );
149 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
151 if (comphelper::LibreOfficeKit::isActive())
153 // When tiled rendering, we always work in logic units, use the non-pixel constants.
158 // The following code is executed for right clicks as well as for left
159 // clicks in order to modify the selection for the right button as a
160 // preparation for the context menu. The functions BegMarkObject() and
161 // BegDragObject(), however, are not called for right clicks because a)
162 // it makes no sense and b) to have IsAction() return sal_False when called
163 // from Command() which is a prerequisite for the context menu.
164 if ((rMEvt
.IsLeft() || rMEvt
.IsRight())
165 && !mpView
->IsAction()
166 && (mpView
->IsFrameDragSingles() || !mpView
->HasMarkablePoints()))
168 /******************************************************************
170 ******************************************************************/
171 mpWindow
->CaptureMouse();
172 pHdl
= mpView
->PickHandle(aMDPos
);
174 Degree100 nAngle0
= GetAngle(aMDPos
- mpView
->GetRef1());
175 nAngle0
-= 27000_deg100
;
176 nAngle0
= NormAngle36000(nAngle0
);
177 bMirrorSide0
= nAngle0
< 18000_deg100
;
179 if (!pHdl
&& mpView
->Is3DRotationCreationActive())
181 /******************************************************************
182 * If 3D-rotation bodies are about to be created,
184 ******************************************************************/
185 bSuppressChangesOfSelection
= true;
186 mpWindow
->EnterWait();
187 mpView
->End3DCreation();
188 bSuppressChangesOfSelection
= false;
189 mpView
->ResetCreationActive();
190 mpWindow
->LeaveWait();
193 bool bTextEdit
= false;
195 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
197 if (eHit
== SdrHitKind::TextEditObj
&& (mpViewShell
->GetFrameView()->IsQuickEdit() || dynamic_cast< sdr::table::SdrTableObj
* >(aVEvt
.mpObj
) != nullptr))
202 // When clicking into a URl field, also go to text edit mode (when not following the link)
203 if (!bTextEdit
&& eHit
== SdrHitKind::UrlField
&& !rMEvt
.IsMod2() && !lcl_followHyperlinkAllowed(rMEvt
))
206 bool bPreventModify
= mpDocSh
->IsReadOnly();
207 if (bPreventModify
&& mpDocSh
->GetSignPDFCertificate().is())
209 // If the just added signature line shape is selected, allow moving / resizing it.
210 bPreventModify
= false;
215 && ((mpView
->IsMarkedHit(aMDPos
, nHitLog
) && !rMEvt
.IsShift() && !rMEvt
.IsMod2()) || pHdl
!= nullptr)
216 && (rMEvt
.GetClicks() != 2)
219 if (!pHdl
&& mpView
->Is3DRotationCreationActive())
221 // Switch between 3D-rotation body -> selection
222 mpView
->ResetCreationActive();
226 // Remember the selected object for proper handling in
228 pWaterCanCandidate
= pickObject (aMDPos
);
232 // hit handle or marked object
233 bFirstMouseMove
= true;
237 if ( ! rMEvt
.IsRight())
238 if (mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
))
239 mpView
->GetDragMethod()->SetShiftPressed( rMEvt
.IsShift() );
244 SdrPageView
* pPV
= nullptr;
245 SdrObject
* pObj
= !rMEvt
.IsMod2() ? mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMACRO
) : nullptr;
248 mpView
->BegMacroObj(aMDPos
, nHitLog
, pObj
, pPV
, mpWindow
);
251 else if ( bTextEdit
)
253 SdrObjKind nSdrObjKind
= aVEvt
.mpObj
->GetObjIdentifier();
255 if (aVEvt
.mpObj
->GetObjInventor() == SdrInventor::Default
&&
256 (nSdrObjKind
== SdrObjKind::Text
||
257 nSdrObjKind
== SdrObjKind::TitleText
||
258 nSdrObjKind
== SdrObjKind::OutlineText
||
259 !aVEvt
.mpObj
->IsEmptyPresObj()))
261 // Seamless Editing: branch to text input
262 if (!rMEvt
.IsShift())
265 SfxUInt16Item
aItem(SID_TEXTEDIT
, 1);
266 mpViewShell
->GetViewFrame()->GetDispatcher()->
267 ExecuteList(SID_TEXTEDIT
,
268 SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
,
270 return bReturn
; // CAUTION, due to the synchronous slot the object is deleted now
273 else if ( !rMEvt
.IsMod2() && rMEvt
.GetClicks() == 1 &&
274 aVEvt
.meEvent
== SdrEventKind::ExecuteUrl
)
276 mpWindow
->ReleaseMouse();
278 if (!aVEvt
.mpURLField
)
281 // If tiled rendering, let client handles URL execution and early returns.
282 if (comphelper::LibreOfficeKit::isActive())
284 SfxViewShell
& rSfxViewShell
= mpViewShell
->GetViewShellBase();
285 rSfxViewShell
.libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED
, aVEvt
.mpURLField
->GetURL().toUtf8());
289 if (!lcl_followHyperlinkAllowed(rMEvt
))
292 SfxStringItem
aStrItem(SID_FILE_NAME
, aVEvt
.mpURLField
->GetURL());
293 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
294 SfxBoolItem
aBrowseItem( SID_BROWSE
, true );
295 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
296 mpWindow
->ReleaseMouse();
301 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
302 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
303 { &aStrItem
, &aBrowseItem
, &aReferer
});
307 // Open in current frame
308 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
309 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
310 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
311 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
316 else if(!rMEvt
.IsMod2()
317 && dynamic_cast< const DrawViewShell
*>( mpViewShell
) != nullptr
320 pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
);
323 // Handle ImageMap click when not just selecting
326 if (lcl_followHyperlinkAllowed(rMEvt
))
327 bReturn
= HandleImageMapClick(pObj
, aMDPos
);
331 && (dynamic_cast<const SdrObjGroup
*>(pObj
) != nullptr
332 || DynCastE3dScene(pObj
)))
334 if (rMEvt
.GetClicks() == 1)
336 // Look into the group
337 pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
,
338 SdrSearchOptions::ALSOONMASTER
339 | SdrSearchOptions::DEEP
);
340 if (pObj
&& lcl_followHyperlinkAllowed(rMEvt
))
341 bReturn
= HandleImageMapClick(pObj
, aMDPos
);
343 else if (!bReadOnly
&& rMEvt
.GetClicks() == 2)
345 // New: double click on selected Group object
348 && pObj
->getSdrPageFromSdrObject() == pPV
->GetPage())
349 bReturn
= pPV
->EnterGroup(pObj
);
354 // #i71727# replaced else here with two possibilities, once the original else (!pObj)
355 // and also ignoring the found object when it's on a masterpage
356 if(!pObj
|| (pObj
->getSdrPageFromSdrObject() && pObj
->getSdrPageFromSdrObject()->IsMasterPage()))
358 if(mpView
->IsGroupEntered() && 2 == rMEvt
.GetClicks())
360 // New: double click on empty space/on obj on MasterPage, leave group
361 mpView
->LeaveOneGroup();
371 if ( ! (rMEvt
.IsShift() || rMEvt
.IsMod2()))
373 // Find the object under the current mouse position
374 // and store it for the MouseButtonUp() method to
376 pWaterCanCandidate
= pickObject (aMDPos
);
382 bool bDeactivateOLE
= false;
384 if ( !rMEvt
.IsShift() && !rMEvt
.IsMod2() )
386 OSL_ASSERT (mpViewShell
->GetViewShell()!=nullptr);
387 Client
* pIPClient
= static_cast<Client
*>(
388 mpViewShell
->GetViewShell()->GetIPClient());
390 if (pIPClient
&& pIPClient
->IsObjectInPlaceActive())
392 // OLE-object gets deactivated in subsequent UnmarkAll()
393 bDeactivateOLE
= true;
399 bool bMarked
= false;
401 if ( !rMEvt
.IsMod1() && !bDeactivateOLE
)
403 if ( rMEvt
.IsMod2() )
405 bMarked
= mpView
->MarkNextObj(aMDPos
, nHitLog
, rMEvt
.IsShift() );
409 bool bToggle
= false;
411 const SdrMarkList
& rMarkList
= mpView
->GetMarkedObjectList();
412 if (rMEvt
.IsShift() && rMarkList
.GetMarkCount() > 1)
414 // No Toggle on single selection
418 bMarked
= mpView
->MarkObj(aMDPos
, nHitLog
, bToggle
);
422 if( !bDeactivateOLE
)
426 (!rMEvt
.IsShift() || mpView
->IsMarkedHit(aMDPos
, nHitLog
)))
428 /**********************************************************
430 **********************************************************/
433 pHdl
=mpView
->PickHandle(aMDPos
);
434 if ( ! rMEvt
.IsRight())
435 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
439 /**********************************************************
441 **********************************************************/
442 if ( ! rMEvt
.IsRight())
443 mpView
->BegMarkObj(aMDPos
);
447 if( bMarked
&& bTempRotation
&& (nSlotId
== SID_OBJECT_ROTATE
) && !rMEvt
.IsShift() && (rMEvt
.GetClicks() != 2) )
449 nSlotId
= SID_OBJECT_SELECT
;
457 && (rMEvt
.IsLeft() || rMEvt
.IsRight())
458 && !mpView
->IsAction())
460 /**********************************************************************
462 **********************************************************************/
463 mpWindow
->CaptureMouse();
465 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
467 if (eHit
== SdrHitKind::Handle
&& aVEvt
.mpHdl
->GetKind() == SdrHdlKind::BezierWeight
)
469 /******************************************************************
471 ******************************************************************/
472 if ( ! rMEvt
.IsRight())
473 mpView
->BegDragObj(aMDPos
, nullptr, aVEvt
.mpHdl
, nDrgLog
);
475 else if (eHit
== SdrHitKind::MarkedObject
&& nEditMode
== SID_BEZIER_INSERT
)
477 /******************************************************************
479 ******************************************************************/
480 mpView
->BegInsObjPoint(aMDPos
, rMEvt
.IsMod1());
482 else if (eHit
== SdrHitKind::MarkedObject
&& rMEvt
.IsMod1())
484 /******************************************************************
486 ******************************************************************/
487 if (!rMEvt
.IsShift())
488 mpView
->UnmarkAllPoints();
490 if ( ! rMEvt
.IsRight())
491 mpView
->BegMarkPoints(aMDPos
);
493 else if (eHit
== SdrHitKind::MarkedObject
&& !rMEvt
.IsShift() && !rMEvt
.IsMod2())
495 /******************************************************************
497 ******************************************************************/
498 if ( ! rMEvt
.IsRight())
499 mpView
->BegDragObj(aMDPos
, nullptr, nullptr, nDrgLog
);
501 else if (eHit
== SdrHitKind::Handle
)
503 /******************************************************************
505 ******************************************************************/
506 if (!mpView
->IsPointMarked(*aVEvt
.mpHdl
) || rMEvt
.IsShift())
508 if (!rMEvt
.IsShift())
510 mpView
->UnmarkAllPoints();
511 pHdl
= mpView
->PickHandle(aMDPos
);
515 if (mpView
->IsPointMarked(*aVEvt
.mpHdl
))
517 mpView
->UnmarkPoint(*aVEvt
.mpHdl
);
522 pHdl
= mpView
->PickHandle(aMDPos
);
528 mpView
->MarkPoint(*pHdl
);
529 if ( ! rMEvt
.IsRight())
530 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
536 // Point IS marked and NO shift is pressed. Start
537 // dragging of selected point(s)
538 pHdl
= mpView
->PickHandle(aMDPos
);
539 if(pHdl
&& ! rMEvt
.IsRight())
540 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
545 /******************************************************************
546 * Select or drag object
547 ******************************************************************/
548 if (!rMEvt
.IsShift() && !rMEvt
.IsMod2() && eHit
== SdrHitKind::UnmarkedObject
)
550 mpView
->UnmarkAllObj();
553 bool bMarked
= false;
559 bMarked
= mpView
->MarkNextObj(aMDPos
, nHitLog
, rMEvt
.IsShift());
563 bMarked
= mpView
->MarkObj(aMDPos
, nHitLog
, rMEvt
.IsShift());
567 const SdrMarkList
& rMarkList
= mpView
->GetMarkedObjectList();
569 (!rMEvt
.IsShift() || eHit
== SdrHitKind::MarkedObject
))
572 if ( ! rMEvt
.IsRight())
573 mpView
->BegDragObj(aMDPos
, nullptr, aVEvt
.mpHdl
, nDrgLog
);
575 else if (rMarkList
.GetMarkCount() != 0)
577 /**************************************************************
579 **************************************************************/
580 if (!rMEvt
.IsShift())
581 mpView
->UnmarkAllPoints();
583 if ( ! rMEvt
.IsRight())
584 mpView
->BegMarkPoints(aMDPos
);
588 /**************************************************************
590 **************************************************************/
591 if ( ! rMEvt
.IsRight())
592 mpView
->BegMarkObj(aMDPos
);
595 ForcePointer(&rMEvt
);
601 ForcePointer(&rMEvt
);
607 bool FuSelection::MouseMove(const MouseEvent
& rMEvt
)
609 bool bReturn
= FuDraw::MouseMove(rMEvt
);
611 if (aDragTimer
.IsActive())
615 bFirstMouseMove
= false;
623 if (mpView
->IsAction())
625 Point
aPix(rMEvt
.GetPosPixel());
626 Point
aPnt(mpWindow
->PixelToLogic(aPix
));
630 if (mpView
->IsInsObjPoint())
632 mpView
->MovInsObjPoint(aPnt
);
636 mpView
->MovAction(aPnt
);
640 ForcePointer(&rMEvt
);
645 bool FuSelection::MouseButtonUp(const MouseEvent
& rMEvt
)
647 bool bReturn
= false;
648 // When the right mouse button is pressed then only select objects
649 // (and deselect others) as a preparation for showing the context
651 const bool bSelectionOnly
= rMEvt
.IsRight();
653 if (aDragTimer
.IsActive() )
656 bIsInDragMode
= false;
662 Point
aPnt( mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() ) );
663 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
664 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(mpView
->GetDragThresholdPixels(),0)).Width() );
666 bool bWasDragged
= false;
667 if (mpView
->IsFrameDragSingles() || !mpView
->HasMarkablePoints())
669 /**********************************************************************
671 **********************************************************************/
672 if ( mpView
->IsDragObj() )
674 /******************************************************************
676 ******************************************************************/
677 FrameView
* pFrameView
= mpViewShell
->GetFrameView();
678 bool bDragWithCopy
= (rMEvt
.IsMod1() && pFrameView
->IsDragWithCopy());
682 bDragWithCopy
= !mpView
->IsPresObjSelected(false);
685 mpView
->SetDragWithCopy(bDragWithCopy
);
686 bWasDragged
= mpView
->EndDragObj(mpView
->IsDragWithCopy());
688 mpView
->ForceMarkedToAnotherPage();
690 if (!rMEvt
.IsShift() && !rMEvt
.IsMod1() && !rMEvt
.IsMod2() &&
691 !bSelectionChanged
&&
692 std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
&&
693 std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
695 /*************************************************************
696 * If a user wants to click on an object in front of a marked
697 * one, he releases the mouse button immediately
698 **************************************************************/
700 SdrObject
* pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
| SdrSearchOptions::BEFOREMARK
);
701 if (pObj
&& pPV
->IsObjMarkable(pObj
))
703 mpView
->UnmarkAllObj();
704 mpView
->MarkObj(pObj
,pPV
);
708 // check for single object selected
709 SdrObject
* pSingleObj
= nullptr;
711 const SdrMarkList
& rMarkList
= mpView
->GetMarkedObjectList();
712 if (rMarkList
.GetMarkCount()==1)
714 pSingleObj
= rMarkList
.GetMark(0)->GetMarkedSdrObj();
717 // Check for click on svx::diagram::DiagramFrameHdl
718 // - if we hit a SdrHdl
719 // - if it was not moved
720 // - if single object is selected
721 // - and it is a Diagram
722 if(pHdl
&& !bWasDragged
&& nullptr != pSingleObj
&& pSingleObj
->isDiagram())
724 svx::diagram::DiagramFrameHdl
* pDiagramFrameHdl(dynamic_cast<svx::diagram::DiagramFrameHdl
*>(pHdl
));
725 if(nullptr != pDiagramFrameHdl
)
727 // let the DiagramFrameHdl decide what to do
728 svx::diagram::DiagramFrameHdl::clicked(aPnt
);
732 /**************************************************************
733 * Toggle between selection and rotation
734 **************************************************************/
735 if (nSlotId
== SID_OBJECT_SELECT
736 && !comphelper::LibreOfficeKit::isActive()
737 && mpView
->IsRotateAllowed()
739 && (rMEvt
.GetClicks() != 2)
740 && (mpViewShell
->GetFrameView()->IsClickChangeRotation()
742 && pSingleObj
->GetObjInventor()==SdrInventor::E3d
))
746 bTempRotation
= true;
747 nSlotId
= SID_OBJECT_ROTATE
;
750 else if (nSlotId
== SID_OBJECT_ROTATE
)
752 nSlotId
= SID_OBJECT_SELECT
;
756 else if (nSlotId
== SID_CONVERT_TO_3D_LATHE
)
760 bSuppressChangesOfSelection
= true;
761 mpView
->Start3DCreation();
762 bSuppressChangesOfSelection
= false;
764 else if (pHdl
->GetKind() != SdrHdlKind::MirrorAxis
&&
765 pHdl
->GetKind() != SdrHdlKind::Ref1
&&
766 pHdl
->GetKind() != SdrHdlKind::Ref2
&& mpView
->Is3DRotationCreationActive())
768 /*********************************************************
769 * If 3D-rotation bodies are about to be created,
771 **********************************************************/
772 Degree100 nAngle1
= GetAngle(aPnt
- mpView
->GetRef1());
773 nAngle1
-= 27000_deg100
;
774 nAngle1
= NormAngle36000(nAngle1
);
775 bool bMirrorSide1
= nAngle1
< 18000_deg100
;
777 if (bMirrorSide0
!= bMirrorSide1
)
779 bSuppressChangesOfSelection
= true;
780 mpWindow
->EnterWait();
781 mpView
->End3DCreation();
782 bSuppressChangesOfSelection
= false;
783 nSlotId
= SID_OBJECT_SELECT
;
784 mpWindow
->LeaveWait();
790 else if (rMEvt
.IsMod1()
792 && std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
793 && std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
796 mpView
->MarkObj(aPnt
, nHitLog
, rMEvt
.IsShift(), rMEvt
.IsMod1());
799 if (mpView
->IsAction() )
804 if (SdModule::get()->GetWaterCan())
806 if( rMEvt
.IsRight() )
808 // In watering-can mode, on press onto right mouse button, an undo is executed
809 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute( SID_UNDO
, SfxCallMode::ASYNCHRON
);
811 else if (pWaterCanCandidate
!= nullptr)
813 // Is the candidate object still under the mouse?
814 if (pickObject (aPnt
) == pWaterCanCandidate
)
816 SdStyleSheetPool
* pPool
= static_cast<SdStyleSheetPool
*>(
817 mpDocSh
->GetStyleSheetPool());
818 if (pPool
!= nullptr)
820 SfxStyleSheet
* pStyleSheet
= static_cast<SfxStyleSheet
*>(
821 pPool
->GetActualStyleSheet());
822 if (pStyleSheet
!= nullptr && mpView
->IsUndoEnabled() )
824 // Added UNDOs for the WaterCan mode. This was never done in
825 // the past, thus it was missing all the time.
826 std::unique_ptr
<SdrUndoAction
> pUndoAttr
= mpDoc
->GetSdrUndoFactory().CreateUndoAttrObject(*pWaterCanCandidate
, true, true);
827 mpView
->BegUndo(pUndoAttr
->GetComment());
828 mpView
->AddUndo(mpDoc
->GetSdrUndoFactory().CreateUndoGeoObject(*pWaterCanCandidate
));
829 mpView
->AddUndo(std::move(pUndoAttr
));
831 pWaterCanCandidate
->SetStyleSheet (pStyleSheet
, false);
838 // else when there has been no object under the mouse when the
839 // button was pressed then nothing happens even when there is
843 sal_uInt16 nClicks
= rMEvt
.GetClicks();
845 if (nClicks
== 2 && rMEvt
.IsLeft() && bMBDown
&&
846 !rMEvt
.IsMod1() && !rMEvt
.IsShift() )
853 ForcePointer(&rMEvt
);
855 mpWindow
->ReleaseMouse();
856 SdrObject
* pSingleObj
= nullptr;
857 const SdrMarkList
& rMarkList
= mpView
->GetMarkedObjectList();
858 const size_t nMarkCount
= rMarkList
.GetMarkCount();
862 pSingleObj
= rMarkList
.GetMark(0)->GetMarkedSdrObj();
865 if (!bWasDragged
&& pSingleObj
&& pSingleObj
->isAnnotationObject() && rMEvt
.IsLeft())
867 auto& pAnnotationData
= pSingleObj
->getAnnotationData();
870 auto* pDrawViewShell
= dynamic_cast<DrawViewShell
*>(mpViewShell
);
871 if (pDrawViewShell
&& pDrawViewShell
->getAnnotationManagerPtr())
873 pDrawViewShell
->getAnnotationManagerPtr()->SelectAnnotation(pAnnotationData
->mxAnnotation
);
875 pAnnotationData
->openPopup();
880 if ( (nSlotId
!= SID_OBJECT_SELECT
&& nMarkCount
==0) ||
881 ( mpView
->GetDragMode() == SdrDragMode::Crook
&&
882 !mpView
->IsCrookAllowed( mpView
->IsCrookNoContortion() ) ) ||
883 ( mpView
->GetDragMode() == SdrDragMode::Shear
&&
884 !mpView
->IsShearAllowed() && !mpView
->IsDistortAllowed() ) ||
885 ( nSlotId
==SID_CONVERT_TO_3D_LATHE
&& pSingleObj
&&
886 (pSingleObj
->GetObjInventor() != SdrInventor::Default
||
887 pSingleObj
->GetObjIdentifier() == SdrObjKind::Measure
) ) )
890 ForcePointer(&rMEvt
);
892 mpWindow
->ReleaseMouse();
893 FuDraw::MouseButtonUp(rMEvt
);
894 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::SYNCHRON
);
895 return bReturn
; // CAUTION, due to the synchronous slot, the object is deleted now.
898 FuDraw::MouseButtonUp(rMEvt
);
902 /**********************************************************************
904 **********************************************************************/
905 if ( mpView
->IsAction() )
907 if ( mpView
->IsInsObjPoint() )
909 mpView
->EndInsObjPoint(SdrCreateCmd::ForceEnd
);
911 else if ( mpView
->IsDragObj() )
913 FrameView
* pFrameView
= mpViewShell
->GetFrameView();
914 bool bDragWithCopy
= (rMEvt
.IsMod1() && pFrameView
->IsDragWithCopy());
918 bDragWithCopy
= !mpView
->IsPresObjSelected(false);
921 mpView
->SetDragWithCopy(bDragWithCopy
);
922 mpView
->EndDragObj( mpView
->IsDragWithCopy() );
928 sal_uInt16 nDrgLog2
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(mpView
->GetDragThresholdPixels(),0)).Width() );
929 Point aPos
= mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() );
931 if (std::abs(aMDPos
.X() - aPos
.X()) < nDrgLog2
&&
932 std::abs(aMDPos
.Y() - aPos
.Y()) < nDrgLog2
&&
933 !rMEvt
.IsShift() && !rMEvt
.IsMod2())
936 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
938 if (eHit
== SdrHitKind::NONE
)
940 // Click on the same place - unselect
941 mpView
->UnmarkAllObj();
946 else if (!rMEvt
.IsShift() && rMEvt
.IsMod1() && !rMEvt
.IsMod2() &&
947 std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
&&
948 std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
951 mpView
->MarkObj(aPnt
, nHitLog
, false, rMEvt
.IsMod1());
954 ForcePointer(&rMEvt
);
956 mpWindow
->ReleaseMouse();
958 FuDraw::MouseButtonUp(rMEvt
);
965 * Process keyboard input
966 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
968 bool FuSelection::KeyInput(const KeyEvent
& rKEvt
)
970 bool bReturn
= false;
972 switch (rKEvt
.GetKeyCode().GetCode())
976 bReturn
= FuSelection::cancel();
979 //add keyboard operation for insert points in drawing curve
985 if(rKEvt
.GetKeyCode().IsShift()&&(nEditMode
== SID_BEZIER_INSERT
)){
986 ::tools::Long nX
= 0;
987 ::tools::Long nY
= 0;
988 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
995 else if (nCode
== KEY_DOWN
)
1001 else if (nCode
== KEY_LEFT
)
1007 else if (nCode
== KEY_RIGHT
)
1015 ::tools::Rectangle rect
= mpView
->GetMarkedObjRect();
1016 centerPoint
= mpWindow
->LogicToPixel(rect
.Center());
1017 Point aPoint
= bMovedToCenterPoint
? oldPoint
:centerPoint
;
1018 Point ePoint
= aPoint
+ Point(nX
,nY
);
1019 mpWindow
->SetPointerPosPixel(ePoint
);
1020 //simulate mouse move action
1021 MouseEvent
eMevt(ePoint
, 1, MouseEventModifiers::DRAGMOVE
, MOUSE_LEFT
, 0);
1024 bMovedToCenterPoint
= true;
1030 if(rKEvt
.GetKeyCode().IsShift()&&(nEditMode
== SID_BEZIER_INSERT
))
1032 if(!bBeginInsertPoint
)
1034 //simulate mouse button down action
1035 MouseEvent
aMevt(oldPoint
, 1,
1036 MouseEventModifiers::SIMPLEMOVE
| MouseEventModifiers::DRAGMOVE
,
1037 MOUSE_LEFT
, KEY_SHIFT
);
1038 MouseButtonDown(aMevt
);
1039 mpWindow
->CaptureMouse();
1040 bBeginInsertPoint
= true;
1044 //simulate mouse button up action
1045 MouseEvent
rMEvt(oldPoint
, 1,
1046 MouseEventModifiers::SIMPLEMOVE
| MouseEventModifiers::ENTERWINDOW
,
1047 MOUSE_LEFT
, KEY_SHIFT
);
1048 MouseButtonUp(rMEvt
);
1049 bBeginInsertPoint
= false;
1057 bReturn
= FuDraw::KeyInput(rKEvt
);
1059 const SdrMarkList
& rMarkList
= mpView
->GetMarkedObjectList();
1060 if(rMarkList
.GetMarkCount() == 0)
1062 mpView
->ResetCreationActive();
1064 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1072 void FuSelection::Activate()
1075 mpView
->ResetCreationActive();
1076 mpView
->SetEditMode(SdrViewEditMode::Edit
);
1080 case SID_OBJECT_ROTATE
:
1082 eMode
= SdrDragMode::Rotate
;
1084 if ( mpView
->GetDragMode() != eMode
)
1085 mpView
->SetDragMode(eMode
);
1089 case SID_OBJECT_MIRROR
:
1091 eMode
= SdrDragMode::Mirror
;
1093 if ( mpView
->GetDragMode() != eMode
)
1094 mpView
->SetDragMode(eMode
);
1098 case SID_OBJECT_CROP
:
1100 eMode
= SdrDragMode::Crop
;
1102 if ( mpView
->GetDragMode() != eMode
)
1103 mpView
->SetDragMode(eMode
);
1107 case SID_OBJECT_TRANSPARENCE
:
1109 eMode
= SdrDragMode::Transparence
;
1111 if ( mpView
->GetDragMode() != eMode
)
1112 mpView
->SetDragMode(eMode
);
1116 case SID_OBJECT_GRADIENT
:
1118 eMode
= SdrDragMode::Gradient
;
1120 if ( mpView
->GetDragMode() != eMode
)
1121 mpView
->SetDragMode(eMode
);
1125 case SID_OBJECT_SHEAR
:
1127 eMode
= SdrDragMode::Shear
;
1129 if ( mpView
->GetDragMode() != eMode
)
1130 mpView
->SetDragMode(eMode
);
1134 case SID_OBJECT_CROOK_ROTATE
:
1136 eMode
= SdrDragMode::Crook
;
1138 if ( mpView
->GetDragMode() != eMode
)
1140 mpView
->SetDragMode(eMode
);
1141 mpView
->SetCrookMode(SdrCrookMode::Rotate
);
1146 case SID_OBJECT_CROOK_SLANT
:
1148 eMode
= SdrDragMode::Crook
;
1150 if ( mpView
->GetDragMode() != eMode
)
1152 mpView
->SetDragMode(eMode
);
1153 mpView
->SetCrookMode(SdrCrookMode::Slant
);
1158 case SID_OBJECT_CROOK_STRETCH
:
1160 eMode
= SdrDragMode::Crook
;
1162 if ( mpView
->GetDragMode() != eMode
)
1164 mpView
->SetDragMode(eMode
);
1165 mpView
->SetCrookMode(SdrCrookMode::Stretch
);
1170 case SID_CONVERT_TO_3D_LATHE
:
1172 eMode
= SdrDragMode::Mirror
;
1173 bSuppressChangesOfSelection
= true;
1175 if ( mpView
->GetDragMode() != eMode
)
1176 mpView
->SetDragMode(eMode
);
1178 if (!mpView
->Is3DRotationCreationActive())
1179 mpView
->Start3DCreation();
1181 bSuppressChangesOfSelection
= false;
1187 eMode
= SdrDragMode::Move
;
1189 if ( mpView
->GetDragMode() != eMode
)
1190 mpView
->SetDragMode(eMode
);
1195 if (nSlotId
!= SID_OBJECT_ROTATE
)
1197 bTempRotation
= false;
1203 void FuSelection::SelectionHasChanged()
1205 bSelectionChanged
= true;
1207 FuDraw::SelectionHasChanged();
1209 if (mpView
->Is3DRotationCreationActive() && !bSuppressChangesOfSelection
)
1211 // Switch rotation body -> selection
1212 mpView
->ResetCreationActive();
1213 nSlotId
= SID_OBJECT_SELECT
;
1217 // Activate the right tool bar for the current context of the view.
1218 mpViewShell
->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(*mpViewShell
, *mpView
);
1222 * Set current bezier edit mode
1224 void FuSelection::SetEditMode(sal_uInt16 nMode
)
1228 if (nEditMode
== SID_BEZIER_INSERT
)
1230 mpView
->SetInsObjPointMode(true);
1234 mpView
->SetInsObjPointMode(false);
1239 SfxBindings
& rBindings
= mpViewShell
->GetViewFrame()->GetBindings();
1240 rBindings
.Invalidate(SID_BEZIER_MOVE
);
1241 rBindings
.Invalidate(SID_BEZIER_INSERT
);
1245 * Execute ImageMap interaction
1247 bool FuSelection::HandleImageMapClick(const SdrObject
* pObj
, const Point
& rPos
)
1249 bool bClosed
= pObj
->IsClosedObj();
1250 bool bFilled
= false;
1254 SfxItemSet
aSet(mpDoc
->GetPool());
1256 aSet
.Put(pObj
->GetMergedItemSet());
1258 const XFillStyleItem
& rFillStyle
= aSet
.Get(XATTR_FILLSTYLE
);
1259 bFilled
= rFillStyle
.GetValue() != drawing::FillStyle_NONE
;
1262 const SdrLayerIDSet
* pVisiLayer
= &mpView
->GetSdrPageView()->GetVisibleLayers();
1263 double fHitLog
= mpWindow
->PixelToLogic(Size(HITPIX
, 0)).Width();
1264 const ::tools::Long n2HitLog
= fHitLog
* 2;
1265 Point
aHitPosR(rPos
);
1266 Point
aHitPosL(rPos
);
1267 Point
aHitPosT(rPos
);
1268 Point
aHitPosB(rPos
);
1270 aHitPosR
.AdjustX(n2HitLog
);
1271 aHitPosL
.AdjustX(-n2HitLog
);
1272 aHitPosT
.AdjustY(n2HitLog
);
1273 aHitPosB
.AdjustY(-n2HitLog
);
1275 if (!bClosed
|| !bFilled
1276 || (SdrObjectPrimitiveHit(*pObj
, aHitPosR
, {fHitLog
, fHitLog
}, *mpView
->GetSdrPageView(), pVisiLayer
,
1278 && SdrObjectPrimitiveHit(*pObj
, aHitPosL
, {fHitLog
, fHitLog
}, *mpView
->GetSdrPageView(),
1280 && SdrObjectPrimitiveHit(*pObj
, aHitPosT
, {fHitLog
, fHitLog
}, *mpView
->GetSdrPageView(),
1282 && SdrObjectPrimitiveHit(*pObj
, aHitPosB
, {fHitLog
, fHitLog
}, *mpView
->GetSdrPageView(),
1283 pVisiLayer
, false)))
1285 if (SvxIMapInfo::GetIMapInfo(pObj
))
1287 const IMapObject
* pIMapObj
= SvxIMapInfo::GetHitIMapObject(pObj
, rPos
);
1289 if (pIMapObj
&& !pIMapObj
->GetURL().isEmpty())
1292 mpWindow
->ReleaseMouse();
1293 SfxStringItem
aStrItem(SID_FILE_NAME
, pIMapObj
->GetURL());
1294 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
1295 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
1296 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
1297 SfxBoolItem
aBrowseItem(SID_BROWSE
, true);
1298 mpWindow
->ReleaseMouse();
1299 pFrame
->GetDispatcher()->ExecuteList(
1300 SID_OPENDOC
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1301 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
1311 /** is called when the current function should be aborted. <p>
1312 This is used when a function gets a KEY_ESCAPE but can also
1315 @returns true if an active function was aborted
1317 bool FuSelection::cancel()
1319 if (mpView
->Is3DRotationCreationActive())
1321 mpView
->ResetCreationActive();
1322 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1331 SdrObject
* FuSelection::pickObject (const Point
& rTestPoint
)
1333 SdrPageView
* pPageView
;
1334 sal_uInt16 nHitLog
= sal_uInt16 (mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width());
1335 return mpView
->PickObj(rTestPoint
, nHitLog
, pPageView
, SdrSearchOptions::PICKMARKABLE
);
1338 void FuSelection::ForcePointer(const MouseEvent
* pMEvt
)
1340 if(bMovedToCenterPoint
&& !bBeginInsertPoint
&& pMEvt
)
1342 MouseEvent
aMEvt(pMEvt
->GetPosPixel(), pMEvt
->GetClicks(),
1343 pMEvt
->GetMode(), pMEvt
->GetButtons(), pMEvt
->GetModifier() & ~KEY_SHIFT
);
1344 FuDraw::ForcePointer(&aMEvt
);
1348 FuDraw::ForcePointer(pMEvt
);
1352 } // end of namespace sd
1354 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */