KiCad PCB EDA Suite
pcbnew/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) 2010-2016 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr
5  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.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 // Set this to 1 if you want to test PostScript printing under MSW.
26 //#define wxTEST_POSTSCRIPT_IN_MSW 1
27 
28 #include <fctsys.h>
29 #include <kiface_i.h>
30 #include <class_drawpanel.h>
31 #include <confirm.h>
32 #include <wxPcbStruct.h>
33 #include <base_units.h>
34 
35 #include <printout_controler.h>
36 #include <pcbnew.h>
37 #include <pcbplot.h>
38 
39 #include <class_board.h>
40 
42 
43 
44 #define PEN_WIDTH_MAX_VALUE ( KiROUND( 5 * IU_PER_MM ) )
45 #define PEN_WIDTH_MIN_VALUE ( KiROUND( 0.005 * IU_PER_MM ) )
46 
47 
49 
50 // Local variables
51 static double s_ScaleList[] =
52 { 0, 0.5, 0.7, 0.999, 1.0, 1.4, 2.0, 3.0, 4.0 };
53 
54 // Define min et max reasonable values for print scale
55 #define MIN_SCALE 0.01
56 #define MAX_SCALE 100.0
57 
58 // static print data and page setup data, to remember settings during the session
59 static wxPrintData* s_PrintData;
60 static wxPageSetupDialogData* s_pageSetupData = (wxPageSetupDialogData*) NULL;
61 
63 
64 
70 {
71 public:
73 
74  bool IsMirrored() { return m_Print_Mirror->IsChecked(); }
75  bool ExcludeEdges() { return m_Exclude_Edges_Pcb->IsChecked(); }
76  bool PrintUsingSinglePage() { return m_PagesOption->GetSelection(); }
78 
79 
80 private:
81 
83  wxConfigBase* m_config;
84  // the list of existing board layers in wxCheckListBox, with the
85  // board layers id:
86  std::pair<wxCheckListBox*, int> m_boxSelectLayer[PCB_LAYER_ID_COUNT];
87  static bool m_ExcludeEdgeLayer;
88 
89  void OnCloseWindow( wxCloseEvent& event ) override;
90  void OnPageSetup( wxCommandEvent& event ) override;
91  void OnPrintPreview( wxCommandEvent& event ) override;
92  void OnPrintButtonClick( wxCommandEvent& event ) override;
93  void OnScaleSelectionClick( wxCommandEvent& event ) override;
94 
95  void OnButtonCancelClick( wxCommandEvent& event ) override { Close(); }
96 
97  void OnInitDlg( wxInitDialogEvent& event ) override
98  {
99  // Call the default wxDialog handler of a wxInitDialogEvent
100  TransferDataToWindow();
101 
102  // Now all widgets have the size fixed, call FinishDialogSettings
104  }
105 
106  void SetPrintParameters( );
107  void SetPenWidth();
108  void initValues( );
109 };
110 
111 
113 
114 
115 void PCB_EDIT_FRAME::ToPrinter( wxCommandEvent& event )
116 {
117  const PAGE_INFO& pageInfo = GetPageSettings();
118 
119  if( s_PrintData == NULL ) // First print
120  {
121  s_PrintData = new wxPrintData();
122 
123  if( !s_PrintData->Ok() )
124  {
125  DisplayError( this, _( "Error Init Printer info" ) );
126  }
127  s_PrintData->SetQuality( wxPRINT_QUALITY_HIGH ); // Default resolution = HIGH;
128  }
129 
130  if( s_pageSetupData == NULL )
131  s_pageSetupData = new wxPageSetupDialogData( *s_PrintData );
132 
133  s_pageSetupData->SetPaperId( pageInfo.GetPaperId() );
134  s_pageSetupData->GetPrintData().SetOrientation( pageInfo.GetWxOrientation() );
135 
136  if( pageInfo.IsCustom() )
137  {
138  if( pageInfo.IsPortrait() )
139  s_pageSetupData->SetPaperSize( wxSize( Mils2mm( pageInfo.GetWidthMils() ),
140  Mils2mm( pageInfo.GetHeightMils() ) ) );
141  else
142  s_pageSetupData->SetPaperSize( wxSize( Mils2mm( pageInfo.GetHeightMils() ),
143  Mils2mm( pageInfo.GetWidthMils() ) ) );
144  }
145 
146  *s_PrintData = s_pageSetupData->GetPrintData();
147 
148  DIALOG_PRINT_USING_PRINTER dlg( this );
149 
150  dlg.ShowModal();
151 }
152 
153 
156 {
157  m_parent = parent;
159  memset( m_boxSelectLayer, 0, sizeof( m_boxSelectLayer ) );
160 
161  initValues( );
162 #ifdef __WXMAC__
163  /* Problems with modal on wx-2.9 - Anyway preview is standard for OSX */
164  m_buttonPreview->Hide();
165 #endif
166 }
167 
168 
170 {
171  wxString msg;
172  BOARD* board = m_parent->GetBoard();
173 
174  s_Parameters.m_PageSetupData = s_pageSetupData;
175 
176  // Create layer list.
177  LSEQ seq = board->GetEnabledLayers().UIOrder();
178 
179  for( ; seq; ++seq )
180  {
181  PCB_LAYER_ID layer = *seq;
182  int checkIndex;
183 
184  if( IsCopperLayer( layer ) )
185  {
186  checkIndex = m_CopperLayersList->Append( board->GetLayerName( layer ) );
187  m_boxSelectLayer[layer] = std::make_pair( m_CopperLayersList, checkIndex );
188  }
189  else
190  {
191  checkIndex = m_TechnicalLayersList->Append( board->GetLayerName( layer ) );
192  m_boxSelectLayer[layer] = std::make_pair( m_TechnicalLayersList, checkIndex );
193  }
194 
195  if( m_config )
196  {
197  wxString layerKey;
198  layerKey.Printf( OPTKEY_LAYERBASE, layer );
199  bool option;
200 
201  if( m_config->Read( layerKey, &option ) )
202  m_boxSelectLayer[layer].first->Check( checkIndex, option );
203  }
204  }
205 
206  // Option for excluding contents of "Edges Pcb" layer
207  m_Exclude_Edges_Pcb->Show( true );
208 
209  // Read the scale adjust option
210  int scale_idx = 4; // default selected scale = ScaleList[4] = 1.000
211 
212  if( m_config )
213  {
214  m_config->Read( OPTKEY_PRINT_X_FINESCALE_ADJ, &s_Parameters.m_XScaleAdjust );
215  m_config->Read( OPTKEY_PRINT_Y_FINESCALE_ADJ, &s_Parameters.m_YScaleAdjust );
216  m_config->Read( OPTKEY_PRINT_SCALE, &scale_idx );
217  m_config->Read( OPTKEY_PRINT_PAGE_FRAME, &s_Parameters.m_Print_Sheet_Ref, 1);
219  m_config->Read( OPTKEY_PRINT_PAGE_PER_LAYER, &s_Parameters.m_OptionPrintPage, 0);
220  int tmp;
223 
224  // Test for a reasonable scale value. Set to 1 if problem
225  if( s_Parameters.m_XScaleAdjust < MIN_SCALE ||
226  s_Parameters.m_YScaleAdjust < MIN_SCALE ||
227  s_Parameters.m_XScaleAdjust > MAX_SCALE ||
228  s_Parameters.m_YScaleAdjust > MAX_SCALE )
229  s_Parameters.m_XScaleAdjust = s_Parameters.m_YScaleAdjust = 1.0;
230  }
231 
232  m_ScaleOption->SetSelection( scale_idx );
233  scale_idx = m_ScaleOption->GetSelection();
234  s_Parameters.m_PrintScale = s_ScaleList[scale_idx];
235  m_Print_Mirror->SetValue(s_Parameters.m_PrintMirror);
237  m_Print_Sheet_Ref->SetValue( s_Parameters.m_Print_Sheet_Ref );
238 
239  // Options to plot pads and vias holes
240  m_Drill_Shape_Opt->SetSelection( s_Parameters.m_DrillShapeOpt );
241 
242  if( s_Parameters.m_Print_Black_and_White )
243  m_ModeColorOption->SetSelection( 1 );
244  else
245  m_ModeColorOption->SetSelection( 0 );
246 
247  m_PagesOption->SetSelection(s_Parameters.m_OptionPrintPage);
250  m_DialogPenWidth->SetValue(
251  StringFromValue( g_UserUnit, s_Parameters.m_PenDefaultSize ) );
252 
253  // Create scale adjust option
254  msg.Printf( wxT( "%f" ), s_Parameters.m_XScaleAdjust );
255  m_FineAdjustXscaleOpt->SetValue( msg );
256 
257  msg.Printf( wxT( "%f" ), s_Parameters.m_YScaleAdjust );
258  m_FineAdjustYscaleOpt->SetValue( msg );
259 
260  bool enable = (s_Parameters.m_PrintScale == 1.0);
261  m_FineAdjustXscaleOpt->Enable(enable);
262  m_FineAdjustYscaleOpt->Enable(enable);
263 }
264 
265 
267 {
268  int page_count = 0;
269 
270  s_Parameters.m_PrintMaskLayer = LSET();
271 
272  for( unsigned ii = 0; ii < DIM(m_boxSelectLayer); ++ii )
273  {
274  if( !m_boxSelectLayer[ii].first )
275  continue;
276 
277  if( m_boxSelectLayer[ii].first->IsChecked( m_boxSelectLayer[ii].second ) )
278  {
279  page_count++;
280  s_Parameters.m_PrintMaskLayer.set( ii );
281  }
282  }
283 
284  // In Pcbnew force the EDGE layer to be printed or not with the other layers
286  if( m_ExcludeEdgeLayer )
287  s_Parameters.m_Flags = 0;
288  else
289  s_Parameters.m_Flags = 1;
290 
291  if( PrintUsingSinglePage() )
292  page_count = 1;
293 
294  s_Parameters.m_PageCount = page_count;
295 
296  return page_count;
297 }
298 
299 
300 void DIALOG_PRINT_USING_PRINTER::OnCloseWindow( wxCloseEvent& event )
301 {
303 
304  if( m_config )
305  {
307  s_Parameters.m_XScaleAdjust );
309  s_Parameters.m_YScaleAdjust );
310  m_config->Write( OPTKEY_PRINT_SCALE, m_ScaleOption->GetSelection() );
311  m_config->Write( OPTKEY_PRINT_PAGE_FRAME, s_Parameters.m_Print_Sheet_Ref);
314  m_config->Write( OPTKEY_PRINT_PADS_DRILL, (long) s_Parameters.m_DrillShapeOpt );
315  wxString layerKey;
316 
317  for( unsigned layer = 0; layer < DIM(m_boxSelectLayer); ++layer )
318  {
319  if( !m_boxSelectLayer[layer].first )
320  continue;
321 
322  layerKey.Printf( OPTKEY_LAYERBASE, layer );
323  m_config->Write( layerKey,
324  m_boxSelectLayer[layer].first->IsChecked( m_boxSelectLayer[layer].second ) );
325  }
326  }
327 
328  EndModal( 0 );
329 }
330 
331 
333 {
335 
336  s_Parameters.m_PrintMirror = m_Print_Mirror->GetValue();
337  s_Parameters.m_Print_Sheet_Ref = m_Print_Sheet_Ref->GetValue();
338  s_Parameters.m_Print_Black_and_White =
339  m_ModeColorOption->GetSelection() != 0;
340 
341  s_Parameters.m_DrillShapeOpt =
343 
344  s_Parameters.m_OptionPrintPage = m_PagesOption->GetSelection() != 0;
345 
347 
348  int idx = m_ScaleOption->GetSelection();
349  s_Parameters.m_PrintScale = s_ScaleList[idx];
350  plot_opts.SetScale( s_Parameters.m_PrintScale );
351 
353  {
354  if( s_Parameters.m_XScaleAdjust > MAX_SCALE ||
355  s_Parameters.m_YScaleAdjust > MAX_SCALE )
356  DisplayInfoMessage( NULL, _( "Warning: Scale option set to a very large value" ) );
357 
358  m_FineAdjustXscaleOpt->GetValue().ToDouble( &s_Parameters.m_XScaleAdjust );
359  }
360 
362  {
363  // Test for a reasonable scale value
364  if( s_Parameters.m_XScaleAdjust < MIN_SCALE ||
365  s_Parameters.m_YScaleAdjust < MIN_SCALE )
366  DisplayInfoMessage( NULL, _( "Warning: Scale option set to a very small value" ) );
367 
368  m_FineAdjustYscaleOpt->GetValue().ToDouble( &s_Parameters.m_YScaleAdjust );
369  }
370 
371  plot_opts.SetFineScaleAdjustX( s_Parameters.m_XScaleAdjust );
372  plot_opts.SetFineScaleAdjustY( s_Parameters.m_YScaleAdjust );
373 
374  m_parent->SetPlotSettings( plot_opts );
375 
376  SetPenWidth();
377 }
378 
379 
381 {
382  // Get the new pen width value, and verify min et max value
383  // NOTE: s_Parameters.m_PenDefaultSize is in internal units
384 
386 
387  if( s_Parameters.m_PenDefaultSize > PEN_WIDTH_MAX_VALUE )
388  {
389  s_Parameters.m_PenDefaultSize = PEN_WIDTH_MAX_VALUE;
390  }
391 
392  if( s_Parameters.m_PenDefaultSize < PEN_WIDTH_MIN_VALUE )
393  {
394  s_Parameters.m_PenDefaultSize = PEN_WIDTH_MIN_VALUE;
395  }
396 
398 
399  m_DialogPenWidth->SetValue(
400  StringFromValue( g_UserUnit, s_Parameters.m_PenDefaultSize ) );
401 }
402 
404 {
405  double scale = s_ScaleList[m_ScaleOption->GetSelection()];
406  bool enable = (scale == 1.0);
407 
409  m_FineAdjustXscaleOpt->Enable(enable);
411  m_FineAdjustYscaleOpt->Enable(enable);
412 }
413 
414 
415 void DIALOG_PRINT_USING_PRINTER::OnPageSetup( wxCommandEvent& event )
416 {
417  wxPageSetupDialog pageSetupDialog( this, s_pageSetupData );
418  pageSetupDialog.ShowModal();
419 
420  (*s_PrintData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
421  (*s_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
422 }
423 
424 
425 void DIALOG_PRINT_USING_PRINTER::OnPrintPreview( wxCommandEvent& event )
426 {
428 
429  // If no layer selected, we have no plot. prompt user if it happens
430  // because he could think there is a bug in Pcbnew:
431  if( s_Parameters.m_PrintMaskLayer == 0 )
432  {
433  DisplayError( this, _( "No layer selected" ) );
434  return;
435  }
436 
437  // Pass two printout objects: for preview, and possible printing.
438  wxString title = _( "Print Preview" );
439  wxPrintPreview* preview =
440  new wxPrintPreview( new BOARD_PRINTOUT_CONTROLLER( s_Parameters, m_parent, title ),
441  new BOARD_PRINTOUT_CONTROLLER( s_Parameters, m_parent, title ),
442  s_PrintData );
443 
444  if( preview == NULL )
445  {
446  DisplayError( this, wxT( "An error occurred attempting to show the print preview window." ) );
447  return;
448  }
449 
450  // Uses the parent position and size.
451  wxPoint WPos = m_parent->GetPosition();
452  wxSize WSize = m_parent->GetSize();
453 
454  preview->SetZoom( 100 );
455 
456  wxPreviewFrame* frame = new wxPreviewFrame( preview, this, title, WPos, WSize );
457  frame->SetMinSize( wxSize( 550, 350 ) );
458  frame->Center();
459 
460  // On wxGTK, set the flag wxTOPLEVEL_EX_DIALOG is mandatory, if we want
461  // close the frame using the X box in caption, when the preview frame is run
462  // from a dialog
463  frame->SetExtraStyle( frame->GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
464 
465  // We use here wxPreviewFrame_WindowModal option to make the wxPrintPreview frame
466  // modal for its caller only.
467  // An other reason is the fact when closing the frame without this option,
468  // all top level frames are reenabled.
469  // With this option, only the parent is reenabled.
470  // Reenabling all top level frames should be made by the parent dialog.
471  frame->InitializeWithModality( wxPreviewFrame_WindowModal );
472 
473  frame->Raise(); // Needed on Ubuntu/Unity to display the frame
474  frame->Show( true );
475 }
476 
477 
479 {
481 
482  // If no layer selected, we have no plot. prompt user if it happens
483  // because he could think there is a bug in Pcbnew:
484  if( s_Parameters.m_PrintMaskLayer == 0 )
485  {
486  DisplayError( this, _( "No layer selected." ) );
487  return;
488  }
489 
490  wxPrintDialogData printDialogData( *s_PrintData );
491  printDialogData.SetMaxPage( s_Parameters.m_PageCount );
492 
493  wxPrinter printer( &printDialogData );
494 
495  wxString title = _( "Print" );
496  BOARD_PRINTOUT_CONTROLLER printout( s_Parameters, m_parent, title );
497 
498  if( !printer.Print( this, &printout, true ) )
499  {
500  if( wxPrinter::GetLastError() == wxPRINTER_ERROR )
501  DisplayError( this, _( "There was a problem printing." ) );
502 
503  return;
504  }
505  else
506  {
507  *s_PrintData = printer.GetPrintDialogData().GetPrintData();
508  }
509 }
#define DIM(x)
of elements in an array
Definition: macros.h:98
void OnButtonCancelClick(wxCommandEvent &event) override
#define OPTKEY_PRINT_MONOCHROME_MODE
Definition: pcbplot.h:58
#define OPTKEY_LAYERBASE
Definition: pcbplot.h:52
Board print handler definition file.
Implementation of conversion functions that require both schematic and board internal units...
This file is part of the common library.
void ToPrinter(wxCommandEvent &event)
Function ToPrinter Install the print dialog.
Class BOARD to handle a board.
wxString StringFromValue(EDA_UNITS_T aUnit, int aValue, bool aAddUnitSymbol)
Function StringFromValue returns the string from aValue according to units (inch, mm ...
Definition: base_units.cpp:203
#define OPTKEY_PRINT_SCALE
Definition: pcbplot.h:55
Class PRINT_PARAMETERS handles the parameters used to print a board drawing.
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void OnScaleSelectionClick(wxCommandEvent &event) override
BOARD * GetBoard() const
#define OPTKEY_PRINT_PAGE_FRAME
Definition: pcbplot.h:57
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
virtual const PCB_PLOT_PARAMS & GetPlotSettings() const
Function GetPlotSettings returns the PCB_PLOT_PARAMS for the BOARD owned by this frame.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
#define OPTKEY_PRINT_Y_FINESCALE_ADJ
Definition: pcbplot.h:54
Board plot function definition file.
void OnPrintButtonClick(wxCommandEvent &event) override
static wxPrintData * s_PrintData
PCB_LAYER_ID
A quick note on layer IDs:
bool IsPortrait() const
Class LSET is a set of PCB_LAYER_IDs.
std::pair< wxCheckListBox *, int > m_boxSelectLayer[PCB_LAYER_ID_COUNT]
static PRINT_PARAMETERS s_Parameters
Class PAGE_INFO describes the page size and margins of a paper page on which to eventually print or p...
int Mils2mm(double x)
Convert mils to mm.
Definition: base_units.h:44
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:101
virtual void SetPlotSettings(const PCB_PLOT_PARAMS &aSettings)
DrillShapeOptT m_DrillShapeOpt
int g_DrawDefaultLineThickness
Default line thickness in internal units used to draw or plot items using a default thickness line va...
Class PCB_PLOT_PARAMS handles plot parameters and options when plotting/printing a board...
int ValueFromTextCtrl(const wxTextCtrl &aTextCtr)
Convert the number Value in a string according to the internal units and the selected unit (g_UserUni...
Definition: base_units.cpp:384
int GetWidthMils() const
void SetScale(double aVal)
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
void OnPageSetup(wxCommandEvent &event) override
wxPageSetupDialogData * m_PageSetupData
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:56
void SetFineScaleAdjustX(double aVal)
void ConfigBaseWriteDouble(wxConfigBase *aConfig, const wxString &aKey, double aValue)
Function ConfigBaseWriteDouble This is a helper function to write doubles in config We cannot use wxC...
void OnInitDlg(wxInitDialogEvent &event) override
void DisplayInfoMessage(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayInfoMessage displays an informational message box with aMessage.
Definition: confirm.cpp:89
bool IsCustom() const
Function IsCustom returns true if the type is Custom.
#define OPTKEY_PRINT_X_FINESCALE_ADJ
Definition: pcbplot.h:53
const int scale
wxPaperSize GetPaperId() const
Function GetPaperId.
void AddUnitSymbol(wxStaticText &Stext, EDA_UNITS_T aUnit)
Definition: base_units.cpp:509
#define OPTKEY_PRINT_PADS_DRILL
Definition: pcbplot.h:60
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:166
Class BOARD_PRINTOUT_CONTROLLER is a class derived from wxPrintout to handle the necessary informatio...
const PAGE_INFO & GetPageSettings() const override
#define OPTKEY_PRINT_PAGE_PER_LAYER
Definition: pcbplot.h:59
void SetFineScaleAdjustY(double aVal)
void OnPrintPreview(wxCommandEvent &event) override
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
void OnCloseWindow(wxCloseEvent &event) override
wxPrintOrientation GetWxOrientation() const
Function GetWxOrientation.
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:69
int GetHeightMils() const
LSEQ UIOrder() const
Definition: lset.cpp:752
static wxPageSetupDialogData * s_pageSetupData