KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_print_generic.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2018 CERN
3 * Copyright The 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 <eda_draw_frame.h>
23#include <printout.h>
24#include <pgm_base.h>
25#include <confirm.h>
26
27#include <wx/print.h>
28#include <wx/printdlg.h>
29
31
32// Define min and max reasonable values for print scale
33static constexpr double MIN_SCALE = 0.01;
34static constexpr double MAX_SCALE = 100.0;
35
36
37
43class KI_PREVIEW_FRAME : public wxPreviewFrame
44{
45public:
46 KI_PREVIEW_FRAME( wxPrintPreview* aPreview, wxWindow* aParent,
47 const wxString& aTitle, const wxPoint& aPos = wxDefaultPosition,
48 const wxSize& aSize = wxDefaultSize ) :
49 wxPreviewFrame( aPreview, aParent, aTitle, aPos, aSize )
50 {
51 }
52
53 bool Show( bool show ) override
54 {
55 bool ret;
56
57 // Show or hide the window. If hiding, save current position and size.
58 // If showing, use previous position and size.
59 if( show )
60 {
61 ret = wxPreviewFrame::Show( show );
62
63 if( s_size.x != 0 && s_size.y != 0 )
64 SetSize( s_pos.x, s_pos.y, s_size.x, s_size.y, 0 );
65 }
66 else
67 {
68 // Save the dialog's position & size before hiding
69 s_size = GetSize();
70 s_pos = GetPosition();
71
72 ret = wxPreviewFrame::Show( show );
73 }
74
75 return ret;
76 }
77
78private:
79 static wxPoint s_pos;
80 static wxSize s_size;
81};
82
83
86
87
89 : DIALOG_PRINT_GENERIC_BASE( aParent ),
90 m_config( nullptr ),
91 m_settings( aSettings )
92{
93 // Note: for the validator, min value is 0.0, to allow typing values like 0.5
94 // that start by 0
95 m_scaleValidator.SetRange( 0.0, MAX_SCALE );
96 m_scaleCustomText->SetValidator( m_scaleValidator );
97
98 // Show m_panelPrinters only if there are printers to list:
100
101 SetupStandardButtons( { { wxID_OK, _( "Print" ) },
102 { wxID_APPLY, _( "Print Preview" ) },
103 { wxID_CANCEL, _( "Close" ) } } );
104
105#if defined(__WXMAC__) or defined(__WXGTK__)
106 // Preview does not work well on GTK or Mac,
107 // but these platforms provide native print preview
108 m_sdbSizer1Apply->Hide();
109#endif
110
112 Layout();
114}
115
116
118{
119}
120
121
123{
124 m_titleBlock->SetValue( aValue );
125 m_titleBlock->Hide();
126
127 if( m_config )
128 {
130 m_settings->m_titleBlock = aValue;
132 }
133}
134
135
137{
139 m_settings->m_titleBlock = m_titleBlock->GetValue();
140 m_settings->m_blackWhite = m_outputMode->GetSelection();
141
142 if( m_config )
144}
145
146
148{
149 if( m_scale1->GetValue() )
150 return 1.0;
151
152 if( m_scaleFit->GetValue() )
153 return 0.0;
154
155 if( m_scaleCustom->GetValue() )
156 {
157 double scale = 1.0;;
158
159 if( !m_scaleCustomText->GetValue().ToDouble( &scale ) )
160 {
161 DisplayInfoMessage( nullptr, _( "Warning: scale is not a number." ) );
162 scale = 1.0;
163 }
164
165 if( scale > MAX_SCALE )
166 {
169 DisplayInfoMessage( nullptr, wxString::Format( _( "Warning: scale set to a very large "
170 "value.\nIt will be clamped to %f." ),
171 scale ) );
172 }
173 else if( scale < MIN_SCALE )
174 {
177 DisplayInfoMessage( nullptr, wxString::Format( _( "Warning: scale set to a very small "
178 "value.\nIt will be clamped to %f." ),
179 scale ) );
180 }
181
182 return scale;
183 }
184
185 wxFAIL_MSG( wxT( "No scale option selected." ) );
186 return 1.0;
187}
188
189
191{
192 wxASSERT( aValue >= 0.0 );
193
194 if( aValue == 0.0 ) // fit to page
195 {
196 m_scaleFit->SetValue( true );
197 }
198 else if( aValue == 1.0 )
199 {
200 m_scale1->SetValue( true );
201 }
202 else
203 {
204 // Silently clamp the value (it comes from the config file).
205 if( aValue > MAX_SCALE )
206 aValue = MAX_SCALE;
207 else if( aValue < MIN_SCALE )
208 aValue = MIN_SCALE;
209
210 m_scaleCustom->SetValue( true );
211 m_scaleCustomText->SetValue( wxString::Format( wxT( "%f" ), aValue ) );
212 }
213}
214
215
217{
218 if( !wxDialog::TransferDataToWindow() )
219 return false;
220
221 if( m_config )
223
226 m_outputMode->SetSelection( m_settings->m_blackWhite ? 1 : 0 );
227
228 return true;
229}
230
231
232void DIALOG_PRINT_GENERIC::onPageSetup( wxCommandEvent& event )
233{
234 wxPageSetupDialog pageSetupDialog( this, s_pageSetupData );
235 pageSetupDialog.ShowModal();
236
237 (*s_PrintData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
238 (*s_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
239}
240
241
242void DIALOG_PRINT_GENERIC::onPrintPreview( wxCommandEvent& event )
243{
244 m_settings->m_pageCount = 0; // it needs to be set by a derived dialog
245 saveSettings();
246
247 if( m_settings->m_pageCount == 0 )
248 {
249 DisplayError( this, _( "Nothing to print" ) );
250 return;
251 }
252
253 wxString selectedPrinterName;
254
255 if( m_panelPrinters )
256 selectedPrinterName = m_panelPrinters->GetSelectedPrinterName();
257
258 s_PrintData->SetPrinterName( selectedPrinterName );
259
260 // Pass two printout objects: for preview, and possible printing.
261 wxString title = _( "Print Preview" );
262 wxPrintPreview* preview =
263 new wxPrintPreview( createPrintout( title ), createPrintout( title ), s_PrintData );
264
265 preview->SetZoom( 100 );
266
267 KI_PREVIEW_FRAME* frame = new KI_PREVIEW_FRAME( preview, this, title );
268
269 // On wxGTK, set the flag wxTOPLEVEL_EX_DIALOG is mandatory, if we want
270 // close the frame using the X box in caption, when the preview frame is run
271 // from a dialog
272 frame->SetExtraStyle( frame->GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
273
274 // We use here wxPreviewFrame_WindowModal option to make the wxPrintPreview frame
275 // modal for its caller only.
276 // An other reason is the fact when closing the frame without this option,
277 // all top level frames are reenabled.
278 // With this option, only the parent is reenabled.
279 // Reenabling all top level frames should be made by the parent dialog.
280 frame->InitializeWithModality( wxPreviewFrame_WindowModal );
281
282 // on first invocation in this runtime session, set to 3/4 size of parent,
283 // but will be changed in Show() if not first time as will position.
284 // Must be called after InitializeWithModality because otherwise in some wxWidget
285 // versions it is not always taken in account
286 frame->SetMinSize( wxSize( 650, 500 ) );
287 frame->SetSize( ( m_parent->GetSize() * 3 ) / 4 );
288
289 frame->Raise(); // Needed on Ubuntu/Unity to display the frame
290 frame->Show( true );
291}
292
293
294void DIALOG_PRINT_GENERIC::onPrintButtonClick( wxCommandEvent& event )
295{
296 if( Pgm().m_Printing )
297 {
298 DisplayError( this, _( "Previous print job not yet complete." ) );
299 return;
300 }
301
302 m_settings->m_pageCount = 0; // it needs to be set by a derived dialog
303 saveSettings();
304
305 if( m_settings->m_pageCount == 0 )
306 {
307 DisplayError( this, _( "Nothing to print" ) );
308 return;
309 }
310
311 wxString selectedPrinterName;
312
313 if( m_panelPrinters )
314 selectedPrinterName = m_panelPrinters->GetSelectedPrinterName();
315
316 s_PrintData->SetPrinterName( selectedPrinterName );
317
318 wxPrintDialogData printDialogData( *s_PrintData );
319 printDialogData.SetMaxPage( m_settings->m_pageCount );
320
321 wxPrinter printer( &printDialogData );
322 auto printout = std::unique_ptr<wxPrintout>( createPrintout( _( "Print" ) ) );
323
324 Pgm().m_Printing = true;
325
326 {
327 if( !printer.Print( this, printout.get(), true ) )
328 {
329 if( wxPrinter::GetLastError() == wxPRINTER_ERROR )
330 DisplayError( this, _( "There was a problem printing." ) );
331 }
332 else
333 {
334 *s_PrintData = printer.GetPrintDialogData().GetPrintData();
335 }
336 }
337
338 Pgm().m_Printing = false;
339}
340
341
342void DIALOG_PRINT_GENERIC::onCancelButtonClick( wxCommandEvent& event )
343{
344 saveSettings();
345
346 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) );
347}
348
349
350void DIALOG_PRINT_GENERIC::onClose( wxCloseEvent& event )
351{
352 saveSettings();
353 event.Skip();
354}
355
356
357void DIALOG_PRINT_GENERIC::onSetCustomScale( wxCommandEvent& event )
358{
359 // Select 'custom scale' radio button when user types in a value in the
360 // custom scale text box
361 m_scaleCustom->SetValue( true );
362}
363
364
366{
367 if( !s_PrintData ) // First print
368 {
369 s_PrintData = new wxPrintData();
370
371 if( !s_PrintData->Ok() )
372 DisplayError( this, _( "An error occurred initializing the printer information." ) );
373
374 s_PrintData->SetQuality( wxPRINT_QUALITY_HIGH ); // Default resolution = HIGH;
375 }
376
377 if( !s_pageSetupData )
378 {
379 const PAGE_INFO& pageInfo = m_settings->m_pageInfo;
380
381 s_pageSetupData = new wxPageSetupDialogData( *s_PrintData );
382 s_pageSetupData->SetPaperId( pageInfo.GetPaperId() );
383 s_pageSetupData->GetPrintData().SetOrientation( pageInfo.GetWxOrientation() );
384
385 if( pageInfo.IsCustom() )
386 {
387 if( pageInfo.IsPortrait() )
388 s_pageSetupData->SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ),
389 EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ) ) );
390 else
391 s_pageSetupData->SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ),
392 EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ) ) );
393 }
394
395 *s_PrintData = s_pageSetupData->GetPrintData();
396 }
397}
398
399
400wxPrintData* DIALOG_PRINT_GENERIC::s_PrintData = nullptr;
401wxPageSetupDialogData* DIALOG_PRINT_GENERIC::s_pageSetupData = nullptr;
Class DIALOG_PRINT_GENERIC_BASE.
PANEL_PRINTER_LIST * m_panelPrinters
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:59
wxPrintOrientation GetWxOrientation() const
Definition: page_info.h:127
double GetHeightMils() const
Definition: page_info.h:141
wxPaperSize GetPaperId() const
Definition: page_info.h:132
double GetWidthMils() const
Definition: page_info.h:136
bool IsCustom() const
Definition: page_info.cpp:182
bool IsPortrait() const
Definition: page_info.h:122
bool m_Printing
wxWidgets on MSW tends to crash if you spool up more than one print job at a time.
Definition: pgm_base.h:378
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:222
This file is part of the common library.
static constexpr double MAX_SCALE
static constexpr double MIN_SCALE
#define _(s)
KICOMMON_API int Mils2mm(double aVal)
Convert mils to mm.
Definition: eda_units.cpp:82
#define MAX_SCALE
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
see class PGM_BASE
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