You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

273 lines
7.4 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
  5. * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  6. * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
  7. * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, you may find one here:
  21. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  22. * or you may search the http://www.gnu.org website for the version 2 license,
  23. * or you may write to the Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. /**
  27. * @file pad_edition_functions.cpp
  28. */
  29. #include <fctsys.h>
  30. #include <class_drawpanel.h>
  31. #include <confirm.h>
  32. #include <trigo.h>
  33. #include <macros.h>
  34. #include <wxBasePcbFrame.h>
  35. #include <pcbnew.h>
  36. #include <class_board.h>
  37. #include <class_module.h>
  38. #include <class_pad.h>
  39. #include <class_board_design_settings.h>
  40. /* Exports the current pad settings to board design settings.
  41. */
  42. void PCB_BASE_FRAME::Export_Pad_Settings( D_PAD* aPad )
  43. {
  44. if( aPad == NULL )
  45. return;
  46. SetMsgPanel( aPad );
  47. D_PAD& mp = GetDesignSettings().m_Pad_Master;
  48. // Copy all settings. Some of them are not used, but they break anything
  49. mp = *aPad;
  50. // The pad orientation, for historical reasons is the
  51. // pad rotation + parent rotation.
  52. // store only the pad rotation.
  53. mp.SetOrientation( aPad->GetOrientation() - aPad->GetParent()->GetOrientation() );
  54. }
  55. /* Imports the board design settings to aPad
  56. * - The position, names, and keys are not modifed.
  57. * The parameters are expected to be correct (i.e. settings are valid)
  58. */
  59. void PCB_BASE_FRAME::Import_Pad_Settings( D_PAD* aPad, bool aDraw )
  60. {
  61. if( aDraw )
  62. {
  63. aPad->SetFlags( DO_NOT_DRAW );
  64. m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() );
  65. aPad->ClearFlags( DO_NOT_DRAW );
  66. }
  67. D_PAD& mp = GetDesignSettings().m_Pad_Master;
  68. aPad->SetShape( mp.GetShape() );
  69. aPad->SetLayerSet( mp.GetLayerSet() );
  70. aPad->SetAttribute( mp.GetAttribute() );
  71. aPad->SetOrientation( mp.GetOrientation() + aPad->GetParent()->GetOrientation() );
  72. aPad->SetSize( mp.GetSize() );
  73. aPad->SetDelta( wxSize( 0, 0 ) );
  74. aPad->SetOffset( mp.GetOffset() );
  75. aPad->SetDrillSize( mp.GetDrillSize() );
  76. aPad->SetDrillShape( mp.GetDrillShape() );
  77. aPad->SetRoundRectRadiusRatio( mp.GetRoundRectRadiusRatio() );
  78. switch( mp.GetShape() )
  79. {
  80. case PAD_SHAPE_TRAPEZOID:
  81. aPad->SetDelta( mp.GetDelta() );
  82. break;
  83. case PAD_SHAPE_CIRCLE:
  84. // ensure size.y == size.x
  85. aPad->SetSize( wxSize( aPad->GetSize().x, aPad->GetSize().x ) );
  86. break;
  87. default:
  88. ;
  89. }
  90. switch( mp.GetAttribute() )
  91. {
  92. case PAD_ATTRIB_SMD:
  93. case PAD_ATTRIB_CONN:
  94. // These pads do not have hole (they are expected to be only on one
  95. // external copper layer)
  96. aPad->SetDrillSize( wxSize( 0, 0 ) );
  97. break;
  98. default:
  99. ;
  100. }
  101. if( aDraw )
  102. m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() );
  103. aPad->GetParent()->SetLastEditTime();
  104. OnModify();
  105. }
  106. /** Compute the 'next' pad number for autoincrement
  107. * aPadName is the last pad name used */
  108. static wxString GetNextPadName( wxString aPadName )
  109. {
  110. // Automatically increment the current pad number.
  111. int num = 0;
  112. int ponder = 1;
  113. // Trim and extract the trailing numeric part
  114. while( aPadName.Len()
  115. && aPadName.Last() >= '0'
  116. && aPadName.Last() <= '9' )
  117. {
  118. num += ( aPadName.Last() - '0' ) * ponder;
  119. aPadName.RemoveLast();
  120. ponder *= 10;
  121. }
  122. num++; // Use next number for the new pad
  123. aPadName << num;
  124. return aPadName;
  125. }
  126. /* Add a new pad to aModule.
  127. */
  128. void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw )
  129. {
  130. m_Pcb->m_Status_Pcb = 0;
  131. aModule->SetLastEditTime();
  132. D_PAD* pad = new D_PAD( aModule );
  133. // Add the new pad to end of the module pad list.
  134. aModule->Pads().PushBack( pad );
  135. // Update the pad properties,
  136. // and keep NETINFO_LIST::ORPHANED as net info
  137. // which is the default when nets cannot be handled.
  138. Import_Pad_Settings( pad, false );
  139. pad->SetPosition( GetCrossHairPosition() );
  140. // Set the relative pad position
  141. // ( pad position for module orient, 0, and relative to the module position)
  142. wxPoint pos0 = pad->GetPosition() - aModule->GetPosition();
  143. RotatePoint( &pos0, -aModule->GetOrientation() );
  144. pad->SetPos0( pos0 );
  145. /* NPTH pads take empty pad number (since they can't be connected),
  146. * other pads get incremented from the last one edited */
  147. wxString padName;
  148. if( pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
  149. {
  150. padName = GetNextPadName( GetDesignSettings()
  151. .m_Pad_Master.GetPadName() );
  152. }
  153. pad->SetPadName( padName );
  154. GetDesignSettings().m_Pad_Master.SetPadName( padName );
  155. aModule->CalculateBoundingBox();
  156. SetMsgPanel( pad );
  157. if( draw )
  158. m_canvas->RefreshDrawingRect( aModule->GetBoundingBox() );
  159. }
  160. void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery )
  161. {
  162. if( aPad == NULL )
  163. return;
  164. MODULE* module = aPad->GetParent();
  165. module->SetLastEditTime();
  166. // aQuery = true to prompt for confirmation, false to delete silently
  167. if( aQuery )
  168. {
  169. wxString msg;
  170. msg.Printf( _( "Delete Pad (footprint %s %s) ?" ),
  171. GetChars( module->GetReference() ),
  172. GetChars( module->GetValue() ) );
  173. if( !IsOK( this, msg ) )
  174. return;
  175. }
  176. // Stores the initial bounding box to refresh the old area
  177. EDA_RECT bbox = module->GetBoundingBox();
  178. m_Pcb->m_Status_Pcb = 0;
  179. GetBoard()->PadDelete( aPad );
  180. // Update the bounding box
  181. module->CalculateBoundingBox();
  182. // Refresh the modified screen area, using the initial bounding box
  183. // which is perhaps larger than the new bounding box
  184. m_canvas->RefreshDrawingRect( bbox );
  185. OnModify();
  186. }
  187. // Rotate selected pad 90 degrees.
  188. void PCB_BASE_FRAME::RotatePad( D_PAD* aPad, wxDC* DC )
  189. {
  190. if( aPad == NULL )
  191. return;
  192. MODULE* module = aPad->GetParent();
  193. module->SetLastEditTime();
  194. OnModify();
  195. if( DC )
  196. module->Draw( m_canvas, DC, GR_XOR );
  197. wxSize sz = aPad->GetSize();
  198. std::swap( sz.x, sz.y );
  199. aPad->SetSize( sz );
  200. sz = aPad->GetDrillSize();
  201. std::swap( sz.x, sz.y );
  202. aPad->SetDrillSize( sz );
  203. wxPoint pt = aPad->GetOffset();
  204. std::swap( pt.x, pt.y );
  205. aPad->SetOffset( pt );
  206. aPad->SetOffset( wxPoint( aPad->GetOffset().x, -aPad->GetOffset().y ) );
  207. sz = aPad->GetDelta();
  208. std::swap( sz.x, sz.y );
  209. sz.x = -sz.x;
  210. aPad->SetDelta( sz );
  211. module->CalculateBoundingBox();
  212. SetMsgPanel( aPad );
  213. if( DC )
  214. module->Draw( m_canvas, DC, GR_OR );
  215. }