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/svdmrkv.hxx>
22 #include <svx/svdetc.hxx>
23 #include <svx/svdoedge.hxx>
24 #include <svx/svdview.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svdotable.hxx>
28 #include "svddrgm1.hxx"
31 #include <svdibrow.hxx>
34 #include <osl/thread.h>
35 #include <svx/svdoole2.hxx>
36 #include <svx/xgrad.hxx>
37 #include <svx/xfillit0.hxx>
38 #include <svx/xflgrit.hxx>
39 #include <svx/xlineit0.hxx>
40 #include "gradtrns.hxx"
41 #include <svx/xflftrit.hxx>
42 #include <svx/dialmgr.hxx>
43 #include <svx/strings.hrc>
44 #include <svx/svdundo.hxx>
45 #include <svx/svdopath.hxx>
46 #include <svx/scene3d.hxx>
47 #include <svx/svdovirt.hxx>
48 #include <sdr/overlay/overlayrollingrectangle.hxx>
49 #include <svx/sdr/overlay/overlaymanager.hxx>
50 #include <svx/sdr/table/tablecontroller.hxx>
51 #include <svx/sdr/contact/viewcontact.hxx>
52 #include <svx/sdrpaintwindow.hxx>
53 #include <svx/sdrpagewindow.hxx>
54 #include <svx/sdrhittesthelper.hxx>
55 #include <svx/svdocapt.hxx>
56 #include <svx/svdograf.hxx>
57 #include <vcl/uitest/logger.hxx>
58 #include <vcl/uitest/eventdescription.hxx>
60 #include <editeng/editdata.hxx>
61 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
62 #include <comphelper/lok.hxx>
63 #include <sfx2/lokhelper.hxx>
64 #include <sfx2/lokcharthelper.hxx>
65 #include <sfx2/viewsh.hxx>
69 #include <com/sun/star/view/XSelectionSupplier.hpp>
71 #include <boost/property_tree/json_parser.hpp>
73 using namespace com::sun::star
;
75 // Migrate Marking of Objects, Points and GluePoints
77 class ImplMarkingOverlay
80 sdr::overlay::OverlayObjectList maObjects
;
82 // The remembered second position in logical coordinates
83 basegfx::B2DPoint maSecondPosition
;
85 // A flag to remember if the action is for unmarking.
86 bool const mbUnmarking
: 1;
89 ImplMarkingOverlay(const SdrPaintView
& rView
, const basegfx::B2DPoint
& rStartPos
, bool bUnmarking
);
91 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
92 // That destructor calls clear() at the list which removes all objects from the
93 // OverlayManager and deletes them.
95 void SetSecondPosition(const basegfx::B2DPoint
& rNewPosition
);
96 bool IsUnmarking() const { return mbUnmarking
; }
99 ImplMarkingOverlay::ImplMarkingOverlay(const SdrPaintView
& rView
, const basegfx::B2DPoint
& rStartPos
, bool bUnmarking
)
100 : maSecondPosition(rStartPos
),
101 mbUnmarking(bUnmarking
)
103 for(sal_uInt32
a(0); a
< rView
.PaintWindowCount(); a
++)
105 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
106 const rtl::Reference
< sdr::overlay::OverlayManager
>& xTargetOverlay
= pCandidate
->GetOverlayManager();
108 if (xTargetOverlay
.is())
110 std::unique_ptr
<sdr::overlay::OverlayRollingRectangleStriped
> pNew(new sdr::overlay::OverlayRollingRectangleStriped(
111 rStartPos
, rStartPos
, false));
112 xTargetOverlay
->add(*pNew
);
113 maObjects
.append(std::move(pNew
));
118 void ImplMarkingOverlay::SetSecondPosition(const basegfx::B2DPoint
& rNewPosition
)
120 if(rNewPosition
!= maSecondPosition
)
122 // apply to OverlayObjects
123 for(sal_uInt32
a(0); a
< maObjects
.count(); a
++)
125 sdr::overlay::OverlayRollingRectangleStriped
& rCandidate
= static_cast< sdr::overlay::OverlayRollingRectangleStriped
&>(maObjects
.getOverlayObject(a
));
126 rCandidate
.setSecondPosition(rNewPosition
);
129 // remember new position
130 maSecondPosition
= rNewPosition
;
138 void SdrMarkView::ImpClearVars()
140 meDragMode
=SdrDragMode::Move
;
141 meEditMode
=SdrViewEditMode::Edit
;
142 meEditMode0
=SdrViewEditMode::Edit
;
146 mbForceFrameHandles
=false;
147 mbPlusHdlAlways
=false;
148 mnFrameHandlesLimit
=50;
149 mbInsPolyPoint
=false;
150 mbMarkedObjRectDirty
=false;
151 mbMarkedPointsRectsDirty
=false;
152 mbMarkHandlesHidden
= false;
155 // Migrate selections
161 SdrMarkView::SdrMarkView(
164 : SdrSnapView(rSdrModel
, pOut
),
165 mpMarkObjOverlay(nullptr),
166 mpMarkPointsOverlay(nullptr),
167 mpMarkGluePointsOverlay(nullptr),
171 StartListening(rSdrModel
);
174 SdrMarkView::~SdrMarkView()
176 // Migrate selections
182 void SdrMarkView::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
184 if (rHint
.GetId() == SfxHintId::ThisIsAnSdrHint
)
186 const SdrHint
* pSdrHint
= static_cast<const SdrHint
*>(&rHint
);
187 SdrHintKind eKind
=pSdrHint
->GetKind();
188 if (eKind
==SdrHintKind::ObjectChange
|| eKind
==SdrHintKind::ObjectInserted
|| eKind
==SdrHintKind::ObjectRemoved
)
190 mbMarkedObjRectDirty
=true;
191 mbMarkedPointsRectsDirty
=true;
194 SdrSnapView::Notify(rBC
,rHint
);
197 void SdrMarkView::ModelHasChanged()
199 SdrPaintView::ModelHasChanged();
200 GetMarkedObjectListWriteAccess().SetNameDirty();
201 mbMarkedObjRectDirty
=true;
202 mbMarkedPointsRectsDirty
=true;
203 // Example: Obj is selected and maMarkedObjectList is sorted.
204 // In another View 2, the ObjOrder is changed (e. g. MovToTop())
205 // Then we need to re-sort MarkList.
206 GetMarkedObjectListWriteAccess().SetUnsorted();
210 SdrView
* pV
=static_cast<SdrView
*>(this);
211 if (pV
!=nullptr && !pV
->IsDragObj() && !pV
->IsInsObjPoint()) {
215 if (comphelper::LibreOfficeKit::isActive() && GetMarkedObjectCount() > 0)
217 //TODO: Is MarkedObjRect valid at this point?
218 tools::Rectangle
aSelection(GetMarkedObjRect());
220 if (aSelection
.IsEmpty())
221 sSelection
= "EMPTY";
224 sal_uInt32 nTotalPaintWindows
= this->PaintWindowCount();
225 if (nTotalPaintWindows
== 1)
227 const vcl::Window
* pWin
= dynamic_cast<const vcl::Window
*>(this->GetFirstOutputDevice());
228 if (pWin
&& pWin
->IsChart())
230 const vcl::Window
* pViewShellWindow
= GetSfxViewShell()->GetEditWindowForActiveOLEObj();
231 if (pViewShellWindow
&& pViewShellWindow
->IsAncestorOf(*pWin
))
233 Point aOffsetPx
= pWin
->GetOffsetPixelFrom(*pViewShellWindow
);
234 Point aLogicOffset
= pWin
->PixelToLogic(aOffsetPx
);
235 aSelection
.Move(aLogicOffset
.getX(), aLogicOffset
.getY());
240 // In case the map mode is in 100th MM, then need to convert the coordinates over to twips for LOK.
243 if (OutputDevice
* pOutputDevice
= mpMarkedPV
->GetView().GetFirstOutputDevice())
245 if (pOutputDevice
->GetMapMode().GetMapUnit() == MapUnit::Map100thMM
)
246 aSelection
= OutputDevice::LogicToLogic(aSelection
, MapMode(MapUnit::Map100thMM
), MapMode(MapUnit::MapTwip
));
250 sSelection
= aSelection
.toString();
253 if(SfxViewShell
* pViewShell
= GetSfxViewShell())
254 SfxLokHelper::notifyInvalidation(pViewShell
, sSelection
);
259 bool SdrMarkView::IsAction() const
261 return SdrSnapView::IsAction() || IsMarkObj() || IsMarkPoints() || IsMarkGluePoints();
264 void SdrMarkView::MovAction(const Point
& rPnt
)
266 SdrSnapView::MovAction(rPnt
);
272 else if(IsMarkPoints())
276 else if(IsMarkGluePoints())
278 MovMarkGluePoints(rPnt
);
282 void SdrMarkView::EndAction()
288 else if(IsMarkPoints())
292 else if(IsMarkGluePoints())
297 SdrSnapView::EndAction();
300 void SdrMarkView::BckAction()
302 SdrSnapView::BckAction();
308 void SdrMarkView::BrkAction()
310 SdrSnapView::BrkAction();
316 void SdrMarkView::TakeActionRect(tools::Rectangle
& rRect
) const
318 if(IsMarkObj() || IsMarkPoints() || IsMarkGluePoints())
320 rRect
= tools::Rectangle(maDragStat
.GetStart(), maDragStat
.GetNow());
324 SdrSnapView::TakeActionRect(rRect
);
329 void SdrMarkView::ClearPageView()
332 SdrSnapView::ClearPageView();
335 void SdrMarkView::HideSdrPage()
339 SdrPageView
* pPageView
= GetSdrPageView();
342 // break all creation actions when hiding page (#75081#)
345 // Discard all selections on this page
346 bMrkChg
= GetMarkedObjectListWriteAccess().DeletePageView(*pPageView
);
349 SdrSnapView::HideSdrPage();
353 MarkListHasChanged();
359 void SdrMarkView::BegMarkObj(const Point
& rPnt
, bool bUnmark
)
363 DBG_ASSERT(nullptr == mpMarkObjOverlay
, "SdrMarkView::BegMarkObj: There exists a mpMarkObjOverlay (!)");
364 basegfx::B2DPoint
aStartPos(rPnt
.X(), rPnt
.Y());
365 mpMarkObjOverlay
= new ImplMarkingOverlay(*this, aStartPos
, bUnmark
);
367 maDragStat
.Reset(rPnt
);
368 maDragStat
.NextPoint();
369 maDragStat
.SetMinMove(mnMinMovLog
);
372 void SdrMarkView::MovMarkObj(const Point
& rPnt
)
374 if(IsMarkObj() && maDragStat
.CheckMinMoved(rPnt
))
376 maDragStat
.NextMove(rPnt
);
377 DBG_ASSERT(mpMarkObjOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
378 basegfx::B2DPoint
aNewPos(rPnt
.X(), rPnt
.Y());
379 mpMarkObjOverlay
->SetSecondPosition(aNewPos
);
383 bool SdrMarkView::EndMarkObj()
389 if(maDragStat
.IsMinMoved())
391 tools::Rectangle
aRect(maDragStat
.GetStart(), maDragStat
.GetNow());
393 MarkObj(aRect
, mpMarkObjOverlay
->IsUnmarking());
404 void SdrMarkView::BrkMarkObj()
408 DBG_ASSERT(mpMarkObjOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
409 delete mpMarkObjOverlay
;
410 mpMarkObjOverlay
= nullptr;
415 bool SdrMarkView::BegMarkPoints(const Point
& rPnt
, bool bUnmark
)
417 if(HasMarkablePoints())
421 DBG_ASSERT(nullptr == mpMarkPointsOverlay
, "SdrMarkView::BegMarkObj: There exists a mpMarkPointsOverlay (!)");
422 basegfx::B2DPoint
aStartPos(rPnt
.X(), rPnt
.Y());
423 mpMarkPointsOverlay
= new ImplMarkingOverlay(*this, aStartPos
, bUnmark
);
425 maDragStat
.Reset(rPnt
);
426 maDragStat
.NextPoint();
427 maDragStat
.SetMinMove(mnMinMovLog
);
435 void SdrMarkView::MovMarkPoints(const Point
& rPnt
)
437 if(IsMarkPoints() && maDragStat
.CheckMinMoved(rPnt
))
439 maDragStat
.NextMove(rPnt
);
441 DBG_ASSERT(mpMarkPointsOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
442 basegfx::B2DPoint
aNewPos(rPnt
.X(), rPnt
.Y());
443 mpMarkPointsOverlay
->SetSecondPosition(aNewPos
);
447 bool SdrMarkView::EndMarkPoints()
453 if(maDragStat
.IsMinMoved())
455 tools::Rectangle
aRect(maDragStat
.GetStart(), maDragStat
.GetNow());
457 MarkPoints(&aRect
, mpMarkPointsOverlay
->IsUnmarking());
469 void SdrMarkView::BrkMarkPoints()
473 DBG_ASSERT(mpMarkPointsOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
474 delete mpMarkPointsOverlay
;
475 mpMarkPointsOverlay
= nullptr;
480 bool SdrMarkView::BegMarkGluePoints(const Point
& rPnt
, bool bUnmark
)
482 if(HasMarkableGluePoints())
486 DBG_ASSERT(nullptr == mpMarkGluePointsOverlay
, "SdrMarkView::BegMarkObj: There exists a mpMarkGluePointsOverlay (!)");
488 basegfx::B2DPoint
aStartPos(rPnt
.X(), rPnt
.Y());
489 mpMarkGluePointsOverlay
= new ImplMarkingOverlay(*this, aStartPos
, bUnmark
);
490 maDragStat
.Reset(rPnt
);
491 maDragStat
.NextPoint();
492 maDragStat
.SetMinMove(mnMinMovLog
);
500 void SdrMarkView::MovMarkGluePoints(const Point
& rPnt
)
502 if(IsMarkGluePoints() && maDragStat
.CheckMinMoved(rPnt
))
504 maDragStat
.NextMove(rPnt
);
506 DBG_ASSERT(mpMarkGluePointsOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
507 basegfx::B2DPoint
aNewPos(rPnt
.X(), rPnt
.Y());
508 mpMarkGluePointsOverlay
->SetSecondPosition(aNewPos
);
512 void SdrMarkView::EndMarkGluePoints()
514 if(IsMarkGluePoints())
516 if(maDragStat
.IsMinMoved())
518 tools::Rectangle
aRect(maDragStat
.GetStart(),maDragStat
.GetNow());
520 MarkGluePoints(&aRect
, mpMarkGluePointsOverlay
->IsUnmarking());
528 void SdrMarkView::BrkMarkGluePoints()
530 if(IsMarkGluePoints())
532 DBG_ASSERT(mpMarkGluePointsOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
533 delete mpMarkGluePointsOverlay
;
534 mpMarkGluePointsOverlay
= nullptr;
538 bool SdrMarkView::MarkableObjectsExceed( int n
) const
540 SdrPageView
* pPV
= GetSdrPageView();
544 SdrObjList
* pOL
=pPV
->GetObjList();
545 const size_t nObjCount
= pOL
->GetObjCount();
546 for (size_t nObjNum
=0; nObjNum
<nObjCount
; ++nObjNum
) {
547 SdrObject
* pObj
=pOL
->GetObj(nObjNum
);
548 if (IsObjMarkable(pObj
,pPV
) && --n
<0)
555 void SdrMarkView::hideMarkHandles()
557 if(!mbMarkHandlesHidden
)
559 mbMarkHandlesHidden
= true;
564 void SdrMarkView::showMarkHandles()
566 if(mbMarkHandlesHidden
)
568 mbMarkHandlesHidden
= false;
573 bool SdrMarkView::ImpIsFrameHandles() const
575 const size_t nMarkCount
=GetMarkedObjectCount();
576 bool bFrmHdl
=nMarkCount
>static_cast<size_t>(mnFrameHandlesLimit
) || mbForceFrameHandles
;
577 bool bStdDrag
=meDragMode
==SdrDragMode::Move
;
578 if (nMarkCount
==1 && bStdDrag
&& bFrmHdl
)
580 const SdrObject
* pObj
=GetMarkedObjectByIndex(0);
581 if (pObj
->GetObjInventor()==SdrInventor::Default
)
583 sal_uInt16 nIdent
=pObj
->GetObjIdentifier();
584 if (nIdent
==OBJ_LINE
|| nIdent
==OBJ_EDGE
|| nIdent
==OBJ_CAPTION
|| nIdent
==OBJ_MEASURE
|| nIdent
==OBJ_CUSTOMSHAPE
|| nIdent
==OBJ_TABLE
)
590 if (!bStdDrag
&& !bFrmHdl
) {
591 // all other drag modes only with FrameHandles
593 if (meDragMode
==SdrDragMode::Rotate
) {
594 // when rotating, use ObjOwn drag, if there's at least 1 PolyObj
595 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& bFrmHdl
; ++nMarkNum
) {
596 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
597 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
598 bFrmHdl
=!pObj
->IsPolyObj();
603 // FrameHandles, if at least 1 Obj can't do SpecialDrag
604 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& !bFrmHdl
; ++nMarkNum
) {
605 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
606 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
607 bFrmHdl
=!pObj
->hasSpecialDrag();
611 // no FrameHdl for crop
612 if(bFrmHdl
&& SdrDragMode::Crop
== meDragMode
)
622 OUString
lcl_getDragMethodServiceName( const OUString
& rCID
)
626 sal_Int32 nIndexStart
= rCID
.indexOf( "DragMethod=" );
627 if( nIndexStart
!= -1 )
629 nIndexStart
= rCID
.indexOf( '=', nIndexStart
);
630 if( nIndexStart
!= -1 )
633 sal_Int32 nNextSlash
= rCID
.indexOf( '/', nIndexStart
);
634 if( nNextSlash
!= -1 )
636 sal_Int32 nIndexEnd
= nNextSlash
;
637 sal_Int32 nNextColon
= rCID
.indexOf( ':', nIndexStart
);
638 if( nNextColon
< nNextSlash
)
639 nIndexEnd
= nNextColon
;
640 aRet
= rCID
.copy(nIndexStart
,nIndexEnd
-nIndexStart
);
647 OUString
lcl_getDragParameterString( const OUString
& rCID
)
651 sal_Int32 nIndexStart
= rCID
.indexOf( "DragParameter=" );
652 if( nIndexStart
!= -1 )
654 nIndexStart
= rCID
.indexOf( '=', nIndexStart
);
655 if( nIndexStart
!= -1 )
658 sal_Int32 nNextSlash
= rCID
.indexOf( '/', nIndexStart
);
659 if( nNextSlash
!= -1 )
661 sal_Int32 nIndexEnd
= nNextSlash
;
662 sal_Int32 nNextColon
= rCID
.indexOf( ':', nIndexStart
);
663 if( nNextColon
< nNextSlash
)
664 nIndexEnd
= nNextColon
;
665 aRet
= rCID
.copy(nIndexStart
,nIndexEnd
-nIndexStart
);
671 } // anonymous namespace
673 void SdrMarkView::SetMarkHandles(SfxViewShell
* pOtherShell
)
675 // remember old focus handle values to search for it again
676 const SdrHdl
* pSaveOldFocusHdl
= maHdlList
.GetFocusHdl();
677 bool bSaveOldFocus(false);
678 sal_uInt32
nSavePolyNum(0), nSavePointNum(0);
679 SdrHdlKind
eSaveKind(SdrHdlKind::Move
);
680 SdrObject
* pSaveObj
= nullptr;
683 && pSaveOldFocusHdl
->GetObj()
684 && dynamic_cast<const SdrPathObj
*>(pSaveOldFocusHdl
->GetObj()) != nullptr
685 && (pSaveOldFocusHdl
->GetKind() == SdrHdlKind::Poly
|| pSaveOldFocusHdl
->GetKind() == SdrHdlKind::BezierWeight
))
687 bSaveOldFocus
= true;
688 nSavePolyNum
= pSaveOldFocusHdl
->GetPolyNum();
689 nSavePointNum
= pSaveOldFocusHdl
->GetPointNum();
690 pSaveObj
= pSaveOldFocusHdl
->GetObj();
691 eSaveKind
= pSaveOldFocusHdl
->GetKind();
694 // delete/clear all handles. This will always be done, even with areMarkHandlesHidden()
696 maHdlList
.SetRotateShear(meDragMode
==SdrDragMode::Rotate
);
697 maHdlList
.SetDistortShear(meDragMode
==SdrDragMode::Shear
);
701 // are handles enabled at all? Create only then
702 if(areMarkHandlesHidden())
705 // There can be multiple mark views, but we're only interested in the one that has a window associated.
706 const bool bTiledRendering
= comphelper::LibreOfficeKit::isActive() && GetFirstOutputDevice() && GetFirstOutputDevice()->GetOutDevType() == OUTDEV_WINDOW
;
708 const size_t nMarkCount
=GetMarkedObjectCount();
709 bool bStdDrag
=meDragMode
==SdrDragMode::Move
;
710 bool bSingleTextObjMark
=false;
711 bool bLimitedRotation(false);
715 mpMarkedObj
=GetMarkedObjectByIndex(0);
717 if(nullptr != mpMarkedObj
)
720 dynamic_cast<const SdrTextObj
*>( mpMarkedObj
) != nullptr &&
721 static_cast<SdrTextObj
*>(mpMarkedObj
)->IsTextFrame();
723 // RotGrfFlyFrame: we may have limited rotation
724 bLimitedRotation
= SdrDragMode::Rotate
== meDragMode
&& mpMarkedObj
->HasLimitedRotation();
728 bool bFrmHdl
=ImpIsFrameHandles();
732 mpMarkedPV
=GetSdrPageViewOfMarkedByIndex(0);
734 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& (mpMarkedPV
!=nullptr || !bFrmHdl
); ++nMarkNum
)
736 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
738 if (mpMarkedPV
!=pM
->GetPageView())
745 SfxViewShell
* pViewShell
= GetSfxViewShell();
747 // check if text edit or ole is active and handles need to be suppressed. This may be the case
748 // when a single object is selected
749 // Using a strict return statement is okay here; no handles means *no* handles.
752 // formerly #i33755#: If TextEdit is active the EditEngine will directly paint
753 // to the window, so suppress Overlay and handles completely; a text frame for
754 // the active text edit will be painted by the repaint mechanism in
755 // SdrObjEditView::ImpPaintOutlinerView in this case. This needs to be reworked
757 // Also formerly #122142#: Pretty much the same for SdrCaptionObj's in calc.
758 if(static_cast<SdrView
*>(this)->IsTextEdit())
760 const SdrTextObj
* pSdrTextObj
= dynamic_cast< const SdrTextObj
* >(mpMarkedObj
);
762 if (pSdrTextObj
&& pSdrTextObj
->IsInEditMode())
764 if (!bTiledRendering
)
769 // formerly #i118524#: if inplace activated OLE is selected, suppress handles
770 const SdrOle2Obj
* pSdrOle2Obj
= dynamic_cast< const SdrOle2Obj
* >(mpMarkedObj
);
772 if(pSdrOle2Obj
&& (pSdrOle2Obj
->isInplaceActive() || pSdrOle2Obj
->isUiActive()))
776 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION
, "INPLACE");
777 SfxLokHelper::notifyOtherViews(pViewShell
, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION
, "selection", "INPLACE");
783 tools::Rectangle
aRect(GetMarkedObjRect());
785 if (bTiledRendering
&& pViewShell
)
787 tools::Rectangle
aSelection(aRect
);
788 bool bIsChart
= false;
790 if (!aRect
.IsEmpty())
792 sal_uInt32 nTotalPaintWindows
= this->PaintWindowCount();
793 if (nTotalPaintWindows
== 1)
795 const vcl::Window
* pWin
= dynamic_cast<const vcl::Window
*>(this->GetFirstOutputDevice());
796 if (pWin
&& pWin
->IsChart())
799 const vcl::Window
* pViewShellWindow
= GetSfxViewShell()->GetEditWindowForActiveOLEObj();
800 if (pViewShellWindow
&& pViewShellWindow
->IsAncestorOf(*pWin
))
802 Point aOffsetPx
= pWin
->GetOffsetPixelFrom(*pViewShellWindow
);
803 Point aLogicOffset
= pWin
->PixelToLogic(aOffsetPx
);
804 aSelection
.Move(aLogicOffset
.getX(), aLogicOffset
.getY());
810 if (!aSelection
.IsEmpty())
812 // In case the map mode is in 100th MM, then need to convert the coordinates over to twips for LOK.
815 if (OutputDevice
* pOutputDevice
= mpMarkedPV
->GetView().GetFirstOutputDevice())
817 if (pOutputDevice
->GetMapMode().GetMapUnit() == MapUnit::Map100thMM
)
818 aSelection
= OutputDevice::LogicToLogic(aSelection
, MapMode(MapUnit::Map100thMM
), MapMode(MapUnit::MapTwip
));
822 // hide the text selection too
823 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION
, "");
827 OString sSelectionText
;
828 boost::property_tree::ptree aTableJsonTree
;
829 bool bTableSelection
= false;
831 if (mpMarkedObj
&& mpMarkedObj
->GetObjIdentifier() == OBJ_TABLE
)
833 auto& rTableObject
= dynamic_cast<sdr::table::SdrTableObj
&>(*mpMarkedObj
);
834 bTableSelection
= rTableObject
.createTableEdgesJson(aTableJsonTree
);
836 if (GetMarkedObjectCount())
838 SdrMark
* pM
= GetSdrMarkByIndex(0);
839 SdrObject
* pO
= pM
->GetMarkedSdrObj();
840 long nRotAngle
= pO
->GetRotateAngle();
841 // true if we are dealing with a RotGrfFlyFrame
842 // (SwVirtFlyDrawObj with a SwGrfNode)
843 bool bWriterGraphic
= pO
->HasLimitedRotation();
850 OStringBuffer aExtraInfo
;
853 aExtraInfo
.append("{ \"isWriterGraphic\": true }");
857 LokChartHelper
aChartHelper(pViewShell
);
858 css::uno::Reference
<css::frame::XController
>& xChartController
= aChartHelper
.GetXController();
859 css::uno::Reference
<css::view::XSelectionSupplier
> xSelectionSupplier( xChartController
, uno::UNO_QUERY
);
860 if (xSelectionSupplier
.is())
862 uno::Any aSel
= xSelectionSupplier
->getSelection();
866 OString
aObjectCID(aValue
.getStr(), aValue
.getLength(), osl_getThreadTextEncoding());
867 aExtraInfo
.append("{ ");
868 const std::vector
<OString
> aProps
{"Draggable", "Resizable", "Rotatable"};
869 for (const auto& rProp
: aProps
)
871 sal_Int32 nPos
= aObjectCID
.indexOf(rProp
);
872 if (nPos
== -1) continue;
873 nPos
+= rProp
.getLength() + 1; // '='
874 if (aExtraInfo
.getLength() > 2) // != "{ "
875 aExtraInfo
.append(", ");
876 aExtraInfo
.append("\"is");
877 aExtraInfo
.append(rProp
);
878 aExtraInfo
.append("\": ");
879 aExtraInfo
.append(OString::boolean(aObjectCID
[nPos
] == '1'));
882 OUString sDragMethod
= lcl_getDragMethodServiceName(aValue
);
883 if (sDragMethod
== "PieSegmentDragging")
885 // old initial offset inside the CID returned by xSelectionSupplier->getSelection()
886 // after a pie segment dragging; using SdrObject::GetName for getting a CID with the updated offset
887 aValue
= pO
->GetName();
888 OUString sDragParameters
= lcl_getDragParameterString(aValue
);
889 if (!sDragParameters
.isEmpty())
891 aExtraInfo
.append(", \"dragInfo\": { ");
892 aExtraInfo
.append("\"dragMethod\": \"");
893 aExtraInfo
.append(sDragMethod
.toUtf8());
894 aExtraInfo
.append("\"");
897 sal_Int32 nStartIndex
= 0;
898 std::array
<int, 5> aDragParameters
;
899 for (auto& rParam
: aDragParameters
)
901 sParam
= sDragParameters
.getToken(0, ',', nStartIndex
);
902 if (sParam
.isEmpty())
904 rParam
= sParam
.toInt32();
907 // initial offset in %
908 if (aDragParameters
[0] < 0)
909 aDragParameters
[0] = 0;
910 else if (aDragParameters
[0] > 100)
911 aDragParameters
[0] = 100;
913 aExtraInfo
.append(", \"initialOffset\": ");
914 aExtraInfo
.append(OString::number(aDragParameters
[0]));
916 // drag direction constraint
917 Point
aMinPos(aDragParameters
[1], aDragParameters
[2]);
918 Point
aMaxPos(aDragParameters
[3], aDragParameters
[4]);
919 Point aDragDirection
= aMaxPos
- aMinPos
;
920 aDragDirection
= OutputDevice::LogicToLogic(aDragDirection
, MapMode(MapUnit::Map100thMM
), MapMode(MapUnit::MapTwip
));
922 aExtraInfo
.append(", \"dragDirection\": [");
923 aExtraInfo
.append(aDragDirection
.toString());
924 aExtraInfo
.append("]");
926 // polygon approximating the pie segment or donut segment
927 if (pO
->GetObjIdentifier() == OBJ_PATHFILL
)
929 const basegfx::B2DPolyPolygon
aPolyPolygon(pO
->TakeXorPoly());
930 if (aPolyPolygon
.count() == 1)
932 const basegfx::B2DPolygon aPolygon
= aPolyPolygon
.getB2DPolygon(0);
933 if (sal_uInt32 nPolySize
= aPolygon
.count())
935 const vcl::Window
* pWin
= dynamic_cast<const vcl::Window
*>(this->GetFirstOutputDevice());
936 const vcl::Window
* pViewShellWindow
= pViewShell
->GetEditWindowForActiveOLEObj();
937 if (pWin
&& pViewShellWindow
&& pViewShellWindow
->IsAncestorOf(*pWin
))
939 // in the following code escaping sequences used inside raw literal strings
940 // are for making them understandable by the JSON parser
942 Point aOffsetPx
= pWin
->GetOffsetPixelFrom(*pViewShellWindow
);
943 Point aLogicOffset
= pWin
->PixelToLogic(aOffsetPx
);
944 OString
sPolygonElem("<polygon points=\\\"");
945 for (sal_uInt32 nIndex
= 0; nIndex
< nPolySize
; ++nIndex
)
947 const basegfx::B2DPoint aB2Point
= aPolygon
.getB2DPoint(nIndex
);
948 Point
aPoint(aB2Point
.getX(), aB2Point
.getY());
949 aPoint
.Move(aLogicOffset
.getX(), aLogicOffset
.getY());
952 sPolygonElem
+= aPoint
.toString();
954 sPolygonElem
+= R
"elem(\" style
=\"stroke
: none
; fill
: rgb(114,159,207); fill
-opacity
: 0.8\"/>)elem
";
956 aSelection = OutputDevice::LogicToLogic(aSelection, MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM));
958 OString sSVGElem = R"elem(<svg version
=\"1.2\" width
=\")elem
" +
959 OString::number(aSelection.GetWidth() / 100.0) +
960 R"elem(mm
\" height
=\")elem
" +
961 OString::number(aSelection.GetHeight() / 100.0) +
962 R"elem(mm
\" viewBox
=\")elem
" +
963 aSelection.toString() +
964 R"elem(\" preserveAspectRatio
=\"xMidYMid
\" xmlns
=\"http
://www.w3.org/2000/svg\">)elem";
966 aExtraInfo
.append(", \"svg\": \"");
967 aExtraInfo
.append(sSVGElem
);
968 aExtraInfo
.append("\\n ");
969 aExtraInfo
.append(sPolygonElem
);
970 aExtraInfo
.append("\\n</svg>");
971 aExtraInfo
.append("\""); // svg
976 aExtraInfo
.append("}"); // dragInfo
979 aExtraInfo
.append(" }");
983 sSelectionText
= aSelection
.toString() +
984 ", " + OString::number(nRotAngle
);
985 if (!aExtraInfo
.isEmpty())
987 sSelectionText
+= ", " + aExtraInfo
.makeStringAndClear();
991 if (sSelectionText
.isEmpty())
992 sSelectionText
= "EMPTY";
996 boost::property_tree::ptree aTableRectangle
;
997 aTableRectangle
.put("x", aSelection
.Left());
998 aTableRectangle
.put("y", aSelection
.Top());
999 aTableRectangle
.put("width", aSelection
.GetWidth());
1000 aTableRectangle
.put("height", aSelection
.GetHeight());
1001 aTableJsonTree
.push_back(std::make_pair("rectangle", aTableRectangle
));
1003 std::stringstream aStream
;
1004 boost::property_tree::write_json(aStream
, aTableJsonTree
);
1005 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED
, aStream
.str().c_str());
1009 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED
, "{}");
1014 // Another shell wants to know about our existing
1016 if (pViewShell
!= pOtherShell
)
1017 SfxLokHelper::notifyOtherView(pViewShell
, pOtherShell
, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION
, "selection", sSelectionText
);
1021 // We have a new selection, so both pViewShell and the
1022 // other views want to know about it.
1023 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION
, sSelectionText
.getStr());
1024 SfxLokHelper::notifyOtherViews(pViewShell
, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION
, "selection", sSelectionText
);
1031 if(!aRect
.IsEmpty())
1033 // otherwise nothing is found
1034 const size_t nSiz0(maHdlList
.GetHdlCount());
1036 if( bSingleTextObjMark
)
1038 mpMarkedObj
->AddToHdlList(maHdlList
);
1042 const bool bWdt0(aRect
.Left() == aRect
.Right());
1043 const bool bHgt0(aRect
.Top() == aRect
.Bottom());
1047 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopLeft(), SdrHdlKind::UpperLeft
));
1049 else if (!bStdDrag
&& (bWdt0
|| bHgt0
))
1051 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopLeft(), SdrHdlKind::UpperLeft
));
1052 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.BottomRight(), SdrHdlKind::LowerRight
));
1056 if (!bWdt0
&& !bHgt0
)
1058 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopLeft(), SdrHdlKind::UpperLeft
));
1061 if (!bLimitedRotation
&& !bHgt0
)
1063 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopCenter(), SdrHdlKind::Upper
));
1066 if (!bWdt0
&& !bHgt0
)
1068 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopRight(), SdrHdlKind::UpperRight
));
1071 if (!bLimitedRotation
&& !bWdt0
)
1073 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.LeftCenter(), SdrHdlKind::Left
));
1076 if (!bLimitedRotation
&& !bWdt0
)
1078 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.RightCenter(), SdrHdlKind::Right
));
1081 if (!bWdt0
&& !bHgt0
)
1083 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.BottomLeft(), SdrHdlKind::LowerLeft
));
1086 if (!bLimitedRotation
&& !bHgt0
)
1088 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.BottomCenter(), SdrHdlKind::Lower
));
1091 if (!bWdt0
&& !bHgt0
)
1093 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.BottomRight(), SdrHdlKind::LowerRight
));
1098 const size_t nSiz1(maHdlList
.GetHdlCount());
1100 // moved setting the missing parameters at SdrHdl here from the
1101 // single loop above (bSingleTextObjMark), this was missing all
1102 // the time. Setting SdrObject is now required to correctly get
1103 // the View-Dependent evtl. GridOffset adapted
1104 for (size_t i
=nSiz0
; i
<nSiz1
; ++i
)
1106 SdrHdl
* pHdl
=maHdlList
.GetHdl(i
);
1107 pHdl
->SetObj(mpMarkedObj
);
1108 pHdl
->SetPageView(mpMarkedPV
);
1109 pHdl
->SetObjHdlNum(sal_uInt16(i
-nSiz0
));
1117 // moved crop handling to non-frame part and the handle creation to SdrGrafObj
1118 if(1 == nMarkCount
&& mpMarkedObj
&& SdrDragMode::Crop
== meDragMode
)
1120 // Default addCropHandles from SdrObject does nothing. When pMarkedObj is SdrGrafObj, previous
1121 // behaviour occurs (code in svx/source/svdraw/svdograf.cxx). When pMarkedObj is SwVirtFlyDrawObj
1122 // writer takes the responsibility of adding handles (code in sw/source/core/draw/dflyobj.cxx)
1123 const size_t nSiz0(maHdlList
.GetHdlCount());
1124 mpMarkedObj
->addCropHandles(maHdlList
);
1125 const size_t nSiz1(maHdlList
.GetHdlCount());
1127 // Was missing: Set infos at SdrCropHdl
1128 for (size_t i
=nSiz0
; i
<nSiz1
; ++i
)
1130 SdrHdl
* pHdl
=maHdlList
.GetHdl(i
);
1131 pHdl
->SetObj(mpMarkedObj
);
1132 pHdl
->SetPageView(mpMarkedPV
);
1133 pHdl
->SetObjHdlNum(sal_uInt16(i
-nSiz0
));
1141 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
)
1143 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
1144 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
1145 SdrPageView
* pPV
=pM
->GetPageView();
1146 const size_t nSiz0
=maHdlList
.GetHdlCount();
1147 pObj
->AddToHdlList(maHdlList
);
1148 const size_t nSiz1
=maHdlList
.GetHdlCount();
1149 bool bPoly
=pObj
->IsPolyObj();
1150 const SdrUShortCont
& rMrkPnts
= pM
->GetMarkedPoints();
1151 for (size_t i
=nSiz0
; i
<nSiz1
; ++i
)
1153 SdrHdl
* pHdl
=maHdlList
.GetHdl(i
);
1155 pHdl
->SetPageView(pPV
);
1156 pHdl
->SetObjHdlNum(sal_uInt16(i
-nSiz0
));
1160 bool bSelected
= rMrkPnts
.find( sal_uInt16(i
-nSiz0
) ) != rMrkPnts
.end();
1161 pHdl
->SetSelected(bSelected
);
1162 if (mbPlusHdlAlways
|| bSelected
)
1164 SdrHdlList
plusList(nullptr);
1165 pObj
->AddToPlusHdlList(plusList
, *pHdl
);
1166 sal_uInt32 nPlusHdlCnt
=plusList
.GetHdlCount();
1167 for (sal_uInt32 nPlusNum
=0; nPlusNum
<nPlusHdlCnt
; nPlusNum
++)
1169 SdrHdl
* pPlusHdl
=plusList
.GetHdl(nPlusNum
);
1170 pPlusHdl
->SetObj(pObj
);
1171 pPlusHdl
->SetPageView(pPV
);
1172 pPlusHdl
->SetPlusHdl(true);
1174 plusList
.MoveTo(maHdlList
);
1182 // GluePoint handles
1183 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
)
1185 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
1186 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
1187 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
1191 SdrPageView
* pPV
=pM
->GetPageView();
1192 const SdrUShortCont
& rMrkGlue
=pM
->GetMarkedGluePoints();
1193 for (sal_uInt16 nId
: rMrkGlue
)
1195 //nNum changed to nNumGP because already used in for loop
1196 sal_uInt16 nNumGP
=pGPL
->FindGluePoint(nId
);
1197 if (nNumGP
!=SDRGLUEPOINT_NOTFOUND
)
1199 const SdrGluePoint
& rGP
=(*pGPL
)[nNumGP
];
1200 Point
aPos(rGP
.GetAbsolutePos(*pObj
));
1201 std::unique_ptr
<SdrHdl
> pGlueHdl(new SdrHdl(aPos
,SdrHdlKind::Glue
));
1202 pGlueHdl
->SetObj(pObj
);
1203 pGlueHdl
->SetPageView(pPV
);
1204 pGlueHdl
->SetObjHdlNum(nId
);
1205 maHdlList
.AddHdl(std::move(pGlueHdl
));
1210 // rotation point/axis of reflection
1211 if(!bLimitedRotation
)
1213 AddDragModeHdl(meDragMode
);
1219 // add custom handles (used by other apps, e.g. AnchorPos)
1222 // try to restore focus handle index from remembered values
1225 for(size_t a
= 0; a
< maHdlList
.GetHdlCount(); ++a
)
1227 SdrHdl
* pCandidate
= maHdlList
.GetHdl(a
);
1229 if(pCandidate
->GetObj()
1230 && pCandidate
->GetObj() == pSaveObj
1231 && pCandidate
->GetKind() == eSaveKind
1232 && pCandidate
->GetPolyNum() == nSavePolyNum
1233 && pCandidate
->GetPointNum() == nSavePointNum
)
1235 maHdlList
.SetFocusHdl(pCandidate
);
1242 void SdrMarkView::AddCustomHdl()
1244 // add custom handles (used by other apps, e.g. AnchorPos)
1247 void SdrMarkView::SetDragMode(SdrDragMode eMode
)
1249 SdrDragMode eMode0
=meDragMode
;
1251 if (meDragMode
==SdrDragMode::Resize
) meDragMode
=SdrDragMode::Move
;
1252 if (meDragMode
!=eMode0
) {
1254 SetMarkHandles(nullptr);
1256 if (AreObjectsMarked()) MarkListHasChanged();
1261 void SdrMarkView::AddDragModeHdl(SdrDragMode eMode
)
1265 case SdrDragMode::Rotate
:
1267 // add rotation center
1268 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(maRef1
, SdrHdlKind::Ref1
));
1271 case SdrDragMode::Mirror
:
1273 // add axis of reflection
1274 std::unique_ptr
<SdrHdl
> pHdl3(new SdrHdl(maRef2
, SdrHdlKind::Ref2
));
1275 std::unique_ptr
<SdrHdl
> pHdl2(new SdrHdl(maRef1
, SdrHdlKind::Ref1
));
1276 std::unique_ptr
<SdrHdl
> pHdl1(new SdrHdlLine(*pHdl2
, *pHdl3
, SdrHdlKind::MirrorAxis
));
1278 pHdl1
->SetObjHdlNum(1); // for sorting
1279 pHdl2
->SetObjHdlNum(2); // for sorting
1280 pHdl3
->SetObjHdlNum(3); // for sorting
1282 maHdlList
.AddHdl(std::move(pHdl1
)); // line comes first, so it is the last in HitTest
1283 maHdlList
.AddHdl(std::move(pHdl2
));
1284 maHdlList
.AddHdl(std::move(pHdl3
));
1288 case SdrDragMode::Transparence
:
1290 // add interactive transparency handle
1291 const size_t nMarkCount
= GetMarkedObjectCount();
1294 SdrObject
* pObj
= GetMarkedObjectByIndex(0);
1295 SdrModel
* pModel
= GetModel();
1296 const SfxItemSet
& rSet
= pObj
->GetMergedItemSet();
1298 if(SfxItemState::SET
!= rSet
.GetItemState(XATTR_FILLFLOATTRANSPARENCE
, false))
1300 // add this item, it's not yet there
1301 XFillFloatTransparenceItem
aNewItem(rSet
.Get(XATTR_FILLFLOATTRANSPARENCE
));
1302 XGradient aGrad
= aNewItem
.GetGradientValue();
1304 aNewItem
.SetEnabled(true);
1305 aGrad
.SetStartIntens(100);
1306 aGrad
.SetEndIntens(100);
1307 aNewItem
.SetGradientValue(aGrad
);
1309 // add undo to allow user to take back this step
1310 if( pModel
->IsUndoEnabled() )
1312 pModel
->BegUndo(SvxResId(SIP_XA_FILLTRANSPARENCE
));
1313 pModel
->AddUndo(pModel
->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
1317 SfxItemSet
aNewSet(pModel
->GetItemPool());
1318 aNewSet
.Put(aNewItem
);
1319 pObj
->SetMergedItemSetAndBroadcast(aNewSet
);
1322 // set values and transform to vector set
1323 GradTransVector aGradTransVector
;
1324 GradTransGradient aGradTransGradient
;
1326 aGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLFLOATTRANSPARENCE
).GetGradientValue();
1327 GradTransformer::GradToVec(aGradTransGradient
, aGradTransVector
, pObj
);
1330 const Point
aTmpPos1(basegfx::fround(aGradTransVector
.maPositionA
.getX()), basegfx::fround(aGradTransVector
.maPositionA
.getY()));
1331 const Point
aTmpPos2(basegfx::fround(aGradTransVector
.maPositionB
.getX()), basegfx::fround(aGradTransVector
.maPositionB
.getY()));
1332 std::unique_ptr
<SdrHdlColor
> pColHdl1(new SdrHdlColor(aTmpPos1
, aGradTransVector
.aCol1
, SDR_HANDLE_COLOR_SIZE_NORMAL
, true));
1333 std::unique_ptr
<SdrHdlColor
> pColHdl2(new SdrHdlColor(aTmpPos2
, aGradTransVector
.aCol2
, SDR_HANDLE_COLOR_SIZE_NORMAL
, true));
1334 std::unique_ptr
<SdrHdlGradient
> pGradHdl(new SdrHdlGradient(aTmpPos1
, aTmpPos2
, false));
1335 DBG_ASSERT(pColHdl1
&& pColHdl2
&& pGradHdl
, "Could not get all necessary handles!");
1338 pGradHdl
->SetColorHandles(pColHdl1
.get(), pColHdl2
.get());
1339 pGradHdl
->SetObj(pObj
);
1340 pColHdl1
->SetColorChangeHdl(LINK(pGradHdl
.get(), SdrHdlGradient
, ColorChangeHdl
));
1341 pColHdl2
->SetColorChangeHdl(LINK(pGradHdl
.get(), SdrHdlGradient
, ColorChangeHdl
));
1344 maHdlList
.AddHdl(std::move(pColHdl1
));
1345 maHdlList
.AddHdl(std::move(pColHdl2
));
1346 maHdlList
.AddHdl(std::move(pGradHdl
));
1350 case SdrDragMode::Gradient
:
1352 // add interactive gradient handle
1353 const size_t nMarkCount
= GetMarkedObjectCount();
1356 SdrObject
* pObj
= GetMarkedObjectByIndex(0);
1357 const SfxItemSet
& rSet
= pObj
->GetMergedItemSet();
1358 drawing::FillStyle eFillStyle
= rSet
.Get(XATTR_FILLSTYLE
).GetValue();
1360 if(eFillStyle
== drawing::FillStyle_GRADIENT
)
1362 // set values and transform to vector set
1363 GradTransVector aGradTransVector
;
1364 GradTransGradient aGradTransGradient
;
1365 Size
aHdlSize(15, 15);
1367 aGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLGRADIENT
).GetGradientValue();
1368 GradTransformer::GradToVec(aGradTransGradient
, aGradTransVector
, pObj
);
1371 const Point
aTmpPos1(basegfx::fround(aGradTransVector
.maPositionA
.getX()), basegfx::fround(aGradTransVector
.maPositionA
.getY()));
1372 const Point
aTmpPos2(basegfx::fround(aGradTransVector
.maPositionB
.getX()), basegfx::fround(aGradTransVector
.maPositionB
.getY()));
1373 std::unique_ptr
<SdrHdlColor
> pColHdl1(new SdrHdlColor(aTmpPos1
, aGradTransVector
.aCol1
, aHdlSize
, false));
1374 std::unique_ptr
<SdrHdlColor
> pColHdl2(new SdrHdlColor(aTmpPos2
, aGradTransVector
.aCol2
, aHdlSize
, false));
1375 std::unique_ptr
<SdrHdlGradient
> pGradHdl(new SdrHdlGradient(aTmpPos1
, aTmpPos2
, true));
1376 DBG_ASSERT(pColHdl1
&& pColHdl2
&& pGradHdl
, "Could not get all necessary handles!");
1379 pGradHdl
->SetColorHandles(pColHdl1
.get(), pColHdl2
.get());
1380 pGradHdl
->SetObj(pObj
);
1381 pColHdl1
->SetColorChangeHdl(LINK(pGradHdl
.get(), SdrHdlGradient
, ColorChangeHdl
));
1382 pColHdl2
->SetColorChangeHdl(LINK(pGradHdl
.get(), SdrHdlGradient
, ColorChangeHdl
));
1385 maHdlList
.AddHdl(std::move(pColHdl1
));
1386 maHdlList
.AddHdl(std::move(pColHdl2
));
1387 maHdlList
.AddHdl(std::move(pGradHdl
));
1392 case SdrDragMode::Crop
:
1401 /** handle mouse over effects for handles */
1402 bool SdrMarkView::MouseMove(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
1404 if(maHdlList
.GetHdlCount())
1406 SdrHdl
* pMouseOverHdl
= nullptr;
1407 if( !rMEvt
.IsLeaveWindow() && pWin
)
1409 Point
aMDPos( pWin
->PixelToLogic( rMEvt
.GetPosPixel() ) );
1410 pMouseOverHdl
= PickHandle(aMDPos
);
1413 // notify last mouse over handle that he lost the mouse
1414 const size_t nHdlCount
= maHdlList
.GetHdlCount();
1416 for(size_t nHdl
= 0; nHdl
< nHdlCount
; ++nHdl
)
1418 SdrHdl
* pCurrentHdl
= GetHdl(nHdl
);
1419 if( pCurrentHdl
->mbMouseOver
)
1421 if( pCurrentHdl
!= pMouseOverHdl
)
1423 pCurrentHdl
->mbMouseOver
= false;
1424 pCurrentHdl
->onMouseLeave();
1430 // notify current mouse over handle
1433 pMouseOverHdl
->mbMouseOver
= true;
1434 pMouseOverHdl
->onMouseEnter(rMEvt
);
1437 return SdrSnapView::MouseMove(rMEvt
, pWin
);
1440 bool SdrMarkView::RequestHelp(const HelpEvent
& rHEvt
)
1442 if (maHdlList
.GetHdlCount())
1444 const size_t nHdlCount
= maHdlList
.GetHdlCount();
1446 for (size_t nHdl
= 0; nHdl
< nHdlCount
; ++nHdl
)
1448 SdrHdl
* pCurrentHdl
= GetHdl(nHdl
);
1449 if (pCurrentHdl
->mbMouseOver
)
1451 pCurrentHdl
->onHelpRequest();
1456 return SdrSnapView::RequestHelp(rHEvt
);
1459 void SdrMarkView::ForceRefToMarked()
1463 case SdrDragMode::Rotate
:
1465 tools::Rectangle
aR(GetMarkedObjRect());
1466 maRef1
= aR
.Center();
1471 case SdrDragMode::Mirror
:
1473 // first calculate the length of the axis of reflection
1479 OutputDevice
* pOut
=GetFirstOutputDevice();
1480 if (pOut
!=nullptr) {
1481 // minimum length: 50 pixels
1482 nMinLen
=pOut
->PixelToLogic(Size(0,50)).Height();
1483 // 20 pixels distance to the Obj for the reference point
1484 nObjDst
=pOut
->PixelToLogic(Size(0,20)).Height();
1486 // margin = minimum length = 10 pixels
1487 long nDst
=pOut
->PixelToLogic(Size(0,10)).Height();
1488 nOutMin
=-pOut
->GetMapMode().GetOrigin().Y();
1489 nOutMax
=pOut
->GetOutputSize().Height()-1+nOutMin
;
1492 // absolute minimum length, however, is 10 pixels
1493 if (nOutMax
-nOutMin
<nDst
) {
1496 nOutMin
-=(nDst
+1)/2;
1497 nOutMax
=nOutMin
+nDst
;
1499 nOutHgt
=nOutMax
-nOutMin
;
1500 // otherwise minimum length = 1/4 OutHgt
1501 long nTemp
=nOutHgt
/4;
1502 if (nTemp
>nMinLen
) nMinLen
=nTemp
;
1505 tools::Rectangle
aR(GetMarkedObjBoundRect());
1506 Point
aCenter(aR
.Center());
1507 long nMarkHgt
=aR
.GetHeight()-1;
1508 long nHgt
=nMarkHgt
+nObjDst
*2; // 20 pixels overlapping above and below
1509 if (nHgt
<nMinLen
) nHgt
=nMinLen
; // minimum length 50 pixels or 1/4 OutHgt, respectively
1511 long nY1
=aCenter
.Y()-(nHgt
+1)/2;
1514 if (pOut
!=nullptr && nMinLen
>nOutHgt
) nMinLen
=nOutHgt
; // TODO: maybe shorten this a little
1516 if (pOut
!=nullptr) { // now move completely into the visible area
1519 if (nY2
<nY1
+nMinLen
) nY2
=nY1
+nMinLen
;
1523 if (nY1
>nY2
-nMinLen
) nY1
=nY2
-nMinLen
;
1527 maRef1
.setX(aCenter
.X() );
1529 maRef2
.setX(aCenter
.X() );
1535 case SdrDragMode::Transparence
:
1536 case SdrDragMode::Gradient
:
1537 case SdrDragMode::Crop
:
1539 tools::Rectangle
aRect(GetMarkedObjBoundRect());
1540 maRef1
= aRect
.TopLeft();
1541 maRef2
= aRect
.BottomRight();
1548 void SdrMarkView::SetRef1(const Point
& rPt
)
1550 if(meDragMode
== SdrDragMode::Rotate
|| meDragMode
== SdrDragMode::Mirror
)
1553 SdrHdl
* pH
= maHdlList
.GetHdl(SdrHdlKind::Ref1
);
1559 void SdrMarkView::SetRef2(const Point
& rPt
)
1561 if(meDragMode
== SdrDragMode::Mirror
)
1564 SdrHdl
* pH
= maHdlList
.GetHdl(SdrHdlKind::Ref2
);
1570 SfxViewShell
* SdrMarkView::GetSfxViewShell() const
1572 return SfxViewShell::Current();
1575 void SdrMarkView::CheckMarked()
1577 for (size_t nm
=GetMarkedObjectCount(); nm
>0;) {
1579 SdrMark
* pM
= GetSdrMarkByIndex(nm
);
1580 SdrObject
* pObj
= pM
->GetMarkedSdrObj();
1581 SdrPageView
* pPV
= pM
->GetPageView();
1582 bool bRaus
= !pObj
|| !pPV
->IsObjMarkable(pObj
);
1585 GetMarkedObjectListWriteAccess().DeleteMark(nm
);
1589 if (!IsGluePointEditMode()) { // selected glue points only in GlueEditMode
1590 SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
1596 // at least reset the remembered BoundRect to prevent handle
1597 // generation if bForceFrameHandles is TRUE.
1598 mbMarkedObjRectDirty
= true;
1601 void SdrMarkView::SetMarkRects()
1603 SdrPageView
* pPV
= GetSdrPageView();
1607 pPV
->SetHasMarkedObj(GetMarkedObjectList().TakeSnapRect(pPV
, pPV
->MarkSnap()));
1608 GetMarkedObjectList().TakeBoundRect(pPV
, pPV
->MarkBound());
1612 void SdrMarkView::SetFrameHandles(bool bOn
)
1614 if (bOn
!=mbForceFrameHandles
) {
1615 bool bOld
=ImpIsFrameHandles();
1616 mbForceFrameHandles
=bOn
;
1617 bool bNew
=ImpIsFrameHandles();
1620 MarkListHasChanged();
1625 void SdrMarkView::SetEditMode(SdrViewEditMode eMode
)
1627 if (eMode
!=meEditMode
) {
1628 bool bGlue0
=meEditMode
==SdrViewEditMode::GluePointEdit
;
1629 bool bEdge0
=static_cast<SdrCreateView
*>(this)->IsEdgeTool();
1630 meEditMode0
=meEditMode
;
1632 bool bGlue1
=meEditMode
==SdrViewEditMode::GluePointEdit
;
1633 bool bEdge1
=static_cast<SdrCreateView
*>(this)->IsEdgeTool();
1634 // avoid flickering when switching between GlueEdit and EdgeTool
1635 if (bGlue1
&& !bGlue0
) ImpSetGlueVisible2(bGlue1
);
1636 if (bEdge1
!=bEdge0
) ImpSetGlueVisible3(bEdge1
);
1637 if (!bGlue1
&& bGlue0
) ImpSetGlueVisible2(bGlue1
);
1638 if (bGlue0
&& !bGlue1
) UnmarkAllGluePoints();
1643 bool SdrMarkView::IsObjMarkable(SdrObject
const * pObj
, SdrPageView
const * pPV
) const
1647 if (pObj
->IsMarkProtect() ||
1648 (!mbDesignMode
&& pObj
->IsUnoObj()))
1650 // object not selectable or
1651 // SdrUnoObj not in DesignMode
1655 return pPV
==nullptr || pPV
->IsObjMarkable(pObj
);
1658 bool SdrMarkView::IsMarkedObjHit(const Point
& rPnt
, short nTol
) const
1661 nTol
=ImpGetHitTolLogic(nTol
,nullptr);
1662 for (size_t nm
=0; nm
<GetMarkedObjectCount() && !bRet
; ++nm
) {
1663 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
1664 bRet
= nullptr != CheckSingleSdrObjectHit(rPnt
,sal_uInt16(nTol
),pM
->GetMarkedSdrObj(),pM
->GetPageView(),SdrSearchOptions::NONE
,nullptr);
1669 SdrHdl
* SdrMarkView::PickHandle(const Point
& rPnt
) const
1671 if (mbSomeObjChgdFlag
) { // recalculate handles, if necessary
1672 FlushComeBackTimer();
1674 return maHdlList
.IsHdlListHit(rPnt
);
1677 bool SdrMarkView::MarkObj(const Point
& rPnt
, short nTol
, bool bToggle
, bool bDeep
)
1680 nTol
=ImpGetHitTolLogic(nTol
,nullptr);
1681 SdrSearchOptions nOptions
=SdrSearchOptions::PICKMARKABLE
;
1682 if (bDeep
) nOptions
=nOptions
|SdrSearchOptions::DEEP
;
1683 SdrObject
* pObj
= PickObj(rPnt
, static_cast<sal_uInt16
>(nTol
), pPV
, nOptions
);
1685 bool bUnmark
=bToggle
&& IsObjMarked(pObj
);
1686 MarkObj(pObj
,pPV
,bUnmark
);
1688 return pObj
!= nullptr;
1691 bool SdrMarkView::MarkNextObj(bool bPrev
)
1693 SdrPageView
* pPageView
= GetSdrPageView();
1700 SortMarkedObjects();
1701 const size_t nMarkCount
=GetMarkedObjectCount();
1702 size_t nChgMarkNum
= SAL_MAX_SIZE
; // number of the MarkEntry we want to replace
1703 size_t nSearchObjNum
= bPrev
? 0 : SAL_MAX_SIZE
;
1704 if (nMarkCount
!=0) {
1705 nChgMarkNum
=bPrev
? 0 : nMarkCount
-1;
1706 SdrMark
* pM
=GetSdrMarkByIndex(nChgMarkNum
);
1707 OSL_ASSERT(pM
!=nullptr);
1708 if (pM
->GetMarkedSdrObj() != nullptr)
1709 nSearchObjNum
= pM
->GetMarkedSdrObj()->GetNavigationPosition();
1712 SdrObject
* pMarkObj
=nullptr;
1713 SdrObjList
* pSearchObjList
=pPageView
->GetObjList();
1714 const size_t nObjCount
= pSearchObjList
->GetObjCount();
1716 if (nSearchObjNum
>nObjCount
) nSearchObjNum
=nObjCount
;
1717 while (pMarkObj
==nullptr && ((!bPrev
&& nSearchObjNum
>0) || (bPrev
&& nSearchObjNum
<nObjCount
)))
1721 SdrObject
* pSearchObj
= pSearchObjList
->GetObjectForNavigationPosition(nSearchObjNum
);
1722 if (IsObjMarkable(pSearchObj
,pPageView
))
1724 if (TryToFindMarkedObject(pSearchObj
)==SAL_MAX_SIZE
)
1726 pMarkObj
=pSearchObj
;
1729 if (bPrev
) nSearchObjNum
++;
1738 if (nChgMarkNum
!=SAL_MAX_SIZE
)
1740 GetMarkedObjectListWriteAccess().DeleteMark(nChgMarkNum
);
1742 MarkObj(pMarkObj
,pPageView
); // also calls MarkListHasChanged(), AdjustMarkHdl()
1746 bool SdrMarkView::MarkNextObj(const Point
& rPnt
, short nTol
, bool bPrev
)
1748 SortMarkedObjects();
1749 nTol
=ImpGetHitTolLogic(nTol
,nullptr);
1750 SdrMark
* pTopMarkHit
=nullptr;
1751 SdrMark
* pBtmMarkHit
=nullptr;
1752 size_t nTopMarkHit
=0;
1753 size_t nBtmMarkHit
=0;
1754 // find topmost of the selected objects that is hit by rPnt
1755 const size_t nMarkCount
=GetMarkedObjectCount();
1756 for (size_t nm
=nMarkCount
; nm
>0 && pTopMarkHit
==nullptr;) {
1758 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
1759 if(CheckSingleSdrObjectHit(rPnt
,sal_uInt16(nTol
),pM
->GetMarkedSdrObj(),pM
->GetPageView(),SdrSearchOptions::NONE
,nullptr))
1765 // nothing found, in this case, just select an object
1766 if (pTopMarkHit
==nullptr) return MarkObj(rPnt
,sal_uInt16(nTol
));
1768 SdrObject
* pTopObjHit
=pTopMarkHit
->GetMarkedSdrObj();
1769 SdrObjList
* pObjList
=pTopObjHit
->getParentSdrObjListFromSdrObject();
1770 SdrPageView
* pPV
=pTopMarkHit
->GetPageView();
1771 // find lowermost of the selected objects that is hit by rPnt
1772 // and is placed on the same PageView as pTopMarkHit
1773 for (size_t nm
=0; nm
<nMarkCount
&& pBtmMarkHit
==nullptr; ++nm
) {
1774 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
1775 SdrPageView
* pPV2
=pM
->GetPageView();
1776 if (pPV2
==pPV
&& CheckSingleSdrObjectHit(rPnt
,sal_uInt16(nTol
),pM
->GetMarkedSdrObj(),pPV2
,SdrSearchOptions::NONE
,nullptr))
1782 if (pBtmMarkHit
==nullptr) { pBtmMarkHit
=pTopMarkHit
; nBtmMarkHit
=nTopMarkHit
; }
1783 SdrObject
* pBtmObjHit
=pBtmMarkHit
->GetMarkedSdrObj();
1784 const size_t nObjCount
= pObjList
->GetObjCount();
1786 size_t nSearchBeg(0);
1787 E3dScene
* pScene(nullptr);
1788 SdrObject
* pObjHit(bPrev
? pBtmObjHit
: pTopObjHit
);
1790 nullptr != dynamic_cast< const E3dCompoundObject
* >(pObjHit
);
1793 pScene
= dynamic_cast< E3dScene
* >(pObjHit
->getParentSdrObjectFromSdrObject());
1794 bRemap
= nullptr != pScene
;
1799 sal_uInt32
nOrdNumBtm(pBtmObjHit
->GetOrdNum());
1803 nOrdNumBtm
= pScene
->RemapOrdNum(nOrdNumBtm
);
1806 nSearchBeg
= nOrdNumBtm
+ 1;
1810 sal_uInt32
nOrdNumTop(pTopObjHit
->GetOrdNum());
1814 nOrdNumTop
= pScene
->RemapOrdNum(nOrdNumTop
);
1817 nSearchBeg
= nOrdNumTop
;
1820 size_t no
=nSearchBeg
;
1821 SdrObject
* pFndObj
=nullptr;
1822 while (pFndObj
==nullptr && ((!bPrev
&& no
>0) || (bPrev
&& no
<nObjCount
))) {
1828 pObj
= pObjList
->GetObj(pScene
->RemapOrdNum(no
));
1832 pObj
= pObjList
->GetObj(no
);
1835 if (CheckSingleSdrObjectHit(rPnt
,sal_uInt16(nTol
),pObj
,pPV
,SdrSearchOptions::TESTMARKABLE
,nullptr))
1837 if (TryToFindMarkedObject(pObj
)==SAL_MAX_SIZE
) {
1840 // TODO: for performance reasons set on to Top or Btm, if necessary
1845 if (pFndObj
!=nullptr)
1847 GetMarkedObjectListWriteAccess().DeleteMark(bPrev
?nBtmMarkHit
:nTopMarkHit
);
1848 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pFndObj
,pPV
));
1849 MarkListHasChanged();
1852 return pFndObj
!=nullptr;
1855 void SdrMarkView::MarkObj(const tools::Rectangle
& rRect
, bool bUnmark
)
1858 tools::Rectangle
aR(rRect
);
1859 SdrObjList
* pObjList
;
1861 SdrPageView
* pPV
= GetSdrPageView();
1865 pObjList
=pPV
->GetObjList();
1866 tools::Rectangle
aFrm1(aR
);
1867 const size_t nObjCount
= pObjList
->GetObjCount();
1868 for (size_t nO
=0; nO
<nObjCount
; ++nO
) {
1869 SdrObject
* pObj
=pObjList
->GetObj(nO
);
1870 tools::Rectangle
aRect(pObj
->GetCurrentBoundRect());
1871 if (aFrm1
.IsInside(aRect
)) {
1873 if (IsObjMarkable(pObj
,pPV
))
1875 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pObj
,pPV
));
1879 const size_t nPos
=TryToFindMarkedObject(pObj
);
1880 if (nPos
!=SAL_MAX_SIZE
)
1882 GetMarkedObjectListWriteAccess().DeleteMark(nPos
);
1890 SortMarkedObjects();
1891 MarkListHasChanged();
1898 void collectUIInformation(const SdrObject
* pObj
)
1900 EventDescription aDescription
;
1901 aDescription
.aAction
= "SELECT";
1902 aDescription
.aParent
= "MainWindow";
1903 aDescription
.aKeyWord
= "CurrentApp";
1905 if (!pObj
->GetName().isEmpty())
1906 aDescription
.aParameters
= {{"OBJECT", pObj
->GetName()}};
1908 aDescription
.aParameters
= {{"OBJECT", "Unnamed_Obj_" + OUString::number(pObj
->GetOrdNum())}};
1910 UITestLogger::getInstance().logEvent(aDescription
);
1915 void SdrMarkView::MarkObj(SdrObject
* pObj
, SdrPageView
* pPV
, bool bUnmark
, bool bImpNoSetMarkHdl
)
1917 if (pObj
!=nullptr && pPV
!=nullptr && IsObjMarkable(pObj
, pPV
)) {
1921 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pObj
,pPV
));
1922 collectUIInformation(pObj
);
1926 const size_t nPos
=TryToFindMarkedObject(pObj
);
1927 if (nPos
!=SAL_MAX_SIZE
)
1929 GetMarkedObjectListWriteAccess().DeleteMark(nPos
);
1932 if (!bImpNoSetMarkHdl
) {
1933 MarkListHasChanged();
1939 bool SdrMarkView::IsObjMarked(SdrObject
const * pObj
) const
1941 return TryToFindMarkedObject(pObj
)!=SAL_MAX_SIZE
;
1944 sal_uInt16
SdrMarkView::GetMarkHdlSizePixel() const
1946 return maHdlList
.GetHdlSize()*2+1;
1949 void SdrMarkView::SetMarkHdlSizePixel(sal_uInt16 nSiz
)
1953 if (nSiz
!=maHdlList
.GetHdlSize()) {
1954 maHdlList
.SetHdlSize(nSiz
);
1958 bool SdrMarkView::getPossibleGridOffsetForSdrObject(
1959 basegfx::B2DVector
& rOffset
,
1960 const SdrObject
* pObj
,
1961 const SdrPageView
* pPV
) const
1963 if(nullptr == pObj
|| nullptr == pPV
)
1968 const OutputDevice
* pOutputDevice(GetFirstOutputDevice());
1970 if(nullptr == pOutputDevice
)
1975 const SdrPageWindow
* pSdrPageWindow(pPV
->FindPageWindow(*pOutputDevice
));
1977 if(nullptr == pSdrPageWindow
)
1982 const sdr::contact::ObjectContact
& rObjectContact(pSdrPageWindow
->GetObjectContact());
1984 if(!rObjectContact
.supportsGridOffsets())
1989 const sdr::contact::ViewObjectContact
& rVOC(pObj
->GetViewContact().GetViewObjectContact(
1990 const_cast<sdr::contact::ObjectContact
&>(rObjectContact
)));
1992 rObjectContact
.calculateGridOffsetForViewOjectContact(rOffset
, rVOC
);
1994 return !rOffset
.equalZero();
1997 bool SdrMarkView::getPossibleGridOffsetForPosition(
1998 basegfx::B2DVector
& rOffset
,
1999 const basegfx::B2DPoint
& rPoint
,
2000 const SdrPageView
* pPV
) const
2007 const OutputDevice
* pOutputDevice(GetFirstOutputDevice());
2009 if(nullptr == pOutputDevice
)
2014 const SdrPageWindow
* pSdrPageWindow(pPV
->FindPageWindow(*pOutputDevice
));
2016 if(nullptr == pSdrPageWindow
)
2021 const sdr::contact::ObjectContact
& rObjectContact(pSdrPageWindow
->GetObjectContact());
2023 if(!rObjectContact
.supportsGridOffsets())
2028 rObjectContact
.calculateGridOffsetForB2DRange(rOffset
, basegfx::B2DRange(rPoint
));
2030 return !rOffset
.equalZero();
2033 SdrObject
* SdrMarkView::CheckSingleSdrObjectHit(const Point
& rPnt
, sal_uInt16 nTol
, SdrObject
* pObj
, SdrPageView
* pPV
, SdrSearchOptions nOptions
, const SdrLayerIDSet
* pMVisLay
) const
2035 if(((nOptions
& SdrSearchOptions::IMPISMASTER
) && pObj
->IsNotVisibleAsMaster()) || (!pObj
->IsVisible()))
2040 const bool bCheckIfMarkable(nOptions
& SdrSearchOptions::TESTMARKABLE
);
2041 const bool bDeep(nOptions
& SdrSearchOptions::DEEP
);
2042 const bool bOLE(dynamic_cast< const SdrOle2Obj
* >(pObj
) != nullptr);
2043 const bool bTXT(dynamic_cast<const SdrTextObj
*>( pObj
) != nullptr && static_cast<SdrTextObj
*>(pObj
)->IsTextFrame());
2044 SdrObject
* pRet
=nullptr;
2045 tools::Rectangle
aRect(pObj
->GetCurrentBoundRect());
2047 // add possible GridOffset to up-to-now view-independent BoundRect data
2048 basegfx::B2DVector
aGridOffset(0.0, 0.0);
2049 if(getPossibleGridOffsetForSdrObject(aGridOffset
, pObj
, pPV
))
2052 basegfx::fround(aGridOffset
.getX()),
2053 basegfx::fround(aGridOffset
.getY()));
2056 sal_uInt16
nTol2(nTol
);
2058 // double tolerance for OLE, text frames and objects in
2060 if(bOLE
|| bTXT
|| pObj
==static_cast<const SdrObjEditView
*>(this)->GetTextEditObject())
2065 aRect
.AdjustLeft( -nTol2
); // add 1 tolerance for all objects
2066 aRect
.AdjustTop( -nTol2
);
2067 aRect
.AdjustRight(nTol2
);
2068 aRect
.AdjustBottom(nTol2
);
2070 if (aRect
.IsInside(rPnt
))
2072 if (!bCheckIfMarkable
|| IsObjMarkable(pObj
,pPV
))
2074 SdrObjList
* pOL
=pObj
->GetSubList();
2076 if (pOL
!=nullptr && pOL
->GetObjCount()!=0)
2079 // adjustment hit point for virtual objects
2082 if ( dynamic_cast<const SdrVirtObj
*>( pObj
) != nullptr )
2084 Point aOffset
= static_cast<SdrVirtObj
*>(pObj
)->GetOffset();
2085 aPnt
.Move( -aOffset
.X(), -aOffset
.Y() );
2088 pRet
=CheckSingleSdrObjectHit(aPnt
,nTol
,pOL
,pPV
,nOptions
,pMVisLay
,pTmpObj
);
2092 if(!pMVisLay
|| pMVisLay
->IsSet(pObj
->GetLayer()))
2094 pRet
= SdrObjectPrimitiveHit(*pObj
, rPnt
, nTol2
, *pPV
, &pPV
->GetVisibleLayers(), false);
2100 if (!bDeep
&& pRet
!=nullptr)
2108 SdrObject
* SdrMarkView::CheckSingleSdrObjectHit(const Point
& rPnt
, sal_uInt16 nTol
, SdrObjList
const * pOL
, SdrPageView
* pPV
, SdrSearchOptions nOptions
, const SdrLayerIDSet
* pMVisLay
, SdrObject
*& rpRootObj
) const
2110 return (*this).CheckSingleSdrObjectHit(rPnt
,nTol
,pOL
,pPV
,nOptions
,pMVisLay
,rpRootObj
,nullptr);
2112 SdrObject
* SdrMarkView::CheckSingleSdrObjectHit(const Point
& rPnt
, sal_uInt16 nTol
, SdrObjList
const * pOL
, SdrPageView
* pPV
, SdrSearchOptions nOptions
, const SdrLayerIDSet
* pMVisLay
, SdrObject
*& rpRootObj
,const SdrMarkList
* pMarkList
) const
2114 SdrObject
* pRet
=nullptr;
2119 nullptr != pOL
->getSdrObjectFromSdrObjList()
2120 && nullptr != dynamic_cast< const E3dScene
* >(pOL
->getSdrObjectFromSdrObjList()));
2121 const E3dScene
* pRemapScene(bRemap
? static_cast< E3dScene
* >(pOL
->getSdrObjectFromSdrObjList()) : nullptr);
2122 const size_t nObjCount(pOL
->GetObjCount());
2123 size_t nObjNum(nObjCount
);
2125 while (pRet
==nullptr && nObjNum
>0)
2132 pObj
= pOL
->GetObj(pRemapScene
->RemapOrdNum(nObjNum
));
2136 pObj
= pOL
->GetObj(nObjNum
);
2138 if (nOptions
& SdrSearchOptions::BEFOREMARK
)
2140 if (pMarkList
!=nullptr)
2142 if ((*pMarkList
).FindObject(pObj
)!=SAL_MAX_SIZE
)
2148 pRet
=CheckSingleSdrObjectHit(rPnt
,nTol
,pObj
,pPV
,nOptions
,pMVisLay
);
2149 if (pRet
!=nullptr) rpRootObj
=pObj
;
2155 SdrObject
* SdrMarkView::PickObj(const Point
& rPnt
, short nTol
, SdrPageView
*& rpPV
, SdrSearchOptions nOptions
) const
2157 return PickObj(rPnt
, nTol
, rpPV
, nOptions
, nullptr);
2160 SdrObject
* SdrMarkView::PickObj(const Point
& rPnt
, short nTol
, SdrPageView
*& rpPV
, SdrSearchOptions nOptions
, SdrObject
** ppRootObj
, bool* pbHitPassDirect
) const
2161 { // TODO: lacks a Pass2,Pass3
2162 SortMarkedObjects();
2163 if (ppRootObj
!=nullptr) *ppRootObj
=nullptr;
2164 if (pbHitPassDirect
!=nullptr) *pbHitPassDirect
=true;
2165 SdrObject
* pRet
= nullptr;
2167 bool bMarked(nOptions
& SdrSearchOptions::MARKED
);
2168 bool bMasters
=!bMarked
&& bool(nOptions
& SdrSearchOptions::ALSOONMASTER
);
2169 // nOptions & SdrSearchOptions::NEXT: n.i.
2170 // nOptions & SdrSearchOptions::PASS2BOUND: n.i.
2171 // nOptions & SdrSearchOptions::PASS3NEAREST// n.i.
2172 if (nTol
<0) nTol
=ImpGetHitTolLogic(nTol
,nullptr);
2173 SdrObject
* pObj
=nullptr;
2174 SdrObject
* pHitObj
=nullptr;
2175 SdrPageView
* pPV
=nullptr;
2176 if (static_cast<const SdrObjEditView
*>(this)->IsTextEditFrameHit(rPnt
)) {
2177 pObj
=static_cast<const SdrObjEditView
*>(this)->GetTextEditObject();
2179 pPV
=static_cast<const SdrObjEditView
*>(this)->GetTextEditPageView();
2182 const size_t nMrkCnt
=GetMarkedObjectCount();
2183 size_t nMrkNum
=nMrkCnt
;
2184 while (pHitObj
==nullptr && nMrkNum
>0) {
2186 SdrMark
* pM
=GetSdrMarkByIndex(nMrkNum
);
2187 pObj
=pM
->GetMarkedSdrObj();
2188 pPV
=pM
->GetPageView();
2189 pHitObj
=CheckSingleSdrObjectHit(rPnt
,nTol
,pObj
,pPV
,nOptions
,nullptr);
2194 pPV
= GetSdrPageView();
2198 SdrPage
* pPage
=pPV
->GetPage();
2199 sal_uInt16 nPgCount
=1;
2201 if(bMasters
&& pPage
->TRG_HasMasterPage())
2205 bool bWholePage(nOptions
& SdrSearchOptions::WHOLEPAGE
);
2206 bool bExtraPassForWholePage
=bWholePage
&& pPage
!=pPV
->GetObjList();
2207 if (bExtraPassForWholePage
) nPgCount
++; // First search in AktObjList, then on the entire page
2208 sal_uInt16 nPgNum
=nPgCount
;
2209 while (pHitObj
==nullptr && nPgNum
>0) {
2210 SdrSearchOptions nTmpOptions
=nOptions
;
2212 const SdrLayerIDSet
* pMVisLay
=nullptr;
2213 SdrObjList
* pObjList
=nullptr;
2214 if (pbHitPassDirect
!=nullptr) *pbHitPassDirect
= true;
2215 if (nPgNum
>=nPgCount
-1 || (bExtraPassForWholePage
&& nPgNum
>=nPgCount
-2))
2217 pObjList
=pPV
->GetObjList();
2218 if (bExtraPassForWholePage
&& nPgNum
==nPgCount
-2) {
2220 if (pbHitPassDirect
!=nullptr) *pbHitPassDirect
= false;
2225 // otherwise MasterPage
2226 SdrPage
& rMasterPage
= pPage
->TRG_GetMasterPage();
2227 pMVisLay
= &pPage
->TRG_GetMasterPageVisibleLayers();
2228 pObjList
= &rMasterPage
;
2230 if (pbHitPassDirect
!=nullptr) *pbHitPassDirect
= false;
2231 nTmpOptions
=nTmpOptions
| SdrSearchOptions::IMPISMASTER
;
2233 pHitObj
=CheckSingleSdrObjectHit(rPnt
,nTol
,pObjList
,pPV
,nTmpOptions
,pMVisLay
,pObj
,&(GetMarkedObjectList()));
2237 if (pHitObj
!=nullptr) {
2238 if (ppRootObj
!=nullptr) *ppRootObj
=pObj
;
2239 if (nOptions
& SdrSearchOptions::DEEP
) pObj
=pHitObj
;
2240 if (nOptions
& SdrSearchOptions::TESTTEXTEDIT
) {
2241 if (!pObj
->HasTextEdit() || pPV
->GetLockedLayers().IsSet(pObj
->GetLayer())) {
2245 if (pObj
!=nullptr && (nOptions
& SdrSearchOptions::TESTMACRO
)) {
2246 SdrObjMacroHitRec aHitRec
;
2249 aHitRec
.pVisiLayer
=&pPV
->GetVisibleLayers();
2250 aHitRec
.pPageView
=pPV
;
2251 if (!pObj
->HasMacro() || !pObj
->IsMacroHit(aHitRec
)) pObj
=nullptr;
2253 if (pObj
!=nullptr) {
2261 bool SdrMarkView::PickMarkedObj(const Point
& rPnt
, SdrObject
*& rpObj
, SdrPageView
*& rpPV
, SdrSearchOptions nOptions
) const
2263 SortMarkedObjects();
2264 const bool bBoundCheckOn2ndPass(nOptions
& SdrSearchOptions::PASS2BOUND
);
2267 const size_t nMarkCount
=GetMarkedObjectCount();
2268 for (size_t nMarkNum
=nMarkCount
; nMarkNum
>0;) {
2270 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
2271 SdrPageView
* pPV
=pM
->GetPageView();
2272 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
2273 if (CheckSingleSdrObjectHit(rPnt
,mnHitTolLog
,pObj
,pPV
,SdrSearchOptions::TESTMARKABLE
,nullptr)) {
2279 if (bBoundCheckOn2ndPass
) {
2280 for (size_t nMarkNum
=nMarkCount
; nMarkNum
>0;) {
2282 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
2283 SdrPageView
* pPV
=pM
->GetPageView();
2284 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
2285 tools::Rectangle
aRect(pObj
->GetCurrentBoundRect());
2286 aRect
.AdjustLeft( -mnHitTolLog
);
2287 aRect
.AdjustTop( -mnHitTolLog
);
2288 aRect
.AdjustRight(mnHitTolLog
);
2289 aRect
.AdjustBottom(mnHitTolLog
);
2290 if (aRect
.IsInside(rPnt
)) {
2301 void SdrMarkView::UnmarkAllObj(SdrPageView
const * pPV
)
2303 if (GetMarkedObjectCount()!=0) {
2307 GetMarkedObjectListWriteAccess().DeletePageView(*pPV
);
2311 GetMarkedObjectListWriteAccess().Clear();
2313 mpMarkedObj
=nullptr;
2315 MarkListHasChanged();
2320 void SdrMarkView::MarkAllObj(SdrPageView
* pPV
)
2326 pPV
= GetSdrPageView();
2329 // #i69171# pPV may still be NULL if there is no SDrPageView (!), e.g. when inserting
2333 const bool bMarkChg(GetMarkedObjectListWriteAccess().InsertPageView(*pPV
));
2337 MarkListHasChanged();
2341 if(GetMarkedObjectCount())
2347 void SdrMarkView::AdjustMarkHdl(SfxViewShell
* pOtherShell
)
2351 SetMarkHandles(pOtherShell
);
2354 // BoundRect in model coordinates, no GridOffset added
2355 tools::Rectangle
SdrMarkView::GetMarkedObjBoundRect() const
2357 tools::Rectangle aRect
;
2358 for (size_t nm
=0; nm
<GetMarkedObjectCount(); ++nm
) {
2359 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
2360 SdrObject
* pO
=pM
->GetMarkedSdrObj();
2361 tools::Rectangle
aR1(pO
->GetCurrentBoundRect());
2362 if (aRect
.IsEmpty()) aRect
=aR1
;
2363 else aRect
.Union(aR1
);
2368 // ObjRect in model coordinates, no GridOffset added
2369 const tools::Rectangle
& SdrMarkView::GetMarkedObjRect() const
2371 if (mbMarkedObjRectDirty
) {
2372 const_cast<SdrMarkView
*>(this)->mbMarkedObjRectDirty
=false;
2373 tools::Rectangle aRect
;
2374 for (size_t nm
=0; nm
<GetMarkedObjectCount(); ++nm
) {
2375 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
2376 SdrObject
* pO
= pM
->GetMarkedSdrObj();
2379 tools::Rectangle
aR1(pO
->GetSnapRect());
2380 if (aRect
.IsEmpty()) aRect
=aR1
;
2381 else aRect
.Union(aR1
);
2383 const_cast<SdrMarkView
*>(this)->maMarkedObjRect
=aRect
;
2385 return maMarkedObjRect
;
2389 OUString
SdrMarkView::ImpGetDescriptionString(const char* pStrCacheID
, ImpGetDescriptionOptions nOpt
) const
2391 OUString sStr
= SvxResId(pStrCacheID
);
2392 const sal_Int32 nPos
= sStr
.indexOf("%1");
2396 if(nOpt
== ImpGetDescriptionOptions::POINTS
)
2398 sStr
= sStr
.replaceAt(nPos
, 2, GetDescriptionOfMarkedPoints());
2400 else if(nOpt
== ImpGetDescriptionOptions::GLUEPOINTS
)
2402 sStr
= sStr
.replaceAt(nPos
, 2, GetDescriptionOfMarkedGluePoints());
2406 sStr
= sStr
.replaceAt(nPos
, 2, GetDescriptionOfMarkedObjects());
2410 return sStr
.replaceFirst("%2", "0");
2414 void SdrMarkView::EnterMarkedGroup()
2416 // We enter only the first group found (in only one PageView), because
2417 // PageView::EnterGroup calls an AdjustMarkHdl.
2418 // TODO: I'll have to prevent that via a flag.
2419 SdrPageView
* pPV
= GetSdrPageView();
2424 for (size_t nm
= GetMarkedObjectCount(); nm
> 0 && !bEnter
;)
2427 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
2428 if (pM
->GetPageView()==pPV
) {
2429 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
2430 if (pObj
->IsGroupObject()) {
2431 if (pPV
->EnterGroup(pObj
)) {
2441 void SdrMarkView::MarkListHasChanged()
2443 GetMarkedObjectListWriteAccess().SetNameDirty();
2444 maSdrViewSelection
.SetEdgesOfMarkedNodesDirty();
2446 mbMarkedObjRectDirty
=true;
2447 mbMarkedPointsRectsDirty
=true;
2449 if (mpItemBrowser
!=nullptr) mpItemBrowser
->SetDirty();
2451 bool bOneEdgeMarked
=false;
2452 if (GetMarkedObjectCount()==1) {
2453 const SdrObject
* pObj
=GetMarkedObjectByIndex(0);
2454 if (pObj
->GetObjInventor()==SdrInventor::Default
) {
2455 sal_uInt16 nIdent
=pObj
->GetObjIdentifier();
2456 bOneEdgeMarked
=nIdent
==OBJ_EDGE
;
2459 ImpSetGlueVisible4(bOneEdgeMarked
);
2463 void SdrMarkView::SetMoveOutside(bool bOn
)
2465 maHdlList
.SetMoveOutside(bOn
);
2468 void SdrMarkView::SetDesignMode( bool bOn
)
2470 if ( mbDesignMode
!= bOn
)
2473 SdrPageView
* pPageView
= GetSdrPageView();
2475 pPageView
->SetDesignMode( bOn
);
2479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */