office-gobmx/svx/source/svdraw/svdcrtv.cxx
Noel Grandin 4e24efb563 tdf#54857 elide more dynamic_cast
add a helper, following the same style as the ones in sw/

Change-Id: I13c673bba5ff47df6beef9d90c200e5801030cf0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142119
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2022-11-01 19:53:23 +01:00

907 lines
29 KiB
C++

/* -*- 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 <svx/svdcrtv.hxx>
#include <svx/xlnclit.hxx>
#include <svx/svdocapt.hxx>
#include <svx/svdoedge.hxx>
#include <svx/svdpagv.hxx>
#include <svx/svdpage.hxx>
#include <svx/scene3d.hxx>
#include <svx/view3d.hxx>
#include <svx/xfillit0.hxx>
#include <svx/xflclit.hxx>
#include <svx/xlineit0.hxx>
#include <svx/svdouno.hxx>
#include <svx/svdopath.hxx>
#include <svx/sdr/overlay/overlaypolypolygon.hxx>
#include <svx/sdr/overlay/overlaymanager.hxx>
#include <svx/sdrpaintwindow.hxx>
#include <fmobj.hxx>
#include <svx/svdocirc.hxx>
#include <svx/sdr/contact/viewcontact.hxx>
#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
#include <vcl/ptrstyle.hxx>
using namespace com::sun::star;
class ImplConnectMarkerOverlay
{
// The OverlayObjects
sdr::overlay::OverlayObjectList maObjects;
// The remembered target object
const SdrObject& mrObject;
public:
ImplConnectMarkerOverlay(const SdrCreateView& rView, SdrObject const & rObject);
// 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.
const SdrObject& GetTargetObject() const { return mrObject; }
};
ImplConnectMarkerOverlay::ImplConnectMarkerOverlay(const SdrCreateView& rView, SdrObject const & rObject)
: mrObject(rObject)
{
basegfx::B2DPolyPolygon aB2DPolyPolygon(rObject.TakeXorPoly());
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())
{
float fScalingFactor = xTargetOverlay->getOutputDevice().GetDPIScaleFactor();
Size aHalfLogicSize(xTargetOverlay->getOutputDevice().PixelToLogic(Size(4 * fScalingFactor, 4 * fScalingFactor)));
// object
std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
aB2DPolyPolygon));
xTargetOverlay->add(*pNew);
maObjects.append(std::move(pNew));
// gluepoints
for(sal_uInt16 i(0); i < 4; i++)
{
SdrGluePoint aGluePoint(rObject.GetVertexGluePoint(i));
const Point& rPosition = aGluePoint.GetAbsolutePos(rObject);
basegfx::B2DPoint aTopLeft(rPosition.X() - aHalfLogicSize.Width(), rPosition.Y() - aHalfLogicSize.Height());
basegfx::B2DPoint aBottomRight(rPosition.X() + aHalfLogicSize.Width(), rPosition.Y() + aHalfLogicSize.Height());
basegfx::B2DPolygon aTempPoly;
aTempPoly.append(aTopLeft);
aTempPoly.append(basegfx::B2DPoint(aBottomRight.getX(), aTopLeft.getY()));
aTempPoly.append(aBottomRight);
aTempPoly.append(basegfx::B2DPoint(aTopLeft.getX(), aBottomRight.getY()));
aTempPoly.setClosed(true);
basegfx::B2DPolyPolygon aTempPolyPoly;
aTempPolyPoly.append(aTempPoly);
std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew2(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
std::move(aTempPolyPoly)));
xTargetOverlay->add(*pNew2);
maObjects.append(std::move(pNew2));
}
}
}
}
class ImpSdrCreateViewExtraData
{
// The OverlayObjects for XOR replacement
sdr::overlay::OverlayObjectList maObjects;
public:
ImpSdrCreateViewExtraData();
~ImpSdrCreateViewExtraData();
void CreateAndShowOverlay(const SdrCreateView& rView, const SdrObject* pObject, const basegfx::B2DPolyPolygon& rPolyPoly);
void HideOverlay();
};
ImpSdrCreateViewExtraData::ImpSdrCreateViewExtraData()
{
}
ImpSdrCreateViewExtraData::~ImpSdrCreateViewExtraData()
{
HideOverlay();
}
void ImpSdrCreateViewExtraData::CreateAndShowOverlay(const SdrCreateView& rView, const SdrObject* pObject, const basegfx::B2DPolyPolygon& rPolyPoly)
{
for(sal_uInt32 a(0); a < rView.PaintWindowCount(); a++)
{
SdrPaintWindow* pCandidate = rView.GetPaintWindow(a);
const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager = pCandidate->GetOverlayManager();
if (xOverlayManager.is())
{
if(pObject)
{
const sdr::contact::ViewContact& rVC = pObject->GetViewContact();
drawinglayer::primitive2d::Primitive2DContainer aSequence;
rVC.getViewIndependentPrimitive2DContainer(aSequence);
std::unique_ptr<sdr::overlay::OverlayObject> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(std::move(aSequence)));
xOverlayManager->add(*pNew);
maObjects.append(std::move(pNew));
}
if(rPolyPoly.count())
{
std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
rPolyPoly));
xOverlayManager->add(*pNew);
maObjects.append(std::move(pNew));
}
}
}
}
void ImpSdrCreateViewExtraData::HideOverlay()
{
// the clear() call of the list removes all objects from the
// OverlayManager and deletes them.
maObjects.clear();
}
// CreateView
void SdrCreateView::ImpClearConnectMarker()
{
mpCoMaOverlay.reset();
}
SdrCreateView::SdrCreateView(SdrModel& rSdrModel, OutputDevice* pOut)
: SdrDragView(rSdrModel, pOut)
, mpCreatePV(nullptr)
, mpCreateViewExtraData(new ImpSdrCreateViewExtraData())
, maCurrentCreatePointer(PointerStyle::Cross)
, mnAutoCloseDistPix(5)
, mnFreeHandMinDistPix(10)
, mnCurrentInvent(SdrInventor::Default)
, mnCurrentIdent(SdrObjKind::NONE)
, mb1stPointAsCenter(false)
, mbUseIncompatiblePathCreateInterface(false)
{
}
SdrCreateView::~SdrCreateView()
{
ImpClearConnectMarker();
mpCreateViewExtraData.reset();
}
bool SdrCreateView::IsAction() const
{
return SdrDragView::IsAction() || mpCurrentCreate!=nullptr;
}
void SdrCreateView::MovAction(const Point& rPnt)
{
SdrDragView::MovAction(rPnt);
if (mpCurrentCreate != nullptr) {
MovCreateObj(rPnt);
}
}
void SdrCreateView::EndAction()
{
if (mpCurrentCreate != nullptr) EndCreateObj(SdrCreateCmd::ForceEnd);
SdrDragView::EndAction();
}
void SdrCreateView::BckAction()
{
if (mpCurrentCreate != nullptr) BckCreateObj();
SdrDragView::BckAction();
}
void SdrCreateView::BrkAction()
{
SdrDragView::BrkAction();
BrkCreateObj();
}
void SdrCreateView::TakeActionRect(tools::Rectangle& rRect) const
{
if (mpCurrentCreate != nullptr)
{
rRect=maDragStat.GetActionRect();
if (rRect.IsEmpty())
{
rRect=tools::Rectangle(maDragStat.GetPrev(),maDragStat.GetNow());
}
}
else
{
SdrDragView::TakeActionRect(rRect);
}
}
bool SdrCreateView::CheckEdgeMode()
{
if (mpCurrentCreate != nullptr)
{
// is managed by EdgeObj
if (mnCurrentInvent==SdrInventor::Default && mnCurrentIdent==SdrObjKind::Edge) return false;
}
if (!IsCreateMode() || mnCurrentInvent!=SdrInventor::Default || mnCurrentIdent!=SdrObjKind::Edge)
{
ImpClearConnectMarker();
return false;
}
else
{
// sal_True, if MouseMove should check Connect
return !IsAction();
}
}
void SdrCreateView::SetConnectMarker(const SdrObjConnection& rCon)
{
SdrObject* pTargetObject = rCon.pObj;
if(pTargetObject)
{
// if target object changes, throw away overlay object to make room for changes
if(mpCoMaOverlay && pTargetObject != &mpCoMaOverlay->GetTargetObject())
{
ImpClearConnectMarker();
}
if(!mpCoMaOverlay)
{
mpCoMaOverlay.reset(new ImplConnectMarkerOverlay(*this, *pTargetObject));
}
}
else
{
ImpClearConnectMarker();
}
}
void SdrCreateView::HideConnectMarker()
{
ImpClearConnectMarker();
}
bool SdrCreateView::MouseMove(const MouseEvent& rMEvt, OutputDevice* pWin)
{
if(CheckEdgeMode() && pWin)
{
SdrPageView* pPV = GetSdrPageView();
if(pPV)
{
// TODO: Change default hit tolerance at IsMarkedHit() some time!
Point aPos(pWin->PixelToLogic(rMEvt.GetPosPixel()));
bool bMarkHit=PickHandle(aPos)!=nullptr || IsMarkedObjHit(aPos);
SdrObjConnection aCon;
if (!bMarkHit) SdrEdgeObj::ImpFindConnector(aPos,*pPV,aCon,nullptr,pWin);
SetConnectMarker(aCon);
}
}
return SdrDragView::MouseMove(rMEvt,pWin);
}
bool SdrCreateView::IsTextTool() const
{
return meEditMode==SdrViewEditMode::Create
&& mnCurrentInvent==SdrInventor::Default
&& (mnCurrentIdent==SdrObjKind::Text
|| mnCurrentIdent==SdrObjKind::TitleText
|| mnCurrentIdent==SdrObjKind::OutlineText);
}
bool SdrCreateView::IsEdgeTool() const
{
return meEditMode==SdrViewEditMode::Create && mnCurrentInvent==SdrInventor::Default && (mnCurrentIdent==SdrObjKind::Edge);
}
bool SdrCreateView::IsMeasureTool() const
{
return meEditMode==SdrViewEditMode::Create && mnCurrentInvent==SdrInventor::Default && (mnCurrentIdent==SdrObjKind::Measure);
}
void SdrCreateView::SetCurrentObj(SdrObjKind nIdent, SdrInventor nInvent)
{
if (mnCurrentInvent!=nInvent || mnCurrentIdent!=nIdent)
{
mnCurrentInvent=nInvent;
mnCurrentIdent=nIdent;
rtl::Reference<SdrObject> pObj = (nIdent == SdrObjKind::NONE) ? nullptr :
SdrObjFactory::MakeNewObject(
*GetModel(),
nInvent,
nIdent);
if(pObj)
{
// Using text tool, mouse cursor is usually I-Beam,
// crosshairs with tiny I-Beam appears only on MouseButtonDown.
if(IsTextTool())
{
// Here the correct pointer needs to be used
// if the default is set to vertical writing
maCurrentCreatePointer = PointerStyle::Text;
}
else
maCurrentCreatePointer = pObj->GetCreatePointer();
}
else
{
maCurrentCreatePointer = PointerStyle::Cross;
}
}
CheckEdgeMode();
ImpSetGlueVisible3(IsEdgeTool());
}
bool SdrCreateView::ImpBegCreateObj(SdrInventor nInvent, SdrObjKind nIdent, const Point& rPnt, OutputDevice* pOut,
sal_Int16 nMinMov, const tools::Rectangle& rLogRect, SdrObject* pPreparedFactoryObject)
{
bool bRet=false;
UnmarkAllObj();
BrkAction();
ImpClearConnectMarker();
mpCreatePV = GetSdrPageView();
if (mpCreatePV != nullptr)
{ // otherwise no side registered!
OUString aLay(maActualLayer);
if(nInvent == SdrInventor::Default && nIdent == SdrObjKind::Measure && !maMeasureLayer.isEmpty())
{
aLay = maMeasureLayer;
}
SdrLayerID nLayer = mpCreatePV->GetPage()->GetLayerAdmin().GetLayerID(aLay);
if (nLayer==SDRLAYER_NOTFOUND) nLayer = SdrLayerID(0);
if (!mpCreatePV->GetLockedLayers().IsSet(nLayer) && mpCreatePV->GetVisibleLayers().IsSet(nLayer))
{
if(pPreparedFactoryObject)
{
mpCurrentCreate = pPreparedFactoryObject;
}
else
{
mpCurrentCreate = SdrObjFactory::MakeNewObject(
*mpModel,
nInvent,
nIdent);
}
Point aPnt(rPnt);
if (mnCurrentInvent != SdrInventor::Default || (mnCurrentIdent != SdrObjKind::Edge &&
mnCurrentIdent != SdrObjKind::FreehandLine &&
mnCurrentIdent != SdrObjKind::FreehandFill )) { // no snapping for Edge and Freehand
aPnt=GetSnapPos(aPnt, mpCreatePV);
}
if (mpCurrentCreate!=nullptr)
{
if (mpDefaultStyleSheet!=nullptr) mpCurrentCreate->NbcSetStyleSheet(mpDefaultStyleSheet, false);
// SW uses a naked SdrObject for frame construction. Normally, such an
// object should not be created. Since it is possible to use it as a helper
// object (e.g. in letting the user define an area with the interactive
// construction) at least no items should be set at that object.
if(nInvent != SdrInventor::Default || nIdent != SdrObjKind::NONE)
{
mpCurrentCreate->SetMergedItemSet(maDefaultAttr);
}
if (mpModel && dynamic_cast<const SdrCaptionObj *>(mpCurrentCreate.get()) != nullptr)
{
SfxItemSet aSet(mpModel->GetItemPool());
aSet.Put(XFillColorItem(OUString(),COL_WHITE)); // in case someone turns on Solid
aSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
mpCurrentCreate->SetMergedItemSet(aSet);
}
if (mpModel && nInvent==SdrInventor::Default && (nIdent==SdrObjKind::Text ||
nIdent==SdrObjKind::TitleText || nIdent==SdrObjKind::OutlineText))
{
// default for all text frames: no background, no border
SfxItemSet aSet(mpModel->GetItemPool());
aSet.Put(XFillColorItem(OUString(),COL_WHITE)); // in case someone turns on Solid
aSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
aSet.Put(XLineColorItem(OUString(),COL_BLACK)); // in case someone turns on Solid
aSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
mpCurrentCreate->SetMergedItemSet(aSet);
}
if (!rLogRect.IsEmpty()) mpCurrentCreate->NbcSetLogicRect(rLogRect);
// make sure drag start point is inside WorkArea
const tools::Rectangle& rWorkArea = GetWorkArea();
if(!rWorkArea.IsEmpty())
{
if(aPnt.X() < rWorkArea.Left())
{
aPnt.setX( rWorkArea.Left() );
}
if(aPnt.X() > rWorkArea.Right())
{
aPnt.setX( rWorkArea.Right() );
}
if(aPnt.Y() < rWorkArea.Top())
{
aPnt.setY( rWorkArea.Top() );
}
if(aPnt.Y() > rWorkArea.Bottom())
{
aPnt.setY( rWorkArea.Bottom() );
}
}
maDragStat.Reset(aPnt);
maDragStat.SetView(static_cast<SdrView*>(this));
maDragStat.SetPageView(mpCreatePV);
maDragStat.SetMinMove(ImpGetMinMovLogic(nMinMov,pOut));
mpDragWin=pOut;
if (mpCurrentCreate->BegCreate(maDragStat))
{
ShowCreateObj(/*pOut,sal_True*/);
bRet=true;
}
else
{
mpCurrentCreate = nullptr;
mpCreatePV = nullptr;
}
}
}
}
return bRet;
}
bool SdrCreateView::BegCreateObj(const Point& rPnt, OutputDevice* pOut, short nMinMov)
{
return ImpBegCreateObj(mnCurrentInvent,mnCurrentIdent,rPnt,pOut,nMinMov,tools::Rectangle(), nullptr);
}
bool SdrCreateView::BegCreatePreparedObject(const Point& rPnt, sal_Int16 nMinMov, SdrObject* pPreparedFactoryObject)
{
SdrInventor nInvent(mnCurrentInvent);
SdrObjKind nIdent(mnCurrentIdent);
if(pPreparedFactoryObject)
{
nInvent = pPreparedFactoryObject->GetObjInventor();
nIdent = pPreparedFactoryObject->GetObjIdentifier();
}
return ImpBegCreateObj(nInvent, nIdent, rPnt, nullptr, nMinMov, tools::Rectangle(), pPreparedFactoryObject);
}
bool SdrCreateView::BegCreateCaptionObj(const Point& rPnt, const Size& rObjSiz,
OutputDevice* pOut, short nMinMov)
{
return ImpBegCreateObj(SdrInventor::Default,SdrObjKind::Caption,rPnt,pOut,nMinMov,
tools::Rectangle(rPnt,Size(rObjSiz.Width()+1,rObjSiz.Height()+1)), nullptr);
}
void SdrCreateView::MovCreateObj(const Point& rPnt)
{
if (mpCurrentCreate==nullptr)
return;
Point aPnt(rPnt);
if (!maDragStat.IsNoSnap())
{
aPnt=GetSnapPos(aPnt, mpCreatePV);
}
if (IsOrtho())
{
if (maDragStat.IsOrtho8Possible()) OrthoDistance8(maDragStat.GetPrev(),aPnt,IsBigOrtho());
else if (maDragStat.IsOrtho4Possible()) OrthoDistance4(maDragStat.GetPrev(),aPnt,IsBigOrtho());
}
// If the drag point was limited and Ortho is active, do
// the small ortho correction (reduction) -> last parameter to FALSE.
bool bDidLimit(ImpLimitToWorkArea(aPnt));
if(bDidLimit && IsOrtho())
{
if(maDragStat.IsOrtho8Possible())
OrthoDistance8(maDragStat.GetPrev(), aPnt, false);
else if(maDragStat.IsOrtho4Possible())
OrthoDistance4(maDragStat.GetPrev(), aPnt, false);
}
if (aPnt==maDragStat.GetNow()) return;
bool bIsMinMoved(maDragStat.IsMinMoved());
if (!maDragStat.CheckMinMoved(aPnt))
return;
if (!bIsMinMoved) maDragStat.NextPoint();
maDragStat.NextMove(aPnt);
mpCurrentCreate->MovCreate(maDragStat);
// MovCreate changes the object, so use ActionChanged() on it
mpCurrentCreate->ActionChanged();
// replace for DrawCreateObjDiff
HideCreateObj();
ShowCreateObj();
}
void SdrCreateView::SetupObjLayer(const SdrPageView* pPageView, const OUString& aActiveLayer, SdrObject* pObj)
{
const SdrLayerAdmin& rAd = pPageView->GetPage()->GetLayerAdmin();
SdrLayerID nLayer(0);
// #i72535#
if(dynamic_cast<const FmFormObj*>( pObj) != nullptr)
{
// for FormControls, force to form layer
nLayer = rAd.GetLayerID(rAd.GetControlLayerName());
}
else
{
nLayer = rAd.GetLayerID(aActiveLayer);
}
if(SDRLAYER_NOTFOUND == nLayer)
{
nLayer = SdrLayerID(0);
}
pObj->SetLayer(nLayer);
}
bool SdrCreateView::EndCreateObj(SdrCreateCmd eCmd)
{
bool bRet=false;
SdrObject* pObjCreated=mpCurrentCreate.get();
if (mpCurrentCreate!=nullptr)
{
sal_uInt32 nCount=maDragStat.GetPointCount();
if (nCount<=1 && eCmd==SdrCreateCmd::ForceEnd)
{
BrkCreateObj(); // objects with only a single point don't exist (at least today)
return false; // sal_False = event not interpreted
}
bool bPntsEq=nCount>1;
sal_uInt32 i=1;
Point aP0=maDragStat.GetPoint(0);
while (bPntsEq && i<nCount) { bPntsEq=aP0==maDragStat.GetPoint(i); i++; }
if (mpCurrentCreate->EndCreate(maDragStat,eCmd))
{
HideCreateObj();
if (!bPntsEq)
{
// otherwise Brk, because all points are equal
rtl::Reference<SdrObject> pObj = std::move(mpCurrentCreate);
SetupObjLayer(mpCreatePV, maActualLayer, pObj.get());
// recognize creation of a new 3D object inside a 3D scene
bool bSceneIntoScene(false);
E3dScene* pObjScene = DynCastE3dScene(pObjCreated);
E3dScene* pCurrentScene = pObjScene ? DynCastE3dScene(mpCreatePV->GetCurrentGroup()) : nullptr;
if (pCurrentScene)
{
bool bDidInsert = static_cast<E3dView*>(this)->ImpCloneAll3DObjectsToDestScene(
pObjScene, pCurrentScene, Point(0, 0));
if(bDidInsert)
{
pObjCreated = nullptr;
bSceneIntoScene = true;
}
}
if(!bSceneIntoScene)
{
// Here an interactively created SdrObject gets added, so
// take into account that interaction created an object in
// model coordinates. If we have e.g. a GirdOffset, this is a
// little bit tricky - we have an object in model coordinates,
// so the fetched offset is at the wrong point in principle
// since we need to 'substract' the offset here to get to
// 'real' model coordinates. But we have nothing better here,
// so go for it.
// The 2nd a little tricky thing is that this will early-create
// a ViewObjectContact for the new SdrObject, but these VOCs
// are anyways layouted for being create-on-demand. This will
// be adapted/replaced correctly later on.
// This *should* be the right place for getting all interactively
// created objects, see InsertObjectAtView below that calls
// CreateUndoNewObject.
basegfx::B2DVector aGridOffset(0.0, 0.0);
if(getPossibleGridOffsetForSdrObject(aGridOffset, pObj.get(), mpCreatePV))
{
const Size aOffset(
basegfx::fround(-aGridOffset.getX()),
basegfx::fround(-aGridOffset.getY()));
pObj->NbcMove(aOffset);
}
// do the same as before
InsertObjectAtView(pObj.get(), *mpCreatePV);
}
mpCreatePV = nullptr;
bRet=true; // sal_True = event interpreted
}
else
{
BrkCreateObj();
}
}
else
{ // more points
if (eCmd==SdrCreateCmd::ForceEnd || // nothing there -- force ending
nCount==0 || // no existing points (should never happen)
(nCount<=1 && !maDragStat.IsMinMoved())) { // MinMove not met
BrkCreateObj();
}
else
{
// replace for DrawCreateObjDiff
HideCreateObj();
ShowCreateObj();
maDragStat.ResetMinMoved(); // NextPoint is at MovCreateObj()
bRet=true;
}
}
}
return bRet;
}
void SdrCreateView::BckCreateObj()
{
if (mpCurrentCreate==nullptr)
return;
if (maDragStat.GetPointCount()<=2 )
{
BrkCreateObj();
}
else
{
HideCreateObj();
maDragStat.PrevPoint();
if (mpCurrentCreate->BckCreate(maDragStat))
{
ShowCreateObj();
}
else
{
BrkCreateObj();
}
}
}
void SdrCreateView::BrkCreateObj()
{
if (mpCurrentCreate!=nullptr)
{
HideCreateObj();
mpCurrentCreate->BrkCreate(maDragStat);
mpCurrentCreate = nullptr;
mpCreatePV = nullptr;
}
}
void SdrCreateView::ShowCreateObj(/*OutputDevice* pOut, sal_Bool bFull*/)
{
if(!IsCreateObj() || maDragStat.IsShown())
return;
if (mpCurrentCreate)
{
// for migration from XOR, replace DrawDragObj here to create
// overlay objects instead.
bool bUseSolidDragging(IsSolidDragging());
// #i101648# check if dragged object is a naked SdrObject (not
// a derivation). This is e.g. used in SW Frame construction
// as placeholder. Do not use SolidDragging for naked SdrObjects,
// they cannot have a valid optical representation
if(bUseSolidDragging && SdrObjKind::NONE == mpCurrentCreate->GetObjIdentifier())
{
bUseSolidDragging = false;
}
// check for objects with no fill and no line
if(bUseSolidDragging)
{
const SfxItemSet& rSet = mpCurrentCreate->GetMergedItemSet();
const drawing::FillStyle eFill(rSet.Get(XATTR_FILLSTYLE).GetValue());
const drawing::LineStyle eLine(rSet.Get(XATTR_LINESTYLE).GetValue());
if(drawing::LineStyle_NONE == eLine && drawing::FillStyle_NONE == eFill)
{
bUseSolidDragging = false;
}
}
// check for form controls
if(bUseSolidDragging)
{
if (dynamic_cast<const SdrUnoObj*>(mpCurrentCreate.get()) != nullptr)
{
bUseSolidDragging = false;
}
}
// #i101781# force to non-solid dragging when not creating a full circle
if(bUseSolidDragging)
{
SdrCircObj* pCircObj = dynamic_cast<SdrCircObj*>(mpCurrentCreate.get());
if(pCircObj && SdrObjKind::CircleOrEllipse != pCircObj->GetObjIdentifier())
{
// #i103058# Allow SolidDragging with four points
if(maDragStat.GetPointCount() < 4)
{
bUseSolidDragging = false;
}
}
}
if(bUseSolidDragging)
{
basegfx::B2DPolyPolygon aDragPolyPolygon;
if (dynamic_cast<const SdrRectObj*>(mpCurrentCreate.get()) != nullptr)
{
// ensure object has some size, necessary for SdrTextObj because
// there are still untested divisions by that sizes
tools::Rectangle aCurrentSnapRect(mpCurrentCreate->GetSnapRect());
if(aCurrentSnapRect.GetWidth() <= 1 || aCurrentSnapRect.GetHeight() <= 1)
{
tools::Rectangle aNewRect(maDragStat.GetStart(), maDragStat.GetStart() + Point(2, 2));
mpCurrentCreate->NbcSetSnapRect(aNewRect);
}
}
if (auto pPathObj = dynamic_cast<SdrPathObj*>(mpCurrentCreate.get()))
{
// The up-to-now created path needs to be set at the object to have something
// that can be visualized
const basegfx::B2DPolyPolygon aCurrentPolyPolygon(pPathObj->getObjectPolyPolygon(maDragStat));
if(aCurrentPolyPolygon.count())
{
pPathObj->NbcSetPathPoly(aCurrentPolyPolygon);
}
aDragPolyPolygon = pPathObj->getDragPolyPolygon(maDragStat);
}
// use the SdrObject directly for overlay
mpCreateViewExtraData->CreateAndShowOverlay(*this, mpCurrentCreate.get(), aDragPolyPolygon);
}
else
{
const ::basegfx::B2DPolyPolygon aPoly(mpCurrentCreate->TakeCreatePoly(maDragStat));
mpCreateViewExtraData->CreateAndShowOverlay(*this, nullptr, aPoly);
}
// #i101679# Force changed overlay to be shown
for(sal_uInt32 a(0); a < PaintWindowCount(); a++)
{
SdrPaintWindow* pCandidate = GetPaintWindow(a);
const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager = pCandidate->GetOverlayManager();
if (xOverlayManager.is())
{
xOverlayManager->flush();
}
}
}
maDragStat.SetShown(true);
}
void SdrCreateView::HideCreateObj()
{
if(IsCreateObj() && maDragStat.IsShown())
{
// for migration from XOR, replace DrawDragObj here to create
// overlay objects instead.
mpCreateViewExtraData->HideOverlay();
//DrawCreateObj(pOut,bFull);
maDragStat.SetShown(false);
}
}
void SdrCreateView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
{
if (mpCurrentCreate)
{
rTargetSet.Put(mpCurrentCreate->GetMergedItemSet());
}
else
{
SdrDragView::GetAttributes(rTargetSet, bOnlyHardAttr);
}
}
bool SdrCreateView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
{
if (mpCurrentCreate)
{
mpCurrentCreate->SetMergedItemSetAndBroadcast(rSet, bReplaceAll);
return true;
}
else
{
return SdrDragView::SetAttributes(rSet,bReplaceAll);
}
}
SfxStyleSheet* SdrCreateView::GetStyleSheet() const
{
if (mpCurrentCreate != nullptr)
{
return mpCurrentCreate->GetStyleSheet();
}
else
{
return SdrDragView::GetStyleSheet();
}
}
void SdrCreateView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
{
if (mpCurrentCreate != nullptr)
{
mpCurrentCreate->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
}
else
{
SdrDragView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */