KiCad PCB EDA Suite
eeschema/dialogs/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-2016 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 <class_drawpanel.h>
29 #include <confirm.h>
30 #include <class_sch_screen.h>
31 #include <schframe.h>
32 #include <base_units.h>
33 
34 #include <general.h>
35 #include <eeschema_config.h>
36 #include <sch_sheet.h>
37 #include <sch_sheet_path.h>
38 
39 #include <invoke_sch_dialog.h>
41 
42 
43 
51 {
52 public:
54 
56  {
57  return ( SCH_EDIT_FRAME* ) wxWindow::GetParent();
58  }
59 
60 private:
61  void OnCloseWindow( wxCloseEvent& event ) override;
62  void OnPageSetup( wxCommandEvent& event ) override;
63  void OnPrintPreview( wxCommandEvent& event ) override;
64  void OnPrintButtonClick( wxCommandEvent& event ) override;
65  void OnButtonCancelClick( wxCommandEvent& event ) override { Close(); }
66 
67  void initDialog();
68  void GetPrintOptions();
69 };
70 
71 
72 
76 class SCH_PRINTOUT : public wxPrintout
77 {
78 private:
80 
81 public:
82  SCH_PRINTOUT( SCH_EDIT_FRAME* aParent, const wxString& aTitle ) :
83  wxPrintout( aTitle )
84  {
85  wxASSERT( aParent != NULL );
86  m_parent = aParent;
87  }
88  bool OnPrintPage( int page ) override;
89  bool HasPage( int page ) override;
90  bool OnBeginDocument( int startPage, int endPage ) override;
91  void GetPageInfo( int* minPage, int* maxPage, int* selPageFrom, int* selPageTo ) override;
92  void DrawPage( SCH_SCREEN* aScreen );
93 };
94 
95 
100 class SCH_PREVIEW_FRAME : public wxPreviewFrame
101 {
102 public:
103  SCH_PREVIEW_FRAME( wxPrintPreview* aPreview, wxWindow* aParent,
104  const wxString& aTitle, const wxPoint& aPos = wxDefaultPosition,
105  const wxSize& aSize = wxDefaultSize ) :
106  wxPreviewFrame( aPreview, aParent, aTitle, aPos, aSize )
107  {
108  }
109 
110  bool Show( bool show ) override
111  {
112  bool ret;
113 
114  // Show or hide the window. If hiding, save current position and size.
115  // If showing, use previous position and size.
116  if( show )
117  {
118  ret = wxPreviewFrame::Show( show );
119 
120  if( s_size.x != 0 && s_size.y != 0 )
121  SetSize( s_pos.x, s_pos.y, s_size.x, s_size.y, 0 );
122  }
123  else
124  {
125  // Save the dialog's position & size before hiding
126  s_size = GetSize();
127  s_pos = GetPosition();
128 
129  ret = wxPreviewFrame::Show( show );
130  }
131 
132  return ret;
133  }
134 
135 private:
136  static wxPoint s_pos;
137  static wxSize s_size;
138 };
139 
140 
143 
144 
147 {
148  wxASSERT( aParent != NULL );
149 
150  m_checkReference->SetValue( aParent->GetPrintSheetReference() );
151  m_checkMonochrome->SetValue( aParent->GetPrintMonochrome() );
152  initDialog();
153 
154 #ifdef __WXMAC__
155  // Problems with modal on wx-2.9 - Anyway preview is standard for OSX
156  m_buttonPreview->Hide();
157 #endif
158 
159  GetSizer()->Fit( this );
160 }
161 
162 
164 {
165  SCH_EDIT_FRAME* parent = GetParent();
166 
167  // Initialize page specific print setup dialog settings.
168  const PAGE_INFO& pageInfo = parent->GetScreen()->GetPageSettings();
169  wxPageSetupDialogData& pageSetupDialogData = parent->GetPageSetupData();
170 
171  pageSetupDialogData.SetPaperId( pageInfo.GetPaperId() );
172 
173  if( pageInfo.IsCustom() )
174  {
175  if( pageInfo.IsPortrait() )
176  pageSetupDialogData.SetPaperSize( wxSize( Mils2mm( pageInfo.GetWidthMils() ),
177  Mils2mm( pageInfo.GetHeightMils() ) ) );
178  else
179  pageSetupDialogData.SetPaperSize( wxSize( Mils2mm( pageInfo.GetHeightMils() ),
180  Mils2mm( pageInfo.GetWidthMils() ) ) );
181  }
182 
183  pageSetupDialogData.GetPrintData().SetOrientation( pageInfo.GetWxOrientation() );
184 
185  if ( GetSizer() )
186  GetSizer()->SetSizeHints( this );
187 
188  // Rely on the policy in class DIALOG_SHIM, which centers the dialog
189  // initially during a runtime session but gives user the ability to move it in
190  // that session.
191  // This dialog may get moved and resized in Show(), but in case this is
192  // the first time, center it for starters.
193  Center();
194 
195  m_buttonPrint->SetDefault(); // on linux, this is inadequate to determine
196  // what ENTER does. Must also SetFocus().
197  m_buttonPrint->SetFocus();
198 }
199 
200 
202 {
203  SCH_EDIT_FRAME* parent = GetParent();
204 
205  parent->SetPrintMonochrome( m_checkMonochrome->IsChecked() );
206  parent->SetPrintSheetReference( m_checkReference->IsChecked() );
207 }
208 
209 
210 void DIALOG_PRINT_USING_PRINTER::OnCloseWindow( wxCloseEvent& event )
211 {
212  SCH_EDIT_FRAME* parent = GetParent();
213 
214  if( !IsIconized() )
215  {
216  parent->SetPrintDialogPosition( GetPosition() );
217  parent->SetPrintDialogSize( GetSize() );
218  }
219 
220  GetPrintOptions();
221 
222  EndDialog( wxID_CANCEL );
223 }
224 
225 
226 /* Open a dialog box for printer setup (printer options, page size ...)
227  */
228 void DIALOG_PRINT_USING_PRINTER::OnPageSetup( wxCommandEvent& event )
229 {
230  SCH_EDIT_FRAME* parent = GetParent();
231 
232  wxPageSetupDialog pageSetupDialog( this, &parent->GetPageSetupData() );
233 
234  pageSetupDialog.ShowModal();
235 
236  parent->GetPageSetupData() = pageSetupDialog.GetPageSetupDialogData();
237 }
238 
239 
240 /* Open and display a previewer frame for printing
241  */
242 void DIALOG_PRINT_USING_PRINTER::OnPrintPreview( wxCommandEvent& event )
243 {
244  SCH_EDIT_FRAME* parent = GetParent();
245 
246  GetPrintOptions();
247 
248  // Pass two printout objects: for preview, and possible printing.
249  wxString title = _( "Preview" );
250  wxPrintPreview* preview = new wxPrintPreview( new SCH_PRINTOUT( parent, title ),
251  new SCH_PRINTOUT( parent, title ),
252  &parent->GetPageSetupData().GetPrintData() );
253 
254  if( preview == NULL )
255  {
256  DisplayError( this, _( "Print preview error!" ) );
257  return;
258  }
259 
260  preview->SetZoom( 100 );
261 
262  SCH_PREVIEW_FRAME* frame = new SCH_PREVIEW_FRAME( preview, this, title );
263  frame->SetMinSize( wxSize( 550, 350 ) );
264 
265  // on first invocation in this runtime session, set to 2/3 size of my parent,
266  // but will be changed in Show() if not first time as will position.
267  frame->SetSize( (parent->GetSize() * 2) / 3 );
268  frame->Center();
269 
270  // On wxGTK, set the flag wxTOPLEVEL_EX_DIALOG is mandatory, if we want
271  // close the frame using the X box in caption, when the preview frame is run
272  // from a dialog
273  frame->SetExtraStyle( frame->GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
274 
275  // We use here wxPreviewFrame_WindowModal option to make the wxPrintPreview frame
276  // modal for its caller only.
277  // An other reason is the fact when closing the frame without this option,
278  // all top level frames are reenabled.
279  // With this option, only the parent is reenabled.
280  // Reenabling all top level frames should be made by the parent dialog.
281  frame->InitializeWithModality( wxPreviewFrame_WindowModal );
282 
283  frame->Raise(); // Needed on Ubuntu/Unity to display the frame
284  frame->Show( true );
285 }
286 
287 
288 void DIALOG_PRINT_USING_PRINTER::OnPrintButtonClick( wxCommandEvent& event )
289 {
290  SCH_EDIT_FRAME* parent = GetParent();
291 
292  GetPrintOptions();
293 
294  wxPrintDialogData printDialogData( parent->GetPageSetupData().GetPrintData() );
295  printDialogData.SetMaxPage( g_RootSheet->CountSheets() );
296 
297  if( g_RootSheet->CountSheets() > 1 )
298  printDialogData.EnablePageNumbers( true );
299 
300  wxPrinter printer( &printDialogData );
301  SCH_PRINTOUT printout( parent, _( "Print Schematic" ) );
302 
303  if( !printer.Print( this, &printout, true ) )
304  {
305  if( wxPrinter::GetLastError() == wxPRINTER_ERROR )
306  wxMessageBox( _( "An error occurred attempting to print the schematic." ),
307  _( "Printing" ), wxOK );
308  }
309  else
310  {
311  parent->GetPageSetupData() = printer.GetPrintDialogData().GetPrintData();
312  }
313 }
314 
315 
317 {
318  SCH_SHEET_LIST sheetList( g_RootSheet );
319 
320  wxCHECK_MSG( page >= 1 && page <= (int)sheetList.size(), false,
321  wxT( "Cannot print invalid page number." ) );
322 
323  wxCHECK_MSG( sheetList[ page - 1].LastScreen() != NULL, false,
324  wxT( "Cannot print page with NULL screen." ) );
325 
326  wxString msg;
327  msg.Printf( _( "Print page %d" ), page );
329  m_parent->AppendMsgPanel( msg, wxEmptyString, CYAN );
330 
331  SCH_SCREEN* screen = m_parent->GetScreen();
332  SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet();
333  m_parent->SetCurrentSheet( sheetList[ page - 1 ] );
336  screen = m_parent->GetCurrentSheet().LastScreen();
337  DrawPage( screen );
338  m_parent->SetCurrentSheet( oldsheetpath );
341 
342  return true;
343 }
344 
345 
346 void SCH_PRINTOUT::GetPageInfo( int* minPage, int* maxPage, int* selPageFrom, int* selPageTo )
347 {
348  *minPage = *selPageFrom = 1;
349  *maxPage = *selPageTo = g_RootSheet->CountSheets();
350 }
351 
352 
353 bool SCH_PRINTOUT::HasPage( int pageNum )
354 {
355  int pageCount;
356 
357  pageCount = g_RootSheet->CountSheets();
358 
359  if( pageCount >= pageNum )
360  return true;
361 
362  return false;
363 }
364 
365 
366 bool SCH_PRINTOUT::OnBeginDocument( int startPage, int endPage )
367 {
368  if( !wxPrintout::OnBeginDocument( startPage, endPage ) )
369  return false;
370 
371 #ifdef __WXDEBUG__
372  wxLogDebug( wxT( "Printer name: " ) +
373  m_parent->GetPageSetupData().GetPrintData().GetPrinterName() );
374  wxLogDebug( wxT( "Paper ID: %d" ),
375  m_parent->GetPageSetupData().GetPrintData().GetPaperId() );
376  wxLogDebug( wxT( "Color: %d" ),
377  (int)m_parent->GetPageSetupData().GetPrintData().GetColour() );
378  wxLogDebug( wxT( "Monochrome: %d" ), m_parent->GetPrintMonochrome() );
379  wxLogDebug( wxT( "Orientation: %d:" ),
380  m_parent->GetPageSetupData().GetPrintData().GetOrientation() );
381  wxLogDebug( wxT( "Quality: %d"),
382  m_parent->GetPageSetupData().GetPrintData().GetQuality() );
383 #endif
384 
385  return true;
386 }
387 
388 
389 /*
390  * This is the real print function: print the active screen
391  */
393 {
394  int oldZoom;
395  wxPoint tmp_startvisu;
396  wxSize pageSizeIU; // Page size in internal units
397  wxPoint old_org;
398  EDA_RECT oldClipBox;
399  wxRect fitRect;
400  wxDC* dc = GetDC();
401  EDA_DRAW_PANEL* panel = m_parent->GetCanvas();
402 
403  wxBusyCursor dummy;
404 
405  // Save current scale factor, offsets, and clip box.
406  tmp_startvisu = aScreen->m_StartVisu;
407  oldZoom = aScreen->GetZoom();
408  old_org = aScreen->m_DrawOrg;
409 
410  oldClipBox = *panel->GetClipBox();
411 
412  // Change clip box to print the whole page.
413  #define MAX_VALUE (INT_MAX/2) // MAX_VALUE is the max we can use in an integer
414  // and that allows calculations without overflow
415  panel->SetClipBox( EDA_RECT( wxPoint( 0, 0 ), wxSize( MAX_VALUE, MAX_VALUE ) ) );
416 
417  // Change scale factor and offset to print the whole page.
418  bool printReference = m_parent->GetPrintSheetReference();
419 
420  pageSizeIU = aScreen->GetPageSettings().GetSizeIU();
421  FitThisSizeToPaper( pageSizeIU );
422  fitRect = GetLogicalPaperRect();
423 
424  wxLogDebug( wxT( "Fit rectangle: x = %d, y = %d, w = %d, h = %d" ),
425  fitRect.x, fitRect.y, fitRect.width, fitRect.height );
426 
427  // When is the actual paper size does not match the schematic page
428  // size, the drawing is not perfectly centered on X or Y axis.
429  // Give a draw offset centers the schematic page on the paper draw area
430  // Because the sizes are fitted, only an Y or X offset is needed
431  // and both are 0 when sizes are identical.
432  // Y or Y offset is not null when the X/Y size ratio differs between
433  // the actual paper size and the schematic page
434  int xoffset = ( fitRect.width - pageSizeIU.x ) / 2;
435 
436  // For an obscure reason, OffsetLogicalOrigin creates issues,
437  // under some circumstances, when yoffset is not always null
438  // and changes from a page to an other page
439  // This is only a workaround, not a fix
440  // see https://bugs.launchpad.net/kicad/+bug/1464773
441  // xoffset does not create issues.
442 #if 0 // FIX ME
443  int yoffset = ( fitRect.height - pageSizeIU.y ) / 2;
444 #else
445  // the Y centering will be not perfect, but this is less annoying
446  // than a blank page or a buggy centering
447  int yoffset = 0;
448 #endif
449  OffsetLogicalOrigin( xoffset, yoffset );
450 
451  GRResetPenAndBrush( dc );
452 
454  GRForceBlackPen( true );
455 
456  aScreen->m_IsPrinting = true;
457 
458  COLOR4D bgColor = m_parent->GetDrawBgColor();
459 
460  aScreen->Draw( panel, dc, (GR_DRAWMODE) 0 );
461 
462  if( printReference )
464  IU_PER_MILS, aScreen->GetFileName() );
465 
466  m_parent->SetDrawBgColor( bgColor );
467  aScreen->m_IsPrinting = false;
468  panel->SetClipBox( oldClipBox );
469 
470  GRForceBlackPen( false );
471 
472  aScreen->m_StartVisu = tmp_startvisu;
473  aScreen->m_DrawOrg = old_org;
474  aScreen->SetZoom( oldZoom );
475 }
476 
477 
479 {
480  DIALOG_PRINT_USING_PRINTER dlg( aCaller );
481 
482  return dlg.ShowModal();
483 }
void SetCurrentSheet(const SCH_SHEET_PATH &aSheet)
Definition: schframe.cpp:574
Definition of the SCH_SHEET class for Eeschema.
Class SCH_SHEET_LIST.
void OnButtonCancelClick(wxCommandEvent &event) override
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:196
void SetPrintDialogPosition(const wxPoint &aPoint)
Definition: schframe.h:677
Implementation of conversion functions that require both schematic and board internal units...
This file is part of the common library.
EDA_DRAW_PANEL * GetCanvas()
Definition: draw_frame.h:299
int CountSheets()
Function CountSheets calculates the number of sheets found in "this" this number includes the full su...
Definition: sch_sheet.cpp:828
bool GetPrintMonochrome()
Definition: schframe.h:687
double GetZoom() const
Function GetZoom returns the current "zoom factor", which is a measure of "internal units per device ...
int GetDefaultLineThickness()
Default line thickness used to draw/plot items having a default thickness line value (i...
const wxString & GetFileName() const
bool GetPrintSheetReference()
Definition: schframe.h:689
Schematic editor (Eeschema) main window.
Definition: schframe.h:117
void SetPrintSheetReference(bool aShow)
Definition: schframe.h:690
SCH_PREVIEW_FRAME(wxPrintPreview *aPreview, wxWindow *aParent, const wxString &aTitle, const wxPoint &aPos=wxDefaultPosition, const wxSize &aSize=wxDefaultSize)
void SetPrintMonochrome(bool aMonochrome)
Definition: schframe.h:688
SCH_SCREEN * LastScreen() const
Function LastScreen.
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...
void SetClipBox(const EDA_RECT &aRect)
void OnPrintButtonClick(wxCommandEvent &event) override
SCH_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
Definition: schframe.cpp:521
int InvokeDialogPrintUsingPrinter(SCH_EDIT_FRAME *aCaller)
Create and show DIALOG_PRINT_USING_PRINTER and return whatever DIALOG_PRINT_USING_PRINTER::ShowModal(...
wxPoint m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device) ...
Custom print out for printing schematics.
bool IsPortrait() const
SCH_SHEET * g_RootSheet
Definition: eeschema.cpp:54
void GRForceBlackPen(bool flagforce)
Function GRForceBlackPen.
Definition: gr_basic.cpp:271
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:41
Definitions for the Eeschema program SCH_SCREEN class.
Class PAGE_INFO describes the page size and margins of a paper page on which to eventually print or p...
SCH_SHEET_PATH & GetCurrentSheet()
Definition: schframe.cpp:566
int Mils2mm(double x)
Convert mils to mm.
Definition: base_units.h:44
Definition: colors.h:59
void Draw(EDA_DRAW_PANEL *aCanvas, wxDC *aDC, GR_DRAWMODE aDrawMode, COLOR4D aColor=COLOR4D::UNSPECIFIED)
Function Draw draws all the items in the screen to aCanvas.
Definition: sch_screen.cpp:558
EDA_RECT * GetClipBox()
Custom schematic print preview frame.
SCH_PRINTOUT(SCH_EDIT_FRAME *aParent, const wxString &aTitle)
bool SetZoom(double iu_per_du)
Function SetZoom adjusts the current zoom factor.
Class SCH_SHEET_PATH.
wxPageSetupDialogData & GetPageSetupData()
Definition: schframe.h:670
COLOR4D GetDrawBgColor() const override
int GetWidthMils() const
#define MAX_VALUE
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.
Definition: draw_frame.cpp:753
bool IsCustom() const
Function IsCustom returns true if the type is Custom.
wxPaperSize GetPaperId() const
Function GetPaperId.
see class PGM_BASE
void SetSheetNumberAndCount()
Function SetSheetNumberAndCount Set the m_ScreenNumber and m_NumberOfScreens members for screens must...
Definition: schframe.cpp:486
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
bool OnBeginDocument(int startPage, int endPage) override
Class EDA_RECT handles the component boundary box.
wxPoint m_DrawOrg
offsets for drawing the circuit on the screen
void OnPrintPreview(wxCommandEvent &event) override
void SetDrawBgColor(COLOR4D aColor) override
const PAGE_INFO & GetPageSettings() const
void OnCloseWindow(wxCloseEvent &event) override
void DrawWorkSheet(wxDC *aDC, BASE_SCREEN *aScreen, int aLineWidth, double aScale, const wxString &aFilename, const wxString &aSheetLayer=wxEmptyString)
Function DrawWorkSheet Draws on screen the page layout with the frame and the basic inscriptions...
Definition: worksheet.cpp:77
wxPrintOrientation GetWxOrientation() const
Function GetWxOrientation.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
void SetPrintDialogSize(const wxSize &aSize)
Definition: schframe.h:683
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:69
void ClearMsgPanel(void)
Clear all messages from the message panel.
Definition: draw_frame.cpp:764
int GetHeightMils() const
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39