/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: svddrag.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006/06/19 14:42:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SVDDRAG_HXX
#define _SVDDRAG_HXX

#ifndef _CONTNR_HXX //autogen
#include <tools/contnr.hxx>
#endif

#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif

#ifndef _FRACT_HXX //autogen
#include <tools/fract.hxx>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

// Statushalter fuer objektspeziefisches Draggen. Damit das Model
// Statusfrei bleibt werden die Statusdaten an der View gehalten
// und dem Objekt zu gegebener Zeit als Parameter uebergeben.
// Ausserdem auch Statushalter fuer den Vorgang der Interaktiven
// Objekterzeugung. pHdl ist in diesem Fall NULL.
class SdrHdl;
class SdrView;
class SdrPageView;
class SdrDragMethod;

struct SVX_DLLPUBLIC SdrDragStatUserData
{
};

class SVX_DLLPUBLIC SdrDragStat {
protected:
	SdrHdl*  pHdl;      // Der Handle an dem der User zottelt
	SdrView* pView;
	SdrPageView* pPageView;
	Container aPnts;    // Alle bisherigen Punkte: [0]=Start, [Count()-2]=Prev
	Point     aRef1;     // Referenzpunkt: Resize-Fixpunkt, (Drehachse,
	Point     aRef2;     // Spiegelachse, ...)
	Point     aPos0;     // Position beim letzten Event
	Point     aRealPos0; // Position beim letzten Event
	Point     aRealNow;  // Aktuelle Dragposition ohne Snap, Ortho und Limit
	Point     aRealLast; // RealPos des letzten Punkts (fuer MinMoved)
	Rectangle aActionRect;

	// Reserve fuer kompatible Erweiterungen, die sonst inkompatibel wuerden.
	Point     aReservePoint1;
	Point     aReservePoint2;
	Point     aReservePoint3;
	Point     aReservePoint4;
	Rectangle aReserveRect1;
	Rectangle aReserveRect2;
	FASTBOOL  bEndDragChangesAttributes;
	FASTBOOL  bEndDragChangesGeoAndAttributes;
	FASTBOOL  bMouseIsUp;
	FASTBOOL  aReserveBool3;
	FASTBOOL  aReserveBool4;
	long      aReserveLong1;
	long      aReserveLong2;
	long      aReserveLong3;
	long      aReserveLong4;
	void*     aReservePtr1;
	void*     aReservePtr2;
	void*     aReservePtr3;
	void*     aReservePtr4;

	FASTBOOL  bShown;    // Xor sichrbar?
	USHORT    nMinMov;   // Soviel muss erstmal minimal bewegt werden
	FASTBOOL  bMinMoved; // MinMove durchbrochen?

	FASTBOOL  bHorFixed; // nur Vertikal draggen
	FASTBOOL  bVerFixed; // nur Horizontal draggen
	FASTBOOL  bWantNoSnap; // TRUE=Fuer die Entscheidung ob fuer pObj->MovCreate() NoSnapPos verwendet
						  // werden soll. Entsprechend wird auch NoSnapPos in den Buffer geschrieben.
	FASTBOOL  bOrtho4;
	FASTBOOL  bOrtho8;

	SdrDragMethod* pDragMethod;

protected:
	void Clear(FASTBOOL bLeaveOne);
	Point& Pnt(ULONG nNum)                           { return *((Point*)aPnts.GetObject(nNum)); }
//public:
	SdrDragStatUserData*    pUser;     // Userdata
public:
	SdrDragStat(): aPnts(1024,16,16)                 { pUser=NULL; Reset(); }
	~SdrDragStat()                                   { Clear(FALSE); }
	void         Reset();
	SdrView*     GetView() const                     { return pView; }
	void         SetView(SdrView* pV)                { pView=pV; }
	SdrPageView* GetPageView() const                 { return pPageView; }
	void         SetPageView(SdrPageView* pPV)       { pPageView=pPV; }
	const Point& GetPoint(ULONG nNum) const          { return *((Point*)aPnts.GetObject(nNum)); }
	ULONG        GetPointAnz() const                 { return aPnts.Count(); }
	const Point& GetStart() const                    { return GetPoint(0); }
	Point&       Start()                             { return Pnt(0); }
	const Point& GetPrev() const                     { return GetPoint(GetPointAnz()-(GetPointAnz()>=2 ? 2:1)); }
	Point& Prev()                                    { return Pnt(GetPointAnz()-(GetPointAnz()>=2 ? 2:1)); }
	const Point& GetPos0() const                     { return aPos0;  }
	Point&       Pos0()                              { return aPos0;  }
	const Point& GetNow() const                      { return GetPoint(GetPointAnz()-1); }
	Point&       Now()                               { return Pnt(GetPointAnz()-1); }
	const Point& GetRealNow() const                  { return aRealNow; }
	Point&       RealNow()                           { return aRealNow; }
	const Point& GetRef1() const                     { return aRef1;  }
	Point&       Ref1()                              { return aRef1;  }
	const Point& GetRef2() const                     { return aRef2;  }
	Point&       Ref2()                              { return aRef2;  }
	const        SdrHdl* GetHdl() const              { return pHdl;   }
	void         SetHdl(SdrHdl* pH)                  { pHdl=pH;       }
	SdrDragStatUserData* GetUser() const             { return pUser;  }
	void SetUser(SdrDragStatUserData* pU)            { pUser=pU; }
	FASTBOOL     IsShown() const                     { return bShown; }
	void         SetShown(FASTBOOL bOn)              { bShown=bOn; }

	FASTBOOL     IsMinMoved() const                  { return bMinMoved; }
	void         SetMinMoved()                       { bMinMoved=TRUE; }
	void         ResetMinMoved()                     { bMinMoved=FALSE; }
	void         SetMinMove(USHORT nDist)            { nMinMov=nDist; if (nMinMov<1) nMinMov=1; }
	USHORT       GetMinMove() const                  { return nMinMov; }

	FASTBOOL     IsHorFixed() const                  { return bHorFixed; }
	void         SetHorFixed(FASTBOOL bOn)           { bHorFixed=bOn; }
	FASTBOOL     IsVerFixed() const                  { return bVerFixed; }
	void         SetVerFixed(FASTBOOL bOn)           { bVerFixed=bOn; }

	// Hier kann das Obj sagen: "Ich will keinen Koordinatenfang!"
	// z.B. fuer den Winkel des Kreisbogen...
	FASTBOOL     IsNoSnap() const                     { return bWantNoSnap; }
	void         SetNoSnap(FASTBOOL bOn=TRUE)         { bWantNoSnap=bOn; }

	// Und hier kann das Obj sagen welches Ortho (wenn ueberhaupt eins)
	// sinnvoll auf ihm angewendet werden kann.
	// Ortho4 bedeutet Ortho in 4 Richtungen (fuer Rect und Cirt)
	FASTBOOL     IsOrtho4Possible() const             { return bOrtho4; }
	void         SetOrtho4Possible(FASTBOOL bOn=TRUE) { bOrtho4=bOn; }
	// Ortho8 bedeutet Ortho in 8 Richtungen (fuer Linien)
	FASTBOOL     IsOrtho8Possible() const             { return bOrtho8; }
	void         SetOrtho8Possible(FASTBOOL bOn=TRUE) { bOrtho8=bOn; }

	// Wird vom gedraggten Objekt gesetzt
	FASTBOOL     IsEndDragChangesAttributes() const   { return bEndDragChangesAttributes; }
	void         SetEndDragChangesAttributes(FASTBOOL bOn) { bEndDragChangesAttributes=bOn; }
	FASTBOOL     IsEndDragChangesGeoAndAttributes() const   { return bEndDragChangesGeoAndAttributes; }
	void         SetEndDragChangesGeoAndAttributes(FASTBOOL bOn) { bEndDragChangesGeoAndAttributes=bOn; }

	// Wird von der View gesetzt und kann vom Obj ausgewertet werden
	FASTBOOL     IsMouseDown() const                  { return !bMouseIsUp; }
	void         SetMouseDown(FASTBOOL bDown)         { bMouseIsUp=!bDown; }

	Point KorregPos(const Point& rNow, const Point& rPrev) const;
	void  Reset(const Point& rPnt);
	void  NextMove(const Point& rPnt);
	void  NextPoint(FASTBOOL bSaveReal=FALSE);
	void  PrevPoint();
	FASTBOOL CheckMinMoved(const Point& rPnt);
	long  GetDX() const                     { return GetNow().X()-GetPrev().X(); }
	long  GetDY() const                     { return GetNow().Y()-GetPrev().Y(); }
	Fraction GetXFact() const;
	Fraction GetYFact() const;

	SdrDragMethod* GetDragMethod() const               { return pDragMethod; }
	void           SetDragMethod(SdrDragMethod* pMth)  { pDragMethod=pMth; }

	const Rectangle& GetActionRect() const             { return aActionRect; }
	void             SetActionRect(const Rectangle& rR) { aActionRect=rR; }

	// Unter Beruecksichtigung von 1stPointAsCenter
	void TakeCreateRect(Rectangle& rRect) const;
};

#endif //_SVDDRAG_HXX

