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 "dialog_gendrill.h"
26
27#include <wx/msgdlg.h>
28#include <wx/dirdlg.h>
29#include <wx/filedlg.h>
30#include <kiplatform/ui.h>
31
32#include <confirm.h>
33#include <core/arraydim.h>
35#include <pcb_edit_frame.h>
36#include <pcbplot.h>
39#include <bitmaps.h>
41#include <footprint.h>
42#include <pad.h>
43#include <pcb_track.h>
44#include <paths.h>
45#include <string_utils.h>
47#include <reporter.h>
49
50// List of allowed precision for EXCELLON files, for integer format. Due to difference between inches and mm,
51// there are 2 precision values, one for inches and one for metric.
52// Note: for decimal format, the precision is not used.
55
56
57/* This function displays the dialog frame for drill tools
58 */
60{
62 DIALOG_GENDRILL dlg( editFrame, editFrame );
63
64 dlg.ShowModal();
65 return 0;
66}
67
68
69DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* aPcbEditFrame, wxWindow* aParent ) :
70 DIALOG_GENDRILL_BASE( aParent ),
71 m_pcbEditFrame( aPcbEditFrame ),
72 m_board( aPcbEditFrame->GetBoard() ),
73 m_plotOpts( aPcbEditFrame->GetPlotSettings() ),
74 m_job( nullptr )
75{
77
78 SetupStandardButtons( { { wxID_OK, _( "Generate" ) },
79 { wxID_CANCEL, _( "Close" ) } } );
80
81 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
82 // non-job versions.
83 m_hash_key = TO_UTF8( GetTitle() );
84
86}
87
88
90 wxWindow* aParent ) :
91 DIALOG_GENDRILL_BASE( aParent ),
92 m_pcbEditFrame( aPcbEditFrame ),
94 m_job( aJob )
95{
97
98 // hide ui elements that dont belong for job config
99 m_buttonReport->Hide();
100 bMainSizer->Remove( bMsgSizer );
101 m_messagesBox->Hide();
102
104
105 SetTitle( m_job->GetSettingsDialogTitle() );
106
107 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
108 // non-job versions.
109 m_hash_key = TO_UTF8( GetTitle() );
110
112}
113
114
116{
117 m_messagesBox->Clear();
118
119 if( !m_job )
120 {
122
123 m_origin->SetSelection( m_plotOpts.GetUseAuxOrigin() ? 1 : 0 );
124
125 // Output directory
126 m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
127 }
128 else
129 {
130 m_browseButton->Hide();
131 m_outputDirectoryName->SetValue( m_job->GetConfiguredOutputPath() );
132
135 m_units->SetSelection( m_job->m_drillUnits == JOB_EXPORT_PCB_DRILL::DRILL_UNITS::INCH );
136 m_zeros->SetSelection( static_cast<int>( m_job->m_zeroFormat ) );
138 m_Check_Minimal->SetValue( m_job->m_excellonMinimalHeader );
139
140 m_origin->SetSelection( m_job->m_drillOrigin == JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN::PLOT );
141
142 m_Check_Mirror->SetValue( m_job->m_excellonMirrorY );
143 m_Check_Merge_PTH_NPTH->SetValue( m_job->m_excellonCombinePTHNPTH );
144 m_choiceDrillMap->SetSelection( static_cast<int>( m_job->m_mapFormat ) );
145 m_altDrillMode->SetValue( !m_job->m_excellonOvalDrillRoute );
146 m_cbGenerateMap->SetValue( m_job->m_generateMap );
147 m_generateTentingLayers->SetValue( m_job->m_generateTenting );
148 }
149
150 wxCommandEvent dummy;
152 return true;
153}
154
155
157{
158 if( !m_job )
159 {
160 genDrillAndMapFiles( true, m_cbGenerateMap->GetValue(), m_generateTentingLayers->GetValue() );
161 // Keep the window open so that the user can see the result
162 return false;
163 }
164 else
165 {
166 m_job->SetConfiguredOutputPath( m_outputDirectoryName->GetValue() );
169 m_job->m_drillUnits = m_units->GetSelection() == 0 ? JOB_EXPORT_PCB_DRILL::DRILL_UNITS::MM
171 m_job->m_drillOrigin = static_cast<JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN>( m_origin->GetSelection() );
172 m_job->m_excellonCombinePTHNPTH = m_Check_Merge_PTH_NPTH->IsChecked();
173 m_job->m_excellonMinimalHeader = m_Check_Minimal->IsChecked();
174 m_job->m_excellonMirrorY = m_Check_Mirror->IsChecked();
175 m_job->m_excellonOvalDrillRoute = !m_altDrillMode->GetValue();
176 m_job->m_mapFormat = static_cast<JOB_EXPORT_PCB_DRILL::MAP_FORMAT>( m_choiceDrillMap->GetSelection() );
177 m_job->m_zeroFormat = static_cast<JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT>( m_zeros->GetSelection() );
178 m_job->m_generateMap = m_cbGenerateMap->IsChecked();
179 m_job->m_generateTenting = m_generateTentingLayers->IsChecked();
180 }
181
182 return true;
183}
184
185
186void DIALOG_GENDRILL::onFileFormatSelection( wxCommandEvent& event )
187{
188 bool enbl_Excellon = m_rbExcellon->GetValue();
189
190 m_unitsLabel->Enable( enbl_Excellon );
191 m_units->Enable( enbl_Excellon );
192 m_zerosLabel->Enable( enbl_Excellon );
193 m_zeros->Enable( enbl_Excellon );
194 m_Check_Mirror->Enable( enbl_Excellon );
195 m_Check_Minimal->Enable( enbl_Excellon );
196 m_Check_Merge_PTH_NPTH->Enable( enbl_Excellon );
197 m_altDrillMode->Enable( enbl_Excellon );
198 m_generateTentingLayers->Enable( !enbl_Excellon );
199
200 if( enbl_Excellon )
201 {
203 }
204 else
205 {
206 m_precisionLabel->Enable( true );
207 m_staticTextPrecision->Enable( true );
208 m_staticTextPrecision->SetLabel( m_plotOpts.GetGerberPrecision() == 6 ? wxT( "4.6" )
209 : wxT( "4.5" ) );
210 }
211}
212
213
215{
216 // Set output directory and replace backslashes with forward ones
217 wxString dirStr = m_outputDirectoryName->GetValue();
218 dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
219 m_plotOpts.SetOutputDirectory( dirStr );
220 m_plotOpts.SetUseAuxOrigin( m_origin->GetSelection() == 1 );
221
222 if( !m_plotOpts.IsSameAs( m_board->GetPlotOptions() ) )
223 {
224 m_board->SetPlotOptions( m_plotOpts );
225 m_pcbEditFrame->OnModify();
226 }
227}
228
229
230void DIALOG_GENDRILL::onSelDrillUnitsSelected( wxCommandEvent& event )
231{
233}
234
235
236void DIALOG_GENDRILL::onSelZerosFmtSelected( wxCommandEvent& event )
237{
239}
240
241
243{
244 if( m_units->GetSelection() == 1 )
245 {
246 // Units = inches
247 m_staticTextPrecision->SetLabel( precisionListForInches.GetPrecisionString() );
248 }
249 else
250 {
251 // metric options
252 m_staticTextPrecision->SetLabel( precisionListForMetric.GetPrecisionString() );
253 }
254
255 if( m_zeros->GetSelection() == EXCELLON_WRITER::DECIMAL_FORMAT )
256 {
257 m_precisionLabel->Enable( false );
258 m_staticTextPrecision->Enable( false );
259 }
260 else
261 {
262 m_precisionLabel->Enable( true );
263 m_staticTextPrecision->Enable( true );
264 }
265}
266
267
269{
270 // Build the absolute path of current output directory to preselect it in the file browser.
271 wxString path = ExpandEnvVarSubstitutions( m_outputDirectoryName->GetValue(), &Prj() );
272 path = Prj().AbsolutePath( path );
273
274 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
275
276 if( dirDialog.ShowModal() == wxID_CANCEL )
277 return;
278
279 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
280 wxFileName fn( Prj().AbsolutePath( m_board->GetFileName() ) );
281 wxString defaultPath = fn.GetPathWithSep();
282
283 if( IsOK( this, wxString::Format( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath ) ) )
284 {
285 if( !dirName.MakeRelativeTo( defaultPath ) )
286 {
287 DisplayErrorMessage( this, _( "Cannot make path relative (target volume different from board "
288 "file volume)!" ) );
289 }
290 }
291
292 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
293}
294
295
296void DIALOG_GENDRILL::genDrillAndMapFiles( bool aGenDrill, bool aGenMap, bool aGenTenting )
297{
298 updateConfig(); // set params and Save drill options
299
300 m_pcbEditFrame->ClearMsgPanel();
301 m_messagesBox->Clear();
303
304 const PLOT_FORMAT filefmt[] = {
305 // Keep these format ids in the same order than m_Choice_Drill_Map choices
307 PLOT_FORMAT::GERBER, // Only X2 format because we need the .FileFunction attribute
311 };
312
313 unsigned choice = (unsigned) m_choiceDrillMap->GetSelection();
314
315 if( choice >= arrayDim( filefmt ) )
316 choice = arrayDim( filefmt )-1; // Last choice = PDF
317
318 // Create output directory if it does not exist (also transform it in absolute form).
319 // Bail if it fails.
320
321 std::function<bool( wxString* )> textResolver =
322 [&]( wxString* token ) -> bool
323 {
324 // Handles m_board->GetTitleBlock() *and* m_board->GetProject()
325 return m_board->ResolveTextVar( token, 0 );
326 };
327
328 wxString path = m_plotOpts.GetOutputDirectory();
329 path = ExpandTextVars( path, &textResolver );
331
332 wxFileName outputDir = wxFileName::DirName( path );
333 wxString boardFilename = m_board->GetFileName();
334
335 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
336 {
337 DisplayError( this, wxString::Format( _( "Could not write drill and/or map files to folder '%s'." ),
338 outputDir.GetPath() ) );
339 return;
340 }
341
342 VECTOR2I drillFileOffset;
343 DRILL_PRECISION precision;
344
345 if( m_origin->GetSelection() == 0 )
346 drillFileOffset = VECTOR2I( 0, 0 );
347 else
348 drillFileOffset = m_board->GetDesignSettings().GetAuxOrigin();
349
350 if( m_units->GetSelection() == 0 )
351 precision = precisionListForMetric;
352 else
353 precision = precisionListForInches;
354
355 if( m_rbExcellon->GetValue() )
356 {
357 EXCELLON_WRITER excellonWriter( m_board );
358 excellonWriter.SetFormat( m_units->GetSelection() == 0, (EXCELLON_WRITER::ZEROS_FMT) m_zeros->GetSelection(),
359 precision.m_Lhs, precision.m_Rhs );
360 excellonWriter.SetOptions( m_Check_Mirror->IsChecked(), m_Check_Minimal->IsChecked(), drillFileOffset,
361 m_Check_Merge_PTH_NPTH->IsChecked() );
362 excellonWriter.SetRouteModeForOvalHoles( !m_altDrillMode->GetValue() );
363 excellonWriter.SetMapFileFormat( filefmt[choice] );
364 excellonWriter.SetPageInfo( &m_board->GetPageSettings() );
365
366 excellonWriter.CreateDrillandMapFilesSet( outputDir.GetFullPath(), aGenDrill, aGenMap, &reporter );
367 }
368 else
369 {
370 GERBER_WRITER gerberWriter( m_board );
371 // Set gerber precision: only 5 or 6 digits for mantissa are allowed
372 // (SetFormat() accept 5 or 6, and any other value set the precision to 5)
373 // the integer part precision is always 4, and units always mm
374 gerberWriter.SetFormat( m_plotOpts.GetGerberPrecision() );
375 gerberWriter.SetOptions( drillFileOffset );
376 gerberWriter.SetMapFileFormat( filefmt[choice] );
377 gerberWriter.SetPageInfo( &m_board->GetPageSettings() );
378
379 gerberWriter.CreateDrillandMapFilesSet( outputDir.GetFullPath(), aGenDrill, aGenMap, aGenTenting, &reporter );
380 }
381}
382
383
384void DIALOG_GENDRILL::onGenReportFile( wxCommandEvent& event )
385{
386 updateConfig(); // set params and Save drill options
387
388 wxFileName fn = m_board->GetFileName();
389
390 fn.SetName( fn.GetName() + wxT( "-drl" ) );
391 fn.SetExt( FILEEXT::ReportFileExtension );
392
393 wxString defaultPath = ExpandEnvVarSubstitutions( m_plotOpts.GetOutputDirectory(), &Prj() );
394 defaultPath = Prj().AbsolutePath( defaultPath );
395
396 if( defaultPath.IsEmpty() )
397 defaultPath = PATHS::GetDefaultUserProjectsPath();
398
399 wxFileDialog dlg( this, _( "Save Drill Report File" ), defaultPath, fn.GetFullName(),
400 FILEEXT::ReportFileWildcard(), wxFD_SAVE );
401
403
404 if( dlg.ShowModal() == wxID_CANCEL )
405 return;
406
407 m_messagesBox->Clear();
408 bool success;
409
410 // Info is slightly different between Excellon and Gerber
411 // (file ext, Merge PTH/NPTH option)
412 if( m_rbExcellon->GetValue() == 0 )
413 {
414 EXCELLON_WRITER excellonWriter( m_board );
415 excellonWriter.SetMergeOption( m_Check_Merge_PTH_NPTH->IsChecked() );
416 success = excellonWriter.GenDrillReportFile( dlg.GetPath() );
417 }
418 else
419 {
420 GERBER_WRITER gerberWriter( m_board );
421 success = gerberWriter.GenDrillReportFile( dlg.GetPath() );
422 }
423
424 if( !success )
425 m_messagesBox->AppendText( wxString::Format( _( "Failed to create file '%s'." ), dlg.GetPath() ) );
426 else
427 m_messagesBox->AppendText( wxString::Format( _( "Report file '%s' created." ), dlg.GetPath() ) );
428}
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
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.
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:392
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:186
Generic, UI-independent tool event.
Definition tool_event.h:171
A wrapper for reporting to a wxTextCtrl object.
Definition reporter.h:167
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition common.cpp:558
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:62
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.
Definition common.cpp:579
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
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.
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()
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:717
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.
std::string path
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
Definition of file extensions used in Kicad.