KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_plot_schematic.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-2018 Jean-Pierre Charras jp.charras at wanadoo.fr
5 * Copyright (C) 1992-2010 Lorenzo Marcantonio
6 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <bitmaps.h>
28#include <common.h> // For ExpandEnvVarSubstitutions
29#include "string_utils.h"
33#include <eeschema_settings.h>
34#include <kiface_base.h>
35#include <locale_io.h>
38#include <reporter.h>
39#include <trace_helpers.h>
41#include <wx_filename.h>
42#include <pgm_base.h>
43#include <sch_edit_frame.h>
44#include <sch_painter.h>
45
46#include <wx/dirdlg.h>
47#include <wx/msgdlg.h>
49#include <wx/log.h>
50
52
53
54// static members (static to remember last state):
56
57
59 DIALOG_PLOT_SCHEMATIC( aEditFrame, aEditFrame )
60{
61}
62
63
65 JOB_EXPORT_SCH_PLOT* aJob ) :
66 DIALOG_PLOT_SCHEMATIC_BASE( aEditFrame ),
67 m_editFrame( aEditFrame ),
68 m_plotFormat( PLOT_FORMAT::UNDEFINED ),
69 m_defaultLineWidth( aEditFrame, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits ),
70 m_job( aJob )
71{
72 m_configChanged = false;
73
74 if( !m_job )
75 {
76 m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
77 m_MessagesBox->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
78 SetupStandardButtons( { { wxID_OK, _( "Plot All Pages" ) },
79 { wxID_APPLY, _( "Plot Current Page" ) },
80 { wxID_CANCEL, _( "Close" ) } } );
81 }
82 else
83 {
84 SetTitle( m_job->GetSettingsDialogTitle() );
85
86 m_browseButton->Hide();
87 m_MessagesBox->Hide();
88
89 m_sdbSizer1Apply->Hide();
90 m_openFileAfterPlot->Hide();
91
93 }
94
95 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
96 // non-job versions (which have different sizes).
97 m_hash_key = TO_UTF8( GetTitle() );
98
99 initDlg();
100
101 // Now all widgets have the size fixed, call FinishDialogSettings
103}
104
105
107{
108 auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
109 wxASSERT( cfg );
110
111 if( !m_job )
112 {
113 if( cfg )
114 {
115 for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() )
116 {
117 int idx = m_colorTheme->Append( settings->GetName(),
118 static_cast<void*>( settings ) );
119
120 if( settings->GetFilename() == cfg->m_PlotPanel.color_theme )
121 m_colorTheme->SetSelection( idx );
122 }
123
124 m_colorTheme->Enable( cfg->m_PlotPanel.color );
125
126 m_plotBackgroundColor->Enable( cfg->m_PlotPanel.color );
127 m_plotBackgroundColor->SetValue( cfg->m_PlotPanel.background_color );
128
129 // Set color or B&W plot option
130 setModeColor( cfg->m_PlotPanel.color );
131
132 // Set plot or not frame reference option
133 setPlotDrawingSheet( cfg->m_PlotPanel.frame_reference );
134
135 setOpenFileAfterPlot( cfg->m_PlotPanel.open_file_after_plot );
136
137 m_plotPDFPropertyPopups->SetValue( cfg->m_PlotPanel.pdf_property_popups );
138 m_plotPDFHierarchicalLinks->SetValue( cfg->m_PlotPanel.pdf_hierarchical_links );
139 m_plotPDFMetadata->SetValue( cfg->m_PlotPanel.pdf_metadata );
140
141 // Switch to the last save plot format
142 PLOT_FORMAT fmt = static_cast<PLOT_FORMAT>( cfg->m_PlotPanel.format );
143
144 switch( fmt )
145 {
146 default:
147 case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 0 ); break;
148 case PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 1 ); break;
149 case PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
150 case PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
151 case PLOT_FORMAT::HPGL: /* no longer supported */ break;
152 }
153
154 if( fmt == PLOT_FORMAT::DXF )
155 m_plotBackgroundColor->Disable();
156
157 // Set the default line width (pen width which should be used for
158 // items that do not have a pen size defined (like frame ref)
159 // the default line width is stored in mils in config
160 m_defaultLineWidth.SetValue( schIUScale.MilsToIU( cfg->m_Drawing.default_line_thickness ) );
161 }
162
163 // Plot directory
165 wxString path = settings.m_PlotDirectoryName;
166#ifdef __WINDOWS__
167 path.Replace( '/', '\\' );
168#endif
169 m_outputPath->SetValue( path );
170 }
171 else if( m_job )
172 {
174 {
175 int idx = m_colorTheme->Append( settings->GetName(), static_cast<void*>( settings ) );
176
177 if( settings->GetName() == m_job->m_theme )
178 m_colorTheme->SetSelection( idx );
179 }
180
181 if( m_colorTheme->GetSelection() == wxNOT_FOUND )
182 m_colorTheme->SetSelection( 0 );
183
189 m_pageSizeSelect = static_cast<int>( m_job->m_pageSizeSelect );
192
193 // Set the plot format
194 switch( m_job->m_plotFormat )
195 {
196 default:
197 case SCH_PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 0 ); break;
198 case SCH_PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 1 ); break;
199 case SCH_PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
200 case SCH_PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
201 case SCH_PLOT_FORMAT::HPGL: /* no longer supported */ break;
202 }
203
204 // And then hide it
205 m_plotFormatOpt->Hide();
206
208 }
209}
210
211
217{
218 // Build the absolute path of current output directory to preselect it in the file browser.
219 wxString path = ExpandEnvVarSubstitutions( m_outputPath->GetValue(), &Prj() );
220
221 // When editing a schematic that is not part of a project in the stand alone mode, the
222 // project path is not defined so point to the users document path to save the plot files.
223 if( Prj().IsNullProject() )
224 {
226 }
227 else
228 {
229 // Build the absolute path of current output directory to preselect it in the file browser.
230 path = ExpandEnvVarSubstitutions( m_outputPath->GetValue(), &Prj() );
231 path = Prj().AbsolutePath( path );
232 }
233
234 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
235
236 if( dirDialog.ShowModal() == wxID_CANCEL )
237 return;
238
239 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
240
241 wxFileName fn( Prj().AbsolutePath( m_editFrame->Schematic().Root().GetFileName() ) );
242 wxString defaultPath = fn.GetPathWithSep();
243 wxString msg;
244 wxFileName relPathTest; // Used to test if we can make the path relative
245
246 relPathTest.Assign( dirDialog.GetPath() );
247
248 // Test if making the path relative is possible before asking the user if they want to do it
249 if( relPathTest.MakeRelativeTo( defaultPath ) )
250 {
251 msg.Printf( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath );
252
253 wxMessageDialog dialog( this, msg, _( "Plot Output Directory" ),
254 wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
255
256 if( dialog.ShowModal() == wxID_YES )
257 dirName.MakeRelativeTo( defaultPath );
258 }
259
260 m_outputPath->SetValue( dirName.GetFullPath() );
261}
262
263
265{
266 switch( m_plotFormatOpt->GetSelection() )
267 {
268 case 0: return PLOT_FORMAT::POST;
269 default:
270 case 1: return PLOT_FORMAT::PDF;
271 case 2: return PLOT_FORMAT::SVG;
272 case 3: return PLOT_FORMAT::DXF;
273 }
274}
275
276
277void DIALOG_PLOT_SCHEMATIC::OnPageSizeSelected( wxCommandEvent& event )
278{
279 m_pageSizeSelect = m_paperSizeOption->GetSelection();
280}
281
282
283void DIALOG_PLOT_SCHEMATIC::OnUpdateUI( wxUpdateUIEvent& event )
284{
286
287 if( fmt != m_plotFormat )
288 {
289 m_plotFormat = fmt;
290
291 wxArrayString paperSizes;
292 paperSizes.push_back( _( "Schematic size" ) );
293
294 int selection;
295
296 paperSizes.push_back( _( "A4" ) );
297 paperSizes.push_back( _( "A" ) );
298
299 selection = m_pageSizeSelect;
300
301 m_openFileAfterPlot->Enable( fmt == PLOT_FORMAT::PDF );
302 m_plotPDFPropertyPopups->Enable( fmt == PLOT_FORMAT::PDF );
303 m_plotPDFHierarchicalLinks->Enable( fmt == PLOT_FORMAT::PDF );
304 m_plotPDFMetadata->Enable( fmt == PLOT_FORMAT::PDF );
305
306 m_paperSizeOption->Set( paperSizes );
307 m_paperSizeOption->SetSelection( selection );
308
309 m_defaultLineWidth.Enable( fmt == PLOT_FORMAT::POST
310 || fmt == PLOT_FORMAT::PDF
311 || fmt == PLOT_FORMAT::SVG );
312
313 m_plotBackgroundColor->Enable( fmt == PLOT_FORMAT::POST
314 || fmt == PLOT_FORMAT::PDF
315 || fmt == PLOT_FORMAT::SVG );
316 }
317}
318
319
321{
322 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
323 wxASSERT( cfg );
324
326
327 if( cfg )
328 {
331 cfg->m_PlotPanel.color_theme = colors->GetFilename();
333 cfg->m_PlotPanel.format = static_cast<int>( GetPlotFileFormat() );
336 cfg->m_PlotPanel.pdf_metadata = m_plotPDFMetadata->GetValue();
338
339 aSettings->SetDefaultFont( cfg->m_Appearance.default_font );
340 }
341
342 aSettings->LoadColors( colors );
343 aSettings->SetMinPenWidth( (int) m_defaultLineWidth.GetValue() );
344
345 if( m_plotBackgroundColor->GetValue() )
347 else
348 aSettings->SetBackgroundColor( COLOR4D::UNSPECIFIED );
349
350 // Plot directory
351 wxString path = m_outputPath->GetValue();
352 path.Replace( '\\', '/' );
353
355
356 if( settings.m_PlotDirectoryName != path )
357 m_configChanged = true;
358
359 settings.m_PlotDirectoryName = path;
360}
361
362
364{
365 int selection = m_colorTheme->GetSelection();
366
367 if( selection < 0 )
368 return ::GetColorSettings( COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT );
369
370 return static_cast<COLOR_SETTINGS*>( m_colorTheme->GetClientData( selection ) );
371}
372
373
374void DIALOG_PLOT_SCHEMATIC::OnPlotCurrent( wxCommandEvent& event )
375{
376 plotSchematic( false );
377}
378
379
380void DIALOG_PLOT_SCHEMATIC::OnPlotAll( wxCommandEvent& event )
381{
382 if( !m_job )
383 {
384 plotSchematic( true );
385 }
386 else
387 {
391
397 m_job->m_plotAll = true;
399
401 m_job->m_theme = colors->GetName();
402
403 event.Skip(); // Allow normal close action
404 }
405}
406
407
409{
410 wxBusyCursor dummy;
411
413 renderSettings.m_ShowHiddenPins = false;
414 renderSettings.m_ShowHiddenFields = false;
415
416 getPlotOptions( &renderSettings );
417
418 std::unique_ptr<SCH_PLOTTER> schPlotter = std::make_unique<SCH_PLOTTER>( m_editFrame );
419
421
422 SCH_PLOT_OPTS plotOpts;
424 plotOpts.m_plotAll = aPlotAll;
425 plotOpts.m_blackAndWhite = !getModeColor();
426 plotOpts.m_useBackgroundColor = m_plotBackgroundColor->GetValue();
427 plotOpts.m_theme = colors->GetFilename();
428 plotOpts.m_PDFPropertyPopups = m_plotPDFPropertyPopups->GetValue();
430 plotOpts.m_PDFMetadata = m_plotPDFMetadata->GetValue();
431 plotOpts.m_outputDirectory = getOutputPath();
434
435 schPlotter->Plot( GetPlotFileFormat(), plotOpts, &renderSettings, &m_MessagesBox->Reporter() );
436
437 if( GetPlotFileFormat() == PLOT_FORMAT::PDF && getOpenFileAfterPlot() )
438 wxLaunchDefaultApplication( schPlotter->GetLastOutputFilePath() );
439}
440
441
443{
444 wxString msg;
445 wxString extMsg;
446 wxFileName fn;
447
448 extMsg.Printf( _( "Falling back to user path '%s'." ), KIPLATFORM::ENV::GetDocumentsPath() );
449
450 // Build the absolute path of current output directory to preselect it in the file browser.
451 std::function<bool( wxString* )> textResolver =
452 [&]( wxString* token ) -> bool
453 {
454 SCHEMATIC& schematic = m_editFrame->Schematic();
455 return schematic.ResolveTextVar( &schematic.CurrentSheet(), token, 0 );
456 };
457
458 wxString path = m_outputPath->GetValue();
459 path = ExpandTextVars( path, &textResolver );
461
462 fn.SetPath( path );
463
464 // If the contents of the path edit control results in an absolute path, return it as is.
465 if( fn.IsAbsolute() )
466 return path;
467
468 // When editing a schematic that is not part of a project in the stand alone mode, the
469 // project path is not defined.
470 if( Prj().IsNullProject() )
471 {
473
474 if( screen && !screen->GetFileName().IsEmpty() )
475 {
476 fn = screen->GetFileName();
477 msg.Printf( _( "Cannot normalize path '%s%s'." ), fn.GetPathWithSep(), path );
478 fn.SetPath( fn.GetPathWithSep() + path );
479
480 // Normalize always returns true for a non-empty file name so clear the file name
481 // and extension so that only the path is normalized.
482 fn.SetName( wxEmptyString );
483 fn.SetExt( wxEmptyString );
484
485 if( fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS ) )
486 {
487 path = fn.GetPath();
488 }
489 else
490 {
491 wxMessageDialog dlg( this, msg, _( "Warning" ), wxOK | wxCENTER | wxRESIZE_BORDER
492 | wxICON_EXCLAMATION | wxSTAY_ON_TOP );
493
494 dlg.SetExtendedMessage( extMsg );
495 dlg.ShowModal();
496
498 }
499 }
500 else
501 {
502 msg = _( "No project or path defined for the current schematic." );
503
504 wxMessageDialog dlg( this, msg, _( "Warning" ), wxOK | wxCENTER | wxRESIZE_BORDER
505 | wxICON_EXCLAMATION | wxSTAY_ON_TOP );
506 dlg.SetExtendedMessage( extMsg );
507 dlg.ShowModal();
508
509 // Always fall back to user's document path if no other absolute path can be normalized.
511 }
512 }
513 else
514 {
515 msg.Printf( _( "Cannot normalize path '%s%s'." ), Prj().GetProjectPath(), path );
516
517 // Build the absolute path of current output directory and the project path.
518 fn.SetPath( Prj().GetProjectPath() + path );
519
520 if( fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS ) )
521 {
522 path = fn.GetPath();
523 }
524 else
525 {
526 wxMessageDialog dlg( this, msg, _( "Warning" ),
527 wxOK | wxCENTER | wxRESIZE_BORDER | wxICON_EXCLAMATION |
528 wxSTAY_ON_TOP );
529
530 dlg.SetExtendedMessage( extMsg );
531 dlg.ShowModal();
532
534 }
535 }
536
537 return path;
538}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:114
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
Color settings are a bit different than most of the settings objects in that there can be more than o...
static const wxString COLOR_BUILTIN_DEFAULT
COLOR4D GetColor(int aLayer) const
const wxString & GetName() const
Class DIALOG_PLOT_SCHEMATIC_BASE.
WX_HTML_REPORT_PANEL * m_MessagesBox
void OnPageSizeSelected(wxCommandEvent &event) override
void OnPlotAll(wxCommandEvent &event) override
void setOpenFileAfterPlot(bool aOpen)
void OnPlotCurrent(wxCommandEvent &event) override
void setModeColor(bool aColor)
void setPlotDrawingSheet(bool aPlot)
JOB_EXPORT_SCH_PLOT * m_job
void getPlotOptions(RENDER_SETTINGS *aSettings)
COLOR_SETTINGS * getColorSettings()
void plotSchematic(bool aPlotAll)
void onOutputDirectoryBrowseClicked(wxCommandEvent &event) override
Set the m_outputDirectoryName variable to the selected directory from directory dialog.
void OnUpdateUI(wxUpdateUIEvent &event) override
DIALOG_PLOT_SCHEMATIC(SCH_EDIT_FRAME *aEditFrame)
wxString getOutputPath()
Determine the best absolute path to plot files given the contents of the path edit control.
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
Definition: dialog_shim.h:194
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
JOB_PAGE_SIZE m_pageSizeSelect
SCH_PLOT_FORMAT m_plotFormat
void SetConfiguredOutputPath(const wxString &aPath)
Sets the configured output path for the job, this path is always saved to file.
Definition: job.cpp:153
virtual wxString GetSettingsDialogTitle() const
Definition: job.cpp:80
wxString GetConfiguredOutputPath() const
Returns the configured output path for the job.
Definition: job.h:227
wxString GetFilename() const
Definition: json_settings.h:81
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
virtual void LoadColors(const COLOR_SETTINGS *aSettings)
void SetDefaultFont(const wxString &aFont)
virtual void SetBackgroundColor(const COLOR4D &aColor)=0
Set the background color.
void SetMinPenWidth(int aWidth)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
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:372
These are loaded from Eeschema settings but then overwritten by the project settings.
Holds all the data relating to one schematic.
Definition: schematic.h:87
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:317
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:213
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
Definition: schematic.cpp:258
SCH_SHEET & Root() const
Definition: schematic.h:139
SCH_SHEET_PATH & CurrentSheet() const
Definition: schematic.h:170
SCH_RENDER_SETTINGS * GetRenderSettings()
Schematic editor (Eeschema) main window.
SCHEMATIC & Schematic() const
const wxString & GetFileName() const
Definition: sch_screen.h:147
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:321
std::vector< COLOR_SETTINGS * > GetColorSettingsList()
void SetBitmap(const wxBitmapBundle &aBmp)
int GetIntValue()
Definition: unit_binder.h:129
virtual long long int GetValue()
Return the current value in Internal Units.
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void SetFileName(const wxString &aReportFileName)
Set the report full file name to the string.
REPORTER & Reporter()
Return the reporter object that reports to this panel.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:353
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition: common.cpp:59
The common library.
#define _(s)
JOB_PAGE_SIZE
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:478
wxString GetDocumentsPath()
Retrieves the operating system specific path for a user's documents.
SETTINGS_MANAGER * GetSettingsManager()
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:893
see class PGM_BASE
PLOT_FORMAT
The set of supported output plot formats.
Definition: plotter.h:64
Plotting engines similar to ps (PostScript, Gerber, svg)
@ PAGE_SIZE_AUTO
Definition: sch_plotter.h:48
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
constexpr int MilsToIU(int mils) const
Definition: base_units.h:97
wxString m_theme
Definition: sch_plotter.h:67
bool m_PDFPropertyPopups
Definition: sch_plotter.h:64
wxString m_outputDirectory
Definition: sch_plotter.h:69
int m_pageSizeSelect
Definition: sch_plotter.h:62
bool m_PDFMetadata
Definition: sch_plotter.h:66
bool m_blackAndWhite
Definition: sch_plotter.h:61
bool m_PDFHierarchicalLinks
Definition: sch_plotter.h:65
bool m_plotHopOver
Definition: sch_plotter.h:60
bool m_useBackgroundColor
Definition: sch_plotter.h:63
bool m_plotDrawingSheet
Definition: sch_plotter.h:57
wxLogTrace helper definitions.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:39