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 .
20 #include <config_features.h>
22 #include <com/sun/star/media/XPlayer.hpp>
24 #include <basic/sbstar.hxx>
25 #include <svx/svddrgmt.hxx>
26 #include <svx/svdpagv.hxx>
27 #include <svx/svdogrp.hxx>
28 #include <svx/scene3d.hxx>
29 #include <drawview.hxx>
30 #include <vcl/imapobj.hxx>
31 #include <svl/urihelper.hxx>
32 #include <unotools/securityoptions.hxx>
33 #include <svx/svxids.hrc>
34 #include <svx/xfillit0.hxx>
35 #include <sfx2/app.hxx>
36 #include <sfx2/viewfrm.hxx>
37 #include <svl/stritem.hxx>
38 #include <svl/intitem.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include <tools/urlobj.hxx>
41 #include <sfx2/docfile.hxx>
42 #include <editeng/flditem.hxx>
44 #include <svx/svdotable.hxx>
48 #include <GraphicDocShell.hxx>
50 #include <DrawDocShell.hxx>
51 #include <stlpool.hxx>
52 #include <anminfo.hxx>
54 #include <ViewShell.hxx>
55 #include <ViewShellBase.hxx>
56 #include <FrameView.hxx>
59 #include <drawdoc.hxx>
60 #include <DrawViewShell.hxx>
61 #include <ToolBarManager.hxx>
65 #include <slideshow.hxx>
67 #include <svx/svdundo.hxx>
68 #include <avmedia/mediawindow.hxx>
70 #include <svx/sdrhittesthelper.hxx>
72 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
73 #include <comphelper/lok.hxx>
75 using namespace ::com::sun::star
;
79 FuSelection::FuSelection (
85 : FuDraw(pViewSh
, pWin
, pView
, pDoc
, rReq
),
87 bSelectionChanged(false),
89 bSuppressChangesOfSelection(false),
91 nEditMode(SID_BEZIER_MOVE
),
92 pWaterCanCandidate(nullptr)
93 //Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point,
94 //and SHIFT+ENTER key to decide the position and draw the new insert point
95 ,bBeginInsertPoint(false),
97 ,bMovedToCenterPoint(false)
101 rtl::Reference
<FuPoor
> FuSelection::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
)
103 rtl::Reference
<FuPoor
> xFunc( new FuSelection( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
104 xFunc
->DoExecute(rReq
);
108 void FuSelection::DoExecute( SfxRequest
& rReq
)
110 FuDraw::DoExecute( rReq
);
113 SelectionHasChanged();
116 FuSelection::~FuSelection()
118 mpView
->UnmarkAllPoints();
119 mpView
->ResetCreationActive();
121 if ( mpView
->GetDragMode() != SdrDragMode::Move
)
123 mpView
->SetDragMode(SdrDragMode::Move
);
127 bool FuSelection::MouseButtonDown(const MouseEvent
& rMEvt
)
130 bool bReturn
= FuDraw::MouseButtonDown(rMEvt
);
131 bool bWaterCan
= SD_MOD()->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(DRGPIX
,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 long nAngle0
= GetAngle(aMDPos
- mpView
->GetRef1());
176 nAngle0
= NormAngle36000(nAngle0
);
177 bMirrorSide0
= nAngle0
< 18000;
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
.pObj
) != nullptr ) )
203 && !mpDocSh
->IsReadOnly()
204 && ((mpView
->IsMarkedHit(aMDPos
, nHitLog
) && !rMEvt
.IsShift() && !rMEvt
.IsMod2()) || pHdl
!= nullptr)
205 && (rMEvt
.GetClicks() != 2)
208 if (!pHdl
&& mpView
->Is3DRotationCreationActive())
210 // Switch between 3D-rotation body -> selection
211 mpView
->ResetCreationActive();
215 // Remember the selected object for proper handling in
217 pWaterCanCandidate
= pickObject (aMDPos
);
221 // hit handle or marked object
222 bFirstMouseMove
= true;
226 if ( ! rMEvt
.IsRight())
227 if (mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
))
228 mpView
->GetDragMethod()->SetShiftPressed( rMEvt
.IsShift() );
233 SdrPageView
* pPV
= nullptr;
234 SdrObject
* pObj
= !rMEvt
.IsMod2() ? mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMACRO
) : nullptr;
237 mpView
->BegMacroObj(aMDPos
, nHitLog
, pObj
, pPV
, mpWindow
);
240 else if ( bTextEdit
)
242 sal_uInt16 nSdrObjKind
= aVEvt
.pObj
->GetObjIdentifier();
244 if (aVEvt
.pObj
->GetObjInventor() == SdrInventor::Default
&&
245 (nSdrObjKind
== OBJ_TEXT
||
246 nSdrObjKind
== OBJ_TITLETEXT
||
247 nSdrObjKind
== OBJ_OUTLINETEXT
||
248 !aVEvt
.pObj
->IsEmptyPresObj()))
250 // Seamless Editing: branch to text input
251 if (!rMEvt
.IsShift())
254 SfxUInt16Item
aItem(SID_TEXTEDIT
, 1);
255 mpViewShell
->GetViewFrame()->GetDispatcher()->
256 ExecuteList(SID_TEXTEDIT
,
257 SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
,
259 return bReturn
; // CAUTION, due to the synchronous slot the object is deleted now
262 else if ( !rMEvt
.IsMod2() && rMEvt
.GetClicks() == 1 &&
263 aVEvt
.eEvent
== SdrEventKind::ExecuteUrl
)
265 mpWindow
->ReleaseMouse();
267 SvtSecurityOptions aSecOpt
;
268 if (!rMEvt
.IsMod1() && aSecOpt
.IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink
))
270 if (rMEvt
.IsMod1() && !aSecOpt
.IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink
))
273 SfxStringItem
aStrItem(SID_FILE_NAME
, aVEvt
.pURLField
->GetURL());
274 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
275 SfxBoolItem
aBrowseItem( SID_BROWSE
, true );
276 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
277 mpWindow
->ReleaseMouse();
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
.pURLField
->GetURL().toUtf8().getStr());
290 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
291 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
292 { &aStrItem
, &aBrowseItem
, &aReferer
});
296 // Open in current frame
297 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
298 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
299 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
300 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
305 else if(!rMEvt
.IsMod2()
306 && dynamic_cast< const DrawViewShell
*>( mpViewShell
) != nullptr
309 pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
);
312 // Animate object when not just selecting.
313 if ( ! bSelectionOnly
)
314 bReturn
= AnimateObj(pObj
, aMDPos
);
316 if( !bReturn
&& (dynamic_cast< const SdrObjGroup
*>( pObj
) != nullptr || dynamic_cast< const E3dScene
* >(pObj
) != nullptr))
318 if(rMEvt
.GetClicks() == 1)
320 // Look into the group
321 pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
| SdrSearchOptions::DEEP
);
323 bReturn
= AnimateObj(pObj
, aMDPos
);
325 else if( !bReadOnly
&& rMEvt
.GetClicks() == 2)
327 // New: double click on selected Group object
329 if ( ! bSelectionOnly
330 && pObj
->getSdrPageFromSdrObject() == pPV
->GetPage())
331 bReturn
= pPV
->EnterGroup(pObj
);
336 // #i71727# replaced else here with two possibilities, once the original else (!pObj)
337 // and also ignoring the found object when it's on a masterpage
338 if(!pObj
|| (pObj
->getSdrPageFromSdrObject() && pObj
->getSdrPageFromSdrObject()->IsMasterPage()))
340 if(mpView
->IsGroupEntered() && 2 == rMEvt
.GetClicks())
342 // New: double click on empty space/on obj on MasterPage, leave group
343 mpView
->LeaveOneGroup();
353 if ( ! (rMEvt
.IsShift() || rMEvt
.IsMod2()))
355 // Find the object under the current mouse position
356 // and store it for the MouseButtonUp() method to
358 pWaterCanCandidate
= pickObject (aMDPos
);
364 bool bDeactivateOLE
= false;
366 if ( !rMEvt
.IsShift() && !rMEvt
.IsMod2() )
368 OSL_ASSERT (mpViewShell
->GetViewShell()!=nullptr);
369 Client
* pIPClient
= static_cast<Client
*>(
370 mpViewShell
->GetViewShell()->GetIPClient());
372 if (pIPClient
&& pIPClient
->IsObjectInPlaceActive())
374 // OLE-object gets deactivated in subsequent UnmarkAll()
375 bDeactivateOLE
= true;
381 bool bMarked
= false;
383 if ( !rMEvt
.IsMod1() && !bDeactivateOLE
)
385 if ( rMEvt
.IsMod2() )
387 bMarked
= mpView
->MarkNextObj(aMDPos
, nHitLog
, rMEvt
.IsShift() );
391 bool bToggle
= false;
393 if (rMEvt
.IsShift() && mpView
->GetMarkedObjectList().GetMarkCount() > 1)
395 // No Toggle on single selection
399 bMarked
= mpView
->MarkObj(aMDPos
, nHitLog
, bToggle
);
403 if( !bDeactivateOLE
)
407 (!rMEvt
.IsShift() || mpView
->IsMarkedHit(aMDPos
, nHitLog
)))
409 /**********************************************************
411 **********************************************************/
414 pHdl
=mpView
->PickHandle(aMDPos
);
415 if ( ! rMEvt
.IsRight())
416 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
420 /**********************************************************
422 **********************************************************/
423 if ( ! rMEvt
.IsRight())
424 mpView
->BegMarkObj(aMDPos
);
428 if( bMarked
&& bTempRotation
&& (nSlotId
== SID_OBJECT_ROTATE
) && !rMEvt
.IsShift() && (rMEvt
.GetClicks() != 2) )
430 nSlotId
= SID_OBJECT_SELECT
;
438 && (rMEvt
.IsLeft() || rMEvt
.IsRight())
439 && !mpView
->IsAction())
441 /**********************************************************************
443 **********************************************************************/
444 mpWindow
->CaptureMouse();
446 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
448 if (eHit
== SdrHitKind::Handle
&& aVEvt
.pHdl
->GetKind() == SdrHdlKind::BezierWeight
)
450 /******************************************************************
452 ******************************************************************/
453 if ( ! rMEvt
.IsRight())
454 mpView
->BegDragObj(aMDPos
, nullptr, aVEvt
.pHdl
, nDrgLog
);
456 else if (eHit
== SdrHitKind::MarkedObject
&& nEditMode
== SID_BEZIER_INSERT
)
458 /******************************************************************
460 ******************************************************************/
461 mpView
->BegInsObjPoint(aMDPos
, rMEvt
.IsMod1());
463 else if (eHit
== SdrHitKind::MarkedObject
&& rMEvt
.IsMod1())
465 /******************************************************************
467 ******************************************************************/
468 if (!rMEvt
.IsShift())
469 mpView
->UnmarkAllPoints();
471 if ( ! rMEvt
.IsRight())
472 mpView
->BegMarkPoints(aMDPos
);
474 else if (eHit
== SdrHitKind::MarkedObject
&& !rMEvt
.IsShift() && !rMEvt
.IsMod2())
476 /******************************************************************
478 ******************************************************************/
479 if ( ! rMEvt
.IsRight())
480 mpView
->BegDragObj(aMDPos
, nullptr, nullptr, nDrgLog
);
482 else if (eHit
== SdrHitKind::Handle
)
484 /******************************************************************
486 ******************************************************************/
487 if (!mpView
->IsPointMarked(*aVEvt
.pHdl
) || rMEvt
.IsShift())
489 if (!rMEvt
.IsShift())
491 mpView
->UnmarkAllPoints();
492 pHdl
= mpView
->PickHandle(aMDPos
);
496 if (mpView
->IsPointMarked(*aVEvt
.pHdl
))
498 mpView
->UnmarkPoint(*aVEvt
.pHdl
);
503 pHdl
= mpView
->PickHandle(aMDPos
);
509 mpView
->MarkPoint(*pHdl
);
510 if ( ! rMEvt
.IsRight())
511 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
517 // Point IS marked and NO shift is pressed. Start
518 // dragging of selected point(s)
519 pHdl
= mpView
->PickHandle(aMDPos
);
520 if(pHdl
&& ! rMEvt
.IsRight())
521 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
526 /******************************************************************
527 * Select or drag object
528 ******************************************************************/
529 if (!rMEvt
.IsShift() && !rMEvt
.IsMod2() && eHit
== SdrHitKind::UnmarkedObject
)
531 mpView
->UnmarkAllObj();
534 bool bMarked
= false;
540 bMarked
= mpView
->MarkNextObj(aMDPos
, nHitLog
, rMEvt
.IsShift());
544 bMarked
= mpView
->MarkObj(aMDPos
, nHitLog
, rMEvt
.IsShift());
549 (!rMEvt
.IsShift() || eHit
== SdrHitKind::MarkedObject
))
552 if ( ! rMEvt
.IsRight())
553 mpView
->BegDragObj(aMDPos
, nullptr, aVEvt
.pHdl
, nDrgLog
);
555 else if (mpView
->AreObjectsMarked())
557 /**************************************************************
559 **************************************************************/
560 if (!rMEvt
.IsShift())
561 mpView
->UnmarkAllPoints();
563 if ( ! rMEvt
.IsRight())
564 mpView
->BegMarkPoints(aMDPos
);
568 /**************************************************************
570 **************************************************************/
571 if ( ! rMEvt
.IsRight())
572 mpView
->BegMarkObj(aMDPos
);
575 ForcePointer(&rMEvt
);
581 ForcePointer(&rMEvt
);
587 bool FuSelection::MouseMove(const MouseEvent
& rMEvt
)
589 bool bReturn
= FuDraw::MouseMove(rMEvt
);
591 if (aDragTimer
.IsActive())
595 bFirstMouseMove
= false;
603 if (mpView
->IsAction())
605 Point
aPix(rMEvt
.GetPosPixel());
606 Point
aPnt(mpWindow
->PixelToLogic(aPix
));
610 if (mpView
->IsInsObjPoint())
612 mpView
->MovInsObjPoint(aPnt
);
616 mpView
->MovAction(aPnt
);
620 ForcePointer(&rMEvt
);
625 bool FuSelection::MouseButtonUp(const MouseEvent
& rMEvt
)
627 bool bReturn
= false;
628 // When the right mouse button is pressed then only select objects
629 // (and deselect others) as a preparation for showing the context
631 const bool bSelectionOnly
= rMEvt
.IsRight();
633 if (aDragTimer
.IsActive() )
636 bIsInDragMode
= false;
642 Point
aPnt( mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() ) );
643 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
644 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(DRGPIX
,0)).Width() );
646 if (mpView
->IsFrameDragSingles() || !mpView
->HasMarkablePoints())
648 /**********************************************************************
650 **********************************************************************/
651 if ( mpView
->IsDragObj() )
653 /******************************************************************
655 ******************************************************************/
656 FrameView
* pFrameView
= mpViewShell
->GetFrameView();
657 bool bDragWithCopy
= (rMEvt
.IsMod1() && pFrameView
->IsDragWithCopy());
661 bDragWithCopy
= !mpView
->IsPresObjSelected(false);
664 mpView
->SetDragWithCopy(bDragWithCopy
);
665 mpView
->EndDragObj( mpView
->IsDragWithCopy() );
667 mpView
->ForceMarkedToAnotherPage();
669 if (!rMEvt
.IsShift() && !rMEvt
.IsMod1() && !rMEvt
.IsMod2() &&
670 !bSelectionChanged
&&
671 std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
&&
672 std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
674 /*************************************************************
675 * If a user wants to click on an object in front of a marked
676 * one, he releases the mouse button immediately
677 **************************************************************/
679 SdrObject
* pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
| SdrSearchOptions::BEFOREMARK
);
680 if (pObj
&& pPV
->IsObjMarkable(pObj
))
682 mpView
->UnmarkAllObj();
683 mpView
->MarkObj(pObj
,pPV
);
686 /**************************************************************
687 * Toggle between selection and rotation
688 **************************************************************/
689 SdrObject
* pSingleObj
= nullptr;
691 if (mpView
->GetMarkedObjectList().GetMarkCount()==1)
693 pSingleObj
= mpView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
696 if (nSlotId
== SID_OBJECT_SELECT
697 && mpView
->IsRotateAllowed()
699 && (rMEvt
.GetClicks() != 2)
700 && (mpViewShell
->GetFrameView()->IsClickChangeRotation()
702 && pSingleObj
->GetObjInventor()==SdrInventor::E3d
))
706 bTempRotation
= true;
707 nSlotId
= SID_OBJECT_ROTATE
;
710 else if (nSlotId
== SID_OBJECT_ROTATE
)
712 nSlotId
= SID_OBJECT_SELECT
;
716 else if (nSlotId
== SID_CONVERT_TO_3D_LATHE
)
720 bSuppressChangesOfSelection
= true;
721 mpView
->Start3DCreation();
722 bSuppressChangesOfSelection
= false;
724 else if (pHdl
->GetKind() != SdrHdlKind::MirrorAxis
&&
725 pHdl
->GetKind() != SdrHdlKind::Ref1
&&
726 pHdl
->GetKind() != SdrHdlKind::Ref2
&& mpView
->Is3DRotationCreationActive())
728 /*********************************************************
729 * If 3D-rotation bodies are about to be created,
731 **********************************************************/
732 long nAngle1
= GetAngle(aPnt
- mpView
->GetRef1());
734 nAngle1
= NormAngle36000(nAngle1
);
735 bool bMirrorSide1
= nAngle1
< 18000;
737 if (bMirrorSide0
!= bMirrorSide1
)
739 bSuppressChangesOfSelection
= true;
740 mpWindow
->EnterWait();
741 mpView
->End3DCreation();
742 bSuppressChangesOfSelection
= false;
743 nSlotId
= SID_OBJECT_SELECT
;
744 mpWindow
->LeaveWait();
750 else if (rMEvt
.IsMod1()
752 && std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
753 && std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
756 mpView
->MarkObj(aPnt
, nHitLog
, rMEvt
.IsShift(), rMEvt
.IsMod1());
759 if (mpView
->IsAction() )
764 if( SD_MOD()->GetWaterCan() )
766 if( rMEvt
.IsRight() )
768 // In watering-can mode, on press onto right mouse button, a undo is executed
769 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute( SID_UNDO
, SfxCallMode::ASYNCHRON
);
771 else if (pWaterCanCandidate
!= nullptr)
773 // Is the candidate object still under the mouse?
774 if (pickObject (aPnt
) == pWaterCanCandidate
)
776 SdStyleSheetPool
* pPool
= static_cast<SdStyleSheetPool
*>(
777 mpDocSh
->GetStyleSheetPool());
778 if (pPool
!= nullptr)
780 SfxStyleSheet
* pStyleSheet
= static_cast<SfxStyleSheet
*>(
781 pPool
->GetActualStyleSheet());
782 if (pStyleSheet
!= nullptr && mpView
->IsUndoEnabled() )
784 // Added UNDOs for the WaterCan mode. This was never done in
785 // the past, thus it was missing all the time.
786 std::unique_ptr
<SdrUndoAction
> pUndoAttr
= mpDoc
->GetSdrUndoFactory().CreateUndoAttrObject(*pWaterCanCandidate
, true, true);
787 mpView
->BegUndo(pUndoAttr
->GetComment());
788 mpView
->AddUndo(mpDoc
->GetSdrUndoFactory().CreateUndoGeoObject(*pWaterCanCandidate
));
789 mpView
->AddUndo(std::move(pUndoAttr
));
791 pWaterCanCandidate
->SetStyleSheet (pStyleSheet
, false);
798 // else when there has been no object under the mouse when the
799 // button was pressed then nothing happens even when there is
803 sal_uInt16 nClicks
= rMEvt
.GetClicks();
805 if (nClicks
== 2 && rMEvt
.IsLeft() && bMBDown
&&
806 !rMEvt
.IsMod1() && !rMEvt
.IsShift() )
813 ForcePointer(&rMEvt
);
815 mpWindow
->ReleaseMouse();
816 SdrObject
* pSingleObj
= nullptr;
817 const size_t nMarkCount
= mpView
->GetMarkedObjectList().GetMarkCount();
821 pSingleObj
= mpView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
824 if ( (nSlotId
!= SID_OBJECT_SELECT
&& nMarkCount
==0) ||
825 ( mpView
->GetDragMode() == SdrDragMode::Crook
&&
826 !mpView
->IsCrookAllowed( mpView
->IsCrookNoContortion() ) ) ||
827 ( mpView
->GetDragMode() == SdrDragMode::Shear
&&
828 !mpView
->IsShearAllowed() && !mpView
->IsDistortAllowed() ) ||
829 ( nSlotId
==SID_CONVERT_TO_3D_LATHE
&& pSingleObj
&&
830 (pSingleObj
->GetObjInventor() != SdrInventor::Default
||
831 pSingleObj
->GetObjIdentifier() == OBJ_MEASURE
) ) )
834 ForcePointer(&rMEvt
);
836 mpWindow
->ReleaseMouse();
837 FuDraw::MouseButtonUp(rMEvt
);
838 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::SYNCHRON
);
839 return bReturn
; // CAUTION, due to the synchronous slot, the object is deleted now.
842 FuDraw::MouseButtonUp(rMEvt
);
846 /**********************************************************************
848 **********************************************************************/
849 if ( mpView
->IsAction() )
851 if ( mpView
->IsInsObjPoint() )
853 mpView
->EndInsObjPoint(SdrCreateCmd::ForceEnd
);
855 else if ( mpView
->IsDragObj() )
857 FrameView
* pFrameView
= mpViewShell
->GetFrameView();
858 bool bDragWithCopy
= (rMEvt
.IsMod1() && pFrameView
->IsDragWithCopy());
862 bDragWithCopy
= !mpView
->IsPresObjSelected(false);
865 mpView
->SetDragWithCopy(bDragWithCopy
);
866 mpView
->EndDragObj( mpView
->IsDragWithCopy() );
872 sal_uInt16 nDrgLog2
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(DRGPIX
,0)).Width() );
873 Point aPos
= mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() );
875 if (std::abs(aMDPos
.X() - aPos
.X()) < nDrgLog2
&&
876 std::abs(aMDPos
.Y() - aPos
.Y()) < nDrgLog2
&&
877 !rMEvt
.IsShift() && !rMEvt
.IsMod2())
880 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
882 if (eHit
== SdrHitKind::NONE
)
884 // Click on the same place - unselect
885 mpView
->UnmarkAllObj();
890 else if (!rMEvt
.IsShift() && rMEvt
.IsMod1() && !rMEvt
.IsMod2() &&
891 std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
&&
892 std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
895 mpView
->MarkObj(aPnt
, nHitLog
, false, rMEvt
.IsMod1());
898 ForcePointer(&rMEvt
);
900 mpWindow
->ReleaseMouse();
902 FuDraw::MouseButtonUp(rMEvt
);
909 * Process keyboard input
910 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
912 bool FuSelection::KeyInput(const KeyEvent
& rKEvt
)
914 bool bReturn
= false;
916 switch (rKEvt
.GetKeyCode().GetCode())
920 bReturn
= FuSelection::cancel();
923 //add keyboard operation for insert points in drawing curve
929 if(rKEvt
.GetKeyCode().IsShift()&&(nEditMode
== SID_BEZIER_INSERT
)){
932 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
939 else if (nCode
== KEY_DOWN
)
945 else if (nCode
== KEY_LEFT
)
951 else if (nCode
== KEY_RIGHT
)
959 ::tools::Rectangle rect
= mpView
->GetMarkedObjRect();
960 centerPoint
= mpWindow
->LogicToPixel(rect
.Center());
961 Point aPoint
= bMovedToCenterPoint
? oldPoint
:centerPoint
;
962 Point ePoint
= aPoint
+ Point(nX
,nY
);
963 mpWindow
->SetPointerPosPixel(ePoint
);
964 //simulate mouse move action
965 MouseEvent
eMevt(ePoint
, 1, MouseEventModifiers::DRAGMOVE
, MOUSE_LEFT
, 0);
968 bMovedToCenterPoint
= true;
974 if(rKEvt
.GetKeyCode().IsShift()&&(nEditMode
== SID_BEZIER_INSERT
))
976 if(!bBeginInsertPoint
)
978 //simulate mouse button down action
979 MouseEvent
aMevt(oldPoint
, 1,
980 MouseEventModifiers::SIMPLEMOVE
| MouseEventModifiers::DRAGMOVE
,
981 MOUSE_LEFT
, KEY_SHIFT
);
982 MouseButtonDown(aMevt
);
983 mpWindow
->CaptureMouse();
984 bBeginInsertPoint
= true;
988 //simulate mouse button up action
989 MouseEvent
rMEvt(oldPoint
, 1,
990 MouseEventModifiers::SIMPLEMOVE
| MouseEventModifiers::ENTERWINDOW
,
991 MOUSE_LEFT
, KEY_SHIFT
);
992 MouseButtonUp(rMEvt
);
993 bBeginInsertPoint
= false;
1001 bReturn
= FuDraw::KeyInput(rKEvt
);
1003 if(mpView
->GetMarkedObjectList().GetMarkCount() == 0)
1005 mpView
->ResetCreationActive();
1007 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1015 void FuSelection::Activate()
1018 mpView
->ResetCreationActive();
1019 mpView
->SetEditMode(SdrViewEditMode::Edit
);
1023 case SID_OBJECT_ROTATE
:
1025 eMode
= SdrDragMode::Rotate
;
1027 if ( mpView
->GetDragMode() != eMode
)
1028 mpView
->SetDragMode(eMode
);
1032 case SID_OBJECT_MIRROR
:
1034 eMode
= SdrDragMode::Mirror
;
1036 if ( mpView
->GetDragMode() != eMode
)
1037 mpView
->SetDragMode(eMode
);
1041 case SID_OBJECT_CROP
:
1043 eMode
= SdrDragMode::Crop
;
1045 if ( mpView
->GetDragMode() != eMode
)
1046 mpView
->SetDragMode(eMode
);
1050 case SID_OBJECT_TRANSPARENCE
:
1052 eMode
= SdrDragMode::Transparence
;
1054 if ( mpView
->GetDragMode() != eMode
)
1055 mpView
->SetDragMode(eMode
);
1059 case SID_OBJECT_GRADIENT
:
1061 eMode
= SdrDragMode::Gradient
;
1063 if ( mpView
->GetDragMode() != eMode
)
1064 mpView
->SetDragMode(eMode
);
1068 case SID_OBJECT_SHEAR
:
1070 eMode
= SdrDragMode::Shear
;
1072 if ( mpView
->GetDragMode() != eMode
)
1073 mpView
->SetDragMode(eMode
);
1077 case SID_OBJECT_CROOK_ROTATE
:
1079 eMode
= SdrDragMode::Crook
;
1081 if ( mpView
->GetDragMode() != eMode
)
1083 mpView
->SetDragMode(eMode
);
1084 mpView
->SetCrookMode(SdrCrookMode::Rotate
);
1089 case SID_OBJECT_CROOK_SLANT
:
1091 eMode
= SdrDragMode::Crook
;
1093 if ( mpView
->GetDragMode() != eMode
)
1095 mpView
->SetDragMode(eMode
);
1096 mpView
->SetCrookMode(SdrCrookMode::Slant
);
1101 case SID_OBJECT_CROOK_STRETCH
:
1103 eMode
= SdrDragMode::Crook
;
1105 if ( mpView
->GetDragMode() != eMode
)
1107 mpView
->SetDragMode(eMode
);
1108 mpView
->SetCrookMode(SdrCrookMode::Stretch
);
1113 case SID_CONVERT_TO_3D_LATHE
:
1115 eMode
= SdrDragMode::Mirror
;
1116 bSuppressChangesOfSelection
= true;
1118 if ( mpView
->GetDragMode() != eMode
)
1119 mpView
->SetDragMode(eMode
);
1121 if (!mpView
->Is3DRotationCreationActive())
1122 mpView
->Start3DCreation();
1124 bSuppressChangesOfSelection
= false;
1130 eMode
= SdrDragMode::Move
;
1132 if ( mpView
->GetDragMode() != eMode
)
1133 mpView
->SetDragMode(eMode
);
1138 if (nSlotId
!= SID_OBJECT_ROTATE
)
1140 bTempRotation
= false;
1146 void FuSelection::SelectionHasChanged()
1148 bSelectionChanged
= true;
1150 FuDraw::SelectionHasChanged();
1152 if (mpView
->Is3DRotationCreationActive() && !bSuppressChangesOfSelection
)
1154 // Switch rotation body -> selection
1155 mpView
->ResetCreationActive();
1156 nSlotId
= SID_OBJECT_SELECT
;
1160 // Activate the right tool bar for the current context of the view.
1161 mpViewShell
->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(*mpViewShell
, *mpView
);
1165 * Set current bezier edit mode
1167 void FuSelection::SetEditMode(sal_uInt16 nMode
)
1171 if (nEditMode
== SID_BEZIER_INSERT
)
1173 mpView
->SetInsObjPointMode(true);
1177 mpView
->SetInsObjPointMode(false);
1182 SfxBindings
& rBindings
= mpViewShell
->GetViewFrame()->GetBindings();
1183 rBindings
.Invalidate(SID_BEZIER_MOVE
);
1184 rBindings
.Invalidate(SID_BEZIER_INSERT
);
1188 * Execute animation or interaction
1190 bool FuSelection::AnimateObj(SdrObject
* pObj
, const Point
& rPos
)
1192 bool bAnimated
= false;
1193 bool bClosed
= pObj
->IsClosedObj();
1194 bool bFilled
= false;
1198 SfxItemSet
aSet(mpDoc
->GetPool());
1200 aSet
.Put(pObj
->GetMergedItemSet());
1202 const XFillStyleItem
& rFillStyle
= aSet
.Get(XATTR_FILLSTYLE
);
1203 bFilled
= rFillStyle
.GetValue() != drawing::FillStyle_NONE
;
1206 const SdrLayerIDSet
* pVisiLayer
= &mpView
->GetSdrPageView()->GetVisibleLayers();
1207 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
1208 const long n2HitLog
= nHitLog
* 2;
1209 Point
aHitPosR(rPos
);
1210 Point
aHitPosL(rPos
);
1211 Point
aHitPosT(rPos
);
1212 Point
aHitPosB(rPos
);
1214 aHitPosR
.AdjustX(n2HitLog
);
1215 aHitPosL
.AdjustX( -n2HitLog
);
1216 aHitPosT
.AdjustY( n2HitLog
);
1217 aHitPosB
.AdjustY( -n2HitLog
);
1221 (SdrObjectPrimitiveHit(*pObj
, aHitPosR
, nHitLog
, *mpView
->GetSdrPageView(), pVisiLayer
, false) &&
1222 SdrObjectPrimitiveHit(*pObj
, aHitPosL
, nHitLog
, *mpView
->GetSdrPageView(), pVisiLayer
, false) &&
1223 SdrObjectPrimitiveHit(*pObj
, aHitPosT
, nHitLog
, *mpView
->GetSdrPageView(), pVisiLayer
, false) &&
1224 SdrObjectPrimitiveHit(*pObj
, aHitPosB
, nHitLog
, *mpView
->GetSdrPageView(), pVisiLayer
, false) ) )
1226 if ( SdDrawDocument::GetIMapInfo( pObj
) )
1228 const IMapObject
* pIMapObj
= SdDrawDocument::GetHitIMapObject( pObj
, rPos
);
1230 if ( pIMapObj
&& !pIMapObj
->GetURL().isEmpty() )
1233 mpWindow
->ReleaseMouse();
1234 SfxStringItem
aStrItem(SID_FILE_NAME
, pIMapObj
->GetURL());
1235 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
1236 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
1237 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
1238 SfxBoolItem
aBrowseItem( SID_BROWSE
, true );
1239 mpWindow
->ReleaseMouse();
1240 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
1241 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1242 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
1247 else if( dynamic_cast< const GraphicDocShell
*>( mpDocSh
) == nullptr &&
1248 dynamic_cast< const DrawView
*>( mpView
) != nullptr &&
1249 SdDrawDocument::GetAnimationInfo(pObj
))
1251 /**********************************************************
1252 * Animation-object hit in the middle -> interaction
1253 **********************************************************/
1254 SdAnimationInfo
* pInfo
= SdDrawDocument::GetAnimationInfo(pObj
);
1255 DrawViewShell
* pDrViewSh
= static_cast<DrawViewShell
*>(mpViewShell
);
1256 mpWindow
->ReleaseMouse();
1258 switch (pInfo
->meClickAction
)
1260 case presentation::ClickAction_BOOKMARK
:
1262 // Jump to Bookmark (Page or Object)
1263 SfxStringItem
aItem(SID_NAVIGATOR_OBJECT
, pInfo
->GetBookmark());
1264 mpViewShell
->GetViewFrame()->GetDispatcher()->ExecuteList(
1265 SID_NAVIGATOR_OBJECT
,
1266 SfxCallMode::SLOT
| SfxCallMode::RECORD
, { &aItem
});
1271 case presentation::ClickAction_DOCUMENT
:
1273 OUString
sBookmark( pInfo
->GetBookmark() );
1275 if (!sBookmark
.isEmpty())
1277 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
1278 SfxStringItem
aStrItem(SID_FILE_NAME
, sBookmark
);
1279 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
1280 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
1281 SfxBoolItem
aBrowseItem( SID_BROWSE
, true );
1282 pFrame
->GetDispatcher()->
1283 ExecuteList(SID_OPENDOC
,
1284 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1285 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
1292 case presentation::ClickAction_PREVPAGE
:
1294 // Jump to the previous page
1295 SfxUInt16Item
aItem(SID_NAVIGATOR_PAGE
, PAGE_PREVIOUS
);
1296 mpViewShell
->GetViewFrame()->GetDispatcher()->
1297 ExecuteList(SID_NAVIGATOR_PAGE
,
1298 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1304 case presentation::ClickAction_NEXTPAGE
:
1306 // Jump to the next page
1307 SfxUInt16Item
aItem(SID_NAVIGATOR_PAGE
, PAGE_NEXT
);
1308 mpViewShell
->GetViewFrame()->GetDispatcher()->
1309 ExecuteList(SID_NAVIGATOR_PAGE
,
1310 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1316 case presentation::ClickAction_FIRSTPAGE
:
1318 // Jump to the first page
1319 SfxUInt16Item
aItem(SID_NAVIGATOR_PAGE
, PAGE_FIRST
);
1320 mpViewShell
->GetViewFrame()->GetDispatcher()->
1321 ExecuteList(SID_NAVIGATOR_PAGE
,
1322 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1328 case presentation::ClickAction_LASTPAGE
:
1330 // Jump to the last page
1331 SfxUInt16Item
aItem(SID_NAVIGATOR_PAGE
, PAGE_LAST
);
1332 mpViewShell
->GetViewFrame()->GetDispatcher()->
1333 ExecuteList(SID_NAVIGATOR_PAGE
,
1334 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1340 case presentation::ClickAction_SOUND
:
1342 #if HAVE_FEATURE_AVMEDIA
1345 mxPlayer
.set( avmedia::MediaWindow::createPlayer( pInfo
->GetBookmark(), ""/*TODO?*/), uno::UNO_SET_THROW
);
1348 catch( uno::Exception
& )
1356 case presentation::ClickAction_VERB
:
1359 mpView
->UnmarkAll();
1360 mpView
->MarkObj(pObj
, mpView
->GetSdrPageView());
1361 pDrViewSh
->DoVerb(static_cast<sal_Int16
>(pInfo
->mnVerb
));
1366 case presentation::ClickAction_PROGRAM
:
1368 OUString aBaseURL
= GetDocSh()->GetMedium()->GetBaseURL();
1369 INetURLObject
aURL( ::URIHelper::SmartRel2Abs( INetURLObject(aBaseURL
), pInfo
->GetBookmark(),
1370 URIHelper::GetMaybeFileHdl(), true, false,
1371 INetURLObject::EncodeMechanism::WasEncoded
, INetURLObject::DecodeMechanism::Unambiguous
) );
1373 if( INetProtocol::File
== aURL
.GetProtocol() )
1375 SfxStringItem
aUrl( SID_FILE_NAME
, aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1376 SfxBoolItem
aBrowsing( SID_BROWSE
, true );
1378 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
1380 pViewFrm
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
1381 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1382 { &aUrl
, &aBrowsing
});
1389 case presentation::ClickAction_MACRO
:
1392 OUString aMacro
= pInfo
->GetBookmark();
1394 if ( SfxApplication::IsXScriptURL( aMacro
) )
1397 uno::Sequence
< sal_Int16
> aOutArgsIndex
;
1398 uno::Sequence
<uno::Any
> aParams
;
1399 uno::Sequence
< uno::Any
> aOutArgs
;
1401 ErrCode eErr
= mpDocSh
->CallXScript( aMacro
,
1402 aParams
, aRet
, aOutArgsIndex
, aOutArgs
);
1404 // Check the return value from the script
1406 bAnimated
= eErr
== ERRCODE_NONE
&&
1407 aRet
.getValueType() == cppu::UnoType
<bool>::get() &&
1408 ( aRet
>>= bTmp
) &&
1413 // aMacro has got following format:
1414 // "Macroname.Modulname.Libname.Documentname" or
1415 // "Macroname.Modulname.Libname.Applicationname"
1416 sal_Int32 nIdx
{ 0 };
1417 const OUString aMacroName
= aMacro
.getToken(0, '.', nIdx
);
1418 const OUString aModulName
= aMacro
.getToken(0, '.', nIdx
);
1420 // In this moment the Call-method only
1421 // resolves modulename+macroname
1422 OUString
aExecMacro(aModulName
+ "." + aMacroName
);
1423 bAnimated
= mpDocSh
->GetBasic()->Call(aExecMacro
);
1437 dynamic_cast< const DrawView
*>( mpView
) != nullptr &&
1438 dynamic_cast< const GraphicDocShell
*>( mpDocSh
) == nullptr &&
1439 SlideShow::IsRunning( mpViewShell
->GetViewShellBase() ) &&
1440 SdDrawDocument::GetAnimationInfo(pObj
))
1442 /**********************************************************
1443 * Effect-Object hit in the middle -> Play effect
1444 **********************************************************/
1445 SdAnimationInfo
* pInfo
= SdDrawDocument::GetAnimationInfo(pObj
);
1447 switch (pInfo
->meClickAction
)
1449 case presentation::ClickAction_VANISH
:
1450 case presentation::ClickAction_INVISIBLE
:
1463 /** is called when the current function should be aborted. <p>
1464 This is used when a function gets a KEY_ESCAPE but can also
1467 @returns true if a active function was aborted
1469 bool FuSelection::cancel()
1471 if (mpView
->Is3DRotationCreationActive())
1473 mpView
->ResetCreationActive();
1474 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1483 SdrObject
* FuSelection::pickObject (const Point
& rTestPoint
)
1485 SdrPageView
* pPageView
;
1486 sal_uInt16 nHitLog
= sal_uInt16 (mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width());
1487 return mpView
->PickObj(rTestPoint
, nHitLog
, pPageView
, SdrSearchOptions::PICKMARKABLE
);
1490 void FuSelection::ForcePointer(const MouseEvent
* pMEvt
)
1492 if(bMovedToCenterPoint
&& !bBeginInsertPoint
&& pMEvt
)
1494 MouseEvent
aMEvt(pMEvt
->GetPosPixel(), pMEvt
->GetClicks(),
1495 pMEvt
->GetMode(), pMEvt
->GetButtons(), pMEvt
->GetModifier() & ~KEY_SHIFT
);
1496 FuDraw::ForcePointer(&aMEvt
);
1500 FuDraw::ForcePointer(pMEvt
);
1504 } // end of namespace sd
1506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */