/* * 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 * Copyright (C) 2011 Wayne Stambaugh * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include /* * 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(); }