KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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#include "dialog_plot.h"
25
26#include <wx/bmpbuttn.h>
27#include <wx/clntdata.h>
28#include <wx/dirdlg.h>
29#include <wx/msgdlg.h>
30#include <wx/rearrangectrl.h>
31
32#include <plotters/plotter.h>
33#include <confirm.h>
34#include <pcb_edit_frame.h>
36#include <pcbplot.h>
37#include <pgm_base.h>
39#include <reporter.h>
41#include <layer_ids.h>
42#include <bitmaps.h>
43#include <dialog_gendrill.h>
44#include <string_utils.h>
48#include <tool/tool_manager.h>
50#include <tools/drc_tool.h>
51#include <math/util.h> // for KiROUND
52#include <macros.h>
61#include <pcb_plotter.h>
62
63
65
66
67static double selectionToScale( int selection )
68{
69 switch( selection )
70 {
71 default: return 1.0;
72 case 0: return 0.0;
73 case 2: return 1.5;
74 case 3: return 2.0;
75 case 4: return 3.0;
76 }
77}
78
79
83class PCB_LAYER_ID_CLIENT_DATA : public wxClientData
84{
85public:
89
91 m_id( aId )
92 { }
93
94 void SetData( PCB_LAYER_ID aId ) { m_id = aId; }
95 PCB_LAYER_ID Layer() const { return m_id; }
96
97private:
99};
100
101
102PCB_LAYER_ID_CLIENT_DATA* getLayerClientData( const wxRearrangeList* aList, int aIdx )
103{
104 return static_cast<PCB_LAYER_ID_CLIENT_DATA*>( aList->GetClientObject( aIdx ) );
105}
106
107
109 : DIALOG_PLOT( aEditFrame, aEditFrame )
110{
111}
112
113
114DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent, JOB_EXPORT_PCB_PLOT* aJob ) :
115 DIALOG_PLOT_BASE( aParent ),
116 m_editFrame( aEditFrame ),
118 m_job( aJob )
119{
120 BOARD* board = m_editFrame->GetBoard();
121
123
124 SetName( DLG_WINDOW_NAME );
126
127 if( m_job )
128 {
129 SetTitle( aJob->GetSettingsDialogTitle() );
130
132 m_messagesPanel->Hide();
133
134 m_browseButton->Hide();
135 m_openDirButton->Hide();
136 m_staticTextPlotFmt->Hide();
137 m_plotFormatOpt->Hide();
138 m_buttonDRC->Hide();
140 m_sdbSizer1Apply->Hide();
141 m_zoneFillCheck->SetLabel( _( "Refill zones before plotting" ) );
142 }
143 else
144 {
145 m_plotOpts = m_editFrame->GetPlotSettings();
146 m_messagesPanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
147 }
148
149 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
150 // non-job versions.
151 m_hash_key = TO_UTF8( GetTitle() );
152
153 m_variantChoiceCtrl->Append( board->GetVariantNamesForUI() );
154 m_variantChoiceCtrl->SetSelection( 0 );
155
156 int order = 0;
157 wxArrayInt plotAllLayersOrder;
158 wxArrayString plotAllLayersChoicesStrings;
159 std::vector<PCB_LAYER_ID> layersIdChoiceList;
160 int textWidth = 0;
161
162 for( PCB_LAYER_ID layer : board->GetEnabledLayers().SeqStackupForPlotting() )
163 {
164 wxString layerName = board->GetLayerName( layer );
165
166 // wxCOL_WIDTH_AUTOSIZE doesn't work on all platforms, so we calculate width here
167 textWidth = std::max( textWidth, KIUI::GetTextSize( layerName, m_layerCheckListBox ).x );
168
169 plotAllLayersChoicesStrings.Add( layerName );
170 layersIdChoiceList.push_back( layer );
171
172 if( alg::contains( m_plotOpts.GetPlotOnAllLayersSequence(), layer ) )
173 plotAllLayersOrder.push_back( order );
174 else
175 plotAllLayersOrder.push_back( ~order );
176
177 order += 1;
178 }
179
180 int checkColSize = 22;
181 int layerColSize = textWidth + 15;
182
183#ifdef __WXMAC__
184 // TODO: something in wxWidgets 3.1.x pads checkbox columns with extra space. (It used to
185 // also be that the width of the column would get set too wide (to 30), but that's patched in
186 // our local wxWidgets fork.)
187 checkColSize += 30;
188#endif
189
190 m_layerCheckListBox->SetMinClientSize( wxSize( checkColSize + layerColSize,
191 m_layerCheckListBox->GetMinClientSize().y ) );
192
193 wxStaticBox* allLayersLabel = new wxStaticBox( this, wxID_ANY, _( "Plot on All Layers" ) );
194 wxStaticBoxSizer* sbSizer = new wxStaticBoxSizer( allLayersLabel, wxVERTICAL );
195
196 m_plotAllLayersList = new wxRearrangeList( sbSizer->GetStaticBox(), wxID_ANY,
197 wxDefaultPosition, wxDefaultSize,
198 plotAllLayersOrder, plotAllLayersChoicesStrings, 0 );
199
200 m_plotAllLayersList->SetMinClientSize( wxSize( checkColSize + layerColSize,
201 m_plotAllLayersList->GetMinClientSize().y ) );
202
203 // Attach the LAYER_ID to each item in m_plotAllLayersList
204 // plotAllLayersChoicesStrings and layersIdChoiceList are in the same order,
205 // but m_plotAllLayersList has these strings in a different order
206 for( size_t idx = 0; idx < layersIdChoiceList.size(); idx++ )
207 {
208 wxString& txt = plotAllLayersChoicesStrings[idx];
209 int list_idx = m_plotAllLayersList->FindString( txt, true );
210
211 PCB_LAYER_ID layer_id = layersIdChoiceList[idx];
212 m_plotAllLayersList->SetClientObject( list_idx, new PCB_LAYER_ID_CLIENT_DATA( layer_id ) );
213 }
214
215 sbSizer->Add( m_plotAllLayersList, 1, wxALL | wxEXPAND | wxFIXED_MINSIZE, 3 );
216
217 wxBoxSizer* bButtonSizer;
218 bButtonSizer = new wxBoxSizer( wxHORIZONTAL );
219
220 m_bpMoveUp = new STD_BITMAP_BUTTON( sbSizer->GetStaticBox(), wxID_ANY, wxNullBitmap,
221 wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW | 0 );
222 m_bpMoveUp->SetToolTip( _( "Move current selection up" ) );
224
225 bButtonSizer->Add( m_bpMoveUp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3 );
226
227 m_bpMoveDown = new STD_BITMAP_BUTTON( sbSizer->GetStaticBox(), wxID_ANY, wxNullBitmap,
228 wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW | 0 );
229 m_bpMoveDown->SetToolTip( _( "Move current selection down" ) );
231
232 bButtonSizer->Add( m_bpMoveDown, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5 );
233
234 sbSizer->Add( bButtonSizer, 0, wxALL | wxEXPAND, 3 );
235
236 bmiddleSizer->Insert( 1, sbSizer, 1, wxALL | wxEXPAND, 5 );
237
240
241 if( m_job )
242 {
244 }
245 else
246 {
247 SetupStandardButtons( { { wxID_OK, _( "Plot" ) },
248 { wxID_APPLY, _( "Generate Drill Files..." ) },
249 { wxID_CANCEL, _( "Close" ) } } );
250 }
251
252 GetSizer()->Fit( this );
253 GetSizer()->SetSizeHints( this );
254
255 m_bpMoveUp->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_PLOT::onPlotAllListMoveUp, this );
256 m_bpMoveDown->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_PLOT::onPlotAllListMoveDown, this );
257
258 m_layerCheckListBox->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( DIALOG_PLOT::OnRightClickLayers ),
259 nullptr, this );
260
261 m_plotAllLayersList->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( DIALOG_PLOT::OnRightClickAllLayers ),
262 nullptr, this );
263}
264
265
267{
268 s_lastAllLayersOrder.clear();
269
270 for( int ii = 0; ii < (int) m_plotAllLayersList->GetCount(); ++ii )
272
273 m_bpMoveDown->Unbind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_PLOT::onPlotAllListMoveDown, this );
274 m_bpMoveUp->Unbind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_PLOT::onPlotAllListMoveUp, this );
275}
276
277
279{
280 BOARD* board = m_editFrame->GetBoard();
281 wxFileName fileName;
282
283 PROJECT_FILE& projectFile = m_editFrame->Prj().GetProjectFile();
284
285 // Could devote a PlotOrder() function in place of UIOrder().
287
288 // Select the current board variant in the variant choice
289 if( m_job )
290 {
291 if( !m_job->m_variant.IsEmpty() )
292 {
293 int idx = m_variantChoiceCtrl->FindString( m_job->m_variant );
294
295 if( idx != wxNOT_FOUND )
296 m_variantChoiceCtrl->SetSelection( idx );
297 }
298 }
299 else
300 {
301 wxString currentVariant = board->GetCurrentVariant();
302
303 if( !currentVariant.IsEmpty() )
304 {
305 int idx = m_variantChoiceCtrl->FindString( currentVariant );
306
307 if( idx != wxNOT_FOUND )
308 m_variantChoiceCtrl->SetSelection( idx );
309 }
310 }
311
312 if( !m_job && !projectFile.m_PcbLastPath[ LAST_PATH_PLOT ].IsEmpty() )
313 m_plotOpts.SetOutputDirectory( projectFile.m_PcbLastPath[ LAST_PATH_PLOT ] );
314
315 if( m_job
316 && !( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::POST
317 && static_cast<JOB_EXPORT_PCB_PS*>( m_job )->m_useGlobalSettings ) )
318 {
319 // When we are using a job we get the PS adjust values from the plot options
320 // The exception is when this is a fresh job and we want to get the global values as defaults
322 m_plotOpts.GetFineScaleAdjustX() ) );
323
325 m_plotOpts.GetFineScaleAdjustY() ) );
326 m_trackWidthCorrection.SetValue( m_plotOpts.GetWidthAdjust() );
327 m_zoneFillCheck->SetValue( m_job->m_checkZonesBeforePlot );
328 }
329
330 // The reasonable width correction value must be in a range of
331 // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
332 m_widthAdjustMinValue = -( board->GetDesignSettings().m_TrackMinWidth - 1 );
334
335 switch( m_plotOpts.GetFormat() )
336 {
337 default:
338 case PLOT_FORMAT::GERBER: m_plotFormatOpt->SetSelection( 0 ); break;
339 case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 1 ); break;
340 case PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
341 case PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
342 case PLOT_FORMAT::HPGL: /* no longer supported */ break;
343 case PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 4 ); break;
344 case PLOT_FORMAT::PNG: m_plotFormatOpt->SetSelection( 5 ); break;
345 }
346
347 m_plotPSNegativeOpt->SetValue( m_plotOpts.GetNegative() );
348 m_forcePSA4OutputOpt->SetValue( m_plotOpts.GetA4Output() );
349
350 // Populate the check list box by all enabled layers names.
351 for( PCB_LAYER_ID layer : m_layerList )
352 {
353 int checkIndex = m_layerCheckListBox->Append( board->GetLayerName( layer ) );
354
355 if( m_plotOpts.GetLayerSelection()[layer] )
356 m_layerCheckListBox->Check( checkIndex );
357 }
358
360
361 // Option for disabling Gerber Aperture Macro (for broken Gerber readers)
362 m_disableApertMacros->SetValue( m_plotOpts.GetDisableGerberMacros() );
363
364 // Option for using proper Gerber extensions. Note also Protel extensions are
365 // a broken feature. However, for now, we need to handle it.
366 m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberProtelExtensions() );
367
368 // Option for including Gerber attributes, from Gerber X2 format, in the output
369 // In X1 format, they will be added as comments
370 m_useGerberX2Format->SetValue( m_plotOpts.GetUseGerberX2format() );
371
372 // Option for including Gerber netlist info (from Gerber X2 format) in the output
373 m_useGerberNetAttributes->SetValue( m_plotOpts.GetIncludeGerberNetlistInfo() );
374
375 // Option to generate a Gerber job file
376 m_generateGerberJobFile->SetValue( m_plotOpts.GetCreateGerberJobFile() );
377
378 // Gerber precision for coordinates
379 m_coordFormatCtrl->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 );
380
381 // SVG precision and units for coordinates
382 m_svgPrecsision->SetValue( m_plotOpts.GetSvgPrecision() );
383 m_SVG_fitPageToBoard->SetValue( m_plotOpts.GetSvgFitPagetoBoard() );
384
385 // PNG options
386 m_pngDPI->SetValue( m_plotOpts.GetPngDPI() );
387 m_pngAntialias->SetValue( m_plotOpts.GetPngAntialias() );
388
389 m_sketchPadsOnFabLayers->SetValue( m_plotOpts.GetSketchPadsOnFabLayers() );
390 m_plotPadNumbers->SetValue( m_plotOpts.GetPlotPadNumbers() );
391 m_plotPadNumbers->Enable( m_plotOpts.GetSketchPadsOnFabLayers() );
392
393 m_plotDNP->SetValue( m_plotOpts.GetHideDNPFPsOnFabLayers()
394 || m_plotOpts.GetSketchDNPFPsOnFabLayers()
395 || m_plotOpts.GetCrossoutDNPFPsOnFabLayers() );
396
397 if( m_plotDNP->GetValue() )
398 {
399 if( m_plotOpts.GetHideDNPFPsOnFabLayers() )
400 m_hideDNP->SetValue( true );
401 else
402 m_crossoutDNP->SetValue( true );
403 }
404
405 m_hideDNP->Enable( m_plotDNP->GetValue() );
406 m_crossoutDNP->Enable( m_plotDNP->GetValue() );
407
408 m_subtractMaskFromSilk->SetValue( m_plotOpts.GetSubtractMaskFromSilk() );
409
410 m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
411
412 m_plotSheetRef->SetValue( m_plotOpts.GetPlotFrameRef() );
413
414 // Options to plot pads and vias holes
415 m_drillShapeOpt->SetSelection( (int) m_plotOpts.GetDrillMarksType() );
416
417 // Scale option
418 m_scaleOpt->SetSelection( m_plotOpts.GetScaleSelection() );
419
420 // DXF outline mode
421 m_DXF_plotModeOpt->SetValue( m_plotOpts.GetDXFPlotPolygonMode() );
422
423 // DXF text mode
425
426 // DXF units selection
427 m_DXF_plotUnits->SetSelection( m_plotOpts.GetDXFPlotUnits() == DXF_UNITS::INCH ? 0 : 1 );
428
429 // Plot mirror option
430 m_plotMirrorOpt->SetValue( m_plotOpts.GetMirror() );
431
432 // Black and white plotting
433 m_SVGColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
434 m_PDFColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
435 m_frontFPPropertyPopups->SetValue( m_plotOpts.m_PDFFrontFPPropertyPopups );
436 m_backFPPropertyPopups->SetValue( m_plotOpts.m_PDFBackFPPropertyPopups );
437 m_pdfMetadata->SetValue( m_plotOpts.m_PDFMetadata );
438 m_pdfSingle->SetValue( m_plotOpts.m_PDFSingle );
439 m_pdfBackgroundColorSwatch->SetSwatchColor( m_plotOpts.m_PDFBackgroundColor, false );
441
442 // Initialize a few other parameters, which can also be modified
443 // from the drill dialog
444 reInitDialog();
445
446 // Update options values:
447 wxCommandEvent cmd_event;
448 SetPlotFormat( cmd_event );
449
450 return true;
451}
452
453
455{
457 {
458 JOB_EXPORT_PCB_GERBERS* gJob = static_cast<JOB_EXPORT_PCB_GERBERS*>( m_job );
459 gJob->m_disableApertureMacros = m_plotOpts.GetDisableGerberMacros();
460 gJob->m_useProtelFileExtension = m_plotOpts.GetUseGerberProtelExtensions();
461 gJob->m_useX2Format = m_plotOpts.GetUseGerberX2format();
462 gJob->m_includeNetlistAttributes = m_plotOpts.GetIncludeGerberNetlistInfo();
463 gJob->m_createJobsFile = m_plotOpts.GetCreateGerberJobFile();
464 gJob->m_precision = m_plotOpts.GetGerberPrecision();
465 gJob->m_useBoardPlotParams = false;
466 }
467 else
468 {
469 m_job->m_scale = selectionToScale( m_plotOpts.GetScaleSelection() );
470 }
471
472 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG )
473 {
474 JOB_EXPORT_PCB_SVG* svgJob = static_cast<JOB_EXPORT_PCB_SVG*>( m_job );
475 svgJob->m_precision = m_plotOpts.GetSvgPrecision();
477 svgJob->m_fitPageToBoard = m_plotOpts.GetSvgFitPagetoBoard();
478 }
479
480 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::DXF )
481 {
482 JOB_EXPORT_PCB_DXF* dxfJob = static_cast<JOB_EXPORT_PCB_DXF*>( m_job );
486 dxfJob->m_polygonMode = m_plotOpts.GetDXFPlotPolygonMode();
487 dxfJob->m_useKiCadFont = m_plotOpts.GetTextMode() != PLOT_TEXT_MODE::NATIVE;
488 dxfJob->m_genMode = m_plotOpts.GetDXFMultiLayeredExportOption() ? JOB_EXPORT_PCB_DXF::GEN_MODE::SINGLE
490 }
491
492 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::POST )
493 {
494 JOB_EXPORT_PCB_PS* psJob = static_cast<JOB_EXPORT_PCB_PS*>( m_job );
496 psJob->m_XScaleAdjust = m_plotOpts.GetFineScaleAdjustX();
497 psJob->m_YScaleAdjust = m_plotOpts.GetFineScaleAdjustY();
498 psJob->m_trackWidthCorrection = pcbIUScale.IUTomm( m_plotOpts.GetWidthAdjust() );
499 psJob->m_forceA4 = m_plotOpts.GetA4Output();
500 // For a fresh job we got the adjusts from the global pcbnew settings
501 // After the user confirmed and/or changed them we stop using the global adjusts
502 psJob->m_useGlobalSettings = false;
503 }
504
505 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::PDF )
506 {
507 JOB_EXPORT_PCB_PDF* pdfJob = static_cast<JOB_EXPORT_PCB_PDF*>( m_job );
508 pdfJob->m_pdfFrontFPPropertyPopups = m_plotOpts.m_PDFFrontFPPropertyPopups;
509 pdfJob->m_pdfBackFPPropertyPopups = m_plotOpts.m_PDFBackFPPropertyPopups;
510 pdfJob->m_pdfMetadata = m_plotOpts.m_PDFMetadata;
511 pdfJob->m_pdfSingle = m_plotOpts.m_PDFSingle;
512 pdfJob->m_pdfBackgroundColor = m_plotOpts.m_PDFBackgroundColor.ToCSSString();
513
514 // we need to embed this for the cli deprecation fix
515 if( pdfJob->m_pdfSingle )
516 {
518 }
519 else
520 {
522 }
523 }
524
525 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::PNG )
526 {
527 JOB_EXPORT_PCB_PNG* pngJob = static_cast<JOB_EXPORT_PCB_PNG*>( m_job );
528 pngJob->m_dpi = m_plotOpts.GetPngDPI();
529 pngJob->m_antialias = m_plotOpts.GetPngAntialias();
530 }
531
532 m_job->m_subtractSolderMaskFromSilk = m_plotOpts.GetSubtractMaskFromSilk();
533 m_job->m_useDrillOrigin = m_plotOpts.GetUseAuxOrigin();
534 m_job->m_crossoutDNPFPsOnFabLayers = m_plotOpts.GetCrossoutDNPFPsOnFabLayers();
535 m_job->m_hideDNPFPsOnFabLayers = m_plotOpts.GetHideDNPFPsOnFabLayers();
536 m_job->m_sketchDNPFPsOnFabLayers = m_plotOpts.GetSketchDNPFPsOnFabLayers();
537 m_job->m_sketchPadsOnFabLayers = m_plotOpts.GetSketchPadsOnFabLayers();
538
539 m_job->m_plotDrawingSheet = m_plotOpts.GetPlotFrameRef();
540 m_job->m_plotPadNumbers = m_plotOpts.GetPlotPadNumbers();
541
542 m_job->m_blackAndWhite = m_plotOpts.GetBlackAndWhite();
543 m_job->m_mirror = m_plotOpts.GetMirror();
544 m_job->m_negative = m_plotOpts.GetNegative();
545 m_job->m_plotLayerSequence = m_plotOpts.GetLayerSelection().SeqStackupForPlotting();
546 m_job->m_plotOnAllLayersSequence = m_plotOpts.GetPlotOnAllLayersSequence();
547
548 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG ||
550 {
551 switch( m_plotOpts.GetDrillMarksType() )
552 {
553 case DRILL_MARKS::NO_DRILL_SHAPE: m_job->m_drillShapeOption = DRILL_MARKS::NO_DRILL_SHAPE; break;
555 default:
556 case DRILL_MARKS::FULL_DRILL_SHAPE: m_job->m_drillShapeOption = DRILL_MARKS::FULL_DRILL_SHAPE; break;
557 }
558 }
559
560 m_job->SetConfiguredOutputPath( m_plotOpts.GetOutputDirectory() );
561
562 // this exists outside plot opts because its usually globally saved
563 m_job->m_checkZonesBeforePlot = m_zoneFillCheck->GetValue();
564
565 m_job->m_variant = getSelectedVariant();
566}
567
568
570{
571 // after calling the Drill or DRC dialogs some parameters can be modified....
572
573 // Output directory
574 m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
575
576 // Origin of coordinates:
577 m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
578
579 int knownViolations = 0;
580 int exclusions = 0;
581
582 for( PCB_MARKER* marker : m_editFrame->GetBoard()->Markers() )
583 {
584 if( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION )
585 exclusions++;
586 else
587 knownViolations++;
588 }
589
590 if( !m_job && ( knownViolations || exclusions ) )
591 {
592 m_DRCExclusionsWarning->SetLabel( wxString::Format( m_DRCWarningTemplate, knownViolations,
593 exclusions ) );
595 }
596 else
597 {
599 }
600
601 BOARD* board = m_editFrame->GetBoard();
602 const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
603
605 ( brd_settings.m_SolderMaskExpansion || brd_settings.m_SolderMaskMinWidth ) )
606 {
608 }
609 else
610 {
612 }
613}
614
615
617{
618 wxString variant;
619 int selection = m_variantChoiceCtrl->GetSelection();
620
621 if( ( selection != 0 ) && ( selection != wxNOT_FOUND ) )
622 variant = m_variantChoiceCtrl->GetString( selection );
623
624 return variant;
625}
626
627
629{
630 auto findLayer =
631 [&]( wxRearrangeList* aList, PCB_LAYER_ID aLayer ) -> int
632 {
633 for( int ii = 0; ii < (int) aList->GetCount(); ++ii )
634 {
635 if( getLayerClientData( aList, ii )->Layer() == aLayer )
636 return ii;
637 }
638
639 return -1;
640 };
641
642 int idx = 0;
643
644 for( PCB_LAYER_ID layer : aSeq )
645 {
646 int currentPos = findLayer( m_plotAllLayersList, layer );
647
648 while( currentPos > idx )
649 {
650 m_plotAllLayersList->Select( currentPos );
651 m_plotAllLayersList->MoveCurrentUp();
652 currentPos--;
653 }
654
655 idx++;
656 }
657}
658
659
660#define ID_LAYER_FAB 13001
661#define ID_SELECT_COPPER_LAYERS 13002
662#define ID_DESELECT_COPPER_LAYERS 13003
663#define ID_SELECT_ALL_LAYERS 13004
664#define ID_DESELECT_ALL_LAYERS 13005
665#define ID_STACKUP_ORDER 13006
666
667
668// A helper function to show a popup menu, when the dialog is right clicked.
669void DIALOG_PLOT::OnRightClickLayers( wxMouseEvent& event )
670{
671 // Build a list of layers for usual fabrication: copper layers + tech layers without courtyard
672 LSET fab_layer_set = ( LSET::AllCuMask() | LSET::AllTechMask() ) & ~LSET( { B_CrtYd, F_CrtYd } );
673
674 wxMenu menu;
675 menu.Append( new wxMenuItem( &menu, ID_LAYER_FAB, _( "Select Fab Layers" ) ) );
676
677 menu.AppendSeparator();
678 menu.Append( new wxMenuItem( &menu, ID_SELECT_COPPER_LAYERS, _( "Select All Copper Layers" ) ) );
679 menu.Append( new wxMenuItem( &menu, ID_DESELECT_COPPER_LAYERS, _( "Deselect All Copper Layers" ) ) );
680
681 menu.AppendSeparator();
682 menu.Append( new wxMenuItem( &menu, ID_SELECT_ALL_LAYERS, _( "Select All Layers" ) ) );
683 menu.Append( new wxMenuItem( &menu, ID_DESELECT_ALL_LAYERS, _( "Deselect All Layers" ) ) );
684
685 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
686 [&]( wxCommandEvent& aCmd )
687 {
688 switch( aCmd.GetId() )
689 {
690 case ID_LAYER_FAB: // Select layers usually needed to build a board
691 {
692 for( unsigned i = 0; i < m_layerList.size(); i++ )
693 {
694 LSET layermask( { m_layerList[ i ] } );
695
696 if( ( layermask & fab_layer_set ).any() )
697 m_layerCheckListBox->Check( i, true );
698 else
699 m_layerCheckListBox->Check( i, false );
700 }
701
702 break;
703 }
704
706 for( unsigned i = 0; i < m_layerList.size(); i++ )
707 {
708 if( IsCopperLayer( m_layerList[i] ) )
709 m_layerCheckListBox->Check( i, true );
710 }
711
712 break;
713
715 for( unsigned i = 0; i < m_layerList.size(); i++ )
716 {
717 if( IsCopperLayer( m_layerList[i] ) )
718 m_layerCheckListBox->Check( i, false );
719 }
720
721 break;
722
724 for( unsigned i = 0; i < m_layerList.size(); i++ )
725 m_layerCheckListBox->Check( i, true );
726
727 break;
728
730 for( unsigned i = 0; i < m_layerList.size(); i++ )
731 m_layerCheckListBox->Check( i, false );
732
733 break;
734
735 default:
736 aCmd.Skip();
737 }
738 } );
739
740 PopupMenu( &menu );
741}
742
743
744void DIALOG_PLOT::OnRightClickAllLayers( wxMouseEvent& event )
745{
746 wxMenu menu;
747 menu.Append( new wxMenuItem( &menu, ID_SELECT_ALL_LAYERS, _( "Select All Layers" ) ) );
748 menu.Append( new wxMenuItem( &menu, ID_DESELECT_ALL_LAYERS, _( "Deselect All Layers" ) ) );
749
750 menu.AppendSeparator();
751 menu.Append( new wxMenuItem( &menu, ID_STACKUP_ORDER, _( "Order as Board Stackup" ) ) );
752
753 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
754 [&]( wxCommandEvent& aCmd )
755 {
756 switch( aCmd.GetId() )
757 {
759 for( unsigned i = 0; i < m_plotAllLayersList->GetCount(); i++ )
760 m_plotAllLayersList->Check( i, true );
761
762 break;
763
765 for( unsigned i = 0; i < m_plotAllLayersList->GetCount(); i++ )
766 m_plotAllLayersList->Check( i, false );
767
768 break;
769
770 case ID_STACKUP_ORDER:
771 {
772 LSEQ stackup = m_editFrame->GetBoard()->GetEnabledLayers().SeqStackupForPlotting();
773 arrangeAllLayersList( stackup );
774 m_plotAllLayersList->Select( -1 );
775 break;
776 }
777
778 default:
779 aCmd.Skip();
780 }
781 } );
782
783 PopupMenu( &menu );
784}
785
786
787void DIALOG_PLOT::CreateDrillFile( wxCommandEvent& event )
788{
789 // Be sure drill file use the same settings (axis option, plot directory) as plot files:
791
792 DIALOG_GENDRILL dlg( m_editFrame, this );
793 dlg.ShowModal();
794
795 // a few plot settings can be modified: take them in account
796 m_plotOpts = m_editFrame->GetPlotSettings();
797 reInitDialog();
798}
799
800
801void DIALOG_PLOT::OnChangeDXFPlotMode( wxCommandEvent& event )
802{
803 // m_DXF_plotTextStrokeFontOpt is disabled if m_DXF_plotModeOpt is checked (plot in DXF
804 // polygon mode)
805 m_DXF_plotTextStrokeFontOpt->Enable( !m_DXF_plotModeOpt->GetValue() );
806
807 // if m_DXF_plotTextStrokeFontOpt option is disabled (plot DXF in polygon mode), force
808 // m_DXF_plotTextStrokeFontOpt to true to use Pcbnew stroke font
809 if( !m_DXF_plotTextStrokeFontOpt->IsEnabled() )
810 m_DXF_plotTextStrokeFontOpt->SetValue( true );
811}
812
813
815{
816 // Build the absolute path of current output directory to preselect it in the file browser.
817 std::function<bool( wxString* )> textResolver =
818 [&]( wxString* token ) -> bool
819 {
820 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
821 };
822
823 wxString path = m_outputDirectoryName->GetValue();
824 path = ExpandTextVars( path, &textResolver );
826 path = Prj().AbsolutePath( path );
827
828 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
829
830 if( dirDialog.ShowModal() == wxID_CANCEL )
831 return;
832
833 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
834
835 wxFileName fn( Prj().AbsolutePath( m_editFrame->GetBoard()->GetFileName() ) );
836 wxString defaultPath = fn.GetPathWithSep();
837 wxFileName relPathTest; // Used to test if we can make the path relative
838
839 relPathTest.Assign( dirDialog.GetPath() );
840
841 // Test if making the path relative is possible before asking the user if they want to do it
842 if( relPathTest.MakeRelativeTo( defaultPath ) )
843 {
844 if( IsOK( this, wxString::Format( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath ) ) )
845 dirName.MakeRelativeTo( defaultPath );
846 }
847
848 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
849}
850
851
853{
854 // plot format id's are ordered like displayed in m_plotFormatOpt
855 static const PLOT_FORMAT plotFmt[] = {
862
863 return plotFmt[m_plotFormatOpt->GetSelection()];
864}
865
866
867void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
868{
869 // this option exist only in DXF format:
871
872 // The alert message about non 0 solder mask min width and margin is shown
873 // only in gerber format and if min mask width or mask margin is not 0
874 BOARD* board = m_editFrame->GetBoard();
875 const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
876
878 && ( brd_settings.m_SolderMaskExpansion || brd_settings.m_SolderMaskMinWidth ) )
879 {
881 }
882 else
883 {
885 }
886
887 wxSizer* shownFormatSizer = nullptr;
888
889 switch( getPlotFormat() )
890 {
891 case PLOT_FORMAT::SVG:
892 case PLOT_FORMAT::PDF:
893 m_drillShapeOpt->Enable( true );
894 m_plotMirrorOpt->Enable( true );
895 m_useAuxOriginCheckBox->Enable( true );
896 m_scaleOpt->Enable( true );
897 m_fineAdjustXCtrl->Enable( false );
898 m_fineAdjustYCtrl->Enable( false );
899 m_trackWidthCorrection.Enable( false );
900 m_plotPSNegativeOpt->Enable( true );
901 m_forcePSA4OutputOpt->Enable( false );
902 m_forcePSA4OutputOpt->SetValue( false );
903
905 break;
906
908 m_drillShapeOpt->Enable( true );
909 m_plotMirrorOpt->Enable( true );
910 m_useAuxOriginCheckBox->Enable( false );
911 m_useAuxOriginCheckBox->SetValue( false );
912 m_scaleOpt->Enable( true );
913 m_fineAdjustXCtrl->Enable( true );
914 m_fineAdjustYCtrl->Enable( true );
915 m_trackWidthCorrection.Enable( true );
916 m_plotPSNegativeOpt->Enable( true );
917 m_forcePSA4OutputOpt->Enable( true );
918
919 shownFormatSizer = m_PSOptionsSizer;
920 break;
921
923 m_drillShapeOpt->Enable( false );
924 m_drillShapeOpt->SetSelection( 0 );
925 m_plotMirrorOpt->Enable( false );
926 m_plotMirrorOpt->SetValue( false );
927 m_useAuxOriginCheckBox->Enable( true );
928 m_scaleOpt->Enable( false );
929 m_scaleOpt->SetSelection( 1 );
930 m_fineAdjustXCtrl->Enable( false );
931 m_fineAdjustYCtrl->Enable( false );
932 m_trackWidthCorrection.Enable( false );
933 m_plotPSNegativeOpt->Enable( false );
934 m_plotPSNegativeOpt->SetValue( false );
935 m_forcePSA4OutputOpt->Enable( false );
936 m_forcePSA4OutputOpt->SetValue( false );
937
938 shownFormatSizer = m_GerberOptionsSizer;
939 break;
940
941 case PLOT_FORMAT::DXF:
942 m_drillShapeOpt->Enable( true );
943 m_plotMirrorOpt->Enable( false );
944 m_plotMirrorOpt->SetValue( false );
945 m_useAuxOriginCheckBox->Enable( true );
946 m_scaleOpt->Enable( true );
947 m_fineAdjustXCtrl->Enable( false );
948 m_fineAdjustYCtrl->Enable( false );
949 m_trackWidthCorrection.Enable( false );
950 m_plotPSNegativeOpt->Enable( false );
951 m_plotPSNegativeOpt->SetValue( false );
952 m_forcePSA4OutputOpt->Enable( false );
953 m_forcePSA4OutputOpt->SetValue( false );
954
955 shownFormatSizer = m_SizerDXF_options;
956 OnChangeDXFPlotMode( event );
957 break;
958
959 case PLOT_FORMAT::PNG:
960 m_drillShapeOpt->Enable( true );
961 m_plotMirrorOpt->Enable( true );
962 m_useAuxOriginCheckBox->Enable( true );
963 m_scaleOpt->Enable( true );
964 m_fineAdjustXCtrl->Enable( false );
965 m_fineAdjustYCtrl->Enable( false );
966 m_trackWidthCorrection.Enable( false );
967 m_plotPSNegativeOpt->Enable( true );
968 m_forcePSA4OutputOpt->Enable( false );
969 m_forcePSA4OutputOpt->SetValue( false );
970
971 shownFormatSizer = m_pngOptionsSizer;
972 break;
973
974 default:
977 break;
978 }
979
980 for( wxSizer* formatSizer : { m_GerberOptionsSizer, m_PSOptionsSizer, m_SizerDXF_options,
982 {
983 m_PlotOptionsSizer->Show( formatSizer, formatSizer == shownFormatSizer );
984 }
985
986 Layout();
987 m_MainSizer->SetSizeHints( this );
988}
989
990
991// A helper function to "clip" aValue between aMin and aMax and write result in * aResult
992// return false if clipped, true if aValue is just copied into * aResult
993static bool setDouble( double* aResult, double aValue, double aMin, double aMax )
994{
995 if( aValue < aMin )
996 {
997 *aResult = aMin;
998 return false;
999 }
1000 else if( aValue > aMax )
1001 {
1002 *aResult = aMax;
1003 return false;
1004 }
1005
1006 *aResult = aValue;
1007 return true;
1008}
1009
1010
1011static bool setInt( int* aResult, int aValue, int aMin, int aMax )
1012{
1013 if( aValue < aMin )
1014 {
1015 *aResult = aMin;
1016 return false;
1017 }
1018 else if( aValue > aMax )
1019 {
1020 *aResult = aMax;
1021 return false;
1022 }
1023
1024 *aResult = aValue;
1025 return true;
1026}
1027
1028
1030{
1031 REPORTER& reporter = m_messagesPanel->Reporter();
1032 PCB_PLOT_PARAMS tempOptions;
1033
1034 tempOptions.SetDashedLineDashRatio( m_plotOpts.GetDashedLineDashRatio() );
1035 tempOptions.SetDashedLineGapRatio( m_plotOpts.GetDashedLineGapRatio() );
1036
1037 tempOptions.SetSubtractMaskFromSilk( m_subtractMaskFromSilk->GetValue() );
1038 tempOptions.SetPlotFrameRef( m_plotSheetRef->GetValue() );
1039 tempOptions.SetSketchPadsOnFabLayers( m_sketchPadsOnFabLayers->GetValue() );
1040 tempOptions.SetPlotPadNumbers( m_plotPadNumbers->GetValue() );
1041 tempOptions.SetHideDNPFPsOnFabLayers( m_plotDNP->GetValue()
1042 && m_hideDNP->GetValue() );
1043 tempOptions.SetSketchDNPFPsOnFabLayers( m_plotDNP->GetValue()
1044 && m_crossoutDNP->GetValue() );
1045 tempOptions.SetCrossoutDNPFPsOnFabLayers( m_plotDNP->GetValue()
1046 && m_crossoutDNP->GetValue() );
1047 tempOptions.SetUseAuxOrigin( m_useAuxOriginCheckBox->GetValue() );
1048 tempOptions.SetScaleSelection( m_scaleOpt->GetSelection() );
1049
1050 int sel = m_drillShapeOpt->GetSelection();
1051 tempOptions.SetDrillMarksType( static_cast<DRILL_MARKS>( sel ) );
1052
1053 tempOptions.SetMirror( m_plotMirrorOpt->GetValue() );
1054 tempOptions.SetDXFPlotPolygonMode( m_DXF_plotModeOpt->GetValue() );
1055
1056 sel = m_DXF_plotUnits->GetSelection();
1057 tempOptions.SetDXFPlotUnits( sel == 0 ? DXF_UNITS::INCH : DXF_UNITS::MM );
1058
1059 if( !m_DXF_plotTextStrokeFontOpt->IsEnabled() ) // Currently, only DXF supports this option
1060 tempOptions.SetTextMode( PLOT_TEXT_MODE::DEFAULT );
1061 else
1064
1066
1068 {
1069 tempOptions.SetBlackAndWhite( m_SVGColorChoice->GetSelection() == 1 );
1070 }
1071 else if( getPlotFormat() == PLOT_FORMAT::PDF )
1072 {
1073 tempOptions.SetBlackAndWhite( m_PDFColorChoice->GetSelection() == 1 );
1074 tempOptions.m_PDFFrontFPPropertyPopups = m_frontFPPropertyPopups->GetValue();
1075 tempOptions.m_PDFBackFPPropertyPopups = m_backFPPropertyPopups->GetValue();
1076 tempOptions.m_PDFMetadata = m_pdfMetadata->GetValue();
1077 tempOptions.m_PDFSingle = m_pdfSingle->GetValue();
1078 tempOptions.m_PDFBackgroundColor = m_pdfBackgroundColorSwatch->GetSwatchColor();
1079 }
1080 else if( getPlotFormat() == PLOT_FORMAT::PNG )
1081 {
1082 // Match the CLI default; a dedicated UI control will be added with the next .fbp regen.
1083 tempOptions.SetBlackAndWhite( false );
1084 }
1085 else
1086 {
1087 tempOptions.SetBlackAndWhite( true );
1088 }
1089
1090 // Update settings from text fields. Rewrite values back to the fields,
1091 // since the values may have been constrained by the setters.
1092
1093 // X scale
1094 double tmpDouble;
1095 wxString msg = m_fineAdjustXCtrl->GetValue();
1096 msg.ToDouble( &tmpDouble );
1097
1099 {
1100 msg.Printf( wxT( "%f" ), m_XScaleAdjust );
1101 m_fineAdjustXCtrl->SetValue( msg );
1102 msg.Printf( _( "X scale constrained." ) );
1103 reporter.Report( msg, RPT_SEVERITY_INFO );
1104 }
1105
1106 // Y scale
1107 msg = m_fineAdjustYCtrl->GetValue();
1108 msg.ToDouble( &tmpDouble );
1109
1111 {
1112 msg.Printf( wxT( "%f" ), m_YScaleAdjust );
1113 m_fineAdjustYCtrl->SetValue( msg );
1114 msg.Printf( _( "Y scale constrained." ) );
1115 reporter.Report( msg, RPT_SEVERITY_INFO );
1116 }
1117
1118 // PS Width correction
1121 {
1123 msg.Printf( _( "Width correction constrained. The width correction value must be in the"
1124 " range of [%s; %s] for the current design rules." ),
1125 m_editFrame->StringFromValue( m_widthAdjustMinValue, true ),
1126 m_editFrame->StringFromValue( m_widthAdjustMaxValue, true ) );
1127 reporter.Report( msg, RPT_SEVERITY_WARNING );
1128 }
1129
1130 if( m_job )
1131 {
1132 // When using a job we store the adjusts in the plot options
1133 tempOptions.SetFineScaleAdjustX( m_XScaleAdjust );
1134 tempOptions.SetFineScaleAdjustY( m_YScaleAdjust );
1135 tempOptions.SetWidthAdjust( m_PSWidthAdjust );
1136 }
1137
1138 tempOptions.SetFormat( getPlotFormat() );
1139
1140 tempOptions.SetDisableGerberMacros( m_disableApertMacros->GetValue() );
1141 tempOptions.SetUseGerberProtelExtensions( m_useGerberExtensions->GetValue() );
1142 tempOptions.SetUseGerberX2format( m_useGerberX2Format->GetValue() );
1143 tempOptions.SetIncludeGerberNetlistInfo( m_useGerberNetAttributes->GetValue() );
1144 tempOptions.SetCreateGerberJobFile( m_generateGerberJobFile->GetValue() );
1145
1146 tempOptions.SetGerberPrecision( m_coordFormatCtrl->GetSelection() == 0 ? 5 : 6 );
1147 tempOptions.SetSvgPrecision( m_svgPrecsision->GetValue() );
1148 tempOptions.SetSvgFitPageToBoard( m_SVG_fitPageToBoard->GetValue() );
1149 tempOptions.SetPngDPI( m_pngDPI->GetValue() );
1150 tempOptions.SetPngAntialias( m_pngAntialias->GetValue() );
1151
1152 LSET selectedLayers;
1153
1154 for( unsigned i = 0; i < m_layerList.size(); i++ )
1155 {
1156 if( m_layerCheckListBox->IsChecked( i ) )
1157 selectedLayers.set( m_layerList[i] );
1158 }
1159
1160 // Get a list of copper layers that aren't being used by inverting enabled layers.
1161 LSET disabledCopperLayers = LSET::AllCuMask() & ~m_editFrame->GetBoard()->GetEnabledLayers();
1162
1163 // Add selected layers from plot on all layers list in order set by user.
1164 wxArrayInt plotOnAllLayers;
1165 LSEQ commonLayers;
1166
1167 if( m_plotAllLayersList->GetCheckedItems( plotOnAllLayers ) )
1168 {
1169 size_t count = plotOnAllLayers.GetCount();
1170
1171 for( size_t i = 0; i < count; i++ )
1172 {
1173 int index = plotOnAllLayers.Item( i );
1175
1176 commonLayers.push_back( client_layer );
1177 }
1178 }
1179
1180 tempOptions.SetPlotOnAllLayersSequence( commonLayers );
1181
1182 // Enable all of the disabled copper layers.
1183 // If someone enables more copper layers they will be selected by default.
1184 selectedLayers = selectedLayers | disabledCopperLayers;
1185 tempOptions.SetLayerSelection( selectedLayers );
1186
1187 tempOptions.SetNegative( m_plotPSNegativeOpt->GetValue() );
1188 tempOptions.SetA4Output( m_forcePSA4OutputOpt->GetValue() );
1189
1190 // Set output directory and replace backslashes with forward ones
1191 wxString dirStr;
1192 dirStr = m_outputDirectoryName->GetValue();
1193 dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
1194 tempOptions.SetOutputDirectory( dirStr );
1195 m_editFrame->Prj().GetProjectFile().m_PcbLastPath[ LAST_PATH_PLOT ] = dirStr;
1196
1197 if( !m_job && !m_plotOpts.IsSameAs( tempOptions ) )
1198 {
1199 m_editFrame->SetPlotSettings( tempOptions );
1200 m_editFrame->OnModify();
1201 m_plotOpts = tempOptions;
1202 }
1203 else
1204 {
1205 m_plotOpts = tempOptions;
1206 }
1207}
1208
1209
1210void DIALOG_PLOT::OnGerberX2Checked( wxCommandEvent& event )
1211{
1212 // Currently: do nothing
1213}
1214
1215
1216void DIALOG_PLOT::Plot( wxCommandEvent& event )
1217{
1218 if( m_job )
1219 {
1222 EndModal( wxID_OK );
1223 }
1224 else
1225 {
1226 BOARD* board = m_editFrame->GetBoard();
1227
1229
1231
1232 m_plotOpts.SetColorSettings( ::GetColorSettings( cfg ? cfg->m_ColorTheme : DEFAULT_THEME ) );
1233
1234 m_plotOpts.SetSketchPadLineWidth( board->GetDesignSettings().GetLineThickness( F_Fab ) );
1235
1236 // If no layer selected, we have nothing plotted.
1237 // Prompt user if it happens because he could think there is a bug in Pcbnew.
1238 if( !m_plotOpts.GetLayerSelection().any() )
1239 {
1240 DisplayError( this, _( "No layer selected, Nothing to plot" ) );
1241 return;
1242 }
1243
1244 // Create output directory if it does not exist (also transform it in absolute form).
1245 // Bail if it fails.
1246
1247 std::function<bool( wxString* )> textResolver =
1248 [&]( wxString* token ) -> bool
1249 {
1250 // Handles board->GetTitleBlock() *and* board->GetProject()
1251 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
1252 };
1253
1254 wxString path = m_plotOpts.GetOutputDirectory();
1255 path = ExpandTextVars( path, &textResolver );
1257
1258 wxFileName outputDir = wxFileName::DirName( path );
1259 wxString boardFilename = m_editFrame->GetBoard()->GetFileName();
1260 REPORTER& reporter = m_messagesPanel->Reporter();
1261
1262 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
1263 {
1264 wxString msg;
1265 msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
1266 DisplayError( this, msg );
1267 return;
1268 }
1269
1270 if( m_zoneFillCheck->GetValue() )
1271 m_editFrame->GetToolManager()->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( this );
1272
1273 m_plotOpts.SetAutoScale( false );
1274
1275 switch( m_plotOpts.GetScaleSelection() )
1276 {
1277 default: m_plotOpts.SetScale( 1 ); break;
1278 case 0: m_plotOpts.SetAutoScale( true ); break;
1279 case 2: m_plotOpts.SetScale( 1.5 ); break;
1280 case 3: m_plotOpts.SetScale( 2 ); break;
1281 case 4: m_plotOpts.SetScale( 3 ); break;
1282 }
1283
1284 /* If the scale factor edit controls are disabled or the scale value
1285 * is 0, don't adjust the base scale factor. This fixes a bug when
1286 * the default scale adjust is initialized to 0 and saved in program
1287 * settings resulting in a divide by zero fault.
1288 */
1290 {
1291 if( m_XScaleAdjust != 0.0 )
1292 m_plotOpts.SetFineScaleAdjustX( m_XScaleAdjust );
1293
1294 if( m_YScaleAdjust != 0.0 )
1295 m_plotOpts.SetFineScaleAdjustY( m_YScaleAdjust );
1296
1297 m_plotOpts.SetWidthAdjust( m_PSWidthAdjust );
1298 }
1299
1300 // Test for a reasonable scale value
1301 // XXX could this actually happen? isn't it constrained in the apply function?
1302 if( m_plotOpts.GetScale() < PLOT_MIN_SCALE )
1303 DisplayInfoMessage( this, _( "Warning: Scale option set to a very small value" ) );
1304
1305 if( m_plotOpts.GetScale() > PLOT_MAX_SCALE )
1306 DisplayInfoMessage( this, _( "Warning: Scale option set to a very large value" ) );
1307
1308
1309 // Save the current plot options in the board
1310 m_editFrame->SetPlotSettings( m_plotOpts );
1311
1312 wxString oldVariant = board->GetCurrentVariant();
1314
1315 PCB_PLOTTER pcbPlotter( m_editFrame->GetBoard(), &reporter, m_plotOpts );
1316
1317 LSEQ layersToPlot = m_plotOpts.GetLayerSelection().UIOrder();
1318
1319 wxArrayInt plotOnAllLayers;
1320 LSEQ commonLayers;
1321
1322 if( m_plotAllLayersList->GetCheckedItems( plotOnAllLayers ) )
1323 {
1324 size_t count = plotOnAllLayers.GetCount();
1325
1326 for( size_t i = 0; i < count; i++ )
1327 {
1328 int index = plotOnAllLayers.Item( i );
1330
1331 commonLayers.push_back( client_layer );
1332 }
1333 }
1334
1335 pcbPlotter.Plot( outputDir.GetPath(), layersToPlot, commonLayers, m_useGerberExtensions->GetValue() );
1336
1337 board->SetCurrentVariant( oldVariant );
1338 }
1339}
1340
1341
1342
1343void DIALOG_PLOT::onRunDRC( wxCommandEvent& event )
1344{
1345 PCB_EDIT_FRAME* parent = dynamic_cast<PCB_EDIT_FRAME*>( GetParent() );
1346
1347 if( parent )
1348 {
1349 DRC_TOOL* drcTool = parent->GetToolManager()->GetTool<DRC_TOOL>();
1350
1351 // First close an existing dialog if open
1352 // (low probability, but can happen)
1353 drcTool->DestroyDRCDialog();
1354
1355 // Open a new drc dialog, with the right parent frame, and in Modal Mode
1356 drcTool->ShowDRCDialog( this );
1357
1358 // Update DRC warnings on return to this dialog
1359 reInitDialog();
1360 }
1361}
1362
1363
1364void DIALOG_PLOT::onOpenOutputDirectory( wxCommandEvent& event )
1365{
1366 std::function<bool( wxString* )> textResolver = [&]( wxString* token ) -> bool
1367 {
1368 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
1369 };
1370
1371 wxString path = m_outputDirectoryName->GetValue();
1372 path = ExpandTextVars( path, &textResolver );
1374 path = Prj().AbsolutePath( path );
1375
1376 if( !wxDirExists( path ) )
1377 {
1378 DisplayError( this, wxString::Format( _( "Directory '%s' does not exist." ), path ) );
1379 return;
1380 }
1381
1382 wxLaunchDefaultApplication( path );
1383}
1384
1385
1386void DIALOG_PLOT::onBoardSetup( wxHyperlinkEvent& aEvent )
1387{
1388 PCB_EDIT_FRAME* parent = dynamic_cast<PCB_EDIT_FRAME*>( GetParent() );
1389
1390 if( parent )
1391 {
1392 parent->ShowBoardSetupDialog( _( "Solder Mask/Paste" ) );
1393
1394 // Update warnings on return to this dialog
1395 reInitDialog();
1396 }
1397}
1398
1399
1400void DIALOG_PLOT::onPlotAllListMoveUp( wxCommandEvent& aEvent )
1401{
1402 if( m_plotAllLayersList->CanMoveCurrentUp() )
1403 m_plotAllLayersList->MoveCurrentUp();
1404}
1405
1406
1407void DIALOG_PLOT::onPlotAllListMoveDown( wxCommandEvent& aEvent )
1408{
1409 if( m_plotAllLayersList->CanMoveCurrentDown() )
1410 m_plotAllLayersList->MoveCurrentDown();
1411}
1412
1413
1414void DIALOG_PLOT::onDNPCheckbox( wxCommandEvent& aEvent )
1415{
1416 m_hideDNP->Enable( aEvent.IsChecked() );
1417 m_crossoutDNP->Enable( aEvent.IsChecked() );
1418}
1419
1420
1421void DIALOG_PLOT::onSketchPads( wxCommandEvent& aEvent )
1422{
1423 m_plotPadNumbers->Enable( aEvent.IsChecked() );
1424}
1425
1426
1428{
1429 if( m_PDFColorChoice->GetSelection() == 1 )
1430 {
1431 m_pdfBackgroundColorSwatch->Disable();
1432 m_pdfBackgroundColorText->Disable();
1433 }
1434 else
1435 {
1437 m_pdfBackgroundColorText->Enable();
1438 }
1439}
1440
1441
1442void DIALOG_PLOT::onPDFColorChoice( wxCommandEvent& aEvent )
1443{
1445}
int index
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
constexpr EDA_IU_SCALE unityScale
Definition base_units.h:128
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
@ small_new_window
wxString m_ColorTheme
Active color theme name.
BASE_SET & set(size_t pos)
Definition base_set.h:116
Container for design settings for a BOARD object.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
void SetCurrentVariant(const wxString &aVariant)
Definition board.cpp:2781
wxArrayString GetVariantNamesForUI() const
Return the variant names for UI display.
Definition board.cpp:2936
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:745
wxString GetCurrentVariant() const
Definition board.h:398
PROJECT * GetProject() const
Definition board.h:587
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1101
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:986
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:402
wxCheckBox * m_frontFPPropertyPopups
wxStaticText * m_DRCExclusionsWarning
wxTextCtrl * m_widthAdjustCtrl
wxCheckBox * m_backFPPropertyPopups
wxTextCtrl * m_fineAdjustXCtrl
wxBoxSizer * bmiddleSizer
wxStaticBoxSizer * m_PDFOptionsSizer
wxCheckBox * m_disableApertMacros
wxChoice * m_coordFormatCtrl
wxCheckBox * m_DXF_plotModeOpt
wxCheckBox * m_pdfSingle
wxChoice * m_SVGColorChoice
wxStaticText * m_staticTextPlotFmt
wxStaticBoxSizer * m_pngOptionsSizer
wxCheckBox * m_DXF_exportAsMultiLayeredFile
STD_BITMAP_BUTTON * m_browseButton
wxTextCtrl * m_outputDirectoryName
wxSpinCtrl * m_svgPrecsision
wxTextCtrl * m_fineAdjustYCtrl
wxCheckBox * m_plotPadNumbers
wxCheckBox * m_useAuxOriginCheckBox
wxStaticBoxSizer * m_PSOptionsSizer
STD_BITMAP_BUTTON * m_openDirButton
wxCheckBox * m_plotPSNegativeOpt
wxChoice * m_variantChoiceCtrl
wxStaticText * m_widthAdjustLabel
wxCheckBox * m_SVG_fitPageToBoard
wxStaticText * m_pdfBackgroundColorText
wxCheckBox * m_DXF_plotTextStrokeFontOpt
wxCheckBox * m_useGerberExtensions
wxCheckBox * m_plotSheetRef
wxBoxSizer * m_SizerSolderMaskAlert
wxCheckBox * m_generateGerberJobFile
wxRadioButton * m_crossoutDNP
wxButton * m_sdbSizer1Apply
wxCheckBox * m_useGerberX2Format
wxCheckListBox * m_layerCheckListBox
wxCheckBox * m_plotMirrorOpt
wxStaticText * m_widthAdjustUnits
wxStaticBoxSizer * m_svgOptionsSizer
COLOR_SWATCH * m_pdfBackgroundColorSwatch
wxCheckBox * m_forcePSA4OutputOpt
wxCheckBox * m_useGerberNetAttributes
wxCheckBox * m_sketchPadsOnFabLayers
wxCheckBox * m_pngAntialias
wxCheckBox * m_subtractMaskFromSilk
wxCheckBox * m_plotDNP
wxBoxSizer * m_PlotOptionsSizer
wxSpinCtrl * m_pngDPI
wxChoice * m_DXF_plotUnits
DIALOG_PLOT_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Plot"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxStaticBoxSizer * m_SizerDXF_options
wxCheckBox * m_pdfMetadata
wxChoice * m_drillShapeOpt
wxRadioButton * m_hideDNP
wxCheckBox * m_zoneFillCheck
wxStaticBoxSizer * m_GerberOptionsSizer
WX_HTML_REPORT_PANEL * m_messagesPanel
wxChoice * m_PDFColorChoice
wxChoice * m_plotFormatOpt
wxBoxSizer * m_MainSizer
void onPDFColorChoice(wxCommandEvent &event) override
DIALOG_PLOT(PCB_EDIT_FRAME *aEditFrame)
void reInitDialog()
void OnRightClickLayers(wxMouseEvent &event)
static LSEQ s_lastAllLayersOrder
The plot on all layers ordering the last time the dialog was opened.
JOB_EXPORT_PCB_PLOT * m_job
PCB_PLOT_PARAMS m_plotOpts
Definition dialog_plot.h:99
STD_BITMAP_BUTTON * m_bpMoveUp
void onPlotAllListMoveUp(wxCommandEvent &aEvent)
void OnChangeDXFPlotMode(wxCommandEvent &event) override
int m_widthAdjustMinValue
Definition dialog_plot.h:92
UNIT_BINDER m_trackWidthCorrection
Definition dialog_plot.h:95
void onBoardSetup(wxHyperlinkEvent &aEvent) override
void OnRightClickAllLayers(wxMouseEvent &event)
void onSketchPads(wxCommandEvent &event) override
void Plot(wxCommandEvent &event) override
void applyPlotSettings()
int m_PSWidthAdjust
Definition dialog_plot.h:88
wxString m_DRCWarningTemplate
Definition dialog_plot.h:97
wxRearrangeList * m_plotAllLayersList
bool TransferDataToWindow() override
void onPlotAllListMoveDown(wxCommandEvent &aEvent)
void onRunDRC(wxCommandEvent &event) override
void arrangeAllLayersList(const LSEQ &aSeq)
double m_YScaleAdjust
Definition dialog_plot.h:86
void onOpenOutputDirectory(wxCommandEvent &event) override
void updatePdfColorOptions()
PCB_EDIT_FRAME * m_editFrame
Definition dialog_plot.h:82
virtual ~DIALOG_PLOT()
STD_BITMAP_BUTTON * m_bpMoveDown
wxString getSelectedVariant() const
void CreateDrillFile(wxCommandEvent &event) override
void onDNPCheckbox(wxCommandEvent &event) override
double m_XScaleAdjust
Definition dialog_plot.h:84
PLOT_FORMAT getPlotFormat()
void transferPlotParamsToJob()
int m_widthAdjustMaxValue
Definition dialog_plot.h:93
void onOutputDirectoryBrowseClicked(wxCommandEvent &event) override
void OnGerberX2Checked(wxCommandEvent &event) override
void SetPlotFormat(wxCommandEvent &event) override
LSEQ m_layerList
Definition dialog_plot.h:83
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
int ShowModal() override
void ShowDRCDialog(wxWindow *aParent)
Opens the DRC dialog.
Definition drc_tool.cpp:78
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition drc_tool.cpp:129
@ ONE_PAGE_PER_LAYER_ONE_FILE
The most traditional output mode KiCad has had.
bool m_pdfSingle
This is a hack to deal with cli having the wrong behavior We will deprecate out the wrong behavior,...
GEN_MODE m_pdfGenMode
The background color specified in a hex string.
virtual wxString GetSettingsDialogTitle() const
Definition job.cpp:80
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:608
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition lset.cpp:743
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition lset.cpp:404
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition lset.cpp:676
The main frame for Pcbnew.
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString, wxWindow *aParent=nullptr)
A helper wxWidgets control client data object to store layer IDs.
PCB_LAYER_ID Layer() const
void SetData(PCB_LAYER_ID aId)
PCB_LAYER_ID_CLIENT_DATA(PCB_LAYER_ID aId)
static void PlotJobToPlotOpts(PCB_PLOT_PARAMS &aOpts, JOB_EXPORT_PCB_PLOT *aJob, REPORTER &aReporter)
Translate a JOB to PCB_PLOT_PARAMS.
bool Plot(const wxString &aOutputPath, const LSEQ &aLayersToPlot, const LSEQ &aCommonLayers, bool aUseGerberFileExtensions, bool aOutputPathIsSingle=false, std::optional< wxString > aLayerName=std::nullopt, std::optional< wxString > aSheetName=std::nullopt, std::optional< wxString > aSheetPath=std::nullopt, std::vector< wxString > *aOutputFiles=nullptr)
Parameters and options when plotting/printing a board.
void SetDrillMarksType(DRILL_MARKS aVal)
void SetLayerSelection(const LSET &aSelection)
void SetOutputDirectory(const wxString &aDir)
void SetSketchPadsOnFabLayers(bool aFlag)
void SetUseGerberX2format(bool aUse)
void SetA4Output(int aForce)
void SetPlotOnAllLayersSequence(LSEQ aSeq)
void SetDXFPlotPolygonMode(bool aFlag)
void SetPlotFrameRef(bool aFlag)
void SetSketchDNPFPsOnFabLayers(bool aFlag)
bool m_PDFMetadata
Generate PDF metadata for SUBJECT and AUTHOR.
void SetDashedLineGapRatio(double aVal)
void SetPlotPadNumbers(bool aFlag)
bool m_PDFFrontFPPropertyPopups
Generate PDF property popup menus for footprints.
void SetDisableGerberMacros(bool aDisable)
void SetDXFMultiLayeredExportOption(bool aFlag)
void SetScaleSelection(int aSelection)
void SetFineScaleAdjustX(double aVal)
void SetMirror(bool aFlag)
void SetBlackAndWhite(bool blackAndWhite)
void SetGerberPrecision(int aPrecision)
void SetSubtractMaskFromSilk(bool aSubtract)
void SetHideDNPFPsOnFabLayers(bool aFlag)
void SetPngDPI(int aDPI)
COLOR4D m_PDFBackgroundColor
Background color to use if m_PDFUseBackgroundColor is true.
void SetUseGerberProtelExtensions(bool aUse)
void SetDashedLineDashRatio(double aVal)
void SetDXFPlotUnits(DXF_UNITS aUnit)
void SetPngAntialias(bool aFlag)
void SetIncludeGerberNetlistInfo(bool aUse)
void SetCreateGerberJobFile(bool aCreate)
bool m_PDFSingle
Generate a single PDF file for all layers.
void SetNegative(bool aFlag)
void SetUseAuxOrigin(bool aAux)
bool m_PDFBackFPPropertyPopups
on front and/or back of board
void SetTextMode(PLOT_TEXT_MODE aVal)
void SetSvgFitPageToBoard(int aSvgFitPageToBoard)
void SetSvgPrecision(unsigned aPrecision)
void SetCrossoutDNPFPsOnFabLayers(bool aFlag)
void SetFormat(PLOT_FORMAT aFormat)
void SetFineScaleAdjustY(double aVal)
void SetWidthAdjust(int aVal)
The backing store for a PROJECT, in JSON format.
wxString m_PcbLastPath[LAST_PATH_SIZE]
MRU path storage.
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:411
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:75
A bitmap button widget that behaves like a standard dialog button except with an icon.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Handle actions specific to filling copper zones.
A type-safe container of any type.
Definition ki_any.h:93
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition common.cpp:708
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:63
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:729
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:278
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:249
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:196
This file is part of the common library.
#define ID_STACKUP_ORDER
static bool setDouble(double *aResult, double aValue, double aMin, double aMax)
static bool setInt(int *aResult, int aValue, int aMin, int aMax)
PCB_LAYER_ID_CLIENT_DATA * getLayerClientData(const wxRearrangeList *aList, int aIdx)
#define ID_SELECT_ALL_LAYERS
static double selectionToScale(int selection)
#define ID_DESELECT_COPPER_LAYERS
#define ID_DESELECT_ALL_LAYERS
#define ID_LAYER_FAB
#define ID_SELECT_COPPER_LAYERS
#define DLG_WINDOW_NAME
Definition dialog_plot.h:30
#define _(s)
Classes used to generate a Gerber job file in JSON.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:679
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ F_CrtYd
Definition layer_ids.h:116
@ F_Fab
Definition layer_ids.h:119
@ B_CrtYd
Definition layer_ids.h:115
@ UNDEFINED_LAYER
Definition layer_ids.h:61
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API wxString StringFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Return the string from aValue according to aUnits (inch, mm ...) for display.
KICOMMON_API wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
Definition ui_common.cpp:78
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
#define PLOT_MIN_SCALE
Definition pcbplot.h:58
#define PLOT_MAX_SCALE
Definition pcbplot.h:59
see class PGM_BASE
DRILL_MARKS
Plots and prints can show holes in pads and vias 3 options are available:
@ SKETCH
Definition plotter.h:82
PLOT_FORMAT
The set of supported output plot formats.
Definition plotter.h:64
Plotting engines similar to ps (PostScript, Gerber, svg)
@ LAST_PATH_PLOT
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_INFO
#define DEFAULT_THEME
COLOR_SETTINGS * GetColorSettings(const wxString &aName)
T * GetAppSettings(const char *aFilename)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::string path
IbisParser parser & reporter
Definition of file extensions used in Kicad.