/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2011 Wayne Stambaugh * Copyright (C) 1992-2019 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 */ /** * @file cvpcb_mainframe.cpp */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include <3d_cache/3d_cache.h> #include #include #include #include #include #include #include #include wxSize const FRAME_MIN_SIZE_DU( 350, 250 ); wxSize const FRAME_DEFAULT_SIZE_DU( 450, 300 ); ///@{ /// \ingroup config static const wxString FilterFootprintEntry = "FilterFootprint"; ///@} BEGIN_EVENT_TABLE( CVPCB_MAINFRAME, KIWAY_PLAYER ) // Menu events EVT_MENU( ID_SAVE_PROJECT, CVPCB_MAINFRAME::OnSaveAndContinue ) EVT_MENU( wxID_EXIT, CVPCB_MAINFRAME::OnQuit ) EVT_MENU( wxID_HELP, CVPCB_MAINFRAME::GetKicadHelp ) EVT_MENU( wxID_ABOUT, CVPCB_MAINFRAME::GetKicadAbout ) EVT_MENU( ID_PREFERENCES_CONFIGURE_PATHS, CVPCB_MAINFRAME::OnConfigurePaths ) EVT_MENU( ID_CVPCB_EQUFILES_LIST_EDIT, CVPCB_MAINFRAME::OnEditEquFilesList ) // Toolbar events EVT_TOOL( ID_CVPCB_LIB_TABLE_EDIT, CVPCB_MAINFRAME::OnEditFootprintLibraryTable ) EVT_TOOL( ID_CVPCB_CREATE_SCREENCMP, CVPCB_MAINFRAME::DisplayModule ) EVT_TOOL( ID_CVPCB_GOTO_FIRSTNA, CVPCB_MAINFRAME::ToFirstNA ) EVT_TOOL( ID_CVPCB_GOTO_PREVIOUSNA, CVPCB_MAINFRAME::ToPreviousNA ) EVT_TOOL( ID_CVPCB_DEL_ALL_ASSOCIATIONS, CVPCB_MAINFRAME::DelAllAssociations ) EVT_TOOL( ID_CVPCB_DEL_ASSOCIATION, CVPCB_MAINFRAME::DelAssociation ) EVT_TOOL( ID_CVPCB_CUT_ASSOCIATION, CVPCB_MAINFRAME::CutAssociation ) EVT_TOOL( ID_CVPCB_COPY_ASSOCIATION, CVPCB_MAINFRAME::CopyAssociation ) EVT_TOOL( ID_CVPCB_PASTE_ASSOCIATION, CVPCB_MAINFRAME::PasteAssociation ) EVT_TOOL( ID_CVPCB_AUTO_ASSOCIE, CVPCB_MAINFRAME::AutomaticFootprintMatching ) EVT_TOOL( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST, CVPCB_MAINFRAME::OnSelectFilteringFootprint ) EVT_TOOL( ID_CVPCB_FOOTPRINT_DISPLAY_PIN_FILTERED_LIST, CVPCB_MAINFRAME::OnSelectFilteringFootprint ) EVT_TOOL( ID_CVPCB_FOOTPRINT_DISPLAY_BY_LIBRARY_LIST, CVPCB_MAINFRAME::OnSelectFilteringFootprint ) EVT_TOOL( ID_CVPCB_FOOTPRINT_DISPLAY_BY_NAME, CVPCB_MAINFRAME::OnSelectFilteringFootprint ) EVT_TEXT( ID_CVPCB_FILTER_TEXT_EDIT, CVPCB_MAINFRAME::OnEnterFilteringText ) // Button events EVT_BUTTON( wxID_OK, CVPCB_MAINFRAME::OnOK ) EVT_BUTTON( wxID_CANCEL, CVPCB_MAINFRAME::OnCancel ) // Frame events EVT_CLOSE( CVPCB_MAINFRAME::OnCloseWindow ) EVT_SIZE( CVPCB_MAINFRAME::OnSize ) // Handle the escape key EVT_TOOL( ID_CVPCB_ESCAPE_KEY, CVPCB_MAINFRAME::OnEscapeKey ) // UI event handlers EVT_UPDATE_UI( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST, CVPCB_MAINFRAME::OnFilterFPbyKeywords ) EVT_UPDATE_UI( ID_CVPCB_FOOTPRINT_DISPLAY_PIN_FILTERED_LIST, CVPCB_MAINFRAME::OnFilterFPbyPinCount ) EVT_UPDATE_UI( ID_CVPCB_FOOTPRINT_DISPLAY_BY_LIBRARY_LIST, CVPCB_MAINFRAME::OnFilterFPbyLibrary ) EVT_UPDATE_UI( ID_CVPCB_FOOTPRINT_DISPLAY_BY_NAME, CVPCB_MAINFRAME::OnFilterFPbyKeyName ) END_EVENT_TABLE() #define CVPCB_MAINFRAME_NAME wxT( "CvpcbFrame" ) CVPCB_MAINFRAME::CVPCB_MAINFRAME( KIWAY* aKiway, wxWindow* aParent ) : KIWAY_PLAYER( aKiway, aParent, FRAME_CVPCB, _( "Assign Footprints" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, CVPCB_MAINFRAME_NAME ) { m_compListBox = NULL; m_footprintListBox = NULL; m_libListBox = NULL; m_mainToolBar = NULL; m_modified = false; m_skipComponentSelect = false; m_filteringOptions = 0; m_tcFilterString = NULL; m_FootprintsList = FOOTPRINT_LIST::GetInstance( Kiway() ); m_initialized = false; // Give an icon wxIcon icon; icon.CopyFromBitmap( KiBitmap( icon_cvpcb_xpm ) ); SetIcon( icon ); SetAutoLayout( true ); LoadSettings( config() ); wxSize const frame_min( ConvertDialogToPixels( FRAME_MIN_SIZE_DU ) ); SetSizeHints( frame_min ); // Frame size and position SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); ReCreateMenuBar(); ReCreateHToolbar(); // Create list of available modules and components of the schematic BuildCmpListBox(); BuildFOOTPRINTS_LISTBOX(); BuildLIBRARY_LISTBOX(); m_auimgr.SetManagedWindow( this ); m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) ); m_auimgr.AddPane( m_libListBox, EDA_PANE().Palette().Name( "Libraries" ).Left().Layer(1) .Caption( _( "Footprint Libraries" ) ) .BestSize( (int) ( m_FrameSize.x * 0.20 ), m_FrameSize.y ) ); m_auimgr.AddPane( m_compListBox, EDA_PANE().Palette().Name( "Components" ).Center().Layer(0) .Caption( _( "Symbol : Footprint Assignments" ) ) ); m_auimgr.AddPane( m_footprintListBox, EDA_PANE().Palette().Name( "Footprints" ).Right().Layer(1) .Caption( _( "Filtered Footprints" ) ) .BestSize( (int) ( m_FrameSize.x * 0.30 ), m_FrameSize.y ) ); // Build the bottom panel, to display 2 status texts and the buttons: auto bottomPanel = new wxPanel( this ); auto panelSizer = new wxBoxSizer( wxVERTICAL ); wxFlexGridSizer* fgSizerStatus = new wxFlexGridSizer( 3, 1, 0, 0 ); fgSizerStatus->SetFlexibleDirection( wxBOTH ); fgSizerStatus->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); m_statusLine1 = new wxStaticText( bottomPanel, wxID_ANY, wxEmptyString ); fgSizerStatus->Add( m_statusLine1, 0, 0, 5 ); m_statusLine2 = new wxStaticText( bottomPanel, wxID_ANY, wxEmptyString ); fgSizerStatus->Add( m_statusLine2, 0, 0, 5 ); m_statusLine3 = new wxStaticText( bottomPanel, wxID_ANY, wxEmptyString ); fgSizerStatus->Add( m_statusLine3, 0, wxBOTTOM, 3 ); panelSizer->Add( fgSizerStatus, 1, wxEXPAND|wxLEFT, 2 ); wxStaticLine* staticline1 = new wxStaticLine( bottomPanel ); panelSizer->Add( staticline1, 0, wxEXPAND, 5 ); wxFont statusFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); statusFont.SetSymbolicSize( wxFONTSIZE_SMALL ); m_statusLine1->SetFont( statusFont ); m_statusLine2->SetFont( statusFont ); m_statusLine3->SetFont( statusFont ); // Add buttons: auto buttonsSizer = new wxBoxSizer( wxHORIZONTAL ); auto sdbSizer = new wxStdDialogButtonSizer(); m_saveAndContinue = new wxButton( bottomPanel, ID_SAVE_PROJECT, _( "Apply, Save Schematic && Continue" ) ); buttonsSizer->Add( m_saveAndContinue, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 20 ); auto sdbSizerOK = new wxButton( bottomPanel, wxID_OK ); sdbSizer->AddButton( sdbSizerOK ); auto sdbSizerCancel = new wxButton( bottomPanel, wxID_CANCEL ); sdbSizer->AddButton( sdbSizerCancel ); sdbSizer->Realize(); buttonsSizer->Add( sdbSizer, 0, 0, 5 ); panelSizer->Add( buttonsSizer, 0, wxALIGN_RIGHT|wxALL, 5 ); bottomPanel->SetSizer( panelSizer ); bottomPanel->Fit(); sdbSizerOK->SetDefault(); m_auimgr.AddPane( bottomPanel, EDA_PANE().HToolbar().Name( "Buttons" ).Bottom().Layer(6) ); m_auimgr.Update(); m_initialized = true; // Connect Events m_saveAndContinue->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CVPCB_MAINFRAME::OnSaveAndContinue ), NULL, this ); m_footprintListBox->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( CVPCB_MAINFRAME::OnFootprintRightClick ), NULL, this ); m_compListBox->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( CVPCB_MAINFRAME::OnComponentRightClick ), NULL, this ); // Add an accelerator to make escape close the window wxAcceleratorEntry entries[1]; entries[0].Set( wxACCEL_NORMAL, WXK_ESCAPE, ID_CVPCB_ESCAPE_KEY ); wxAcceleratorTable accel( 1, entries ); SetAcceleratorTable( accel ); } CVPCB_MAINFRAME::~CVPCB_MAINFRAME() { // Disconnect Events m_saveAndContinue->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CVPCB_MAINFRAME::OnSaveAndContinue ), NULL, this ); m_footprintListBox->Disconnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( CVPCB_MAINFRAME::OnFootprintRightClick ), NULL, this ); m_auimgr.UnInit(); } void CVPCB_MAINFRAME::LoadSettings( wxConfigBase* aCfg ) { EDA_BASE_FRAME::LoadSettings( aCfg ); wxSize const frame_default( ConvertDialogToPixels( FRAME_DEFAULT_SIZE_DU ) ); if( m_FrameSize == wxDefaultSize ) m_FrameSize = frame_default; aCfg->Read( FilterFootprintEntry, &m_filteringOptions, FOOTPRINTS_LISTBOX::UNFILTERED_FP_LIST ); } void CVPCB_MAINFRAME::SaveSettings( wxConfigBase* aCfg ) { EDA_BASE_FRAME::SaveSettings( aCfg ); aCfg->Write( FilterFootprintEntry, m_filteringOptions ); } void CVPCB_MAINFRAME::OnSize( wxSizeEvent& event ) { event.Skip(); } void CVPCB_MAINFRAME::OnCloseWindow( wxCloseEvent& Event ) { if( m_modified ) { if( !HandleUnsavedChanges( this, _( "Symbol to Footprint links have been modified. " "Save before exit?" ), [&]()->bool { return SaveFootprintAssociation( false ); } ) ) { Event.Veto(); return; } } // Close module display frame if( GetFootprintViewerFrame() ) GetFootprintViewerFrame()->Close( true ); m_modified = false; // clear highlight symbol in schematic: SendMessageToEESCHEMA( true ); // Delete window Destroy(); } void CVPCB_MAINFRAME::ChangeFocus( bool aMoveRight ) { wxWindow* hasFocus = wxWindow::FindFocus(); if( aMoveRight ) { if( hasFocus == m_libListBox ) m_compListBox->SetFocus(); else if( hasFocus == m_compListBox ) m_footprintListBox->SetFocus(); else if( hasFocus == m_footprintListBox ) m_libListBox->SetFocus(); } else { if( hasFocus == m_libListBox ) m_footprintListBox->SetFocus(); else if( hasFocus == m_compListBox ) m_libListBox->SetFocus(); else if( hasFocus == m_footprintListBox ) m_compListBox->SetFocus(); } } void CVPCB_MAINFRAME::ToFirstNA( wxCommandEvent& event ) { if( m_netlist.IsEmpty() ) return; int first_selected = m_compListBox->GetFirstSelected(); if( first_selected < 0 ) first_selected = -1; // We will start to 0 for the first search , if no item selected int candidate = -1; for( int jj = first_selected+1; jj < (int)m_netlist.GetCount(); jj++ ) { if( m_netlist.GetComponent( jj )->GetFPID().empty() ) { candidate = jj; break; } } if( candidate >= 0 ) { m_compListBox->DeselectAll(); m_compListBox->SetSelection( candidate ); SendMessageToEESCHEMA(); } } void CVPCB_MAINFRAME::ToPreviousNA( wxCommandEvent& event ) { if( m_netlist.IsEmpty() ) return; int first_selected = m_compListBox->GetFirstSelected(); if( first_selected < 0 ) first_selected = m_compListBox->GetCount(); int candidate = -1; for( int jj = first_selected-1; jj >= 0; jj-- ) { if( m_netlist.GetComponent( jj )->GetFPID().empty() ) { candidate = jj; break; } } if( candidate >= 0 ) { m_compListBox->DeselectAll(); m_compListBox->SetSelection( candidate ); SendMessageToEESCHEMA(); } } void CVPCB_MAINFRAME::OnEscapeKey( wxCommandEvent& aEvent ) { Close( false ); } void CVPCB_MAINFRAME::OnOK( wxCommandEvent& aEvent ) { SaveFootprintAssociation( false ); m_modified = false; Close( true ); } void CVPCB_MAINFRAME::OnSaveAndContinue( wxCommandEvent& aEvent ) { SaveFootprintAssociation( true ); m_modified = false; } void CVPCB_MAINFRAME::OnCancel( wxCommandEvent& event ) { // Throw away modifications on a Cancel m_modified = false; Close( false ); } void CVPCB_MAINFRAME::OnQuit( wxCommandEvent& event ) { Close( false ); } void CVPCB_MAINFRAME::CutAssociation( wxCommandEvent& event ) { int itmIdx = m_compListBox->GetFirstSelected(); if( itmIdx == -1 ) return; if( m_netlist.IsEmpty() ) return; COMPONENT* component = m_netlist.GetComponent( itmIdx ); if( component && component->GetFPID().IsValid() ) { m_clipboardBuffer = component->GetFPID().Format().wx_str(); SetNewPkg( wxEmptyString, itmIdx ); m_compListBox->RefreshItem( itmIdx ); } } void CVPCB_MAINFRAME::CopyAssociation( wxCommandEvent& event ) { int itmIdx = m_compListBox->GetFirstSelected(); if( itmIdx == -1 ) return; if( m_netlist.IsEmpty() ) return; COMPONENT* component = m_netlist.GetComponent( itmIdx ); if( component && component->GetFPID().IsValid() ) m_clipboardBuffer = component->GetFPID().Format().wx_str(); } void CVPCB_MAINFRAME::PasteAssociation( wxCommandEvent& event ) { if( m_clipboardBuffer.IsEmpty() ) return; int itmIdx = m_compListBox->GetFirstSelected(); while( itmIdx != -1 ) { SetNewPkg( m_clipboardBuffer, itmIdx ); m_compListBox->RefreshItem( itmIdx ); itmIdx = m_compListBox->GetNextSelected( itmIdx ); } DisplayStatus(); } void CVPCB_MAINFRAME::DelAssociation( wxCommandEvent& event ) { int itmIdx = m_compListBox->GetFirstSelected(); while( itmIdx != -1 ) { SetNewPkg( wxEmptyString, itmIdx ); m_compListBox->RefreshItem( itmIdx ); itmIdx = m_compListBox->GetNextSelected( itmIdx ); } DisplayStatus(); } void CVPCB_MAINFRAME::DelAllAssociations( wxCommandEvent& event ) { if( IsOK( this, _( "Delete all footprint assocations?" ) ) ) { m_skipComponentSelect = true; // Remove all selections to avoid issues when setting the fpids m_compListBox->DeselectAll(); for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { LIB_ID fpid; m_netlist.GetComponent( i )->SetFPID( fpid ); SetNewPkg( wxEmptyString ); } // Remove all selections after setting the fpids m_compListBox->DeselectAll(); m_skipComponentSelect = false; m_compListBox->SetSelection( 0 ); } DisplayStatus(); } bool CVPCB_MAINFRAME::OpenProjectFiles( const std::vector& aFileSet, int aCtl ) { return true; } void CVPCB_MAINFRAME::OnEditFootprintLibraryTable( wxCommandEvent& aEvent ) { KIFACE* kiface = Kiway().KiFACE( KIWAY::FACE_PCB ); kiface->CreateWindow( this, DIALOG_PCB_LIBRARY_TABLE, &Kiway() ); wxBusyCursor dummy; BuildLIBRARY_LISTBOX(); m_FootprintsList->ReadFootprintFiles( Prj().PcbFootprintLibs( Kiway() ) ); } void CVPCB_MAINFRAME::DisplayModule( wxCommandEvent& event ) { CreateScreenCmp(); GetFootprintViewerFrame()->RedrawScreen( wxPoint( 0, 0 ), false ); } void CVPCB_MAINFRAME::OnComponentRightClick( wxMouseEvent& event ) { wxMenu menu; menu.Append( ID_CVPCB_CREATE_SCREENCMP, _( "View Footprint" ), _( "Show the assigned footprint in the footprint viewer" ) ); menu.Append( ID_CVPCB_CUT_ASSOCIATION, _( "Cut Footprint Association" ), _( "Cut the assigned footprint" ) ); menu.Append( ID_CVPCB_COPY_ASSOCIATION, _( "Copy Footprint Association" ), _( "Copy the assigned footprint" ) ); menu.Append( ID_CVPCB_PASTE_ASSOCIATION, _( "Paste Footprint Association" ), _( "Paste a footprint assignment" ) ); menu.Append( ID_CVPCB_DEL_ASSOCIATION, _( "Delete Footprint Association" ), _( "Delete the assigned footprint" ) ); PopupMenu( &menu ); } void CVPCB_MAINFRAME::OnFootprintRightClick( wxMouseEvent& event ) { wxMenu menu; menu.Append( ID_CVPCB_CREATE_SCREENCMP, _( "View Footprint" ), _( "Show the current footprint in the footprint viewer" ) ); PopupMenu( &menu ); } void CVPCB_MAINFRAME::OnSelectComponent( wxListEvent& event ) { if( m_skipComponentSelect ) return; wxString libraryName; COMPONENT* component = GetSelectedComponent(); libraryName = m_libListBox->GetSelectedLibrary(); m_footprintListBox->SetFootprints( *m_FootprintsList, libraryName, component, m_currentSearchPattern, m_filteringOptions); if( component && component->GetFPID().IsValid() ) m_footprintListBox->SetSelectedFootprint( component->GetFPID() ); else m_footprintListBox->SetSelection( m_footprintListBox->GetSelection(), false ); refreshAfterComponentSearch (component); } void CVPCB_MAINFRAME::refreshAfterComponentSearch( COMPONENT* component ) { // Tell AuiMgr that objects are changed ! if( m_auimgr.GetManagedWindow() ) // Be sure Aui Manager is initialized // (could be not the case when starting CvPcb m_auimgr.Update(); if( component == NULL ) { DisplayStatus(); return; } // Preview of the already assigned footprint. // Find the footprint that was already chosen for this component and select it, // but only if the selection is made from the component list or the library list. // If the selection is made from the footprint list, do not change the current // selected footprint. if( FindFocus() == m_compListBox || FindFocus() == m_libListBox ) { wxString module = FROM_UTF8( component->GetFPID().Format().c_str() ); m_footprintListBox->SetSelection( m_footprintListBox->GetSelection(), false ); for( int ii = 0; ii < m_footprintListBox->GetCount(); ii++ ) { wxString footprintName; wxString msg = m_footprintListBox->OnGetItemText( ii, 0 ); msg.Trim( true ); msg.Trim( false ); footprintName = msg.AfterFirst( wxChar( ' ' ) ); if( module.Cmp( footprintName ) == 0 ) { m_footprintListBox->SetSelection( ii, true ); break; } } if( GetFootprintViewerFrame() ) CreateScreenCmp(); } SendMessageToEESCHEMA(); DisplayStatus(); } void CVPCB_MAINFRAME::OnSelectFilteringFootprint( wxCommandEvent& event ) { int option = 0; switch( event.GetId() ) { case ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST: option = FOOTPRINTS_LISTBOX::FILTERING_BY_COMPONENT_KEYWORD; break; case ID_CVPCB_FOOTPRINT_DISPLAY_PIN_FILTERED_LIST: option = FOOTPRINTS_LISTBOX::FILTERING_BY_PIN_COUNT; break; case ID_CVPCB_FOOTPRINT_DISPLAY_BY_LIBRARY_LIST: option = FOOTPRINTS_LISTBOX::FILTERING_BY_LIBRARY; break; case ID_CVPCB_FOOTPRINT_DISPLAY_BY_NAME: m_currentSearchPattern = m_tcFilterString->GetValue(); option = FOOTPRINTS_LISTBOX::FILTERING_BY_NAME; break; } if( event.IsChecked() ) m_filteringOptions |= option; else m_filteringOptions &= ~option; wxListEvent l_event; OnSelectComponent( l_event ); } void CVPCB_MAINFRAME::OnFilterFPbyKeywords( wxUpdateUIEvent& event ) { event.Check( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_COMPONENT_KEYWORD ); } void CVPCB_MAINFRAME::OnFilterFPbyPinCount( wxUpdateUIEvent& event ) { event.Check( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_PIN_COUNT ); } void CVPCB_MAINFRAME::OnFilterFPbyLibrary( wxUpdateUIEvent& event ) { event.Check( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_LIBRARY ); } void CVPCB_MAINFRAME::OnFilterFPbyKeyName( wxUpdateUIEvent& event ) { event.Check( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_NAME ); } void CVPCB_MAINFRAME::OnEnterFilteringText( wxCommandEvent& aEvent ) { // Called when changing the filter string in main toolbar. // If the option FOOTPRINTS_LISTBOX::FILTERING_BY_NAME is set, update the list of // available footprints which match the filter m_currentSearchPattern = m_tcFilterString->GetValue(); if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_NAME ) == 0 ) return; OnSelectFilteringFootprint( aEvent ); } void CVPCB_MAINFRAME::DisplayStatus() { if( !m_initialized ) return; wxString filters, msg; COMPONENT* component = GetSelectedComponent(); if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_COMPONENT_KEYWORD ) ) { msg.Empty(); if( component ) { for( unsigned ii = 0; ii < component->GetFootprintFilters().GetCount(); ii++ ) { if( msg.IsEmpty() ) msg += component->GetFootprintFilters()[ii]; else msg += wxT( ", " ) + component->GetFootprintFilters()[ii]; } } filters += _( "key words" ) + wxString::Format( wxT( " (%s)" ), msg ); } if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_PIN_COUNT ) ) { msg.Empty(); if( component ) msg = wxString::Format( wxT( "%i" ), component->GetPinCount() ); if( !filters.IsEmpty() ) filters += wxT( ", " ); filters += _( "pin count" ) + wxString::Format( wxT( " (%s)" ), msg ); } if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_LIBRARY ) ) { msg = m_libListBox->GetSelectedLibrary(); if( !filters.IsEmpty() ) filters += wxT( ", " ); filters += _( "library" ) + wxString::Format( wxT( " (%s)" ), msg ); } if( ( m_filteringOptions & FOOTPRINTS_LISTBOX::FILTERING_BY_NAME ) ) { if( !filters.IsEmpty() ) filters += wxT( ", " ); filters += _( "search text" ); } if( filters.IsEmpty() ) msg = _( "No filtering" ); else msg.Printf( _( "Filtered by %s" ), GetChars( filters ) ); msg << wxT( ": " ) << m_footprintListBox->GetCount(); SetStatusText( msg ); msg.Empty(); wxString footprintName = GetSelectedFootprint(); FOOTPRINT_INFO* module = m_FootprintsList->GetModuleInfo( footprintName ); if( module ) // can be NULL if no netlist loaded { msg = wxString::Format( _( "Description: %s; Key words: %s" ), module->GetDescription(), module->GetKeywords() ); } SetStatusText( msg, 1 ); msg.Empty(); if( module ) // can be NULL if no netlist loaded { FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs( Kiway() ); wxString modLib = module->GetLibNickname(); if( fptbl->HasLibrary( modLib ) ) { msg = wxString::Format( _( "Library location: %s" ), fptbl->GetFullURI( modLib ) ); } } SetStatusText( msg, 2 ); } bool CVPCB_MAINFRAME::LoadFootprintFiles() { FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs( Kiway() ); // Check if there are footprint libraries in the footprint library table. if( !fptbl || !fptbl->GetLogicalLibs().size() ) { wxMessageBox( _( "No PCB footprint libraries are listed in the current footprint " "library table." ), _( "Configuration Error" ), wxOK | wxICON_ERROR ); return false; } WX_PROGRESS_REPORTER progressReporter( this, _( "Loading Footprint Libraries" ), 2 ); m_FootprintsList->ReadFootprintFiles( fptbl, nullptr, &progressReporter ); if( m_FootprintsList->GetErrorCount() ) { m_FootprintsList->DisplayErrors( this ); } return true; } void CVPCB_MAINFRAME::SendMessageToEESCHEMA( bool aClearHighligntOnly ) { if( m_netlist.IsEmpty() ) return; // clear highlight of previously selected components (if any): // Selecting a non existing symbol clears any previously highlighted symbols std::string packet = "$CLEAR: \"HIGHLIGHTED\""; if( Kiface().IsSingle() ) SendCommand( MSG_TO_SCH, packet.c_str() ); else Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this ); if( aClearHighligntOnly ) return; int selection = m_compListBox->GetSelection(); if ( selection < 0 ) // Nothing selected return; if( m_netlist.GetComponent( selection ) == NULL ) return; // Now highlight the selected component: COMPONENT* component = m_netlist.GetComponent( selection ); packet = StrPrintf( "$PART: \"%s\"", TO_UTF8( component->GetReference() ) ); if( Kiface().IsSingle() ) SendCommand( MSG_TO_SCH, packet.c_str() ); else Kiway().ExpressMail( FRAME_SCH, MAIL_CROSS_PROBE, packet, this ); } int CVPCB_MAINFRAME::ReadSchematicNetlist( const std::string& aNetlist ) { STRING_LINE_READER* strrdr = new STRING_LINE_READER( aNetlist, "Eeschema via Kiway" ); KICAD_NETLIST_READER netrdr( strrdr, &m_netlist ); m_netlist.Clear(); try { netrdr.LoadNetlist(); } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error loading schematic.\n%s" ), ioe.What().GetData() ); wxMessageBox( msg, _( "Load Error" ), wxOK | wxICON_ERROR ); return 1; } // We also remove footprint name if it is "$noname" because this is a dummy name, // not the actual name of the footprint. for( unsigned ii = 0; ii < m_netlist.GetCount(); ii++ ) { if( m_netlist.GetComponent( ii )->GetFPID().GetLibItemName() == std::string( "$noname" ) ) m_netlist.GetComponent( ii )->SetFPID( LIB_ID() ); } // Sort components by reference: m_netlist.SortByReference(); return 0; } void CVPCB_MAINFRAME::CreateScreenCmp() { DISPLAY_FOOTPRINTS_FRAME* fpframe = GetFootprintViewerFrame(); if( !fpframe ) { fpframe = (DISPLAY_FOOTPRINTS_FRAME*) Kiway().Player( FRAME_CVPCB_DISPLAY, true, this ); fpframe->Show( true ); } else { if( fpframe->IsIconized() ) fpframe->Iconize( false ); // The display footprint window might be buried under some other // windows, so CreateScreenCmp() on an existing window would not // show any difference, leaving the user confused. // So we want to put it to front, second after our CVPCB_MAINFRAME. // We do this by a little dance of bringing it to front then the main // frame back. wxWindow* focus = FindFocus(); fpframe->Raise(); // Make sure that is visible. Raise(); // .. but still we want the focus. if( focus ) focus->SetFocus(); } fpframe->InitDisplay(); } void CVPCB_MAINFRAME::BuildFOOTPRINTS_LISTBOX() { wxFont guiFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); if( m_footprintListBox == NULL ) { m_footprintListBox = new FOOTPRINTS_LISTBOX( this, ID_CVPCB_FOOTPRINT_LIST, wxDefaultPosition, wxDefaultSize ); m_footprintListBox->SetFont( wxFont( guiFont.GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL ) ); } m_footprintListBox->SetFootprints( *m_FootprintsList, wxEmptyString, NULL, wxEmptyString, FOOTPRINTS_LISTBOX::UNFILTERED_FP_LIST ); DisplayStatus(); } void CVPCB_MAINFRAME::BuildCmpListBox() { wxString msg; COMPONENT* component; wxFont guiFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); if( m_compListBox == NULL ) { m_compListBox = new COMPONENTS_LISTBOX( this, ID_CVPCB_COMPONENT_LIST, wxDefaultPosition, wxDefaultSize ); m_compListBox->SetFont( wxFont( guiFont.GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL ) ); } m_compListBox->m_ComponentList.Clear(); for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); msg.Printf( CMP_FORMAT, m_compListBox->GetCount() + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); m_compListBox->m_ComponentList.Add( msg ); } if( m_compListBox->m_ComponentList.Count() ) { m_compListBox->SetItemCount( m_compListBox->m_ComponentList.Count() ); m_compListBox->SetSelection( 0, true ); m_compListBox->RefreshItems( 0L, m_compListBox->m_ComponentList.Count()-1 ); m_compListBox->UpdateWidth(); } } void CVPCB_MAINFRAME::BuildLIBRARY_LISTBOX() { wxFont guiFont = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); if( m_libListBox == NULL ) { m_libListBox = new LIBRARY_LISTBOX( this, ID_CVPCB_LIBRARY_LIST, wxDefaultPosition, wxDefaultSize ); m_libListBox->SetFont( wxFont( guiFont.GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL ) ); } FP_LIB_TABLE* tbl = Prj().PcbFootprintLibs( Kiway() ); if( tbl ) { wxArrayString libNames; std::vector< wxString > libNickNames = tbl->GetLogicalLibs(); for( unsigned ii = 0; ii < libNickNames.size(); ii++ ) libNames.Add( libNickNames[ii] ); m_libListBox->SetLibraryList( libNames ); } } COMPONENT* CVPCB_MAINFRAME::GetSelectedComponent() { int selection = m_compListBox->GetSelection(); if( selection >= 0 && selection < (int) m_netlist.GetCount() ) return m_netlist.GetComponent( selection ); return NULL; } DISPLAY_FOOTPRINTS_FRAME* CVPCB_MAINFRAME::GetFootprintViewerFrame() { // returns the Footprint Viewer frame, if exists, or NULL return dynamic_cast ( wxWindow::FindWindowByName( FOOTPRINTVIEWER_FRAME_NAME ) ); } wxString CVPCB_MAINFRAME::GetSelectedFootprint() { // returns the LIB_ID of the selected footprint in footprint listview // or a empty string return m_footprintListBox->GetSelectedFootprint(); } void CVPCB_MAINFRAME::SetStatusText( const wxString& aText, int aNumber ) { wxASSERT( aNumber < 3 ); if( aNumber == 2 ) m_statusLine3->SetLabel( aText ); else if( aNumber == 1 ) m_statusLine2->SetLabel( aText ); else m_statusLine1->SetLabel( aText ); } void CVPCB_MAINFRAME::OnConfigurePaths( wxCommandEvent& aEvent ) { DIALOG_CONFIGURE_PATHS dlg( this, Prj().Get3DCacheManager()->GetResolver() ); dlg.ShowModal(); } void CVPCB_MAINFRAME::ShowChangedLanguage() { EDA_BASE_FRAME::ShowChangedLanguage(); ReCreateHToolbar(); DisplayStatus(); } void CVPCB_MAINFRAME::KiwayMailIn( KIWAY_EXPRESS& mail ) { const std::string& payload = mail.GetPayload(); //DBG(printf( "%s: %s\n", __func__, payload.c_str() );) switch( mail.Command() ) { case MAIL_EESCHEMA_NETLIST: ReadNetListAndFpFiles( payload ); /* @todo Go into SCH_EDIT_FRAME::OnOpenCvpcb( wxCommandEvent& event ) and trim GNL_ALL down. */ break; case MAIL_STATUS: SetStatusText( payload, 1 ); break; default: ; // ignore most } }