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/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/drawinglayer_primitivetypes2d.hxx>
46 #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
47 #include <svx/sdr/contact/objectcontactofpageview.hxx>
48 #include <sal/log.hxx>
49 #include <vcl/ptrstyle.hxx>
50 #include <vcl/window.hxx>
51 #include <comphelper/lok.hxx>
54 SdrViewEvent::SdrViewEvent()
60 meHit(SdrHitKind::NONE
),
61 meEvent(SdrEventKind::NONE
),
63 mnMouseMode(MouseEventModifiers::NONE
),
73 mbPrevNextMark(false),
78 // helper class for all D&D overlays
80 void SdrDropMarkerOverlay::ImplCreateOverlays(
82 const basegfx::B2DPolyPolygon
& rLinePolyPolygon
)
84 for(sal_uInt32
a(0); a
< rView
.PaintWindowCount(); a
++)
86 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
87 const rtl::Reference
< sdr::overlay::OverlayManager
>& xTargetOverlay
= pCandidate
->GetOverlayManager();
89 if (xTargetOverlay
.is())
91 std::unique_ptr
<sdr::overlay::OverlayPolyPolygonStripedAndFilled
> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
94 xTargetOverlay
->add(*pNew
);
95 maObjects
.append(std::move(pNew
));
100 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const SdrObject
& rObject
)
104 rObject
.TakeXorPoly());
107 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const tools::Rectangle
& rRectangle
)
109 basegfx::B2DPolygon aB2DPolygon
;
111 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()));
112 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
113 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
114 aB2DPolygon
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
115 aB2DPolygon
.setClosed(true);
119 basegfx::B2DPolyPolygon(aB2DPolygon
));
122 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView
& rView
, const Point
& rStart
, const Point
& rEnd
)
124 basegfx::B2DPolygon aB2DPolygon
;
126 aB2DPolygon
.append(basegfx::B2DPoint(rStart
.X(), rStart
.Y()));
127 aB2DPolygon
.append(basegfx::B2DPoint(rEnd
.X(), rEnd
.Y()));
128 aB2DPolygon
.setClosed(true);
132 basegfx::B2DPolyPolygon(aB2DPolygon
));
135 SdrDropMarkerOverlay::~SdrDropMarkerOverlay()
137 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
138 // That destructor calls clear() at the list which removes all objects from the
139 // OverlayManager and deletes them.
145 : SdrCreateView(rSdrModel
, pOut
),
146 mbNoExtendedMouseDispatcher(false),
147 mbNoExtendedKeyDispatcher(false),
148 mbMasterPagePaintCaching(false)
156 bool SdrView::KeyInput(const KeyEvent
& rKEvt
, vcl::Window
* pWin
)
158 SetActualWin(pWin
? pWin
->GetOutDev() : nullptr);
159 bool bRet
= SdrCreateView::KeyInput(rKEvt
,pWin
);
160 if (!bRet
&& !IsExtendedKeyInputDispatcherEnabled()) {
162 switch (rKEvt
.GetKeyCode().GetFullFunction()) {
163 case KeyFuncType::DELETE
: DeleteMarked(); break;
164 case KeyFuncType::UNDO
: GetModel().Undo(); break;
165 case KeyFuncType::REDO
: GetModel().Redo(); break;
167 switch (rKEvt
.GetKeyCode().GetFullCode()) {
169 if (IsTextEdit()) SdrEndTextEdit();
170 if (IsAction()) BrkAction();
171 if (pWin
!=nullptr) pWin
->ReleaseMouse();
173 case KEY_DELETE
: DeleteMarked(); break;
174 case KEY_UNDO
: case KEY_BACKSPACE
+KEY_MOD2
: GetModel().Undo(); break;
175 case KEY_BACKSPACE
+KEY_MOD2
+KEY_SHIFT
: GetModel().Redo(); break;
176 case KEY_REPEAT
: case KEY_BACKSPACE
+KEY_MOD2
+KEY_MOD1
: GetModel().Repeat(*this); break;
177 case KEY_MOD1
+KEY_A
: MarkAll(); break;
182 if (bRet
&& pWin
!=nullptr) {
183 pWin
->SetPointer(GetPreferredPointer(
184 pWin
->PixelToLogic(pWin
->ScreenToOutputPixel( pWin
->GetPointerPosPixel() ) ),
186 rKEvt
.GetKeyCode().GetModifier()));
192 bool SdrView::MouseButtonDown(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
195 if (rMEvt
.IsLeft()) maDragStat
.SetMouseDown(true);
196 bool bRet
= SdrCreateView::MouseButtonDown(rMEvt
,pWin
);
197 if (!bRet
&& !IsExtendedMouseEventDispatcherEnabled()) {
199 PickAnything(rMEvt
,SdrMouseEventKind::BUTTONDOWN
,aVEvt
);
200 bRet
= DoMouseEvent(aVEvt
);
205 bool SdrView::MouseButtonUp(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
208 if (rMEvt
.IsLeft()) maDragStat
.SetMouseDown(false);
209 bool bAction
= IsAction();
210 bool bRet
= !bAction
&& SdrCreateView::MouseButtonUp(rMEvt
,pWin
);
211 if (!bRet
&& !IsExtendedMouseEventDispatcherEnabled()) {
213 PickAnything(rMEvt
,SdrMouseEventKind::BUTTONUP
,aVEvt
);
214 bRet
= DoMouseEvent(aVEvt
);
219 bool SdrView::MouseMove(const MouseEvent
& rMEvt
, OutputDevice
* pWin
)
222 maDragStat
.SetMouseDown(rMEvt
.IsLeft());
223 bool bRet
= SdrCreateView::MouseMove(rMEvt
,pWin
);
224 if (!IsExtendedMouseEventDispatcherEnabled() && !IsTextEditInSelectionMode()) {
226 PickAnything(rMEvt
,SdrMouseEventKind::MOVE
,aVEvt
);
227 if (DoMouseEvent(aVEvt
)) bRet
=true;
233 bool SdrView::Command(const CommandEvent
& rCEvt
, vcl::Window
* pWin
)
235 SetActualWin(pWin
->GetOutDev());
236 bool bRet
= SdrCreateView::Command(rCEvt
,pWin
);
240 void SdrView::GetAttributes(SfxItemSet
& rTargetSet
, bool bOnlyHardAttr
) const
242 SdrCreateView::GetAttributes(rTargetSet
, bOnlyHardAttr
);
245 SdrHitKind
SdrView::PickAnything(const MouseEvent
& rMEvt
, SdrMouseEventKind nEventKind
, SdrViewEvent
& rVEvt
) const
247 rVEvt
.mbMouseDown
= nEventKind
==SdrMouseEventKind::BUTTONDOWN
;
248 rVEvt
.mbMouseUp
= nEventKind
==SdrMouseEventKind::BUTTONUP
;
249 rVEvt
.mnMouseClicks
= rMEvt
.GetClicks();
250 rVEvt
.mnMouseMode
= rMEvt
.GetMode();
251 rVEvt
.mnMouseCode
= rMEvt
.GetButtons() | rMEvt
.GetModifier();
252 const OutputDevice
* pOut
=mpActualOutDev
;
255 pOut
= GetFirstOutputDevice();
257 Point
aPnt(rMEvt
.GetPosPixel());
258 if (pOut
!=nullptr) aPnt
=pOut
->PixelToLogic(aPnt
);
262 // Shape's x coordinates are all negated,
263 // Hence negate mouse event's x coord to match.
264 aPnt
.setX(-aPnt
.X());
267 rVEvt
.maLogicPos
= aPnt
;
268 return PickAnything(aPnt
,rVEvt
);
271 // Dragging with the Mouse (Move)
272 // Example when creating a rectangle: MouseDown has to happen without a ModKey,
273 // else we usually force a selection (see below).
274 // When pressing Shift, Ctrl and Alt at the same time while doing a MouseMove,
275 // a centered, not snapped square is created.
276 // The dual allocation of Ortho and Shift won't usually create a problem, as the
277 // two functions are in most cases mutually exclusive. Only shearing (the kind
278 // that happens when contorting, not when rotating) can use both functions at
279 // the same time. To get around this, the user can use e. g. help lines.
280 #define MODKEY_NoSnap bCtrl /* temporarily disable snapping */
281 #define MODKEY_Ortho bShift /* ortho */
282 #define MODKEY_Center bAlt /* create/resize centeredly */
283 #define MODKEY_AngleSnap bShift
284 #define MODKEY_CopyDrag bCtrl /* drag and copy */
286 // click somewhere (MouseDown)
287 #define MODKEY_PolyPoly bAlt /* new Poly at InsPt and at Create */
288 #define MODKEY_MultiMark bShift /* MarkObj without doing UnmarkAll first */
289 #define MODKEY_Unmark bAlt /* deselect with a dragged frame */
290 #define MODKEY_ForceMark bCtrl /* force dragging a frame, even if there's an object at cursor position */
291 #define MODKEY_DeepMark bAlt /* MarkNextObj */
292 #define MODKEY_DeepBackw bShift /* MarkNextObj but backwards */
294 SdrHitKind
SdrView::PickAnything(const Point
& rLogicPos
, SdrViewEvent
& rVEvt
) const
296 const OutputDevice
* pOut
=mpActualOutDev
;
299 pOut
= GetFirstOutputDevice();
302 // #i73628# Use a non-changeable copy of he logic position
303 const Point
aLocalLogicPosition(rLogicPos
);
305 bool bEditMode
=IsEditMode();
306 bool bPointMode
=bEditMode
&& HasMarkablePoints();
307 bool bGluePointMode
=IsGluePointEditMode();
308 bool bInsPolyPt
=bPointMode
&& IsInsObjPointMode() && IsInsObjPointPossible();
309 bool bInsGluePt
=bGluePointMode
&& IsInsGluePointMode() && IsInsGluePointPossible();
310 bool bIsTextEdit
=IsTextEdit();
311 bool bTextEditHit
=IsTextEditHit(aLocalLogicPosition
);
312 bool bTextEditSel
=IsTextEditInSelectionMode();
313 bool bShift
= (rVEvt
.mnMouseCode
& KEY_SHIFT
) != 0;
314 bool bCtrl
= (rVEvt
.mnMouseCode
& KEY_MOD1
) != 0;
315 bool bAlt
= (rVEvt
.mnMouseCode
& KEY_MOD2
) != 0;
316 SdrHitKind eHit
=SdrHitKind::NONE
;
317 SdrHdl
* pHdl
=pOut
!=nullptr && !bTextEditSel
? PickHandle(aLocalLogicPosition
) : nullptr;
318 SdrPageView
* pPV
=nullptr;
319 SdrObject
* pObj
=nullptr;
320 SdrObject
* pHitObj
=nullptr;
321 bool bHitPassDirect
=true;
322 sal_uInt16 nHlplIdx
=0;
323 sal_uInt16 nGlueId
=0;
324 if (bTextEditHit
|| bTextEditSel
)
326 eHit
=SdrHitKind::TextEdit
;
328 else if (pHdl
!=nullptr)
330 eHit
=SdrHitKind::Handle
; // handle is hit: highest priority
332 else if (bEditMode
&& IsHlplVisible() && IsHlplFront() && pOut
!=nullptr && PickHelpLine(aLocalLogicPosition
,mnHitTolLog
,*pOut
,nHlplIdx
,pPV
))
334 eHit
=SdrHitKind::HelpLine
; // help line in the foreground hit: can be moved now
336 else if (bGluePointMode
&& PickGluePoint(aLocalLogicPosition
,pObj
,nGlueId
,pPV
))
338 eHit
=SdrHitKind::Gluepoint
; // deselected gluepoint hit
340 else if ((pHitObj
= PickObj(aLocalLogicPosition
,mnHitTolLog
,pPV
,SdrSearchOptions::DEEP
|SdrSearchOptions::MARKED
,&pObj
,&bHitPassDirect
)))
342 eHit
=SdrHitKind::MarkedObject
;
343 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast< sdr::table::SdrTableObj
* >( pObj
);
346 sal_Int32 nX
= 0, nY
= 0;
347 switch( pTableObj
->CheckTableHit( aLocalLogicPosition
, nX
, nY
) )
349 case sdr::table::TableHitKind::Cell
:
350 eHit
= SdrHitKind::Cell
;
352 case sdr::table::TableHitKind::CellTextArea
:
353 eHit
= SdrHitKind::TextEditObj
;
360 else if ((pHitObj
= PickObj(aLocalLogicPosition
,mnHitTolLog
,pPV
,SdrSearchOptions::DEEP
|SdrSearchOptions::ALSOONMASTER
|SdrSearchOptions::WHOLEPAGE
,&pObj
,&bHitPassDirect
)))
362 // MasterPages and WholePage for Macro and URL
363 eHit
=SdrHitKind::UnmarkedObject
;
364 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast< sdr::table::SdrTableObj
* >( pObj
);
367 sal_Int32 nX
= 0, nY
= 0;
368 switch( pTableObj
->CheckTableHit( aLocalLogicPosition
, nX
, nY
, mnHitTolLog
) )
370 case sdr::table::TableHitKind::Cell
:
371 eHit
= SdrHitKind::Cell
;
373 case sdr::table::TableHitKind::CellTextArea
:
374 // Keep state on UnmarkedObject to allow the below
375 // 'check for URL field' to be executed, else popups
376 // for e.g. URL links when hoovering and clicking
377 // them will not work. Tried several other changes,
378 // but this one safely keeps existing behaviour as-is.
379 // Except for the LOK. LOK doesn't have hoovering popup
381 eHit
= comphelper::LibreOfficeKit::isActive() ? SdrHitKind::TextEditObj
: SdrHitKind::UnmarkedObject
;
388 else if (bEditMode
&& IsHlplVisible() && !IsHlplFront() && pOut
!=nullptr && PickHelpLine(aLocalLogicPosition
,mnHitTolLog
,*pOut
,nHlplIdx
,pPV
))
390 eHit
=SdrHitKind::HelpLine
; // help line in foreground hit: can be moved now
392 if (eHit
==SdrHitKind::UnmarkedObject
)
394 bool bRoot
=pObj
->HasMacro();
395 bool bDeep
=pObj
!=pHitObj
&& pHitObj
->HasMacro();
396 bool bMid
=false; // Have we hit upon a grouped group with a macro?
397 SdrObject
* pMidObj
=nullptr;
400 SdrObject
* pObjTmp
=pHitObj
->getParentSdrObjectFromSdrObject();
401 if (pObjTmp
==pObj
) pObjTmp
=nullptr;
402 while (pObjTmp
!=nullptr)
404 if (pObjTmp
->HasMacro())
409 pObjTmp
=pObjTmp
->getParentSdrObjectFromSdrObject();
410 if (pObjTmp
==pObj
) pObjTmp
=nullptr;
414 if (bDeep
|| bMid
|| bRoot
)
416 SdrObjMacroHitRec aHitRec
;
417 aHitRec
.aPos
=aLocalLogicPosition
;
418 aHitRec
.nTol
=mnHitTolLog
;
419 aHitRec
.pVisiLayer
=&pPV
->GetVisibleLayers();
420 aHitRec
.pPageView
=pPV
;
421 if (bDeep
) bDeep
=pHitObj
->IsMacroHit(aHitRec
);
422 if (bMid
) bMid
=pMidObj
->IsMacroHit(aHitRec
);
423 if (bRoot
) bRoot
=pObj
->IsMacroHit(aHitRec
);
424 if (bRoot
|| bMid
|| bDeep
)
426 // Priorities: 1. Root, 2. Mid, 3. Deep
427 rVEvt
.mpRootObj
= pObj
;
428 if (!bRoot
) pObj
=pMidObj
;
429 if (!bRoot
&& !bMid
) pObj
=pHitObj
;
430 eHit
=SdrHitKind::Macro
;
434 // check for URL field
435 if (eHit
==SdrHitKind::UnmarkedObject
)
437 SdrTextObj
* pTextObj
=DynCastSdrTextObj( pHitObj
);
438 if (pTextObj
!=nullptr && pTextObj
->HasText())
440 // use the primitive-based HitTest which is more accurate anyways. It
441 // will correctly handle rotated/mirrored/sheared/scaled text and can
442 // now return a HitContainer containing the primitive hierarchy of the
443 // primitive that triggered the hit. The first entry is that primitive,
444 // the others are the full stack of primitives leading to that one which
445 // includes grouping primitives (like TextHierarchyPrimitives we deed here)
446 // but also all decomposed ones which lead to the creation of that primitive
447 drawinglayer::primitive2d::Primitive2DContainer aHitContainer
;
448 const bool bTEHit(pPV
&& SdrObjectPrimitiveHit(*pTextObj
, aLocalLogicPosition
, {0, 0}, *pPV
, &pPV
->GetVisibleLayers(), true, &aHitContainer
));
450 if (bTEHit
&& !aHitContainer
.empty())
452 // search for TextHierarchyFieldPrimitive2D which contains the needed information
453 // about a possible URLField
454 const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D
* pTextHierarchyFieldPrimitive2D
= nullptr;
456 for (const drawinglayer::primitive2d::Primitive2DReference
& xReference
: aHitContainer
)
458 auto pBasePrimitive
= xReference
.get();
459 if (pBasePrimitive
&& pBasePrimitive
->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D
)
461 pTextHierarchyFieldPrimitive2D
= static_cast<const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D
*>(pBasePrimitive
);
466 if (nullptr != pTextHierarchyFieldPrimitive2D
)
468 if (drawinglayer::primitive2d::FieldType::FIELD_TYPE_URL
== pTextHierarchyFieldPrimitive2D
->getType())
470 // problem with the old code is that a *pointer* to an instance of
471 // SvxURLField is set in the Event which is per se not good since that
472 // data comes from a temporary EditEngine's data and could vanish any
473 // moment. Have to replace for now with a static instance that gets
474 // filled/initialized from the original data held in the TextHierarchyField-
475 // Primitive2D (see impTextBreakupHandler::impCheckFieldPrimitive).
476 // Unfortunately things like 'TargetFrame' are still used in Calc, so this
477 // can currently not get replaced. For the future the Name/Value vector or
478 // the TextHierarchyFieldPrimitive2D itself should/will be used for handling
480 static SvxURLField aSvxURLField
;
482 aSvxURLField
.SetURL(pTextHierarchyFieldPrimitive2D
->getValue(u
"URL"_ustr
));
483 aSvxURLField
.SetRepresentation(pTextHierarchyFieldPrimitive2D
->getValue(u
"Representation"_ustr
));
484 aSvxURLField
.SetTargetFrame(pTextHierarchyFieldPrimitive2D
->getValue(u
"TargetFrame"_ustr
));
485 const OUString
aFormat(pTextHierarchyFieldPrimitive2D
->getValue(u
"SvxURLFormat"_ustr
));
487 if (!aFormat
.isEmpty())
489 aSvxURLField
.SetFormat(static_cast<SvxURLFormat
>(aFormat
.toInt32()));
492 // set HitKind and pointer to local static instance in the Event
493 // to comply to old stuff
494 eHit
= SdrHitKind::UrlField
;
495 rVEvt
.mpURLField
= &aSvxURLField
;
500 if (eHit
==SdrHitKind::UnmarkedObject
&& !pHitObj
->getHyperlink().isEmpty())
502 static SvxURLField aSvxURLField
;
503 aSvxURLField
.SetURL(pHitObj
->getHyperlink());
504 rVEvt
.mpURLField
= &aSvxURLField
;
505 eHit
= SdrHitKind::UrlField
;
509 if (bHitPassDirect
&&
510 (eHit
==SdrHitKind::MarkedObject
|| eHit
==SdrHitKind::UnmarkedObject
) &&
511 (IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj
->HasTextEdit())
513 auto pTextObj
= DynCastSdrTextObj(pHitObj
);
515 // Around the TextEditArea there's a border to select without going into text edit mode.
516 tools::Rectangle aBoundRect
;
517 // Force to SnapRect when Fontwork
518 if (pTextObj
&& pTextObj
->IsFontwork())
519 aBoundRect
= pHitObj
->GetSnapRect();
520 else if (pTextObj
&& !pTextObj
->GetGeoStat().m_nRotationAngle
521 && !pTextObj
->GetGeoStat().m_nShearAngle
)
523 pTextObj
->TakeTextEditArea(nullptr, nullptr, &aBoundRect
, nullptr);
526 aBoundRect
= pHitObj
->GetCurrentBoundRect();
528 sal_Int32
nTolerance(mnHitTolLog
);
529 bool bBoundRectHit(false);
533 nTolerance
= pOut
->PixelToLogic(Size(2, 0)).Width();
536 if( (aLocalLogicPosition
.X() >= aBoundRect
.Left() - nTolerance
&& aLocalLogicPosition
.X() <= aBoundRect
.Left() + nTolerance
)
537 || (aLocalLogicPosition
.X() >= aBoundRect
.Right() - nTolerance
&& aLocalLogicPosition
.X() <= aBoundRect
.Right() + nTolerance
)
538 || (aLocalLogicPosition
.Y() >= aBoundRect
.Top() - nTolerance
&& aLocalLogicPosition
.Y() <= aBoundRect
.Top() + nTolerance
)
539 || (aLocalLogicPosition
.Y() >= aBoundRect
.Bottom() - nTolerance
&& aLocalLogicPosition
.Y() <= aBoundRect
.Bottom() + nTolerance
))
541 bBoundRectHit
= true;
544 if(!bBoundRectHit
&& aBoundRect
.Contains(aLocalLogicPosition
))
547 && SdrObjectPrimitiveHit(*pHitObj
, aLocalLogicPosition
, { 2000.0, 0.0 },
548 *pPV
, &pPV
->GetVisibleLayers(), true));
550 // TextEdit attached to an object in a locked layer
551 if (bTEHit
&& pPV
->GetLockedLayers().IsSet(pHitObj
->GetLayer()))
558 rVEvt
.mpRootObj
=pObj
;
560 eHit
=SdrHitKind::TextEditObj
;
564 if (!bHitPassDirect
&& eHit
==SdrHitKind::UnmarkedObject
) {
565 eHit
=SdrHitKind::NONE
;
569 bool bMouseLeft
= (rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0;
570 bool bMouseRight
= (rVEvt
.mnMouseCode
& MOUSE_RIGHT
) != 0;
571 bool bMouseDown
= rVEvt
.mbMouseDown
;
572 bool bMouseUp
= rVEvt
.mbMouseUp
;
573 SdrEventKind eEvent
=SdrEventKind::NONE
;
574 bool bIsAction
=IsAction();
580 if (bMouseRight
) eEvent
=SdrEventKind::BackAction
;
586 eEvent
=SdrEventKind::EndAction
;
589 eEvent
=SdrEventKind::EndDrag
;
591 else if (IsCreateObj() || IsInsObjPoint())
593 eEvent
=IsCreateObj() ? SdrEventKind::EndCreate
: SdrEventKind::EndInsertObjPoint
;
595 else if (IsMarking())
597 eEvent
=SdrEventKind::EndMark
;
598 if (!maDragStat
.IsMinMoved())
600 eEvent
=SdrEventKind::BrkMark
;
601 rVEvt
.mbAddMark
= MODKEY_MultiMark
;
608 eEvent
=SdrEventKind::MoveAction
;
611 else if (eHit
==SdrHitKind::TextEdit
)
613 eEvent
=SdrEventKind::TextEdit
;
615 else if (bMouseDown
&& bMouseLeft
)
617 if (rVEvt
.mnMouseClicks
== 2 && rVEvt
.mnMouseCode
== MOUSE_LEFT
&& pObj
!=nullptr && pHitObj
!=nullptr && pHitObj
->HasTextEdit() && eHit
==SdrHitKind::MarkedObject
)
619 rVEvt
.mpRootObj
= pObj
;
621 eEvent
=SdrEventKind::BeginTextEdit
;
623 else if (MODKEY_ForceMark
&& eHit
!=SdrHitKind::UrlField
)
625 eEvent
=SdrEventKind::BeginMark
; // AddMark,Unmark */
627 else if (eHit
==SdrHitKind::HelpLine
)
629 eEvent
=SdrEventKind::BeginDragHelpline
; // nothing, actually
631 else if (eHit
==SdrHitKind::Gluepoint
)
633 eEvent
=SdrEventKind::MarkGluePoint
; // AddMark+Drag
634 rVEvt
.mbAddMark
= MODKEY_MultiMark
|| MODKEY_DeepMark
; // if not hit with Deep
636 else if (eHit
==SdrHitKind::Handle
)
638 eEvent
=SdrEventKind::BeginDragObj
; // Mark+Drag,AddMark+Drag,DeepMark+Drag,Unmark
639 bool bGlue
=pHdl
->GetKind()==SdrHdlKind::Glue
;
640 bool bPoly
=!bGlue
&& IsPointMarkable(*pHdl
);
641 bool bMarked
=bGlue
|| (bPoly
&& pHdl
->IsSelected());
644 eEvent
=bGlue
? SdrEventKind::MarkGluePoint
: SdrEventKind::MarkPoint
;
647 rVEvt
.mbAddMark
= true;
648 rVEvt
.mbPrevNextMark
= true;
649 rVEvt
.mbMarkPrev
= MODKEY_DeepBackw
;
651 else if (MODKEY_MultiMark
)
653 rVEvt
.mbAddMark
= true;
654 rVEvt
.mbUnmark
= bMarked
; // Toggle
658 nGlueId
=static_cast<sal_uInt16
>(pHdl
->GetObjHdlNum());
663 eEvent
=SdrEventKind::BeginDragObj
; // don't change MarkState, only change Drag
667 else if (bInsPolyPt
&& (MODKEY_PolyPoly
|| (!MODKEY_MultiMark
&& !MODKEY_DeepMark
)))
669 eEvent
=SdrEventKind::BeginInsertObjPoint
;
671 else if (bInsGluePt
&& !MODKEY_MultiMark
&& !MODKEY_DeepMark
)
673 eEvent
=SdrEventKind::BeginInsertGluePoint
;
675 else if (eHit
==SdrHitKind::TextEditObj
)
677 eEvent
=SdrEventKind::BeginTextEdit
; // AddMark+Drag,DeepMark+Drag,Unmark
678 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
679 { // if not hit with Deep
680 eEvent
=SdrEventKind::MarkObj
;
683 else if (eHit
==SdrHitKind::Macro
)
685 eEvent
=SdrEventKind::BeginMacroObj
; // AddMark+Drag
686 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
687 { // if not hit with Deep
688 eEvent
=SdrEventKind::MarkObj
;
691 else if (eHit
==SdrHitKind::UrlField
)
693 eEvent
=SdrEventKind::ExecuteUrl
; // AddMark+Drag
694 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
695 { // if not hit with Deep
696 eEvent
=SdrEventKind::MarkObj
;
699 else if (eHit
==SdrHitKind::MarkedObject
)
701 eEvent
=SdrEventKind::BeginDragObj
; // DeepMark+Drag,Unmark
703 if (MODKEY_MultiMark
|| MODKEY_DeepMark
)
704 { // if not hit with Deep
705 eEvent
=SdrEventKind::MarkObj
;
708 else if (IsCreateMode())
710 eEvent
=SdrEventKind::BeginCreateObj
; // nothing, actually
712 else if (eHit
==SdrHitKind::UnmarkedObject
)
714 eEvent
=SdrEventKind::MarkObj
; // AddMark+Drag
718 eEvent
=SdrEventKind::BeginMark
;
721 if (eEvent
==SdrEventKind::MarkObj
)
723 rVEvt
.mbAddMark
= MODKEY_MultiMark
|| MODKEY_DeepMark
; // if not hit with Deep
724 rVEvt
.mbPrevNextMark
= MODKEY_DeepMark
;
725 rVEvt
.mbMarkPrev
= MODKEY_DeepMark
&& MODKEY_DeepBackw
;
727 if (eEvent
==SdrEventKind::BeginMark
)
729 rVEvt
.mbAddMark
= MODKEY_MultiMark
;
730 rVEvt
.mbUnmark
= MODKEY_Unmark
;
733 rVEvt
.mbIsAction
= bIsAction
;
734 rVEvt
.mbIsTextEdit
= bIsTextEdit
;
735 rVEvt
.maLogicPos
= aLocalLogicPosition
;
738 if (rVEvt
.mpRootObj
== nullptr)
739 rVEvt
.mpRootObj
= pObj
;
741 rVEvt
.mnHlplIdx
= nHlplIdx
;
742 rVEvt
.mnGlueId
= nGlueId
;
744 rVEvt
.meEvent
= eEvent
;
746 if (rVEvt
.mpRootObj
!= nullptr)
748 if (rVEvt
.mpRootObj
->getParentSdrObjListFromSdrObject() != rVEvt
.mpPV
->GetObjList())
750 OSL_FAIL("SdrView::PickAnything(): pRootObj->getParentSdrObjListFromSdrObject()!=pPV->GetObjList() !");
757 bool SdrView::DoMouseEvent(const SdrViewEvent
& rVEvt
)
760 SdrHitKind eHit
= rVEvt
.meHit
;
761 Point
aLogicPos(rVEvt
.maLogicPos
);
763 bool bShift
= (rVEvt
.mnMouseCode
& KEY_SHIFT
) != 0;
764 bool bCtrl
= (rVEvt
.mnMouseCode
& KEY_MOD1
) != 0;
765 bool bAlt
= (rVEvt
.mnMouseCode
& KEY_MOD2
) != 0;
766 bool bMouseLeft
= (rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0;
767 bool bMouseDown
= rVEvt
.mbMouseDown
;
768 bool bMouseUp
= rVEvt
.mbMouseUp
;
770 if (bMouseLeft
) maDragStat
.SetMouseDown(true);
771 } else if (bMouseUp
) {
772 if (bMouseLeft
) maDragStat
.SetMouseDown(false);
773 } else { // else, MouseMove
774 maDragStat
.SetMouseDown(bMouseLeft
);
778 SetSnapEnabled(!MODKEY_NoSnap
);
781 SetOrtho(MODKEY_Ortho
!=IsOrthoDesired());
783 #ifdef MODKEY_AngleSnap
784 SetAngleSnapEnabled(MODKEY_AngleSnap
);
786 #ifdef MODKEY_CopyDrag
787 SetDragWithCopy(MODKEY_CopyDrag
);
790 SetCreate1stPointAsCenter(MODKEY_Center
);
791 SetResizeAtCenter(MODKEY_Center
);
792 SetCrookAtCenter(MODKEY_Center
);
794 if (bMouseLeft
&& bMouseDown
&& rVEvt
.mbIsTextEdit
&& (eHit
==SdrHitKind::UnmarkedObject
|| eHit
==SdrHitKind::NONE
)) {
795 SdrEndTextEdit(); // User has clicked beneath object, exit edit mode.
796 // pHdl is invalid, then, that shouldn't matter, though, as we expect
797 // pHdl==NULL (because of eHit).
799 switch (rVEvt
.meEvent
)
801 case SdrEventKind::NONE
: bRet
=false; break;
802 case SdrEventKind::TextEdit
: bRet
=false; break; // Events handled by the OutlinerView are not taken into account here.
803 case SdrEventKind::MoveAction
: MovAction(aLogicPos
); bRet
=true; break;
804 case SdrEventKind::EndAction
: EndAction(); bRet
=true; break;
805 case SdrEventKind::BackAction
: BckAction(); bRet
=true; break;
806 case SdrEventKind::EndMark
: EndAction(); bRet
=true; break;
807 case SdrEventKind::BrkMark
: {
809 if (!MarkObj(aLogicPos
, mnHitTolLog
, rVEvt
.mbAddMark
))
811 // No object hit. Do the following:
812 // 1. deselect any selected gluepoints
813 // 2. deselect any selected polygon points
814 // 3. deselect any selected objects
815 if (!rVEvt
.mbAddMark
) UnmarkAll();
819 case SdrEventKind::EndCreate
: { // if necessary, MarkObj
820 SdrCreateCmd eCmd
=SdrCreateCmd::NextPoint
;
821 if (MODKEY_PolyPoly
) eCmd
=SdrCreateCmd::NextObject
;
822 if (rVEvt
.mnMouseClicks
> 1) eCmd
=SdrCreateCmd::ForceEnd
;
823 if (!EndCreateObj(eCmd
)) { // Don't evaluate event for Create? -> Select
824 if (eHit
==SdrHitKind::UnmarkedObject
|| eHit
==SdrHitKind::TextEdit
) {
825 MarkObj(rVEvt
.mpRootObj
, rVEvt
.mpPV
);
826 if (eHit
==SdrHitKind::TextEdit
)
828 bool bRet2(mpActualOutDev
&& OUTDEV_WINDOW
== mpActualOutDev
->GetOutDevType() &&
829 SdrBeginTextEdit(rVEvt
.mpObj
, rVEvt
.mpPV
, mpActualOutDev
->GetOwnerWindow()));
833 MouseEvent
aMEvt(mpActualOutDev
->LogicToPixel(aLogicPos
), 1,
834 rVEvt
.mnMouseMode
,rVEvt
.mnMouseCode
,rVEvt
.mnMouseCode
);
836 OutlinerView
* pOLV
=GetTextEditOutlinerView();
838 pOLV
->MouseButtonDown(aMEvt
); // event for the Outliner, but without double-click
839 pOLV
->MouseButtonUp(aMEvt
); // event for the Outliner, but without double-click
843 bRet
=true; // object is selected and (if necessary) TextEdit is started
844 } else bRet
=false; // canceled Create, nothing else
845 } else bRet
=true; // return true for EndCreate
847 case SdrEventKind::EndDrag
: {
848 bRet
=EndDragObj(IsDragWithCopy());
849 ForceMarkedObjToAnotherPage(); // TODO: Undo+bracing missing!
851 case SdrEventKind::MarkObj
: { // + (if applicable) BegDrag
852 if (!rVEvt
.mbAddMark
) UnmarkAllObj();
853 bool bUnmark
= rVEvt
.mbUnmark
;
854 if (rVEvt
.mbPrevNextMark
) {
855 bRet
=MarkNextObj(aLogicPos
, mnHitTolLog
, rVEvt
.mbMarkPrev
);
857 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
858 rMarkList
.ForceSort();
859 const size_t nCount0
=rMarkList
.GetMarkCount();
860 bRet
=MarkObj(aLogicPos
, mnHitTolLog
, rVEvt
.mbAddMark
);
861 rMarkList
.ForceSort();
862 const size_t nCount1
=rMarkList
.GetMarkCount();
863 bUnmark
=nCount1
<nCount0
;
866 BegDragObj(aLogicPos
,nullptr,nullptr,mnMinMovLog
);
870 case SdrEventKind::MarkPoint
: { // + (if applicable) BegDrag
871 if (!rVEvt
.mbAddMark
) UnmarkAllPoints();
872 if (rVEvt
.mbPrevNextMark
) {
876 bRet
= MarkPoint(*rVEvt
.mpHdl
, rVEvt
.mbUnmark
);
878 if (!rVEvt
.mbUnmark
&& !rVEvt
.mbPrevNextMark
) {
879 BegDragObj(aLogicPos
, nullptr, rVEvt
.mpHdl
, mnMinMovLog
);
883 case SdrEventKind::MarkGluePoint
: { // + (if applicable) BegDrag
884 if (!rVEvt
.mbAddMark
) UnmarkAllGluePoints();
885 if (rVEvt
.mbPrevNextMark
) {
889 bRet
=MarkGluePoint(rVEvt
.mpObj
,rVEvt
.mnGlueId
,rVEvt
.mbUnmark
);
891 if (!rVEvt
.mbUnmark
&& !rVEvt
.mbPrevNextMark
) {
892 SdrHdl
* pHdl
= GetGluePointHdl(rVEvt
.mpObj
, rVEvt
.mnGlueId
);
893 BegDragObj(aLogicPos
,nullptr,pHdl
,mnMinMovLog
);
897 case SdrEventKind::BeginMark
: bRet
= BegMark(aLogicPos
,rVEvt
.mbAddMark
,rVEvt
.mbUnmark
); break;
898 case SdrEventKind::BeginInsertObjPoint
: bRet
= BegInsObjPoint(aLogicPos
, MODKEY_PolyPoly
); break;
899 case SdrEventKind::EndInsertObjPoint
: {
900 SdrCreateCmd eCmd
=SdrCreateCmd::NextPoint
;
901 if (MODKEY_PolyPoly
) eCmd
=SdrCreateCmd::NextObject
;
902 if (rVEvt
.mnMouseClicks
> 1) eCmd
= SdrCreateCmd::ForceEnd
;
903 EndInsObjPoint(eCmd
);
906 case SdrEventKind::BeginInsertGluePoint
: bRet
=BegInsGluePoint(aLogicPos
); break;
907 case SdrEventKind::BeginDragHelpline
: bRet
= BegDragHelpLine(rVEvt
.mnHlplIdx
,rVEvt
.mpPV
); break;
908 case SdrEventKind::BeginDragObj
: bRet
=BegDragObj(aLogicPos
, nullptr, rVEvt
.mpHdl
, mnMinMovLog
); break;
909 case SdrEventKind::BeginCreateObj
: {
910 if (mnCurrentInvent
==SdrInventor::Default
&& mnCurrentIdent
==SdrObjKind::Caption
) {
911 tools::Long nHgt
=SdrEngineDefaults::GetFontHeight();
912 bRet
=BegCreateCaptionObj(aLogicPos
,Size(5*nHgt
,2*nHgt
));
913 } else bRet
=BegCreateObj(aLogicPos
);
915 case SdrEventKind::BeginMacroObj
: {
916 BegMacroObj(aLogicPos
, mnHitTolLog
, rVEvt
.mpObj
, rVEvt
.mpPV
, mpActualOutDev
->GetOwnerWindow());
919 case SdrEventKind::BeginTextEdit
: {
920 if (!IsObjMarked(rVEvt
.mpObj
)) {
922 MarkObj(rVEvt
.mpRootObj
,rVEvt
.mpPV
);
925 bRet
= mpActualOutDev
&& OUTDEV_WINDOW
== mpActualOutDev
->GetOutDevType()&&
926 SdrBeginTextEdit(rVEvt
.mpObj
, rVEvt
.mpPV
, mpActualOutDev
->GetOwnerWindow());
930 MouseEvent
aMEvt(mpActualOutDev
->LogicToPixel(aLogicPos
),
931 1, rVEvt
.mnMouseMode
, rVEvt
.mnMouseCode
, rVEvt
.mnMouseCode
);
932 OutlinerView
* pOLV
=GetTextEditOutlinerView();
933 if (pOLV
!=nullptr) pOLV
->MouseButtonDown(aMEvt
); // event for the Outliner, but without double-click
938 if (bRet
&& mpActualOutDev
&& mpActualOutDev
->GetOutDevType()==OUTDEV_WINDOW
) {
939 vcl::Window
* pWin
=mpActualOutDev
->GetOwnerWindow();
940 // left mouse button pressed?
941 bool bLeftDown
= (rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0 && rVEvt
.mbMouseDown
;
942 // left mouse button released?
943 bool bLeftUp
= (rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0 && rVEvt
.mbMouseUp
;
944 // left mouse button pressed or held?
945 bool bLeftDown1
=(rVEvt
.mnMouseCode
& MOUSE_LEFT
) != 0 && !rVEvt
.mbMouseUp
;
946 pWin
->SetPointer(GetPreferredPointer(rVEvt
.maLogicPos
, pWin
->GetOutDev(),
947 rVEvt
.mnMouseCode
& (KEY_SHIFT
|KEY_MOD1
|KEY_MOD2
),bLeftDown1
));
948 bool bAction
=IsAction();
949 if (bLeftDown
&& bAction
)
950 pWin
->CaptureMouse();
951 else if (bLeftUp
|| (rVEvt
.mbIsAction
&& !bAction
))
952 pWin
->ReleaseMouse();
957 PointerStyle
SdrView::GetPreferredPointer(const Point
& rMousePos
, const OutputDevice
* pOut
, sal_uInt16 nModifier
, bool bLeftDown
) const
962 return mpCurrentCreate
->GetCreatePointer();
964 if (mpCurrentSdrDragMethod
)
966 return mpCurrentSdrDragMethod
->GetSdrDragPointer();
968 if (IsMarkObj() || IsMarkPoints() || IsMarkGluePoints() || IsSetPageOrg()) return PointerStyle::Arrow
;
969 if (IsDragHelpLine()) return GetDraggedHelpLinePointer();
971 SdrObjMacroHitRec aHitRec
;
972 aHitRec
.aPos
=pOut
->LogicToPixel(rMousePos
);
973 aHitRec
.nTol
=m_nMacroTol
;
974 aHitRec
.pVisiLayer
=&m_pMacroPV
->GetVisibleLayers();
975 aHitRec
.pPageView
=m_pMacroPV
;
976 return m_pMacroObj
->GetMacroPointer(aHitRec
);
979 // TextEdit, ObjEdit, Macro
980 if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos
)))
982 if(!pOut
|| IsTextEditInSelectionMode())
984 if (mpTextEditOutliner
->IsVertical())
985 return PointerStyle::TextVertical
;
987 return PointerStyle::Text
;
989 // Outliner should return something here...
990 Point
aPos(pOut
->LogicToPixel(rMousePos
));
991 PointerStyle
aPointer(mpTextEditOutlinerView
->GetPointer(aPos
));
992 if (aPointer
==PointerStyle::Arrow
)
994 if (mpTextEditOutliner
->IsVertical())
995 aPointer
= PointerStyle::TextVertical
;
997 aPointer
= PointerStyle::Text
;
1003 aVEvt
.mnMouseCode
= (nModifier
&(KEY_SHIFT
|KEY_MOD1
|KEY_MOD2
))|MOUSE_LEFT
; // to see what would happen on MouseLeftDown
1004 aVEvt
.mbMouseDown
= !bLeftDown
; // What if ..?
1005 aVEvt
.mbMouseUp
= bLeftDown
; // What if ..?
1007 const_cast<SdrView
*>(this)->SetActualWin(pOut
);
1008 SdrHitKind eHit
=PickAnything(rMousePos
,aVEvt
);
1009 SdrEventKind eEvent
= aVEvt
.meEvent
;
1012 case SdrEventKind::BeginCreateObj
:
1013 return maCurrentCreatePointer
;
1014 case SdrEventKind::MarkObj
:
1015 return PointerStyle::Move
;
1016 case SdrEventKind::BeginMark
:
1017 return PointerStyle::Arrow
;
1018 case SdrEventKind::MarkPoint
:
1019 case SdrEventKind::MarkGluePoint
:
1020 return PointerStyle::MovePoint
;
1021 case SdrEventKind::BeginInsertObjPoint
:
1022 case SdrEventKind::BeginInsertGluePoint
:
1023 return PointerStyle::Cross
;
1024 case SdrEventKind::ExecuteUrl
:
1025 return PointerStyle::RefHand
;
1026 case SdrEventKind::BeginMacroObj
:
1028 SdrObjMacroHitRec aHitRec
;
1029 aHitRec
.aPos
= aVEvt
.maLogicPos
;
1030 aHitRec
.nTol
=mnHitTolLog
;
1031 aHitRec
.pVisiLayer
= &aVEvt
.mpPV
->GetVisibleLayers();
1032 aHitRec
.pPageView
= aVEvt
.mpPV
;
1033 return aVEvt
.mpObj
->GetMacroPointer(aHitRec
);
1040 case SdrHitKind::Cell
:
1041 return PointerStyle::Arrow
;
1042 case SdrHitKind::HelpLine
:
1043 return aVEvt
.mpPV
->GetHelpLines()[aVEvt
.mnHlplIdx
].GetPointer();
1044 case SdrHitKind::Gluepoint
:
1045 return PointerStyle::MovePoint
;
1046 case SdrHitKind::TextEdit
:
1047 case SdrHitKind::TextEditObj
:
1049 SdrTextObj
* pText
= DynCastSdrTextObj(aVEvt
.mpObj
);
1050 if(pText
&& pText
->HasText())
1052 OutlinerParaObject
* pParaObj
= pText
->GetOutlinerParaObject();
1053 if(pParaObj
&& pParaObj
->IsEffectivelyVertical())
1054 return PointerStyle::TextVertical
;
1056 return PointerStyle::Text
;
1061 bool bMarkHit
=eHit
==SdrHitKind::MarkedObject
;
1062 SdrHdl
* pHdl
= aVEvt
.mpHdl
;
1063 // now check the pointers for dragging
1064 if (pHdl
!=nullptr || bMarkHit
) {
1065 SdrHdlKind eHdl
= pHdl
!=nullptr ? pHdl
->GetKind() : SdrHdlKind::Move
;
1066 bool bCorner
=pHdl
!=nullptr && pHdl
->IsCornerHdl();
1067 bool bVertex
=pHdl
!=nullptr && pHdl
->IsVertexHdl();
1068 bool bMov
=eHdl
==SdrHdlKind::Move
;
1069 if (bMov
&& (meDragMode
==SdrDragMode::Move
|| meDragMode
==SdrDragMode::Resize
|| mbMarkedHitMovesAlways
)) {
1070 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1071 return PointerStyle::Move
;
1073 switch (meDragMode
) {
1074 case SdrDragMode::Rotate
: {
1075 if ((bCorner
|| bMov
) && !IsRotateAllowed(true))
1076 return PointerStyle::NotAllowed
;
1078 // are 3D objects selected?
1079 bool b3DObjSelected
= false;
1080 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
1081 for (size_t a
=0; !b3DObjSelected
&& a
<rMarkList
.GetMarkCount(); ++a
) {
1082 SdrObject
* pObj
= rMarkList
.GetMark(a
)->GetMarkedSdrObj();
1083 if(DynCastE3dObject(pObj
))
1084 b3DObjSelected
= true;
1086 // If we have a 3D object, go on despite !IsShearAllowed,
1087 // because then we have a rotation instead of a shear.
1088 if (bVertex
&& !IsShearAllowed() && !b3DObjSelected
)
1089 return PointerStyle::NotAllowed
;
1091 return PointerStyle::Rotate
;
1093 case SdrDragMode::Shear
: {
1095 if (!IsDistortAllowed(true) && !IsDistortAllowed()) return PointerStyle::NotAllowed
;
1096 else return PointerStyle::RefHand
;
1098 if (bVertex
&& !IsShearAllowed()) return PointerStyle::NotAllowed
;
1100 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1101 return PointerStyle::Move
;
1104 case SdrDragMode::Mirror
: {
1105 if (bCorner
|| bVertex
|| bMov
) {
1106 SdrHdl
* pH1
=maHdlList
.GetHdl(SdrHdlKind::Ref1
);
1107 SdrHdl
* pH2
=maHdlList
.GetHdl(SdrHdlKind::Ref2
);
1110 if (pH1
!=nullptr && pH2
!=nullptr) {
1111 Point aDif
= pH2
->GetPos()-pH1
->GetPos();
1112 b90
=(aDif
.X()==0) || aDif
.Y()==0;
1113 b45
=b90
|| (std::abs(aDif
.X())==std::abs(aDif
.Y()));
1116 if (!IsMirrorAllowed(true,true)) bNo
=true; // any mirroring is forbidden
1117 if (!IsMirrorAllowed() && !b45
) bNo
=true; // mirroring freely is forbidden
1118 if (!IsMirrorAllowed(true) && !b90
) bNo
=true; // mirroring horizontally/vertically is allowed
1119 if (bNo
) return PointerStyle::NotAllowed
;
1121 return PointerStyle::Mirror
;
1123 return PointerStyle::Mirror
;
1127 case SdrDragMode::Transparence
:
1129 if(!IsTransparenceAllowed())
1130 return PointerStyle::NotAllowed
;
1132 return PointerStyle::RefHand
;
1135 case SdrDragMode::Gradient
:
1137 if(!IsGradientAllowed())
1138 return PointerStyle::NotAllowed
;
1140 return PointerStyle::RefHand
;
1143 case SdrDragMode::Crook
: {
1144 if (bCorner
|| bVertex
|| bMov
) {
1145 if (!IsCrookAllowed(true) && !IsCrookAllowed()) return PointerStyle::NotAllowed
;
1146 return PointerStyle::Crook
;
1151 case SdrDragMode::Crop
:
1153 return PointerStyle::Crop
;
1157 if ((bCorner
|| bVertex
) && !IsResizeAllowed(true)) return PointerStyle::NotAllowed
;
1160 if (pHdl
!=nullptr) return pHdl
->GetPointer();
1162 if (!IsMoveAllowed()) return PointerStyle::Arrow
; // because double click or drag & drop is possible
1163 return PointerStyle::Move
;
1166 if (meEditMode
==SdrViewEditMode::Create
) return maCurrentCreatePointer
;
1167 return PointerStyle::Arrow
;
1170 constexpr OUString STR_NOTHING
= u
"nothing"_ustr
;
1171 OUString
SdrView::GetStatusText()
1174 OUString aStr
= STR_NOTHING
;
1176 if (mpCurrentCreate
!=nullptr)
1178 aStr
=mpCurrentCreate
->getSpecialDragComment(maDragStat
);
1182 aName
= mpCurrentCreate
->TakeObjNameSingul();
1183 aStr
= SvxResId(STR_ViewCreateObj
);
1186 else if (mpCurrentSdrDragMethod
)
1188 if (mbInsPolyPoint
|| IsInsertGluePoint())
1190 aStr
=maInsPointUndoStr
;
1194 if (maDragStat
.IsMinMoved())
1198 "(" << this << ") " << mpCurrentSdrDragMethod
.get());
1199 aStr
= mpCurrentSdrDragMethod
->GetSdrDragComment();
1203 else if(IsMarkObj())
1205 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
1206 if(rMarkList
.GetMarkCount() != 0)
1208 aStr
= SvxResId(STR_ViewMarkMoreObjs
);
1212 aStr
= SvxResId(STR_ViewMarkObjs
);
1215 else if(IsMarkPoints())
1217 if(HasMarkedPoints())
1219 aStr
= SvxResId(STR_ViewMarkMorePoints
);
1223 aStr
= SvxResId(STR_ViewMarkPoints
);
1225 } else if (IsMarkGluePoints())
1227 if(HasMarkedGluePoints())
1229 aStr
= SvxResId(STR_ViewMarkMoreGluePoints
);
1233 aStr
= SvxResId(STR_ViewMarkGluePoints
);
1236 else if (IsTextEdit() && mpTextEditOutlinerView
!= nullptr) {
1237 aStr
=SvxResId(STR_ViewTextEdit
); // "TextEdit - Row y, Column x";
1238 ESelection
aSel(mpTextEditOutlinerView
->GetSelection());
1239 tools::Long nPar
= aSel
.end
.nPara
, nLin
= 0, nCol
= aSel
.end
.nIndex
;
1240 if (aSel
.end
.nPara
>0) {
1241 for (sal_Int32 nParaNum
=0; nParaNum
<aSel
.end
.nPara
; nParaNum
++) {
1242 nLin
+= mpTextEditOutliner
->GetLineCount(nParaNum
);
1245 // A little imperfection:
1246 // At the end of a line of any multi-line paragraph, we display the
1247 // position of the next line of the same paragraph, if there is one.
1248 sal_uInt16 nParaLine
= 0;
1249 sal_Int32 nParaLineCount
= mpTextEditOutliner
->GetLineCount(aSel
.end
.nPara
);
1253 sal_uInt16 nLen
= mpTextEditOutliner
->GetLineLen(aSel
.end
.nPara
, nParaLine
);
1254 bool bLastLine
= (nParaLine
== nParaLineCount
- 1);
1255 if (nCol
>nLen
|| (!bLastLine
&& nCol
== nLen
))
1265 bBrk
= true; // to be sure
1268 aStr
= aStr
.replaceFirst("%1", OUString::number(nPar
+ 1));
1269 aStr
= aStr
.replaceFirst("%2", OUString::number(nLin
+ 1));
1270 aStr
= aStr
.replaceFirst("%3", OUString::number(nCol
+ 1));
1273 aStr
+= ", Level " + OUString::number(mpTextEditOutliner
->GetDepth( aSel
.end
.nPara
));
1277 if(aStr
== STR_NOTHING
)
1279 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
1280 if (rMarkList
.GetMarkCount() != 0) {
1281 aStr
= ImpGetDescriptionString(STR_ViewMarked
);
1282 if (IsGluePointEditMode()) {
1283 if (HasMarkedGluePoints()) {
1284 aStr
= ImpGetDescriptionString(STR_ViewMarked
, ImpGetDescriptionOptions::GLUEPOINTS
);
1287 if (HasMarkedPoints()) {
1288 aStr
= ImpGetDescriptionString(STR_ViewMarked
, ImpGetDescriptionOptions::POINTS
);
1295 else if(!aName
.isEmpty())
1297 aStr
= aStr
.replaceFirst("%1", aName
);
1302 // capitalize first letter
1303 aStr
= aStr
.replaceAt(0, 1, OUString(aStr
[0]).toAsciiUpperCase());
1308 SdrViewContext
SdrView::GetContext() const
1310 if( IsGluePointEditMode() )
1311 return SdrViewContext::GluePointEdit
;
1313 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
1314 const size_t nMarkCount
= rMarkList
.GetMarkCount();
1316 if( HasMarkablePoints() && !IsFrameHandles() )
1319 for( size_t nMarkNum
= 0; nMarkNum
< nMarkCount
&& bPath
; ++nMarkNum
)
1320 if (dynamic_cast<const SdrPathObj
*>(rMarkList
.GetMark(nMarkNum
)->GetMarkedSdrObj()) == nullptr)
1324 return SdrViewContext::PointEdit
;
1327 if( rMarkList
.GetMarkCount() )
1329 bool bGraf
= true, bMedia
= true, bTable
= true;
1331 for( size_t nMarkNum
= 0; nMarkNum
< nMarkCount
&& ( bGraf
|| bMedia
); ++nMarkNum
)
1333 const SdrObject
* pMarkObj
= rMarkList
.GetMark(nMarkNum
)->GetMarkedSdrObj();
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::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
&& (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
.CollapseToEnd();
1400 GetTextEditOutlinerView()->SetSelection(eSel
);
1401 } else if (HasMarkedGluePoints()) UnmarkAllGluePoints();
1402 else if (HasMarkedPoints()) UnmarkAllPoints(); // Marked, not Markable!
1403 else UnmarkAllObj();
1406 const tools::Rectangle
& SdrView::GetMarkedRect() const
1408 if (IsGluePointEditMode() && HasMarkedGluePoints()) {
1409 return GetMarkedGluePointsRect();
1411 if (HasMarkedPoints()) {
1412 return GetMarkedPointsRect();
1414 return GetMarkedObjRect();
1417 void SdrView::DeleteMarked()
1421 SdrObjEditView::KeyInput(KeyEvent(0, vcl::KeyCode(KeyFuncType::DELETE
)), mpTextEditWin
);
1425 if( mxSelectionController
.is() && mxSelectionController
->DeleteMarked() )
1427 // action already performed by current selection controller, do nothing
1429 else if (IsGluePointEditMode() && HasMarkedGluePoints())
1431 DeleteMarkedGluePoints();
1433 else if (GetContext()==SdrViewContext::PointEdit
&& HasMarkedPoints())
1435 DeleteMarkedPoints();
1444 bool SdrView::BegMark(const Point
& rPnt
, bool bAddMark
, bool bUnmark
)
1446 if (bUnmark
) bAddMark
=true;
1447 if (IsGluePointEditMode()) {
1448 if (!bAddMark
) UnmarkAllGluePoints();
1449 return BegMarkGluePoints(rPnt
,bUnmark
);
1450 } else if (HasMarkablePoints()) {
1451 if (!bAddMark
) UnmarkAllPoints();
1452 return BegMarkPoints(rPnt
,bUnmark
);
1454 if (!bAddMark
) UnmarkAllObj();
1455 BegMarkObj(rPnt
,bUnmark
);
1460 bool SdrView::MoveShapeHandle(const sal_uInt32 handleNum
, const Point
& aEndPoint
, const sal_Int32 aObjectOrdNum
)
1462 if (GetHdlList().IsMoveOutside())
1465 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
1466 if (!rMarkList
.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::SetMasterPagePaintCaching(bool bOn
)
1508 if(mbMasterPagePaintCaching
== bOn
)
1511 mbMasterPagePaintCaching
= bOn
;
1513 // reset at all SdrPageWindows
1514 SdrPageView
* pPageView
= GetSdrPageView();
1519 for(sal_uInt32
b(0); b
< pPageView
->PageWindowCount(); b
++)
1521 SdrPageWindow
* pPageWindow
= pPageView
->GetPageWindow(b
);
1522 assert(pPageWindow
&& "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)");
1524 // force deletion of ObjectContact, so at re-display all VOCs
1525 // will be re-created with updated flag setting
1526 pPageWindow
->ResetObjectContact();
1529 // force redraw of this view
1530 pPageView
->InvalidateAllWin();
1533 // Default ObjectContact is ObjectContactOfPageView
1534 sdr::contact::ObjectContact
* SdrView::createViewSpecificObjectContact(
1535 SdrPageWindow
& rPageWindow
,
1536 const char* pDebugName
) const
1538 return new sdr::contact::ObjectContactOfPageView(rPageWindow
, pDebugName
);
1541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */