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
17 * along with this program. If not, see <https://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#include <printing.h>
27
28#include <wx/print.h>
29#include <wx/printdlg.h>
30
32
33// Define min and max reasonable values for print scale
34static constexpr double MIN_SCALE = 0.01;
35static constexpr double MAX_SCALE = 100.0;
36
37wxPrintData* DIALOG_PRINT_GENERIC::s_printData = nullptr;
38wxPageSetupDialogData* DIALOG_PRINT_GENERIC::s_pageSetupData = nullptr;
39
40
46class KI_PREVIEW_FRAME : public wxPreviewFrame
47{
48public:
49 KI_PREVIEW_FRAME( wxPrintPreview* aPreview, wxWindow* aParent, const wxString& aTitle,
50 const wxPoint& aPos = wxDefaultPosition, const wxSize& aSize = wxDefaultSize ) :
51 wxPreviewFrame( aPreview, aParent, aTitle, aPos, aSize )
52 {
53 }
54
55 bool Show( bool show ) override
56 {
57 bool ret;
58
59 // Show or hide the window. If hiding, save current position and size.
60 // If showing, use previous position and size.
61 if( show )
62 {
63 ret = wxPreviewFrame::Show( show );
64
65 if( s_size.x != 0 && s_size.y != 0 )
66 SetSize( s_pos.x, s_pos.y, s_size.x, s_size.y, 0 );
67 }
68 else
69 {
70 // Save the dialog's position & size before hiding
71 s_size = GetSize();
72 s_pos = GetPosition();
73
74 ret = wxPreviewFrame::Show( show );
75 }
76
77 return ret;
78 }
79
80private:
81 static wxPoint s_pos;
82 static wxSize s_size;
83};
84
85
88
89
92 m_settings( aSettings )
93{
94 // Show m_panelPrinters only if there are printers to list:
95 m_panelPrinters->Show( m_panelPrinters->HasPrintersAvailable() );
96
97 SetupStandardButtons( { { wxID_OK, _( "Print" ) },
98 { wxID_APPLY, _( "Print Preview" ) },
99 { wxID_CANCEL, _( "Close" ) } } );
100
101#if defined(__WXMAC__) or defined(__WXGTK__)
102 // Preview does not work well on GTK or Mac,
103 // but these platforms provide native print preview
104 m_sdbSizer1Apply->Hide();
105#endif
106
108 Layout();
110}
111
112
114{
115 m_titleBlock->SetValue( aValue );
116 m_titleBlock->Hide();
117}
118
119
121{
122 m_settings->m_scale = getScaleValue();
123 m_settings->m_titleBlock = m_titleBlock->GetValue();
124 m_settings->m_blackWhite = m_outputMode->GetSelection();
125}
126
127
129{
130 if( m_scale1->GetValue() )
131 {
132 return 1.0;
133 }
134 else if( m_scaleFit->GetValue() )
135 {
136 return 0.0;
137 }
138 else if( m_scaleCustom->GetValue() )
139 {
140 double scale = 1.0;;
141
142 if( !m_scaleCustomText->GetValue().ToDouble( &scale ) )
143 {
144 DisplayInfoMessage( nullptr, _( "Warning: custom scale is not a number." ) );
145 setScaleValue( 1.0 );
146 scale = 1.0;
147 }
148
149 if( scale > MAX_SCALE )
150 {
153 DisplayInfoMessage( nullptr, wxString::Format( _( "Warning: custom scale is too large.\n"
154 "It will be clamped to %f." ), scale ) );
155 }
156 else if( scale < MIN_SCALE )
157 {
160 DisplayInfoMessage( nullptr, wxString::Format( _( "Warning: custom scale is too small.\n"
161 "It will be clamped to %f." ), scale ) );
162 }
163
164 return scale;
165 }
166
167 wxFAIL_MSG( wxT( "No scale option selected." ) );
168 return 1.0;
169}
170
171
173{
174 wxASSERT( aValue >= 0.0 );
175
176 if( aValue == 0.0 ) // fit to page
177 {
178 m_scaleFit->SetValue( true );
179 }
180 else if( aValue == 1.0 )
181 {
182 m_scale1->SetValue( true );
183 }
184 else
185 {
186 // Silently clamp the value (it comes from the config file).
187 if( aValue > MAX_SCALE )
188 aValue = MAX_SCALE;
189 else if( aValue < MIN_SCALE )
190 aValue = MIN_SCALE;
191
192 m_scaleCustom->SetValue( true );
193 m_scaleCustomText->SetValue( wxString::Format( wxT( "%f" ), aValue ) );
194 }
195}
196
197
199{
200 if( !wxDialog::TransferDataToWindow() )
201 return false;
202
203 setScaleValue( m_settings->m_scale );
204 m_titleBlock->SetValue( m_settings->m_titleBlock );
205 m_outputMode->SetSelection( m_settings->m_blackWhite ? 1 : 0 );
206
207 return true;
208}
209
210
211void DIALOG_PRINT_GENERIC::onPageSetup( wxCommandEvent& event )
212{
213 wxPageSetupDialog pageSetupDialog( this, s_pageSetupData );
214 pageSetupDialog.ShowModal();
215
216 (*s_printData ) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
217 (*s_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
218}
219
220
221void DIALOG_PRINT_GENERIC::onPrintPreview( wxCommandEvent& event )
222{
223 m_settings->m_pageCount = 0; // it needs to be set by a derived dialog
224 saveSettings();
225
226 if( m_settings->m_pageCount == 0 )
227 {
228 DisplayError( this, _( "Nothing to print" ) );
229 return;
230 }
231
232 wxString selectedPrinterName;
233
234 if( m_panelPrinters )
235 selectedPrinterName = m_panelPrinters->GetSelectedPrinterName();
236
237 s_printData->SetPrinterName( selectedPrinterName );
238
239 // Pass two printout objects: for preview, and possible printing.
240 wxString title = _( "Print Preview" );
241 wxPrintPreview* preview = new wxPrintPreview( createPrintout( title ), createPrintout( title ), s_printData );
242
243 preview->SetZoom( 100 );
244
245 KI_PREVIEW_FRAME* frame = new KI_PREVIEW_FRAME( preview, this, title );
246
247 // On wxGTK, set the flag wxTOPLEVEL_EX_DIALOG is mandatory, if we want
248 // close the frame using the X box in caption, when the preview frame is run
249 // from a dialog
250 frame->SetExtraStyle( frame->GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
251
252 // We use here wxPreviewFrame_WindowModal option to make the wxPrintPreview frame
253 // modal for its caller only.
254 // An other reason is the fact when closing the frame without this option,
255 // all top level frames are reenabled.
256 // With this option, only the parent is reenabled.
257 // Reenabling all top level frames should be made by the parent dialog.
258 frame->InitializeWithModality( wxPreviewFrame_WindowModal );
259
260 // on first invocation in this runtime session, set to 3/4 size of parent,
261 // but will be changed in Show() if not first time as will position.
262 // Must be called after InitializeWithModality because otherwise in some wxWidget
263 // versions it is not always taken in account
264 frame->SetMinSize( wxSize( 650, 500 ) );
265 frame->SetSize( ( m_parent->GetSize() * 3 ) / 4 );
266
267 frame->Raise(); // Needed on Ubuntu/Unity to display the frame
268 frame->Show( true );
269}
270
271
272void DIALOG_PRINT_GENERIC::onPrintButtonClick( wxCommandEvent& event )
273{
274 if( Pgm().m_Printing )
275 {
276 DisplayError( this, _( "Previous print job not yet complete." ) );
277 return;
278 }
279
280 m_settings->m_pageCount = 0; // it needs to be set by a derived dialog
281 saveSettings();
282
283 if( m_settings->m_pageCount == 0 )
284 {
285 DisplayError( this, _( "Nothing to print" ) );
286 return;
287 }
288
289 wxString selectedPrinterName;
290
291 if( m_panelPrinters )
292 selectedPrinterName = m_panelPrinters->GetSelectedPrinterName();
293
294 s_printData->SetPrinterName( selectedPrinterName );
295
296 wxPrintDialogData printDialogData( *s_printData );
297 printDialogData.SetMaxPage( m_settings->m_pageCount );
298
299 wxPrinter printer( &printDialogData );
300 auto printout = std::unique_ptr<wxPrintout>( createPrintout( _( "Print" ) ) );
301
302 Pgm().m_Printing = true;
303
304 {
305 if( !printer.Print( this, printout.get(), true ) )
306 {
307 if( wxPrinter::GetLastError() == wxPRINTER_ERROR )
308 DisplayError( this, _( "There was a problem printing." ) );
309 }
310 else
311 {
312 *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 {
368 s_pageSetupData->SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ),
369 EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ) ) );
370 }
371 else
372 {
373 s_pageSetupData->SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ),
374 EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ) ) );
375 }
376 }
377
378 *s_printData = s_pageSetupData->GetPrintData();
379 }
380}
381
DIALOG_PRINT_GENERIC_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Print"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
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
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:75
wxPrintOrientation GetWxOrientation() const
Definition page_info.h:129
double GetHeightMils() const
Definition page_info.h:143
wxPaperSize GetPaperId() const
Definition page_info.h:134
double GetWidthMils() const
Definition page_info.h:138
bool IsCustom() const
bool IsPortrait() const
Definition page_info.h:124
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:393
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
static constexpr double MIN_SCALE
#define _(s)
KICOMMON_API int Mils2mm(double aVal)
Convert mils to mm.
Definition eda_units.cpp:78
void ResetPrintToFilePath(wxPrintData &aData)
Clear any leftover "print to file" destination from aData.
#define MAX_SCALE
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
const int scale
Handle the parameters used to print a board drawing.
Definition printout.h:32