diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index b13a8c5cd3..7a5881952b 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -2254,3 +2254,7 @@ bool EAGLE_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath ) } */ + +namespace { + static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::EAGLE, wxT("Eagle"), []() -> PLUGIN* { return new EAGLE_PLUGIN; } ); +}; diff --git a/pcbnew/github/github_plugin.cpp b/pcbnew/github/github_plugin.cpp index 29fca902ed..0e59707ecb 100644 --- a/pcbnew/github/github_plugin.cpp +++ b/pcbnew/github/github_plugin.cpp @@ -594,6 +594,10 @@ void GITHUB_PLUGIN::remoteGetZip( const wxString& aRepoURL ) } } +namespace { + static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::GITHUB, wxT("Github"), []() -> PLUGIN* { return new GITHUB_PLUGIN; } ); +}; + #if 0 && defined(STANDALONE) int main( int argc, char** argv ) diff --git a/pcbnew/gpcb_plugin.cpp b/pcbnew/gpcb_plugin.cpp index 2c123bf59a..e1a6bd8450 100644 --- a/pcbnew/gpcb_plugin.cpp +++ b/pcbnew/gpcb_plugin.cpp @@ -1141,3 +1141,7 @@ bool GPCB_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath ) return m_cache->IsWritable(); } + +namespace { + static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::GEDA_PCB, wxT("GEDA/Pcb"), []() -> PLUGIN* { return new GPCB_PLUGIN; } ); +}; diff --git a/pcbnew/io_mgr.cpp b/pcbnew/io_mgr.cpp index cff29cdfd7..fc7773c837 100644 --- a/pcbnew/io_mgr.cpp +++ b/pcbnew/io_mgr.cpp @@ -60,35 +60,7 @@ PLUGIN* IO_MGR::PluginFind( PCB_FILE_T aFileType ) // This implementation is subject to change, any magic is allowed here. // The public IO_MGR API is the only pertinent public information. - switch( aFileType ) - { - case LEGACY: - return new LEGACY_PLUGIN(); - - case KICAD_SEXP: - return new PCB_IO(); - - case EAGLE: - return new EAGLE_PLUGIN(); - - case PCAD: - return new PCAD_PLUGIN(); - - case GEDA_PCB: - return new GPCB_PLUGIN(); - - case GITHUB: -#if defined(BUILD_GITHUB_PLUGIN) - return new GITHUB_PLUGIN(); -#else - THROW_IO_ERROR( "BUILD_GITHUB_PLUGIN not enabled in cmake build environment" ); -#endif - - case FILE_TYPE_NONE: - return NULL; - } - - return NULL; + return PLUGIN_REGISTRY::Instance()->Create( aFileType ); } @@ -108,29 +80,17 @@ const wxString IO_MGR::ShowType( PCB_FILE_T aType ) // text spellings. If you change the spellings, you will obsolete // library tables, so don't do change, only additions are ok. - switch( aType ) + const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins(); + + for( const auto& plugin : plugins ) { - default: - return wxString::Format( _( "Unknown PCB_FILE_T value: %d" ), aType ); - - case LEGACY: - return wxString( wxT( "Legacy" ) ); - - case KICAD_SEXP: - return wxString( wxT( "KiCad" ) ); - - case EAGLE: - return wxString( wxT( "Eagle" ) ); - - case PCAD: - return wxString( wxT( "P-Cad" ) ); - - case GEDA_PCB: - return wxString( wxT( "Geda-PCB" ) ); - - case GITHUB: - return wxString( wxT( "Github" ) ); + if ( plugin.m_type == aType ) + { + return plugin.m_name; + } } + + return wxString::Format( _( "Unknown PCB_FILE_T value: %d" ), aType ); } @@ -140,25 +100,15 @@ IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType ) // text spellings. If you change the spellings, you will obsolete // library tables, so don't do change, only additions are ok. - if( aType == wxT( "KiCad" ) ) - return KICAD_SEXP; + const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins(); - if( aType == wxT( "Legacy" ) ) - return LEGACY; - - if( aType == wxT( "Eagle" ) ) - return EAGLE; - - if( aType == wxT( "P-Cad" ) ) - return PCAD; - - if( aType == wxT( "Geda-PCB" ) ) - return GEDA_PCB; - - if( aType == wxT( "Github" ) ) - return GITHUB; - - // wxASSERT( blow up here ) + for( const auto& plugin : plugins ) + { + if ( plugin.m_name == aType ) + { + return plugin.m_type; + } + } return PCB_FILE_T( -1 ); } diff --git a/pcbnew/io_mgr.h b/pcbnew/io_mgr.h index ce889a45c9..ae829e95ff 100644 --- a/pcbnew/io_mgr.h +++ b/pcbnew/io_mgr.h @@ -27,7 +27,7 @@ #include #include - +#include class BOARD; class PLUGIN; @@ -65,6 +65,78 @@ public: FILE_TYPE_NONE }; + /** + * Class PLUGIN_REGISTRY + * Holds a list of available plugins, created using a singleton REGISTER_PLUGIN object. + * This way, plugins can be added link-time. + */ + class PLUGIN_REGISTRY + { + public: + struct ENTRY + { + PCB_FILE_T m_type; + std::function m_createFunc; + wxString m_name; + }; + + static PLUGIN_REGISTRY *Instance() + { + static PLUGIN_REGISTRY *self = nullptr; + + if( !self ) + { + self = new PLUGIN_REGISTRY; + } + return self; + } + + void Register( PCB_FILE_T aType, const wxString& aName, std::function aCreateFunc ) + { + ENTRY ent; + ent.m_type = aType; + ent.m_createFunc = aCreateFunc; + ent.m_name = aName; + m_plugins.push_back( ent ); + } + + PLUGIN* Create( PCB_FILE_T aFileType ) const + { + for( auto& ent : m_plugins ) + { + if ( ent.m_type == aFileType ) + { + return ent.m_createFunc(); + } + } + return nullptr; + } + + const std::vector& AllPlugins() const + { + return m_plugins; + } + + private: + std::vector m_plugins; + }; + + /** + * Class REGISTER_PLUGIN + * Registers a plugin. Declare as a static variable in an anonymous namespace. + * @param aType: type of the plugin + * @param aName: name of the file format + * @param aCreateFunc: function that creates a new object for the plugin. + */ + struct REGISTER_PLUGIN + { + REGISTER_PLUGIN( PCB_FILE_T aType, const wxString& aName, std::function aCreateFunc ) + { + PLUGIN_REGISTRY::Instance()->Register( aType, aName, aCreateFunc ); + } + }; + + /** * Function PluginFind * returns a PLUGIN which the caller can use to import, export, save, or load diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 9431384acf..dd52699ee1 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -2214,3 +2214,7 @@ bool PCB_IO::IsFootprintLibWritable( const wxString& aLibraryPath ) return m_cache->IsWritable(); } + +namespace { + static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::KICAD_SEXP, wxT("KiCad"), []() -> PLUGIN* { return new PCB_IO; } ); +}; diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index f98452d777..8eab2bd9b9 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -3505,3 +3505,7 @@ LEGACY_PLUGIN::~LEGACY_PLUGIN() delete m_cache; delete m_mapping; } + +namespace { + static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::LEGACY, wxT("Legacy"), []() -> PLUGIN* { return new LEGACY_PLUGIN; } ); +}; diff --git a/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.cpp b/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.cpp index 0c7c75c974..6945d7eb38 100644 --- a/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.cpp +++ b/pcbnew/pcad2kicadpcb_plugin/pcad_plugin.cpp @@ -89,3 +89,7 @@ BOARD* PCAD_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const P return m_board; } + +namespace { + static IO_MGR::REGISTER_PLUGIN registerSelf( IO_MGR::PCAD, wxT("P-Cad"), []() -> PLUGIN* { return new PCAD_PLUGIN; } ); +};