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>
55 #include <svx/svdundo.hxx>
57 #include <svx/sdrhittesthelper.hxx>
58 #include <svx/diagram/IDiagramHelper.hxx>
60 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
61 #include <comphelper/lok.hxx>
63 using namespace ::com::sun::star
;
67 FuSelection::FuSelection (
73 : FuDraw(pViewSh
, pWin
, pView
, pDoc
, rReq
),
75 bSelectionChanged(false),
77 bSuppressChangesOfSelection(false),
79 nEditMode(SID_BEZIER_MOVE
),
80 pWaterCanCandidate(nullptr)
81 //Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point,
82 //and SHIFT+ENTER key to decide the position and draw the new insert point
83 ,bBeginInsertPoint(false),
85 ,bMovedToCenterPoint(false)
89 rtl::Reference
<FuPoor
> FuSelection::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
)
91 rtl::Reference
<FuPoor
> xFunc( new FuSelection( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
92 xFunc
->DoExecute(rReq
);
96 void FuSelection::DoExecute( SfxRequest
& rReq
)
98 FuDraw::DoExecute( rReq
);
101 SelectionHasChanged();
104 FuSelection::~FuSelection()
106 mpView
->UnmarkAllPoints();
107 mpView
->ResetCreationActive();
109 if ( mpView
->GetDragMode() != SdrDragMode::Move
)
111 mpView
->SetDragMode(SdrDragMode::Move
);
116 bool lcl_followHyperlinkAllowed(const MouseEvent
& rMEvt
) {
117 if (!rMEvt
.IsMod1() && SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink
))
119 if (rMEvt
.IsMod1() && !SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink
))
125 bool FuSelection::MouseButtonDown(const MouseEvent
& rMEvt
)
128 bool bReturn
= FuDraw::MouseButtonDown(rMEvt
);
129 bool bWaterCan
= SD_MOD()->GetWaterCan();
130 const bool bReadOnly
= mpDocSh
->IsReadOnly();
131 // When the right mouse button is pressed then only select objects
132 // (and deselect others) as a preparation for showing the context
134 const bool bSelectionOnly
= rMEvt
.IsRight();
137 bSelectionChanged
= false;
139 if ( mpView
->IsAction() )
141 if ( rMEvt
.IsRight() )
146 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(mpView
->GetDragThresholdPixels(),0)).Width() );
147 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
149 if (comphelper::LibreOfficeKit::isActive())
151 // When tiled rendering, we always work in logic units, use the non-pixel constants.
156 // The following code is executed for right clicks as well as for left
157 // clicks in order to modify the selection for the right button as a
158 // preparation for the context menu. The functions BegMarkObject() and
159 // BegDragObject(), however, are not called for right clicks because a)
160 // it makes no sense and b) to have IsAction() return sal_False when called
161 // from Command() which is a prerequisite for the context menu.
162 if ((rMEvt
.IsLeft() || rMEvt
.IsRight())
163 && !mpView
->IsAction()
164 && (mpView
->IsFrameDragSingles() || !mpView
->HasMarkablePoints()))
166 /******************************************************************
168 ******************************************************************/
169 mpWindow
->CaptureMouse();
170 pHdl
= mpView
->PickHandle(aMDPos
);
172 Degree100 nAngle0
= GetAngle(aMDPos
- mpView
->GetRef1());
173 nAngle0
-= 27000_deg100
;
174 nAngle0
= NormAngle36000(nAngle0
);
175 bMirrorSide0
= nAngle0
< 18000_deg100
;
177 if (!pHdl
&& mpView
->Is3DRotationCreationActive())
179 /******************************************************************
180 * If 3D-rotation bodies are about to be created,
182 ******************************************************************/
183 bSuppressChangesOfSelection
= true;
184 mpWindow
->EnterWait();
185 mpView
->End3DCreation();
186 bSuppressChangesOfSelection
= false;
187 mpView
->ResetCreationActive();
188 mpWindow
->LeaveWait();
191 bool bTextEdit
= false;
193 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
195 if (eHit
== SdrHitKind::TextEditObj
&& (mpViewShell
->GetFrameView()->IsQuickEdit() || dynamic_cast< sdr::table::SdrTableObj
* >(aVEvt
.mpObj
) != nullptr))
200 // When clicking into a URl field, also go to text edit mode (when not following the link)
201 if (!bTextEdit
&& eHit
== SdrHitKind::UrlField
&& !rMEvt
.IsMod2() && !lcl_followHyperlinkAllowed(rMEvt
))
204 bool bPreventModify
= mpDocSh
->IsReadOnly();
205 if (bPreventModify
&& mpDocSh
->GetSignPDFCertificate().is())
207 // If the just added signature line shape is selected, allow moving / resizing it.
208 bPreventModify
= false;
213 && ((mpView
->IsMarkedHit(aMDPos
, nHitLog
) && !rMEvt
.IsShift() && !rMEvt
.IsMod2()) || pHdl
!= nullptr)
214 && (rMEvt
.GetClicks() != 2)
217 if (!pHdl
&& mpView
->Is3DRotationCreationActive())
219 // Switch between 3D-rotation body -> selection
220 mpView
->ResetCreationActive();
224 // Remember the selected object for proper handling in
226 pWaterCanCandidate
= pickObject (aMDPos
);
230 // hit handle or marked object
231 bFirstMouseMove
= true;
235 if ( ! rMEvt
.IsRight())
236 if (mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
))
237 mpView
->GetDragMethod()->SetShiftPressed( rMEvt
.IsShift() );
242 SdrPageView
* pPV
= nullptr;
243 SdrObject
* pObj
= !rMEvt
.IsMod2() ? mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMACRO
) : nullptr;
246 mpView
->BegMacroObj(aMDPos
, nHitLog
, pObj
, pPV
, mpWindow
);
249 else if ( bTextEdit
)
251 SdrObjKind nSdrObjKind
= aVEvt
.mpObj
->GetObjIdentifier();
253 if (aVEvt
.mpObj
->GetObjInventor() == SdrInventor::Default
&&
254 (nSdrObjKind
== SdrObjKind::Text
||
255 nSdrObjKind
== SdrObjKind::TitleText
||
256 nSdrObjKind
== SdrObjKind::OutlineText
||
257 !aVEvt
.mpObj
->IsEmptyPresObj()))
259 // Seamless Editing: branch to text input
260 if (!rMEvt
.IsShift())
263 SfxUInt16Item
aItem(SID_TEXTEDIT
, 1);
264 mpViewShell
->GetViewFrame()->GetDispatcher()->
265 ExecuteList(SID_TEXTEDIT
,
266 SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
,
268 return bReturn
; // CAUTION, due to the synchronous slot the object is deleted now
271 else if ( !rMEvt
.IsMod2() && rMEvt
.GetClicks() == 1 &&
272 aVEvt
.meEvent
== SdrEventKind::ExecuteUrl
)
274 mpWindow
->ReleaseMouse();
276 if (!aVEvt
.mpURLField
)
279 // If tiled rendering, let client handles URL execution and early returns.
280 if (comphelper::LibreOfficeKit::isActive())
282 SfxViewShell
& rSfxViewShell
= mpViewShell
->GetViewShellBase();
283 rSfxViewShell
.libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED
, aVEvt
.mpURLField
->GetURL().toUtf8());
287 if (!lcl_followHyperlinkAllowed(rMEvt
))
290 SfxStringItem
aStrItem(SID_FILE_NAME
, aVEvt
.mpURLField
->GetURL());
291 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
292 SfxBoolItem
aBrowseItem( SID_BROWSE
, true );
293 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
294 mpWindow
->ReleaseMouse();
299 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
300 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
301 { &aStrItem
, &aBrowseItem
, &aReferer
});
305 // Open in current frame
306 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
307 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
308 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
309 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
314 else if(!rMEvt
.IsMod2()
315 && dynamic_cast< const DrawViewShell
*>( mpViewShell
) != nullptr
318 pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
);
321 // Handle ImageMap click when not just selecting
324 if (lcl_followHyperlinkAllowed(rMEvt
))
325 bReturn
= HandleImageMapClick(pObj
, aMDPos
);
329 && (dynamic_cast<const SdrObjGroup
*>(pObj
) != nullptr
330 || DynCastE3dScene(pObj
)))
332 if (rMEvt
.GetClicks() == 1)
334 // Look into the group
335 pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
,
336 SdrSearchOptions::ALSOONMASTER
337 | SdrSearchOptions::DEEP
);
338 if (pObj
&& lcl_followHyperlinkAllowed(rMEvt
))
339 bReturn
= HandleImageMapClick(pObj
, aMDPos
);
341 else if (!bReadOnly
&& rMEvt
.GetClicks() == 2)
343 // New: double click on selected Group object
346 && pObj
->getSdrPageFromSdrObject() == pPV
->GetPage())
347 bReturn
= pPV
->EnterGroup(pObj
);
352 // #i71727# replaced else here with two possibilities, once the original else (!pObj)
353 // and also ignoring the found object when it's on a masterpage
354 if(!pObj
|| (pObj
->getSdrPageFromSdrObject() && pObj
->getSdrPageFromSdrObject()->IsMasterPage()))
356 if(mpView
->IsGroupEntered() && 2 == rMEvt
.GetClicks())
358 // New: double click on empty space/on obj on MasterPage, leave group
359 mpView
->LeaveOneGroup();
369 if ( ! (rMEvt
.IsShift() || rMEvt
.IsMod2()))
371 // Find the object under the current mouse position
372 // and store it for the MouseButtonUp() method to
374 pWaterCanCandidate
= pickObject (aMDPos
);
380 bool bDeactivateOLE
= false;
382 if ( !rMEvt
.IsShift() && !rMEvt
.IsMod2() )
384 OSL_ASSERT (mpViewShell
->GetViewShell()!=nullptr);
385 Client
* pIPClient
= static_cast<Client
*>(
386 mpViewShell
->GetViewShell()->GetIPClient());
388 if (pIPClient
&& pIPClient
->IsObjectInPlaceActive())
390 // OLE-object gets deactivated in subsequent UnmarkAll()
391 bDeactivateOLE
= true;
397 bool bMarked
= false;
399 if ( !rMEvt
.IsMod1() && !bDeactivateOLE
)
401 if ( rMEvt
.IsMod2() )
403 bMarked
= mpView
->MarkNextObj(aMDPos
, nHitLog
, rMEvt
.IsShift() );
407 bool bToggle
= false;
409 if (rMEvt
.IsShift() && mpView
->GetMarkedObjectList().GetMarkCount() > 1)
411 // No Toggle on single selection
415 bMarked
= mpView
->MarkObj(aMDPos
, nHitLog
, bToggle
);
419 if( !bDeactivateOLE
)
423 (!rMEvt
.IsShift() || mpView
->IsMarkedHit(aMDPos
, nHitLog
)))
425 /**********************************************************
427 **********************************************************/
430 pHdl
=mpView
->PickHandle(aMDPos
);
431 if ( ! rMEvt
.IsRight())
432 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
436 /**********************************************************
438 **********************************************************/
439 if ( ! rMEvt
.IsRight())
440 mpView
->BegMarkObj(aMDPos
);
444 if( bMarked
&& bTempRotation
&& (nSlotId
== SID_OBJECT_ROTATE
) && !rMEvt
.IsShift() && (rMEvt
.GetClicks() != 2) )
446 nSlotId
= SID_OBJECT_SELECT
;
454 && (rMEvt
.IsLeft() || rMEvt
.IsRight())
455 && !mpView
->IsAction())
457 /**********************************************************************
459 **********************************************************************/
460 mpWindow
->CaptureMouse();
462 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
464 if (eHit
== SdrHitKind::Handle
&& aVEvt
.mpHdl
->GetKind() == SdrHdlKind::BezierWeight
)
466 /******************************************************************
468 ******************************************************************/
469 if ( ! rMEvt
.IsRight())
470 mpView
->BegDragObj(aMDPos
, nullptr, aVEvt
.mpHdl
, nDrgLog
);
472 else if (eHit
== SdrHitKind::MarkedObject
&& nEditMode
== SID_BEZIER_INSERT
)
474 /******************************************************************
476 ******************************************************************/
477 mpView
->BegInsObjPoint(aMDPos
, rMEvt
.IsMod1());
479 else if (eHit
== SdrHitKind::MarkedObject
&& rMEvt
.IsMod1())
481 /******************************************************************
483 ******************************************************************/
484 if (!rMEvt
.IsShift())
485 mpView
->UnmarkAllPoints();
487 if ( ! rMEvt
.IsRight())
488 mpView
->BegMarkPoints(aMDPos
);
490 else if (eHit
== SdrHitKind::MarkedObject
&& !rMEvt
.IsShift() && !rMEvt
.IsMod2())
492 /******************************************************************
494 ******************************************************************/
495 if ( ! rMEvt
.IsRight())
496 mpView
->BegDragObj(aMDPos
, nullptr, nullptr, nDrgLog
);
498 else if (eHit
== SdrHitKind::Handle
)
500 /******************************************************************
502 ******************************************************************/
503 if (!mpView
->IsPointMarked(*aVEvt
.mpHdl
) || rMEvt
.IsShift())
505 if (!rMEvt
.IsShift())
507 mpView
->UnmarkAllPoints();
508 pHdl
= mpView
->PickHandle(aMDPos
);
512 if (mpView
->IsPointMarked(*aVEvt
.mpHdl
))
514 mpView
->UnmarkPoint(*aVEvt
.mpHdl
);
519 pHdl
= mpView
->PickHandle(aMDPos
);
525 mpView
->MarkPoint(*pHdl
);
526 if ( ! rMEvt
.IsRight())
527 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
533 // Point IS marked and NO shift is pressed. Start
534 // dragging of selected point(s)
535 pHdl
= mpView
->PickHandle(aMDPos
);
536 if(pHdl
&& ! rMEvt
.IsRight())
537 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
542 /******************************************************************
543 * Select or drag object
544 ******************************************************************/
545 if (!rMEvt
.IsShift() && !rMEvt
.IsMod2() && eHit
== SdrHitKind::UnmarkedObject
)
547 mpView
->UnmarkAllObj();
550 bool bMarked
= false;
556 bMarked
= mpView
->MarkNextObj(aMDPos
, nHitLog
, rMEvt
.IsShift());
560 bMarked
= mpView
->MarkObj(aMDPos
, nHitLog
, rMEvt
.IsShift());
565 (!rMEvt
.IsShift() || eHit
== SdrHitKind::MarkedObject
))
568 if ( ! rMEvt
.IsRight())
569 mpView
->BegDragObj(aMDPos
, nullptr, aVEvt
.mpHdl
, nDrgLog
);
571 else if (mpView
->AreObjectsMarked())
573 /**************************************************************
575 **************************************************************/
576 if (!rMEvt
.IsShift())
577 mpView
->UnmarkAllPoints();
579 if ( ! rMEvt
.IsRight())
580 mpView
->BegMarkPoints(aMDPos
);
584 /**************************************************************
586 **************************************************************/
587 if ( ! rMEvt
.IsRight())
588 mpView
->BegMarkObj(aMDPos
);
591 ForcePointer(&rMEvt
);
597 ForcePointer(&rMEvt
);
603 bool FuSelection::MouseMove(const MouseEvent
& rMEvt
)
605 bool bReturn
= FuDraw::MouseMove(rMEvt
);
607 if (aDragTimer
.IsActive())
611 bFirstMouseMove
= false;
619 if (mpView
->IsAction())
621 Point
aPix(rMEvt
.GetPosPixel());
622 Point
aPnt(mpWindow
->PixelToLogic(aPix
));
626 if (mpView
->IsInsObjPoint())
628 mpView
->MovInsObjPoint(aPnt
);
632 mpView
->MovAction(aPnt
);
636 ForcePointer(&rMEvt
);
641 bool FuSelection::MouseButtonUp(const MouseEvent
& rMEvt
)
643 bool bReturn
= false;
644 // When the right mouse button is pressed then only select objects
645 // (and deselect others) as a preparation for showing the context
647 const bool bSelectionOnly
= rMEvt
.IsRight();
649 if (aDragTimer
.IsActive() )
652 bIsInDragMode
= false;
658 Point
aPnt( mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() ) );
659 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
660 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(mpView
->GetDragThresholdPixels(),0)).Width() );
662 if (mpView
->IsFrameDragSingles() || !mpView
->HasMarkablePoints())
664 /**********************************************************************
666 **********************************************************************/
667 if ( mpView
->IsDragObj() )
669 /******************************************************************
671 ******************************************************************/
672 FrameView
* pFrameView
= mpViewShell
->GetFrameView();
673 bool bDragWithCopy
= (rMEvt
.IsMod1() && pFrameView
->IsDragWithCopy());
677 bDragWithCopy
= !mpView
->IsPresObjSelected(false);
680 mpView
->SetDragWithCopy(bDragWithCopy
);
681 bool bWasDragged(mpView
->EndDragObj( mpView
->IsDragWithCopy() ));
683 mpView
->ForceMarkedToAnotherPage();
685 if (!rMEvt
.IsShift() && !rMEvt
.IsMod1() && !rMEvt
.IsMod2() &&
686 !bSelectionChanged
&&
687 std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
&&
688 std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
690 /*************************************************************
691 * If a user wants to click on an object in front of a marked
692 * one, he releases the mouse button immediately
693 **************************************************************/
695 SdrObject
* pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
| SdrSearchOptions::BEFOREMARK
);
696 if (pObj
&& pPV
->IsObjMarkable(pObj
))
698 mpView
->UnmarkAllObj();
699 mpView
->MarkObj(pObj
,pPV
);
703 // check for single object selected
704 SdrObject
* pSingleObj
= nullptr;
706 if (mpView
->GetMarkedObjectList().GetMarkCount()==1)
708 pSingleObj
= mpView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
711 // Check for click on svx::diagram::DiagramFrameHdl
712 // - if we hit a SdrHdl
713 // - if it was not moved
714 // - if single object is selected
715 // - and it is a Diagram
716 if(pHdl
&& !bWasDragged
&& nullptr != pSingleObj
&& pSingleObj
->isDiagram())
718 svx::diagram::DiagramFrameHdl
* pDiagramFrameHdl(dynamic_cast<svx::diagram::DiagramFrameHdl
*>(pHdl
));
719 if(nullptr != pDiagramFrameHdl
)
721 // let the DiagramFrameHdl decide what to do
722 svx::diagram::DiagramFrameHdl::clicked(aPnt
);
726 /**************************************************************
727 * Toggle between selection and rotation
728 **************************************************************/
729 if (nSlotId
== SID_OBJECT_SELECT
730 && !comphelper::LibreOfficeKit::isActive()
731 && mpView
->IsRotateAllowed()
733 && (rMEvt
.GetClicks() != 2)
734 && (mpViewShell
->GetFrameView()->IsClickChangeRotation()
736 && pSingleObj
->GetObjInventor()==SdrInventor::E3d
))
740 bTempRotation
= true;
741 nSlotId
= SID_OBJECT_ROTATE
;
744 else if (nSlotId
== SID_OBJECT_ROTATE
)
746 nSlotId
= SID_OBJECT_SELECT
;
750 else if (nSlotId
== SID_CONVERT_TO_3D_LATHE
)
754 bSuppressChangesOfSelection
= true;
755 mpView
->Start3DCreation();
756 bSuppressChangesOfSelection
= false;
758 else if (pHdl
->GetKind() != SdrHdlKind::MirrorAxis
&&
759 pHdl
->GetKind() != SdrHdlKind::Ref1
&&
760 pHdl
->GetKind() != SdrHdlKind::Ref2
&& mpView
->Is3DRotationCreationActive())
762 /*********************************************************
763 * If 3D-rotation bodies are about to be created,
765 **********************************************************/
766 Degree100 nAngle1
= GetAngle(aPnt
- mpView
->GetRef1());
767 nAngle1
-= 27000_deg100
;
768 nAngle1
= NormAngle36000(nAngle1
);
769 bool bMirrorSide1
= nAngle1
< 18000_deg100
;
771 if (bMirrorSide0
!= bMirrorSide1
)
773 bSuppressChangesOfSelection
= true;
774 mpWindow
->EnterWait();
775 mpView
->End3DCreation();
776 bSuppressChangesOfSelection
= false;
777 nSlotId
= SID_OBJECT_SELECT
;
778 mpWindow
->LeaveWait();
784 else if (rMEvt
.IsMod1()
786 && std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
787 && std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
790 mpView
->MarkObj(aPnt
, nHitLog
, rMEvt
.IsShift(), rMEvt
.IsMod1());
793 if (mpView
->IsAction() )
798 if( SD_MOD()->GetWaterCan() )
800 if( rMEvt
.IsRight() )
802 // In watering-can mode, on press onto right mouse button, an undo is executed
803 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute( SID_UNDO
, SfxCallMode::ASYNCHRON
);
805 else if (pWaterCanCandidate
!= nullptr)
807 // Is the candidate object still under the mouse?
808 if (pickObject (aPnt
) == pWaterCanCandidate
)
810 SdStyleSheetPool
* pPool
= static_cast<SdStyleSheetPool
*>(
811 mpDocSh
->GetStyleSheetPool());
812 if (pPool
!= nullptr)
814 SfxStyleSheet
* pStyleSheet
= static_cast<SfxStyleSheet
*>(
815 pPool
->GetActualStyleSheet());
816 if (pStyleSheet
!= nullptr && mpView
->IsUndoEnabled() )
818 // Added UNDOs for the WaterCan mode. This was never done in
819 // the past, thus it was missing all the time.
820 std::unique_ptr
<SdrUndoAction
> pUndoAttr
= mpDoc
->GetSdrUndoFactory().CreateUndoAttrObject(*pWaterCanCandidate
, true, true);
821 mpView
->BegUndo(pUndoAttr
->GetComment());
822 mpView
->AddUndo(mpDoc
->GetSdrUndoFactory().CreateUndoGeoObject(*pWaterCanCandidate
));
823 mpView
->AddUndo(std::move(pUndoAttr
));
825 pWaterCanCandidate
->SetStyleSheet (pStyleSheet
, false);
832 // else when there has been no object under the mouse when the
833 // button was pressed then nothing happens even when there is
837 sal_uInt16 nClicks
= rMEvt
.GetClicks();
839 if (nClicks
== 2 && rMEvt
.IsLeft() && bMBDown
&&
840 !rMEvt
.IsMod1() && !rMEvt
.IsShift() )
847 ForcePointer(&rMEvt
);
849 mpWindow
->ReleaseMouse();
850 SdrObject
* pSingleObj
= nullptr;
851 const size_t nMarkCount
= mpView
->GetMarkedObjectList().GetMarkCount();
855 pSingleObj
= mpView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
858 if ( (nSlotId
!= SID_OBJECT_SELECT
&& nMarkCount
==0) ||
859 ( mpView
->GetDragMode() == SdrDragMode::Crook
&&
860 !mpView
->IsCrookAllowed( mpView
->IsCrookNoContortion() ) ) ||
861 ( mpView
->GetDragMode() == SdrDragMode::Shear
&&
862 !mpView
->IsShearAllowed() && !mpView
->IsDistortAllowed() ) ||
863 ( nSlotId
==SID_CONVERT_TO_3D_LATHE
&& pSingleObj
&&
864 (pSingleObj
->GetObjInventor() != SdrInventor::Default
||
865 pSingleObj
->GetObjIdentifier() == SdrObjKind::Measure
) ) )
868 ForcePointer(&rMEvt
);
870 mpWindow
->ReleaseMouse();
871 FuDraw::MouseButtonUp(rMEvt
);
872 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::SYNCHRON
);
873 return bReturn
; // CAUTION, due to the synchronous slot, the object is deleted now.
876 FuDraw::MouseButtonUp(rMEvt
);
880 /**********************************************************************
882 **********************************************************************/
883 if ( mpView
->IsAction() )
885 if ( mpView
->IsInsObjPoint() )
887 mpView
->EndInsObjPoint(SdrCreateCmd::ForceEnd
);
889 else if ( mpView
->IsDragObj() )
891 FrameView
* pFrameView
= mpViewShell
->GetFrameView();
892 bool bDragWithCopy
= (rMEvt
.IsMod1() && pFrameView
->IsDragWithCopy());
896 bDragWithCopy
= !mpView
->IsPresObjSelected(false);
899 mpView
->SetDragWithCopy(bDragWithCopy
);
900 mpView
->EndDragObj( mpView
->IsDragWithCopy() );
906 sal_uInt16 nDrgLog2
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(mpView
->GetDragThresholdPixels(),0)).Width() );
907 Point aPos
= mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() );
909 if (std::abs(aMDPos
.X() - aPos
.X()) < nDrgLog2
&&
910 std::abs(aMDPos
.Y() - aPos
.Y()) < nDrgLog2
&&
911 !rMEvt
.IsShift() && !rMEvt
.IsMod2())
914 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
916 if (eHit
== SdrHitKind::NONE
)
918 // Click on the same place - unselect
919 mpView
->UnmarkAllObj();
924 else if (!rMEvt
.IsShift() && rMEvt
.IsMod1() && !rMEvt
.IsMod2() &&
925 std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
&&
926 std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
929 mpView
->MarkObj(aPnt
, nHitLog
, false, rMEvt
.IsMod1());
932 ForcePointer(&rMEvt
);
934 mpWindow
->ReleaseMouse();
936 FuDraw::MouseButtonUp(rMEvt
);
943 * Process keyboard input
944 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
946 bool FuSelection::KeyInput(const KeyEvent
& rKEvt
)
948 bool bReturn
= false;
950 switch (rKEvt
.GetKeyCode().GetCode())
954 bReturn
= FuSelection::cancel();
957 //add keyboard operation for insert points in drawing curve
963 if(rKEvt
.GetKeyCode().IsShift()&&(nEditMode
== SID_BEZIER_INSERT
)){
964 ::tools::Long nX
= 0;
965 ::tools::Long nY
= 0;
966 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
973 else if (nCode
== KEY_DOWN
)
979 else if (nCode
== KEY_LEFT
)
985 else if (nCode
== KEY_RIGHT
)
993 ::tools::Rectangle rect
= mpView
->GetMarkedObjRect();
994 centerPoint
= mpWindow
->LogicToPixel(rect
.Center());
995 Point aPoint
= bMovedToCenterPoint
? oldPoint
:centerPoint
;
996 Point ePoint
= aPoint
+ Point(nX
,nY
);
997 mpWindow
->SetPointerPosPixel(ePoint
);
998 //simulate mouse move action
999 MouseEvent
eMevt(ePoint
, 1, MouseEventModifiers::DRAGMOVE
, MOUSE_LEFT
, 0);
1002 bMovedToCenterPoint
= true;
1008 if(rKEvt
.GetKeyCode().IsShift()&&(nEditMode
== SID_BEZIER_INSERT
))
1010 if(!bBeginInsertPoint
)
1012 //simulate mouse button down action
1013 MouseEvent
aMevt(oldPoint
, 1,
1014 MouseEventModifiers::SIMPLEMOVE
| MouseEventModifiers::DRAGMOVE
,
1015 MOUSE_LEFT
, KEY_SHIFT
);
1016 MouseButtonDown(aMevt
);
1017 mpWindow
->CaptureMouse();
1018 bBeginInsertPoint
= true;
1022 //simulate mouse button up action
1023 MouseEvent
rMEvt(oldPoint
, 1,
1024 MouseEventModifiers::SIMPLEMOVE
| MouseEventModifiers::ENTERWINDOW
,
1025 MOUSE_LEFT
, KEY_SHIFT
);
1026 MouseButtonUp(rMEvt
);
1027 bBeginInsertPoint
= false;
1035 bReturn
= FuDraw::KeyInput(rKEvt
);
1037 if(mpView
->GetMarkedObjectList().GetMarkCount() == 0)
1039 mpView
->ResetCreationActive();
1041 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1049 void FuSelection::Activate()
1052 mpView
->ResetCreationActive();
1053 mpView
->SetEditMode(SdrViewEditMode::Edit
);
1057 case SID_OBJECT_ROTATE
:
1059 eMode
= SdrDragMode::Rotate
;
1061 if ( mpView
->GetDragMode() != eMode
)
1062 mpView
->SetDragMode(eMode
);
1066 case SID_OBJECT_MIRROR
:
1068 eMode
= SdrDragMode::Mirror
;
1070 if ( mpView
->GetDragMode() != eMode
)
1071 mpView
->SetDragMode(eMode
);
1075 case SID_OBJECT_CROP
:
1077 eMode
= SdrDragMode::Crop
;
1079 if ( mpView
->GetDragMode() != eMode
)
1080 mpView
->SetDragMode(eMode
);
1084 case SID_OBJECT_TRANSPARENCE
:
1086 eMode
= SdrDragMode::Transparence
;
1088 if ( mpView
->GetDragMode() != eMode
)
1089 mpView
->SetDragMode(eMode
);
1093 case SID_OBJECT_GRADIENT
:
1095 eMode
= SdrDragMode::Gradient
;
1097 if ( mpView
->GetDragMode() != eMode
)
1098 mpView
->SetDragMode(eMode
);
1102 case SID_OBJECT_SHEAR
:
1104 eMode
= SdrDragMode::Shear
;
1106 if ( mpView
->GetDragMode() != eMode
)
1107 mpView
->SetDragMode(eMode
);
1111 case SID_OBJECT_CROOK_ROTATE
:
1113 eMode
= SdrDragMode::Crook
;
1115 if ( mpView
->GetDragMode() != eMode
)
1117 mpView
->SetDragMode(eMode
);
1118 mpView
->SetCrookMode(SdrCrookMode::Rotate
);
1123 case SID_OBJECT_CROOK_SLANT
:
1125 eMode
= SdrDragMode::Crook
;
1127 if ( mpView
->GetDragMode() != eMode
)
1129 mpView
->SetDragMode(eMode
);
1130 mpView
->SetCrookMode(SdrCrookMode::Slant
);
1135 case SID_OBJECT_CROOK_STRETCH
:
1137 eMode
= SdrDragMode::Crook
;
1139 if ( mpView
->GetDragMode() != eMode
)
1141 mpView
->SetDragMode(eMode
);
1142 mpView
->SetCrookMode(SdrCrookMode::Stretch
);
1147 case SID_CONVERT_TO_3D_LATHE
:
1149 eMode
= SdrDragMode::Mirror
;
1150 bSuppressChangesOfSelection
= true;
1152 if ( mpView
->GetDragMode() != eMode
)
1153 mpView
->SetDragMode(eMode
);
1155 if (!mpView
->Is3DRotationCreationActive())
1156 mpView
->Start3DCreation();
1158 bSuppressChangesOfSelection
= false;
1164 eMode
= SdrDragMode::Move
;
1166 if ( mpView
->GetDragMode() != eMode
)
1167 mpView
->SetDragMode(eMode
);
1172 if (nSlotId
!= SID_OBJECT_ROTATE
)
1174 bTempRotation
= false;
1180 void FuSelection::SelectionHasChanged()
1182 bSelectionChanged
= true;
1184 FuDraw::SelectionHasChanged();
1186 if (mpView
->Is3DRotationCreationActive() && !bSuppressChangesOfSelection
)
1188 // Switch rotation body -> selection
1189 mpView
->ResetCreationActive();
1190 nSlotId
= SID_OBJECT_SELECT
;
1194 // Activate the right tool bar for the current context of the view.
1195 mpViewShell
->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(*mpViewShell
, *mpView
);
1199 * Set current bezier edit mode
1201 void FuSelection::SetEditMode(sal_uInt16 nMode
)
1205 if (nEditMode
== SID_BEZIER_INSERT
)
1207 mpView
->SetInsObjPointMode(true);
1211 mpView
->SetInsObjPointMode(false);
1216 SfxBindings
& rBindings
= mpViewShell
->GetViewFrame()->GetBindings();
1217 rBindings
.Invalidate(SID_BEZIER_MOVE
);
1218 rBindings
.Invalidate(SID_BEZIER_INSERT
);
1222 * Execute ImageMap interaction
1224 bool FuSelection::HandleImageMapClick(const SdrObject
* pObj
, const Point
& rPos
)
1226 bool bClosed
= pObj
->IsClosedObj();
1227 bool bFilled
= false;
1231 SfxItemSet
aSet(mpDoc
->GetPool());
1233 aSet
.Put(pObj
->GetMergedItemSet());
1235 const XFillStyleItem
& rFillStyle
= aSet
.Get(XATTR_FILLSTYLE
);
1236 bFilled
= rFillStyle
.GetValue() != drawing::FillStyle_NONE
;
1239 const SdrLayerIDSet
* pVisiLayer
= &mpView
->GetSdrPageView()->GetVisibleLayers();
1240 double fHitLog
= mpWindow
->PixelToLogic(Size(HITPIX
, 0)).Width();
1241 const ::tools::Long n2HitLog
= fHitLog
* 2;
1242 Point
aHitPosR(rPos
);
1243 Point
aHitPosL(rPos
);
1244 Point
aHitPosT(rPos
);
1245 Point
aHitPosB(rPos
);
1247 aHitPosR
.AdjustX(n2HitLog
);
1248 aHitPosL
.AdjustX(-n2HitLog
);
1249 aHitPosT
.AdjustY(n2HitLog
);
1250 aHitPosB
.AdjustY(-n2HitLog
);
1252 if (!bClosed
|| !bFilled
1253 || (SdrObjectPrimitiveHit(*pObj
, aHitPosR
, {fHitLog
, fHitLog
}, *mpView
->GetSdrPageView(), pVisiLayer
,
1255 && SdrObjectPrimitiveHit(*pObj
, aHitPosL
, {fHitLog
, fHitLog
}, *mpView
->GetSdrPageView(),
1257 && SdrObjectPrimitiveHit(*pObj
, aHitPosT
, {fHitLog
, fHitLog
}, *mpView
->GetSdrPageView(),
1259 && SdrObjectPrimitiveHit(*pObj
, aHitPosB
, {fHitLog
, fHitLog
}, *mpView
->GetSdrPageView(),
1260 pVisiLayer
, false)))
1262 if (SvxIMapInfo::GetIMapInfo(pObj
))
1264 const IMapObject
* pIMapObj
= SvxIMapInfo::GetHitIMapObject(pObj
, rPos
);
1266 if (pIMapObj
&& !pIMapObj
->GetURL().isEmpty())
1269 mpWindow
->ReleaseMouse();
1270 SfxStringItem
aStrItem(SID_FILE_NAME
, pIMapObj
->GetURL());
1271 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
1272 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
1273 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
1274 SfxBoolItem
aBrowseItem(SID_BROWSE
, true);
1275 mpWindow
->ReleaseMouse();
1276 pFrame
->GetDispatcher()->ExecuteList(
1277 SID_OPENDOC
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1278 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
1288 /** is called when the current function should be aborted. <p>
1289 This is used when a function gets a KEY_ESCAPE but can also
1292 @returns true if an active function was aborted
1294 bool FuSelection::cancel()
1296 if (mpView
->Is3DRotationCreationActive())
1298 mpView
->ResetCreationActive();
1299 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1308 SdrObject
* FuSelection::pickObject (const Point
& rTestPoint
)
1310 SdrPageView
* pPageView
;
1311 sal_uInt16 nHitLog
= sal_uInt16 (mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width());
1312 return mpView
->PickObj(rTestPoint
, nHitLog
, pPageView
, SdrSearchOptions::PICKMARKABLE
);
1315 void FuSelection::ForcePointer(const MouseEvent
* pMEvt
)
1317 if(bMovedToCenterPoint
&& !bBeginInsertPoint
&& pMEvt
)
1319 MouseEvent
aMEvt(pMEvt
->GetPosPixel(), pMEvt
->GetClicks(),
1320 pMEvt
->GetMode(), pMEvt
->GetButtons(), pMEvt
->GetModifier() & ~KEY_SHIFT
);
1321 FuDraw::ForcePointer(&aMEvt
);
1325 FuDraw::ForcePointer(pMEvt
);
1329 } // end of namespace sd
1331 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */