KiCad PCB EDA Suite
dialog_print_using_printer.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2015-2019 KiCad Developers, see CHANGELOG.TXT for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <fctsys.h>
26 #include <pgm_base.h>
27 #include <gr_basic.h>
28 #include <confirm.h>
29 #include <sch_screen.h>
30 #include <sch_edit_frame.h>
31 #include <base_units.h>
32 #include <general.h>
33 #include <sch_sheet.h>
34 #include <sch_sheet_path.h>
36 
37 
39 {
40 public:
42  ~DIALOG_PRINT_USING_PRINTER() override;
43 
44 private:
45  bool TransferDataToWindow() override;
46  bool TransferDataFromWindow() override;
47 
48  void OnPageSetup( wxCommandEvent& event ) override;
49  void OnPrintPreview( wxCommandEvent& event ) override;
50 
51  void GetPrintOptions();
52 
54 };
55 
56 
57 
61 class SCH_PRINTOUT : public wxPrintout
62 {
63 private:
65 
66 public:
67  SCH_PRINTOUT( SCH_EDIT_FRAME* aParent, const wxString& aTitle ) :
68  wxPrintout( aTitle )
69  {
70  wxASSERT( aParent != NULL );
71  m_parent = aParent;
72  }
73 
74  bool OnPrintPage( int page ) override;
75  bool HasPage( int page ) override;
76  bool OnBeginDocument( int startPage, int endPage ) override;
77  void GetPageInfo( int* minPage, int* maxPage, int* selPageFrom, int* selPageTo ) override;
78  void PrintPage( SCH_SCREEN* aScreen );
79 };
80 
81 
86 class SCH_PREVIEW_FRAME : public wxPreviewFrame
87 {
88 public:
89  SCH_PREVIEW_FRAME( wxPrintPreview* aPreview, wxWindow* aParent,
90  const wxString& aTitle, const wxPoint& aPos = wxDefaultPosition,
91  const wxSize& aSize = wxDefaultSize ) :
92  wxPreviewFrame( aPreview, aParent, aTitle, aPos, aSize )
93  {
94  }
95 
96  bool Show( bool show ) override
97  {
98  bool ret;
99 
100  // Show or hide the window. If hiding, save current position and size.
101  // If showing, use previous position and size.
102  if( show )
103  {
104  ret = wxPreviewFrame::Show( show );
105 
106  if( s_size.x != 0 && s_size.y != 0 )
107  SetSize( s_pos.x, s_pos.y, s_size.x, s_size.y, 0 );
108  }
109  else
110  {
111  // Save the dialog's position & size before hiding
112  s_size = GetSize();
113  s_pos = GetPosition();
114 
115  ret = wxPreviewFrame::Show( show );
116  }
117 
118  return ret;
119  }
120 
121 private:
122  static wxPoint s_pos;
123  static wxSize s_size;
124 };
125 
126 
129 
130 
133  m_parent( aParent )
134 {
135  wxASSERT( aParent != NULL );
136 
137  m_checkReference->SetValue( aParent->GetPrintSheetReference() );
138  m_checkMonochrome->SetValue( aParent->GetPrintMonochrome() );
139 
140  // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
141  // that requires us to correct the button labels here.
142  m_sdbSizer1OK->SetLabel( _( "Print" ) );
143  m_sdbSizer1Apply->SetLabel( _( "Preview" ) );
144  m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
145  m_sdbSizer1->Layout();
146 
147 #ifdef __WXMAC__
148  // Problems with modal on wx-2.9 - Anyway preview is standard for OSX
149  m_sdbSizer1Apply->Hide();
150 #endif
151 
152  m_sdbSizer1OK->SetDefault(); // on linux, this is inadequate to determine
153  // what ENTER does. Must also SetFocus().
154  m_sdbSizer1OK->SetFocus();
155 
157 }
158 
159 
161 {
162  GetPrintOptions();
163 }
164 
165 
167 {
168  // Initialize page specific print setup dialog settings.
169  const PAGE_INFO& pageInfo = m_parent->GetScreen()->GetPageSettings();
170  wxPageSetupDialogData& pageSetupDialogData = m_parent->GetPageSetupData();
171 
172  pageSetupDialogData.SetPaperId( pageInfo.GetPaperId() );
173 
174  if( pageInfo.IsCustom() )
175  {
176  if( pageInfo.IsPortrait() )
177  pageSetupDialogData.SetPaperSize( wxSize( Mils2mm( pageInfo.GetWidthMils() ),
178  Mils2mm( pageInfo.GetHeightMils() ) ) );
179  else
180  pageSetupDialogData.SetPaperSize( wxSize( Mils2mm( pageInfo.GetHeightMils() ),
181  Mils2mm( pageInfo.GetWidthMils() ) ) );
182  }
183 
184  pageSetupDialogData.GetPrintData().SetOrientation( pageInfo.GetWxOrientation() );
185 
186  return true;
187 }
188 
189 
191 {
194 }
195 
196 
197 /* Open a dialog box for printer setup (printer options, page size ...)
198  */
199 void DIALOG_PRINT_USING_PRINTER::OnPageSetup( wxCommandEvent& event )
200 {
201  wxPageSetupDialog pageSetupDialog( this, &m_parent->GetPageSetupData() );
202  pageSetupDialog.ShowModal();
203 
204  m_parent->GetPageSetupData() = pageSetupDialog.GetPageSetupDialogData();
205 }
206 
207 
208 /* Open and display a previewer frame for printing
209  */
210 void DIALOG_PRINT_USING_PRINTER::OnPrintPreview( wxCommandEvent& event )
211 {
212  GetPrintOptions();
213 
214  // Pass two printout objects: for preview, and possible printing.
215  wxString title = _( "Preview" );
216  wxPrintPreview* preview = new wxPrintPreview( new SCH_PRINTOUT( m_parent, title ),
217  new SCH_PRINTOUT( m_parent, title ),
218  &m_parent->GetPageSetupData().GetPrintData() );
219 
220  preview->SetZoom( 100 );
221 
222  SCH_PREVIEW_FRAME* frame = new SCH_PREVIEW_FRAME( preview, this, title );
223  frame->SetMinSize( wxSize( 550, 350 ) );
224 
225  // on first invocation in this runtime session, set to 2/3 size of my parent,
226  // but will be changed in Show() if not first time as will position.
227  frame->SetSize( (m_parent->GetSize() * 2) / 3 );
228  frame->Center();
229 
230  // On wxGTK, set the flag wxTOPLEVEL_EX_DIALOG is mandatory, if we want
231  // close the frame using the X box in caption, when the preview frame is run
232  // from a dialog
233  frame->SetExtraStyle( frame->GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
234 
235  // We use here wxPreviewFrame_WindowModal option to make the wxPrintPreview frame
236  // modal for its caller only.
237  // another reason is the fact when closing the frame without this option,
238  // all top level frames are reenabled.
239  // With this option, only the parent is reenabled.
240  // Reenabling all top level frames should be made by the parent dialog.
241  frame->InitializeWithModality( wxPreviewFrame_WindowModal );
242 
243  frame->Raise(); // Needed on Ubuntu/Unity to display the frame
244  frame->Show( true );
245 }
246 
247 
249 {
250  if( Pgm().m_Printing )
251  {
252  DisplayError( this, _( "Previous print job not yet complete." ) );
253  return false;
254  }
255 
256  GetPrintOptions();
257 
258  wxPrintDialogData printDialogData( m_parent->GetPageSetupData().GetPrintData() );
259  printDialogData.SetMaxPage( g_RootSheet->CountSheets() );
260 
261  if( g_RootSheet->CountSheets() > 1 )
262  printDialogData.EnablePageNumbers( true );
263 
264  wxPrinter printer( &printDialogData );
265  SCH_PRINTOUT printout( m_parent, _( "Print Schematic" ) );
266 
267  Pgm().m_Printing = true;
268  {
269  if( !printer.Print( this, &printout, true ) )
270  {
271  if( wxPrinter::GetLastError() == wxPRINTER_ERROR )
272  DisplayError( this, _( "An error occurred attempting to print the schematic." ) );
273  }
274  else
275  {
276  m_parent->GetPageSetupData() = printer.GetPrintDialogData().GetPrintData();
277  }
278  }
279  Pgm().m_Printing = false;
280 
281  return true;
282 }
283 
284 
286 {
287  SCH_SHEET_LIST sheetList( g_RootSheet );
288 
289  wxCHECK_MSG( page >= 1 && page <= (int)sheetList.size(), false,
290  wxT( "Cannot print invalid page number." ) );
291 
292  wxCHECK_MSG( sheetList[ page - 1].LastScreen() != NULL, false,
293  wxT( "Cannot print page with NULL screen." ) );
294 
295  wxString msg;
296  msg.Printf( _( "Print page %d" ), page );
298  m_parent->AppendMsgPanel( msg, wxEmptyString, CYAN );
299 
300  SCH_SCREEN* screen = m_parent->GetScreen();
301  SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet();
302  m_parent->SetCurrentSheet( sheetList[ page - 1 ] );
305  screen = m_parent->GetCurrentSheet().LastScreen();
306  PrintPage( screen );
307  m_parent->SetCurrentSheet( oldsheetpath );
310 
311  return true;
312 }
313 
314 
315 void SCH_PRINTOUT::GetPageInfo( int* minPage, int* maxPage, int* selPageFrom, int* selPageTo )
316 {
317  *minPage = *selPageFrom = 1;
318  *maxPage = *selPageTo = g_RootSheet->CountSheets();
319 }
320 
321 
322 bool SCH_PRINTOUT::HasPage( int pageNum )
323 {
324  return g_RootSheet->CountSheets() >= pageNum;
325 }
326 
327 
328 bool SCH_PRINTOUT::OnBeginDocument( int startPage, int endPage )
329 {
330  if( !wxPrintout::OnBeginDocument( startPage, endPage ) )
331  return false;
332 
333 #ifdef DEBUG
334  wxLogDebug( wxT( "Printer name: " ) +
335  m_parent->GetPageSetupData().GetPrintData().GetPrinterName() );
336  wxLogDebug( wxT( "Paper ID: %d" ),
337  m_parent->GetPageSetupData().GetPrintData().GetPaperId() );
338  wxLogDebug( wxT( "Color: %d" ),
339  (int)m_parent->GetPageSetupData().GetPrintData().GetColour() );
340  wxLogDebug( wxT( "Monochrome: %d" ), m_parent->GetPrintMonochrome() );
341  wxLogDebug( wxT( "Orientation: %d:" ),
342  m_parent->GetPageSetupData().GetPrintData().GetOrientation() );
343  wxLogDebug( wxT( "Quality: %d"),
344  m_parent->GetPageSetupData().GetPrintData().GetQuality() );
345 #endif
346 
347  return true;
348 }
349 
350 
351 /*
352  * This is the real print function: print the active screen
353  */
355 {
356  int oldZoom;
357  wxPoint tmp_startvisu;
358  wxSize pageSizeIU; // Page size in internal units
359  wxPoint old_org;
360  wxRect fitRect;
361  wxDC* dc = GetDC();
362 
363  wxBusyCursor dummy;
364 
365  // Save current scale factor, offsets, and clip box.
366  tmp_startvisu = aScreen->m_StartVisu;
367  oldZoom = aScreen->GetZoom();
368  old_org = aScreen->m_DrawOrg;
369 
370  // Change scale factor and offset to print the whole page.
371  bool printReference = m_parent->GetPrintSheetReference();
372 
373  pageSizeIU = aScreen->GetPageSettings().GetSizeIU();
374  FitThisSizeToPaper( pageSizeIU );
375  fitRect = GetLogicalPaperRect();
376 
377  wxLogDebug( wxT( "Fit rectangle: x = %d, y = %d, w = %d, h = %d" ),
378  fitRect.x, fitRect.y, fitRect.width, fitRect.height );
379 
380  // When is the actual paper size does not match the schematic page size, the drawing will
381  // not be centered on X or Y axis. Give a draw offset to center the schematic page on the
382  // paper draw area.
383  int xoffset = ( fitRect.width - pageSizeIU.x ) / 2;
384  int yoffset = ( fitRect.height - pageSizeIU.y ) / 2;
385 
386  if( dc->CanUseTransformMatrix() )
387  {
388  wxAffineMatrix2D matrix = dc->GetTransformMatrix();
389 
390  // Check for portrait/landscape mismatch:
391  if( ( fitRect.width > fitRect.height ) != ( pageSizeIU.x > pageSizeIU.y ) )
392  {
393  matrix.Rotate( M_PI_2 );
394  xoffset = ( fitRect.height - pageSizeIU.x ) / 2;
395  yoffset = ( fitRect.width - pageSizeIU.y ) / 2;
396  }
397 
398  matrix.Translate( xoffset, yoffset );
399  dc->SetTransformMatrix( matrix );
400  }
401  else
402  {
403  // wxWidgets appears to have a bug when OffsetLogicalOrigin()'s yoffset changes from
404  // page to page.
405  // NB: this is a workaround, not a fix. The Y centering will be off, but this is less
406  // annoying than a blank page. See https://bugs.launchpad.net/kicad/+bug/1464773.
407  yoffset = 0;
408 
409  OffsetLogicalOrigin( xoffset, yoffset );
410  }
411 
412  dc->SetLogicalFunction( wxCOPY );
413  GRResetPenAndBrush( dc );
414 
415  aScreen->m_IsPrinting = true;
416 
417  COLOR4D bgColor = m_parent->GetDrawBgColor();
419 
420  GRSFilledRect( nullptr, dc, fitRect.GetX(), fitRect.GetY(), fitRect.GetRight(),
421  fitRect.GetBottom(), 0, COLOR4D::WHITE, COLOR4D::WHITE );
422 
424  GRForceBlackPen( true );
425 
426  aScreen->Print( dc );
427 
428  if( printReference )
429  {
431  aScreen->GetFileName(), wxEmptyString,
433  }
434 
435  m_parent->SetDrawBgColor( bgColor );
436  aScreen->m_IsPrinting = false;
437 
438  GRForceBlackPen( false );
439 
440  aScreen->m_StartVisu = tmp_startvisu;
441  aScreen->m_DrawOrg = old_org;
442  aScreen->SetZoom( oldZoom );
443 }
444 
445 
447 {
448  DIALOG_PRINT_USING_PRINTER dlg( aCaller );
449 
450  return dlg.ShowModal();
451 }
void SetCurrentSheet(const SCH_SHEET_PATH &aSheet)
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
Class SCH_SHEET_LIST.
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:120
const wxString & GetFileName() const
Definition: sch_screen.h:123
void PrintWorkSheet(wxDC *aDC, BASE_SCREEN *aScreen, int aLineWidth, double aScale, const wxString &aFilename, const wxString &aSheetLayer=wxEmptyString, COLOR4D aColor=COLOR4D::UNSPECIFIED)
Prints the page layout with the frame and the basic inscriptions.
wxPrintOrientation GetWxOrientation() const
Function GetWxOrientation.
Definition: page_info.h:127
void GRSFilledRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, int aWidth, COLOR4D aColor, COLOR4D aBgColor)
Definition: gr_basic.cpp:923
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
int GetHeightMils() const
Definition: page_info.h:140
double GetZoom() const
Function GetZoom returns the current "zoom factor", which is a measure of "internal units per device ...
Definition: base_screen.h:240
int CountSheets()
Count the number of sheets found in "this" sheet includeing all of the subsheets.
Definition: sch_sheet.cpp:625
bool GetPrintMonochrome()
int GetDefaultLineThickness()
Default line thickness used to draw/plot items having a default thickness line value (i....
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
virtual void SetDrawBgColor(COLOR4D aColor)
bool GetPrintSheetReference()
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
Schematic editor (Eeschema) main window.
void SetPrintSheetReference(bool aShow)
SCH_PREVIEW_FRAME(wxPrintPreview *aPreview, wxWindow *aParent, const wxString &aTitle, const wxPoint &aPos=wxDefaultPosition, const wxSize &aSize=wxDefaultSize)
void SetPrintMonochrome(bool aMonochrome)
bool IsCustom() const
Function IsCustom returns true if the type is Custom.
Definition: page_info.cpp:176
void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) override
void UpdateAllScreenReferences()
Function UpdateAllScreenReferences updates the reference and the m_Multi parameter (part selection) f...
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
Definition: eeschema.cpp:167
const PAGE_INFO & GetPageSettings() const
Definition: sch_screen.h:118
wxPaperSize GetPaperId() const
Function GetPaperId.
Definition: page_info.h:134
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_EDIT_FRAME * m_parent
wxPoint m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device)
Definition: base_screen.h:117
void PrintPage(SCH_SCREEN *aScreen)
Custom print out for printing schematics.
int InvokeDialogPrintUsingPrinter(SCH_EDIT_FRAME *aCaller)
Create and show DIALOG_PRINT_USING_PRINTER and return whatever DIALOG_PRINT_USING_PRINTER::ShowModal(...
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:47
void GRForceBlackPen(bool flagforce)
Function GRForceBlackPen.
Definition: gr_basic.cpp:201
Class PAGE_INFO describes the page size and margins of a paper page on which to eventually print or p...
Definition: page_info.h:54
SCH_SHEET_PATH & GetCurrentSheet()
bool OnPrintPage(int page) override
int Mils2mm(double x)
Convert mils to mm.
Definition: base_units.h:54
Definition: colors.h:59
Class DIALOG_PRINT_USING_PRINTER_BASE.
Custom schematic print preview frame.
SCH_PRINTOUT(SCH_EDIT_FRAME *aParent, const wxString &aTitle)
SCH_LAYER_ID
Eeschema drawing layers.
virtual bool SetZoom(double iu_per_du)
Function SetZoom adjusts the current zoom factor.
Definition: base_screen.cpp:86
Class SCH_SHEET_PATH.
wxPageSetupDialogData & GetPageSetupData()
virtual void ClearMsgPanel()
Clear all messages from the message panel.
#define _(s)
bool m_IsPrinting
Definition: base_screen.h:139
void OnPageSetup(wxCommandEvent &event) override
void AppendMsgPanel(const wxString &textUpper, const wxString &textLower, COLOR4D color, int pad=6)
Append a message to the message panel.
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:368
bool Show(bool show) override
see class PGM_BASE
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
bool OnBeginDocument(int startPage, int endPage) override
bool IsPortrait() const
Definition: page_info.h:121
wxPoint m_DrawOrg
offsets for drawing the circuit on the screen
Definition: base_screen.h:112
#define IU_PER_MILS
Definition: plotter.cpp:136
Definition: colors.h:49
void OnPrintPreview(wxCommandEvent &event) override
virtual COLOR4D GetDrawBgColor() const
void Print(wxDC *aDC)
Print all the items in the screen to aDC.
Definition: sch_screen.cpp:525
DIALOG_PRINT_USING_PRINTER(SCH_EDIT_FRAME *aParent)
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
bool HasPage(int page) override
SCH_SCREEN * LastScreen() const
Function LastScreen.
int GetWidthMils() const
Definition: page_info.h:137
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39