KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_gendrill.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 (C) 1992-2019 Jean_Pierre Charras <jp.charras at wanadoo.fr>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <confirm.h>
26#include <core/arraydim.h>
28#include <pcb_edit_frame.h>
29#include <pcbplot.h>
32#include <bitmaps.h>
34#include <footprint.h>
35#include <pad.h>
36#include <pcb_track.h>
37#include <paths.h>
38#include <dialog_gendrill.h>
40#include <reporter.h>
41#include <wx/msgdlg.h>
42#include <wx/dirdlg.h>
43#include <wx/filedlg.h>
45
46// List of allowed precision for EXCELLON files, for integer format. Due to difference between inches and mm,
47// there are 2 precision values, one for inches and one for metric.
48// Note: for decimal format, the precision is not used.
51
52
53/* This function displays the dialog frame for drill tools
54 */
56{
57 PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
58 DIALOG_GENDRILL dlg( editFrame, editFrame );
59
60 dlg.ShowModal();
61 return 0;
62}
63
64
65DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* aPcbEditFrame, wxWindow* aParent ) :
66 DIALOG_GENDRILL_BASE( aParent ),
67 m_pcbEditFrame( aPcbEditFrame ),
68 m_board( aPcbEditFrame->GetBoard() ),
69 m_plotOpts( aPcbEditFrame->GetPlotSettings() ),
70 m_job( nullptr )
71{
72 m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
73
74 SetupStandardButtons( { { wxID_OK, _( "Generate" ) },
75 { wxID_CANCEL, _( "Close" ) } } );
76
77 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
78 // non-job versions.
79 m_hash_key = TO_UTF8( GetTitle() );
80
82}
83
84
86 wxWindow* aParent ) :
87 DIALOG_GENDRILL_BASE( aParent ),
88 m_pcbEditFrame( aPcbEditFrame ),
89 m_board( m_pcbEditFrame->GetBoard() ),
90 m_job( aJob )
91{
92 m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
93
94 // hide ui elements that dont belong for job config
95 m_buttonReport->Hide();
96 bMainSizer->Remove( bMsgSizer );
97 m_messagesBox->Hide();
98
100
101 SetTitle( m_job->GetSettingsDialogTitle() );
102
103 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
104 // non-job versions.
105 m_hash_key = TO_UTF8( GetTitle() );
106
108}
109
110
112{
113 m_messagesBox->Clear();
114
115 if( !m_job )
116 {
118
119 m_origin->SetSelection( m_plotOpts.GetUseAuxOrigin() ? 1 : 0 );
120
121 // Output directory
123 }
124 else
125 {
126 m_browseButton->Hide();
128
132 m_zeros->SetSelection( static_cast<int>( m_job->m_zeroFormat ) );
135
137
140 m_choiceDrillMap->SetSelection( static_cast<int>( m_job->m_mapFormat ) );
142 m_cbGenerateMap->SetValue( m_job->m_generateMap );
144 }
145
146 wxCommandEvent dummy;
148 return true;
149}
150
151
153{
154 if( !m_job )
155 {
156 genDrillAndMapFiles( true, m_cbGenerateMap->GetValue(), m_generateTentingLayers->GetValue() );
157 // Keep the window open so that the user can see the result
158 return false;
159 }
160 else
161 {
167 m_job->m_drillOrigin = static_cast<JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN>( m_origin->GetSelection() );
170 m_job->m_excellonMirrorY = m_Check_Mirror->IsChecked();
172 m_job->m_mapFormat = static_cast<JOB_EXPORT_PCB_DRILL::MAP_FORMAT>( m_choiceDrillMap->GetSelection() );
173 m_job->m_zeroFormat = static_cast<JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT>( m_zeros->GetSelection() );
174 m_job->m_generateMap = m_cbGenerateMap->IsChecked();
176 }
177
178 return true;
179}
180
181
182void DIALOG_GENDRILL::onFileFormatSelection( wxCommandEvent& event )
183{
184 bool enbl_Excellon = m_rbExcellon->GetValue();
185
186 m_unitsLabel->Enable( enbl_Excellon );
187 m_units->Enable( enbl_Excellon );
188 m_zerosLabel->Enable( enbl_Excellon );
189 m_zeros->Enable( enbl_Excellon );
190 m_Check_Mirror->Enable( enbl_Excellon );
191 m_Check_Minimal->Enable( enbl_Excellon );
192 m_Check_Merge_PTH_NPTH->Enable( enbl_Excellon );
193 m_altDrillMode->Enable( enbl_Excellon );
194 m_generateTentingLayers->Enable( !enbl_Excellon );
195
196 if( enbl_Excellon )
197 {
199 }
200 else
201 {
202 m_precisionLabel->Enable( true );
203 m_staticTextPrecision->Enable( true );
204 m_staticTextPrecision->SetLabel( m_plotOpts.GetGerberPrecision() == 6 ? wxT( "4.6" )
205 : wxT( "4.5" ) );
206 }
207}
208
209
211{
212 // Set output directory and replace backslashes with forward ones
213 wxString dirStr = m_outputDirectoryName->GetValue();
214 dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
216 m_plotOpts.SetUseAuxOrigin( m_origin->GetSelection() == 1 );
217
219 {
222 }
223}
224
225
226void DIALOG_GENDRILL::onSelDrillUnitsSelected( wxCommandEvent& event )
227{
229}
230
231
232void DIALOG_GENDRILL::onSelZerosFmtSelected( wxCommandEvent& event )
233{
235}
236
237
239{
240 if( m_units->GetSelection() == 1 )
241 {
242 // Units = inches
244 }
245 else
246 {
247 // metric options
249 }
250
251 if( m_zeros->GetSelection() == EXCELLON_WRITER::DECIMAL_FORMAT )
252 {
253 m_precisionLabel->Enable( false );
254 m_staticTextPrecision->Enable( false );
255 }
256 else
257 {
258 m_precisionLabel->Enable( true );
259 m_staticTextPrecision->Enable( true );
260 }
261}
262
263
265{
266 // Build the absolute path of current output directory to preselect it in the file browser.
267 wxString path = ExpandEnvVarSubstitutions( m_outputDirectoryName->GetValue(), &Prj() );
268 path = Prj().AbsolutePath( path );
269
270 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
271
272 if( dirDialog.ShowModal() == wxID_CANCEL )
273 return;
274
275 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
276 wxFileName fn( Prj().AbsolutePath( m_board->GetFileName() ) );
277 wxString defaultPath = fn.GetPathWithSep();
278
279 if( IsOK( this, wxString::Format( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath ) ) )
280 {
281 if( !dirName.MakeRelativeTo( defaultPath ) )
282 {
283 DisplayErrorMessage( this, _( "Cannot make path relative (target volume different from board "
284 "file volume)!" ) );
285 }
286 }
287
288 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
289}
290
291
292void DIALOG_GENDRILL::genDrillAndMapFiles( bool aGenDrill, bool aGenMap, bool aGenTenting )
293{
294 updateConfig(); // set params and Save drill options
295
297 m_messagesBox->Clear();
299
300 const PLOT_FORMAT filefmt[] = {
301 // Keep these format ids in the same order than m_Choice_Drill_Map choices
302 PLOT_FORMAT::POST,
303 PLOT_FORMAT::GERBER, // Only X2 format because we need the .FileFunction attribute
304 PLOT_FORMAT::DXF,
305 PLOT_FORMAT::SVG,
306 PLOT_FORMAT::PDF
307 };
308
309 unsigned choice = (unsigned) m_choiceDrillMap->GetSelection();
310
311 if( choice >= arrayDim( filefmt ) )
312 choice = arrayDim( filefmt )-1; // Last choice = PDF
313
314 // Create output directory if it does not exist (also transform it in absolute form).
315 // Bail if it fails.
316
317 std::function<bool( wxString* )> textResolver =
318 [&]( wxString* token ) -> bool
319 {
320 // Handles m_board->GetTitleBlock() *and* m_board->GetProject()
321 return m_board->ResolveTextVar( token, 0 );
322 };
323
325 path = ExpandTextVars( path, &textResolver );
326 path = ExpandEnvVarSubstitutions( path, nullptr );
327
328 wxFileName outputDir = wxFileName::DirName( path );
329 wxString boardFilename = m_board->GetFileName();
330
331 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
332 {
333 DisplayError( this, wxString::Format( _( "Could not write drill and/or map files to folder '%s'." ),
334 outputDir.GetPath() ) );
335 return;
336 }
337
338 VECTOR2I drillFileOffset;
339 DRILL_PRECISION precision;
340
341 if( m_origin->GetSelection() == 0 )
342 drillFileOffset = VECTOR2I( 0, 0 );
343 else
344 drillFileOffset = m_board->GetDesignSettings().GetAuxOrigin();
345
346 if( m_units->GetSelection() == 0 )
347 precision = precisionListForMetric;
348 else
349 precision = precisionListForInches;
350
351 if( m_rbExcellon->GetValue() )
352 {
353 EXCELLON_WRITER excellonWriter( m_board );
354 excellonWriter.SetFormat( m_units->GetSelection() == 0, (EXCELLON_WRITER::ZEROS_FMT) m_zeros->GetSelection(),
355 precision.m_Lhs, precision.m_Rhs );
356 excellonWriter.SetOptions( m_Check_Mirror->IsChecked(), m_Check_Minimal->IsChecked(), drillFileOffset,
357 m_Check_Merge_PTH_NPTH->IsChecked() );
358 excellonWriter.SetRouteModeForOvalHoles( !m_altDrillMode->GetValue() );
359 excellonWriter.SetMapFileFormat( filefmt[choice] );
360 excellonWriter.SetPageInfo( &m_board->GetPageSettings() );
361
362 excellonWriter.CreateDrillandMapFilesSet( outputDir.GetFullPath(), aGenDrill, aGenMap, &reporter );
363 }
364 else
365 {
366 GERBER_WRITER gerberWriter( m_board );
367 // Set gerber precision: only 5 or 6 digits for mantissa are allowed
368 // (SetFormat() accept 5 or 6, and any other value set the precision to 5)
369 // the integer part precision is always 4, and units always mm
370 gerberWriter.SetFormat( m_plotOpts.GetGerberPrecision() );
371 gerberWriter.SetOptions( drillFileOffset );
372 gerberWriter.SetMapFileFormat( filefmt[choice] );
373 gerberWriter.SetPageInfo( &m_board->GetPageSettings() );
374
375 gerberWriter.CreateDrillandMapFilesSet( outputDir.GetFullPath(), aGenDrill, aGenMap, aGenTenting, &reporter );
376 }
377}
378
379
380void DIALOG_GENDRILL::onGenReportFile( wxCommandEvent& event )
381{
382 updateConfig(); // set params and Save drill options
383
384 wxFileName fn = m_board->GetFileName();
385
386 fn.SetName( fn.GetName() + wxT( "-drl" ) );
387 fn.SetExt( FILEEXT::ReportFileExtension );
388
389 wxString defaultPath = ExpandEnvVarSubstitutions( m_plotOpts.GetOutputDirectory(), &Prj() );
390 defaultPath = Prj().AbsolutePath( defaultPath );
391
392 if( defaultPath.IsEmpty() )
393 defaultPath = PATHS::GetDefaultUserProjectsPath();
394
395 wxFileDialog dlg( this, _( "Save Drill Report File" ), defaultPath, fn.GetFullName(),
396 FILEEXT::ReportFileWildcard(), wxFD_SAVE );
397
398 if( dlg.ShowModal() == wxID_CANCEL )
399 return;
400
401 m_messagesBox->Clear();
402 bool success;
403
404 // Info is slightly different between Excellon and Gerber
405 // (file ext, Merge PTH/NPTH option)
406 if( m_rbExcellon->GetValue() == 0 )
407 {
408 EXCELLON_WRITER excellonWriter( m_board );
409 excellonWriter.SetMergeOption( m_Check_Merge_PTH_NPTH->IsChecked() );
410 success = excellonWriter.GenDrillReportFile( dlg.GetPath() );
411 }
412 else
413 {
414 GERBER_WRITER gerberWriter( m_board );
415 success = gerberWriter.GenDrillReportFile( dlg.GetPath() );
416 }
417
418 if( !success )
419 m_messagesBox->AppendText( wxString::Format( _( "Failed to create file '%s'." ), dlg.GetPath() ) );
420 else
421 m_messagesBox->AppendText( wxString::Format( _( "Report file '%s' created." ), dlg.GetPath() ) );
422}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
const VECTOR2I & GetAuxOrigin() const
int GenerateDrillFiles(const TOOL_EVENT &aEvent)
void SetPlotOptions(const PCB_PLOT_PARAMS &aOptions)
Definition: board.h:746
const PAGE_INFO & GetPageSettings() const
Definition: board.h:742
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: board.cpp:500
const wxString & GetFileName() const
Definition: board.h:354
const PCB_PLOT_PARAMS & GetPlotOptions() const
Definition: board.h:745
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:1024
Class DIALOG_GENDRILL_BASE.
wxRadioButton * m_rbExcellon
wxStaticText * m_staticTextPrecision
STD_BITMAP_BUTTON * m_browseButton
wxStaticBoxSizer * bMsgSizer
wxRadioButton * m_rbGerberX2
wxCheckBox * m_Check_Merge_PTH_NPTH
wxTextCtrl * m_outputDirectoryName
wxCheckBox * m_generateTentingLayers
wxStaticText * m_precisionLabel
PCB_PLOT_PARAMS m_plotOpts
void onOutputDirectoryBrowseClicked(wxCommandEvent &event) override
void onFileFormatSelection(wxCommandEvent &event) override
void genDrillAndMapFiles(bool aGenDrill, bool aGenMap, bool aGenTenting)
Call to create EXCELLON drill files and/or drill map files.
bool TransferDataFromWindow() override
PCB_EDIT_FRAME * m_pcbEditFrame
DIALOG_GENDRILL(PCB_EDIT_FRAME *aPcbEditFrame, wxWindow *aParent)
bool TransferDataToWindow() override
void onSelZerosFmtSelected(wxCommandEvent &event) override
void onGenReportFile(wxCommandEvent &event) override
JOB_EXPORT_PCB_DRILL * m_job
void onSelDrillUnitsSelected(wxCommandEvent &event) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:236
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
int ShowModal() override
Helper to handle drill precision format in excellon files.
virtual void ClearMsgPanel()
Clear all messages from the message panel.
Create Excellon drill, drill map, and drill report files.
void SetFormat(bool aMetric, ZEROS_FMT aZerosFmt=DECIMAL_FORMAT, int aLeftDigits=0, int aRightDigits=0)
Initialize internal parameters to match the given format.
bool CreateDrillandMapFilesSet(const wxString &aPlotDirectory, bool aGenDrill, bool aGenMap, REPORTER *aReporter=nullptr)
Create the full set of Excellon drill file for the board.
void SetOptions(bool aMirror, bool aMinimalHeader, const VECTOR2I &aOffset, bool aMerge_PTH_NPTH)
Initialize internal parameters to match drill options.
void SetRouteModeForOvalHoles(bool aUseRouteModeForOvalHoles)
void SetMapFileFormat(PLOT_FORMAT aMapFmt)
Initialize the format for the drill map file.
bool GenDrillReportFile(const wxString &aFullFileName)
Create a plain text report file giving a list of drill values and drill count for through holes,...
void SetMergeOption(bool aMerge)
Set the option to make separate drill files for PTH and NPTH.
void SetPageInfo(const PAGE_INFO *aPageInfo)
Set the page info used to plot drill maps.
Used to create Gerber drill files.
bool CreateDrillandMapFilesSet(const wxString &aPlotDirectory, bool aGenDrill, bool aGenMap, bool aGenTenting, REPORTER *aReporter=nullptr)
Create the full set of Excellon drill file for the board filenames are computed from the board name,...
void SetOptions(const VECTOR2I &aOffset)
Initialize internal parameters to match drill options.
void SetFormat(int aRightDigits=6)
Initialize internal parameters to match the given format.
wxString GetSettingsDialogTitle() const override
void SetConfiguredOutputPath(const wxString &aPath)
Sets the configured output path for the job, this path is always saved to file.
Definition: job.cpp:153
wxString GetConfiguredOutputPath() const
Returns the configured output path for the job.
Definition: job.h:232
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:136
The main frame for Pcbnew.
void OnModify() override
Must be called after a board change to set the modified flag.
bool GetUseAuxOrigin() const
void SetOutputDirectory(const wxString &aDir)
wxString GetOutputDirectory() const
int GetGerberPrecision() const
bool IsSameAs(const PCB_PLOT_PARAMS &aPcbPlotParams) const
Compare current settings to aPcbPlotParams, including not saved parameters in brd file.
void SetUseAuxOrigin(bool aAux)
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:373
void SetBitmap(const wxBitmapBundle &aBmp)
Generic, UI-independent tool event.
Definition: tool_event.h:168
A wrapper for reporting to a wxTextCtrl object.
Definition: reporter.h:164
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:355
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition: common.cpp:59
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.
Definition: common.cpp:376
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:251
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:169
This file is part of the common library.
static DRILL_PRECISION precisionListForInches(2, 4)
static DRILL_PRECISION precisionListForMetric(3, 3)
#define _(s)
Classes used in drill files, map files and report files generation.
Classes used in drill files, map files and report files generation.
static const std::string ReportFileExtension
static wxString ReportFileWildcard()
BOARD * GetBoard()
PLOT_FORMAT
The set of supported output plot formats.
Definition: plotter.h:64
std::vector< FAB_LAYER_COLOR > dummy
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:429
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
Definition of file extensions used in Kicad.