/* * 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-2011 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 */ /** * @file pad_edition_functions.cpp */ #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& mp = GetDesignSettings().m_Pad_Master; // Copy all settings. Some of them are not used, but they break anything mp.Copy( aPad ); // The pad orientation, for historical reasons is the // pad rotation + parent rotation. // store only the pad rotation. mp.SetOrientation( aPad->GetOrientation() - aPad->GetParent()->GetOrientation() ); } /* 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 ); } D_PAD& mp = GetDesignSettings().m_Pad_Master; aPad->SetShape( mp.GetShape() ); aPad->SetLayerSet( mp.GetLayerSet() ); aPad->SetAttribute( mp.GetAttribute() ); aPad->SetOrientation( mp.GetOrientation() + aPad->GetParent()->GetOrientation() ); aPad->SetSize( mp.GetSize() ); aPad->SetDelta( wxSize( 0, 0 ) ); aPad->SetOffset( mp.GetOffset() ); aPad->SetDrillSize( mp.GetDrillSize() ); aPad->SetDrillShape( mp.GetDrillShape() ); aPad->SetRoundRectRadiusRatio( mp.GetRoundRectRadiusRatio() ); switch( mp.GetShape() ) { case PAD_SHAPE_TRAPEZOID: aPad->SetDelta( mp.GetDelta() ); break; case PAD_SHAPE_CIRCLE: // ensure size.y == size.x aPad->SetSize( wxSize( aPad->GetSize().x, aPad->GetSize().x ) ); break; default: ; } switch( mp.GetAttribute() ) { case PAD_ATTRIB_SMD: case PAD_ATTRIB_CONN: // These pads do not have hole (they are expected to be only on one // external copper layer) aPad->SetDrillSize( wxSize( 0, 0 ) ); break; default: ; } 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->Pads().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.GetPadName() ); } pad->SetPadName( padName ); GetDesignSettings().m_Pad_Master.SetPadName( 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; msg.Printf( _( "Delete Pad (footprint %s %s) ?" ), GetChars( module->GetReference() ), GetChars( 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(); } // Rotate selected pad 90 degrees. void PCB_BASE_FRAME::RotatePad( D_PAD* aPad, wxDC* DC ) { if( aPad == NULL ) return; MODULE* module = aPad->GetParent(); module->SetLastEditTime(); OnModify(); if( DC ) module->Draw( m_canvas, DC, GR_XOR ); wxSize sz = aPad->GetSize(); std::swap( sz.x, sz.y ); aPad->SetSize( sz ); sz = aPad->GetDrillSize(); std::swap( sz.x, sz.y ); aPad->SetDrillSize( sz ); wxPoint pt = aPad->GetOffset(); std::swap( pt.x, pt.y ); aPad->SetOffset( pt ); aPad->SetOffset( wxPoint( aPad->GetOffset().x, -aPad->GetOffset().y ) ); sz = aPad->GetDelta(); std::swap( sz.x, sz.y ); sz.x = -sz.x; aPad->SetDelta( sz ); module->CalculateBoundingBox(); SetMsgPanel( aPad ); if( DC ) module->Draw( m_canvas, DC, GR_OR ); }