kicad/pcbnew/xchgmod.cpp

626 lines
18 KiB
C++
Raw Normal View History

/******************************/
/* PCBNEW: echange de modules */
/******************************/
/* Fichier xchmod.cpp */
#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "pcbnew.h"
#include "autorout.h"
#include "protos.h"
/* variables locales */
enum id_ExchangeModule
{
ID_EXEC_EXCHANGE_MODULE = 1900,
ID_EXEC_EXCHANGE_ID_MODULES,
ID_EXEC_EXCHANGE_ID_MODULE_AND_VALUE,
ID_EXEC_EXCHANGE_ALL_MODULES,
ID_CLOSE_EXCHANGE_MODULE,
ID_BROWSE_LIB_MODULES
};
/************************************/
/* class WinEDA_ExchangeModuleFrame */
/************************************/
class WinEDA_ExchangeModuleFrame: public wxDialog
{
private:
WinEDA_BasePcbFrame * m_Parent;
wxDC * m_DC;
MODULE * m_CurrentModule;
WinEDA_EnterText * m_OldModule;
WinEDA_EnterText * m_OldValue;
WinEDA_EnterText * m_NewModule;
wxTextCtrl * m_WinMsg;
public:
// Constructor and destructor
WinEDA_ExchangeModuleFrame(WinEDA_BasePcbFrame *parent,
MODULE * Module, wxDC * DC, const wxPoint & pos);
~WinEDA_ExchangeModuleFrame(void)
{
}
private:
void OnQuit(wxCommandEvent& event);
void Change_Module(wxCommandEvent& event);
void Change_ModuleId(wxCommandEvent& event);
void Change_ModuleAll(wxCommandEvent& event);
int Maj_ListeCmp(
const wxString & reference,
const wxString & old_name,
const wxString & new_name, bool ShowError);
MODULE * Change_1_Module(MODULE * Module, const wxString& new_module, bool ShowError);
void Sel_NewMod_By_Liste(wxCommandEvent& event);
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE(WinEDA_ExchangeModuleFrame, wxDialog)
EVT_BUTTON(ID_EXEC_EXCHANGE_MODULE, WinEDA_ExchangeModuleFrame::Change_Module)
EVT_BUTTON(ID_EXEC_EXCHANGE_ID_MODULES, WinEDA_ExchangeModuleFrame::Change_ModuleId)
EVT_BUTTON(ID_EXEC_EXCHANGE_ID_MODULE_AND_VALUE, WinEDA_ExchangeModuleFrame::Change_ModuleId)
EVT_BUTTON(ID_EXEC_EXCHANGE_ALL_MODULES, WinEDA_ExchangeModuleFrame::Change_ModuleAll)
EVT_BUTTON(ID_CLOSE_EXCHANGE_MODULE, WinEDA_ExchangeModuleFrame::OnQuit)
EVT_BUTTON(ID_BROWSE_LIB_MODULES, WinEDA_ExchangeModuleFrame::Sel_NewMod_By_Liste)
END_EVENT_TABLE()
WinEDA_ExchangeModuleFrame::WinEDA_ExchangeModuleFrame(WinEDA_BasePcbFrame *parent,
MODULE * Module,wxDC * DC,
const wxPoint & framepos):
wxDialog(parent, -1, _("Exchange Modules"), framepos, wxSize(360, 460),
DIALOG_STYLE)
{
wxButton * Button;
m_Parent = parent;
SetFont(*g_DialogFont);
m_DC = DC;
Centre();
m_CurrentModule = Module;
wxBoxSizer * MainBoxSizer = new wxBoxSizer(wxVERTICAL);
SetSizer(MainBoxSizer);
wxBoxSizer * UpperBoxSizer = new wxBoxSizer(wxHORIZONTAL);
MainBoxSizer->Add(UpperBoxSizer, 0, wxGROW|wxALL, 5);
wxBoxSizer * LeftBoxSizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer * RightBoxSizer = new wxBoxSizer(wxVERTICAL);
UpperBoxSizer->Add(LeftBoxSizer, 0, wxGROW|wxALL, 5);
UpperBoxSizer->Add(RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
/* Creation des boutons de commande */
Button = new wxButton(this, ID_EXEC_EXCHANGE_MODULE,
_("Change module"));
Button->SetForegroundColour(*wxBLUE);
RightBoxSizer->Add(Button, 0, wxGROW|wxLEFT|wxRIGHT|wxTOP, 5);
Button = new wxButton(this, ID_EXEC_EXCHANGE_ID_MODULES,
_("Change same modules"));
Button->SetForegroundColour(*wxRED);
RightBoxSizer->Add(Button, 0, wxGROW|wxLEFT|wxRIGHT, 5);
Button = new wxButton(this, ID_EXEC_EXCHANGE_ID_MODULE_AND_VALUE,
_("Ch. same module+value"));
Button->SetForegroundColour(*wxRED);
RightBoxSizer->Add(Button, 0, wxGROW|wxLEFT|wxRIGHT, 5);
Button = new wxButton(this, ID_EXEC_EXCHANGE_ALL_MODULES,
_("Change all"));
Button->SetForegroundColour(*wxRED);
RightBoxSizer->Add(Button, 0, wxGROW|wxLEFT|wxRIGHT, 5);
Button = new wxButton(this, ID_BROWSE_LIB_MODULES,
_("Browse Libs modules"));
Button->SetForegroundColour(wxColour(0,100,0) );
RightBoxSizer->Add(Button, 0, wxGROW|wxLEFT|wxRIGHT, 5);
Button = new wxButton(this, ID_CLOSE_EXCHANGE_MODULE,
_("Close"));
Button->SetForegroundColour(*wxBLUE);
RightBoxSizer->Add(Button, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5);
m_OldModule = new WinEDA_EnterText(this, _("Current Module"),
m_CurrentModule ? m_CurrentModule->m_LibRef.GetData() :wxEmptyString,
LeftBoxSizer, wxSize( 150,-1) );
m_OldModule->Enable(FALSE);
m_OldValue = new WinEDA_EnterText(this, _("Current Value"),
m_CurrentModule ? m_CurrentModule->m_Value->m_Text.GetData() :wxEmptyString,
LeftBoxSizer, wxSize( 150,-1) );
m_OldValue->Enable(FALSE);
m_NewModule = new WinEDA_EnterText(this, _("New Module"),
m_OldModule->GetValue(), LeftBoxSizer, wxSize( 150,-1) );
m_WinMsg = new wxTextCtrl(this, -1,wxEmptyString, wxDefaultPosition, wxSize(340, 230),
wxTE_READONLY|wxTE_MULTILINE);
MainBoxSizer->Add(m_WinMsg, 0, wxGROW|wxALL, 5);
GetSizer()->Fit(this);
GetSizer()->SetSizeHints(this);
}
/*********************************************************************/
void WinEDA_BasePcbFrame::InstallExchangeModuleFrame( MODULE * Module,
wxDC * DC, const wxPoint & pos)
/*********************************************************************/
{
WinEDA_ExchangeModuleFrame * frame = new WinEDA_ExchangeModuleFrame(this,
Module, DC, pos);
frame->ShowModal(); frame->Destroy();
}
/**********************************************************************/
void WinEDA_ExchangeModuleFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
/**********************************************************************/
{
Close(true); // true is to force the frame to close
}
/************************************************************************/
int WinEDA_ExchangeModuleFrame::Maj_ListeCmp(
const wxString & reference,
const wxString & old_name,
const wxString & new_name, bool ShowError)
/************************************************************************/
/*
Met a jour le fichier name.CMP (s'il existe) apres un echange de module
(par la commande changeMod), si les modules sont geres par ce fichier
Si ShowError != 0 affiche message d'erreur si le fichier .cmp n'est pas
trouve.
Retoure 1 si erreur
*/
{
wxString FileNameCmp, tmpfile;
FILE * FichCmp, *NewFile;
char Line[1024];
wxString msg;
if ( old_name == new_name ) return(0); /* pas de changement de nom */
/* Calcul nom fichier CMP par changement de l'extension du nom netliste */
if ( NetNameBuffer == wxEmptyString )
FileNameCmp = m_Parent->m_CurrentScreen->m_FileName;
else FileNameCmp = NetNameBuffer;
ChangeFileNameExt(FileNameCmp,NetCmpExtBuffer) ;
// Modification du fichier .cmp correcpondant
FichCmp = wxFopen(FileNameCmp, wxT("rt"));
if( FichCmp == NULL )
{
if ( ShowError )
{
msg.Printf( _("file %s not found"), FileNameCmp.GetData());
m_WinMsg->WriteText(msg);
}
return(1);
}
/* Analyse du fichier et modif */
tmpfile = FileNameCmp;
ChangeFileNameExt(tmpfile, wxT(".$$$"));
NewFile = wxFopen(tmpfile, wxT("wt"));
if( NewFile == NULL )
{
if ( ShowError )
{
msg.Printf( _("Unable to create file %s"), tmpfile.GetData());
m_WinMsg->WriteText(msg);
}
return(1);
}
fgets(Line, sizeof(Line), FichCmp);
fprintf(NewFile,"Cmp-Mod V01 Genere par PcbNew le %s\n", DateAndTime(Line) );
bool start_descr = FALSE;
while( fgets(Line, sizeof(Line), FichCmp) != NULL )
{
if ( strnicmp( Line, "Reference = ", 9 ) == 0 )
{
char buf[1024];
strcpy( buf, Line + 12);
strtok(buf,";\n\r");
if ( stricmp( buf , CONV_TO_UTF8(reference) ) == 0 )
{
start_descr = TRUE;
}
}
if ( (strnicmp( Line, "Begin", 5 ) == 0) ||
(strnicmp( Line, "End", 3) == 0) )
{
start_descr = FALSE;
}
if ( start_descr && strnicmp( Line, "IdModule", 8 ) == 0 )
{
sprintf(Line + 8," = %s;\n", CONV_TO_UTF8(new_name) );
msg.Printf( wxT(" * in %s\n"), FileNameCmp.GetData());
m_WinMsg->WriteText(msg);
start_descr = FALSE;
}
fputs(Line, NewFile);
}
fclose(FichCmp);
fclose(NewFile);
wxRemoveFile(FileNameCmp);
wxRenameFile(tmpfile, FileNameCmp);
return(0);
}
/********************************************************************/
void WinEDA_ExchangeModuleFrame::Change_Module(wxCommandEvent& event)
/********************************************************************/
/* Routine de changement d'un module:
Change le module pointe par la souris, par un autre en conservant
- meme orientation
- meme position
- memes textes valeur et ref
- memes netnames pour pads de meme nom
*/
{
wxString newmodulename = m_NewModule->GetValue();
if( newmodulename == wxEmptyString ) return;
if( Change_1_Module(m_CurrentModule, newmodulename,TRUE ) )
{
m_Parent->m_Pcb->m_Status_Pcb = 0;
m_Parent->build_liste_pads();
}
}
/*********************************************************************/
void WinEDA_ExchangeModuleFrame::Change_ModuleId(wxCommandEvent& event)
/**********************************************************************/
/* Routine de changement de tous les modules de meme nom lib que celui
selectionne, en conservant
- meme orientation
- meme position
- memes textes valeur et ref
- memes netnames pour pads de meme nom
et en remplacant l'ancien module par le noveau module
Attention: m_CurrentModule ne pointe plus sur le module de reference
puisque celui ci a ete change!!
*/
{
wxString msg;
MODULE * PtModule, *PtBack;
bool change = FALSE;
wxString newmodulename = m_NewModule->GetValue();
wxString value, lib_reference; // pour memo Reflib et value de reference
bool check_module_value = FALSE;
int ShowErr = 5; // Affiche 5 messages d'err maxi
if( m_Parent->m_Pcb->m_Modules == NULL ) return;
if( newmodulename == wxEmptyString ) return;
lib_reference = m_CurrentModule->m_LibRef;
if ( event.GetId() == ID_EXEC_EXCHANGE_ID_MODULE_AND_VALUE )
{
check_module_value = TRUE;
value = m_CurrentModule->m_Value->m_Text;
msg.Printf( _("Change modules <%s> -> <%s> (val = %s)?"),
m_CurrentModule->m_LibRef.GetData(),
newmodulename.GetData(),
m_CurrentModule->m_Value->m_Text.GetData() );
}
else
{
msg.Printf( _("Change modules <%s> -> <%s> ?"),
lib_reference.GetData(), newmodulename.GetData() );
}
if( !IsOK(this, msg) ) return;
/* Le changement s'effectue a partir du dernier module car la routine
Change_1_Module() modifie le dernier module de la liste
*/
PtModule = m_Parent->m_Pcb->m_Modules;
for ( ; PtModule != NULL; PtModule = (MODULE*)PtModule->Pnext)
{
if(PtModule->Pnext == NULL) break;
}
/* Ici PtModule pointe le dernier module de la liste */
for ( ; PtModule != (MODULE*)m_Parent->m_Pcb; PtModule = PtBack)
{
MODULE * module;
PtBack = (MODULE*)PtModule->Pback;
if( lib_reference.CmpNoCase(PtModule->m_LibRef) != 0 )
continue;
if ( check_module_value )
{
if( value.CmpNoCase(PtModule->m_Value->m_Text) != 0 )
continue;
}
module = Change_1_Module(PtModule, newmodulename.GetData(), ShowErr);
if ( module ) change = TRUE;
else if (ShowErr) ShowErr--;
}
if( change )
{
m_Parent->m_Pcb->m_Status_Pcb = 0;
m_Parent->build_liste_pads();
}
}
/***********************************************************************/
void WinEDA_ExchangeModuleFrame::Change_ModuleAll(wxCommandEvent& event)
/***********************************************************************/
/* Routine de changement de tous les modules par les modules de meme nom lib:
en conservant
- meme orientation
- meme position
- memes textes valeur et ref
- memes netnames pour pads de meme nom
*/
{
MODULE * PtModule, *PtBack;
bool change = FALSE;
int ShowErr = 5; // Affiche 5 messages d'err maxi
if(m_Parent->m_Pcb->m_Modules == NULL) return;
if( !IsOK(this, _("Change ALL modules ?")) ) return;
/* Le changement s'effectue a partir du dernier module car la routine
Change_1_Module() modifie le dernier module de la liste
*/
PtModule = (MODULE*) m_Parent->m_Pcb->m_Modules;
for ( ; PtModule != NULL; PtModule = (MODULE*)PtModule->Pnext)
{
if(PtModule->Pnext == NULL) break;
}
/* Ici PtModule pointe le dernier module de la liste */
for ( ; PtModule != (MODULE*)(m_Parent->m_Pcb); PtModule = PtBack)
{
PtBack = (MODULE*)PtModule->Pback;
if ( Change_1_Module(PtModule, PtModule->m_LibRef.GetData(), ShowErr) )
change = TRUE;
else if (ShowErr) ShowErr--;
}
if( change)
{
m_Parent->m_Pcb->m_Status_Pcb = 0;
m_Parent->build_liste_pads();
}
}
/******************************************************************/
MODULE * WinEDA_ExchangeModuleFrame::Change_1_Module(MODULE * PtModule,
const wxString& new_module, bool ShowError)
/*******************************************************************/
/* Routine de changement d'un module:
Change le module de numero empr, avec le module de nom new_module
- meme orientation
- meme position
- memes textes valeur et ref
- memes netnames pour pads de meme nom
Retourne :
0 si pas de changement ( si le nouveau module n'est pas en libr)
1 si OK
*/
{
wxString namecmp, oldnamecmp;
MODULE * NewModule;
wxString Line;
if(PtModule == NULL) return(NULL);
wxBusyCursor dummy;
/* Memorisation des parametres utiles de l'ancien module */
oldnamecmp = PtModule->m_LibRef;
namecmp = new_module;
/* Chargement du module */
Line.Printf( _("Change module %s (%s) "),
PtModule->m_Reference->m_Text.GetData(), oldnamecmp.GetData());
m_WinMsg->WriteText(Line);
namecmp.Trim(TRUE);
namecmp.Trim(FALSE);
NewModule = m_Parent->Get_Librairie_Module(this, wxEmptyString, namecmp, ShowError);
if( NewModule == NULL) /* Nouveau module NON trouve, reaffichage de l'ancien */
{
m_WinMsg->WriteText( wxT("No\n"));
return(NULL);
}
if ( PtModule == m_CurrentModule ) m_CurrentModule = NewModule;
m_WinMsg->WriteText( wxT("Ok\n"));
/* Effacement a l'ecran de l'ancien module */
PtModule->Draw(m_Parent->DrawPanel, m_DC, wxPoint(0,0), GR_XOR);
m_Parent->Exchange_Module(this, PtModule, NewModule);
/* Affichage du nouveau module */
NewModule->Draw(m_Parent->DrawPanel, m_DC, wxPoint(0,0),GR_OR);
Maj_ListeCmp(NewModule->m_Reference->m_Text, oldnamecmp, namecmp, ShowError);
return(NewModule);
}
/***********************************************************************************/
MODULE * WinEDA_BasePcbFrame::Exchange_Module(wxWindow * winaff,
MODULE * OldModule, MODULE * NewModule)
/***********************************************************************************/
/*
Remplace le module OldModule par le module NewModule (en conservant position, orientation..)
OldModule est supprim<EFBFBD> de la memoire.
*/
{
wxPoint oldpos; /* memorisation temporaire pos curseur */
D_PAD * pt_pad, * pt_old_pad;
if ( (OldModule->m_StructType != TYPEMODULE) || (NewModule->m_StructType != TYPEMODULE) )
{
DisplayError(winaff, wxT("WinEDA_BasePcbFrame::Exchange_Module() StuctType error" ));
}
NewModule->m_Parent = m_Pcb;
m_Pcb->m_Status_Pcb = 0 ;
oldpos = m_CurrentScreen->m_Curseur;
m_CurrentScreen->m_Curseur = OldModule->m_Pos;
Place_Module(NewModule, NULL);
m_CurrentScreen->m_Curseur = oldpos;
/* Changement eventuel de couche */
if( OldModule->m_Layer != NewModule->m_Layer)
{
Change_Side_Module(NewModule, NULL);
}
/* Rotation eventuelle du module */
if( OldModule->m_Orient != NewModule->m_Orient )
{
Rotate_Module(NULL, NewModule,OldModule->m_Orient, FALSE );
}
/* Mise a jour des textes ref et val */
NewModule->m_Reference->m_Text = OldModule->m_Reference->m_Text;
NewModule->m_Value->m_Text = OldModule->m_Value->m_Text;
/* Mise a jour des autres parametres */
NewModule->m_TimeStamp = OldModule->m_TimeStamp;
/* mise a jour des netnames ( lorsque c'est possible) */
pt_pad = NewModule->m_Pads;
for( ; pt_pad != NULL; pt_pad = (D_PAD*)pt_pad->Pnext)
{
pt_pad->m_Netname = wxEmptyString;
pt_pad->m_NetCode = 0;
pt_old_pad = OldModule->m_Pads;
for( ; pt_old_pad != NULL; pt_old_pad = (D_PAD*)pt_old_pad->Pnext )
{
if(strnicmp( pt_pad->m_Padname, pt_old_pad->m_Padname,sizeof(pt_pad->m_Padname)) == 0)
{
pt_pad->m_Netname = pt_old_pad->m_Netname;
pt_pad->m_NetCode = pt_old_pad->m_NetCode;
}
}
}
/* Effacement de l'ancien module */
DeleteStructure(OldModule);
m_Pcb->m_Status_Pcb = 0;
NewModule->m_Flags = 0;
m_CurrentScreen->SetModify();
return NewModule;
}
/***************************************************************************/
void WinEDA_ExchangeModuleFrame::Sel_NewMod_By_Liste(wxCommandEvent& event)
/***************************************************************************/
/*affiche la liste des modules en librairie et selectione 1 nom */
{
wxString newname;
newname = m_Parent->Select_1_Module_From_List( m_Parent, wxEmptyString, wxEmptyString, wxEmptyString);
if ( newname != wxEmptyString )
m_NewModule->SetValue(newname);
}
/***************************************************/
bool WinEDA_PcbFrame::RecreateCmpFileFromBoard(void)
/***************************************************/
{
wxString FullFileNameCmp, mask;
FILE * FichCmp;
char Line[1024];
MODULE * Module = m_Pcb->m_Modules;
wxString msg;
if ( Module == NULL)
{
DisplayError(this, _("No Modules!") );
return FALSE;
}
/* Calcul nom fichier CMP par changement de l'extension du nom netliste */
if ( NetNameBuffer == wxEmptyString )
FullFileNameCmp = m_CurrentScreen->m_FileName;
else FullFileNameCmp = NetNameBuffer;
ChangeFileNameExt(FullFileNameCmp,NetCmpExtBuffer) ;
mask = wxT("*") + NetCmpExtBuffer;
FullFileNameCmp = EDA_FileSelector( _("Cmp files:"),
wxEmptyString, /* Chemin par defaut */
FullFileNameCmp, /* nom fichier par defaut */
NetCmpExtBuffer, /* extension par defaut */
mask, /* Masque d'affichage */
this,
wxFD_SAVE,
FALSE
);
if ( FullFileNameCmp.IsEmpty() ) return FALSE;
FichCmp = wxFopen(FullFileNameCmp, wxT("wt"));
if( FichCmp == NULL )
{
msg = _("Unable to create file ") + FullFileNameCmp;
DisplayError(this, msg);
return FALSE;
}
fgets(Line, sizeof(Line), FichCmp);
fprintf(FichCmp,"Cmp-Mod V01 Genere par PcbNew le %s\n", DateAndTime(Line) );
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
{
fprintf(FichCmp,"\nBeginCmp\n" );
fprintf(FichCmp,"TimeStamp = %8.8lX\n", Module->m_TimeStamp);
fprintf(FichCmp,"Reference = %s;\n",
! Module->m_Reference->m_Text.IsEmpty() ?
CONV_TO_UTF8(Module->m_Reference->m_Text) : "[NoRef]" );
fprintf(FichCmp,"ValeurCmp = %s;\n",
!Module->m_Value->m_Text.IsEmpty() ?
CONV_TO_UTF8(Module->m_Value->m_Text) : "[NoVal]" );
fprintf(FichCmp,"IdModule = %s;\n", CONV_TO_UTF8(Module->m_LibRef));
fprintf(FichCmp,"EndCmp\n" );
}
fprintf(FichCmp,"\nEndListe\n");
fclose(FichCmp);
return TRUE;
}