diff --git a/eeschema/dialogs/dialog_edit_symbols_libid.cpp b/eeschema/dialogs/dialog_edit_symbols_libid.cpp index 17fc8ec817..ccac7969aa 100644 --- a/eeschema/dialogs/dialog_edit_symbols_libid.cpp +++ b/eeschema/dialogs/dialog_edit_symbols_libid.cpp @@ -670,6 +670,7 @@ bool DIALOG_EDIT_SYMBOLS_LIBID::setLibIdByBrowser( int aRow ) { // Use library viewer to choose a symbol std::vector dummyHistory; + std::vector dummyAlreadyPlaced; LIB_ID preselected; wxString current = getLibIdValue( m_grid, aRow, COL_NEW_LIBID ); @@ -679,8 +680,8 @@ bool DIALOG_EDIT_SYMBOLS_LIBID::setLibIdByBrowser( int aRow ) if( !current.IsEmpty() ) preselected.Parse( current, true ); - PICKED_SYMBOL sel = GetParent()->PickSymbolFromLibrary( nullptr, dummyHistory, false, - &preselected, false ); + PICKED_SYMBOL sel = GetParent()->PickSymbolFromLibrary( + nullptr, dummyHistory, dummyAlreadyPlaced, false, &preselected, false ); if( sel.LibId.empty() ) // command aborted return false; diff --git a/eeschema/dialogs/dialog_symbol_chooser.cpp b/eeschema/dialogs/dialog_symbol_chooser.cpp index b4db696fdb..9a44713877 100644 --- a/eeschema/dialogs/dialog_symbol_chooser.cpp +++ b/eeschema/dialogs/dialog_symbol_chooser.cpp @@ -40,13 +40,14 @@ std::mutex DIALOG_SYMBOL_CHOOSER::g_Mutex; DIALOG_SYMBOL_CHOOSER::DIALOG_SYMBOL_CHOOSER( SCH_BASE_FRAME* aParent, const LIB_ID* aPreselect, const SYMBOL_LIBRARY_FILTER* aFilter, - std::vector& aHistoryList, + std::vector& aHistoryList, + std::vector& aAlreadyPlaced, bool aAllowFieldEdits, bool aShowFootprints ) : DIALOG_SHIM( aParent, wxID_ANY, _( "Choose Symbol" ), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) { wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); - m_chooserPanel = new PANEL_SYMBOL_CHOOSER( aParent, this, aFilter, aHistoryList, + m_chooserPanel = new PANEL_SYMBOL_CHOOSER( aParent, this, aFilter, aHistoryList, aAlreadyPlaced, aAllowFieldEdits, aShowFootprints, [this]() { diff --git a/eeschema/dialogs/dialog_symbol_chooser.h b/eeschema/dialogs/dialog_symbol_chooser.h index 4ae1c58bb9..fa972bed30 100644 --- a/eeschema/dialogs/dialog_symbol_chooser.h +++ b/eeschema/dialogs/dialog_symbol_chooser.h @@ -24,6 +24,7 @@ #define DIALOG_SYMBOL_CHOOSER_H #include "dialog_shim.h" +#include #include #include #include @@ -50,7 +51,8 @@ public: DIALOG_SYMBOL_CHOOSER( SCH_BASE_FRAME* aParent, const LIB_ID* aPreselect, const SYMBOL_LIBRARY_FILTER* aFilter, std::vector& aHistoryList, - bool aAllowFieldEdits, bool aShowFootprints ); + std::vector& aAlreadyPlaced, bool aAllowFieldEdits, + bool aShowFootprints ); ~DIALOG_SYMBOL_CHOOSER(); diff --git a/eeschema/picksymbol.cpp b/eeschema/picksymbol.cpp index e132da5dcd..f2789d08a2 100644 --- a/eeschema/picksymbol.cpp +++ b/eeschema/picksymbol.cpp @@ -24,6 +24,7 @@ */ #include +#include #include #include #include @@ -46,7 +47,8 @@ #include PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibrary( const SYMBOL_LIBRARY_FILTER* aFilter, - std::vector& aHistoryList, + std::vector& aHistoryList, + std::vector& aAlreadyPlaced, bool aShowFootprints, const LIB_ID* aHighlight, bool aAllowFields ) { @@ -56,8 +58,8 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibrary( const SYMBOL_LIBRARY_FILTER if( !dialogLock.try_lock() ) return PICKED_SYMBOL(); - DIALOG_SYMBOL_CHOOSER dlg( this, aHighlight, aFilter, aHistoryList, aAllowFields, - aShowFootprints ); + DIALOG_SYMBOL_CHOOSER dlg( this, aHighlight, aFilter, aHistoryList, aAlreadyPlaced, + aAllowFields, aShowFootprints ); if( dlg.ShowModal() == wxID_CANCEL ) return PICKED_SYMBOL(); diff --git a/eeschema/sch_base_frame.h b/eeschema/sch_base_frame.h index e729a176a2..a55685032e 100644 --- a/eeschema/sch_base_frame.h +++ b/eeschema/sch_base_frame.h @@ -154,7 +154,8 @@ public: * @return the selected symbol */ PICKED_SYMBOL PickSymbolFromLibrary( const SYMBOL_LIBRARY_FILTER* aFilter, - std::vector& aHistoryList, + std::vector& aHistoryList, + std::vector& aAlreadyPlaced, bool aShowFootprints, const LIB_ID* aHighlight = nullptr, bool aAllowFields = true ); diff --git a/eeschema/symbol_chooser_frame.cpp b/eeschema/symbol_chooser_frame.cpp index 556c9d974b..cbf091b602 100644 --- a/eeschema/symbol_chooser_frame.cpp +++ b/eeschema/symbol_chooser_frame.cpp @@ -72,13 +72,16 @@ SYMBOL_CHOOSER_FRAME::SYMBOL_CHOOSER_FRAME( KIWAY* aKiway, wxWindow* aParent ) : SetModal( true ); wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL ); - m_chooserPanel = new PANEL_SYMBOL_CHOOSER( this, this, nullptr /* no filter */, - s_SymbolHistoryList, false, false, - [this]() - { - wxCommandEvent dummy; - OnOK( dummy ); - } ); + + std::vector dummyAlreadyPlaced; + m_chooserPanel = + new PANEL_SYMBOL_CHOOSER( this, this, nullptr /* no filter */, s_SymbolHistoryList, + dummyAlreadyPlaced, false, false, + [this]() + { + wxCommandEvent dummy; + OnOK( dummy ); + } ); sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 ); diff --git a/eeschema/tools/sch_drawing_tools.cpp b/eeschema/tools/sch_drawing_tools.cpp index d0f5d66d73..e37de97193 100644 --- a/eeschema/tools/sch_drawing_tools.cpp +++ b/eeschema/tools/sch_drawing_tools.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -49,7 +50,7 @@ #include #include #include -#include +#include #include #include #include @@ -303,10 +304,43 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent ) { m_toolMgr->RunAction( EE_ACTIONS::clearSelection ); + SCH_SHEET_LIST sheets = m_frame->Schematic().GetSheets(); + SYMBOL_LIB_TABLE* libs = PROJECT_SCH::SchSymbolLibTable( &m_frame->Prj() ); + SYMBOL_LIB* cache = PROJECT_SCH::SchLibs( &m_frame->Prj() )->GetCacheLibrary(); + + std::vector part_list; + + for( SCH_SHEET_PATH& sheet : sheets ) + { + for( SCH_ITEM* item : sheet.LastScreen()->Items() ) + { + if( item->Type() != SCH_SYMBOL_T ) + continue; + + SCH_SYMBOL* s = static_cast( item ); + LIB_SYMBOL* libSymbol = SchGetLibSymbol( s->GetLibId(), libs, cache ); + + if( libSymbol ) + part_list.push_back( libSymbol ); + } + } + + // Remove redundant parts + sort( part_list.begin(), part_list.end() ); + part_list.erase( unique( part_list.begin(), part_list.end() ), part_list.end() ); + + std::vector alreadyPlaced; + for( LIB_SYMBOL* libSymbol : part_list ) + { + PICKED_SYMBOL pickedSymbol; + pickedSymbol.LibId = libSymbol->GetLibId(); + alreadyPlaced.push_back( pickedSymbol ); + } + // Pick the symbol to be placed bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview; - PICKED_SYMBOL sel = m_frame->PickSymbolFromLibrary( &filter, *historyList, - footprintPreviews ); + PICKED_SYMBOL sel = m_frame->PickSymbolFromLibrary( + &filter, *historyList, alreadyPlaced, footprintPreviews ); LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ? m_frame->GetLibSymbol( sel.LibId ) : nullptr; diff --git a/eeschema/widgets/panel_symbol_chooser.cpp b/eeschema/widgets/panel_symbol_chooser.cpp index f297048262..265e38ed49 100644 --- a/eeschema/widgets/panel_symbol_chooser.cpp +++ b/eeschema/widgets/panel_symbol_chooser.cpp @@ -51,7 +51,8 @@ wxString PANEL_SYMBOL_CHOOSER::g_powerSearchString; PANEL_SYMBOL_CHOOSER::PANEL_SYMBOL_CHOOSER( SCH_BASE_FRAME* aFrame, wxWindow* aParent, const SYMBOL_LIBRARY_FILTER* aFilter, - std::vector& aHistoryList, + std::vector& aHistoryList, + std::vector& aAlreadyPlaced, bool aAllowFieldEdits, bool aShowFootprints, std::function aCloseHandler ) : wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize ), @@ -119,29 +120,39 @@ PANEL_SYMBOL_CHOOSER::PANEL_SYMBOL_CHOOSER( SCH_BASE_FRAME* aFrame, wxWindow* aP std::vector history_list_storage; std::vector history_list; + std::vector already_placed_storage; + std::vector already_placed; - history_list_storage.reserve( aHistoryList.size() ); - - for( const PICKED_SYMBOL& i : aHistoryList ) + // Lambda to encapsulate the common logic + auto processList = [&]( const std::vector& inputList, + std::vector& storageList, + std::vector& resultList ) { - LIB_SYMBOL* symbol = m_frame->GetLibSymbol( i.LibId ); + storageList.reserve( inputList.size() ); - // This can be null, for example when a symbol has been deleted from a library - if( symbol ) + for( const PICKED_SYMBOL& i : inputList ) { - history_list_storage.emplace_back( *symbol ); + LIB_SYMBOL* symbol = m_frame->GetLibSymbol( i.LibId ); - for( const std::pair& fieldDef : i.Fields ) + if( symbol ) { - LIB_FIELD* field = history_list_storage.back().GetFieldById( fieldDef.first ); + storageList.emplace_back( *symbol ); - if( field ) - field->SetText( fieldDef.second ); + for( const std::pair& fieldDef : i.Fields ) + { + LIB_FIELD* field = storageList.back().GetFieldById( fieldDef.first ); + + if( field ) + field->SetText( fieldDef.second ); + } + + resultList.push_back( &storageList.back() ); } - - history_list.push_back( &history_list_storage.back() ); } - } + }; + + processList( aHistoryList, history_list_storage, history_list ); + processList( aAlreadyPlaced, already_placed_storage, already_placed ); adapter->DoAddLibrary( wxT( "-- " ) + _( "Recently Used" ) + wxT( " --" ), wxEmptyString, history_list, false, true ); @@ -149,6 +160,9 @@ PANEL_SYMBOL_CHOOSER::PANEL_SYMBOL_CHOOSER( SCH_BASE_FRAME* aFrame, wxWindow* aP if( !aHistoryList.empty() ) adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit ); + adapter->DoAddLibrary( wxT( "-- " ) + _( "Already Placed" ) + wxT( " --" ), wxEmptyString, + already_placed, false, true ); + const std::vector< wxString > libNicknames = libs->GetLogicalLibs(); if( !loaded ) diff --git a/eeschema/widgets/panel_symbol_chooser.h b/eeschema/widgets/panel_symbol_chooser.h index 5d836509cb..0bbf0973f9 100644 --- a/eeschema/widgets/panel_symbol_chooser.h +++ b/eeschema/widgets/panel_symbol_chooser.h @@ -57,6 +57,7 @@ public: PANEL_SYMBOL_CHOOSER( SCH_BASE_FRAME* aFrame, wxWindow* aParent, const SYMBOL_LIBRARY_FILTER* aFilter, std::vector& aHistoryList, + std::vector& aAlreadyPlaced, bool aAllowFieldEdits, bool aShowFootprints, std::function aCloseHandler );