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.

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