KiCad PCB EDA Suite
dialog_plot.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 
25 #include <kiface_base.h>
26 #include <plotters/plotter.h>
27 #include <confirm.h>
28 #include <pcb_edit_frame.h>
29 #include <pcbnew_settings.h>
30 #include <pcbplot.h>
31 #include <pgm_base.h>
32 #include <gerber_jobfile_writer.h>
33 #include <reporter.h>
35 #include <layer_ids.h>
36 #include <locale_io.h>
37 #include <bitmaps.h>
38 #include <board.h>
39 #include <board_design_settings.h>
40 #include <dialog_plot.h>
41 #include <dialog_gendrill.h>
42 #include <wx_html_report_panel.h>
43 #include <tool/tool_manager.h>
44 #include <tools/zone_filler_tool.h>
45 #include <tools/drc_tool.h>
46 #include <math/util.h> // for KiROUND
47 #include <macros.h>
48 
49 #include <wx/dirdlg.h>
50 
51 
52 
54  DIALOG_PLOT_BASE( aParent ), m_parent( aParent ),
55  m_defaultPenSize( aParent, m_hpglPenLabel, m_hpglPenCtrl, m_hpglPenUnits ),
56  m_trackWidthCorrection( aParent, m_widthAdjustLabel, m_widthAdjustCtrl, m_widthAdjustUnits )
57 {
58  SetName( DLG_WINDOW_NAME );
59  m_plotOpts = aParent->GetPlotSettings();
61 
62  m_messagesPanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
63 
64  init_Dialog();
65 
66  // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
67  // that requires us to correct the button labels here.
68  m_sdbSizer1OK->SetLabel( _( "Plot" ) );
69  m_sdbSizer1Apply->SetLabel( _( "Generate Drill Files..." ) );
70  m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
71  m_sizerButtons->Layout();
72 
73  m_sdbSizer1OK->SetDefault();
74 
75  GetSizer()->Fit( this );
76  GetSizer()->SetSizeHints( this );
77 }
78 
79 
81 {
82  BOARD* board = m_parent->GetBoard();
83  wxFileName fileName;
84 
85  auto cfg = m_parent->GetPcbNewSettings();
86 
87  m_XScaleAdjust = cfg->m_Plot.fine_scale_x;
88  m_YScaleAdjust = cfg->m_Plot.fine_scale_y;
89 
90  m_zoneFillCheck->SetValue( cfg->m_Plot.check_zones_before_plotting );
91 
93 
94  // m_PSWidthAdjust is stored in mm in user config
95  m_PSWidthAdjust = KiROUND( cfg->m_Plot.ps_fine_width_adjust * IU_PER_MM );
96 
97  // The reasonable width correction value must be in a range of
98  // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
101 
102  switch( m_plotOpts.GetFormat() )
103  {
104  default:
105  case PLOT_FORMAT::GERBER: m_plotFormatOpt->SetSelection( 0 ); break;
106  case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 1 ); break;
107  case PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
108  case PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
109  case PLOT_FORMAT::HPGL: m_plotFormatOpt->SetSelection( 4 ); break;
110  case PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 5 ); break;
111  }
112 
113  // Set units and value for HPGL pen size (this param is in mils).
115 
116  // Test for a reasonable scale value. Set to 1 if problem
119  {
121  }
122 
125 
126  // Test for a reasonable PS width correction value. Set to 0 if problem.
127  if( m_PSWidthAdjust < m_widthAdjustMinValue || m_PSWidthAdjust > m_widthAdjustMaxValue )
128  m_PSWidthAdjust = 0.;
129 
131 
134 
135  // Could devote a PlotOrder() function in place of UIOrder().
136  m_layerList = board->GetEnabledLayers().UIOrder();
137 
138  // Populate the check list box by all enabled layers names
139  for( LSEQ seq = m_layerList; seq; ++seq )
140  {
141  PCB_LAYER_ID layer = *seq;
142 
143  int checkIndex = m_layerCheckListBox->Append( board->GetLayerName( layer ) );
144 
145  if( m_plotOpts.GetLayerSelection()[layer] )
146  m_layerCheckListBox->Check( checkIndex );
147  }
148 
149  // Option for disabling Gerber Aperture Macro (for broken Gerber readers)
151 
152  // Option for using proper Gerber extensions. Note also Protel extensions are
153  // a broken feature. However, for now, we need to handle it.
155 
156  // Option for including Gerber attributes, from Gerber X2 format, in the output
157  // In X1 format, they will be added as comments
159 
160  // Option for including Gerber netlist info (from Gerber X2 format) in the output
162 
163  // Option to generate a Gerber job file
165 
166  // Gerber precision for coordinates
167  m_coordFormatCtrl->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 );
168 
169  // SVG precision and units for coordinates
171  m_svgUnits->SetSelection( m_plotOpts.GetSvgUseInch() );
172 
173  // Option for excluding contents of "Edges Pcb" layer
175 
176  // Option to exclude pads from silkscreen layers
178 
179  // Option to tent vias
181 
182  // Option to use aux origin
184 
185  // Option to plot page references:
187 
188  // Options to plot texts on footprints
192 
193  // Options to plot pads and vias holes
194  m_drillShapeOpt->SetSelection( m_plotOpts.GetDrillMarksType() );
195 
196  // Scale option
197  m_scaleOpt->SetSelection( m_plotOpts.GetScaleSelection() );
198 
199  // Plot mode
201 
202  // DXF outline mode
204 
205  // DXF text mode
207 
208  // DXF units selection
209  m_DXF_plotUnits->SetSelection( m_plotOpts.GetDXFPlotUnits() == DXF_UNITS::INCHES ? 0 : 1);
210 
211  // Plot mirror option
212  m_plotMirrorOpt->SetValue( m_plotOpts.GetMirror() );
213 
214  // Put vias on mask layer
216 
217  // Initialize a few other parameters, which can also be modified
218  // from the drill dialog
219  reInitDialog();
220 
221  // Update options values:
222  wxCommandEvent cmd_event;
223  SetPlotFormat( cmd_event );
224  OnSetScaleOpt( cmd_event );
225 }
226 
227 
229 {
230  // after calling the Drill or DRC dialogs some parameters can be modified....
231 
232  // Output directory
234 
235  // Origin of coordinates:
237 
238  int knownViolations = 0;
239  int exclusions = 0;
240 
241  for( PCB_MARKER* marker : m_parent->GetBoard()->Markers() )
242  {
243  if( marker->IsExcluded() )
244  exclusions++;
245  else
246  knownViolations++;
247  }
248 
249  if( knownViolations || exclusions )
250  {
251  m_DRCExclusionsWarning->SetLabel( wxString::Format( m_DRCWarningTemplate, knownViolations,
252  exclusions ) );
253  m_DRCExclusionsWarning->Show();
254  }
255  else
256  {
257  m_DRCExclusionsWarning->Hide();
258  }
259 
260  BOARD* board = m_parent->GetBoard();
261  const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
262 
264  ( brd_settings.m_SolderMaskMargin || brd_settings.m_SolderMaskMinWidth ) )
265  {
267  }
268  else
269  {
271  }
272 }
273 
274 
275 // A helper function to show a popup menu, when the dialog is right clicked.
276 void DIALOG_PLOT::OnRightClick( wxMouseEvent& event )
277 {
278  PopupMenu( m_popMenu );
279 }
280 
281 
282 // Select or deselect groups of layers in the layers list:
283 void DIALOG_PLOT::OnPopUpLayers( wxCommandEvent& event )
284 {
285  // Build a list of layers for usual fabrication: copper layers + tech layers without courtyard
286  LSET fab_layer_set = ( LSET::AllCuMask() | LSET::AllTechMask() ) & ~LSET( 2, B_CrtYd, F_CrtYd );
287 
288  switch( event.GetId() )
289  {
290  case ID_LAYER_FAB: // Select layers usually needed to build a board
291  for( unsigned i = 0; i < m_layerList.size(); i++ )
292  {
293  LSET layermask( m_layerList[ i ] );
294 
295  if( ( layermask & fab_layer_set ).any() )
296  m_layerCheckListBox->Check( i, true );
297  else
298  m_layerCheckListBox->Check( i, false );
299  }
300  break;
301 
303  for( unsigned i = 0; i < m_layerList.size(); i++ )
304  {
305  if( IsCopperLayer( m_layerList[i] ) )
306  m_layerCheckListBox->Check( i, true );
307  }
308  break;
309 
311  for( unsigned i = 0; i < m_layerList.size(); i++ )
312  {
313  if( IsCopperLayer( m_layerList[i] ) )
314  m_layerCheckListBox->Check( i, false );
315  }
316  break;
317 
319  for( unsigned i = 0; i < m_layerList.size(); i++ )
320  m_layerCheckListBox->Check( i, true );
321  break;
322 
324  for( unsigned i = 0; i < m_layerList.size(); i++ )
325  m_layerCheckListBox->Check( i, false );
326  break;
327 
328  default:
329  break;
330  }
331 }
332 
333 
334 void DIALOG_PLOT::CreateDrillFile( wxCommandEvent& event )
335 {
336  // Be sure drill file use the same settings (axis option, plot directory) as plot files:
338 
339  DIALOG_GENDRILL dlg( m_parent, this );
340  dlg.ShowModal();
341 
342  // a few plot settings can be modified: take them in account
344  reInitDialog();
345 }
346 
347 
348 void DIALOG_PLOT::OnChangeDXFPlotMode( wxCommandEvent& event )
349 {
350  // m_DXF_plotTextStrokeFontOpt is disabled if m_DXF_plotModeOpt is checked (plot in DXF
351  // polygon mode)
352  m_DXF_plotTextStrokeFontOpt->Enable( !m_DXF_plotModeOpt->GetValue() );
353 
354  // if m_DXF_plotTextStrokeFontOpt option is disabled (plot DXF in polygon mode), force
355  // m_DXF_plotTextStrokeFontOpt to true to use Pcbnew stroke font
356  if( !m_DXF_plotTextStrokeFontOpt->IsEnabled() )
357  m_DXF_plotTextStrokeFontOpt->SetValue( true );
358 }
359 
360 
361 void DIALOG_PLOT::OnSetScaleOpt( wxCommandEvent& event )
362 {
363  /* Disable sheet reference for scale != 1:1 */
364  bool scale1 = ( m_scaleOpt->GetSelection() == 1 );
365 
366  m_plotSheetRef->Enable( scale1 );
367 
368  if( !scale1 )
369  m_plotSheetRef->SetValue( false );
370 }
371 
372 
373 void DIALOG_PLOT::OnOutputDirectoryBrowseClicked( wxCommandEvent& event )
374 {
375  // Build the absolute path of current output directory to preselect it in the file browser.
376  wxString path = ExpandEnvVarSubstitutions( m_outputDirectoryName->GetValue(), &Prj() );
377  path = Prj().AbsolutePath( path );
378 
379  wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
380 
381  if( dirDialog.ShowModal() == wxID_CANCEL )
382  return;
383 
384  wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
385 
386  wxFileName fn( Prj().AbsolutePath( m_parent->GetBoard()->GetFileName() ) );
387  wxString defaultPath = fn.GetPathWithSep();
388  wxString msg;
389  wxFileName relPathTest; // Used to test if we can make the path relative
390 
391  relPathTest.Assign( dirDialog.GetPath() );
392 
393  // Test if making the path relative is possible before asking the user if they want to do it
394  if( relPathTest.MakeRelativeTo( defaultPath ) )
395  {
396  msg.Printf( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath );
397 
398  wxMessageDialog dialog( this, msg, _( "Plot Output Directory" ),
399  wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
400 
401  if( dialog.ShowModal() == wxID_YES )
402  dirName.MakeRelativeTo( defaultPath );
403  }
404 
405  m_outputDirectoryName->SetValue( dirName.GetFullPath() );
406 }
407 
408 
410 {
411  // plot format id's are ordered like displayed in m_plotFormatOpt
412  static const PLOT_FORMAT plotFmt[] = {
419 
420  return plotFmt[m_plotFormatOpt->GetSelection()];
421 }
422 
423 
424 // Enable or disable widgets according to the plot format selected
425 // and clear also some optional values
426 void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
427 {
428  // this option exist only in DXF format:
430 
431  // The alert message about non 0 solder mask min width and margin is shown
432  // only in gerber format and if min mask width or mask margin is not 0
433  BOARD* board = m_parent->GetBoard();
434  const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
435 
437  && ( brd_settings.m_SolderMaskMargin || brd_settings.m_SolderMaskMinWidth ) )
438  {
440  }
441  else
442  {
444  }
445 
446 
447  switch( getPlotFormat() )
448  {
449  case PLOT_FORMAT::SVG:
450  case PLOT_FORMAT::PDF:
451  m_drillShapeOpt->Enable( true );
452  m_plotModeOpt->Enable( false );
454  m_plotMirrorOpt->Enable( true );
455  m_useAuxOriginCheckBox->Enable( false );
456  m_useAuxOriginCheckBox->SetValue( false );
457  m_defaultPenSize.Enable( false );
458  m_includeEdgeLayerOpt->Enable( true );
459  m_scaleOpt->Enable( false );
460  m_scaleOpt->SetSelection( 1 );
461  m_fineAdjustXCtrl->Enable( false );
462  m_fineAdjustYCtrl->Enable( false );
464  m_plotPSNegativeOpt->Enable( true );
465  m_forcePSA4OutputOpt->Enable( false );
466  m_forcePSA4OutputOpt->SetValue( false );
467 
470  else
472 
477  break;
478 
479  case PLOT_FORMAT::POST:
480  m_drillShapeOpt->Enable( true );
481  m_plotModeOpt->Enable( true );
482  m_plotMirrorOpt->Enable( true );
483  m_useAuxOriginCheckBox->Enable( false );
484  m_useAuxOriginCheckBox->SetValue( false );
485  m_defaultPenSize.Enable( false );
486  m_includeEdgeLayerOpt->Enable( true );
487  m_scaleOpt->Enable( true );
488  m_fineAdjustXCtrl->Enable( true );
489  m_fineAdjustYCtrl->Enable( true );
491  m_plotPSNegativeOpt->Enable( true );
492  m_forcePSA4OutputOpt->Enable( true );
493 
499  break;
500 
501  case PLOT_FORMAT::GERBER:
502  m_drillShapeOpt->Enable( false );
503  m_drillShapeOpt->SetSelection( 0 );
504  m_plotModeOpt->Enable( false );
506  m_plotMirrorOpt->Enable( false );
507  m_plotMirrorOpt->SetValue( false );
508  m_useAuxOriginCheckBox->Enable( true );
509  m_defaultPenSize.Enable( false );
510  m_includeEdgeLayerOpt->Enable( true );
511  m_scaleOpt->Enable( false );
512  m_scaleOpt->SetSelection( 1 );
513  m_fineAdjustXCtrl->Enable( false );
514  m_fineAdjustYCtrl->Enable( false );
516  m_plotPSNegativeOpt->Enable( false );
517  m_plotPSNegativeOpt->SetValue( false );
518  m_forcePSA4OutputOpt->Enable( false );
519  m_forcePSA4OutputOpt->SetValue( false );
520 
526  break;
527 
528  case PLOT_FORMAT::HPGL:
529  m_drillShapeOpt->Enable( true );
530  m_plotModeOpt->Enable( true );
531  m_plotMirrorOpt->Enable( true );
532  m_useAuxOriginCheckBox->Enable( false );
533  m_useAuxOriginCheckBox->SetValue( false );
534  m_defaultPenSize.Enable( true );
535  m_includeEdgeLayerOpt->Enable( true );
536  m_scaleOpt->Enable( true );
537  m_fineAdjustXCtrl->Enable( false );
538  m_fineAdjustYCtrl->Enable( false );
540  m_plotPSNegativeOpt->SetValue( false );
541  m_plotPSNegativeOpt->Enable( false );
542  m_forcePSA4OutputOpt->Enable( true );
543 
549  break;
550 
551  case PLOT_FORMAT::DXF:
552  m_drillShapeOpt->Enable( true );
553  m_plotModeOpt->Enable( false );
555  m_plotMirrorOpt->Enable( false );
556  m_plotMirrorOpt->SetValue( false );
557  m_useAuxOriginCheckBox->Enable( true );
558  m_defaultPenSize.Enable( false );
559  m_includeEdgeLayerOpt->Enable( true );
560  m_scaleOpt->Enable( false );
561  m_scaleOpt->SetSelection( 1 );
562  m_fineAdjustXCtrl->Enable( false );
563  m_fineAdjustYCtrl->Enable( false );
565  m_plotPSNegativeOpt->Enable( false );
566  m_plotPSNegativeOpt->SetValue( false );
567  m_forcePSA4OutputOpt->Enable( false );
568  m_forcePSA4OutputOpt->SetValue( false );
569 
575 
576  OnChangeDXFPlotMode( event );
577  break;
578 
580  break;
581  }
582 
583  /* Update the interlock between scale and frame reference
584  * (scaling would mess up the frame border...) */
585  OnSetScaleOpt( event );
586 
587  Layout();
588  m_MainSizer->SetSizeHints( this );
589 }
590 
591 
592 // A helper function to "clip" aValue between aMin and aMax and write result in * aResult
593 // return false if clipped, true if aValue is just copied into * aResult
594 static bool setDouble( double* aResult, double aValue, double aMin, double aMax )
595 {
596  if( aValue < aMin )
597  {
598  *aResult = aMin;
599  return false;
600  }
601  else if( aValue > aMax )
602  {
603  *aResult = aMax;
604  return false;
605  }
606 
607  *aResult = aValue;
608  return true;
609 }
610 
611 
612 static bool setInt( int* aResult, int aValue, int aMin, int aMax )
613 {
614  if( aValue < aMin )
615  {
616  *aResult = aMin;
617  return false;
618  }
619  else if( aValue > aMax )
620  {
621  *aResult = aMax;
622  return false;
623  }
624 
625  *aResult = aValue;
626  return true;
627 }
628 
629 
631 {
632  REPORTER& reporter = m_messagesPanel->Reporter();
633  int sel;
634  PCB_PLOT_PARAMS tempOptions;
635 
636  tempOptions.SetExcludeEdgeLayer( !m_includeEdgeLayerOpt->GetValue() );
637  tempOptions.SetSubtractMaskFromSilk( m_subtractMaskFromSilk->GetValue() );
638  tempOptions.SetPlotFrameRef( m_plotSheetRef->GetValue() );
639  tempOptions.SetSketchPadsOnFabLayers( m_sketchPadsOnFabLayers->GetValue() );
640  tempOptions.SetUseAuxOrigin( m_useAuxOriginCheckBox->GetValue() );
641  tempOptions.SetPlotValue( m_plotModuleValueOpt->GetValue() );
642  tempOptions.SetPlotReference( m_plotModuleRefOpt->GetValue() );
643  tempOptions.SetPlotInvisibleText( m_plotInvisibleText->GetValue() );
644  tempOptions.SetScaleSelection( m_scaleOpt->GetSelection() );
645 
646  sel = m_drillShapeOpt->GetSelection();
647  tempOptions.SetDrillMarksType( static_cast<PCB_PLOT_PARAMS::DrillMarksType>( sel ) );
648 
649  tempOptions.SetMirror( m_plotMirrorOpt->GetValue() );
650  tempOptions.SetPlotMode( m_plotModeOpt->GetSelection() == 1 ? SKETCH : FILLED );
651  tempOptions.SetDXFPlotPolygonMode( m_DXF_plotModeOpt->GetValue() );
652 
653  sel = m_DXF_plotUnits->GetSelection();
654  tempOptions.SetDXFPlotUnits( sel == 0 ? DXF_UNITS::INCHES : DXF_UNITS::MILLIMETERS );
655 
656  tempOptions.SetPlotViaOnMaskLayer( m_plotNoViaOnMaskOpt->GetValue() );
657 
658  if( !m_DXF_plotTextStrokeFontOpt->IsEnabled() ) // Currently, only DXF supports this option
659  tempOptions.SetTextMode( PLOT_TEXT_MODE::DEFAULT );
660  else
663 
664  // Update settings from text fields. Rewrite values back to the fields,
665  // since the values may have been constrained by the setters.
666  wxString msg;
667 
668  // read HPLG pen size (this param is stored in mils)
669  // However, due to issues when converting this value from or to mm
670  // that can slightly change the value, update this param only if it
671  // is in use
673  {
674  if( !tempOptions.SetHPGLPenDiameter( m_defaultPenSize.GetValue() / IU_PER_MILS ) )
675  {
677  msg.Printf( _( "HPGL pen size constrained." ) );
678  reporter.Report( msg, RPT_SEVERITY_INFO );
679  }
680  }
681  else // keep the last value (initial value if no HPGL plot made)
682  {
684  }
685 
686  // X scale
687  double tmpDouble;
688  msg = m_fineAdjustXCtrl->GetValue();
689  msg.ToDouble( &tmpDouble );
690 
691  if( !setDouble( &m_XScaleAdjust, tmpDouble, PLOT_MIN_SCALE, PLOT_MAX_SCALE ) )
692  {
693  msg.Printf( wxT( "%f" ), m_XScaleAdjust );
694  m_fineAdjustXCtrl->SetValue( msg );
695  msg.Printf( _( "X scale constrained." ) );
696  reporter.Report( msg, RPT_SEVERITY_INFO );
697  }
698 
699  // Y scale
700  msg = m_fineAdjustYCtrl->GetValue();
701  msg.ToDouble( &tmpDouble );
702 
703  if( !setDouble( &m_YScaleAdjust, tmpDouble, PLOT_MIN_SCALE, PLOT_MAX_SCALE ) )
704  {
705  msg.Printf( wxT( "%f" ), m_YScaleAdjust );
706  m_fineAdjustYCtrl->SetValue( msg );
707  msg.Printf( _( "Y scale constrained." ) );
708  reporter.Report( msg, RPT_SEVERITY_INFO );
709  }
710 
711  auto cfg = m_parent->GetPcbNewSettings();
712 
714  cfg->m_Plot.fine_scale_y = m_YScaleAdjust;
715 
716  cfg->m_Plot.check_zones_before_plotting = m_zoneFillCheck->GetValue();
717 
718  // PS Width correction
721  {
723  msg.Printf( _( "Width correction constrained. "
724  "The reasonable width correction value must be in a range of "
725  " [%s; %s] (%s) for current design rules." ),
729  reporter.Report( msg, RPT_SEVERITY_WARNING );
730  }
731 
732  // Store m_PSWidthAdjust in mm in user config
733  cfg->m_Plot.ps_fine_width_adjust = Iu2Millimeter( m_PSWidthAdjust );
734 
735  tempOptions.SetFormat( getPlotFormat() );
736 
737  tempOptions.SetDisableGerberMacros( m_disableApertMacros->GetValue() );
738  tempOptions.SetUseGerberProtelExtensions( m_useGerberExtensions->GetValue() );
739  tempOptions.SetUseGerberX2format( m_useGerberX2Format->GetValue() );
740  tempOptions.SetIncludeGerberNetlistInfo( m_useGerberNetAttributes->GetValue() );
741  tempOptions.SetCreateGerberJobFile( m_generateGerberJobFile->GetValue() );
742 
743  tempOptions.SetGerberPrecision( m_coordFormatCtrl->GetSelection() == 0 ? 5 : 6 );
744  tempOptions.SetSvgPrecision( m_svgPrecsision->GetValue(), m_svgUnits->GetSelection() );
745 
746  LSET selectedLayers;
747 
748  for( unsigned i = 0; i < m_layerList.size(); i++ )
749  {
750  if( m_layerCheckListBox->IsChecked( i ) )
751  selectedLayers.set( m_layerList[i] );
752  }
753 
754  // Get a list of copper layers that aren't being used by inverting enabled layers.
755  LSET disabledCopperLayers = LSET::AllCuMask() & ~m_parent->GetBoard()->GetEnabledLayers();
756  // Enable all of the disabled copper layers.
757  // If someone enables more copper layers they will be selected by default.
758  selectedLayers = selectedLayers | disabledCopperLayers;
759  tempOptions.SetLayerSelection( selectedLayers );
760 
761  tempOptions.SetNegative( m_plotPSNegativeOpt->GetValue() );
762  tempOptions.SetA4Output( m_forcePSA4OutputOpt->GetValue() );
763 
764  // Set output directory and replace backslashes with forward ones
765  wxString dirStr;
766  dirStr = m_outputDirectoryName->GetValue();
767  dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
768  tempOptions.SetOutputDirectory( dirStr );
769 
770  if( !m_plotOpts.IsSameAs( tempOptions ) )
771  {
772  m_parent->SetPlotSettings( tempOptions );
773  m_parent->OnModify();
774  m_plotOpts = tempOptions;
775  }
776 }
777 
778 
779 void DIALOG_PLOT::OnGerberX2Checked( wxCommandEvent& event )
780 {
781  // Currently: do nothing
782 }
783 
784 
785 void DIALOG_PLOT::Plot( wxCommandEvent& event )
786 {
787  BOARD* board = m_parent->GetBoard();
788 
790 
791  SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
793 
795 
797 
798  // If no layer selected, we have nothing plotted.
799  // Prompt user if it happens because he could think there is a bug in Pcbnew.
800  if( !m_plotOpts.GetLayerSelection().any() )
801  {
802  DisplayError( this, _( "No layer selected, Nothing to plot" ) );
803  return;
804  }
805 
806  // Create output directory if it does not exist (also transform it in
807  // absolute form). Bail if it fails
809  wxFileName outputDir = wxFileName::DirName( path );
810  wxString boardFilename = m_parent->GetBoard()->GetFileName();
811  REPORTER& reporter = m_messagesPanel->Reporter();
812 
813  if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
814  {
815  wxString msg;
816  msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
817  DisplayError( this, msg );
818  return;
819  }
820 
821  if( m_zoneFillCheck->GetValue() )
822  m_parent->GetToolManager()->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( this );
823 
824  m_plotOpts.SetAutoScale( false );
825 
826  switch( m_plotOpts.GetScaleSelection() )
827  {
828  default: m_plotOpts.SetScale( 1 ); break;
829  case 0: m_plotOpts.SetAutoScale( true ); break;
830  case 2: m_plotOpts.SetScale( 1.5 ); break;
831  case 3: m_plotOpts.SetScale( 2 ); break;
832  case 4: m_plotOpts.SetScale( 3 ); break;
833  }
834 
835  /* If the scale factor edit controls are disabled or the scale value
836  * is 0, don't adjust the base scale factor. This fixes a bug when
837  * the default scale adjust is initialized to 0 and saved in program
838  * settings resulting in a divide by zero fault.
839  */
841  {
842  if( m_XScaleAdjust != 0.0 )
844 
845  if( m_YScaleAdjust != 0.0 )
847 
849  }
850 
851  wxString file_ext( GetDefaultPlotExtension( m_plotOpts.GetFormat() ) );
852 
853  // Test for a reasonable scale value
854  // XXX could this actually happen? isn't it constrained in the apply
855  // function?
857  DisplayInfoMessage( this, _( "Warning: Scale option set to a very small value" ) );
858 
860  DisplayInfoMessage( this, _( "Warning: Scale option set to a very large value" ) );
861 
862  GERBER_JOBFILE_WRITER jobfile_writer( board, &reporter );
863 
864  // Save the current plot options in the board
866 
867  wxBusyCursor dummy;
868 
869  for( LSEQ seq = m_plotOpts.GetLayerSelection().UIOrder(); seq; ++seq )
870  {
871  PCB_LAYER_ID layer = *seq;
872 
873  // All copper layers that are disabled are actually selected
874  // This is due to wonkyness in automatically selecting copper layers
875  // for plotting when adding more than two layers to a board.
876  // If plot options become accessible to the layers setup dialog
877  // please move this functionality there!
878  // This skips a copper layer if it is actually disabled on the board.
879  if( ( LSET::AllCuMask() & ~board->GetEnabledLayers() )[layer] )
880  continue;
881 
882  // Pick the basename from the board file
883  wxFileName fn( boardFilename );
884 
885  // Use Gerber Extensions based on layer number
886  // (See http://en.wikipedia.org/wiki/Gerber_File)
888  file_ext = GetGerberProtelExtension( layer );
889 
890  BuildPlotFileName( &fn, outputDir.GetPath(), board->GetLayerName( layer ), file_ext );
891  wxString fullname = fn.GetFullName();
892  jobfile_writer.AddGbrFile( layer, fullname );
893 
894  LOCALE_IO toggle;
895 
896  PLOTTER* plotter = StartPlotBoard( board, &m_plotOpts, layer, fn.GetFullPath(), wxEmptyString );
897 
898  // Print diags in messages box:
899  wxString msg;
900 
901  if( plotter )
902  {
903  PlotOneBoardLayer( board, plotter, layer, m_plotOpts );
904  plotter->EndPlot();
905  delete plotter->RenderSettings();
906  delete plotter;
907 
908  msg.Printf( _( "Plotted to '%s'." ), fn.GetFullPath() );
909  reporter.Report( msg, RPT_SEVERITY_ACTION );
910  }
911  else
912  {
913  msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
914  reporter.Report( msg, RPT_SEVERITY_ERROR );
915  }
916 
917  wxSafeYield(); // displays report message.
918  }
919 
921  {
922  // Pick the basename from the board file
923  wxFileName fn( boardFilename );
924  // Build gerber job file from basename
925  BuildPlotFileName( &fn, outputDir.GetPath(), "job", GerberJobFileExtension );
926  jobfile_writer.CreateJobFile( fn.GetFullPath() );
927  }
928 
929  reporter.ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
930 }
931 
932 
933 void DIALOG_PLOT::onRunDRC( wxCommandEvent& event )
934 {
935  PCB_EDIT_FRAME* parent = dynamic_cast<PCB_EDIT_FRAME*>( GetParent() );
936 
937  if( parent )
938  {
939  DRC_TOOL* drcTool = parent->GetToolManager()->GetTool<DRC_TOOL>();
940 
941  // First close an existing dialog if open
942  // (low probability, but can happen)
943  drcTool->DestroyDRCDialog();
944 
945  // Open a new drc dialod, with the right parent frame, and in Modal Mode
946  drcTool->ShowDRCDialog( this );
947 
948  // Update DRC warnings on return to this dialog
949  reInitDialog();
950  }
951 }
952 
953 
954 void DIALOG_PLOT::onBoardSetup( wxHyperlinkEvent& aEvent )
955 {
956  PCB_EDIT_FRAME* parent = dynamic_cast<PCB_EDIT_FRAME*>( GetParent() );
957 
958  if( parent )
959  {
960  parent->ShowBoardSetupDialog( _( "Solder Mask/Paste" ) );
961 
962  // Update warnings on return to this dialog
963  reInitDialog();
964  }
965 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
void SetUseGerberProtelExtensions(bool aUse)
void SetPlotReference(bool aFlag)
void SetExcludeEdgeLayer(bool aFlag)
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:271
WX_HTML_REPORT_PANEL * m_messagesPanel
OUTLINE_MODE GetPlotMode() const
wxStaticBoxSizer * m_HPGLOptionsSizer
void SetScaleSelection(int aSelection)
LSEQ m_layerList
Definition: dialog_plot.h:70
void SetIncludeGerberNetlistInfo(bool aUse)
void SetDXFPlotPolygonMode(bool aFlag)
double m_YScaleAdjust
Definition: dialog_plot.h:73
bool GetCreateGerberJobFile() const
void OnModify() override
Must be called after a board change to set the modified flag.
wxCheckBox * m_useGerberExtensions
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
void SetGerberPrecision(int aPrecision)
void OnOutputDirectoryBrowseClicked(wxCommandEvent &event) override
wxButton * m_sdbSizer1Cancel
void SetPlotViaOnMaskLayer(bool aFlag)
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:361
bool GetPlotFrameRef() const
bool CreateJobFile(const wxString &aFullFilename)
Creates a Gerber job file.
wxCheckBox * m_includeEdgeLayerOpt
bool GetDXFPlotPolygonMode() const
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:40
wxString GetDefaultPlotExtension(PLOT_FORMAT aFormat)
Returns the default plot extension for a format.
void SetLayerSelection(LSET aSelection)
void OnGerberX2Checked(wxCommandEvent &event) override
void SetUseAuxOrigin(bool aAux)
This file is part of the common library.
void SetSketchPadLineWidth(int aWidth)
static constexpr double IU_PER_MM
Mock up a conversion function.
void OnChangeDXFPlotMode(wxCommandEvent &event) override
void PlotOneBoardLayer(BOARD *aBoard, PLOTTER *aPlotter, PCB_LAYER_ID aLayer, const PCB_PLOT_PARAMS &aPlotOpt)
Plot one copper or technical layer.
wxCheckBox * m_plotPSNegativeOpt
#define PLOT_MIN_SCALE
Definition: pcbplot.h:54
bool GetDisableGerberMacros() const
MARKERS & Markers()
Definition: board.h:242
PLOTTER * StartPlotBoard(BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer, const wxString &aFullFileName, const wxString &aSheetDesc)
Open a new plotfile using the options (and especially the format) specified in the options and prepar...
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition: reporter.h:99
void SetCreateGerberJobFile(bool aCreate)
void SetOutputDirectory(const wxString &aDir)
void onRunDRC(wxCommandEvent &event) override
void SetMirror(bool aFlag)
wxButton * m_sdbSizer1OK
const wxString GetGerberProtelExtension(LAYER_NUM aLayer)
Definition: pcbplot.cpp:46
wxCheckBox * m_plotMirrorOpt
void SetTextMode(PLOT_TEXT_MODE aVal)
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:466
wxString GetAbbreviatedUnitsLabel(EDA_UNITS aUnit, EDA_DATA_TYPE aType)
Get the units string for a given units type.
Definition: base_units.cpp:424
void ShowDRCDialog(wxWindow *aParent)
Open a dialog and prompts the user, then if a test run button is clicked, runs the test(s) and create...
Definition: drc_tool.cpp:70
wxCheckBox * m_zoneFillCheck
void SetDrillMarksType(DrillMarksType aVal)
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:279
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:70
wxChoice * m_plotFormatOpt
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:820
virtual const PCB_PLOT_PARAMS & GetPlotSettings() const
Return the PCB_PLOT_PARAMS for the BOARD owned by this frame.
wxChoice * m_coordFormatCtrl
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
void SetDXFPlotUnits(DXF_UNITS aUnit)
void CreateDrillFile(wxCommandEvent &event) override
const wxString & GetFileName() const
Definition: board.h:228
Classes used to generate a Gerber job file in JSON.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:589
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
wxStaticBoxSizer * m_SizerDXF_options
double GetScale() const
UNIT_BINDER m_trackWidthCorrection
Definition: dialog_plot.h:83
void SetA4Output(int aForce)
bool GetUseGerberX2format() const
double m_XScaleAdjust
Definition: dialog_plot.h:71
wxButton * m_sdbSizer1Apply
wxTextCtrl * m_fineAdjustYCtrl
wxCheckBox * m_DXF_plotModeOpt
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition: project.cpp:269
This file contains miscellaneous commonly used macros and functions.
bool GetMirror() const
void SetPlotValue(bool aFlag)
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:119
wxBoxSizer * m_SizerSolderMaskAlert
Board plot function definition file.
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
wxCheckBox * m_plotSheetRef
virtual bool EndPlot()=0
void SetPlotFrameRef(bool aFlag)
void SetPlotFormat(wxCommandEvent &event) override
void Plot(wxCommandEvent &event) override
wxTextCtrl * m_fineAdjustXCtrl
Class DIALOG_PLOT_BASE.
void SetDisableGerberMacros(bool aDisable)
bool GetA4Output() const
Handle actions specific to filling copper zones.
int GetGerberPrecision() const
wxSpinCtrl * m_svgPrecsision
GERBER_JOBFILE_WRITER is a class used to create Gerber job file a Gerber job file stores info to make...
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:502
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString)
PLOT_FORMAT GetFormat() const
PCB_EDIT_FRAME * m_parent
Definition: dialog_plot.h:69
int m_widthAdjustMaxValue
Definition: dialog_plot.h:80
bool IsSameAs(const PCB_PLOT_PARAMS &aPcbPlotParams) const
Compare current settings to aPcbPlotParams, including not saved parameters in brd file.
bool GetUseGerberProtelExtensions() const
void SetColorSettings(COLOR_SETTINGS *aSettings)
PLOT_FORMAT getPlotFormat()
unsigned GetSvgPrecision() const
PLOT_FORMAT
The set of supported output plot formats.
Definition: plotter.h:67
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
void onBoardSetup(wxHyperlinkEvent &aEvent) override
static bool setDouble(double *aResult, double aValue, double aMin, double aMax)
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.
Definition: common.cpp:307
#define PLOT_MAX_SCALE
Definition: pcbplot.h:55
bool GetIncludeGerberNetlistInfo() const
int m_PSWidthAdjust
Definition: dialog_plot.h:75
T * GetAppSettings(bool aLoadNow=true)
Returns a handle to the a given settings by type If the settings have already been loaded,...
const std::string GerberJobFileExtension
Definition of file extensions used in Kicad.
PLOT_TEXT_MODE GetTextMode() const
wxCheckBox * m_forcePSA4OutputOpt
void OnPopUpLayers(wxCommandEvent &event) override
void SetSubtractMaskFromSilk(bool aSubtract)
void AddGbrFile(PCB_LAYER_ID aLayer, wxString &aFilename)
add a gerber file name and type in job file list
#define _(s)
void setPlotModeChoiceSelection(OUTLINE_MODE aPlotMode)
Definition: dialog_plot.h:64
void SetUseGerberX2format(bool aUse)
virtual void SetPlotSettings(const PCB_PLOT_PARAMS &aSettings)
void OnSetScaleOpt(wxCommandEvent &event) override
wxStaticBoxSizer * m_GerberOptionsSizer
wxCheckBox * m_useGerberNetAttributes
wxCheckBox * m_disableApertMacros
wxChoice * m_DXF_plotUnits
void SetFormat(PLOT_FORMAT aFormat)
int m_widthAdjustMinValue
Definition: dialog_plot.h:79
wxCheckBox * m_generateGerberJobFile
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
Parameters and options when plotting/printing a board.
wxTextCtrl * m_outputDirectoryName
void SetPlotInvisibleText(bool aFlag)
void SetScale(double aVal)
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:463
wxCheckBox * m_DXF_plotTextStrokeFontOpt
void SetPlotMode(OUTLINE_MODE aPlotMode)
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:787
PCB_PLOT_PARAMS m_plotOpts
Definition: dialog_plot.h:87
void SetNegative(bool aFlag)
bool GetPlotValue() const
void SetSvgPrecision(unsigned aPrecision, bool aUseInch)
wxString GetOutputDirectory() const
void SetFineScaleAdjustX(double aVal)
wxChoice * m_scaleOpt
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void BuildPlotFileName(wxFileName *aFilename, const wxString &aOutputDir, const wxString &aSuffix, const wxString &aExtension)
Complete a plot filename.
Definition: pcbplot.cpp:372
void reInitDialog()
wxCheckBox * m_plotModuleRefOpt
COLOR_SETTINGS * GetColorSettings(const wxString &aName="user")
Retrieves a color settings object that applications can read colors from.
bool SetHPGLPenDiameter(double aValue)
wxString m_DRCWarningTemplate
Definition: dialog_plot.h:85
Base plotter engine class.
Definition: plotter.h:121
wxBoxSizer * m_sizerButtons
wxCheckBox * m_subtractMaskFromSilk
bool GetSketchPadsOnFabLayers() const
void init_Dialog()
Definition: dialog_plot.cpp:80
wxCheckBox * m_plotNoViaOnMaskOpt
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:156
wxCheckBox * m_plotModuleValueOpt
bool GetPlotViaOnMaskLayer() const
wxChoice * m_drillShapeOpt
see class PGM_BASE
void applyPlotSettings()
void SetWidthAdjust(int aVal)
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
bool GetSubtractMaskFromSilk() const
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:64
static bool setInt(int *aResult, int aValue, int aMin, int aMax)
virtual void SetValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
wxCheckBox * m_plotInvisibleText
double GetHPGLPenDiameter() const
wxCheckBox * m_sketchPadsOnFabLayers
The main frame for Pcbnew.
PCBNEW_SETTINGS * GetPcbNewSettings() const
#define IU_PER_MILS
Definition: plotter.cpp:136
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:73
wxCheckBox * m_useAuxOriginCheckBox
DIALOG_PLOT m_Plot
bool GetPlotInvisibleText() const
void SetAutoScale(bool aFlag)
void SetFineScaleAdjustY(double aVal)
wxChoice * m_plotModeOpt
virtual long long int GetValue()
Return the current value in Internal Units.
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:204
int GetScaleSelection() const
DXF_UNITS GetDXFPlotUnits() const
UNIT_BINDER m_defaultPenSize
Definition: dialog_plot.h:82
void OnRightClick(wxMouseEvent &event) override
bool GetSvgUseInch() const
wxBitmapButton * m_browseButton
wxBoxSizer * m_MainSizer
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
bool GetNegative() const
wxCheckBox * m_useGerberX2Format
wxStaticBoxSizer * m_svgOptionsSizer
BOARD * GetBoard() const
bool GetUseAuxOrigin() const
wxCheckListBox * m_layerCheckListBox
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition: drc_tool.cpp:121
void SetFileName(const wxString &aReportFileName)
wxStaticBoxSizer * m_PSOptionsSizer
LSET GetLayerSelection() const
LSEQ UIOrder() const
Definition: lset.cpp:895
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:299
DrillMarksType GetDrillMarksType() const
wxBoxSizer * m_PlotOptionsSizer
bool GetPlotReference() const
DIALOG_PLOT(PCB_EDIT_FRAME *parent)
Definition: dialog_plot.cpp:53
#define DLG_WINDOW_NAME
wxStaticText * m_DRCExclusionsWarning
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
bool GetExcludeEdgeLayer() const
void SetSketchPadsOnFabLayers(bool aFlag)
Container for design settings for a BOARD object.
wxString m_ColorTheme
Active color theme name.
Definition: app_settings.h:184