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