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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include "dialog_gendrill.h"
22
23#include <common.h>
24#include <wx/msgdlg.h>
25#include <wx/dirdlg.h>
26#include <wx/filedlg.h>
27#include <kiplatform/ui.h>
28
29#include <confirm.h>
30#include <core/arraydim.h>
32#include <pcb_edit_frame.h>
33#include <pcbplot.h>
36#include <bitmaps.h>
38#include <footprint.h>
39#include <pad.h>
40#include <pcb_track.h>
41#include <paths.h>
42#include <string_utils.h>
44#include <reporter.h>
46
47// List of allowed precision for EXCELLON files, for integer format. Due to difference between inches and mm,
48// there are 2 precision values, one for inches and one for metric.
49// Note: for decimal format, the precision is not used.
52
53
54/* This function displays the dialog frame for drill tools
55 */
57{
59 DIALOG_GENDRILL dlg( editFrame, editFrame );
60
61 dlg.ShowModal();
62 return 0;
63}
64
65
66DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* aPcbEditFrame, wxWindow* aParent ) :
67 DIALOG_GENDRILL_BASE( aParent ),
68 m_pcbEditFrame( aPcbEditFrame ),
69 m_board( aPcbEditFrame->GetBoard() ),
70 m_plotOpts( aPcbEditFrame->GetPlotSettings() ),
71 m_job( nullptr )
72{
74
75 SetupStandardButtons( { { wxID_OK, _( "Generate" ) },
76 { wxID_CANCEL, _( "Close" ) } } );
77
78 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
79 // non-job versions.
80 m_hash_key = TO_UTF8( GetTitle() );
81
83}
84
85
87 wxWindow* aParent ) :
88 DIALOG_GENDRILL_BASE( aParent ),
89 m_pcbEditFrame( aPcbEditFrame ),
90 m_board( m_pcbEditFrame->GetBoard() ),
91 m_job( aJob )
92{
94
95 // hide ui elements that dont belong for job config
96 m_buttonReport->Hide();
97 bMainSizer->Remove( bMsgSizer );
98 m_messagesBox->Hide();
99
101
102 SetTitle( m_job->GetSettingsDialogTitle() );
103
104 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
105 // non-job versions.
106 m_hash_key = TO_UTF8( GetTitle() );
107
109}
110
111
113{
114 m_messagesBox->Clear();
115
116 if( !m_job )
117 {
119
120 m_origin->SetSelection( m_plotOpts.GetUseAuxOrigin() ? 1 : 0 );
121
122 // Output directory
123 m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
124 }
125 else
126 {
127 m_browseButton->Hide();
128 m_outputDirectoryName->SetValue( m_job->GetConfiguredOutputPath() );
129
132 m_units->SetSelection( m_job->m_drillUnits == JOB_EXPORT_PCB_DRILL::DRILL_UNITS::INCH );
133 m_zeros->SetSelection( static_cast<int>( m_job->m_zeroFormat ) );
135 m_Check_Minimal->SetValue( m_job->m_excellonMinimalHeader );
136
137 m_origin->SetSelection( m_job->m_drillOrigin == JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN::PLOT );
138
139 m_Check_Mirror->SetValue( m_job->m_excellonMirrorY );
140 m_Check_Merge_PTH_NPTH->SetValue( m_job->m_excellonCombinePTHNPTH );
141 m_choiceDrillMap->SetSelection( static_cast<int>( m_job->m_mapFormat ) );
142 m_altDrillMode->SetValue( !m_job->m_excellonOvalDrillRoute );
143 m_cbGenerateMap->SetValue( m_job->m_generateMap );
144 m_generateTentingLayers->SetValue( m_job->m_generateTenting );
145 }
146
147 wxCommandEvent dummy;
149 return true;
150}
151
152
154{
155 if( !m_job )
156 {
157 genDrillAndMapFiles( true, m_cbGenerateMap->GetValue(), m_generateTentingLayers->GetValue() );
158 // Keep the window open so that the user can see the result
159 return false;
160 }
161 else
162 {
163 m_job->SetConfiguredOutputPath( m_outputDirectoryName->GetValue() );
166 m_job->m_drillUnits = m_units->GetSelection() == 0 ? JOB_EXPORT_PCB_DRILL::DRILL_UNITS::MM
168 m_job->m_drillOrigin = static_cast<JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN>( m_origin->GetSelection() );
169 m_job->m_excellonCombinePTHNPTH = m_Check_Merge_PTH_NPTH->IsChecked();
170 m_job->m_excellonMinimalHeader = m_Check_Minimal->IsChecked();
171 m_job->m_excellonMirrorY = m_Check_Mirror->IsChecked();
172 m_job->m_excellonOvalDrillRoute = !m_altDrillMode->GetValue();
173 m_job->m_mapFormat = static_cast<JOB_EXPORT_PCB_DRILL::MAP_FORMAT>( m_choiceDrillMap->GetSelection() );
174 m_job->m_zeroFormat = static_cast<JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT>( m_zeros->GetSelection() );
175 m_job->m_generateMap = m_cbGenerateMap->IsChecked();
176 m_job->m_generateTenting = m_generateTentingLayers->IsChecked();
177 }
178
179 return true;
180}
181
182
183void DIALOG_GENDRILL::onFileFormatSelection( wxCommandEvent& event )
184{
185 bool enbl_Excellon = m_rbExcellon->GetValue();
186
187 m_unitsLabel->Enable( enbl_Excellon );
188 m_units->Enable( enbl_Excellon );
189 m_zerosLabel->Enable( enbl_Excellon );
190 m_zeros->Enable( enbl_Excellon );
191 m_Check_Mirror->Enable( enbl_Excellon );
192 m_Check_Minimal->Enable( enbl_Excellon );
193 m_Check_Merge_PTH_NPTH->Enable( enbl_Excellon );
194 m_altDrillMode->Enable( enbl_Excellon );
195 m_generateTentingLayers->Enable( !enbl_Excellon );
196
197 if( enbl_Excellon )
198 {
200 }
201 else
202 {
203 m_precisionLabel->Enable( true );
204 m_staticTextPrecision->Enable( true );
205 m_staticTextPrecision->SetLabel( m_plotOpts.GetGerberPrecision() == 6 ? wxT( "4.6" )
206 : wxT( "4.5" ) );
207 }
208}
209
210
212{
213 // Set output directory and replace backslashes with forward ones
214 wxString dirStr = m_outputDirectoryName->GetValue();
215 dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
216 m_plotOpts.SetOutputDirectory( dirStr );
217 m_plotOpts.SetUseAuxOrigin( m_origin->GetSelection() == 1 );
218
219 if( !m_plotOpts.IsSameAs( m_board->GetPlotOptions() ) )
220 {
221 m_board->SetPlotOptions( m_plotOpts );
222 m_pcbEditFrame->OnModify();
223 }
224}
225
226
227void DIALOG_GENDRILL::onSelDrillUnitsSelected( wxCommandEvent& event )
228{
230}
231
232
233void DIALOG_GENDRILL::onSelZerosFmtSelected( wxCommandEvent& event )
234{
236}
237
238
240{
241 if( m_units->GetSelection() == 1 )
242 {
243 // Units = inches
244 m_staticTextPrecision->SetLabel( precisionListForInches.GetPrecisionString() );
245 }
246 else
247 {
248 // metric options
249 m_staticTextPrecision->SetLabel( precisionListForMetric.GetPrecisionString() );
250 }
251
252 if( m_zeros->GetSelection() == EXCELLON_WRITER::DECIMAL_FORMAT )
253 {
254 m_precisionLabel->Enable( false );
255 m_staticTextPrecision->Enable( false );
256 }
257 else
258 {
259 m_precisionLabel->Enable( true );
260 m_staticTextPrecision->Enable( true );
261 }
262}
263
264
266{
267 // Build the absolute path of current output directory to preselect it in the file browser.
268 wxString path = ResolveProjectPath( m_outputDirectoryName->GetValue(), &Prj() );
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
296 m_pcbEditFrame->ClearMsgPanel();
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
303 PLOT_FORMAT::GERBER, // Only X2 format because we need the .FileFunction attribute
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
324 wxString path = ExpandPathVariables( m_plotOpts.GetOutputDirectory(), &Prj(), &textResolver );
325
326 wxFileName outputDir = wxFileName::DirName( path );
327 wxString boardFilename = m_board->GetFileName();
328
329 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
330 {
331 DisplayError( this, wxString::Format( _( "Could not write drill and/or map files to folder '%s'." ),
332 outputDir.GetPath() ) );
333 return;
334 }
335
336 VECTOR2I drillFileOffset;
337 DRILL_PRECISION precision;
338
339 if( m_origin->GetSelection() == 0 )
340 drillFileOffset = VECTOR2I( 0, 0 );
341 else
342 drillFileOffset = m_board->GetDesignSettings().GetAuxOrigin();
343
344 if( m_units->GetSelection() == 0 )
345 precision = precisionListForMetric;
346 else
347 precision = precisionListForInches;
348
349 if( m_rbExcellon->GetValue() )
350 {
351 EXCELLON_WRITER excellonWriter( m_board );
352 excellonWriter.SetFormat( m_units->GetSelection() == 0, (EXCELLON_WRITER::ZEROS_FMT) m_zeros->GetSelection(),
353 precision.m_Lhs, precision.m_Rhs );
354 excellonWriter.SetOptions( m_Check_Mirror->IsChecked(), m_Check_Minimal->IsChecked(), drillFileOffset,
355 m_Check_Merge_PTH_NPTH->IsChecked() );
356 excellonWriter.SetRouteModeForOvalHoles( !m_altDrillMode->GetValue() );
357 excellonWriter.SetMapFileFormat( filefmt[choice] );
358 excellonWriter.SetPageInfo( &m_board->GetPageSettings() );
359
360 excellonWriter.CreateDrillandMapFilesSet( outputDir.GetFullPath(), aGenDrill, aGenMap, &reporter );
361 }
362 else
363 {
364 GERBER_WRITER gerberWriter( m_board );
365 // Set gerber precision: only 5 or 6 digits for mantissa are allowed
366 // (SetFormat() accept 5 or 6, and any other value set the precision to 5)
367 // the integer part precision is always 4, and units always mm
368 gerberWriter.SetFormat( m_plotOpts.GetGerberPrecision() );
369 gerberWriter.SetOptions( drillFileOffset );
370 gerberWriter.SetMapFileFormat( filefmt[choice] );
371 gerberWriter.SetPageInfo( &m_board->GetPageSettings() );
372
373 gerberWriter.CreateDrillandMapFilesSet( outputDir.GetFullPath(), aGenDrill, aGenMap, aGenTenting, &reporter );
374 }
375}
376
377
378void DIALOG_GENDRILL::onGenReportFile( wxCommandEvent& event )
379{
380 updateConfig(); // set params and Save drill options
381
382 wxFileName fn = m_board->GetFileName();
383
384 fn.SetName( fn.GetName() + wxT( "-drl" ) );
385 fn.SetExt( FILEEXT::ReportFileExtension );
386
387 wxString defaultPath = ResolveProjectPath( m_plotOpts.GetOutputDirectory(), &Prj() );
388
389 if( defaultPath.IsEmpty() )
390 defaultPath = PATHS::GetDefaultUserProjectsPath();
391
392 wxFileDialog dlg( this, _( "Save Drill Report File" ), defaultPath, fn.GetFullName(),
393 FILEEXT::ReportFileWildcard(), wxFD_SAVE );
394
396
397 if( dlg.ShowModal() == wxID_CANCEL )
398 return;
399
400 m_messagesBox->Clear();
401 bool success;
402
403 // Info is slightly different between Excellon and Gerber
404 // (file ext, Merge PTH/NPTH option)
405 if( m_rbExcellon->GetValue() == 0 )
406 {
407 EXCELLON_WRITER excellonWriter( m_board );
408 excellonWriter.SetMergeOption( m_Check_Merge_PTH_NPTH->IsChecked() );
409 success = excellonWriter.GenDrillReportFile( dlg.GetPath() );
410 }
411 else
412 {
413 GERBER_WRITER gerberWriter( m_board );
414 success = gerberWriter.GenDrillReportFile( dlg.GetPath() );
415 }
416
417 if( !success )
418 m_messagesBox->AppendText( wxString::Format( _( "Failed to create file '%s'." ), dlg.GetPath() ) );
419 else
420 m_messagesBox->AppendText( wxString::Format( _( "Report file '%s' created." ), dlg.GetPath() ) );
421}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition arraydim.h:27
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
int GenerateDrillFiles(const TOOL_EVENT &aEvent)
wxStaticText * m_staticTextPrecision
STD_BITMAP_BUTTON * m_browseButton
wxStaticBoxSizer * bMsgSizer
DIALOG_GENDRILL_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Generate Drill Files"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxCheckBox * m_Check_Merge_PTH_NPTH
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
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.
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.
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.
bool GenDrillReportFile(const wxString &aFullFileName, REPORTER *aReporter=nullptr)
Create a plain text report file giving a list of drill values and drill count for through holes,...
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.
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:137
The main frame for Pcbnew.
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:182
Generic, UI-independent tool event.
Definition tool_event.h:167
A wrapper for reporting to a wxTextCtrl object.
Definition reporter.h:218
wxString ExpandPathVariables(const wxString &aPath, const PROJECT *aProject, const std::function< bool(wxString *)> *aTextResolver)
Expand text variables, environment variables and a leading '~' in a user-entered file path.
Definition common.cpp:798
wxString ResolveProjectPath(const wxString &aPath, const PROJECT *aProject, const std::function< bool(wxString *)> *aTextResolver)
Expand a user-entered file path as ExpandPathVariables() does, then anchor a relative result at the p...
Definition common.cpp:817
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:829
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
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()
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition idf_helpers.h:37
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:640
PLOT_FORMAT
The set of supported output plot formats.
Definition plotter.h:65
std::vector< FAB_LAYER_COLOR > dummy
std::string path
IbisParser parser & reporter
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
Definition of file extensions used in Kicad.