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/svdview.hxx>
23 #include <svx/svdpagv.hxx>
24 #include <svx/svdpage.hxx>
25 #include <svx/svdotable.hxx>
27 #include <osl/thread.h>
28 #include <rtl/strbuf.hxx>
29 #include <svx/svdoole2.hxx>
30 #include <svx/xgrad.hxx>
31 #include <svx/xfillit0.hxx>
32 #include <svx/xflgrit.hxx>
33 #include "gradtrns.hxx"
34 #include <svx/xflftrit.hxx>
35 #include <svx/dialmgr.hxx>
36 #include <svx/strings.hrc>
37 #include <svx/svdundo.hxx>
38 #include <svx/svdopath.hxx>
39 #include <svx/scene3d.hxx>
40 #include <svx/svdovirt.hxx>
41 #include <sdr/overlay/overlayrollingrectangle.hxx>
42 #include <svx/sdr/contact/objectcontact.hxx>
43 #include <svx/sdr/overlay/overlaymanager.hxx>
44 #include <svx/sdr/overlay/overlayselection.hxx>
45 #include <svx/sdr/contact/viewcontact.hxx>
46 #include <svx/sdr/contact/viewobjectcontact.hxx>
47 #include <svx/sdrpaintwindow.hxx>
48 #include <svx/sdrpagewindow.hxx>
49 #include <svx/sdrhittesthelper.hxx>
50 #include <vcl/uitest/logger.hxx>
51 #include <vcl/uitest/eventdescription.hxx>
53 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
54 #include <comphelper/lok.hxx>
55 #include <sfx2/lokhelper.hxx>
56 #include <sfx2/lokcharthelper.hxx>
57 #include <sfx2/viewsh.hxx>
61 #include <com/sun/star/frame/XController.hpp>
62 #include <com/sun/star/view/XSelectionSupplier.hpp>
64 #include <boost/property_tree/json_parser.hpp>
66 using namespace com::sun::star
;
68 // Migrate Marking of Objects, Points and GluePoints
70 class ImplMarkingOverlay
73 sdr::overlay::OverlayObjectList maObjects
;
75 // The remembered second position in logical coordinates
76 basegfx::B2DPoint maSecondPosition
;
78 // A flag to remember if the action is for unmarking.
82 ImplMarkingOverlay(const SdrPaintView
& rView
, const basegfx::B2DPoint
& rStartPos
, bool bUnmarking
);
84 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
85 // That destructor calls clear() at the list which removes all objects from the
86 // OverlayManager and deletes them.
88 void SetSecondPosition(const basegfx::B2DPoint
& rNewPosition
);
89 bool IsUnmarking() const { return mbUnmarking
; }
92 ImplMarkingOverlay::ImplMarkingOverlay(const SdrPaintView
& rView
, const basegfx::B2DPoint
& rStartPos
, bool bUnmarking
)
93 : maSecondPosition(rStartPos
),
94 mbUnmarking(bUnmarking
)
96 if (comphelper::LibreOfficeKit::isActive())
97 return; // We do client-side object manipulation with the Kit API
99 for(sal_uInt32
a(0); a
< rView
.PaintWindowCount(); a
++)
101 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
102 const rtl::Reference
< sdr::overlay::OverlayManager
>& xTargetOverlay
= pCandidate
->GetOverlayManager();
104 if (xTargetOverlay
.is())
106 std::unique_ptr
<sdr::overlay::OverlayRollingRectangleStriped
> pNew(new sdr::overlay::OverlayRollingRectangleStriped(
107 rStartPos
, rStartPos
, false));
108 xTargetOverlay
->add(*pNew
);
109 maObjects
.append(std::move(pNew
));
114 void ImplMarkingOverlay::SetSecondPosition(const basegfx::B2DPoint
& rNewPosition
)
116 if(rNewPosition
!= maSecondPosition
)
118 // apply to OverlayObjects
119 for(sal_uInt32
a(0); a
< maObjects
.count(); a
++)
121 sdr::overlay::OverlayRollingRectangleStriped
& rCandidate
= static_cast< sdr::overlay::OverlayRollingRectangleStriped
&>(maObjects
.getOverlayObject(a
));
122 rCandidate
.setSecondPosition(rNewPosition
);
125 // remember new position
126 maSecondPosition
= rNewPosition
;
130 class MarkingSubSelectionOverlay
132 sdr::overlay::OverlayObjectList maObjects
;
135 MarkingSubSelectionOverlay(const SdrPaintView
& rView
, std::vector
<basegfx::B2DRectangle
> const & rSelections
)
137 if (comphelper::LibreOfficeKit::isActive())
138 return; // We do client-side object manipulation with the Kit API
140 for (sal_uInt32
a(0); a
< rView
.PaintWindowCount(); a
++)
142 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
143 const rtl::Reference
<sdr::overlay::OverlayManager
>& xTargetOverlay
= pCandidate
->GetOverlayManager();
145 if (xTargetOverlay
.is())
147 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer
;
148 const Color aHighlightColor
= aSvtOptionsDrawinglayer
.getHilightColor();
150 std::unique_ptr
<sdr::overlay::OverlaySelection
> pNew
=
151 std::make_unique
<sdr::overlay::OverlaySelection
>(
152 sdr::overlay::OverlayType::Transparent
,
153 aHighlightColor
, rSelections
, false);
155 xTargetOverlay
->add(*pNew
);
156 maObjects
.append(std::move(pNew
));
162 SdrMarkView::SdrMarkView(SdrModel
& rSdrModel
, OutputDevice
* pOut
)
163 : SdrSnapView(rSdrModel
, pOut
)
164 , mpMarkedObj(nullptr)
165 , mpMarkedPV(nullptr)
167 , meDragMode(SdrDragMode::Move
)
168 , meEditMode(SdrViewEditMode::Edit
)
169 , meEditMode0(SdrViewEditMode::Edit
)
170 , mbDesignMode(false)
171 , mbForceFrameHandles(false)
172 , mbPlusHdlAlways(false)
173 , mbInsPolyPoint(false)
174 , mbMarkedObjRectDirty(false)
175 , mbMrkPntDirty(false)
176 , mbMarkedPointsRectsDirty(false)
177 , mbMarkHandlesHidden(false)
184 StartListening(rSdrModel
);
187 SdrMarkView::~SdrMarkView()
189 // Migrate selections
195 void SdrMarkView::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
197 if (rHint
.GetId() == SfxHintId::ThisIsAnSdrHint
)
199 const SdrHint
* pSdrHint
= static_cast<const SdrHint
*>(&rHint
);
200 SdrHintKind eKind
=pSdrHint
->GetKind();
201 if (eKind
==SdrHintKind::ObjectChange
|| eKind
==SdrHintKind::ObjectInserted
|| eKind
==SdrHintKind::ObjectRemoved
)
203 mbMarkedObjRectDirty
=true;
204 mbMarkedPointsRectsDirty
=true;
207 SdrSnapView::Notify(rBC
,rHint
);
210 void SdrMarkView::ModelHasChanged()
212 SdrPaintView::ModelHasChanged();
213 GetMarkedObjectListWriteAccess().SetNameDirty();
214 mbMarkedObjRectDirty
=true;
215 mbMarkedPointsRectsDirty
=true;
216 // Example: Obj is selected and maMarkedObjectList is sorted.
217 // In another View 2, the ObjOrder is changed (e. g. MovToTop())
218 // Then we need to re-sort MarkList.
219 GetMarkedObjectListWriteAccess().SetUnsorted();
223 SdrView
* pV
=static_cast<SdrView
*>(this);
224 if (pV
!=nullptr && !pV
->IsDragObj() && !pV
->IsInsObjPoint()) {
228 if (!(comphelper::LibreOfficeKit::isActive() && GetMarkedObjectCount() > 0))
231 //TODO: Is MarkedObjRect valid at this point?
232 tools::Rectangle
aSelection(GetMarkedObjRect());
234 if (aSelection
.IsEmpty())
235 sSelection
= "EMPTY";
238 sal_uInt32 nTotalPaintWindows
= this->PaintWindowCount();
239 if (nTotalPaintWindows
== 1)
241 const vcl::Window
* pWin
= dynamic_cast<const vcl::Window
*>(this->GetFirstOutputDevice());
242 if (pWin
&& pWin
->IsChart())
244 const vcl::Window
* pViewShellWindow
= GetSfxViewShell()->GetEditWindowForActiveOLEObj();
245 if (pViewShellWindow
&& pViewShellWindow
->IsAncestorOf(*pWin
))
247 Point aOffsetPx
= pWin
->GetOffsetPixelFrom(*pViewShellWindow
);
248 Point aLogicOffset
= pWin
->PixelToLogic(aOffsetPx
);
249 aSelection
.Move(aLogicOffset
.getX(), aLogicOffset
.getY());
254 // In case the map mode is in 100th MM, then need to convert the coordinates over to twips for LOK.
257 if (OutputDevice
* pOutputDevice
= mpMarkedPV
->GetView().GetFirstOutputDevice())
259 if (pOutputDevice
->GetMapMode().GetMapUnit() == MapUnit::Map100thMM
)
260 aSelection
= OutputDevice::LogicToLogic(aSelection
, MapMode(MapUnit::Map100thMM
), MapMode(MapUnit::MapTwip
));
264 sSelection
= aSelection
.toString();
267 if(SfxViewShell
* pViewShell
= GetSfxViewShell())
268 SfxLokHelper::notifyInvalidation(pViewShell
, sSelection
);
272 bool SdrMarkView::IsAction() const
274 return SdrSnapView::IsAction() || IsMarkObj() || IsMarkPoints() || IsMarkGluePoints();
277 void SdrMarkView::MovAction(const Point
& rPnt
)
279 SdrSnapView::MovAction(rPnt
);
285 else if(IsMarkPoints())
289 else if(IsMarkGluePoints())
291 MovMarkGluePoints(rPnt
);
295 void SdrMarkView::EndAction()
301 else if(IsMarkPoints())
305 else if(IsMarkGluePoints())
310 SdrSnapView::EndAction();
313 void SdrMarkView::BckAction()
315 SdrSnapView::BckAction();
321 void SdrMarkView::BrkAction()
323 SdrSnapView::BrkAction();
329 void SdrMarkView::TakeActionRect(tools::Rectangle
& rRect
) const
331 if(IsMarkObj() || IsMarkPoints() || IsMarkGluePoints())
333 rRect
= tools::Rectangle(maDragStat
.GetStart(), maDragStat
.GetNow());
337 SdrSnapView::TakeActionRect(rRect
);
342 void SdrMarkView::ClearPageView()
345 SdrSnapView::ClearPageView();
348 void SdrMarkView::HideSdrPage()
352 SdrPageView
* pPageView
= GetSdrPageView();
355 // break all creation actions when hiding page (#75081#)
358 // Discard all selections on this page
359 bMrkChg
= GetMarkedObjectListWriteAccess().DeletePageView(*pPageView
);
362 SdrSnapView::HideSdrPage();
366 MarkListHasChanged();
372 void SdrMarkView::BegMarkObj(const Point
& rPnt
, bool bUnmark
)
376 DBG_ASSERT(!mpMarkObjOverlay
, "SdrMarkView::BegMarkObj: There exists a mpMarkObjOverlay (!)");
378 basegfx::B2DPoint
aStartPos(rPnt
.X(), rPnt
.Y());
379 mpMarkObjOverlay
.reset(new ImplMarkingOverlay(*this, aStartPos
, bUnmark
));
381 maDragStat
.Reset(rPnt
);
382 maDragStat
.NextPoint();
383 maDragStat
.SetMinMove(mnMinMovLog
);
386 void SdrMarkView::MovMarkObj(const Point
& rPnt
)
388 if(IsMarkObj() && maDragStat
.CheckMinMoved(rPnt
))
390 maDragStat
.NextMove(rPnt
);
391 DBG_ASSERT(mpMarkObjOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
392 basegfx::B2DPoint
aNewPos(rPnt
.X(), rPnt
.Y());
393 mpMarkObjOverlay
->SetSecondPosition(aNewPos
);
397 bool SdrMarkView::EndMarkObj()
403 if(maDragStat
.IsMinMoved())
405 tools::Rectangle
aRect(maDragStat
.GetStart(), maDragStat
.GetNow());
407 MarkObj(aRect
, mpMarkObjOverlay
->IsUnmarking());
418 void SdrMarkView::BrkMarkObj()
422 DBG_ASSERT(mpMarkObjOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
423 mpMarkObjOverlay
.reset();
428 bool SdrMarkView::BegMarkPoints(const Point
& rPnt
, bool bUnmark
)
430 if(HasMarkablePoints())
434 DBG_ASSERT(!mpMarkPointsOverlay
, "SdrMarkView::BegMarkObj: There exists a mpMarkPointsOverlay (!)");
435 basegfx::B2DPoint
aStartPos(rPnt
.X(), rPnt
.Y());
436 mpMarkPointsOverlay
.reset(new ImplMarkingOverlay(*this, aStartPos
, bUnmark
));
438 maDragStat
.Reset(rPnt
);
439 maDragStat
.NextPoint();
440 maDragStat
.SetMinMove(mnMinMovLog
);
448 void SdrMarkView::MovMarkPoints(const Point
& rPnt
)
450 if(IsMarkPoints() && maDragStat
.CheckMinMoved(rPnt
))
452 maDragStat
.NextMove(rPnt
);
454 DBG_ASSERT(mpMarkPointsOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
455 basegfx::B2DPoint
aNewPos(rPnt
.X(), rPnt
.Y());
456 mpMarkPointsOverlay
->SetSecondPosition(aNewPos
);
460 bool SdrMarkView::EndMarkPoints()
466 if(maDragStat
.IsMinMoved())
468 tools::Rectangle
aRect(maDragStat
.GetStart(), maDragStat
.GetNow());
470 MarkPoints(&aRect
, mpMarkPointsOverlay
->IsUnmarking());
482 void SdrMarkView::BrkMarkPoints()
486 DBG_ASSERT(mpMarkPointsOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
487 mpMarkPointsOverlay
.reset();
492 bool SdrMarkView::BegMarkGluePoints(const Point
& rPnt
, bool bUnmark
)
494 if(HasMarkableGluePoints())
498 DBG_ASSERT(!mpMarkGluePointsOverlay
, "SdrMarkView::BegMarkObj: There exists a mpMarkGluePointsOverlay (!)");
500 basegfx::B2DPoint
aStartPos(rPnt
.X(), rPnt
.Y());
501 mpMarkGluePointsOverlay
.reset(new ImplMarkingOverlay(*this, aStartPos
, bUnmark
));
502 maDragStat
.Reset(rPnt
);
503 maDragStat
.NextPoint();
504 maDragStat
.SetMinMove(mnMinMovLog
);
512 void SdrMarkView::MovMarkGluePoints(const Point
& rPnt
)
514 if(IsMarkGluePoints() && maDragStat
.CheckMinMoved(rPnt
))
516 maDragStat
.NextMove(rPnt
);
518 DBG_ASSERT(mpMarkGluePointsOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
519 basegfx::B2DPoint
aNewPos(rPnt
.X(), rPnt
.Y());
520 mpMarkGluePointsOverlay
->SetSecondPosition(aNewPos
);
524 void SdrMarkView::EndMarkGluePoints()
526 if(IsMarkGluePoints())
528 if(maDragStat
.IsMinMoved())
530 tools::Rectangle
aRect(maDragStat
.GetStart(),maDragStat
.GetNow());
532 MarkGluePoints(&aRect
, mpMarkGluePointsOverlay
->IsUnmarking());
540 void SdrMarkView::BrkMarkGluePoints()
542 if(IsMarkGluePoints())
544 DBG_ASSERT(mpMarkGluePointsOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
545 mpMarkGluePointsOverlay
.reset();
549 bool SdrMarkView::MarkableObjectsExceed( int n
) const
551 SdrPageView
* pPV
= GetSdrPageView();
555 SdrObjList
* pOL
=pPV
->GetObjList();
556 const size_t nObjCount
= pOL
->GetObjCount();
557 for (size_t nObjNum
=0; nObjNum
<nObjCount
; ++nObjNum
) {
558 SdrObject
* pObj
=pOL
->GetObj(nObjNum
);
559 if (IsObjMarkable(pObj
,pPV
) && --n
<0)
566 void SdrMarkView::hideMarkHandles()
568 if(!mbMarkHandlesHidden
)
570 mbMarkHandlesHidden
= true;
575 void SdrMarkView::showMarkHandles()
577 if(mbMarkHandlesHidden
)
579 mbMarkHandlesHidden
= false;
584 bool SdrMarkView::ImpIsFrameHandles() const
586 const size_t nMarkCount
=GetMarkedObjectCount();
587 bool bFrmHdl
=nMarkCount
>static_cast<size_t>(mnFrameHandlesLimit
) || mbForceFrameHandles
;
588 bool bStdDrag
=meDragMode
==SdrDragMode::Move
;
589 if (nMarkCount
==1 && bStdDrag
&& bFrmHdl
)
591 const SdrObject
* pObj
=GetMarkedObjectByIndex(0);
592 if (pObj
->GetObjInventor()==SdrInventor::Default
)
594 sal_uInt16 nIdent
=pObj
->GetObjIdentifier();
595 if (nIdent
==OBJ_LINE
|| nIdent
==OBJ_EDGE
|| nIdent
==OBJ_CAPTION
|| nIdent
==OBJ_MEASURE
|| nIdent
==OBJ_CUSTOMSHAPE
|| nIdent
==OBJ_TABLE
)
601 if (!bStdDrag
&& !bFrmHdl
) {
602 // all other drag modes only with FrameHandles
604 if (meDragMode
==SdrDragMode::Rotate
) {
605 // when rotating, use ObjOwn drag, if there's at least 1 PolyObj
606 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& bFrmHdl
; ++nMarkNum
) {
607 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
608 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
609 bFrmHdl
=!pObj
->IsPolyObj();
614 // FrameHandles, if at least 1 Obj can't do SpecialDrag
615 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& !bFrmHdl
; ++nMarkNum
) {
616 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
617 const SdrObject
* pObj
=pM
->GetMarkedSdrObj();
618 bFrmHdl
=!pObj
->hasSpecialDrag();
622 // no FrameHdl for crop
623 if(bFrmHdl
&& SdrDragMode::Crop
== meDragMode
)
633 OUString
lcl_getDragMethodServiceName( const OUString
& rCID
)
637 sal_Int32 nIndexStart
= rCID
.indexOf( "DragMethod=" );
638 if( nIndexStart
!= -1 )
640 nIndexStart
= rCID
.indexOf( '=', nIndexStart
);
641 if( nIndexStart
!= -1 )
644 sal_Int32 nNextSlash
= rCID
.indexOf( '/', nIndexStart
);
645 if( nNextSlash
!= -1 )
647 sal_Int32 nIndexEnd
= nNextSlash
;
648 sal_Int32 nNextColon
= rCID
.indexOf( ':', nIndexStart
);
649 if( nNextColon
< nNextSlash
)
650 nIndexEnd
= nNextColon
;
651 aRet
= rCID
.copy(nIndexStart
,nIndexEnd
-nIndexStart
);
658 OUString
lcl_getDragParameterString( const OUString
& rCID
)
662 sal_Int32 nIndexStart
= rCID
.indexOf( "DragParameter=" );
663 if( nIndexStart
!= -1 )
665 nIndexStart
= rCID
.indexOf( '=', nIndexStart
);
666 if( nIndexStart
!= -1 )
669 sal_Int32 nNextSlash
= rCID
.indexOf( '/', nIndexStart
);
670 if( nNextSlash
!= -1 )
672 sal_Int32 nIndexEnd
= nNextSlash
;
673 sal_Int32 nNextColon
= rCID
.indexOf( ':', nIndexStart
);
674 if( nNextColon
< nNextSlash
)
675 nIndexEnd
= nNextColon
;
676 aRet
= rCID
.copy(nIndexStart
,nIndexEnd
-nIndexStart
);
682 } // anonymous namespace
684 void SdrMarkView::SetMarkHandlesForLOKit(tools::Rectangle
const & rRect
, const SfxViewShell
* pOtherShell
)
686 SfxViewShell
* pViewShell
= GetSfxViewShell();
688 tools::Rectangle
aSelection(rRect
);
689 bool bIsChart
= false;
691 if (!rRect
.IsEmpty())
693 sal_uInt32 nTotalPaintWindows
= this->PaintWindowCount();
694 if (nTotalPaintWindows
== 1)
696 const vcl::Window
* pWin
= dynamic_cast<const vcl::Window
*>(this->GetFirstOutputDevice());
697 if (pWin
&& pWin
->IsChart())
700 const vcl::Window
* pViewShellWindow
= GetSfxViewShell()->GetEditWindowForActiveOLEObj();
701 if (pViewShellWindow
&& pViewShellWindow
->IsAncestorOf(*pWin
))
703 Point aOffsetPx
= pWin
->GetOffsetPixelFrom(*pViewShellWindow
);
704 Point aLogicOffset
= pWin
->PixelToLogic(aOffsetPx
);
705 aSelection
.Move(aLogicOffset
.getX(), aLogicOffset
.getY());
711 if (!aSelection
.IsEmpty())
713 // In case the map mode is in 100th MM, then need to convert the coordinates over to twips for LOK.
716 if (OutputDevice
* pOutputDevice
= mpMarkedPV
->GetView().GetFirstOutputDevice())
718 if (pOutputDevice
->GetMapMode().GetMapUnit() == MapUnit::Map100thMM
)
719 aSelection
= OutputDevice::LogicToLogic(aSelection
, MapMode(MapUnit::Map100thMM
), MapMode(MapUnit::MapTwip
));
723 // hide the text selection too
724 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION
, "");
728 OString sSelectionText
;
729 boost::property_tree::ptree aTableJsonTree
;
730 bool bTableSelection
= false;
732 if (mpMarkedObj
&& mpMarkedObj
->GetObjIdentifier() == OBJ_TABLE
)
734 auto& rTableObject
= dynamic_cast<sdr::table::SdrTableObj
&>(*mpMarkedObj
);
735 bTableSelection
= rTableObject
.createTableEdgesJson(aTableJsonTree
);
737 if (GetMarkedObjectCount())
739 SdrMark
* pM
= GetSdrMarkByIndex(0);
740 SdrObject
* pO
= pM
->GetMarkedSdrObj();
741 tools::Long nRotAngle
= pO
->GetRotateAngle();
742 // true if we are dealing with a RotGrfFlyFrame
743 // (SwVirtFlyDrawObj with a SwGrfNode)
744 bool bWriterGraphic
= pO
->HasLimitedRotation();
751 OStringBuffer aExtraInfo
;
753 aExtraInfo
.append("{\"id\":\"");
754 aExtraInfo
.append(OString::number(reinterpret_cast<sal_IntPtr
>(pO
)));
755 aExtraInfo
.append("\",\"type\":");
756 aExtraInfo
.append(OString::number(pO
->GetObjIdentifier()));
760 aExtraInfo
.append(", \"isWriterGraphic\": true");
764 LokChartHelper
aChartHelper(pViewShell
);
765 css::uno::Reference
<css::frame::XController
>& xChartController
= aChartHelper
.GetXController();
766 css::uno::Reference
<css::view::XSelectionSupplier
> xSelectionSupplier( xChartController
, uno::UNO_QUERY
);
767 if (xSelectionSupplier
.is())
769 uno::Any aSel
= xSelectionSupplier
->getSelection();
773 OString
aObjectCID(aValue
.getStr(), aValue
.getLength(), osl_getThreadTextEncoding());
774 const std::vector
<OString
> aProps
{"Draggable", "Resizable", "Rotatable"};
775 for (const auto& rProp
: aProps
)
777 sal_Int32 nPos
= aObjectCID
.indexOf(rProp
);
778 if (nPos
== -1) continue;
779 nPos
+= rProp
.getLength() + 1; // '='
780 if (aExtraInfo
.getLength() > 2) // != "{ "
781 aExtraInfo
.append(", ");
782 aExtraInfo
.append("\"is");
783 aExtraInfo
.append(rProp
);
784 aExtraInfo
.append("\": ");
785 aExtraInfo
.append(OString::boolean(aObjectCID
[nPos
] == '1'));
788 OUString sDragMethod
= lcl_getDragMethodServiceName(aValue
);
789 if (sDragMethod
== "PieSegmentDragging")
791 // old initial offset inside the CID returned by xSelectionSupplier->getSelection()
792 // after a pie segment dragging; using SdrObject::GetName for getting a CID with the updated offset
793 aValue
= pO
->GetName();
794 OUString sDragParameters
= lcl_getDragParameterString(aValue
);
795 if (!sDragParameters
.isEmpty())
797 aExtraInfo
.append(", \"dragInfo\": { ");
798 aExtraInfo
.append("\"dragMethod\": \"");
799 aExtraInfo
.append(sDragMethod
.toUtf8());
800 aExtraInfo
.append("\"");
803 sal_Int32 nStartIndex
= 0;
804 std::array
<int, 5> aDragParameters
;
805 for (auto& rParam
: aDragParameters
)
807 sParam
= sDragParameters
.getToken(0, ',', nStartIndex
);
808 if (sParam
.isEmpty())
810 rParam
= sParam
.toInt32();
813 // initial offset in %
814 if (aDragParameters
[0] < 0)
815 aDragParameters
[0] = 0;
816 else if (aDragParameters
[0] > 100)
817 aDragParameters
[0] = 100;
819 aExtraInfo
.append(", \"initialOffset\": ");
820 aExtraInfo
.append(OString::number(aDragParameters
[0]));
822 // drag direction constraint
823 Point
aMinPos(aDragParameters
[1], aDragParameters
[2]);
824 Point
aMaxPos(aDragParameters
[3], aDragParameters
[4]);
825 Point aDragDirection
= aMaxPos
- aMinPos
;
826 aDragDirection
= OutputDevice::LogicToLogic(aDragDirection
, MapMode(MapUnit::Map100thMM
), MapMode(MapUnit::MapTwip
));
828 aExtraInfo
.append(", \"dragDirection\": [");
829 aExtraInfo
.append(aDragDirection
.toString());
830 aExtraInfo
.append("]");
832 // polygon approximating the pie segment or donut segment
833 if (pO
->GetObjIdentifier() == OBJ_PATHFILL
)
835 const basegfx::B2DPolyPolygon
aPolyPolygon(pO
->TakeXorPoly());
836 if (aPolyPolygon
.count() == 1)
838 const basegfx::B2DPolygon aPolygon
= aPolyPolygon
.getB2DPolygon(0);
839 if (sal_uInt32 nPolySize
= aPolygon
.count())
841 const vcl::Window
* pWin
= dynamic_cast<const vcl::Window
*>(this->GetFirstOutputDevice());
842 const vcl::Window
* pViewShellWindow
= pViewShell
->GetEditWindowForActiveOLEObj();
843 if (pWin
&& pViewShellWindow
&& pViewShellWindow
->IsAncestorOf(*pWin
))
845 // in the following code escaping sequences used inside raw literal strings
846 // are for making them understandable by the JSON parser
848 Point aOffsetPx
= pWin
->GetOffsetPixelFrom(*pViewShellWindow
);
849 Point aLogicOffset
= pWin
->PixelToLogic(aOffsetPx
);
850 OString
sPolygonElem("<polygon points=\\\"");
851 for (sal_uInt32 nIndex
= 0; nIndex
< nPolySize
; ++nIndex
)
853 const basegfx::B2DPoint aB2Point
= aPolygon
.getB2DPoint(nIndex
);
854 Point
aPoint(aB2Point
.getX(), aB2Point
.getY());
855 aPoint
.Move(aLogicOffset
.getX(), aLogicOffset
.getY());
858 sPolygonElem
+= aPoint
.toString();
860 sPolygonElem
+= R
"elem(\" style
=\"stroke
: none
; fill
: rgb(114,159,207); fill
-opacity
: 0.8\"/>)elem
";
862 aSelection = OutputDevice::LogicToLogic(aSelection, MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM));
864 OString sSVGElem = R"elem(<svg version
=\"1.2\" width
=\")elem
" +
865 OString::number(aSelection.GetWidth() / 100.0) +
866 R"elem(mm
\" height
=\")elem
" +
867 OString::number(aSelection.GetHeight() / 100.0) +
868 R"elem(mm
\" viewBox
=\")elem
" +
869 aSelection.toString() +
870 R"elem(\" preserveAspectRatio
=\"xMidYMid
\" xmlns
=\"http
://www.w3.org/2000/svg\">)elem";
872 aExtraInfo
.append(", \"svg\": \"");
873 aExtraInfo
.append(sSVGElem
);
874 aExtraInfo
.append("\\n ");
875 aExtraInfo
.append(sPolygonElem
);
876 aExtraInfo
.append("\\n</svg>");
877 aExtraInfo
.append("\""); // svg
882 aExtraInfo
.append("}"); // dragInfo
888 aExtraInfo
.append("}");
890 sSelectionText
= aSelection
.toString() +
891 ", " + OString::number(nRotAngle
);
892 if (!aExtraInfo
.isEmpty())
894 sSelectionText
+= ", " + aExtraInfo
.makeStringAndClear();
898 if (sSelectionText
.isEmpty())
899 sSelectionText
= "EMPTY";
903 boost::property_tree::ptree aTableRectangle
;
904 aTableRectangle
.put("x", aSelection
.Left());
905 aTableRectangle
.put("y", aSelection
.Top());
906 aTableRectangle
.put("width", aSelection
.GetWidth());
907 aTableRectangle
.put("height", aSelection
.GetHeight());
908 aTableJsonTree
.push_back(std::make_pair("rectangle", aTableRectangle
));
910 std::stringstream aStream
;
911 boost::property_tree::write_json(aStream
, aTableJsonTree
);
912 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED
, aStream
.str().c_str());
916 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED
, "{}");
921 // Another shell wants to know about our existing
923 if (pViewShell
!= pOtherShell
)
924 SfxLokHelper::notifyOtherView(pViewShell
, pOtherShell
, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION
, "selection", sSelectionText
);
928 // We have a new selection, so both pViewShell and the
929 // other views want to know about it.
930 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_GRAPHIC_SELECTION
, sSelectionText
.getStr());
931 SfxLokHelper::notifyOtherViews(pViewShell
, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION
, "selection", sSelectionText
);
936 void SdrMarkView::SetMarkHandles(SfxViewShell
* pOtherShell
)
938 // remember old focus handle values to search for it again
939 const SdrHdl
* pSaveOldFocusHdl
= maHdlList
.GetFocusHdl();
940 bool bSaveOldFocus(false);
941 sal_uInt32
nSavePolyNum(0), nSavePointNum(0);
942 SdrHdlKind
eSaveKind(SdrHdlKind::Move
);
943 SdrObject
* pSaveObj
= nullptr;
945 mpMarkingSubSelectionOverlay
.reset();
948 && pSaveOldFocusHdl
->GetObj()
949 && dynamic_cast<const SdrPathObj
*>(pSaveOldFocusHdl
->GetObj()) != nullptr
950 && (pSaveOldFocusHdl
->GetKind() == SdrHdlKind::Poly
|| pSaveOldFocusHdl
->GetKind() == SdrHdlKind::BezierWeight
))
952 bSaveOldFocus
= true;
953 nSavePolyNum
= pSaveOldFocusHdl
->GetPolyNum();
954 nSavePointNum
= pSaveOldFocusHdl
->GetPointNum();
955 pSaveObj
= pSaveOldFocusHdl
->GetObj();
956 eSaveKind
= pSaveOldFocusHdl
->GetKind();
959 // delete/clear all handles. This will always be done, even with areMarkHandlesHidden()
961 maHdlList
.SetRotateShear(meDragMode
==SdrDragMode::Rotate
);
962 maHdlList
.SetDistortShear(meDragMode
==SdrDragMode::Shear
);
966 // are handles enabled at all? Create only then
967 if(areMarkHandlesHidden())
970 // There can be multiple mark views, but we're only interested in the one that has a window associated.
971 const bool bTiledRendering
= comphelper::LibreOfficeKit::isActive() && GetFirstOutputDevice() && GetFirstOutputDevice()->GetOutDevType() == OUTDEV_WINDOW
;
973 const size_t nMarkCount
=GetMarkedObjectCount();
974 bool bStdDrag
=meDragMode
==SdrDragMode::Move
;
975 bool bSingleTextObjMark
=false;
976 bool bLimitedRotation(false);
980 mpMarkedObj
=GetMarkedObjectByIndex(0);
982 if(nullptr != mpMarkedObj
)
985 dynamic_cast<const SdrTextObj
*>( mpMarkedObj
) != nullptr &&
986 static_cast<SdrTextObj
*>(mpMarkedObj
)->IsTextFrame();
988 // RotGrfFlyFrame: we may have limited rotation
989 bLimitedRotation
= SdrDragMode::Rotate
== meDragMode
&& mpMarkedObj
->HasLimitedRotation();
993 bool bFrmHdl
=ImpIsFrameHandles();
997 mpMarkedPV
=GetSdrPageViewOfMarkedByIndex(0);
999 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
&& (mpMarkedPV
!=nullptr || !bFrmHdl
); ++nMarkNum
)
1001 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
1003 if (mpMarkedPV
!=pM
->GetPageView())
1010 SfxViewShell
* pViewShell
= GetSfxViewShell();
1012 // check if text edit or ole is active and handles need to be suppressed. This may be the case
1013 // when a single object is selected
1014 // Using a strict return statement is okay here; no handles means *no* handles.
1017 // formerly #i33755#: If TextEdit is active the EditEngine will directly paint
1018 // to the window, so suppress Overlay and handles completely; a text frame for
1019 // the active text edit will be painted by the repaint mechanism in
1020 // SdrObjEditView::ImpPaintOutlinerView in this case. This needs to be reworked
1022 // Also formerly #122142#: Pretty much the same for SdrCaptionObj's in calc.
1023 if(static_cast<SdrView
*>(this)->IsTextEdit())
1025 const SdrTextObj
* pSdrTextObj
= dynamic_cast< const SdrTextObj
* >(mpMarkedObj
);
1027 if (pSdrTextObj
&& pSdrTextObj
->IsInEditMode())
1029 if (!bTiledRendering
)
1034 // formerly #i118524#: if inplace activated OLE is selected, suppress handles
1035 const SdrOle2Obj
* pSdrOle2Obj
= dynamic_cast< const SdrOle2Obj
* >(mpMarkedObj
);
1037 if(pSdrOle2Obj
&& (pSdrOle2Obj
->isInplaceActive() || pSdrOle2Obj
->isUiActive()))
1042 if (!maSubSelectionList
.empty())
1044 mpMarkingSubSelectionOverlay
= std::make_unique
<MarkingSubSelectionOverlay
>(*this, maSubSelectionList
);
1048 tools::Rectangle
aRect(GetMarkedObjRect());
1050 if (bTiledRendering
&& pViewShell
)
1052 SetMarkHandlesForLOKit(aRect
, pOtherShell
);
1057 if(!aRect
.IsEmpty())
1059 // otherwise nothing is found
1060 const size_t nSiz0(maHdlList
.GetHdlCount());
1062 if( bSingleTextObjMark
)
1064 mpMarkedObj
->AddToHdlList(maHdlList
);
1068 const bool bWdt0(aRect
.Left() == aRect
.Right());
1069 const bool bHgt0(aRect
.Top() == aRect
.Bottom());
1073 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopLeft(), SdrHdlKind::UpperLeft
));
1075 else if (!bStdDrag
&& (bWdt0
|| bHgt0
))
1077 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopLeft(), SdrHdlKind::UpperLeft
));
1078 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.BottomRight(), SdrHdlKind::LowerRight
));
1082 if (!bWdt0
&& !bHgt0
)
1084 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopLeft(), SdrHdlKind::UpperLeft
));
1087 if (!bLimitedRotation
&& !bHgt0
)
1089 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopCenter(), SdrHdlKind::Upper
));
1092 if (!bWdt0
&& !bHgt0
)
1094 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.TopRight(), SdrHdlKind::UpperRight
));
1097 if (!bLimitedRotation
&& !bWdt0
)
1099 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.LeftCenter(), SdrHdlKind::Left
));
1102 if (!bLimitedRotation
&& !bWdt0
)
1104 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.RightCenter(), SdrHdlKind::Right
));
1107 if (!bWdt0
&& !bHgt0
)
1109 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.BottomLeft(), SdrHdlKind::LowerLeft
));
1112 if (!bLimitedRotation
&& !bHgt0
)
1114 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.BottomCenter(), SdrHdlKind::Lower
));
1117 if (!bWdt0
&& !bHgt0
)
1119 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(aRect
.BottomRight(), SdrHdlKind::LowerRight
));
1124 const size_t nSiz1(maHdlList
.GetHdlCount());
1126 // moved setting the missing parameters at SdrHdl here from the
1127 // single loop above (bSingleTextObjMark), this was missing all
1128 // the time. Setting SdrObject is now required to correctly get
1129 // the View-Dependent evtl. GridOffset adapted
1130 for (size_t i
=nSiz0
; i
<nSiz1
; ++i
)
1132 SdrHdl
* pHdl
=maHdlList
.GetHdl(i
);
1133 pHdl
->SetObj(mpMarkedObj
);
1134 pHdl
->SetPageView(mpMarkedPV
);
1135 pHdl
->SetObjHdlNum(sal_uInt16(i
-nSiz0
));
1143 // moved crop handling to non-frame part and the handle creation to SdrGrafObj
1144 if(1 == nMarkCount
&& mpMarkedObj
&& SdrDragMode::Crop
== meDragMode
)
1146 // Default addCropHandles from SdrObject does nothing. When pMarkedObj is SdrGrafObj, previous
1147 // behaviour occurs (code in svx/source/svdraw/svdograf.cxx). When pMarkedObj is SwVirtFlyDrawObj
1148 // writer takes the responsibility of adding handles (code in sw/source/core/draw/dflyobj.cxx)
1149 const size_t nSiz0(maHdlList
.GetHdlCount());
1150 mpMarkedObj
->addCropHandles(maHdlList
);
1151 const size_t nSiz1(maHdlList
.GetHdlCount());
1153 // Was missing: Set infos at SdrCropHdl
1154 for (size_t i
=nSiz0
; i
<nSiz1
; ++i
)
1156 SdrHdl
* pHdl
=maHdlList
.GetHdl(i
);
1157 pHdl
->SetObj(mpMarkedObj
);
1158 pHdl
->SetPageView(mpMarkedPV
);
1159 pHdl
->SetObjHdlNum(sal_uInt16(i
-nSiz0
));
1167 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
)
1169 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
1170 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
1171 SdrPageView
* pPV
=pM
->GetPageView();
1172 const size_t nSiz0
=maHdlList
.GetHdlCount();
1173 pObj
->AddToHdlList(maHdlList
);
1174 const size_t nSiz1
=maHdlList
.GetHdlCount();
1175 bool bPoly
=pObj
->IsPolyObj();
1176 const SdrUShortCont
& rMrkPnts
= pM
->GetMarkedPoints();
1177 for (size_t i
=nSiz0
; i
<nSiz1
; ++i
)
1179 SdrHdl
* pHdl
=maHdlList
.GetHdl(i
);
1181 pHdl
->SetPageView(pPV
);
1182 pHdl
->SetObjHdlNum(sal_uInt16(i
-nSiz0
));
1186 bool bSelected
= rMrkPnts
.find( sal_uInt16(i
-nSiz0
) ) != rMrkPnts
.end();
1187 pHdl
->SetSelected(bSelected
);
1188 if (mbPlusHdlAlways
|| bSelected
)
1190 SdrHdlList
plusList(nullptr);
1191 pObj
->AddToPlusHdlList(plusList
, *pHdl
);
1192 sal_uInt32 nPlusHdlCnt
=plusList
.GetHdlCount();
1193 for (sal_uInt32 nPlusNum
=0; nPlusNum
<nPlusHdlCnt
; nPlusNum
++)
1195 SdrHdl
* pPlusHdl
=plusList
.GetHdl(nPlusNum
);
1196 pPlusHdl
->SetObj(pObj
);
1197 pPlusHdl
->SetPageView(pPV
);
1198 pPlusHdl
->SetPlusHdl(true);
1200 plusList
.MoveTo(maHdlList
);
1208 // GluePoint handles
1209 for (size_t nMarkNum
=0; nMarkNum
<nMarkCount
; ++nMarkNum
)
1211 const SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
1212 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
1213 const SdrGluePointList
* pGPL
=pObj
->GetGluePointList();
1217 SdrPageView
* pPV
=pM
->GetPageView();
1218 const SdrUShortCont
& rMrkGlue
=pM
->GetMarkedGluePoints();
1219 for (sal_uInt16 nId
: rMrkGlue
)
1221 //nNum changed to nNumGP because already used in for loop
1222 sal_uInt16 nNumGP
=pGPL
->FindGluePoint(nId
);
1223 if (nNumGP
!=SDRGLUEPOINT_NOTFOUND
)
1225 const SdrGluePoint
& rGP
=(*pGPL
)[nNumGP
];
1226 Point
aPos(rGP
.GetAbsolutePos(*pObj
));
1227 std::unique_ptr
<SdrHdl
> pGlueHdl(new SdrHdl(aPos
,SdrHdlKind::Glue
));
1228 pGlueHdl
->SetObj(pObj
);
1229 pGlueHdl
->SetPageView(pPV
);
1230 pGlueHdl
->SetObjHdlNum(nId
);
1231 maHdlList
.AddHdl(std::move(pGlueHdl
));
1236 // rotation point/axis of reflection
1237 if(!bLimitedRotation
)
1239 AddDragModeHdl(meDragMode
);
1245 // add custom handles (used by other apps, e.g. AnchorPos)
1248 // try to restore focus handle index from remembered values
1252 for(size_t a
= 0; a
< maHdlList
.GetHdlCount(); ++a
)
1254 SdrHdl
* pCandidate
= maHdlList
.GetHdl(a
);
1256 if(pCandidate
->GetObj()
1257 && pCandidate
->GetObj() == pSaveObj
1258 && pCandidate
->GetKind() == eSaveKind
1259 && pCandidate
->GetPolyNum() == nSavePolyNum
1260 && pCandidate
->GetPointNum() == nSavePointNum
)
1262 maHdlList
.SetFocusHdl(pCandidate
);
1268 void SdrMarkView::AddCustomHdl()
1270 // add custom handles (used by other apps, e.g. AnchorPos)
1273 void SdrMarkView::SetDragMode(SdrDragMode eMode
)
1275 SdrDragMode eMode0
=meDragMode
;
1277 if (meDragMode
==SdrDragMode::Resize
) meDragMode
=SdrDragMode::Move
;
1278 if (meDragMode
!=eMode0
) {
1280 SetMarkHandles(nullptr);
1282 if (AreObjectsMarked()) MarkListHasChanged();
1287 void SdrMarkView::AddDragModeHdl(SdrDragMode eMode
)
1291 case SdrDragMode::Rotate
:
1293 // add rotation center
1294 maHdlList
.AddHdl(std::make_unique
<SdrHdl
>(maRef1
, SdrHdlKind::Ref1
));
1297 case SdrDragMode::Mirror
:
1299 // add axis of reflection
1300 std::unique_ptr
<SdrHdl
> pHdl3(new SdrHdl(maRef2
, SdrHdlKind::Ref2
));
1301 std::unique_ptr
<SdrHdl
> pHdl2(new SdrHdl(maRef1
, SdrHdlKind::Ref1
));
1302 std::unique_ptr
<SdrHdl
> pHdl1(new SdrHdlLine(*pHdl2
, *pHdl3
, SdrHdlKind::MirrorAxis
));
1304 pHdl1
->SetObjHdlNum(1); // for sorting
1305 pHdl2
->SetObjHdlNum(2); // for sorting
1306 pHdl3
->SetObjHdlNum(3); // for sorting
1308 maHdlList
.AddHdl(std::move(pHdl1
)); // line comes first, so it is the last in HitTest
1309 maHdlList
.AddHdl(std::move(pHdl2
));
1310 maHdlList
.AddHdl(std::move(pHdl3
));
1314 case SdrDragMode::Transparence
:
1316 // add interactive transparency handle
1317 const size_t nMarkCount
= GetMarkedObjectCount();
1320 SdrObject
* pObj
= GetMarkedObjectByIndex(0);
1321 SdrModel
* pModel
= GetModel();
1322 const SfxItemSet
& rSet
= pObj
->GetMergedItemSet();
1324 if(SfxItemState::SET
!= rSet
.GetItemState(XATTR_FILLFLOATTRANSPARENCE
, false))
1326 // add this item, it's not yet there
1327 XFillFloatTransparenceItem
aNewItem(rSet
.Get(XATTR_FILLFLOATTRANSPARENCE
));
1328 XGradient aGrad
= aNewItem
.GetGradientValue();
1330 aNewItem
.SetEnabled(true);
1331 aGrad
.SetStartIntens(100);
1332 aGrad
.SetEndIntens(100);
1333 aNewItem
.SetGradientValue(aGrad
);
1335 // add undo to allow user to take back this step
1336 if( pModel
->IsUndoEnabled() )
1338 pModel
->BegUndo(SvxResId(SIP_XA_FILLTRANSPARENCE
));
1339 pModel
->AddUndo(pModel
->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
1343 SfxItemSet
aNewSet(pModel
->GetItemPool());
1344 aNewSet
.Put(aNewItem
);
1345 pObj
->SetMergedItemSetAndBroadcast(aNewSet
);
1348 // set values and transform to vector set
1349 GradTransVector aGradTransVector
;
1350 GradTransGradient aGradTransGradient
;
1352 aGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLFLOATTRANSPARENCE
).GetGradientValue();
1353 GradTransformer::GradToVec(aGradTransGradient
, aGradTransVector
, pObj
);
1356 const Point
aTmpPos1(basegfx::fround(aGradTransVector
.maPositionA
.getX()), basegfx::fround(aGradTransVector
.maPositionA
.getY()));
1357 const Point
aTmpPos2(basegfx::fround(aGradTransVector
.maPositionB
.getX()), basegfx::fround(aGradTransVector
.maPositionB
.getY()));
1358 std::unique_ptr
<SdrHdlColor
> pColHdl1(new SdrHdlColor(aTmpPos1
, aGradTransVector
.aCol1
, SDR_HANDLE_COLOR_SIZE_NORMAL
, true));
1359 std::unique_ptr
<SdrHdlColor
> pColHdl2(new SdrHdlColor(aTmpPos2
, aGradTransVector
.aCol2
, SDR_HANDLE_COLOR_SIZE_NORMAL
, true));
1360 std::unique_ptr
<SdrHdlGradient
> pGradHdl(new SdrHdlGradient(aTmpPos1
, aTmpPos2
, false));
1361 DBG_ASSERT(pColHdl1
&& pColHdl2
&& pGradHdl
, "Could not get all necessary handles!");
1364 pGradHdl
->SetColorHandles(pColHdl1
.get(), pColHdl2
.get());
1365 pGradHdl
->SetObj(pObj
);
1366 pColHdl1
->SetColorChangeHdl(LINK(pGradHdl
.get(), SdrHdlGradient
, ColorChangeHdl
));
1367 pColHdl2
->SetColorChangeHdl(LINK(pGradHdl
.get(), SdrHdlGradient
, ColorChangeHdl
));
1370 maHdlList
.AddHdl(std::move(pColHdl1
));
1371 maHdlList
.AddHdl(std::move(pColHdl2
));
1372 maHdlList
.AddHdl(std::move(pGradHdl
));
1376 case SdrDragMode::Gradient
:
1378 // add interactive gradient handle
1379 const size_t nMarkCount
= GetMarkedObjectCount();
1382 SdrObject
* pObj
= GetMarkedObjectByIndex(0);
1383 const SfxItemSet
& rSet
= pObj
->GetMergedItemSet();
1384 drawing::FillStyle eFillStyle
= rSet
.Get(XATTR_FILLSTYLE
).GetValue();
1386 if(eFillStyle
== drawing::FillStyle_GRADIENT
)
1388 // set values and transform to vector set
1389 GradTransVector aGradTransVector
;
1390 GradTransGradient aGradTransGradient
;
1391 Size
aHdlSize(15, 15);
1393 aGradTransGradient
.aGradient
= rSet
.Get(XATTR_FILLGRADIENT
).GetGradientValue();
1394 GradTransformer::GradToVec(aGradTransGradient
, aGradTransVector
, pObj
);
1397 const Point
aTmpPos1(basegfx::fround(aGradTransVector
.maPositionA
.getX()), basegfx::fround(aGradTransVector
.maPositionA
.getY()));
1398 const Point
aTmpPos2(basegfx::fround(aGradTransVector
.maPositionB
.getX()), basegfx::fround(aGradTransVector
.maPositionB
.getY()));
1399 std::unique_ptr
<SdrHdlColor
> pColHdl1(new SdrHdlColor(aTmpPos1
, aGradTransVector
.aCol1
, aHdlSize
, false));
1400 std::unique_ptr
<SdrHdlColor
> pColHdl2(new SdrHdlColor(aTmpPos2
, aGradTransVector
.aCol2
, aHdlSize
, false));
1401 std::unique_ptr
<SdrHdlGradient
> pGradHdl(new SdrHdlGradient(aTmpPos1
, aTmpPos2
, true));
1402 DBG_ASSERT(pColHdl1
&& pColHdl2
&& pGradHdl
, "Could not get all necessary handles!");
1405 pGradHdl
->SetColorHandles(pColHdl1
.get(), pColHdl2
.get());
1406 pGradHdl
->SetObj(pObj
);
1407 pColHdl1
->SetColorChangeHdl(LINK(pGradHdl
.get(), SdrHdlGradient
, ColorChangeHdl
));
1408 pColHdl2
->SetColorChangeHdl(LINK(pGradHdl
.get(), SdrHdlGradient
, ColorChangeHdl
));
1411 maHdlList
.AddHdl(std::move(pColHdl1
));
1412 maHdlList
.AddHdl(std::move(pColHdl2
));
1413 maHdlList
.AddHdl(std::move(pGradHdl
));
1418 case SdrDragMode::Crop
:
1427 /** handle mouse over effects for handles */
1428 bool SdrMarkView::MouseMove(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
1430 if(maHdlList
.GetHdlCount())
1432 SdrHdl
* pMouseOverHdl
= nullptr;
1433 if( !rMEvt
.IsLeaveWindow() && pWin
)
1435 Point
aMDPos( pWin
->PixelToLogic( rMEvt
.GetPosPixel() ) );
1436 pMouseOverHdl
= PickHandle(aMDPos
);
1439 // notify last mouse over handle that he lost the mouse
1440 const size_t nHdlCount
= maHdlList
.GetHdlCount();
1442 for(size_t nHdl
= 0; nHdl
< nHdlCount
; ++nHdl
)
1444 SdrHdl
* pCurrentHdl
= GetHdl(nHdl
);
1445 if( pCurrentHdl
->mbMouseOver
)
1447 if( pCurrentHdl
!= pMouseOverHdl
)
1449 pCurrentHdl
->mbMouseOver
= false;
1450 pCurrentHdl
->onMouseLeave();
1456 // notify current mouse over handle
1459 pMouseOverHdl
->mbMouseOver
= true;
1460 pMouseOverHdl
->onMouseEnter(rMEvt
);
1463 return SdrSnapView::MouseMove(rMEvt
, pWin
);
1466 bool SdrMarkView::RequestHelp(const HelpEvent
& rHEvt
)
1468 if (maHdlList
.GetHdlCount())
1470 const size_t nHdlCount
= maHdlList
.GetHdlCount();
1472 for (size_t nHdl
= 0; nHdl
< nHdlCount
; ++nHdl
)
1474 SdrHdl
* pCurrentHdl
= GetHdl(nHdl
);
1475 if (pCurrentHdl
->mbMouseOver
)
1477 pCurrentHdl
->onHelpRequest();
1482 return SdrSnapView::RequestHelp(rHEvt
);
1485 void SdrMarkView::ForceRefToMarked()
1489 case SdrDragMode::Rotate
:
1491 tools::Rectangle
aR(GetMarkedObjRect());
1492 maRef1
= aR
.Center();
1497 case SdrDragMode::Mirror
:
1499 // first calculate the length of the axis of reflection
1500 tools::Long nOutMin
=0;
1501 tools::Long nOutMax
=0;
1502 tools::Long nMinLen
=0;
1503 tools::Long nObjDst
=0;
1504 tools::Long nOutHgt
=0;
1505 OutputDevice
* pOut
=GetFirstOutputDevice();
1506 if (pOut
!=nullptr) {
1507 // minimum length: 50 pixels
1508 nMinLen
=pOut
->PixelToLogic(Size(0,50)).Height();
1509 // 20 pixels distance to the Obj for the reference point
1510 nObjDst
=pOut
->PixelToLogic(Size(0,20)).Height();
1512 // margin = minimum length = 10 pixels
1513 tools::Long nDst
=pOut
->PixelToLogic(Size(0,10)).Height();
1514 nOutMin
=-pOut
->GetMapMode().GetOrigin().Y();
1515 nOutMax
=pOut
->GetOutputSize().Height()-1+nOutMin
;
1518 // absolute minimum length, however, is 10 pixels
1519 if (nOutMax
-nOutMin
<nDst
) {
1522 nOutMin
-=(nDst
+1)/2;
1523 nOutMax
=nOutMin
+nDst
;
1525 nOutHgt
=nOutMax
-nOutMin
;
1526 // otherwise minimum length = 1/4 OutHgt
1527 tools::Long nTemp
=nOutHgt
/4;
1528 if (nTemp
>nMinLen
) nMinLen
=nTemp
;
1531 tools::Rectangle
aR(GetMarkedObjBoundRect());
1532 Point
aCenter(aR
.Center());
1533 tools::Long nMarkHgt
=aR
.GetHeight()-1;
1534 tools::Long nHgt
=nMarkHgt
+nObjDst
*2; // 20 pixels overlapping above and below
1535 if (nHgt
<nMinLen
) nHgt
=nMinLen
; // minimum length 50 pixels or 1/4 OutHgt, respectively
1537 tools::Long nY1
=aCenter
.Y()-(nHgt
+1)/2;
1538 tools::Long nY2
=nY1
+nHgt
;
1540 if (pOut
!=nullptr && nMinLen
>nOutHgt
) nMinLen
=nOutHgt
; // TODO: maybe shorten this a little
1542 if (pOut
!=nullptr) { // now move completely into the visible area
1545 if (nY2
<nY1
+nMinLen
) nY2
=nY1
+nMinLen
;
1549 if (nY1
>nY2
-nMinLen
) nY1
=nY2
-nMinLen
;
1553 maRef1
.setX(aCenter
.X() );
1555 maRef2
.setX(aCenter
.X() );
1561 case SdrDragMode::Transparence
:
1562 case SdrDragMode::Gradient
:
1563 case SdrDragMode::Crop
:
1565 tools::Rectangle
aRect(GetMarkedObjBoundRect());
1566 maRef1
= aRect
.TopLeft();
1567 maRef2
= aRect
.BottomRight();
1574 void SdrMarkView::SetRef1(const Point
& rPt
)
1576 if(meDragMode
== SdrDragMode::Rotate
|| meDragMode
== SdrDragMode::Mirror
)
1579 SdrHdl
* pH
= maHdlList
.GetHdl(SdrHdlKind::Ref1
);
1585 void SdrMarkView::SetRef2(const Point
& rPt
)
1587 if(meDragMode
== SdrDragMode::Mirror
)
1590 SdrHdl
* pH
= maHdlList
.GetHdl(SdrHdlKind::Ref2
);
1596 SfxViewShell
* SdrMarkView::GetSfxViewShell() const
1598 return SfxViewShell::Current();
1601 void SdrMarkView::CheckMarked()
1603 for (size_t nm
=GetMarkedObjectCount(); nm
>0;) {
1605 SdrMark
* pM
= GetSdrMarkByIndex(nm
);
1606 SdrObject
* pObj
= pM
->GetMarkedSdrObj();
1607 SdrPageView
* pPV
= pM
->GetPageView();
1608 bool bRaus
= !pObj
|| !pPV
->IsObjMarkable(pObj
);
1611 GetMarkedObjectListWriteAccess().DeleteMark(nm
);
1615 if (!IsGluePointEditMode()) { // selected glue points only in GlueEditMode
1616 SdrUShortCont
& rPts
= pM
->GetMarkedGluePoints();
1622 // at least reset the remembered BoundRect to prevent handle
1623 // generation if bForceFrameHandles is TRUE.
1624 mbMarkedObjRectDirty
= true;
1627 void SdrMarkView::SetMarkRects()
1629 SdrPageView
* pPV
= GetSdrPageView();
1633 pPV
->SetHasMarkedObj(GetMarkedObjectList().TakeSnapRect(pPV
, pPV
->MarkSnap()));
1634 GetMarkedObjectList().TakeBoundRect(pPV
, pPV
->MarkBound());
1638 void SdrMarkView::SetFrameHandles(bool bOn
)
1640 if (bOn
!=mbForceFrameHandles
) {
1641 bool bOld
=ImpIsFrameHandles();
1642 mbForceFrameHandles
=bOn
;
1643 bool bNew
=ImpIsFrameHandles();
1646 MarkListHasChanged();
1651 void SdrMarkView::SetEditMode(SdrViewEditMode eMode
)
1653 if (eMode
==meEditMode
) return;
1655 bool bGlue0
=meEditMode
==SdrViewEditMode::GluePointEdit
;
1656 bool bEdge0
=static_cast<SdrCreateView
*>(this)->IsEdgeTool();
1657 meEditMode0
=meEditMode
;
1659 bool bGlue1
=meEditMode
==SdrViewEditMode::GluePointEdit
;
1660 bool bEdge1
=static_cast<SdrCreateView
*>(this)->IsEdgeTool();
1661 // avoid flickering when switching between GlueEdit and EdgeTool
1662 if (bGlue1
&& !bGlue0
) ImpSetGlueVisible2(bGlue1
);
1663 if (bEdge1
!=bEdge0
) ImpSetGlueVisible3(bEdge1
);
1664 if (!bGlue1
&& bGlue0
) ImpSetGlueVisible2(bGlue1
);
1665 if (bGlue0
&& !bGlue1
) UnmarkAllGluePoints();
1669 bool SdrMarkView::IsObjMarkable(SdrObject
const * pObj
, SdrPageView
const * pPV
) const
1673 if (pObj
->IsMarkProtect() ||
1674 (!mbDesignMode
&& pObj
->IsUnoObj()))
1676 // object not selectable or
1677 // SdrUnoObj not in DesignMode
1681 return pPV
==nullptr || pPV
->IsObjMarkable(pObj
);
1684 bool SdrMarkView::IsMarkedObjHit(const Point
& rPnt
, short nTol
) const
1687 nTol
=ImpGetHitTolLogic(nTol
,nullptr);
1688 for (size_t nm
=0; nm
<GetMarkedObjectCount() && !bRet
; ++nm
) {
1689 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
1690 bRet
= nullptr != CheckSingleSdrObjectHit(rPnt
,sal_uInt16(nTol
),pM
->GetMarkedSdrObj(),pM
->GetPageView(),SdrSearchOptions::NONE
,nullptr);
1695 SdrHdl
* SdrMarkView::PickHandle(const Point
& rPnt
) const
1697 if (mbSomeObjChgdFlag
) { // recalculate handles, if necessary
1698 FlushComeBackTimer();
1700 return maHdlList
.IsHdlListHit(rPnt
);
1703 bool SdrMarkView::MarkObj(const Point
& rPnt
, short nTol
, bool bToggle
, bool bDeep
)
1706 nTol
=ImpGetHitTolLogic(nTol
,nullptr);
1707 SdrSearchOptions nOptions
=SdrSearchOptions::PICKMARKABLE
;
1708 if (bDeep
) nOptions
=nOptions
|SdrSearchOptions::DEEP
;
1709 SdrObject
* pObj
= PickObj(rPnt
, static_cast<sal_uInt16
>(nTol
), pPV
, nOptions
);
1711 bool bUnmark
=bToggle
&& IsObjMarked(pObj
);
1712 MarkObj(pObj
,pPV
,bUnmark
);
1714 return pObj
!= nullptr;
1717 bool SdrMarkView::MarkNextObj(bool bPrev
)
1719 SdrPageView
* pPageView
= GetSdrPageView();
1726 SortMarkedObjects();
1727 const size_t nMarkCount
=GetMarkedObjectCount();
1728 size_t nChgMarkNum
= SAL_MAX_SIZE
; // number of the MarkEntry we want to replace
1729 size_t nSearchObjNum
= bPrev
? 0 : SAL_MAX_SIZE
;
1730 if (nMarkCount
!=0) {
1731 nChgMarkNum
=bPrev
? 0 : nMarkCount
-1;
1732 SdrMark
* pM
=GetSdrMarkByIndex(nChgMarkNum
);
1733 OSL_ASSERT(pM
!=nullptr);
1734 if (pM
->GetMarkedSdrObj() != nullptr)
1735 nSearchObjNum
= pM
->GetMarkedSdrObj()->GetNavigationPosition();
1738 SdrObject
* pMarkObj
=nullptr;
1739 SdrObjList
* pSearchObjList
=pPageView
->GetObjList();
1740 const size_t nObjCount
= pSearchObjList
->GetObjCount();
1742 if (nSearchObjNum
>nObjCount
) nSearchObjNum
=nObjCount
;
1743 while (pMarkObj
==nullptr && ((!bPrev
&& nSearchObjNum
>0) || (bPrev
&& nSearchObjNum
<nObjCount
)))
1747 SdrObject
* pSearchObj
= pSearchObjList
->GetObjectForNavigationPosition(nSearchObjNum
);
1748 if (IsObjMarkable(pSearchObj
,pPageView
))
1750 if (TryToFindMarkedObject(pSearchObj
)==SAL_MAX_SIZE
)
1752 pMarkObj
=pSearchObj
;
1755 if (bPrev
) nSearchObjNum
++;
1764 if (nChgMarkNum
!=SAL_MAX_SIZE
)
1766 GetMarkedObjectListWriteAccess().DeleteMark(nChgMarkNum
);
1768 MarkObj(pMarkObj
,pPageView
); // also calls MarkListHasChanged(), AdjustMarkHdl()
1772 bool SdrMarkView::MarkNextObj(const Point
& rPnt
, short nTol
, bool bPrev
)
1774 SortMarkedObjects();
1775 nTol
=ImpGetHitTolLogic(nTol
,nullptr);
1776 SdrMark
* pTopMarkHit
=nullptr;
1777 SdrMark
* pBtmMarkHit
=nullptr;
1778 size_t nTopMarkHit
=0;
1779 size_t nBtmMarkHit
=0;
1780 // find topmost of the selected objects that is hit by rPnt
1781 const size_t nMarkCount
=GetMarkedObjectCount();
1782 for (size_t nm
=nMarkCount
; nm
>0 && pTopMarkHit
==nullptr;) {
1784 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
1785 if(CheckSingleSdrObjectHit(rPnt
,sal_uInt16(nTol
),pM
->GetMarkedSdrObj(),pM
->GetPageView(),SdrSearchOptions::NONE
,nullptr))
1791 // nothing found, in this case, just select an object
1792 if (pTopMarkHit
==nullptr) return MarkObj(rPnt
,sal_uInt16(nTol
));
1794 SdrObject
* pTopObjHit
=pTopMarkHit
->GetMarkedSdrObj();
1795 SdrObjList
* pObjList
=pTopObjHit
->getParentSdrObjListFromSdrObject();
1796 SdrPageView
* pPV
=pTopMarkHit
->GetPageView();
1797 // find lowermost of the selected objects that is hit by rPnt
1798 // and is placed on the same PageView as pTopMarkHit
1799 for (size_t nm
=0; nm
<nMarkCount
&& pBtmMarkHit
==nullptr; ++nm
) {
1800 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
1801 SdrPageView
* pPV2
=pM
->GetPageView();
1802 if (pPV2
==pPV
&& CheckSingleSdrObjectHit(rPnt
,sal_uInt16(nTol
),pM
->GetMarkedSdrObj(),pPV2
,SdrSearchOptions::NONE
,nullptr))
1808 if (pBtmMarkHit
==nullptr) { pBtmMarkHit
=pTopMarkHit
; nBtmMarkHit
=nTopMarkHit
; }
1809 SdrObject
* pBtmObjHit
=pBtmMarkHit
->GetMarkedSdrObj();
1810 const size_t nObjCount
= pObjList
->GetObjCount();
1812 size_t nSearchBeg(0);
1813 E3dScene
* pScene(nullptr);
1814 SdrObject
* pObjHit(bPrev
? pBtmObjHit
: pTopObjHit
);
1816 nullptr != dynamic_cast< const E3dCompoundObject
* >(pObjHit
);
1819 pScene
= dynamic_cast< E3dScene
* >(pObjHit
->getParentSdrObjectFromSdrObject());
1820 bRemap
= nullptr != pScene
;
1825 sal_uInt32
nOrdNumBtm(pBtmObjHit
->GetOrdNum());
1829 nOrdNumBtm
= pScene
->RemapOrdNum(nOrdNumBtm
);
1832 nSearchBeg
= nOrdNumBtm
+ 1;
1836 sal_uInt32
nOrdNumTop(pTopObjHit
->GetOrdNum());
1840 nOrdNumTop
= pScene
->RemapOrdNum(nOrdNumTop
);
1843 nSearchBeg
= nOrdNumTop
;
1846 size_t no
=nSearchBeg
;
1847 SdrObject
* pFndObj
=nullptr;
1848 while (pFndObj
==nullptr && ((!bPrev
&& no
>0) || (bPrev
&& no
<nObjCount
))) {
1854 pObj
= pObjList
->GetObj(pScene
->RemapOrdNum(no
));
1858 pObj
= pObjList
->GetObj(no
);
1861 if (CheckSingleSdrObjectHit(rPnt
,sal_uInt16(nTol
),pObj
,pPV
,SdrSearchOptions::TESTMARKABLE
,nullptr))
1863 if (TryToFindMarkedObject(pObj
)==SAL_MAX_SIZE
) {
1866 // TODO: for performance reasons set on to Top or Btm, if necessary
1871 if (pFndObj
!=nullptr)
1873 GetMarkedObjectListWriteAccess().DeleteMark(bPrev
?nBtmMarkHit
:nTopMarkHit
);
1874 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pFndObj
,pPV
));
1875 MarkListHasChanged();
1878 return pFndObj
!=nullptr;
1881 void SdrMarkView::MarkObj(const tools::Rectangle
& rRect
, bool bUnmark
)
1884 tools::Rectangle
aR(rRect
);
1885 SdrObjList
* pObjList
;
1887 SdrPageView
* pPV
= GetSdrPageView();
1891 pObjList
=pPV
->GetObjList();
1892 tools::Rectangle
aFrm1(aR
);
1893 const size_t nObjCount
= pObjList
->GetObjCount();
1894 for (size_t nO
=0; nO
<nObjCount
; ++nO
) {
1895 SdrObject
* pObj
=pObjList
->GetObj(nO
);
1896 tools::Rectangle
aRect(pObj
->GetCurrentBoundRect());
1897 if (aFrm1
.IsInside(aRect
)) {
1899 if (IsObjMarkable(pObj
,pPV
))
1901 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pObj
,pPV
));
1905 const size_t nPos
=TryToFindMarkedObject(pObj
);
1906 if (nPos
!=SAL_MAX_SIZE
)
1908 GetMarkedObjectListWriteAccess().DeleteMark(nPos
);
1916 SortMarkedObjects();
1917 MarkListHasChanged();
1924 void collectUIInformation(const SdrObject
* pObj
)
1926 EventDescription aDescription
;
1927 aDescription
.aAction
= "SELECT";
1928 aDescription
.aParent
= "MainWindow";
1929 aDescription
.aKeyWord
= "CurrentApp";
1931 if (!pObj
->GetName().isEmpty())
1932 aDescription
.aParameters
= {{"OBJECT", pObj
->GetName()}};
1934 aDescription
.aParameters
= {{"OBJECT", "Unnamed_Obj_" + OUString::number(pObj
->GetOrdNum())}};
1936 UITestLogger::getInstance().logEvent(aDescription
);
1941 void SdrMarkView::MarkObj(SdrObject
* pObj
, SdrPageView
* pPV
, bool bUnmark
, bool bDoNoSetMarkHdl
,
1942 std::vector
<basegfx::B2DRectangle
> const & rSubSelections
)
1944 if (!(pObj
!=nullptr && pPV
!=nullptr && IsObjMarkable(pObj
, pPV
)))
1950 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pObj
,pPV
));
1951 collectUIInformation(pObj
);
1955 const size_t nPos
=TryToFindMarkedObject(pObj
);
1956 if (nPos
!=SAL_MAX_SIZE
)
1958 GetMarkedObjectListWriteAccess().DeleteMark(nPos
);
1962 maSubSelectionList
= rSubSelections
;
1964 if (!bDoNoSetMarkHdl
) {
1965 MarkListHasChanged();
1970 bool SdrMarkView::IsObjMarked(SdrObject
const * pObj
) const
1972 return TryToFindMarkedObject(pObj
)!=SAL_MAX_SIZE
;
1975 sal_uInt16
SdrMarkView::GetMarkHdlSizePixel() const
1977 return maHdlList
.GetHdlSize()*2+1;
1980 void SdrMarkView::SetMarkHdlSizePixel(sal_uInt16 nSiz
)
1984 if (nSiz
!=maHdlList
.GetHdlSize()) {
1985 maHdlList
.SetHdlSize(nSiz
);
1989 bool SdrMarkView::getPossibleGridOffsetForSdrObject(
1990 basegfx::B2DVector
& rOffset
,
1991 const SdrObject
* pObj
,
1992 const SdrPageView
* pPV
) const
1994 if(nullptr == pObj
|| nullptr == pPV
)
1999 const OutputDevice
* pOutputDevice(GetFirstOutputDevice());
2001 if(nullptr == pOutputDevice
)
2006 const SdrPageWindow
* pSdrPageWindow(pPV
->FindPageWindow(*pOutputDevice
));
2008 if(nullptr == pSdrPageWindow
)
2013 const sdr::contact::ObjectContact
& rObjectContact(pSdrPageWindow
->GetObjectContact());
2015 if(!rObjectContact
.supportsGridOffsets())
2020 const sdr::contact::ViewObjectContact
& rVOC(pObj
->GetViewContact().GetViewObjectContact(
2021 const_cast<sdr::contact::ObjectContact
&>(rObjectContact
)));
2023 rOffset
= rVOC
.getGridOffset();
2025 return !rOffset
.equalZero();
2028 bool SdrMarkView::getPossibleGridOffsetForPosition(
2029 basegfx::B2DVector
& rOffset
,
2030 const basegfx::B2DPoint
& rPoint
,
2031 const SdrPageView
* pPV
) const
2038 const OutputDevice
* pOutputDevice(GetFirstOutputDevice());
2040 if(nullptr == pOutputDevice
)
2045 const SdrPageWindow
* pSdrPageWindow(pPV
->FindPageWindow(*pOutputDevice
));
2047 if(nullptr == pSdrPageWindow
)
2052 const sdr::contact::ObjectContact
& rObjectContact(pSdrPageWindow
->GetObjectContact());
2054 if(!rObjectContact
.supportsGridOffsets())
2059 rObjectContact
.calculateGridOffsetForB2DRange(rOffset
, basegfx::B2DRange(rPoint
));
2061 return !rOffset
.equalZero();
2064 SdrObject
* SdrMarkView::CheckSingleSdrObjectHit(const Point
& rPnt
, sal_uInt16 nTol
, SdrObject
* pObj
, SdrPageView
* pPV
, SdrSearchOptions nOptions
, const SdrLayerIDSet
* pMVisLay
) const
2066 if(((nOptions
& SdrSearchOptions::IMPISMASTER
) && pObj
->IsNotVisibleAsMaster()) || (!pObj
->IsVisible()))
2071 const bool bCheckIfMarkable(nOptions
& SdrSearchOptions::TESTMARKABLE
);
2072 const bool bDeep(nOptions
& SdrSearchOptions::DEEP
);
2073 const bool bOLE(dynamic_cast< const SdrOle2Obj
* >(pObj
) != nullptr);
2074 const bool bTXT(dynamic_cast<const SdrTextObj
*>( pObj
) != nullptr && static_cast<SdrTextObj
*>(pObj
)->IsTextFrame());
2075 SdrObject
* pRet
=nullptr;
2076 tools::Rectangle
aRect(pObj
->GetCurrentBoundRect());
2078 // add possible GridOffset to up-to-now view-independent BoundRect data
2079 basegfx::B2DVector
aGridOffset(0.0, 0.0);
2080 if(getPossibleGridOffsetForSdrObject(aGridOffset
, pObj
, pPV
))
2083 basegfx::fround(aGridOffset
.getX()),
2084 basegfx::fround(aGridOffset
.getY()));
2087 sal_uInt16
nTol2(nTol
);
2089 // double tolerance for OLE, text frames and objects in
2091 if(bOLE
|| bTXT
|| pObj
==static_cast<const SdrObjEditView
*>(this)->GetTextEditObject())
2096 aRect
.AdjustLeft( -nTol2
); // add 1 tolerance for all objects
2097 aRect
.AdjustTop( -nTol2
);
2098 aRect
.AdjustRight(nTol2
);
2099 aRect
.AdjustBottom(nTol2
);
2101 if (aRect
.IsInside(rPnt
))
2103 if (!bCheckIfMarkable
|| IsObjMarkable(pObj
,pPV
))
2105 SdrObjList
* pOL
=pObj
->GetSubList();
2107 if (pOL
!=nullptr && pOL
->GetObjCount()!=0)
2110 // adjustment hit point for virtual objects
2113 if ( auto pVirtObj
= dynamic_cast<const SdrVirtObj
*>( pObj
) )
2115 Point aOffset
= pVirtObj
->GetOffset();
2116 aPnt
.Move( -aOffset
.X(), -aOffset
.Y() );
2119 pRet
=CheckSingleSdrObjectHit(aPnt
,nTol
,pOL
,pPV
,nOptions
,pMVisLay
,pTmpObj
);
2123 if(!pMVisLay
|| pMVisLay
->IsSet(pObj
->GetLayer()))
2125 pRet
= SdrObjectPrimitiveHit(*pObj
, rPnt
, nTol2
, *pPV
, &pPV
->GetVisibleLayers(), false);
2131 if (!bDeep
&& pRet
!=nullptr)
2139 SdrObject
* SdrMarkView::CheckSingleSdrObjectHit(const Point
& rPnt
, sal_uInt16 nTol
, SdrObjList
const * pOL
, SdrPageView
* pPV
, SdrSearchOptions nOptions
, const SdrLayerIDSet
* pMVisLay
, SdrObject
*& rpRootObj
) const
2141 return (*this).CheckSingleSdrObjectHit(rPnt
,nTol
,pOL
,pPV
,nOptions
,pMVisLay
,rpRootObj
,nullptr);
2143 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
2145 SdrObject
* pRet
=nullptr;
2150 nullptr != pOL
->getSdrObjectFromSdrObjList()
2151 && nullptr != dynamic_cast< const E3dScene
* >(pOL
->getSdrObjectFromSdrObjList()));
2152 const E3dScene
* pRemapScene(bRemap
? static_cast< E3dScene
* >(pOL
->getSdrObjectFromSdrObjList()) : nullptr);
2153 const size_t nObjCount(pOL
->GetObjCount());
2154 size_t nObjNum(nObjCount
);
2156 while (pRet
==nullptr && nObjNum
>0)
2163 pObj
= pOL
->GetObj(pRemapScene
->RemapOrdNum(nObjNum
));
2167 pObj
= pOL
->GetObj(nObjNum
);
2169 if (nOptions
& SdrSearchOptions::BEFOREMARK
)
2171 if (pMarkList
!=nullptr)
2173 if ((*pMarkList
).FindObject(pObj
)!=SAL_MAX_SIZE
)
2179 pRet
=CheckSingleSdrObjectHit(rPnt
,nTol
,pObj
,pPV
,nOptions
,pMVisLay
);
2180 if (pRet
!=nullptr) rpRootObj
=pObj
;
2186 SdrObject
* SdrMarkView::PickObj(const Point
& rPnt
, short nTol
, SdrPageView
*& rpPV
, SdrSearchOptions nOptions
) const
2188 return PickObj(rPnt
, nTol
, rpPV
, nOptions
, nullptr);
2191 SdrObject
* SdrMarkView::PickObj(const Point
& rPnt
, short nTol
, SdrPageView
*& rpPV
, SdrSearchOptions nOptions
, SdrObject
** ppRootObj
, bool* pbHitPassDirect
) const
2192 { // TODO: lacks a Pass2,Pass3
2193 SortMarkedObjects();
2194 if (ppRootObj
!=nullptr) *ppRootObj
=nullptr;
2195 if (pbHitPassDirect
!=nullptr) *pbHitPassDirect
=true;
2196 SdrObject
* pRet
= nullptr;
2198 bool bMarked(nOptions
& SdrSearchOptions::MARKED
);
2199 bool bMasters
=!bMarked
&& bool(nOptions
& SdrSearchOptions::ALSOONMASTER
);
2200 // nOptions & SdrSearchOptions::NEXT: n.i.
2201 // nOptions & SdrSearchOptions::PASS2BOUND: n.i.
2202 // nOptions & SdrSearchOptions::PASS3NEAREST// n.i.
2203 if (nTol
<0) nTol
=ImpGetHitTolLogic(nTol
,nullptr);
2204 SdrObject
* pObj
=nullptr;
2205 SdrObject
* pHitObj
=nullptr;
2206 SdrPageView
* pPV
=nullptr;
2207 if (static_cast<const SdrObjEditView
*>(this)->IsTextEditFrameHit(rPnt
)) {
2208 pObj
=static_cast<const SdrObjEditView
*>(this)->GetTextEditObject();
2210 pPV
=static_cast<const SdrObjEditView
*>(this)->GetTextEditPageView();
2213 const size_t nMrkCnt
=GetMarkedObjectCount();
2214 size_t nMrkNum
=nMrkCnt
;
2215 while (pHitObj
==nullptr && nMrkNum
>0) {
2217 SdrMark
* pM
=GetSdrMarkByIndex(nMrkNum
);
2218 pObj
=pM
->GetMarkedSdrObj();
2219 pPV
=pM
->GetPageView();
2220 pHitObj
=CheckSingleSdrObjectHit(rPnt
,nTol
,pObj
,pPV
,nOptions
,nullptr);
2225 pPV
= GetSdrPageView();
2229 SdrPage
* pPage
=pPV
->GetPage();
2230 sal_uInt16 nPgCount
=1;
2232 if(bMasters
&& pPage
->TRG_HasMasterPage())
2236 bool bWholePage(nOptions
& SdrSearchOptions::WHOLEPAGE
);
2237 bool bExtraPassForWholePage
=bWholePage
&& pPage
!=pPV
->GetObjList();
2238 if (bExtraPassForWholePage
) nPgCount
++; // First search in AktObjList, then on the entire page
2239 sal_uInt16 nPgNum
=nPgCount
;
2240 while (pHitObj
==nullptr && nPgNum
>0) {
2241 SdrSearchOptions nTmpOptions
=nOptions
;
2243 const SdrLayerIDSet
* pMVisLay
=nullptr;
2244 SdrObjList
* pObjList
=nullptr;
2245 if (pbHitPassDirect
!=nullptr) *pbHitPassDirect
= true;
2246 if (nPgNum
>=nPgCount
-1 || (bExtraPassForWholePage
&& nPgNum
>=nPgCount
-2))
2248 pObjList
=pPV
->GetObjList();
2249 if (bExtraPassForWholePage
&& nPgNum
==nPgCount
-2) {
2251 if (pbHitPassDirect
!=nullptr) *pbHitPassDirect
= false;
2256 // otherwise MasterPage
2257 SdrPage
& rMasterPage
= pPage
->TRG_GetMasterPage();
2258 pMVisLay
= &pPage
->TRG_GetMasterPageVisibleLayers();
2259 pObjList
= &rMasterPage
;
2261 if (pbHitPassDirect
!=nullptr) *pbHitPassDirect
= false;
2262 nTmpOptions
=nTmpOptions
| SdrSearchOptions::IMPISMASTER
;
2264 pHitObj
=CheckSingleSdrObjectHit(rPnt
,nTol
,pObjList
,pPV
,nTmpOptions
,pMVisLay
,pObj
,&(GetMarkedObjectList()));
2268 if (pHitObj
!=nullptr) {
2269 if (ppRootObj
!=nullptr) *ppRootObj
=pObj
;
2270 if (nOptions
& SdrSearchOptions::DEEP
) pObj
=pHitObj
;
2271 if (nOptions
& SdrSearchOptions::TESTTEXTEDIT
) {
2272 if (!pObj
->HasTextEdit() || pPV
->GetLockedLayers().IsSet(pObj
->GetLayer())) {
2276 if (pObj
!=nullptr && (nOptions
& SdrSearchOptions::TESTMACRO
)) {
2277 SdrObjMacroHitRec aHitRec
;
2280 aHitRec
.pVisiLayer
=&pPV
->GetVisibleLayers();
2281 aHitRec
.pPageView
=pPV
;
2282 if (!pObj
->HasMacro() || !pObj
->IsMacroHit(aHitRec
)) pObj
=nullptr;
2284 if (pObj
!=nullptr) {
2292 bool SdrMarkView::PickMarkedObj(const Point
& rPnt
, SdrObject
*& rpObj
, SdrPageView
*& rpPV
, SdrSearchOptions nOptions
) const
2294 SortMarkedObjects();
2295 const bool bBoundCheckOn2ndPass(nOptions
& SdrSearchOptions::PASS2BOUND
);
2298 const size_t nMarkCount
=GetMarkedObjectCount();
2299 for (size_t nMarkNum
=nMarkCount
; nMarkNum
>0;) {
2301 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
2302 SdrPageView
* pPV
=pM
->GetPageView();
2303 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
2304 if (CheckSingleSdrObjectHit(rPnt
,mnHitTolLog
,pObj
,pPV
,SdrSearchOptions::TESTMARKABLE
,nullptr)) {
2310 if (bBoundCheckOn2ndPass
) {
2311 for (size_t nMarkNum
=nMarkCount
; nMarkNum
>0;) {
2313 SdrMark
* pM
=GetSdrMarkByIndex(nMarkNum
);
2314 SdrPageView
* pPV
=pM
->GetPageView();
2315 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
2316 tools::Rectangle
aRect(pObj
->GetCurrentBoundRect());
2317 aRect
.AdjustLeft( -mnHitTolLog
);
2318 aRect
.AdjustTop( -mnHitTolLog
);
2319 aRect
.AdjustRight(mnHitTolLog
);
2320 aRect
.AdjustBottom(mnHitTolLog
);
2321 if (aRect
.IsInside(rPnt
)) {
2332 void SdrMarkView::UnmarkAllObj(SdrPageView
const * pPV
)
2334 if (GetMarkedObjectCount()==0)
2340 GetMarkedObjectListWriteAccess().DeletePageView(*pPV
);
2344 GetMarkedObjectListWriteAccess().Clear();
2346 mpMarkedObj
=nullptr;
2348 MarkListHasChanged();
2352 void SdrMarkView::MarkAllObj(SdrPageView
* pPV
)
2358 pPV
= GetSdrPageView();
2361 // #i69171# pPV may still be NULL if there is no SDrPageView (!), e.g. when inserting
2365 const bool bMarkChg(GetMarkedObjectListWriteAccess().InsertPageView(*pPV
));
2369 MarkListHasChanged();
2373 if(GetMarkedObjectCount())
2379 void SdrMarkView::AdjustMarkHdl(SfxViewShell
* pOtherShell
)
2383 SetMarkHandles(pOtherShell
);
2386 // BoundRect in model coordinates, no GridOffset added
2387 tools::Rectangle
SdrMarkView::GetMarkedObjBoundRect() const
2389 tools::Rectangle aRect
;
2390 for (size_t nm
=0; nm
<GetMarkedObjectCount(); ++nm
) {
2391 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
2392 SdrObject
* pO
=pM
->GetMarkedSdrObj();
2393 tools::Rectangle
aR1(pO
->GetCurrentBoundRect());
2394 if (aRect
.IsEmpty()) aRect
=aR1
;
2395 else aRect
.Union(aR1
);
2400 // ObjRect in model coordinates, no GridOffset added
2401 const tools::Rectangle
& SdrMarkView::GetMarkedObjRect() const
2403 if (mbMarkedObjRectDirty
) {
2404 const_cast<SdrMarkView
*>(this)->mbMarkedObjRectDirty
=false;
2405 tools::Rectangle aRect
;
2406 for (size_t nm
=0; nm
<GetMarkedObjectCount(); ++nm
) {
2407 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
2408 SdrObject
* pO
= pM
->GetMarkedSdrObj();
2411 tools::Rectangle
aR1(pO
->GetSnapRect());
2412 if (aRect
.IsEmpty()) aRect
=aR1
;
2413 else aRect
.Union(aR1
);
2415 const_cast<SdrMarkView
*>(this)->maMarkedObjRect
=aRect
;
2417 return maMarkedObjRect
;
2421 OUString
SdrMarkView::ImpGetDescriptionString(const char* pStrCacheID
, ImpGetDescriptionOptions nOpt
) const
2423 OUString sStr
= SvxResId(pStrCacheID
);
2424 const sal_Int32 nPos
= sStr
.indexOf("%1");
2428 if(nOpt
== ImpGetDescriptionOptions::POINTS
)
2430 sStr
= sStr
.replaceAt(nPos
, 2, GetDescriptionOfMarkedPoints());
2432 else if(nOpt
== ImpGetDescriptionOptions::GLUEPOINTS
)
2434 sStr
= sStr
.replaceAt(nPos
, 2, GetDescriptionOfMarkedGluePoints());
2438 sStr
= sStr
.replaceAt(nPos
, 2, GetDescriptionOfMarkedObjects());
2442 return sStr
.replaceFirst("%2", "0");
2446 void SdrMarkView::EnterMarkedGroup()
2448 // We enter only the first group found (in only one PageView), because
2449 // PageView::EnterGroup calls an AdjustMarkHdl.
2450 // TODO: I'll have to prevent that via a flag.
2451 SdrPageView
* pPV
= GetSdrPageView();
2457 for (size_t nm
= GetMarkedObjectCount(); nm
> 0 && !bEnter
;)
2460 SdrMark
* pM
=GetSdrMarkByIndex(nm
);
2461 if (pM
->GetPageView()==pPV
) {
2462 SdrObject
* pObj
=pM
->GetMarkedSdrObj();
2463 if (pObj
->IsGroupObject()) {
2464 if (pPV
->EnterGroup(pObj
)) {
2473 void SdrMarkView::MarkListHasChanged()
2475 GetMarkedObjectListWriteAccess().SetNameDirty();
2476 maSdrViewSelection
.SetEdgesOfMarkedNodesDirty();
2478 mbMarkedObjRectDirty
=true;
2479 mbMarkedPointsRectsDirty
=true;
2480 bool bOneEdgeMarked
=false;
2481 if (GetMarkedObjectCount()==1) {
2482 const SdrObject
* pObj
=GetMarkedObjectByIndex(0);
2483 if (pObj
->GetObjInventor()==SdrInventor::Default
) {
2484 sal_uInt16 nIdent
=pObj
->GetObjIdentifier();
2485 bOneEdgeMarked
=nIdent
==OBJ_EDGE
;
2488 ImpSetGlueVisible4(bOneEdgeMarked
);
2492 void SdrMarkView::SetMoveOutside(bool bOn
)
2494 maHdlList
.SetMoveOutside(bOn
);
2497 void SdrMarkView::SetDesignMode( bool bOn
)
2499 if ( mbDesignMode
!= bOn
)
2502 SdrPageView
* pPageView
= GetSdrPageView();
2504 pPageView
->SetDesignMode( bOn
);
2508 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */