KiCad PCB EDA Suite
dialog_print_generic.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2018 CERN
3 * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
4 * Author: Maciej Suminski <[email protected]>
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21
22#include <confirm.h>
23#include <eda_draw_frame.h>
24#include <printout.h>
25#include <pgm_base.h>
26
27#include <wx/print.h>
28#include <wx/printdlg.h>
29
30// Define min and max reasonable values for print scale
31static constexpr double MIN_SCALE = 0.01;
32static constexpr double MAX_SCALE = 100.0;
33
34
35
40class KI_PREVIEW_FRAME : public wxPreviewFrame
41{
42public:
43 KI_PREVIEW_FRAME( wxPrintPreview* aPreview, wxWindow* aParent,
44 const wxString& aTitle, const wxPoint& aPos = wxDefaultPosition,
45 const wxSize& aSize = wxDefaultSize ) :
46 wxPreviewFrame( aPreview, aParent, aTitle, aPos, aSize )
47 {
48 }
49
50 bool Show( bool show ) override
51 {
52 bool ret;
53
54 // Show or hide the window. If hiding, save current position and size.
55 // If showing, use previous position and size.
56 if( show )
57 {
58 ret = wxPreviewFrame::Show( show );
59
60 if( s_size.x != 0 && s_size.y != 0 )
61 SetSize( s_pos.x, s_pos.y, s_size.x, s_size.y, 0 );
62 }
63 else
64 {
65 // Save the dialog's position & size before hiding
66 s_size = GetSize();
67 s_pos = GetPosition();
68
69 ret = wxPreviewFrame::Show( show );
70 }
71
72 return ret;
73 }
74
75private:
76 static wxPoint s_pos;
77 static wxSize s_size;
78};
79
80
83
84
86 : DIALOG_PRINT_GENERIC_BASE( aParent ),
87 m_config( nullptr ),
88 m_settings( aSettings )
89{
90 // Note: for the validator, min value is 0.0, to allow typing values like 0.5
91 // that start by 0
92 m_scaleValidator.SetRange( 0.0, MAX_SCALE );
93 m_scaleCustomText->SetValidator( m_scaleValidator );
94
95 SetupStandardButtons( { { wxID_OK, _( "Print" ) },
96 { wxID_APPLY, _( "Print Preview" ) },
97 { wxID_CANCEL, _( "Close" ) } } );
98
99#if defined(__WXMAC__) or defined(__WXGTK__)
100 // Preview does not work well on GTK or Mac,
101 // but these platforms provide native print preview
102 m_sdbSizer1Apply->Hide();
103#endif
104
106 Layout();
108}
109
110
112{
113}
114
115
117{
118 m_titleBlock->SetValue( aValue );
119 m_titleBlock->Hide();
120
121 if( m_config )
122 {
124 m_settings->m_titleBlock = aValue;
126 }
127}
128
129
131{
133 m_settings->m_titleBlock = m_titleBlock->GetValue();
134 m_settings->m_blackWhite = m_outputMode->GetSelection();
135
136 if( m_config )
138}
139
140
142{
143 if( m_scale1->GetValue() )
144 return 1.0;
145
146 if( m_scaleFit->GetValue() )
147 return 0.0;
148
149 if( m_scaleCustom->GetValue() )
150 {
151 double scale = 1.0;;
152
153 if( !m_scaleCustomText->GetValue().ToDouble( &scale ) )
154 {
155 DisplayInfoMessage( nullptr, _( "Warning: Bad scale number" ) );
156 scale = 1.0;
157 }
158
159 if( scale > MAX_SCALE )
160 {
163 DisplayInfoMessage( nullptr,
164 wxString::Format( _( "Warning: Scale option set to a very large value.\n"
165 " Clamped to %f" ), scale ) );
166 }
167 else if( scale < MIN_SCALE )
168 {
171 DisplayInfoMessage( nullptr,
172 wxString::Format( _( "Warning: Scale option set to a very small value.\n"
173 " Clamped to %f" ), scale ) );
174 }
175
176 return scale;
177 }
178
179 wxCHECK( false, 1.0 );
180}
181
182
184{
185 wxASSERT( aValue >= 0.0 );
186
187 if( aValue == 0.0 ) // fit to page
188 {
189 m_scaleFit->SetValue( true );
190 }
191 else if( aValue == 1.0 )
192 {
193 m_scale1->SetValue( true );
194 }
195 else
196 {
197 // Silently clamp the value (it comes from the config file).
198 if( aValue > MAX_SCALE )
199 aValue = MAX_SCALE;
200 else if( aValue < MIN_SCALE )
201 aValue = MIN_SCALE;
202
203 m_scaleCustom->SetValue( true );
204 m_scaleCustomText->SetValue( wxString::Format( wxT( "%f" ), aValue ) );
205 }
206}
207
208
210{
211 if( !wxDialog::TransferDataToWindow() )
212 return false;
213
214 if( m_config )
216
219 m_outputMode->SetSelection( m_settings->m_blackWhite ? 1 : 0 );
220
221 return true;
222}
223
224
225void DIALOG_PRINT_GENERIC::onPageSetup( wxCommandEvent& event )
226{
227 wxPageSetupDialog pageSetupDialog( this, s_pageSetupData );
228 pageSetupDialog.ShowModal();
229
230 (*s_PrintData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
231 (*s_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
232}
233
234
235void DIALOG_PRINT_GENERIC::onPrintPreview( wxCommandEvent& event )
236{
237 m_settings->m_pageCount = 0; // it needs to be set by a derived dialog
238 saveSettings();
239
240 if( m_settings->m_pageCount == 0 )
241 {
242 DisplayError( this, _( "Nothing to print" ) );
243 return;
244 }
245
246 // Pass two printout objects: for preview, and possible printing.
247 wxString title = _( "Print Preview" );
248 wxPrintPreview* preview =
249 new wxPrintPreview( createPrintout( title ), createPrintout( title ), s_PrintData );
250
251 preview->SetZoom( 100 );
252
253 KI_PREVIEW_FRAME* frame = new KI_PREVIEW_FRAME( preview, this, title );
254
255 // On wxGTK, set the flag wxTOPLEVEL_EX_DIALOG is mandatory, if we want
256 // close the frame using the X box in caption, when the preview frame is run
257 // from a dialog
258 frame->SetExtraStyle( frame->GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
259
260 // We use here wxPreviewFrame_WindowModal option to make the wxPrintPreview frame
261 // modal for its caller only.
262 // An other reason is the fact when closing the frame without this option,
263 // all top level frames are reenabled.
264 // With this option, only the parent is reenabled.
265 // Reenabling all top level frames should be made by the parent dialog.
266 frame->InitializeWithModality( wxPreviewFrame_WindowModal );
267
268 // on first invocation in this runtime session, set to 3/4 size of parent,
269 // but will be changed in Show() if not first time as will position.
270 // Must be called after InitializeWithModality because otherwise in some wxWidget
271 // versions it is not always taken in account
272 frame->SetMinSize( wxSize( 650, 500 ) );
273 frame->SetSize( (m_parent->GetSize() * 3) / 4 );
274
275 frame->Raise(); // Needed on Ubuntu/Unity to display the frame
276 frame->Show( true );
277}
278
279
280void DIALOG_PRINT_GENERIC::onPrintButtonClick( wxCommandEvent& event )
281{
282 if( Pgm().m_Printing )
283 {
284 DisplayError( this, _( "Previous print job not yet complete." ) );
285 return;
286 }
287
288 m_settings->m_pageCount = 0; // it needs to be set by a derived dialog
289 saveSettings();
290
291 if( m_settings->m_pageCount == 0 )
292 {
293 DisplayError( this, _( "Nothing to print" ) );
294 return;
295 }
296
297 wxPrintDialogData printDialogData( *s_PrintData );
298 printDialogData.SetMaxPage( m_settings->m_pageCount );
299
300 wxPrinter printer( &printDialogData );
301 auto printout = std::unique_ptr<wxPrintout>( createPrintout( _( "Print" ) ) );
302
303 Pgm().m_Printing = true;
304
305 {
306 if( !printer.Print( this, printout.get(), true ) )
307 {
308 if( wxPrinter::GetLastError() == wxPRINTER_ERROR )
309 DisplayError( this, _( "There was a problem printing." ) );
310 }
311 else
312 {
313 *s_PrintData = printer.GetPrintDialogData().GetPrintData();
314 }
315 }
316
317 Pgm().m_Printing = false;
318}
319
320
321void DIALOG_PRINT_GENERIC::onCancelButtonClick( wxCommandEvent& event )
322{
323 saveSettings();
324
325 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) );
326}
327
328
329void DIALOG_PRINT_GENERIC::onClose( wxCloseEvent& event )
330{
331 saveSettings();
332 event.Skip();
333}
334
335
336void DIALOG_PRINT_GENERIC::onSetCustomScale( wxCommandEvent& event )
337{
338 // Select 'custom scale' radio button when user types in a value in the
339 // custom scale text box
340 m_scaleCustom->SetValue( true );
341}
342
343
345{
346 if( !s_PrintData ) // First print
347 {
348 s_PrintData = new wxPrintData();
349
350 if( !s_PrintData->Ok() )
351 DisplayError( this, _( "An error occurred initializing the printer information." ) );
352
353 s_PrintData->SetQuality( wxPRINT_QUALITY_HIGH ); // Default resolution = HIGH;
354 }
355
356 if( !s_pageSetupData )
357 {
358 const PAGE_INFO& pageInfo = m_settings->m_pageInfo;
359
360 s_pageSetupData = new wxPageSetupDialogData( *s_PrintData );
361 s_pageSetupData->SetPaperId( pageInfo.GetPaperId() );
362 s_pageSetupData->GetPrintData().SetOrientation( pageInfo.GetWxOrientation() );
363
364 if( pageInfo.IsCustom() )
365 {
366 if( pageInfo.IsPortrait() )
367 s_pageSetupData->SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ),
368 EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ) ) );
369 else
370 s_pageSetupData->SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ),
371 EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ) ) );
372 }
373
374 *s_PrintData = s_pageSetupData->GetPrintData();
375 }
376}
377
378
379wxPrintData* DIALOG_PRINT_GENERIC::s_PrintData = nullptr;
380wxPageSetupDialogData* DIALOG_PRINT_GENERIC::s_pageSetupData = nullptr;
Class DIALOG_PRINT_GENERIC_BASE.
APP_SETTINGS_BASE * m_config
DIALOG_PRINT_GENERIC(EDA_DRAW_FRAME *aParent, PRINTOUT_SETTINGS *aSettings)
void onClose(wxCloseEvent &event) override
void setScaleValue(double aValue)
Select a corresponding scale radio button and update custom scale value if needed.
void onSetCustomScale(wxCommandEvent &event) override
static wxPrintData * s_PrintData
void onCancelButtonClick(wxCommandEvent &aEvent) override
virtual wxPrintout * createPrintout(const wxString &aTitle)=0
Create a printout with a requested title.
bool TransferDataToWindow() override
void onPageSetup(wxCommandEvent &event) override
double getScaleValue()
Return scale value selected in the dialog.
void onPrintButtonClick(wxCommandEvent &event) override
wxFloatingPointValidator< double > m_scaleValidator
void ForcePrintBorder(bool aValue)
Set 'print border and title block' to a requested value and hides the corresponding checkbox.
static wxPageSetupDialogData * s_pageSetupData
void onPrintPreview(wxCommandEvent &event) override
PRINTOUT_SETTINGS * m_settings
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...
The base class for create windows for drawing purpose.
Custom print preview frame.
bool Show(bool show) override
KI_PREVIEW_FRAME(wxPrintPreview *aPreview, wxWindow *aParent, const wxString &aTitle, const wxPoint &aPos=wxDefaultPosition, const wxSize &aSize=wxDefaultSize)
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
wxPrintOrientation GetWxOrientation() const
Definition: page_info.h:122
int GetHeightMils() const
Definition: page_info.h:133
wxPaperSize GetPaperId() const
Definition: page_info.h:127
int GetWidthMils() const
Definition: page_info.h:130
bool IsCustom() const
Definition: page_info.cpp:181
bool IsPortrait() const
Definition: page_info.h:117
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:280
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:320
This file is part of the common library.
static constexpr double MAX_SCALE
static constexpr double MIN_SCALE
#define _(s)
int Mils2mm(double aVal)
Convert mils to mm.
Definition: eda_units.cpp:62
see class PGM_BASE
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
const int scale
Handle the parameters used to print a board drawing.
Definition: printout.h:32
virtual void Save(APP_SETTINGS_BASE *aConfig)
Definition: printout.cpp:24
bool m_titleBlock
Print frame and title block.
Definition: printout.h:59
bool m_blackWhite
Print in B&W or Color.
Definition: printout.h:60
int m_pageCount
Number of pages to print.
Definition: printout.h:61
const PAGE_INFO & m_pageInfo
Definition: printout.h:63
virtual void Load(APP_SETTINGS_BASE *aConfig)
Definition: printout.cpp:32
double m_scale
Printing scale.
Definition: printout.h:58