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>
23 #include <basic/sbstar.hxx>
24 #include <svx/svddrgmt.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdogrp.hxx>
27 #include <svx/scene3d.hxx>
28 #include <drawview.hxx>
29 #include <svtools/imapobj.hxx>
30 #include <svl/urihelper.hxx>
31 #include <unotools/localfilehelper.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/aeitem.hxx>
38 #include <svl/stritem.hxx>
39 #include <svl/intitem.hxx>
40 #include <sfx2/dispatch.hxx>
41 #include <tools/urlobj.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <editeng/eeitem.hxx>
44 #include <editeng/flditem.hxx>
46 #include <svx/svdotable.hxx>
50 #include <GraphicDocShell.hxx>
52 #include <DrawDocShell.hxx>
53 #include <stlpool.hxx>
54 #include <anminfo.hxx>
56 #include <ViewShell.hxx>
57 #include <ViewShellBase.hxx>
58 #include <FrameView.hxx>
61 #include <drawdoc.hxx>
63 #include <DrawViewShell.hxx>
64 #include <ToolBarManager.hxx>
66 #include <svx/globl3d.hxx>
69 #include <slideshow.hxx>
71 #include <svx/svdundo.hxx>
72 #include <avmedia/mediawindow.hxx>
74 #include <svx/sdrhittesthelper.hxx>
76 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
77 #include <comphelper/lok.hxx>
79 using namespace ::com::sun::star
;
83 FuSelection::FuSelection (
89 : FuDraw(pViewSh
, pWin
, pView
, pDoc
, rReq
),
91 bSelectionChanged(false),
93 bSuppressChangesOfSelection(false),
95 nEditMode(SID_BEZIER_MOVE
),
96 pWaterCanCandidate(nullptr)
97 //Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point,
98 //and SHIFT+ENTER key to decide the position and draw the new insert point
99 ,bBeginInsertPoint(false),
101 ,bMovedToCenterPoint(false)
105 rtl::Reference
<FuPoor
> FuSelection::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
)
107 rtl::Reference
<FuPoor
> xFunc( new FuSelection( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
108 xFunc
->DoExecute(rReq
);
112 void FuSelection::DoExecute( SfxRequest
& rReq
)
114 FuDraw::DoExecute( rReq
);
117 SelectionHasChanged();
120 FuSelection::~FuSelection()
122 mpView
->UnmarkAllPoints();
123 mpView
->ResetCreationActive();
125 if ( mpView
->GetDragMode() != SdrDragMode::Move
)
127 mpView
->SetDragMode(SdrDragMode::Move
);
131 bool FuSelection::MouseButtonDown(const MouseEvent
& rMEvt
)
134 bool bReturn
= FuDraw::MouseButtonDown(rMEvt
);
135 bool bWaterCan
= SD_MOD()->GetWaterCan();
136 const bool bReadOnly
= mpDocSh
->IsReadOnly();
137 // When the right mouse button is pressed then only select objects
138 // (and deselect others) as a preparation for showing the context
140 const bool bSelectionOnly
= rMEvt
.IsRight();
143 bSelectionChanged
= false;
145 if ( mpView
->IsAction() )
147 if ( rMEvt
.IsRight() )
152 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(DRGPIX
,0)).Width() );
153 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
155 if (comphelper::LibreOfficeKit::isActive())
157 // When tiled rendering, we always work in logic units, use the non-pixel constants.
162 // The following code is executed for right clicks as well as for left
163 // clicks in order to modify the selection for the right button as a
164 // preparation for the context menu. The functions BegMarkObject() and
165 // BegDragObject(), however, are not called for right clicks because a)
166 // it makes no sense and b) to have IsAction() return sal_False when called
167 // from Command() which is a prerequisite for the context menu.
168 if ((rMEvt
.IsLeft() || rMEvt
.IsRight())
169 && !mpView
->IsAction()
170 && (mpView
->IsFrameDragSingles() || !mpView
->HasMarkablePoints()))
172 /******************************************************************
174 ******************************************************************/
175 mpWindow
->CaptureMouse();
176 pHdl
= mpView
->PickHandle(aMDPos
);
178 long nAngle0
= GetAngle(aMDPos
- mpView
->GetRef1());
180 nAngle0
= NormAngle360(nAngle0
);
181 bMirrorSide0
= nAngle0
< 18000;
183 if (!pHdl
&& mpView
->Is3DRotationCreationActive())
185 /******************************************************************
186 * If 3D-rotation bodies are about to be created,
188 ******************************************************************/
189 bSuppressChangesOfSelection
= true;
190 mpWindow
->EnterWait();
191 mpView
->End3DCreation();
192 bSuppressChangesOfSelection
= false;
193 mpView
->ResetCreationActive();
194 mpWindow
->LeaveWait();
197 bool bTextEdit
= false;
199 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
201 if ( eHit
== SdrHitKind::TextEditObj
&& ( mpViewShell
->GetFrameView()->IsQuickEdit() || dynamic_cast< sdr::table::SdrTableObj
* >( aVEvt
.pObj
) != nullptr ) )
207 && !mpDocSh
->IsReadOnly()
208 && ((mpView
->IsMarkedHit(aMDPos
, nHitLog
) && !rMEvt
.IsShift() && !rMEvt
.IsMod2()) || pHdl
!= nullptr)
209 && (rMEvt
.GetClicks() != 2)
212 if (!pHdl
&& mpView
->Is3DRotationCreationActive())
214 // Switch between 3D-rotation body -> selection
215 mpView
->ResetCreationActive();
219 // Remember the selected object for proper handling in
221 pWaterCanCandidate
= pickObject (aMDPos
);
225 // hit handle or marked object
226 bFirstMouseMove
= true;
230 if ( ! rMEvt
.IsRight())
231 if (mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
))
232 mpView
->GetDragMethod()->SetShiftPressed( rMEvt
.IsShift() );
237 SdrPageView
* pPV
= nullptr;
238 SdrObject
* pObj
= !rMEvt
.IsMod2() ? mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::PICKMACRO
) : nullptr;
241 mpView
->BegMacroObj(aMDPos
, nHitLog
, pObj
, pPV
, mpWindow
);
244 else if ( bTextEdit
)
246 sal_uInt16 nSdrObjKind
= aVEvt
.pObj
->GetObjIdentifier();
248 if (aVEvt
.pObj
->GetObjInventor() == SdrInventor::Default
&&
249 (nSdrObjKind
== OBJ_TEXT
||
250 nSdrObjKind
== OBJ_TITLETEXT
||
251 nSdrObjKind
== OBJ_OUTLINETEXT
||
252 !aVEvt
.pObj
->IsEmptyPresObj()))
254 // Seamless Editing: branch to text input
255 if (!rMEvt
.IsShift())
258 SfxUInt16Item
aItem(SID_TEXTEDIT
, 1);
259 mpViewShell
->GetViewFrame()->GetDispatcher()->
260 ExecuteList(SID_TEXTEDIT
,
261 SfxCallMode::SYNCHRON
| SfxCallMode::RECORD
,
263 return bReturn
; // CAUTION, due to the synchronous slot the object is deleted now
266 else if ( !rMEvt
.IsMod2() && rMEvt
.GetClicks() == 1 &&
267 aVEvt
.eEvent
== SdrEventKind::ExecuteUrl
)
269 mpWindow
->ReleaseMouse();
271 SvtSecurityOptions aSecOpt
;
272 if (!rMEvt
.IsMod1() && aSecOpt
.IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink
))
274 if (rMEvt
.IsMod1() && !aSecOpt
.IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink
))
277 SfxStringItem
aStrItem(SID_FILE_NAME
, aVEvt
.pURLField
->GetURL());
278 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
279 SfxBoolItem
aBrowseItem( SID_BROWSE
, true );
280 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
281 mpWindow
->ReleaseMouse();
283 // If tiled rendering, let client handles URL execution and early returns.
284 if (comphelper::LibreOfficeKit::isActive())
286 SfxViewShell
& rSfxViewShell
= mpViewShell
->GetViewShellBase();
287 rSfxViewShell
.libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED
, aVEvt
.pURLField
->GetURL().toUtf8().getStr());
294 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
295 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
296 { &aStrItem
, &aBrowseItem
, &aReferer
});
300 // Open in current frame
301 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
302 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
303 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
304 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
309 else if(!rMEvt
.IsMod2()
310 && dynamic_cast< const DrawViewShell
*>( mpViewShell
) != nullptr
313 pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
);
316 // Animate object when not just selecting.
317 if ( ! bSelectionOnly
)
318 bReturn
= AnimateObj(pObj
, aMDPos
);
320 if( !bReturn
&& (dynamic_cast< const SdrObjGroup
*>( pObj
) != nullptr || dynamic_cast< const E3dScene
* >(pObj
) != nullptr))
322 if(rMEvt
.GetClicks() == 1)
324 // Look into the group
325 pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
| SdrSearchOptions::DEEP
);
327 bReturn
= AnimateObj(pObj
, aMDPos
);
329 else if( !bReadOnly
&& rMEvt
.GetClicks() == 2)
331 // New: double click on selected Group object
333 if ( ! bSelectionOnly
334 && pObj
->GetPage() == pPV
->GetPage())
335 bReturn
= pPV
->EnterGroup(pObj
);
340 // #i71727# replaced else here with two possibilities, once the original else (!pObj)
341 // and also ignoring the found object when it's on a masterpage
342 if(!pObj
|| (pObj
->GetPage() && pObj
->GetPage()->IsMasterPage()))
344 if(mpView
->IsGroupEntered() && 2 == rMEvt
.GetClicks())
346 // New: double click on empty space/on obj on MasterPage, leave group
347 mpView
->LeaveOneGroup();
357 if ( ! (rMEvt
.IsShift() || rMEvt
.IsMod2()))
359 // Find the object under the current mouse position
360 // and store it for the MouseButtonUp() method to
362 pWaterCanCandidate
= pickObject (aMDPos
);
368 bool bDeactivateOLE
= false;
370 if ( !rMEvt
.IsShift() && !rMEvt
.IsMod2() )
372 OSL_ASSERT (mpViewShell
->GetViewShell()!=nullptr);
373 Client
* pIPClient
= static_cast<Client
*>(
374 mpViewShell
->GetViewShell()->GetIPClient());
376 if (pIPClient
&& pIPClient
->IsObjectInPlaceActive())
378 // OLE-object gets deactivated in subsequent UnmarkAll()
379 bDeactivateOLE
= true;
385 bool bMarked
= false;
387 if ( !rMEvt
.IsMod1() && !bDeactivateOLE
)
389 if ( rMEvt
.IsMod2() )
391 bMarked
= mpView
->MarkNextObj(aMDPos
, nHitLog
, rMEvt
.IsShift() );
395 bool bToggle
= false;
397 if (rMEvt
.IsShift() && mpView
->GetMarkedObjectList().GetMarkCount() > 1)
399 // No Toggle on single selection
403 bMarked
= mpView
->MarkObj(aMDPos
, nHitLog
, bToggle
);
407 if( !bDeactivateOLE
)
411 (!rMEvt
.IsShift() || mpView
->IsMarkedHit(aMDPos
, nHitLog
)))
413 /**********************************************************
415 **********************************************************/
418 pHdl
=mpView
->PickHandle(aMDPos
);
419 if ( ! rMEvt
.IsRight())
420 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
424 /**********************************************************
426 **********************************************************/
427 if ( ! rMEvt
.IsRight())
428 mpView
->BegMarkObj(aMDPos
);
432 if( bMarked
&& bTempRotation
&& (nSlotId
== SID_OBJECT_ROTATE
) && !rMEvt
.IsShift() && (rMEvt
.GetClicks() != 2) )
434 nSlotId
= SID_OBJECT_SELECT
;
442 && (rMEvt
.IsLeft() || rMEvt
.IsRight())
443 && !mpView
->IsAction())
445 /**********************************************************************
447 **********************************************************************/
448 mpWindow
->CaptureMouse();
450 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
452 if (eHit
== SdrHitKind::Handle
&& aVEvt
.pHdl
->GetKind() == SdrHdlKind::BezierWeight
)
454 /******************************************************************
456 ******************************************************************/
457 if ( ! rMEvt
.IsRight())
458 mpView
->BegDragObj(aMDPos
, nullptr, aVEvt
.pHdl
, nDrgLog
);
460 else if (eHit
== SdrHitKind::MarkedObject
&& nEditMode
== SID_BEZIER_INSERT
)
462 /******************************************************************
464 ******************************************************************/
465 mpView
->BegInsObjPoint(aMDPos
, rMEvt
.IsMod1());
467 else if (eHit
== SdrHitKind::MarkedObject
&& rMEvt
.IsMod1())
469 /******************************************************************
471 ******************************************************************/
472 if (!rMEvt
.IsShift())
473 mpView
->UnmarkAllPoints();
475 if ( ! rMEvt
.IsRight())
476 mpView
->BegMarkPoints(aMDPos
);
478 else if (eHit
== SdrHitKind::MarkedObject
&& !rMEvt
.IsShift() && !rMEvt
.IsMod2())
480 /******************************************************************
482 ******************************************************************/
483 if ( ! rMEvt
.IsRight())
484 mpView
->BegDragObj(aMDPos
, nullptr, nullptr, nDrgLog
);
486 else if (eHit
== SdrHitKind::Handle
)
488 /******************************************************************
490 ******************************************************************/
491 if (!mpView
->IsPointMarked(*aVEvt
.pHdl
) || rMEvt
.IsShift())
493 if (!rMEvt
.IsShift())
495 mpView
->UnmarkAllPoints();
496 pHdl
= mpView
->PickHandle(aMDPos
);
500 if (mpView
->IsPointMarked(*aVEvt
.pHdl
))
502 mpView
->UnmarkPoint(*aVEvt
.pHdl
);
507 pHdl
= mpView
->PickHandle(aMDPos
);
513 mpView
->MarkPoint(*pHdl
);
514 if ( ! rMEvt
.IsRight())
515 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
521 // Point IS marked and NO shift is pressed. Start
522 // dragging of selected point(s)
523 pHdl
= mpView
->PickHandle(aMDPos
);
525 if ( ! rMEvt
.IsRight())
526 mpView
->BegDragObj(aMDPos
, nullptr, pHdl
, nDrgLog
);
531 /******************************************************************
532 * Select or drag object
533 ******************************************************************/
534 if (!rMEvt
.IsShift() && !rMEvt
.IsMod2() && eHit
== SdrHitKind::UnmarkedObject
)
536 mpView
->UnmarkAllObj();
539 bool bMarked
= false;
545 bMarked
= mpView
->MarkNextObj(aMDPos
, nHitLog
, rMEvt
.IsShift());
549 bMarked
= mpView
->MarkObj(aMDPos
, nHitLog
, rMEvt
.IsShift());
554 (!rMEvt
.IsShift() || eHit
== SdrHitKind::MarkedObject
))
557 if ( ! rMEvt
.IsRight())
558 mpView
->BegDragObj(aMDPos
, nullptr, aVEvt
.pHdl
, nDrgLog
);
560 else if (mpView
->AreObjectsMarked())
562 /**************************************************************
564 **************************************************************/
565 if (!rMEvt
.IsShift())
566 mpView
->UnmarkAllPoints();
568 if ( ! rMEvt
.IsRight())
569 mpView
->BegMarkPoints(aMDPos
);
573 /**************************************************************
575 **************************************************************/
576 if ( ! rMEvt
.IsRight())
577 mpView
->BegMarkObj(aMDPos
);
580 ForcePointer(&rMEvt
);
586 ForcePointer(&rMEvt
);
592 bool FuSelection::MouseMove(const MouseEvent
& rMEvt
)
594 bool bReturn
= FuDraw::MouseMove(rMEvt
);
596 if (aDragTimer
.IsActive())
600 bFirstMouseMove
= false;
608 if (mpView
->IsAction())
610 Point
aPix(rMEvt
.GetPosPixel());
611 Point
aPnt(mpWindow
->PixelToLogic(aPix
));
615 if (mpView
->IsInsObjPoint())
617 mpView
->MovInsObjPoint(aPnt
);
621 mpView
->MovAction(aPnt
);
625 ForcePointer(&rMEvt
);
630 bool FuSelection::MouseButtonUp(const MouseEvent
& rMEvt
)
632 bool bReturn
= false;
633 // When the right mouse button is pressed then only select objects
634 // (and deselect others) as a preparation for showing the context
636 const bool bSelectionOnly
= rMEvt
.IsRight();
638 if (aDragTimer
.IsActive() )
641 bIsInDragMode
= false;
647 Point
aPnt( mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() ) );
648 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
649 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(DRGPIX
,0)).Width() );
651 if (mpView
->IsFrameDragSingles() || !mpView
->HasMarkablePoints())
653 /**********************************************************************
655 **********************************************************************/
656 if ( mpView
->IsDragObj() )
658 /******************************************************************
660 ******************************************************************/
661 FrameView
* pFrameView
= mpViewShell
->GetFrameView();
662 bool bDragWithCopy
= (rMEvt
.IsMod1() && pFrameView
->IsDragWithCopy());
666 bDragWithCopy
= !mpView
->IsPresObjSelected(false);
669 mpView
->SetDragWithCopy(bDragWithCopy
);
670 mpView
->EndDragObj( mpView
->IsDragWithCopy() );
672 mpView
->ForceMarkedToAnotherPage();
674 if (!rMEvt
.IsShift() && !rMEvt
.IsMod1() && !rMEvt
.IsMod2() &&
675 !bSelectionChanged
&&
676 std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
&&
677 std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
679 /*************************************************************
680 * If a user wants to click on an object in front of a marked
681 * one, he releases the mouse button immediately
682 **************************************************************/
684 SdrObject
* pObj
= mpView
->PickObj(aMDPos
, mpView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
| SdrSearchOptions::BEFOREMARK
);
687 if (pPV
->IsObjMarkable(pObj
))
689 mpView
->UnmarkAllObj();
690 mpView
->MarkObj(pObj
,pPV
);
694 /**************************************************************
695 * Toggle between selection and rotation
696 **************************************************************/
697 SdrObject
* pSingleObj
= nullptr;
699 if (mpView
->GetMarkedObjectList().GetMarkCount()==1)
701 pSingleObj
= mpView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
704 if (nSlotId
== SID_OBJECT_SELECT
705 && mpView
->IsRotateAllowed()
707 && (rMEvt
.GetClicks() != 2)
708 && (mpViewShell
->GetFrameView()->IsClickChangeRotation()
710 && pSingleObj
->GetObjInventor()==SdrInventor::E3d
))
714 bTempRotation
= true;
715 nSlotId
= SID_OBJECT_ROTATE
;
718 else if (nSlotId
== SID_OBJECT_ROTATE
)
720 nSlotId
= SID_OBJECT_SELECT
;
724 else if (nSlotId
== SID_CONVERT_TO_3D_LATHE
)
728 bSuppressChangesOfSelection
= true;
729 mpView
->Start3DCreation();
730 bSuppressChangesOfSelection
= false;
732 else if (pHdl
->GetKind() != SdrHdlKind::MirrorAxis
&&
733 pHdl
->GetKind() != SdrHdlKind::Ref1
&&
734 pHdl
->GetKind() != SdrHdlKind::Ref2
&& mpView
->Is3DRotationCreationActive())
736 /*********************************************************
737 * If 3D-rotation bodies are about to be created,
739 **********************************************************/
740 long nAngle1
= GetAngle(aPnt
- mpView
->GetRef1());
742 nAngle1
= NormAngle360(nAngle1
);
743 bool bMirrorSide1
= nAngle1
< 18000;
745 if (bMirrorSide0
!= bMirrorSide1
)
747 bSuppressChangesOfSelection
= true;
748 mpWindow
->EnterWait();
749 mpView
->End3DCreation();
750 bSuppressChangesOfSelection
= false;
751 nSlotId
= SID_OBJECT_SELECT
;
752 mpWindow
->LeaveWait();
758 else if (rMEvt
.IsMod1()
760 && std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
761 && std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
764 mpView
->MarkObj(aPnt
, nHitLog
, rMEvt
.IsShift(), rMEvt
.IsMod1());
767 if (mpView
->IsAction() )
772 if( SD_MOD()->GetWaterCan() )
774 if( rMEvt
.IsRight() )
776 // In watering-can mode, on press onto right mouse button, a undo is executed
777 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute( SID_UNDO
, SfxCallMode::ASYNCHRON
);
779 else if (pWaterCanCandidate
!= nullptr)
781 // Is the candidate object still under the mouse?
782 if (pickObject (aPnt
) == pWaterCanCandidate
)
784 SdStyleSheetPool
* pPool
= static_cast<SdStyleSheetPool
*>(
785 mpDocSh
->GetStyleSheetPool());
786 if (pPool
!= nullptr)
788 SfxStyleSheet
* pStyleSheet
= static_cast<SfxStyleSheet
*>(
789 pPool
->GetActualStyleSheet());
790 if (pStyleSheet
!= nullptr && mpView
->IsUndoEnabled() )
792 // Added UNDOs for the WaterCan mode. This was never done in
793 // the past, thus it was missing all the time.
794 SdrUndoAction
* pUndoAttr
= mpDoc
->GetSdrUndoFactory().CreateUndoAttrObject(*pWaterCanCandidate
, true, true);
795 mpView
->BegUndo(pUndoAttr
->GetComment());
796 mpView
->AddUndo(mpDoc
->GetSdrUndoFactory().CreateUndoGeoObject(*pWaterCanCandidate
));
797 mpView
->AddUndo(pUndoAttr
);
799 pWaterCanCandidate
->SetStyleSheet (pStyleSheet
, false);
806 // else when there has been no object under the mouse when the
807 // button was pressed then nothing happens even when there is
811 sal_uInt16 nClicks
= rMEvt
.GetClicks();
813 if (nClicks
== 2 && rMEvt
.IsLeft() && bMBDown
&&
814 !rMEvt
.IsMod1() && !rMEvt
.IsShift() )
821 ForcePointer(&rMEvt
);
823 mpWindow
->ReleaseMouse();
824 SdrObject
* pSingleObj
= nullptr;
825 const size_t nMarkCount
= mpView
->GetMarkedObjectList().GetMarkCount();
829 pSingleObj
= mpView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
832 if ( (nSlotId
!= SID_OBJECT_SELECT
&& nMarkCount
==0) ||
833 ( mpView
->GetDragMode() == SdrDragMode::Crook
&&
834 !mpView
->IsCrookAllowed( mpView
->IsCrookNoContortion() ) ) ||
835 ( mpView
->GetDragMode() == SdrDragMode::Shear
&&
836 !mpView
->IsShearAllowed() && !mpView
->IsDistortAllowed() ) ||
837 ( nSlotId
==SID_CONVERT_TO_3D_LATHE
&& pSingleObj
&&
838 (pSingleObj
->GetObjInventor() != SdrInventor::Default
||
839 pSingleObj
->GetObjIdentifier() == OBJ_MEASURE
) ) )
842 ForcePointer(&rMEvt
);
844 mpWindow
->ReleaseMouse();
845 FuDraw::MouseButtonUp(rMEvt
);
846 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::SYNCHRON
);
847 return bReturn
; // CAUTION, due to the synchronous slot, the object is deleted now.
850 FuDraw::MouseButtonUp(rMEvt
);
854 /**********************************************************************
856 **********************************************************************/
857 if ( mpView
->IsAction() )
859 if ( mpView
->IsInsObjPoint() )
861 mpView
->EndInsObjPoint(SdrCreateCmd::ForceEnd
);
863 else if ( mpView
->IsDragObj() )
865 FrameView
* pFrameView
= mpViewShell
->GetFrameView();
866 bool bDragWithCopy
= (rMEvt
.IsMod1() && pFrameView
->IsDragWithCopy());
870 bDragWithCopy
= !mpView
->IsPresObjSelected(false);
873 mpView
->SetDragWithCopy(bDragWithCopy
);
874 mpView
->EndDragObj( mpView
->IsDragWithCopy() );
880 sal_uInt16 nDrgLog2
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(DRGPIX
,0)).Width() );
881 Point aPos
= mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() );
883 if (std::abs(aMDPos
.X() - aPos
.X()) < nDrgLog2
&&
884 std::abs(aMDPos
.Y() - aPos
.Y()) < nDrgLog2
&&
885 !rMEvt
.IsShift() && !rMEvt
.IsMod2())
888 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
890 if (eHit
== SdrHitKind::NONE
)
892 // Click on the same place - unselect
893 mpView
->UnmarkAllObj();
898 else if (!rMEvt
.IsShift() && rMEvt
.IsMod1() && !rMEvt
.IsMod2() &&
899 std::abs(aPnt
.X() - aMDPos
.X()) < nDrgLog
&&
900 std::abs(aPnt
.Y() - aMDPos
.Y()) < nDrgLog
)
903 mpView
->MarkObj(aPnt
, nHitLog
, false, rMEvt
.IsMod1());
906 ForcePointer(&rMEvt
);
908 mpWindow
->ReleaseMouse();
910 FuDraw::MouseButtonUp(rMEvt
);
917 * Process keyboard input
918 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
920 bool FuSelection::KeyInput(const KeyEvent
& rKEvt
)
922 bool bReturn
= false;
924 switch (rKEvt
.GetKeyCode().GetCode())
928 bReturn
= FuSelection::cancel();
931 //add keyboard operation for insert points in drawing curve
937 if(rKEvt
.GetKeyCode().IsShift()&&(nEditMode
== SID_BEZIER_INSERT
)){
940 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
947 else if (nCode
== KEY_DOWN
)
953 else if (nCode
== KEY_LEFT
)
959 else if (nCode
== KEY_RIGHT
)
967 ::tools::Rectangle rect
= mpView
->GetMarkedObjRect();
968 centerPoint
= mpWindow
->LogicToPixel(rect
.Center());
969 Point aPoint
= bMovedToCenterPoint
? oldPoint
:centerPoint
;
970 Point ePoint
= aPoint
+ Point(nX
,nY
);
971 mpWindow
->SetPointerPosPixel(ePoint
);
972 //simulate mouse move action
973 MouseEvent
eMevt(ePoint
, 1, MouseEventModifiers::DRAGMOVE
, MOUSE_LEFT
, 0);
976 bMovedToCenterPoint
= true;
982 if(rKEvt
.GetKeyCode().IsShift()&&(nEditMode
== SID_BEZIER_INSERT
))
984 if(!bBeginInsertPoint
)
986 //simulate mouse button down action
987 MouseEvent
aMevt(oldPoint
, 1,
988 MouseEventModifiers::SIMPLEMOVE
| MouseEventModifiers::DRAGMOVE
,
989 MOUSE_LEFT
, KEY_SHIFT
);
990 MouseButtonDown(aMevt
);
991 mpWindow
->CaptureMouse();
992 bBeginInsertPoint
= true;
996 //simulate mouse button up action
997 MouseEvent
rMEvt(oldPoint
, 1,
998 MouseEventModifiers::SIMPLEMOVE
| MouseEventModifiers::ENTERWINDOW
,
999 MOUSE_LEFT
, KEY_SHIFT
);
1000 MouseButtonUp(rMEvt
);
1001 bBeginInsertPoint
= false;
1009 bReturn
= FuDraw::KeyInput(rKEvt
);
1011 if(mpView
->GetMarkedObjectList().GetMarkCount() == 0)
1013 mpView
->ResetCreationActive();
1015 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1023 void FuSelection::Activate()
1026 mpView
->ResetCreationActive();
1027 mpView
->SetEditMode(SdrViewEditMode::Edit
);
1031 case SID_OBJECT_ROTATE
:
1033 eMode
= SdrDragMode::Rotate
;
1035 if ( mpView
->GetDragMode() != eMode
)
1036 mpView
->SetDragMode(eMode
);
1040 case SID_OBJECT_MIRROR
:
1042 eMode
= SdrDragMode::Mirror
;
1044 if ( mpView
->GetDragMode() != eMode
)
1045 mpView
->SetDragMode(eMode
);
1049 case SID_OBJECT_CROP
:
1051 eMode
= SdrDragMode::Crop
;
1053 if ( mpView
->GetDragMode() != eMode
)
1054 mpView
->SetDragMode(eMode
);
1058 case SID_OBJECT_TRANSPARENCE
:
1060 eMode
= SdrDragMode::Transparence
;
1062 if ( mpView
->GetDragMode() != eMode
)
1063 mpView
->SetDragMode(eMode
);
1067 case SID_OBJECT_GRADIENT
:
1069 eMode
= SdrDragMode::Gradient
;
1071 if ( mpView
->GetDragMode() != eMode
)
1072 mpView
->SetDragMode(eMode
);
1076 case SID_OBJECT_SHEAR
:
1078 eMode
= SdrDragMode::Shear
;
1080 if ( mpView
->GetDragMode() != eMode
)
1081 mpView
->SetDragMode(eMode
);
1085 case SID_OBJECT_CROOK_ROTATE
:
1087 eMode
= SdrDragMode::Crook
;
1089 if ( mpView
->GetDragMode() != eMode
)
1091 mpView
->SetDragMode(eMode
);
1092 mpView
->SetCrookMode(SdrCrookMode::Rotate
);
1097 case SID_OBJECT_CROOK_SLANT
:
1099 eMode
= SdrDragMode::Crook
;
1101 if ( mpView
->GetDragMode() != eMode
)
1103 mpView
->SetDragMode(eMode
);
1104 mpView
->SetCrookMode(SdrCrookMode::Slant
);
1109 case SID_OBJECT_CROOK_STRETCH
:
1111 eMode
= SdrDragMode::Crook
;
1113 if ( mpView
->GetDragMode() != eMode
)
1115 mpView
->SetDragMode(eMode
);
1116 mpView
->SetCrookMode(SdrCrookMode::Stretch
);
1121 case SID_CONVERT_TO_3D_LATHE
:
1123 eMode
= SdrDragMode::Mirror
;
1124 bSuppressChangesOfSelection
= true;
1126 if ( mpView
->GetDragMode() != eMode
)
1127 mpView
->SetDragMode(eMode
);
1129 if (!mpView
->Is3DRotationCreationActive())
1130 mpView
->Start3DCreation();
1132 bSuppressChangesOfSelection
= false;
1138 eMode
= SdrDragMode::Move
;
1140 if ( mpView
->GetDragMode() != eMode
)
1141 mpView
->SetDragMode(eMode
);
1146 if (nSlotId
!= SID_OBJECT_ROTATE
)
1148 bTempRotation
= false;
1154 void FuSelection::SelectionHasChanged()
1156 bSelectionChanged
= true;
1158 FuDraw::SelectionHasChanged();
1160 if (mpView
->Is3DRotationCreationActive() && !bSuppressChangesOfSelection
)
1162 // Switch rotation body -> selection
1163 mpView
->ResetCreationActive();
1164 nSlotId
= SID_OBJECT_SELECT
;
1168 // Activate the right tool bar for the current context of the view.
1169 mpViewShell
->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(*mpViewShell
, *mpView
);
1173 * Set current bezier edit mode
1175 void FuSelection::SetEditMode(sal_uInt16 nMode
)
1179 if (nEditMode
== SID_BEZIER_INSERT
)
1181 mpView
->SetInsObjPointMode(true);
1185 mpView
->SetInsObjPointMode(false);
1190 SfxBindings
& rBindings
= mpViewShell
->GetViewFrame()->GetBindings();
1191 rBindings
.Invalidate(SID_BEZIER_MOVE
);
1192 rBindings
.Invalidate(SID_BEZIER_INSERT
);
1196 * Execute animation or interaction
1198 bool FuSelection::AnimateObj(SdrObject
* pObj
, const Point
& rPos
)
1200 bool bAnimated
= false;
1201 bool bClosed
= pObj
->IsClosedObj();
1202 bool bFilled
= false;
1206 SfxItemSet
aSet(mpDoc
->GetPool());
1208 aSet
.Put(pObj
->GetMergedItemSet());
1210 const XFillStyleItem
& rFillStyle
= aSet
.Get(XATTR_FILLSTYLE
);
1211 bFilled
= rFillStyle
.GetValue() != drawing::FillStyle_NONE
;
1214 const SdrLayerIDSet
* pVisiLayer
= &mpView
->GetSdrPageView()->GetVisibleLayers();
1215 sal_uInt16 nHitLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width() );
1216 const long n2HitLog
= nHitLog
* 2;
1217 Point
aHitPosR(rPos
);
1218 Point
aHitPosL(rPos
);
1219 Point
aHitPosT(rPos
);
1220 Point
aHitPosB(rPos
);
1222 aHitPosR
.AdjustX(n2HitLog
);
1223 aHitPosL
.AdjustX( -n2HitLog
);
1224 aHitPosT
.AdjustY( n2HitLog
);
1225 aHitPosB
.AdjustY( -n2HitLog
);
1229 (SdrObjectPrimitiveHit(*pObj
, aHitPosR
, nHitLog
, *mpView
->GetSdrPageView(), pVisiLayer
, false) &&
1230 SdrObjectPrimitiveHit(*pObj
, aHitPosL
, nHitLog
, *mpView
->GetSdrPageView(), pVisiLayer
, false) &&
1231 SdrObjectPrimitiveHit(*pObj
, aHitPosT
, nHitLog
, *mpView
->GetSdrPageView(), pVisiLayer
, false) &&
1232 SdrObjectPrimitiveHit(*pObj
, aHitPosB
, nHitLog
, *mpView
->GetSdrPageView(), pVisiLayer
, false) ) )
1234 if ( SdDrawDocument::GetIMapInfo( pObj
) )
1236 const IMapObject
* pIMapObj
= SdDrawDocument::GetHitIMapObject( pObj
, rPos
);
1238 if ( pIMapObj
&& !pIMapObj
->GetURL().isEmpty() )
1241 mpWindow
->ReleaseMouse();
1242 SfxStringItem
aStrItem(SID_FILE_NAME
, pIMapObj
->GetURL());
1243 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
1244 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
1245 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
1246 SfxBoolItem
aBrowseItem( SID_BROWSE
, true );
1247 mpWindow
->ReleaseMouse();
1248 pFrame
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
1249 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1250 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
1255 else if( dynamic_cast< const GraphicDocShell
*>( mpDocSh
) == nullptr &&
1256 dynamic_cast< const DrawView
*>( mpView
) != nullptr &&
1257 SdDrawDocument::GetAnimationInfo(pObj
))
1259 /**********************************************************
1260 * Animation-object hit in the middle -> interaction
1261 **********************************************************/
1262 SdAnimationInfo
* pInfo
= SdDrawDocument::GetAnimationInfo(pObj
);
1263 DrawViewShell
* pDrViewSh
= static_cast<DrawViewShell
*>(mpViewShell
);
1264 mpWindow
->ReleaseMouse();
1266 switch (pInfo
->meClickAction
)
1268 case presentation::ClickAction_BOOKMARK
:
1270 // Jump to Bookmark (Page or Object)
1271 SfxStringItem
aItem(SID_NAVIGATOR_OBJECT
, pInfo
->GetBookmark());
1272 mpViewShell
->GetViewFrame()->GetDispatcher()->ExecuteList(
1273 SID_NAVIGATOR_OBJECT
,
1274 SfxCallMode::SLOT
| SfxCallMode::RECORD
, { &aItem
});
1279 case presentation::ClickAction_DOCUMENT
:
1281 OUString
sBookmark( pInfo
->GetBookmark() );
1283 if (!sBookmark
.isEmpty())
1285 SfxStringItem
aReferer(SID_REFERER
, mpDocSh
->GetMedium()->GetName());
1286 SfxStringItem
aStrItem(SID_FILE_NAME
, sBookmark
);
1287 SfxViewFrame
* pFrame
= mpViewShell
->GetViewFrame();
1288 SfxFrameItem
aFrameItem(SID_DOCFRAME
, pFrame
);
1289 SfxBoolItem
aBrowseItem( SID_BROWSE
, true );
1290 pFrame
->GetDispatcher()->
1291 ExecuteList(SID_OPENDOC
,
1292 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1293 { &aStrItem
, &aFrameItem
, &aBrowseItem
, &aReferer
});
1300 case presentation::ClickAction_PREVPAGE
:
1302 // Jump to the previous page
1303 SfxUInt16Item
aItem(SID_NAVIGATOR_PAGE
, PAGE_PREVIOUS
);
1304 mpViewShell
->GetViewFrame()->GetDispatcher()->
1305 ExecuteList(SID_NAVIGATOR_PAGE
,
1306 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1312 case presentation::ClickAction_NEXTPAGE
:
1314 // Jump to the next page
1315 SfxUInt16Item
aItem(SID_NAVIGATOR_PAGE
, PAGE_NEXT
);
1316 mpViewShell
->GetViewFrame()->GetDispatcher()->
1317 ExecuteList(SID_NAVIGATOR_PAGE
,
1318 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1324 case presentation::ClickAction_FIRSTPAGE
:
1326 // Jump to the first page
1327 SfxUInt16Item
aItem(SID_NAVIGATOR_PAGE
, PAGE_FIRST
);
1328 mpViewShell
->GetViewFrame()->GetDispatcher()->
1329 ExecuteList(SID_NAVIGATOR_PAGE
,
1330 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1336 case presentation::ClickAction_LASTPAGE
:
1338 // Jump to the last page
1339 SfxUInt16Item
aItem(SID_NAVIGATOR_PAGE
, PAGE_LAST
);
1340 mpViewShell
->GetViewFrame()->GetDispatcher()->
1341 ExecuteList(SID_NAVIGATOR_PAGE
,
1342 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1348 case presentation::ClickAction_SOUND
:
1350 #if HAVE_FEATURE_AVMEDIA
1353 mxPlayer
.set( avmedia::MediaWindow::createPlayer( pInfo
->GetBookmark(), ""/*TODO?*/), uno::UNO_QUERY_THROW
);
1356 catch( uno::Exception
& )
1364 case presentation::ClickAction_VERB
:
1367 mpView
->UnmarkAll();
1368 mpView
->MarkObj(pObj
, mpView
->GetSdrPageView());
1369 pDrViewSh
->DoVerb(static_cast<sal_Int16
>(pInfo
->mnVerb
));
1374 case presentation::ClickAction_PROGRAM
:
1376 OUString aBaseURL
= GetDocSh()->GetMedium()->GetBaseURL();
1377 INetURLObject
aURL( ::URIHelper::SmartRel2Abs( INetURLObject(aBaseURL
), pInfo
->GetBookmark(),
1378 URIHelper::GetMaybeFileHdl(), true, false,
1379 INetURLObject::EncodeMechanism::WasEncoded
, INetURLObject::DecodeMechanism::Unambiguous
) );
1381 if( INetProtocol::File
== aURL
.GetProtocol() )
1383 SfxStringItem
aUrl( SID_FILE_NAME
, aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1384 SfxBoolItem
aBrowsing( SID_BROWSE
, true );
1386 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
1388 pViewFrm
->GetDispatcher()->ExecuteList(SID_OPENDOC
,
1389 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
1390 { &aUrl
, &aBrowsing
});
1397 case presentation::ClickAction_MACRO
:
1400 OUString aMacro
= pInfo
->GetBookmark();
1402 if ( SfxApplication::IsXScriptURL( aMacro
) )
1405 uno::Sequence
< sal_Int16
> aOutArgsIndex
;
1406 uno::Sequence
<uno::Any
> aParams
;
1407 uno::Sequence
< uno::Any
> aOutArgs
;
1409 ErrCode eErr
= mpDocSh
->CallXScript( aMacro
,
1410 aParams
, aRet
, aOutArgsIndex
, aOutArgs
);
1412 // Check the return value from the script
1414 bAnimated
= eErr
== ERRCODE_NONE
&&
1415 aRet
.getValueType() == cppu::UnoType
<bool>::get() &&
1416 ( aRet
>>= bTmp
) &&
1421 // aMacro has got following format:
1422 // "Macroname.Modulname.Libname.Documentname" or
1423 // "Macroname.Modulname.Libname.Applicationname"
1424 OUString aMacroName
= aMacro
.getToken(0, '.');
1425 OUString aModulName
= aMacro
.getToken(1, '.');
1427 // In this moment the Call-method only
1428 // resolves modulename+macroname
1429 OUString
aExecMacro(aModulName
+ "." + aMacroName
);
1430 bAnimated
= mpDocSh
->GetBasic()->Call(aExecMacro
);
1444 dynamic_cast< const DrawView
*>( mpView
) != nullptr &&
1445 dynamic_cast< const GraphicDocShell
*>( mpDocSh
) == nullptr &&
1446 SlideShow::IsRunning( mpViewShell
->GetViewShellBase() ) &&
1447 SdDrawDocument::GetAnimationInfo(pObj
))
1449 /**********************************************************
1450 * Effect-Object hit in the middle -> Play effect
1451 **********************************************************/
1452 SdAnimationInfo
* pInfo
= SdDrawDocument::GetAnimationInfo(pObj
);
1454 switch (pInfo
->meClickAction
)
1456 case presentation::ClickAction_VANISH
:
1457 case presentation::ClickAction_INVISIBLE
:
1470 /** is called when the current function should be aborted. <p>
1471 This is used when a function gets a KEY_ESCAPE but can also
1474 @returns true if a active function was aborted
1476 bool FuSelection::cancel()
1478 if (mpView
->Is3DRotationCreationActive())
1480 mpView
->ResetCreationActive();
1481 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1490 SdrObject
* FuSelection::pickObject (const Point
& rTestPoint
)
1492 SdrPageView
* pPageView
;
1493 sal_uInt16 nHitLog
= sal_uInt16 (mpWindow
->PixelToLogic(Size(HITPIX
,0)).Width());
1494 return mpView
->PickObj(rTestPoint
, nHitLog
, pPageView
, SdrSearchOptions::PICKMARKABLE
);
1497 void FuSelection::ForcePointer(const MouseEvent
* pMEvt
)
1499 if(bMovedToCenterPoint
&& !bBeginInsertPoint
&& pMEvt
)
1501 MouseEvent
aMEvt(pMEvt
->GetPosPixel(), pMEvt
->GetClicks(),
1502 pMEvt
->GetMode(), pMEvt
->GetButtons(), pMEvt
->GetModifier() & ~KEY_SHIFT
);
1503 FuDraw::ForcePointer(&aMEvt
);
1507 FuDraw::ForcePointer(pMEvt
);
1511 } // end of namespace sd
1513 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */