/* -*- 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 .
*/
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.
}
// 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.mnMouseCode & KEY_SHIFT) != 0; bool bCtrl = (rVEvt.mnMouseCode & KEY_MOD1) != 0; bool bAlt = (rVEvt.mnMouseCode & 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;
} elseif (pHdl!=nullptr)
{
eHit=SdrHitKind::Handle; // handle is hit: highest priority
} elseif (bEditMode && IsHlplVisible() && IsHlplFront() && pOut!=nullptr && PickHelpLine(aLocalLogicPosition,mnHitTolLog,*pOut,nHlplIdx,pPV))
{
eHit=SdrHitKind::HelpLine; // help line in the foreground hit: can be moved now
} elseif (bGluePointMode && PickGluePoint(aLocalLogicPosition,pObj,nGlueId,pPV))
{
eHit=SdrHitKind::Gluepoint; // deselected gluepoint hit
} elseif ((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;
}
}
} elseif ((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. // Except for the LOK. LOK doesn't have hoovering popup // feature.
eHit = comphelper::LibreOfficeKit::isActive() ? SdrHitKind::TextEditObj : SdrHitKind::UnmarkedObject; break; default: break;
}
}
} elseif (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.mpRootObj = pObj; if (!bRoot) pObj=pMidObj; if (!bRoot && !bMid) pObj=pHitObj;
eHit=SdrHitKind::Macro;
}
}
} // check for URL field if (eHit==SdrHitKind::UnmarkedObject)
{
SdrTextObj* pTextObj=DynCastSdrTextObj( 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; constbool bTEHit(pPV && SdrObjectPrimitiveHit(*pTextObj, aLocalLogicPosition, {0, 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)
{ auto pBasePrimitive = xReference.get(); if (pBasePrimitive && pBasePrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D)
{
pTextHierarchyFieldPrimitive2D = static_cast<const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D*>(pBasePrimitive); 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;
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.mpURLField = &aSvxURLField;
}
}
}
} if (eHit==SdrHitKind::UnmarkedObject && !pHitObj->getHyperlink().isEmpty())
{ static SvxURLField aSvxURLField;
aSvxURLField.SetURL(pHitObj->getHyperlink());
rVEvt.mpURLField = &aSvxURLField;
eHit = SdrHitKind::UrlField;
}
}
if (bHitPassDirect &&
(eHit==SdrHitKind::MarkedObject || eHit==SdrHitKind::UnmarkedObject) &&
(IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj->HasTextEdit())
{ auto pTextObj = DynCastSdrTextObj(pHitObj);
// Around the TextEditArea there's a border to select without going into text edit mode.
tools::Rectangle aBoundRect; // Force to SnapRect when Fontwork if (pTextObj && pTextObj->IsFontwork())
aBoundRect = pHitObj->GetSnapRect(); elseif (pTextObj && !pTextObj->GetGeoStat().m_nRotationAngle
&& !pTextObj->GetGeoStat().m_nShearAngle)
{
pTextObj->TakeTextEditArea(nullptr, nullptr, &aBoundRect, nullptr);
} else
aBoundRect = pHitObj->GetCurrentBoundRect();
// TextEdit, ObjEdit, Macro if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos)))
{ if(!pOut || IsTextEditInSelectionMode())
{ if (mpTextEditOutliner->IsVertical()) return PointerStyle::TextVertical; else return PointerStyle::Text;
} // Outliner should return something here...
Point aPos(pOut->LogicToPixel(rMousePos));
PointerStyle aPointer(mpTextEditOutlinerView->GetPointer(aPos)); if (aPointer==PointerStyle::Arrow)
{ if (mpTextEditOutliner->IsVertical())
aPointer = PointerStyle::TextVertical; else
aPointer = PointerStyle::Text;
} return aPointer;
}
SdrViewEvent aVEvt;
aVEvt.mnMouseCode = (nModifier&(KEY_SHIFT|KEY_MOD1|KEY_MOD2))|MOUSE_LEFT; // to see what would happen on MouseLeftDown
aVEvt.mbMouseDown = !bLeftDown; // What if ..?
aVEvt.mbMouseUp = bLeftDown; // What if ..? if (pOut!=nullptr) const_cast<SdrView*>(this)->SetActualWin(pOut);
SdrHitKind eHit=PickAnything(rMousePos,aVEvt);
SdrEventKind eEvent = aVEvt.meEvent; switch (eEvent)
{ case SdrEventKind::BeginCreateObj: return maCurrentCreatePointer; 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.maLogicPos;
aHitRec.nTol=mnHitTolLog;
aHitRec.pVisiLayer = &aVEvt.mpPV->GetVisibleLayers();
aHitRec.pPageView = aVEvt.mpPV; return aVEvt.mpObj->GetMacroPointer(aHitRec);
} default: break;
} // switch
switch(eHit)
{ case SdrHitKind::Cell: return PointerStyle::Arrow; case SdrHitKind::HelpLine : return aVEvt.mpPV->GetHelpLines()[aVEvt.mnHlplIdx].GetPointer(); case SdrHitKind::Gluepoint: return PointerStyle::MovePoint; case SdrHitKind::TextEdit : case SdrHitKind::TextEditObj:
{
SdrTextObj* pText = DynCastSdrTextObj(aVEvt.mpObj); if(pText && pText->HasText())
{
OutlinerParaObject* pParaObj = pText->GetOutlinerParaObject(); if(pParaObj && pParaObj->IsEffectivelyVertical()) return PointerStyle::TextVertical;
} return PointerStyle::Text;
} default: break;
}
bool bMarkHit=eHit==SdrHitKind::MarkedObject;
SdrHdl* pHdl = aVEvt.mpHdl; // 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; const SdrMarkList& rMarkList = GetMarkedObjectList(); for (size_t a=0; !b3DObjSelected && a<rMarkList.GetMarkCount(); ++a) {
SdrObject* pObj = rMarkList.GetMark(a)->GetMarkedSdrObj(); if(DynCastE3dObject(pObj))
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; elsereturn 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; if (pH1!=nullptr && pH2!=nullptr) {
Point 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 maCurrentCreatePointer; return PointerStyle::Arrow;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.