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/svdoutl.hxx>
34 #include <svx/svdview.hxx>
35 #include <editeng/flditem.hxx>
36 #include <svx/obj3d.hxx>
37 #include <svx/svddrgmt.hxx>
38 #include <svx/svdotable.hxx>
39 #include <tools/debug.hxx>
40 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
41 #include <svx/sdr/overlay/overlaymanager.hxx>
42 #include <svx/sdrpaintwindow.hxx>
43 #include <svx/sdrpagewindow.hxx>
44 #include <svx/sdrhittesthelper.hxx>
45 #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
46 #include <svx/sdr/contact/objectcontactofpageview.hxx>
47 #include <sal/log.hxx>
48 #include <vcl/ptrstyle.hxx>
51 SdrViewEvent::SdrViewEvent()
57 eHit(SdrHitKind::NONE
),
58 eEvent(SdrEventKind::NONE
),
60 nMouseMode(MouseEventModifiers::NONE
),
75 SdrViewEvent::~SdrViewEvent()
80 // helper class for all D&D overlays
82 void SdrDropMarkerOverlay::ImplCreateOverlays(
84 const basegfx::B2DPolyPolygon
& rLinePolyPolygon
)
86 for(sal_uInt32
a(0); a
< rView
.PaintWindowCount(); a
++)
88 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
89 const rtl::Reference
< sdr::overlay::OverlayManager
>& xTargetOverlay
= pCandidate
->GetOverlayManager();
91 if (xTargetOverlay
.is())
93 std::unique_ptr
<sdr::overlay::OverlayPolyPolygonStripedAndFilled
> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
96 xTargetOverlay
->add(*pNew
);
97 maObjects
.append(std::move(pNew
));
102 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const SdrObject
& rObject
)
106 rObject
.TakeXorPoly());
109 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const tools::Rectangle
& rRectangle
)
111 basegfx::B2DPolygon aB2DPolygon
;
113 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()));
114 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
115 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
116 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
117 aB2DPolygon
.setClosed(true);
121 basegfx::B2DPolyPolygon(aB2DPolygon
));
124 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const Point
& rStart
, const Point
& rEnd
)
126 basegfx::B2DPolygon aB2DPolygon
;
128 aB2DPolygon
.append(basegfx::B2DPoint(rStart
.X(), rStart
.Y()));
129 aB2DPolygon
.append(basegfx::B2DPoint(rEnd
.X(), rEnd
.Y()));
130 aB2DPolygon
.setClosed(true);
134 basegfx::B2DPolyPolygon(aB2DPolygon
));
137 SdrDropMarkerOverlay::~SdrDropMarkerOverlay()
139 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
140 // That destructor calls clear() at the list which removes all objects from the
141 // OverlayManager and deletes them.
147 : SdrCreateView(rSdrModel
, pOut
),
148 bNoExtendedMouseDispatcher(false),
149 bNoExtendedKeyDispatcher(false),
150 mbMasterPagePaintCaching(false)
152 maAccessibilityOptions
.AddListener(this);
153 onAccessibilityOptionsChanged();
158 maAccessibilityOptions
.RemoveListener(this);
161 bool SdrView::KeyInput(const KeyEvent
& rKEvt
, vcl::Window
* pWin
)
164 bool bRet
= SdrCreateView::KeyInput(rKEvt
,pWin
);
165 if (!bRet
&& !IsExtendedKeyInputDispatcherEnabled()) {
167 switch (rKEvt
.GetKeyCode().GetFullFunction()) {
168 case KeyFuncType::DELETE
: DeleteMarked(); break;
169 case KeyFuncType::UNDO
: mpModel
->Undo(); break;
170 case KeyFuncType::REDO
: mpModel
->Redo(); break;
172 switch (rKEvt
.GetKeyCode().GetFullCode()) {
174 if (IsTextEdit()) SdrEndTextEdit();
175 if (IsAction()) BrkAction();
176 if (pWin
!=nullptr) pWin
->ReleaseMouse();
178 case KEY_DELETE
: DeleteMarked(); break;
179 case KEY_UNDO
: case KEY_BACKSPACE
+KEY_MOD2
: mpModel
->Undo(); break;
180 case KEY_BACKSPACE
+KEY_MOD2
+KEY_SHIFT
: mpModel
->Redo(); break;
181 case KEY_REPEAT
: case KEY_BACKSPACE
+KEY_MOD2
+KEY_MOD1
: mpModel
->Repeat(*this); break;
182 case KEY_MOD1
+KEY_A
: MarkAll(); break;
187 if (bRet
&& pWin
!=nullptr) {
188 pWin
->SetPointer(GetPreferredPointer(
189 pWin
->PixelToLogic(pWin
->ScreenToOutputPixel( pWin
->GetPointerPosPixel() ) ),
191 rKEvt
.GetKeyCode().GetModifier()));
197 bool SdrView::MouseButtonDown(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
200 if (rMEvt
.IsLeft()) maDragStat
.SetMouseDown(true);
201 bool bRet
= SdrCreateView::MouseButtonDown(rMEvt
,pWin
);
202 if (!bRet
&& !IsExtendedMouseEventDispatcherEnabled()) {
204 PickAnything(rMEvt
,SdrMouseEventKind::BUTTONDOWN
,aVEvt
);
205 bRet
= DoMouseEvent(aVEvt
);
210 bool SdrView::MouseButtonUp(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
213 if (rMEvt
.IsLeft()) maDragStat
.SetMouseDown(false);
214 bool bAction
= IsAction();
215 bool bRet
= !bAction
&& SdrCreateView::MouseButtonUp(rMEvt
,pWin
);
216 if (!bRet
&& !IsExtendedMouseEventDispatcherEnabled()) {
218 PickAnything(rMEvt
,SdrMouseEventKind::BUTTONUP
,aVEvt
);
219 bRet
= DoMouseEvent(aVEvt
);
224 bool SdrView::MouseMove(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
227 maDragStat
.SetMouseDown(rMEvt
.IsLeft());
228 bool bRet
= SdrCreateView::MouseMove(rMEvt
,pWin
);
229 if (!IsExtendedMouseEventDispatcherEnabled() && !IsTextEditInSelectionMode()) {
231 PickAnything(rMEvt
,SdrMouseEventKind::MOVE
,aVEvt
);
232 if (DoMouseEvent(aVEvt
)) bRet
=true;
238 bool SdrView::Command(const CommandEvent
& rCEvt
, vcl::Window
* pWin
)
241 bool bRet
= SdrCreateView::Command(rCEvt
,pWin
);
245 void SdrView::GetAttributes(SfxItemSet
& rTargetSet
, bool bOnlyHardAttr
) const
247 SdrCreateView::GetAttributes(rTargetSet
, bOnlyHardAttr
);
250 SdrHitKind
SdrView::PickAnything(const MouseEvent
& rMEvt
, SdrMouseEventKind nEventKind
, SdrViewEvent
& rVEvt
) const
252 rVEvt
.bMouseDown
=nEventKind
==SdrMouseEventKind::BUTTONDOWN
;
253 rVEvt
.bMouseUp
=nEventKind
==SdrMouseEventKind::BUTTONUP
;
254 rVEvt
.nMouseClicks
=rMEvt
.GetClicks();
255 rVEvt
.nMouseMode
=rMEvt
.GetMode();
256 rVEvt
.nMouseCode
=rMEvt
.GetButtons() | rMEvt
.GetModifier();
257 const OutputDevice
* pOut
=mpActualOutDev
;
260 pOut
= GetFirstOutputDevice();
262 Point
aPnt(rMEvt
.GetPosPixel());
263 if (pOut
!=nullptr) aPnt
=pOut
->PixelToLogic(aPnt
);
264 rVEvt
.aLogicPos
=aPnt
;
265 return PickAnything(aPnt
,rVEvt
);
268 // Dragging with the Mouse (Move)
269 // Example when creating a rectangle: MouseDown has to happen without a ModKey,
270 // else we usually force a selection (see below).
271 // When pressing Shift, Ctrl and Alt at the same time while doing a MouseMove,
272 // a centered, not snapped square is created.
273 // The dual allocation of Ortho and Shift won't usually create a problem, as the
274 // two functions are in most cases mutually exclusive. Only shearing (the kind
275 // that happens when contorting, not when rotating) can use both functions at
276 // the same time. To get around this, the user can use e. g. help lines.
277 #define MODKEY_NoSnap bCtrl /* temporarily disable snapping */
278 #define MODKEY_Ortho bShift /* ortho */
279 #define MODKEY_Center bAlt /* create/resize centeredly */
280 #define MODKEY_AngleSnap bShift
281 #define MODKEY_CopyDrag bCtrl /* drag and copy */
283 // click somewhere (MouseDown)
284 #define MODKEY_PolyPoly bAlt /* new Poly at InsPt and at Create */
285 #define MODKEY_MultiMark bShift /* MarkObj without doing UnmarkAll first */
286 #define MODKEY_Unmark bAlt /* deselect with a dragged frame */
287 #define MODKEY_ForceMark bCtrl /* force dragging a frame, even if there's an object at cursor position */
288 #define MODKEY_DeepMark bAlt /* MarkNextObj */
289 #define MODKEY_DeepBackw bShift /* MarkNextObj but backwards */
291 SdrHitKind
SdrView::PickAnything(const Point
& rLogicPos
, SdrViewEvent
& rVEvt
) const
293 const OutputDevice
* pOut
=mpActualOutDev
;
296 pOut
= GetFirstOutputDevice();
299 // #i73628# Use a non-changeable copy of he logic position
300 const Point
aLocalLogicPosition(rLogicPos
);
302 bool bEditMode
=IsEditMode();
303 bool bPointMode
=bEditMode
&& HasMarkablePoints();
304 bool bGluePointMode
=IsGluePointEditMode();
305 bool bInsPolyPt
=bPointMode
&& IsInsObjPointMode() && IsInsObjPointPossible();
306 bool bInsGluePt
=bGluePointMode
&& IsInsGluePointMode() && IsInsGluePointPossible();
307 bool bIsTextEdit
=IsTextEdit();
308 bool bTextEditHit
=IsTextEditHit(aLocalLogicPosition
);
309 bool bTextEditSel
=IsTextEditInSelectionMode();
310 bool bShift
=(rVEvt
.nMouseCode
& KEY_SHIFT
) !=0;
311 bool bCtrl
=(rVEvt
.nMouseCode
& KEY_MOD1
) !=0;
312 bool bAlt
=(rVEvt
.nMouseCode
& KEY_MOD2
) !=0;
313 SdrHitKind eHit
=SdrHitKind::NONE
;
314 SdrHdl
* pHdl
=pOut
!=nullptr && !bTextEditSel
? PickHandle(aLocalLogicPosition
) : nullptr;
315 SdrPageView
* pPV
=nullptr;
316 SdrObject
* pObj
=nullptr;
317 SdrObject
* pHitObj
=nullptr;
318 bool bHitPassDirect
=true;
319 sal_uInt16 nHlplIdx
=0;
320 sal_uInt16 nGlueId
=0;
321 if (bTextEditHit
|| bTextEditSel
)
323 eHit
=SdrHitKind::TextEdit
;
325 else if (pHdl
!=nullptr)
327 eHit
=SdrHitKind::Handle
; // handle is hit: highest priority
329 else if (bEditMode
&& IsHlplVisible() && IsHlplFront() && pOut
!=nullptr && PickHelpLine(aLocalLogicPosition
,mnHitTolLog
,*pOut
,nHlplIdx
,pPV
))
331 eHit
=SdrHitKind::HelpLine
; // help line in the foreground hit: can be moved now
333 else if (bGluePointMode
&& PickGluePoint(aLocalLogicPosition
,pObj
,nGlueId
,pPV
))
335 eHit
=SdrHitKind::Gluepoint
; // deselected glue point hit
337 else if ((pHitObj
= PickObj(aLocalLogicPosition
,mnHitTolLog
,pPV
,SdrSearchOptions::DEEP
|SdrSearchOptions::MARKED
,&pObj
,&bHitPassDirect
)))
339 eHit
=SdrHitKind::MarkedObject
;
340 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast< sdr::table::SdrTableObj
* >( pObj
);
343 sal_Int32 nX
= 0, nY
= 0;
344 switch( pTableObj
->CheckTableHit( aLocalLogicPosition
, nX
, nY
) )
346 case sdr::table::TableHitKind::Cell
:
347 eHit
= SdrHitKind::Cell
;
349 case sdr::table::TableHitKind::CellTextArea
:
350 eHit
= SdrHitKind::TextEditObj
;
357 else if ((pHitObj
= PickObj(aLocalLogicPosition
,mnHitTolLog
,pPV
,SdrSearchOptions::DEEP
|SdrSearchOptions::ALSOONMASTER
|SdrSearchOptions::WHOLEPAGE
,&pObj
,&bHitPassDirect
)))
359 // MasterPages and WholePage for Macro and URL
360 eHit
=SdrHitKind::UnmarkedObject
;
361 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast< sdr::table::SdrTableObj
* >( pObj
);
364 sal_Int32 nX
= 0, nY
= 0;
365 switch( pTableObj
->CheckTableHit( aLocalLogicPosition
, nX
, nY
, mnHitTolLog
) )
367 case sdr::table::TableHitKind::Cell
:
368 eHit
= SdrHitKind::Cell
;
370 case sdr::table::TableHitKind::CellTextArea
:
371 // Keep state on UnmarkedObject to allow the below
372 // 'check for URL field' to be executed, else popups
373 // for e.g. URL links when hoovering and clicking
374 // them will not work. Tried several other changes,
375 // but this one safely keeps existing behaviour as-is.
376 eHit
= SdrHitKind::UnmarkedObject
;
383 else if (bEditMode
&& IsHlplVisible() && !IsHlplFront() && pOut
!=nullptr && PickHelpLine(aLocalLogicPosition
,mnHitTolLog
,*pOut
,nHlplIdx
,pPV
))
385 eHit
=SdrHitKind::HelpLine
; // help line in foreground hit: can be moved now
387 if (eHit
==SdrHitKind::UnmarkedObject
)
389 bool bRoot
=pObj
->HasMacro();
390 bool bDeep
=pObj
!=pHitObj
&& pHitObj
->HasMacro();
391 bool bMid
=false; // Have we hit upon a grouped group with a macro?
392 SdrObject
* pMidObj
=nullptr;
395 SdrObject
* pObjTmp
=pHitObj
->getParentSdrObjectFromSdrObject();
396 if (pObjTmp
==pObj
) pObjTmp
=nullptr;
397 while (pObjTmp
!=nullptr)
399 if (pObjTmp
->HasMacro())
404 pObjTmp
=pObjTmp
->getParentSdrObjectFromSdrObject();
405 if (pObjTmp
==pObj
) pObjTmp
=nullptr;
409 if (bDeep
|| bMid
|| bRoot
)
411 SdrObjMacroHitRec aHitRec
;
412 aHitRec
.aPos
=aLocalLogicPosition
;
413 aHitRec
.nTol
=mnHitTolLog
;
414 aHitRec
.pVisiLayer
=&pPV
->GetVisibleLayers();
415 aHitRec
.pPageView
=pPV
;
416 if (bDeep
) bDeep
=pHitObj
->IsMacroHit(aHitRec
);
417 if (bMid
) bMid
=pMidObj
->IsMacroHit(aHitRec
);
418 if (bRoot
) bRoot
=pObj
->IsMacroHit(aHitRec
);
419 if (bRoot
|| bMid
|| bDeep
)
421 // Priorities: 1. Root, 2. Mid, 3. Deep
423 if (!bRoot
) pObj
=pMidObj
;
424 if (!bRoot
&& !bMid
) pObj
=pHitObj
;
425 eHit
=SdrHitKind::Macro
;
429 // check for URL field
430 if (eHit
==SdrHitKind::UnmarkedObject
)
432 SdrTextObj
* pTextObj
=dynamic_cast<SdrTextObj
*>( pHitObj
);
433 if (pTextObj
!=nullptr && pTextObj
->HasText())
435 // use the primitive-based HitTest which is more accurate anyways. It
436 // will correctly handle rotated/mirrored/sheared/scaled text and can
437 // now return a HitContainer containing the primitive hierarchy of the
438 // primitive that triggered the hit. The first entry is that primitive,
439 // the others are the full stack of primitives leading to that one which
440 // includes grouping primitives (like TextHierarchyPrimitives we deed here)
441 // but also all decomposed ones which lead to the creation of that primitive
442 drawinglayer::primitive2d::Primitive2DContainer aHitContainer
;
443 const bool bTEHit(pPV
&& SdrObjectPrimitiveHit(*pTextObj
, aLocalLogicPosition
, 0, *pPV
, &pPV
->GetVisibleLayers(), true, &aHitContainer
));
445 if (bTEHit
&& !aHitContainer
.empty())
447 // search for TextHierarchyFieldPrimitive2D which contains the needed information
448 // about a possible URLField
449 const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D
* pTextHierarchyFieldPrimitive2D
= nullptr;
451 for (const drawinglayer::primitive2d::Primitive2DReference
& xReference
: aHitContainer
)
455 // try to cast to drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D implementation
456 pTextHierarchyFieldPrimitive2D
= dynamic_cast<const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D
*>(xReference
.get());
458 if (pTextHierarchyFieldPrimitive2D
)
465 if (nullptr != pTextHierarchyFieldPrimitive2D
)
467 if (drawinglayer::primitive2d::FieldType::FIELD_TYPE_URL
== pTextHierarchyFieldPrimitive2D
->getType())
469 // problem with the old code is that a *pointer* to an instance of
470 // SvxURLField is set in the Event which is per se not good since that
471 // data comes from a temporary EditEngine's data and could vanish any
472 // moment. Have to replace for now with a static instance that gets
473 // filled/initialized from the original data held in the TextHierarchyField-
474 // Primitive2D (see impTextBreakupHandler::impCheckFieldPrimitive).
475 // Unfortunately things like 'TargetFrame' are still used in Calc, so this
476 // can currently not get replaced. For the future the Name/Value vector or
477 // the TextHierarchyFieldPrimitive2D itself should/will be used for handling
479 static SvxURLField aSvxURLField
;
481 aSvxURLField
.SetURL(pTextHierarchyFieldPrimitive2D
->getValue("URL"));
482 aSvxURLField
.SetRepresentation(pTextHierarchyFieldPrimitive2D
->getValue("Representation"));
483 aSvxURLField
.SetTargetFrame(pTextHierarchyFieldPrimitive2D
->getValue("TargetFrame"));
484 const OUString
aFormat(pTextHierarchyFieldPrimitive2D
->getValue("SvxURLFormat"));
486 if (!aFormat
.isEmpty())
488 aSvxURLField
.SetFormat(static_cast<SvxURLFormat
>(aFormat
.toInt32()));
491 // set HitKind and pointer to local static instance in the Event
492 // to comply to old stuff
493 eHit
= SdrHitKind::UrlField
;
494 rVEvt
.pURLField
= &aSvxURLField
;
501 if (bHitPassDirect
&&
502 (eHit
==SdrHitKind::MarkedObject
|| eHit
==SdrHitKind::UnmarkedObject
) &&
503 (IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj
->HasTextEdit())
505 // Around the TextEditArea there's a border to select without going into text edit mode.
506 tools::Rectangle
aBoundRect(pHitObj
->GetCurrentBoundRect());
508 // Force to SnapRect when Fontwork
509 if( dynamic_cast<const SdrTextObj
*>( pHitObj
) != nullptr && static_cast<SdrTextObj
*>(pHitObj
)->IsFontwork())
511 aBoundRect
= pHitObj
->GetSnapRect();
514 sal_Int32
nTolerance(mnHitTolLog
);
515 bool bBoundRectHit(false);
519 nTolerance
= pOut
->PixelToLogic(Size(2, 0)).Width();
522 if( (aLocalLogicPosition
.X() >= aBoundRect
.Left() - nTolerance
&& aLocalLogicPosition
.X() <= aBoundRect
.Left() + nTolerance
)
523 || (aLocalLogicPosition
.X() >= aBoundRect
.Right() - nTolerance
&& aLocalLogicPosition
.X() <= aBoundRect
.Right() + nTolerance
)
524 || (aLocalLogicPosition
.Y() >= aBoundRect
.Top() - nTolerance
&& aLocalLogicPosition
.Y() <= aBoundRect
.Top() + nTolerance
)
525 || (aLocalLogicPosition
.Y() >= aBoundRect
.Bottom() - nTolerance
&& aLocalLogicPosition
.Y() <= aBoundRect
.Bottom() + nTolerance
))
527 bBoundRectHit
= true;
533 SdrObjectPrimitiveHit(*pHitObj
, aLocalLogicPosition
, 0, *pPV
, &pPV
->GetVisibleLayers(), true));
535 // TextEdit attached to an object in a locked layer
536 if (pPV
->GetLockedLayers().IsSet(pHitObj
->GetLayer()))
545 eHit
=SdrHitKind::TextEditObj
;
549 if (!bHitPassDirect
&& eHit
==SdrHitKind::UnmarkedObject
) {
550 eHit
=SdrHitKind::NONE
;
554 bool bMouseLeft
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0;
555 bool bMouseRight
=(rVEvt
.nMouseCode
&MOUSE_RIGHT
)!=0;
556 bool bMouseDown
=rVEvt
.bMouseDown
;
557 bool bMouseUp
=rVEvt
.bMouseUp
;
558 SdrEventKind eEvent
=SdrEventKind::NONE
;
559 bool bIsAction
=IsAction();
565 if (bMouseRight
) eEvent
=SdrEventKind::BackAction
;
571 eEvent
=SdrEventKind::EndAction
;
574 eEvent
=SdrEventKind::EndDrag
;
576 else if (IsCreateObj() || IsInsObjPoint())
578 eEvent
=IsCreateObj() ? SdrEventKind::EndCreate
: SdrEventKind::EndInsertObjPoint
;
580 else if (IsMarking())
582 eEvent
=SdrEventKind::EndMark
;
583 if (!maDragStat
.IsMinMoved())
585 eEvent
=SdrEventKind::BrkMark
;
586 rVEvt
.bAddMark
=MODKEY_MultiMark
;
593 eEvent
=SdrEventKind::MoveAction
;
596 else if (eHit
==SdrHitKind::TextEdit
)
598 eEvent
=SdrEventKind::TextEdit
;
600 else if (bMouseDown
&& bMouseLeft
)
602 if (rVEvt
.nMouseClicks
==2 && rVEvt
.nMouseCode
==MOUSE_LEFT
&& pObj
!=nullptr && pHitObj
!=nullptr && pHitObj
->HasTextEdit() && eHit
==SdrHitKind::MarkedObject
)
606 eEvent
=SdrEventKind::BeginTextEdit
;
608 else if (MODKEY_ForceMark
&& eHit
!=SdrHitKind::UrlField
)
610 eEvent
=SdrEventKind::BeginMark
; // AddMark,Unmark */
612 else if (eHit
==SdrHitKind::HelpLine
)
614 eEvent
=SdrEventKind::BeginDragHelpline
; // nothing, actually
616 else if (eHit
==SdrHitKind::Gluepoint
)
618 eEvent
=SdrEventKind::MarkGluePoint
; // AddMark+Drag
619 rVEvt
.bAddMark
=MODKEY_MultiMark
|| MODKEY_DeepMark
; // if not hit with Deep
621 else if (eHit
==SdrHitKind::Handle
)
623 eEvent
=SdrEventKind::BeginDragObj
; // Mark+Drag,AddMark+Drag,DeepMark+Drag,Unmark
624 bool bGlue
=pHdl
->GetKind()==SdrHdlKind::Glue
;
625 bool bPoly
=!bGlue
&& IsPointMarkable(*pHdl
);
626 bool bMarked
=bGlue
|| (bPoly
&& pHdl
->IsSelected());
629 eEvent
=bGlue
? SdrEventKind::MarkGluePoint
: SdrEventKind::MarkPoint
;
633 rVEvt
.bPrevNextMark
=true;
634 rVEvt
.bMarkPrev
=MODKEY_DeepBackw
;
636 else if (MODKEY_MultiMark
)
639 rVEvt
.bUnmark
=bMarked
; // Toggle
643 nGlueId
=static_cast<sal_uInt16
>(pHdl
->GetObjHdlNum());
648 eEvent
=SdrEventKind::BeginDragObj
; // don't change MarkState, only change Drag
652 else if (bInsPolyPt
&& (MODKEY_PolyPoly
|| (!MODKEY_MultiMark
&& !MODKEY_DeepMark
)))
654 eEvent
=SdrEventKind::BeginInsertObjPoint
;
656 else if (bInsGluePt
&& !MODKEY_MultiMark
&& !MODKEY_DeepMark
)
658 eEvent
=SdrEventKind::BeginInsertGluePoint
;
660 else if (eHit
==SdrHitKind::TextEditObj
)
662 eEvent
=SdrEventKind::BeginTextEdit
; // AddMark+Drag,DeepMark+Drag,Unmark
663 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
664 { // if not hit with Deep
665 eEvent
=SdrEventKind::MarkObj
;
668 else if (eHit
==SdrHitKind::Macro
)
670 eEvent
=SdrEventKind::BeginMacroObj
; // AddMark+Drag
671 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
672 { // if not hit with Deep
673 eEvent
=SdrEventKind::MarkObj
;
676 else if (eHit
==SdrHitKind::UrlField
)
678 eEvent
=SdrEventKind::ExecuteUrl
; // AddMark+Drag
679 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
680 { // if not hit with Deep
681 eEvent
=SdrEventKind::MarkObj
;
684 else if (eHit
==SdrHitKind::MarkedObject
)
686 eEvent
=SdrEventKind::BeginDragObj
; // DeepMark+Drag,Unmark
688 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
689 { // if not hit with Deep
690 eEvent
=SdrEventKind::MarkObj
;
693 else if (IsCreateMode())
695 eEvent
=SdrEventKind::BeginCreateObj
; // nothing, actually
697 else if (eHit
==SdrHitKind::UnmarkedObject
)
699 eEvent
=SdrEventKind::MarkObj
; // AddMark+Drag
703 eEvent
=SdrEventKind::BeginMark
;
706 if (eEvent
==SdrEventKind::MarkObj
)
708 rVEvt
.bAddMark
=MODKEY_MultiMark
|| MODKEY_DeepMark
; // if not hit with Deep
709 rVEvt
.bPrevNextMark
=MODKEY_DeepMark
;
710 rVEvt
.bMarkPrev
=MODKEY_DeepMark
&& MODKEY_DeepBackw
;
712 if (eEvent
==SdrEventKind::BeginMark
)
714 rVEvt
.bAddMark
=MODKEY_MultiMark
;
715 rVEvt
.bUnmark
=MODKEY_Unmark
;
718 rVEvt
.bIsAction
=bIsAction
;
719 rVEvt
.bIsTextEdit
=bIsTextEdit
;
720 rVEvt
.aLogicPos
=aLocalLogicPosition
;
723 if(rVEvt
.pRootObj
==nullptr)
726 rVEvt
.nHlplIdx
=nHlplIdx
;
727 rVEvt
.nGlueId
=nGlueId
;
731 if (rVEvt
.pRootObj
!=NULL
) {
732 if (rVEvt
.pRootObj
->getParentSdrObjListFromSdrObject()!=rVEvt
.pPV
->GetObjList()) {
733 OSL_FAIL("SdrView::PickAnything(): pRootObj->getParentSdrObjListFromSdrObject()!=pPV->GetObjList() !");
740 bool SdrView::DoMouseEvent(const SdrViewEvent
& rVEvt
)
743 SdrHitKind eHit
=rVEvt
.eHit
;
744 Point
aLogicPos(rVEvt
.aLogicPos
);
746 bool bShift
=(rVEvt
.nMouseCode
& KEY_SHIFT
) !=0;
747 bool bCtrl
=(rVEvt
.nMouseCode
& KEY_MOD1
) !=0;
748 bool bAlt
=(rVEvt
.nMouseCode
& KEY_MOD2
) !=0;
749 bool bMouseLeft
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0;
750 bool bMouseDown
=rVEvt
.bMouseDown
;
751 bool bMouseUp
=rVEvt
.bMouseUp
;
753 if (bMouseLeft
) maDragStat
.SetMouseDown(true);
754 } else if (bMouseUp
) {
755 if (bMouseLeft
) maDragStat
.SetMouseDown(false);
756 } else { // else, MouseMove
757 maDragStat
.SetMouseDown(bMouseLeft
);
761 SetSnapEnabled(!MODKEY_NoSnap
);
764 SetOrtho(MODKEY_Ortho
!=IsOrthoDesired());
766 #ifdef MODKEY_AngleSnap
767 SetAngleSnapEnabled(MODKEY_AngleSnap
);
769 #ifdef MODKEY_CopyDrag
770 SetDragWithCopy(MODKEY_CopyDrag
);
773 SetCreate1stPointAsCenter(MODKEY_Center
);
774 SetResizeAtCenter(MODKEY_Center
);
775 SetCrookAtCenter(MODKEY_Center
);
777 if (bMouseLeft
&& bMouseDown
&& rVEvt
.bIsTextEdit
&& (eHit
==SdrHitKind::UnmarkedObject
|| eHit
==SdrHitKind::NONE
)) {
778 SdrEndTextEdit(); // User has clicked beneath object, exit edit mode.
779 // pHdl is invalid, then, that shouldn't matter, though, as we expect
780 // pHdl==NULL (because of eHit).
782 switch (rVEvt
.eEvent
) {
783 case SdrEventKind::NONE
: bRet
=false; break;
784 case SdrEventKind::TextEdit
: bRet
=false; break; // Events handled by the OutlinerView are not taken into account here.
785 case SdrEventKind::MoveAction
: MovAction(aLogicPos
); bRet
=true; break;
786 case SdrEventKind::EndAction
: EndAction(); bRet
=true; break;
787 case SdrEventKind::BackAction
: BckAction(); bRet
=true; break;
788 case SdrEventKind::EndMark
: EndAction(); bRet
=true; break;
789 case SdrEventKind::BrkMark
: {
791 if (!MarkObj(aLogicPos
,mnHitTolLog
,rVEvt
.bAddMark
)) {
792 // No object hit. Do the following:
793 // 1. deselect any selected glue points
794 // 2. deselect any selected polygon points
795 // 3. deselect any selected objects
796 if (!rVEvt
.bAddMark
) UnmarkAll();
800 case SdrEventKind::EndCreate
: { // if necessary, MarkObj
801 SdrCreateCmd eCmd
=SdrCreateCmd::NextPoint
;
802 if (MODKEY_PolyPoly
) eCmd
=SdrCreateCmd::NextObject
;
803 if (rVEvt
.nMouseClicks
>1) eCmd
=SdrCreateCmd::ForceEnd
;
804 if (!EndCreateObj(eCmd
)) { // Don't evaluate event for Create? -> Select
805 if (eHit
==SdrHitKind::UnmarkedObject
|| eHit
==SdrHitKind::TextEdit
) {
806 MarkObj(rVEvt
.pRootObj
,rVEvt
.pPV
);
807 if (eHit
==SdrHitKind::TextEdit
)
809 bool bRet2(mpActualOutDev
&& OUTDEV_WINDOW
== mpActualOutDev
->GetOutDevType() &&
810 SdrBeginTextEdit(rVEvt
.pObj
, rVEvt
.pPV
, static_cast<vcl::Window
*>(mpActualOutDev
.get())));
814 MouseEvent
aMEvt(mpActualOutDev
->LogicToPixel(aLogicPos
),
815 1,rVEvt
.nMouseMode
,rVEvt
.nMouseCode
,rVEvt
.nMouseCode
);
817 OutlinerView
* pOLV
=GetTextEditOutlinerView();
819 pOLV
->MouseButtonDown(aMEvt
); // event for the Outliner, but without double-click
820 pOLV
->MouseButtonUp(aMEvt
); // event for the Outliner, but without double-click
824 bRet
=true; // object is selected and (if necessary) TextEdit is started
825 } else bRet
=false; // canceled Create, nothing else
826 } else bRet
=true; // return true for EndCreate
828 case SdrEventKind::EndDrag
: {
829 bRet
=EndDragObj(IsDragWithCopy());
830 ForceMarkedObjToAnotherPage(); // TODO: Undo+bracing missing!
832 case SdrEventKind::MarkObj
: { // + (if applicable) BegDrag
833 if (!rVEvt
.bAddMark
) UnmarkAllObj();
834 bool bUnmark
=rVEvt
.bUnmark
;
835 if (rVEvt
.bPrevNextMark
) {
836 bRet
=MarkNextObj(aLogicPos
,mnHitTolLog
,rVEvt
.bMarkPrev
);
839 const size_t nCount0
=GetMarkedObjectCount();
840 bRet
=MarkObj(aLogicPos
,mnHitTolLog
,rVEvt
.bAddMark
);
842 const size_t nCount1
=GetMarkedObjectCount();
843 bUnmark
=nCount1
<nCount0
;
846 BegDragObj(aLogicPos
,nullptr,nullptr,mnMinMovLog
);
850 case SdrEventKind::MarkPoint
: { // + (if applicable) BegDrag
851 if (!rVEvt
.bAddMark
) UnmarkAllPoints();
852 if (rVEvt
.bPrevNextMark
) {
856 bRet
=MarkPoint(*rVEvt
.pHdl
,rVEvt
.bUnmark
);
858 if (!rVEvt
.bUnmark
&& !rVEvt
.bPrevNextMark
) {
859 BegDragObj(aLogicPos
,nullptr,rVEvt
.pHdl
,mnMinMovLog
);
863 case SdrEventKind::MarkGluePoint
: { // + (if applicable) BegDrag
864 if (!rVEvt
.bAddMark
) UnmarkAllGluePoints();
865 if (rVEvt
.bPrevNextMark
) {
869 bRet
=MarkGluePoint(rVEvt
.pObj
,rVEvt
.nGlueId
,rVEvt
.bUnmark
);
871 if (!rVEvt
.bUnmark
&& !rVEvt
.bPrevNextMark
) {
872 SdrHdl
* pHdl
=GetGluePointHdl(rVEvt
.pObj
,rVEvt
.nGlueId
);
873 BegDragObj(aLogicPos
,nullptr,pHdl
,mnMinMovLog
);
877 case SdrEventKind::BeginMark
: bRet
=BegMark(aLogicPos
,rVEvt
.bAddMark
,rVEvt
.bUnmark
); break;
878 case SdrEventKind::BeginInsertObjPoint
: bRet
= BegInsObjPoint(aLogicPos
, MODKEY_PolyPoly
); break;
879 case SdrEventKind::EndInsertObjPoint
: {
880 SdrCreateCmd eCmd
=SdrCreateCmd::NextPoint
;
881 if (MODKEY_PolyPoly
) eCmd
=SdrCreateCmd::NextObject
;
882 if (rVEvt
.nMouseClicks
>1) eCmd
=SdrCreateCmd::ForceEnd
;
883 EndInsObjPoint(eCmd
);
886 case SdrEventKind::BeginInsertGluePoint
: bRet
=BegInsGluePoint(aLogicPos
); break;
887 case SdrEventKind::BeginDragHelpline
: bRet
=BegDragHelpLine(rVEvt
.nHlplIdx
,rVEvt
.pPV
); break;
888 case SdrEventKind::BeginDragObj
: bRet
=BegDragObj(aLogicPos
,nullptr,rVEvt
.pHdl
,mnMinMovLog
); break;
889 case SdrEventKind::BeginCreateObj
: {
890 if (nCurrentInvent
==SdrInventor::Default
&& nCurrentIdent
==OBJ_CAPTION
) {
891 tools::Long nHgt
=SdrEngineDefaults::GetFontHeight();
892 bRet
=BegCreateCaptionObj(aLogicPos
,Size(5*nHgt
,2*nHgt
));
893 } else bRet
=BegCreateObj(aLogicPos
);
895 case SdrEventKind::BeginMacroObj
: {
896 BegMacroObj(aLogicPos
,mnHitTolLog
,rVEvt
.pObj
,rVEvt
.pPV
,static_cast<vcl::Window
*>(mpActualOutDev
.get()));
899 case SdrEventKind::BeginTextEdit
: {
900 if (!IsObjMarked(rVEvt
.pObj
)) {
902 MarkObj(rVEvt
.pRootObj
,rVEvt
.pPV
);
905 bRet
= mpActualOutDev
&& OUTDEV_WINDOW
== mpActualOutDev
->GetOutDevType()&&
906 SdrBeginTextEdit(rVEvt
.pObj
, rVEvt
.pPV
, static_cast<vcl::Window
*>(mpActualOutDev
.get()));
910 MouseEvent
aMEvt(mpActualOutDev
->LogicToPixel(aLogicPos
),
911 1,rVEvt
.nMouseMode
,rVEvt
.nMouseCode
,rVEvt
.nMouseCode
);
912 OutlinerView
* pOLV
=GetTextEditOutlinerView();
913 if (pOLV
!=nullptr) pOLV
->MouseButtonDown(aMEvt
); // event for the Outliner, but without double-click
918 if (bRet
&& mpActualOutDev
&& mpActualOutDev
->GetOutDevType()==OUTDEV_WINDOW
) {
919 vcl::Window
* pWin
=static_cast<vcl::Window
*>(mpActualOutDev
.get());
920 // left mouse button pressed?
921 bool bLeftDown
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0 && rVEvt
.bMouseDown
;
922 // left mouse button released?
923 bool bLeftUp
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0 && rVEvt
.bMouseUp
;
924 // left mouse button pressed or held?
925 bool bLeftDown1
=(rVEvt
.nMouseCode
&MOUSE_LEFT
)!=0 && !rVEvt
.bMouseUp
;
926 pWin
->SetPointer(GetPreferredPointer(rVEvt
.aLogicPos
,pWin
,
927 rVEvt
.nMouseCode
& (KEY_SHIFT
|KEY_MOD1
|KEY_MOD2
),bLeftDown1
));
928 bool bAction
=IsAction();
929 if (bLeftDown
&& bAction
)
930 pWin
->CaptureMouse();
931 else if (bLeftUp
|| (rVEvt
.bIsAction
&& !bAction
))
932 pWin
->ReleaseMouse();
937 PointerStyle
SdrView::GetPreferredPointer(const Point
& rMousePos
, const OutputDevice
* pOut
, sal_uInt16 nModifier
, bool bLeftDown
) const
942 return pCurrentCreate
->GetCreatePointer();
944 if (mpCurrentSdrDragMethod
)
946 return mpCurrentSdrDragMethod
->GetSdrDragPointer();
948 if (IsMarkObj() || IsMarkPoints() || IsMarkGluePoints() || IsSetPageOrg()) return PointerStyle::Arrow
;
949 if (IsDragHelpLine()) return GetDraggedHelpLinePointer();
951 SdrObjMacroHitRec aHitRec
;
952 aHitRec
.aPos
=pOut
->LogicToPixel(rMousePos
);
953 aHitRec
.nTol
=nMacroTol
;
954 aHitRec
.pVisiLayer
=&pMacroPV
->GetVisibleLayers();
955 aHitRec
.pPageView
=pMacroPV
;
956 return pMacroObj
->GetMacroPointer(aHitRec
);
959 // TextEdit, ObjEdit, Macro
960 if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos
)))
962 if(!pOut
|| IsTextEditInSelectionMode())
964 if(pTextEditOutliner
->IsVertical())
965 return PointerStyle::TextVertical
;
967 return PointerStyle::Text
;
969 // Outliner should return something here...
970 Point
aPos(pOut
->LogicToPixel(rMousePos
));
971 PointerStyle
aPointer(pTextEditOutlinerView
->GetPointer(aPos
));
972 if (aPointer
==PointerStyle::Arrow
)
974 if(pTextEditOutliner
->IsVertical())
975 aPointer
= PointerStyle::TextVertical
;
977 aPointer
= PointerStyle::Text
;
983 aVEvt
.nMouseCode
=(nModifier
&(KEY_SHIFT
|KEY_MOD1
|KEY_MOD2
))|MOUSE_LEFT
; // to see what would happen on MouseLeftDown
984 aVEvt
.bMouseDown
=!bLeftDown
; // What if ..?
985 aVEvt
.bMouseUp
=bLeftDown
; // What if ..?
987 const_cast<SdrView
*>(this)->SetActualWin(pOut
);
988 SdrHitKind eHit
=PickAnything(rMousePos
,aVEvt
);
989 SdrEventKind eEvent
=aVEvt
.eEvent
;
992 case SdrEventKind::BeginCreateObj
:
993 return aCurrentCreatePointer
;
994 case SdrEventKind::MarkObj
:
995 return PointerStyle::Move
;
996 case SdrEventKind::BeginMark
:
997 return PointerStyle::Arrow
;
998 case SdrEventKind::MarkPoint
:
999 case SdrEventKind::MarkGluePoint
:
1000 return PointerStyle::MovePoint
;
1001 case SdrEventKind::BeginInsertObjPoint
:
1002 case SdrEventKind::BeginInsertGluePoint
:
1003 return PointerStyle::Cross
;
1004 case SdrEventKind::ExecuteUrl
:
1005 return PointerStyle::RefHand
;
1006 case SdrEventKind::BeginMacroObj
:
1008 SdrObjMacroHitRec aHitRec
;
1009 aHitRec
.aPos
=aVEvt
.aLogicPos
;
1010 aHitRec
.nTol
=mnHitTolLog
;
1011 aHitRec
.pVisiLayer
=&aVEvt
.pPV
->GetVisibleLayers();
1012 aHitRec
.pPageView
=aVEvt
.pPV
;
1013 return aVEvt
.pObj
->GetMacroPointer(aHitRec
);
1020 case SdrHitKind::Cell
:
1021 return PointerStyle::Arrow
;
1022 case SdrHitKind::HelpLine
:
1023 return aVEvt
.pPV
->GetHelpLines()[aVEvt
.nHlplIdx
].GetPointer();
1024 case SdrHitKind::Gluepoint
:
1025 return PointerStyle::MovePoint
;
1026 case SdrHitKind::TextEdit
:
1027 case SdrHitKind::TextEditObj
:
1029 SdrTextObj
* pText
= dynamic_cast< SdrTextObj
* >( aVEvt
.pObj
);
1030 if(pText
&& pText
->HasText())
1032 OutlinerParaObject
* pParaObj
= pText
->GetOutlinerParaObject();
1033 if(pParaObj
&& pParaObj
->IsVertical())
1034 return PointerStyle::TextVertical
;
1036 return PointerStyle::Text
;
1041 bool bMarkHit
=eHit
==SdrHitKind::MarkedObject
;
1042 SdrHdl
* pHdl
=aVEvt
.pHdl
;
1043 // now check the pointers for dragging
1044 if (pHdl
!=nullptr || bMarkHit
) {
1045 SdrHdlKind eHdl
= pHdl
!=nullptr ? pHdl
->GetKind() : SdrHdlKind::Move
;
1046 bool bCorner
=pHdl
!=nullptr && pHdl
->IsCornerHdl();
1047 bool bVertex
=pHdl
!=nullptr && pHdl
->IsVertexHdl();
1048 bool bMov
=eHdl
==SdrHdlKind::Move
;
1049 if (bMov
&& (meDragMode
==SdrDragMode::Move
|| meDragMode
==SdrDragMode::Resize
|| mbMarkedHitMovesAlways
)) {
1050 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1051 return PointerStyle::Move
;
1053 switch (meDragMode
) {
1054 case SdrDragMode::Rotate
: {
1055 if ((bCorner
|| bMov
) && !IsRotateAllowed(true))
1056 return PointerStyle::NotAllowed
;
1058 // are 3D objects selected?
1059 bool b3DObjSelected
= false;
1060 for (size_t a
=0; !b3DObjSelected
&& a
<GetMarkedObjectCount(); ++a
) {
1061 SdrObject
* pObj
= GetMarkedObjectByIndex(a
);
1062 if(dynamic_cast<const E3dObject
* >(pObj
) != nullptr)
1063 b3DObjSelected
= true;
1065 // If we have a 3D object, go on despite !IsShearAllowed,
1066 // because then we have a rotation instead of a shear.
1067 if (bVertex
&& !IsShearAllowed() && !b3DObjSelected
)
1068 return PointerStyle::NotAllowed
;
1070 return PointerStyle::Rotate
;
1072 case SdrDragMode::Shear
: {
1074 if (!IsDistortAllowed(true) && !IsDistortAllowed()) return PointerStyle::NotAllowed
;
1075 else return PointerStyle::RefHand
;
1077 if (bVertex
&& !IsShearAllowed()) return PointerStyle::NotAllowed
;
1079 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1080 return PointerStyle::Move
;
1083 case SdrDragMode::Mirror
: {
1084 if (bCorner
|| bVertex
|| bMov
) {
1085 SdrHdl
* pH1
=maHdlList
.GetHdl(SdrHdlKind::Ref1
);
1086 SdrHdl
* pH2
=maHdlList
.GetHdl(SdrHdlKind::Ref2
);
1089 if (pH1
!=nullptr && pH2
!=nullptr) {
1090 Point aDif
= pH2
->GetPos()-pH1
->GetPos();
1091 b90
=(aDif
.X()==0) || aDif
.Y()==0;
1092 b45
=b90
|| (std::abs(aDif
.X())==std::abs(aDif
.Y()));
1095 if (!IsMirrorAllowed(true,true)) bNo
=true; // any mirroring is forbidden
1096 if (!IsMirrorAllowed() && !b45
) bNo
=true; // mirroring freely is forbidden
1097 if (!IsMirrorAllowed(true) && !b90
) bNo
=true; // mirroring horizontally/vertically is allowed
1098 if (bNo
) return PointerStyle::NotAllowed
;
1100 return PointerStyle::Mirror
;
1102 return PointerStyle::Mirror
;
1106 case SdrDragMode::Transparence
:
1108 if(!IsTransparenceAllowed())
1109 return PointerStyle::NotAllowed
;
1111 return PointerStyle::RefHand
;
1114 case SdrDragMode::Gradient
:
1116 if(!IsGradientAllowed())
1117 return PointerStyle::NotAllowed
;
1119 return PointerStyle::RefHand
;
1122 case SdrDragMode::Crook
: {
1123 if (bCorner
|| bVertex
|| bMov
) {
1124 if (!IsCrookAllowed(true) && !IsCrookAllowed()) return PointerStyle::NotAllowed
;
1125 return PointerStyle::Crook
;
1130 case SdrDragMode::Crop
:
1132 return PointerStyle::Crop
;
1136 if ((bCorner
|| bVertex
) && !IsResizeAllowed(true)) return PointerStyle::NotAllowed
;
1139 if (pHdl
!=nullptr) return pHdl
->GetPointer();
1141 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1142 return PointerStyle::Move
;
1145 if (meEditMode
==SdrViewEditMode::Create
) return aCurrentCreatePointer
;
1146 return PointerStyle::Arrow
;
1149 #define STR_NOTHING "nothing"
1150 OUString
SdrView::GetStatusText()
1153 OUString aStr
= STR_NOTHING
;
1155 if (pCurrentCreate
!=nullptr)
1157 aStr
=pCurrentCreate
->getSpecialDragComment(maDragStat
);
1161 aName
= pCurrentCreate
->TakeObjNameSingul();
1162 aStr
= SvxResId(STR_ViewCreateObj
);
1165 else if (mpCurrentSdrDragMethod
)
1167 if (mbInsPolyPoint
|| IsInsertGluePoint())
1169 aStr
=maInsPointUndoStr
;
1173 if (maDragStat
.IsMinMoved())
1177 "(" << this << ") " << mpCurrentSdrDragMethod
.get());
1178 aStr
= mpCurrentSdrDragMethod
->GetSdrDragComment();
1182 else if(IsMarkObj())
1184 if(AreObjectsMarked())
1186 aStr
= SvxResId(STR_ViewMarkMoreObjs
);
1190 aStr
= SvxResId(STR_ViewMarkObjs
);
1193 else if(IsMarkPoints())
1195 if(HasMarkedPoints())
1197 aStr
= SvxResId(STR_ViewMarkMorePoints
);
1201 aStr
= SvxResId(STR_ViewMarkPoints
);
1203 } else if (IsMarkGluePoints())
1205 if(HasMarkedGluePoints())
1207 aStr
= SvxResId(STR_ViewMarkMoreGluePoints
);
1211 aStr
= SvxResId(STR_ViewMarkGluePoints
);
1214 else if (IsTextEdit() && pTextEditOutlinerView
!=nullptr) {
1215 aStr
=SvxResId(STR_ViewTextEdit
); // "TextEdit - Row y, Column x";
1216 ESelection
aSel(pTextEditOutlinerView
->GetSelection());
1217 tools::Long nPar
=aSel
.nEndPara
,nLin
=0,nCol
=aSel
.nEndPos
;
1218 if (aSel
.nEndPara
>0) {
1219 for (sal_Int32 nParaNum
=0; nParaNum
<aSel
.nEndPara
; nParaNum
++) {
1220 nLin
+=pTextEditOutliner
->GetLineCount(nParaNum
);
1223 // A little imperfection:
1224 // At the end of a line of any multi-line paragraph, we display the
1225 // position of the next line of the same paragraph, if there is one.
1226 sal_uInt16 nParaLine
= 0;
1227 sal_uLong nParaLineCount
= pTextEditOutliner
->GetLineCount(aSel
.nEndPara
);
1231 sal_uInt16 nLen
= pTextEditOutliner
->GetLineLen(aSel
.nEndPara
, nParaLine
);
1232 bool bLastLine
= (nParaLine
== nParaLineCount
- 1);
1233 if (nCol
>nLen
|| (!bLastLine
&& nCol
== nLen
))
1243 bBrk
= true; // to be sure
1246 aStr
= aStr
.replaceFirst("%1", OUString::number(nPar
+ 1));
1247 aStr
= aStr
.replaceFirst("%2", OUString::number(nLin
+ 1));
1248 aStr
= aStr
.replaceFirst("%3", OUString::number(nCol
+ 1));
1251 aStr
+= ", Level " + OUString::number( pTextEditOutliner
->GetDepth( aSel
.nEndPara
) );
1255 if(aStr
== STR_NOTHING
)
1257 if (AreObjectsMarked()) {
1258 aStr
= ImpGetDescriptionString(STR_ViewMarked
);
1259 if (IsGluePointEditMode()) {
1260 if (HasMarkedGluePoints()) {
1261 aStr
= ImpGetDescriptionString(STR_ViewMarked
, ImpGetDescriptionOptions::GLUEPOINTS
);
1264 if (HasMarkedPoints()) {
1265 aStr
= ImpGetDescriptionString(STR_ViewMarked
, ImpGetDescriptionOptions::POINTS
);
1272 else if(!aName
.isEmpty())
1274 aStr
= aStr
.replaceFirst("%1", aName
);
1279 // capitalize first letter
1280 aStr
= aStr
.replaceAt(0, 1, OUString(aStr
[0]).toAsciiUpperCase());
1285 SdrViewContext
SdrView::GetContext() const
1287 if( IsGluePointEditMode() )
1288 return SdrViewContext::GluePointEdit
;
1290 const size_t nMarkCount
= GetMarkedObjectCount();
1292 if( HasMarkablePoints() && !IsFrameHandles() )
1295 for( size_t nMarkNum
= 0; nMarkNum
< nMarkCount
&& bPath
; ++nMarkNum
)
1296 if (dynamic_cast<const SdrPathObj
*>(GetMarkedObjectByIndex(nMarkNum
)) == nullptr)
1300 return SdrViewContext::PointEdit
;
1303 if( GetMarkedObjectCount() )
1305 bool bGraf
= true, bMedia
= true, bTable
= true;
1307 for( size_t nMarkNum
= 0; nMarkNum
< nMarkCount
&& ( bGraf
|| bMedia
); ++nMarkNum
)
1309 const SdrObject
* pMarkObj
= GetMarkedObjectByIndex( nMarkNum
);
1310 DBG_ASSERT( pMarkObj
, "SdrView::GetContext(), null pointer in mark list!" );
1315 if( dynamic_cast<const SdrGrafObj
*>( pMarkObj
) == nullptr )
1318 if( dynamic_cast<const SdrMediaObj
*>( pMarkObj
) == nullptr )
1321 if( dynamic_cast<const sdr::table::SdrTableObj
* >( pMarkObj
) == nullptr )
1326 return SdrViewContext::Graphic
;
1328 return SdrViewContext::Media
;
1330 return SdrViewContext::Table
;
1333 return SdrViewContext::Standard
;
1336 void SdrView::MarkAll()
1339 GetTextEditOutlinerView()->SetSelection(ESelection(0,0,EE_PARA_ALL
,EE_TEXTPOS_ALL
));
1340 } else if (IsGluePointEditMode()) MarkAllGluePoints();
1341 else if (HasMarkablePoints()) MarkAllPoints();
1345 void SdrView::UnmarkAll()
1348 ESelection eSel
=GetTextEditOutlinerView()->GetSelection();
1349 eSel
.nStartPara
=eSel
.nEndPara
;
1350 eSel
.nStartPos
=eSel
.nEndPos
;
1351 GetTextEditOutlinerView()->SetSelection(eSel
);
1352 } else if (HasMarkedGluePoints()) UnmarkAllGluePoints();
1353 else if (HasMarkedPoints()) UnmarkAllPoints(); // Marked, not Markable!
1354 else UnmarkAllObj();
1357 const tools::Rectangle
& SdrView::GetMarkedRect() const
1359 if (IsGluePointEditMode() && HasMarkedGluePoints()) {
1360 return GetMarkedGluePointsRect();
1362 if (HasMarkedPoints()) {
1363 return GetMarkedPointsRect();
1365 return GetMarkedObjRect();
1368 void SdrView::DeleteMarked()
1372 SdrObjEditView::KeyInput(KeyEvent(0,vcl::KeyCode(KeyFuncType::DELETE
)),pTextEditWin
);
1376 if( mxSelectionController
.is() && mxSelectionController
->DeleteMarked() )
1378 // action already performed by current selection controller, do nothing
1380 else if (IsGluePointEditMode() && HasMarkedGluePoints())
1382 DeleteMarkedGluePoints();
1384 else if (GetContext()==SdrViewContext::PointEdit
&& HasMarkedPoints())
1386 DeleteMarkedPoints();
1395 bool SdrView::BegMark(const Point
& rPnt
, bool bAddMark
, bool bUnmark
)
1397 if (bUnmark
) bAddMark
=true;
1398 if (IsGluePointEditMode()) {
1399 if (!bAddMark
) UnmarkAllGluePoints();
1400 return BegMarkGluePoints(rPnt
,bUnmark
);
1401 } else if (HasMarkablePoints()) {
1402 if (!bAddMark
) UnmarkAllPoints();
1403 return BegMarkPoints(rPnt
,bUnmark
);
1405 if (!bAddMark
) UnmarkAllObj();
1406 BegMarkObj(rPnt
,bUnmark
);
1411 void SdrView::ConfigurationChanged( ::utl::ConfigurationBroadcaster
*p
, ConfigurationHints nHint
)
1413 onAccessibilityOptionsChanged();
1414 SdrCreateView::ConfigurationChanged(p
, nHint
);
1418 /** method is called whenever the global SvtAccessibilityOptions is changed */
1419 void SdrView::onAccessibilityOptionsChanged()
1423 void SdrView::SetMasterPagePaintCaching(bool bOn
)
1425 if(mbMasterPagePaintCaching
== bOn
)
1428 mbMasterPagePaintCaching
= bOn
;
1430 // reset at all SdrPageWindows
1431 SdrPageView
* pPageView
= GetSdrPageView();
1436 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1438 SdrPageWindow
* pPageWindow
= pPageView
->GetPageWindow(b
);
1439 assert(pPageWindow
&& "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)");
1441 // force deletion of ObjectContact, so at re-display all VOCs
1442 // will be re-created with updated flag setting
1443 pPageWindow
->ResetObjectContact();
1446 // force redraw of this view
1447 pPageView
->InvalidateAllWin();
1450 // Default ObjectContact is ObjectContactOfPageView
1451 sdr::contact::ObjectContact
* SdrView::createViewSpecificObjectContact(
1452 SdrPageWindow
& rPageWindow
,
1453 const char* pDebugName
) const
1455 return new sdr::contact::ObjectContactOfPageView(rPageWindow
, pDebugName
);
1458 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */