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.

869 lines
28 KiB

16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
  1. /*******************************************************************/
  2. /* dialog_pad_properties.cpp: Pad editing functions and dialog box */
  3. /* see also dialog_pad_properties.xxx (built with wxFormBuilder) */
  4. /*******************************************************************/
  5. #include "fctsys.h"
  6. #include "common.h"
  7. #include "class_drawpanel.h"
  8. #include "confirm.h"
  9. #include "pcbnew.h"
  10. #include "trigo.h"
  11. #include <wx/dcbuffer.h>
  12. #define NBSHAPES 4
  13. int CodeShape[NBSHAPES] = // list of pad shapes.
  14. {
  15. PAD_CIRCLE, PAD_OVAL, PAD_RECT, PAD_TRAPEZOID
  16. };
  17. #define NBTYPES 4
  18. int CodeType[NBTYPES] =
  19. {
  20. PAD_STANDARD, PAD_SMD, PAD_CONN, PAD_HOLE_NOT_PLATED
  21. };
  22. // Default mask layers setup for pads according to the pad type
  23. static long Std_Pad_Layers[NBTYPES] =
  24. {
  25. // PAD_STANDARD:
  26. PAD_STANDARD_DEFAULT_LAYERS,
  27. // PAD_CONN:
  28. PAD_CONN_DEFAULT_LAYERS,
  29. // PAD_SMD:
  30. PAD_SMD_DEFAULT_LAYERS,
  31. //PAD_HOLE_NOT_PLATED:
  32. PAD_HOLE_NOT_PLATED_DEFAULT_LAYERS
  33. };
  34. #include "dialog_pad_properties_base.h"
  35. extern int ChangeSideMaskLayer( int masque );
  36. /**
  37. * class DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE,
  38. * created by wxFormBuilder
  39. */
  40. class DIALOG_PAD_PROPERTIES : public DIALOG_PAD_PROPERTIES_BASE
  41. {
  42. private:
  43. PCB_BASE_FRAME* m_Parent;
  44. D_PAD* m_CurrentPad; // Pad currently edited
  45. D_PAD* m_dummyPad; // a working copy used to show changes
  46. BOARD* m_Board;
  47. bool m_isFlipped; /* true if the parent footprint (therefore pads) is flipped (mirrored)
  48. * in this case, some Y coordinates values must be negated
  49. */
  50. bool m_canUpdate;
  51. public:
  52. DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* parent, D_PAD* Pad );
  53. ~DIALOG_PAD_PROPERTIES()
  54. {
  55. delete m_dummyPad;
  56. }
  57. private:
  58. void initValues();
  59. void OnPadShapeSelection( wxCommandEvent& event );
  60. void OnDrillShapeSelected( wxCommandEvent& event );
  61. void PadOrientEvent( wxCommandEvent& event );
  62. void PadTypeSelected( wxCommandEvent& event );
  63. void PadPropertiesAccept( wxCommandEvent& event );
  64. void SetPadLayersList( long layer_mask );
  65. void OnSetLayer( wxCommandEvent& event );
  66. void OnCancelButtonClick( wxCommandEvent& event );
  67. void OnPaintShowPanel( wxPaintEvent& event );
  68. bool TransfertDataToPad( D_PAD* aPad, bool aPromptOnError = false );
  69. void OnValuesChanged( wxCommandEvent& event );
  70. };
  71. void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
  72. {
  73. wxPaintDC dc( m_panelShowPad );
  74. PAD_DRAWINFO drawInfo;
  75. int color = 0;
  76. if( m_dummyPad->m_Masque_Layer & LAYER_FRONT )
  77. {
  78. color = m_Board->GetVisibleElementColor( PAD_FR_VISIBLE );
  79. }
  80. if( m_dummyPad->m_Masque_Layer & LAYER_BACK )
  81. {
  82. color |= m_Board->GetVisibleElementColor( PAD_BK_VISIBLE );
  83. }
  84. if( color == 0 )
  85. color = LIGHTGRAY;
  86. drawInfo.m_Color = color;
  87. drawInfo.m_HoleColor = DARKGRAY;
  88. drawInfo.m_Offset = m_dummyPad->m_Pos;
  89. drawInfo.m_Display_padnum = true;
  90. drawInfo.m_Display_netname = true;
  91. // Shows the local pad clearance
  92. drawInfo.m_PadClearance = m_dummyPad->m_LocalClearance;
  93. wxSize dc_size = dc.GetSize();
  94. dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
  95. // Calculate a suitable scale to fit the available draw area
  96. int dim = m_dummyPad->m_Size.x + ABS( m_dummyPad->m_DeltaSize.y);
  97. if( m_dummyPad->m_LocalClearance > 0 )
  98. dim += m_dummyPad->m_LocalClearance * 2;
  99. double scale = (double) dc_size.x / dim;
  100. dim = m_dummyPad->m_Size.y + ABS( m_dummyPad->m_DeltaSize.x);
  101. if( m_dummyPad->m_LocalClearance > 0 )
  102. dim += m_dummyPad->m_LocalClearance * 2;
  103. double altscale = (double) dc_size.y / dim;
  104. scale = MIN( scale, altscale );
  105. // Give a margin
  106. scale *= 0.7;
  107. dc.SetUserScale( scale, scale );
  108. m_dummyPad->DrawShape( NULL, &dc, drawInfo );
  109. event.Skip();
  110. }
  111. /*******************************************************************************************/
  112. DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* parent, D_PAD* Pad ) :
  113. DIALOG_PAD_PROPERTIES_BASE( parent )
  114. /*******************************************************************************************/
  115. {
  116. m_canUpdate = false;
  117. m_Parent = parent;
  118. m_CurrentPad = Pad;
  119. m_Board = m_Parent->GetBoard();
  120. m_dummyPad = new D_PAD( (MODULE*) NULL );
  121. if( m_CurrentPad )
  122. m_dummyPad->Copy( m_CurrentPad );
  123. else
  124. m_dummyPad->Copy( &g_Pad_Master );
  125. initValues();
  126. m_sdbSizer1OK->SetDefault();
  127. GetSizer()->SetSizeHints( this );
  128. Center();
  129. m_canUpdate = true;
  130. }
  131. void PCB_BASE_FRAME::InstallPadOptionsFrame( D_PAD* Pad )
  132. {
  133. DIALOG_PAD_PROPERTIES dlg( this, Pad );
  134. dlg.ShowModal();
  135. }
  136. /***************************************/
  137. void DIALOG_PAD_PROPERTIES::initValues()
  138. /***************************************/
  139. {
  140. SetFocus(); // Required under wxGTK if we want to demiss the dialog with the ESC key
  141. int internalUnits = m_Parent->m_InternalUnits;
  142. wxString msg;
  143. m_isFlipped = false;
  144. if( m_CurrentPad )
  145. {
  146. MODULE* Module = (MODULE*) m_CurrentPad->GetParent();
  147. if( Module->GetLayer() == LAYER_N_BACK )
  148. {
  149. m_isFlipped = true;
  150. m_staticModuleSideValue->SetLabel( _( "Back side (footprint is mirrored)" ) );
  151. }
  152. msg.Printf( wxT( "%.1f" ), (double) Module->m_Orient / 10 );
  153. m_staticModuleRotValue->SetLabel( msg );
  154. }
  155. if( m_isFlipped )
  156. {
  157. NEGATE( m_dummyPad->m_Offset.y );
  158. NEGATE( m_dummyPad->m_DeltaSize.y );
  159. /* flip pads layers*/
  160. m_dummyPad->m_Masque_Layer = ChangeSideMaskLayer( m_dummyPad->m_Masque_Layer );
  161. }
  162. m_staticTextWarningPadFlipped->Show(m_isFlipped);
  163. m_PadNumCtrl->SetValue( m_dummyPad->ReturnStringPadName() );
  164. m_PadNetNameCtrl->SetValue( m_dummyPad->GetNetname() );
  165. // Display current unit name in dialog:
  166. m_PadPosX_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  167. m_PadPosY_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  168. m_PadDrill_X_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  169. m_PadDrill_Y_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  170. m_PadShapeSizeX_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  171. m_PadShapeSizeY_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  172. m_PadShapeOffsetX_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  173. m_PadShapeOffsetY_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  174. m_PadShapeDelta_Unit->SetLabel( GetUnitsLabel( g_UserUnit ) );
  175. m_NetClearanceUnits->SetLabel( GetUnitsLabel( g_UserUnit ) );
  176. // Display current pad masks clearances units
  177. m_NetClearanceUnits->SetLabel( GetUnitsLabel( g_UserUnit ) );
  178. m_SolderMaskMarginUnits->SetLabel( GetUnitsLabel( g_UserUnit ) );
  179. m_SolderPasteMarginUnits->SetLabel( GetUnitsLabel( g_UserUnit ) );
  180. // Display current pad parameters units:
  181. PutValueInLocalUnits( *m_PadPosition_X_Ctrl, m_dummyPad->m_Pos.x, internalUnits );
  182. PutValueInLocalUnits( *m_PadPosition_Y_Ctrl, m_dummyPad->m_Pos.y, internalUnits );
  183. PutValueInLocalUnits( *m_PadDrill_X_Ctrl, m_dummyPad->m_Drill.x, internalUnits );
  184. PutValueInLocalUnits( *m_PadDrill_Y_Ctrl, m_dummyPad->m_Drill.y, internalUnits );
  185. PutValueInLocalUnits( *m_ShapeSize_X_Ctrl, m_dummyPad->m_Size.x, internalUnits );
  186. PutValueInLocalUnits( *m_ShapeSize_Y_Ctrl, m_dummyPad->m_Size.y, internalUnits );
  187. PutValueInLocalUnits( *m_ShapeOffset_X_Ctrl, m_dummyPad->m_Offset.x, internalUnits );
  188. PutValueInLocalUnits( *m_ShapeOffset_Y_Ctrl, m_dummyPad->m_Offset.y, internalUnits );
  189. if( m_dummyPad->m_DeltaSize.x )
  190. {
  191. PutValueInLocalUnits( *m_ShapeDelta_Ctrl, m_dummyPad->m_DeltaSize.x, internalUnits );
  192. m_radioBtnDeltaXdir->SetValue(true);
  193. }
  194. else
  195. {
  196. PutValueInLocalUnits( *m_ShapeDelta_Ctrl, m_dummyPad->m_DeltaSize.y, internalUnits );
  197. m_radioBtnDeltaYdir->SetValue(true);
  198. }
  199. PutValueInLocalUnits( *m_NetClearanceValueCtrl, m_dummyPad->m_LocalClearance, internalUnits );
  200. PutValueInLocalUnits( *m_SolderMaskMarginCtrl,
  201. m_dummyPad->m_LocalSolderMaskMargin,
  202. internalUnits );
  203. // These 2 parameters are usually < 0, so prepare entering a negative value, if current is 0
  204. PutValueInLocalUnits( *m_SolderPasteMarginCtrl,
  205. m_dummyPad->m_LocalSolderPasteMargin,
  206. internalUnits );
  207. if( m_dummyPad->m_LocalSolderPasteMargin == 0 )
  208. m_SolderPasteMarginCtrl->SetValue( wxT( "-" ) + m_SolderPasteMarginCtrl->GetValue() );
  209. msg.Printf( wxT( "%.1f" ), m_dummyPad->m_LocalSolderPasteMarginRatio * 100.0 );
  210. if( m_dummyPad->m_LocalSolderPasteMarginRatio == 0.0
  211. && msg[0] == '0' ) // Sometimes Printf add a sign if the value is small
  212. m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg );
  213. else
  214. m_SolderPasteMarginRatioCtrl->SetValue( msg );
  215. if( m_CurrentPad )
  216. {
  217. MODULE* Module = (MODULE*) m_CurrentPad->GetParent();
  218. m_dummyPad->m_Orient = m_CurrentPad->m_Orient - Module->m_Orient;
  219. if( m_isFlipped )
  220. NEGATE( m_dummyPad->m_Orient );
  221. }
  222. // adjust rotation agngle to -1800 to 1800 in internal units (0.1 deg)
  223. NORMALIZE_ANGLE_180( m_dummyPad->m_Orient );
  224. // Set layers used by this pad: :
  225. SetPadLayersList( m_dummyPad->m_Masque_Layer );
  226. msg.Clear();
  227. msg << m_dummyPad->m_Orient;
  228. m_PadOrientCtrl->SetValue( msg );
  229. // Pad Orient
  230. switch( m_dummyPad->m_Orient )
  231. {
  232. case 0:
  233. m_PadOrient->SetSelection( 0 );
  234. break;
  235. case 900:
  236. m_PadOrient->SetSelection( 1 );
  237. break;
  238. case - 900:
  239. m_PadOrient->SetSelection( 2 );
  240. break;
  241. case 1800:
  242. case - 1800:
  243. m_PadOrient->SetSelection( 3 );
  244. break;
  245. default:
  246. m_PadOrient->SetSelection( 4 );
  247. break;
  248. }
  249. switch( m_dummyPad->m_PadShape )
  250. {
  251. default:
  252. case PAD_CIRCLE:
  253. m_PadShape->SetSelection( 0 );
  254. break;
  255. case PAD_OVAL:
  256. m_PadShape->SetSelection( 1 );
  257. break;
  258. case PAD_RECT:
  259. m_PadShape->SetSelection( 2 );
  260. break;
  261. case PAD_TRAPEZOID:
  262. m_PadShape->SetSelection( 3 );
  263. break;
  264. }
  265. msg.Printf( wxT( "%d" ), m_dummyPad->m_Orient );
  266. m_PadOrientCtrl->SetValue( msg );
  267. // Selection du type
  268. m_PadType->SetSelection( 0 );
  269. for( int ii = 0; ii < NBTYPES; ii++ )
  270. {
  271. if( CodeType[ii] == m_dummyPad->m_Attribut )
  272. {
  273. m_PadType->SetSelection( ii );
  274. break;
  275. }
  276. }
  277. if( m_dummyPad->m_DrillShape != PAD_OVAL )
  278. m_DrillShapeCtrl->SetSelection( 0 );
  279. else
  280. m_DrillShapeCtrl->SetSelection( 1 );
  281. // Setup layers names from board
  282. m_PadLayerCu->SetLabel( m_Board->GetLayerName( LAYER_N_BACK ) );
  283. m_PadLayerCmp->SetLabel( m_Board->GetLayerName( LAYER_N_FRONT ) );
  284. m_PadLayerAdhCmp->SetLabel( m_Board->GetLayerName( ADHESIVE_N_FRONT ) );
  285. m_PadLayerAdhCu->SetLabel( m_Board->GetLayerName( ADHESIVE_N_BACK ) );
  286. m_PadLayerPateCmp->SetLabel( m_Board->GetLayerName( SOLDERPASTE_N_FRONT ) );
  287. m_PadLayerPateCu->SetLabel( m_Board->GetLayerName( SOLDERPASTE_N_BACK ) );
  288. m_PadLayerSilkCmp->SetLabel( m_Board->GetLayerName( SILKSCREEN_N_FRONT ) );
  289. m_PadLayerSilkCu->SetLabel( m_Board->GetLayerName( SILKSCREEN_N_BACK ) );
  290. m_PadLayerMaskCmp->SetLabel( m_Board->GetLayerName( SOLDERMASK_N_FRONT ) );
  291. m_PadLayerMaskCu->SetLabel( m_Board->GetLayerName( SOLDERMASK_N_BACK ) );
  292. m_PadLayerECO1->SetLabel( m_Board->GetLayerName( ECO1_N ) );
  293. m_PadLayerECO2->SetLabel( m_Board->GetLayerName( ECO2_N ) );
  294. m_PadLayerDraft->SetLabel( m_Board->GetLayerName( DRAW_N ) );
  295. /* All init are done,
  296. * Update some dialog widgets state (Enable/disable options):
  297. */
  298. wxCommandEvent cmd_event;
  299. OnPadShapeSelection( cmd_event );
  300. OnDrillShapeSelected( cmd_event );
  301. }
  302. /*********************************************************************/
  303. void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
  304. /*********************************************************************/
  305. {
  306. switch( m_PadShape->GetSelection() )
  307. {
  308. case 0: //CIRCLE:
  309. m_ShapeDelta_Ctrl->Enable( false );
  310. m_radioBtnDeltaXdir->Enable( false );
  311. m_radioBtnDeltaYdir->Enable( false );
  312. m_ShapeSize_Y_Ctrl->Enable( false );
  313. break;
  314. case 1: //OVALE:
  315. m_ShapeDelta_Ctrl->Enable( false );
  316. m_radioBtnDeltaXdir->Enable( false );
  317. m_radioBtnDeltaYdir->Enable( false );
  318. m_ShapeSize_Y_Ctrl->Enable( true );
  319. break;
  320. case 2: // PAD_RECT:
  321. m_ShapeDelta_Ctrl->Enable( false );
  322. m_radioBtnDeltaXdir->Enable( false );
  323. m_radioBtnDeltaYdir->Enable( false );
  324. m_ShapeSize_Y_Ctrl->Enable( true );
  325. break;
  326. case 3: //TRAPEZE:
  327. m_ShapeDelta_Ctrl->Enable( true );
  328. m_radioBtnDeltaXdir->Enable( true );
  329. m_radioBtnDeltaYdir->Enable( true );
  330. m_ShapeSize_Y_Ctrl->Enable( true );
  331. break;
  332. }
  333. TransfertDataToPad( m_dummyPad );
  334. m_panelShowPad->Refresh();
  335. }
  336. /**********************************************************************/
  337. void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event )
  338. /**********************************************************************/
  339. {
  340. if( (m_PadType->GetSelection() == 1) || (m_PadType->GetSelection() == 2) )
  341. {
  342. // pad type = SMD or CONN: no hole allowed
  343. m_PadDrill_X_Ctrl->Enable( false );
  344. m_PadDrill_Y_Ctrl->Enable( false );
  345. }
  346. else
  347. {
  348. switch( m_DrillShapeCtrl->GetSelection() )
  349. {
  350. case 0: //CIRCLE:
  351. m_PadDrill_X_Ctrl->Enable( true );
  352. m_PadDrill_Y_Ctrl->Enable( false );
  353. break;
  354. case 1: //OVALE:
  355. m_PadDrill_X_Ctrl->Enable( true );
  356. m_PadDrill_Y_Ctrl->Enable( true );
  357. break;
  358. }
  359. }
  360. TransfertDataToPad( m_dummyPad );
  361. m_panelShowPad->Refresh();
  362. }
  363. /*******************************************************************/
  364. void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event )
  365. /********************************************************************/
  366. {
  367. switch( m_PadOrient->GetSelection() )
  368. {
  369. case 0:
  370. m_dummyPad->m_Orient = 0;
  371. break;
  372. case 1:
  373. m_dummyPad->m_Orient = 900;
  374. break;
  375. case 2:
  376. m_dummyPad->m_Orient = -900;
  377. break;
  378. case 3:
  379. m_dummyPad->m_Orient = 1800;
  380. break;
  381. default:
  382. break;
  383. }
  384. wxString msg;
  385. msg.Printf( wxT( "%d" ), m_dummyPad->m_Orient );
  386. m_PadOrientCtrl->SetValue( msg );
  387. TransfertDataToPad( m_dummyPad );
  388. m_panelShowPad->Refresh();
  389. }
  390. /*****************************************************************/
  391. void DIALOG_PAD_PROPERTIES::PadTypeSelected( wxCommandEvent& event )
  392. /*****************************************************************/
  393. /* Adjust the better mask layer according to the selected pad type
  394. */
  395. {
  396. long layer_mask;
  397. int ii;
  398. ii = m_PadType->GetSelection();
  399. if( (ii < 0) || ( ii >= NBTYPES) )
  400. ii = 0;
  401. layer_mask = Std_Pad_Layers[ii];
  402. SetPadLayersList( layer_mask );
  403. // Enable/disable drill dialog items:
  404. event.SetId( m_DrillShapeCtrl->GetSelection() );
  405. OnDrillShapeSelected( event );
  406. }
  407. /****************************************************************/
  408. void DIALOG_PAD_PROPERTIES::SetPadLayersList( long layer_mask )
  409. /****************************************************************/
  410. /** SetPadLayersList
  411. * Update the CheckBoxes state in pad layers list,
  412. * @param layer_mask = pad layer mask (ORed layers bit mask)
  413. */
  414. {
  415. m_PadLayerCu->SetValue( ( layer_mask & LAYER_BACK ) );
  416. m_PadLayerCmp->SetValue( ( layer_mask & LAYER_FRONT ) );
  417. m_PadLayerAdhCmp->SetValue( ( layer_mask & ADHESIVE_LAYER_FRONT ) );
  418. m_PadLayerAdhCu->SetValue( ( layer_mask & ADHESIVE_LAYER_BACK ) );
  419. m_PadLayerPateCmp->SetValue( ( layer_mask & SOLDERPASTE_LAYER_FRONT ) );
  420. m_PadLayerPateCu->SetValue( ( layer_mask & SOLDERPASTE_LAYER_BACK ) );
  421. m_PadLayerSilkCmp->SetValue( ( layer_mask & SILKSCREEN_LAYER_FRONT ) );
  422. m_PadLayerSilkCu->SetValue( ( layer_mask & SILKSCREEN_LAYER_BACK ) );
  423. m_PadLayerMaskCmp->SetValue( ( layer_mask & SOLDERMASK_LAYER_FRONT ) );
  424. m_PadLayerMaskCu->SetValue( ( layer_mask & SOLDERMASK_LAYER_BACK ) );
  425. m_PadLayerECO1->SetValue( ( layer_mask & ECO1_LAYER ) );
  426. m_PadLayerECO2->SetValue( ( layer_mask & ECO2_LAYER ) );
  427. m_PadLayerDraft->SetValue( ( layer_mask & DRAW_LAYER ) );
  428. }
  429. // Called when select/deselect a layer.
  430. void DIALOG_PAD_PROPERTIES::OnSetLayer( wxCommandEvent& event )
  431. {
  432. TransfertDataToPad( m_dummyPad );
  433. m_panelShowPad->Refresh();
  434. }
  435. /*************************************************************************/
  436. void DIALOG_PAD_PROPERTIES::PadPropertiesAccept( wxCommandEvent& event )
  437. /*************************************************************************/
  438. /* Updates the different parameters for the component being edited.
  439. */
  440. {
  441. bool rastnestIsChanged = false;
  442. int isign = m_isFlipped ? -1 : 1;
  443. bool success = TransfertDataToPad( m_dummyPad, true );
  444. if( !success ) // An error on parameters has occured
  445. return;
  446. TransfertDataToPad( &g_Pad_Master, false );
  447. if( m_CurrentPad ) // Set current Pad parameters
  448. {
  449. MODULE* Module = (MODULE*) m_CurrentPad->GetParent();
  450. m_Parent->SaveCopyInUndoList( Module, UR_CHANGED );
  451. Module->m_LastEdit_Time = time( NULL );
  452. // redraw the area where the pad was, without pad (delete pad on screen)
  453. m_CurrentPad->m_Flags |= DO_NOT_DRAW;
  454. m_Parent->DrawPanel->RefreshDrawingRect( m_CurrentPad->GetBoundingBox() );
  455. m_CurrentPad->m_Flags &= ~DO_NOT_DRAW;
  456. // Update values
  457. m_CurrentPad->m_PadShape = g_Pad_Master.m_PadShape;
  458. m_CurrentPad->m_Attribut = g_Pad_Master.m_Attribut;
  459. if( m_CurrentPad->m_Pos != g_Pad_Master.m_Pos )
  460. {
  461. m_CurrentPad->m_Pos = g_Pad_Master.m_Pos;
  462. rastnestIsChanged = true;
  463. }
  464. /* compute the pos 0 value, i.e. pad position for module orient = 0 i.e.
  465. * refer to module origin (module position) */
  466. m_CurrentPad->m_Pos0 = m_CurrentPad->m_Pos;
  467. m_CurrentPad->m_Pos0 -= Module->m_Pos;
  468. m_CurrentPad->m_Orient = (g_Pad_Master.m_Orient * isign) + Module->m_Orient;
  469. RotatePoint( &m_CurrentPad->m_Pos0.x, &m_CurrentPad->m_Pos0.y, -Module->m_Orient );
  470. m_CurrentPad->m_Size = g_Pad_Master.m_Size;
  471. m_CurrentPad->m_DeltaSize = g_Pad_Master.m_DeltaSize;
  472. m_CurrentPad->m_DeltaSize.y *= isign;
  473. m_CurrentPad->m_Drill = g_Pad_Master.m_Drill;
  474. m_CurrentPad->m_DrillShape = g_Pad_Master.m_DrillShape;
  475. m_CurrentPad->m_Offset = g_Pad_Master.m_Offset;
  476. m_CurrentPad->m_Offset.y *= isign;
  477. if( m_CurrentPad->m_Masque_Layer != g_Pad_Master.m_Masque_Layer )
  478. {
  479. rastnestIsChanged = true;
  480. m_CurrentPad->m_Masque_Layer = g_Pad_Master.m_Masque_Layer;
  481. }
  482. if( m_isFlipped )
  483. m_CurrentPad->m_Masque_Layer = ChangeSideMaskLayer( m_CurrentPad->m_Masque_Layer );
  484. m_CurrentPad->SetPadName( g_Pad_Master.ReturnStringPadName() );
  485. if( m_CurrentPad->GetNetname() != g_Pad_Master.GetNetname() )
  486. {
  487. if( g_Pad_Master.GetNetname().IsEmpty() )
  488. {
  489. rastnestIsChanged = true;
  490. m_CurrentPad->SetNet( 0 );
  491. m_CurrentPad->SetNetname( wxEmptyString );
  492. }
  493. else
  494. {
  495. const NETINFO_ITEM* net = m_Parent->GetBoard()->FindNet( g_Pad_Master.GetNetname() );
  496. if( net )
  497. {
  498. rastnestIsChanged = true;
  499. m_CurrentPad->SetNetname( g_Pad_Master.GetNetname() );
  500. m_CurrentPad->SetNet( net->GetNet() );
  501. }
  502. else
  503. DisplayError( NULL, _( "Unknown netname, netname not changed" ) );
  504. }
  505. }
  506. m_CurrentPad->m_LocalClearance = g_Pad_Master.m_LocalClearance;
  507. m_CurrentPad->m_LocalSolderMaskMargin = g_Pad_Master.m_LocalSolderMaskMargin;
  508. m_CurrentPad->m_LocalSolderPasteMargin = g_Pad_Master.m_LocalSolderPasteMargin;
  509. m_CurrentPad->m_LocalSolderPasteMarginRatio = g_Pad_Master.m_LocalSolderPasteMarginRatio;
  510. m_CurrentPad->ComputeShapeMaxRadius();
  511. Module->Set_Rectangle_Encadrement();
  512. m_CurrentPad->DisplayInfo( m_Parent );
  513. // redraw the area where the pad was
  514. m_Parent->DrawPanel->RefreshDrawingRect( m_CurrentPad->GetBoundingBox() );
  515. m_Parent->OnModify();
  516. }
  517. EndModal( wxID_OK );
  518. if( rastnestIsChanged ) // The net ratsnest must be recalculated
  519. m_Parent->GetBoard()->m_Status_Pcb = 0;
  520. }
  521. bool DIALOG_PAD_PROPERTIES::TransfertDataToPad( D_PAD* aPad, bool aPromptOnError )
  522. {
  523. long PadLayerMask;
  524. int internalUnits = m_Parent->m_InternalUnits;
  525. wxString msg;
  526. aPad->m_Attribut = CodeType[m_PadType->GetSelection()];
  527. aPad->m_PadShape = CodeShape[m_PadShape->GetSelection()];
  528. // Read pad clearances values:
  529. aPad->m_LocalClearance = ReturnValueFromTextCtrl( *m_NetClearanceValueCtrl,
  530. internalUnits );
  531. aPad->m_LocalSolderMaskMargin = ReturnValueFromTextCtrl( *m_SolderMaskMarginCtrl,
  532. internalUnits );
  533. aPad->m_LocalSolderPasteMargin = ReturnValueFromTextCtrl( *m_SolderPasteMarginCtrl,
  534. internalUnits );
  535. double dtmp = 0.0;
  536. msg = m_SolderPasteMarginRatioCtrl->GetValue();
  537. msg.ToDouble( &dtmp );
  538. // A margin ratio de -50% means no paste on a pad, the ratio must be >= 50 %
  539. if( dtmp < -50 )
  540. dtmp = -50;
  541. if( dtmp > +100 )
  542. dtmp = +100;
  543. aPad->m_LocalSolderPasteMarginRatio = dtmp / 100;
  544. // Read pad position:
  545. aPad->m_Pos.x = ReturnValueFromTextCtrl( *m_PadPosition_X_Ctrl, internalUnits );
  546. aPad->m_Pos.y = ReturnValueFromTextCtrl( *m_PadPosition_Y_Ctrl, internalUnits );
  547. aPad->m_Pos0 = aPad->m_Pos;
  548. // Read pad drill:
  549. aPad->m_Drill.x = ReturnValueFromTextCtrl( *m_PadDrill_X_Ctrl, internalUnits );
  550. aPad->m_Drill.y = ReturnValueFromTextCtrl( *m_PadDrill_Y_Ctrl, internalUnits );
  551. if( m_DrillShapeCtrl->GetSelection() == 0 )
  552. {
  553. aPad->m_DrillShape = PAD_CIRCLE;
  554. aPad->m_Drill.y = aPad->m_Drill.x;
  555. }
  556. else
  557. aPad->m_DrillShape = PAD_OVAL;
  558. // Read pad shape size:
  559. aPad->m_Size.x = ReturnValueFromTextCtrl( *m_ShapeSize_X_Ctrl, internalUnits );
  560. aPad->m_Size.y = ReturnValueFromTextCtrl( *m_ShapeSize_Y_Ctrl, internalUnits );
  561. if( aPad->m_PadShape == PAD_CIRCLE )
  562. aPad->m_Size.y = aPad->m_Size.x;
  563. // Read pad shape delta size:
  564. // m_DeltaSize.x or m_DeltaSize.y must be NULL. for a trapezoid.
  565. wxSize delta;
  566. if( m_radioBtnDeltaXdir->GetValue() )
  567. delta.x = ReturnValueFromTextCtrl( *m_ShapeDelta_Ctrl, internalUnits );
  568. else
  569. delta.y = ReturnValueFromTextCtrl( *m_ShapeDelta_Ctrl, internalUnits );
  570. aPad->m_DeltaSize = delta;
  571. // Test bad values (be sure delta values are not to large)
  572. // remember DeltaSize.x is the Y size variation
  573. bool error = false;
  574. if( (aPad->m_DeltaSize.x < 0) && (aPad->m_DeltaSize.x <= -aPad->m_Size.y) )
  575. {
  576. aPad->m_DeltaSize.x = -aPad->m_Size.y + 2;
  577. error = true;
  578. }
  579. if( (aPad->m_DeltaSize.x > 0) && (aPad->m_DeltaSize.x >= aPad->m_Size.y) )
  580. {
  581. aPad->m_DeltaSize.x = aPad->m_Size.y - 2;
  582. error = true;
  583. }
  584. if( (aPad->m_DeltaSize.y < 0) && (aPad->m_DeltaSize.y <= -aPad->m_Size.x) )
  585. {
  586. aPad->m_DeltaSize.y = -aPad->m_Size.x + 2;
  587. error = true;
  588. }
  589. if( (aPad->m_DeltaSize.y > 0) && (aPad->m_DeltaSize.y >= aPad->m_Size.x) )
  590. {
  591. aPad->m_DeltaSize.y = aPad->m_Size.x - 2;
  592. error = true;
  593. }
  594. // Read pad shape offset:
  595. aPad->m_Offset.x = ReturnValueFromTextCtrl( *m_ShapeOffset_X_Ctrl, internalUnits );
  596. aPad->m_Offset.y = ReturnValueFromTextCtrl( *m_ShapeOffset_Y_Ctrl, internalUnits );
  597. long orient_value = 0;
  598. msg = m_PadOrientCtrl->GetValue();
  599. msg.ToLong( &orient_value );
  600. aPad->m_Orient = orient_value;
  601. msg = m_PadNumCtrl->GetValue().Left( 4 );
  602. aPad->SetPadName( msg );
  603. aPad->SetNetname( m_PadNetNameCtrl->GetValue() );
  604. // Clear some values, according to the pad type and shape
  605. switch( aPad->m_PadShape )
  606. {
  607. case PAD_CIRCLE:
  608. aPad->m_Offset = wxSize( 0, 0 );
  609. aPad->m_DeltaSize = wxSize( 0, 0 );
  610. aPad->m_Size.y = aPad->m_Size.x;
  611. break;
  612. case PAD_RECT:
  613. aPad->m_DeltaSize = wxSize( 0, 0 );
  614. break;
  615. case PAD_OVAL:
  616. aPad->m_DeltaSize = wxSize( 0, 0 );
  617. break;
  618. case PAD_TRAPEZOID:
  619. break;
  620. }
  621. switch( aPad->m_Attribut )
  622. {
  623. case PAD_STANDARD:
  624. break;
  625. case PAD_CONN:
  626. case PAD_SMD:
  627. aPad->m_Offset = wxSize( 0, 0 );
  628. aPad->m_Drill = wxSize( 0, 0 );
  629. break;
  630. case PAD_HOLE_NOT_PLATED:
  631. break;
  632. default:
  633. DisplayError( this, wxT( "Error: unknown pad type" ) );
  634. break;
  635. }
  636. PadLayerMask = 0;
  637. if( m_PadLayerCu->GetValue() )
  638. PadLayerMask |= LAYER_BACK;
  639. if( m_PadLayerCmp->GetValue() )
  640. PadLayerMask |= LAYER_FRONT;
  641. if( ( PadLayerMask & (LAYER_BACK | LAYER_FRONT) ) == (LAYER_BACK | LAYER_FRONT) )
  642. PadLayerMask |= ALL_CU_LAYERS;
  643. if( m_PadLayerAdhCmp->GetValue() )
  644. PadLayerMask |= ADHESIVE_LAYER_FRONT;
  645. if( m_PadLayerAdhCu->GetValue() )
  646. PadLayerMask |= ADHESIVE_LAYER_BACK;
  647. if( m_PadLayerPateCmp->GetValue() )
  648. PadLayerMask |= SOLDERPASTE_LAYER_FRONT;
  649. if( m_PadLayerPateCu->GetValue() )
  650. PadLayerMask |= SOLDERPASTE_LAYER_BACK;
  651. if( m_PadLayerSilkCmp->GetValue() )
  652. PadLayerMask |= SILKSCREEN_LAYER_FRONT;
  653. if( m_PadLayerSilkCu->GetValue() )
  654. PadLayerMask |= SILKSCREEN_LAYER_BACK;
  655. if( m_PadLayerMaskCmp->GetValue() )
  656. PadLayerMask |= SOLDERMASK_LAYER_FRONT;
  657. if( m_PadLayerMaskCu->GetValue() )
  658. PadLayerMask |= SOLDERMASK_LAYER_BACK;
  659. if( m_PadLayerECO1->GetValue() )
  660. PadLayerMask |= ECO1_LAYER;
  661. if( m_PadLayerECO2->GetValue() )
  662. PadLayerMask |= ECO2_LAYER;
  663. if( m_PadLayerDraft->GetValue() )
  664. PadLayerMask |= DRAW_LAYER;
  665. aPad->m_Masque_Layer = PadLayerMask;
  666. /* Test for incorrect values */
  667. if( aPromptOnError )
  668. {
  669. if( (aPad->m_Size.x < aPad->m_Drill.x)
  670. || (aPad->m_Size.y < aPad->m_Drill.y) )
  671. {
  672. DisplayError( this, _( "Incorrect value for pad drill: pad drill bigger than pad size" ) );
  673. return false;
  674. }
  675. int padlayers_mask = PadLayerMask & (LAYER_BACK | LAYER_FRONT);
  676. if( padlayers_mask == 0 )
  677. {
  678. if( aPad->m_Drill.x || aPad->m_Drill.y )
  679. {
  680. DisplayError( this, _( "Error: pad is not on a copper layer and has a hole" ) );
  681. return false;
  682. }
  683. }
  684. if( ( aPad->m_Size.x / 2 <= ABS( aPad->m_Offset.x ) )
  685. || ( aPad->m_Size.y / 2 <= ABS( aPad->m_Offset.y ) ) )
  686. {
  687. DisplayError( this, _( "Incorrect value for pad offset" ) );
  688. return false;
  689. }
  690. if( error )
  691. {
  692. DisplayError( this, _( "Too large value for pad delta size" ) );
  693. return false;
  694. }
  695. }
  696. return true;
  697. }
  698. // Called when a dimension has change.
  699. // Update the pad dimensions shown in the panel.
  700. void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
  701. {
  702. if( m_canUpdate )
  703. {
  704. TransfertDataToPad( m_dummyPad );
  705. m_panelShowPad->Refresh();
  706. }
  707. }
  708. /*********************************************************************/
  709. void DIALOG_PAD_PROPERTIES::OnCancelButtonClick( wxCommandEvent& event )
  710. /*********************************************************************/
  711. {
  712. EndModal( wxID_CANCEL );
  713. }