339 lines
10 KiB
C++
339 lines
10 KiB
C++
|
/*
|
||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||
|
*
|
||
|
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||
|
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||
|
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||
|
* Copyright (C) 1992-2018 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 <fctsys.h>
|
||
|
#include <class_drawpanel.h>
|
||
|
#include <confirm.h>
|
||
|
#include <trigo.h>
|
||
|
#include <macros.h>
|
||
|
#include <pcb_base_frame.h>
|
||
|
#include <pcb_edit_frame.h>
|
||
|
#include <footprint_edit_frame.h>
|
||
|
#include <pcbnew.h>
|
||
|
#include <class_board.h>
|
||
|
#include <class_module.h>
|
||
|
#include <class_pad.h>
|
||
|
#include <board_design_settings.h>
|
||
|
#include <dialog_push_pad_properties.h>
|
||
|
|
||
|
/*
|
||
|
* Exports the current pad settings to board design settings.
|
||
|
*/
|
||
|
void PCB_BASE_FRAME::Export_Pad_Settings( D_PAD* aPad )
|
||
|
{
|
||
|
if( aPad == NULL )
|
||
|
return;
|
||
|
|
||
|
SetMsgPanel( aPad );
|
||
|
|
||
|
D_PAD& masterPad = GetDesignSettings().m_Pad_Master;
|
||
|
|
||
|
masterPad.ImportSettingsFromMaster( *aPad );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Imports the board design settings to aPad
|
||
|
* - The position, names, and keys are not modifed.
|
||
|
* The parameters are expected to be correct (i.e. settings are valid)
|
||
|
*/
|
||
|
void PCB_BASE_FRAME::Import_Pad_Settings( D_PAD* aPad, bool aDraw )
|
||
|
{
|
||
|
if( aDraw )
|
||
|
{
|
||
|
aPad->SetFlags( DO_NOT_DRAW );
|
||
|
m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() );
|
||
|
aPad->ClearFlags( DO_NOT_DRAW );
|
||
|
}
|
||
|
|
||
|
const D_PAD& mp = GetDesignSettings().m_Pad_Master;
|
||
|
|
||
|
aPad->ImportSettingsFromMaster( mp );
|
||
|
|
||
|
if( aDraw )
|
||
|
m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() );
|
||
|
|
||
|
aPad->GetParent()->SetLastEditTime();
|
||
|
|
||
|
OnModify();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Compute the 'next' pad number for autoincrement
|
||
|
* aPadName is the last pad name used
|
||
|
* */
|
||
|
static wxString GetNextPadName( wxString aPadName )
|
||
|
{
|
||
|
// Automatically increment the current pad number.
|
||
|
int num = 0;
|
||
|
int ponder = 1;
|
||
|
|
||
|
// Trim and extract the trailing numeric part
|
||
|
while( aPadName.Len() && aPadName.Last() >= '0' && aPadName.Last() <= '9' )
|
||
|
{
|
||
|
num += ( aPadName.Last() - '0' ) * ponder;
|
||
|
aPadName.RemoveLast();
|
||
|
ponder *= 10;
|
||
|
}
|
||
|
|
||
|
num++; // Use next number for the new pad
|
||
|
aPadName << num;
|
||
|
|
||
|
return aPadName;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Add a new pad to aModule.
|
||
|
*/
|
||
|
void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw )
|
||
|
{
|
||
|
m_Pcb->m_Status_Pcb = 0;
|
||
|
aModule->SetLastEditTime();
|
||
|
|
||
|
D_PAD* pad = new D_PAD( aModule );
|
||
|
|
||
|
// Add the new pad to end of the module pad list.
|
||
|
aModule->PadsList().PushBack( pad );
|
||
|
|
||
|
// Update the pad properties,
|
||
|
// and keep NETINFO_LIST::ORPHANED as net info
|
||
|
// which is the default when nets cannot be handled.
|
||
|
Import_Pad_Settings( pad, false );
|
||
|
|
||
|
pad->SetPosition( GetCrossHairPosition() );
|
||
|
|
||
|
// Set the relative pad position
|
||
|
// ( pad position for module orient, 0, and relative to the module position)
|
||
|
|
||
|
wxPoint pos0 = pad->GetPosition() - aModule->GetPosition();
|
||
|
RotatePoint( &pos0, -aModule->GetOrientation() );
|
||
|
pad->SetPos0( pos0 );
|
||
|
|
||
|
/* NPTH pads take empty pad number (since they can't be connected),
|
||
|
* other pads get incremented from the last one edited */
|
||
|
wxString padName;
|
||
|
|
||
|
if( pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
|
||
|
padName = GetNextPadName( GetDesignSettings().m_Pad_Master.GetName() );
|
||
|
|
||
|
pad->SetName( padName );
|
||
|
GetDesignSettings().m_Pad_Master.SetName( padName );
|
||
|
|
||
|
aModule->CalculateBoundingBox();
|
||
|
SetMsgPanel( pad );
|
||
|
|
||
|
if( draw )
|
||
|
m_canvas->RefreshDrawingRect( aModule->GetBoundingBox() );
|
||
|
}
|
||
|
|
||
|
|
||
|
void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery )
|
||
|
{
|
||
|
if( aPad == NULL )
|
||
|
return;
|
||
|
|
||
|
MODULE* module = aPad->GetParent();
|
||
|
module->SetLastEditTime();
|
||
|
|
||
|
// aQuery = true to prompt for confirmation, false to delete silently
|
||
|
if( aQuery )
|
||
|
{
|
||
|
wxString msg = wxString::Format( _( "Delete pad (footprint %s %s)?" ),
|
||
|
module->GetReference(),
|
||
|
module->GetValue() );
|
||
|
|
||
|
if( !IsOK( this, msg ) )
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Stores the initial bounding box to refresh the old area
|
||
|
EDA_RECT bbox = module->GetBoundingBox();
|
||
|
|
||
|
m_Pcb->m_Status_Pcb = 0;
|
||
|
|
||
|
GetBoard()->PadDelete( aPad );
|
||
|
|
||
|
// Update the bounding box
|
||
|
module->CalculateBoundingBox();
|
||
|
|
||
|
// Refresh the modified screen area, using the initial bounding box
|
||
|
// which is perhaps larger than the new bounding box
|
||
|
m_canvas->RefreshDrawingRect( bbox );
|
||
|
|
||
|
OnModify();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* PCB_EDIT_FRAME::Function PushPadProperties
|
||
|
* Function to change pad caracteristics for the given footprint or all identical footprints
|
||
|
* Options are set by the opened dialog.
|
||
|
*/
|
||
|
void PCB_EDIT_FRAME::PushPadProperties( D_PAD* aPad )
|
||
|
{
|
||
|
if( !aPad )
|
||
|
return;
|
||
|
|
||
|
MODULE* module = aPad->GetParent();
|
||
|
|
||
|
if( !module )
|
||
|
return;
|
||
|
|
||
|
SetMsgPanel( module );
|
||
|
|
||
|
DIALOG_PUSH_PAD_PROPERTIES dlg( this );
|
||
|
int retCode = dlg.ShowModal();
|
||
|
|
||
|
if( retCode == wxID_CANCEL )
|
||
|
return;
|
||
|
|
||
|
bool edit_Same_Modules = ( retCode == 1 );
|
||
|
|
||
|
DoPushPadProperties( aPad, edit_Same_Modules,
|
||
|
DIALOG_PUSH_PAD_PROPERTIES::m_Pad_Shape_Filter,
|
||
|
DIALOG_PUSH_PAD_PROPERTIES::m_Pad_Orient_Filter,
|
||
|
DIALOG_PUSH_PAD_PROPERTIES::m_Pad_Layer_Filter,
|
||
|
true );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* FOOTPRINT_EDIT_FRAME::Function PushPadProperties
|
||
|
* Function to change pad caracteristics for the footprint.
|
||
|
* Options are set by the opened dialog.
|
||
|
*/
|
||
|
void FOOTPRINT_EDIT_FRAME::PushPadProperties( D_PAD* aPad )
|
||
|
{
|
||
|
if( !aPad )
|
||
|
return;
|
||
|
|
||
|
MODULE* module = aPad->GetParent();
|
||
|
|
||
|
if( !module )
|
||
|
return;
|
||
|
|
||
|
SetMsgPanel( module );
|
||
|
|
||
|
DIALOG_PUSH_PAD_PROPERTIES dlg( this );
|
||
|
int retCode = dlg.ShowModal();
|
||
|
|
||
|
if( retCode == wxID_CANCEL )
|
||
|
return;
|
||
|
|
||
|
bool edit_Same_Modules = ( retCode == 1 );
|
||
|
|
||
|
DoPushPadProperties( aPad, edit_Same_Modules,
|
||
|
DIALOG_PUSH_PAD_PROPERTIES::m_Pad_Shape_Filter,
|
||
|
DIALOG_PUSH_PAD_PROPERTIES::m_Pad_Orient_Filter,
|
||
|
DIALOG_PUSH_PAD_PROPERTIES::m_Pad_Layer_Filter,
|
||
|
false );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Function DoPushPadProperties
|
||
|
* Function to change pad properties for the given footprint or all identical footprints
|
||
|
* aPad is the pattern. The given footprint is the parent of this pad
|
||
|
* aSameFootprints: if true, make changes on all identical footprints
|
||
|
* aPadShapeFilter: if true, make changes only on pads having the same shape as aPad
|
||
|
* aPadOrientFilter: if true, make changes only on pads having the same orientation as aPad
|
||
|
* aPadLayerFilter: if true, make changes only on pads having the same layers as aPad
|
||
|
* aSaveForUndo: if true: create an entry in the Undo/Redo list
|
||
|
* (usually: true in Schematic editor, false in Module editor)
|
||
|
*/
|
||
|
void PCB_BASE_FRAME::DoPushPadProperties( D_PAD* aPad, bool aSameFootprints,
|
||
|
bool aPadShapeFilter,
|
||
|
bool aPadOrientFilter,
|
||
|
bool aPadLayerFilter,
|
||
|
bool aSaveForUndo )
|
||
|
{
|
||
|
MODULE* Module_Ref = aPad->GetParent();
|
||
|
double pad_orient = aPad->GetOrientation() - Module_Ref->GetOrientation();
|
||
|
|
||
|
// Prepare an undo list:
|
||
|
if( aSaveForUndo )
|
||
|
{
|
||
|
PICKED_ITEMS_LIST itemsList;
|
||
|
|
||
|
if( aSameFootprints )
|
||
|
{
|
||
|
for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() )
|
||
|
{
|
||
|
if( module->GetFPID() == Module_Ref->GetFPID() )
|
||
|
{
|
||
|
ITEM_PICKER itemWrapper( module, UR_CHANGED );
|
||
|
itemsList.PushItem( itemWrapper );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ITEM_PICKER itemWrapper( Module_Ref, UR_CHANGED );
|
||
|
itemsList.PushItem( itemWrapper );
|
||
|
}
|
||
|
|
||
|
SaveCopyInUndoList( itemsList, UR_CHANGED );
|
||
|
}
|
||
|
|
||
|
// Update the current module and same others modules if requested.
|
||
|
for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() )
|
||
|
{
|
||
|
if( !aSameFootprints && (module != Module_Ref) )
|
||
|
continue;
|
||
|
|
||
|
if( module->GetFPID() != Module_Ref->GetFPID() )
|
||
|
continue;
|
||
|
|
||
|
// Erase module on screen
|
||
|
module->SetFlags( DO_NOT_DRAW );
|
||
|
m_canvas->RefreshDrawingRect( module->GetBoundingBox() );
|
||
|
module->ClearFlags( DO_NOT_DRAW );
|
||
|
|
||
|
for( D_PAD* pad = module->PadsList(); pad; pad = pad->Next() )
|
||
|
{
|
||
|
if( aPadShapeFilter && ( pad->GetShape() != aPad->GetShape() ) )
|
||
|
continue;
|
||
|
|
||
|
double currpad_orient = pad->GetOrientation() - module->GetOrientation();
|
||
|
|
||
|
if( aPadOrientFilter && ( currpad_orient != pad_orient ) )
|
||
|
continue;
|
||
|
|
||
|
if( aPadLayerFilter && ( pad->GetLayerSet() != aPad->GetLayerSet() ) )
|
||
|
continue;
|
||
|
|
||
|
// Do not copy pad to itself, it can create issues with custom pad primitives.
|
||
|
if( pad == aPad )
|
||
|
continue;
|
||
|
|
||
|
pad->ImportSettingsFromMaster( *aPad );
|
||
|
}
|
||
|
|
||
|
module->CalculateBoundingBox();
|
||
|
m_canvas->RefreshDrawingRect( module->GetBoundingBox() );
|
||
|
}
|
||
|
|
||
|
OnModify();
|
||
|
}
|