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/eeitem.hxx>
21 #include <editeng/outlobj.hxx>
23 #include <svx/strings.hrc>
24 #include <svx/dialmgr.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdmrkv.hxx>
27 #include <svx/svdedxv.hxx>
28 #include <svx/svdobj.hxx>
29 #include <svx/svdopath.hxx>
30 #include <svx/svdograf.hxx>
31 #include <svx/svdomedia.hxx>
32 #include <svx/svdetc.hxx>
35 #include <svdibrow.hxx>
38 #include <svx/svdoutl.hxx>
39 #include <svx/svdview.hxx>
40 #include <editeng/editview.hxx>
41 #include <editeng/flditem.hxx>
42 #include <svx/obj3d.hxx>
43 #include <svx/svddrgmt.hxx>
44 #include <svx/svdotable.hxx>
45 #include <tools/debug.hxx>
46 #include <tools/tenccvt.hxx>
47 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
48 #include <svx/sdr/overlay/overlaymanager.hxx>
49 #include <svx/sdrpaintwindow.hxx>
50 #include <svx/sdrpagewindow.hxx>
51 #include <svx/sdrhittesthelper.hxx>
52 #include <svx/sdr/contact/viewcontact.hxx>
53 #include <drawinglayer/processor2d/contourextractor2d.hxx>
54 #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
55 #include <svx/sdr/contact/objectcontactofpageview.hxx>
56 #include <sal/log.hxx>
57 #include <vcl/ptrstyle.hxx>
60 SdrViewEvent::SdrViewEvent()
66 eHit(SdrHitKind::NONE
),
67 eEvent(SdrEventKind::NONE
),
69 nMouseMode(MouseEventModifiers::NONE
),
84 SdrViewEvent::~SdrViewEvent()
89 // helper class for all D&D overlays
91 void SdrDropMarkerOverlay::ImplCreateOverlays(
93 const basegfx::B2DPolyPolygon
& rLinePolyPolygon
)
95 for(sal_uInt32
a(0); a
< rView
.PaintWindowCount(); a
++)
97 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
98 const rtl::Reference
< sdr::overlay::OverlayManager
>& xTargetOverlay
= pCandidate
->GetOverlayManager();
100 if (xTargetOverlay
.is())
102 std::unique_ptr
<sdr::overlay::OverlayPolyPolygonStripedAndFilled
> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
105 xTargetOverlay
->add(*pNew
);
106 maObjects
.append(std::move(pNew
));
111 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const SdrObject
& rObject
)
115 rObject
.TakeXorPoly());
118 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const tools::Rectangle
& rRectangle
)
120 basegfx::B2DPolygon aB2DPolygon
;
122 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()));
123 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
124 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
125 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
126 aB2DPolygon
.setClosed(true);
130 basegfx::B2DPolyPolygon(aB2DPolygon
));
133 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const Point
& rStart
, const Point
& rEnd
)
135 basegfx::B2DPolygon aB2DPolygon
;
137 aB2DPolygon
.append(basegfx::B2DPoint(rStart
.X(), rStart
.Y()));
138 aB2DPolygon
.append(basegfx::B2DPoint(rEnd
.X(), rEnd
.Y()));
139 aB2DPolygon
.setClosed(true);
143 basegfx::B2DPolyPolygon(aB2DPolygon
));
146 SdrDropMarkerOverlay::~SdrDropMarkerOverlay()
148 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
149 // That destructor calls clear() at the list which removes all objects from the
150 // OverlayManager and deletes them.
156 : SdrCreateView(rSdrModel
, pOut
),
157 bNoExtendedMouseDispatcher(false),
158 bNoExtendedKeyDispatcher(false),
159 mbMasterPagePaintCaching(false)
161 maAccessibilityOptions
.AddListener(this);
162 onAccessibilityOptionsChanged();
167 maAccessibilityOptions
.RemoveListener(this);
170 bool SdrView::KeyInput(const KeyEvent
& rKEvt
, vcl::Window
* pWin
)
173 bool bRet
= SdrCreateView::KeyInput(rKEvt
,pWin
);
174 if (!bRet
&& !IsExtendedKeyInputDispatcherEnabled()) {
176 switch (rKEvt
.GetKeyCode().GetFullFunction()) {
177 case KeyFuncType::DELETE
: DeleteMarked(); break;
178 case KeyFuncType::UNDO
: mpModel
->Undo(); break;
179 case KeyFuncType::REDO
: mpModel
->Redo(); break;
180 case KeyFuncType::REPEAT
: mpModel
->Repeat(*this); break;
182 switch (rKEvt
.GetKeyCode().GetFullCode()) {
184 if (IsTextEdit()) SdrEndTextEdit();
185 if (IsAction()) BrkAction();
186 if (pWin
!=nullptr) pWin
->ReleaseMouse();
188 case KEY_DELETE
: DeleteMarked(); break;
189 case KEY_UNDO
: case KEY_BACKSPACE
+KEY_MOD2
: mpModel
->Undo(); break;
190 case KEY_BACKSPACE
+KEY_MOD2
+KEY_SHIFT
: mpModel
->Redo(); break;
191 case KEY_REPEAT
: case KEY_BACKSPACE
+KEY_MOD2
+KEY_MOD1
: mpModel
->Repeat(*this); break;
192 case KEY_MOD1
+KEY_A
: MarkAll(); break;
197 if (bRet
&& pWin
!=nullptr) {
198 pWin
->SetPointer(GetPreferredPointer(
199 pWin
->PixelToLogic(pWin
->ScreenToOutputPixel( pWin
->GetPointerPosPixel() ) ),
201 rKEvt
.GetKeyCode().GetModifier()));
207 bool SdrView::MouseButtonDown(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
210 if (rMEvt
.IsLeft()) maDragStat
.SetMouseDown(true);
211 bool bRet
= SdrCreateView::MouseButtonDown(rMEvt
,pWin
);
212 if (!bRet
&& !IsExtendedMouseEventDispatcherEnabled()) {
214 PickAnything(rMEvt
,SdrMouseEventKind::BUTTONDOWN
,aVEvt
);
215 bRet
= DoMouseEvent(aVEvt
);
220 bool SdrView::MouseButtonUp(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
223 if (rMEvt
.IsLeft()) maDragStat
.SetMouseDown(false);
224 bool bAction
= IsAction();
225 bool bRet
= !bAction
&& SdrCreateView::MouseButtonUp(rMEvt
,pWin
);
226 if (!bRet
&& !IsExtendedMouseEventDispatcherEnabled()) {
228 PickAnything(rMEvt
,SdrMouseEventKind::BUTTONUP
,aVEvt
);
229 bRet
= DoMouseEvent(aVEvt
);
234 bool SdrView::MouseMove(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
237 maDragStat
.SetMouseDown(rMEvt
.IsLeft());
238 bool bRet
= SdrCreateView::MouseMove(rMEvt
,pWin
);
239 if (!IsExtendedMouseEventDispatcherEnabled() && !IsTextEditInSelectionMode()) {
241 PickAnything(rMEvt
,SdrMouseEventKind::MOVE
,aVEvt
);
242 if (DoMouseEvent(aVEvt
)) bRet
=true;
248 bool SdrView::Command(const CommandEvent
& rCEvt
, vcl::Window
* pWin
)
251 bool bRet
= SdrCreateView::Command(rCEvt
,pWin
);
255 void SdrView::GetAttributes(SfxItemSet
& rTargetSet
, bool bOnlyHardAttr
) const
257 SdrCreateView::GetAttributes(rTargetSet
, bOnlyHardAttr
);
260 SdrHitKind
SdrView::PickAnything(const MouseEvent
& rMEvt
, SdrMouseEventKind nEventKind
, SdrViewEvent
& rVEvt
) const
262 rVEvt
.bMouseDown
=nEventKind
==SdrMouseEventKind::BUTTONDOWN
;
263 rVEvt
.bMouseUp
=nEventKind
==SdrMouseEventKind::BUTTONUP
;
264 rVEvt
.nMouseClicks
=rMEvt
.GetClicks();
265 rVEvt
.nMouseMode
=rMEvt
.GetMode();
266 rVEvt
.nMouseCode
=rMEvt
.GetButtons() | rMEvt
.GetModifier();
267 const OutputDevice
* pOut
=mpActualOutDev
;
270 pOut
= GetFirstOutputDevice();
272 Point
aPnt(rMEvt
.GetPosPixel());
273 if (pOut
!=nullptr) aPnt
=pOut
->PixelToLogic(aPnt
);
274 rVEvt
.aLogicPos
=aPnt
;
275 return PickAnything(aPnt
,rVEvt
);
278 // Dragging with the Mouse (Move)
279 // Example when creating a rectangle: MouseDown has to happen without a ModKey,
280 // else we usually force a selection (see below).
281 // When pressing Shift, Ctrl and Alt at the same time while doing a MouseMove,
282 // a centered, not snapped square is created.
283 // The dual allocation of Ortho and Shift won't usually create a problem, as the
284 // two functions are in most cases mutually exclusive. Only shearing (the kind
285 // that happens when contorting, not when rotating) can use both functions at
286 // the same time. To get around this, the user can use e. g. help lines.
287 #define MODKEY_NoSnap bCtrl /* temporarily disable snapping */
288 #define MODKEY_Ortho bShift /* ortho */
289 #define MODKEY_Center bAlt /* create/resize centeredly */
290 #define MODKEY_AngleSnap bShift
291 #define MODKEY_CopyDrag bCtrl /* drag and copy */
293 // click somewhere (MouseDown)
294 #define MODKEY_PolyPoly bAlt /* new Poly at InsPt and at Create */
295 #define MODKEY_MultiMark bShift /* MarkObj without doing UnmarkAll first */
296 #define MODKEY_Unmark bAlt /* deselect with a dragged frame */
297 #define MODKEY_ForceMark bCtrl /* force dragging a frame, even if there's an object at cursor position */
298 #define MODKEY_DeepMark bAlt /* MarkNextObj */
299 #define MODKEY_DeepBackw bShift /* MarkNextObj but backwards */
301 SdrHitKind
SdrView::PickAnything(const Point
& rLogicPos
, SdrViewEvent
& rVEvt
) const
303 const OutputDevice
* pOut
=mpActualOutDev
;
306 pOut
= GetFirstOutputDevice();
309 // #i73628# Use a non-changeable copy of he logic position
310 const Point
aLocalLogicPosition(rLogicPos
);
312 bool bEditMode
=IsEditMode();
313 bool bPointMode
=bEditMode
&& HasMarkablePoints();
314 bool bGluePointMode
=IsGluePointEditMode();
315 bool bInsPolyPt
=bPointMode
&& IsInsObjPointMode() && IsInsObjPointPossible();
316 bool bInsGluePt
=bGluePointMode
&& IsInsGluePointMode() && IsInsGluePointPossible();
317 bool bIsTextEdit
=IsTextEdit();
318 bool bTextEditHit
=IsTextEditHit(aLocalLogicPosition
);
319 bool bTextEditSel
=IsTextEditInSelectionMode();
320 bool bShift
=(rVEvt
.nMouseCode
& KEY_SHIFT
) !=0;
321 bool bCtrl
=(rVEvt
.nMouseCode
& KEY_MOD1
) !=0;
322 bool bAlt
=(rVEvt
.nMouseCode
& KEY_MOD2
) !=0;
323 SdrHitKind eHit
=SdrHitKind::NONE
;
324 SdrHdl
* pHdl
=pOut
!=nullptr && !bTextEditSel
? PickHandle(aLocalLogicPosition
) : nullptr;
325 SdrPageView
* pPV
=nullptr;
326 SdrObject
* pObj
=nullptr;
327 SdrObject
* pHitObj
=nullptr;
328 bool bHitPassDirect
=true;
329 sal_uInt16 nHlplIdx
=0;
330 sal_uInt16 nGlueId
=0;
331 if (bTextEditHit
|| bTextEditSel
)
333 eHit
=SdrHitKind::TextEdit
;
336 else if (pHdl
!=nullptr)
338 eHit
=SdrHitKind::Handle
; // handle is hit: highest priority
340 else if (bEditMode
&& IsHlplVisible() && IsHlplFront() && pOut
!=nullptr && PickHelpLine(aLocalLogicPosition
,mnHitTolLog
,*pOut
,nHlplIdx
,pPV
))
342 eHit
=SdrHitKind::HelpLine
; // help line in the foreground hit: can be moved now
344 else if (bGluePointMode
&& PickGluePoint(aLocalLogicPosition
,pObj
,nGlueId
,pPV
))
346 eHit
=SdrHitKind::Gluepoint
; // deselected glue point hit
348 else if ((pHitObj
= PickObj(aLocalLogicPosition
,mnHitTolLog
,pPV
,SdrSearchOptions::DEEP
|SdrSearchOptions::MARKED
,&pObj
,&bHitPassDirect
)))
350 eHit
=SdrHitKind::MarkedObject
;
351 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast< sdr::table::SdrTableObj
* >( pObj
);
354 sal_Int32 nX
= 0, nY
= 0;
355 switch( pTableObj
->CheckTableHit( aLocalLogicPosition
, nX
, nY
) )
357 case sdr::table::TableHitKind::Cell
:
358 eHit
= SdrHitKind::Cell
;
360 case sdr::table::TableHitKind::CellTextArea
:
361 eHit
= SdrHitKind::TextEditObj
;
368 else if ((pHitObj
= PickObj(aLocalLogicPosition
,mnHitTolLog
,pPV
,SdrSearchOptions::DEEP
|SdrSearchOptions::ALSOONMASTER
|SdrSearchOptions::WHOLEPAGE
,&pObj
,&bHitPassDirect
)))
370 // MasterPages and WholePage for Macro and URL
371 eHit
=SdrHitKind::UnmarkedObject
;
372 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast< sdr::table::SdrTableObj
* >( pObj
);
375 sal_Int32 nX
= 0, nY
= 0;
376 switch( pTableObj
->CheckTableHit( aLocalLogicPosition
, nX
, nY
, mnHitTolLog
) )
378 case sdr::table::TableHitKind::Cell
:
379 eHit
= SdrHitKind::Cell
;
381 case sdr::table::TableHitKind::CellTextArea
:
382 // Keep state on UnmarkedObject to allow the below
383 // 'check for URL field' to be executed, else popups
384 // for e.g. URL links when hoovering and clicking
385 // them will not work. Tried several other changes,
386 // but this one safely keeps existing behaviour as-is.
387 eHit
= SdrHitKind::UnmarkedObject
;
394 else if (bEditMode
&& IsHlplVisible() && !IsHlplFront() && pOut
!=nullptr && PickHelpLine(aLocalLogicPosition
,mnHitTolLog
,*pOut
,nHlplIdx
,pPV
))
396 eHit
=SdrHitKind::HelpLine
; // help line in foreground hit: can be moved now
398 if (eHit
==SdrHitKind::UnmarkedObject
)
400 bool bRoot
=pObj
->HasMacro();
401 bool bDeep
=pObj
!=pHitObj
&& pHitObj
->HasMacro();
402 bool bMid
=false; // Have we hit upon a grouped group with a macro?
403 SdrObject
* pMidObj
=nullptr;
406 SdrObject
* pObjTmp
=pHitObj
->getParentSdrObjectFromSdrObject();
407 if (pObjTmp
==pObj
) pObjTmp
=nullptr;
408 while (pObjTmp
!=nullptr)
410 if (pObjTmp
->HasMacro())
415 pObjTmp
=pObjTmp
->getParentSdrObjectFromSdrObject();
416 if (pObjTmp
==pObj
) pObjTmp
=nullptr;
420 if (bDeep
|| bMid
|| bRoot
)
422 SdrObjMacroHitRec aHitRec
;
423 aHitRec
.aPos
=aLocalLogicPosition
;
424 aHitRec
.nTol
=mnHitTolLog
;
425 aHitRec
.pVisiLayer
=&pPV
->GetVisibleLayers();
426 aHitRec
.pPageView
=pPV
;
427 if (bDeep
) bDeep
=pHitObj
->IsMacroHit(aHitRec
);
428 if (bMid
) bMid
=pMidObj
->IsMacroHit(aHitRec
);
429 if (bRoot
) bRoot
=pObj
->IsMacroHit(aHitRec
);
430 if (bRoot
|| bMid
|| bDeep
)
432 // Priorities: 1. Root, 2. Mid, 3. Deep
434 if (!bRoot
) pObj
=pMidObj
;
435 if (!bRoot
&& !bMid
) pObj
=pHitObj
;
436 eHit
=SdrHitKind::Macro
;
440 // check for URL field
441 if (eHit
==SdrHitKind::UnmarkedObject
)
443 SdrTextObj
* pTextObj
=dynamic_cast<SdrTextObj
*>( pHitObj
);
444 if (pTextObj
!=nullptr && pTextObj
->HasText())
446 // use the primitive-based HitTest which is more accurate anyways. It
447 // will correctly handle rotated/mirrored/sheared/scaled text and can
448 // now return a HitContainer containing the primitive hierarchy of the
449 // primitive that triggered the hit. The first entry is that primitive,
450 // the others are the full stack of primitives leading to that one which
451 // includes grouping primitives (like TextHierarchyPrimitives we deed here)
452 // but also all decomposed ones which lead to the creation of that primitive
453 drawinglayer::primitive2d::Primitive2DContainer aHitContainer
;
454 const bool bTEHit(pPV
&& SdrObjectPrimitiveHit(*pTextObj
, aLocalLogicPosition
, 0, *pPV
, &pPV
->GetVisibleLayers(), true, &aHitContainer
));
456 if (bTEHit
&& !aHitContainer
.empty())
458 // search for TextHierarchyFieldPrimitive2D which contains the needed information
459 // about a possible URLField
460 const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D
* pTextHierarchyFieldPrimitive2D
= nullptr;
462 for (const drawinglayer::primitive2d::Primitive2DReference
& xReference
: aHitContainer
)
466 // try to cast to drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D implementation
467 pTextHierarchyFieldPrimitive2D
= dynamic_cast<const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D
*>(xReference
.get());
469 if (pTextHierarchyFieldPrimitive2D
)
476 if (nullptr != pTextHierarchyFieldPrimitive2D
)
478 if (drawinglayer::primitive2d::FieldType::FIELD_TYPE_URL
== pTextHierarchyFieldPrimitive2D
->getType())
480 // problem with the old code is that a *pointer* to an instance of
481 // SvxURLField is set in the Event which is per se not good since that
482 // data comes from a temporary EditEngine's data and could vanish any
483 // moment. Have to replace for now with a static instance that gets
484 // filled/initialized from the original data held in the TextHierarchyField-
485 // Primitive2D (see impTextBreakupHandler::impCheckFieldPrimitive).
486 // Unfortunately things like 'TargetFrame' are still used in Calc, so this
487 // can currently not get replaced. For the future the Name/Value vector or
488 // the TextHierarchyFieldPrimitive2D itself should/will be used for handling
490 static SvxURLField aSvxURLField
;
492 aSvxURLField
.SetURL(pTextHierarchyFieldPrimitive2D
->getValue("URL"));
493 aSvxURLField
.SetRepresentation(pTextHierarchyFieldPrimitive2D
->getValue("Representation"));
494 aSvxURLField
.SetTargetFrame(pTextHierarchyFieldPrimitive2D
->getValue("TargetFrame"));
495 const OUString
aFormat(pTextHierarchyFieldPrimitive2D
->getValue("SvxURLFormat"));
497 if (!aFormat
.isEmpty())
499 aSvxURLField
.SetFormat(static_cast<SvxURLFormat
>(aFormat
.toInt32()));
502 // set HitKind and pointer to local static instance in the Event
503 // to comply to old stuff
504 eHit
= SdrHitKind::UrlField
;
505 rVEvt
.pURLField
= &aSvxURLField
;
512 if (bHitPassDirect
&&
513 (eHit
==SdrHitKind::MarkedObject
|| eHit
==SdrHitKind::UnmarkedObject
) &&
514 (IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj
->HasTextEdit())
516 // Around the TextEditArea there's a border to select without going into text edit mode.
517 tools::Rectangle
aBoundRect(pHitObj
->GetCurrentBoundRect());
519 // Force to SnapRect when Fontwork
520 if( dynamic_cast<const SdrTextObj
*>( pHitObj
) != nullptr && static_cast<SdrTextObj
*>(pHitObj
)->IsFontwork())
522 aBoundRect
= pHitObj
->GetSnapRect();
525 sal_Int32
nTolerance(mnHitTolLog
);
526 bool bBoundRectHit(false);
530 nTolerance
= pOut
->PixelToLogic(Size(2, 0)).Width();
533 if( (aLocalLogicPosition
.X() >= aBoundRect
.Left() - nTolerance
&& aLocalLogicPosition
.X() <= aBoundRect
.Left() + nTolerance
)
534 || (aLocalLogicPosition
.X() >= aBoundRect
.Right() - nTolerance
&& aLocalLogicPosition
.X() <= aBoundRect
.Right() + nTolerance
)
535 || (aLocalLogicPosition
.Y() >= aBoundRect
.Top() - nTolerance
&& aLocalLogicPosition
.Y() <= aBoundRect
.Top() + nTolerance
)
536 || (aLocalLogicPosition
.Y() >= aBoundRect
.Bottom() - nTolerance
&& aLocalLogicPosition
.Y() <= aBoundRect
.Bottom() + nTolerance
))
538 bBoundRectHit
= true;
544 SdrObjectPrimitiveHit(*pHitObj
, aLocalLogicPosition
, 0, *pPV
, &pPV
->GetVisibleLayers(), true));
546 // TextEdit attached to an object in a locked layer
547 if (pPV
->GetLockedLayers().IsSet(pHitObj
->GetLayer()))
556 eHit
=SdrHitKind::TextEditObj
;
560 if (!bHitPassDirect
&& eHit
==SdrHitKind::UnmarkedObject
) {
561 eHit
=SdrHitKind::NONE
;
565 bool bMouseLeft
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0;
566 bool bMouseRight
=(rVEvt
.nMouseCode
&MOUSE_RIGHT
)!=0;
567 bool bMouseDown
=rVEvt
.bMouseDown
;
568 bool bMouseUp
=rVEvt
.bMouseUp
;
569 SdrEventKind eEvent
=SdrEventKind::NONE
;
570 bool bIsAction
=IsAction();
576 if (bMouseRight
) eEvent
=SdrEventKind::BackAction
;
582 eEvent
=SdrEventKind::EndAction
;
585 eEvent
=SdrEventKind::EndDrag
;
587 else if (IsCreateObj() || IsInsObjPoint())
589 eEvent
=IsCreateObj() ? SdrEventKind::EndCreate
: SdrEventKind::EndInsertObjPoint
;
591 else if (IsMarking())
593 eEvent
=SdrEventKind::EndMark
;
594 if (!maDragStat
.IsMinMoved())
596 eEvent
=SdrEventKind::BrkMark
;
597 rVEvt
.bAddMark
=MODKEY_MultiMark
;
604 eEvent
=SdrEventKind::MoveAction
;
607 else if (eHit
==SdrHitKind::TextEdit
)
609 eEvent
=SdrEventKind::TextEdit
;
611 else if (bMouseDown
&& bMouseLeft
)
613 if (rVEvt
.nMouseClicks
==2 && rVEvt
.nMouseCode
==MOUSE_LEFT
&& pObj
!=nullptr && pHitObj
!=nullptr && pHitObj
->HasTextEdit() && eHit
==SdrHitKind::MarkedObject
)
617 eEvent
=SdrEventKind::BeginTextEdit
;
619 else if (MODKEY_ForceMark
&& eHit
!=SdrHitKind::UrlField
)
621 eEvent
=SdrEventKind::BeginMark
; // AddMark,Unmark */
623 else if (eHit
==SdrHitKind::HelpLine
)
625 eEvent
=SdrEventKind::BeginDragHelpline
; // nothing, actually
627 else if (eHit
==SdrHitKind::Gluepoint
)
629 eEvent
=SdrEventKind::MarkGluePoint
; // AddMark+Drag
630 rVEvt
.bAddMark
=MODKEY_MultiMark
|| MODKEY_DeepMark
; // if not hit with Deep
632 else if (eHit
==SdrHitKind::Handle
)
634 eEvent
=SdrEventKind::BeginDragObj
; // Mark+Drag,AddMark+Drag,DeepMark+Drag,Unmark
635 bool bGlue
=pHdl
->GetKind()==SdrHdlKind::Glue
;
636 bool bPoly
=!bGlue
&& IsPointMarkable(*pHdl
);
637 bool bMarked
=bGlue
|| (bPoly
&& pHdl
->IsSelected());
640 eEvent
=bGlue
? SdrEventKind::MarkGluePoint
: SdrEventKind::MarkPoint
;
644 rVEvt
.bPrevNextMark
=true;
645 rVEvt
.bMarkPrev
=MODKEY_DeepBackw
;
647 else if (MODKEY_MultiMark
)
650 rVEvt
.bUnmark
=bMarked
; // Toggle
654 nGlueId
=static_cast<sal_uInt16
>(pHdl
->GetObjHdlNum());
659 eEvent
=SdrEventKind::BeginDragObj
; // don't change MarkState, only change Drag
663 else if (bInsPolyPt
&& (MODKEY_PolyPoly
|| (!MODKEY_MultiMark
&& !MODKEY_DeepMark
)))
665 eEvent
=SdrEventKind::BeginInsertObjPoint
;
667 else if (bInsGluePt
&& !MODKEY_MultiMark
&& !MODKEY_DeepMark
)
669 eEvent
=SdrEventKind::BeginInsertGluePoint
;
671 else if (eHit
==SdrHitKind::TextEditObj
)
673 eEvent
=SdrEventKind::BeginTextEdit
; // AddMark+Drag,DeepMark+Drag,Unmark
674 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
675 { // if not hit with Deep
676 eEvent
=SdrEventKind::MarkObj
;
679 else if (eHit
==SdrHitKind::Macro
)
681 eEvent
=SdrEventKind::BeginMacroObj
; // AddMark+Drag
682 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
683 { // if not hit with Deep
684 eEvent
=SdrEventKind::MarkObj
;
687 else if (eHit
==SdrHitKind::UrlField
)
689 eEvent
=SdrEventKind::ExecuteUrl
; // AddMark+Drag
690 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
691 { // if not hit with Deep
692 eEvent
=SdrEventKind::MarkObj
;
695 else if (eHit
==SdrHitKind::MarkedObject
)
697 eEvent
=SdrEventKind::BeginDragObj
; // DeepMark+Drag,Unmark
699 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
700 { // if not hit with Deep
701 eEvent
=SdrEventKind::MarkObj
;
704 else if (IsCreateMode())
706 eEvent
=SdrEventKind::BeginCreateObj
; // nothing, actually
708 else if (eHit
==SdrHitKind::UnmarkedObject
)
710 eEvent
=SdrEventKind::MarkObj
; // AddMark+Drag
714 eEvent
=SdrEventKind::BeginMark
;
717 if (eEvent
==SdrEventKind::MarkObj
)
719 rVEvt
.bAddMark
=MODKEY_MultiMark
|| MODKEY_DeepMark
; // if not hit with Deep
720 rVEvt
.bPrevNextMark
=MODKEY_DeepMark
;
721 rVEvt
.bMarkPrev
=MODKEY_DeepMark
&& MODKEY_DeepBackw
;
723 if (eEvent
==SdrEventKind::BeginMark
)
725 rVEvt
.bAddMark
=MODKEY_MultiMark
;
726 rVEvt
.bUnmark
=MODKEY_Unmark
;
729 rVEvt
.bIsAction
=bIsAction
;
730 rVEvt
.bIsTextEdit
=bIsTextEdit
;
731 rVEvt
.aLogicPos
=aLocalLogicPosition
;
734 if(rVEvt
.pRootObj
==nullptr)
737 rVEvt
.nHlplIdx
=nHlplIdx
;
738 rVEvt
.nGlueId
=nGlueId
;
742 if (rVEvt
.pRootObj
!=NULL
) {
743 if (rVEvt
.pRootObj
->getParentSdrObjListFromSdrObject()!=rVEvt
.pPV
->GetObjList()) {
744 OSL_FAIL("SdrView::PickAnything(): pRootObj->getParentSdrObjListFromSdrObject()!=pPV->GetObjList() !");
751 bool SdrView::DoMouseEvent(const SdrViewEvent
& rVEvt
)
754 SdrHitKind eHit
=rVEvt
.eHit
;
755 Point
aLogicPos(rVEvt
.aLogicPos
);
757 bool bShift
=(rVEvt
.nMouseCode
& KEY_SHIFT
) !=0;
758 bool bCtrl
=(rVEvt
.nMouseCode
& KEY_MOD1
) !=0;
759 bool bAlt
=(rVEvt
.nMouseCode
& KEY_MOD2
) !=0;
760 bool bMouseLeft
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0;
761 bool bMouseDown
=rVEvt
.bMouseDown
;
762 bool bMouseUp
=rVEvt
.bMouseUp
;
764 if (bMouseLeft
) maDragStat
.SetMouseDown(true);
765 } else if (bMouseUp
) {
766 if (bMouseLeft
) maDragStat
.SetMouseDown(false);
767 } else { // else, MouseMove
768 maDragStat
.SetMouseDown(bMouseLeft
);
772 SetSnapEnabled(!MODKEY_NoSnap
);
775 SetOrtho(MODKEY_Ortho
!=IsOrthoDesired());
777 #ifdef MODKEY_AngleSnap
778 SetAngleSnapEnabled(MODKEY_AngleSnap
);
780 #ifdef MODKEY_CopyDrag
781 SetDragWithCopy(MODKEY_CopyDrag
);
784 SetCreate1stPointAsCenter(MODKEY_Center
);
785 SetResizeAtCenter(MODKEY_Center
);
786 SetCrookAtCenter(MODKEY_Center
);
788 if (bMouseLeft
&& bMouseDown
&& rVEvt
.bIsTextEdit
&& (eHit
==SdrHitKind::UnmarkedObject
|| eHit
==SdrHitKind::NONE
)) {
789 SdrEndTextEdit(); // User has clicked beneath object, exit edit mode.
790 // pHdl is invalid, then, that shouldn't matter, though, as we expect
791 // pHdl==NULL (because of eHit).
793 switch (rVEvt
.eEvent
) {
794 case SdrEventKind::NONE
: bRet
=false; break;
795 case SdrEventKind::TextEdit
: bRet
=false; break; // Events handled by the OutlinerView are not taken into account here.
796 case SdrEventKind::MoveAction
: MovAction(aLogicPos
); bRet
=true; break;
797 case SdrEventKind::EndAction
: EndAction(); bRet
=true; break;
798 case SdrEventKind::BackAction
: BckAction(); bRet
=true; break;
799 case SdrEventKind::EndMark
: EndAction(); bRet
=true; break;
800 case SdrEventKind::BrkMark
: {
802 if (!MarkObj(aLogicPos
,mnHitTolLog
,rVEvt
.bAddMark
)) {
803 // No object hit. Do the following:
804 // 1. deselect any selected glue points
805 // 2. deselect any selected polygon points
806 // 3. deselect any selected objects
807 if (!rVEvt
.bAddMark
) UnmarkAll();
811 case SdrEventKind::EndCreate
: { // if necessary, MarkObj
812 SdrCreateCmd eCmd
=SdrCreateCmd::NextPoint
;
813 if (MODKEY_PolyPoly
) eCmd
=SdrCreateCmd::NextObject
;
814 if (rVEvt
.nMouseClicks
>1) eCmd
=SdrCreateCmd::ForceEnd
;
815 if (!EndCreateObj(eCmd
)) { // Don't evaluate event for Create? -> Select
816 if (eHit
==SdrHitKind::UnmarkedObject
|| eHit
==SdrHitKind::TextEdit
) {
817 MarkObj(rVEvt
.pRootObj
,rVEvt
.pPV
);
818 if (eHit
==SdrHitKind::TextEdit
)
820 bool bRet2(mpActualOutDev
&& OUTDEV_WINDOW
== mpActualOutDev
->GetOutDevType() &&
821 SdrBeginTextEdit(rVEvt
.pObj
, rVEvt
.pPV
, static_cast<vcl::Window
*>(mpActualOutDev
.get())));
825 MouseEvent
aMEvt(mpActualOutDev
->LogicToPixel(aLogicPos
),
826 1,rVEvt
.nMouseMode
,rVEvt
.nMouseCode
,rVEvt
.nMouseCode
);
828 OutlinerView
* pOLV
=GetTextEditOutlinerView();
830 pOLV
->MouseButtonDown(aMEvt
); // event for the Outliner, but without double-click
831 pOLV
->MouseButtonUp(aMEvt
); // event for the Outliner, but without double-click
835 bRet
=true; // object is selected and (if necessary) TextEdit is started
836 } else bRet
=false; // canceled Create, nothing else
837 } else bRet
=true; // return true for EndCreate
839 case SdrEventKind::EndDrag
: {
840 bRet
=EndDragObj(IsDragWithCopy());
841 ForceMarkedObjToAnotherPage(); // TODO: Undo+bracing missing!
843 case SdrEventKind::MarkObj
: { // + (if applicable) BegDrag
844 if (!rVEvt
.bAddMark
) UnmarkAllObj();
845 bool bUnmark
=rVEvt
.bUnmark
;
846 if (rVEvt
.bPrevNextMark
) {
847 bRet
=MarkNextObj(aLogicPos
,mnHitTolLog
,rVEvt
.bMarkPrev
);
850 const size_t nCount0
=GetMarkedObjectCount();
851 bRet
=MarkObj(aLogicPos
,mnHitTolLog
,rVEvt
.bAddMark
);
853 const size_t nCount1
=GetMarkedObjectCount();
854 bUnmark
=nCount1
<nCount0
;
857 BegDragObj(aLogicPos
,nullptr,nullptr,mnMinMovLog
);
861 case SdrEventKind::MarkPoint
: { // + (if applicable) BegDrag
862 if (!rVEvt
.bAddMark
) UnmarkAllPoints();
863 if (rVEvt
.bPrevNextMark
) {
867 bRet
=MarkPoint(*rVEvt
.pHdl
,rVEvt
.bUnmark
);
869 if (!rVEvt
.bUnmark
&& !rVEvt
.bPrevNextMark
) {
870 BegDragObj(aLogicPos
,nullptr,rVEvt
.pHdl
,mnMinMovLog
);
874 case SdrEventKind::MarkGluePoint
: { // + (if applicable) BegDrag
875 if (!rVEvt
.bAddMark
) UnmarkAllGluePoints();
876 if (rVEvt
.bPrevNextMark
) {
880 bRet
=MarkGluePoint(rVEvt
.pObj
,rVEvt
.nGlueId
,rVEvt
.bUnmark
);
882 if (!rVEvt
.bUnmark
&& !rVEvt
.bPrevNextMark
) {
883 SdrHdl
* pHdl
=GetGluePointHdl(rVEvt
.pObj
,rVEvt
.nGlueId
);
884 BegDragObj(aLogicPos
,nullptr,pHdl
,mnMinMovLog
);
888 case SdrEventKind::BeginMark
: bRet
=BegMark(aLogicPos
,rVEvt
.bAddMark
,rVEvt
.bUnmark
); break;
889 case SdrEventKind::BeginInsertObjPoint
: bRet
= BegInsObjPoint(aLogicPos
, MODKEY_PolyPoly
); break;
890 case SdrEventKind::EndInsertObjPoint
: {
891 SdrCreateCmd eCmd
=SdrCreateCmd::NextPoint
;
892 if (MODKEY_PolyPoly
) eCmd
=SdrCreateCmd::NextObject
;
893 if (rVEvt
.nMouseClicks
>1) eCmd
=SdrCreateCmd::ForceEnd
;
894 EndInsObjPoint(eCmd
);
897 case SdrEventKind::BeginInsertGluePoint
: bRet
=BegInsGluePoint(aLogicPos
); break;
898 case SdrEventKind::BeginDragHelpline
: bRet
=BegDragHelpLine(rVEvt
.nHlplIdx
,rVEvt
.pPV
); break;
899 case SdrEventKind::BeginDragObj
: bRet
=BegDragObj(aLogicPos
,nullptr,rVEvt
.pHdl
,mnMinMovLog
); break;
900 case SdrEventKind::BeginCreateObj
: {
901 if (nCurrentInvent
==SdrInventor::Default
&& nCurrentIdent
==OBJ_CAPTION
) {
902 long nHgt
=SdrEngineDefaults::GetFontHeight();
903 bRet
=BegCreateCaptionObj(aLogicPos
,Size(5*nHgt
,2*nHgt
));
904 } else bRet
=BegCreateObj(aLogicPos
);
906 case SdrEventKind::BeginMacroObj
: {
907 BegMacroObj(aLogicPos
,mnHitTolLog
,rVEvt
.pObj
,rVEvt
.pPV
,static_cast<vcl::Window
*>(mpActualOutDev
.get()));
910 case SdrEventKind::BeginTextEdit
: {
911 if (!IsObjMarked(rVEvt
.pObj
)) {
913 MarkObj(rVEvt
.pRootObj
,rVEvt
.pPV
);
916 bRet
= mpActualOutDev
&& OUTDEV_WINDOW
== mpActualOutDev
->GetOutDevType()&&
917 SdrBeginTextEdit(rVEvt
.pObj
, rVEvt
.pPV
, static_cast<vcl::Window
*>(mpActualOutDev
.get()));
921 MouseEvent
aMEvt(mpActualOutDev
->LogicToPixel(aLogicPos
),
922 1,rVEvt
.nMouseMode
,rVEvt
.nMouseCode
,rVEvt
.nMouseCode
);
923 OutlinerView
* pOLV
=GetTextEditOutlinerView();
924 if (pOLV
!=nullptr) pOLV
->MouseButtonDown(aMEvt
); // event for the Outliner, but without double-click
929 if (bRet
&& mpActualOutDev
&& mpActualOutDev
->GetOutDevType()==OUTDEV_WINDOW
) {
930 vcl::Window
* pWin
=static_cast<vcl::Window
*>(mpActualOutDev
.get());
931 // left mouse button pressed?
932 bool bLeftDown
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0 && rVEvt
.bMouseDown
;
933 // left mouse button released?
934 bool bLeftUp
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0 && rVEvt
.bMouseUp
;
935 // left mouse button pressed or held?
936 bool bLeftDown1
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0 && !rVEvt
.bMouseUp
;
937 pWin
->SetPointer(GetPreferredPointer(rVEvt
.aLogicPos
,pWin
,
938 rVEvt
.nMouseCode
& (KEY_SHIFT
|KEY_MOD1
|KEY_MOD2
),bLeftDown1
));
939 bool bAction
=IsAction();
940 if (bLeftDown
&& bAction
)
941 pWin
->CaptureMouse();
942 else if (bLeftUp
|| (rVEvt
.bIsAction
&& !bAction
))
943 pWin
->ReleaseMouse();
948 PointerStyle
SdrView::GetPreferredPointer(const Point
& rMousePos
, const OutputDevice
* pOut
, sal_uInt16 nModifier
, bool bLeftDown
) const
953 return pCurrentCreate
->GetCreatePointer();
955 if (mpCurrentSdrDragMethod
)
957 return mpCurrentSdrDragMethod
->GetSdrDragPointer();
959 if (IsMarkObj() || IsMarkPoints() || IsMarkGluePoints() || IsSetPageOrg()) return PointerStyle::Arrow
;
960 if (IsDragHelpLine()) return GetDraggedHelpLinePointer();
962 SdrObjMacroHitRec aHitRec
;
963 aHitRec
.aPos
=pOut
->LogicToPixel(rMousePos
);
964 aHitRec
.nTol
=nMacroTol
;
965 aHitRec
.pVisiLayer
=&pMacroPV
->GetVisibleLayers();
966 aHitRec
.pPageView
=pMacroPV
;
967 return pMacroObj
->GetMacroPointer(aHitRec
);
970 // TextEdit, ObjEdit, Macro
971 if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos
)))
973 if(!pOut
|| IsTextEditInSelectionMode())
975 if(pTextEditOutliner
->IsVertical())
976 return PointerStyle::TextVertical
;
978 return PointerStyle::Text
;
980 // Outliner should return something here...
981 Point
aPos(pOut
->LogicToPixel(rMousePos
));
982 PointerStyle
aPointer(pTextEditOutlinerView
->GetPointer(aPos
));
983 if (aPointer
==PointerStyle::Arrow
)
985 if(pTextEditOutliner
->IsVertical())
986 aPointer
= PointerStyle::TextVertical
;
988 aPointer
= PointerStyle::Text
;
994 aVEvt
.nMouseCode
=(nModifier
&(KEY_SHIFT
|KEY_MOD1
|KEY_MOD2
))|MOUSE_LEFT
; // to see what would happen on MouseLeftDown
995 aVEvt
.bMouseDown
=!bLeftDown
; // What if ..?
996 aVEvt
.bMouseUp
=bLeftDown
; // What if ..?
998 const_cast<SdrView
*>(this)->SetActualWin(pOut
);
999 SdrHitKind eHit
=PickAnything(rMousePos
,aVEvt
);
1000 SdrEventKind eEvent
=aVEvt
.eEvent
;
1003 case SdrEventKind::BeginCreateObj
:
1004 return aCurrentCreatePointer
;
1005 case SdrEventKind::MarkObj
:
1006 return PointerStyle::Move
;
1007 case SdrEventKind::BeginMark
:
1008 return PointerStyle::Arrow
;
1009 case SdrEventKind::MarkPoint
:
1010 case SdrEventKind::MarkGluePoint
:
1011 return PointerStyle::MovePoint
;
1012 case SdrEventKind::BeginInsertObjPoint
:
1013 case SdrEventKind::BeginInsertGluePoint
:
1014 return PointerStyle::Cross
;
1015 case SdrEventKind::ExecuteUrl
:
1016 return PointerStyle::RefHand
;
1017 case SdrEventKind::BeginMacroObj
:
1019 SdrObjMacroHitRec aHitRec
;
1020 aHitRec
.aPos
=aVEvt
.aLogicPos
;
1021 aHitRec
.nTol
=mnHitTolLog
;
1022 aHitRec
.pVisiLayer
=&aVEvt
.pPV
->GetVisibleLayers();
1023 aHitRec
.pPageView
=aVEvt
.pPV
;
1024 return aVEvt
.pObj
->GetMacroPointer(aHitRec
);
1031 case SdrHitKind::Cell
:
1032 return PointerStyle::Arrow
;
1033 case SdrHitKind::HelpLine
:
1034 return aVEvt
.pPV
->GetHelpLines()[aVEvt
.nHlplIdx
].GetPointer();
1035 case SdrHitKind::Gluepoint
:
1036 return PointerStyle::MovePoint
;
1037 case SdrHitKind::TextEdit
:
1038 case SdrHitKind::TextEditObj
:
1040 SdrTextObj
* pText
= dynamic_cast< SdrTextObj
* >( aVEvt
.pObj
);
1041 if(pText
&& pText
->HasText())
1043 OutlinerParaObject
* pParaObj
= pText
->GetOutlinerParaObject();
1044 if(pParaObj
&& pParaObj
->IsVertical())
1045 return PointerStyle::TextVertical
;
1047 return PointerStyle::Text
;
1052 bool bMarkHit
=eHit
==SdrHitKind::MarkedObject
;
1053 SdrHdl
* pHdl
=aVEvt
.pHdl
;
1054 // now check the pointers for dragging
1055 if (pHdl
!=nullptr || bMarkHit
) {
1056 SdrHdlKind eHdl
= pHdl
!=nullptr ? pHdl
->GetKind() : SdrHdlKind::Move
;
1057 bool bCorner
=pHdl
!=nullptr && pHdl
->IsCornerHdl();
1058 bool bVertex
=pHdl
!=nullptr && pHdl
->IsVertexHdl();
1059 bool bMov
=eHdl
==SdrHdlKind::Move
;
1060 if (bMov
&& (meDragMode
==SdrDragMode::Move
|| meDragMode
==SdrDragMode::Resize
|| mbMarkedHitMovesAlways
)) {
1061 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1062 return PointerStyle::Move
;
1064 switch (meDragMode
) {
1065 case SdrDragMode::Rotate
: {
1066 if ((bCorner
|| bMov
) && !IsRotateAllowed(true))
1067 return PointerStyle::NotAllowed
;
1069 // are 3D objects selected?
1070 bool b3DObjSelected
= false;
1071 for (size_t a
=0; !b3DObjSelected
&& a
<GetMarkedObjectCount(); ++a
) {
1072 SdrObject
* pObj
= GetMarkedObjectByIndex(a
);
1073 if(dynamic_cast<const E3dObject
* >(pObj
) != nullptr)
1074 b3DObjSelected
= true;
1076 // If we have a 3D object, go on despite !IsShearAllowed,
1077 // because then we have a rotation instead of a shear.
1078 if (bVertex
&& !IsShearAllowed() && !b3DObjSelected
)
1079 return PointerStyle::NotAllowed
;
1081 return PointerStyle::Rotate
;
1083 case SdrDragMode::Shear
: {
1085 if (!IsDistortAllowed(true) && !IsDistortAllowed()) return PointerStyle::NotAllowed
;
1086 else return PointerStyle::RefHand
;
1088 if (bVertex
&& !IsShearAllowed()) return PointerStyle::NotAllowed
;
1090 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1091 return PointerStyle::Move
;
1094 case SdrDragMode::Mirror
: {
1095 if (bCorner
|| bVertex
|| bMov
) {
1096 SdrHdl
* pH1
=maHdlList
.GetHdl(SdrHdlKind::Ref1
);
1097 SdrHdl
* pH2
=maHdlList
.GetHdl(SdrHdlKind::Ref2
);
1101 if (pH1
!=nullptr && pH2
!=nullptr) {
1102 aDif
=pH2
->GetPos()-pH1
->GetPos();
1103 b90
=(aDif
.X()==0) || aDif
.Y()==0;
1104 b45
=b90
|| (std::abs(aDif
.X())==std::abs(aDif
.Y()));
1107 if (!IsMirrorAllowed(true,true)) bNo
=true; // any mirroring is forbidden
1108 if (!IsMirrorAllowed() && !b45
) bNo
=true; // mirroring freely is forbidden
1109 if (!IsMirrorAllowed(true) && !b90
) bNo
=true; // mirroring horizontally/vertically is allowed
1110 if (bNo
) return PointerStyle::NotAllowed
;
1112 return PointerStyle::Mirror
;
1114 return PointerStyle::Mirror
;
1118 case SdrDragMode::Transparence
:
1120 if(!IsTransparenceAllowed())
1121 return PointerStyle::NotAllowed
;
1123 return PointerStyle::RefHand
;
1126 case SdrDragMode::Gradient
:
1128 if(!IsGradientAllowed())
1129 return PointerStyle::NotAllowed
;
1131 return PointerStyle::RefHand
;
1134 case SdrDragMode::Crook
: {
1135 if (bCorner
|| bVertex
|| bMov
) {
1136 if (!IsCrookAllowed(true) && !IsCrookAllowed()) return PointerStyle::NotAllowed
;
1137 return PointerStyle::Crook
;
1142 case SdrDragMode::Crop
:
1144 return PointerStyle::Crop
;
1148 if ((bCorner
|| bVertex
) && !IsResizeAllowed(true)) return PointerStyle::NotAllowed
;
1151 if (pHdl
!=nullptr) return pHdl
->GetPointer();
1153 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1154 return PointerStyle::Move
;
1157 if (meEditMode
==SdrViewEditMode::Create
) return aCurrentCreatePointer
;
1158 return PointerStyle::Arrow
;
1161 #define STR_NOTHING "nothing"
1162 OUString
SdrView::GetStatusText()
1165 OUString aStr
= STR_NOTHING
;
1167 if (pCurrentCreate
!=nullptr)
1169 aStr
=pCurrentCreate
->getSpecialDragComment(maDragStat
);
1173 aName
= pCurrentCreate
->TakeObjNameSingul();
1174 aStr
= SvxResId(STR_ViewCreateObj
);
1177 else if (mpCurrentSdrDragMethod
)
1179 if (mbInsPolyPoint
|| IsInsertGluePoint())
1181 aStr
=maInsPointUndoStr
;
1185 if (maDragStat
.IsMinMoved())
1189 "(" << this << ") " << mpCurrentSdrDragMethod
.get());
1190 aStr
= mpCurrentSdrDragMethod
->GetSdrDragComment();
1194 else if(IsMarkObj())
1196 if(AreObjectsMarked())
1198 aStr
= SvxResId(STR_ViewMarkMoreObjs
);
1202 aStr
= SvxResId(STR_ViewMarkObjs
);
1205 else if(IsMarkPoints())
1207 if(HasMarkedPoints())
1209 aStr
= SvxResId(STR_ViewMarkMorePoints
);
1213 aStr
= SvxResId(STR_ViewMarkPoints
);
1215 } else if (IsMarkGluePoints())
1217 if(HasMarkedGluePoints())
1219 aStr
= SvxResId(STR_ViewMarkMoreGluePoints
);
1223 aStr
= SvxResId(STR_ViewMarkGluePoints
);
1226 else if (IsTextEdit() && pTextEditOutlinerView
!=nullptr) {
1227 aStr
=SvxResId(STR_ViewTextEdit
); // "TextEdit - Row y, Column x";
1228 ESelection
aSel(pTextEditOutlinerView
->GetSelection());
1229 long nPar
=aSel
.nEndPara
,nLin
=0,nCol
=aSel
.nEndPos
;
1230 if (aSel
.nEndPara
>0) {
1231 for (sal_Int32 nParaNum
=0; nParaNum
<aSel
.nEndPara
; nParaNum
++) {
1232 nLin
+=pTextEditOutliner
->GetLineCount(nParaNum
);
1235 // A little imperfection:
1236 // At the end of a line of any multi-line paragraph, we display the
1237 // position of the next line of the same paragraph, if there is one.
1238 sal_uInt16 nParaLine
= 0;
1239 sal_uIntPtr nParaLineCount
= pTextEditOutliner
->GetLineCount(aSel
.nEndPara
);
1243 sal_uInt16 nLen
= pTextEditOutliner
->GetLineLen(aSel
.nEndPara
, nParaLine
);
1244 bool bLastLine
= (nParaLine
== nParaLineCount
- 1);
1245 if (nCol
>nLen
|| (!bLastLine
&& nCol
== nLen
))
1255 bBrk
= true; // to be sure
1258 aStr
= aStr
.replaceFirst("%1", OUString::number(nPar
+ 1));
1259 aStr
= aStr
.replaceFirst("%2", OUString::number(nLin
+ 1));
1260 aStr
= aStr
.replaceFirst("%3", OUString::number(nCol
+ 1));
1263 aStr
+= ", Level " + OUString::number( pTextEditOutliner
->GetDepth( aSel
.nEndPara
) );
1267 if(aStr
== STR_NOTHING
)
1269 if (AreObjectsMarked()) {
1270 aStr
= ImpGetDescriptionString(STR_ViewMarked
);
1271 if (IsGluePointEditMode()) {
1272 if (HasMarkedGluePoints()) {
1273 aStr
= ImpGetDescriptionString(STR_ViewMarked
, ImpGetDescriptionOptions::GLUEPOINTS
);
1276 if (HasMarkedPoints()) {
1277 aStr
= ImpGetDescriptionString(STR_ViewMarked
, ImpGetDescriptionOptions::POINTS
);
1284 else if(!aName
.isEmpty())
1286 aStr
= aStr
.replaceFirst("%1", aName
);
1291 // capitalize first letter
1292 aStr
= aStr
.replaceAt(0, 1, OUString(aStr
[0]).toAsciiUpperCase());
1297 SdrViewContext
SdrView::GetContext() const
1299 if( IsGluePointEditMode() )
1300 return SdrViewContext::GluePointEdit
;
1302 const size_t nMarkCount
= GetMarkedObjectCount();
1304 if( HasMarkablePoints() && !IsFrameHandles() )
1307 for( size_t nMarkNum
= 0; nMarkNum
< nMarkCount
&& bPath
; ++nMarkNum
)
1308 if (dynamic_cast<const SdrPathObj
*>(GetMarkedObjectByIndex(nMarkNum
)) == nullptr)
1312 return SdrViewContext::PointEdit
;
1315 if( GetMarkedObjectCount() )
1317 bool bGraf
= true, bMedia
= true, bTable
= true;
1319 for( size_t nMarkNum
= 0; nMarkNum
< nMarkCount
&& ( bGraf
|| bMedia
); ++nMarkNum
)
1321 const SdrObject
* pMarkObj
= GetMarkedObjectByIndex( nMarkNum
);
1322 DBG_ASSERT( pMarkObj
, "SdrView::GetContext(), null pointer in mark list!" );
1327 if( dynamic_cast<const SdrGrafObj
*>( pMarkObj
) == nullptr )
1330 if( dynamic_cast<const SdrMediaObj
*>( pMarkObj
) == nullptr )
1333 if( dynamic_cast<const sdr::table::SdrTableObj
* >( pMarkObj
) == nullptr )
1338 return SdrViewContext::Graphic
;
1340 return SdrViewContext::Media
;
1342 return SdrViewContext::Table
;
1345 return SdrViewContext::Standard
;
1348 void SdrView::MarkAll()
1351 GetTextEditOutlinerView()->SetSelection(ESelection(0,0,EE_PARA_ALL
,EE_TEXTPOS_ALL
));
1353 if (mpItemBrowser
!=nullptr) mpItemBrowser
->SetDirty();
1355 } else if (IsGluePointEditMode()) MarkAllGluePoints();
1356 else if (HasMarkablePoints()) MarkAllPoints();
1360 void SdrView::UnmarkAll()
1363 ESelection eSel
=GetTextEditOutlinerView()->GetSelection();
1364 eSel
.nStartPara
=eSel
.nEndPara
;
1365 eSel
.nStartPos
=eSel
.nEndPos
;
1366 GetTextEditOutlinerView()->SetSelection(eSel
);
1368 if (mpItemBrowser
!=nullptr) mpItemBrowser
->SetDirty();
1370 } else if (HasMarkedGluePoints()) UnmarkAllGluePoints();
1371 else if (HasMarkedPoints()) UnmarkAllPoints(); // Marked, not Markable!
1372 else UnmarkAllObj();
1375 const tools::Rectangle
& SdrView::GetMarkedRect() const
1377 if (IsGluePointEditMode() && HasMarkedGluePoints()) {
1378 return GetMarkedGluePointsRect();
1380 if (HasMarkedPoints()) {
1381 return GetMarkedPointsRect();
1383 return GetMarkedObjRect();
1386 void SdrView::DeleteMarked()
1390 SdrObjEditView::KeyInput(KeyEvent(0,vcl::KeyCode(KeyFuncType::DELETE
)),pTextEditWin
);
1394 if( mxSelectionController
.is() && mxSelectionController
->DeleteMarked() )
1396 // action already performed by current selection controller, do nothing
1398 else if (IsGluePointEditMode() && HasMarkedGluePoints())
1400 DeleteMarkedGluePoints();
1402 else if (GetContext()==SdrViewContext::PointEdit
&& HasMarkedPoints())
1404 DeleteMarkedPoints();
1413 bool SdrView::BegMark(const Point
& rPnt
, bool bAddMark
, bool bUnmark
)
1415 if (bUnmark
) bAddMark
=true;
1416 if (IsGluePointEditMode()) {
1417 if (!bAddMark
) UnmarkAllGluePoints();
1418 return BegMarkGluePoints(rPnt
,bUnmark
);
1419 } else if (HasMarkablePoints()) {
1420 if (!bAddMark
) UnmarkAllPoints();
1421 return BegMarkPoints(rPnt
,bUnmark
);
1423 if (!bAddMark
) UnmarkAllObj();
1424 BegMarkObj(rPnt
,bUnmark
);
1429 void SdrView::ConfigurationChanged( ::utl::ConfigurationBroadcaster
*p
, ConfigurationHints nHint
)
1431 onAccessibilityOptionsChanged();
1432 SdrCreateView::ConfigurationChanged(p
, nHint
);
1436 /** method is called whenever the global SvtAccessibilityOptions is changed */
1437 void SdrView::onAccessibilityOptionsChanged()
1441 void SdrView::SetMasterPagePaintCaching(bool bOn
)
1443 if(mbMasterPagePaintCaching
!= bOn
)
1445 mbMasterPagePaintCaching
= bOn
;
1447 // reset at all SdrPageWindows
1448 SdrPageView
* pPageView
= GetSdrPageView();
1452 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1454 SdrPageWindow
* pPageWindow
= pPageView
->GetPageWindow(b
);
1455 assert(pPageWindow
&& "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)");
1457 // force deletion of ObjectContact, so at re-display all VOCs
1458 // will be re-created with updated flag setting
1459 pPageWindow
->ResetObjectContact();
1462 // force redraw of this view
1463 pPageView
->InvalidateAllWin();
1468 // Default ObjectContact is ObjectContactOfPageView
1469 sdr::contact::ObjectContact
* SdrView::createViewSpecificObjectContact(
1470 SdrPageWindow
& rPageWindow
,
1471 const sal_Char
* pDebugName
) const
1473 return new sdr::contact::ObjectContactOfPageView(rPageWindow
, pDebugName
);
1476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */