Pcbnew: add append board function, only available when Pcbnew is run in standalone mode (outside a project), to allow a basic panelization.
(this function is not compatible with a project, because it breaks the coherency with the schematic)
This commit is contained in:
parent
70a61b8028
commit
980ffac1c3
|
@ -166,6 +166,7 @@ set( PCBNEW_CLASS_SRCS
|
||||||
modview_frame.cpp
|
modview_frame.cpp
|
||||||
pcbframe.cpp
|
pcbframe.cpp
|
||||||
pcb_base_edit_frame.cpp
|
pcb_base_edit_frame.cpp
|
||||||
|
append_board_to_current.cpp
|
||||||
attribut.cpp
|
attribut.cpp
|
||||||
board_items_to_polygon_shape_transform.cpp
|
board_items_to_polygon_shape_transform.cpp
|
||||||
board_undo_redo.cpp
|
board_undo_redo.cpp
|
||||||
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
|
* Copyright (C) 2014 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file append_board_to_current.cpp
|
||||||
|
* @brief append a board to the currently edited board.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fctsys.h>
|
||||||
|
#include <confirm.h>
|
||||||
|
#include <wxPcbStruct.h>
|
||||||
|
#include <pcbnew.h>
|
||||||
|
#include <io_mgr.h>
|
||||||
|
#include <class_module.h>
|
||||||
|
#include <class_zone.h>
|
||||||
|
#include <class_board.h>
|
||||||
|
#include <pcb_draw_panel_gal.h>
|
||||||
|
|
||||||
|
// Defined in files.cpp:
|
||||||
|
extern IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl );
|
||||||
|
|
||||||
|
|
||||||
|
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.errorText )
|
||||||
|
);
|
||||||
|
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
|
||||||
|
|
||||||
|
bboxInit = false;
|
||||||
|
bbox.Merge(track->GetBoundingBox() );
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -69,10 +69,11 @@ static const wxChar autosavePrefix[] = wxT( "_autosave-" );
|
||||||
* @param aCtl is where to put the OpenProjectFiles() control bits.
|
* @param aCtl is where to put the OpenProjectFiles() control bits.
|
||||||
*
|
*
|
||||||
* @param aFileName on entry is a probable choice, on return is the chosen filename.
|
* @param aFileName on entry is a probable choice, on return is the chosen filename.
|
||||||
|
* @param aKicadFilesOnly true to list kiacad pcb files plugins only, false to list all plugins.
|
||||||
*
|
*
|
||||||
* @return bool - true if chosen, else false if user aborted.
|
* @return bool - true if chosen, else false if user aborted.
|
||||||
*/
|
*/
|
||||||
bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName )
|
bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName, bool aKicadFilesOnly = false )
|
||||||
{
|
{
|
||||||
// This is a subset of all PLUGINs which are trusted to be able to
|
// This is a subset of all PLUGINs which are trusted to be able to
|
||||||
// load a BOARD. User may occasionally use the wrong plugin to load a
|
// load a BOARD. User may occasionally use the wrong plugin to load a
|
||||||
|
@ -93,7 +94,9 @@ bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName )
|
||||||
wxFileName fileName( *aFileName );
|
wxFileName fileName( *aFileName );
|
||||||
wxString fileFilters;
|
wxString fileFilters;
|
||||||
|
|
||||||
for( unsigned i=0; i<DIM( loaders ); ++i )
|
unsigned pluginsCount = aKicadFilesOnly ? 2 : DIM( loaders );
|
||||||
|
|
||||||
|
for( unsigned i=0; i < pluginsCount; ++i )
|
||||||
{
|
{
|
||||||
if( i > 0 )
|
if( i > 0 )
|
||||||
fileFilters += wxChar( '|' );
|
fileFilters += wxChar( '|' );
|
||||||
|
@ -291,10 +294,12 @@ void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
|
||||||
int open_ctl;
|
int open_ctl;
|
||||||
wxString fileName;
|
wxString fileName;
|
||||||
|
|
||||||
if( !AskLoadBoardFileName( this, &open_ctl, &fileName ) )
|
if( !AskLoadBoardFileName( this, &open_ctl, &fileName, true ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
AppendBoardFile( fileName, open_ctl );
|
AppendBoardFile( fileName, open_ctl );
|
||||||
|
|
||||||
|
m_canvas->Refresh();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -343,7 +348,7 @@ void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
|
||||||
// The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
|
// The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
|
||||||
// determine how to load the BOARD here, with minor assistance from KICTL_EAGLE_BRD
|
// determine how to load the BOARD here, with minor assistance from KICTL_EAGLE_BRD
|
||||||
// bit flag.
|
// bit flag.
|
||||||
static IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
|
IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
|
||||||
{
|
{
|
||||||
IO_MGR::PCB_FILE_T pluginType;
|
IO_MGR::PCB_FILE_T pluginType;
|
||||||
|
|
||||||
|
@ -369,19 +374,6 @@ static IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PCB_EDIT_FRAME::AppendBoardFile( const wxString& aFullFileName, int aCtl )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// I'll never use it, and it was mucking up OpenProjectFiles() with
|
|
||||||
// complicated cruft. If you must, put it here separate from that important
|
|
||||||
// function.
|
|
||||||
|
|
||||||
// Actually I think this serves too many masters. Just do panelization in
|
|
||||||
// a good gerber file manager.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
|
bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
|
||||||
{
|
{
|
||||||
// This is for python:
|
// This is for python:
|
||||||
|
@ -713,7 +705,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
|
||||||
);
|
);
|
||||||
DisplayError( this, msg );
|
DisplayError( this, msg );
|
||||||
|
|
||||||
lowerTxt = _( "Failed to create " ) + pcbFileName.GetFullPath();
|
lowerTxt.Printf( _( "Failed to create '%s'" ), GetChars( pcbFileName.GetFullPath() ) );
|
||||||
|
|
||||||
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
||||||
|
|
||||||
|
@ -739,9 +731,9 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
|
||||||
wxRemoveFile( autoSaveFileName.GetFullPath() );
|
wxRemoveFile( autoSaveFileName.GetFullPath() );
|
||||||
|
|
||||||
if( !!backupFileName )
|
if( !!backupFileName )
|
||||||
upperTxt = _( "Backup file: " ) + backupFileName;
|
upperTxt.Printf( _( "Backup file: '%s'" ), GetChars( backupFileName ) );
|
||||||
|
|
||||||
lowerTxt = _( "Wrote board file: " ) + pcbFileName.GetFullPath();
|
lowerTxt.Printf( _( "Wrote board file: '%s'" ), GetChars( pcbFileName.GetFullPath() ) );
|
||||||
|
|
||||||
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
|
||||||
{
|
{
|
||||||
wxString text;
|
wxString text;
|
||||||
wxMenuBar* menuBar = GetMenuBar();
|
wxMenuBar* menuBar = GetMenuBar();
|
||||||
|
wxMenuItem * menutitem;
|
||||||
|
|
||||||
wxFileHistory& fhist = Kiface().GetFileHistory();
|
wxFileHistory& fhist = Kiface().GetFileHistory();
|
||||||
|
|
||||||
|
@ -95,10 +96,14 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
|
||||||
KiBitmap( open_project_xpm ) );
|
KiBitmap( open_project_xpm ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
AddMenuItem( filesMenu, ID_APPEND_FILE,
|
menutitem = AddMenuItem( filesMenu, ID_APPEND_FILE,
|
||||||
_( "&Append Board" ),
|
_( "&Append Board" ),
|
||||||
_( "Append another Pcbnew board to the current loaded board" ),
|
_( "Append another Pcbnew board to the current loaded board. Available only when Pcbnew runs in stand alone mode" ),
|
||||||
KiBitmap( import_xpm ) );
|
KiBitmap( import_xpm ) );
|
||||||
|
if( ! Kiface().IsSingle() ) // disable when under a project mgr
|
||||||
|
menutitem->Enable( false );
|
||||||
|
|
||||||
|
|
||||||
filesMenu->AppendSeparator();
|
filesMenu->AppendSeparator();
|
||||||
|
|
||||||
text = AddHotkeyName( _( "&Save" ), g_Board_Editor_Hokeys_Descr, HK_SAVE_BOARD );
|
text = AddHotkeyName( _( "&Save" ), g_Board_Editor_Hokeys_Descr, HK_SAVE_BOARD );
|
||||||
|
|
|
@ -67,7 +67,7 @@ void FOOTPRINT_EDIT_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
|
||||||
GRSetDrawMode( DC, GR_COPY );
|
GRSetDrawMode( DC, GR_COPY );
|
||||||
|
|
||||||
m_canvas->DrawBackGround( DC );
|
m_canvas->DrawBackGround( DC );
|
||||||
DrawWorkSheet( DC, screen, 0, IU_PER_MILS, wxEmptyString );
|
DrawWorkSheet( DC, screen, 0, IU_PER_MILS, wxEmptyString );
|
||||||
|
|
||||||
// Redraw the footprints
|
// Redraw the footprints
|
||||||
for( MODULE* module = GetBoard()->m_Modules; module; module = module->Next() )
|
for( MODULE* module = GetBoard()->m_Modules; module; module = module->Next() )
|
||||||
|
@ -153,11 +153,19 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* DC, GR_DRAWMODE aDrawMode, const
|
||||||
*/
|
*/
|
||||||
for( TRACK* track = m_Track; track; track = track->Next() )
|
for( TRACK* track = m_Track; track; track = track->Next() )
|
||||||
{
|
{
|
||||||
|
if( track->IsMoving() )
|
||||||
|
continue;
|
||||||
|
|
||||||
track->Draw( aPanel, DC, aDrawMode );
|
track->Draw( aPanel, DC, aDrawMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SEGZONE is outdated, only her for compatibility with
|
||||||
|
// very old designs
|
||||||
for( SEGZONE* zone = m_Zone; zone; zone = zone->Next() )
|
for( SEGZONE* zone = m_Zone; zone; zone = zone->Next() )
|
||||||
{
|
{
|
||||||
|
if( zone->IsMoving() )
|
||||||
|
continue;
|
||||||
|
|
||||||
zone->Draw( aPanel, DC, aDrawMode );
|
zone->Draw( aPanel, DC, aDrawMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue