diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp index a8d46ef64b..51fc1b3f71 100644 --- a/pcbnew/tools/common_actions.cpp +++ b/pcbnew/tools/common_actions.cpp @@ -395,6 +395,10 @@ TOOL_ACTION COMMON_ACTIONS::crossProbeSchToPcb( "pcbnew.EditorControl.crossProbS AS_GLOBAL, 0, "", "" ); +TOOL_ACTION COMMON_ACTIONS::appendBoard( "pcbnew.EditorControl.appendBoard", + AS_GLOBAL, 0, + "", "" ); + TOOL_ACTION COMMON_ACTIONS::highlightNet( "pcbnew.EditorControl.highlightNet", AS_GLOBAL, 0, "", "" ); @@ -702,6 +706,9 @@ boost::optional COMMON_ACTIONS::TranslateLegacyId( int aId ) case ID_PCB_HIGHLIGHT_BUTT: return COMMON_ACTIONS::highlightNetCursor.MakeEvent(); + case ID_APPEND_FILE: + return COMMON_ACTIONS::appendBoard.MakeEvent(); + case ID_PCB_SHOW_1_RATSNEST_BUTT: case ID_TB_OPTIONS_SHOW_MODULE_RATSNEST: return COMMON_ACTIONS::toBeDone.MakeEvent(); diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h index 54decad2d3..1684bc788f 100644 --- a/pcbnew/tools/common_actions.h +++ b/pcbnew/tools/common_actions.h @@ -300,6 +300,7 @@ public: static TOOL_ACTION highlightNetCursor; static TOOL_ACTION drillOrigin; static TOOL_ACTION crossProbeSchToPcb; + static TOOL_ACTION appendBoard; static TOOL_ACTION showHelp; static TOOL_ACTION toBeDone; diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index 9545533e08..98d408eba6 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -28,17 +28,20 @@ #include "picker_tool.h" #include "grid_helper.h" -#include -#include #include #include #include #include -#include #include + #include #include +#include +#include +#include +#include +#include #include #include #include @@ -48,6 +51,12 @@ #include +// files.cpp +extern bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName, + bool aKicadFilesOnly = false ); +extern IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl ); + + PCBNEW_CONTROL::PCBNEW_CONTROL() : TOOL_INTERACTIVE( "pcbnew.Control" ), m_frame( NULL ) { @@ -746,6 +755,152 @@ int PCBNEW_CONTROL::DeleteItemCursor( const TOOL_EVENT& aEvent ) } +int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent ) +{ + int open_ctl; + wxString fileName; + PICKED_ITEMS_LIST undoListPicker; + ITEM_PICKER picker( NULL, UR_NEW ); + + PCB_EDIT_FRAME* editFrame = dynamic_cast( m_frame ); + BOARD* board = getModel(); + KIGFX::VIEW* view = getView(); + + if( !editFrame ) + return 0; + + // Pick a file to append + if( !AskLoadBoardFileName( editFrame, &open_ctl, &fileName, true ) ) + return 0; + + IO_MGR::PCB_FILE_T pluginType = plugin_type( fileName, open_ctl ); + PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); + + // keep track of existing items, in order to know what are the new items + // (for undo command for instance) + + // Tracks are inserted, not appended, so mark the existing tracks to know what are the new tracks + for( TRACK* track = board->m_Track; track; track = track->Next() ) + track->SetFlags( FLAG0 ); + + // Other items are appended to the item list, so keep trace to the last existing item is enough + MODULE* module = board->m_Modules.GetLast(); + BOARD_ITEM* drawing = board->m_Drawings.GetLast(); + int zonescount = board->GetAreaCount(); + + // Keep also the count of copper layers, to adjust if necessary + int initialCopperLayerCount = board->GetCopperLayerCount(); + LSET initialEnabledLayers = board->GetEnabledLayers(); + + // Load the data + try + { + PROPERTIES props; + char xbuf[30]; + char ybuf[30]; + + // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet. + sprintf( xbuf, "%d", editFrame->GetPageSizeIU().x ); + sprintf( ybuf, "%d", editFrame->GetPageSizeIU().y ); + + props["page_width"] = xbuf; + props["page_height"] = ybuf; + + editFrame->GetDesignSettings().m_NetClasses.Clear(); + pi->Load( fileName, board, &props ); + } + catch( const IO_ERROR& ioe ) + { + wxString msg = wxString::Format( _( "Error loading board.\n%s" ), GetChars( ioe.errorText )); + DisplayError( editFrame, msg ); + + return 0; + } + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + + // Process the new items + for( TRACK* track = board->m_Track; track; track = track->Next() ) + { + if( track->GetFlags() & FLAG0 ) + { + track->ClearFlags( FLAG0 ); + continue; + } + + picker.SetItem( track ); + undoListPicker.PushItem( picker ); + view->Add( track ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, track ); + } + + module = module ? module->Next() : board->m_Modules; + + for( ; module; module = module->Next() ) + { + picker.SetItem( module ); + undoListPicker.PushItem( picker ); + + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); + view->Add( module ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, module ); + } + + drawing = drawing ? drawing->Next() : board->m_Drawings; + + for( ; drawing; drawing = drawing->Next() ) + { + picker.SetItem( drawing ); + undoListPicker.PushItem( picker ); + view->Add( drawing ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, drawing ); + } + + for( ZONE_CONTAINER* zone = board->GetArea( zonescount ); zone; + zone = board->GetArea( zonescount ) ) + { + picker.SetItem( zone ); + undoListPicker.PushItem( picker ); + zonescount++; + view->Add( zone ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, zone ); + } + + if( undoListPicker.GetCount() == 0 ) + return 0; + + editFrame->SaveCopyInUndoList( undoListPicker, UR_NEW ); + + // Synchronize layers + // we should not ask PLUGINs to do these items: + int copperLayerCount = board->GetCopperLayerCount(); + + if( copperLayerCount > initialCopperLayerCount ) + board->SetCopperLayerCount( copperLayerCount ); + + // Enable all used layers, and make them visible: + LSET enabledLayers = board->GetEnabledLayers(); + enabledLayers |= initialEnabledLayers; + board->SetEnabledLayers( enabledLayers ); + board->SetVisibleLayers( enabledLayers ); + editFrame->ReCreateLayerBox(); + editFrame->ReFillLayerWidget(); + static_cast( editFrame->GetGalCanvas() )->SyncLayersVisibility( board ); + + // Ratsnest + board->BuildListOfNets(); + board->SynchronizeNetsAndNetClasses(); + board->GetRatsnest()->Recalculate(); + + // Start dragging the appended board + VECTOR2D v( static_cast( undoListPicker.GetPickedItem( 0 ) )->GetPosition() ); + getViewControls()->WarpCursor( v, true, true ); + m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" ); + + return 0; +} + + int PCBNEW_CONTROL::ShowHelp( const TOOL_EVENT& aEvent ) { DisplayHotkeyList( m_frame, m_frame->GetHotkeyConfig() ); @@ -830,6 +985,7 @@ void PCBNEW_CONTROL::SetTransitions() Go( &PCBNEW_CONTROL::SwitchCursor, COMMON_ACTIONS::switchCursor.MakeEvent() ); Go( &PCBNEW_CONTROL::SwitchUnits, COMMON_ACTIONS::switchUnits.MakeEvent() ); Go( &PCBNEW_CONTROL::DeleteItemCursor, COMMON_ACTIONS::deleteItemCursor.MakeEvent() ); + Go( &PCBNEW_CONTROL::AppendBoard, COMMON_ACTIONS::appendBoard.MakeEvent() ); Go( &PCBNEW_CONTROL::ShowHelp, COMMON_ACTIONS::showHelp.MakeEvent() ); Go( &PCBNEW_CONTROL::ToBeDone, COMMON_ACTIONS::toBeDone.MakeEvent() ); } diff --git a/pcbnew/tools/pcbnew_control.h b/pcbnew/tools/pcbnew_control.h index 628efb70d8..78374f477e 100644 --- a/pcbnew/tools/pcbnew_control.h +++ b/pcbnew/tools/pcbnew_control.h @@ -87,6 +87,7 @@ public: int SwitchCursor( const TOOL_EVENT& aEvent ); int SwitchUnits( const TOOL_EVENT& aEvent ); int DeleteItemCursor( const TOOL_EVENT& aEvent ); + int AppendBoard( const TOOL_EVENT& aEvent ); int ShowHelp( const TOOL_EVENT& aEvent ); int ToBeDone( const TOOL_EVENT& aEvent );