|
|
/**
* @file xchgmod.cpp */
/*
* This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
#include <fctsys.h>
#include <class_drawpanel.h>
#include <confirm.h>
#include <kicad_string.h>
#include <wxPcbStruct.h>
#include <macros.h>
#include <pcbcommon.h>
#include <class_board.h>
#include <class_module.h>
#include <pcbnew.h>
#include <dialog_exchange_modules_base.h>
#include <wildcards_and_files_ext.h>
static char* quiet_gcc_4_4_3; // GCC 4.4.3 and next ..
int s_SelectionMode = 0; // Remember the last exchange option, when exit dialog.
class DIALOG_EXCHANGE_MODULE : public DIALOG_EXCHANGE_MODULE_BASE{private:
PCB_EDIT_FRAME* m_Parent; MODULE* m_CurrentModule;
public: DIALOG_EXCHANGE_MODULE( PCB_EDIT_FRAME* aParent, MODULE* aModule ); ~DIALOG_EXCHANGE_MODULE() { };
private: void OnSelectionClicked( wxCommandEvent& event ); void OnOkClick( wxCommandEvent& event ); void OnQuit( wxCommandEvent& event ); void BrowseAndSelectFootprint( wxCommandEvent& event ); void Init();
void Change_Current_Module(); void Change_ModuleId( bool aUseValue ); void Change_ModuleAll(); int Maj_ListeCmp( const wxString& reference, const wxString& old_name, const wxString& new_name, bool ShowError ); bool Change_1_Module( MODULE* Module, const wxString& new_module, PICKED_ITEMS_LIST* aUndoPickList, bool ShowError );};
DIALOG_EXCHANGE_MODULE::DIALOG_EXCHANGE_MODULE( PCB_EDIT_FRAME* parent, MODULE* Module ) : DIALOG_EXCHANGE_MODULE_BASE( parent ){ m_Parent = parent; m_CurrentModule = Module; Init(); GetSizer()->Fit( this ); GetSizer()->SetSizeHints( this );}
void PCB_EDIT_FRAME::InstallExchangeModuleFrame( MODULE* Module ){ DIALOG_EXCHANGE_MODULE dialog( this, Module );
dialog.ShowModal();}
void DIALOG_EXCHANGE_MODULE::OnQuit( wxCommandEvent& event ){ s_SelectionMode = m_Selection->GetSelection(); EndModal( 0 );}
void DIALOG_EXCHANGE_MODULE::Init(){ SetFocus();
m_OldModule->AppendText( m_CurrentModule->GetLibRef() ); m_NewModule->AppendText( m_CurrentModule->GetLibRef() ); m_OldValue->AppendText( m_CurrentModule->GetValue() ); m_Selection->SetSelection( s_SelectionMode );
// Enable/disable widgets:
wxCommandEvent event; OnSelectionClicked( event );}
void DIALOG_EXCHANGE_MODULE::OnOkClick( wxCommandEvent& event ){ s_SelectionMode = m_Selection->GetSelection(); switch( m_Selection->GetSelection() ) { case 0: Change_Current_Module(); break;
case 1: Change_ModuleId( false ); break;
case 2: Change_ModuleId( true ); break;
case 3: Change_ModuleAll(); break; }}
void DIALOG_EXCHANGE_MODULE::OnSelectionClicked( wxCommandEvent& event ){ switch( m_Selection->GetSelection() ) { case 0: case 1: case 2: m_NewModule->Enable( true ); m_Browsebutton->Enable( true ); break;
case 3: m_NewModule->Enable( false ); m_Browsebutton->Enable( false ); break; }}
/*
* Updates the file name.CMP (if any) after an exchange module * (By command changeMod), if the modules are managed by this file * * If ShowError! = 0 displays error message if the file. Cmp is not found. * Return 1 if error */int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference, const wxString& old_name, const wxString& new_name, bool ShowError ){ wxFileName fn; wxFileName tmpFileName; FILE* FichCmp, * NewFile; char line[1024]; wxString msg;
if( old_name == new_name ) return 0;
/* Build CMP file name by changing the extension of NetList filename */ fn = m_Parent->GetBoard()->GetFileName(); fn.SetExt( ComponentFileExtension );
FichCmp = wxFopen( fn.GetFullPath(), wxT( "rt" ) );
if( FichCmp == NULL ) { if( ShowError ) { msg.Printf( _( "file <%s> not found" ), GetChars( fn.GetFullPath() ) ); m_WinMessages->AppendText( msg ); }
return 1; }
tmpFileName = fn; tmpFileName.SetExt( wxT( "$$$" ) ); NewFile = wxFopen( tmpFileName.GetFullPath(), wxT( "wt" ) );
if( NewFile == NULL ) { if( ShowError ) { msg.Printf( _( "Unable to create file <%s>" ), GetChars( tmpFileName.GetFullPath() ) ); m_WinMessages->AppendText( msg ); }
return 1; }
quiet_gcc_4_4_3 = fgets( line, sizeof(line), FichCmp );
fprintf( NewFile, "Cmp-Mod V01 Created by PcbNew date = %s\n", TO_UTF8( DateAndTime() ) );
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, 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", TO_UTF8( new_name ) );
msg = wxT( " * in <" ) + fn.GetFullPath() + wxT( ">.\n" ); m_WinMessages->AppendText( msg );
start_descr = false; }
fputs( line, NewFile ); }
fclose( FichCmp ); fclose( NewFile ); wxRemoveFile( fn.GetFullPath() ); wxRenameFile( tmpFileName.GetFullPath(), fn.GetFullPath() ); return 0;}
/* Change the module at the current cursor position.
* Retains the following: * - Same direction * - Same position * - Same text value and ref * - Same NetNames for pads same name */void DIALOG_EXCHANGE_MODULE::Change_Current_Module(){ wxString newmodulename = m_NewModule->GetValue();
if( newmodulename == wxEmptyString ) return;
PICKED_ITEMS_LIST pickList;
if( Change_1_Module( m_CurrentModule, newmodulename, &pickList, true ) ) { if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) m_Parent->Compile_Ratsnest( NULL, true );
m_Parent->RefreshCanvas(); }
if( pickList.GetCount() ) m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );}
/*
* Change of all modules with the same name as that lib * Retains: * - Same direction * - Same position * - Same text value and ref * - Same NetNames for pads same name * And replacing the old module with the new module * Note: m_CurrentModule no longer on the module reference * since it has been changed! */void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue ){ wxString msg; MODULE* Module, * PtBack; bool change = false; wxString newmodulename = m_NewModule->GetValue(); wxString value, lib_reference; bool check_module_value = false; int ShowErr = 3; // Post 3 error messages max.
if( m_Parent->GetBoard()->m_Modules == NULL ) return;
if( newmodulename == wxEmptyString ) return;
lib_reference = m_CurrentModule->GetLibRef();
if( aUseValue ) { check_module_value = true; value = m_CurrentModule->GetValue(); msg.Printf( _( "Change modules %s -> %s (for value = %s)?" ), GetChars( m_CurrentModule->GetLibRef() ), GetChars( newmodulename ), GetChars( m_CurrentModule->GetValue() ) ); } else { msg.Printf( _( "Change modules %s -> %s ?" ), GetChars( lib_reference ), GetChars( newmodulename ) ); }
if( !IsOK( this, msg ) ) return;
/* The change is done from the last module for the routine
* Change_1_Module () modifies the last module in the list. */ PICKED_ITEMS_LIST pickList;
/* note: for the first module in chain (the last here), Module->Back()
* points the board or is NULL */ Module = m_Parent->GetBoard()->m_Modules.GetLast();
for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack ) { PtBack = Module->Back();
if( lib_reference.CmpNoCase( Module->GetLibRef() ) != 0 ) continue;
if( check_module_value ) { if( value.CmpNoCase( Module->GetValue() ) != 0 ) continue; }
if( Change_1_Module( Module, newmodulename, &pickList, ShowErr ) ) change = true; else if( ShowErr ) ShowErr--; }
if( change ) { if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) m_Parent->Compile_Ratsnest( NULL, true );
m_Parent->RefreshCanvas(); }
if( pickList.GetCount() ) m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );}
/*
* Change all modules with module of the same name in library. * Maintains: * - Same direction * - Same position * - Same text value and ref * - Same NetNames for pads same name */void DIALOG_EXCHANGE_MODULE::Change_ModuleAll(){ MODULE* Module, * PtBack; bool change = false; int ShowErr = 3; // Post 3 error messages max.
if( m_Parent->GetBoard()->m_Modules == NULL ) return;
if( !IsOK( this, _( "Change ALL modules ?" ) ) ) return;
/* The change is done from the last module for the routine
* Change_1_Module () modifies the last module in the list */ PICKED_ITEMS_LIST pickList;
/* note: for the first module in chain (the last here), Module->Back()
* points the board or is NULL */ Module = m_Parent->GetBoard()->m_Modules.GetLast();
for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack ) { PtBack = Module->Back();
if( Change_1_Module( Module, Module->GetLibRef(), &pickList, ShowErr ) ) change = true; else if( ShowErr ) ShowErr--; }
if( change ) { if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) m_Parent->Compile_Ratsnest( NULL, true );
m_Parent->RefreshCanvas(); }
if( pickList.GetCount() ) m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );}
/*
* Change the number empr module with the module name new_module * - Same direction * - Same position * - Same text value and ref * - Same NetNames for pads same name * Returns: * False if no change (if the new module is not free) * True if OK * Ratsnest must be recalculated after module exchange */bool DIALOG_EXCHANGE_MODULE::Change_1_Module( MODULE* Module, const wxString& new_module, PICKED_ITEMS_LIST* aUndoPickList, bool ShowError ){ wxString namecmp, oldnamecmp; MODULE* NewModule; wxString line;
if( Module == NULL ) return false;
wxBusyCursor dummy;
/* Copy parameters from the old module. */ oldnamecmp = Module->GetLibRef(); namecmp = new_module;
/* Load module. */ line.Printf( _( "Change module %s (from %s) " ), GetChars( Module->GetReference() ), GetChars( oldnamecmp ) ); m_WinMessages->AppendText( line );
namecmp.Trim( true ); namecmp.Trim( false ); NewModule = m_Parent->GetModuleLibrary( wxEmptyString, namecmp, ShowError );
if( NewModule == NULL ) /* New module not found, redraw the old one. */ { m_WinMessages->AppendText( wxT( "No\n" ) ); return false; }
m_Parent->GetBoard()->Add( NewModule, ADD_APPEND );
if( Module == m_CurrentModule ) m_CurrentModule = NewModule;
m_WinMessages->AppendText( wxT( "OK\n" ) );
m_Parent->Exchange_Module( Module, NewModule, aUndoPickList );
Maj_ListeCmp( NewModule->GetReference(), oldnamecmp, namecmp, ShowError );
return true;}
void PCB_EDIT_FRAME::Exchange_Module( MODULE* aOldModule, MODULE* aNewModule, PICKED_ITEMS_LIST* aUndoPickList ){ wxPoint oldpos; D_PAD* pad, * old_pad;
if( ( aOldModule->Type() != PCB_MODULE_T ) || ( aNewModule->Type() != PCB_MODULE_T ) ) { wxMessageBox( wxT( "PCB_EDIT_FRAME::Exchange_Module() StuctType error" ) ); return; }
aNewModule->SetParent( GetBoard() );
GetBoard()->m_Status_Pcb = 0; oldpos = GetScreen()->GetCrossHairPosition(); GetScreen()->SetCrossHairPosition( aOldModule->GetPosition(), false );
/* place module without ratsnest refresh: this will be made later
* when all modules are on board */ PlaceModule( aNewModule, NULL, true ); GetScreen()->SetCrossHairPosition( oldpos, false );
/* Flip footprint if needed */ if( aOldModule->GetLayer() != aNewModule->GetLayer() ) { aNewModule->Flip( aNewModule->GetPosition() ); }
/* Rotate footprint if needed */ if( aOldModule->GetOrientation() != aNewModule->GetOrientation() ) { Rotate_Module( NULL, aNewModule, aOldModule->GetOrientation(), false ); }
/* Update reference and value */ aNewModule->SetReference( aOldModule->GetReference() ); aNewModule->SetValue( aOldModule->GetValue() );
/* Updating other parameters */ aNewModule->SetTimeStamp( aOldModule->GetTimeStamp() ); aNewModule->SetPath( aOldModule->GetPath() );
/* Update pad netnames ( when possible) */ pad = aNewModule->Pads();
for( ; pad != NULL; pad = pad->Next() ) { pad->SetNetname( wxEmptyString ); pad->SetNet( 0 ); old_pad = aOldModule->Pads();
for( ; old_pad != NULL; old_pad = old_pad->Next() ) { if( pad->PadNameEqual( old_pad ) ) { pad->SetNetname( old_pad->GetNetname() ); pad->SetNet( old_pad->GetNet() ); } } }
if( aUndoPickList ) { GetBoard()->Remove( aOldModule ); ITEM_PICKER picker_old( aOldModule, UR_DELETED ); ITEM_PICKER picker_new( aNewModule, UR_NEW ); aUndoPickList->PushItem( picker_old ); aUndoPickList->PushItem( picker_new ); } else { aOldModule->DeleteStructure(); }
GetBoard()->m_Status_Pcb = 0; aNewModule->ClearFlags(); OnModify();}
/*
* Displays the list of modules in library name and select 1 name. */void DIALOG_EXCHANGE_MODULE::BrowseAndSelectFootprint( wxCommandEvent& event ){ wxString newname;
newname = m_Parent->SelectFootprint( m_Parent, wxEmptyString, wxEmptyString, wxEmptyString, m_Parent->GetFootprintLibraryTable() );
if( newname != wxEmptyString ) m_NewModule->SetValue( newname );}
void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent ){ wxFileName fn; FILE* FichCmp; char line[1024]; MODULE* Module = GetBoard()->m_Modules; wxString msg; wxString wildcard;
if( Module == NULL ) { DisplayError( this, _( "No Modules!" ) ); return; }
/* Calculation file name by changing the extension name to NetList */ fn = GetBoard()->GetFileName(); fn.SetExt( ComponentFileExtension ); wildcard = wxGetTranslation( ComponentFileWildcard );
wxFileDialog dlg( this, _( "Save Component Files" ), wxGetCwd(), fn.GetFullName(), wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
if( dlg.ShowModal() == wxID_CANCEL ) return;
fn = dlg.GetPath();
FichCmp = wxFopen( fn.GetFullPath(), wxT( "wt" ) );
if( FichCmp == NULL ) { msg = _( "Unable to create file " ) + fn.GetFullPath(); DisplayError( this, msg ); return; }
quiet_gcc_4_4_3 = fgets( line, sizeof(line), FichCmp ); fprintf( FichCmp, "Cmp-Mod V01 Genere par PcbNew le %s\n", TO_UTF8( DateAndTime() ) );
for( ; Module != NULL; Module = Module->Next() ) { fprintf( FichCmp, "\nBeginCmp\n" ); fprintf( FichCmp, "TimeStamp = %8.8lX\n", Module->GetTimeStamp() ); fprintf( FichCmp, "Path = %s\n", TO_UTF8( Module->GetPath() ) ); fprintf( FichCmp, "Reference = %s;\n", !Module->GetReference().IsEmpty() ? TO_UTF8( Module->GetReference() ) : "[NoRef]" ); fprintf( FichCmp, "ValeurCmp = %s;\n", !Module->GetValue().IsEmpty() ? TO_UTF8( Module->GetValue() ) : "[NoVal]" ); fprintf( FichCmp, "IdModule = %s;\n", TO_UTF8( Module->GetLibRef() ) ); fprintf( FichCmp, "EndCmp\n" ); }
fprintf( FichCmp, "\nEndListe\n" ); fclose( FichCmp );}
|