Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / svdraw / svdcrtv.cxx
blob3a27e56694c74bbd0fca28ac22516dfc57175729
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <svx/svdcrtv.hxx>
22 #include <svx/xlnclit.hxx>
23 #include <svx/svdocapt.hxx>
24 #include <svx/svdoedge.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/scene3d.hxx>
28 #include <svx/view3d.hxx>
29 #include <svx/xfillit0.hxx>
30 #include <svx/xflclit.hxx>
31 #include <svx/xlineit0.hxx>
32 #include <svx/svdouno.hxx>
33 #include <svx/svdopath.hxx>
34 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
35 #include <svx/sdr/overlay/overlaymanager.hxx>
36 #include <svx/sdrpaintwindow.hxx>
37 #include <fmobj.hxx>
38 #include <svx/svdocirc.hxx>
39 #include <svx/sdr/contact/viewcontact.hxx>
40 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
41 #include <vcl/ptrstyle.hxx>
43 using namespace com::sun::star;
45 class ImplConnectMarkerOverlay
47 // The OverlayObjects
48 sdr::overlay::OverlayObjectList maObjects;
50 // The remembered target object
51 const SdrObject& mrObject;
53 public:
54 ImplConnectMarkerOverlay(const SdrCreateView& rView, SdrObject const & rObject);
56 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
57 // That destructor calls clear() at the list which removes all objects from the
58 // OverlayManager and deletes them.
60 const SdrObject& GetTargetObject() const { return mrObject; }
63 ImplConnectMarkerOverlay::ImplConnectMarkerOverlay(const SdrCreateView& rView, SdrObject const & rObject)
64 : mrObject(rObject)
66 basegfx::B2DPolyPolygon aB2DPolyPolygon(rObject.TakeXorPoly());
68 for(sal_uInt32 a(0); a < rView.PaintWindowCount(); a++)
70 SdrPaintWindow* pCandidate = rView.GetPaintWindow(a);
71 const rtl::Reference< sdr::overlay::OverlayManager >& xTargetOverlay = pCandidate->GetOverlayManager();
73 if(xTargetOverlay.is())
75 float fScalingFactor = xTargetOverlay->getOutputDevice().GetDPIScaleFactor();
76 Size aHalfLogicSize(xTargetOverlay->getOutputDevice().PixelToLogic(Size(4 * fScalingFactor, 4 * fScalingFactor)));
78 // object
79 std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
80 aB2DPolyPolygon));
81 xTargetOverlay->add(*pNew);
82 maObjects.append(std::move(pNew));
84 // gluepoints
85 for(sal_uInt16 i(0); i < 4; i++)
87 SdrGluePoint aGluePoint(rObject.GetVertexGluePoint(i));
88 const Point& rPosition = aGluePoint.GetAbsolutePos(rObject);
90 basegfx::B2DPoint aTopLeft(rPosition.X() - aHalfLogicSize.Width(), rPosition.Y() - aHalfLogicSize.Height());
91 basegfx::B2DPoint aBottomRight(rPosition.X() + aHalfLogicSize.Width(), rPosition.Y() + aHalfLogicSize.Height());
93 basegfx::B2DPolygon aTempPoly;
94 aTempPoly.append(aTopLeft);
95 aTempPoly.append(basegfx::B2DPoint(aBottomRight.getX(), aTopLeft.getY()));
96 aTempPoly.append(aBottomRight);
97 aTempPoly.append(basegfx::B2DPoint(aTopLeft.getX(), aBottomRight.getY()));
98 aTempPoly.setClosed(true);
100 basegfx::B2DPolyPolygon aTempPolyPoly;
101 aTempPolyPoly.append(aTempPoly);
103 std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew2(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
104 std::move(aTempPolyPoly)));
105 xTargetOverlay->add(*pNew2);
106 maObjects.append(std::move(pNew2));
112 class ImpSdrCreateViewExtraData
114 // The OverlayObjects for XOR replacement
115 sdr::overlay::OverlayObjectList maObjects;
117 public:
118 ImpSdrCreateViewExtraData();
119 ~ImpSdrCreateViewExtraData();
121 void CreateAndShowOverlay(const SdrCreateView& rView, const SdrObject* pObject, const basegfx::B2DPolyPolygon& rPolyPoly);
122 void HideOverlay();
125 ImpSdrCreateViewExtraData::ImpSdrCreateViewExtraData()
129 ImpSdrCreateViewExtraData::~ImpSdrCreateViewExtraData()
131 HideOverlay();
134 void ImpSdrCreateViewExtraData::CreateAndShowOverlay(const SdrCreateView& rView, const SdrObject* pObject, const basegfx::B2DPolyPolygon& rPolyPoly)
136 for(sal_uInt32 a(0); a < rView.PaintWindowCount(); a++)
138 SdrPaintWindow* pCandidate = rView.GetPaintWindow(a);
139 const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager = pCandidate->GetOverlayManager();
141 if (xOverlayManager.is())
143 if(pObject)
145 const sdr::contact::ViewContact& rVC = pObject->GetViewContact();
146 drawinglayer::primitive2d::Primitive2DContainer aSequence;
147 rVC.getViewIndependentPrimitive2DContainer(aSequence);
148 std::unique_ptr<sdr::overlay::OverlayObject> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(std::move(aSequence)));
150 xOverlayManager->add(*pNew);
151 maObjects.append(std::move(pNew));
154 if(rPolyPoly.count())
156 std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
157 rPolyPoly));
158 xOverlayManager->add(*pNew);
159 maObjects.append(std::move(pNew));
165 void ImpSdrCreateViewExtraData::HideOverlay()
167 // the clear() call of the list removes all objects from the
168 // OverlayManager and deletes them.
169 maObjects.clear();
173 // CreateView
176 void SdrCreateView::ImpClearConnectMarker()
178 mpCoMaOverlay.reset();
181 SdrCreateView::SdrCreateView(SdrModel& rSdrModel, OutputDevice* pOut)
182 : SdrDragView(rSdrModel, pOut)
183 , mpCreatePV(nullptr)
184 , mpCreateViewExtraData(new ImpSdrCreateViewExtraData())
185 , maCurrentCreatePointer(PointerStyle::Cross)
186 , mnAutoCloseDistPix(5)
187 , mnFreeHandMinDistPix(10)
188 , mnCurrentInvent(SdrInventor::Default)
189 , mnCurrentIdent(SdrObjKind::NONE)
190 , mb1stPointAsCenter(false)
191 , mbUseIncompatiblePathCreateInterface(false)
195 SdrCreateView::~SdrCreateView()
197 ImpClearConnectMarker();
198 mpCreateViewExtraData.reset();
201 bool SdrCreateView::IsAction() const
203 return SdrDragView::IsAction() || mpCurrentCreate!=nullptr;
206 void SdrCreateView::MovAction(const Point& rPnt)
208 SdrDragView::MovAction(rPnt);
209 if (mpCurrentCreate != nullptr) {
210 MovCreateObj(rPnt);
214 void SdrCreateView::EndAction()
216 if (mpCurrentCreate != nullptr) EndCreateObj(SdrCreateCmd::ForceEnd);
217 SdrDragView::EndAction();
220 void SdrCreateView::BckAction()
222 if (mpCurrentCreate != nullptr) BckCreateObj();
223 SdrDragView::BckAction();
226 void SdrCreateView::BrkAction()
228 SdrDragView::BrkAction();
229 BrkCreateObj();
232 void SdrCreateView::TakeActionRect(tools::Rectangle& rRect) const
234 if (mpCurrentCreate != nullptr)
236 rRect=maDragStat.GetActionRect();
237 if (rRect.IsEmpty())
239 rRect=tools::Rectangle(maDragStat.GetPrev(),maDragStat.GetNow());
242 else
244 SdrDragView::TakeActionRect(rRect);
248 bool SdrCreateView::CheckEdgeMode()
250 if (mpCurrentCreate != nullptr)
252 // is managed by EdgeObj
253 if (mnCurrentInvent==SdrInventor::Default && mnCurrentIdent==SdrObjKind::Edge) return false;
256 if (!IsCreateMode() || mnCurrentInvent!=SdrInventor::Default || mnCurrentIdent!=SdrObjKind::Edge)
258 ImpClearConnectMarker();
259 return false;
261 else
263 // sal_True, if MouseMove should check Connect
264 return !IsAction();
268 void SdrCreateView::SetConnectMarker(const SdrObjConnection& rCon)
270 SdrObject* pTargetObject = rCon.pObj;
272 if(pTargetObject)
274 // if target object changes, throw away overlay object to make room for changes
275 if(mpCoMaOverlay && pTargetObject != &mpCoMaOverlay->GetTargetObject())
277 ImpClearConnectMarker();
280 if(!mpCoMaOverlay)
282 mpCoMaOverlay.reset(new ImplConnectMarkerOverlay(*this, *pTargetObject));
285 else
287 ImpClearConnectMarker();
291 void SdrCreateView::HideConnectMarker()
293 ImpClearConnectMarker();
296 bool SdrCreateView::MouseMove(const MouseEvent& rMEvt, OutputDevice* pWin)
298 if(CheckEdgeMode() && pWin)
300 SdrPageView* pPV = GetSdrPageView();
302 if(pPV)
304 // TODO: Change default hit tolerance at IsMarkedHit() some time!
305 Point aPos(pWin->PixelToLogic(rMEvt.GetPosPixel()));
306 bool bMarkHit=PickHandle(aPos)!=nullptr || IsMarkedObjHit(aPos);
307 SdrObjConnection aCon;
308 if (!bMarkHit) SdrEdgeObj::ImpFindConnector(aPos,*pPV,aCon,nullptr,pWin);
309 SetConnectMarker(aCon);
312 return SdrDragView::MouseMove(rMEvt,pWin);
315 bool SdrCreateView::IsTextTool() const
317 return meEditMode==SdrViewEditMode::Create
318 && mnCurrentInvent==SdrInventor::Default
319 && (mnCurrentIdent==SdrObjKind::Text
320 || mnCurrentIdent==SdrObjKind::TitleText
321 || mnCurrentIdent==SdrObjKind::OutlineText);
324 bool SdrCreateView::IsEdgeTool() const
326 return meEditMode==SdrViewEditMode::Create && mnCurrentInvent==SdrInventor::Default && (mnCurrentIdent==SdrObjKind::Edge);
329 bool SdrCreateView::IsMeasureTool() const
331 return meEditMode==SdrViewEditMode::Create && mnCurrentInvent==SdrInventor::Default && (mnCurrentIdent==SdrObjKind::Measure);
334 void SdrCreateView::SetCurrentObj(SdrObjKind nIdent, SdrInventor nInvent)
336 if (mnCurrentInvent!=nInvent || mnCurrentIdent!=nIdent)
338 mnCurrentInvent=nInvent;
339 mnCurrentIdent=nIdent;
340 rtl::Reference<SdrObject> pObj = (nIdent == SdrObjKind::NONE) ? nullptr :
341 SdrObjFactory::MakeNewObject(
342 GetModel(),
343 nInvent,
344 nIdent);
346 if(pObj)
348 // Using text tool, mouse cursor is usually I-Beam,
349 // crosshairs with tiny I-Beam appears only on MouseButtonDown.
350 if(IsTextTool())
352 // Here the correct pointer needs to be used
353 // if the default is set to vertical writing
354 maCurrentCreatePointer = PointerStyle::Text;
356 else
357 maCurrentCreatePointer = pObj->GetCreatePointer();
359 else
361 maCurrentCreatePointer = PointerStyle::Cross;
365 CheckEdgeMode();
366 ImpSetGlueVisible3(IsEdgeTool());
369 bool SdrCreateView::ImpBegCreateObj(SdrInventor nInvent, SdrObjKind nIdent, const Point& rPnt, OutputDevice* pOut,
370 sal_Int16 nMinMov, const tools::Rectangle& rLogRect, SdrObject* pPreparedFactoryObject)
372 bool bRet=false;
373 UnmarkAllObj();
374 BrkAction();
376 ImpClearConnectMarker();
378 mpCreatePV = GetSdrPageView();
380 if (mpCreatePV != nullptr)
381 { // otherwise no side registered!
382 OUString aLay(maActualLayer);
384 if(nInvent == SdrInventor::Default && nIdent == SdrObjKind::Measure && !maMeasureLayer.isEmpty())
386 aLay = maMeasureLayer;
389 SdrLayerID nLayer = mpCreatePV->GetPage()->GetLayerAdmin().GetLayerID(aLay);
390 if (nLayer==SDRLAYER_NOTFOUND) nLayer = SdrLayerID(0);
391 if (!mpCreatePV->GetLockedLayers().IsSet(nLayer) && mpCreatePV->GetVisibleLayers().IsSet(nLayer))
393 if(pPreparedFactoryObject)
395 mpCurrentCreate = pPreparedFactoryObject;
397 else
399 mpCurrentCreate = SdrObjFactory::MakeNewObject(
400 GetModel(), nInvent, nIdent);
403 Point aPnt(rPnt);
404 if (mnCurrentInvent != SdrInventor::Default || (mnCurrentIdent != SdrObjKind::Edge &&
405 mnCurrentIdent != SdrObjKind::FreehandLine &&
406 mnCurrentIdent != SdrObjKind::FreehandFill )) { // no snapping for Edge and Freehand
407 aPnt=GetSnapPos(aPnt, mpCreatePV);
409 if (mpCurrentCreate!=nullptr)
411 if (mpDefaultStyleSheet!=nullptr) mpCurrentCreate->NbcSetStyleSheet(mpDefaultStyleSheet, false);
413 // SW uses a naked SdrObject for frame construction. Normally, such an
414 // object should not be created. Since it is possible to use it as a helper
415 // object (e.g. in letting the user define an area with the interactive
416 // construction) at least no items should be set at that object.
417 if(nInvent != SdrInventor::Default || nIdent != SdrObjKind::NewFrame)
419 mpCurrentCreate->SetMergedItemSet(maDefaultAttr);
422 if (dynamic_cast<const SdrCaptionObj *>(mpCurrentCreate.get()) != nullptr)
424 SfxItemSet aSet(GetModel().GetItemPool());
425 aSet.Put(XFillColorItem(OUString(),COL_WHITE)); // in case someone turns on Solid
426 aSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
428 mpCurrentCreate->SetMergedItemSet(aSet);
430 if (nInvent == SdrInventor::Default && (nIdent==SdrObjKind::Text || nIdent==SdrObjKind::TitleText || nIdent==SdrObjKind::OutlineText))
432 // default for all text frames: no background, no border
433 SfxItemSet aSet(GetModel().GetItemPool());
434 aSet.Put(XFillColorItem(OUString(),COL_WHITE)); // in case someone turns on Solid
435 aSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
436 aSet.Put(XLineColorItem(OUString(),COL_BLACK)); // in case someone turns on Solid
437 aSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
439 mpCurrentCreate->SetMergedItemSet(aSet);
441 if (!rLogRect.IsEmpty()) mpCurrentCreate->NbcSetLogicRect(rLogRect);
443 // make sure drag start point is inside WorkArea
444 const tools::Rectangle& rWorkArea = GetWorkArea();
446 if(!rWorkArea.IsEmpty())
448 if(aPnt.X() < rWorkArea.Left())
450 aPnt.setX( rWorkArea.Left() );
453 if(aPnt.X() > rWorkArea.Right())
455 aPnt.setX( rWorkArea.Right() );
458 if(aPnt.Y() < rWorkArea.Top())
460 aPnt.setY( rWorkArea.Top() );
463 if(aPnt.Y() > rWorkArea.Bottom())
465 aPnt.setY( rWorkArea.Bottom() );
469 maDragStat.Reset(aPnt);
470 maDragStat.SetView(static_cast<SdrView*>(this));
471 maDragStat.SetPageView(mpCreatePV);
472 maDragStat.SetMinMove(ImpGetMinMovLogic(nMinMov,pOut));
473 mpDragWin=pOut;
474 if (mpCurrentCreate->BegCreate(maDragStat))
476 ShowCreateObj(/*pOut,sal_True*/);
477 bRet=true;
479 else
481 mpCurrentCreate = nullptr;
482 mpCreatePV = nullptr;
487 return bRet;
490 bool SdrCreateView::BegCreateObj(const Point& rPnt, OutputDevice* pOut, short nMinMov)
492 return ImpBegCreateObj(mnCurrentInvent,mnCurrentIdent,rPnt,pOut,nMinMov,tools::Rectangle(), nullptr);
495 bool SdrCreateView::BegCreatePreparedObject(const Point& rPnt, sal_Int16 nMinMov, SdrObject* pPreparedFactoryObject)
497 SdrInventor nInvent(mnCurrentInvent);
498 SdrObjKind nIdent(mnCurrentIdent);
500 if(pPreparedFactoryObject)
502 nInvent = pPreparedFactoryObject->GetObjInventor();
503 nIdent = pPreparedFactoryObject->GetObjIdentifier();
506 return ImpBegCreateObj(nInvent, nIdent, rPnt, nullptr, nMinMov, tools::Rectangle(), pPreparedFactoryObject);
509 bool SdrCreateView::BegCreateCaptionObj(const Point& rPnt, const Size& rObjSiz,
510 OutputDevice* pOut, short nMinMov)
512 return ImpBegCreateObj(SdrInventor::Default,SdrObjKind::Caption,rPnt,pOut,nMinMov,
513 tools::Rectangle(rPnt,Size(rObjSiz.Width()+1,rObjSiz.Height()+1)), nullptr);
516 void SdrCreateView::MovCreateObj(const Point& rPnt)
518 if (mpCurrentCreate==nullptr)
519 return;
521 Point aPnt(rPnt);
522 if (!maDragStat.IsNoSnap())
524 aPnt=GetSnapPos(aPnt, mpCreatePV);
526 if (IsOrtho())
528 if (maDragStat.IsOrtho8Possible()) OrthoDistance8(maDragStat.GetPrev(),aPnt,IsBigOrtho());
529 else if (maDragStat.IsOrtho4Possible()) OrthoDistance4(maDragStat.GetPrev(),aPnt,IsBigOrtho());
532 // If the drag point was limited and Ortho is active, do
533 // the small ortho correction (reduction) -> last parameter to FALSE.
534 bool bDidLimit(ImpLimitToWorkArea(aPnt));
535 if(bDidLimit && IsOrtho())
537 if(maDragStat.IsOrtho8Possible())
538 OrthoDistance8(maDragStat.GetPrev(), aPnt, false);
539 else if(maDragStat.IsOrtho4Possible())
540 OrthoDistance4(maDragStat.GetPrev(), aPnt, false);
543 if (aPnt==maDragStat.GetNow()) return;
544 bool bIsMinMoved(maDragStat.IsMinMoved());
545 if (!maDragStat.CheckMinMoved(aPnt))
546 return;
548 if (!bIsMinMoved) maDragStat.NextPoint();
549 maDragStat.NextMove(aPnt);
550 mpCurrentCreate->MovCreate(maDragStat);
552 // MovCreate changes the object, so use ActionChanged() on it
553 mpCurrentCreate->ActionChanged();
555 // replace for DrawCreateObjDiff
556 HideCreateObj();
557 ShowCreateObj();
560 void SdrCreateView::SetupObjLayer(const SdrPageView* pPageView, const OUString& aActiveLayer, SdrObject* pObj)
562 const SdrLayerAdmin& rAd = pPageView->GetPage()->GetLayerAdmin();
563 SdrLayerID nLayer(0);
565 // #i72535#
566 if(dynamic_cast<const FmFormObj*>( pObj) != nullptr)
568 // for FormControls, force to form layer
569 nLayer = rAd.GetLayerID(rAd.GetControlLayerName());
571 else
573 nLayer = rAd.GetLayerID(aActiveLayer);
576 if(SDRLAYER_NOTFOUND == nLayer)
578 nLayer = SdrLayerID(0);
581 pObj->SetLayer(nLayer);
584 bool SdrCreateView::EndCreateObj(SdrCreateCmd eCmd)
586 bool bRet=false;
587 SdrObject* pObjCreated=mpCurrentCreate.get();
589 if (mpCurrentCreate!=nullptr)
591 sal_uInt32 nCount=maDragStat.GetPointCount();
593 if (nCount<=1 && eCmd==SdrCreateCmd::ForceEnd)
595 BrkCreateObj(); // objects with only a single point don't exist (at least today)
596 return false; // sal_False = event not interpreted
599 bool bPntsEq=nCount>1;
600 sal_uInt32 i=1;
601 Point aP0=maDragStat.GetPoint(0);
602 while (bPntsEq && i<nCount) { bPntsEq=aP0==maDragStat.GetPoint(i); i++; }
604 if (mpCurrentCreate->EndCreate(maDragStat,eCmd))
606 HideCreateObj();
608 if (!bPntsEq)
610 // otherwise Brk, because all points are equal
611 rtl::Reference<SdrObject> pObj = std::move(mpCurrentCreate);
613 SetupObjLayer(mpCreatePV, maActualLayer, pObj.get());
615 // recognize creation of a new 3D object inside a 3D scene
616 bool bSceneIntoScene(false);
618 E3dScene* pObjScene = DynCastE3dScene(pObjCreated);
619 E3dScene* pCurrentScene = pObjScene ? DynCastE3dScene(mpCreatePV->GetCurrentGroup()) : nullptr;
620 if (pCurrentScene)
622 bool bDidInsert = static_cast<E3dView*>(this)->ImpCloneAll3DObjectsToDestScene(
623 pObjScene, pCurrentScene, Point(0, 0));
625 if(bDidInsert)
627 pObjCreated = nullptr;
628 bSceneIntoScene = true;
632 if(!bSceneIntoScene)
634 // Here an interactively created SdrObject gets added, so
635 // take into account that interaction created an object in
636 // model coordinates. If we have e.g. a GirdOffset, this is a
637 // little bit tricky - we have an object in model coordinates,
638 // so the fetched offset is at the wrong point in principle
639 // since we need to 'substract' the offset here to get to
640 // 'real' model coordinates. But we have nothing better here,
641 // so go for it.
642 // The 2nd a little tricky thing is that this will early-create
643 // a ViewObjectContact for the new SdrObject, but these VOCs
644 // are anyways layouted for being create-on-demand. This will
645 // be adapted/replaced correctly later on.
646 // This *should* be the right place for getting all interactively
647 // created objects, see InsertObjectAtView below that calls
648 // CreateUndoNewObject.
649 basegfx::B2DVector aGridOffset(0.0, 0.0);
650 if(getPossibleGridOffsetForSdrObject(aGridOffset, pObj.get(), mpCreatePV))
652 const Size aOffset(
653 basegfx::fround(-aGridOffset.getX()),
654 basegfx::fround(-aGridOffset.getY()));
656 pObj->NbcMove(aOffset);
659 // do the same as before
660 InsertObjectAtView(pObj.get(), *mpCreatePV);
663 mpCreatePV = nullptr;
664 bRet=true; // sal_True = event interpreted
666 else
668 BrkCreateObj();
671 else
672 { // more points
673 if (eCmd==SdrCreateCmd::ForceEnd || // nothing there -- force ending
674 nCount==0 || // no existing points (should never happen)
675 (nCount<=1 && !maDragStat.IsMinMoved())) { // MinMove not met
676 BrkCreateObj();
678 else
680 // replace for DrawCreateObjDiff
681 HideCreateObj();
682 ShowCreateObj();
683 maDragStat.ResetMinMoved(); // NextPoint is at MovCreateObj()
684 bRet=true;
688 return bRet;
691 void SdrCreateView::BckCreateObj()
693 if (mpCurrentCreate==nullptr)
694 return;
696 if (maDragStat.GetPointCount()<=2 )
698 BrkCreateObj();
700 else
702 HideCreateObj();
703 maDragStat.PrevPoint();
704 if (mpCurrentCreate->BckCreate(maDragStat))
706 ShowCreateObj();
708 else
710 BrkCreateObj();
715 void SdrCreateView::BrkCreateObj()
717 if (mpCurrentCreate!=nullptr)
719 HideCreateObj();
720 mpCurrentCreate->BrkCreate(maDragStat);
721 mpCurrentCreate = nullptr;
722 mpCreatePV = nullptr;
726 void SdrCreateView::ShowCreateObj(/*OutputDevice* pOut, sal_Bool bFull*/)
728 if(!IsCreateObj() || maDragStat.IsShown())
729 return;
731 if (mpCurrentCreate)
733 // for migration from XOR, replace DrawDragObj here to create
734 // overlay objects instead.
735 bool bUseSolidDragging(IsSolidDragging());
737 // #i101648# check if dragged object is a SdrObjKind::NewFrame.
738 // This is e.g. used in SW Frame construction as placeholder.
739 // Do not use SolidDragging for SdrObjKind::NewFrame kind of objects,
740 // they cannot have a valid optical representation.
741 if (bUseSolidDragging && SdrObjKind::NewFrame == mpCurrentCreate->GetObjIdentifier())
743 bUseSolidDragging = false;
746 // check for objects with no fill and no line
747 if(bUseSolidDragging)
749 const SfxItemSet& rSet = mpCurrentCreate->GetMergedItemSet();
750 const drawing::FillStyle eFill(rSet.Get(XATTR_FILLSTYLE).GetValue());
751 const drawing::LineStyle eLine(rSet.Get(XATTR_LINESTYLE).GetValue());
753 if(drawing::LineStyle_NONE == eLine && drawing::FillStyle_NONE == eFill)
755 bUseSolidDragging = false;
759 // check for form controls
760 if(bUseSolidDragging)
762 if (dynamic_cast<const SdrUnoObj*>(mpCurrentCreate.get()) != nullptr)
764 bUseSolidDragging = false;
768 // #i101781# force to non-solid dragging when not creating a full circle
769 if(bUseSolidDragging)
771 SdrCircObj* pCircObj = dynamic_cast<SdrCircObj*>(mpCurrentCreate.get());
773 if(pCircObj && SdrObjKind::CircleOrEllipse != pCircObj->GetObjIdentifier())
775 // #i103058# Allow SolidDragging with four points
776 if(maDragStat.GetPointCount() < 4)
778 bUseSolidDragging = false;
783 if(bUseSolidDragging)
785 basegfx::B2DPolyPolygon aDragPolyPolygon;
787 if (dynamic_cast<const SdrRectObj*>(mpCurrentCreate.get()) != nullptr)
789 // ensure object has some size, necessary for SdrTextObj because
790 // there are still untested divisions by that sizes
791 tools::Rectangle aCurrentSnapRect(mpCurrentCreate->GetSnapRect());
793 if(aCurrentSnapRect.GetWidth() <= 1 || aCurrentSnapRect.GetHeight() <= 1)
795 tools::Rectangle aNewRect(maDragStat.GetStart(), maDragStat.GetStart() + Point(2, 2));
796 mpCurrentCreate->NbcSetSnapRect(aNewRect);
800 if (auto pPathObj = dynamic_cast<SdrPathObj*>(mpCurrentCreate.get()))
802 // The up-to-now created path needs to be set at the object to have something
803 // that can be visualized
804 const basegfx::B2DPolyPolygon aCurrentPolyPolygon(pPathObj->getObjectPolyPolygon(maDragStat));
806 if(aCurrentPolyPolygon.count())
808 pPathObj->NbcSetPathPoly(aCurrentPolyPolygon);
811 aDragPolyPolygon = pPathObj->getDragPolyPolygon(maDragStat);
814 // use the SdrObject directly for overlay
815 mpCreateViewExtraData->CreateAndShowOverlay(*this, mpCurrentCreate.get(), aDragPolyPolygon);
817 else
819 const ::basegfx::B2DPolyPolygon aPoly(mpCurrentCreate->TakeCreatePoly(maDragStat));
821 mpCreateViewExtraData->CreateAndShowOverlay(*this, nullptr, aPoly);
824 // #i101679# Force changed overlay to be shown
825 for(sal_uInt32 a(0); a < PaintWindowCount(); a++)
827 SdrPaintWindow* pCandidate = GetPaintWindow(a);
828 const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager = pCandidate->GetOverlayManager();
830 if (xOverlayManager.is())
832 xOverlayManager->flush();
837 maDragStat.SetShown(true);
840 void SdrCreateView::HideCreateObj()
842 if(IsCreateObj() && maDragStat.IsShown())
844 // for migration from XOR, replace DrawDragObj here to create
845 // overlay objects instead.
846 mpCreateViewExtraData->HideOverlay();
848 //DrawCreateObj(pOut,bFull);
849 maDragStat.SetShown(false);
854 void SdrCreateView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
856 if (mpCurrentCreate)
858 rTargetSet.Put(mpCurrentCreate->GetMergedItemSet());
860 else
862 SdrDragView::GetAttributes(rTargetSet, bOnlyHardAttr);
866 bool SdrCreateView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
868 if (mpCurrentCreate)
870 mpCurrentCreate->SetMergedItemSetAndBroadcast(rSet, bReplaceAll);
872 return true;
874 else
876 return SdrDragView::SetAttributes(rSet,bReplaceAll);
880 SfxStyleSheet* SdrCreateView::GetStyleSheet() const
882 if (mpCurrentCreate != nullptr)
884 return mpCurrentCreate->GetStyleSheet();
886 else
888 return SdrDragView::GetStyleSheet();
892 void SdrCreateView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
894 if (mpCurrentCreate != nullptr)
896 mpCurrentCreate->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
898 else
900 SdrDragView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
904 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */