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<PCB_EDIT_FRAME*>( m_frame ); BOARD* board = getModel<BOARD>(); 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<PCB_DRAW_PANEL_GAL*>( editFrame->GetGalCanvas() )->SyncLayersVisibility( board ); // Ratsnest board->BuildListOfNets(); board->SynchronizeNetsAndNetClasses(); board->GetRatsnest()->Recalculate(); // Start dragging the appended board VECTOR2D v( static_cast<BOARD_ITEM*>( undoListPicker.GetPickedItem( 0 ) )->GetPosition() ); getViewControls()->WarpCursor( v, true, true ); m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" ); return 0; }
bool PCB_EDIT_FRAME::AppendBoardFile( const wxString& aFullFileName, int aCtl ) { IO_MGR::PCB_FILE_T pluginType = plugin_type( aFullFileName, aCtl ); PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); // keep trace of existing items, in order to know what are the new items // (for undo command for instance) // Tracks are inserted, not append, so mark existing tracks to know what are // the new tracks for( TRACK* track = GetBoard()->m_Track; track; track = track->Next() ) track->SetFlags( FLAG0 ); // Other items are append to the item list, so keep trace to the // last existing item is enough MODULE* module = GetBoard()->m_Modules.GetLast(); BOARD_ITEM* drawing = GetBoard()->m_Drawings.GetLast(); int zonescount = GetBoard()->GetAreaCount(); // Keep also the count of copper layers, because we can happen boards // with different copper layers counts, // and the enabled layers int initialCopperLayerCount = GetBoard()->GetCopperLayerCount(); LSET initialEnabledLayers = GetBoard()->GetEnabledLayers(); 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", GetPageSizeIU().x ); sprintf( ybuf, "%d", GetPageSizeIU().y ); props["page_width"] = xbuf; props["page_height"] = ybuf; GetDesignSettings().m_NetClasses.Clear(); pi->Load( aFullFileName, GetBoard(), &props ); } catch( const IO_ERROR& ioe ) { for( TRACK* track = GetBoard()->m_Track; track; track = track->Next() ) track->ClearFlags( FLAG0 ); wxString msg = wxString::Format( _( "Error loading board.\n%s" ), GetChars( ioe.What() ) ); DisplayError( this, msg ); return false; } // Now prepare a block move command to place the new items, and // prepare the undo command. BLOCK_SELECTOR& blockmove = GetScreen()->m_BlockLocate; HandleBlockBegin( NULL, BLOCK_PRESELECT_MOVE, wxPoint( 0, 0) ); PICKED_ITEMS_LIST& blockitemsList = blockmove.GetItems(); PICKED_ITEMS_LIST undoListPicker; ITEM_PICKER picker( NULL, UR_NEW ); EDA_RECT bbox; // the new items bounding box, for block move bool bboxInit = true; // true until the bounding box is initialized for( TRACK* track = GetBoard()->m_Track; track; track = track->Next() ) { if( track->GetFlags() & FLAG0 ) { track->ClearFlags( FLAG0 ); continue; } track->SetFlags( IS_MOVED ); picker.SetItem( track ); undoListPicker.PushItem( picker ); blockitemsList.PushItem( picker ); if( bboxInit ) bbox = track->GetBoundingBox(); else bbox.Merge( track->GetBoundingBox() ); bboxInit = false; } if( module ) module = module->Next(); else module = GetBoard()->m_Modules; for( ; module; module = module->Next() ) { module->SetFlags( IS_MOVED ); picker.SetItem( module ); undoListPicker.PushItem( picker ); blockitemsList.PushItem( picker ); if( bboxInit ) bbox = module->GetBoundingBox(); else bbox.Merge( module->GetBoundingBox() ); bboxInit = false; } if( drawing ) drawing = drawing->Next(); else drawing = GetBoard()->m_Drawings; for( ; drawing; drawing = drawing->Next() ) { drawing->SetFlags( IS_MOVED ); picker.SetItem( drawing ); undoListPicker.PushItem( picker ); blockitemsList.PushItem( picker ); if( bboxInit ) bbox = drawing->GetBoundingBox(); else bbox.Merge( drawing->GetBoundingBox() ); bboxInit = false; } for( ZONE_CONTAINER* zone = GetBoard()->GetArea( zonescount ); zone; zone = GetBoard()->GetArea( zonescount ) ) { zone->SetFlags( IS_MOVED ); picker.SetItem( zone ); undoListPicker.PushItem( picker ); blockitemsList.PushItem( picker ); zonescount++; if( bboxInit ) bbox = zone->GetBoundingBox(); else bbox.Merge( zone->GetBoundingBox() ); bboxInit = false; } SaveCopyInUndoList( undoListPicker, UR_NEW ); // we should not ask PLUGINs to do these items: int copperLayerCount = GetBoard()->GetCopperLayerCount(); if( copperLayerCount > initialCopperLayerCount ) GetBoard()->SetCopperLayerCount( copperLayerCount ); // Enable all used layers, and make them visible: LSET enabledLayers = GetBoard()->GetEnabledLayers(); enabledLayers |= initialEnabledLayers; GetBoard()->SetEnabledLayers( enabledLayers ); GetBoard()->SetVisibleLayers( enabledLayers ); ReCreateLayerBox(); ReFillLayerWidget(); if( IsGalCanvasActive() ) static_cast<PCB_DRAW_PANEL_GAL*>( GetGalCanvas() )->SyncLayersVisibility( GetBoard() ); GetBoard()->BuildListOfNets(); GetBoard()->SynchronizeNetsAndNetClasses(); SetStatusText( wxEmptyString ); BestZoom(); // Finish block move command: wxPoint cpos = GetNearestGridPosition( bbox.Centre() ); blockmove.SetOrigin( bbox.GetOrigin() ); blockmove.SetSize( bbox.GetSize() ); blockmove.SetLastCursorPosition( cpos ); HandleBlockEnd( NULL ); return true; }