android: Update app-specific/MIME type icons
[LibreOffice.git] / sd / source / ui / animations / motionpathtag.cxx
blob5ddcc9ac7921a05606261d5b6a49ac9042a44958
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 .
20 #include <com/sun/star/util/XChangesNotifier.hpp>
22 #include <basegfx/matrix/b2dhommatrix.hxx>
23 #include <basegfx/polygon/b2dpolygontools.hxx>
24 #include <basegfx/matrix/b2dhommatrixtools.hxx>
26 #include <sfx2/viewfrm.hxx>
27 #include <sfx2/dispatch.hxx>
29 #include <svx/svdpagv.hxx>
30 #include <svx/sdrpagewindow.hxx>
31 #include <svx/sdrpaintwindow.hxx>
32 #include <svx/svdopath.hxx>
33 #include <svx/xfillit0.hxx>
34 #include <svx/xlineit0.hxx>
35 #include <svx/xlndsit.hxx>
36 #include <svx/xlnclit.hxx>
37 #include <svx/xlnstit.hxx>
38 #include <svx/xlnedit.hxx>
39 #include <svx/xlnstwit.hxx>
40 #include <svx/xlnedwit.hxx>
41 #include <svx/xlnstcit.hxx>
42 #include <svx/xlnedcit.hxx>
43 #include <svx/xlntrit.hxx>
44 #include <svx/svxids.hrc>
45 #include <svx/polypolygoneditor.hxx>
46 #include <svx/svddrgmt.hxx>
48 #include <CustomAnimationPane.hxx>
49 #include <View.hxx>
50 #include "motionpathtag.hxx"
51 #include <ViewShell.hxx>
52 #include <Window.hxx>
54 #include <svx/sdr/contact/viewcontact.hxx>
55 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
56 #include <utility>
58 using sdr::PolyPolygonEditor;
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::lang;
62 using namespace ::com::sun::star::util;
63 using namespace ::com::sun::star::drawing;
65 namespace sd
68 const sal_uInt32 SMART_TAG_HDL_NUM = SAL_MAX_UINT32;
69 const int DRGPIX = 2; // Drag MinMove in Pixel
71 namespace {
73 class PathDragMove : public SdrDragMove
75 private:
76 basegfx::B2DPolyPolygon maPathPolyPolygon;
78 protected:
79 virtual void createSdrDragEntries() override;
81 public:
82 PathDragMove(SdrDragView& rNewView,
83 rtl::Reference <MotionPathTag > xTag,
84 basegfx::B2DPolyPolygon aPathPolyPolygon)
85 : SdrDragMove(rNewView),
86 maPathPolyPolygon(std::move(aPathPolyPolygon)),
87 mxTag(std::move( xTag ))
90 PathDragMove(SdrDragView& rNewView,
91 rtl::Reference <MotionPathTag > xTag)
92 : SdrDragMove(rNewView),
93 mxTag(std::move( xTag ))
96 virtual bool BeginSdrDrag() override;
97 virtual bool EndSdrDrag(bool bCopy) override;
99 rtl::Reference <MotionPathTag > mxTag;
104 void PathDragMove::createSdrDragEntries()
106 // call parent
107 SdrDragMove::createSdrDragEntries();
109 if(maPathPolyPolygon.count())
111 addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(maPathPolyPolygon)));
115 bool PathDragMove::BeginSdrDrag()
117 if( mxTag.is() )
119 SdrPathObj* pPathObj = mxTag->getPathObj();
120 if( pPathObj )
122 DragStat().SetActionRect(pPathObj->GetCurrentBoundRect());
125 Show();
126 return true;
129 bool PathDragMove::EndSdrDrag(bool /*bCopy*/)
131 Hide();
132 if( mxTag.is() )
133 mxTag->MovePath( DragStat().GetDX(), DragStat().GetDY() );
134 return true;
137 namespace {
139 class PathDragResize : public SdrDragResize
141 private:
142 basegfx::B2DPolyPolygon maPathPolyPolygon;
144 protected:
145 virtual void createSdrDragEntries() override;
147 public:
148 PathDragResize(SdrDragView& rNewView,
149 rtl::Reference <MotionPathTag > xTag,
150 basegfx::B2DPolyPolygon aPathPolyPolygon)
151 : SdrDragResize(rNewView),
152 maPathPolyPolygon(std::move(aPathPolyPolygon)),
153 mxTag(std::move( xTag ))
156 PathDragResize(SdrDragView& rNewView,
157 rtl::Reference <MotionPathTag > xTag)
158 : SdrDragResize(rNewView),
159 mxTag(std::move( xTag ))
162 virtual bool EndSdrDrag(bool bCopy) override;
163 rtl::Reference <MotionPathTag > mxTag;
168 void PathDragResize::createSdrDragEntries()
170 // call parent
171 SdrDragResize::createSdrDragEntries();
173 if(maPathPolyPolygon.count())
175 addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(maPathPolyPolygon)));
179 bool PathDragResize::EndSdrDrag(bool /*bCopy*/)
181 Hide();
182 if( mxTag.is() )
184 SdrPathObj* pPathObj = mxTag->getPathObj();
185 if( pPathObj )
187 const Point aRef( DragStat().GetRef1() );
188 basegfx::B2DHomMatrix aTrans(basegfx::utils::createTranslateB2DHomMatrix(-aRef.X(), -aRef.Y()));
189 aTrans.scale(double(aXFact), double(aYFact));
190 aTrans.translate(aRef.X(), aRef.Y());
191 basegfx::B2DPolyPolygon aDragPoly(pPathObj->GetPathPoly());
192 aDragPoly.transform(aTrans);
193 pPathObj->SetPathPoly( aDragPoly );
196 return true;
199 namespace {
201 class PathDragObjOwn : public SdrDragObjOwn
203 private:
204 basegfx::B2DPolyPolygon maPathPolyPolygon;
206 protected:
207 virtual void createSdrDragEntries() override;
209 public:
210 PathDragObjOwn(SdrDragView& rNewView,
211 basegfx::B2DPolyPolygon aPathPolyPolygon)
212 : SdrDragObjOwn(rNewView),
213 maPathPolyPolygon(std::move(aPathPolyPolygon))
216 explicit PathDragObjOwn(SdrDragView& rNewView)
217 : SdrDragObjOwn(rNewView)
220 virtual bool EndSdrDrag(bool bCopy) override;
225 void PathDragObjOwn::createSdrDragEntries()
227 // call parent
228 SdrDragObjOwn::createSdrDragEntries();
230 if(maPathPolyPolygon.count())
232 addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(maPathPolyPolygon)));
236 bool PathDragObjOwn::EndSdrDrag(bool /*bCopy*/)
238 Hide();
240 SdrObject* pObj = GetDragObj();
242 if(pObj && pObj->applySpecialDrag(DragStat()))
244 pObj->SetChanged();
245 pObj->BroadcastObjectChange();
246 return true;
248 else
250 return false;
254 namespace {
256 class SdPathHdl : public SmartHdl
258 public:
259 SdPathHdl( const SmartTagReference& xTag, SdrPathObj* mpPathObj );
261 virtual void CreateB2dIAObject() override;
262 virtual bool IsFocusHdl() const override;
264 private:
265 SdrPathObj* mpPathObj;
270 SdPathHdl::SdPathHdl( const SmartTagReference& xTag, SdrPathObj* pPathObj )
271 : SmartHdl( xTag, pPathObj->GetCurrentBoundRect().TopLeft(), SdrHdlKind::SmartTag )
272 , mpPathObj( pPathObj )
276 void SdPathHdl::CreateB2dIAObject()
278 // first throw away old one
279 GetRidOfIAObject();
281 if(!pHdlList)
282 return;
284 SdrMarkView* pView = pHdlList->GetView();
286 if(!pView || pView->areMarkHandlesHidden())
287 return;
289 SdrPageView* pPageView = pView->GetSdrPageView();
291 if(!pPageView)
292 return;
294 for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
296 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
298 if(rPageWindow.GetPaintWindow().OutputToWindow())
300 const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
301 if (xManager.is() && mpPathObj)
303 const sdr::contact::ViewContact& rVC = mpPathObj->GetViewContact();
304 drawinglayer::primitive2d::Primitive2DContainer aSequence;
305 rVC.getViewIndependentPrimitive2DContainer(aSequence);
306 std::unique_ptr<sdr::overlay::OverlayObject> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(std::move(aSequence)));
308 // OVERLAYMANAGER
309 insertNewlyCreatedOverlayObjectForSdrHdl(
310 std::move(pNew),
311 rPageWindow.GetObjectContact(),
312 *xManager);
318 bool SdPathHdl::IsFocusHdl() const
320 return false;
323 MotionPathTag::MotionPathTag( CustomAnimationPane& rPane, ::sd::View& rView, const CustomAnimationEffectPtr& pEffect )
324 : SmartTag( rView )
325 , mrPane( rPane )
326 , mpEffect( pEffect )
327 , mxOrigin( pEffect->getTargetShape() )
328 , msLastPath( pEffect->getPath() )
329 , mbInUpdatePath( false )
331 mpPathObj = mpEffect->createSdrPathObjFromPath(rView.getSdrModelFromSdrView());
332 mxPolyPoly = mpPathObj->GetPathPoly();
333 if (mxOrigin.is())
334 maOriginPos = mxOrigin->getPosition();
336 XDash aDash( css::drawing::DashStyle_RECT, 1, 80, 1, 80, 80);
337 OUString aEmpty( "?" );
338 mpPathObj->SetMergedItem( XLineDashItem( aEmpty, aDash ) );
339 mpPathObj->SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
340 mpPathObj->SetMergedItem( XLineColorItem(aEmpty, COL_GRAY) );
341 mpPathObj->SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
343 ::basegfx::B2DPolygon aStartArrow;
344 aStartArrow.append(::basegfx::B2DPoint(20.0, 0.0));
345 aStartArrow.append(::basegfx::B2DPoint(0.0, 0.0));
346 aStartArrow.append(::basegfx::B2DPoint(10.0, 30.0));
347 aStartArrow.setClosed(true);
348 mpPathObj->SetMergedItem(XLineStartItem(aEmpty,::basegfx::B2DPolyPolygon(aStartArrow)));
349 mpPathObj->SetMergedItem(XLineStartWidthItem(400));
350 mpPathObj->SetMergedItem(XLineStartCenterItem(true));
352 updatePathAttributes();
354 mpPathObj->SetMergedItem(XLineTransparenceItem(50));
356 mpMark.reset(new SdrMark( mpPathObj.get(), mrView.GetSdrPageView() ));
358 mpPathObj->AddListener( *this );
360 Reference< XChangesNotifier > xNotifier( mpEffect->getNode(), UNO_QUERY );
361 if( xNotifier.is() )
363 xNotifier->addChangesListener( this );
367 MotionPathTag::~MotionPathTag()
369 DBG_ASSERT( mpPathObj == nullptr, "sd::MotionPathTag::~MotionPathTag(), dispose me first!" );
370 Dispose();
373 void MotionPathTag::updatePathAttributes()
375 ::basegfx::B2DPolygon aCandidate;
376 if( mxPolyPoly.count() )
378 aCandidate = mxPolyPoly.getB2DPolygon(0);
379 ::basegfx::utils::checkClosed( aCandidate );
382 if( !aCandidate.isClosed() )
384 ::basegfx::B2DPolygon aEndArrow;
385 aEndArrow.append(::basegfx::B2DPoint(10.0, 0.0));
386 aEndArrow.append(::basegfx::B2DPoint(0.0, 30.0));
387 aEndArrow.append(::basegfx::B2DPoint(20.0, 30.0));
388 aEndArrow.setClosed(true);
389 mpPathObj->SetMergedItem(XLineEndItem("?",::basegfx::B2DPolyPolygon(aEndArrow)));
390 mpPathObj->SetMergedItem(XLineEndWidthItem(400));
391 mpPathObj->SetMergedItem(XLineEndCenterItem(true));
393 else
395 mpPathObj->SetMergedItem(XLineEndItem());
399 void MotionPathTag::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
401 if( !(mpPathObj && !mbInUpdatePath && rHint.GetId() == SfxHintId::ThisIsAnSdrHint && mpEffect) )
402 return;
404 if( mxPolyPoly != mpPathObj->GetPathPoly() )
406 mbInUpdatePath = true;
407 mxPolyPoly = mpPathObj->GetPathPoly();
408 rtl::Reference< MotionPathTag > xTag( this );
409 mrPane.updatePathFromMotionPathTag( xTag );
410 msLastPath = mpEffect->getPath();
411 updatePathAttributes();
412 mbInUpdatePath = false;
416 void MotionPathTag::MovePath( int nDX, int nDY )
418 if( mpPathObj )
420 mpPathObj->Move( Size( nDX, nDY ) );
421 mrView.updateHandles();
425 /** returns true if the MotionPathTag handled the event. */
426 bool MotionPathTag::MouseButtonDown( const MouseEvent& rMEvt, SmartHdl& rHdl )
428 if( !mpPathObj )
429 return false;
431 if( !isSelected() )
433 SmartTagReference xTag( this );
434 mrView.getSmartTags().select( xTag );
435 selectionChanged();
436 return true;
438 else
440 if( rMEvt.IsLeft() && (rMEvt.GetClicks() == 2) )
442 mrView.GetViewShell()->GetViewFrame()->GetDispatcher()->Execute(SID_BEZIER_EDIT, SfxCallMode::ASYNCHRON);
443 return true;
445 else if( rMEvt.IsLeft() )
447 OutputDevice* pOut = mrView.GetViewShell()->GetActiveWindow()->GetOutDev();
448 Point aMDPos( pOut->PixelToLogic( rMEvt.GetPosPixel() ) );
450 if( !mrView.IsFrameDragSingles() && mrView.IsInsObjPointMode() && (rHdl.GetObjHdlNum() == SMART_TAG_HDL_NUM) )
452 // insert a point in edit mode
453 const bool bNewObj = rMEvt.IsMod1();
455 mrView.BrkAction();
457 Point aPt(aMDPos); // - pMarkedPV->GetOffset());
459 if(bNewObj)
460 aPt = mrView.GetSnapPos(aPt,mrView.GetSdrPageView());
462 bool bClosed0(mpPathObj->IsClosedObj());
464 sal_uInt32 nInsPointNum = mpPathObj->NbcInsPointOld(aPt, bNewObj);
466 if(bClosed0 != mpPathObj->IsClosedObj())
468 // Obj was closed implicit
469 // object changed
470 mpPathObj->SetChanged();
471 mpPathObj->BroadcastObjectChange();
474 if(0xffffffff != nInsPointNum)
476 mrView.UnmarkAllPoints();
477 mrView.updateHandles();
479 bool bRet = mrView.BegDragObj(aMDPos, pOut, mrView.GetHdl(nInsPointNum+1), 0, new PathDragObjOwn( mrView ) );
481 if (bRet)
483 const_cast< SdrDragStat* >( &mrView.GetDragStat() )->SetMinMoved();
484 mrView.MovDragObj(aMDPos);
487 return true;
489 else
491 SmartHdl* pHdl = &rHdl;
492 if (!mrView.IsPointMarked(*pHdl) || rMEvt.IsShift())
494 if (!rMEvt.IsShift())
496 mrView.UnmarkAllPoints();
497 pHdl = dynamic_cast< SmartHdl* >( mrView.PickHandle(aMDPos) );
499 else
501 if (mrView.IsPointMarked(*pHdl) )
503 mrView.UnmarkPoint(*pHdl);
504 pHdl = nullptr;
506 else
508 pHdl = dynamic_cast< SmartHdl* >( mrView.PickHandle(aMDPos) );
512 if (pHdl)
513 mrView.MarkPoint(*pHdl);
516 if( pHdl && !rMEvt.IsRight() )
518 mrView.BrkAction();
519 const sal_uInt16 nDrgLog = static_cast<sal_uInt16>(pOut->PixelToLogic(Size(DRGPIX,0)).Width());
521 rtl::Reference< MotionPathTag > xTag( this );
522 SdrDragMethod* pDragMethod;
524 // #i95646# add DragPoly as geometry to each local SdrDragMethod to be able
525 // to create the needed local SdrDragEntry for it in createSdrDragEntries()
526 basegfx::B2DPolyPolygon aDragPoly(mpPathObj->GetPathPoly());
528 if( (pHdl->GetKind() == SdrHdlKind::Move) || (pHdl->GetKind() == SdrHdlKind::SmartTag) )
530 pDragMethod = new PathDragMove( mrView, xTag, aDragPoly );
531 pHdl->SetPos( aMDPos );
533 else if( pHdl->GetKind() == SdrHdlKind::Poly )
535 pDragMethod = new PathDragObjOwn( mrView, aDragPoly );
537 else
539 pDragMethod = new PathDragResize( mrView, xTag, std::move(aDragPoly) );
542 mrView.BegDragObj(aMDPos, nullptr, pHdl, nDrgLog, pDragMethod );
544 return true;
549 return false;
552 /** returns true if the SmartTag consumes this event. */
553 bool MotionPathTag::KeyInput( const KeyEvent& rKEvt )
555 if( !mpPathObj )
556 return false;
558 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
559 switch( nCode )
561 case KEY_DELETE:
562 return OnDelete();
564 case KEY_DOWN:
565 case KEY_UP:
566 case KEY_LEFT:
567 case KEY_RIGHT:
568 return OnMove( rKEvt );
570 case KEY_ESCAPE:
572 SmartTagReference xThis( this );
573 mrView.getSmartTags().deselect();
574 return true;
577 case KEY_TAB:
578 return OnTabHandles( rKEvt );
580 case KEY_SPACE:
581 return OnMarkHandle( rKEvt );
583 default:
584 break;
586 return false;
589 bool MotionPathTag::OnDelete()
591 mrPane.remove( mpEffect );
592 return true;
595 bool MotionPathTag::OnTabHandles( const KeyEvent& rKEvt )
597 if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2())
599 const SdrHdlList& rHdlList = mrView.GetHdlList();
600 bool bForward(!rKEvt.GetKeyCode().IsShift());
602 const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
604 // guarantee visibility of focused handle
605 SdrHdl* pHdl = rHdlList.GetFocusHdl();
607 if(pHdl)
609 Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
610 if( pWindow )
612 Point aHdlPosition(pHdl->GetPos());
613 ::tools::Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200));
614 mrView.MakeVisible(aVisRect, *pWindow);
618 return true;
621 return false;
624 bool MotionPathTag::OnMarkHandle( const KeyEvent& rKEvt )
626 const SdrHdlList& rHdlList = mrView.GetHdlList();
627 SdrHdl* pHdl = rHdlList.GetFocusHdl();
629 if(pHdl && pHdl->GetKind() == SdrHdlKind::Poly )
631 // rescue ID of point with focus
632 sal_uInt32 nPol(pHdl->GetPolyNum());
633 sal_uInt32 nPnt(pHdl->GetPointNum());
635 if(mrView.IsPointMarked(*pHdl))
637 if(rKEvt.GetKeyCode().IsShift())
639 mrView.UnmarkPoint(*pHdl);
642 else
644 if(!rKEvt.GetKeyCode().IsShift())
646 mrView.UnmarkAllPoints();
648 mrView.MarkPoint(*pHdl);
651 if(nullptr == rHdlList.GetFocusHdl())
653 // restore point with focus
654 SdrHdl* pNewOne = nullptr;
656 for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a)
658 SdrHdl* pAct = rHdlList.GetHdl(a);
660 if(pAct && pAct->GetKind() == SdrHdlKind::Poly && pAct->GetPolyNum() == nPol && pAct->GetPointNum() == nPnt)
661 pNewOne = pAct;
664 if(pNewOne)
665 const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne);
669 return true;
672 bool MotionPathTag::OnMove( const KeyEvent& rKEvt )
674 ::tools::Long nX = 0;
675 ::tools::Long nY = 0;
677 switch( rKEvt.GetKeyCode().GetCode() )
679 case KEY_UP: nY = -1; break;
680 case KEY_DOWN: nY = 1; break;
681 case KEY_LEFT: nX = -1; break;
682 case KEY_RIGHT: nX = 1; break;
683 default: break;
686 if(rKEvt.GetKeyCode().IsMod2())
688 OutputDevice* pOut = mrView.GetViewShell()->GetActiveWindow()->GetOutDev();
689 Size aLogicSizeOnePixel = pOut ? pOut->PixelToLogic(Size(1,1)) : Size(100, 100);
690 nX *= aLogicSizeOnePixel.Width();
691 nY *= aLogicSizeOnePixel.Height();
693 else
695 // old, fixed move distance
696 nX *= 100;
697 nY *= 100;
700 if( nX || nY )
702 // in point edit mode move the handle with the focus
703 const SdrHdlList& rHdlList = mrView.GetHdlList();
704 SdrHdl* pHdl = rHdlList.GetFocusHdl();
706 if(pHdl)
708 // now move the Handle (nX, nY)
709 Point aStartPoint(pHdl->GetPos());
710 Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
712 // start dragging
713 rtl::Reference< MotionPathTag > xTag( this );
714 SdrDragMethod* pDragMethod = nullptr;
715 if( (pHdl->GetKind() == SdrHdlKind::Move) || (pHdl->GetKind() == SdrHdlKind::SmartTag) )
717 pDragMethod = new PathDragMove( mrView, xTag );
719 else if( pHdl->GetKind() == SdrHdlKind::Poly )
721 pDragMethod = new PathDragObjOwn( mrView );
723 else if( pHdl->GetKind() != SdrHdlKind::BezierWeight )
725 pDragMethod = new PathDragResize( mrView, xTag );
727 mrView.BegDragObj(aStartPoint, nullptr, pHdl, 0, pDragMethod);
729 if(mrView.IsDragObj())
731 bool bWasNoSnap = mrView.GetDragStat().IsNoSnap();
732 bool bWasSnapEnabled = mrView.IsSnapEnabled();
734 // switch snapping off
735 if(!bWasNoSnap)
736 const_cast<SdrDragStat&>(mrView.GetDragStat()).SetNoSnap();
737 if(bWasSnapEnabled)
738 mrView.SetSnapEnabled(false);
740 mrView.MovAction(aEndPoint);
741 mrView.EndDragObj();
743 // restore snap
744 if(!bWasNoSnap)
745 const_cast<SdrDragStat&>(mrView.GetDragStat()).SetNoSnap(bWasNoSnap);
746 if(bWasSnapEnabled)
747 mrView.SetSnapEnabled(bWasSnapEnabled);
750 else
752 // move the path
753 MovePath( nX, nY );
757 return true;
760 sal_Int32 MotionPathTag::GetMarkablePointCount() const
762 if( mpPathObj && isSelected() )
764 return mpPathObj->GetPointCount();
766 else
768 return 0;
772 sal_Int32 MotionPathTag::GetMarkedPointCount() const
774 if( mpMark )
776 const SdrUShortCont& rPts = mpMark->GetMarkedPoints();
777 return rPts.size();
779 else
781 return 0;
785 bool MotionPathTag::MarkPoint(SdrHdl& rHdl, bool bUnmark )
787 bool bRet=false;
788 if( mpPathObj && mrView.IsPointMarkable( rHdl ) && (rHdl.GetKind() != SdrHdlKind::SmartTag) )
790 SmartHdl* pSmartHdl = dynamic_cast< SmartHdl* >( &rHdl );
791 if( pSmartHdl && pSmartHdl->getTag().get() == this )
793 if (mrView.MarkPointHelper(&rHdl,mpMark.get(),bUnmark))
795 mrView.MarkListHasChanged();
796 bRet=true;
800 return bRet;
803 bool MotionPathTag::MarkPoints(const ::tools::Rectangle* pRect, bool bUnmark )
805 bool bChgd=false;
807 if( mpPathObj && isSelected() )
809 size_t nHdlNum = mrView.GetHdlList().GetHdlCount();
810 if ( nHdlNum <= 1 )
811 return false;
813 while( --nHdlNum > 0 )
815 SmartHdl* pHdl = dynamic_cast< SmartHdl* >( mrView.GetHdl( nHdlNum ) );
817 if( pHdl && (pHdl->getTag().get() == this) && mrView.IsPointMarkable(*pHdl) && pHdl->IsSelected() == bUnmark)
819 Point aPos(pHdl->GetPos());
820 if( pRect==nullptr || pRect->Contains(aPos))
822 if( mrView.MarkPointHelper(pHdl,mpMark.get(),bUnmark) )
823 bChgd=true;
828 if(bChgd)
829 mrView.MarkListHasChanged();
832 return bChgd;
835 bool MotionPathTag::getContext( SdrViewContext& rContext )
837 if( mpPathObj && isSelected() && !mrView.IsFrameDragSingles() )
839 rContext = SdrViewContext::PointEdit;
840 return true;
842 else
844 return false;
848 void MotionPathTag::CheckPossibilities()
850 if( !(mpPathObj && isSelected()) )
851 return;
853 mrView.SetMoveAllowed( true );
854 mrView.SetMoveProtected( false );
855 mrView.SetResizeFreeAllowed( true );
856 mrView.SetResizePropAllowed( true );
857 mrView.SetResizeProtected( false );
859 if( !mrView.IsFrameDragSingles() )
861 bool b1stSmooth(true);
862 bool b1stSegm(true);
863 bool bCurve(false);
864 bool bSmoothFuz(false);
865 bool bSegmFuz(false);
866 basegfx::B2VectorContinuity eSmooth = basegfx::B2VectorContinuity::NONE;
868 mrView.CheckPolyPossibilitiesHelper( mpMark.get(), b1stSmooth, b1stSegm, bCurve, bSmoothFuz, bSegmFuz, eSmooth );
872 void MotionPathTag::addCustomHandles( SdrHdlList& rHandlerList )
874 if( !mpPathObj )
875 return;
877 css::awt::Point aPos;
878 if (mxOrigin.is())
879 aPos = mxOrigin->getPosition();
880 if( (aPos.X != maOriginPos.X) || (aPos.Y != maOriginPos.Y) )
882 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createTranslateB2DHomMatrix(
883 aPos.X - maOriginPos.X, aPos.Y - maOriginPos.Y));
884 mxPolyPoly.transform( aTransform );
885 mpPathObj->SetPathPoly( mxPolyPoly );
886 maOriginPos = aPos;
889 SmartTagReference xThis( this );
890 std::unique_ptr<SdPathHdl> pHdl(new SdPathHdl( xThis, mpPathObj.get() ));
891 pHdl->SetObjHdlNum( SMART_TAG_HDL_NUM );
892 pHdl->SetPageView( mrView.GetSdrPageView() );
893 pHdl->SetObj(mpPathObj.get());
894 rHandlerList.AddHdl( std::move(pHdl) );
896 if( !isSelected() )
897 return;
899 mrView.GetSdrPageView()->SetHasMarkedObj(true);
901 if( !mrView.IsFrameDragSingles() )
903 SdrHdlList aTemp( rHandlerList.GetView() );
904 mpPathObj->AddToHdlList( aTemp );
905 const SdrUShortCont& rMrkPnts = mpMark->GetMarkedPoints();
907 for( size_t nHandle = 0; nHandle < aTemp.GetHdlCount(); ++nHandle )
909 SdrHdl* pTempHdl = aTemp.GetHdl( nHandle );
911 SmartHdl* pSmartHdl = new SmartHdl( xThis, mpPathObj.get(), pTempHdl->GetPos(), pTempHdl->GetKind() );
912 pSmartHdl->SetObjHdlNum( static_cast<sal_uInt32>(nHandle) );
913 pSmartHdl->SetPolyNum( pTempHdl->GetPolyNum() );
914 pSmartHdl->SetPointNum( pTempHdl->GetPointNum() );
915 pSmartHdl->SetPlusHdl( pTempHdl->IsPlusHdl() );
916 pSmartHdl->SetSourceHdlNum( pTempHdl->GetSourceHdlNum() );
917 pSmartHdl->SetPageView( mrView.GetSdrPageView() );
919 rHandlerList.AddHdl( std::unique_ptr<SmartHdl>(pSmartHdl) );
921 const bool bSelected = rMrkPnts.find( sal_uInt16(nHandle) ) != rMrkPnts.end();
922 pSmartHdl->SetSelected(bSelected);
924 if( mrView.IsPlusHandlesAlwaysVisible() || bSelected )
926 SdrHdlList plusList(nullptr);
927 mpPathObj->AddToPlusHdlList(plusList, *pSmartHdl);
928 sal_uInt32 nPlusHdlCnt=plusList.GetHdlCount();
929 for (sal_uInt32 nPlusNum=0; nPlusNum<nPlusHdlCnt; nPlusNum++)
931 SdrHdl* pPlusHdl = plusList.GetHdl(nPlusNum);
932 pPlusHdl->SetObj(mpPathObj.get());
933 pPlusHdl->SetPageView(mrView.GetSdrPageView());
934 pPlusHdl->SetPlusHdl(true);
936 plusList.MoveTo(rHandlerList);
940 else
942 ::tools::Rectangle aRect(mpPathObj->GetCurrentBoundRect());
944 if(!aRect.IsEmpty())
946 size_t nCount = rHandlerList.GetHdlCount();
948 bool bWdt0=aRect.Left()==aRect.Right();
949 bool bHgt0=aRect.Top()==aRect.Bottom();
950 if (bWdt0 && bHgt0)
952 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.TopLeft(),SdrHdlKind::UpperLeft));
954 else if (bWdt0 || bHgt0)
956 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.TopLeft() ,SdrHdlKind::UpperLeft));
957 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.BottomRight(),SdrHdlKind::LowerRight));
959 else // !bWdt0 && !bHgt0
961 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.TopLeft() ,SdrHdlKind::UpperLeft));
962 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.TopCenter() ,SdrHdlKind::Upper));
963 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.TopRight() ,SdrHdlKind::UpperRight));
964 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.LeftCenter() ,SdrHdlKind::Left ));
965 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.RightCenter() ,SdrHdlKind::Right));
966 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.BottomLeft() ,SdrHdlKind::LowerLeft));
967 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.BottomCenter(),SdrHdlKind::Lower));
968 rHandlerList.AddHdl(std::make_unique<SmartHdl>( xThis, mpPathObj.get(), aRect.BottomRight() ,SdrHdlKind::LowerRight));
971 while( nCount < rHandlerList.GetHdlCount() )
973 rHandlerList.GetHdl(nCount++)->SetPageView( mrView.GetSdrPageView() );
979 void MotionPathTag::disposing()
981 Reference< XChangesNotifier > xNotifier( mpEffect->getNode(), UNO_QUERY );
982 if( xNotifier.is() )
984 xNotifier->removeChangesListener( this );
987 if( mpPathObj )
989 mpPathObj = nullptr;
990 mrView.updateHandles();
993 mpMark.reset();
995 SmartTag::disposing();
998 void MotionPathTag::deselect()
1000 SmartTag::deselect();
1002 if( mpMark )
1004 SdrUShortCont& rPts = mpMark->GetMarkedPoints();
1005 rPts.clear();
1008 selectionChanged();
1011 void MotionPathTag::selectionChanged()
1013 if( mrView.GetViewShell() && mrView.GetViewShell()->GetViewFrame() )
1015 SfxBindings& rBindings = mrView.GetViewShell()->GetViewFrame()->GetBindings();
1016 rBindings.InvalidateAll(true);
1020 // IPolyPolygonEditorController
1022 void MotionPathTag::DeleteMarkedPoints()
1024 if( !(mpPathObj && IsDeleteMarkedPointsPossible()) )
1025 return;
1027 mrView.BrkAction();
1029 SdrUShortCont& rPts = mpMark->GetMarkedPoints();
1030 PolyPolygonEditor aEditor( mpPathObj->GetPathPoly());
1031 if (aEditor.DeletePoints(rPts))
1033 if( aEditor.GetPolyPolygon().count() )
1035 mpPathObj->SetPathPoly( aEditor.GetPolyPolygon() );
1038 mrView.UnmarkAllPoints();
1039 mrView.MarkListHasChanged();
1040 mrView.updateHandles();
1044 bool MotionPathTag::IsDeleteMarkedPointsPossible() const
1046 return mpPathObj && isSelected() && (GetMarkedPointCount() != 0);
1049 void MotionPathTag::RipUpAtMarkedPoints()
1051 // not supported for motion path
1054 bool MotionPathTag::IsRipUpAtMarkedPointsPossible() const
1056 // not supported for motion path
1057 return false;
1060 bool MotionPathTag::IsSetMarkedSegmentsKindPossible() const
1062 if( mpPathObj )
1063 return mrView.IsSetMarkedSegmentsKindPossible();
1064 else
1065 return false;
1068 SdrPathSegmentKind MotionPathTag::GetMarkedSegmentsKind() const
1070 if( mpPathObj )
1071 return mrView.GetMarkedSegmentsKind();
1072 else
1073 return SdrPathSegmentKind::Line;
1076 void MotionPathTag::SetMarkedSegmentsKind(SdrPathSegmentKind eKind)
1078 if(mpPathObj && isSelected() && (GetMarkedPointCount() != 0))
1080 SdrUShortCont& rPts = mpMark->GetMarkedPoints();
1081 PolyPolygonEditor aEditor( mpPathObj->GetPathPoly() );
1082 if (aEditor.SetSegmentsKind(eKind, rPts))
1084 mpPathObj->SetPathPoly(aEditor.GetPolyPolygon());
1085 mrView.MarkListHasChanged();
1086 mrView.updateHandles();
1091 bool MotionPathTag::IsSetMarkedPointsSmoothPossible() const
1093 if( mpPathObj )
1094 return mrView.IsSetMarkedPointsSmoothPossible();
1095 else
1096 return false;
1099 SdrPathSmoothKind MotionPathTag::GetMarkedPointsSmooth() const
1101 if( mpPathObj )
1102 return mrView.GetMarkedPointsSmooth();
1103 else
1104 return SdrPathSmoothKind::Angular;
1107 void MotionPathTag::SetMarkedPointsSmooth(SdrPathSmoothKind eKind)
1109 basegfx::B2VectorContinuity eFlags;
1111 if(SdrPathSmoothKind::Angular == eKind)
1113 eFlags = basegfx::B2VectorContinuity::NONE;
1115 else if(SdrPathSmoothKind::Asymmetric == eKind)
1117 eFlags = basegfx::B2VectorContinuity::C1;
1119 else if(SdrPathSmoothKind::Symmetric == eKind)
1121 eFlags = basegfx::B2VectorContinuity::C2;
1123 else
1125 return;
1128 if(mpPathObj && mpMark && isSelected() && (GetMarkedPointCount() != 0))
1130 SdrUShortCont& rPts = mpMark->GetMarkedPoints();
1131 PolyPolygonEditor aEditor( mpPathObj->GetPathPoly());
1132 if (aEditor.SetPointsSmooth(eFlags, rPts))
1134 mpPathObj->SetPathPoly(aEditor.GetPolyPolygon());
1135 mrView.MarkListHasChanged();
1136 mrView.updateHandles();
1141 bool MotionPathTag::IsOpenCloseMarkedObjectsPossible() const
1143 // not supported for motion path
1144 return false;
1147 SdrObjClosedKind MotionPathTag::GetMarkedObjectsClosedState() const
1149 // not supported for motion path
1150 return SdrObjClosedKind::Open;
1153 // XChangesListener
1154 void SAL_CALL MotionPathTag::changesOccurred( const ChangesEvent& /*Event*/ )
1156 if( mpPathObj && !mbInUpdatePath && (mpEffect->getPath() != msLastPath) )
1158 mbInUpdatePath =true;
1159 msLastPath = mpEffect->getPath();
1160 mpEffect->updateSdrPathObjFromPath( *mpPathObj );
1161 mbInUpdatePath = false;
1162 updatePathAttributes();
1163 mrView.updateHandles();
1167 void SAL_CALL MotionPathTag::disposing( const EventObject& /*Source*/ )
1169 if( mpPathObj )
1170 Dispose();
1173 Any SAL_CALL MotionPathTag::queryInterface( const css::uno::Type& aType )
1175 if( aType == cppu::UnoType<XChangesListener>::get() )
1176 return Any( Reference< XChangesListener >( this ) );
1177 if( aType == cppu::UnoType<XEventListener>::get() )
1178 return Any( Reference< XEventListener >( this ) );
1179 if( aType == cppu::UnoType<XInterface>::get() )
1180 return Any( Reference< XInterface >( this ) );
1182 return Any();
1185 void SAL_CALL MotionPathTag::acquire() noexcept
1187 SimpleReferenceComponent::acquire();
1190 void SAL_CALL MotionPathTag::release( ) noexcept
1192 SimpleReferenceComponent::release();
1195 } // end of namespace sd
1197 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */