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-2021 KiCad Developers, see AUTHORS.txt for contributors.
4  * Author: Maciej Suminski <maciej.suminski@cern.ch>
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
31 static constexpr double MIN_SCALE = 0.01;
32 static constexpr double MAX_SCALE = 100.0;
33 
34 
36  : DIALOG_PRINT_GENERIC_BASE( aParent ),
37  m_config( nullptr ),
38  m_settings( aSettings )
39 {
40  // Note: for the validator, min value is 0.0, to allow typing values like 0.5
41  // that start by 0
42  m_scaleValidator.SetRange( 0.0, MAX_SCALE );
43  m_scaleCustomText->SetValidator( m_scaleValidator );
44 
45  // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
46  // that requires us to correct the button labels here.
47  m_sdbSizer1OK->SetLabel( _( "Print" ) );
48  m_sdbSizer1Apply->SetLabel( _( "Print Preview" ) );
49  m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
50  m_sdbSizer1->Layout();
51 
52  m_sdbSizer1OK->SetDefault();
53 
54 #if defined(__WXMAC__) or defined(__WXGTK__)
55  // Preview does not work well on GTK or Mac,
56  // but these platforms provide native print preview
57  m_sdbSizer1Apply->Hide();
58 #endif
59 
61  Layout();
62  initPrintData();
63 }
64 
65 
67 {
68 }
69 
70 
72 {
73  m_titleBlock->SetValue( aValue );
74  m_titleBlock->Hide();
75 
76  if( m_config )
77  {
79  m_settings->m_titleBlock = aValue;
81  }
82 }
83 
84 
86 {
88  m_settings->m_titleBlock = m_titleBlock->GetValue();
89  m_settings->m_blackWhite = m_outputMode->GetSelection();
90 
91  if( m_config )
93 }
94 
95 
97 {
98  if( m_scale1->GetValue() )
99  return 1.0;
100 
101  if( m_scaleFit->GetValue() )
102  return 0.0;
103 
104  if( m_scaleCustom->GetValue() )
105  {
106  double scale = 1.0;;
107 
108  if( !m_scaleCustomText->GetValue().ToDouble( &scale ) )
109  {
110  DisplayInfoMessage( nullptr, _( "Warning: Bad scale number" ) );
111  scale = 1.0;
112  }
113 
114  if( scale > MAX_SCALE )
115  {
116  scale = MAX_SCALE;
117  setScaleValue( scale );
118  DisplayInfoMessage( nullptr,
119  wxString::Format( _( "Warning: Scale option set to a very large value.\n"
120  " Clamped to %f" ), scale ) );
121  }
122  else if( scale < MIN_SCALE )
123  {
124  scale = MIN_SCALE;
125  setScaleValue( scale );
126  DisplayInfoMessage( nullptr,
127  wxString::Format( _( "Warning: Scale option set to a very small value.\n"
128  " Clamped to %f" ), scale ) );
129  }
130 
131  return scale;
132  }
133 
134  wxCHECK( false, 1.0 );
135 }
136 
137 
139 {
140  wxASSERT( aValue >= 0.0 );
141 
142  if( aValue == 0.0 ) // fit to page
143  {
144  m_scaleFit->SetValue( true );
145  }
146  else if( aValue == 1.0 )
147  {
148  m_scale1->SetValue( true );
149  }
150  else
151  {
152  // Silently clamp the value (it comes from the config file).
153  if( aValue > MAX_SCALE )
154  aValue = MAX_SCALE;
155  else if( aValue < MIN_SCALE )
156  aValue = MIN_SCALE;
157 
158  m_scaleCustom->SetValue( true );
159  m_scaleCustomText->SetValue( wxString::Format( wxT( "%f" ), aValue ) );
160  }
161 }
162 
163 
165 {
166  if( !wxDialog::TransferDataToWindow() )
167  return false;
168 
169  if( m_config )
171 
173  m_titleBlock->SetValue( m_settings->m_titleBlock );
174  m_outputMode->SetSelection( m_settings->m_blackWhite ? 1 : 0 );
175 
176  return true;
177 }
178 
179 
180 void DIALOG_PRINT_GENERIC::onPageSetup( wxCommandEvent& event )
181 {
182  wxPageSetupDialog pageSetupDialog( this, s_pageSetupData );
183  pageSetupDialog.ShowModal();
184 
185  (*s_PrintData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
186  (*s_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
187 }
188 
189 
190 void DIALOG_PRINT_GENERIC::onPrintPreview( wxCommandEvent& event )
191 {
192  m_settings->m_pageCount = 0; // it needs to be set by a derived dialog
193  saveSettings();
194 
195  if( m_settings->m_pageCount == 0 )
196  {
197  DisplayError( this, _( "Nothing to print" ) );
198  return;
199  }
200 
201  // Pass two printout objects: for preview, and possible printing.
202  wxString title = _( "Print Preview" );
203  wxPrintPreview* preview =
204  new wxPrintPreview( createPrintout( title ), createPrintout( title ), s_PrintData );
205 
206  preview->SetZoom( 100 );
207 
208  wxPreviewFrame* frame = new wxPreviewFrame( preview, this, title, m_parent->GetPosition(),
209  m_parent->GetSize() );
210  frame->SetMinSize( wxSize( 550, 350 ) );
211  frame->Center();
212 
213  // On wxGTK, set the flag wxTOPLEVEL_EX_DIALOG is mandatory, if we want
214  // close the frame using the X box in caption, when the preview frame is run
215  // from a dialog
216  frame->SetExtraStyle( frame->GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
217 
218  // We use here wxPreviewFrame_WindowModal option to make the wxPrintPreview frame
219  // modal for its caller only.
220  // An other reason is the fact when closing the frame without this option,
221  // all top level frames are reenabled.
222  // With this option, only the parent is reenabled.
223  // Reenabling all top level frames should be made by the parent dialog.
224  frame->InitializeWithModality( wxPreviewFrame_WindowModal );
225 
226  frame->Raise(); // Needed on Ubuntu/Unity to display the frame
227  frame->Show( true );
228 }
229 
230 
231 void DIALOG_PRINT_GENERIC::onPrintButtonClick( wxCommandEvent& event )
232 {
233  if( Pgm().m_Printing )
234  {
235  DisplayError( this, _( "Previous print job not yet complete." ) );
236  return;
237  }
238 
239  m_settings->m_pageCount = 0; // it needs to be set by a derived dialog
240  saveSettings();
241 
242  if( m_settings->m_pageCount == 0 )
243  {
244  DisplayError( this, _( "Nothing to print" ) );
245  return;
246  }
247 
248  wxPrintDialogData printDialogData( *s_PrintData );
249  printDialogData.SetMaxPage( m_settings->m_pageCount );
250 
251  wxPrinter printer( &printDialogData );
252  auto printout = std::unique_ptr<wxPrintout>( createPrintout( _( "Print" ) ) );
253 
254  Pgm().m_Printing = true;
255 
256  {
257  if( !printer.Print( this, printout.get(), true ) )
258  {
259  if( wxPrinter::GetLastError() == wxPRINTER_ERROR )
260  DisplayError( this, _( "There was a problem printing." ) );
261  }
262  else
263  {
264  *s_PrintData = printer.GetPrintDialogData().GetPrintData();
265  }
266  }
267 
268  Pgm().m_Printing = false;
269 }
270 
271 
272 void DIALOG_PRINT_GENERIC::onCancelButtonClick( wxCommandEvent& event )
273 {
274  saveSettings();
275 
276  wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) );
277 }
278 
279 
280 void DIALOG_PRINT_GENERIC::onClose( wxCloseEvent& event )
281 {
282  saveSettings();
283  event.Skip();
284 }
285 
286 
287 void DIALOG_PRINT_GENERIC::onSetCustomScale( wxCommandEvent& event )
288 {
289  // Select 'custom scale' radio button when user types in a value in the
290  // custom scale text box
291  m_scaleCustom->SetValue( true );
292 }
293 
294 
296 {
297  if( !s_PrintData ) // First print
298  {
299  s_PrintData = new wxPrintData();
300 
301  if( !s_PrintData->Ok() )
302  DisplayError( this, _( "An error occurred initializing the printer information." ) );
303 
304  s_PrintData->SetQuality( wxPRINT_QUALITY_HIGH ); // Default resolution = HIGH;
305  }
306 
307  if( !s_pageSetupData )
308  {
309  const PAGE_INFO& pageInfo = m_settings->m_pageInfo;
310 
311  s_pageSetupData = new wxPageSetupDialogData( *s_PrintData );
312  s_pageSetupData->SetPaperId( pageInfo.GetPaperId() );
313  s_pageSetupData->GetPrintData().SetOrientation( pageInfo.GetWxOrientation() );
314 
315  if( pageInfo.IsCustom() )
316  {
317  if( pageInfo.IsPortrait() )
318  s_pageSetupData->SetPaperSize( wxSize( Mils2mm( pageInfo.GetWidthMils() ),
319  Mils2mm( pageInfo.GetHeightMils() ) ) );
320  else
321  s_pageSetupData->SetPaperSize( wxSize( Mils2mm( pageInfo.GetHeightMils() ),
322  Mils2mm( pageInfo.GetWidthMils() ) ) );
323  }
324 
325  *s_PrintData = s_pageSetupData->GetPrintData();
326  }
327 }
328 
329 
330 wxPrintData* DIALOG_PRINT_GENERIC::s_PrintData = nullptr;
331 wxPageSetupDialogData* DIALOG_PRINT_GENERIC::s_pageSetupData = nullptr;
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:271
double getScaleValue()
Return scale value selected in the dialog.
const PAGE_INFO & m_pageInfo
Definition: printout.h:63
wxPrintOrientation GetWxOrientation() const
Definition: page_info.h:122
virtual void Save(APP_SETTINGS_BASE *aConfig)
Definition: printout.cpp:24
Handle the parameters used to print a board drawing.
Definition: printout.h:31
This file is part of the common library.
int GetHeightMils() const
Definition: page_info.h:133
void onPageSetup(wxCommandEvent &event) override
void onCancelButtonClick(wxCommandEvent &aEvent) override
Class DIALOG_PRINT_GENERIC_BASE.
bool IsCustom() const
Definition: page_info.cpp:180
The base class for create windows for drawing purpose.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
static constexpr double MIN_SCALE
wxPaperSize GetPaperId() const
Definition: page_info.h:127
virtual void Load(APP_SETTINGS_BASE *aConfig)
Definition: printout.cpp:32
double m_scale
Printing scale.
Definition: printout.h:58
void onPrintButtonClick(wxCommandEvent &event) override
void setScaleValue(double aValue)
Select a corresponding scale radio button and update custom scale value if needed.
bool m_titleBlock
Print frame and title block.
Definition: printout.h:59
static constexpr double MAX_SCALE
PRINTOUT_SETTINGS * m_settings
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
static wxPrintData * s_PrintData
#define _(s)
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
bool m_blackWhite
Print in B&W or Color.
Definition: printout.h:60
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
bool TransferDataToWindow() override
const int scale
see class PGM_BASE
bool IsPortrait() const
Definition: page_info.h:117
int m_pageCount
Number of pages to print.
Definition: printout.h:61
static wxPageSetupDialogData * s_pageSetupData
DIALOG_PRINT_GENERIC(EDA_DRAW_FRAME *aParent, PRINTOUT_SETTINGS *aSettings)
int Mils2mm(double x)
Convert mils to mm.
Definition: base_units.cpp:62
void onClose(wxCloseEvent &event) override
void ForcePrintBorder(bool aValue)
Set 'print border and title block' to a requested value and hides the corresponding checkbox.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:299
void onPrintPreview(wxCommandEvent &event) override
APP_SETTINGS_BASE * m_config
void onSetCustomScale(wxCommandEvent &event) override
wxStdDialogButtonSizer * m_sdbSizer1
virtual wxPrintout * createPrintout(const wxString &aTitle)=0
Create a printout with a requested title.
int GetWidthMils() const
Definition: page_info.h:130
wxFloatingPointValidator< double > m_scaleValidator