blob: 1862c22edcb2e242d47862371fc67b3b8d0a9198 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"
#include <com/sun/star/util/XChangesNotifier.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/dispatch.hxx>
#include <svx/sdr/overlay/overlaymanager.hxx>
#include <svx/sdr/overlay/overlaypolypolygon.hxx>
#include <svx/svdpagv.hxx>
#include <svx/sdrpagewindow.hxx>
#include <svx/sdrpaintwindow.hxx>
#include <svx/svdopath.hxx>
#include <svx/xlndsit.hxx>
#include <svx/xlnclit.hxx>
#include <svx/xlnstit.hxx>
#include <svx/xlnedit.hxx>
#include <svx/xlnstwit.hxx>
#include <svx/xlnedwit.hxx>
#include <svx/xlnstcit.hxx>
#include <svx/xlnedcit.hxx>
#include <svx/xlntrit.hxx>
#include <svx/svxids.hrc>
#include <svx/polypolygoneditor.hxx>
#include <svx/svddrgmt.hxx>
#include "CustomAnimationPane.hxx"
#include "View.hxx"
#include "motionpathtag.hxx"
#include "sdpage.hxx"
#include "ViewShell.hxx"
#include "app.hrc"
#include "Window.hxx"
#include <svx/sdr/contact/viewcontact.hxx>
#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
using ::rtl::OUString;
using ::sdr::PolyPolygonEditor;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::drawing;
namespace sd
{
const sal_uInt32 SMART_TAG_HDL_NUM = SAL_MAX_UINT32;
static const int DRGPIX = 2; // Drag MinMove in Pixel
// --------------------------------------------------------------------
class PathDragMove : public SdrDragMove
{
private:
basegfx::B2DPolyPolygon maPathPolyPolygon;
protected:
virtual void createSdrDragEntries();
public:
PathDragMove(SdrDragView& rNewView,
const rtl::Reference <MotionPathTag >& xTag,
const basegfx::B2DPolyPolygon& rPathPolyPolygon)
: SdrDragMove(rNewView),
maPathPolyPolygon(rPathPolyPolygon),
mxTag( xTag )
{}
PathDragMove(SdrDragView& rNewView,
const rtl::Reference <MotionPathTag >& xTag)
: SdrDragMove(rNewView),
maPathPolyPolygon(),
mxTag( xTag )
{}
virtual bool BeginSdrDrag();
virtual bool EndSdrDrag(bool bCopy);
rtl::Reference <MotionPathTag > mxTag;
};
void PathDragMove::createSdrDragEntries()
{
// call parent
SdrDragMove::createSdrDragEntries();
if(maPathPolyPolygon.count())
{
addSdrDragEntry(new SdrDragEntryPolyPolygon(maPathPolyPolygon));
}
}
bool PathDragMove::BeginSdrDrag()
{
if( mxTag.is() )
{
SdrPathObj* pPathObj = mxTag->getPathObj();
if( pPathObj )
{
DragStat().SetActionRect(pPathObj->GetCurrentBoundRect());
}
}
Show();
return sal_True;
}
bool PathDragMove::EndSdrDrag(bool /*bCopy*/)
{
Hide();
if( mxTag.is() )
mxTag->MovePath( DragStat().GetDX(), DragStat().GetDY() );
return sal_True;
}
// --------------------------------------------------------------------
class PathDragResize : public SdrDragResize
{
private:
basegfx::B2DPolyPolygon maPathPolyPolygon;
protected:
virtual void createSdrDragEntries();
public:
PathDragResize(SdrDragView& rNewView,
const rtl::Reference <MotionPathTag >& xTag,
const basegfx::B2DPolyPolygon& rPathPolyPolygon)
: SdrDragResize(rNewView),
maPathPolyPolygon(rPathPolyPolygon),
mxTag( xTag )
{}
PathDragResize(SdrDragView& rNewView,
const rtl::Reference <MotionPathTag >& xTag)
: SdrDragResize(rNewView),
maPathPolyPolygon(),
mxTag( xTag )
{}
virtual bool EndSdrDrag(bool bCopy);
rtl::Reference <MotionPathTag > mxTag;
};
void PathDragResize::createSdrDragEntries()
{
// call parent
SdrDragResize::createSdrDragEntries();
if(maPathPolyPolygon.count())
{
addSdrDragEntry(new SdrDragEntryPolyPolygon(maPathPolyPolygon));
}
}
bool PathDragResize::EndSdrDrag(bool /*bCopy*/)
{
Hide();
if( mxTag.is() )
{
SdrPathObj* pPathObj = mxTag->getPathObj();
if( pPathObj )
{
const Point aRef( DragStat().Ref1() );
basegfx::B2DHomMatrix aTrans(basegfx::tools::createTranslateB2DHomMatrix(-aRef.X(), -aRef.Y()));
aTrans.scale(double(aXFact), double(aYFact));
aTrans.translate(aRef.X(), aRef.Y());
basegfx::B2DPolyPolygon aDragPoly(pPathObj->GetPathPoly());
aDragPoly.transform(aTrans);
pPathObj->SetPathPoly( aDragPoly );
}
}
return sal_True;
}
// --------------------------------------------------------------------
class PathDragObjOwn : public SdrDragObjOwn
{
private:
basegfx::B2DPolyPolygon maPathPolyPolygon;
protected:
virtual void createSdrDragEntries();
public:
PathDragObjOwn(SdrDragView& rNewView,
const basegfx::B2DPolyPolygon& rPathPolyPolygon)
: SdrDragObjOwn(rNewView),
maPathPolyPolygon(rPathPolyPolygon)
{}
PathDragObjOwn(SdrDragView& rNewView)
: SdrDragObjOwn(rNewView),
maPathPolyPolygon()
{}
virtual bool EndSdrDrag(bool bCopy);
};
void PathDragObjOwn::createSdrDragEntries()
{
// call parent
SdrDragObjOwn::createSdrDragEntries();
if(maPathPolyPolygon.count())
{
addSdrDragEntry(new SdrDragEntryPolyPolygon(maPathPolyPolygon));
}
}
bool PathDragObjOwn::EndSdrDrag(bool /*bCopy*/)
{
Hide();
SdrObject* pObj = GetDragObj();
if(pObj)
{
return pObj->applySpecialDrag(DragStat());
}
else
{
return false;
}
}
// --------------------------------------------------------------------
class SdPathHdl : public SmartHdl
{
public:
SdPathHdl( const SmartTagReference& xTag, SdrPathObj* mpPathObj );
virtual ~SdPathHdl();
virtual void CreateB2dIAObject();
virtual sal_Bool IsFocusHdl() const;
virtual Pointer GetSdrDragPointer() const;
virtual bool isMarkable() const;
private:
SdrPathObj* mpPathObj;
rtl::Reference< MotionPathTag > mxTag;
};
// --------------------------------------------------------------------
SdPathHdl::SdPathHdl( const SmartTagReference& xTag, SdrPathObj* pPathObj )
: SmartHdl( xTag, pPathObj->GetCurrentBoundRect().TopLeft() )
, mpPathObj( pPathObj )
, mxTag( dynamic_cast< MotionPathTag* >( xTag.get() ) )
{
}
// --------------------------------------------------------------------
SdPathHdl::~SdPathHdl()
{
}
// --------------------------------------------------------------------
void SdPathHdl::CreateB2dIAObject()
{
// first throw away old one
GetRidOfIAObject();
if(pHdlList)
{
SdrMarkView* pView = pHdlList->GetView();
if(pView && !pView->areMarkHandlesHidden())
{
SdrPageView* pPageView = pView->GetSdrPageView();
if(pPageView)
{
for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
{
const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
if(rPageWindow.GetPaintWindow().OutputToWindow())
{
if(rPageWindow.GetOverlayManager() && mpPathObj)
{
const sdr::contact::ViewContact& rVC = mpPathObj->GetViewContact();
const drawinglayer::primitive2d::Primitive2DSequence aSequence = rVC.getViewIndependentPrimitive2DSequence();
sdr::overlay::OverlayObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence);
rPageWindow.GetOverlayManager()->add(*pNew);
maOverlayGroup.append(*pNew);
}
}
}
}
}
}
}
// --------------------------------------------------------------------
sal_Bool SdPathHdl::IsFocusHdl() const
{
return sal_False;
}
// --------------------------------------------------------------------
bool SdPathHdl::isMarkable() const
{
return false;
}
// --------------------------------------------------------------------
Pointer SdPathHdl::GetSdrDragPointer() const
{
PointerStyle eStyle = POINTER_NOTALLOWED;
if( mxTag.is() )
{
if( mxTag->isSelected() )
{
if( !mxTag->getView().IsFrameDragSingles() && mxTag->getView().IsInsObjPointMode() )
eStyle = POINTER_CROSS;
else
eStyle = POINTER_MOVE;
}
else
{
eStyle = POINTER_ARROW;
}
}
return Pointer( eStyle );
}
// ====================================================================
MotionPathTag::MotionPathTag( CustomAnimationPane& rPane, ::sd::View& rView, const CustomAnimationEffectPtr& pEffect )
: SmartTag( rView )
, mrPane( rPane )
, mpEffect( pEffect )
, mxOrigin( pEffect->getTargetShape() )
, msLastPath( pEffect->getPath() )
, mbInUpdatePath( false )
{
mpPathObj = mpEffect->createSdrPathObjFromPath();
mxPolyPoly = mpPathObj->GetPathPoly();
maOriginPos = mxOrigin->getPosition();
SdrPage* pPage = mrView.GetSdrPageView()->GetPage();
if( pPage )
{
mpPathObj->SetPage( pPage );
mpPathObj->SetObjList( pPage );
}
XDash aDash( XDASH_RECT, 1, 80, 1, 80, 80);
String aEmpty( RTL_CONSTASCII_USTRINGPARAM("?") );
mpPathObj->SetMergedItem( XLineDashItem( aEmpty, aDash ) );
mpPathObj->SetMergedItem( XLineStyleItem( XLINE_DASH ) );
mpPathObj->SetMergedItem( XLineColorItem(aEmpty, ::Color(COL_GRAY)) );
mpPathObj->SetMergedItem( XFillStyleItem( XFILL_NONE ) );
::basegfx::B2DPolygon aStartArrow;
aStartArrow.append(::basegfx::B2DPoint(20.0, 0.0));
aStartArrow.append(::basegfx::B2DPoint(0.0, 0.0));
aStartArrow.append(::basegfx::B2DPoint(10.0, 30.0));
aStartArrow.setClosed(true);
mpPathObj->SetMergedItem(XLineStartItem(aEmpty,::basegfx::B2DPolyPolygon(aStartArrow)));
mpPathObj->SetMergedItem(XLineStartWidthItem(400));
mpPathObj->SetMergedItem(XLineStartCenterItem(sal_True));
updatePathAttributes();
mpPathObj->SetMergedItem(XLineTransparenceItem(50));
mpMark = new SdrMark( mpPathObj, mrView.GetSdrPageView() );
mpPathObj->AddListener( *this );
Reference< XChangesNotifier > xNotifier( mpEffect->getNode(), UNO_QUERY );
if( xNotifier.is() )
{
Reference< XChangesListener > xListener( this );
xNotifier->addChangesListener( this );
}
}
// --------------------------------------------------------------------
MotionPathTag::~MotionPathTag()
{
DBG_ASSERT( mpPathObj == 0, "sd::MotionPathTag::~MotionPathTag(), dispose me first!" );
Dispose();
}
// --------------------------------------------------------------------
void MotionPathTag::updatePathAttributes()
{
String aEmpty( RTL_CONSTASCII_USTRINGPARAM("?") );
::basegfx::B2DPolygon aCandidate;
if( mxPolyPoly.count() )
{
aCandidate = mxPolyPoly.getB2DPolygon(0);
::basegfx::tools::checkClosed( aCandidate );
}
if( !aCandidate.isClosed() )
{
::basegfx::B2DPolygon aEndArrow;
aEndArrow.append(::basegfx::B2DPoint(10.0, 0.0));
aEndArrow.append(::basegfx::B2DPoint(0.0, 30.0));
aEndArrow.append(::basegfx::B2DPoint(20.0, 30.0));
aEndArrow.setClosed(true);
mpPathObj->SetMergedItem(XLineEndItem(aEmpty,::basegfx::B2DPolyPolygon(aEndArrow)));
mpPathObj->SetMergedItem(XLineEndWidthItem(400));
mpPathObj->SetMergedItem(XLineEndCenterItem(sal_True));
}
else
{
mpPathObj->SetMergedItem(XLineEndItem());
}
}
// --------------------------------------------------------------------
void MotionPathTag::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
{
if( mpPathObj && !mbInUpdatePath && dynamic_cast< const SdrHint* >( &rHint ) && (mpEffect.get() != 0) )
{
if( mxPolyPoly != mpPathObj->GetPathPoly() )
{
mbInUpdatePath = true;
mxPolyPoly = mpPathObj->GetPathPoly();
rtl::Reference< MotionPathTag > xTag( this );
mrPane.updatePathFromMotionPathTag( xTag );
msLastPath = mpEffect->getPath();
updatePathAttributes();
mbInUpdatePath = false;
}
}
}
// --------------------------------------------------------------------
void MotionPathTag::MovePath( int nDX, int nDY )
{
if( mpPathObj )
{
mpPathObj->Move( Size( nDX, nDY ) );
mrView.updateHandles();
}
}
// --------------------------------------------------------------------
/** returns true if the MotionPathTag handled the event. */
bool MotionPathTag::MouseButtonDown( const MouseEvent& rMEvt, SmartHdl& rHdl )
{
if( !mpPathObj )
return false;
if( !isSelected() )
{
SmartTagReference xTag( this );
mrView.getSmartTags().select( xTag );
selectionChanged();
return true;
}
else
{
if( rMEvt.IsLeft() && (rMEvt.GetClicks() == 2) )
{
mrView.GetViewShell()->GetViewFrame()->GetDispatcher()->Execute(SID_BEZIER_EDIT, SFX_CALLMODE_ASYNCHRON);
return true;
}
else if( rMEvt.IsLeft() )
{
OutputDevice* pOut = mrView.GetViewShell()->GetActiveWindow();
Point aMDPos( pOut->PixelToLogic( rMEvt.GetPosPixel() ) );
if( !mrView.IsFrameDragSingles() && mrView.IsInsObjPointMode() && (rHdl.GetObjHdlNum() == SMART_TAG_HDL_NUM) )
{
// insert a point in edit mode
const bool bNewObj = rMEvt.IsMod1();
mrView.BrkAction();
Point aPt(aMDPos); // - pMarkedPV->GetOffset());
if(bNewObj)
aPt = mrView.GetSnapPos(aPt,mrView.GetSdrPageView());
sal_Bool bClosed0(mpPathObj->IsClosedObj());
sal_uInt32 nInsPointNum = mpPathObj->NbcInsPointOld(aPt, bNewObj, sal_True);
if(bClosed0 != mpPathObj->IsClosedObj())
{
// Obj was closed implicit
// object changed
mpPathObj->SetChanged();
mpPathObj->BroadcastObjectChange();
}
if(0xffffffff != nInsPointNum)
{
mrView.UnmarkAllPoints();
mrView.updateHandles();
bool bRet = mrView.BegDragObj(aMDPos, pOut, mrView.GetHdl(nInsPointNum+1), 0, new PathDragObjOwn( mrView ) );
if (bRet)
{
const_cast< SdrDragStat* >( &mrView.GetDragStat() )->SetMinMoved();
mrView.MovDragObj(aMDPos);
}
}
return true;
}
else
{
SmartHdl* pHdl = &rHdl;
if (!mrView.IsPointMarked(*pHdl) || rMEvt.IsShift())
{
if (!rMEvt.IsShift())
{
mrView.UnmarkAllPoints();
pHdl = dynamic_cast< SmartHdl* >( mrView.PickHandle(aMDPos) );
}
else
{
if (mrView.IsPointMarked(*pHdl) )
{
mrView.UnmarkPoint(*pHdl);
pHdl = NULL;
}
else
{
pHdl = dynamic_cast< SmartHdl* >( mrView.PickHandle(aMDPos) );
}
}
if (pHdl)
mrView.MarkPoint(*pHdl);
}
if( pHdl && !rMEvt.IsRight() )
{
mrView.BrkAction();
const sal_uInt16 nDrgLog = (sal_uInt16)pOut->PixelToLogic(Size(DRGPIX,0)).Width();
rtl::Reference< MotionPathTag > xTag( this );
SdrDragMethod* pDragMethod;
// #i95646# add DragPoly as geometry to each local SdrDragMethod to be able
// to create the needed local SdrDragEntry for it in createSdrDragEntries()
const basegfx::B2DPolyPolygon aDragPoly(mpPathObj->GetPathPoly());
if( (pHdl->GetKind() == HDL_MOVE) || (pHdl->GetKind() == HDL_SMARTTAG) )
{
pDragMethod = new PathDragMove( mrView, xTag, aDragPoly );
pHdl->SetPos( aMDPos );
}
else if( pHdl->GetKind() == HDL_POLY )
{
pDragMethod = new PathDragObjOwn( mrView, aDragPoly );
}
else
{
pDragMethod = new PathDragResize( mrView, xTag, aDragPoly );
}
mrView.BegDragObj(aMDPos, NULL, pHdl, nDrgLog, pDragMethod );
}
return true;
}
}
}
return false;
}
// --------------------------------------------------------------------
/** returns true if the SmartTag consumes this event. */
bool MotionPathTag::KeyInput( const KeyEvent& rKEvt )
{
if( !mpPathObj )
return false;
sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
switch( nCode )
{
case KEY_DELETE:
return OnDelete();
case KEY_DOWN:
case KEY_UP:
case KEY_LEFT:
case KEY_RIGHT:
return OnMove( rKEvt );
case KEY_ESCAPE:
{
SmartTagReference xThis( this );
mrView.getSmartTags().deselect();
return true;
}
case KEY_TAB:
return OnTabHandles( rKEvt );
case KEY_SPACE:
return OnMarkHandle( rKEvt );
default:
break;
}
return false;
}
bool MotionPathTag::OnDelete()
{
mrPane.remove( mpEffect );
return true;
}
bool MotionPathTag::OnTabHandles( const KeyEvent& rKEvt )
{
if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2())
{
const SdrHdlList& rHdlList = mrView.GetHdlList();
sal_Bool bForward(!rKEvt.GetKeyCode().IsShift());
((SdrHdlList&)rHdlList).TravelFocusHdl(bForward);
// guarantee visibility of focused handle
SdrHdl* pHdl = rHdlList.GetFocusHdl();
if(pHdl)
{
Window* pWindow = mrView.GetViewShell()->GetActiveWindow();
if( pWindow )
{
Point aHdlPosition(pHdl->GetPos());
Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200));
mrView.MakeVisible(aVisRect, *pWindow);
}
}
return true;
}
return false;
}
bool MotionPathTag::OnMarkHandle( const KeyEvent& rKEvt )
{
const SdrHdlList& rHdlList = mrView.GetHdlList();
SdrHdl* pHdl = rHdlList.GetFocusHdl();
if(pHdl && pHdl->GetKind() == HDL_POLY )
{
// rescue ID of point with focus
sal_uInt32 nPol(pHdl->GetPolyNum());
sal_uInt32 nPnt(pHdl->GetPointNum());
if(mrView.IsPointMarked(*pHdl))
{
if(rKEvt.GetKeyCode().IsShift())
{
mrView.UnmarkPoint(*pHdl);
}
}
else
{
if(!rKEvt.GetKeyCode().IsShift())
{
mrView.UnmarkAllPoints();
}
mrView.MarkPoint(*pHdl);
}
if(0L == rHdlList.GetFocusHdl())
{
// restore point with focus
SdrHdl* pNewOne = 0L;
for(sal_uInt32 a(0); !pNewOne && a < rHdlList.GetHdlCount(); a++)
{
SdrHdl* pAct = rHdlList.GetHdl(a);
if(pAct && pAct->GetKind() == HDL_POLY && pAct->GetPolyNum() == nPol && pAct->GetPointNum() == nPnt)
pNewOne = pAct;
}
if(pNewOne)
((SdrHdlList&)rHdlList).SetFocusHdl(pNewOne);
}
}
return true;
}
bool MotionPathTag::OnMove( const KeyEvent& rKEvt )
{
long nX = 0;
long nY = 0;
switch( rKEvt.GetKeyCode().GetCode() )
{
case KEY_UP: nY = -1; break;
case KEY_DOWN: nY = 1; break;
case KEY_LEFT: nX = -1; break;
case KEY_RIGHT: nX = 1; break;
default: break;
}
if(rKEvt.GetKeyCode().IsMod2())
{
OutputDevice* pOut = mrView.GetViewShell()->GetActiveWindow();
Size aLogicSizeOnePixel = (pOut) ? pOut->PixelToLogic(Size(1,1)) : Size(100, 100);
nX *= aLogicSizeOnePixel.Width();
nY *= aLogicSizeOnePixel.Height();
}
else
{
// old, fixed move distance
nX *= 100;
nY *= 100;
}
if( nX || nY )
{
// in point edit mode move the handle with the focus
const SdrHdlList& rHdlList = mrView.GetHdlList();
SdrHdl* pHdl = rHdlList.GetFocusHdl();
if(pHdl)
{
// now move the Handle (nX, nY)
Point aStartPoint(pHdl->GetPos());
Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
// start dragging
rtl::Reference< MotionPathTag > xTag( this );
SdrDragMethod* pDragMethod = 0;
if( (pHdl->GetKind() == HDL_MOVE) || (pHdl->GetKind() == HDL_SMARTTAG) )
{
pDragMethod = new PathDragMove( mrView, xTag );
}
else if( pHdl->GetKind() == HDL_POLY )
{
pDragMethod = new PathDragObjOwn( mrView );
}
else if( pHdl->GetKind() != HDL_BWGT )
{
pDragMethod = new PathDragResize( mrView, xTag );
}
mrView.BegDragObj(aStartPoint, 0, pHdl, 0, pDragMethod);
if(mrView.IsDragObj())
{
FASTBOOL bWasNoSnap = mrView.GetDragStat().IsNoSnap();
sal_Bool bWasSnapEnabled = mrView.IsSnapEnabled();
// switch snapping off
if(!bWasNoSnap)
((SdrDragStat&)mrView.GetDragStat()).SetNoSnap(sal_True);
if(bWasSnapEnabled)
mrView.SetSnapEnabled(sal_False);
mrView.MovAction(aEndPoint);
mrView.EndDragObj();
// restore snap
if(!bWasNoSnap)
((SdrDragStat&)mrView.GetDragStat()).SetNoSnap(bWasNoSnap);
if(bWasSnapEnabled)
mrView.SetSnapEnabled(bWasSnapEnabled);
}
}
else
{
// move the path
MovePath( nX, nY );
}
}
return true;
}
// --------------------------------------------------------------------
sal_uLong MotionPathTag::GetMarkablePointCount() const
{
if( mpPathObj && isSelected() )
{
return mpPathObj->GetPointCount();
}
else
{
return 0;
}
}
// --------------------------------------------------------------------
sal_uLong MotionPathTag::GetMarkedPointCount() const
{
if( mpMark )
{
const SdrUShortCont* pPts=mpMark->GetMarkedPoints();
return pPts ? pPts->GetCount() : 0;
}
else
{
return 0;
}
}
// --------------------------------------------------------------------
sal_Bool MotionPathTag::MarkPoint(SdrHdl& rHdl, sal_Bool bUnmark )
{
sal_Bool bRet=sal_False;
if( mpPathObj && mrView.IsPointMarkable( rHdl ) && (rHdl.GetKind() != HDL_SMARTTAG) )
{
SmartHdl* pSmartHdl = dynamic_cast< SmartHdl* >( &rHdl );
if( pSmartHdl && pSmartHdl->getTag().get() == this )
{
SdrUShortCont* pPts=mpMark->ForceMarkedPoints();
pPts->ForceSort();
if (mrView.MarkPointHelper(&rHdl,mpMark,bUnmark))
{
pPts->ForceSort();
mrView.MarkListHasChanged();
bRet=sal_True;
}
}
}
return bRet;
}
// --------------------------------------------------------------------
sal_Bool MotionPathTag::MarkPoints(const Rectangle* pRect, sal_Bool bUnmark )
{
sal_Bool bChgd=sal_False;
if( mpPathObj && isSelected() )
{
sal_Int32 nHdlNum = mrView.GetHdlList().GetHdlCount() - 1;
while( nHdlNum > 0 )
{
SmartHdl* pHdl = dynamic_cast< SmartHdl* >( mrView.GetHdl( sal::static_int_cast< sal_uLong >( nHdlNum-- ) ) );
if( pHdl && (pHdl->getTag().get() == this) && mrView.IsPointMarkable(*pHdl) && pHdl->IsSelected()==bUnmark)
{
Point aPos(pHdl->GetPos());
if( pRect==NULL || pRect->IsInside(aPos))
{
if( mrView.MarkPointHelper(pHdl,mpMark,bUnmark) )
bChgd=sal_True;
}
}
}
if(bChgd)
mrView.MarkListHasChanged();
}
return bChgd;
}
// --------------------------------------------------------------------
bool MotionPathTag::getContext( SdrViewContext& rContext )
{
if( mpPathObj && isSelected() && !mrView.IsFrameDragSingles() )
{
rContext = SDRCONTEXT_POINTEDIT;
return true;
}
else
{
return false;
}
}
// --------------------------------------------------------------------
void MotionPathTag::CheckPossibilities()
{
if( mpPathObj )
{
if( isSelected() )
{
mrView.SetMoveAllowed( true );
mrView.SetMoveProtected( false );
mrView.SetResizeFreeAllowed( true );
mrView.SetResizePropAllowed( true );
mrView.SetResizeProtected( false );
if( !mrView.IsFrameDragSingles() )
{
bool b1stSmooth(true);
bool b1stSegm(true);
bool bCurve(false);
bool bSmoothFuz(false);
bool bSegmFuz(false);
basegfx::B2VectorContinuity eSmooth = basegfx::CONTINUITY_NONE;
mrView.CheckPolyPossibilitiesHelper( mpMark, b1stSmooth, b1stSegm, bCurve, bSmoothFuz, bSegmFuz, eSmooth );
}
}
}
}
// --------------------------------------------------------------------
void MotionPathTag::addCustomHandles( SdrHdlList& rHandlerList )
{
if( mpPathObj )
{
::com::sun::star::awt::Point aPos( mxOrigin->getPosition() );
if( (aPos.X != maOriginPos.X) || (aPos.Y != maOriginPos.Y) )
{
const basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(
aPos.X - maOriginPos.X, aPos.Y - maOriginPos.Y));
mxPolyPoly.transform( aTransform );
mpPathObj->SetPathPoly( mxPolyPoly );
maOriginPos = aPos;
}
SmartTagReference xThis( this );
SdPathHdl* pHdl = new SdPathHdl( xThis, mpPathObj );
pHdl->SetObjHdlNum( SMART_TAG_HDL_NUM );
pHdl->SetPageView( mrView.GetSdrPageView() );
pHdl->SetObj(mpPathObj);
rHandlerList.AddHdl( pHdl );
if( isSelected() )
{
mrView.GetSdrPageView()->SetHasMarkedObj(sal_True);
if( !mrView.IsFrameDragSingles() )
{
SdrHdlList aTemp( rHandlerList.GetView() );
mpPathObj->AddToHdlList( aTemp );
const SdrUShortCont* pMrkPnts=mpMark->GetMarkedPoints();
sal_uInt32 nHandle;
for( nHandle = 0; nHandle < aTemp.GetHdlCount(); ++nHandle )
{
SdrHdl* pTempHdl = aTemp.GetHdl( nHandle );
SmartHdl* pSmartHdl = new SmartHdl( xThis, mpPathObj, pTempHdl->GetPos(), pTempHdl->GetKind() );
pSmartHdl->SetObjHdlNum( nHandle );
pSmartHdl->SetPolyNum( pTempHdl->GetPolyNum() );
pSmartHdl->SetPointNum( pTempHdl->GetPointNum() );
pSmartHdl->SetPlusHdl( pTempHdl->IsPlusHdl() );
pSmartHdl->SetSourceHdlNum( pTempHdl->GetSourceHdlNum() );
pSmartHdl->SetPageView( mrView.GetSdrPageView() );
rHandlerList.AddHdl( pSmartHdl );
const bool bSelected= pMrkPnts && pMrkPnts->Exist(sal::static_int_cast< sal_uInt16 >(nHandle));
pSmartHdl->SetSelected(bSelected);
if( mrView.IsPlusHandlesAlwaysVisible() || bSelected )
{
sal_uInt32 nPlusAnz=mpPathObj->GetPlusHdlCount(*pSmartHdl);
for (sal_uInt32 nPlusNum=0; nPlusNum<nPlusAnz; nPlusNum++)
{
SdrHdl* pPlusHdl = mpPathObj->GetPlusHdl(*pSmartHdl,nPlusNum);
if (pPlusHdl!=NULL)
{
pPlusHdl->SetObj(mpPathObj);
pPlusHdl->SetPageView(mrView.GetSdrPageView());
pPlusHdl->SetPlusHdl(sal_True);
rHandlerList.AddHdl(pPlusHdl);
}
}
}
}
}
else
{
Rectangle aRect(mpPathObj->GetCurrentBoundRect());
if(!aRect.IsEmpty())
{
sal_uLong nCount = rHandlerList.GetHdlCount();
sal_Bool bWdt0=aRect.Left()==aRect.Right();
sal_Bool bHgt0=aRect.Top()==aRect.Bottom();
if (bWdt0 && bHgt0)
{
rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.TopLeft(),HDL_UPLFT));
}
else if (bWdt0 || bHgt0)
{
rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.TopLeft() ,HDL_UPLFT));
rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.BottomRight(),HDL_LWRGT));
}
else
{
if (!bWdt0 && !bHgt0) rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.TopLeft() ,HDL_UPLFT));
if ( !bHgt0) rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.TopCenter() ,HDL_UPPER));
if (!bWdt0 && !bHgt0) rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.TopRight() ,HDL_UPRGT));
if (!bWdt0 ) rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.LeftCenter() ,HDL_LEFT ));
if (!bWdt0 ) rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.RightCenter() ,HDL_RIGHT));
if (!bWdt0 && !bHgt0) rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.BottomLeft() ,HDL_LWLFT));
if ( !bHgt0) rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.BottomCenter(),HDL_LOWER));
if (!bWdt0 && !bHgt0) rHandlerList.AddHdl(new SmartHdl( xThis, mpPathObj, aRect.BottomRight() ,HDL_LWRGT));
}
while( nCount < rHandlerList.GetHdlCount() )
{
rHandlerList.GetHdl(nCount++)->SetPageView( mrView.GetSdrPageView() );
}
}
}
}
}
}
// --------------------------------------------------------------------
void MotionPathTag::disposing()
{
Reference< XChangesNotifier > xNotifier( mpEffect->getNode(), UNO_QUERY );
if( xNotifier.is() )
{
Reference< XChangesListener > xListener( this );
xNotifier->removeChangesListener( this );
}
if( mpPathObj )
{
SdrPathObj* pPathObj = mpPathObj;
mpPathObj = 0;
mrView.updateHandles();
delete pPathObj;
}
if( mpMark )
{
delete mpMark;
mpMark = 0;
}
SmartTag::disposing();
}
// --------------------------------------------------------------------
void MotionPathTag::deselect()
{
SmartTag::deselect();
if( mpMark )
{
SdrUShortCont* pPts = mpMark->GetMarkedPoints();
if( pPts )
pPts->Clear();
}
selectionChanged();
}
void MotionPathTag::selectionChanged()
{
if( mrView.GetViewShell() && mrView.GetViewShell()->GetViewFrame() )
{
SfxBindings& rBindings = mrView.GetViewShell()->GetViewFrame()->GetBindings();
rBindings.InvalidateAll(sal_True);
}
}
// --------------------------------------------------------------------
// IPolyPolygonEditorController
// --------------------------------------------------------------------
void MotionPathTag::DeleteMarkedPoints()
{
if( mpPathObj && IsDeleteMarkedPointsPossible() )
{
mrView.BrkAction();
// Description
// BegUndo(ImpGetResStr(STR_EditDelete),GetDescriptionOfMarkedPoints(),SDRREPFUNC_OBJ_DELETE);
SdrUShortCont* pPts = mpMark->GetMarkedPoints();
if( pPts )
{
PolyPolygonEditor aEditor( mpPathObj->GetPathPoly(), mpPathObj->IsClosed() );
if( aEditor.DeletePoints( pPts->getContainer() ) )
{
if( aEditor.GetPolyPolygon().count() )
{
// AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath ));
mpPathObj->SetPathPoly( aEditor.GetPolyPolygon() );
}
else
{
// AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoDeleteObject(*pPath ) );
// pM->GetPageView()->GetObjList()->RemoveObject(pObj->GetOrdNum());
}
mrView.UnmarkAllPoints();
mrView.MarkListHasChanged();
mrView.updateHandles();
}
}
// EndUndo();
}
}
sal_Bool MotionPathTag::IsDeleteMarkedPointsPossible() const
{
return mpPathObj && isSelected() && (GetMarkedPointCount() != 0);
}
void MotionPathTag::RipUpAtMarkedPoints()
{
// not supported for motion path
}
bool MotionPathTag::IsRipUpAtMarkedPointsPossible() const
{
// not supported for motion path
return false;
}
sal_Bool MotionPathTag::IsSetMarkedSegmentsKindPossible() const
{
if( mpPathObj )
return mrView.IsSetMarkedSegmentsKindPossible();
else
return sal_False;
}
SdrPathSegmentKind MotionPathTag::GetMarkedSegmentsKind() const
{
if( mpPathObj )
return mrView.GetMarkedSegmentsKind();
else
return SDRPATHSEGMENT_LINE;
}
void MotionPathTag::SetMarkedSegmentsKind(SdrPathSegmentKind eKind)
{
if(mpPathObj && isSelected() && (GetMarkedPointCount() != 0))
{
SdrUShortCont* pPts = mpMark->GetMarkedPoints();
if(pPts)
{
PolyPolygonEditor aEditor( mpPathObj->GetPathPoly(), mpPathObj->IsClosed() );
if(aEditor.SetSegmentsKind( eKind, pPts->getContainer()) )
{
// AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath));
mpPathObj->SetPathPoly(aEditor.GetPolyPolygon());
mrView.MarkListHasChanged();
mrView.updateHandles();
}
}
}
}
sal_Bool MotionPathTag::IsSetMarkedPointsSmoothPossible() const
{
if( mpPathObj )
return mrView.IsSetMarkedPointsSmoothPossible();
else
return sal_False;
}
SdrPathSmoothKind MotionPathTag::GetMarkedPointsSmooth() const
{
if( mpPathObj )
return mrView.GetMarkedPointsSmooth();
else
return SDRPATHSMOOTH_ANGULAR;
}
void MotionPathTag::SetMarkedPointsSmooth(SdrPathSmoothKind eKind)
{
basegfx::B2VectorContinuity eFlags;
if(SDRPATHSMOOTH_ANGULAR == eKind)
{
eFlags = basegfx::CONTINUITY_NONE;
}
else if(SDRPATHSMOOTH_ASYMMETRIC == eKind)
{
eFlags = basegfx::CONTINUITY_C1;
}
else if(SDRPATHSMOOTH_SYMMETRIC == eKind)
{
eFlags = basegfx::CONTINUITY_C2;
}
else
{
return;
}
if(mpPathObj && mpMark && isSelected() && (GetMarkedPointCount() != 0))
{
SdrUShortCont* pPts = mpMark->GetMarkedPoints();
if(pPts)
{
PolyPolygonEditor aEditor( mpPathObj->GetPathPoly(), mpPathObj->IsClosed() );
if(aEditor.SetPointsSmooth( eFlags, pPts->getContainer() ) )
{
// AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pPath));
mpPathObj->SetPathPoly(aEditor.GetPolyPolygon());
mrView.MarkListHasChanged();
mrView.updateHandles();
}
}
}
}
void MotionPathTag::CloseMarkedObjects(sal_Bool /*bToggle*/, sal_Bool /*bOpen*/ )
{
// not supported for motion path
}
bool MotionPathTag::IsOpenCloseMarkedObjectsPossible() const
{
// not supported for motion path
return false;
}
SdrObjClosedKind MotionPathTag::GetMarkedObjectsClosedState() const
{
// not supported for motion path
return SDROBJCLOSED_OPEN;
}
// XChangesListener
void SAL_CALL MotionPathTag::changesOccurred( const ChangesEvent& /*Event*/ ) throw (RuntimeException)
{
if( mpPathObj && !mbInUpdatePath && (mpEffect->getPath() != msLastPath) )
{
mbInUpdatePath =true;
msLastPath = mpEffect->getPath();
mpEffect->updateSdrPathObjFromPath( *mpPathObj );
mbInUpdatePath = false;
updatePathAttributes();
mrView.updateHandles();
}
}
void SAL_CALL MotionPathTag::disposing( const EventObject& /*Source*/ ) throw (RuntimeException)
{
if( mpPathObj )
Dispose();
}
Any SAL_CALL MotionPathTag::queryInterface( const ::com::sun::star::uno::Type& aType ) throw (RuntimeException)
{
if( aType == XChangesListener::static_type() )
return Any( Reference< XChangesListener >( this ) );
if( aType == XEventListener::static_type() )
return Any( Reference< XEventListener >( this ) );
if( aType == XInterface::static_type() )
return Any( Reference< XInterface >( this ) );
return Any();
}
void SAL_CALL MotionPathTag::acquire() throw ()
{
SimpleReferenceComponent::acquire();
}
void SAL_CALL MotionPathTag::release( ) throw ()
{
SimpleReferenceComponent::release();
}
} // end of namespace sd