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