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 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 if( !m_job && !projectFile.m_PcbLastPath[ LAST_PATH_PLOT ].IsEmpty() )
285 m_plotOpts.SetOutputDirectory( projectFile.m_PcbLastPath[ LAST_PATH_PLOT ] );
286
287 if( m_job
288 && !( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::POST
289 && static_cast<JOB_EXPORT_PCB_PS*>( m_job )->m_useGlobalSettings ) )
290 {
291 // When we are using a job we get the PS adjust values from the plot options
292 // The exception is when this is a fresh job and we want to get the global values as defaults
294 m_plotOpts.GetFineScaleAdjustX() ) );
295
297 m_plotOpts.GetFineScaleAdjustY() ) );
298 m_trackWidthCorrection.SetValue( m_plotOpts.GetWidthAdjust() );
299 m_zoneFillCheck->SetValue( m_job->m_checkZonesBeforePlot );
300 }
301
302 // The reasonable width correction value must be in a range of
303 // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
304 m_widthAdjustMinValue = -( board->GetDesignSettings().m_TrackMinWidth - 1 );
306
307 switch( m_plotOpts.GetFormat() )
308 {
309 default:
310 case PLOT_FORMAT::GERBER: m_plotFormatOpt->SetSelection( 0 ); break;
311 case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 1 ); break;
312 case PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
313 case PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
314 case PLOT_FORMAT::HPGL: /* no longer supported */ break;
315 case PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 4 ); break;
316 }
317
318 m_plotPSNegativeOpt->SetValue( m_plotOpts.GetNegative() );
319 m_forcePSA4OutputOpt->SetValue( m_plotOpts.GetA4Output() );
320
321 // Populate the check list box by all enabled layers names.
322 for( PCB_LAYER_ID layer : m_layerList )
323 {
324 int checkIndex = m_layerCheckListBox->Append( board->GetLayerName( layer ) );
325
326 if( m_plotOpts.GetLayerSelection()[layer] )
327 m_layerCheckListBox->Check( checkIndex );
328 }
329
331
332 // Option for disabling Gerber Aperture Macro (for broken Gerber readers)
333 m_disableApertMacros->SetValue( m_plotOpts.GetDisableGerberMacros() );
334
335 // Option for using proper Gerber extensions. Note also Protel extensions are
336 // a broken feature. However, for now, we need to handle it.
337 m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberProtelExtensions() );
338
339 // Option for including Gerber attributes, from Gerber X2 format, in the output
340 // In X1 format, they will be added as comments
341 m_useGerberX2Format->SetValue( m_plotOpts.GetUseGerberX2format() );
342
343 // Option for including Gerber netlist info (from Gerber X2 format) in the output
344 m_useGerberNetAttributes->SetValue( m_plotOpts.GetIncludeGerberNetlistInfo() );
345
346 // Option to generate a Gerber job file
347 m_generateGerberJobFile->SetValue( m_plotOpts.GetCreateGerberJobFile() );
348
349 // Gerber precision for coordinates
350 m_coordFormatCtrl->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 );
351
352 // SVG precision and units for coordinates
353 m_svgPrecsision->SetValue( m_plotOpts.GetSvgPrecision() );
354 m_SVG_fitPageToBoard->SetValue( m_plotOpts.GetSvgFitPagetoBoard() );
355
356 m_sketchPadsOnFabLayers->SetValue( m_plotOpts.GetSketchPadsOnFabLayers() );
357 m_plotPadNumbers->SetValue( m_plotOpts.GetPlotPadNumbers() );
358 m_plotPadNumbers->Enable( m_plotOpts.GetSketchPadsOnFabLayers() );
359
360 m_plotDNP->SetValue( m_plotOpts.GetHideDNPFPsOnFabLayers()
361 || m_plotOpts.GetSketchDNPFPsOnFabLayers()
362 || m_plotOpts.GetCrossoutDNPFPsOnFabLayers() );
363
364 if( m_plotDNP->GetValue() )
365 {
366 if( m_plotOpts.GetHideDNPFPsOnFabLayers() )
367 m_hideDNP->SetValue( true );
368 else
369 m_crossoutDNP->SetValue( true );
370 }
371
372 m_hideDNP->Enable( m_plotDNP->GetValue() );
373 m_crossoutDNP->Enable( m_plotDNP->GetValue() );
374
375 m_subtractMaskFromSilk->SetValue( m_plotOpts.GetSubtractMaskFromSilk() );
376
377 m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
378
379 m_plotSheetRef->SetValue( m_plotOpts.GetPlotFrameRef() );
380
381 // Options to plot pads and vias holes
382 m_drillShapeOpt->SetSelection( (int) m_plotOpts.GetDrillMarksType() );
383
384 // Scale option
385 m_scaleOpt->SetSelection( m_plotOpts.GetScaleSelection() );
386
387 // DXF outline mode
388 m_DXF_plotModeOpt->SetValue( m_plotOpts.GetDXFPlotPolygonMode() );
389
390 // DXF text mode
392
393 // DXF units selection
394 m_DXF_plotUnits->SetSelection( m_plotOpts.GetDXFPlotUnits() == DXF_UNITS::INCH ? 0 : 1 );
395
396 // Plot mirror option
397 m_plotMirrorOpt->SetValue( m_plotOpts.GetMirror() );
398
399 // Black and white plotting
400 m_SVGColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
401 m_PDFColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
402 m_frontFPPropertyPopups->SetValue( m_plotOpts.m_PDFFrontFPPropertyPopups );
403 m_backFPPropertyPopups->SetValue( m_plotOpts.m_PDFBackFPPropertyPopups );
404 m_pdfMetadata->SetValue( m_plotOpts.m_PDFMetadata );
405 m_pdfSingle->SetValue( m_plotOpts.m_PDFSingle );
406 m_pdfBackgroundColorSwatch->SetSwatchColor( m_plotOpts.m_PDFBackgroundColor, false );
408
409 // Initialize a few other parameters, which can also be modified
410 // from the drill dialog
411 reInitDialog();
412
413 // Update options values:
414 wxCommandEvent cmd_event;
415 SetPlotFormat( cmd_event );
416
417 return true;
418}
419
420
422{
424 {
425 JOB_EXPORT_PCB_GERBERS* gJob = static_cast<JOB_EXPORT_PCB_GERBERS*>( m_job );
426 gJob->m_disableApertureMacros = m_plotOpts.GetDisableGerberMacros();
427 gJob->m_useProtelFileExtension = m_plotOpts.GetUseGerberProtelExtensions();
428 gJob->m_useX2Format = m_plotOpts.GetUseGerberX2format();
429 gJob->m_includeNetlistAttributes = m_plotOpts.GetIncludeGerberNetlistInfo();
430 gJob->m_createJobsFile = m_plotOpts.GetCreateGerberJobFile();
431 gJob->m_precision = m_plotOpts.GetGerberPrecision();
432 gJob->m_useBoardPlotParams = false;
433 }
434 else
435 {
436 m_job->m_scale = selectionToScale( m_plotOpts.GetScaleSelection() );
437 }
438
439 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG )
440 {
441 JOB_EXPORT_PCB_SVG* svgJob = static_cast<JOB_EXPORT_PCB_SVG*>( m_job );
442 svgJob->m_precision = m_plotOpts.GetSvgPrecision();
444 svgJob->m_fitPageToBoard = m_plotOpts.GetSvgFitPagetoBoard();
445 }
446
447 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::DXF )
448 {
449 JOB_EXPORT_PCB_DXF* dxfJob = static_cast<JOB_EXPORT_PCB_DXF*>( m_job );
453 dxfJob->m_polygonMode = m_plotOpts.GetDXFPlotPolygonMode();
454 dxfJob->m_genMode = m_plotOpts.GetDXFMultiLayeredExportOption() ? JOB_EXPORT_PCB_DXF::GEN_MODE::SINGLE
456 }
457
458 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::POST )
459 {
460 JOB_EXPORT_PCB_PS* psJob = static_cast<JOB_EXPORT_PCB_PS*>( m_job );
462 psJob->m_XScaleAdjust = m_plotOpts.GetFineScaleAdjustX();
463 psJob->m_YScaleAdjust = m_plotOpts.GetFineScaleAdjustY();
464 psJob->m_trackWidthCorrection = pcbIUScale.IUTomm( m_plotOpts.GetWidthAdjust() );
465 psJob->m_forceA4 = m_plotOpts.GetA4Output();
466 // For a fresh job we got the adjusts from the global pcbnew settings
467 // After the user confirmed and/or changed them we stop using the global adjusts
468 psJob->m_useGlobalSettings = false;
469 }
470
471 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::PDF )
472 {
473 JOB_EXPORT_PCB_PDF* pdfJob = static_cast<JOB_EXPORT_PCB_PDF*>( m_job );
474 pdfJob->m_pdfFrontFPPropertyPopups = m_plotOpts.m_PDFFrontFPPropertyPopups;
475 pdfJob->m_pdfBackFPPropertyPopups = m_plotOpts.m_PDFBackFPPropertyPopups;
476 pdfJob->m_pdfMetadata = m_plotOpts.m_PDFMetadata;
477 pdfJob->m_pdfSingle = m_plotOpts.m_PDFSingle;
478 pdfJob->m_pdfBackgroundColor = m_plotOpts.m_PDFBackgroundColor.ToCSSString();
479
480 // we need to embed this for the cli deprecation fix
481 if( pdfJob->m_pdfSingle )
482 {
484 }
485 else
486 {
488 }
489 }
490
491 m_job->m_subtractSolderMaskFromSilk = m_plotOpts.GetSubtractMaskFromSilk();
492 m_job->m_useDrillOrigin = m_plotOpts.GetUseAuxOrigin();
493 m_job->m_crossoutDNPFPsOnFabLayers = m_plotOpts.GetCrossoutDNPFPsOnFabLayers();
494 m_job->m_hideDNPFPsOnFabLayers = m_plotOpts.GetHideDNPFPsOnFabLayers();
495 m_job->m_sketchDNPFPsOnFabLayers = m_plotOpts.GetSketchDNPFPsOnFabLayers();
496 m_job->m_sketchPadsOnFabLayers = m_plotOpts.GetSketchPadsOnFabLayers();
497
498 m_job->m_plotDrawingSheet = m_plotOpts.GetPlotFrameRef();
499 m_job->m_plotPadNumbers = m_plotOpts.GetPlotPadNumbers();
500
501 m_job->m_blackAndWhite = m_plotOpts.GetBlackAndWhite();
502 m_job->m_mirror = m_plotOpts.GetMirror();
503 m_job->m_negative = m_plotOpts.GetNegative();
504 m_job->m_plotLayerSequence = m_plotOpts.GetLayerSelection().SeqStackupForPlotting();
505 m_job->m_plotOnAllLayersSequence = m_plotOpts.GetPlotOnAllLayersSequence();
506
507 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG ||
509 {
510 switch( m_plotOpts.GetDrillMarksType() )
511 {
512 case DRILL_MARKS::NO_DRILL_SHAPE: m_job->m_drillShapeOption = DRILL_MARKS::NO_DRILL_SHAPE; break;
514 default:
515 case DRILL_MARKS::FULL_DRILL_SHAPE: m_job->m_drillShapeOption = DRILL_MARKS::FULL_DRILL_SHAPE; break;
516 }
517 }
518
519 m_job->SetConfiguredOutputPath( m_plotOpts.GetOutputDirectory() );
520
521 // this exists outside plot opts because its usually globally saved
522 m_job->m_checkZonesBeforePlot = m_zoneFillCheck->GetValue();
523}
524
525
527{
528 // after calling the Drill or DRC dialogs some parameters can be modified....
529
530 // Output directory
531 m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
532
533 // Origin of coordinates:
534 m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
535
536 int knownViolations = 0;
537 int exclusions = 0;
538
539 for( PCB_MARKER* marker : m_editFrame->GetBoard()->Markers() )
540 {
541 if( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION )
542 exclusions++;
543 else
544 knownViolations++;
545 }
546
547 if( !m_job && ( knownViolations || exclusions ) )
548 {
549 m_DRCExclusionsWarning->SetLabel( wxString::Format( m_DRCWarningTemplate, knownViolations,
550 exclusions ) );
552 }
553 else
554 {
556 }
557
558 BOARD* board = m_editFrame->GetBoard();
559 const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
560
562 ( brd_settings.m_SolderMaskExpansion || brd_settings.m_SolderMaskMinWidth ) )
563 {
565 }
566 else
567 {
569 }
570}
571
572
574{
575 auto findLayer =
576 [&]( wxRearrangeList* aList, PCB_LAYER_ID aLayer ) -> int
577 {
578 for( int ii = 0; ii < (int) aList->GetCount(); ++ii )
579 {
580 if( getLayerClientData( aList, ii )->Layer() == aLayer )
581 return ii;
582 }
583
584 return -1;
585 };
586
587 int idx = 0;
588
589 for( PCB_LAYER_ID layer : aSeq )
590 {
591 int currentPos = findLayer( m_plotAllLayersList, layer );
592
593 while( currentPos > idx )
594 {
595 m_plotAllLayersList->Select( currentPos );
596 m_plotAllLayersList->MoveCurrentUp();
597 currentPos--;
598 }
599
600 idx++;
601 }
602}
603
604
605#define ID_LAYER_FAB 13001
606#define ID_SELECT_COPPER_LAYERS 13002
607#define ID_DESELECT_COPPER_LAYERS 13003
608#define ID_SELECT_ALL_LAYERS 13004
609#define ID_DESELECT_ALL_LAYERS 13005
610#define ID_STACKUP_ORDER 13006
611
612
613// A helper function to show a popup menu, when the dialog is right clicked.
614void DIALOG_PLOT::OnRightClickLayers( wxMouseEvent& event )
615{
616 // Build a list of layers for usual fabrication: copper layers + tech layers without courtyard
617 LSET fab_layer_set = ( LSET::AllCuMask() | LSET::AllTechMask() ) & ~LSET( { B_CrtYd, F_CrtYd } );
618
619 wxMenu menu;
620 menu.Append( new wxMenuItem( &menu, ID_LAYER_FAB, _( "Select Fab Layers" ) ) );
621
622 menu.AppendSeparator();
623 menu.Append( new wxMenuItem( &menu, ID_SELECT_COPPER_LAYERS, _( "Select All Copper Layers" ) ) );
624 menu.Append( new wxMenuItem( &menu, ID_DESELECT_COPPER_LAYERS, _( "Deselect All Copper Layers" ) ) );
625
626 menu.AppendSeparator();
627 menu.Append( new wxMenuItem( &menu, ID_SELECT_ALL_LAYERS, _( "Select All Layers" ) ) );
628 menu.Append( new wxMenuItem( &menu, ID_DESELECT_ALL_LAYERS, _( "Deselect All Layers" ) ) );
629
630 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
631 [&]( wxCommandEvent& aCmd )
632 {
633 switch( aCmd.GetId() )
634 {
635 case ID_LAYER_FAB: // Select layers usually needed to build a board
636 {
637 for( unsigned i = 0; i < m_layerList.size(); i++ )
638 {
639 LSET layermask( { m_layerList[ i ] } );
640
641 if( ( layermask & fab_layer_set ).any() )
642 m_layerCheckListBox->Check( i, true );
643 else
644 m_layerCheckListBox->Check( i, false );
645 }
646
647 break;
648 }
649
651 for( unsigned i = 0; i < m_layerList.size(); i++ )
652 {
653 if( IsCopperLayer( m_layerList[i] ) )
654 m_layerCheckListBox->Check( i, true );
655 }
656
657 break;
658
660 for( unsigned i = 0; i < m_layerList.size(); i++ )
661 {
662 if( IsCopperLayer( m_layerList[i] ) )
663 m_layerCheckListBox->Check( i, false );
664 }
665
666 break;
667
669 for( unsigned i = 0; i < m_layerList.size(); i++ )
670 m_layerCheckListBox->Check( i, true );
671
672 break;
673
675 for( unsigned i = 0; i < m_layerList.size(); i++ )
676 m_layerCheckListBox->Check( i, false );
677
678 break;
679
680 default:
681 aCmd.Skip();
682 }
683 } );
684
685 PopupMenu( &menu );
686}
687
688
689void DIALOG_PLOT::OnRightClickAllLayers( wxMouseEvent& event )
690{
691 wxMenu menu;
692 menu.Append( new wxMenuItem( &menu, ID_SELECT_ALL_LAYERS, _( "Select All Layers" ) ) );
693 menu.Append( new wxMenuItem( &menu, ID_DESELECT_ALL_LAYERS, _( "Deselect All Layers" ) ) );
694
695 menu.AppendSeparator();
696 menu.Append( new wxMenuItem( &menu, ID_STACKUP_ORDER, _( "Order as Board Stackup" ) ) );
697
698 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
699 [&]( wxCommandEvent& aCmd )
700 {
701 switch( aCmd.GetId() )
702 {
704 for( unsigned i = 0; i < m_plotAllLayersList->GetCount(); i++ )
705 m_plotAllLayersList->Check( i, true );
706
707 break;
708
710 for( unsigned i = 0; i < m_plotAllLayersList->GetCount(); i++ )
711 m_plotAllLayersList->Check( i, false );
712
713 break;
714
715 case ID_STACKUP_ORDER:
716 {
717 LSEQ stackup = m_editFrame->GetBoard()->GetEnabledLayers().SeqStackupForPlotting();
718 arrangeAllLayersList( stackup );
719 m_plotAllLayersList->Select( -1 );
720 break;
721 }
722
723 default:
724 aCmd.Skip();
725 }
726 } );
727
728 PopupMenu( &menu );
729}
730
731
732void DIALOG_PLOT::CreateDrillFile( wxCommandEvent& event )
733{
734 // Be sure drill file use the same settings (axis option, plot directory) as plot files:
736
737 DIALOG_GENDRILL dlg( m_editFrame, this );
738 dlg.ShowModal();
739
740 // a few plot settings can be modified: take them in account
741 m_plotOpts = m_editFrame->GetPlotSettings();
742 reInitDialog();
743}
744
745
746void DIALOG_PLOT::OnChangeDXFPlotMode( wxCommandEvent& event )
747{
748 // m_DXF_plotTextStrokeFontOpt is disabled if m_DXF_plotModeOpt is checked (plot in DXF
749 // polygon mode)
750 m_DXF_plotTextStrokeFontOpt->Enable( !m_DXF_plotModeOpt->GetValue() );
751
752 // if m_DXF_plotTextStrokeFontOpt option is disabled (plot DXF in polygon mode), force
753 // m_DXF_plotTextStrokeFontOpt to true to use Pcbnew stroke font
754 if( !m_DXF_plotTextStrokeFontOpt->IsEnabled() )
755 m_DXF_plotTextStrokeFontOpt->SetValue( true );
756}
757
758
760{
761 // Build the absolute path of current output directory to preselect it in the file browser.
762 std::function<bool( wxString* )> textResolver =
763 [&]( wxString* token ) -> bool
764 {
765 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
766 };
767
768 wxString path = m_outputDirectoryName->GetValue();
769 path = ExpandTextVars( path, &textResolver );
771 path = Prj().AbsolutePath( path );
772
773 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
774
775 if( dirDialog.ShowModal() == wxID_CANCEL )
776 return;
777
778 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
779
780 wxFileName fn( Prj().AbsolutePath( m_editFrame->GetBoard()->GetFileName() ) );
781 wxString defaultPath = fn.GetPathWithSep();
782 wxString msg;
783 wxFileName relPathTest; // Used to test if we can make the path relative
784
785 relPathTest.Assign( dirDialog.GetPath() );
786
787 // Test if making the path relative is possible before asking the user if they want to do it
788 if( relPathTest.MakeRelativeTo( defaultPath ) )
789 {
790 if( IsOK( this, wxString::Format( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath ) ) )
791 dirName.MakeRelativeTo( defaultPath );
792 }
793
794 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
795}
796
797
799{
800 // plot format id's are ordered like displayed in m_plotFormatOpt
801 static const PLOT_FORMAT plotFmt[] = {
807
808 return plotFmt[m_plotFormatOpt->GetSelection()];
809}
810
811
812void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
813{
814 // this option exist only in DXF format:
816
817 // The alert message about non 0 solder mask min width and margin is shown
818 // only in gerber format and if min mask width or mask margin is not 0
819 BOARD* board = m_editFrame->GetBoard();
820 const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
821
823 && ( brd_settings.m_SolderMaskExpansion || brd_settings.m_SolderMaskMinWidth ) )
824 {
826 }
827 else
828 {
830 }
831
832 switch( getPlotFormat() )
833 {
834 case PLOT_FORMAT::SVG:
835 case PLOT_FORMAT::PDF:
836 m_drillShapeOpt->Enable( true );
837 m_plotMirrorOpt->Enable( true );
838 m_useAuxOriginCheckBox->Enable( true );
839 m_scaleOpt->Enable( true );
840 m_fineAdjustXCtrl->Enable( false );
841 m_fineAdjustYCtrl->Enable( false );
842 m_trackWidthCorrection.Enable( false );
843 m_plotPSNegativeOpt->Enable( true );
844 m_forcePSA4OutputOpt->Enable( false );
845 m_forcePSA4OutputOpt->SetValue( false );
846
848 {
851 }
852 else
853 {
856 }
857
861 break;
862
864 m_drillShapeOpt->Enable( true );
865 m_plotMirrorOpt->Enable( true );
866 m_useAuxOriginCheckBox->Enable( false );
867 m_useAuxOriginCheckBox->SetValue( false );
868 m_scaleOpt->Enable( true );
869 m_fineAdjustXCtrl->Enable( true );
870 m_fineAdjustYCtrl->Enable( true );
871 m_trackWidthCorrection.Enable( true );
872 m_plotPSNegativeOpt->Enable( true );
873 m_forcePSA4OutputOpt->Enable( true );
874
880 break;
881
883 m_drillShapeOpt->Enable( false );
884 m_drillShapeOpt->SetSelection( 0 );
885 m_plotMirrorOpt->Enable( false );
886 m_plotMirrorOpt->SetValue( false );
887 m_useAuxOriginCheckBox->Enable( true );
888 m_scaleOpt->Enable( false );
889 m_scaleOpt->SetSelection( 1 );
890 m_fineAdjustXCtrl->Enable( false );
891 m_fineAdjustYCtrl->Enable( false );
892 m_trackWidthCorrection.Enable( false );
893 m_plotPSNegativeOpt->Enable( false );
894 m_plotPSNegativeOpt->SetValue( false );
895 m_forcePSA4OutputOpt->Enable( false );
896 m_forcePSA4OutputOpt->SetValue( false );
897
903 break;
904
905 case PLOT_FORMAT::DXF:
906 m_drillShapeOpt->Enable( true );
907 m_plotMirrorOpt->Enable( false );
908 m_plotMirrorOpt->SetValue( false );
909 m_useAuxOriginCheckBox->Enable( true );
910 m_scaleOpt->Enable( true );
911 m_fineAdjustXCtrl->Enable( false );
912 m_fineAdjustYCtrl->Enable( false );
913 m_trackWidthCorrection.Enable( false );
914 m_plotPSNegativeOpt->Enable( false );
915 m_plotPSNegativeOpt->SetValue( false );
916 m_forcePSA4OutputOpt->Enable( false );
917 m_forcePSA4OutputOpt->SetValue( false );
918
924
925 OnChangeDXFPlotMode( event );
926 break;
927
928 default:
931 break;
932 }
933
934 Layout();
935 m_MainSizer->SetSizeHints( this );
936}
937
938
939// A helper function to "clip" aValue between aMin and aMax and write result in * aResult
940// return false if clipped, true if aValue is just copied into * aResult
941static bool setDouble( double* aResult, double aValue, double aMin, double aMax )
942{
943 if( aValue < aMin )
944 {
945 *aResult = aMin;
946 return false;
947 }
948 else if( aValue > aMax )
949 {
950 *aResult = aMax;
951 return false;
952 }
953
954 *aResult = aValue;
955 return true;
956}
957
958
959static bool setInt( int* aResult, int aValue, int aMin, int aMax )
960{
961 if( aValue < aMin )
962 {
963 *aResult = aMin;
964 return false;
965 }
966 else if( aValue > aMax )
967 {
968 *aResult = aMax;
969 return false;
970 }
971
972 *aResult = aValue;
973 return true;
974}
975
976
978{
979 REPORTER& reporter = m_messagesPanel->Reporter();
980 PCB_PLOT_PARAMS tempOptions;
981
982 tempOptions.SetSubtractMaskFromSilk( m_subtractMaskFromSilk->GetValue() );
983 tempOptions.SetPlotFrameRef( m_plotSheetRef->GetValue() );
984 tempOptions.SetSketchPadsOnFabLayers( m_sketchPadsOnFabLayers->GetValue() );
985 tempOptions.SetPlotPadNumbers( m_plotPadNumbers->GetValue() );
986 tempOptions.SetHideDNPFPsOnFabLayers( m_plotDNP->GetValue()
987 && m_hideDNP->GetValue() );
988 tempOptions.SetSketchDNPFPsOnFabLayers( m_plotDNP->GetValue()
989 && m_crossoutDNP->GetValue() );
990 tempOptions.SetCrossoutDNPFPsOnFabLayers( m_plotDNP->GetValue()
991 && m_crossoutDNP->GetValue() );
992 tempOptions.SetUseAuxOrigin( m_useAuxOriginCheckBox->GetValue() );
993 tempOptions.SetScaleSelection( m_scaleOpt->GetSelection() );
994
995 int sel = m_drillShapeOpt->GetSelection();
996 tempOptions.SetDrillMarksType( static_cast<DRILL_MARKS>( sel ) );
997
998 tempOptions.SetMirror( m_plotMirrorOpt->GetValue() );
999 tempOptions.SetDXFPlotPolygonMode( m_DXF_plotModeOpt->GetValue() );
1000
1001 sel = m_DXF_plotUnits->GetSelection();
1002 tempOptions.SetDXFPlotUnits( sel == 0 ? DXF_UNITS::INCH : DXF_UNITS::MM );
1003
1004 if( !m_DXF_plotTextStrokeFontOpt->IsEnabled() ) // Currently, only DXF supports this option
1005 tempOptions.SetTextMode( PLOT_TEXT_MODE::DEFAULT );
1006 else
1009
1011
1013 {
1014 tempOptions.SetBlackAndWhite( m_SVGColorChoice->GetSelection() == 1 );
1015 }
1016 else if( getPlotFormat() == PLOT_FORMAT::PDF )
1017 {
1018 tempOptions.SetBlackAndWhite( m_PDFColorChoice->GetSelection() == 1 );
1019 tempOptions.m_PDFFrontFPPropertyPopups = m_frontFPPropertyPopups->GetValue();
1020 tempOptions.m_PDFBackFPPropertyPopups = m_backFPPropertyPopups->GetValue();
1021 tempOptions.m_PDFMetadata = m_pdfMetadata->GetValue();
1022 tempOptions.m_PDFSingle = m_pdfSingle->GetValue();
1023 tempOptions.m_PDFBackgroundColor = m_pdfBackgroundColorSwatch->GetSwatchColor();
1024 }
1025 else
1026 {
1027 tempOptions.SetBlackAndWhite( true );
1028 }
1029
1030 // Update settings from text fields. Rewrite values back to the fields,
1031 // since the values may have been constrained by the setters.
1032
1033 // X scale
1034 double tmpDouble;
1035 wxString msg = m_fineAdjustXCtrl->GetValue();
1036 msg.ToDouble( &tmpDouble );
1037
1039 {
1040 msg.Printf( wxT( "%f" ), m_XScaleAdjust );
1041 m_fineAdjustXCtrl->SetValue( msg );
1042 msg.Printf( _( "X scale constrained." ) );
1043 reporter.Report( msg, RPT_SEVERITY_INFO );
1044 }
1045
1046 // Y scale
1047 msg = m_fineAdjustYCtrl->GetValue();
1048 msg.ToDouble( &tmpDouble );
1049
1051 {
1052 msg.Printf( wxT( "%f" ), m_YScaleAdjust );
1053 m_fineAdjustYCtrl->SetValue( msg );
1054 msg.Printf( _( "Y scale constrained." ) );
1055 reporter.Report( msg, RPT_SEVERITY_INFO );
1056 }
1057
1058 // PS Width correction
1061 {
1063 msg.Printf( _( "Width correction constrained. The width correction value must be in the"
1064 " range of [%s; %s] for the current design rules." ),
1065 m_editFrame->StringFromValue( m_widthAdjustMinValue, true ),
1066 m_editFrame->StringFromValue( m_widthAdjustMaxValue, true ) );
1067 reporter.Report( msg, RPT_SEVERITY_WARNING );
1068 }
1069
1070 if( m_job )
1071 {
1072 // When using a job we store the adjusts in the plot options
1073 tempOptions.SetFineScaleAdjustX( m_XScaleAdjust );
1074 tempOptions.SetFineScaleAdjustY( m_YScaleAdjust );
1075 tempOptions.SetWidthAdjust( m_PSWidthAdjust );
1076 }
1077
1078 tempOptions.SetFormat( getPlotFormat() );
1079
1080 tempOptions.SetDisableGerberMacros( m_disableApertMacros->GetValue() );
1081 tempOptions.SetUseGerberProtelExtensions( m_useGerberExtensions->GetValue() );
1082 tempOptions.SetUseGerberX2format( m_useGerberX2Format->GetValue() );
1083 tempOptions.SetIncludeGerberNetlistInfo( m_useGerberNetAttributes->GetValue() );
1084 tempOptions.SetCreateGerberJobFile( m_generateGerberJobFile->GetValue() );
1085
1086 tempOptions.SetGerberPrecision( m_coordFormatCtrl->GetSelection() == 0 ? 5 : 6 );
1087 tempOptions.SetSvgPrecision( m_svgPrecsision->GetValue() );
1088 tempOptions.SetSvgFitPageToBoard( m_SVG_fitPageToBoard->GetValue() );
1089
1090 LSET selectedLayers;
1091
1092 for( unsigned i = 0; i < m_layerList.size(); i++ )
1093 {
1094 if( m_layerCheckListBox->IsChecked( i ) )
1095 selectedLayers.set( m_layerList[i] );
1096 }
1097
1098 // Get a list of copper layers that aren't being used by inverting enabled layers.
1099 LSET disabledCopperLayers = LSET::AllCuMask() & ~m_editFrame->GetBoard()->GetEnabledLayers();
1100
1101 // Add selected layers from plot on all layers list in order set by user.
1102 wxArrayInt plotOnAllLayers;
1103 LSEQ commonLayers;
1104
1105 if( m_plotAllLayersList->GetCheckedItems( plotOnAllLayers ) )
1106 {
1107 size_t count = plotOnAllLayers.GetCount();
1108
1109 for( size_t i = 0; i < count; i++ )
1110 {
1111 int index = plotOnAllLayers.Item( i );
1113
1114 commonLayers.push_back( client_layer );
1115 }
1116 }
1117
1118 tempOptions.SetPlotOnAllLayersSequence( commonLayers );
1119
1120 // Enable all of the disabled copper layers.
1121 // If someone enables more copper layers they will be selected by default.
1122 selectedLayers = selectedLayers | disabledCopperLayers;
1123 tempOptions.SetLayerSelection( selectedLayers );
1124
1125 tempOptions.SetNegative( m_plotPSNegativeOpt->GetValue() );
1126 tempOptions.SetA4Output( m_forcePSA4OutputOpt->GetValue() );
1127
1128 // Set output directory and replace backslashes with forward ones
1129 wxString dirStr;
1130 dirStr = m_outputDirectoryName->GetValue();
1131 dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
1132 tempOptions.SetOutputDirectory( dirStr );
1133 m_editFrame->Prj().GetProjectFile().m_PcbLastPath[ LAST_PATH_PLOT ] = dirStr;
1134
1135 if( !m_job && !m_plotOpts.IsSameAs( tempOptions ) )
1136 {
1137 m_editFrame->SetPlotSettings( tempOptions );
1138 m_editFrame->OnModify();
1139 m_plotOpts = tempOptions;
1140 }
1141 else
1142 {
1143 m_plotOpts = tempOptions;
1144 }
1145}
1146
1147
1148void DIALOG_PLOT::OnGerberX2Checked( wxCommandEvent& event )
1149{
1150 // Currently: do nothing
1151}
1152
1153
1154void DIALOG_PLOT::Plot( wxCommandEvent& event )
1155{
1156 if( m_job )
1157 {
1160 EndModal( wxID_OK );
1161 }
1162 else
1163 {
1164 BOARD* board = m_editFrame->GetBoard();
1165
1167
1169
1170 m_plotOpts.SetColorSettings( ::GetColorSettings( cfg ? cfg->m_ColorTheme : DEFAULT_THEME ) );
1171
1172 m_plotOpts.SetSketchPadLineWidth( board->GetDesignSettings().GetLineThickness( F_Fab ) );
1173
1174 // If no layer selected, we have nothing plotted.
1175 // Prompt user if it happens because he could think there is a bug in Pcbnew.
1176 if( !m_plotOpts.GetLayerSelection().any() )
1177 {
1178 DisplayError( this, _( "No layer selected, Nothing to plot" ) );
1179 return;
1180 }
1181
1182 // Create output directory if it does not exist (also transform it in absolute form).
1183 // Bail if it fails.
1184
1185 std::function<bool( wxString* )> textResolver =
1186 [&]( wxString* token ) -> bool
1187 {
1188 // Handles board->GetTitleBlock() *and* board->GetProject()
1189 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
1190 };
1191
1192 wxString path = m_plotOpts.GetOutputDirectory();
1193 path = ExpandTextVars( path, &textResolver );
1195
1196 wxFileName outputDir = wxFileName::DirName( path );
1197 wxString boardFilename = m_editFrame->GetBoard()->GetFileName();
1198 REPORTER& reporter = m_messagesPanel->Reporter();
1199
1200 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
1201 {
1202 wxString msg;
1203 msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
1204 DisplayError( this, msg );
1205 return;
1206 }
1207
1208 if( m_zoneFillCheck->GetValue() )
1209 m_editFrame->GetToolManager()->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( this );
1210
1211 m_plotOpts.SetAutoScale( false );
1212
1213 switch( m_plotOpts.GetScaleSelection() )
1214 {
1215 default: m_plotOpts.SetScale( 1 ); break;
1216 case 0: m_plotOpts.SetAutoScale( true ); break;
1217 case 2: m_plotOpts.SetScale( 1.5 ); break;
1218 case 3: m_plotOpts.SetScale( 2 ); break;
1219 case 4: m_plotOpts.SetScale( 3 ); break;
1220 }
1221
1222 /* If the scale factor edit controls are disabled or the scale value
1223 * is 0, don't adjust the base scale factor. This fixes a bug when
1224 * the default scale adjust is initialized to 0 and saved in program
1225 * settings resulting in a divide by zero fault.
1226 */
1228 {
1229 if( m_XScaleAdjust != 0.0 )
1230 m_plotOpts.SetFineScaleAdjustX( m_XScaleAdjust );
1231
1232 if( m_YScaleAdjust != 0.0 )
1233 m_plotOpts.SetFineScaleAdjustY( m_YScaleAdjust );
1234
1235 m_plotOpts.SetWidthAdjust( m_PSWidthAdjust );
1236 }
1237
1238 // Test for a reasonable scale value
1239 // XXX could this actually happen? isn't it constrained in the apply function?
1240 if( m_plotOpts.GetScale() < PLOT_MIN_SCALE )
1241 DisplayInfoMessage( this, _( "Warning: Scale option set to a very small value" ) );
1242
1243 if( m_plotOpts.GetScale() > PLOT_MAX_SCALE )
1244 DisplayInfoMessage( this, _( "Warning: Scale option set to a very large value" ) );
1245
1246
1247 // Save the current plot options in the board
1248 m_editFrame->SetPlotSettings( m_plotOpts );
1249
1250 PCB_PLOTTER pcbPlotter( m_editFrame->GetBoard(), &reporter, m_plotOpts );
1251
1252 LSEQ layersToPlot = m_plotOpts.GetLayerSelection().UIOrder();
1253
1254 wxArrayInt plotOnAllLayers;
1255 LSEQ commonLayers;
1256
1257 if( m_plotAllLayersList->GetCheckedItems( plotOnAllLayers ) )
1258 {
1259 size_t count = plotOnAllLayers.GetCount();
1260
1261 for( size_t i = 0; i < count; i++ )
1262 {
1263 int index = plotOnAllLayers.Item( i );
1265
1266 commonLayers.push_back( client_layer );
1267 }
1268 }
1269
1270 pcbPlotter.Plot( outputDir.GetPath(), layersToPlot, commonLayers, m_useGerberExtensions->GetValue() );
1271 }
1272}
1273
1274
1275
1276void DIALOG_PLOT::onRunDRC( wxCommandEvent& event )
1277{
1278 PCB_EDIT_FRAME* parent = dynamic_cast<PCB_EDIT_FRAME*>( GetParent() );
1279
1280 if( parent )
1281 {
1282 DRC_TOOL* drcTool = parent->GetToolManager()->GetTool<DRC_TOOL>();
1283
1284 // First close an existing dialog if open
1285 // (low probability, but can happen)
1286 drcTool->DestroyDRCDialog();
1287
1288 // Open a new drc dialog, with the right parent frame, and in Modal Mode
1289 drcTool->ShowDRCDialog( this );
1290
1291 // Update DRC warnings on return to this dialog
1292 reInitDialog();
1293 }
1294}
1295
1296
1297void DIALOG_PLOT::onOpenOutputDirectory( wxCommandEvent& event )
1298{
1299 std::function<bool( wxString* )> textResolver = [&]( wxString* token ) -> bool
1300 {
1301 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
1302 };
1303
1304 wxString path = m_outputDirectoryName->GetValue();
1305 path = ExpandTextVars( path, &textResolver );
1307 path = Prj().AbsolutePath( path );
1308
1309 if( !wxDirExists( path ) )
1310 {
1311 DisplayError( this, wxString::Format( _( "Directory '%s' does not exist." ), path ) );
1312 return;
1313 }
1314
1315 wxLaunchDefaultApplication( path );
1316}
1317
1318
1319void DIALOG_PLOT::onBoardSetup( wxHyperlinkEvent& aEvent )
1320{
1321 PCB_EDIT_FRAME* parent = dynamic_cast<PCB_EDIT_FRAME*>( GetParent() );
1322
1323 if( parent )
1324 {
1325 parent->ShowBoardSetupDialog( _( "Solder Mask/Paste" ) );
1326
1327 // Update warnings on return to this dialog
1328 reInitDialog();
1329 }
1330}
1331
1332
1333void DIALOG_PLOT::onPlotAllListMoveUp( wxCommandEvent& aEvent )
1334{
1335 if( m_plotAllLayersList->CanMoveCurrentUp() )
1336 m_plotAllLayersList->MoveCurrentUp();
1337}
1338
1339
1340void DIALOG_PLOT::onPlotAllListMoveDown( wxCommandEvent& aEvent )
1341{
1342 if( m_plotAllLayersList->CanMoveCurrentDown() )
1343 m_plotAllLayersList->MoveCurrentDown();
1344}
1345
1346
1347void DIALOG_PLOT::onDNPCheckbox( wxCommandEvent& aEvent )
1348{
1349 m_hideDNP->Enable( aEvent.IsChecked() );
1350 m_crossoutDNP->Enable( aEvent.IsChecked() );
1351}
1352
1353
1354void DIALOG_PLOT::onSketchPads( wxCommandEvent& aEvent )
1355{
1356 m_plotPadNumbers->Enable( aEvent.IsChecked() );
1357}
1358
1359
1361{
1362 if( m_PDFColorChoice->GetSelection() == 1 )
1363 {
1364 m_pdfBackgroundColorSwatch->Disable();
1365 m_pdfBackgroundColorText->Disable();
1366 }
1367 else
1368 {
1370 m_pdfBackgroundColorText->Enable();
1371 }
1372}
1373
1374
1375void DIALOG_PLOT::onPDFColorChoice( wxCommandEvent& aEvent )
1376{
1378}
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
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:728
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
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:98
STD_BITMAP_BUTTON * m_bpMoveUp
void onPlotAllListMoveUp(wxCommandEvent &aEvent)
void OnChangeDXFPlotMode(wxCommandEvent &event) override
int m_widthAdjustMinValue
Definition dialog_plot.h:91
UNIT_BINDER m_trackWidthCorrection
Definition dialog_plot.h:94
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:87
wxString m_DRCWarningTemplate
Definition dialog_plot.h:96
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:85
void onOpenOutputDirectory(wxCommandEvent &event) override
void updatePdfColorOptions()
PCB_EDIT_FRAME * m_editFrame
Definition dialog_plot.h:81
virtual ~DIALOG_PLOT()
STD_BITMAP_BUTTON * m_bpMoveDown
void CreateDrillFile(wxCommandEvent &event) override
void onDNPCheckbox(wxCommandEvent &event) override
double m_XScaleAdjust
Definition dialog_plot.h:83
PLOT_FORMAT getPlotFormat()
void transferPlotParamsToJob()
int m_widthAdjustMaxValue
Definition dialog_plot.h:92
void onOutputDirectoryBrowseClicked(wxCommandEvent &event) override
void OnGerberX2Checked(wxCommandEvent &event) override
void SetPlotFormat(wxCommandEvent &event) override
LSEQ m_layerList
Definition dialog_plot.h:82
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:72
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition drc_tool.cpp:123
@ 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:726
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition lset.cpp:387
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition lset.cpp:659
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:591
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:391
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:557
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:61
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:578
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.