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