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