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 m_plotPDFMetadata->SetValue( cfg->m_PlotPanel.pdf_metadata );
115
116 // HPGL plot origin and unit system configuration
117 m_plotOriginOpt->SetSelection( cfg->m_PlotPanel.hpgl_origin );
118
119 m_HPGLPaperSizeSelect = static_cast<HPGL_PAGE_SIZE>( cfg->m_PlotPanel.hpgl_paper_size );
120
121 // HPGL Pen Size is stored in mm in config
122 m_HPGLPenSize = cfg->m_PlotPanel.hpgl_pen_size * schIUScale.IU_PER_MM;
123
124 // Switch to the last save plot format
125 PLOT_FORMAT fmt = static_cast<PLOT_FORMAT>( cfg->m_PlotPanel.format );
126
127 switch( fmt )
128 {
129 default:
130 case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 0 ); break;
131 case PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 1 ); break;
132 case PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
133 case PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
134 case PLOT_FORMAT::HPGL: m_plotFormatOpt->SetSelection( 4 ); break;
135 }
136
137 if( fmt == PLOT_FORMAT::DXF || fmt == PLOT_FORMAT::HPGL )
138 m_plotBackgroundColor->Disable();
139
140 // Set the default line width (pen width which should be used for
141 // items that do not have a pen size defined (like frame ref)
142 // the default line width is stored in mils in config
143 m_defaultLineWidth.SetValue( schIUScale.MilsToIU( cfg->m_Drawing.default_line_thickness ) );
144 }
145
146 // Initialize HPGL specific widgets
148
149 // Plot directory
151 wxString path = settings.m_PlotDirectoryName;
152#ifdef __WINDOWS__
153 path.Replace( '/', '\\' );
154#endif
155 m_outputDirectoryName->SetValue( path );
156}
157
158
164{
165 // Build the absolute path of current output directory to preselect it in the file browser.
166 wxString path = ExpandEnvVarSubstitutions( m_outputDirectoryName->GetValue(), &Prj() );
167
168 // When editing a schematic that is not part of a project in the stand alone mode, the
169 // project path is not defined so point to the users document path to save the plot files.
170 if( Prj().IsNullProject() )
171 {
173 }
174 else
175 {
176 // Build the absolute path of current output directory to preselect it in the file browser.
178 path = Prj().AbsolutePath( path );
179 }
180
181 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
182
183 if( dirDialog.ShowModal() == wxID_CANCEL )
184 return;
185
186 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
187
188 wxFileName fn( Prj().AbsolutePath( m_parent->Schematic().Root().GetFileName() ) );
189 wxString defaultPath = fn.GetPathWithSep();
190 wxString msg;
191 wxFileName relPathTest; // Used to test if we can make the path relative
192
193 relPathTest.Assign( dirDialog.GetPath() );
194
195 // Test if making the path relative is possible before asking the user if they want to do it
196 if( relPathTest.MakeRelativeTo( defaultPath ) )
197 {
198 msg.Printf( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath );
199
200 wxMessageDialog dialog( this, msg, _( "Plot Output Directory" ),
201 wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
202
203 if( dialog.ShowModal() == wxID_YES )
204 dirName.MakeRelativeTo( defaultPath );
205 }
206
207 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
208}
209
210
212{
213 switch( m_plotFormatOpt->GetSelection() )
214 {
215 default:
216 case 0: return PLOT_FORMAT::POST;
217 case 1: return PLOT_FORMAT::PDF;
218 case 2: return PLOT_FORMAT::SVG;
219 case 3: return PLOT_FORMAT::DXF;
220 case 4: return PLOT_FORMAT::HPGL;
221 }
222}
223
224
225void DIALOG_PLOT_SCHEMATIC::OnPageSizeSelected( wxCommandEvent& event )
226{
227 if( GetPlotFileFormat() == PLOT_FORMAT::HPGL )
228 m_HPGLPaperSizeSelect = static_cast<HPGL_PAGE_SIZE>( m_paperSizeOption->GetSelection() );
229 else
230 m_pageSizeSelect = m_paperSizeOption->GetSelection();
231}
232
233
234void DIALOG_PLOT_SCHEMATIC::OnUpdateUI( wxUpdateUIEvent& event )
235{
237
238 if( fmt != m_plotFormat )
239 {
240 m_plotFormat = fmt;
241
242 wxArrayString paperSizes;
243 paperSizes.push_back( _( "Schematic size" ) );
244
245 int selection;
246
247 if( fmt == PLOT_FORMAT::HPGL )
248 {
249 paperSizes.push_back( _( "A5" ) );
250 paperSizes.push_back( _( "A4" ) );
251 paperSizes.push_back( _( "A3" ) );
252 paperSizes.push_back( _( "A2" ) );
253 paperSizes.push_back( _( "A1" ) );
254 paperSizes.push_back( _( "A0" ) );
255 paperSizes.push_back( _( "A" ) );
256 paperSizes.push_back( _( "B" ) );
257 paperSizes.push_back( _( "C" ) );
258 paperSizes.push_back( _( "D" ) );
259 paperSizes.push_back( _( "E" ) );
260
261 selection = static_cast<int>( m_HPGLPaperSizeSelect );
262 }
263 else
264 {
265 paperSizes.push_back( _( "A4" ) );
266 paperSizes.push_back( _( "A" ) );
267
268 selection = m_pageSizeSelect;
269 }
270
271 m_openFileAfterPlot->Enable( fmt == PLOT_FORMAT::PDF );
272 m_plotPDFPropertyPopups->Enable( fmt == PLOT_FORMAT::PDF );
273 m_plotPDFMetadata->Enable( fmt == PLOT_FORMAT::PDF );
274
275 m_paperSizeOption->Set( paperSizes );
276 m_paperSizeOption->SetSelection( selection );
277
279 fmt == PLOT_FORMAT::POST || fmt == PLOT_FORMAT::PDF || fmt == PLOT_FORMAT::SVG );
280
281 m_plotOriginTitle->Enable( fmt == PLOT_FORMAT::HPGL );
282 m_plotOriginOpt->Enable( fmt == PLOT_FORMAT::HPGL );
283 m_penWidth.Enable( fmt == PLOT_FORMAT::HPGL );
284
285 m_plotBackgroundColor->Enable(
286 fmt == PLOT_FORMAT::POST || fmt == PLOT_FORMAT::PDF || fmt == PLOT_FORMAT::SVG );
287
288 m_colorTheme->Enable( fmt != PLOT_FORMAT::HPGL );
289 m_ModeColorOption->Enable( fmt != PLOT_FORMAT::HPGL );
290 }
291}
292
293
295{
297
298 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
299 wxASSERT( cfg );
300
302
303 if( cfg )
304 {
307 cfg->m_PlotPanel.color_theme = colors->GetFilename();
309 cfg->m_PlotPanel.format = static_cast<int>( GetPlotFileFormat() );
310 cfg->m_PlotPanel.hpgl_origin = m_plotOriginOpt->GetSelection();
311 cfg->m_PlotPanel.hpgl_paper_size = static_cast<int>( m_HPGLPaperSizeSelect );
313 cfg->m_PlotPanel.pdf_metadata = m_plotPDFMetadata->GetValue();
315
316 // HPGL Pen Size is stored in mm in config
318
319 aSettings->SetDefaultFont( cfg->m_Appearance.default_font );
320 }
321
322 aSettings->LoadColors( colors );
323 aSettings->SetMinPenWidth( (int) m_defaultLineWidth.GetValue() );
324
325 if( m_plotBackgroundColor->GetValue() )
327 else
328 aSettings->SetBackgroundColor( COLOR4D::UNSPECIFIED );
329
330 // Plot directory
331 wxString path = m_outputDirectoryName->GetValue();
332 path.Replace( '\\', '/' );
333
335
336 if( settings.m_PlotDirectoryName != path )
337 m_configChanged = true;
338
339 settings.m_PlotDirectoryName = path;
340}
341
342
344{
345 int selection = m_colorTheme->GetSelection();
346
347 if( selection < 0 )
348 {
351 }
352
353 return static_cast<COLOR_SETTINGS*>( m_colorTheme->GetClientData( selection ) );
354}
355
356
357void DIALOG_PLOT_SCHEMATIC::OnPlotCurrent( wxCommandEvent& event )
358{
359 plotSchematic( false );
360}
361
362
363void DIALOG_PLOT_SCHEMATIC::OnPlotAll( wxCommandEvent& event )
364{
365 plotSchematic( true );
366}
367
368
370{
371 wxBusyCursor dummy;
372
373 SCH_RENDER_SETTINGS renderSettings( *m_parent->GetRenderSettings() );
374 renderSettings.m_ShowHiddenPins = false;
375 renderSettings.m_ShowHiddenFields = false;
376
377 getPlotOptions( &renderSettings );
378
379 std::unique_ptr<SCH_PLOTTER> schPlotter = std::make_unique<SCH_PLOTTER>( m_parent );
380
382
383 SCH_PLOT_OPTS plotOpts;
385 plotOpts.m_plotAll = aPlotAll;
386 plotOpts.m_blackAndWhite = !getModeColor();
387 plotOpts.m_useBackgroundColor = m_plotBackgroundColor->GetValue();
388 plotOpts.m_theme = colors->GetFilename();
389 plotOpts.m_PDFPropertyPopups = m_plotPDFPropertyPopups->GetValue();
390 plotOpts.m_PDFMetadata = m_plotPDFMetadata->GetValue();
392 plotOpts.m_HPGLPlotOrigin =
393 static_cast<HPGL_PLOT_ORIGIN_AND_UNITS>( m_plotOriginOpt->GetSelection() );
394 plotOpts.m_HPGLPenSize = m_HPGLPenSize;
395 plotOpts.m_outputDirectory = getOutputPath();
397
398 schPlotter->Plot( GetPlotFileFormat(), plotOpts, &renderSettings, &m_MessagesBox->Reporter() );
399
400 if( GetPlotFileFormat() == PLOT_FORMAT::PDF && getOpenFileAfterPlot() )
401 wxLaunchDefaultApplication( schPlotter->GetLastOutputFilePath() );
402}
403
404
406{
408
409 if( m_HPGLPenSize > schIUScale.mmToIU( 2 ) )
411
412 if( m_HPGLPenSize < schIUScale.mmToIU( 0.01 ) )
414}
415
416
418{
419 wxString msg;
420 wxString extMsg;
421 wxFileName fn;
422
423 extMsg.Printf( _( "Falling back to user path '%s'." ), KIPLATFORM::ENV::GetDocumentsPath() );
424
425 // Build the absolute path of current output directory to preselect it in the file browser.
426 std::function<bool( wxString* )> textResolver =
427 [&]( wxString* token ) -> bool
428 {
429 SCHEMATIC& schematic = m_parent->Schematic();
430 return schematic.ResolveTextVar( &schematic.CurrentSheet(), token, 0 );
431 };
432
433 wxString path = m_outputDirectoryName->GetValue();
434 path = ExpandTextVars( path, &textResolver );
436
437 fn.SetPath( path );
438
439 // If the contents of the path edit control results in an absolute path, return it as is.
440 if( fn.IsAbsolute() )
441 return path;
442
443 // When editing a schematic that is not part of a project in the stand alone mode, the
444 // project path is not defined.
445 if( Prj().IsNullProject() )
446 {
448
449 if( screen && !screen->GetFileName().IsEmpty() )
450 {
451 fn = screen->GetFileName();
452 msg.Printf( _( "Cannot normalize path '%s%s'." ), fn.GetPathWithSep(), path );
453 fn.SetPath( fn.GetPathWithSep() + path );
454
455 // Normalize always returns true for a non-empty file name so clear the file name
456 // and extension so that only the path is normalized.
457 fn.SetName( wxEmptyString );
458 fn.SetExt( wxEmptyString );
459
460 if( fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS ) )
461 {
462 path = fn.GetPath();
463 }
464 else
465 {
466 wxMessageDialog dlg( this, msg, _( "Warning" ), wxOK | wxCENTER | wxRESIZE_BORDER
467 | wxICON_EXCLAMATION | wxSTAY_ON_TOP );
468
469 dlg.SetExtendedMessage( extMsg );
470 dlg.ShowModal();
471
473 }
474 }
475 else
476 {
477 msg = _( "No project or path defined for the current schematic." );
478
479 wxMessageDialog dlg( this, msg, _( "Warning" ), wxOK | wxCENTER | wxRESIZE_BORDER
480 | wxICON_EXCLAMATION | wxSTAY_ON_TOP );
481 dlg.SetExtendedMessage( extMsg );
482 dlg.ShowModal();
483
484 // Always fall back to user's document path if no other absolute path can be normalized.
486 }
487 }
488 else
489 {
490 msg.Printf( _( "Cannot normalize path '%s%s'." ), Prj().GetProjectPath(), path );
491
492 // Build the absolute path of current output directory and the project path.
493 fn.SetPath( Prj().GetProjectPath() + path );
494
495 if( fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS ) )
496 {
497 path = fn.GetPath();
498 }
499 else
500 {
501 wxMessageDialog dlg( this, msg, _( "Warning" ),
502 wxOK | wxCENTER | wxRESIZE_BORDER | wxICON_EXCLAMATION |
503 wxSTAY_ON_TOP );
504
505 dlg.SetExtendedMessage( extMsg );
506 dlg.ShowModal();
507
509 }
510 }
511
512 return path;
513}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
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:80
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 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:320
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:287
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:197
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
Definition: schematic.cpp:228
SCH_SHEET & Root() const
Definition: schematic.h:105
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:306
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:334
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:58
The common library.
#define _(s)
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:390
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:57
HPGL_PAGE_SIZE
Definition: sch_plotter.h:64
HPGL_PLOT_ORIGIN_AND_UNITS
Definition: sch_plotter.h:47
std::vector< FAB_LAYER_COLOR > dummy
const double IU_PER_MM
Definition: base_units.h:76
constexpr int MilsToIU(int mils) const
Definition: base_units.h:93
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
wxString m_theme
Definition: sch_plotter.h:93
bool m_PDFPropertyPopups
Definition: sch_plotter.h:91
wxString m_outputDirectory
Definition: sch_plotter.h:95
HPGL_PLOT_ORIGIN_AND_UNITS m_HPGLPlotOrigin
Definition: sch_plotter.h:98
int m_pageSizeSelect
Definition: sch_plotter.h:87
bool m_PDFMetadata
Definition: sch_plotter.h:92
bool m_blackAndWhite
Definition: sch_plotter.h:86
HPGL_PAGE_SIZE m_HPGLPaperSizeSelect
Definition: sch_plotter.h:90
double m_HPGLPenSize
Definition: sch_plotter.h:89
bool m_useBackgroundColor
Definition: sch_plotter.h:88
bool m_plotDrawingSheet
Definition: sch_plotter.h:83
wxLogTrace helper definitions.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:39