summaryrefslogtreecommitdiffstats
path: root/svx/source/svdraw/svdview.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/svdraw/svdview.cxx')
-rw-r--r--svx/source/svdraw/svdview.cxx1460
1 files changed, 1460 insertions, 0 deletions
diff --git a/svx/source/svdraw/svdview.cxx b/svx/source/svdraw/svdview.cxx
new file mode 100644
index 000000000..33cf89ab8
--- /dev/null
+++ b/svx/source/svdraw/svdview.cxx
@@ -0,0 +1,1460 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/outlobj.hxx>
+
+#include <svx/strings.hrc>
+#include <svx/dialmgr.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdmrkv.hxx>
+#include <svx/svdedxv.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdomedia.hxx>
+#include <svx/svdetc.hxx>
+
+#include <svx/svdoutl.hxx>
+#include <svx/svdview.hxx>
+#include <editeng/flditem.hxx>
+#include <svx/obj3d.hxx>
+#include <svx/svddrgmt.hxx>
+#include <svx/svdotable.hxx>
+#include <tools/debug.hxx>
+#include <svx/sdr/overlay/overlaypolypolygon.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <svx/sdrpagewindow.hxx>
+#include <svx/sdrhittesthelper.hxx>
+#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
+#include <svx/sdr/contact/objectcontactofpageview.hxx>
+#include <sal/log.hxx>
+#include <vcl/ptrstyle.hxx>
+
+
+SdrViewEvent::SdrViewEvent()
+: pHdl(nullptr),
+ pObj(nullptr),
+ pRootObj(nullptr),
+ pPV(nullptr),
+ pURLField(nullptr),
+ eHit(SdrHitKind::NONE),
+ eEvent(SdrEventKind::NONE),
+ nMouseClicks(0),
+ nMouseMode(MouseEventModifiers::NONE),
+ nMouseCode(0),
+ nHlplIdx(0),
+ nGlueId(0),
+ bMouseDown(false),
+ bMouseUp(false),
+ bIsAction(false),
+ bIsTextEdit(false),
+ bAddMark(false),
+ bUnmark(false),
+ bPrevNextMark(false),
+ bMarkPrev(false)
+{
+}
+
+SdrViewEvent::~SdrViewEvent()
+{
+}
+
+
+// helper class for all D&D overlays
+
+void SdrDropMarkerOverlay::ImplCreateOverlays(
+ const SdrView& rView,
+ const basegfx::B2DPolyPolygon& rLinePolyPolygon)
+{
+ for(sal_uInt32 a(0); a < rView.PaintWindowCount(); a++)
+ {
+ SdrPaintWindow* pCandidate = rView.GetPaintWindow(a);
+ const rtl::Reference< sdr::overlay::OverlayManager >& xTargetOverlay = pCandidate->GetOverlayManager();
+
+ if (xTargetOverlay.is())
+ {
+ std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
+ rLinePolyPolygon));
+
+ xTargetOverlay->add(*pNew);
+ maObjects.append(std::move(pNew));
+ }
+ }
+}
+
+SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const SdrObject& rObject)
+{
+ ImplCreateOverlays(
+ rView,
+ rObject.TakeXorPoly());
+}
+
+SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const tools::Rectangle& rRectangle)
+{
+ basegfx::B2DPolygon aB2DPolygon;
+
+ aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top()));
+ aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top()));
+ aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom()));
+ aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
+ aB2DPolygon.setClosed(true);
+
+ ImplCreateOverlays(
+ rView,
+ basegfx::B2DPolyPolygon(aB2DPolygon));
+}
+
+SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const Point& rStart, const Point& rEnd)
+{
+ basegfx::B2DPolygon aB2DPolygon;
+
+ aB2DPolygon.append(basegfx::B2DPoint(rStart.X(), rStart.Y()));
+ aB2DPolygon.append(basegfx::B2DPoint(rEnd.X(), rEnd.Y()));
+ aB2DPolygon.setClosed(true);
+
+ ImplCreateOverlays(
+ rView,
+ basegfx::B2DPolyPolygon(aB2DPolygon));
+}
+
+SdrDropMarkerOverlay::~SdrDropMarkerOverlay()
+{
+ // The OverlayObjects are cleared using the destructor of OverlayObjectList.
+ // That destructor calls clear() at the list which removes all objects from the
+ // OverlayManager and deletes them.
+}
+
+SdrView::SdrView(
+ SdrModel& rSdrModel,
+ OutputDevice* pOut)
+: SdrCreateView(rSdrModel, pOut),
+ bNoExtendedMouseDispatcher(false),
+ bNoExtendedKeyDispatcher(false),
+ mbMasterPagePaintCaching(false)
+{
+ maAccessibilityOptions.AddListener(this);
+ onAccessibilityOptionsChanged();
+}
+
+SdrView::~SdrView()
+{
+ maAccessibilityOptions.RemoveListener(this);
+}
+
+bool SdrView::KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin)
+{
+ SetActualWin(pWin);
+ bool bRet = SdrCreateView::KeyInput(rKEvt,pWin);
+ if (!bRet && !IsExtendedKeyInputDispatcherEnabled()) {
+ bRet = true;
+ switch (rKEvt.GetKeyCode().GetFullFunction()) {
+ case KeyFuncType::DELETE: DeleteMarked(); break;
+ case KeyFuncType::UNDO: mpModel->Undo(); break;
+ case KeyFuncType::REDO: mpModel->Redo(); break;
+ case KeyFuncType::REPEAT: mpModel->Repeat(*this); break;
+ default: {
+ switch (rKEvt.GetKeyCode().GetFullCode()) {
+ case KEY_ESCAPE: {
+ if (IsTextEdit()) SdrEndTextEdit();
+ if (IsAction()) BrkAction();
+ if (pWin!=nullptr) pWin->ReleaseMouse();
+ } break;
+ case KEY_DELETE: DeleteMarked(); break;
+ case KEY_UNDO: case KEY_BACKSPACE+KEY_MOD2: mpModel->Undo(); break;
+ case KEY_BACKSPACE+KEY_MOD2+KEY_SHIFT: mpModel->Redo(); break;
+ case KEY_REPEAT: case KEY_BACKSPACE+KEY_MOD2+KEY_MOD1: mpModel->Repeat(*this); break;
+ case KEY_MOD1+KEY_A: MarkAll(); break;
+ default: bRet=false;
+ } // switch
+ }
+ } // switch
+ if (bRet && pWin!=nullptr) {
+ pWin->SetPointer(GetPreferredPointer(
+ pWin->PixelToLogic(pWin->ScreenToOutputPixel( pWin->GetPointerPosPixel() ) ),
+ pWin,
+ rKEvt.GetKeyCode().GetModifier()));
+ }
+ }
+ return bRet;
+}
+
+bool SdrView::MouseButtonDown(const MouseEvent& rMEvt, OutputDevice* pWin)
+{
+ SetActualWin(pWin);
+ if (rMEvt.IsLeft()) maDragStat.SetMouseDown(true);
+ bool bRet = SdrCreateView::MouseButtonDown(rMEvt,pWin);
+ if (!bRet && !IsExtendedMouseEventDispatcherEnabled()) {
+ SdrViewEvent aVEvt;
+ PickAnything(rMEvt,SdrMouseEventKind::BUTTONDOWN,aVEvt);
+ bRet = DoMouseEvent(aVEvt);
+ }
+ return bRet;
+}
+
+bool SdrView::MouseButtonUp(const MouseEvent& rMEvt, OutputDevice* pWin)
+{
+ SetActualWin(pWin);
+ if (rMEvt.IsLeft()) maDragStat.SetMouseDown(false);
+ bool bAction = IsAction();
+ bool bRet = !bAction && SdrCreateView::MouseButtonUp(rMEvt,pWin);
+ if (!bRet && !IsExtendedMouseEventDispatcherEnabled()) {
+ SdrViewEvent aVEvt;
+ PickAnything(rMEvt,SdrMouseEventKind::BUTTONUP,aVEvt);
+ bRet = DoMouseEvent(aVEvt);
+ }
+ return bRet;
+}
+
+bool SdrView::MouseMove(const MouseEvent& rMEvt, OutputDevice* pWin)
+{
+ SetActualWin(pWin);
+ maDragStat.SetMouseDown(rMEvt.IsLeft());
+ bool bRet = SdrCreateView::MouseMove(rMEvt,pWin);
+ if (!IsExtendedMouseEventDispatcherEnabled() && !IsTextEditInSelectionMode()) {
+ SdrViewEvent aVEvt;
+ PickAnything(rMEvt,SdrMouseEventKind::MOVE,aVEvt);
+ if (DoMouseEvent(aVEvt)) bRet=true;
+ }
+
+ return bRet;
+}
+
+bool SdrView::Command(const CommandEvent& rCEvt, vcl::Window* pWin)
+{
+ SetActualWin(pWin);
+ bool bRet = SdrCreateView::Command(rCEvt,pWin);
+ return bRet;
+}
+
+void SdrView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
+{
+ SdrCreateView::GetAttributes(rTargetSet, bOnlyHardAttr);
+}
+
+SdrHitKind SdrView::PickAnything(const MouseEvent& rMEvt, SdrMouseEventKind nEventKind, SdrViewEvent& rVEvt) const
+{
+ rVEvt.bMouseDown=nEventKind==SdrMouseEventKind::BUTTONDOWN;
+ rVEvt.bMouseUp=nEventKind==SdrMouseEventKind::BUTTONUP;
+ rVEvt.nMouseClicks=rMEvt.GetClicks();
+ rVEvt.nMouseMode=rMEvt.GetMode();
+ rVEvt.nMouseCode=rMEvt.GetButtons() | rMEvt.GetModifier();
+ const OutputDevice* pOut=mpActualOutDev;
+ if (pOut==nullptr)
+ {
+ pOut = GetFirstOutputDevice();
+ }
+ Point aPnt(rMEvt.GetPosPixel());
+ if (pOut!=nullptr) aPnt=pOut->PixelToLogic(aPnt);
+ rVEvt.aLogicPos=aPnt;
+ return PickAnything(aPnt,rVEvt);
+}
+
+// Dragging with the Mouse (Move)
+// Example when creating a rectangle: MouseDown has to happen without a ModKey,
+// else we usually force a selection (see below).
+// When pressing Shift, Ctrl and Alt at the same time while doing a MouseMove,
+// a centered, not snapped square is created.
+// The dual allocation of Ortho and Shift won't usually create a problem, as the
+// two functions are in most cases mutually exclusive. Only shearing (the kind
+// that happens when contorting, not when rotating) can use both functions at
+// the same time. To get around this, the user can use e. g. help lines.
+#define MODKEY_NoSnap bCtrl /* temporarily disable snapping */
+#define MODKEY_Ortho bShift /* ortho */
+#define MODKEY_Center bAlt /* create/resize centeredly */
+#define MODKEY_AngleSnap bShift
+#define MODKEY_CopyDrag bCtrl /* drag and copy */
+
+// click somewhere (MouseDown)
+#define MODKEY_PolyPoly bAlt /* new Poly at InsPt and at Create */
+#define MODKEY_MultiMark bShift /* MarkObj without doing UnmarkAll first */
+#define MODKEY_Unmark bAlt /* deselect with a dragged frame */
+#define MODKEY_ForceMark bCtrl /* force dragging a frame, even if there's an object at cursor position */
+#define MODKEY_DeepMark bAlt /* MarkNextObj */
+#define MODKEY_DeepBackw bShift /* MarkNextObj but backwards */
+
+SdrHitKind SdrView::PickAnything(const Point& rLogicPos, SdrViewEvent& rVEvt) const
+{
+ const OutputDevice* pOut=mpActualOutDev;
+ if (pOut==nullptr)
+ {
+ pOut = GetFirstOutputDevice();
+ }
+
+ // #i73628# Use a non-changeable copy of he logic position
+ const Point aLocalLogicPosition(rLogicPos);
+
+ bool bEditMode=IsEditMode();
+ bool bPointMode=bEditMode && HasMarkablePoints();
+ bool bGluePointMode=IsGluePointEditMode();
+ bool bInsPolyPt=bPointMode && IsInsObjPointMode() && IsInsObjPointPossible();
+ bool bInsGluePt=bGluePointMode && IsInsGluePointMode() && IsInsGluePointPossible();
+ bool bIsTextEdit=IsTextEdit();
+ bool bTextEditHit=IsTextEditHit(aLocalLogicPosition);
+ bool bTextEditSel=IsTextEditInSelectionMode();
+ bool bShift=(rVEvt.nMouseCode & KEY_SHIFT) !=0;
+ bool bCtrl=(rVEvt.nMouseCode & KEY_MOD1) !=0;
+ bool bAlt=(rVEvt.nMouseCode & KEY_MOD2) !=0;
+ SdrHitKind eHit=SdrHitKind::NONE;
+ SdrHdl* pHdl=pOut!=nullptr && !bTextEditSel ? PickHandle(aLocalLogicPosition) : nullptr;
+ SdrPageView* pPV=nullptr;
+ SdrObject* pObj=nullptr;
+ SdrObject* pHitObj=nullptr;
+ bool bHitPassDirect=true;
+ sal_uInt16 nHlplIdx=0;
+ sal_uInt16 nGlueId=0;
+ if (bTextEditHit || bTextEditSel)
+ {
+ eHit=SdrHitKind::TextEdit;
+ }
+ else if (pHdl!=nullptr)
+ {
+ eHit=SdrHitKind::Handle; // handle is hit: highest priority
+ }
+ else if (bEditMode && IsHlplVisible() && IsHlplFront() && pOut!=nullptr && PickHelpLine(aLocalLogicPosition,mnHitTolLog,*pOut,nHlplIdx,pPV))
+ {
+ eHit=SdrHitKind::HelpLine; // help line in the foreground hit: can be moved now
+ }
+ else if (bGluePointMode && PickGluePoint(aLocalLogicPosition,pObj,nGlueId,pPV))
+ {
+ eHit=SdrHitKind::Gluepoint; // deselected glue point hit
+ }
+ else if ((pHitObj = PickObj(aLocalLogicPosition,mnHitTolLog,pPV,SdrSearchOptions::DEEP|SdrSearchOptions::MARKED,&pObj,&bHitPassDirect)))
+ {
+ eHit=SdrHitKind::MarkedObject;
+ sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( pObj );
+ if( pTableObj )
+ {
+ sal_Int32 nX = 0, nY = 0;
+ switch( pTableObj->CheckTableHit( aLocalLogicPosition, nX, nY ) )
+ {
+ case sdr::table::TableHitKind::Cell:
+ eHit = SdrHitKind::Cell;
+ break;
+ case sdr::table::TableHitKind::CellTextArea:
+ eHit = SdrHitKind::TextEditObj;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else if ((pHitObj = PickObj(aLocalLogicPosition,mnHitTolLog,pPV,SdrSearchOptions::DEEP|SdrSearchOptions::ALSOONMASTER|SdrSearchOptions::WHOLEPAGE,&pObj,&bHitPassDirect)))
+ {
+ // MasterPages and WholePage for Macro and URL
+ eHit=SdrHitKind::UnmarkedObject;
+ sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( pObj );
+ if( pTableObj )
+ {
+ sal_Int32 nX = 0, nY = 0;
+ switch( pTableObj->CheckTableHit( aLocalLogicPosition, nX, nY, mnHitTolLog ) )
+ {
+ case sdr::table::TableHitKind::Cell:
+ eHit = SdrHitKind::Cell;
+ break;
+ case sdr::table::TableHitKind::CellTextArea:
+ // Keep state on UnmarkedObject to allow the below
+ // 'check for URL field' to be executed, else popups
+ // for e.g. URL links when hoovering and clicking
+ // them will not work. Tried several other changes,
+ // but this one safely keeps existing behaviour as-is.
+ eHit = SdrHitKind::UnmarkedObject;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else if (bEditMode && IsHlplVisible() && !IsHlplFront() && pOut!=nullptr && PickHelpLine(aLocalLogicPosition,mnHitTolLog,*pOut,nHlplIdx,pPV))
+ {
+ eHit=SdrHitKind::HelpLine; // help line in foreground hit: can be moved now
+ }
+ if (eHit==SdrHitKind::UnmarkedObject)
+ {
+ bool bRoot=pObj->HasMacro();
+ bool bDeep=pObj!=pHitObj && pHitObj->HasMacro();
+ bool bMid=false; // Have we hit upon a grouped group with a macro?
+ SdrObject* pMidObj=nullptr;
+ if (pObj!=pHitObj)
+ {
+ SdrObject* pObjTmp=pHitObj->getParentSdrObjectFromSdrObject();
+ if (pObjTmp==pObj) pObjTmp=nullptr;
+ while (pObjTmp!=nullptr)
+ {
+ if (pObjTmp->HasMacro())
+ {
+ bMid=true;
+ pMidObj=pObjTmp;
+ }
+ pObjTmp=pObjTmp->getParentSdrObjectFromSdrObject();
+ if (pObjTmp==pObj) pObjTmp=nullptr;
+ }
+ }
+
+ if (bDeep || bMid || bRoot)
+ {
+ SdrObjMacroHitRec aHitRec;
+ aHitRec.aPos=aLocalLogicPosition;
+ aHitRec.nTol=mnHitTolLog;
+ aHitRec.pVisiLayer=&pPV->GetVisibleLayers();
+ aHitRec.pPageView=pPV;
+ if (bDeep) bDeep=pHitObj->IsMacroHit(aHitRec);
+ if (bMid ) bMid =pMidObj->IsMacroHit(aHitRec);
+ if (bRoot) bRoot=pObj->IsMacroHit(aHitRec);
+ if (bRoot || bMid || bDeep)
+ {
+ // Priorities: 1. Root, 2. Mid, 3. Deep
+ rVEvt.pRootObj=pObj;
+ if (!bRoot) pObj=pMidObj;
+ if (!bRoot && !bMid) pObj=pHitObj;
+ eHit=SdrHitKind::Macro;
+ }
+ }
+ }
+ // check for URL field
+ if (eHit==SdrHitKind::UnmarkedObject)
+ {
+ SdrTextObj* pTextObj=dynamic_cast<SdrTextObj*>( pHitObj );
+ if (pTextObj!=nullptr && pTextObj->HasText())
+ {
+ // use the primitive-based HitTest which is more accurate anyways. It
+ // will correctly handle rotated/mirrored/sheared/scaled text and can
+ // now return a HitContainer containing the primitive hierarchy of the
+ // primitive that triggered the hit. The first entry is that primitive,
+ // the others are the full stack of primitives leading to that one which
+ // includes grouping primitives (like TextHierarchyPrimitives we deed here)
+ // but also all decomposed ones which lead to the creation of that primitive
+ drawinglayer::primitive2d::Primitive2DContainer aHitContainer;
+ const bool bTEHit(pPV && SdrObjectPrimitiveHit(*pTextObj, aLocalLogicPosition, 0, *pPV, &pPV->GetVisibleLayers(), true, &aHitContainer));
+
+ if (bTEHit && !aHitContainer.empty())
+ {
+ // search for TextHierarchyFieldPrimitive2D which contains the needed information
+ // about a possible URLField
+ const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D* pTextHierarchyFieldPrimitive2D = nullptr;
+
+ for (const drawinglayer::primitive2d::Primitive2DReference& xReference : aHitContainer)
+ {
+ if (xReference.is())
+ {
+ // try to cast to drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D implementation
+ pTextHierarchyFieldPrimitive2D = dynamic_cast<const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D*>(xReference.get());
+
+ if (pTextHierarchyFieldPrimitive2D)
+ {
+ break;
+ }
+ }
+ }
+
+ if (nullptr != pTextHierarchyFieldPrimitive2D)
+ {
+ if (drawinglayer::primitive2d::FieldType::FIELD_TYPE_URL == pTextHierarchyFieldPrimitive2D->getType())
+ {
+ // problem with the old code is that a *pointer* to an instance of
+ // SvxURLField is set in the Event which is per se not good since that
+ // data comes from a temporary EditEngine's data and could vanish any
+ // moment. Have to replace for now with a static instance that gets
+ // filled/initialized from the original data held in the TextHierarchyField-
+ // Primitive2D (see impTextBreakupHandler::impCheckFieldPrimitive).
+ // Unfortunately things like 'TargetFrame' are still used in Calc, so this
+ // can currently not get replaced. For the future the Name/Value vector or
+ // the TextHierarchyFieldPrimitive2D itself should/will be used for handling
+ // that data
+ static SvxURLField aSvxURLField;
+
+ aSvxURLField.SetURL(pTextHierarchyFieldPrimitive2D->getValue("URL"));
+ aSvxURLField.SetRepresentation(pTextHierarchyFieldPrimitive2D->getValue("Representation"));
+ aSvxURLField.SetTargetFrame(pTextHierarchyFieldPrimitive2D->getValue("TargetFrame"));
+ const OUString aFormat(pTextHierarchyFieldPrimitive2D->getValue("SvxURLFormat"));
+
+ if (!aFormat.isEmpty())
+ {
+ aSvxURLField.SetFormat(static_cast<SvxURLFormat>(aFormat.toInt32()));
+ }
+
+ // set HitKind and pointer to local static instance in the Event
+ // to comply to old stuff
+ eHit = SdrHitKind::UrlField;
+ rVEvt.pURLField = &aSvxURLField;
+ }
+ }
+ }
+ }
+ }
+
+ if (bHitPassDirect &&
+ (eHit==SdrHitKind::MarkedObject || eHit==SdrHitKind::UnmarkedObject) &&
+ (IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj->HasTextEdit())
+ {
+ // Around the TextEditArea there's a border to select without going into text edit mode.
+ tools::Rectangle aBoundRect(pHitObj->GetCurrentBoundRect());
+
+ // Force to SnapRect when Fontwork
+ if( dynamic_cast<const SdrTextObj*>( pHitObj) != nullptr && static_cast<SdrTextObj*>(pHitObj)->IsFontwork())
+ {
+ aBoundRect = pHitObj->GetSnapRect();
+ }
+
+ sal_Int32 nTolerance(mnHitTolLog);
+ bool bBoundRectHit(false);
+
+ if(pOut)
+ {
+ nTolerance = pOut->PixelToLogic(Size(2, 0)).Width();
+ }
+
+ if( (aLocalLogicPosition.X() >= aBoundRect.Left() - nTolerance && aLocalLogicPosition.X() <= aBoundRect.Left() + nTolerance)
+ || (aLocalLogicPosition.X() >= aBoundRect.Right() - nTolerance && aLocalLogicPosition.X() <= aBoundRect.Right() + nTolerance)
+ || (aLocalLogicPosition.Y() >= aBoundRect.Top() - nTolerance && aLocalLogicPosition.Y() <= aBoundRect.Top() + nTolerance)
+ || (aLocalLogicPosition.Y() >= aBoundRect.Bottom() - nTolerance && aLocalLogicPosition.Y() <= aBoundRect.Bottom() + nTolerance))
+ {
+ bBoundRectHit = true;
+ }
+
+ if(!bBoundRectHit)
+ {
+ bool bTEHit(pPV &&
+ SdrObjectPrimitiveHit(*pHitObj, aLocalLogicPosition, 0, *pPV, &pPV->GetVisibleLayers(), true));
+
+ // TextEdit attached to an object in a locked layer
+ if (pPV->GetLockedLayers().IsSet(pHitObj->GetLayer()))
+ {
+ bTEHit=false;
+ }
+
+ if (bTEHit)
+ {
+ rVEvt.pRootObj=pObj;
+ pObj=pHitObj;
+ eHit=SdrHitKind::TextEditObj;
+ }
+ }
+ }
+ if (!bHitPassDirect && eHit==SdrHitKind::UnmarkedObject) {
+ eHit=SdrHitKind::NONE;
+ pObj=nullptr;
+ pPV=nullptr;
+ }
+ bool bMouseLeft=(rVEvt.nMouseCode&MOUSE_LEFT)!=0;
+ bool bMouseRight=(rVEvt.nMouseCode&MOUSE_RIGHT)!=0;
+ bool bMouseDown=rVEvt.bMouseDown;
+ bool bMouseUp=rVEvt.bMouseUp;
+ SdrEventKind eEvent=SdrEventKind::NONE;
+ bool bIsAction=IsAction();
+
+ if (bIsAction)
+ {
+ if (bMouseDown)
+ {
+ if (bMouseRight) eEvent=SdrEventKind::BackAction;
+ }
+ else if (bMouseUp)
+ {
+ if (bMouseLeft)
+ {
+ eEvent=SdrEventKind::EndAction;
+ if (IsDragObj())
+ {
+ eEvent=SdrEventKind::EndDrag;
+ }
+ else if (IsCreateObj() || IsInsObjPoint())
+ {
+ eEvent=IsCreateObj() ? SdrEventKind::EndCreate : SdrEventKind::EndInsertObjPoint;
+ }
+ else if (IsMarking())
+ {
+ eEvent=SdrEventKind::EndMark;
+ if (!maDragStat.IsMinMoved())
+ {
+ eEvent=SdrEventKind::BrkMark;
+ rVEvt.bAddMark=MODKEY_MultiMark;
+ }
+ }
+ }
+ }
+ else
+ {
+ eEvent=SdrEventKind::MoveAction;
+ }
+ }
+ else if (eHit==SdrHitKind::TextEdit)
+ {
+ eEvent=SdrEventKind::TextEdit;
+ }
+ else if (bMouseDown && bMouseLeft)
+ {
+ if (rVEvt.nMouseClicks==2 && rVEvt.nMouseCode==MOUSE_LEFT && pObj!=nullptr && pHitObj!=nullptr && pHitObj->HasTextEdit() && eHit==SdrHitKind::MarkedObject)
+ {
+ rVEvt.pRootObj=pObj;
+ pObj=pHitObj;
+ eEvent=SdrEventKind::BeginTextEdit;
+ }
+ else if (MODKEY_ForceMark && eHit!=SdrHitKind::UrlField)
+ {
+ eEvent=SdrEventKind::BeginMark; // AddMark,Unmark */
+ }
+ else if (eHit==SdrHitKind::HelpLine)
+ {
+ eEvent=SdrEventKind::BeginDragHelpline; // nothing, actually
+ }
+ else if (eHit==SdrHitKind::Gluepoint)
+ {
+ eEvent=SdrEventKind::MarkGluePoint; // AddMark+Drag
+ rVEvt.bAddMark=MODKEY_MultiMark || MODKEY_DeepMark; // if not hit with Deep
+ }
+ else if (eHit==SdrHitKind::Handle)
+ {
+ eEvent=SdrEventKind::BeginDragObj; // Mark+Drag,AddMark+Drag,DeepMark+Drag,Unmark
+ bool bGlue=pHdl->GetKind()==SdrHdlKind::Glue;
+ bool bPoly=!bGlue && IsPointMarkable(*pHdl);
+ bool bMarked=bGlue || (bPoly && pHdl->IsSelected());
+ if (bGlue || bPoly)
+ {
+ eEvent=bGlue ? SdrEventKind::MarkGluePoint : SdrEventKind::MarkPoint;
+ if (MODKEY_DeepMark)
+ {
+ rVEvt.bAddMark=true;
+ rVEvt.bPrevNextMark=true;
+ rVEvt.bMarkPrev=MODKEY_DeepBackw;
+ }
+ else if (MODKEY_MultiMark)
+ {
+ rVEvt.bAddMark=true;
+ rVEvt.bUnmark=bMarked; // Toggle
+ if (bGlue)
+ {
+ pObj=pHdl->GetObj();
+ nGlueId=static_cast<sal_uInt16>(pHdl->GetObjHdlNum());
+ }
+ }
+ else if (bMarked)
+ {
+ eEvent=SdrEventKind::BeginDragObj; // don't change MarkState, only change Drag
+ }
+ }
+ }
+ else if (bInsPolyPt && (MODKEY_PolyPoly || (!MODKEY_MultiMark && !MODKEY_DeepMark)))
+ {
+ eEvent=SdrEventKind::BeginInsertObjPoint;
+ }
+ else if (bInsGluePt && !MODKEY_MultiMark && !MODKEY_DeepMark)
+ {
+ eEvent=SdrEventKind::BeginInsertGluePoint;
+ }
+ else if (eHit==SdrHitKind::TextEditObj)
+ {
+ eEvent=SdrEventKind::BeginTextEdit; // AddMark+Drag,DeepMark+Drag,Unmark
+ if (MODKEY_MultiMark || MODKEY_DeepMark)
+ { // if not hit with Deep
+ eEvent=SdrEventKind::MarkObj;
+ }
+ }
+ else if (eHit==SdrHitKind::Macro)
+ {
+ eEvent=SdrEventKind::BeginMacroObj; // AddMark+Drag
+ if (MODKEY_MultiMark || MODKEY_DeepMark)
+ { // if not hit with Deep
+ eEvent=SdrEventKind::MarkObj;
+ }
+ }
+ else if (eHit==SdrHitKind::UrlField)
+ {
+ eEvent=SdrEventKind::ExecuteUrl; // AddMark+Drag
+ if (MODKEY_MultiMark || MODKEY_DeepMark)
+ { // if not hit with Deep
+ eEvent=SdrEventKind::MarkObj;
+ }
+ }
+ else if (eHit==SdrHitKind::MarkedObject)
+ {
+ eEvent=SdrEventKind::BeginDragObj; // DeepMark+Drag,Unmark
+
+ if (MODKEY_MultiMark || MODKEY_DeepMark)
+ { // if not hit with Deep
+ eEvent=SdrEventKind::MarkObj;
+ }
+ }
+ else if (IsCreateMode())
+ {
+ eEvent=SdrEventKind::BeginCreateObj; // nothing, actually
+ }
+ else if (eHit==SdrHitKind::UnmarkedObject)
+ {
+ eEvent=SdrEventKind::MarkObj; // AddMark+Drag
+ }
+ else
+ {
+ eEvent=SdrEventKind::BeginMark;
+ }
+
+ if (eEvent==SdrEventKind::MarkObj)
+ {
+ rVEvt.bAddMark=MODKEY_MultiMark || MODKEY_DeepMark; // if not hit with Deep
+ rVEvt.bPrevNextMark=MODKEY_DeepMark;
+ rVEvt.bMarkPrev=MODKEY_DeepMark && MODKEY_DeepBackw;
+ }
+ if (eEvent==SdrEventKind::BeginMark)
+ {
+ rVEvt.bAddMark=MODKEY_MultiMark;
+ rVEvt.bUnmark=MODKEY_Unmark;
+ }
+ }
+ rVEvt.bIsAction=bIsAction;
+ rVEvt.bIsTextEdit=bIsTextEdit;
+ rVEvt.aLogicPos=aLocalLogicPosition;
+ rVEvt.pHdl=pHdl;
+ rVEvt.pObj=pObj;
+ if(rVEvt.pRootObj==nullptr)
+ rVEvt.pRootObj=pObj;
+ rVEvt.pPV=pPV;
+ rVEvt.nHlplIdx=nHlplIdx;
+ rVEvt.nGlueId=nGlueId;
+ rVEvt.eHit=eHit;
+ rVEvt.eEvent=eEvent;
+#ifdef DGB_UTIL
+ if (rVEvt.pRootObj!=NULL) {
+ if (rVEvt.pRootObj->getParentSdrObjListFromSdrObject()!=rVEvt.pPV->GetObjList()) {
+ OSL_FAIL("SdrView::PickAnything(): pRootObj->getParentSdrObjListFromSdrObject()!=pPV->GetObjList() !");
+ }
+ }
+#endif
+ return eHit;
+}
+
+bool SdrView::DoMouseEvent(const SdrViewEvent& rVEvt)
+{
+ bool bRet=false;
+ SdrHitKind eHit=rVEvt.eHit;
+ Point aLogicPos(rVEvt.aLogicPos);
+
+ bool bShift=(rVEvt.nMouseCode & KEY_SHIFT) !=0;
+ bool bCtrl=(rVEvt.nMouseCode & KEY_MOD1) !=0;
+ bool bAlt=(rVEvt.nMouseCode & KEY_MOD2) !=0;
+ bool bMouseLeft=(rVEvt.nMouseCode&MOUSE_LEFT)!=0;
+ bool bMouseDown=rVEvt.bMouseDown;
+ bool bMouseUp=rVEvt.bMouseUp;
+ if (bMouseDown) {
+ if (bMouseLeft) maDragStat.SetMouseDown(true);
+ } else if (bMouseUp) {
+ if (bMouseLeft) maDragStat.SetMouseDown(false);
+ } else { // else, MouseMove
+ maDragStat.SetMouseDown(bMouseLeft);
+ }
+
+#ifdef MODKEY_NoSnap
+ SetSnapEnabled(!MODKEY_NoSnap);
+#endif
+#ifdef MODKEY_Ortho
+ SetOrtho(MODKEY_Ortho!=IsOrthoDesired());
+#endif
+#ifdef MODKEY_AngleSnap
+ SetAngleSnapEnabled(MODKEY_AngleSnap);
+#endif
+#ifdef MODKEY_CopyDrag
+ SetDragWithCopy(MODKEY_CopyDrag);
+#endif
+#ifdef MODKEY_Center
+ SetCreate1stPointAsCenter(MODKEY_Center);
+ SetResizeAtCenter(MODKEY_Center);
+ SetCrookAtCenter(MODKEY_Center);
+#endif
+ if (bMouseLeft && bMouseDown && rVEvt.bIsTextEdit && (eHit==SdrHitKind::UnmarkedObject || eHit==SdrHitKind::NONE)) {
+ SdrEndTextEdit(); // User has clicked beneath object, exit edit mode.
+ // pHdl is invalid, then, that shouldn't matter, though, as we expect
+ // pHdl==NULL (because of eHit).
+ }
+ switch (rVEvt.eEvent) {
+ case SdrEventKind::NONE: bRet=false; break;
+ case SdrEventKind::TextEdit: bRet=false; break; // Events handled by the OutlinerView are not taken into account here.
+ case SdrEventKind::MoveAction: MovAction(aLogicPos); bRet=true; break;
+ case SdrEventKind::EndAction: EndAction(); bRet=true; break;
+ case SdrEventKind::BackAction: BckAction(); bRet=true; break;
+ case SdrEventKind::EndMark : EndAction(); bRet=true; break;
+ case SdrEventKind::BrkMark : {
+ BrkAction();
+ if (!MarkObj(aLogicPos,mnHitTolLog,rVEvt.bAddMark)) {
+ // No object hit. Do the following:
+ // 1. deselect any selected glue points
+ // 2. deselect any selected polygon points
+ // 3. deselect any selected objects
+ if (!rVEvt.bAddMark) UnmarkAll();
+ }
+ bRet=true;
+ } break;
+ case SdrEventKind::EndCreate: { // if necessary, MarkObj
+ SdrCreateCmd eCmd=SdrCreateCmd::NextPoint;
+ if (MODKEY_PolyPoly) eCmd=SdrCreateCmd::NextObject;
+ if (rVEvt.nMouseClicks>1) eCmd=SdrCreateCmd::ForceEnd;
+ if (!EndCreateObj(eCmd)) { // Don't evaluate event for Create? -> Select
+ if (eHit==SdrHitKind::UnmarkedObject || eHit==SdrHitKind::TextEdit) {
+ MarkObj(rVEvt.pRootObj,rVEvt.pPV);
+ if (eHit==SdrHitKind::TextEdit)
+ {
+ bool bRet2(mpActualOutDev && OUTDEV_WINDOW == mpActualOutDev->GetOutDevType() &&
+ SdrBeginTextEdit(rVEvt.pObj, rVEvt.pPV, static_cast<vcl::Window*>(mpActualOutDev.get())));
+
+ if(bRet2)
+ {
+ MouseEvent aMEvt(mpActualOutDev->LogicToPixel(aLogicPos),
+ 1,rVEvt.nMouseMode,rVEvt.nMouseCode,rVEvt.nMouseCode);
+
+ OutlinerView* pOLV=GetTextEditOutlinerView();
+ if (pOLV!=nullptr) {
+ pOLV->MouseButtonDown(aMEvt); // event for the Outliner, but without double-click
+ pOLV->MouseButtonUp(aMEvt); // event for the Outliner, but without double-click
+ }
+ }
+ }
+ bRet=true; // object is selected and (if necessary) TextEdit is started
+ } else bRet=false; // canceled Create, nothing else
+ } else bRet=true; // return true for EndCreate
+ } break;
+ case SdrEventKind::EndDrag: {
+ bRet=EndDragObj(IsDragWithCopy());
+ ForceMarkedObjToAnotherPage(); // TODO: Undo+bracing missing!
+ } break;
+ case SdrEventKind::MarkObj: { // + (if applicable) BegDrag
+ if (!rVEvt.bAddMark) UnmarkAllObj();
+ bool bUnmark=rVEvt.bUnmark;
+ if (rVEvt.bPrevNextMark) {
+ bRet=MarkNextObj(aLogicPos,mnHitTolLog,rVEvt.bMarkPrev);
+ } else {
+ SortMarkedObjects();
+ const size_t nCount0=GetMarkedObjectCount();
+ bRet=MarkObj(aLogicPos,mnHitTolLog,rVEvt.bAddMark);
+ SortMarkedObjects();
+ const size_t nCount1=GetMarkedObjectCount();
+ bUnmark=nCount1<nCount0;
+ }
+ if (!bUnmark) {
+ BegDragObj(aLogicPos,nullptr,nullptr,mnMinMovLog);
+ bRet=true;
+ }
+ } break;
+ case SdrEventKind::MarkPoint: { // + (if applicable) BegDrag
+ if (!rVEvt.bAddMark) UnmarkAllPoints();
+ if (rVEvt.bPrevNextMark) {
+ MarkNextPoint();
+ bRet=false;
+ } else {
+ bRet=MarkPoint(*rVEvt.pHdl,rVEvt.bUnmark);
+ }
+ if (!rVEvt.bUnmark && !rVEvt.bPrevNextMark) {
+ BegDragObj(aLogicPos,nullptr,rVEvt.pHdl,mnMinMovLog);
+ bRet=true;
+ }
+ } break;
+ case SdrEventKind::MarkGluePoint: { // + (if applicable) BegDrag
+ if (!rVEvt.bAddMark) UnmarkAllGluePoints();
+ if (rVEvt.bPrevNextMark) {
+ MarkNextGluePoint();
+ bRet=false;
+ } else {
+ bRet=MarkGluePoint(rVEvt.pObj,rVEvt.nGlueId,rVEvt.bUnmark);
+ }
+ if (!rVEvt.bUnmark && !rVEvt.bPrevNextMark) {
+ SdrHdl* pHdl=GetGluePointHdl(rVEvt.pObj,rVEvt.nGlueId);
+ BegDragObj(aLogicPos,nullptr,pHdl,mnMinMovLog);
+ bRet=true;
+ }
+ } break;
+ case SdrEventKind::BeginMark: bRet=BegMark(aLogicPos,rVEvt.bAddMark,rVEvt.bUnmark); break;
+ case SdrEventKind::BeginInsertObjPoint: bRet = BegInsObjPoint(aLogicPos, MODKEY_PolyPoly); break;
+ case SdrEventKind::EndInsertObjPoint: {
+ SdrCreateCmd eCmd=SdrCreateCmd::NextPoint;
+ if (MODKEY_PolyPoly) eCmd=SdrCreateCmd::NextObject;
+ if (rVEvt.nMouseClicks>1) eCmd=SdrCreateCmd::ForceEnd;
+ EndInsObjPoint(eCmd);
+ bRet=true;
+ } break;
+ case SdrEventKind::BeginInsertGluePoint: bRet=BegInsGluePoint(aLogicPos); break;
+ case SdrEventKind::BeginDragHelpline: bRet=BegDragHelpLine(rVEvt.nHlplIdx,rVEvt.pPV); break;
+ case SdrEventKind::BeginDragObj: bRet=BegDragObj(aLogicPos,nullptr,rVEvt.pHdl,mnMinMovLog); break;
+ case SdrEventKind::BeginCreateObj: {
+ if (nCurrentInvent==SdrInventor::Default && nCurrentIdent==OBJ_CAPTION) {
+ long nHgt=SdrEngineDefaults::GetFontHeight();
+ bRet=BegCreateCaptionObj(aLogicPos,Size(5*nHgt,2*nHgt));
+ } else bRet=BegCreateObj(aLogicPos);
+ } break;
+ case SdrEventKind::BeginMacroObj: {
+ BegMacroObj(aLogicPos,mnHitTolLog,rVEvt.pObj,rVEvt.pPV,static_cast<vcl::Window*>(mpActualOutDev.get()));
+ bRet=false;
+ } break;
+ case SdrEventKind::BeginTextEdit: {
+ if (!IsObjMarked(rVEvt.pObj)) {
+ UnmarkAllObj();
+ MarkObj(rVEvt.pRootObj,rVEvt.pPV);
+ }
+
+ bRet = mpActualOutDev && OUTDEV_WINDOW == mpActualOutDev->GetOutDevType()&&
+ SdrBeginTextEdit(rVEvt.pObj, rVEvt.pPV, static_cast<vcl::Window*>(mpActualOutDev.get()));
+
+ if(bRet)
+ {
+ MouseEvent aMEvt(mpActualOutDev->LogicToPixel(aLogicPos),
+ 1,rVEvt.nMouseMode,rVEvt.nMouseCode,rVEvt.nMouseCode);
+ OutlinerView* pOLV=GetTextEditOutlinerView();
+ if (pOLV!=nullptr) pOLV->MouseButtonDown(aMEvt); // event for the Outliner, but without double-click
+ }
+ } break;
+ default: break;
+ } // switch
+ if (bRet && mpActualOutDev && mpActualOutDev->GetOutDevType()==OUTDEV_WINDOW) {
+ vcl::Window* pWin=static_cast<vcl::Window*>(mpActualOutDev.get());
+ // left mouse button pressed?
+ bool bLeftDown=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && rVEvt.bMouseDown;
+ // left mouse button released?
+ bool bLeftUp=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && rVEvt.bMouseUp;
+ // left mouse button pressed or held?
+ bool bLeftDown1=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && !rVEvt.bMouseUp;
+ pWin->SetPointer(GetPreferredPointer(rVEvt.aLogicPos,pWin,
+ rVEvt.nMouseCode & (KEY_SHIFT|KEY_MOD1|KEY_MOD2),bLeftDown1));
+ bool bAction=IsAction();
+ if (bLeftDown && bAction)
+ pWin->CaptureMouse();
+ else if (bLeftUp || (rVEvt.bIsAction && !bAction))
+ pWin->ReleaseMouse();
+ }
+ return bRet;
+}
+
+PointerStyle SdrView::GetPreferredPointer(const Point& rMousePos, const OutputDevice* pOut, sal_uInt16 nModifier, bool bLeftDown) const
+{
+ // Actions
+ if (IsCreateObj())
+ {
+ return pCurrentCreate->GetCreatePointer();
+ }
+ if (mpCurrentSdrDragMethod)
+ {
+ return mpCurrentSdrDragMethod->GetSdrDragPointer();
+ }
+ if (IsMarkObj() || IsMarkPoints() || IsMarkGluePoints() || IsSetPageOrg()) return PointerStyle::Arrow;
+ if (IsDragHelpLine()) return GetDraggedHelpLinePointer();
+ if (IsMacroObj()) {
+ SdrObjMacroHitRec aHitRec;
+ aHitRec.aPos=pOut->LogicToPixel(rMousePos);
+ aHitRec.nTol=nMacroTol;
+ aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers();
+ aHitRec.pPageView=pMacroPV;
+ return pMacroObj->GetMacroPointer(aHitRec);
+ }
+
+ // TextEdit, ObjEdit, Macro
+ if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos)))
+ {
+ if(!pOut || IsTextEditInSelectionMode())
+ {
+ if(pTextEditOutliner->IsVertical())
+ return PointerStyle::TextVertical;
+ else
+ return PointerStyle::Text;
+ }
+ // Outliner should return something here...
+ Point aPos(pOut->LogicToPixel(rMousePos));
+ PointerStyle aPointer(pTextEditOutlinerView->GetPointer(aPos));
+ if (aPointer==PointerStyle::Arrow)
+ {
+ if(pTextEditOutliner->IsVertical())
+ aPointer = PointerStyle::TextVertical;
+ else
+ aPointer = PointerStyle::Text;
+ }
+ return aPointer;
+ }
+
+ SdrViewEvent aVEvt;
+ aVEvt.nMouseCode=(nModifier&(KEY_SHIFT|KEY_MOD1|KEY_MOD2))|MOUSE_LEFT; // to see what would happen on MouseLeftDown
+ aVEvt.bMouseDown=!bLeftDown; // What if ..?
+ aVEvt.bMouseUp=bLeftDown; // What if ..?
+ if (pOut!=nullptr)
+ const_cast<SdrView*>(this)->SetActualWin(pOut);
+ SdrHitKind eHit=PickAnything(rMousePos,aVEvt);
+ SdrEventKind eEvent=aVEvt.eEvent;
+ switch (eEvent)
+ {
+ case SdrEventKind::BeginCreateObj:
+ return aCurrentCreatePointer;
+ case SdrEventKind::MarkObj:
+ return PointerStyle::Move;
+ case SdrEventKind::BeginMark:
+ return PointerStyle::Arrow;
+ case SdrEventKind::MarkPoint:
+ case SdrEventKind::MarkGluePoint:
+ return PointerStyle::MovePoint;
+ case SdrEventKind::BeginInsertObjPoint:
+ case SdrEventKind::BeginInsertGluePoint:
+ return PointerStyle::Cross;
+ case SdrEventKind::ExecuteUrl:
+ return PointerStyle::RefHand;
+ case SdrEventKind::BeginMacroObj:
+ {
+ SdrObjMacroHitRec aHitRec;
+ aHitRec.aPos=aVEvt.aLogicPos;
+ aHitRec.nTol=mnHitTolLog;
+ aHitRec.pVisiLayer=&aVEvt.pPV->GetVisibleLayers();
+ aHitRec.pPageView=aVEvt.pPV;
+ return aVEvt.pObj->GetMacroPointer(aHitRec);
+ }
+ default: break;
+ } // switch
+
+ switch(eHit)
+ {
+ case SdrHitKind::Cell:
+ return PointerStyle::Arrow;
+ case SdrHitKind::HelpLine :
+ return aVEvt.pPV->GetHelpLines()[aVEvt.nHlplIdx].GetPointer();
+ case SdrHitKind::Gluepoint:
+ return PointerStyle::MovePoint;
+ case SdrHitKind::TextEdit :
+ case SdrHitKind::TextEditObj:
+ {
+ SdrTextObj* pText = dynamic_cast< SdrTextObj* >( aVEvt.pObj );
+ if(pText && pText->HasText())
+ {
+ OutlinerParaObject* pParaObj = pText->GetOutlinerParaObject();
+ if(pParaObj && pParaObj->IsVertical())
+ return PointerStyle::TextVertical;
+ }
+ return PointerStyle::Text;
+ }
+ default: break;
+ }
+
+ bool bMarkHit=eHit==SdrHitKind::MarkedObject;
+ SdrHdl* pHdl=aVEvt.pHdl;
+ // now check the pointers for dragging
+ if (pHdl!=nullptr || bMarkHit) {
+ SdrHdlKind eHdl= pHdl!=nullptr ? pHdl->GetKind() : SdrHdlKind::Move;
+ bool bCorner=pHdl!=nullptr && pHdl->IsCornerHdl();
+ bool bVertex=pHdl!=nullptr && pHdl->IsVertexHdl();
+ bool bMov=eHdl==SdrHdlKind::Move;
+ if (bMov && (meDragMode==SdrDragMode::Move || meDragMode==SdrDragMode::Resize || mbMarkedHitMovesAlways)) {
+ if (!IsMoveAllowed()) return PointerStyle::Arrow; // because double click or drag & drop is possible
+ return PointerStyle::Move;
+ }
+ switch (meDragMode) {
+ case SdrDragMode::Rotate: {
+ if ((bCorner || bMov) && !IsRotateAllowed(true))
+ return PointerStyle::NotAllowed;
+
+ // are 3D objects selected?
+ bool b3DObjSelected = false;
+ for (size_t a=0; !b3DObjSelected && a<GetMarkedObjectCount(); ++a) {
+ SdrObject* pObj = GetMarkedObjectByIndex(a);
+ if(dynamic_cast<const E3dObject* >(pObj) != nullptr)
+ b3DObjSelected = true;
+ }
+ // If we have a 3D object, go on despite !IsShearAllowed,
+ // because then we have a rotation instead of a shear.
+ if (bVertex && !IsShearAllowed() && !b3DObjSelected)
+ return PointerStyle::NotAllowed;
+ if (bMov)
+ return PointerStyle::Rotate;
+ } break;
+ case SdrDragMode::Shear: {
+ if (bCorner) {
+ if (!IsDistortAllowed(true) && !IsDistortAllowed()) return PointerStyle::NotAllowed;
+ else return PointerStyle::RefHand;
+ }
+ if (bVertex && !IsShearAllowed()) return PointerStyle::NotAllowed;
+ if (bMov) {
+ if (!IsMoveAllowed()) return PointerStyle::Arrow; // because double click or drag & drop is possible
+ return PointerStyle::Move;
+ }
+ } break;
+ case SdrDragMode::Mirror: {
+ if (bCorner || bVertex || bMov) {
+ SdrHdl* pH1=maHdlList.GetHdl(SdrHdlKind::Ref1);
+ SdrHdl* pH2=maHdlList.GetHdl(SdrHdlKind::Ref2);
+ bool b90=false;
+ bool b45=false;
+ Point aDif;
+ if (pH1!=nullptr && pH2!=nullptr) {
+ aDif=pH2->GetPos()-pH1->GetPos();
+ b90=(aDif.X()==0) || aDif.Y()==0;
+ b45=b90 || (std::abs(aDif.X())==std::abs(aDif.Y()));
+ }
+ bool bNo=false;
+ if (!IsMirrorAllowed(true,true)) bNo=true; // any mirroring is forbidden
+ if (!IsMirrorAllowed() && !b45) bNo=true; // mirroring freely is forbidden
+ if (!IsMirrorAllowed(true) && !b90) bNo=true; // mirroring horizontally/vertically is allowed
+ if (bNo) return PointerStyle::NotAllowed;
+ if (b90) {
+ return PointerStyle::Mirror;
+ }
+ return PointerStyle::Mirror;
+ }
+ } break;
+
+ case SdrDragMode::Transparence:
+ {
+ if(!IsTransparenceAllowed())
+ return PointerStyle::NotAllowed;
+
+ return PointerStyle::RefHand;
+ }
+
+ case SdrDragMode::Gradient:
+ {
+ if(!IsGradientAllowed())
+ return PointerStyle::NotAllowed;
+
+ return PointerStyle::RefHand;
+ }
+
+ case SdrDragMode::Crook: {
+ if (bCorner || bVertex || bMov) {
+ if (!IsCrookAllowed(true) && !IsCrookAllowed()) return PointerStyle::NotAllowed;
+ return PointerStyle::Crook;
+ }
+ break;
+ }
+
+ case SdrDragMode::Crop:
+ {
+ return PointerStyle::Crop;
+ }
+
+ default: {
+ if ((bCorner || bVertex) && !IsResizeAllowed(true)) return PointerStyle::NotAllowed;
+ }
+ }
+ if (pHdl!=nullptr) return pHdl->GetPointer();
+ if (bMov) {
+ if (!IsMoveAllowed()) return PointerStyle::Arrow; // because double click or drag & drop is possible
+ return PointerStyle::Move;
+ }
+ }
+ if (meEditMode==SdrViewEditMode::Create) return aCurrentCreatePointer;
+ return PointerStyle::Arrow;
+}
+
+#define STR_NOTHING "nothing"
+OUString SdrView::GetStatusText()
+{
+ OUString aName;
+ OUString aStr = STR_NOTHING;
+
+ if (pCurrentCreate!=nullptr)
+ {
+ aStr=pCurrentCreate->getSpecialDragComment(maDragStat);
+
+ if(aStr.isEmpty())
+ {
+ aName = pCurrentCreate->TakeObjNameSingul();
+ aStr = SvxResId(STR_ViewCreateObj);
+ }
+ }
+ else if (mpCurrentSdrDragMethod)
+ {
+ if (mbInsPolyPoint || IsInsertGluePoint())
+ {
+ aStr=maInsPointUndoStr;
+ }
+ else
+ {
+ if (maDragStat.IsMinMoved())
+ {
+ SAL_INFO(
+ "svx.svdraw",
+ "(" << this << ") " << mpCurrentSdrDragMethod.get());
+ aStr = mpCurrentSdrDragMethod->GetSdrDragComment();
+ }
+ }
+ }
+ else if(IsMarkObj())
+ {
+ if(AreObjectsMarked())
+ {
+ aStr = SvxResId(STR_ViewMarkMoreObjs);
+ }
+ else
+ {
+ aStr = SvxResId(STR_ViewMarkObjs);
+ }
+ }
+ else if(IsMarkPoints())
+ {
+ if(HasMarkedPoints())
+ {
+ aStr = SvxResId(STR_ViewMarkMorePoints);
+ }
+ else
+ {
+ aStr = SvxResId(STR_ViewMarkPoints);
+ }
+ } else if (IsMarkGluePoints())
+ {
+ if(HasMarkedGluePoints())
+ {
+ aStr = SvxResId(STR_ViewMarkMoreGluePoints);
+ }
+ else
+ {
+ aStr = SvxResId(STR_ViewMarkGluePoints);
+ }
+ }
+ else if (IsTextEdit() && pTextEditOutlinerView!=nullptr) {
+ aStr=SvxResId(STR_ViewTextEdit); // "TextEdit - Row y, Column x";
+ ESelection aSel(pTextEditOutlinerView->GetSelection());
+ long nPar=aSel.nEndPara,nLin=0,nCol=aSel.nEndPos;
+ if (aSel.nEndPara>0) {
+ for (sal_Int32 nParaNum=0; nParaNum<aSel.nEndPara; nParaNum++) {
+ nLin+=pTextEditOutliner->GetLineCount(nParaNum);
+ }
+ }
+ // A little imperfection:
+ // At the end of a line of any multi-line paragraph, we display the
+ // position of the next line of the same paragraph, if there is one.
+ sal_uInt16 nParaLine = 0;
+ sal_uLong nParaLineCount = pTextEditOutliner->GetLineCount(aSel.nEndPara);
+ bool bBrk = false;
+ while (!bBrk)
+ {
+ sal_uInt16 nLen = pTextEditOutliner->GetLineLen(aSel.nEndPara, nParaLine);
+ bool bLastLine = (nParaLine == nParaLineCount - 1);
+ if (nCol>nLen || (!bLastLine && nCol == nLen))
+ {
+ nCol -= nLen;
+ nLin++;
+ nParaLine++;
+ }
+ else
+ bBrk = true;
+
+ if (nLen == 0)
+ bBrk = true; // to be sure
+ }
+
+ aStr = aStr.replaceFirst("%1", OUString::number(nPar + 1));
+ aStr = aStr.replaceFirst("%2", OUString::number(nLin + 1));
+ aStr = aStr.replaceFirst("%3", OUString::number(nCol + 1));
+
+#ifdef DBG_UTIL
+ aStr += ", Level " + OUString::number( pTextEditOutliner->GetDepth( aSel.nEndPara ) );
+#endif
+ }
+
+ if(aStr == STR_NOTHING)
+ {
+ if (AreObjectsMarked()) {
+ aStr = ImpGetDescriptionString(STR_ViewMarked);
+ if (IsGluePointEditMode()) {
+ if (HasMarkedGluePoints()) {
+ aStr = ImpGetDescriptionString(STR_ViewMarked, ImpGetDescriptionOptions::GLUEPOINTS);
+ }
+ } else {
+ if (HasMarkedPoints()) {
+ aStr = ImpGetDescriptionString(STR_ViewMarked, ImpGetDescriptionOptions::POINTS);
+ }
+ }
+ } else {
+ aStr.clear();
+ }
+ }
+ else if(!aName.isEmpty())
+ {
+ aStr = aStr.replaceFirst("%1", aName);
+ }
+
+ if(!aStr.isEmpty())
+ {
+ // capitalize first letter
+ aStr = aStr.replaceAt(0, 1, OUString(aStr[0]).toAsciiUpperCase());
+ }
+ return aStr;
+}
+
+SdrViewContext SdrView::GetContext() const
+{
+ if( IsGluePointEditMode() )
+ return SdrViewContext::GluePointEdit;
+
+ const size_t nMarkCount = GetMarkedObjectCount();
+
+ if( HasMarkablePoints() && !IsFrameHandles() )
+ {
+ bool bPath=true;
+ for( size_t nMarkNum = 0; nMarkNum < nMarkCount && bPath; ++nMarkNum )
+ if (dynamic_cast<const SdrPathObj*>(GetMarkedObjectByIndex(nMarkNum)) == nullptr)
+ bPath=false;
+
+ if( bPath )
+ return SdrViewContext::PointEdit;
+ }
+
+ if( GetMarkedObjectCount() )
+ {
+ bool bGraf = true, bMedia = true, bTable = true;
+
+ for( size_t nMarkNum = 0; nMarkNum < nMarkCount && ( bGraf || bMedia ); ++nMarkNum )
+ {
+ const SdrObject* pMarkObj = GetMarkedObjectByIndex( nMarkNum );
+ DBG_ASSERT( pMarkObj, "SdrView::GetContext(), null pointer in mark list!" );
+
+ if( !pMarkObj )
+ continue;
+
+ if( dynamic_cast<const SdrGrafObj*>( pMarkObj) == nullptr )
+ bGraf = false;
+
+ if( dynamic_cast<const SdrMediaObj*>( pMarkObj) == nullptr )
+ bMedia = false;
+
+ if( dynamic_cast<const sdr::table::SdrTableObj* >( pMarkObj ) == nullptr )
+ bTable = false;
+ }
+
+ if( bGraf )
+ return SdrViewContext::Graphic;
+ else if( bMedia )
+ return SdrViewContext::Media;
+ else if( bTable )
+ return SdrViewContext::Table;
+ }
+
+ return SdrViewContext::Standard;
+}
+
+void SdrView::MarkAll()
+{
+ if (IsTextEdit()) {
+ GetTextEditOutlinerView()->SetSelection(ESelection(0,0,EE_PARA_ALL,EE_TEXTPOS_ALL));
+ } else if (IsGluePointEditMode()) MarkAllGluePoints();
+ else if (HasMarkablePoints()) MarkAllPoints();
+ else MarkAllObj();
+}
+
+void SdrView::UnmarkAll()
+{
+ if (IsTextEdit()) {
+ ESelection eSel=GetTextEditOutlinerView()->GetSelection();
+ eSel.nStartPara=eSel.nEndPara;
+ eSel.nStartPos=eSel.nEndPos;
+ GetTextEditOutlinerView()->SetSelection(eSel);
+ } else if (HasMarkedGluePoints()) UnmarkAllGluePoints();
+ else if (HasMarkedPoints()) UnmarkAllPoints(); // Marked, not Markable!
+ else UnmarkAllObj();
+}
+
+const tools::Rectangle& SdrView::GetMarkedRect() const
+{
+ if (IsGluePointEditMode() && HasMarkedGluePoints()) {
+ return GetMarkedGluePointsRect();
+ }
+ if (HasMarkedPoints()) {
+ return GetMarkedPointsRect();
+ }
+ return GetMarkedObjRect();
+}
+
+void SdrView::DeleteMarked()
+{
+ if (IsTextEdit())
+ {
+ SdrObjEditView::KeyInput(KeyEvent(0,vcl::KeyCode(KeyFuncType::DELETE)),pTextEditWin);
+ }
+ else
+ {
+ if( mxSelectionController.is() && mxSelectionController->DeleteMarked() )
+ {
+ // action already performed by current selection controller, do nothing
+ }
+ else if (IsGluePointEditMode() && HasMarkedGluePoints())
+ {
+ DeleteMarkedGluePoints();
+ }
+ else if (GetContext()==SdrViewContext::PointEdit && HasMarkedPoints())
+ {
+ DeleteMarkedPoints();
+ }
+ else
+ {
+ DeleteMarkedObj();
+ }
+ }
+}
+
+bool SdrView::BegMark(const Point& rPnt, bool bAddMark, bool bUnmark)
+{
+ if (bUnmark) bAddMark=true;
+ if (IsGluePointEditMode()) {
+ if (!bAddMark) UnmarkAllGluePoints();
+ return BegMarkGluePoints(rPnt,bUnmark);
+ } else if (HasMarkablePoints()) {
+ if (!bAddMark) UnmarkAllPoints();
+ return BegMarkPoints(rPnt,bUnmark);
+ } else {
+ if (!bAddMark) UnmarkAllObj();
+ BegMarkObj(rPnt,bUnmark);
+ return true;
+ }
+}
+
+void SdrView::ConfigurationChanged( ::utl::ConfigurationBroadcaster*p, ConfigurationHints nHint)
+{
+ onAccessibilityOptionsChanged();
+ SdrCreateView::ConfigurationChanged(p, nHint);
+}
+
+
+/** method is called whenever the global SvtAccessibilityOptions is changed */
+void SdrView::onAccessibilityOptionsChanged()
+{
+}
+
+void SdrView::SetMasterPagePaintCaching(bool bOn)
+{
+ if(mbMasterPagePaintCaching != bOn)
+ {
+ mbMasterPagePaintCaching = bOn;
+
+ // reset at all SdrPageWindows
+ SdrPageView* pPageView = GetSdrPageView();
+
+ if(pPageView)
+ {
+ for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
+ {
+ SdrPageWindow* pPageWindow = pPageView->GetPageWindow(b);
+ assert(pPageWindow && "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)");
+
+ // force deletion of ObjectContact, so at re-display all VOCs
+ // will be re-created with updated flag setting
+ pPageWindow->ResetObjectContact();
+ }
+
+ // force redraw of this view
+ pPageView->InvalidateAllWin();
+ }
+ }
+}
+
+// Default ObjectContact is ObjectContactOfPageView
+sdr::contact::ObjectContact* SdrView::createViewSpecificObjectContact(
+ SdrPageWindow& rPageWindow,
+ const char* pDebugName) const
+{
+ return new sdr::contact::ObjectContactOfPageView(rPageWindow, pDebugName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */