KiCad PCB EDA Suite
dialog_print_pcbnew.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  * Copyright (C) 2018 CERN
7  * Author: Maciej Suminski <maciej.suminski@cern.ch>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <fctsys.h>
28 #include <kiface_i.h>
29 #include <class_drawpanel.h>
30 #include <confirm.h>
31 #include <pcb_edit_frame.h>
32 #include <footprint_edit_frame.h>
33 #include <base_units.h>
34 #include <pcbnew.h>
35 #include <pcbplot.h>
36 #include <class_board.h>
37 
38 #include <tool/tool_manager.h>
39 #include <tools/pcb_actions.h>
40 
41 #include <dialog_print_generic.h>
42 #include <pcbnew_printout.h>
43 
44 
46 {
47 public:
50 
51 private:
53  {
54  wxASSERT( dynamic_cast<PCBNEW_PRINTOUT_SETTINGS*>( m_settings ) );
55  return static_cast<PCBNEW_PRINTOUT_SETTINGS*>( m_settings );
56  }
57 
58  bool TransferDataToWindow() override;
59 
60  void createExtraOptions();
61  void createLeftPanel();
62 
63  void onSelectAllClick( wxCommandEvent& event );
64  void onDeselectAllClick( wxCommandEvent& event );
65 
67  void setListBoxValue( wxCheckListBox* aList, bool aValue );
68 
70  bool isLayerEnabled( unsigned int aLayer ) const;
71 
73  void enableLayer( unsigned int aLayer, bool aValue );
74 
76  int setLayerSetFromList();
77 
78  void saveSettings() override;
79 
80  wxPrintout* createPrintout( const wxString& aTitle ) override
81  {
82  return new PCBNEW_PRINTOUT( m_parent->GetBoard(), *settings(),
83  m_parent->GetGalCanvas()->GetView(), aTitle );
84  }
85 
87 
88  // List of existing board layers in wxCheckListBox, with the board layers id:
89  std::pair<wxCheckListBox*, int> m_layers[PCB_LAYER_ID_COUNT];
90 
91  // Extra widgets
92  wxCheckListBox* m_listTechLayers;
93  wxCheckListBox* m_listCopperLayers;
94  wxButton* m_buttonSelectAll;
96  wxCheckBox* m_checkboxNoEdge;
97  wxCheckBox* m_checkboxMirror;
98  wxChoice* m_drillMarksChoice;
99  wxRadioBox* m_boxPagination;
100 };
101 
102 
104  DIALOG_PRINT_GENERIC( aParent, aSettings ), m_parent( aParent )
105 {
107  memset( m_layers, 0, sizeof( m_layers ) );
108 
110  createLeftPanel();
111 }
112 
113 
115 {
117  return false;
118 
119  BOARD* board = m_parent->GetBoard();
120 
121  // Create layer list
122  for( LSEQ seq = board->GetEnabledLayers().UIOrder(); seq; ++seq )
123  {
124  PCB_LAYER_ID layer = *seq;
125  int checkIndex;
126 
127  if( IsCopperLayer( layer ) )
128  {
129  checkIndex = m_listCopperLayers->Append( board->GetLayerName( layer ) );
130  m_layers[layer] = std::make_pair( m_listCopperLayers, checkIndex );
131  }
132  else
133  {
134  checkIndex = m_listTechLayers->Append( board->GetLayerName( layer ) );
135  m_layers[layer] = std::make_pair( m_listTechLayers, checkIndex );
136  }
137 
138  m_layers[layer].first->Check( checkIndex, settings()->m_layerSet.test( layer ) );
139  }
140 
141  m_checkboxMirror->SetValue( settings()->m_mirror );
142  m_checkboxNoEdge->SetValue( settings()->m_noEdgeLayer );
143  m_titleBlock->SetValue( settings()->m_titleBlock );
144 
145  // Options to plot pads and vias holes
146  m_drillMarksChoice->SetSelection( settings()->m_drillMarks );
147 
148  // Print all layers one one page or separately
149  m_boxPagination->SetSelection( settings()->m_pagination );
150 
151  // Update the dialog layout when layers are added
152  GetSizer()->Fit( this );
153 
154  return true;
155 }
156 
157 
159 {
160  wxGridBagSizer* optionsSizer = getOptionsSizer();
161  wxStaticBox* box = getOptionsBox();
162  int rows = optionsSizer->GetEffectiveRowsCount();
163  int cols = optionsSizer->GetEffectiveColsCount();
164 
165  // Drill marks option
166  auto drillMarksLabel = new wxStaticText( box, wxID_ANY, _( "Drill marks:" ) );
167  std::vector<wxString> drillMarkChoices =
168  { _( "No drill mark" ), _( "Small mark" ), _( "Real drill" ) };
169  m_drillMarksChoice = new wxChoice( box, wxID_ANY, wxDefaultPosition,
170  wxDefaultSize, drillMarkChoices.size(), drillMarkChoices.data(), 0 );
171  m_drillMarksChoice->SetSelection( 0 );
172 
173  // Print mirrored
174  m_checkboxMirror = new wxCheckBox( box, wxID_ANY, _( "Print mirrored" ) );
175 
176  // Pagination
177  std::vector<wxString> pagesOption = { _( "One page per layer" ), _( "All layers on single page" ) };
178  m_boxPagination = new wxRadioBox( box, wxID_ANY, _( "Pagination" ), wxDefaultPosition,
179  wxDefaultSize, pagesOption.size(), pagesOption.data(), 1, wxRA_SPECIFY_COLS );
180  m_boxPagination->SetSelection( 0 );
181 
182  // Sizer layout
183  optionsSizer->Add( drillMarksLabel, wxGBPosition( rows, 0 ), wxGBSpan( 1, 1 ),
184  wxBOTTOM | wxRIGHT | wxLEFT | wxALIGN_CENTER_VERTICAL, 5 );
185  optionsSizer->Add( m_drillMarksChoice, wxGBPosition( rows, 1 ), wxGBSpan( 1, cols - 1 ),
186  wxBOTTOM | wxRIGHT | wxLEFT, 5 );
187  optionsSizer->Add( m_checkboxMirror, wxGBPosition( rows + 1, 0 ), wxGBSpan( 1, cols ),
188  wxBOTTOM | wxRIGHT | wxLEFT, 5 );
189  optionsSizer->Add( m_boxPagination, wxGBPosition( rows + 2, 0 ), wxGBSpan( 1, cols ), wxALL | wxEXPAND, 5 );
190 }
191 
192 
194 {
195  wxStaticBoxSizer* sbLayersSizer = new wxStaticBoxSizer( new wxStaticBox( this,
196  wxID_ANY, _( "Included Layers" ) ), wxVERTICAL );
197 
198  // Copper layer list
199  auto copperLabel = new wxStaticText( sbLayersSizer->GetStaticBox(), wxID_ANY, _( "Copper layers:" ) );
200  m_listCopperLayers = new wxCheckListBox( sbLayersSizer->GetStaticBox(), wxID_ANY );
201 
202  wxBoxSizer* sizerLeft = new wxBoxSizer( wxVERTICAL );
203  sizerLeft->Add( copperLabel, 0, wxRIGHT | wxLEFT, 5 );
204  sizerLeft->Add( m_listCopperLayers, 1, wxEXPAND | wxBOTTOM | wxRIGHT | wxLEFT, 5 );
205 
206 
207  // Technical layer list
208  auto technicalLabel = new wxStaticText( sbLayersSizer->GetStaticBox(), wxID_ANY, _( "Technical layers:" ) );
209  m_listTechLayers = new wxCheckListBox( sbLayersSizer->GetStaticBox(), wxID_ANY );
210 
211  wxBoxSizer* sizerRight = new wxBoxSizer( wxVERTICAL );
212  sizerRight->Add( technicalLabel, 0, wxRIGHT | wxLEFT, 5 );
213  sizerRight->Add( m_listTechLayers, 1, wxEXPAND | wxBOTTOM | wxRIGHT | wxLEFT, 5 );
214 
215 
216  // Layer list layout
217  wxBoxSizer* bLayerListsSizer = new wxBoxSizer( wxHORIZONTAL );
218  bLayerListsSizer->Add( sizerLeft, 1, wxEXPAND, 5 );
219  bLayerListsSizer->Add( sizerRight, 1, wxEXPAND, 5 );
220 
221 
222  // Select/Unselect all buttons
223  m_buttonSelectAll = new wxButton( sbLayersSizer->GetStaticBox(), wxID_ANY, _( "Select all" ) );
224  m_buttonDeselectAll = new wxButton( sbLayersSizer->GetStaticBox(), wxID_ANY, _( "Deselect all" ) );
225 
226  m_buttonSelectAll->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
227  wxCommandEventHandler( DIALOG_PRINT_PCBNEW::onSelectAllClick ), NULL, this );
228  m_buttonDeselectAll->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
229  wxCommandEventHandler( DIALOG_PRINT_PCBNEW::onDeselectAllClick ), NULL, this );
230 
231  wxBoxSizer* buttonSizer = new wxBoxSizer( wxHORIZONTAL );
232  buttonSizer->Add( m_buttonSelectAll, 1, wxALL, 5 );
233  buttonSizer->Add( m_buttonDeselectAll, 1, wxALL, 5 );
234 
235 
236  // Exclude Edge.Pcb layer checkbox
237  m_checkboxNoEdge = new wxCheckBox( sbLayersSizer->GetStaticBox(), wxID_ANY, _( "Exclude PCB edge layer" ) );
238  m_checkboxNoEdge->SetToolTip( _("Exclude contents of Edges_Pcb layer from all other layers") );
239 
240  // Static box sizer layout
241  sbLayersSizer->Add( bLayerListsSizer, 1, wxALL | wxEXPAND, 5 );
242  sbLayersSizer->Add( buttonSizer, 0, wxALL | wxEXPAND, 5 );
243  sbLayersSizer->Add( m_checkboxNoEdge, 0, wxALL | wxEXPAND, 5 );
244 
245  getMainSizer()->Insert( 0, sbLayersSizer, 1, wxEXPAND );
246 }
247 
248 
249 void DIALOG_PRINT_PCBNEW::onSelectAllClick( wxCommandEvent& event )
250 {
253 }
254 
255 
256 void DIALOG_PRINT_PCBNEW::onDeselectAllClick( wxCommandEvent& event )
257 {
260 }
261 
262 
263 void DIALOG_PRINT_PCBNEW::setListBoxValue( wxCheckListBox* aList, bool aValue )
264 {
265  for( unsigned int i = 0; i < aList->GetCount(); ++i )
266  aList->Check( i, aValue );
267 }
268 
269 
270 bool DIALOG_PRINT_PCBNEW::isLayerEnabled( unsigned int aLayer ) const
271 {
272  wxCHECK( aLayer < DIM( m_layers ), false );
273  const auto& layerInfo = m_layers[aLayer];
274 
275  if( layerInfo.first )
276  return layerInfo.first->IsChecked( layerInfo.second );
277 
278  return false;
279 }
280 
281 
282 void DIALOG_PRINT_PCBNEW::enableLayer( unsigned int aLayer, bool aValue )
283 {
284  wxCHECK( aLayer < DIM( m_layers ), /* void */ );
285  const auto& layerInfo = m_layers[aLayer];
286  layerInfo.first->Check( layerInfo.second, aValue );
287 }
288 
289 
291 {
292  settings()->m_layerSet = LSET();
293  int& pageCount = settings()->m_pageCount;
294  pageCount = 0;
295 
296  for( unsigned int layer = 0; layer < DIM( m_layers ); ++layer )
297  {
298  if( isLayerEnabled( layer ) )
299  {
300  ++pageCount;
301  settings()->m_layerSet.set( layer );
302  }
303  }
304 
305  // In Pcbnew force the EDGE layer to be printed or not with the other layers
306  settings()->m_noEdgeLayer = m_checkboxNoEdge->IsChecked();
307 
308  // All layers on one page (only if there is at least one layer selected)
309  if( m_boxPagination->GetSelection() != 0 && pageCount > 0 )
310  pageCount = 1;
311 
312  return pageCount;
313 }
314 
315 
317 {
319 
322 
323  settings()->m_pagination = m_boxPagination->GetSelection() == 0
325 
326  settings()->m_mirror = m_checkboxMirror->GetValue();
327 
329 }
330 
331 
332 void PCB_EDIT_FRAME::ToPrinter( wxCommandEvent& event )
333 {
334  // Selection affects the original item visibility
335  GetToolManager()->RunAction( PCB_ACTIONS::selectionClear, true );
336 
337  PCBNEW_PRINTOUT_SETTINGS settings( GetPageSettings() );
338  DIALOG_PRINT_PCBNEW dlg( this, &settings );
339  dlg.ShowModal();
340 }
341 
342 
343 void FOOTPRINT_EDIT_FRAME::ToPrinter( wxCommandEvent& event )
344 {
345  // Selection affects the original item visibility
346  GetToolManager()->RunAction( PCB_ACTIONS::selectionClear, true );
347 
348  PCBNEW_PRINTOUT_SETTINGS settings( GetPageSettings() );
349  DIALOG_PRINT_PCBNEW dlg( this, &settings );
350  dlg.ForcePrintBorder( false );
351  dlg.ShowModal();
352 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
bool isLayerEnabled(unsigned int aLayer) const
Check whether a layer is enabled in a listbox
#define DIM(x)
of elements in an array
Definition: macros.h:98
bool m_noEdgeLayer
Disable board outline on each page.
void onDeselectAllClick(wxCommandEvent &event)
Implementation of conversion functions that require both schematic and board internal units...
This file is part of the common library.
int setLayerSetFromList()
Update layerset basing on the selected layers
void ToPrinter(wxCommandEvent &event)
Function ToPrinter Install the print dialog.
std::pair< wxCheckListBox *, int > m_layers[PCB_LAYER_ID_COUNT]
PCBNEW_PRINTOUT_SETTINGS * settings() const
Class BOARD to handle a board.
void saveSettings() override
void enableLayer(unsigned int aLayer, bool aValue)
Enable/disable layer in a listbox
wxPrintout * createPrintout(const wxString &aTitle) override
Create a printout with a requested title.
BOARD * GetBoard() const
wxCheckListBox * m_listCopperLayers
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
wxStaticBox * getOptionsBox()
Definition of class FOOTPRINT_EDIT_FRAME.
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
void onSelectAllClick(wxCommandEvent &event)
Board plot function definition file.
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
bool m_mirror
Print mirrored.
PCB_BASE_EDIT_FRAME * m_parent
DIALOG_PRINT_PCBNEW(PCB_BASE_EDIT_FRAME *aParent, PCBNEW_PRINTOUT_SETTINGS *aSettings)
PRINTOUT_SETTINGS * m_settings
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:103
wxCheckListBox * m_listTechLayers
void setListBoxValue(wxCheckListBox *aList, bool aValue)
(Un)checks all items in a checklist box
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
bool TransferDataToWindow() override
bool TransferDataToWindow() override
Common, abstract interface for edit frames.
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
int m_pageCount
Number of pages to print.
Definition: printout.h:47
void ToPrinter(wxCommandEvent &event)
Install the print dialog.
size_t i
Definition: json11.cpp:597
enum PCBNEW_PRINTOUT_SETTINGS::PAGINATION_T m_pagination
Pagination.
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:908
enum PCBNEW_PRINTOUT_SETTINGS::DRILL_MARK_SHAPE_T m_drillMarks
Drill marks shape.
wxGridBagSizer * getOptionsSizer()
void ForcePrintBorder(bool aValue)
Set &#39;print border and title block&#39; to a requested value and hides the corresponding checkbox...
LSET m_layerSet
Layers to print.
LSEQ UIOrder() const
Definition: lset.cpp:800