From 867a0444bd98c47b30e3cc2e83c37d37db45870e Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Fri, 29 Jan 2016 11:24:39 +0100 Subject: [PATCH] eeschema: single click PCB update feature added --- eeschema/eeschema_id.h | 5 +- eeschema/hotkeys.cpp | 3 + eeschema/hotkeys.h | 1 + eeschema/menubar.cpp | 14 + eeschema/schframe.cpp | 18 + eeschema/schframe.h | 1 + include/mail_type.h | 1 + pcbnew/CMakeLists.txt | 3 + pcbnew/board_netlist_updater.cpp | 680 ++++++++++++++++++++++ pcbnew/board_netlist_updater.h | 160 +++++ pcbnew/cross-probing.cpp | 25 + pcbnew/dialogs/dialog_update_pcb.cpp | 110 ++++ pcbnew/dialogs/dialog_update_pcb.fbp | 661 +++++++++++++++++++++ pcbnew/dialogs/dialog_update_pcb.h | 56 ++ pcbnew/dialogs/dialog_update_pcb_base.cpp | 85 +++ pcbnew/dialogs/dialog_update_pcb_base.h | 60 ++ 16 files changed, 1882 insertions(+), 1 deletion(-) create mode 100644 pcbnew/board_netlist_updater.cpp create mode 100644 pcbnew/board_netlist_updater.h create mode 100644 pcbnew/dialogs/dialog_update_pcb.cpp create mode 100644 pcbnew/dialogs/dialog_update_pcb.fbp create mode 100644 pcbnew/dialogs/dialog_update_pcb.h create mode 100644 pcbnew/dialogs/dialog_update_pcb_base.cpp create mode 100644 pcbnew/dialogs/dialog_update_pcb_base.h diff --git a/eeschema/eeschema_id.h b/eeschema/eeschema_id.h index 2a7e903d0f..c030095b7a 100644 --- a/eeschema/eeschema_id.h +++ b/eeschema/eeschema_id.h @@ -247,7 +247,10 @@ enum id_eeschema_frm ID_LIBVIEW_CMP_EXPORT_TO_SCHEMATIC, ID_SET_RELATIVE_OFFSET, - ID_END_EESCHEMA_ID_LIST + ID_END_EESCHEMA_ID_LIST, + + ID_UPDATE_PCB_FROM_SCH, + ID_UPDATE_SCH_FROM_PCB }; diff --git a/eeschema/hotkeys.cpp b/eeschema/hotkeys.cpp index d31c392669..40d758a387 100644 --- a/eeschema/hotkeys.cpp +++ b/eeschema/hotkeys.cpp @@ -223,6 +223,8 @@ static EDA_HOTKEY HkLoadSchematic( _HKI( "Load Schematic" ), HK_LOAD_SCH, 'L' + static EDA_HOTKEY HkAutoplaceFields( _HKI( "Autoplace Fields" ), HK_AUTOPLACE_FIELDS, 'O', ID_AUTOPLACE_FIELDS ); +static EDA_HOTKEY HkUpdatePcbFromSch( _HKI( "Update PCB from Schematics" ), HK_UPDATE_PCB_FROM_SCH, WXK_F8 ); + // List of common hotkey descriptors static EDA_HOTKEY* common_Hotkey_List[] = { @@ -296,6 +298,7 @@ static EDA_HOTKEY* schematic_Hotkey_List[] = &HkAddGraphicPolyLine, &HkAddGraphicText, &HkLeaveSheet, + &HkUpdatePcbFromSch, &HkAutoplaceFields, &HkDeleteNode, NULL diff --git a/eeschema/hotkeys.h b/eeschema/hotkeys.h index 22f3f382e2..4963fa86d8 100644 --- a/eeschema/hotkeys.h +++ b/eeschema/hotkeys.h @@ -78,6 +78,7 @@ enum hotkey_id_commnand { HK_LEFT_CLICK, HK_LEFT_DCLICK, HK_LEAVE_SHEET, + HK_UPDATE_PCB_FROM_SCH, HK_AUTOPLACE_FIELDS, HK_DELETE_NODE }; diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index 5ce4edf6a6..308f7c0bd8 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -427,6 +427,20 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // Menu Tools: wxMenu* toolsMenu = new wxMenu; + text = AddHotkeyName( _( "Update PCB from Schematics" ), g_Schematic_Hokeys_Descr, HK_UPDATE_PCB_FROM_SCH ); + + wxMenuItem* updItem = AddMenuItem( toolsMenu, + ID_UPDATE_PCB_FROM_SCH, + text, _( "Updates the PCB design with the current schematic." ), + KiBitmap( libedit_xpm ) ); + + KIWAY_PLAYER* pcbFrame = Kiway().Player( FRAME_PCB, false ); // test open already. + + //if( Kiface().IsSingle() || !pcbFrame ) FIXME: refresh + //updItem->Enable( false ); + + toolsMenu->AppendSeparator(); + AddMenuItem( toolsMenu, ID_RUN_LIBRARY, _( "Library &Editor" ), HELP_RUN_LIB_EDITOR, diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index ea6d2f21b8..81cf99ea80 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -60,6 +60,9 @@ #include #include +#include +#include + // non-member so it can be moved easily, and kept REALLY private. // Do NOT Clear() in here. @@ -260,6 +263,7 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_TOOL( wxID_PRINT, SCH_EDIT_FRAME::OnPrint ) EVT_TOOL( ID_GET_ERC, SCH_EDIT_FRAME::OnErc ) EVT_TOOL( ID_GET_NETLIST, SCH_EDIT_FRAME::OnCreateNetlist ) + EVT_TOOL( ID_UPDATE_PCB_FROM_SCH, SCH_EDIT_FRAME::OnUpdatePCB ) EVT_TOOL( ID_GET_TOOLS, SCH_EDIT_FRAME::OnCreateBillOfMaterials ) EVT_TOOL( ID_FIND_ITEMS, SCH_EDIT_FRAME::OnFindItems ) EVT_TOOL( wxID_REPLACE, SCH_EDIT_FRAME::OnFindItems ) @@ -817,6 +821,20 @@ void SCH_EDIT_FRAME::OnErc( wxCommandEvent& event ) InvokeDialogERC( this ); } +void SCH_EDIT_FRAME::OnUpdatePCB( wxCommandEvent& event ) +{ + NETLIST_OBJECT_LIST* net_atoms = BuildNetListBase(); + NETLIST_EXPORTER_KICAD exporter( net_atoms, Prj().SchLibs() ); + STRING_FORMATTER formatter; + + exporter.Format( &formatter, GNL_ALL ); + + Kiway().ExpressMail( FRAME_PCB, + MAIL_SCH_PCB_UPDATE, + formatter.GetString(), // an abbreviated "kicad" (s-expr) netlist + this + ); +} void SCH_EDIT_FRAME::OnCreateNetlist( wxCommandEvent& event ) { diff --git a/eeschema/schframe.h b/eeschema/schframe.h index f057a4f649..23a9bb0581 100644 --- a/eeschema/schframe.h +++ b/eeschema/schframe.h @@ -809,6 +809,7 @@ private: void OnAnnotate( wxCommandEvent& event ); void OnErc( wxCommandEvent& event ); void OnCreateNetlist( wxCommandEvent& event ); + void OnUpdatePCB( wxCommandEvent& event ); void OnCreateBillOfMaterials( wxCommandEvent& event ); void OnFindItems( wxCommandEvent& event ); void OnFindDialogClose( wxFindDialogEvent& event ); diff --git a/include/mail_type.h b/include/mail_type.h index dc9d03ed05..57ca1a4452 100644 --- a/include/mail_type.h +++ b/include/mail_type.h @@ -39,6 +39,7 @@ enum MAIL_T MAIL_CROSS_PROBE, ///< PCB<->SCH, CVPCB->SCH cross-probing. MAIL_BACKANNOTATE_FOOTPRINTS, ///< CVPCB->SCH footprint stuffing at cvpcb termination MAIL_EESCHEMA_NETLIST, ///< EESCHEMA->CVPCB netlist immediately after launching CVPCB + MAIL_SCH_PCB_UPDATE ///< Sch->PCB forward update }; #endif // MAIL_TYPE_H_ diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 7580776452..64d80929f1 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -145,6 +145,8 @@ set( PCBNEW_DIALOGS dialogs/dialog_track_via_properties_base.cpp dialogs/dialog_track_via_size.cpp dialogs/dialog_track_via_size_base.cpp + dialogs/dialog_update_pcb_base.cpp + dialogs/dialog_update_pcb.cpp footprint_wizard.cpp footprint_wizard_frame.cpp dialogs/dialog_footprint_wizard_list_base.cpp @@ -193,6 +195,7 @@ set( PCBNEW_CLASS_SRCS attribut.cpp board_items_to_polygon_shape_transform.cpp board_undo_redo.cpp + board_netlist_updater.cpp block.cpp block_module_editor.cpp build_BOM_from_board.cpp diff --git a/pcbnew/board_netlist_updater.cpp b/pcbnew/board_netlist_updater.cpp new file mode 100644 index 0000000000..0559baa74d --- /dev/null +++ b/pcbnew/board_netlist_updater.cpp @@ -0,0 +1,680 @@ +/** + * @file board_netlist_updater.h + * @brief BOARD_NETLIST_UPDATER class definition + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2015 CERN + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2015 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 // for PAGE_INFO + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + + +BOARD_NETLIST_UPDATER::BOARD_NETLIST_UPDATER ( PCB_EDIT_FRAME *aFrame, BOARD *aBoard ) : + m_frame ( aFrame ), + m_board( aBoard ) +{ + m_reporter = &NULL_REPORTER::GetInstance(); + m_undoList = new PICKED_ITEMS_LIST; +} + +BOARD_NETLIST_UPDATER::~BOARD_NETLIST_UPDATER () +{ + delete m_undoList; +} + +void BOARD_NETLIST_UPDATER::pushUndo( BOARD_ITEM* aItem, UNDO_REDO_T aCommandType ) +{ + m_undoList->PushItem( ITEM_PICKER( aItem, aCommandType ) ); +} + +wxPoint BOARD_NETLIST_UPDATER::estimateComponentInsertionPosition() +{ + wxPoint bestPosition; + + if( !m_board->IsEmpty() ) + { + // Position new components below any existing board features. + EDA_RECT bbox = m_board->ComputeBoundingBox( true ); + + if( bbox.GetWidth() || bbox.GetHeight() ) + { + bestPosition.x = bbox.Centre().x; + bestPosition.y = bbox.GetBottom() + Millimeter2iu( 10 ); + } + } + else + { + // Position new components in the center of the page when the board is empty. + wxSize pageSize = m_board->GetPageSettings().GetSizeIU(); + + bestPosition.x = pageSize.GetWidth() / 2; + bestPosition.y = pageSize.GetHeight() / 2; + } + + return bestPosition; +} + + +MODULE* BOARD_NETLIST_UPDATER::addNewComponent( COMPONENT* aComponent ) +{ + wxString msg; + + if( aComponent->GetModule() != NULL ) + { + msg.Printf( _( "Adding new component \"%s:%s\" footprint \"%s\".\n" ), + GetChars( aComponent->GetReference() ), + GetChars( aComponent->GetTimeStamp() ), + GetChars( aComponent->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + msg.Printf( _( "Add component %s, footprint: %s.\n" ), + GetChars( aComponent->GetReference() ), + GetChars( aComponent->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + + if( !m_isDryRun ) + { + // Owned by NETLIST, can only copy it. + MODULE *footprint = new MODULE( *aComponent->GetModule() ); + footprint->SetParent( m_board ); + footprint->SetPosition( estimateComponentInsertionPosition( ) ); + footprint->SetTimeStamp( GetNewTimeStamp() ); + + m_board->Add( footprint, ADD_APPEND ); + + pushUndo( footprint, UR_NEW ); + + return footprint; + } + } + else + { + msg.Printf( _( "Cannot add component %s due to missing footprint %s.\n" ), + GetChars( aComponent->GetReference() ), + GetChars( aComponent->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_ERROR ); + + msg.Printf( _( "Cannot add new component \"%s:%s\" due to missing " + "footprint \"%s\".\n" ), + GetChars( aComponent->GetReference() ), + GetChars( aComponent->GetTimeStamp() ), + GetChars( aComponent->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + m_errorCount ++; + } + + return NULL; +} + +MODULE* BOARD_NETLIST_UPDATER::replaceComponent( NETLIST& aNetlist, MODULE *aPcbComponent, COMPONENT* aNewComponent ) +{ + wxString msg; + + if( !m_replaceFootprints ) + return NULL; + +// Test if the footprint has not changed + if( aNewComponent->GetFPID().empty() || + aPcbComponent->GetFPID() == aNewComponent->GetFPID() ) + return NULL; + + if( aNewComponent->GetModule() != NULL ) + { + msg.Printf( _( "Change component %s footprint from %s to %s.\n"), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetFPID().Format() ), + GetChars( aNewComponent->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + msg.Printf( _( "Replacing component \"%s:%s\" footprint \"%s\" with " + "\"%s\".\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetPath() ), + GetChars( aPcbComponent->GetFPID().Format() ), + GetChars( aNewComponent->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + if( !m_isDryRun ) + { + wxASSERT( aPcbComponent != NULL ); + MODULE* newFootprint = new MODULE( *aNewComponent->GetModule() ); + + if( aNetlist.IsFindByTimeStamp() ) + newFootprint->SetReference( aPcbComponent->GetReference() ); + else + newFootprint->SetPath( aPcbComponent->GetPath() ); + + aPcbComponent->CopyNetlistSettings( newFootprint ); + m_board->Remove( aPcbComponent ); + m_board->Add( newFootprint, ADD_APPEND ); + + pushUndo( aPcbComponent, UR_DELETED ); + pushUndo( newFootprint, UR_NEW ); + + return newFootprint; + } + } else { + + msg.Printf( _( "Cannot change component %s footprint due to missing " + "footprint %s.\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aNewComponent->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_ERROR ); + + msg.Printf( _( "Cannot replace component \"%s:%s\" due to missing " + "footprint \"%s\".\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetPath() ), + GetChars( aNewComponent->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + m_errorCount ++; + } + + return NULL; +} + +bool BOARD_NETLIST_UPDATER::updateComponentParameters( MODULE *aPcbComponent, COMPONENT* aNewComponent ) +{ + wxString msg; + + if( !aPcbComponent ) + return false; + + pushUndo ( aPcbComponent, UR_CHANGED ); + + // Test for reference designator field change. + if( aPcbComponent->GetReference() != aNewComponent->GetReference() ) + { + msg.Printf( _( "Change component %s reference to %s.\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aNewComponent->GetReference() ) ); + + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + msg.Printf( _( "Changing component \"%s:%s\" reference to \"%s\".\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetPath() ), + GetChars( aNewComponent->GetReference() ) ); + + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + if ( !m_isDryRun ) + aPcbComponent->SetReference( aNewComponent->GetReference() ); + } + + // Test for value field change. + if( aPcbComponent->GetValue() != aNewComponent->GetValue() ) + { + msg.Printf( _( "Change component %s value from %s to %s.\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetValue() ), + GetChars( aNewComponent->GetValue() ) ); + + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + msg.Printf( _( "Changing component \"%s:%s\" value from \"%s\" to \"%s\".\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetPath() ), + GetChars( aPcbComponent->GetValue() ), + GetChars( aNewComponent->GetValue() ) ); + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + if ( !m_isDryRun ) + aPcbComponent->SetValue( aNewComponent->GetValue() ); + } + + // Test for time stamp change. + if( aPcbComponent->GetPath() != aNewComponent->GetTimeStamp() ) + { + msg.Printf( _( "Changing component path \"%s:%s\" to \"%s\".\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetPath() ), + GetChars( aNewComponent->GetTimeStamp() ) ); + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + if ( !m_isDryRun ) + aPcbComponent->SetPath( aNewComponent->GetTimeStamp() ); + } + + return true; +} + +bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( MODULE *aPcbComponent, COMPONENT* aNewComponent ) +{ + wxString msg; + + // At this point, the component footprint is updated. Now update the nets. + for( D_PAD *pad = aPcbComponent->Pads(); pad; pad = pad->Next() ) + { + COMPONENT_NET net = aNewComponent->GetNet( pad->GetPadName() ); + + if( !net.IsValid() ) // New footprint pad has no net. + { + if( !pad->GetNetname().IsEmpty() ) + { + msg.Printf( _( "Disconnect component %s pin %s.\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( pad->GetPadName() ) ); + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + msg.Printf( _( "Clearing component \"%s:%s\" pin \"%s\" net name.\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetPath() ), + GetChars( pad->GetPadName() ) ); + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + } + + + + if( !m_isDryRun ) + { + pushUndo( pad, UR_CHANGED ); + pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); + } + } + else // New footprint pad has a net. + { + if( net.GetNetName() != pad->GetNetname() ) + { + NETINFO_ITEM* netinfo = m_board->FindNet( net.GetNetName() ); + + if( netinfo == NULL ) + { + // It is a new net, we have to add it + if( !m_isDryRun ) + { + netinfo = new NETINFO_ITEM( m_board, net.GetNetName() ); + m_board->AppendNet( netinfo ); + pushUndo( netinfo, UR_NEW ); + } + + msg.Printf( _( "Add net %s.\n" ), + GetChars( net.GetNetName() ) ); + + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + } + + if( pad->GetNetname() != wxString("") ) + { + msg.Printf( _( "Reconnect component %s pin %s from net %s to net %s.\n"), + GetChars( aPcbComponent->GetReference() ), + GetChars( pad->GetPadName() ), + GetChars( pad->GetNetname() ), + GetChars( net.GetNetName() ) ); + + } else { + msg.Printf( _( "Connect component %s pin %s to net %s.\n"), + GetChars( aPcbComponent->GetReference() ), + GetChars( pad->GetPadName() ), + GetChars( net.GetNetName() ) ); + } + + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + msg.Printf( _( "Changing component \"%s:%s\" pin \"%s\" net name from " + "\"%s\" to \"%s\".\n" ), + GetChars( aPcbComponent->GetReference() ), + GetChars( aPcbComponent->GetPath() ), + GetChars( pad->GetPadName() ), + GetChars( pad->GetNetname() ), + GetChars( net.GetNetName() ) ); + + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + if ( !m_isDryRun ) + { + pushUndo( pad, UR_CHANGED ); + pad->SetNetCode( netinfo->GetNet() ); + } + } + } + } + + return true; +} + +bool BOARD_NETLIST_UPDATER::deleteUnusedComponents( NETLIST& aNetlist ) +{ + wxString msg; + MODULE* nextModule; + const COMPONENT* component; + + for( MODULE* module = m_board->m_Modules; module != NULL; module = nextModule ) + { + nextModule = module->Next(); + + if( module->IsLocked() ) + continue; + + if( m_lookupByTimestamp ) + component = aNetlist.GetComponentByTimeStamp( module->GetPath() ); + else + component = aNetlist.GetComponentByReference( module->GetReference() ); + + if( component == NULL ) + { + msg.Printf( _( "Remove component %s." ), + GetChars( module->GetReference() ) ); + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + msg.Printf( _( "Removing unused component \"%s:%s\".\n" ), + GetChars( module->GetReference() ), + GetChars( module->GetPath() ) ); + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + if( !m_isDryRun ) + { + pushUndo( module, UR_DELETED ); + module->DeleteStructure(); + } + } + } + + return true; +} + +bool BOARD_NETLIST_UPDATER::deleteSinglePadNets() +{ + int count = 0; + wxString netname; + wxString msg; + D_PAD* pad = NULL; + D_PAD* previouspad = NULL; + + // We need the pad list, for next tests. + // padlist is the list of pads, sorted by netname. + + m_board->BuildListOfNets(); + + if( m_isDryRun ) + return false; + + std::vector padlist = m_board->GetPads(); + + for( unsigned ii = 0; ii < padlist.size(); ii++ ) + { + pad = padlist[ii]; + + + if( pad->GetNetname().IsEmpty() ) + continue; + + if( netname != pad->GetNetname() ) // End of net + { + if( previouspad && count == 1 ) + { + // First, see if we have a copper zone attached to this pad. + // If so, this is not really a single pad net + + for( int ii = 0; ii < m_board->GetAreaCount(); ii++ ) + { + ZONE_CONTAINER* zone = m_board->GetArea( ii ); + + if( !zone->IsOnCopperLayer() ) + continue; + + if( zone->GetIsKeepout() ) + continue; + + if( zone->GetNet() == previouspad->GetNet() ) + { + count++; + break; + } + } + + if( count == 1 ) // Really one pad, and nothing else + { + msg.Printf( _( "Remove single pad net %s." ), + GetChars( previouspad->GetNetname() ) ); + + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + msg.Printf( _( "Remove single pad net \"%s\" on \"%s\" pad '%s'\n" ), + GetChars( previouspad->GetNetname() ), + GetChars( previouspad->GetParent()->GetReference() ), + GetChars( previouspad->GetPadName() ) ); + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + pushUndo( previouspad, UR_CHANGED ); + previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED ); + } + } + + netname = pad->GetNetname(); + count = 1; + } + else + { + count++; + } + + previouspad = pad; + } + + // Examine last pad + if( pad && count == 1 ) + { + pushUndo( pad, UR_CHANGED ); + pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); + } + return true; +} + +bool BOARD_NETLIST_UPDATER::testConnectivity( NETLIST& aNetlist ) +{ + // Last step: Some tests: + // verify all pads found in netlist: + // They should exist in footprints, otherwise the footprint is wrong + // note also references or time stamps are updated, so we use only + // the reference to find a footprint + // + // Also verify if zones have acceptable nets, i.e. nets with pads. + // Zone with no pad belongs to a "dead" net which happens after changes in schematic + // when no more pad use this net name. + + wxString msg; + wxString padname; + + for( int i = 0; i < (int) aNetlist.GetCount(); i++ ) + { + const COMPONENT* component = aNetlist.GetComponent( i ); + MODULE* footprint = m_board->FindModuleByReference( component->GetReference() ); + + if( footprint == NULL ) // It can be missing in partial designs + continue; + + // Explore all pins/pads in component + for( unsigned jj = 0; jj < component->GetNetCount(); jj++ ) + { + COMPONENT_NET net = component->GetNet( jj ); + padname = net.GetPinName(); + + if( footprint->FindPadByName( padname ) ) + continue; // OK, pad found + + // not found: bad footprint, report error + msg.Printf( _( "Component %s pad %s not found in footprint %s\n" ), + GetChars( component->GetReference() ), + GetChars( padname ), + GetChars( footprint->GetFPID().Format() ) ); + m_reporter->Report( msg, REPORTER::RPT_ERROR ); + m_errorCount ++; + } + } + + // Test copper zones to detect "dead" nets (nets without any pad): + for( int i = 0; i < m_board->GetAreaCount(); i++ ) + { + ZONE_CONTAINER* zone = m_board->GetArea( i ); + + if( !zone->IsOnCopperLayer() || zone->GetIsKeepout() ) + continue; + + int nc = zone->GetNet()->GetNodesCount(); + + if( nc == 0 ) + { + msg.Printf( _( "Copper zone (net name %s): net has no pads connected." ), + GetChars( zone->GetNet()->GetNetname() ) ); + m_reporter->Report( msg, REPORTER::RPT_WARNING ); + m_warningCount ++; + } + } + + return true; +} + +bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist ) +{ + wxString msg; + + m_errorCount = 0; + m_warningCount = 0; + + if( !m_isDryRun ) + { + m_board->SetStatus( 0 ); + } + + + for( int i = 0; i < (int) aNetlist.GetCount(); i++ ) + { + COMPONENT* component = aNetlist.GetComponent( i ); + MODULE *footprint = NULL; + + msg.Printf( _( "Processing component \"%s:%s:%s\".\n" ), + GetChars( component->GetReference() ), + GetChars( component->GetTimeStamp() ), + GetChars( component->GetFPID().Format() ) ); + + m_reporter->Report( msg, REPORTER::RPT_INFO ); + + if( aNetlist.IsFindByTimeStamp() ) + footprint = m_board->FindModule( component->GetTimeStamp(), true ); + else + footprint = m_board->FindModule( component->GetReference() ); + + if( footprint ) // An existing footprint. + { + MODULE *newFootprint = replaceComponent ( aNetlist, footprint, component ); + if ( newFootprint ) + footprint = newFootprint; + } + else + { + footprint = addNewComponent( component ); + } + + if( footprint ) + { + updateComponentParameters( footprint, component ); + updateComponentPadConnections( footprint, component ); + } + } + + + + + //aNetlist.GetDeleteExtraFootprints() + + if( m_deleteUnusedComponents ) + deleteUnusedComponents( aNetlist ); + + if( m_deleteSinglePadNets ) + deleteSinglePadNets(); + + if ( !m_isDryRun ) + { + m_frame->SaveCopyInUndoList( *m_undoList, UR_UNSPECIFIED, wxPoint(0, 0) ); + m_frame->OnModify(); + } + + // Update the ratsnest + m_board->GetRatsnest()->ProcessBoard(); + + testConnectivity( aNetlist ); + + m_reporter->Report( _(""), REPORTER::RPT_ACTION ); + m_reporter->Report( _(""), REPORTER::RPT_ACTION ); + + msg.Printf( _( "Total warnings: %d, errors: %d." ), + m_warningCount, m_errorCount ); + + m_reporter->Report( msg, REPORTER::RPT_ACTION ); + + + if ( m_errorCount ) + { + + m_reporter->Report( _("Errors occured during the netlist update. Unless you " + "fix them, your board will not be consistent with the schematics." ), + REPORTER::RPT_ERROR ); + + return false; + } else { + m_reporter->Report( _("Netlist update successful!" ), + REPORTER::RPT_ACTION ); + + } + + return true; +} + +bool BOARD_NETLIST_UPDATER::UpdateNetlist( const wxString& aNetlistFileName, + const wxString& aCmpFileName ) +{ + return false; +} diff --git a/pcbnew/board_netlist_updater.h b/pcbnew/board_netlist_updater.h new file mode 100644 index 0000000000..9d06952a4b --- /dev/null +++ b/pcbnew/board_netlist_updater.h @@ -0,0 +1,160 @@ +/** + * @file board_netlist_updater.h + * @brief BOARD_NETLIST_UPDATER class definition + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2015 CERN + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2015 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 + */ + +#ifndef __BOARD_NETLIST_UPDATER_H +#define __BOARD_NETLIST_UPDATER_H + +class BOARD; +class REPORTER; +class NETLIST; +class COMPONENT; +class MODULE; +class PICKED_ITEMS_LIST; +class PCB_EDIT_FRAME; + +#include + +/** + * Class BOARD_NETLIST_UPDATER + * updates the #BOARD with a new netlist. + * + * The changes are made to the board are as follows they are not disabled in the status + * settings in the #NETLIST: + * - If a new component is found in the #NETLIST and not in the #BOARD, it is added + * to the #BOARD. + * - If a the component in the #NETLIST is already on the #BOARD, then one or more of the + * following actions can occur: + * + If the footprint name in the #NETLIST does not match the footprint name on the + * #BOARD, the footprint on the #BOARD is replaced with the footprint specified in + * the #NETLIST and the proper parameters are copied from the existing footprint. + * + If the reference designator in the #NETLIST does not match the reference designator + * on the #BOARD, the reference designator is updated from the #NETLIST. + * + If the value field in the #NETLIST does not match the value field on the #BOARD, + * the value field is updated from the #NETLIST. + * + If the time stamp in the #NETLIST does not match the time stamp on the #BOARD, + * the time stamp is updated from the #NETLIST. + * - After each footprint is added or update as described above, each footprint pad net + * name is compared and updated to the value defined in the #NETLIST. + * - After all of the footprints have been added, updated, and net names properly set, + * any extra unlock footprints are removed from the #BOARD. + * + */ +class BOARD_NETLIST_UPDATER +{ +public: + + BOARD_NETLIST_UPDATER( PCB_EDIT_FRAME *aFrame, BOARD *aBoard ); + ~BOARD_NETLIST_UPDATER(); + + /** + * Function UpdateNetlist() + * + * Updates the board's components according to the new netlist. + * See BOARD_NETLIST_UPDATER class description for the details of the process. + * @param aNetlist the new netlist + * @return true if process was completed successfully + */ + bool UpdateNetlist( NETLIST& aNetlist ); + + // @todo: implement and move NETLIST::ReadPcbNetlist here + bool UpdateNetlist( const wxString& aNetlistFileName, + const wxString& aCmpFileName ); + + + ///> Sets the reporter object + void SetReporter ( REPORTER *aReporter ) + { + m_reporter = aReporter; + } + + ///> Enables "delete single pad nets" option + void SetDeleteSinglePadNets( bool aEnabled ) + { + m_deleteSinglePadNets = aEnabled; + } + + ///> Enables dry run mode (just report, no changes to PCB) + void SetIsDryRun ( bool aEnabled ) + { + m_isDryRun = aEnabled; + } + + ///> Enables replacing footprints with new ones + void SetReplaceFootprints ( bool aEnabled ) + { + m_replaceFootprints = aEnabled; + } + + ///> Enables removing unused components + void SetDeleteUnusedComponents ( bool aEnabled ) + { + m_deleteUnusedComponents = aEnabled; + } + + ///> Enables component lookup by timestamp instead of reference + void SetLookupByTimestamp ( bool aEnabled ) + { + m_lookupByTimestamp = aEnabled; + } + +private: + + void pushUndo( BOARD_ITEM* aItem, UNDO_REDO_T aCommandType ); + + wxPoint estimateComponentInsertionPosition(); + MODULE* addNewComponent( COMPONENT* aComponent ); + MODULE* replaceComponent( NETLIST& aNetlist, MODULE *aPcbComponent, COMPONENT* aNewComponent ); + bool updateComponentParameters( MODULE *aPcbComponent, COMPONENT* aNewComponent ); + bool updateComponentPadConnections( MODULE *aPcbComponent, COMPONENT* aNewComponent ); + bool deleteUnusedComponents( NETLIST& aNetlist ); + bool deleteSinglePadNets(); + bool testConnectivity( NETLIST& aNetlist ); + + PICKED_ITEMS_LIST *m_undoList; + PCB_EDIT_FRAME *m_frame; + BOARD *m_board; + REPORTER *m_reporter; + + bool m_deleteSinglePadNets; + bool m_deleteUnusedComponents; + bool m_isDryRun; + bool m_replaceFootprints; + bool m_lookupByTimestamp; + + int m_warningCount; + int m_errorCount; +}; + +#endif + + diff --git a/pcbnew/cross-probing.cpp b/pcbnew/cross-probing.cpp index 9c95569ee1..d980ee4df8 100644 --- a/pcbnew/cross-probing.cpp +++ b/pcbnew/cross-probing.cpp @@ -24,6 +24,9 @@ #include #include +#include +#include +#include #include #include @@ -243,6 +246,28 @@ void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail ) ExecuteRemoteCommand( payload.c_str() ); break; + case MAIL_SCH_PCB_UPDATE: + { + NETLIST netlist; + + try { + STRING_LINE_READER* lineReader = new STRING_LINE_READER( payload, _( "EEschema netlist" ) ); + KICAD_NETLIST_READER netlistReader( lineReader, &netlist ); + netlistReader.LoadNetlist(); + } + catch( const IO_ERROR& ioe ) + { + assert( false ); // should never happen + } + + DIALOG_UPDATE_PCB updateDialog( this, &netlist ); + + updateDialog.PerformUpdate( true ); + updateDialog.ShowModal(); + + break; + } + // many many others. default: ; diff --git a/pcbnew/dialogs/dialog_update_pcb.cpp b/pcbnew/dialogs/dialog_update_pcb.cpp new file mode 100644 index 0000000000..4a361a1d89 --- /dev/null +++ b/pcbnew/dialogs/dialog_update_pcb.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +DIALOG_UPDATE_PCB::DIALOG_UPDATE_PCB( PCB_EDIT_FRAME* aParent, NETLIST *aNetlist ) : + DIALOG_UPDATE_PCB_BASE ( aParent ), + m_frame (aParent), + m_netlist (aNetlist) +{ + m_messagePanel->SetLabel( _("Changes to be applied:") ); + m_messagePanel->SetLazyUpdate ( true ); + m_netlist->SortByReference(); + m_btnPerformUpdate->SetFocus(); + + m_messagePanel->SetVisibleSeverities( REPORTER::RPT_WARNING | REPORTER::RPT_ERROR | REPORTER::RPT_ACTION ); +} + +DIALOG_UPDATE_PCB::~DIALOG_UPDATE_PCB() +{ + +} + +void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun ) +{ + m_messagePanel->Clear(); + + REPORTER &reporter = m_messagePanel->Reporter(); + KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView(); + TOOL_MANAGER *toolManager = m_frame->GetToolManager(); + BOARD *board = m_frame->GetBoard(); + + if( !aDryRun ) + { + // Remove old modules + for( MODULE* module = board->m_Modules; module; module = module->Next() ) + { + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); + view->Remove( module ); + } + + // Clear selection, just in case a selected item has to be removed + toolManager->RunAction( COMMON_ACTIONS::selectionClear, true ); + } + + m_frame->LoadFootprints( *m_netlist, &reporter ); + + BOARD_NETLIST_UPDATER updater( m_frame, m_frame->GetBoard() ); + + updater.SetReporter ( &reporter ); + updater.SetIsDryRun( aDryRun); + updater.SetLookupByTimestamp( true ); + updater.SetDeleteUnusedComponents ( true ); + updater.SetReplaceFootprints( true ); + updater.SetDeleteSinglePadNets ( false ); + + updater.UpdateNetlist( *m_netlist ); + + m_messagePanel->Flush(); + + if( aDryRun ) + return; + + m_frame->OnModify(); + + m_frame->SetCurItem( NULL ); + + // Reload modules + for( MODULE* module = board->m_Modules; module; module = module->Next() ) + { + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); + view->Add( module ); + module->ViewUpdate(); + } + + // Rebuild the board connectivity: + if( m_frame->IsGalCanvasActive() ) + board->GetRatsnest()->ProcessBoard(); + + m_frame->Compile_Ratsnest( NULL, true ); + + m_frame->SetMsgPanel( board ); + +} + +void DIALOG_UPDATE_PCB::OnMatchChange( wxCommandEvent& event ) +{ + +} + +void DIALOG_UPDATE_PCB::OnCancelClick( wxCommandEvent& event ) +{ + EndModal( wxID_CANCEL ); +} + +void DIALOG_UPDATE_PCB::OnUpdateClick( wxCommandEvent& event ) +{ + m_messagePanel->SetLabel( _("Changes applied to the PCB:") ); + PerformUpdate( false ); + m_btnCancel->SetFocus( ); +} diff --git a/pcbnew/dialogs/dialog_update_pcb.fbp b/pcbnew/dialogs/dialog_update_pcb.fbp new file mode 100644 index 0000000000..69b6cbc1ac --- /dev/null +++ b/pcbnew/dialogs/dialog_update_pcb.fbp @@ -0,0 +1,661 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_update_pcb_base + 1000 + none + 1 + dialog_update_pcb_base + + . + + 1 + 1 + 1 + 1 + UI + 1 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + 800,700 + DIALOG_UPDATE_PCB_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Update PCB from Schematics + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bMainSizer + wxVERTICAL + none + + 5 + wxEXPAND|wxALL + 0 + + 3 + wxBOTH + + + 0 + + fgSizer2 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Match components by: + + 0 + + + 0 + + 1 + m_staticText1 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Reference + + 0 + + + 0 + + 1 + m_matchByReference + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 0 + + + + + + + + + + + + + + + + + + + + + OnMatchChange + + + + + + + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Timestamp + + 0 + + + 0 + + 1 + m_matchByTimestamp + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 0 + + + + + + + + + + + + + + + + + + + + + OnMatchChange + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bLowerSizer + wxVERTICAL + none + + 5 + wxEXPAND | wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + -300,150 + 1 + m_messagePanel + 1 + + + protected + 1 + + Resizable + 1 + + WX_HTML_REPORT_PANEL; wx_html_report_panel.h + 0 + + + + wxTAB_TRAVERSAL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + 5 + wxBOTH + 0 + + 0 + + fgSizer1 + wxFLEX_GROWMODE_SPECIFIED + none + 1 + 0 + + 5 + wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_CANCEL + Close + + 0 + + + 0 + + 1 + m_btnCancel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnCancelClick + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Perform PCB Update + + 0 + + + 0 + + 1 + m_btnPerformUpdate + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnUpdateClick + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_update_pcb.h b/pcbnew/dialogs/dialog_update_pcb.h new file mode 100644 index 0000000000..88b7151cb9 --- /dev/null +++ b/pcbnew/dialogs/dialog_update_pcb.h @@ -0,0 +1,56 @@ +/** + * @file pcbnew/dialogs/dialog_update_pcb.h + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.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 + */ + +#ifndef _DIALOG_UPDATE_PCB_H_ +#define _DIALOG_UPDATE_PCB_H_ + +#include + +class NETLIST; +class PCB_EDIT_FRAME; + +class DIALOG_UPDATE_PCB : public DIALOG_UPDATE_PCB_BASE +{ +private: + PCB_EDIT_FRAME* m_frame; + NETLIST *m_netlist; + +public: + DIALOG_UPDATE_PCB( PCB_EDIT_FRAME* aParent, NETLIST *aNetlist ); + ~DIALOG_UPDATE_PCB(); + + void PerformUpdate( bool aDryRun ); + +private: + + virtual void OnMatchChange( wxCommandEvent& event ); + virtual void OnCancelClick( wxCommandEvent& event ); + virtual void OnUpdateClick( wxCommandEvent& event ); + +}; + +#endif diff --git a/pcbnew/dialogs/dialog_update_pcb_base.cpp b/pcbnew/dialogs/dialog_update_pcb_base.cpp new file mode 100644 index 0000000000..66d3932752 --- /dev/null +++ b/pcbnew/dialogs/dialog_update_pcb_base.cpp @@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 6 2014) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "wx_html_report_panel.h" + +#include "dialog_update_pcb_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_UPDATE_PCB_BASE::DIALOG_UPDATE_PCB_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( 800,700 ), wxDefaultSize ); + + wxBoxSizer* bMainSizer; + bMainSizer = new wxBoxSizer( wxVERTICAL ); + + wxFlexGridSizer* fgSizer2; + fgSizer2 = new wxFlexGridSizer( 0, 3, 0, 0 ); + fgSizer2->SetFlexibleDirection( wxBOTH ); + fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticText1 = new wxStaticText( this, wxID_ANY, _("Match components by:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1->Wrap( -1 ); + fgSizer2->Add( m_staticText1, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_matchByReference = new wxRadioButton( this, wxID_ANY, _("Reference"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->Add( m_matchByReference, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_matchByTimestamp = new wxRadioButton( this, wxID_ANY, _("Timestamp"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer2->Add( m_matchByTimestamp, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bMainSizer->Add( fgSizer2, 0, wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bLowerSizer; + bLowerSizer = new wxBoxSizer( wxVERTICAL ); + + m_messagePanel = new WX_HTML_REPORT_PANEL( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_messagePanel->SetMinSize( wxSize( -300,150 ) ); + + bLowerSizer->Add( m_messagePanel, 1, wxEXPAND | wxALL, 5 ); + + + bMainSizer->Add( bLowerSizer, 1, wxEXPAND, 5 ); + + wxFlexGridSizer* fgSizer1; + fgSizer1 = new wxFlexGridSizer( 1, 5, 0, 0 ); + fgSizer1->AddGrowableCol( 0 ); + fgSizer1->SetFlexibleDirection( wxBOTH ); + fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_btnCancel = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer1->Add( m_btnCancel, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 ); + + m_btnPerformUpdate = new wxButton( this, wxID_ANY, _("Perform PCB Update"), wxDefaultPosition, wxDefaultSize, 0 ); + fgSizer1->Add( m_btnPerformUpdate, 0, wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + + bMainSizer->Add( fgSizer1, 0, wxEXPAND, 5 ); + + + this->SetSizer( bMainSizer ); + this->Layout(); + bMainSizer->Fit( this ); + + // Connect Events + m_matchByReference->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnMatchChange ), NULL, this ); + m_matchByTimestamp->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnMatchChange ), NULL, this ); + m_btnCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnCancelClick ), NULL, this ); + m_btnPerformUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnUpdateClick ), NULL, this ); +} + +DIALOG_UPDATE_PCB_BASE::~DIALOG_UPDATE_PCB_BASE() +{ + // Disconnect Events + m_matchByReference->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnMatchChange ), NULL, this ); + m_matchByTimestamp->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnMatchChange ), NULL, this ); + m_btnCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnCancelClick ), NULL, this ); + m_btnPerformUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnUpdateClick ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_update_pcb_base.h b/pcbnew/dialogs/dialog_update_pcb_base.h new file mode 100644 index 0000000000..b414d0e5e8 --- /dev/null +++ b/pcbnew/dialogs/dialog_update_pcb_base.h @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 6 2014) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_UPDATE_PCB_BASE_H__ +#define __DIALOG_UPDATE_PCB_BASE_H__ + +#include +#include +#include +class DIALOG_SHIM; +class WX_HTML_REPORT_PANEL; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_UPDATE_PCB_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_UPDATE_PCB_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxStaticText* m_staticText1; + wxRadioButton* m_matchByReference; + wxRadioButton* m_matchByTimestamp; + WX_HTML_REPORT_PANEL* m_messagePanel; + wxButton* m_btnCancel; + wxButton* m_btnPerformUpdate; + + // Virtual event handlers, overide them in your derived class + virtual void OnMatchChange( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnUpdateClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_UPDATE_PCB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Update PCB from Schematics"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_UPDATE_PCB_BASE(); + +}; + +#endif //__DIALOG_UPDATE_PCB_BASE_H__