1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <editeng/outlobj.hxx>
22 #include <svx/strings.hrc>
23 #include <svx/dialmgr.hxx>
24 #include <svx/svdpagv.hxx>
25 #include <svx/svdmrkv.hxx>
26 #include <svx/svdedxv.hxx>
27 #include <svx/svdobj.hxx>
28 #include <svx/svdopath.hxx>
29 #include <svx/svdograf.hxx>
30 #include <svx/svdomedia.hxx>
31 #include <svx/svdetc.hxx>
33 #include <svx/sdr/table/tablecontroller.hxx>
34 #include <svx/svdoutl.hxx>
35 #include <svx/svdview.hxx>
36 #include <editeng/flditem.hxx>
37 #include <svx/obj3d.hxx>
38 #include <svx/svddrgmt.hxx>
39 #include <svx/svdotable.hxx>
40 #include <tools/debug.hxx>
41 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
42 #include <svx/sdr/overlay/overlaymanager.hxx>
43 #include <svx/sdrpaintwindow.hxx>
44 #include <svx/sdrpagewindow.hxx>
45 #include <svx/sdrhittesthelper.hxx>
46 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
47 #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
48 #include <svx/sdr/contact/objectcontactofpageview.hxx>
49 #include <sal/log.hxx>
50 #include <vcl/ptrstyle.hxx>
51 #include <vcl/window.hxx>
52 #include <comphelper/lok.hxx>
55 SdrViewEvent::SdrViewEvent()
61 meHit(SdrHitKind::NONE
),
62 meEvent(SdrEventKind::NONE
),
64 mnMouseMode(MouseEventModifiers::NONE
),
74 mbPrevNextMark(false),
79 // helper class for all D&D overlays
81 void SdrDropMarkerOverlay::ImplCreateOverlays(
83 const basegfx::B2DPolyPolygon
& rLinePolyPolygon
)
85 for(sal_uInt32
a(0); a
< rView
.PaintWindowCount(); a
++)
87 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
88 const rtl::Reference
< sdr::overlay::OverlayManager
>& xTargetOverlay
= pCandidate
->GetOverlayManager();
90 if (xTargetOverlay
.is())
92 std::unique_ptr
<sdr::overlay::OverlayPolyPolygonStripedAndFilled
> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
95 xTargetOverlay
->add(*pNew
);
96 maObjects
.append(std::move(pNew
));
101 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const SdrObject
& rObject
)
105 rObject
.TakeXorPoly());
108 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const tools::Rectangle
& rRectangle
)
110 basegfx::B2DPolygon aB2DPolygon
;
112 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()));
113 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
114 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
115 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
116 aB2DPolygon
.setClosed(true);
120 basegfx::B2DPolyPolygon(aB2DPolygon
));
123 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const Point
& rStart
, const Point
& rEnd
)
125 basegfx::B2DPolygon aB2DPolygon
;
127 aB2DPolygon
.append(basegfx::B2DPoint(rStart
.X(), rStart
.Y()));
128 aB2DPolygon
.append(basegfx::B2DPoint(rEnd
.X(), rEnd
.Y()));
129 aB2DPolygon
.setClosed(true);
133 basegfx::B2DPolyPolygon(aB2DPolygon
));
136 SdrDropMarkerOverlay::~SdrDropMarkerOverlay()
138 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
139 // That destructor calls clear() at the list which removes all objects from the
140 // OverlayManager and deletes them.
146 : SdrCreateView(rSdrModel
, pOut
),
147 mbNoExtendedMouseDispatcher(false),
148 mbNoExtendedKeyDispatcher(false),
149 mbMasterPagePaintCaching(false)
151 maAccessibilityOptions
.AddListener(this);
152 onAccessibilityOptionsChanged();
157 maAccessibilityOptions
.RemoveListener(this);
160 bool SdrView::KeyInput(const KeyEvent
& rKEvt
, vcl::Window
* pWin
)
162 SetActualWin(pWin
? pWin
->GetOutDev() : nullptr);
163 bool bRet
= SdrCreateView::KeyInput(rKEvt
,pWin
);
164 if (!bRet
&& !IsExtendedKeyInputDispatcherEnabled()) {
166 switch (rKEvt
.GetKeyCode().GetFullFunction()) {
167 case KeyFuncType::DELETE
: DeleteMarked(); break;
168 case KeyFuncType::UNDO
: GetModel().Undo(); break;
169 case KeyFuncType::REDO
: GetModel().Redo(); break;
171 switch (rKEvt
.GetKeyCode().GetFullCode()) {
173 if (IsTextEdit()) SdrEndTextEdit();
174 if (IsAction()) BrkAction();
175 if (pWin
!=nullptr) pWin
->ReleaseMouse();
177 case KEY_DELETE
: DeleteMarked(); break;
178 case KEY_UNDO
: case KEY_BACKSPACE
+KEY_MOD2
: GetModel().Undo(); break;
179 case KEY_BACKSPACE
+KEY_MOD2
+KEY_SHIFT
: GetModel().Redo(); break;
180 case KEY_REPEAT
: case KEY_BACKSPACE
+KEY_MOD2
+KEY_MOD1
: GetModel().Repeat(*this); break;
181 case KEY_MOD1
+KEY_A
: MarkAll(); break;
186 if (bRet
&& pWin
!=nullptr) {
187 pWin
->SetPointer(GetPreferredPointer(
188 pWin
->PixelToLogic(pWin
->ScreenToOutputPixel( pWin
->GetPointerPosPixel() ) ),
190 rKEvt
.GetKeyCode().GetModifier()));
196 bool SdrView::MouseButtonDown(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
199 if (rMEvt
.IsLeft()) maDragStat
.SetMouseDown(true);
200 bool bRet
= SdrCreateView::MouseButtonDown(rMEvt
,pWin
);
201 if (!bRet
&& !IsExtendedMouseEventDispatcherEnabled()) {
203 PickAnything(rMEvt
,SdrMouseEventKind::BUTTONDOWN
,aVEvt
);
204 bRet
= DoMouseEvent(aVEvt
);
209 bool SdrView::MouseButtonUp(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
212 if (rMEvt
.IsLeft()) maDragStat
.SetMouseDown(false);
213 bool bAction
= IsAction();
214 bool bRet
= !bAction
&& SdrCreateView::MouseButtonUp(rMEvt
,pWin
);
215 if (!bRet
&& !IsExtendedMouseEventDispatcherEnabled()) {
217 PickAnything(rMEvt
,SdrMouseEventKind::BUTTONUP
,aVEvt
);
218 bRet
= DoMouseEvent(aVEvt
);
223 bool SdrView::MouseMove(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
226 maDragStat
.SetMouseDown(rMEvt
.IsLeft());
227 bool bRet
= SdrCreateView::MouseMove(rMEvt
,pWin
);
228 if (!IsExtendedMouseEventDispatcherEnabled() && !IsTextEditInSelectionMode()) {
230 PickAnything(rMEvt
,SdrMouseEventKind::MOVE
,aVEvt
);
231 if (DoMouseEvent(aVEvt
)) bRet
=true;
237 bool SdrView::Command(const CommandEvent
& rCEvt
, vcl::Window
* pWin
)
239 SetActualWin(pWin
->GetOutDev());
240 bool bRet
= SdrCreateView::Command(rCEvt
,pWin
);
244 void SdrView::GetAttributes(SfxItemSet
& rTargetSet
, bool bOnlyHardAttr
) const
246 SdrCreateView::GetAttributes(rTargetSet
, bOnlyHardAttr
);
249 SdrHitKind
SdrView::PickAnything(const MouseEvent
& rMEvt
, SdrMouseEventKind nEventKind
, SdrViewEvent
& rVEvt
) const
251 rVEvt
.mbMouseDown
= nEventKind
==SdrMouseEventKind::BUTTONDOWN
;
252 rVEvt
.mbMouseUp
= nEventKind
==SdrMouseEventKind::BUTTONUP
;
253 rVEvt
.mnMouseClicks
= rMEvt
.GetClicks();
254 rVEvt
.mnMouseMode
= rMEvt
.GetMode();
255 rVEvt
.mnMouseCode
= rMEvt
.GetButtons() | rMEvt
.GetModifier();
256 const OutputDevice
* pOut
=mpActualOutDev
;
259 pOut
= GetFirstOutputDevice();
261 Point
aPnt(rMEvt
.GetPosPixel());
262 if (pOut
!=nullptr) aPnt
=pOut
->PixelToLogic(aPnt
);
266 // Shape's x coordinates are all negated,
267 // Hence negate mouse event's x coord to match.
268 aPnt
.setX(-aPnt
.X());
271 rVEvt
.maLogicPos
= aPnt
;
272 return PickAnything(aPnt
,rVEvt
);
275 // Dragging with the Mouse (Move)
276 // Example when creating a rectangle: MouseDown has to happen without a ModKey,
277 // else we usually force a selection (see below).
278 // When pressing Shift, Ctrl and Alt at the same time while doing a MouseMove,
279 // a centered, not snapped square is created.
280 // The dual allocation of Ortho and Shift won't usually create a problem, as the
281 // two functions are in most cases mutually exclusive. Only shearing (the kind
282 // that happens when contorting, not when rotating) can use both functions at
283 // the same time. To get around this, the user can use e. g. help lines.
284 #define MODKEY_NoSnap bCtrl /* temporarily disable snapping */
285 #define MODKEY_Ortho bShift /* ortho */
286 #define MODKEY_Center bAlt /* create/resize centeredly */
287 #define MODKEY_AngleSnap bShift
288 #define MODKEY_CopyDrag bCtrl /* drag and copy */
290 // click somewhere (MouseDown)
291 #define MODKEY_PolyPoly bAlt /* new Poly at InsPt and at Create */
292 #define MODKEY_MultiMark bShift /* MarkObj without doing UnmarkAll first */
293 #define MODKEY_Unmark bAlt /* deselect with a dragged frame */
294 #define MODKEY_ForceMark bCtrl /* force dragging a frame, even if there's an object at cursor position */
295 #define MODKEY_DeepMark bAlt /* MarkNextObj */
296 #define MODKEY_DeepBackw bShift /* MarkNextObj but backwards */
298 SdrHitKind
SdrView::PickAnything(const Point
& rLogicPos
, SdrViewEvent
& rVEvt
) const
300 const OutputDevice
* pOut
=mpActualOutDev
;
303 pOut
= GetFirstOutputDevice();
306 // #i73628# Use a non-changeable copy of he logic position
307 const Point
aLocalLogicPosition(rLogicPos
);
309 bool bEditMode
=IsEditMode();
310 bool bPointMode
=bEditMode
&& HasMarkablePoints();
311 bool bGluePointMode
=IsGluePointEditMode();
312 bool bInsPolyPt
=bPointMode
&& IsInsObjPointMode() && IsInsObjPointPossible();
313 bool bInsGluePt
=bGluePointMode
&& IsInsGluePointMode() && IsInsGluePointPossible();
314 bool bIsTextEdit
=IsTextEdit();
315 bool bTextEditHit
=IsTextEditHit(aLocalLogicPosition
);
316 bool bTextEditSel
=IsTextEditInSelectionMode();
317 bool bShift
= (rVEvt
.mnMouseCode
& KEY_SHIFT
) != 0;
318 bool bCtrl
= (rVEvt
.mnMouseCode
& KEY_MOD1
) != 0;
319 bool bAlt
= (rVEvt
.mnMouseCode
& KEY_MOD2
) != 0;
320 SdrHitKind eHit
=SdrHitKind::NONE
;
321 SdrHdl
* pHdl
=pOut
!=nullptr && !bTextEditSel
? PickHandle(aLocalLogicPosition
) : nullptr;
322 SdrPageView
* pPV
=nullptr;
323 SdrObject
* pObj
=nullptr;
324 SdrObject
* pHitObj
=nullptr;
325 bool bHitPassDirect
=true;
326 sal_uInt16 nHlplIdx
=0;
327 sal_uInt16 nGlueId
=0;
328 if (bTextEditHit
|| bTextEditSel
)
330 eHit
=SdrHitKind::TextEdit
;
332 else if (pHdl
!=nullptr)
334 eHit
=SdrHitKind::Handle
; // handle is hit: highest priority
336 else if (bEditMode
&& IsHlplVisible() && IsHlplFront() && pOut
!=nullptr && PickHelpLine(aLocalLogicPosition
,mnHitTolLog
,*pOut
,nHlplIdx
,pPV
))
338 eHit
=SdrHitKind::HelpLine
; // help line in the foreground hit: can be moved now
340 else if (bGluePointMode
&& PickGluePoint(aLocalLogicPosition
,pObj
,nGlueId
,pPV
))
342 eHit
=SdrHitKind::Gluepoint
; // deselected gluepoint hit
344 else if ((pHitObj
= PickObj(aLocalLogicPosition
,mnHitTolLog
,pPV
,SdrSearchOptions::DEEP
|SdrSearchOptions::MARKED
,&pObj
,&bHitPassDirect
)))
346 eHit
=SdrHitKind::MarkedObject
;
347 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast< sdr::table::SdrTableObj
* >( pObj
);
350 sal_Int32 nX
= 0, nY
= 0;
351 switch( pTableObj
->CheckTableHit( aLocalLogicPosition
, nX
, nY
) )
353 case sdr::table::TableHitKind::Cell
:
354 eHit
= SdrHitKind::Cell
;
356 case sdr::table::TableHitKind::CellTextArea
:
357 eHit
= SdrHitKind::TextEditObj
;
364 else if ((pHitObj
= PickObj(aLocalLogicPosition
,mnHitTolLog
,pPV
,SdrSearchOptions::DEEP
|SdrSearchOptions::ALSOONMASTER
|SdrSearchOptions::WHOLEPAGE
,&pObj
,&bHitPassDirect
)))
366 // MasterPages and WholePage for Macro and URL
367 eHit
=SdrHitKind::UnmarkedObject
;
368 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast< sdr::table::SdrTableObj
* >( pObj
);
371 sal_Int32 nX
= 0, nY
= 0;
372 switch( pTableObj
->CheckTableHit( aLocalLogicPosition
, nX
, nY
, mnHitTolLog
) )
374 case sdr::table::TableHitKind::Cell
:
375 eHit
= SdrHitKind::Cell
;
377 case sdr::table::TableHitKind::CellTextArea
:
378 // Keep state on UnmarkedObject to allow the below
379 // 'check for URL field' to be executed, else popups
380 // for e.g. URL links when hoovering and clicking
381 // them will not work. Tried several other changes,
382 // but this one safely keeps existing behaviour as-is.
383 // Except for the LOK. LOK doesn't have hoovering popup
385 eHit
= comphelper::LibreOfficeKit::isActive() ? SdrHitKind::TextEditObj
: SdrHitKind::UnmarkedObject
;
392 else if (bEditMode
&& IsHlplVisible() && !IsHlplFront() && pOut
!=nullptr && PickHelpLine(aLocalLogicPosition
,mnHitTolLog
,*pOut
,nHlplIdx
,pPV
))
394 eHit
=SdrHitKind::HelpLine
; // help line in foreground hit: can be moved now
396 if (eHit
==SdrHitKind::UnmarkedObject
)
398 bool bRoot
=pObj
->HasMacro();
399 bool bDeep
=pObj
!=pHitObj
&& pHitObj
->HasMacro();
400 bool bMid
=false; // Have we hit upon a grouped group with a macro?
401 SdrObject
* pMidObj
=nullptr;
404 SdrObject
* pObjTmp
=pHitObj
->getParentSdrObjectFromSdrObject();
405 if (pObjTmp
==pObj
) pObjTmp
=nullptr;
406 while (pObjTmp
!=nullptr)
408 if (pObjTmp
->HasMacro())
413 pObjTmp
=pObjTmp
->getParentSdrObjectFromSdrObject();
414 if (pObjTmp
==pObj
) pObjTmp
=nullptr;
418 if (bDeep
|| bMid
|| bRoot
)
420 SdrObjMacroHitRec aHitRec
;
421 aHitRec
.aPos
=aLocalLogicPosition
;
422 aHitRec
.nTol
=mnHitTolLog
;
423 aHitRec
.pVisiLayer
=&pPV
->GetVisibleLayers();
424 aHitRec
.pPageView
=pPV
;
425 if (bDeep
) bDeep
=pHitObj
->IsMacroHit(aHitRec
);
426 if (bMid
) bMid
=pMidObj
->IsMacroHit(aHitRec
);
427 if (bRoot
) bRoot
=pObj
->IsMacroHit(aHitRec
);
428 if (bRoot
|| bMid
|| bDeep
)
430 // Priorities: 1. Root, 2. Mid, 3. Deep
431 rVEvt
.mpRootObj
= pObj
;
432 if (!bRoot
) pObj
=pMidObj
;
433 if (!bRoot
&& !bMid
) pObj
=pHitObj
;
434 eHit
=SdrHitKind::Macro
;
438 // check for URL field
439 if (eHit
==SdrHitKind::UnmarkedObject
)
441 SdrTextObj
* pTextObj
=DynCastSdrTextObj( pHitObj
);
442 if (pTextObj
!=nullptr && pTextObj
->HasText())
444 // use the primitive-based HitTest which is more accurate anyways. It
445 // will correctly handle rotated/mirrored/sheared/scaled text and can
446 // now return a HitContainer containing the primitive hierarchy of the
447 // primitive that triggered the hit. The first entry is that primitive,
448 // the others are the full stack of primitives leading to that one which
449 // includes grouping primitives (like TextHierarchyPrimitives we deed here)
450 // but also all decomposed ones which lead to the creation of that primitive
451 drawinglayer::primitive2d::Primitive2DContainer aHitContainer
;
452 const bool bTEHit(pPV
&& SdrObjectPrimitiveHit(*pTextObj
, aLocalLogicPosition
, {0, 0}, *pPV
, &pPV
->GetVisibleLayers(), true, &aHitContainer
));
454 if (bTEHit
&& !aHitContainer
.empty())
456 // search for TextHierarchyFieldPrimitive2D which contains the needed information
457 // about a possible URLField
458 const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D
* pTextHierarchyFieldPrimitive2D
= nullptr;
460 for (const drawinglayer::primitive2d::Primitive2DReference
& xReference
: aHitContainer
)
462 auto pBasePrimitive
= xReference
.get();
463 if (pBasePrimitive
&& pBasePrimitive
->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D
)
465 pTextHierarchyFieldPrimitive2D
= static_cast<const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D
*>(pBasePrimitive
);
470 if (nullptr != pTextHierarchyFieldPrimitive2D
)
472 if (drawinglayer::primitive2d::FieldType::FIELD_TYPE_URL
== pTextHierarchyFieldPrimitive2D
->getType())
474 // problem with the old code is that a *pointer* to an instance of
475 // SvxURLField is set in the Event which is per se not good since that
476 // data comes from a temporary EditEngine's data and could vanish any
477 // moment. Have to replace for now with a static instance that gets
478 // filled/initialized from the original data held in the TextHierarchyField-
479 // Primitive2D (see impTextBreakupHandler::impCheckFieldPrimitive).
480 // Unfortunately things like 'TargetFrame' are still used in Calc, so this
481 // can currently not get replaced. For the future the Name/Value vector or
482 // the TextHierarchyFieldPrimitive2D itself should/will be used for handling
484 static SvxURLField aSvxURLField
;
486 aSvxURLField
.SetURL(pTextHierarchyFieldPrimitive2D
->getValue("URL"));
487 aSvxURLField
.SetRepresentation(pTextHierarchyFieldPrimitive2D
->getValue("Representation"));
488 aSvxURLField
.SetTargetFrame(pTextHierarchyFieldPrimitive2D
->getValue("TargetFrame"));
489 const OUString
aFormat(pTextHierarchyFieldPrimitive2D
->getValue("SvxURLFormat"));
491 if (!aFormat
.isEmpty())
493 aSvxURLField
.SetFormat(static_cast<SvxURLFormat
>(aFormat
.toInt32()));
496 // set HitKind and pointer to local static instance in the Event
497 // to comply to old stuff
498 eHit
= SdrHitKind::UrlField
;
499 rVEvt
.mpURLField
= &aSvxURLField
;
504 if (eHit
==SdrHitKind::UnmarkedObject
&& !pHitObj
->getHyperlink().isEmpty())
506 static SvxURLField aSvxURLField
;
507 aSvxURLField
.SetURL(pHitObj
->getHyperlink());
508 rVEvt
.mpURLField
= &aSvxURLField
;
509 eHit
= SdrHitKind::UrlField
;
513 if (bHitPassDirect
&&
514 (eHit
==SdrHitKind::MarkedObject
|| eHit
==SdrHitKind::UnmarkedObject
) &&
515 (IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj
->HasTextEdit())
517 auto pTextObj
= DynCastSdrTextObj(pHitObj
);
519 // Around the TextEditArea there's a border to select without going into text edit mode.
520 tools::Rectangle aBoundRect
;
521 const GeoStat
& rGeo
= pTextObj
->GetGeoStat();
522 if (pTextObj
&& !rGeo
.m_nRotationAngle
&& !rGeo
.m_nShearAngle
)
524 pTextObj
->TakeTextEditArea(nullptr, nullptr, &aBoundRect
, nullptr);
527 aBoundRect
= pHitObj
->GetCurrentBoundRect();
529 // Force to SnapRect when Fontwork
530 if( pTextObj
&& pTextObj
->IsFontwork() )
531 aBoundRect
= pHitObj
->GetSnapRect();
533 sal_Int32
nTolerance(mnHitTolLog
);
534 bool bBoundRectHit(false);
538 nTolerance
= pOut
->PixelToLogic(Size(2, 0)).Width();
541 if( (aLocalLogicPosition
.X() >= aBoundRect
.Left() - nTolerance
&& aLocalLogicPosition
.X() <= aBoundRect
.Left() + nTolerance
)
542 || (aLocalLogicPosition
.X() >= aBoundRect
.Right() - nTolerance
&& aLocalLogicPosition
.X() <= aBoundRect
.Right() + nTolerance
)
543 || (aLocalLogicPosition
.Y() >= aBoundRect
.Top() - nTolerance
&& aLocalLogicPosition
.Y() <= aBoundRect
.Top() + nTolerance
)
544 || (aLocalLogicPosition
.Y() >= aBoundRect
.Bottom() - nTolerance
&& aLocalLogicPosition
.Y() <= aBoundRect
.Bottom() + nTolerance
))
546 bBoundRectHit
= true;
549 if(!bBoundRectHit
&& aBoundRect
.Contains(aLocalLogicPosition
))
552 && SdrObjectPrimitiveHit(*pHitObj
, aLocalLogicPosition
, { 2000.0, 0.0 },
553 *pPV
, &pPV
->GetVisibleLayers(), true));
555 // TextEdit attached to an object in a locked layer
556 if (bTEHit
&& pPV
->GetLockedLayers().IsSet(pHitObj
->GetLayer()))
563 rVEvt
.mpRootObj
=pObj
;
565 eHit
=SdrHitKind::TextEditObj
;
569 if (!bHitPassDirect
&& eHit
==SdrHitKind::UnmarkedObject
) {
570 eHit
=SdrHitKind::NONE
;
574 bool bMouseLeft
= (rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0;
575 bool bMouseRight
= (rVEvt
.mnMouseCode
& MOUSE_RIGHT
) != 0;
576 bool bMouseDown
= rVEvt
.mbMouseDown
;
577 bool bMouseUp
= rVEvt
.mbMouseUp
;
578 SdrEventKind eEvent
=SdrEventKind::NONE
;
579 bool bIsAction
=IsAction();
585 if (bMouseRight
) eEvent
=SdrEventKind::BackAction
;
591 eEvent
=SdrEventKind::EndAction
;
594 eEvent
=SdrEventKind::EndDrag
;
596 else if (IsCreateObj() || IsInsObjPoint())
598 eEvent
=IsCreateObj() ? SdrEventKind::EndCreate
: SdrEventKind::EndInsertObjPoint
;
600 else if (IsMarking())
602 eEvent
=SdrEventKind::EndMark
;
603 if (!maDragStat
.IsMinMoved())
605 eEvent
=SdrEventKind::BrkMark
;
606 rVEvt
.mbAddMark
= MODKEY_MultiMark
;
613 eEvent
=SdrEventKind::MoveAction
;
616 else if (eHit
==SdrHitKind::TextEdit
)
618 eEvent
=SdrEventKind::TextEdit
;
620 else if (bMouseDown
&& bMouseLeft
)
622 if (rVEvt
.mnMouseClicks
== 2 && rVEvt
.mnMouseCode
== MOUSE_LEFT
&& pObj
!=nullptr && pHitObj
!=nullptr && pHitObj
->HasTextEdit() && eHit
==SdrHitKind::MarkedObject
)
624 rVEvt
.mpRootObj
= pObj
;
626 eEvent
=SdrEventKind::BeginTextEdit
;
628 else if (MODKEY_ForceMark
&& eHit
!=SdrHitKind::UrlField
)
630 eEvent
=SdrEventKind::BeginMark
; // AddMark,Unmark */
632 else if (eHit
==SdrHitKind::HelpLine
)
634 eEvent
=SdrEventKind::BeginDragHelpline
; // nothing, actually
636 else if (eHit
==SdrHitKind::Gluepoint
)
638 eEvent
=SdrEventKind::MarkGluePoint
; // AddMark+Drag
639 rVEvt
.mbAddMark
= MODKEY_MultiMark
|| MODKEY_DeepMark
; // if not hit with Deep
641 else if (eHit
==SdrHitKind::Handle
)
643 eEvent
=SdrEventKind::BeginDragObj
; // Mark+Drag,AddMark+Drag,DeepMark+Drag,Unmark
644 bool bGlue
=pHdl
->GetKind()==SdrHdlKind::Glue
;
645 bool bPoly
=!bGlue
&& IsPointMarkable(*pHdl
);
646 bool bMarked
=bGlue
|| (bPoly
&& pHdl
->IsSelected());
649 eEvent
=bGlue
? SdrEventKind::MarkGluePoint
: SdrEventKind::MarkPoint
;
652 rVEvt
.mbAddMark
= true;
653 rVEvt
.mbPrevNextMark
= true;
654 rVEvt
.mbMarkPrev
= MODKEY_DeepBackw
;
656 else if (MODKEY_MultiMark
)
658 rVEvt
.mbAddMark
= true;
659 rVEvt
.mbUnmark
= bMarked
; // Toggle
663 nGlueId
=static_cast<sal_uInt16
>(pHdl
->GetObjHdlNum());
668 eEvent
=SdrEventKind::BeginDragObj
; // don't change MarkState, only change Drag
672 else if (bInsPolyPt
&& (MODKEY_PolyPoly
|| (!MODKEY_MultiMark
&& !MODKEY_DeepMark
)))
674 eEvent
=SdrEventKind::BeginInsertObjPoint
;
676 else if (bInsGluePt
&& !MODKEY_MultiMark
&& !MODKEY_DeepMark
)
678 eEvent
=SdrEventKind::BeginInsertGluePoint
;
680 else if (eHit
==SdrHitKind::TextEditObj
)
682 eEvent
=SdrEventKind::BeginTextEdit
; // AddMark+Drag,DeepMark+Drag,Unmark
683 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
684 { // if not hit with Deep
685 eEvent
=SdrEventKind::MarkObj
;
688 else if (eHit
==SdrHitKind::Macro
)
690 eEvent
=SdrEventKind::BeginMacroObj
; // AddMark+Drag
691 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
692 { // if not hit with Deep
693 eEvent
=SdrEventKind::MarkObj
;
696 else if (eHit
==SdrHitKind::UrlField
)
698 eEvent
=SdrEventKind::ExecuteUrl
; // AddMark+Drag
699 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
700 { // if not hit with Deep
701 eEvent
=SdrEventKind::MarkObj
;
704 else if (eHit
==SdrHitKind::MarkedObject
)
706 eEvent
=SdrEventKind::BeginDragObj
; // DeepMark+Drag,Unmark
708 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
709 { // if not hit with Deep
710 eEvent
=SdrEventKind::MarkObj
;
713 else if (IsCreateMode())
715 eEvent
=SdrEventKind::BeginCreateObj
; // nothing, actually
717 else if (eHit
==SdrHitKind::UnmarkedObject
)
719 eEvent
=SdrEventKind::MarkObj
; // AddMark+Drag
723 eEvent
=SdrEventKind::BeginMark
;
726 if (eEvent
==SdrEventKind::MarkObj
)
728 rVEvt
.mbAddMark
= MODKEY_MultiMark
|| MODKEY_DeepMark
; // if not hit with Deep
729 rVEvt
.mbPrevNextMark
= MODKEY_DeepMark
;
730 rVEvt
.mbMarkPrev
= MODKEY_DeepMark
&& MODKEY_DeepBackw
;
732 if (eEvent
==SdrEventKind::BeginMark
)
734 rVEvt
.mbAddMark
= MODKEY_MultiMark
;
735 rVEvt
.mbUnmark
= MODKEY_Unmark
;
738 rVEvt
.mbIsAction
= bIsAction
;
739 rVEvt
.mbIsTextEdit
= bIsTextEdit
;
740 rVEvt
.maLogicPos
= aLocalLogicPosition
;
743 if (rVEvt
.mpRootObj
== nullptr)
744 rVEvt
.mpRootObj
= pObj
;
746 rVEvt
.mnHlplIdx
= nHlplIdx
;
747 rVEvt
.mnGlueId
= nGlueId
;
749 rVEvt
.meEvent
= eEvent
;
751 if (rVEvt
.mpRootObj
!= nullptr)
753 if (rVEvt
.mpRootObj
->getParentSdrObjListFromSdrObject() != rVEvt
.mpPV
->GetObjList())
755 OSL_FAIL("SdrView::PickAnything(): pRootObj->getParentSdrObjListFromSdrObject()!=pPV->GetObjList() !");
762 bool SdrView::DoMouseEvent(const SdrViewEvent
& rVEvt
)
765 SdrHitKind eHit
= rVEvt
.meHit
;
766 Point
aLogicPos(rVEvt
.maLogicPos
);
768 bool bShift
= (rVEvt
.mnMouseCode
& KEY_SHIFT
) != 0;
769 bool bCtrl
= (rVEvt
.mnMouseCode
& KEY_MOD1
) != 0;
770 bool bAlt
= (rVEvt
.mnMouseCode
& KEY_MOD2
) != 0;
771 bool bMouseLeft
= (rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0;
772 bool bMouseDown
= rVEvt
.mbMouseDown
;
773 bool bMouseUp
= rVEvt
.mbMouseUp
;
775 if (bMouseLeft
) maDragStat
.SetMouseDown(true);
776 } else if (bMouseUp
) {
777 if (bMouseLeft
) maDragStat
.SetMouseDown(false);
778 } else { // else, MouseMove
779 maDragStat
.SetMouseDown(bMouseLeft
);
783 SetSnapEnabled(!MODKEY_NoSnap
);
786 SetOrtho(MODKEY_Ortho
!=IsOrthoDesired());
788 #ifdef MODKEY_AngleSnap
789 SetAngleSnapEnabled(MODKEY_AngleSnap
);
791 #ifdef MODKEY_CopyDrag
792 SetDragWithCopy(MODKEY_CopyDrag
);
795 SetCreate1stPointAsCenter(MODKEY_Center
);
796 SetResizeAtCenter(MODKEY_Center
);
797 SetCrookAtCenter(MODKEY_Center
);
799 if (bMouseLeft
&& bMouseDown
&& rVEvt
.mbIsTextEdit
&& (eHit
==SdrHitKind::UnmarkedObject
|| eHit
==SdrHitKind::NONE
)) {
800 SdrEndTextEdit(); // User has clicked beneath object, exit edit mode.
801 // pHdl is invalid, then, that shouldn't matter, though, as we expect
802 // pHdl==NULL (because of eHit).
804 switch (rVEvt
.meEvent
)
806 case SdrEventKind::NONE
: bRet
=false; break;
807 case SdrEventKind::TextEdit
: bRet
=false; break; // Events handled by the OutlinerView are not taken into account here.
808 case SdrEventKind::MoveAction
: MovAction(aLogicPos
); bRet
=true; break;
809 case SdrEventKind::EndAction
: EndAction(); bRet
=true; break;
810 case SdrEventKind::BackAction
: BckAction(); bRet
=true; break;
811 case SdrEventKind::EndMark
: EndAction(); bRet
=true; break;
812 case SdrEventKind::BrkMark
: {
814 if (!MarkObj(aLogicPos
, mnHitTolLog
, rVEvt
.mbAddMark
))
816 // No object hit. Do the following:
817 // 1. deselect any selected gluepoints
818 // 2. deselect any selected polygon points
819 // 3. deselect any selected objects
820 if (!rVEvt
.mbAddMark
) UnmarkAll();
824 case SdrEventKind::EndCreate
: { // if necessary, MarkObj
825 SdrCreateCmd eCmd
=SdrCreateCmd::NextPoint
;
826 if (MODKEY_PolyPoly
) eCmd
=SdrCreateCmd::NextObject
;
827 if (rVEvt
.mnMouseClicks
> 1) eCmd
=SdrCreateCmd::ForceEnd
;
828 if (!EndCreateObj(eCmd
)) { // Don't evaluate event for Create? -> Select
829 if (eHit
==SdrHitKind::UnmarkedObject
|| eHit
==SdrHitKind::TextEdit
) {
830 MarkObj(rVEvt
.mpRootObj
, rVEvt
.mpPV
);
831 if (eHit
==SdrHitKind::TextEdit
)
833 bool bRet2(mpActualOutDev
&& OUTDEV_WINDOW
== mpActualOutDev
->GetOutDevType() &&
834 SdrBeginTextEdit(rVEvt
.mpObj
, rVEvt
.mpPV
, mpActualOutDev
->GetOwnerWindow()));
838 MouseEvent
aMEvt(mpActualOutDev
->LogicToPixel(aLogicPos
), 1,
839 rVEvt
.mnMouseMode
,rVEvt
.mnMouseCode
,rVEvt
.mnMouseCode
);
841 OutlinerView
* pOLV
=GetTextEditOutlinerView();
843 pOLV
->MouseButtonDown(aMEvt
); // event for the Outliner, but without double-click
844 pOLV
->MouseButtonUp(aMEvt
); // event for the Outliner, but without double-click
848 bRet
=true; // object is selected and (if necessary) TextEdit is started
849 } else bRet
=false; // canceled Create, nothing else
850 } else bRet
=true; // return true for EndCreate
852 case SdrEventKind::EndDrag
: {
853 bRet
=EndDragObj(IsDragWithCopy());
854 ForceMarkedObjToAnotherPage(); // TODO: Undo+bracing missing!
856 case SdrEventKind::MarkObj
: { // + (if applicable) BegDrag
857 if (!rVEvt
.mbAddMark
) UnmarkAllObj();
858 bool bUnmark
= rVEvt
.mbUnmark
;
859 if (rVEvt
.mbPrevNextMark
) {
860 bRet
=MarkNextObj(aLogicPos
, mnHitTolLog
, rVEvt
.mbMarkPrev
);
863 const size_t nCount0
=GetMarkedObjectCount();
864 bRet
=MarkObj(aLogicPos
, mnHitTolLog
, rVEvt
.mbAddMark
);
866 const size_t nCount1
=GetMarkedObjectCount();
867 bUnmark
=nCount1
<nCount0
;
870 BegDragObj(aLogicPos
,nullptr,nullptr,mnMinMovLog
);
874 case SdrEventKind::MarkPoint
: { // + (if applicable) BegDrag
875 if (!rVEvt
.mbAddMark
) UnmarkAllPoints();
876 if (rVEvt
.mbPrevNextMark
) {
880 bRet
= MarkPoint(*rVEvt
.mpHdl
, rVEvt
.mbUnmark
);
882 if (!rVEvt
.mbUnmark
&& !rVEvt
.mbPrevNextMark
) {
883 BegDragObj(aLogicPos
, nullptr, rVEvt
.mpHdl
, mnMinMovLog
);
887 case SdrEventKind::MarkGluePoint
: { // + (if applicable) BegDrag
888 if (!rVEvt
.mbAddMark
) UnmarkAllGluePoints();
889 if (rVEvt
.mbPrevNextMark
) {
893 bRet
=MarkGluePoint(rVEvt
.mpObj
,rVEvt
.mnGlueId
,rVEvt
.mbUnmark
);
895 if (!rVEvt
.mbUnmark
&& !rVEvt
.mbPrevNextMark
) {
896 SdrHdl
* pHdl
= GetGluePointHdl(rVEvt
.mpObj
, rVEvt
.mnGlueId
);
897 BegDragObj(aLogicPos
,nullptr,pHdl
,mnMinMovLog
);
901 case SdrEventKind::BeginMark
: bRet
= BegMark(aLogicPos
,rVEvt
.mbAddMark
,rVEvt
.mbUnmark
); break;
902 case SdrEventKind::BeginInsertObjPoint
: bRet
= BegInsObjPoint(aLogicPos
, MODKEY_PolyPoly
); break;
903 case SdrEventKind::EndInsertObjPoint
: {
904 SdrCreateCmd eCmd
=SdrCreateCmd::NextPoint
;
905 if (MODKEY_PolyPoly
) eCmd
=SdrCreateCmd::NextObject
;
906 if (rVEvt
.mnMouseClicks
> 1) eCmd
= SdrCreateCmd::ForceEnd
;
907 EndInsObjPoint(eCmd
);
910 case SdrEventKind::BeginInsertGluePoint
: bRet
=BegInsGluePoint(aLogicPos
); break;
911 case SdrEventKind::BeginDragHelpline
: bRet
= BegDragHelpLine(rVEvt
.mnHlplIdx
,rVEvt
.mpPV
); break;
912 case SdrEventKind::BeginDragObj
: bRet
=BegDragObj(aLogicPos
, nullptr, rVEvt
.mpHdl
, mnMinMovLog
); break;
913 case SdrEventKind::BeginCreateObj
: {
914 if (mnCurrentInvent
==SdrInventor::Default
&& mnCurrentIdent
==SdrObjKind::Caption
) {
915 tools::Long nHgt
=SdrEngineDefaults::GetFontHeight();
916 bRet
=BegCreateCaptionObj(aLogicPos
,Size(5*nHgt
,2*nHgt
));
917 } else bRet
=BegCreateObj(aLogicPos
);
919 case SdrEventKind::BeginMacroObj
: {
920 BegMacroObj(aLogicPos
, mnHitTolLog
, rVEvt
.mpObj
, rVEvt
.mpPV
, mpActualOutDev
->GetOwnerWindow());
923 case SdrEventKind::BeginTextEdit
: {
924 if (!IsObjMarked(rVEvt
.mpObj
)) {
926 MarkObj(rVEvt
.mpRootObj
,rVEvt
.mpPV
);
929 bRet
= mpActualOutDev
&& OUTDEV_WINDOW
== mpActualOutDev
->GetOutDevType()&&
930 SdrBeginTextEdit(rVEvt
.mpObj
, rVEvt
.mpPV
, mpActualOutDev
->GetOwnerWindow());
934 MouseEvent
aMEvt(mpActualOutDev
->LogicToPixel(aLogicPos
),
935 1, rVEvt
.mnMouseMode
, rVEvt
.mnMouseCode
, rVEvt
.mnMouseCode
);
936 OutlinerView
* pOLV
=GetTextEditOutlinerView();
937 if (pOLV
!=nullptr) pOLV
->MouseButtonDown(aMEvt
); // event for the Outliner, but without double-click
942 if (bRet
&& mpActualOutDev
&& mpActualOutDev
->GetOutDevType()==OUTDEV_WINDOW
) {
943 vcl::Window
* pWin
=mpActualOutDev
->GetOwnerWindow();
944 // left mouse button pressed?
945 bool bLeftDown
= (rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0 && rVEvt
.mbMouseDown
;
946 // left mouse button released?
947 bool bLeftUp
= (rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0 && rVEvt
.mbMouseUp
;
948 // left mouse button pressed or held?
949 bool bLeftDown1
=(rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0 && !rVEvt
.mbMouseUp
;
950 pWin
->SetPointer(GetPreferredPointer(rVEvt
.maLogicPos
, pWin
->GetOutDev(),
951 rVEvt
.mnMouseCode
& (KEY_SHIFT
|KEY_MOD1
|KEY_MOD2
),bLeftDown1
));
952 bool bAction
=IsAction();
953 if (bLeftDown
&& bAction
)
954 pWin
->CaptureMouse();
955 else if (bLeftUp
|| (rVEvt
.mbIsAction
&& !bAction
))
956 pWin
->ReleaseMouse();
961 PointerStyle
SdrView::GetPreferredPointer(const Point
& rMousePos
, const OutputDevice
* pOut
, sal_uInt16 nModifier
, bool bLeftDown
) const
966 return mpCurrentCreate
->GetCreatePointer();
968 if (mpCurrentSdrDragMethod
)
970 return mpCurrentSdrDragMethod
->GetSdrDragPointer();
972 if (IsMarkObj() || IsMarkPoints() || IsMarkGluePoints() || IsSetPageOrg()) return PointerStyle::Arrow
;
973 if (IsDragHelpLine()) return GetDraggedHelpLinePointer();
975 SdrObjMacroHitRec aHitRec
;
976 aHitRec
.aPos
=pOut
->LogicToPixel(rMousePos
);
977 aHitRec
.nTol
=nMacroTol
;
978 aHitRec
.pVisiLayer
=&pMacroPV
->GetVisibleLayers();
979 aHitRec
.pPageView
=pMacroPV
;
980 return pMacroObj
->GetMacroPointer(aHitRec
);
983 // TextEdit, ObjEdit, Macro
984 if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos
)))
986 if(!pOut
|| IsTextEditInSelectionMode())
988 if (mpTextEditOutliner
->IsVertical())
989 return PointerStyle::TextVertical
;
991 return PointerStyle::Text
;
993 // Outliner should return something here...
994 Point
aPos(pOut
->LogicToPixel(rMousePos
));
995 PointerStyle
aPointer(mpTextEditOutlinerView
->GetPointer(aPos
));
996 if (aPointer
==PointerStyle::Arrow
)
998 if (mpTextEditOutliner
->IsVertical())
999 aPointer
= PointerStyle::TextVertical
;
1001 aPointer
= PointerStyle::Text
;
1007 aVEvt
.mnMouseCode
= (nModifier
&(KEY_SHIFT
|KEY_MOD1
|KEY_MOD2
))|MOUSE_LEFT
; // to see what would happen on MouseLeftDown
1008 aVEvt
.mbMouseDown
= !bLeftDown
; // What if ..?
1009 aVEvt
.mbMouseUp
= bLeftDown
; // What if ..?
1011 const_cast<SdrView
*>(this)->SetActualWin(pOut
);
1012 SdrHitKind eHit
=PickAnything(rMousePos
,aVEvt
);
1013 SdrEventKind eEvent
= aVEvt
.meEvent
;
1016 case SdrEventKind::BeginCreateObj
:
1017 return maCurrentCreatePointer
;
1018 case SdrEventKind::MarkObj
:
1019 return PointerStyle::Move
;
1020 case SdrEventKind::BeginMark
:
1021 return PointerStyle::Arrow
;
1022 case SdrEventKind::MarkPoint
:
1023 case SdrEventKind::MarkGluePoint
:
1024 return PointerStyle::MovePoint
;
1025 case SdrEventKind::BeginInsertObjPoint
:
1026 case SdrEventKind::BeginInsertGluePoint
:
1027 return PointerStyle::Cross
;
1028 case SdrEventKind::ExecuteUrl
:
1029 return PointerStyle::RefHand
;
1030 case SdrEventKind::BeginMacroObj
:
1032 SdrObjMacroHitRec aHitRec
;
1033 aHitRec
.aPos
= aVEvt
.maLogicPos
;
1034 aHitRec
.nTol
=mnHitTolLog
;
1035 aHitRec
.pVisiLayer
= &aVEvt
.mpPV
->GetVisibleLayers();
1036 aHitRec
.pPageView
= aVEvt
.mpPV
;
1037 return aVEvt
.mpObj
->GetMacroPointer(aHitRec
);
1044 case SdrHitKind::Cell
:
1045 return PointerStyle::Arrow
;
1046 case SdrHitKind::HelpLine
:
1047 return aVEvt
.mpPV
->GetHelpLines()[aVEvt
.mnHlplIdx
].GetPointer();
1048 case SdrHitKind::Gluepoint
:
1049 return PointerStyle::MovePoint
;
1050 case SdrHitKind::TextEdit
:
1051 case SdrHitKind::TextEditObj
:
1053 SdrTextObj
* pText
= DynCastSdrTextObj(aVEvt
.mpObj
);
1054 if(pText
&& pText
->HasText())
1056 OutlinerParaObject
* pParaObj
= pText
->GetOutlinerParaObject();
1057 if(pParaObj
&& pParaObj
->IsEffectivelyVertical())
1058 return PointerStyle::TextVertical
;
1060 return PointerStyle::Text
;
1065 bool bMarkHit
=eHit
==SdrHitKind::MarkedObject
;
1066 SdrHdl
* pHdl
= aVEvt
.mpHdl
;
1067 // now check the pointers for dragging
1068 if (pHdl
!=nullptr || bMarkHit
) {
1069 SdrHdlKind eHdl
= pHdl
!=nullptr ? pHdl
->GetKind() : SdrHdlKind::Move
;
1070 bool bCorner
=pHdl
!=nullptr && pHdl
->IsCornerHdl();
1071 bool bVertex
=pHdl
!=nullptr && pHdl
->IsVertexHdl();
1072 bool bMov
=eHdl
==SdrHdlKind::Move
;
1073 if (bMov
&& (meDragMode
==SdrDragMode::Move
|| meDragMode
==SdrDragMode::Resize
|| mbMarkedHitMovesAlways
)) {
1074 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1075 return PointerStyle::Move
;
1077 switch (meDragMode
) {
1078 case SdrDragMode::Rotate
: {
1079 if ((bCorner
|| bMov
) && !IsRotateAllowed(true))
1080 return PointerStyle::NotAllowed
;
1082 // are 3D objects selected?
1083 bool b3DObjSelected
= false;
1084 for (size_t a
=0; !b3DObjSelected
&& a
<GetMarkedObjectCount(); ++a
) {
1085 SdrObject
* pObj
= GetMarkedObjectByIndex(a
);
1086 if(DynCastE3dObject(pObj
))
1087 b3DObjSelected
= true;
1089 // If we have a 3D object, go on despite !IsShearAllowed,
1090 // because then we have a rotation instead of a shear.
1091 if (bVertex
&& !IsShearAllowed() && !b3DObjSelected
)
1092 return PointerStyle::NotAllowed
;
1094 return PointerStyle::Rotate
;
1096 case SdrDragMode::Shear
: {
1098 if (!IsDistortAllowed(true) && !IsDistortAllowed()) return PointerStyle::NotAllowed
;
1099 else return PointerStyle::RefHand
;
1101 if (bVertex
&& !IsShearAllowed()) return PointerStyle::NotAllowed
;
1103 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1104 return PointerStyle::Move
;
1107 case SdrDragMode::Mirror
: {
1108 if (bCorner
|| bVertex
|| bMov
) {
1109 SdrHdl
* pH1
=maHdlList
.GetHdl(SdrHdlKind::Ref1
);
1110 SdrHdl
* pH2
=maHdlList
.GetHdl(SdrHdlKind::Ref2
);
1113 if (pH1
!=nullptr && pH2
!=nullptr) {
1114 Point aDif
= pH2
->GetPos()-pH1
->GetPos();
1115 b90
=(aDif
.X()==0) || aDif
.Y()==0;
1116 b45
=b90
|| (std::abs(aDif
.X())==std::abs(aDif
.Y()));
1119 if (!IsMirrorAllowed(true,true)) bNo
=true; // any mirroring is forbidden
1120 if (!IsMirrorAllowed() && !b45
) bNo
=true; // mirroring freely is forbidden
1121 if (!IsMirrorAllowed(true) && !b90
) bNo
=true; // mirroring horizontally/vertically is allowed
1122 if (bNo
) return PointerStyle::NotAllowed
;
1124 return PointerStyle::Mirror
;
1126 return PointerStyle::Mirror
;
1130 case SdrDragMode::Transparence
:
1132 if(!IsTransparenceAllowed())
1133 return PointerStyle::NotAllowed
;
1135 return PointerStyle::RefHand
;
1138 case SdrDragMode::Gradient
:
1140 if(!IsGradientAllowed())
1141 return PointerStyle::NotAllowed
;
1143 return PointerStyle::RefHand
;
1146 case SdrDragMode::Crook
: {
1147 if (bCorner
|| bVertex
|| bMov
) {
1148 if (!IsCrookAllowed(true) && !IsCrookAllowed()) return PointerStyle::NotAllowed
;
1149 return PointerStyle::Crook
;
1154 case SdrDragMode::Crop
:
1156 return PointerStyle::Crop
;
1160 if ((bCorner
|| bVertex
) && !IsResizeAllowed(true)) return PointerStyle::NotAllowed
;
1163 if (pHdl
!=nullptr) return pHdl
->GetPointer();
1165 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1166 return PointerStyle::Move
;
1169 if (meEditMode
==SdrViewEditMode::Create
) return maCurrentCreatePointer
;
1170 return PointerStyle::Arrow
;
1173 constexpr OUString STR_NOTHING
= u
"nothing"_ustr
;
1174 OUString
SdrView::GetStatusText()
1177 OUString aStr
= STR_NOTHING
;
1179 if (mpCurrentCreate
!=nullptr)
1181 aStr
=mpCurrentCreate
->getSpecialDragComment(maDragStat
);
1185 aName
= mpCurrentCreate
->TakeObjNameSingul();
1186 aStr
= SvxResId(STR_ViewCreateObj
);
1189 else if (mpCurrentSdrDragMethod
)
1191 if (mbInsPolyPoint
|| IsInsertGluePoint())
1193 aStr
=maInsPointUndoStr
;
1197 if (maDragStat
.IsMinMoved())
1201 "(" << this << ") " << mpCurrentSdrDragMethod
.get());
1202 aStr
= mpCurrentSdrDragMethod
->GetSdrDragComment();
1206 else if(IsMarkObj())
1208 if(AreObjectsMarked())
1210 aStr
= SvxResId(STR_ViewMarkMoreObjs
);
1214 aStr
= SvxResId(STR_ViewMarkObjs
);
1217 else if(IsMarkPoints())
1219 if(HasMarkedPoints())
1221 aStr
= SvxResId(STR_ViewMarkMorePoints
);
1225 aStr
= SvxResId(STR_ViewMarkPoints
);
1227 } else if (IsMarkGluePoints())
1229 if(HasMarkedGluePoints())
1231 aStr
= SvxResId(STR_ViewMarkMoreGluePoints
);
1235 aStr
= SvxResId(STR_ViewMarkGluePoints
);
1238 else if (IsTextEdit() && mpTextEditOutlinerView
!= nullptr) {
1239 aStr
=SvxResId(STR_ViewTextEdit
); // "TextEdit - Row y, Column x";
1240 ESelection
aSel(mpTextEditOutlinerView
->GetSelection());
1241 tools::Long nPar
= aSel
.nEndPara
,nLin
=0,nCol
=aSel
.nEndPos
;
1242 if (aSel
.nEndPara
>0) {
1243 for (sal_Int32 nParaNum
=0; nParaNum
<aSel
.nEndPara
; nParaNum
++) {
1244 nLin
+= mpTextEditOutliner
->GetLineCount(nParaNum
);
1247 // A little imperfection:
1248 // At the end of a line of any multi-line paragraph, we display the
1249 // position of the next line of the same paragraph, if there is one.
1250 sal_uInt16 nParaLine
= 0;
1251 sal_uLong nParaLineCount
= mpTextEditOutliner
->GetLineCount(aSel
.nEndPara
);
1255 sal_uInt16 nLen
= mpTextEditOutliner
->GetLineLen(aSel
.nEndPara
, nParaLine
);
1256 bool bLastLine
= (nParaLine
== nParaLineCount
- 1);
1257 if (nCol
>nLen
|| (!bLastLine
&& nCol
== nLen
))
1267 bBrk
= true; // to be sure
1270 aStr
= aStr
.replaceFirst("%1", OUString::number(nPar
+ 1));
1271 aStr
= aStr
.replaceFirst("%2", OUString::number(nLin
+ 1));
1272 aStr
= aStr
.replaceFirst("%3", OUString::number(nCol
+ 1));
1275 aStr
+= ", Level " + OUString::number(mpTextEditOutliner
->GetDepth( aSel
.nEndPara
));
1279 if(aStr
== STR_NOTHING
)
1281 if (AreObjectsMarked()) {
1282 aStr
= ImpGetDescriptionString(STR_ViewMarked
);
1283 if (IsGluePointEditMode()) {
1284 if (HasMarkedGluePoints()) {
1285 aStr
= ImpGetDescriptionString(STR_ViewMarked
, ImpGetDescriptionOptions::GLUEPOINTS
);
1288 if (HasMarkedPoints()) {
1289 aStr
= ImpGetDescriptionString(STR_ViewMarked
, ImpGetDescriptionOptions::POINTS
);
1296 else if(!aName
.isEmpty())
1298 aStr
= aStr
.replaceFirst("%1", aName
);
1303 // capitalize first letter
1304 aStr
= aStr
.replaceAt(0, 1, OUString(aStr
[0]).toAsciiUpperCase());
1309 SdrViewContext
SdrView::GetContext() const
1311 if( IsGluePointEditMode() )
1312 return SdrViewContext::GluePointEdit
;
1314 const size_t nMarkCount
= GetMarkedObjectCount();
1316 if( HasMarkablePoints() && !IsFrameHandles() )
1319 for( size_t nMarkNum
= 0; nMarkNum
< nMarkCount
&& bPath
; ++nMarkNum
)
1320 if (dynamic_cast<const SdrPathObj
*>(GetMarkedObjectByIndex(nMarkNum
)) == nullptr)
1324 return SdrViewContext::PointEdit
;
1327 if( GetMarkedObjectCount() )
1329 bool bGraf
= true, bMedia
= true, bTable
= true;
1331 for( size_t nMarkNum
= 0; nMarkNum
< nMarkCount
&& ( bGraf
|| bMedia
); ++nMarkNum
)
1333 const SdrObject
* pMarkObj
= GetMarkedObjectByIndex( nMarkNum
);
1334 DBG_ASSERT( pMarkObj
, "SdrView::GetContext(), null pointer in mark list!" );
1339 if( dynamic_cast<const SdrGrafObj
*>( pMarkObj
) == nullptr )
1342 if( dynamic_cast<const SdrMediaObj
*>( pMarkObj
) == nullptr )
1345 if( dynamic_cast<const sdr::table::SdrTableObj
* >( pMarkObj
) == nullptr )
1350 return SdrViewContext::Graphic
;
1352 return SdrViewContext::Media
;
1354 return SdrViewContext::Table
;
1357 return SdrViewContext::Standard
;
1360 void SdrView::MarkAll()
1363 GetTextEditOutlinerView()->SetSelection(ESelection(0,0,EE_PARA_ALL
,EE_TEXTPOS_ALL
));
1364 } else if (IsGluePointEditMode()) MarkAllGluePoints();
1365 else if (HasMarkablePoints()) MarkAllPoints();
1368 bool bMarkAll
= true;
1369 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
1370 if (rMarkList
.GetMarkCount() == 1)
1372 const SdrObject
* pObj(rMarkList
.GetMark(0)->GetMarkedSdrObj());
1373 SdrView
* pView
= this;
1374 if (pObj
&& pView
&& (pObj
->GetObjInventor() == SdrInventor::Default
)
1375 && (pObj
->GetObjIdentifier() == SdrObjKind::Table
))
1377 mxSelectionController
.clear();
1378 mxSelectionController
= sdr::table::CreateTableController(
1379 *pView
, static_cast<const sdr::table::SdrTableObj
&>(*pObj
),
1380 mxLastSelectionController
);
1382 if (mxSelectionController
.is())
1384 mxLastSelectionController
.clear();
1385 mxSelectionController
->onSelectAll();
1395 void SdrView::UnmarkAll()
1398 ESelection eSel
=GetTextEditOutlinerView()->GetSelection();
1399 eSel
.nStartPara
=eSel
.nEndPara
;
1400 eSel
.nStartPos
=eSel
.nEndPos
;
1401 GetTextEditOutlinerView()->SetSelection(eSel
);
1402 } else if (HasMarkedGluePoints()) UnmarkAllGluePoints();
1403 else if (HasMarkedPoints()) UnmarkAllPoints(); // Marked, not Markable!
1404 else UnmarkAllObj();
1407 const tools::Rectangle
& SdrView::GetMarkedRect() const
1409 if (IsGluePointEditMode() && HasMarkedGluePoints()) {
1410 return GetMarkedGluePointsRect();
1412 if (HasMarkedPoints()) {
1413 return GetMarkedPointsRect();
1415 return GetMarkedObjRect();
1418 void SdrView::DeleteMarked()
1422 SdrObjEditView::KeyInput(KeyEvent(0, vcl::KeyCode(KeyFuncType::DELETE
)), mpTextEditWin
);
1426 if( mxSelectionController
.is() && mxSelectionController
->DeleteMarked() )
1428 // action already performed by current selection controller, do nothing
1430 else if (IsGluePointEditMode() && HasMarkedGluePoints())
1432 DeleteMarkedGluePoints();
1434 else if (GetContext()==SdrViewContext::PointEdit
&& HasMarkedPoints())
1436 DeleteMarkedPoints();
1445 bool SdrView::BegMark(const Point
& rPnt
, bool bAddMark
, bool bUnmark
)
1447 if (bUnmark
) bAddMark
=true;
1448 if (IsGluePointEditMode()) {
1449 if (!bAddMark
) UnmarkAllGluePoints();
1450 return BegMarkGluePoints(rPnt
,bUnmark
);
1451 } else if (HasMarkablePoints()) {
1452 if (!bAddMark
) UnmarkAllPoints();
1453 return BegMarkPoints(rPnt
,bUnmark
);
1455 if (!bAddMark
) UnmarkAllObj();
1456 BegMarkObj(rPnt
,bUnmark
);
1461 bool SdrView::MoveShapeHandle(const sal_uInt32 handleNum
, const Point
& aEndPoint
, const sal_Int32 aObjectOrdNum
)
1463 if (GetHdlList().IsMoveOutside())
1466 if (!GetMarkedObjectList().GetMarkCount())
1469 SdrHdl
* pHdl
= GetHdlList().GetHdl(handleNum
);
1470 if (pHdl
== nullptr)
1473 SdrDragStat
& rDragStat
= const_cast<SdrDragStat
&>(GetDragStat());
1475 BegDragObj(pHdl
->GetPos(), nullptr, pHdl
, 0);
1479 bool bWasNoSnap
= rDragStat
.IsNoSnap();
1480 bool bWasSnapEnabled
= IsSnapEnabled();
1482 // switch snapping off
1484 rDragStat
.SetNoSnap();
1486 SetSnapEnabled(false);
1488 if (aObjectOrdNum
!= -1)
1490 rDragStat
.GetGlueOptions().objectOrdNum
= aObjectOrdNum
;
1492 MovDragObj(aEndPoint
);
1495 // Clear Glue Options
1496 rDragStat
.GetGlueOptions().objectOrdNum
= -1;
1499 rDragStat
.SetNoSnap(bWasNoSnap
);
1500 if (bWasSnapEnabled
)
1501 SetSnapEnabled(bWasSnapEnabled
);
1506 void SdrView::ConfigurationChanged( ::utl::ConfigurationBroadcaster
*p
, ConfigurationHints nHint
)
1508 onAccessibilityOptionsChanged();
1509 SdrCreateView::ConfigurationChanged(p
, nHint
);
1513 /** method is called whenever the global SvtAccessibilityOptions is changed */
1514 void SdrView::onAccessibilityOptionsChanged()
1518 void SdrView::SetMasterPagePaintCaching(bool bOn
)
1520 if(mbMasterPagePaintCaching
== bOn
)
1523 mbMasterPagePaintCaching
= bOn
;
1525 // reset at all SdrPageWindows
1526 SdrPageView
* pPageView
= GetSdrPageView();
1531 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1533 SdrPageWindow
* pPageWindow
= pPageView
->GetPageWindow(b
);
1534 assert(pPageWindow
&& "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)");
1536 // force deletion of ObjectContact, so at re-display all VOCs
1537 // will be re-created with updated flag setting
1538 pPageWindow
->ResetObjectContact();
1541 // force redraw of this view
1542 pPageView
->InvalidateAllWin();
1545 // Default ObjectContact is ObjectContactOfPageView
1546 sdr::contact::ObjectContact
* SdrView::createViewSpecificObjectContact(
1547 SdrPageWindow
& rPageWindow
,
1548 const char* pDebugName
) const
1550 return new sdr::contact::ObjectContactOfPageView(rPageWindow
, pDebugName
);
1553 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */