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.

824 lines
28 KiB

  1. /**
  2. * @file dialog_plot.cpp
  3. */
  4. /*
  5. * This program source code file is part of KiCad, a free EDA CAD application.
  6. *
  7. * Copyright (C) 1992-2012 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. #include <appl_wxstruct.h>
  27. #include <plot_common.h>
  28. #include <confirm.h>
  29. #include <wxPcbStruct.h>
  30. #include <pcbplot.h>
  31. #include <base_units.h>
  32. #include <macros.h>
  33. #include <reporter.h>
  34. #include <class_board.h>
  35. #include <wx/ffile.h>
  36. #include <dialog_plot.h>
  37. DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aParent ) :
  38. DIALOG_PLOT_BASE( aParent ), m_parent( aParent ),
  39. m_board( aParent->GetBoard() ),
  40. m_plotOpts( aParent->GetPlotSettings() )
  41. {
  42. m_config = wxGetApp().GetSettings();
  43. m_brdSettings = m_board->GetDesignSettings();
  44. Init_Dialog();
  45. GetSizer()->Fit( this );
  46. GetSizer()->SetSizeHints( this );
  47. }
  48. void DIALOG_PLOT::Init_Dialog()
  49. {
  50. wxString msg;
  51. wxFileName fileName;
  52. m_config->Read( OPTKEY_PLOT_X_FINESCALE_ADJ, &m_XScaleAdjust );
  53. m_config->Read( OPTKEY_PLOT_Y_FINESCALE_ADJ, &m_YScaleAdjust );
  54. // m_PSWidthAdjust is stored in mm in user config
  55. double dtmp;
  56. m_config->Read( CONFIG_PS_FINEWIDTH_ADJ, &dtmp, 0 );
  57. m_PSWidthAdjust = KiROUND( dtmp * IU_PER_MM );
  58. // The reasonable width correction value must be in a range of
  59. // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
  60. m_widthAdjustMinValue = -(m_board->GetDesignSettings().m_TrackMinWidth - 1);
  61. m_widthAdjustMaxValue = m_board->GetSmallestClearanceValue() - 1;
  62. switch( m_plotOpts.GetFormat() )
  63. {
  64. default:
  65. case PLOT_FORMAT_GERBER:
  66. m_plotFormatOpt->SetSelection( 0 );
  67. break;
  68. case PLOT_FORMAT_POST:
  69. m_plotFormatOpt->SetSelection( 1 );
  70. break;
  71. case PLOT_FORMAT_SVG:
  72. m_plotFormatOpt->SetSelection( 2 );
  73. break;
  74. case PLOT_FORMAT_DXF:
  75. m_plotFormatOpt->SetSelection( 3 );
  76. break;
  77. case PLOT_FORMAT_HPGL:
  78. m_plotFormatOpt->SetSelection( 4 );
  79. break;
  80. case PLOT_FORMAT_PDF:
  81. m_plotFormatOpt->SetSelection( 5 );
  82. break;
  83. }
  84. msg = ReturnStringFromValue( g_UserUnit, m_brdSettings.m_SolderMaskMargin, true );
  85. m_SolderMaskMarginCurrValue->SetLabel( msg );
  86. msg = ReturnStringFromValue( g_UserUnit, m_brdSettings.m_SolderMaskMinWidth, true );
  87. m_SolderMaskMinWidthCurrValue->SetLabel( msg );
  88. // Set units and value for HPGL pen size (this param in in mils).
  89. AddUnitSymbol( *m_textPenSize, g_UserUnit );
  90. msg = ReturnStringFromValue( g_UserUnit,
  91. m_plotOpts.GetHPGLPenDiameter() * IU_PER_MILS );
  92. m_HPGLPenSizeOpt->AppendText( msg );
  93. // Set units and value for HPGL pen overlay (this param in in mils).
  94. AddUnitSymbol( *m_textPenOvr, g_UserUnit );
  95. msg = ReturnStringFromValue( g_UserUnit,
  96. m_plotOpts.GetHPGLPenOverlay() * IU_PER_MILS );
  97. m_HPGLPenOverlayOpt->AppendText( msg );
  98. AddUnitSymbol( *m_textDefaultPenSize, g_UserUnit );
  99. msg = ReturnStringFromValue( g_UserUnit, m_plotOpts.GetLineWidth() );
  100. m_linesWidth->AppendText( msg );
  101. // Set units for PS global width correction.
  102. AddUnitSymbol( *m_textPSFineAdjustWidth, g_UserUnit );
  103. m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
  104. // Test for a reasonable scale value. Set to 1 if problem
  105. if( m_XScaleAdjust < PLOT_MIN_SCALE || m_YScaleAdjust < PLOT_MIN_SCALE
  106. || m_XScaleAdjust > PLOT_MAX_SCALE || m_YScaleAdjust > PLOT_MAX_SCALE )
  107. m_XScaleAdjust = m_YScaleAdjust = 1.0;
  108. msg.Printf( wxT( "%f" ), m_XScaleAdjust );
  109. m_fineAdjustXscaleOpt->AppendText( msg );
  110. msg.Printf( wxT( "%f" ), m_YScaleAdjust );
  111. m_fineAdjustYscaleOpt->AppendText( msg );
  112. // Test for a reasonable PS width correction value. Set to 0 if problem.
  113. if( m_PSWidthAdjust < m_widthAdjustMinValue || m_PSWidthAdjust > m_widthAdjustMaxValue )
  114. m_PSWidthAdjust = 0.;
  115. msg.Printf( wxT( "%f" ), To_User_Unit( g_UserUnit, m_PSWidthAdjust ) );
  116. m_PSFineAdjustWidthOpt->AppendText( msg );
  117. m_plotPSNegativeOpt->SetValue( m_plotOpts.GetNegative() );
  118. m_forcePSA4OutputOpt->SetValue( m_plotOpts.GetA4Output() );
  119. // List layers in same order than in setup layers dialog
  120. // (Front or Top to Back or Bottom)
  121. DECLARE_LAYERS_ORDER_LIST( layersOrder );
  122. int layerIndex, checkIndex;
  123. LAYER_NUM layer;
  124. for( layerIndex = 0; layerIndex < NB_LAYERS; layerIndex++ )
  125. {
  126. layer = layersOrder[layerIndex];
  127. wxASSERT( layer < NB_LAYERS );
  128. if( !m_board->IsLayerEnabled( layer ) )
  129. continue;
  130. m_layerList.push_back( layer );
  131. checkIndex = m_layerCheckListBox->Append( m_board->GetLayerName( layer ) );
  132. if( m_plotOpts.GetLayerSelection() & GetLayerMask( layer ) )
  133. m_layerCheckListBox->Check( checkIndex );
  134. }
  135. // Option for using proper Gerber extensions
  136. m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberExtensions() );
  137. // Option for excluding contents of "Edges Pcb" layer
  138. m_excludeEdgeLayerOpt->SetValue( m_plotOpts.GetExcludeEdgeLayer() );
  139. m_subtractMaskFromSilk->SetValue( m_plotOpts.GetSubtractMaskFromSilk() );
  140. // Option to plot page references:
  141. m_plotSheetRef->SetValue( m_plotOpts.GetPlotFrameRef() );
  142. // Option to allow pads on silkscreen layers
  143. m_plotPads_on_Silkscreen->SetValue( m_plotOpts.GetPlotPadsOnSilkLayer() );
  144. // Options to plot texts on footprints
  145. m_plotModuleValueOpt->SetValue( m_plotOpts.GetPlotValue() );
  146. m_plotModuleRefOpt->SetValue( m_plotOpts.GetPlotReference() );
  147. m_plotTextOther->SetValue( m_plotOpts.GetPlotOtherText() );
  148. m_plotInvisibleText->SetValue( m_plotOpts.GetPlotInvisibleText() );
  149. // Options to plot pads and vias holes
  150. m_drillShapeOpt->SetSelection( m_plotOpts.GetDrillMarksType() );
  151. // Scale option
  152. m_scaleOpt->SetSelection( m_plotOpts.GetScaleSelection() );
  153. // Plot mode
  154. m_plotModeOpt->SetSelection( m_plotOpts.GetMode() );
  155. // Plot mirror option
  156. m_plotMirrorOpt->SetValue( m_plotOpts.GetMirror() );
  157. // Put vias on mask layer
  158. m_plotNoViaOnMaskOpt->SetValue( m_plotOpts.GetPlotViaOnMaskLayer() );
  159. // Output directory
  160. m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
  161. // Update options values:
  162. wxCommandEvent cmd_event;
  163. SetPlotFormat( cmd_event );
  164. OnSetScaleOpt( cmd_event );
  165. }
  166. void DIALOG_PLOT::OnQuit( wxCommandEvent& event )
  167. {
  168. Close( true ); // true is to force the frame to close
  169. }
  170. void DIALOG_PLOT::OnClose( wxCloseEvent& event )
  171. {
  172. applyPlotSettings();
  173. EndModal( 0 );
  174. }
  175. // A helper function to show a popup menu, when the dialog is right clicked.
  176. void DIALOG_PLOT::OnRightClick( wxMouseEvent& event )
  177. {
  178. PopupMenu( m_popMenu );
  179. }
  180. // Select or deselect groups of layers in the layers list:
  181. #include <layers_id_colors_and_visibility.h>
  182. void DIALOG_PLOT::OnPopUpLayers( wxCommandEvent& event )
  183. {
  184. unsigned int i;
  185. switch( event.GetId() )
  186. {
  187. case ID_LAYER_FAB: // Select layers usually needed to build a board
  188. for( i = 0; i < m_layerList.size(); i++ )
  189. {
  190. LAYER_MSK layermask = GetLayerMask( m_layerList[ i ] );
  191. if( layermask & ( ALL_CU_LAYERS | ALL_AUX_LAYERS ) )
  192. m_layerCheckListBox->Check( i, true );
  193. else
  194. m_layerCheckListBox->Check( i, false );
  195. }
  196. break;
  197. case ID_SELECT_COPPER_LAYERS:
  198. for( i = 0; i < m_layerList.size(); i++ )
  199. {
  200. if( m_layerList[i] <= LAST_COPPER_LAYER )
  201. m_layerCheckListBox->Check( i, true );
  202. }
  203. break;
  204. case ID_DESELECT_COPPER_LAYERS:
  205. for( i = 0; i < m_layerList.size(); i++ )
  206. {
  207. if( m_layerList[i] <= LAST_COPPER_LAYER )
  208. m_layerCheckListBox->Check( i, false );
  209. }
  210. break;
  211. case ID_SELECT_ALL_LAYERS:
  212. for( i = 0; i < m_layerList.size(); i++ )
  213. m_layerCheckListBox->Check( i, true );
  214. break;
  215. case ID_DESELECT_ALL_LAYERS:
  216. for( i = 0; i < m_layerList.size(); i++ )
  217. m_layerCheckListBox->Check( i, false );
  218. break;
  219. default:
  220. break;
  221. }
  222. }
  223. void DIALOG_PLOT::CreateDrillFile( wxCommandEvent& event )
  224. {
  225. m_parent->InstallDrillFrame( event );
  226. }
  227. void DIALOG_PLOT::OnSetScaleOpt( wxCommandEvent& event )
  228. {
  229. /* Disable sheet reference for scale != 1:1 */
  230. bool scale1 = ( m_scaleOpt->GetSelection() == 1 );
  231. m_plotSheetRef->Enable( scale1 );
  232. if( !scale1 )
  233. m_plotSheetRef->SetValue( false );
  234. }
  235. void DIALOG_PLOT::OnOutputDirectoryBrowseClicked( wxCommandEvent& event )
  236. {
  237. // Build the absolute path of current output plot directory
  238. // to preselect it when opening the dialog.
  239. wxFileName fn( m_outputDirectoryName->GetValue() );
  240. wxString path;
  241. if( fn.IsRelative() )
  242. path = wxGetCwd() + fn.GetPathSeparator() + m_outputDirectoryName->GetValue();
  243. else
  244. path = m_outputDirectoryName->GetValue();
  245. wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
  246. if( dirDialog.ShowModal() == wxID_CANCEL )
  247. return;
  248. wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
  249. wxMessageDialog dialog( this, _( "Use a relative path? " ),
  250. _( "Plot Output Directory" ),
  251. wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
  252. if( dialog.ShowModal() == wxID_YES )
  253. {
  254. wxString boardFilePath = ( (wxFileName) m_parent->GetBoard()->GetFileName() ).GetPath();
  255. if( !dirName.MakeRelativeTo( boardFilePath ) )
  256. wxMessageBox( _( "Cannot make path relative (target volume different from board file volume)!" ),
  257. _( "Plot Output Directory" ), wxOK | wxICON_ERROR );
  258. }
  259. m_outputDirectoryName->SetValue( dirName.GetFullPath() );
  260. }
  261. PlotFormat DIALOG_PLOT::GetPlotFormat()
  262. {
  263. // plot format id's are ordered like displayed in m_plotFormatOpt
  264. static const PlotFormat plotFmt[] =
  265. {
  266. PLOT_FORMAT_GERBER,
  267. PLOT_FORMAT_POST,
  268. PLOT_FORMAT_SVG,
  269. PLOT_FORMAT_DXF,
  270. PLOT_FORMAT_HPGL,
  271. PLOT_FORMAT_PDF
  272. };
  273. return plotFmt[ m_plotFormatOpt->GetSelection() ];
  274. }
  275. // Enable or disable widgets according to the plot format selected
  276. // and clear also some optional values
  277. void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
  278. {
  279. switch( GetPlotFormat() )
  280. {
  281. case PLOT_FORMAT_PDF:
  282. case PLOT_FORMAT_SVG:
  283. m_drillShapeOpt->Enable( true );
  284. m_plotModeOpt->Enable( false );
  285. m_plotModeOpt->SetSelection( 1 );
  286. m_plotMirrorOpt->Enable( true );
  287. m_useAuxOriginCheckBox->Enable( false );
  288. m_useAuxOriginCheckBox->SetValue( false );
  289. m_linesWidth->Enable( true );
  290. m_HPGLPenSizeOpt->Enable( false );
  291. m_HPGLPenOverlayOpt->Enable( false );
  292. m_excludeEdgeLayerOpt->Enable( true );
  293. m_subtractMaskFromSilk->Enable( false );
  294. m_subtractMaskFromSilk->SetValue( false );
  295. m_useGerberExtensions->Enable( false );
  296. m_useGerberExtensions->SetValue( false );
  297. m_scaleOpt->Enable( false );
  298. m_scaleOpt->SetSelection( 1 );
  299. m_fineAdjustXscaleOpt->Enable( false );
  300. m_fineAdjustYscaleOpt->Enable( false );
  301. m_PSFineAdjustWidthOpt->Enable( false );
  302. m_plotPSNegativeOpt->Enable( true );
  303. m_forcePSA4OutputOpt->Enable( false );
  304. m_forcePSA4OutputOpt->SetValue( false );
  305. m_PlotOptionsSizer->Hide( m_GerberOptionsSizer );
  306. m_PlotOptionsSizer->Hide( m_HPGLOptionsSizer );
  307. m_PlotOptionsSizer->Hide( m_PSOptionsSizer );
  308. break;
  309. case PLOT_FORMAT_POST:
  310. m_drillShapeOpt->Enable( true );
  311. m_plotModeOpt->Enable( true );
  312. m_plotMirrorOpt->Enable( true );
  313. m_useAuxOriginCheckBox->Enable( false );
  314. m_useAuxOriginCheckBox->SetValue( false );
  315. m_linesWidth->Enable( true );
  316. m_HPGLPenSizeOpt->Enable( false );
  317. m_HPGLPenOverlayOpt->Enable( false );
  318. m_excludeEdgeLayerOpt->Enable( true );
  319. m_subtractMaskFromSilk->Enable( false );
  320. m_subtractMaskFromSilk->SetValue( false );
  321. m_useGerberExtensions->Enable( false );
  322. m_useGerberExtensions->SetValue( false );
  323. m_scaleOpt->Enable( true );
  324. m_fineAdjustXscaleOpt->Enable( true );
  325. m_fineAdjustYscaleOpt->Enable( true );
  326. m_PSFineAdjustWidthOpt->Enable( true );
  327. m_plotPSNegativeOpt->Enable( true );
  328. m_forcePSA4OutputOpt->Enable( true );
  329. m_PlotOptionsSizer->Hide( m_GerberOptionsSizer );
  330. m_PlotOptionsSizer->Hide( m_HPGLOptionsSizer );
  331. m_PlotOptionsSizer->Show( m_PSOptionsSizer );
  332. break;
  333. case PLOT_FORMAT_GERBER:
  334. m_drillShapeOpt->Enable( false );
  335. m_drillShapeOpt->SetSelection( 0 );
  336. m_plotModeOpt->Enable( false );
  337. m_plotModeOpt->SetSelection( 1 );
  338. m_plotMirrorOpt->Enable( false );
  339. m_plotMirrorOpt->SetValue( false );
  340. m_useAuxOriginCheckBox->Enable( true );
  341. m_linesWidth->Enable( true );
  342. m_HPGLPenSizeOpt->Enable( false );
  343. m_HPGLPenOverlayOpt->Enable( false );
  344. m_excludeEdgeLayerOpt->Enable( true );
  345. m_subtractMaskFromSilk->Enable( true );
  346. m_useGerberExtensions->Enable( true );
  347. m_scaleOpt->Enable( false );
  348. m_scaleOpt->SetSelection( 1 );
  349. m_fineAdjustXscaleOpt->Enable( false );
  350. m_fineAdjustYscaleOpt->Enable( false );
  351. m_PSFineAdjustWidthOpt->Enable( false );
  352. m_plotPSNegativeOpt->Enable( false );
  353. m_plotPSNegativeOpt->SetValue( false );
  354. m_forcePSA4OutputOpt->Enable( false );
  355. m_forcePSA4OutputOpt->SetValue( false );
  356. m_PlotOptionsSizer->Show( m_GerberOptionsSizer );
  357. m_PlotOptionsSizer->Hide( m_HPGLOptionsSizer );
  358. m_PlotOptionsSizer->Hide( m_PSOptionsSizer );
  359. break;
  360. case PLOT_FORMAT_HPGL:
  361. m_drillShapeOpt->Enable( true );
  362. m_plotModeOpt->Enable( true );
  363. m_plotMirrorOpt->Enable( true );
  364. m_useAuxOriginCheckBox->Enable( false );
  365. m_useAuxOriginCheckBox->SetValue( false );
  366. m_linesWidth->Enable( false );
  367. m_HPGLPenSizeOpt->Enable( true );
  368. m_HPGLPenOverlayOpt->Enable( true );
  369. m_excludeEdgeLayerOpt->Enable( true );
  370. m_subtractMaskFromSilk->Enable( false );
  371. m_subtractMaskFromSilk->SetValue( false );
  372. m_useGerberExtensions->Enable( false );
  373. m_useGerberExtensions->SetValue( false );
  374. m_scaleOpt->Enable( true );
  375. m_fineAdjustXscaleOpt->Enable( false );
  376. m_fineAdjustYscaleOpt->Enable( false );
  377. m_PSFineAdjustWidthOpt->Enable( false );
  378. m_plotPSNegativeOpt->SetValue( false );
  379. m_plotPSNegativeOpt->Enable( false );
  380. m_forcePSA4OutputOpt->Enable( true );
  381. m_PlotOptionsSizer->Hide( m_GerberOptionsSizer );
  382. m_PlotOptionsSizer->Show( m_HPGLOptionsSizer );
  383. m_PlotOptionsSizer->Hide( m_PSOptionsSizer );
  384. break;
  385. case PLOT_FORMAT_DXF:
  386. m_drillShapeOpt->Enable( true );
  387. m_plotModeOpt->Enable( true );
  388. m_plotMirrorOpt->Enable( false );
  389. m_plotMirrorOpt->SetValue( false );
  390. m_useAuxOriginCheckBox->Enable( true );
  391. m_linesWidth->Enable( false );
  392. m_HPGLPenSizeOpt->Enable( false );
  393. m_HPGLPenOverlayOpt->Enable( false );
  394. m_excludeEdgeLayerOpt->Enable( true );
  395. m_subtractMaskFromSilk->Enable( false );
  396. m_subtractMaskFromSilk->SetValue( false );
  397. m_useGerberExtensions->Enable( false );
  398. m_useGerberExtensions->SetValue( false );
  399. m_scaleOpt->Enable( false );
  400. m_scaleOpt->SetSelection( 1 );
  401. m_fineAdjustXscaleOpt->Enable( false );
  402. m_fineAdjustYscaleOpt->Enable( false );
  403. m_PSFineAdjustWidthOpt->Enable( false );
  404. m_plotPSNegativeOpt->Enable( false );
  405. m_plotPSNegativeOpt->SetValue( false );
  406. m_forcePSA4OutputOpt->Enable( false );
  407. m_forcePSA4OutputOpt->SetValue( false );
  408. m_PlotOptionsSizer->Show( m_GerberOptionsSizer );
  409. m_PlotOptionsSizer->Hide( m_HPGLOptionsSizer );
  410. m_PlotOptionsSizer->Hide( m_PSOptionsSizer );
  411. break;
  412. default:
  413. wxASSERT( false );
  414. }
  415. /* Update the interlock between scale and frame reference
  416. * (scaling would mess up the frame border...) */
  417. OnSetScaleOpt( event );
  418. Layout();
  419. m_MainSizer->SetSizeHints( this );
  420. }
  421. // A helper function to "clip" aValue between aMin and aMax
  422. // and write result in * aResult
  423. // return false if clipped, true if aValue is just copied into * aResult
  424. static bool setDouble( double* aResult, double aValue, double aMin, double aMax )
  425. {
  426. if( aValue < aMin )
  427. {
  428. *aResult = aMin;
  429. return false;
  430. }
  431. else if( aValue > aMax )
  432. {
  433. *aResult = aMax;
  434. return false;
  435. }
  436. *aResult = aValue;
  437. return true;
  438. }
  439. static bool setInt( int* aResult, int aValue, int aMin, int aMax )
  440. {
  441. if( aValue < aMin )
  442. {
  443. *aResult = aMin;
  444. return false;
  445. }
  446. else if( aValue > aMax )
  447. {
  448. *aResult = aMax;
  449. return false;
  450. }
  451. *aResult = aValue;
  452. return true;
  453. }
  454. void DIALOG_PLOT::applyPlotSettings()
  455. {
  456. PCB_PLOT_PARAMS tempOptions;
  457. tempOptions.SetExcludeEdgeLayer( m_excludeEdgeLayerOpt->GetValue() );
  458. tempOptions.SetSubtractMaskFromSilk( m_subtractMaskFromSilk->GetValue() );
  459. tempOptions.SetPlotFrameRef( m_plotSheetRef->GetValue() );
  460. tempOptions.SetPlotPadsOnSilkLayer( m_plotPads_on_Silkscreen->GetValue() );
  461. tempOptions.SetUseAuxOrigin( m_useAuxOriginCheckBox->GetValue() );
  462. tempOptions.SetPlotValue( m_plotModuleValueOpt->GetValue() );
  463. tempOptions.SetPlotReference( m_plotModuleRefOpt->GetValue() );
  464. tempOptions.SetPlotOtherText( m_plotTextOther->GetValue() );
  465. tempOptions.SetPlotInvisibleText( m_plotInvisibleText->GetValue() );
  466. tempOptions.SetScaleSelection( m_scaleOpt->GetSelection() );
  467. tempOptions.SetDrillMarksType( static_cast<PCB_PLOT_PARAMS::DrillMarksType>
  468. ( m_drillShapeOpt->GetSelection() ) );
  469. tempOptions.SetMirror( m_plotMirrorOpt->GetValue() );
  470. tempOptions.SetMode( static_cast<EDA_DRAW_MODE_T>( m_plotModeOpt->GetSelection() ) );
  471. tempOptions.SetPlotViaOnMaskLayer( m_plotNoViaOnMaskOpt->GetValue() );
  472. // Update settings from text fields. Rewrite values back to the fields,
  473. // since the values may have been constrained by the setters.
  474. // read HPLG pen size (this param is stored in mils)
  475. wxString msg = m_HPGLPenSizeOpt->GetValue();
  476. int tmp = ReturnValueFromString( g_UserUnit, msg ) / IU_PER_MILS;
  477. if( !tempOptions.SetHPGLPenDiameter( tmp ) )
  478. {
  479. msg = ReturnStringFromValue( g_UserUnit, tempOptions.GetHPGLPenDiameter() * IU_PER_MILS );
  480. m_HPGLPenSizeOpt->SetValue( msg );
  481. msg.Printf( _( "HPGL pen size constrained!\n" ) );
  482. m_messagesBox->AppendText( msg );
  483. }
  484. // Read HPGL pen overlay (this param is stored in mils)
  485. msg = m_HPGLPenOverlayOpt->GetValue();
  486. tmp = ReturnValueFromString( g_UserUnit, msg ) / IU_PER_MILS;
  487. if( !tempOptions.SetHPGLPenOverlay( tmp ) )
  488. {
  489. msg = ReturnStringFromValue( g_UserUnit,
  490. tempOptions.GetHPGLPenOverlay() * IU_PER_MILS );
  491. m_HPGLPenOverlayOpt->SetValue( msg );
  492. msg.Printf( _( "HPGL pen overlay constrained!\n" ) );
  493. m_messagesBox->AppendText( msg );
  494. }
  495. // Default linewidth
  496. msg = m_linesWidth->GetValue();
  497. tmp = ReturnValueFromString( g_UserUnit, msg );
  498. if( !tempOptions.SetLineWidth( tmp ) )
  499. {
  500. msg = ReturnStringFromValue( g_UserUnit, tempOptions.GetLineWidth() );
  501. m_linesWidth->SetValue( msg );
  502. msg.Printf( _( "Default line width constrained!\n" ) );
  503. m_messagesBox->AppendText( msg );
  504. }
  505. // X scale
  506. double tmpDouble;
  507. msg = m_fineAdjustXscaleOpt->GetValue();
  508. msg.ToDouble( &tmpDouble );
  509. if( !setDouble( &m_XScaleAdjust, tmpDouble, PLOT_MIN_SCALE, PLOT_MAX_SCALE ) )
  510. {
  511. msg.Printf( wxT( "%f" ), m_XScaleAdjust );
  512. m_fineAdjustXscaleOpt->SetValue( msg );
  513. msg.Printf( _( "X scale constrained!\n" ) );
  514. m_messagesBox->AppendText( msg );
  515. }
  516. ConfigBaseWriteDouble( m_config, OPTKEY_PLOT_X_FINESCALE_ADJ, m_XScaleAdjust );
  517. // Y scale
  518. msg = m_fineAdjustYscaleOpt->GetValue();
  519. msg.ToDouble( &tmpDouble );
  520. if( !setDouble( &m_YScaleAdjust, tmpDouble, PLOT_MIN_SCALE, PLOT_MAX_SCALE ) )
  521. {
  522. msg.Printf( wxT( "%f" ), m_YScaleAdjust );
  523. m_fineAdjustYscaleOpt->SetValue( msg );
  524. msg.Printf( _( "Y scale constrained!\n" ) );
  525. m_messagesBox->AppendText( msg );
  526. }
  527. ConfigBaseWriteDouble( m_config, OPTKEY_PLOT_Y_FINESCALE_ADJ, m_YScaleAdjust );
  528. // PS Width correction
  529. msg = m_PSFineAdjustWidthOpt->GetValue();
  530. int itmp = ReturnValueFromString( g_UserUnit, msg );
  531. if( !setInt( &m_PSWidthAdjust, itmp, m_widthAdjustMinValue, m_widthAdjustMaxValue ) )
  532. {
  533. msg = ReturnStringFromValue( g_UserUnit, m_PSWidthAdjust );
  534. m_PSFineAdjustWidthOpt->SetValue( msg );
  535. msg.Printf( _( "Width correction constrained!\n"
  536. "The reasonable width correction value must be in a range of\n"
  537. " [%+f; %+f] (%s) for current design rules!\n" ),
  538. To_User_Unit( g_UserUnit, m_widthAdjustMinValue ),
  539. To_User_Unit( g_UserUnit, m_widthAdjustMaxValue ),
  540. ( g_UserUnit == INCHES ) ? wxT( "\"" ) : wxT( "mm" ) );
  541. m_messagesBox->AppendText( msg );
  542. }
  543. // Store m_PSWidthAdjust in mm in user config
  544. ConfigBaseWriteDouble( m_config, CONFIG_PS_FINEWIDTH_ADJ,
  545. (double)m_PSWidthAdjust / IU_PER_MM );
  546. tempOptions.SetUseGerberExtensions( m_useGerberExtensions->GetValue() );
  547. tempOptions.SetFormat( GetPlotFormat() );
  548. long selectedLayers = 0;
  549. unsigned int i;
  550. for( i = 0; i < m_layerList.size(); i++ )
  551. {
  552. if( m_layerCheckListBox->IsChecked( i ) )
  553. selectedLayers |= GetLayerMask( m_layerList[i] );
  554. }
  555. tempOptions.SetLayerSelection( selectedLayers );
  556. tempOptions.SetNegative( m_plotPSNegativeOpt->GetValue() );
  557. tempOptions.SetA4Output( m_forcePSA4OutputOpt->GetValue() );
  558. // Set output directory and replace backslashes with forward ones
  559. wxString dirStr;
  560. dirStr = m_outputDirectoryName->GetValue();
  561. dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
  562. tempOptions.SetOutputDirectory( dirStr );
  563. if( m_plotOpts != tempOptions )
  564. {
  565. m_parent->SetPlotSettings( tempOptions );
  566. m_plotOpts = tempOptions;
  567. m_parent->OnModify();
  568. }
  569. }
  570. void DIALOG_PLOT::Plot( wxCommandEvent& event )
  571. {
  572. applyPlotSettings();
  573. // Create output directory if it does not exist (also transform it in
  574. // absolute form). Bail if it fails
  575. wxFileName outputDir = wxFileName::DirName( m_plotOpts.GetOutputDirectory() );
  576. wxString boardFilename = m_parent->GetBoard()->GetFileName();
  577. WX_TEXT_CTRL_REPORTER reporter( m_messagesBox );
  578. if( !EnsureOutputDirectory( &outputDir, boardFilename, &reporter ) )
  579. {
  580. wxString msg;
  581. msg.Printf( _( "Could not write plot files to folder \"%s\"." ),
  582. GetChars( outputDir.GetPath() ) );
  583. DisplayError( this, msg );
  584. return;
  585. }
  586. m_plotOpts.SetAutoScale( false );
  587. m_plotOpts.SetScale( 1 );
  588. switch( m_plotOpts.GetScaleSelection() )
  589. {
  590. default:
  591. break;
  592. case 0: // Autoscale option
  593. m_plotOpts.SetAutoScale( true );
  594. break;
  595. case 2: // 3:2 option
  596. m_plotOpts.SetScale( 1.5 );
  597. break;
  598. case 3: // 2:1 option
  599. m_plotOpts.SetScale( 2 );
  600. break;
  601. case 4: // 3:1 option
  602. m_plotOpts.SetScale( 3 );
  603. break;
  604. }
  605. /* If the scale factor edit controls are disabled or the scale value
  606. * is 0, don't adjust the base scale factor. This fixes a bug when
  607. * the default scale adjust is initialized to 0 and saved in program
  608. * settings resulting in a divide by zero fault.
  609. */
  610. if( m_fineAdjustXscaleOpt->IsEnabled() && m_XScaleAdjust != 0.0 )
  611. m_plotOpts.SetFineScaleAdjustX( m_XScaleAdjust );
  612. if( m_fineAdjustYscaleOpt->IsEnabled() && m_YScaleAdjust != 0.0 )
  613. m_plotOpts.SetFineScaleAdjustY( m_YScaleAdjust );
  614. if( m_PSFineAdjustWidthOpt->IsEnabled() )
  615. m_plotOpts.SetWidthAdjust( m_PSWidthAdjust );
  616. wxString file_ext( GetDefaultPlotExtension( m_plotOpts.GetFormat() ) );
  617. // Test for a reasonable scale value
  618. // XXX could this actually happen? isn't it constrained in the apply
  619. // function?
  620. if( m_plotOpts.GetScale() < PLOT_MIN_SCALE )
  621. DisplayInfoMessage( this,
  622. _( "Warning: Scale option set to a very small value" ) );
  623. if( m_plotOpts.GetScale() > PLOT_MAX_SCALE )
  624. DisplayInfoMessage( this,
  625. _( "Warning: Scale option set to a very large value" ) );
  626. // Save the current plot options in the board
  627. m_parent->SetPlotSettings( m_plotOpts );
  628. for( LAYER_NUM layer = FIRST_LAYER; layer < NB_PCB_LAYERS; ++layer )
  629. {
  630. if( m_plotOpts.GetLayerSelection() & GetLayerMask( layer ) )
  631. {
  632. // Pick the basename from the board file
  633. wxFileName fn( boardFilename );
  634. // Use Gerber Extensions based on layer number
  635. // (See http://en.wikipedia.org/wiki/Gerber_File)
  636. if( ( m_plotOpts.GetFormat() == PLOT_FORMAT_GERBER )
  637. && m_useGerberExtensions->GetValue() )
  638. file_ext = GetGerberExtension( layer );
  639. // Create file name (from the English layer name for non copper layers).
  640. BuildPlotFileName( &fn, outputDir.GetPath(),
  641. m_board->GetStandardLayerName( layer ),
  642. file_ext );
  643. LOCALE_IO toggle;
  644. BOARD *board = m_parent->GetBoard();
  645. PLOTTER *plotter = StartPlotBoard( board, &m_plotOpts,
  646. fn.GetFullPath(),
  647. wxEmptyString );
  648. // Print diags in messages box:
  649. wxString msg;
  650. if( plotter )
  651. {
  652. PlotOneBoardLayer( board, plotter, layer, m_plotOpts );
  653. plotter->EndPlot();
  654. delete plotter;
  655. msg.Printf( _( "Plot file <%s> created" ), GetChars( fn.GetFullPath() ) );
  656. }
  657. else
  658. msg.Printf( _( "Unable to create <%s>" ), GetChars( fn.GetFullPath() ) );
  659. msg << wxT( "\n" );
  660. m_messagesBox->AppendText( msg );
  661. }
  662. }
  663. // If no layer selected, we have nothing plotted.
  664. // Prompt user if it happens because he could think there is a bug in Pcbnew.
  665. if( !m_plotOpts.GetLayerSelection() )
  666. DisplayError( this, _( "No layer selected" ) );
  667. }