diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp index e35cda8809..8eb08658b4 100644 --- a/common/fp_lib_table.cpp +++ b/common/fp_lib_table.cpp @@ -25,11 +25,11 @@ #include // wxExpandEnvVars() +#include +#include #include -#include - #include #include @@ -302,7 +302,7 @@ PLUGIN* FP_LIB_TABLE::PluginFind( const wxString& aLibraryNickName ) } -const wxString FP_LIB_TABLE::ExpandSubtitutions( const wxString aString ) +const wxString FP_LIB_TABLE::ExpandSubstitutions( const wxString aString ) { // We reserve the right to do this another way, by providing our own member // function. @@ -310,6 +310,48 @@ const wxString FP_LIB_TABLE::ExpandSubtitutions( const wxString aString ) } +void FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARSE_ERROR ) +{ + wxFileName fn = GetGlobalTableFileName(); + + wxLogDebug( wxT( "Loading global footprint table file: %s" ), GetChars( fn.GetFullPath() ) ); + + if( !fn.FileExists() ) + { + /// @todo call some script to create initial global footprint table. + } + else + { + FILE_LINE_READER reader( fn.GetFullPath() ); + FP_LIB_TABLE_LEXER lexer( &reader ); + + aTable.Parse( &lexer ); + } +} + + +wxString FP_LIB_TABLE::GetGlobalTableFileName() +{ + wxFileName fn; + + fn.SetPath( wxStandardPaths::Get().GetUserConfigDir() ); + +#if defined( __WINDOWS__ ) + fn.AppendDir( wxT( "kicad" ) ); +#endif + + fn.SetName( GetFileName() ); + + return fn.GetFullPath(); +} + + +wxString FP_LIB_TABLE::GetFileName() +{ + return wxString( wxT( ".fp-lib-table" ) ); +} + + #if 0 // don't know that this is needed yet MODULE* FP_LIB_TABLE::LookupFootprint( const FP_LIB_ID& aFootprintId ) throw( IO_ERROR ) diff --git a/include/appl_wxstruct.h b/include/appl_wxstruct.h index 014de9a7e1..f4a33286a6 100644 --- a/include/appl_wxstruct.h +++ b/include/appl_wxstruct.h @@ -59,7 +59,6 @@ class wxHtmlHelpController; */ class EDA_APP : public wxApp { - protected: /// Used mainly to handle default paths libs m_Id = APP_EESCHEMA_T, APP_PCBNEW_T ... EDA_APP_T m_Id; @@ -416,6 +415,7 @@ public: bool LockFile( const wxString& fileName ); }; + /* * Use wxGetApp() to access EDA_APP. It is not necessary to keep copies * of the application pointer all over the place or worse yet in a global diff --git a/include/fp_lib_table.h b/include/fp_lib_table.h index 7010421844..955bb6d306 100644 --- a/include/fp_lib_table.h +++ b/include/fp_lib_table.h @@ -105,7 +105,7 @@ public: } ROW( const wxString& aNick, const wxString& aURI, const wxString& aType, - const wxString& aOptions, const wxString& aDescr = wxEmptyString ) : + const wxString& aOptions, const wxString& aDescr = wxEmptyString ) : nickName( aNick ), uri( aURI ), options( aOptions ), @@ -355,6 +355,11 @@ public: */ const ROW* FindRow( const wxString& aNickName ) throw( IO_ERROR ); + /** + * Function IsEmpty + * @return true if the footprint library table is empty. + */ + bool IsEmpty() const { return rows.empty(); } /** * Function ExpandEnvSubsitutions @@ -363,13 +368,31 @@ public: * This enables (fp_lib_table)s to have platform dependent environment * variables in them, allowing for a uniform table across platforms. */ - static const wxString ExpandSubtitutions( const wxString aString ); + static const wxString ExpandSubstitutions( const wxString aString ); /** - * Function IsEmpty - * @return true if the footprint library table is empty. + * Function LoadGlobalTable + * loads the global footprint library table into \a aTable. + * + * This probably should be move into the application object when KiCad is changed + * to a single process application. This is the least painful solution for the + * time being. + * + * @param aTable the #FP_LIB_TABLE object to load. */ - bool IsEmpty() const { return rows.empty(); } + static void LoadGlobalTable( FP_LIB_TABLE& aTable ) throw (IO_ERROR, PARSE_ERROR ); + + /** + * Function GetGlobalTableFileName + * @return the platform specific global footprint library path and file name. + */ + static wxString GetGlobalTableFileName(); + + /** + * Function GetFootprintTableFileName + * @return the footprint library file name. + */ + static wxString GetFileName(); protected: diff --git a/include/fpid.h b/include/fpid.h index babbb2293c..acb53df5b9 100644 --- a/include/fpid.h +++ b/include/fpid.h @@ -102,7 +102,7 @@ public: * Function GetFootprintName * returns the footprint name, i.e. footprintName. */ - const std::string& GetFootprintName() const; + const std::string& GetFootprintName() const { return footprint; } /** * Function SetFootprintName diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 24e6332e45..6a01be4d43 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -54,6 +54,8 @@ class GENERAL_COLLECTORS_GUIDE; class BOARD_DESIGN_SETTINGS; class ZONE_SETTINGS; class PCB_PLOT_PARAMS; +class FP_LIB_TABLE; +class FPID; /** @@ -83,9 +85,14 @@ protected: BOARD* m_Pcb; GENERAL_COLLECTOR* m_Collector; + /// The project footprint library table. This is a combination of the project + /// footprint library table and the global footprint table. This is the one to + /// use when finding a #MODULE. + FP_LIB_TABLE* m_footprintLibTable; + /// Auxiliary tool bar typically shown below the main tool bar at the top of the /// main window. - wxAuiToolBar* m_auxiliaryToolBar; + wxAuiToolBar* m_auxiliaryToolBar; void updateGridSelectBox(); void updateZoomSelectBox(); @@ -93,15 +100,15 @@ protected: /** * Function loadFootprint - * attempts to load \a aFootprintName from the list of libraries. + * attempts to load \a aFootprintId from the footprint library table. * - * @param aFootprintName is the name of component footprint to load. - * @return the #MODULE if found or NULL if \a aFootprintName not found in any of the - * libraries. + * @param aFootprintId is the #FPID of component footprint to load. + * @return the #MODULE if found or NULL if \a aFootprintId not found in any of the + * libraries in #m_footprintLibTable. * @throw IO_ERROR if an I/O error occurs or a #PARSE_ERROR if a file parsing error * occurs while reading footprint library files. */ - MODULE* loadFootprint( const wxString& aFootprintName ) + MODULE* loadFootprint( const FPID& aFootprintId ) throw( IO_ERROR, PARSE_ERROR ); public: @@ -442,27 +449,31 @@ public: * @param aKeyWord = keyword list, to display a filtered list of module * having one (or more) of these keywords in their * keyword list ( aKeyWord = wxEmptyString if not used ) + * @param aTable is the #FP_LIB_TABLE to search. * * @return wxEmptyString if abort or fails, or the selected module name if Ok */ wxString SelectFootprint( EDA_DRAW_FRAME* aWindow, const wxString& aLibraryFullFilename, const wxString& aMask, - const wxString& aKeyWord ); + const wxString& aKeyWord, + FP_LIB_TABLE* aTable ); /** - * Function Load_Module_From_Library + * Function LoadModuleFromLibrary * opens a dialog to select a footprint, and loads it into current board. * * @param aLibrary = the library name to use, or empty string to search * in all loaded libraries + * @param aTable is the #FP_LIB_TABLE containing the avaiable footprint libraries. * @param aUseFootprintViewer = true to show the option * allowing the footprint selection by the footprint viewer * @param aDC (can be NULL ) = the current Device Context, to draw the new footprint */ - MODULE* Load_Module_From_Library( const wxString& aLibrary, - bool aUseFootprintViewer = true, - wxDC* aDC = NULL ); + MODULE* LoadModuleFromLibrary( const wxString& aLibrary, + FP_LIB_TABLE* aTable, + bool aUseFootprintViewer = true, + wxDC* aDC = NULL ); /** * SelectFootprintFromLibBrowser @@ -471,6 +482,14 @@ public: */ wxString SelectFootprintFromLibBrowser( void ); + /** + * Function GetFootprintLibraryTable + * @return the project #FP_LIB_TABLE so programs can find footprints. + */ + FP_LIB_TABLE* GetFootprintLibraryTable() { return m_footprintLibTable; } + + void SetFootprintLibraryTable( FP_LIB_TABLE* aTable ) { m_footprintLibTable = aTable; } + // ratsnest functions /** * Function Compile_Ratsnest diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index c5b586235d..ccd909f55b 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -63,6 +63,7 @@ class NETLIST; class REPORTER; class PARSE_ERROR; class IO_ERROR; +class FP_LIB_TABLE; /** @@ -84,6 +85,9 @@ class PCB_EDIT_FRAME : public PCB_BASE_FRAME /// The auxiliary right vertical tool bar used to access the microwave tools. wxAuiToolBar* m_microWaveToolBar; + /// The global footprint library table. + FP_LIB_TABLE* m_globalFootprintTable; + /** * Function loadFootprints * loads the footprints for each #COMPONENT in \a aNetlist from the list of libraries. @@ -198,6 +202,12 @@ protected: */ void duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone ); + /** + * Function loadFootprintLibTable + * deletes the existing #FP_LIB_TABLE and creates a new one when a new project is loaded. + */ + void loadFootprintLibTable(); + public: PCB_LAYER_BOX_SELECTOR* m_SelLayerBox; // a combo box to display and select active layer wxComboBox* m_SelTrackWidthBox; // a combo box to display and select current track width @@ -1659,12 +1669,11 @@ public: */ void UpdateTitle(); + DECLARE_EVENT_TABLE() }; -class FP_LIB_TABLE; - /** * Function InvokePcbLibTableEditor * shows the modal DIALOG_FP_LIB_TABLE for purposes of editing two lib tables. diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index ee0e094ee0..5639a2946d 100755 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -218,7 +218,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer(); if( viewer == NULL ) { - viewer = new FOOTPRINT_VIEWER_FRAME( this, NULL ); + viewer = new FOOTPRINT_VIEWER_FRAME( this, m_footprintLibTable, NULL ); viewer->Show( true ); viewer->Zoom_Automatique( false ); } diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index 966f116703..72cc975729 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -463,9 +463,11 @@ wxString FOOTPRINT_EDIT_FRAME::CreateNewLibrary() bool FOOTPRINT_EDIT_FRAME::DeleteModuleFromCurrentLibrary() { - wxString libPath = getLibPath(); - wxString footprintName = PCB_BASE_FRAME::SelectFootprint( this, libPath, - wxEmptyString, wxEmptyString ); + PCB_EDIT_FRAME* parent = (PCB_EDIT_FRAME*) GetParent(); + wxString libPath = getLibPath(); + wxString footprintName = PCB_BASE_FRAME::SelectFootprint( this, libPath, + wxEmptyString, wxEmptyString, + parent->GetFootprintLibraryTable() ); if( !footprintName ) return false; diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index 49116062b4..2cd9db7dec 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -123,8 +125,8 @@ wxString PCB_BASE_FRAME::SelectFootprintFromLibBrowser( void ) if( viewer ) viewer->Destroy(); - viewer = new FOOTPRINT_VIEWER_FRAME( this, &semaphore, - KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT ); + viewer = new FOOTPRINT_VIEWER_FRAME( this, m_footprintLibTable, &semaphore, + KICAD_DEFAULT_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT ); // Show the library viewer frame until it is closed while( semaphore.TryWait() == wxSEMA_BUSY ) // Wait for viewer closing event @@ -147,9 +149,10 @@ wxString PCB_BASE_FRAME::SelectFootprintFromLibBrowser( void ) } -MODULE* PCB_BASE_FRAME::Load_Module_From_Library( const wxString& aLibrary, - bool aUseFootprintViewer, - wxDC* aDC ) +MODULE* PCB_BASE_FRAME::LoadModuleFromLibrary( const wxString& aLibrary, + FP_LIB_TABLE* aTable, + bool aUseFootprintViewer, + wxDC* aDC ) { MODULE* module; wxPoint curspos = GetScreen()->GetCrossHairPosition(); @@ -195,7 +198,7 @@ MODULE* PCB_BASE_FRAME::Load_Module_From_Library( const wxString& aLibrary, { allowWildSeach = false; keys = moduleName; - moduleName = SelectFootprint( this, libName, wxEmptyString, keys ); + moduleName = SelectFootprint( this, libName, wxEmptyString, keys, aTable ); if( moduleName.IsEmpty() ) // Cancel command { @@ -207,7 +210,7 @@ MODULE* PCB_BASE_FRAME::Load_Module_From_Library( const wxString& aLibrary, || moduleName.Contains( wxT( "*" ) ) ) // Selection wild card { allowWildSeach = false; - moduleName = SelectFootprint( this, libName, moduleName, wxEmptyString ); + moduleName = SelectFootprint( this, libName, moduleName, wxEmptyString, aTable ); if( moduleName.IsEmpty() ) { @@ -225,7 +228,7 @@ MODULE* PCB_BASE_FRAME::Load_Module_From_Library( const wxString& aLibrary, wxString wildname = wxChar( '*' ) + moduleName + wxChar( '*' ); moduleName = wildname; - moduleName = SelectFootprint( this, libName, moduleName, wxEmptyString ); + moduleName = SelectFootprint( this, libName, moduleName, wxEmptyString, aTable ); if( moduleName.IsEmpty() ) { @@ -390,38 +393,40 @@ MODULE* PCB_BASE_FRAME::loadFootprintFromLibraries( } -MODULE* PCB_BASE_FRAME::loadFootprint( const wxString& aFootprintName ) +MODULE* PCB_BASE_FRAME::loadFootprint( const FPID& aFootprintId ) throw( IO_ERROR, PARSE_ERROR ) { - wxString libPath; - wxFileName fn; - MODULE* footprint; + wxCHECK_MSG( m_footprintLibTable != NULL, NULL, + wxT( "Cannot look up FPID in NULL FP_LIB_TABLE." ) ); - PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) ); + wxString libName = FROM_UTF8( aFootprintId.GetLibNickname().c_str() ); - for( unsigned ii = 0; ii < g_LibraryNames.GetCount(); ii++ ) + const FP_LIB_TABLE::ROW* row = m_footprintLibTable->FindRow( libName ); + + if( row == NULL ) { - fn = wxFileName( wxEmptyString, g_LibraryNames[ii], LegacyFootprintLibPathExtension ); - - libPath = wxGetApp().FindLibraryPath( fn ); - - if( !libPath ) - continue; - - footprint = pi->FootprintLoad( libPath, aFootprintName ); - - if( footprint ) - return footprint; + wxString msg; + msg.Printf( _( "No library named <%s> was found in the footprint library table." ), + aFootprintId.GetLibNickname().c_str() ); + THROW_IO_ERROR( msg ); } - return NULL; + wxString footprintName = FROM_UTF8( aFootprintId.GetFootprintName().c_str() ); + wxString libPath = row->GetFullURI(); + + libPath = FP_LIB_TABLE::ExpandSubstitutions( libPath ); + + PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::EnumFromStr( row->GetType() ) ) ); + + return pi->FootprintLoad( libPath, footprintName ); } wxString PCB_BASE_FRAME::SelectFootprint( EDA_DRAW_FRAME* aWindow, const wxString& aLibraryFullFilename, const wxString& aMask, - const wxString& aKeyWord ) + const wxString& aKeyWord, + FP_LIB_TABLE* aTable ) { static wxString OldName; // Save the name of the last module loaded. wxString CmpName; @@ -431,9 +436,26 @@ wxString PCB_BASE_FRAME::SelectFootprint( EDA_DRAW_FRAME* aWindow, if( aLibraryFullFilename.IsEmpty() ) + { +#if !defined( USE_FP_LIB_TABLE ) libraries = g_LibraryNames; +#else + wxASSERT( aTable != NULL ); + + std::vector< wxString > libNames = aTable->GetLogicalLibs(); + + for( unsigned i = 0; i < libNames.size(); i++ ) + { + wxString uri = aTable->FindRow( libNames[i] )->GetFullURI(); + uri = FP_LIB_TABLE::ExpandSubstitutions( uri ); + libraries.Add( uri ); + } +#endif + } else + { libraries.Add( aLibraryFullFilename ); + } if( libraries.IsEmpty() ) { diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index 91718e5915..50aad23fcf 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -234,9 +234,10 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_OPEN_MODULE_VIEWER: { FOOTPRINT_VIEWER_FRAME * viewer = FOOTPRINT_VIEWER_FRAME::GetActiveFootprintViewer(); + if( viewer == NULL ) { - viewer = new FOOTPRINT_VIEWER_FRAME( this, NULL ); + viewer = new FOOTPRINT_VIEWER_FRAME( this, m_footprintLibTable, NULL ); viewer->Show( true ); viewer->Zoom_Automatique( false ); } @@ -459,6 +460,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_MODEDIT_LOAD_MODULE: { + PCB_EDIT_FRAME* parent = (PCB_EDIT_FRAME*) GetParent(); wxString libPath = getLibPath(); // might be empty wxLogDebug( wxT( "Loading module from library " ) + libPath ); @@ -467,7 +469,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) SetCurItem( NULL ); Clear_Pcb( true ); GetScreen()->SetCrossHairPosition( wxPoint( 0, 0 ) ); - Load_Module_From_Library( libPath, true ); + LoadModuleFromLibrary( libPath, parent->GetFootprintLibraryTable(), true ); redraw = true; } diff --git a/pcbnew/modview.cpp b/pcbnew/modview.cpp index 1ffeab8726..a923535d3c 100644 --- a/pcbnew/modview.cpp +++ b/pcbnew/modview.cpp @@ -143,9 +143,11 @@ void FOOTPRINT_VIEWER_FRAME::SelectCurrentLibrary( wxCommandEvent& event ) void FOOTPRINT_VIEWER_FRAME::SelectCurrentFootprint( wxCommandEvent& event ) { - wxString libname = m_libraryName + wxT( "." ) + LegacyFootprintLibPathExtension; - MODULE* oldmodule = GetBoard()->m_Modules; - MODULE * module = Load_Module_From_Library( libname, false ); + PCB_EDIT_FRAME* parent = (PCB_EDIT_FRAME*) GetParent(); + wxString libname = m_libraryName + wxT( "." ) + LegacyFootprintLibPathExtension; + MODULE* oldmodule = GetBoard()->m_Modules; + MODULE* module = LoadModuleFromLibrary( libname, parent->GetFootprintLibraryTable(), + false ); if( module ) { diff --git a/pcbnew/modview_frame.cpp b/pcbnew/modview_frame.cpp index fc596e2bd8..d95939ce74 100644 --- a/pcbnew/modview_frame.cpp +++ b/pcbnew/modview_frame.cpp @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #include #include @@ -113,13 +116,18 @@ static wxAcceleratorEntry accels[] = #define FOOTPRINT_VIEWER_FRAME_NAME wxT( "ModViewFrame" ) -FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* parent, - wxSemaphore* semaphore, long style ) : - PCB_BASE_FRAME( parent, MODULE_VIEWER_FRAME_TYPE, _( "Footprint Library Browser" ), - wxDefaultPosition, wxDefaultSize, style, GetFootprintViewerFrameName() ) +FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* aParent, + FP_LIB_TABLE* aTable, + wxSemaphore* aSemaphore, + long aStyle ) : + PCB_BASE_FRAME( aParent, MODULE_VIEWER_FRAME_TYPE, _( "Footprint Library Browser" ), + wxDefaultPosition, wxDefaultSize, aStyle, GetFootprintViewerFrameName() ) { + wxASSERT( aTable != NULL ); + wxAcceleratorTable table( ACCEL_TABLE_CNT, accels ); + m_footprintLibTable = aTable; m_FrameName = GetFootprintViewerFrameName(); m_configPath = wxT( "FootprintViewer" ); m_showAxis = true; // true to draw axis. @@ -134,11 +142,11 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* parent, m_LibList = NULL; m_LibListWindow = NULL; m_FootprintListWindow = NULL; - m_Semaphore = semaphore; + m_Semaphore = aSemaphore; m_selectedFootprintName.Empty(); if( m_Semaphore ) - SetModalMode(true); + SetModalMode( true ); SetBoard( new BOARD() ); // Ensure all layers and items are visible: @@ -177,16 +185,16 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* parent, m_FootprintListSize.y = size.y; win_pos.x = m_LibListSize.x; m_FootprintListWindow = new wxSashLayoutWindow( this, ID_MODVIEW_FOOTPRINT_WINDOW, - win_pos, wxDefaultSize, - wxCLIP_CHILDREN | wxSW_3D, - wxT( "CmpWindow" ) ); + win_pos, wxDefaultSize, + wxCLIP_CHILDREN | wxSW_3D, + wxT( "CmpWindow" ) ); m_FootprintListWindow->SetOrientation( wxLAYOUT_VERTICAL ); m_FootprintListWindow->SetSashVisible( wxSASH_RIGHT, true ); m_FootprintListWindow->SetExtraBorderSize( EXTRA_BORDER_SIZE ); m_FootprintList = new wxListBox( m_FootprintListWindow, ID_MODVIEW_FOOTPRINT_LIST, - wxPoint( 0, 0 ), wxDefaultSize, - 0, NULL, wxLB_HSCROLL ); + wxPoint( 0, 0 ), wxDefaultSize, + 0, NULL, wxLB_HSCROLL ); ReCreateLibraryList(); @@ -194,8 +202,17 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* parent, // If a footprint was previsiously loaded, reload it if( !m_libraryName.IsEmpty() && !m_footprintName.IsEmpty() ) + { +#if !defined( USE_FP_LIB_TABLE ) GetModuleLibrary( m_libraryName + wxT(".") + LegacyFootprintLibPathExtension, - m_footprintName, false ); + m_footprintName, false ); +#else + FPID id; + id.SetLibNickname( TO_UTF8( m_libraryName ) ); + id.SetFootprintName( TO_UTF8( m_footprintName ) ); + GetBoard()->Add( loadFootprint( id ) ); +#endif + } if( m_canvas ) @@ -239,18 +256,19 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* parent, // Manage the message panel m_auimgr.AddPane( m_messagePanel, - wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom().Layer(10) ); + wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom().Layer( 10 ) ); /* Now the minimum windows are fixed, set library list * and component list of the previous values from last viewlib use */ if( m_LibListWindow ) { - wxAuiPaneInfo& pane = m_auimgr.GetPane(m_LibListWindow); - pane.MinSize( wxSize(m_LibListSize.x, -1)); + wxAuiPaneInfo& pane = m_auimgr.GetPane( m_LibListWindow ); + pane.MinSize( wxSize( m_LibListSize.x, -1 ) ); } - wxAuiPaneInfo& pane = m_auimgr.GetPane(m_FootprintListWindow); - pane.MinSize(wxSize(m_FootprintListSize.x, -1)); + + wxAuiPaneInfo& pane = m_auimgr.GetPane( m_FootprintListWindow ); + pane.MinSize( wxSize( m_FootprintListSize.x, -1 ) ); m_auimgr.Update(); @@ -296,7 +314,7 @@ void FOOTPRINT_VIEWER_FRAME::OnCloseWindow( wxCloseEvent& Event ) if( m_Semaphore ) { m_Semaphore->Post(); - SetModalMode(false); + SetModalMode( false ); // This window will be destroyed by the calling function, // to avoid side effects } @@ -359,10 +377,18 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateLibraryList() return; m_LibList->Clear(); + +#if !defined( USE_FP_LIB_TABLE ) for( unsigned ii = 0; ii < g_LibraryNames.GetCount(); ii++ ) { m_LibList->Append( g_LibraryNames[ii] ); } +#else + std::vector< wxString > libName = m_footprintLibTable->GetLogicalLibs(); + + for( unsigned ii = 0; ii < libName.size(); ii++ ) + m_LibList->Append( libName[ii] ); +#endif // Search for a previous selection: int index = m_LibList->FindString( m_libraryName ); @@ -400,7 +426,21 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList() } wxArrayString libsList; + +#if !defined( USE_FP_LIB_TABLE ) libsList.Add( m_libraryName ); +#else + wxString uri = m_footprintLibTable->FindRow( m_libraryName )->GetFullURI(); + + if( uri.IsEmpty() ) + return; + + uri = FP_LIB_TABLE::ExpandSubstitutions( uri ); + wxLogDebug( wxT( "Footprint library <%s> selected." ), GetChars( uri ) ); + + libsList.Add( uri ); +#endif + FOOTPRINT_LIST fp_info_list; fp_info_list.ReadFootprintFiles( libsList ); @@ -455,8 +495,28 @@ void FOOTPRINT_VIEWER_FRAME::ClickOnFootprintList( wxCommandEvent& event ) SetCurItem( NULL ); // Delete the current footprint GetBoard()->m_Modules.DeleteAll(); +#if !defined( USE_FP_LIB_TABLE ) GetModuleLibrary( m_libraryName + wxT(".") + LegacyFootprintLibPathExtension, m_footprintName, true ); +#else + FPID id; + id.SetLibNickname( TO_UTF8( m_libraryName ) ); + id.SetFootprintName( TO_UTF8( m_footprintName ) ); + + try + { + GetBoard()->Add( loadFootprint( id ) ); + } + catch( IO_ERROR ioe ) + { + wxString msg; + msg.Printf( _( "Could not load footprint \"%s\" from library \"%s\".\n\n" + "Error %s." ), GetChars( m_footprintName ), GetChars( m_libraryName ), + GetChars( ioe.errorText ) ); + DisplayError( this, msg ); + } +#endif + DisplayLibInfos(); Zoom_Automatique( false ); m_canvas->Refresh(); @@ -464,6 +524,7 @@ void FOOTPRINT_VIEWER_FRAME::ClickOnFootprintList( wxCommandEvent& event ) } } + void FOOTPRINT_VIEWER_FRAME::DClickOnFootprintList( wxCommandEvent& event ) { if( m_Semaphore ) @@ -478,6 +539,7 @@ void FOOTPRINT_VIEWER_FRAME::DClickOnFootprintList( wxCommandEvent& event ) } } + void FOOTPRINT_VIEWER_FRAME::ExportSelectedFootprint( wxCommandEvent& event ) { int ii = m_FootprintList->GetSelection(); @@ -549,11 +611,13 @@ void FOOTPRINT_VIEWER_FRAME::OnActivate( wxActivateEvent& event ) if( g_LibraryNames.GetCount() == m_LibList->GetCount() ) { unsigned ii; + for( ii = 0; ii < g_LibraryNames.GetCount(); ii++ ) { if( m_LibList->GetString(ii) != g_LibraryNames[ii] ) break; } + if( ii == g_LibraryNames.GetCount() ) return; } @@ -677,11 +741,7 @@ void FOOTPRINT_VIEWER_FRAME::Show3D_Frame( wxCommandEvent& event ) m_Draw3DFrame->Show( true ); } -/** - * Function Update3D_Frame - * must be called after a footprint selection - * Updates the 3D view and 3D frame title. - */ + void FOOTPRINT_VIEWER_FRAME::Update3D_Frame( bool aForceReloadFootprint ) { if( m_Draw3DFrame == NULL ) @@ -694,14 +754,15 @@ void FOOTPRINT_VIEWER_FRAME::Update3D_Frame( bool aForceReloadFootprint ) if( aForceReloadFootprint ) { m_Draw3DFrame->ReloadRequest(); + // Force 3D screen refresh immediately if( GetBoard()->m_Modules ) m_Draw3DFrame->NewDisplay(); } } + EDA_COLOR_T FOOTPRINT_VIEWER_FRAME::GetGridColor() const { return g_ColorsSettings.GetItemColor( GRID_VISIBLE ); } - diff --git a/pcbnew/modview_frame.h b/pcbnew/modview_frame.h index f034df5525..61afcffbd5 100644 --- a/pcbnew/modview_frame.h +++ b/pcbnew/modview_frame.h @@ -35,6 +35,7 @@ class wxSashLayoutWindow; class wxListBox; class wxSemaphore; +class FP_LIB_TABLE; /** @@ -64,8 +65,9 @@ protected: // the selected footprint is here public: - FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* parent, wxSemaphore* semaphore = NULL, - long style = KICAD_DEFAULT_DRAWFRAME_STYLE ); + FOOTPRINT_VIEWER_FRAME( PCB_BASE_FRAME* aParent, FP_LIB_TABLE* aTable, + wxSemaphore* aSemaphore = NULL, + long aStyle = KICAD_DEFAULT_DRAWFRAME_STYLE ); ~FOOTPRINT_VIEWER_FRAME(); diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index 0e42cfd2a5..f655b1a6a0 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -347,7 +347,8 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) ) { m_canvas->MoveCursorToCrossHair(); - DrawStruct = (BOARD_ITEM*) Load_Module_From_Library( wxEmptyString, true, aDC ); + DrawStruct = (BOARD_ITEM*) LoadModuleFromLibrary( wxEmptyString, m_footprintLibTable, + true, aDC ); SetCurItem( DrawStruct ); if( DrawStruct ) diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 554dde10c5..a744fe4038 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -40,6 +40,7 @@ #include #include <3d_viewer.h> #include +#include #include #include @@ -56,6 +57,7 @@ #include #include + #if defined(KICAD_SCRIPTING) || defined(KICAD_SCRIPTING_WXPYTHON) #include #endif @@ -291,9 +293,13 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, m_RecordingMacros = -1; m_microWaveToolBar = NULL; m_useCmpFileForFpNames = true; + m_footprintLibTable = NULL; + m_globalFootprintTable = NULL; + #ifdef KICAD_SCRIPTING_WXPYTHON m_pythonPanel = NULL; #endif + for ( int i = 0; i < 10; i++ ) m_Macros[i].m_Record.clear(); @@ -424,7 +430,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, m_pythonPanel = CreatePythonShellWindow( this ); m_auimgr.AddPane( m_pythonPanel, - pythonAuiInfo.Name( wxT( "PythonPanel" ) ).Bottom().Layer(9) ); + pythonAuiInfo.Name( wxT( "PythonPanel" ) ).Bottom().Layer(9) ); m_pythonPanelHidden = true; #endif @@ -447,6 +453,7 @@ PCB_EDIT_FRAME::~PCB_EDIT_FRAME() m_Macros[i].m_Record.clear(); delete m_drc; + delete m_globalFootprintTable; } diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 65ac98731c..7ba939a8c6 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -188,9 +189,28 @@ bool EDA_APP::OnInit() frame->LoadProjectSettings( fn.GetFullPath() ); // Set the KISYSMOD environment variable for the current process if it is not already - // defined. This is required to expand the global footprint library table paths. + // defined in the user's environment. This is required to expand the global footprint + // library table paths. if( !wxGetEnv( wxT( "KISYSMOD" ), &msg ) && !GetLibraryPathList().IsEmpty() ) - wxSetEnv( wxT( "KISYSMOD" ), GetLibraryPathList()[0] ); + { + unsigned modFileCount = 0; + wxString bestPath; + wxArrayString tmp; + + for( unsigned i = 0; i < GetLibraryPathList().GetCount(); i++ ) + { + unsigned cnt = wxDir::GetAllFiles( GetLibraryPathList()[i], &tmp, wxT( "*.mod" ) ); + + if( cnt > modFileCount ) + { + modFileCount = cnt; + bestPath = GetLibraryPathList()[i]; + } + } + + wxLogDebug( wxT( "Setting $KISYSMOD=\"%s\"." ), GetChars( bestPath ) ); + wxSetEnv( wxT( "KISYSMOD" ), bestPath ); + } /* Load file specified in the command line. */ if( fn.IsOk() ) diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index fa622281c5..d96272b27e 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -41,12 +41,10 @@ #include #include #include - -#include #include - #include +#include #include #include #include @@ -84,73 +82,28 @@ void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) break; case ID_PCB_LIB_TABLE_EDIT: + { + int r = InvokePcbLibTableEditor( this, m_globalFootprintTable, m_footprintLibTable ); + + if( r & 1 ) { - // scaffolding: dummy up some data into tables, until actual load/save are in place. - FP_LIB_TABLE gbl; - FP_LIB_TABLE prj; + FILE_OUTPUTFORMATTER sf( FP_LIB_TABLE::GetGlobalTableFileName() ); + m_globalFootprintTable->Format( &sf, 0 ); - FP_LIB_TABLE_LEXER glex( - "(fp_lib_table\n" - " (lib (name passives)(descr \"R/C Lib\")(type KiCad)(uri ${KISYSMODS}/passives.pretty))\n" - " (lib (name micros)(descr \"Small stuff\")(type Legacy)(uri ${KISYSMODS}/passives.mod)(options \"op1=2\"))\n" - " (lib (name chips)(descr \"Potatoe chips\")(type Eagle)(uri /opt/eagle-6.2.0/lbr/con-amp-micromatch.lbr))\n" - ")", wxT( "gbl" ) ); - - FP_LIB_TABLE_LEXER plex( - "(fp_lib_table\n" - " (lib (name passives)(descr \"Demo Lib\")(type KiCad)(uri ${KIUSRMODS}/passives.pretty))\n" - " (lib (name micros)(descr \"Small stuff\")(type Legacy)(uri ${KIUSRMODS}/micros.mod)(options \"op1=2\"))\n" - " (lib (name chips)(descr \"Potatoe chips\")(type Eagle)(uri /opt/eagle-6.2.0/lbr/con-amp-micromatch.lbr))\n" - ")", wxT( "prj" ) ); - - try - { - gbl.Parse( &glex ); - prj.Parse( &plex ); - } - /* PARSE_ERROR is an IO_ERROR, handle them the same for now. - catch( PARSE_ERROR pe ) - { - DisplayError( this, pe.errorText ); - break; - } - */ - catch( IO_ERROR ioe ) - { - DisplayError( this, ioe.errorText ); - break; - } - - int r = InvokePcbLibTableEditor( this, &gbl, &prj ); - - if( r & 1 ) - { -#if defined(DEBUG) - printf( "changed global:\n" ); - - STRING_FORMATTER sf; - - gbl.Format( &sf, 0 ); - - printf( "%s\n", sf.GetString().c_str() ); -#endif - // save global table to disk and apply it - } - - if( r & 2 ) - { -#if defined(DEBUG) - printf( "changed project:\n" ); - - STRING_FORMATTER sf; - - prj.Format( &sf, 0 ); - - printf( "%s\n", sf.GetString().c_str() ); -#endif - // save project table to disk and apply it - } } + + if( r & 2 ) + { + wxFileName fn = GetBoard()->GetFileName(); + fn.SetName( FP_LIB_TABLE::GetFileName() ); + fn.SetExt( wxEmptyString ); + + FILE_OUTPUTFORMATTER sf( fn.GetFullPath() ); + m_footprintLibTable->Format( &sf, 0 ); + + } + } + break; case ID_PCB_MASK_CLEARANCE: @@ -268,6 +221,8 @@ bool PCB_EDIT_FRAME::LoadProjectSettings( const wxString& aProjectFileName ) SetElementVisibility( RATSNEST_VISIBLE, showRats ); #endif + loadFootprintLibTable(); + return true; } @@ -579,3 +534,48 @@ void PCB_EDIT_FRAME::ReadMacros() macrosNode = (XNODE*) macrosNode->GetNext(); } } + + +void PCB_EDIT_FRAME::loadFootprintLibTable() +{ + if( m_globalFootprintTable == NULL ) + { + try + { + m_globalFootprintTable = new FP_LIB_TABLE(); + FP_LIB_TABLE::LoadGlobalTable( *m_globalFootprintTable ); + } + catch( IO_ERROR ioe ) + { + wxString msg; + msg.Printf( _( "An error occurred attempting to load the global footprint library " + "table:\n\n%s" ), GetChars( ioe.errorText ) ); + DisplayError( this, msg ); + } + } + + delete m_footprintLibTable; + + wxFileName fn = GetBoard()->GetFileName(); + fn.SetName( FP_LIB_TABLE::GetFileName() ); + fn.SetExt( wxEmptyString ); + + // Check if a project footprint table is defined and load it. If no project footprint + // table is defined, then the global library table is the footprint library table. + + m_footprintLibTable = new FP_LIB_TABLE( m_globalFootprintTable ); + + if( fn.FileExists() ) + { + try + { + FILE_LINE_READER reader( fn.GetFullPath() ); + FP_LIB_TABLE_LEXER lexer( &reader ); + m_footprintLibTable->Parse( &lexer ); + } + catch( IO_ERROR ioe ) + { + DisplayError( this, ioe.errorText ); + } + } +} diff --git a/pcbnew/xchgmod.cpp b/pcbnew/xchgmod.cpp index 9e529c247c..15804bc945 100644 --- a/pcbnew/xchgmod.cpp +++ b/pcbnew/xchgmod.cpp @@ -589,7 +589,8 @@ void DIALOG_EXCHANGE_MODULE::BrowseAndSelectFootprint( wxCommandEvent& event ) { wxString newname; - newname = m_Parent->SelectFootprint( m_Parent, wxEmptyString, wxEmptyString, wxEmptyString ); + newname = m_Parent->SelectFootprint( m_Parent, wxEmptyString, wxEmptyString, wxEmptyString, + m_Parent->GetFootprintLibraryTable() ); if( newname != wxEmptyString ) m_NewModule->SetValue( newname );