/////////////////////////////////////////////////////////////////////////////
// Name:        sheet.cpp
// Purpose:     
// Author:      jean-pierre Charras
// Modified by: 
// Created:     08/02/2006 18:37:02
// RCS-ID:      
// Copyright:   License GNU
// Licence:     
/////////////////////////////////////////////////////////////////////////////

// Generated by DialogBlocks (unregistered), 08/02/2006 18:37:02

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "sheet.h"
#endif

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

////@begin includes
////@end includes
#include "fctsys.h"
#include "gr_basic.h"

#include "common.h"
#include "program.h"
#include "libcmp.h"
#include "general.h"

#include "protos.h"

/* Routines Locales */
static void ExitSheet(WinEDA_DrawFrame * frame, wxDC * DC);
static void DeplaceSheet(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);

/* Variables locales, communes a sheetlab.cpp */

/* Variables locales */
static int s_SheetMindx, s_SheetMindy;
static wxPoint s_OldPos;	/* Ancienne pos pour annulation ReSize ou move */


#include "sheet.h"

////@begin XPM images
////@end XPM images

/*!
 * WinEDA_SheetPropertiesFrame type definition
 */

IMPLEMENT_DYNAMIC_CLASS( WinEDA_SheetPropertiesFrame, wxDialog )

/*!
 * WinEDA_SheetPropertiesFrame event table definition
 */

BEGIN_EVENT_TABLE( WinEDA_SheetPropertiesFrame, wxDialog )

////@begin WinEDA_SheetPropertiesFrame event table entries
    EVT_BUTTON( wxID_CANCEL, WinEDA_SheetPropertiesFrame::OnCancelClick )

    EVT_BUTTON( wxID_OK, WinEDA_SheetPropertiesFrame::OnOkClick )

////@end WinEDA_SheetPropertiesFrame event table entries

END_EVENT_TABLE()

/*!
 * WinEDA_SheetPropertiesFrame constructors
 */

WinEDA_SheetPropertiesFrame::WinEDA_SheetPropertiesFrame( )
{
}

WinEDA_SheetPropertiesFrame::WinEDA_SheetPropertiesFrame( WinEDA_SchematicFrame* parent,
		DrawSheetStruct * currentsheet,
		wxWindowID id, const wxString& caption,
		const wxPoint& pos, const wxSize& size, long style )
{
	m_Parent = parent;
	m_CurrentSheet = currentsheet;
    Create(parent, id, caption, pos, size, style);

	AddUnitSymbol(*m_SheetNameTextSize);
	PutValueInLocalUnits(*m_SheetNameSize,m_CurrentSheet->m_Field[VALUE].m_Size.x,
			m_Parent->m_InternalUnits);

	AddUnitSymbol(*m_FileNameTextSize);
	PutValueInLocalUnits(*m_FileNameSize,
			m_CurrentSheet->m_Field[SHEET_FILENAME].m_Size.x,
			m_Parent->m_InternalUnits);
}

/*!
 * WinEDA_SheetPropertiesFrame creator
 */

bool WinEDA_SheetPropertiesFrame::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
////@begin WinEDA_SheetPropertiesFrame member initialisation
    m_FileNameWin = NULL;
    m_SheetNameWin = NULL;
    m_FileNameTextSize = NULL;
    m_FileNameSize = NULL;
    m_SheetNameTextSize = NULL;
    m_SheetNameSize = NULL;
////@end WinEDA_SheetPropertiesFrame member initialisation

////@begin WinEDA_SheetPropertiesFrame creation
    SetExtraStyle(GetExtraStyle()|wxWS_EX_BLOCK_EVENTS);
    wxDialog::Create( parent, id, caption, pos, size, style );

    CreateControls();
    GetSizer()->Fit(this);
    GetSizer()->SetSizeHints(this);
    Centre();
////@end WinEDA_SheetPropertiesFrame creation
    return true;
}

/*!
 * Control creation for WinEDA_SheetPropertiesFrame
 */

void WinEDA_SheetPropertiesFrame::CreateControls()
{    
	SetFont(*g_DialogFont);

////@begin WinEDA_SheetPropertiesFrame content construction
    // Generated by DialogBlocks, 27/02/2006 14:12:10 (unregistered)

    WinEDA_SheetPropertiesFrame* itemDialog1 = this;

    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
    itemDialog1->SetSizer(itemBoxSizer2);

    wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
    itemBoxSizer2->Add(itemBoxSizer3, 0, wxGROW|wxALL, 5);

    wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxVERTICAL);
    itemBoxSizer3->Add(itemBoxSizer4, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    wxStaticText* itemStaticText5 = new wxStaticText( itemDialog1, wxID_STATIC, _("Filename:"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer4->Add(itemStaticText5, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);

    m_FileNameWin = new wxTextCtrl( itemDialog1, ID_TEXTCTRL1, _T(""), wxDefaultPosition, wxSize(300, -1), wxTE_PROCESS_ENTER );
    itemBoxSizer4->Add(m_FileNameWin, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxBOTTOM, 5);

    wxStaticText* itemStaticText7 = new wxStaticText( itemDialog1, wxID_STATIC, _("Sheetname:"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer4->Add(itemStaticText7, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);

    m_SheetNameWin = new wxTextCtrl( itemDialog1, ID_TEXTCTRL, _T(""), wxDefaultPosition, wxSize(300, -1), 0 );
    itemBoxSizer4->Add(m_SheetNameWin, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxBOTTOM, 5);

    wxBoxSizer* itemBoxSizer9 = new wxBoxSizer(wxVERTICAL);
    itemBoxSizer3->Add(itemBoxSizer9, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    m_FileNameTextSize = new wxStaticText( itemDialog1, wxID_STATIC, _("Size"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer9->Add(m_FileNameTextSize, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);

    m_FileNameSize = new wxTextCtrl( itemDialog1, ID_TEXTCTRL2, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer9->Add(m_FileNameSize, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxBOTTOM, 5);

    m_SheetNameTextSize = new wxStaticText( itemDialog1, wxID_STATIC, _("Size"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer9->Add(m_SheetNameTextSize, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);

    m_SheetNameSize = new wxTextCtrl( itemDialog1, ID_TEXTCTRL3, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer9->Add(m_SheetNameSize, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxBOTTOM, 5);

    itemBoxSizer2->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);

    wxBoxSizer* itemBoxSizer15 = new wxBoxSizer(wxHORIZONTAL);
    itemBoxSizer2->Add(itemBoxSizer15, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);

    wxButton* itemButton16 = new wxButton( itemDialog1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
    itemButton16->SetForegroundColour(wxColour(0, 0, 255));
    itemBoxSizer15->Add(itemButton16, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    wxButton* itemButton17 = new wxButton( itemDialog1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
    itemButton17->SetForegroundColour(wxColour(196, 0, 0));
    itemBoxSizer15->Add(itemButton17, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    // Set validators
    m_FileNameWin->SetValidator( wxTextValidator(wxFILTER_NONE, & m_CurrentSheet->m_Field[SHEET_FILENAME].m_Text) );
    m_SheetNameWin->SetValidator( wxTextValidator(wxFILTER_NONE, & m_CurrentSheet->m_Field[VALUE].m_Text) );
////@end WinEDA_SheetPropertiesFrame content construction
}

/*!
 * Should we show tooltips?
 */

bool WinEDA_SheetPropertiesFrame::ShowToolTips()
{
    return true;
}

/*!
 * Get bitmap resources
 */

wxBitmap WinEDA_SheetPropertiesFrame::GetBitmapResource( const wxString& name )
{
    // Bitmap retrieval
////@begin WinEDA_SheetPropertiesFrame bitmap retrieval
    wxUnusedVar(name);
    return wxNullBitmap;
////@end WinEDA_SheetPropertiesFrame bitmap retrieval
}

/*!
 * Get icon resources
 */

wxIcon WinEDA_SheetPropertiesFrame::GetIconResource( const wxString& name )
{
    // Icon retrieval
////@begin WinEDA_SheetPropertiesFrame icon retrieval
    wxUnusedVar(name);
    return wxNullIcon;
////@end WinEDA_SheetPropertiesFrame icon retrieval
}



/*****************************************************************************/
void WinEDA_SheetPropertiesFrame::SheetPropertiesAccept(wxCommandEvent& event)
/*****************************************************************************/
{
wxString FileName, msg;
	
	FileName = m_FileNameWin->GetValue();
	FileName.Trim(FALSE); FileName.Trim(TRUE);
	
	if ( FileName.IsEmpty() )
	{
		DisplayError(this, _("No Filename! Aborted") );
		EndModal (FALSE);
		return;
	}

	ChangeFileNameExt( FileName,g_SchExtBuffer );
	
	m_CurrentSheet->m_Field[SHEET_FILENAME].m_Text = FileName;
	msg = m_FileNameSize->GetValue();
	m_CurrentSheet->m_Field[SHEET_FILENAME].m_Size.x = 
		m_CurrentSheet->m_Field[SHEET_FILENAME].m_Size.y =
			ReturnValueFromString(g_UnitMetric,
				msg, m_Parent->m_InternalUnits);

	m_CurrentSheet->m_Field[VALUE].m_Text = m_SheetNameWin->GetValue();
	msg = m_SheetNameSize->GetValue();
	m_CurrentSheet->m_Field[VALUE].m_Size.x = 
		m_CurrentSheet->m_Field[VALUE].m_Size.y =
			ReturnValueFromString(g_UnitMetric,
				msg, m_Parent->m_InternalUnits);

	if( (m_CurrentSheet->m_Field[VALUE].m_Text.IsEmpty() ) )
		m_CurrentSheet->m_Field[VALUE].m_Text =
			m_CurrentSheet->m_Field[SHEET_FILENAME].m_Text;


	EndModal(TRUE);
}

/*************************************************************************/
bool WinEDA_SchematicFrame::EditSheet(DrawSheetStruct * Sheet, wxDC * DC)
/*************************************************************************/
/* Routine de modification des textes (Name et FileName) de la Sheet */
{
BASE_SCREEN * ScreenSheet = NULL;
WinEDA_SheetPropertiesFrame * frame;
bool edit = TRUE;

	if ( Sheet == NULL ) return FALSE;

	ScreenSheet = (BASE_SCREEN*)Sheet->m_Son;

	/* Demande du nouveau texte */
	RedrawOneStruct(DrawPanel, DC, Sheet, g_XorMode);

    DrawPanel->m_IgnoreMouseEvents = TRUE;
	frame = new WinEDA_SheetPropertiesFrame(this, Sheet);
	edit = frame->ShowModal(); frame->Destroy();
    DrawPanel->MouseToCursorSchema();
    DrawPanel->m_IgnoreMouseEvents = FALSE;
	
	if ( edit )
		{
		/* Correction du nom fichier dans la structure SCREEN correspondante */
		if( ScreenSheet )
			{
			ScreenSheet->m_FileName = Sheet->m_Field[SHEET_FILENAME].m_Text;
			}
		SetFlagModify(GetScreen());
		}

	RedrawOneStruct(DrawPanel, DC, Sheet, GR_DEFAULT_DRAWMODE);
	return edit;
}


#define SHEET_MIN_WIDTH  500
#define SHEET_MIN_HEIGHT 150
/****************************************************************/
DrawSheetStruct * WinEDA_SchematicFrame::CreateSheet(wxDC * DC)
/****************************************************************/
/* Routine de Creation d'une feuille de hierarchie (Sheet) */
{
	g_ItemToRepeat = NULL;

	DrawSheetStruct * Sheet = new DrawSheetStruct(m_CurrentScreen->m_Curseur);

	Sheet->m_Flags = IS_NEW | IS_RESIZED;
	Sheet->m_TimeStamp = GetTimeStamp();
	Sheet->m_Parent = m_CurrentScreen;
	s_SheetMindx =  SHEET_MIN_WIDTH;
	s_SheetMindy = SHEET_MIN_HEIGHT;

	m_CurrentScreen->m_CurrentItem = Sheet;

	m_CurrentScreen->ManageCurseur = DeplaceSheet;
	m_CurrentScreen->ForceCloseManageCurseur = ExitSheet;

	m_CurrentScreen->ManageCurseur(DrawPanel, DC, FALSE);

	return Sheet;
}


/*******************************************************************************/
void WinEDA_SchematicFrame::ReSizeSheet(DrawSheetStruct * Sheet, wxDC * DC)
/*******************************************************************************/
{
DrawSheetLabelStruct* sheetlabel;

	if ( Sheet == NULL ) return;
	if( Sheet->m_Flags & IS_NEW) return;

	if( Sheet->m_StructType != DRAW_SHEET_STRUCT_TYPE)
		{
		DisplayError(this, wxT("WinEDA_SchematicFrame::ReSizeSheet: Bad SructType"));
		return;
		}

	SetFlagModify(GetScreen());
	Sheet->m_Flags |= IS_RESIZED;

	/* sauvegarde des anciennes valeurs */
	s_OldPos.x = Sheet->m_Size.x;
	s_OldPos.y = Sheet->m_Size.y;

	/* Recalcul des dims min de la sheet */
	s_SheetMindx =  SHEET_MIN_WIDTH;
	s_SheetMindy = SHEET_MIN_HEIGHT;
	sheetlabel = Sheet->m_Label;
	while(sheetlabel)
	{
		s_SheetMindx = MAX(s_SheetMindx,
					(int)((sheetlabel->GetLength()+1) * sheetlabel->m_Size.x) );
		s_SheetMindy = MAX(s_SheetMindy,sheetlabel->m_Pos.y - Sheet->m_Pos.y);
		sheetlabel = (DrawSheetLabelStruct *) sheetlabel->Pnext;
	}
	m_CurrentScreen->ManageCurseur = DeplaceSheet ;
	m_CurrentScreen->ForceCloseManageCurseur = ExitSheet;
	m_CurrentScreen->ManageCurseur(DrawPanel, DC, TRUE);
}


/*********************************************************************************/
void WinEDA_SchematicFrame::StartMoveSheet(DrawSheetStruct* Sheet, wxDC * DC)
/*********************************************************************************/
{
	if ( (Sheet == NULL) || ( Sheet->m_StructType != DRAW_SHEET_STRUCT_TYPE)  )
		return;

 	m_CurrentScreen->CursorOff(DrawPanel, DC);
 	m_CurrentScreen->m_Curseur = Sheet->m_Pos;
 	DrawPanel->MouseToCursorSchema();
 
	s_OldPos = Sheet->m_Pos;
	Sheet->m_Flags |= IS_MOVED;
	m_CurrentScreen->ManageCurseur = DeplaceSheet ;
	m_CurrentScreen->ForceCloseManageCurseur = ExitSheet;
	m_CurrentScreen->ManageCurseur(DrawPanel, DC, TRUE);
 
 	m_CurrentScreen->CursorOn(DrawPanel, DC);
}

/********************************************************/
/*** 	Routine de deplacement Sheet, lie au curseur.	*/
/*  Appele par GeneralControle grace a  ManageCurseur.  */
/********************************************************/
static void DeplaceSheet(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
{
int dx, dy;
DrawSheetLabelStruct * SheetLabel;
BASE_SCREEN * screen = panel->m_Parent->m_CurrentScreen;

DrawSheetStruct * Sheet = (DrawSheetStruct *)
					screen->m_CurrentItem;

	/* Effacement du composant: tj apres depl curseur */
	if( erase )
		RedrawOneStruct(panel, DC, Sheet, g_XorMode);

	if( Sheet->m_Flags & IS_RESIZED)
		{
		Sheet->m_Size.x = MAX(s_SheetMindx,
							screen->m_Curseur.x	- Sheet->m_Pos.x);
		Sheet->m_Size.y = MAX(s_SheetMindy,
							screen->m_Curseur.y	- Sheet->m_Pos.y);
		SheetLabel = Sheet->m_Label;
		while(SheetLabel)
			{
			if( SheetLabel->m_Edge)
				SheetLabel->m_Pos.x = Sheet->m_Pos.x + Sheet->m_Size.x;
			SheetLabel = (DrawSheetLabelStruct *) SheetLabel->Pnext;
			}
		}
	else	/* Move Sheet */
		{
		dx = screen->m_Curseur.x - Sheet->m_Pos.x;
		dy = screen->m_Curseur.y - Sheet->m_Pos.y;
		MoveOneStruct(Sheet, dx, dy);
		}

	RedrawOneStruct(panel, DC, Sheet, g_XorMode);
}

/****************************************************************/

/****************************************************************/
void DrawSheetStruct::Place( WinEDA_DrawFrame * frame, wxDC * DC)
{
	/* Placement en liste des structures si nouveau composant:*/
	if(m_Flags & IS_NEW)
	{
		if ( ! ((WinEDA_SchematicFrame*)frame)->EditSheet(this, DC) )
		{
			frame->m_CurrentScreen->m_CurrentItem = NULL;
			frame->m_CurrentScreen->ManageCurseur = NULL;
			frame->m_CurrentScreen->ForceCloseManageCurseur = NULL;
			RedrawOneStruct(frame->DrawPanel, DC, this, g_XorMode);
			delete this;
			return;
		}


		if ( wxFileExists(m_Field[SHEET_FILENAME].m_Text) )
		{
			if ( m_Son == NULL )
			{
				SCH_SCREEN * newscreen = ScreenSch ;
				while(newscreen->Pnext) newscreen = (SCH_SCREEN*) newscreen->Pnext;
				newscreen->Pnext = CreateNewScreen(frame, newscreen, m_TimeStamp);

				newscreen = (SCH_SCREEN*)newscreen->Pnext;
				m_Son = newscreen;
				newscreen->m_Parent = this;
				newscreen->m_FileName = m_Field[SHEET_FILENAME].m_Text;
				newscreen->m_RootSheet = this;
			}
				((WinEDA_SchematicFrame*)frame)->LoadOneSheet(
					(SCH_SCREEN*)m_Son, m_Field[SHEET_FILENAME].m_Text);
		}
	}

	EDA_BaseStruct::Place(frame, DC);
}

/****************************************/
/*  Routine de sortie du Menu de Sheet  */
/****************************************/
static void ExitSheet(WinEDA_DrawFrame * frame, wxDC * DC)
{
DrawSheetStruct * Sheet = (DrawSheetStruct *)
		frame->m_CurrentScreen->m_CurrentItem;

	if ( Sheet == NULL) return;

	/* Deplacement composant en cours */
	if ( Sheet->m_Flags & IS_NEW ) /* Nouveau Placement en cours, on l'efface */
		{
		RedrawOneStruct(frame->DrawPanel, DC, Sheet, g_XorMode);
		delete Sheet;
		}
	else if ( Sheet->m_Flags & IS_RESIZED )/* resize en cours: on l'annule */
		{
		RedrawOneStruct(frame->DrawPanel, DC, Sheet, g_XorMode);
		Sheet->m_Size.x = s_OldPos.x;
		Sheet->m_Size.y = s_OldPos.y;
		RedrawOneStruct(frame->DrawPanel, DC, Sheet, GR_DEFAULT_DRAWMODE);
		Sheet->m_Flags = 0;
		}

	else if ( Sheet->m_Flags & IS_MOVED )/* move en cours: on l'annule */
		{
		wxPoint curspos = frame->m_CurrentScreen->m_Curseur;
		frame->m_CurrentScreen->m_Curseur = s_OldPos;
		DeplaceSheet(frame->DrawPanel, DC, TRUE);
		RedrawOneStruct(frame->DrawPanel, DC, Sheet, GR_DEFAULT_DRAWMODE);
		Sheet->m_Flags = 0;
		frame->m_CurrentScreen->m_Curseur = curspos;
		}

	else Sheet->m_Flags = 0;

	frame->m_CurrentScreen->m_CurrentItem = NULL;
	frame->m_CurrentScreen->ManageCurseur = NULL;
	frame->m_CurrentScreen->ForceCloseManageCurseur =NULL;
}



/********************************************************************/
void DrawSheetStruct::CleanupSheet(WinEDA_SchematicFrame * frame, wxDC *DC)
/********************************************************************/
/* Delete pinsheets which are not corresponding to a Global label
 if DC != NULL, redraw Sheet
*/
{
DrawSheetLabelStruct* Pinsheet, * NextPinsheet;
SCH_SCREEN * Screen = (SCH_SCREEN*) m_Son;
	
	if ( Screen == NULL )
	{
		DisplayError(frame, _("This sheet has no data, cleanup aborted"));
		return;
	}

	if( ! IsOK(frame, _("Ok to cleanup this sheet") ) ) return;
		
	Pinsheet = m_Label;
	while(Pinsheet)
	{
		/* Search Glabel corresponding to this Pinsheet */

		EDA_BaseStruct *DrawStruct = Screen->EEDrawList;
		DrawGlobalLabelStruct * GLabel = NULL;
		for (; DrawStruct != NULL; DrawStruct = DrawStruct->Pnext )
		{
			if( DrawStruct->m_StructType != DRAW_GLOBAL_LABEL_STRUCT_TYPE )
				continue;
			GLabel = (DrawGlobalLabelStruct *) DrawStruct;
			if( Pinsheet->m_Text.CmpNoCase(GLabel->m_Text) == 0 )
				break;	// Found!
			GLabel = NULL;
		}

		NextPinsheet = (DrawSheetLabelStruct *) Pinsheet->Pnext;
		if ( GLabel == NULL )	// Glabel not found: delete pinsheet
		{
			SetFlagModify(frame->GetScreen());
			frame->DeleteSheetLabel(DC, Pinsheet);
		}
		Pinsheet = NextPinsheet;
	}
}
/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
 */

void WinEDA_SheetPropertiesFrame::OnCancelClick( wxCommandEvent& event )
{
	EndModal(0);
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_OK
 */

void WinEDA_SheetPropertiesFrame::OnOkClick( wxCommandEvent& event )
{
	SheetPropertiesAccept(event);
	EndModal(1);
}


