		/******************************************************/
		/*	 Edition des contours du pcb: Routines		  	  */
		/* d'effacement et d'edition  de segments et contours */
		/*   du type PCB, draw, edgePCB						  */
		/******************************************************/

#include "fctsys.h"
#include "gr_basic.h"

#include "common.h"
#include "pcbnew.h"

#include "protos.h"

/* Routines Locales */
static void Exit_EditEdge(WinEDA_DrawPanel * Panel, wxDC * DC);
static void Montre_Position_NewSegment(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
static void Move_Segment(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);

/* Variables locales : */
static wxPoint cursor_pos;	// position originelle du curseur souris (fct deplacement)
static wxPoint cursor_pos0;	// position courante du curseur souris

/****************************************************************************/
void WinEDA_PcbFrame::Start_Move_DrawItem(DRAWSEGMENT * drawitem, wxDC * DC)
/****************************************************************************/
 /* Routine de preparation du deplacement d'un element graphique type DRAWSEGMENT
*/
{
	if( drawitem == NULL ) return;
	Trace_DrawSegmentPcb(DrawPanel, DC, drawitem,GR_XOR) ;
	drawitem->m_Flags |= IS_MOVED;
	cursor_pos = cursor_pos0 = GetScreen()->m_Curseur;
	Affiche_Infos_DrawSegment(this, drawitem);
	DrawPanel->ManageCurseur = Move_Segment;
	DrawPanel->ForceCloseManageCurseur = Exit_EditEdge;
	GetScreen()->m_CurrentItem = drawitem;
	DrawPanel->ManageCurseur( DrawPanel, DC, FALSE);
}

/*********************************************************************/
void WinEDA_PcbFrame::Place_DrawItem(DRAWSEGMENT * drawitem, wxDC * DC)
/*********************************************************************/
/*
 Routine de placement de l'element graphique type DRAWSEGMENT en cours de deplacement
*/
{
	if( drawitem == NULL ) return;

	Trace_DrawSegmentPcb(DrawPanel, DC, drawitem,GR_OR) ;
	DrawPanel->ManageCurseur = NULL;
	DrawPanel->ForceCloseManageCurseur = NULL;
	GetScreen()->m_CurrentItem = NULL;
	GetScreen()->SetModify();
	drawitem->m_Flags = 0;
}


/************************************************************************/
static void Move_Segment(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
/************************************************************************/
/* redessin du contour du Segment Edge lors des deplacements de la souris */
{
DRAWSEGMENT * Segment = ( DRAWSEGMENT * )
	panel->GetScreen()->m_CurrentItem ;
int t_fill = DisplayOpt.DisplayDrawItems;

	if(Segment == NULL) return ;

	DisplayOpt.DisplayDrawItems = SKETCH ;

	/* efface ancienne position */
	if( erase )
		Trace_DrawSegmentPcb(panel, DC, Segment, GR_XOR);

wxPoint delta;
	delta.x = panel->GetScreen()->m_Curseur.x - cursor_pos.x;
	delta.y = panel->GetScreen()->m_Curseur.y - cursor_pos.y;
	Segment->m_Start.x += delta.x;
	Segment->m_Start.y += delta.y;
	Segment->m_End.x += delta.x;
	Segment->m_End.y += delta.y;
	cursor_pos = panel->GetScreen()->m_Curseur;

	Trace_DrawSegmentPcb(panel, DC, Segment,GR_XOR);
	DisplayOpt.DisplayDrawItems = t_fill ;
}



/**************************************************************************/
void WinEDA_PcbFrame::Delete_Segment_Edge( DRAWSEGMENT* Segment,  wxDC * DC)
/**************************************************************************/
{
EDA_BaseStruct * PtStruct;
int track_fill_copy  = DisplayOpt.DisplayDrawItems;

	if (Segment == NULL ) return;

	if(Segment->m_Flags & IS_NEW)  // Trace en cours, on peut effacer le dernier segment
		{
		/* effacement du segment en cours de trace */
		DisplayOpt.DisplayDrawItems = SKETCH ;
		Trace_DrawSegmentPcb(DrawPanel, DC, Segment,GR_XOR) ;
		PtStruct = Segment->Pback;
		DeleteStructure(Segment);
		if( PtStruct && (PtStruct->m_StructType == TYPEDRAWSEGMENT ) )
			Segment = (DRAWSEGMENT*) PtStruct;
		DisplayOpt.DisplayDrawItems = track_fill_copy ;
		GetScreen()->m_CurrentItem = NULL;
		}

	else
		{
		Trace_DrawSegmentPcb(DrawPanel, DC, (DRAWSEGMENT *)Segment,GR_XOR) ;
		Segment->m_Flags = 0;
		DeleteStructure(Segment);
		GetScreen()->m_CurrentItem = NULL;
		GetScreen()->SetModify();
		}
}


/*************************************************************************/
void WinEDA_PcbFrame::Drawing_SetNewWidth(DRAWSEGMENT *DrawSegm, wxDC * DC)
/*************************************************************************/
/* Met a la largeur courante le segment pointe part la souris
*/
{

	if( DrawSegm == NULL ) return;

	Trace_DrawSegmentPcb(DrawPanel, DC, DrawSegm, GR_XOR);

	if(DrawSegm->m_Layer == EDGE_N) DrawSegm->m_Width = g_DesignSettings.m_EdgeSegmentWidth;
	else DrawSegm->m_Width = g_DesignSettings.m_DrawSegmentWidth;

	Trace_DrawSegmentPcb(DrawPanel, DC, DrawSegm, GR_OR);

	Affiche_Infos_DrawSegment(this, DrawSegm);

	GetScreen()->SetModify();
}


/******************************************************************************/
void WinEDA_PcbFrame::Delete_Drawings_All_Layer(DRAWSEGMENT *Segment, wxDC * DC)
/******************************************************************************/
{
DRAWSEGMENT * pt_segm;
TEXTE_PCB* pt_txt;
EDA_BaseStruct * PtStruct, *PtNext;
COTATION * Cotation;
int layer = Segment->m_Layer;

	if(layer <= CMP_N)
		{
		DisplayError(this, _("Copper layer global delete not allowed!"), 20);
		return;
		}

	if ( Segment->m_Flags )
		{
		DisplayError(this, _("Segment is being edited"), 10);
		return;
		}

	wxString msg = _("Delete Layer ") + ReturnPcbLayerName(layer);
	if( !IsOK(this, msg) ) return ;

	PtStruct = m_Pcb->m_Drawings;
	for( ; PtStruct != NULL; PtStruct = PtNext )
		{
		GetScreen()->SetModify();
		PtNext = PtStruct->Pnext;
		switch( PtStruct->m_StructType)
			{
			case TYPEDRAWSEGMENT:
				pt_segm = (DRAWSEGMENT*) PtStruct;
				if(pt_segm->m_Layer == layer)
					{
					Trace_DrawSegmentPcb(DrawPanel, DC, pt_segm,GR_XOR);
					DeleteStructure(PtStruct);
					}
				break;

			case TYPETEXTE:
				pt_txt = (TEXTE_PCB*)PtStruct;
				if(pt_txt->m_Layer == layer)
					{
					pt_txt->Draw(DrawPanel, DC, wxPoint(0, 0), GR_XOR);
					DeleteStructure( PtStruct );
					}
				break;


			case TYPECOTATION:
				Cotation = (COTATION*)PtStruct;
				if(Cotation->m_Layer == layer)
					{
					Cotation->Draw(DrawPanel, DC, wxPoint(0, 0), GR_XOR);
					DeleteStructure(PtStruct);
					}
				break;

			default: DisplayError(this, wxT("Type Drawing Inconnu") );
				break;
			}
		}
}


/*************************************************************/
static void Exit_EditEdge(WinEDA_DrawPanel * Panel, wxDC * DC)
/*************************************************************/
{
DRAWSEGMENT *Segment = (DRAWSEGMENT *) Panel->GetScreen()->m_CurrentItem ;

	if (Segment == NULL) return;

	if( Segment->m_Flags & IS_NEW )
	{
		Panel->ManageCurseur(Panel, DC, FALSE);
		DeleteStructure(Segment);
		Segment = NULL;
	}

	else
	{
		wxPoint pos = Panel->GetScreen()->m_Curseur;
		Panel->GetScreen()->m_Curseur = cursor_pos0;
		Panel->ManageCurseur(Panel, DC, TRUE);
		Panel->GetScreen()->m_Curseur = pos;
		Segment->m_Flags = 0;
		Trace_DrawSegmentPcb(Panel, DC, Segment,GR_OR) ;
	}
	Panel->ManageCurseur = NULL;
	Panel->ForceCloseManageCurseur = NULL;
	Panel->GetScreen()->m_CurrentItem = NULL;
}

/**********************************************************************/
DRAWSEGMENT * WinEDA_PcbFrame::Begin_DrawSegment(DRAWSEGMENT * Segment,
			int shape, wxDC * DC)
/**********************************************************************/
/* Routine d'initialisation du trace d'un segment de type autre que piste
*/
{
int s_large;
int angle = 0;
DRAWSEGMENT * DrawItem;

	s_large = g_DesignSettings.m_DrawSegmentWidth;
	if(GetScreen()->m_Active_Layer == EDGE_N)
		{
		s_large = g_DesignSettings.m_EdgeSegmentWidth;
		}

	if ( shape == S_ARC ) angle = 900;

	if(Segment == NULL )		/* debut reel du trace */
		{
		GetScreen()->m_CurrentItem = Segment = new DRAWSEGMENT( m_Pcb);
		Segment->m_Flags = IS_NEW;
		Segment->m_Layer = GetScreen()->m_Active_Layer;
		Segment->m_Width = s_large;
		Segment->m_Shape = shape;
		Segment->m_Angle = 900;
		Segment->m_Start = Segment->m_End = GetScreen()->m_Curseur ;
		DrawPanel->ManageCurseur = Montre_Position_NewSegment;
		DrawPanel->ForceCloseManageCurseur = Exit_EditEdge;
		}

	else	/* trace en cours : les coord du point d'arrivee ont ete mises
			a jour par la routine Montre_Position_NewSegment*/
		{
		if( (Segment->m_Start.x != Segment->m_End.x )
			|| (Segment->m_Start.y != Segment->m_End.y ) )
			{
			if ( Segment->m_Shape == S_SEGMENT )
				{
				Segment->Pnext = m_Pcb->m_Drawings;
				Segment->Pback = m_Pcb;
				if( m_Pcb->m_Drawings )
				 m_Pcb->m_Drawings->Pback = Segment;
				m_Pcb->m_Drawings = Segment;
				GetScreen()->SetModify();
				Segment->m_Flags = 0;

				Trace_DrawSegmentPcb(DrawPanel, DC, Segment,GR_OR);

				DrawItem = Segment;

				GetScreen()->m_CurrentItem = Segment = new DRAWSEGMENT( m_Pcb );

				Segment->m_Flags = IS_NEW;
				Segment->m_Layer = DrawItem->m_Layer;
				Segment->m_Width = s_large;
				Segment->m_Shape = DrawItem->m_Shape;
				Segment->m_Type = DrawItem->m_Type;
				Segment->m_Angle = DrawItem->m_Angle;
				Segment->m_Start = Segment->m_End = DrawItem->m_End;
				Montre_Position_NewSegment(DrawPanel, DC, FALSE);
				}
			else
				{
				End_Edge(Segment, DC);
				Segment = NULL;
				}
			}
		}
	return Segment;
}


/***************************************************************/
void WinEDA_PcbFrame::End_Edge(DRAWSEGMENT * Segment, wxDC * DC)
/***************************************************************/
{

	if( Segment == NULL ) return ;
	Trace_DrawSegmentPcb(DrawPanel, DC, (DRAWSEGMENT *)Segment,GR_OR);

	/* Effacement si Longueur nulle */
	if( (Segment->m_Start.x == Segment->m_End.x) &&
   		(Segment->m_Start.y == Segment->m_End.y) )
		DeleteStructure(Segment);

	else
		{
		Segment->m_Flags = 0;
		Segment->Pnext = m_Pcb->m_Drawings;
		Segment->Pback = m_Pcb;
		if( m_Pcb->m_Drawings ) m_Pcb->m_Drawings->Pback = Segment;
		m_Pcb->m_Drawings = Segment;
		GetScreen()->SetModify();
		}

	DrawPanel->ManageCurseur = NULL;
	DrawPanel->ForceCloseManageCurseur = NULL;
	GetScreen()->m_CurrentItem = NULL;
}


/************************************************************/
static void Montre_Position_NewSegment(WinEDA_DrawPanel * panel,
        wxDC * DC, bool erase)
/************************************************************/
/* redessin du contour du Segment Edge lors des deplacements de la souris */
{
DRAWSEGMENT * Segment = ( DRAWSEGMENT * )
	panel->GetScreen()->m_CurrentItem ;
int t_fill = DisplayOpt.DisplayDrawItems;

	if(Segment == NULL) return ;

	DisplayOpt.DisplayDrawItems = SKETCH ;

	/* efface ancienne position */
	if( erase )
		Trace_DrawSegmentPcb(panel, DC, Segment, GR_XOR);

	if( Segments_45_Only && (Segment->m_Shape == S_SEGMENT ) )
		{
		Calcule_Coord_Extremite_45(Segment->m_Start.x,Segment->m_Start.y,
							&Segment->m_End.x, &Segment->m_End.y);
		}

	else	/* ici l'angle d'inclinaison est quelconque */
		{
		Segment->m_End = panel->GetScreen()->m_Curseur;
		}

	Trace_DrawSegmentPcb(panel, DC, Segment,GR_XOR);
	DisplayOpt.DisplayDrawItems = t_fill ;
}


