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 (C) 1992-2023 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
32#include <eeschema_settings.h>
33#include <kiface_base.h>
34#include <locale_io.h>
38#include <reporter.h>
39#include <trace_helpers.h>
42#include <wx_filename.h>
43
44#include <sch_edit_frame.h>
45#include <sch_painter.h>
46#include <schematic.h>
47#include <sch_screen.h>
48
49#include <wx/dirdlg.h>
50#include <wx/msgdlg.h>
52#include <wx/log.h>
53
54
55// static members (static to remember last state):
58
59
62 m_parent( parent ),
63 m_plotFormat( PLOT_FORMAT::UNDEFINED ),
64 m_HPGLPenSize( 1.0 ),
65 m_defaultLineWidth( parent, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits ),
66 m_penWidth( parent, m_penWidthLabel, m_penWidthCtrl, m_penWidthUnits )
67{
68 m_configChanged = false;
69
70 m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
71
72 m_MessagesBox->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
73
74 SetupStandardButtons( { { wxID_OK, _( "Plot All Pages" ) },
75 { wxID_APPLY, _( "Plot Current Page" ) },
76 { wxID_CANCEL, _( "Close" ) } } );
77
78 initDlg();
79
80 // Now all widgets have the size fixed, call FinishDialogSettings
82}
83
84
86{
87 auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
88 wxASSERT( cfg );
89
90 if( cfg )
91 {
93 {
94 int idx = m_colorTheme->Append( settings->GetName(), static_cast<void*>( settings ) );
95
96 if( settings->GetFilename() == cfg->m_PlotPanel.color_theme )
97 m_colorTheme->SetSelection( idx );
98 }
99
100 m_colorTheme->Enable( cfg->m_PlotPanel.color );
101
102 m_plotBackgroundColor->Enable( cfg->m_PlotPanel.color );
103 m_plotBackgroundColor->SetValue( cfg->m_PlotPanel.background_color );
104
105 // Set color or B&W plot option
106 setModeColor( cfg->m_PlotPanel.color );
107
108 // Set plot or not frame reference option
109 setPlotDrawingSheet( cfg->m_PlotPanel.frame_reference );
110
111 setOpenFileAfterPlot( cfg->m_PlotPanel.open_file_after_plot );
112
113 m_plotPDFPropertyPopups->SetValue( cfg->m_PlotPanel.pdf_property_popups );
114
115 // HPGL plot origin and unit system configuration
116 m_plotOriginOpt->SetSelection( cfg->m_PlotPanel.hpgl_origin );
117
118 m_HPGLPaperSizeSelect = static_cast<HPGL_PAGE_SIZE>( cfg->m_PlotPanel.hpgl_paper_size );
119
120 // HPGL Pen Size is stored in mm in config
121 m_HPGLPenSize = cfg->m_PlotPanel.hpgl_pen_size * schIUScale.IU_PER_MM;
122
123 // Switch to the last save plot format
124 PLOT_FORMAT fmt = static_cast<PLOT_FORMAT>( cfg->m_PlotPanel.format );
125
126 switch( fmt )
127 {
128 default:
129 case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 0 ); break;
130 case PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 1 ); break;
131 case PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
132 case PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
133 case PLOT_FORMAT::HPGL: m_plotFormatOpt->SetSelection( 4 ); break;
134 }
135
136 if( fmt == PLOT_FORMAT::DXF || fmt == PLOT_FORMAT::HPGL )
137 m_plotBackgroundColor->Disable();
138
139 // Set the default line width (pen width which should be used for
140 // items that do not have a pen size defined (like frame ref)
141 // the default line width is stored in mils in config
142 m_defaultLineWidth.SetValue( schIUScale.MilsToIU( cfg->m_Drawing.default_line_thickness ) );
143 }
144
145 // Initialize HPGL specific widgets
147
148 // Plot directory
150 wxString path = settings.m_PlotDirectoryName;
151#ifdef __WINDOWS__
152 path.Replace( '/', '\\' );
153#endif
154 m_outputDirectoryName->SetValue( path );
155}
156
157
163{
164 // Build the absolute path of current output directory to preselect it in the file browser.
165 wxString path = ExpandEnvVarSubstitutions( m_outputDirectoryName->GetValue(), &Prj() );
166
167 // When editing a schematic that is not part of a project in the stand alone mode, the
168 // project path is not defined so point to the users document path to save the plot files.
169 if( Prj().IsNullProject() )
170 {
172 }
173 else
174 {
175 // Build the absolute path of current output directory to preselect it in the file browser.
177 path = Prj().AbsolutePath( path );
178 }
179
180 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
181
182 if( dirDialog.ShowModal() == wxID_CANCEL )
183 return;
184
185 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
186
187 wxFileName fn( Prj().AbsolutePath( m_parent->Schematic().Root().GetFileName() ) );
188 wxString defaultPath = fn.GetPathWithSep();
189 wxString msg;
190 wxFileName relPathTest; // Used to test if we can make the path relative
191
192 relPathTest.Assign( dirDialog.GetPath() );
193
194 // Test if making the path relative is possible before asking the user if they want to do it
195 if( relPathTest.MakeRelativeTo( defaultPath ) )
196 {
197 msg.Printf( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath );
198
199 wxMessageDialog dialog( this, msg, _( "Plot Output Directory" ),
200 wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
201
202 if( dialog.ShowModal() == wxID_YES )
203 dirName.MakeRelativeTo( defaultPath );
204 }
205
206 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
207}
208
209
211{
212 switch( m_plotFormatOpt->GetSelection() )
213 {
214 default:
215 case 0: return PLOT_FORMAT::POST;
216 case 1: return PLOT_FORMAT::PDF;
217 case 2: return PLOT_FORMAT::SVG;
218 case 3: return PLOT_FORMAT::DXF;
219 case 4: return PLOT_FORMAT::HPGL;
220 }
221}
222
223
224void DIALOG_PLOT_SCHEMATIC::OnPageSizeSelected( wxCommandEvent& event )
225{
226 if( GetPlotFileFormat() == PLOT_FORMAT::HPGL )
227 m_HPGLPaperSizeSelect = static_cast<HPGL_PAGE_SIZE>( m_paperSizeOption->GetSelection() );
228 else
229 m_pageSizeSelect = m_paperSizeOption->GetSelection();
230}
231
232
233void DIALOG_PLOT_SCHEMATIC::OnUpdateUI( wxUpdateUIEvent& event )
234{
236
237 if( fmt != m_plotFormat )
238 {
239 m_plotFormat = fmt;
240
241 wxArrayString paperSizes;
242 paperSizes.push_back( _( "Schematic size" ) );
243
244 int selection;
245
246 if( fmt == PLOT_FORMAT::HPGL )
247 {
248 paperSizes.push_back( _( "A5" ) );
249 paperSizes.push_back( _( "A4" ) );
250 paperSizes.push_back( _( "A3" ) );
251 paperSizes.push_back( _( "A2" ) );
252 paperSizes.push_back( _( "A1" ) );
253 paperSizes.push_back( _( "A0" ) );
254 paperSizes.push_back( _( "A" ) );
255 paperSizes.push_back( _( "B" ) );
256 paperSizes.push_back( _( "C" ) );
257 paperSizes.push_back( _( "D" ) );
258 paperSizes.push_back( _( "E" ) );
259
260 selection = static_cast<int>( m_HPGLPaperSizeSelect );
261 }
262 else
263 {
264 paperSizes.push_back( _( "A4" ) );
265 paperSizes.push_back( _( "A" ) );
266
267 selection = m_pageSizeSelect;
268 }
269
270 m_openFileAfterPlot->Enable( fmt == PLOT_FORMAT::PDF );
271 m_plotPDFPropertyPopups->Enable( fmt == PLOT_FORMAT::PDF );
272
273 m_paperSizeOption->Set( paperSizes );
274 m_paperSizeOption->SetSelection( selection );
275
277 fmt == PLOT_FORMAT::POST || fmt == PLOT_FORMAT::PDF || fmt == PLOT_FORMAT::SVG );
278
279 m_plotOriginTitle->Enable( fmt == PLOT_FORMAT::HPGL );
280 m_plotOriginOpt->Enable( fmt == PLOT_FORMAT::HPGL );
281 m_penWidth.Enable( fmt == PLOT_FORMAT::HPGL );
282
283 m_plotBackgroundColor->Enable(
284 fmt == PLOT_FORMAT::POST || fmt == PLOT_FORMAT::PDF || fmt == PLOT_FORMAT::SVG );
285
286 m_colorTheme->Enable( fmt != PLOT_FORMAT::HPGL );
287 m_ModeColorOption->Enable( fmt != PLOT_FORMAT::HPGL );
288 }
289}
290
291
293{
295
296 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
297 wxASSERT( cfg );
298
300
301 if( cfg )
302 {
305 cfg->m_PlotPanel.color_theme = colors->GetFilename();
307 cfg->m_PlotPanel.format = static_cast<int>( GetPlotFileFormat() );
308 cfg->m_PlotPanel.hpgl_origin = m_plotOriginOpt->GetSelection();
309 cfg->m_PlotPanel.hpgl_paper_size = static_cast<int>( m_HPGLPaperSizeSelect );
312
313 // HPGL Pen Size is stored in mm in config
315
316 aSettings->SetDefaultFont( cfg->m_Appearance.default_font );
317 }
318
319 aSettings->LoadColors( colors );
320 aSettings->SetMinPenWidth( (int) m_defaultLineWidth.GetValue() );
321
322 if( m_plotBackgroundColor->GetValue() )
324 else
325 aSettings->SetBackgroundColor( COLOR4D::UNSPECIFIED );
326
327 // Plot directory
328 wxString path = m_outputDirectoryName->GetValue();
329 path.Replace( '\\', '/' );
330
332
333 if( settings.m_PlotDirectoryName != path )
334 m_configChanged = true;
335
336 settings.m_PlotDirectoryName = path;
337}
338
339
341{
342 int selection = m_colorTheme->GetSelection();
343
344 if( selection < 0 )
345 {
348 }
349
350 return static_cast<COLOR_SETTINGS*>( m_colorTheme->GetClientData( selection ) );
351}
352
353
354void DIALOG_PLOT_SCHEMATIC::OnPlotCurrent( wxCommandEvent& event )
355{
356 plotSchematic( false );
357}
358
359
360void DIALOG_PLOT_SCHEMATIC::OnPlotAll( wxCommandEvent& event )
361{
362 plotSchematic( true );
363}
364
365
367{
368 wxBusyCursor dummy;
369
371
372 getPlotOptions( &renderSettings );
373
374 std::unique_ptr<SCH_PLOTTER> schPlotter = std::make_unique<SCH_PLOTTER>( m_parent );
375
377
378 SCH_PLOT_SETTINGS plotSettings;
380 plotSettings.m_plotAll = aPlotAll;
381 plotSettings.m_blackAndWhite = !getModeColor();
382 plotSettings.m_useBackgroundColor = m_plotBackgroundColor->GetValue();
383 plotSettings.m_theme = colors->GetFilename();
384 plotSettings.m_PDFPropertyPopups = m_plotPDFPropertyPopups->GetValue();
385 plotSettings.m_HPGLPaperSizeSelect = static_cast<HPGL_PAGE_SIZE>( m_HPGLPaperSizeSelect );
386 plotSettings.m_HPGLPlotOrigin =
387 static_cast<HPGL_PLOT_ORIGIN_AND_UNITS>( m_plotOriginOpt->GetSelection() );
388 plotSettings.m_HPGLPenSize = m_HPGLPenSize;
389 plotSettings.m_outputDirectory = getOutputPath();
390 plotSettings.m_pageSizeSelect = m_pageSizeSelect;
391
392
393 schPlotter->Plot( GetPlotFileFormat(), plotSettings, &renderSettings,
395
396 if( GetPlotFileFormat() == PLOT_FORMAT::PDF && getOpenFileAfterPlot() )
397 wxLaunchDefaultApplication( schPlotter->GetLastOutputFilePath() );
398}
399
400
402{
404
405 if( m_HPGLPenSize > schIUScale.mmToIU( 2 ) )
407
408 if( m_HPGLPenSize < schIUScale.mmToIU( 0.01 ) )
410}
411
412
414{
415 wxString msg;
416 wxString extMsg;
417 wxFileName fn;
418
419 extMsg.Printf( _( "Falling back to user path '%s'." ), KIPLATFORM::ENV::GetDocumentsPath() );
420
421 // Build the absolute path of current output directory to preselect it in the file browser.
422 std::function<bool( wxString* )> textResolver =
423 [&]( wxString* token ) -> bool
424 {
425 SCHEMATIC& schematic = m_parent->Schematic();
426 return schematic.ResolveTextVar( &schematic.CurrentSheet(), token, 0 );
427 };
428
429 wxString path = m_outputDirectoryName->GetValue();
430 path = ExpandTextVars( path, &textResolver );
432
433 fn.SetPath( path );
434
435 // If the contents of the path edit control results in an absolute path, return it as is.
436 if( fn.IsAbsolute() )
437 return path;
438
439 // When editing a schematic that is not part of a project in the stand alone mode, the
440 // project path is not defined.
441 if( Prj().IsNullProject() )
442 {
444
445 if( screen && !screen->GetFileName().IsEmpty() )
446 {
447 fn = screen->GetFileName();
448 msg.Printf( _( "Cannot normalize path '%s%s'." ), fn.GetPathWithSep(), path );
449 fn.SetPath( fn.GetPathWithSep() + path );
450
451 // Normalize always returns true for a non-empty file name so clear the file name
452 // and extension so that only the path is normalized.
453 fn.SetName( wxEmptyString );
454 fn.SetExt( wxEmptyString );
455
456 if( fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS ) )
457 {
458 path = fn.GetPath();
459 }
460 else
461 {
462 wxMessageDialog dlg( this, msg, _( "Warning" ), wxOK | wxCENTER | wxRESIZE_BORDER
463 | wxICON_EXCLAMATION | wxSTAY_ON_TOP );
464
465 dlg.SetExtendedMessage( extMsg );
466 dlg.ShowModal();
467
469 }
470 }
471 else
472 {
473 msg = _( "No project or path defined for the current schematic." );
474
475 wxMessageDialog dlg( this, msg, _( "Warning" ), wxOK | wxCENTER | wxRESIZE_BORDER
476 | wxICON_EXCLAMATION | wxSTAY_ON_TOP );
477 dlg.SetExtendedMessage( extMsg );
478 dlg.ShowModal();
479
480 // Always fall back to user's document path if no other absolute path can be normalized.
482 }
483 }
484 else
485 {
486 msg.Printf( _( "Cannot normalize path '%s%s'." ), Prj().GetProjectPath(), path );
487
488 // Build the absolute path of current output directory and the project path.
489 fn.SetPath( Prj().GetProjectPath() + path );
490
491 if( fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS ) )
492 {
493 path = fn.GetPath();
494 }
495 else
496 {
497 wxMessageDialog dlg( this, msg, _( "Warning" ),
498 wxOK | wxCENTER | wxRESIZE_BORDER | wxICON_EXCLAMATION |
499 wxSTAY_ON_TOP );
500
501 dlg.SetExtendedMessage( extMsg );
502 dlg.ShowModal();
503
505 }
506 }
507
508 return path;
509}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
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
Class DIALOG_PLOT_SCHEMATIC_BASE.
WX_HTML_REPORT_PANEL * m_MessagesBox
DIALOG_PLOT_SCHEMATIC(SCH_EDIT_FRAME *parent)
void OnPageSizeSelected(wxCommandEvent &event) override
void OnPlotAll(wxCommandEvent &event) override
static HPGL_PAGE_SIZE m_HPGLPaperSizeSelect
void OnOutputDirectoryBrowseClicked(wxCommandEvent &event) override
Set the m_outputDirectoryName variable to the selected directory from directory dialog.
void OnPlotCurrent(wxCommandEvent &event) override
void setModeColor(bool aColor)
void setPlotDrawingSheet(bool aPlot)
void setOpenFileAfterPlot(bool aOpenFileAfterPlot)
void getPlotOptions(RENDER_SETTINGS *aSettings)
COLOR_SETTINGS * getColorSettings()
void plotSchematic(bool aPlotAll)
void OnUpdateUI(wxUpdateUIEvent &event) override
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={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
SETTINGS_MANAGER * GetSettingsManager() const
wxString GetFilename() const
Definition: json_settings.h:73
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)
Store schematic specific render settings.
Definition: sch_painter.h:71
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
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:328
These settings were stored in SCH_BASE_FRAME previously.
Holds all the data relating to one schematic.
Definition: schematic.h:75
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:136
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:209
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:126
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
Definition: schematic.cpp:156
SCH_SHEET & Root() const
Definition: schematic.h:105
KIGFX::SCH_RENDER_SETTINGS * GetRenderSettings()
Schematic editor (Eeschema) main window.
SCHEMATIC & Schematic() const
const wxString & GetFileName() const
Definition: sch_screen.h:144
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:308
COLOR_SETTINGS * GetColorSettings(const wxString &aName="user")
Retrieves a color settings object that applications can read colors from.
std::vector< COLOR_SETTINGS * > GetColorSettingsList()
void SetBitmap(const wxBitmapBundle &aBmp)
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)
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:317
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:58
The common library.
#define _(s)
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:382
wxString GetDocumentsPath()
Retrieves the operating system specific path for a user's documents.
PLOT_FORMAT
The set of supported output plot formats.
Definition: plotter.h:64
Plotting engine (HPGL)
Plotting engines similar to ps (PostScript, Gerber, svg)
@ PAGE_SIZE_AUTO
Definition: sch_plotter.h:56
HPGL_PAGE_SIZE
Definition: sch_plotter.h:63
HPGL_PLOT_ORIGIN_AND_UNITS
Definition: sch_plotter.h:46
std::vector< FAB_LAYER_COLOR > dummy
const double IU_PER_MM
Definition: base_units.h:77
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
bool m_PDFPropertyPopups
Definition: sch_plotter.h:90
double m_HPGLPenSize
Definition: sch_plotter.h:88
wxString m_theme
Definition: sch_plotter.h:91
HPGL_PAGE_SIZE m_HPGLPaperSizeSelect
Definition: sch_plotter.h:89
HPGL_PLOT_ORIGIN_AND_UNITS m_HPGLPlotOrigin
Definition: sch_plotter.h:96
bool m_useBackgroundColor
Definition: sch_plotter.h:87
wxString m_outputDirectory
Definition: sch_plotter.h:93
wxLogTrace helper definitions.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:39