/**************************************************************
 * 
 * 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_svx.hxx"

#include <svx/svdcrtv.hxx>
#include "svx/xattr.hxx"
#include <svx/svdundo.hxx>
#include <svx/svdocapt.hxx> // Spezialbehandlung: Nach dem Create transparente Fuellung
#include <svx/svdoedge.hxx>
#include <svx/svdpagv.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdetc.hxx>
#include <svx/scene3d.hxx>
#include <svx/view3d.hxx>
#include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
#include <svx/sdr/contact/displayinfo.hxx>
#include <svx/svdouno.hxx>
#define XOR_CREATE_PEN			PEN_SOLID
#include <svx/svdopath.hxx>
#include <svx/sdr/overlay/overlaypolypolygon.hxx>
#include <svx/sdr/overlay/overlaymanager.hxx>
#include <svx/sdrpaintwindow.hxx>
#include "fmobj.hxx"
#include <svx/svdocirc.hxx>
#include <svx/sdr/contact/viewcontact.hxx>
#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
#include <svx/sdr/overlay/overlaymanager.hxx>

////////////////////////////////////////////////////////////////////////////////////////////////////

class ImplConnectMarkerOverlay
{
	// The OverlayObjects
	::sdr::overlay::OverlayObjectList				maObjects;

	// The remembered target object
	const SdrObject&								mrObject;

public:
	ImplConnectMarkerOverlay(const SdrCreateView& rView, SdrObject& rObject);
	~ImplConnectMarkerOverlay();

	const SdrObject& GetTargetObject() const { return mrObject; }
};

ImplConnectMarkerOverlay::ImplConnectMarkerOverlay(const SdrCreateView& rView, SdrObject& rObject)
:	mrObject(rObject)
{
	basegfx::B2DPolyPolygon aB2DPolyPolygon(rObject.TakeXorPoly());

	for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++)
	{
		SdrPaintWindow* pCandidate = rView.GetPaintWindow(a);
		::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager();

		if(pTargetOverlay)
		{
			Size aHalfLogicSize(pTargetOverlay->getOutputDevice().PixelToLogic(Size(4, 4)));

			// object
			::sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
                aB2DPolyPolygon);
			pTargetOverlay->add(*pNew);
			maObjects.append(*pNew);

			// gluepoints
			if(rView.IsAutoVertexConnectors()) 
			{
				for(sal_uInt16 i(0); i < 4; i++) 
				{
					SdrGluePoint aGluePoint(rObject.GetVertexGluePoint(i));
					const Point& rPosition = aGluePoint.GetAbsolutePos(rObject);

					basegfx::B2DPoint aTopLeft(rPosition.X() - aHalfLogicSize.Width(), rPosition.Y() - aHalfLogicSize.Height());
					basegfx::B2DPoint aBottomRight(rPosition.X() + aHalfLogicSize.Width(), rPosition.Y() + aHalfLogicSize.Height());

					basegfx::B2DPolygon aTempPoly;
					aTempPoly.append(aTopLeft);
					aTempPoly.append(basegfx::B2DPoint(aBottomRight.getX(), aTopLeft.getY()));
					aTempPoly.append(aBottomRight);
					aTempPoly.append(basegfx::B2DPoint(aTopLeft.getX(), aBottomRight.getY()));
					aTempPoly.setClosed(true);

					basegfx::B2DPolyPolygon aTempPolyPoly;
					aTempPolyPoly.append(aTempPoly);

					pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
                        aTempPolyPoly);
					pTargetOverlay->add(*pNew);
					maObjects.append(*pNew);
				}
			}
		}
	}
}

ImplConnectMarkerOverlay::~ImplConnectMarkerOverlay()
{
	// The OverlayObjects are cleared using the destructor of OverlayObjectList.
	// That destructor calls clear() at the list which removes all objects from the
	// OverlayManager and deletes them.
}

////////////////////////////////////////////////////////////////////////////////////////////////////

class ImpSdrCreateViewExtraData
{
	// The OverlayObjects for XOR replacement
	::sdr::overlay::OverlayObjectList				maObjects;

public:
	ImpSdrCreateViewExtraData();
	~ImpSdrCreateViewExtraData();

	void CreateAndShowOverlay(const SdrCreateView& rView, const SdrObject* pObject, const basegfx::B2DPolyPolygon& rPolyPoly);
	void HideOverlay();
};

ImpSdrCreateViewExtraData::ImpSdrCreateViewExtraData()
{
}

ImpSdrCreateViewExtraData::~ImpSdrCreateViewExtraData()
{
	HideOverlay();
}

void ImpSdrCreateViewExtraData::CreateAndShowOverlay(const SdrCreateView& rView, const SdrObject* pObject, const basegfx::B2DPolyPolygon& rPolyPoly)
{
	for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++)
	{
		SdrPaintWindow* pCandidate = rView.GetPaintWindow(a);
		::sdr::overlay::OverlayManager* pOverlayManager = pCandidate->GetOverlayManager();

		if(pOverlayManager)
		{
			if(pObject)
			{
				const sdr::contact::ViewContact& rVC = pObject->GetViewContact();
				const drawinglayer::primitive2d::Primitive2DSequence aSequence = rVC.getViewIndependentPrimitive2DSequence();
				sdr::overlay::OverlayObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence);
			    
				pOverlayManager->add(*pNew);
			    maObjects.append(*pNew);
			}

			if(rPolyPoly.count())
			{
				::sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
                    rPolyPoly);
				pOverlayManager->add(*pNew);
				maObjects.append(*pNew);
			}
		}
	}
}

void ImpSdrCreateViewExtraData::HideOverlay()
{
	// the clear() call at the list removes all objects from the
	// OverlayManager and deletes them.
	maObjects.clear();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
//
//   @@@@  @@@@@  @@@@@  @@@@  @@@@@@ @@@@@  @@ @@ @@ @@@@@ @@   @@
//  @@  @@ @@  @@ @@    @@  @@   @@   @@     @@ @@ @@ @@    @@   @@
//  @@     @@  @@ @@    @@  @@   @@   @@     @@ @@ @@ @@    @@ @ @@
//  @@     @@@@@  @@@@  @@@@@@   @@   @@@@   @@@@@ @@ @@@@  @@@@@@@
//  @@     @@  @@ @@    @@  @@   @@   @@      @@@  @@ @@    @@@@@@@
//  @@  @@ @@  @@ @@    @@  @@   @@   @@      @@@  @@ @@    @@@ @@@
//   @@@@  @@  @@ @@@@@ @@  @@   @@   @@@@@    @   @@ @@@@@ @@   @@
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void SdrCreateView::ImpClearConnectMarker()
{
	if(mpCoMaOverlay)
	{
		delete mpCoMaOverlay;
		mpCoMaOverlay = 0L;
	}
}

void SdrCreateView::ImpClearVars()
{
	nAktInvent=SdrInventor;
	nAktIdent=OBJ_NONE;
	pAktCreate=NULL;
	pCreatePV=NULL;
	bAutoTextEdit=sal_False;
	b1stPointAsCenter=sal_False;
	aAktCreatePointer=Pointer(POINTER_CROSS);
	bUseIncompatiblePathCreateInterface=sal_False;
	bAutoClosePolys=sal_True;
	nAutoCloseDistPix=5;
	nFreeHandMinDistPix=10;

	ImpClearConnectMarker();
}

void SdrCreateView::ImpMakeCreateAttr()
{
}

SdrCreateView::SdrCreateView(SdrModel* pModel1, OutputDevice* pOut)
:	SdrDragView(pModel1,pOut),
	mpCoMaOverlay(0L),
	mpCreateViewExtraData(new ImpSdrCreateViewExtraData())
{
	ImpClearVars();
	ImpMakeCreateAttr();
}

SdrCreateView::~SdrCreateView()
{
	ImpClearConnectMarker();
	delete mpCreateViewExtraData;
    SdrObject::Free( pAktCreate );
}

void SdrCreateView::ImpDelCreateAttr()
{
}

sal_Bool SdrCreateView::IsAction() const
{
	return SdrDragView::IsAction() || pAktCreate!=NULL;
}

void SdrCreateView::MovAction(const Point& rPnt)
{
	SdrDragView::MovAction(rPnt);
	if (pAktCreate!=NULL) {
		MovCreateObj(rPnt);
	}
}

void SdrCreateView::EndAction()
{
	if (pAktCreate!=NULL) EndCreateObj(SDRCREATE_FORCEEND);
	SdrDragView::EndAction();
}

void SdrCreateView::BckAction()
{
	if (pAktCreate!=NULL) BckCreateObj();
	SdrDragView::BckAction();
}

void SdrCreateView::BrkAction()
{
	SdrDragView::BrkAction();
	BrkCreateObj();
}

void SdrCreateView::TakeActionRect(Rectangle& rRect) const
{
	if (pAktCreate!=NULL) 
	{
		rRect=aDragStat.GetActionRect();
		if (rRect.IsEmpty()) 
		{
			rRect=Rectangle(aDragStat.GetPrev(),aDragStat.GetNow());
		}
	} 
	else 
	{
		SdrDragView::TakeActionRect(rRect);
	}
}

sal_Bool SdrCreateView::CheckEdgeMode()
{
	sal_uInt32 nInv=nAktInvent;
	sal_uInt16 nIdn=nAktIdent;
	if (pAktCreate!=NULL) 
	{
		nInv=pAktCreate->GetObjInventor();
		nIdn=pAktCreate->GetObjIdentifier();
		// wird vom EdgeObj gemanaged
		if (nAktInvent==SdrInventor && nAktIdent==OBJ_EDGE) return sal_False;
	}
	
	if (!IsCreateMode() || nAktInvent!=SdrInventor || nAktIdent!=OBJ_EDGE) 
	{
		ImpClearConnectMarker();
		return sal_False;
	} 
	else 
	{
		// sal_True heisst: MouseMove soll Connect checken
		return !IsAction();
	}
}

void SdrCreateView::SetConnectMarker(const SdrObjConnection& rCon, const SdrPageView& /*rPV*/)
{
	SdrObject* pTargetObject = rCon.pObj;

	if(pTargetObject) 
	{
		// if target object changes, throw away overlay object to make room for changes
		if(mpCoMaOverlay && pTargetObject != &mpCoMaOverlay->GetTargetObject())
		{
			ImpClearConnectMarker();
		}

		if(!mpCoMaOverlay)
		{
			mpCoMaOverlay = new ImplConnectMarkerOverlay(*this, *pTargetObject);
		}
	} 
	else 
	{
		ImpClearConnectMarker();
	}
}

void SdrCreateView::HideConnectMarker()
{
	ImpClearConnectMarker();
}

sal_Bool SdrCreateView::MouseMove(const MouseEvent& rMEvt, Window* pWin)
{
	if(CheckEdgeMode() && pWin) 
	{
		SdrPageView* pPV = GetSdrPageView();
	
		if(pPV) 
		{
			// Defaultete Hit-Toleranz bei IsMarkedHit() mal aendern !!!!
			Point aPos(pWin->PixelToLogic(rMEvt.GetPosPixel()));
			sal_Bool bMarkHit=PickHandle(aPos)!=NULL || IsMarkedObjHit(aPos);
			SdrObjConnection aCon;
			if (!bMarkHit) SdrEdgeObj::ImpFindConnector(aPos,*pPV,aCon,NULL,pWin);
			SetConnectMarker(aCon,*pPV);
		}
	}
	return SdrDragView::MouseMove(rMEvt,pWin);
}

sal_Bool SdrCreateView::IsTextTool() const
{
	return eEditMode==SDREDITMODE_CREATE && nAktInvent==SdrInventor && (nAktIdent==OBJ_TEXT || nAktIdent==OBJ_TEXTEXT || nAktIdent==OBJ_TITLETEXT || nAktIdent==OBJ_OUTLINETEXT);
}

sal_Bool SdrCreateView::IsEdgeTool() const
{
	return eEditMode==SDREDITMODE_CREATE && nAktInvent==SdrInventor && (nAktIdent==OBJ_EDGE);
}

sal_Bool SdrCreateView::IsMeasureTool() const
{
	return eEditMode==SDREDITMODE_CREATE && nAktInvent==SdrInventor && (nAktIdent==OBJ_MEASURE);
}

void SdrCreateView::SetCurrentObj(sal_uInt16 nIdent, sal_uInt32 nInvent)
{
	if (nAktInvent!=nInvent || nAktIdent!=nIdent) 
	{
		nAktInvent=nInvent;
		nAktIdent=nIdent;
		SdrObject* pObj = SdrObjFactory::MakeNewObject(nInvent,nIdent,NULL,NULL);
		
		if(pObj) 
		{
			// Auf pers. Wunsch von Marco:
			// Mauszeiger bei Textwerkzeug immer I-Beam. Fadenkreuz
			// mit kleinem I-Beam erst bai MouseButtonDown
			if(IsTextTool()) 
			{
				// #81944# AW: Here the correct pointer needs to be used
				// if the default is set to vertical writing
				aAktCreatePointer = POINTER_TEXT;
			}
			else 
				aAktCreatePointer = pObj->GetCreatePointer();

			SdrObject::Free( pObj );
		} 
		else 
		{
			aAktCreatePointer = Pointer(POINTER_CROSS);
		}
	}

	CheckEdgeMode();
	ImpSetGlueVisible3(IsEdgeTool());
}

sal_Bool SdrCreateView::ImpBegCreateObj(sal_uInt32 nInvent, sal_uInt16 nIdent, const Point& rPnt, OutputDevice* pOut,
	short nMinMov, SdrPageView* pPV, const Rectangle& rLogRect, SdrObject* pPreparedFactoryObject)
{
	sal_Bool bRet=sal_False;
	UnmarkAllObj();
	BrkAction();
	
	ImpClearConnectMarker();

	if (pPV!=NULL) 
	{
		pCreatePV=pPV;
	}
	else 
	{
		pCreatePV = GetSdrPageView();
	}
	if (pCreatePV!=NULL) 
	{ // ansonsten keine Seite angemeldet!
		String aLay(aAktLayer);
		
		if(nInvent == SdrInventor && nIdent == OBJ_MEASURE && aMeasureLayer.Len()) 
		{
			aLay = aMeasureLayer;
		}

		SdrLayerID nLayer=pCreatePV->GetPage()->GetLayerAdmin().GetLayerID(aLay,sal_True);
		if (nLayer==SDRLAYER_NOTFOUND) nLayer=0;
		if (!pCreatePV->GetLockedLayers().IsSet(nLayer) && pCreatePV->GetVisibleLayers().IsSet(nLayer)) 
		{
			if(pPreparedFactoryObject)
			{
				pAktCreate = pPreparedFactoryObject;
				
				if(pCreatePV->GetPage())
				{
					pAktCreate->SetPage(pCreatePV->GetPage());
				}
				else if (pMod)
				{
					pAktCreate->SetModel(pMod);
				}
			}
			else
			{
				pAktCreate = SdrObjFactory::MakeNewObject(nInvent, nIdent, pCreatePV->GetPage(), pMod);
			}

			Point aPnt(rPnt);
			if (nAktInvent!=SdrInventor || (nAktIdent!=sal_uInt16(OBJ_EDGE) &&
											nAktIdent!=sal_uInt16(OBJ_FREELINE) &&
											nAktIdent!=sal_uInt16(OBJ_FREEFILL) )) { // Kein Fang fuer Edge und Freihand!
				aPnt=GetSnapPos(aPnt,pCreatePV);
			}
			if (pAktCreate!=NULL) 
			{
				sal_Bool bStartEdit=sal_False; // nach Ende von Create automatisch TextEdit starten
				if (pDefaultStyleSheet!=NULL) pAktCreate->NbcSetStyleSheet(pDefaultStyleSheet, sal_False);

				// #101618# SW uses a naked SdrObject for frame construction. Normally, such an
				// object should not be created. Since it is possible to use it as a helper
				// object (e.g. in letting the user define an area with the interactive
				// construction) at least no items should be set at that object.
				if(nInvent != SdrInventor || nIdent != OBJ_NONE)
				{
					pAktCreate->SetMergedItemSet(aDefaultAttr);
				}

				if (HAS_BASE(SdrCaptionObj,pAktCreate)) 
				{
					SfxItemSet aSet(pMod->GetItemPool());
					aSet.Put(XFillColorItem(String(),Color(COL_WHITE))); // Falls einer auf Solid umschaltet
					aSet.Put(XFillStyleItem(XFILL_NONE));
					
					pAktCreate->SetMergedItemSet(aSet);

					bStartEdit=sal_True;
				}
				if (nInvent==SdrInventor && (nIdent==OBJ_TEXT || nIdent==OBJ_TEXTEXT ||
					nIdent==OBJ_TITLETEXT || nIdent==OBJ_OUTLINETEXT)) 
				{
					// Fuer alle Textrahmen default keinen Hintergrund und keine Umrandung
					SfxItemSet aSet(pMod->GetItemPool());
					aSet.Put(XFillColorItem(String(),Color(COL_WHITE))); // Falls einer auf Solid umschaltet
					aSet.Put(XFillStyleItem(XFILL_NONE));
					aSet.Put(XLineColorItem(String(),Color(COL_BLACK))); // Falls einer auf Solid umschaltet
					aSet.Put(XLineStyleItem(XLINE_NONE));
					
					pAktCreate->SetMergedItemSet(aSet);

					bStartEdit=sal_True;
				}
				if (!rLogRect.IsEmpty()) pAktCreate->NbcSetLogicRect(rLogRect);

				// #90129# make sure drag start point is inside WorkArea
				const Rectangle& rWorkArea = ((SdrDragView*)this)->GetWorkArea();

				if(!rWorkArea.IsEmpty())
				{
					if(aPnt.X() < rWorkArea.Left())
					{
						aPnt.X() = rWorkArea.Left();
					}

					if(aPnt.X() > rWorkArea.Right())
					{
						aPnt.X() = rWorkArea.Right();
					}

					if(aPnt.Y() < rWorkArea.Top())
					{
						aPnt.Y() = rWorkArea.Top();
					}

					if(aPnt.Y() > rWorkArea.Bottom())
					{
						aPnt.Y() = rWorkArea.Bottom();
					}
				}

				aDragStat.Reset(aPnt);
				aDragStat.SetView((SdrView*)this);
				aDragStat.SetPageView(pCreatePV);
				aDragStat.SetMinMove(ImpGetMinMovLogic(nMinMov,pOut));
				pDragWin=pOut;
				if (pAktCreate->BegCreate(aDragStat)) 
				{
					ShowCreateObj(/*pOut,sal_True*/);
					bRet=sal_True;
				} 
				else 
				{
					SdrObject::Free( pAktCreate );
					pAktCreate=NULL;
					pCreatePV=NULL;
				}
			}
		}
	}
	return bRet;
}

sal_Bool SdrCreateView::BegCreateObj(const Point& rPnt, OutputDevice* pOut, short nMinMov, SdrPageView* pPV)
{
	return ImpBegCreateObj(nAktInvent,nAktIdent,rPnt,pOut,nMinMov,pPV,Rectangle(), 0L);
}

sal_Bool SdrCreateView::BegCreatePreparedObject(const Point& rPnt, sal_Int16 nMinMov, SdrObject* pPreparedFactoryObject)
{
	sal_uInt32 nInvent(nAktInvent);
	sal_uInt16 nIdent(nAktIdent);

	if(pPreparedFactoryObject)
	{
		nInvent = pPreparedFactoryObject->GetObjInventor();
		nIdent = pPreparedFactoryObject->GetObjIdentifier();
	}

	return ImpBegCreateObj(nInvent, nIdent, rPnt, 0L, nMinMov, 0L, Rectangle(), pPreparedFactoryObject);
}

sal_Bool SdrCreateView::BegCreateCaptionObj(const Point& rPnt, const Size& rObjSiz,
	OutputDevice* pOut, short nMinMov, SdrPageView* pPV)
{
	return ImpBegCreateObj(SdrInventor,OBJ_CAPTION,rPnt,pOut,nMinMov,pPV,
		Rectangle(rPnt,Size(rObjSiz.Width()+1,rObjSiz.Height()+1)), 0L);
}

void SdrCreateView::MovCreateObj(const Point& rPnt)
{
	if (pAktCreate!=NULL) {
		Point aPnt(rPnt);
		if (!aDragStat.IsNoSnap()) 
		{
			aPnt=GetSnapPos(aPnt,pCreatePV);
		}
		if (IsOrtho()) 
		{
			if (aDragStat.IsOrtho8Possible()) OrthoDistance8(aDragStat.GetPrev(),aPnt,IsBigOrtho());
			else if (aDragStat.IsOrtho4Possible()) OrthoDistance4(aDragStat.GetPrev(),aPnt,IsBigOrtho());
		}

		// #77734# If the drag point was limited and Ortho is active, do
		// the small ortho correction (reduction) -> last parameter to FALSE.
		sal_Bool bDidLimit(ImpLimitToWorkArea(aPnt));
		if(bDidLimit && IsOrtho())
		{
			if(aDragStat.IsOrtho8Possible()) 
				OrthoDistance8(aDragStat.GetPrev(), aPnt, sal_False);
			else if(aDragStat.IsOrtho4Possible()) 
				OrthoDistance4(aDragStat.GetPrev(), aPnt, sal_False);
		}

		if (aPnt==aDragStat.GetNow()) return;
		bool bMerk(aDragStat.IsMinMoved());
		if (aDragStat.CheckMinMoved(aPnt)) 
		{
			Rectangle aBound;
			if (!bMerk) aDragStat.NextPoint();
			aDragStat.NextMove(aPnt);
			pAktCreate->MovCreate(aDragStat);

			// MovCreate changes the object, so use ActionChanged() on it
			pAktCreate->ActionChanged();

			// replace for DrawCreateObjDiff
			HideCreateObj();
			ShowCreateObj();
		}
	}
}

sal_Bool SdrCreateView::EndCreateObj(SdrCreateCmd eCmd)
{
	sal_Bool bRet=sal_False;
	SdrObject* pObjMerk=pAktCreate;
	SdrPageView* pPVMerk=pCreatePV;
	
	if (pAktCreate!=NULL) 
	{
		sal_uIntPtr nAnz=aDragStat.GetPointAnz();
		
		if (nAnz<=1 && eCmd==SDRCREATE_FORCEEND) 
		{
			BrkCreateObj(); // Objekte mit nur einem Punkt gibt's nicht (zumindest noch nicht)
			return sal_False; // sal_False=Event nicht ausgewertet
		}

		sal_Bool bPntsEq=nAnz>1;
		sal_uIntPtr i=1;
		Point aP0=aDragStat.GetPoint(0);
		while (bPntsEq && i<nAnz) { bPntsEq=aP0==aDragStat.GetPoint(i); i++; }

		if (pAktCreate->EndCreate(aDragStat,eCmd)) 
		{
			HideCreateObj();

			if (!bPntsEq) 
			{ 
				// sonst Brk, weil alle Punkte gleich sind.
				SdrObject* pObj=pAktCreate;
				pAktCreate=NULL;
				
				const SdrLayerAdmin& rAd = pCreatePV->GetPage()->GetLayerAdmin();
				SdrLayerID nLayer(0);
				
				// #i72535#
				if(pObj->ISA(FmFormObj))
				{
					// for FormControls, force to form layer
					nLayer = rAd.GetLayerID(rAd.GetControlLayerName(), true);
				}
				else
				{
					nLayer = rAd.GetLayerID(aAktLayer, sal_True);
				}

				if(SDRLAYER_NOTFOUND == nLayer) 
				{
					nLayer=0;
				}

				pObj->SetLayer(nLayer);

				// #83403# recognize creation of a new 3D object inside a 3D scene
				sal_Bool bSceneIntoScene(sal_False);
				
				if(pObjMerk 
					&& pObjMerk->ISA(E3dScene) 
					&& pCreatePV 
					&& pCreatePV->GetAktGroup() 
					&& pCreatePV->GetAktGroup()->ISA(E3dScene))
				{
					sal_Bool bDidInsert = ((E3dView*)this)->ImpCloneAll3DObjectsToDestScene(
						(E3dScene*)pObjMerk, (E3dScene*)pCreatePV->GetAktGroup(), Point(0, 0));

					if(bDidInsert)
					{
						// delete object, it's content is cloned and inserted
                        SdrObject::Free( pObjMerk );
						pObjMerk = 0L;
						bRet = sal_False;
						bSceneIntoScene = sal_True;
					}
				}

				if(!bSceneIntoScene)
				{
					// do the same as before
					InsertObjectAtView(pObj, *pCreatePV);
				}

				pCreatePV=NULL;
				bRet=sal_True; // sal_True=Event ausgewertet
			} 
			else 
			{
				BrkCreateObj();
			}
		} 
		else 
		{ // Mehr Punkte
			if (eCmd==SDRCREATE_FORCEEND || // nix da, Ende erzwungen
				nAnz==0 ||                             // keine Punkte da (kann eigentlich nicht vorkommen)
				(nAnz<=1 && !aDragStat.IsMinMoved())) { // MinMove nicht erfuellt
				BrkCreateObj();
			} 
			else 
			{
				// replace for DrawCreateObjDiff
				HideCreateObj();
				ShowCreateObj();
				aDragStat.ResetMinMoved(); // NextPoint gibt's bei MovCreateObj()
				bRet=sal_True;
			}
		}
		if (bRet && pObjMerk!=NULL && IsTextEditAfterCreate()) 
		{
			SdrTextObj* pText=PTR_CAST(SdrTextObj,pObjMerk);
			if (pText!=NULL && pText->IsTextFrame()) 
			{
				SdrBeginTextEdit(pText, pPVMerk, (Window*)0L, sal_True, (SdrOutliner*)0L, (OutlinerView*)0L);
			}
		}
	}
	return bRet;
}

void SdrCreateView::BckCreateObj()
{
	if (pAktCreate!=NULL) 
	{
		if (aDragStat.GetPointAnz()<=2 ) 
		{
			BrkCreateObj();
		} 
		else 
		{
			HideCreateObj();
			aDragStat.PrevPoint();
			if (pAktCreate->BckCreate(aDragStat)) 
			{
				ShowCreateObj();
			} 
			else 
			{
				BrkCreateObj();
			}
		}
	}
}

void SdrCreateView::BrkCreateObj()
{
	if (pAktCreate!=NULL) 
	{
		HideCreateObj();
		pAktCreate->BrkCreate(aDragStat);
		SdrObject::Free( pAktCreate );
		pAktCreate=NULL;
		pCreatePV=NULL;
	}
}

void SdrCreateView::ShowCreateObj(/*OutputDevice* pOut, sal_Bool bFull*/)
{
	if(IsCreateObj() && !aDragStat.IsShown()) 
	{
		if(pAktCreate)
		{
			// for migration from XOR, replace DrawDragObj here to create
			// overlay objects instead.
			sal_Bool bUseSolidDragging(IsSolidDragging());

			// #i101648# check if dragged object is a naked SdrObject (no
			// derivation of). This is e.g. used in SW Frame construction
			// as placeholder. Do not use SolidDragging for naked SDrObjects,
			// they cannot have a valid optical representation
			if(bUseSolidDragging && OBJ_NONE == pAktCreate->GetObjIdentifier())
			{
				bUseSolidDragging = false;
			}

			// check for objects with no fill and no line
			if(bUseSolidDragging)
			{
				const SfxItemSet& rSet = pAktCreate->GetMergedItemSet();
				const XFillStyle eFill(((XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue());
				const XLineStyle eLine(((XLineStyleItem&)(rSet.Get(XATTR_LINESTYLE))).GetValue());
				
				if(XLINE_NONE == eLine && XFILL_NONE == eFill)
				{
					bUseSolidDragging = sal_False;
				}
			}

			// check for form controls
			if(bUseSolidDragging)
			{
				if(pAktCreate->ISA(SdrUnoObj))
				{
					bUseSolidDragging = sal_False;
				}
			}

  			// #i101781# force to non-solid dragging when not creating a full circle
			if(bUseSolidDragging)
            {
                SdrCircObj* pCircObj = dynamic_cast< SdrCircObj* >(pAktCreate);

                if(pCircObj && OBJ_CIRC != pCircObj->GetObjIdentifier())
                {
                    // #i103058# Allow SolidDragging with four points
                    if(aDragStat.GetPointAnz() < 4)
                    {
        				bUseSolidDragging = false;
                    }
                }
            }

			if(bUseSolidDragging)
			{
				basegfx::B2DPolyPolygon aDragPolyPolygon;

				if(pAktCreate->ISA(SdrRectObj))
				{
					// ensure object has some size, necessary for SdrTextObj because
					// there are still untested divisions by that sizes
					Rectangle aCurrentSnapRect(pAktCreate->GetSnapRect());

					if(!(aCurrentSnapRect.GetWidth() > 1 && aCurrentSnapRect.GetHeight() > 1))
					{
						Rectangle aNewRect(aDragStat.GetStart(), aDragStat.GetStart() + Point(2, 2));
						pAktCreate->NbcSetSnapRect(aNewRect);
					}
				}

				if(pAktCreate->ISA(SdrPathObj))
				{
					// The up-to-now created path needs to be set at the object to have something
					// that can be visualized
					SdrPathObj& rPathObj((SdrPathObj&)(*pAktCreate));
					const basegfx::B2DPolyPolygon aCurrentPolyPolygon(rPathObj.getObjectPolyPolygon(aDragStat));

					if(aCurrentPolyPolygon.count())
					{
						rPathObj.NbcSetPathPoly(aCurrentPolyPolygon);
					}

					aDragPolyPolygon = rPathObj.getDragPolyPolygon(aDragStat);
				}

				// use directly the SdrObject for overlay
				mpCreateViewExtraData->CreateAndShowOverlay(*this, pAktCreate, aDragPolyPolygon);
			}
			else
			{
				mpCreateViewExtraData->CreateAndShowOverlay(*this, 0, pAktCreate->TakeCreatePoly(aDragStat));
			}

			// #i101679# Force changed overlay to be shown
			for(sal_uInt32 a(0); a < PaintWindowCount(); a++)
			{
				SdrPaintWindow* pCandidate = GetPaintWindow(a);
				sdr::overlay::OverlayManager* pOverlayManager = pCandidate->GetOverlayManager();

				if(pOverlayManager)
				{
					pOverlayManager->flush();
				}
			}
		}

		aDragStat.SetShown(sal_True);
	}
}

void SdrCreateView::HideCreateObj()
{
	if(IsCreateObj() && aDragStat.IsShown()) 
	{
		// for migration from XOR, replace DrawDragObj here to create
		// overlay objects instead.
		mpCreateViewExtraData->HideOverlay();

		//DrawCreateObj(pOut,bFull);
		aDragStat.SetShown(sal_False);
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

/* new interface src537 */
sal_Bool SdrCreateView::GetAttributes(SfxItemSet& rTargetSet, sal_Bool bOnlyHardAttr) const
{
	if(pAktCreate)
	{
		rTargetSet.Put(pAktCreate->GetMergedItemSet());
		return sal_True;
	}
	else
	{
		return SdrDragView::GetAttributes(rTargetSet, bOnlyHardAttr);
	}
}

sal_Bool SdrCreateView::SetAttributes(const SfxItemSet& rSet, sal_Bool bReplaceAll)
{
	if(pAktCreate) 
	{
		pAktCreate->SetMergedItemSetAndBroadcast(rSet, bReplaceAll);

		return sal_True;
	} 
	else 
	{
		return SdrDragView::SetAttributes(rSet,bReplaceAll);
	}
}

SfxStyleSheet* SdrCreateView::GetStyleSheet() const // SfxStyleSheet* SdrCreateView::GetStyleSheet(sal_Bool& rOk) const
{
	if (pAktCreate!=NULL) 
	{
		//rOk=sal_True;
		return pAktCreate->GetStyleSheet();
	} 
	else 
	{
		return SdrDragView::GetStyleSheet(); // SdrDragView::GetStyleSheet(rOk);
	}
}

sal_Bool SdrCreateView::SetStyleSheet(SfxStyleSheet* pStyleSheet, sal_Bool bDontRemoveHardAttr)
{
	if (pAktCreate!=NULL) 
	{
		pAktCreate->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
		return sal_True;
	} 
	else 
	{
		return SdrDragView::SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
	}
}

