KiCad PCB EDA Suite
dialog_page_settings.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) 1992-2020 Kicad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <base_screen.h>
25 #include <confirm.h>
26 #include <core/arraydim.h>
27 #include <dialog_page_settings.h>
28 #include <eda_draw_frame.h>
29 #include <eda_item.h>
30 #include <gr_basic.h>
31 #include <kiface_i.h>
32 #include <math/util.h> // for KiROUND, Clamp
33 #include <project.h>
34 #include <title_block.h>
35 #include <tool/actions.h>
36 #include <tool/tool_manager.h>
39 #include <page_layout/ws_painter.h>
40 #include <wx/valgen.h>
41 #include <wx/tokenzr.h>
42 
43 #ifdef EESCHEMA
44 #include <general.h>
45 #include <sch_edit_frame.h>
46 #include <sch_screen.h>
47 #include <schematic.h>
48 #include <eeschema_settings.h>
49 #endif
50 
51 #define MAX_PAGE_EXAMPLE_SIZE 200
52 
53 
54 // List of page formats.
55 // they are prefixed by "_HKI" (already in use for hotkeys) instead of "_",
56 // because we need both the translated and the not translated version.
57 // when displayed in dialog we should explicitly call wxGetTranslation()
58 // to show the translated version.
59 // See hotkeys_basic.h for more info
60 #define _HKI( x ) wxT( x )
61 static const wxString pageFmts[] =
62 {
63  _HKI("A5 148x210mm"),
64  _HKI("A4 210x297mm"),
65  _HKI("A3 297x420mm"),
66  _HKI("A2 420x594mm"),
67  _HKI("A1 594x841mm"),
68  _HKI("A0 841x1189mm"),
69  _HKI("A 8.5x11in"),
70  _HKI("B 11x17in"),
71  _HKI("C 17x22in"),
72  _HKI("D 22x34in"),
73  _HKI("E 34x44in"),
74  _HKI("USLetter 8.5x11in"), // USLetter without space is correct
75  _HKI("USLegal 8.5x14in"), // USLegal without space is correct
76  _HKI("USLedger 11x17in"), // USLedger without space is correct
77  _HKI("User (Custom)"), // size defined by user. The string must contain "Custom"
78  // to be recognized in code
79 };
80 
81 DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* parent, wxSize aMaxUserSizeMils ) :
83  m_initialized( false ),
84  m_customSizeX( parent, m_userSizeXLabel, m_userSizeXCtrl, m_userSizeXUnits, false ),
85  m_customSizeY( parent, m_userSizeYLabel, m_userSizeYCtrl, m_userSizeYUnits, false )
86 {
87  m_parent = parent;
91  m_maxPageSizeMils = aMaxUserSizeMils;
93  m_customFmt = false;
95 
97  wxString serialization;
99  m_pagelayout->SetPageLayout( TO_UTF8( serialization ) );
100 
101  m_PickDate->SetValue( wxDateTime::Now() );
102 
103  if( parent->GetName() == PL_EDITOR_FRAME_NAME )
104  {
105  SetTitle( _( "Preview Settings" ) );
106  m_staticTextPaper->SetLabel( _( "Preview Paper" ) );
107  m_staticTextTitleBlock->SetLabel( _( "Preview Title Block Data" ) );
108  }
109  else
110  {
111  SetTitle( _( "Page Settings" ) );
112  m_staticTextPaper->SetLabel( _( "Paper" ) );
113  m_staticTextTitleBlock->SetLabel( _( "Title Block" ) );
114  }
115 
116  initDialog();
117 
118  GetSizer()->SetSizeHints( this );
119  Centre();
120 }
121 
122 
124 {
125 #ifdef EESCHEMA
126  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
127  wxASSERT( cfg );
128 
129  cfg->m_PageSettings.export_paper = m_PaperExport->GetValue();
130  cfg->m_PageSettings.export_revision = m_RevisionExport->GetValue();
131  cfg->m_PageSettings.export_date = m_DateExport->GetValue();
132  cfg->m_PageSettings.export_title = m_TitleExport->GetValue();
133  cfg->m_PageSettings.export_company = m_CompanyExport->GetValue();
134  cfg->m_PageSettings.export_comment1 = m_Comment1Export->GetValue();
135  cfg->m_PageSettings.export_comment2 = m_Comment2Export->GetValue();
136  cfg->m_PageSettings.export_comment3 = m_Comment3Export->GetValue();
137  cfg->m_PageSettings.export_comment4 = m_Comment4Export->GetValue();
138  cfg->m_PageSettings.export_comment5 = m_Comment5Export->GetValue();
139  cfg->m_PageSettings.export_comment6 = m_Comment6Export->GetValue();
140  cfg->m_PageSettings.export_comment7 = m_Comment7Export->GetValue();
141  cfg->m_PageSettings.export_comment8 = m_Comment8Export->GetValue();
142  cfg->m_PageSettings.export_comment9 = m_Comment9Export->GetValue();
143 #endif
144 
145  delete m_page_bitmap;
146  delete m_pagelayout;
147 }
148 
149 
151 {
152  wxString msg;
153 
154  // initialize page format choice box and page format list.
155  // The first shows translated strings, the second contains not translated strings
156  m_paperSizeComboBox->Clear();
157 
158  for( const wxString& pageFmt : pageFmts )
159  {
160  m_pageFmt.Add( pageFmt );
161  m_paperSizeComboBox->Append( wxGetTranslation( pageFmt ) );
162  }
163 
164  // initialize the page layout descr filename
166 
167 #ifdef EESCHEMA
168  // Init display value for schematic sub-sheet number
169  wxString format = m_TextSheetCount->GetLabel();
170  msg.Printf( format, m_screen->GetPageCount() );
171  m_TextSheetCount->SetLabel( msg );
172 
173  format = m_TextSheetNumber->GetLabel();
174  msg.Printf( format, m_screen->GetVirtualPageNumber() );
175  m_TextSheetNumber->SetLabel( msg );
176 #else
177  m_TextSheetCount->Show( false );
178  m_TextSheetNumber->Show( false );
179 #endif
180 
183  m_orientationComboBox->SetSelection( m_pageInfo.IsPortrait() );
184 
185  // only a click fires the "selection changed" event, so have to fabricate this check
186  wxCommandEvent dummy;
188 
189  if( m_customFmt )
190  {
193  }
194  else
195  {
198  }
199 
200  m_TextRevision->SetValue( m_tb.GetRevision() );
201  m_TextDate->SetValue( m_tb.GetDate() );
202  m_TextTitle->SetValue( m_tb.GetTitle() );
203  m_TextCompany->SetValue( m_tb.GetCompany() );
204  m_TextComment1->SetValue( m_tb.GetComment( 0 ) );
205  m_TextComment2->SetValue( m_tb.GetComment( 1 ) );
206  m_TextComment3->SetValue( m_tb.GetComment( 2 ) );
207  m_TextComment4->SetValue( m_tb.GetComment( 3 ) );
208  m_TextComment5->SetValue( m_tb.GetComment( 4 ) );
209  m_TextComment6->SetValue( m_tb.GetComment( 5 ) );
210  m_TextComment7->SetValue( m_tb.GetComment( 6 ) );
211  m_TextComment8->SetValue( m_tb.GetComment( 7 ) );
212  m_TextComment9->SetValue( m_tb.GetComment( 8 ) );
213 
214 #ifdef EESCHEMA
215  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
216  wxASSERT( cfg );
217 
218  m_PaperExport->SetValue( cfg->m_PageSettings.export_paper );
219  m_RevisionExport->SetValue( cfg->m_PageSettings.export_revision );
220  m_DateExport->SetValue( cfg->m_PageSettings.export_date );
221  m_TitleExport->SetValue( cfg->m_PageSettings.export_title );
222  m_CompanyExport->SetValue( cfg->m_PageSettings.export_company );
223  m_Comment1Export->SetValue( cfg->m_PageSettings.export_comment1 );
224  m_Comment2Export->SetValue( cfg->m_PageSettings.export_comment2 );
225  m_Comment3Export->SetValue( cfg->m_PageSettings.export_comment3 );
226  m_Comment4Export->SetValue( cfg->m_PageSettings.export_comment4 );
227  m_Comment5Export->SetValue( cfg->m_PageSettings.export_comment5 );
228  m_Comment6Export->SetValue( cfg->m_PageSettings.export_comment6 );
229  m_Comment7Export->SetValue( cfg->m_PageSettings.export_comment7 );
230  m_Comment8Export->SetValue( cfg->m_PageSettings.export_comment8 );
231  m_Comment9Export->SetValue( cfg->m_PageSettings.export_comment9 );
232 #else
233  m_PaperExport->Show( false );
234  m_RevisionExport->Show( false );
235  m_DateExport->Show( false );
236  m_TitleExport->Show( false );
237  m_CompanyExport->Show( false );
238  m_Comment1Export->Show( false );
239  m_Comment2Export->Show( false );
240  m_Comment3Export->Show( false );
241  m_Comment4Export->Show( false );
242  m_Comment5Export->Show( false );
243  m_Comment6Export->Show( false );
244  m_Comment7Export->Show( false );
245  m_Comment8Export->Show( false );
246  m_Comment9Export->Show( false );
247 #endif
248 
251 
252  // Make the OK button the default.
253  m_sdbSizerOK->SetDefault();
254  m_initialized = true;
255 }
256 
257 
258 void DIALOG_PAGES_SETTINGS::OnOkClick( wxCommandEvent& event )
259 {
261  return;
262 
264  return;
265 
266  if( SavePageSettings() )
267  {
268  m_screen->SetModify();
269 
270  if( LocalPrjConfigChanged() )
272 
273  // Call the post processing (if any) after changes
275  }
276 
277  event.Skip();
278 }
279 
280 
281 void DIALOG_PAGES_SETTINGS::OnPaperSizeChoice( wxCommandEvent& event )
282 {
283  int idx = m_paperSizeComboBox->GetSelection();
284 
285  if( idx < 0 )
286  idx = 0;
287 
288  const wxString paperType = m_pageFmt[idx];
289 
290  if( paperType.Contains( PAGE_INFO::Custom ) )
291  {
292  m_orientationComboBox->Enable( false );
293  m_customSizeX.Enable( true );
294  m_customSizeY.Enable( true );
295  m_customFmt = true;
296  }
297  else
298  {
299  m_orientationComboBox->Enable( true );
300 
301 #if 0
302  // ForcePortrait() does not exist, but could be useful.
303  // so I leave these lines, which could be seen as a todo feature
304  if( paperType.ForcePortrait() )
305  {
306  m_orientationComboBox->SetStringSelection( _( "Portrait" ) );
307  m_orientationComboBox->Enable( false );
308  }
309 #endif
310  m_customSizeX.Enable( false );
311  m_customSizeY.Enable( false );
312  m_customFmt = false;
313  }
314 
317 }
318 
319 
321 {
322  if( m_initialized )
323  {
326  }
327 }
328 
329 
331 {
332  if( m_initialized )
333  {
336  }
337 }
338 
339 
341 {
342  if( m_initialized )
343  {
346  }
347 }
348 
349 
350 void DIALOG_PAGES_SETTINGS::OnRevisionTextUpdated( wxCommandEvent& event )
351 {
352  if( m_initialized && m_TextRevision->IsModified() )
353  {
355  m_tb.SetRevision( m_TextRevision->GetValue() );
357  }
358 }
359 
360 
361 void DIALOG_PAGES_SETTINGS::OnDateTextUpdated( wxCommandEvent& event )
362 {
363  if( m_initialized && m_TextDate->IsModified() )
364  {
366  m_tb.SetDate( m_TextDate->GetValue() );
368  }
369 }
370 
371 
372 void DIALOG_PAGES_SETTINGS::OnTitleTextUpdated( wxCommandEvent& event )
373 {
374  if( m_initialized && m_TextTitle->IsModified() )
375  {
377  m_tb.SetTitle( m_TextTitle->GetValue() );
379  }
380 }
381 
382 
383 void DIALOG_PAGES_SETTINGS::OnCompanyTextUpdated( wxCommandEvent& event )
384 {
385  if( m_initialized && m_TextCompany->IsModified() )
386  {
388  m_tb.SetCompany( m_TextCompany->GetValue() );
390  }
391 }
392 
393 
394 void DIALOG_PAGES_SETTINGS::OnComment1TextUpdated( wxCommandEvent& event )
395 {
396  if( m_initialized && m_TextComment1->IsModified() )
397  {
399  m_tb.SetComment( 0, m_TextComment1->GetValue() );
401  }
402 }
403 
404 
405 void DIALOG_PAGES_SETTINGS::OnComment2TextUpdated( wxCommandEvent& event )
406 {
407  if( m_initialized && m_TextComment2->IsModified() )
408  {
410  m_tb.SetComment( 1, m_TextComment2->GetValue() );
412  }
413 }
414 
415 
416 void DIALOG_PAGES_SETTINGS::OnComment3TextUpdated( wxCommandEvent& event )
417 {
418  if( m_initialized && m_TextComment3->IsModified() )
419  {
421  m_tb.SetComment( 2, m_TextComment3->GetValue() );
423  }
424 }
425 
426 
427 void DIALOG_PAGES_SETTINGS::OnComment4TextUpdated( wxCommandEvent& event )
428 {
429  if( m_initialized && m_TextComment4->IsModified() )
430  {
432  m_tb.SetComment( 3, m_TextComment4->GetValue() );
434  }
435 }
436 
437 
438 void DIALOG_PAGES_SETTINGS::OnComment5TextUpdated( wxCommandEvent& event )
439 {
440  if( m_initialized && m_TextComment5->IsModified() )
441  {
443  m_tb.SetComment( 4, m_TextComment5->GetValue() );
445  }
446 }
447 
448 
449 void DIALOG_PAGES_SETTINGS::OnComment6TextUpdated( wxCommandEvent& event )
450 {
451  if( m_initialized && m_TextComment6->IsModified() )
452  {
454  m_tb.SetComment( 5, m_TextComment6->GetValue() );
456  }
457 }
458 
459 
460 void DIALOG_PAGES_SETTINGS::OnComment7TextUpdated( wxCommandEvent& event )
461 {
462  if( m_initialized && m_TextComment7->IsModified() )
463  {
465  m_tb.SetComment( 6, m_TextComment7->GetValue() );
467  }
468 }
469 
470 
471 void DIALOG_PAGES_SETTINGS::OnComment8TextUpdated( wxCommandEvent& event )
472 {
473  if( m_initialized && m_TextComment8->IsModified() )
474  {
476  m_tb.SetComment( 7, m_TextComment8->GetValue() );
478  }
479 }
480 
481 
482 void DIALOG_PAGES_SETTINGS::OnComment9TextUpdated( wxCommandEvent& event )
483 {
484  if( m_initialized && m_TextComment9->IsModified() )
485  {
487  m_tb.SetComment( 8, m_TextComment9->GetValue() );
489  }
490 }
491 
492 
493 void DIALOG_PAGES_SETTINGS::OnDateApplyClick( wxCommandEvent& event )
494 {
495  wxDateTime datetime = m_PickDate->GetValue();
496  wxString date =
497  // We can choose different formats. Only one must be uncommented
498  //
499  // datetime.Format( wxLocale::GetInfo( wxLOCALE_SHORT_DATE_FMT ) );
500  // datetime.Format( wxLocale::GetInfo( wxLOCALE_LONG_DATE_FMT ) );
501  // datetime.Format( wxT("%Y-%b-%d") );
502  datetime.FormatISODate();
503 
504  m_TextDate->SetValue( date );
505 }
506 
507 
509 {
510  bool success = false;
511 
512  wxString fileName = GetWksFileName();
513 
515  {
516  wxString fullFileName = WS_DATA_MODEL::MakeFullFileName( fileName, m_projectPath );
517 
518  if( !fullFileName.IsEmpty() && !wxFileExists( fullFileName ) )
519  {
520  wxString msg;
521  msg.Printf( _( "Page layout description file \"%s\" not found." ), fullFileName );
522  wxMessageBox( msg );
523  return false;
524  }
525 
528  pglayout.SetPageLayout( fullFileName );
530  }
531 
532  int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 );
533  const wxString paperType = m_pageFmt[idx];
534 
535  if( paperType.Contains( PAGE_INFO::Custom ) )
536  {
538 
539  success = m_pageInfo.SetType( PAGE_INFO::Custom );
540 
541  if( success )
542  {
545 
548  }
549  }
550  else
551  {
552  // search for longest common string first, e.g. A4 before A
553  if( paperType.Contains( PAGE_INFO::USLetter ) )
555  else if( paperType.Contains( PAGE_INFO::USLegal ) )
557  else if( paperType.Contains( PAGE_INFO::USLedger ) )
559  else if( paperType.Contains( PAGE_INFO::GERBER ) )
560  success = m_pageInfo.SetType( PAGE_INFO::GERBER );
561  else if( paperType.Contains( PAGE_INFO::A5 ) )
562  success = m_pageInfo.SetType( PAGE_INFO::A5 );
563  else if( paperType.Contains( PAGE_INFO::A4 ) )
564  success = m_pageInfo.SetType( PAGE_INFO::A4 );
565  else if( paperType.Contains( PAGE_INFO::A3 ) )
566  success = m_pageInfo.SetType( PAGE_INFO::A3 );
567  else if( paperType.Contains( PAGE_INFO::A2 ) )
568  success = m_pageInfo.SetType( PAGE_INFO::A2 );
569  else if( paperType.Contains( PAGE_INFO::A1 ) )
570  success = m_pageInfo.SetType( PAGE_INFO::A1 );
571  else if( paperType.Contains( PAGE_INFO::A0 ) )
572  success = m_pageInfo.SetType( PAGE_INFO::A0 );
573  else if( paperType.Contains( PAGE_INFO::A ) )
574  success = m_pageInfo.SetType( PAGE_INFO::A );
575  else if( paperType.Contains( PAGE_INFO::B ) )
576  success = m_pageInfo.SetType( PAGE_INFO::B );
577  else if( paperType.Contains( PAGE_INFO::C ) )
578  success = m_pageInfo.SetType( PAGE_INFO::C );
579  else if( paperType.Contains( PAGE_INFO::D ) )
580  success = m_pageInfo.SetType( PAGE_INFO::D );
581  else if( paperType.Contains( PAGE_INFO::E ) )
582  success = m_pageInfo.SetType( PAGE_INFO::E );
583 
584  if( success )
585  {
586  int choice = m_orientationComboBox->GetSelection();
587  m_pageInfo.SetPortrait( choice != 0 );
588  }
589  }
590 
591  if( !success )
592  {
593  wxASSERT_MSG( false, _( "the translation for paper size must preserve original spellings" ) );
595  }
596 
598 
599  m_tb.SetRevision( m_TextRevision->GetValue() );
600  m_tb.SetDate( m_TextDate->GetValue() );
601  m_tb.SetCompany( m_TextCompany->GetValue() );
602  m_tb.SetTitle( m_TextTitle->GetValue() );
603  m_tb.SetComment( 0, m_TextComment1->GetValue() );
604  m_tb.SetComment( 1, m_TextComment2->GetValue() );
605  m_tb.SetComment( 2, m_TextComment3->GetValue() );
606  m_tb.SetComment( 3, m_TextComment4->GetValue() );
607  m_tb.SetComment( 4, m_TextComment5->GetValue() );
608  m_tb.SetComment( 5, m_TextComment6->GetValue() );
609  m_tb.SetComment( 6, m_TextComment7->GetValue() );
610  m_tb.SetComment( 7, m_TextComment8->GetValue() );
611  m_tb.SetComment( 8, m_TextComment9->GetValue() );
612 
614 
615 
616 #ifdef EESCHEMA
617  wxCHECK_MSG( dynamic_cast<SCH_EDIT_FRAME*>( m_parent ), true,
618  "DIALOG_PAGES_SETTINGS::OnDateApplyClick frame is not a schematic frame!" );
619 
620  // Exports settings to other sheets if requested:
621  SCH_SCREENS ScreenList( dynamic_cast<SCH_EDIT_FRAME*>( m_parent )->Schematic().Root() );
622 
623  // Update page info and/or title blocks for all screens
624  for( SCH_SCREEN* screen = ScreenList.GetFirst(); screen; screen = ScreenList.GetNext() )
625  {
626  if( screen == m_screen )
627  continue;
628 
629  if( m_PaperExport->IsChecked() )
630  screen->SetPageSettings( m_pageInfo );
631 
632  TITLE_BLOCK tb2 = screen->GetTitleBlock();
633 
634  if( m_RevisionExport->IsChecked() )
635  tb2.SetRevision( m_tb.GetRevision() );
636 
637  if( m_DateExport->IsChecked() )
638  tb2.SetDate( m_tb.GetDate() );
639 
640  if( m_TitleExport->IsChecked() )
641  tb2.SetTitle( m_tb.GetTitle() );
642 
643  if( m_CompanyExport->IsChecked() )
644  tb2.SetCompany( m_tb.GetCompany() );
645 
646  if( m_Comment1Export->IsChecked() )
647  tb2.SetComment( 0, m_tb.GetComment( 0 ) );
648 
649  if( m_Comment2Export->IsChecked() )
650  tb2.SetComment( 1, m_tb.GetComment( 1 ) );
651 
652  if( m_Comment3Export->IsChecked() )
653  tb2.SetComment( 2, m_tb.GetComment( 2 ) );
654 
655  if( m_Comment4Export->IsChecked() )
656  tb2.SetComment( 3, m_tb.GetComment( 3 ) );
657 
658  if( m_Comment5Export->IsChecked() )
659  tb2.SetComment( 4, m_tb.GetComment( 4 ) );
660 
661  if( m_Comment6Export->IsChecked() )
662  tb2.SetComment( 5, m_tb.GetComment( 5 ) );
663 
664  if( m_Comment7Export->IsChecked() )
665  tb2.SetComment( 6, m_tb.GetComment( 6 ) );
666 
667  if( m_Comment8Export->IsChecked() )
668  tb2.SetComment( 7, m_tb.GetComment( 7 ) );
669 
670  if( m_Comment9Export->IsChecked() )
671  tb2.SetComment( 8, m_tb.GetComment( 8 ) );
672 
673  screen->SetTitleBlock( tb2 );
674  }
675 #endif
676 
677  return true;
678 }
679 
680 
681 void DIALOG_PAGES_SETTINGS::SetCurrentPageSizeSelection( const wxString& aPaperSize )
682 {
683  // search all the not translated label list containing our paper type
684  for( unsigned i = 0; i < m_pageFmt.GetCount(); ++i )
685  {
686  // parse each label looking for aPaperSize within it
687  wxStringTokenizer st( m_pageFmt[i] );
688 
689  while( st.HasMoreTokens() )
690  {
691  if( st.GetNextToken() == aPaperSize )
692  {
693  m_paperSizeComboBox->SetSelection( i );
694  return;
695  }
696  }
697  }
698 }
699 
700 
702 {
703  int lyWidth, lyHeight;
704 
705  wxSize clamped_layout_size( Clamp( MIN_PAGE_SIZE_MILS, m_layout_size.x, m_maxPageSizeMils.x ),
707 
708  double lyRatio = clamped_layout_size.x < clamped_layout_size.y ?
709  (double) clamped_layout_size.y / clamped_layout_size.x :
710  (double) clamped_layout_size.x / clamped_layout_size.y;
711 
712  if( clamped_layout_size.x < clamped_layout_size.y )
713  {
714  lyHeight = MAX_PAGE_EXAMPLE_SIZE;
715  lyWidth = KiROUND( (double) lyHeight / lyRatio );
716  }
717  else
718  {
719  lyWidth = MAX_PAGE_EXAMPLE_SIZE;
720  lyHeight = KiROUND( (double) lyWidth / lyRatio );
721  }
722 
723  if( m_page_bitmap )
724  {
725  m_PageLayoutExampleBitmap->SetBitmap( wxNullBitmap );
726  delete m_page_bitmap;
727  }
728 
729  m_page_bitmap = new wxBitmap( lyWidth + 1, lyHeight + 1 );
730 
731  if( m_page_bitmap->IsOk() )
732  {
733  double scaleW = (double) lyWidth / clamped_layout_size.x;
734  double scaleH = (double) lyHeight / clamped_layout_size.y;
735  double scale = std::min( scaleW, scaleH );
736 
737  // Prepare DC.
738  wxSize example_size( lyWidth + 1, lyHeight + 1 );
739  wxMemoryDC memDC;
740  memDC.SelectObject( *m_page_bitmap );
741  memDC.SetClippingRegion( wxPoint( 0, 0 ), example_size );
742  memDC.Clear();
743  memDC.SetUserScale( scale, scale );
744 
745  // Get logical page size and margins.
746  PAGE_INFO pageDUMMY;
747 
748  // Get page type
749  int idx = m_paperSizeComboBox->GetSelection();
750 
751  if( idx < 0 )
752  idx = 0;
753 
754  wxString pageFmtName = m_pageFmt[idx].BeforeFirst( ' ' );
755  bool portrait = clamped_layout_size.x < clamped_layout_size.y;
756  pageDUMMY.SetType( pageFmtName, portrait );
757  if( m_customFmt )
758  {
759  pageDUMMY.SetWidthMils( clamped_layout_size.x );
760  pageDUMMY.SetHeightMils( clamped_layout_size.y );
761  }
762 
763  // Draw layout preview.
764  wxString emptyString;
765  GRResetPenAndBrush( &memDC );
766 
768  KIGFX::WS_RENDER_SETTINGS renderSettings;
769  renderSettings.SetDefaultPenWidth( 1 );
770  renderSettings.SetLayerColor( LAYER_WORKSHEET, COLOR4D( RED ) );
771  renderSettings.SetPrintDC( &memDC );
772 
773  GRFilledRect( NULL, &memDC, 0, 0, m_layout_size.x, m_layout_size.y, WHITE, WHITE );
774 
775  PrintPageLayout( &renderSettings, pageDUMMY, emptyString, emptyString, m_tb,
777  wxEmptyString, m_screen->GetVirtualPageNumber() == 1 );
778 
779  memDC.SelectObject( wxNullBitmap );
782 
783  // Refresh the dialog.
784  Layout();
785  Refresh();
786  }
787 }
788 
789 
791 {
792  int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 );
793  const wxString paperType = m_pageFmt[idx];
794 
795  // here we assume translators will keep original paper size spellings
796  if( paperType.Contains( PAGE_INFO::Custom ) )
797  {
799 
800  if( m_layout_size.x && m_layout_size.y )
801  {
802  if( m_layout_size.x < m_layout_size.y )
803  m_orientationComboBox->SetStringSelection( _( "Portrait" ) );
804  else
805  m_orientationComboBox->SetStringSelection( _( "Landscape" ) );
806  }
807  }
808  else
809  {
810  PAGE_INFO pageInfo; // SetType() later to lookup size
811 
812  static const wxChar* papers[] = {
813  // longest common string first, since sequential search below
820  PAGE_INFO::A,
821  PAGE_INFO::B,
822  PAGE_INFO::C,
823  PAGE_INFO::D,
824  PAGE_INFO::E,
828  };
829 
830  unsigned i;
831 
832  for( i=0; i < arrayDim( papers ); ++i )
833  {
834  if( paperType.Contains( papers[i] ) )
835  {
836  pageInfo.SetType( papers[i] );
837  break;
838  }
839  }
840 
841  wxASSERT( i != arrayDim(papers) ); // dialog UI match the above list?
842 
843  m_layout_size = pageInfo.GetSizeMils();
844 
845  // swap sizes to match orientation
846  bool isPortrait = (bool) m_orientationComboBox->GetSelection();
847 
848  if( ( isPortrait && m_layout_size.x >= m_layout_size.y ) ||
849  ( !isPortrait && m_layout_size.x < m_layout_size.y ) )
850  {
852  }
853  }
854 }
855 
856 
858 {
859  double customSizeX = (double) m_customSizeX.GetValue() / IU_PER_MILS;
860  double customSizeY = (double) m_customSizeY.GetValue() / IU_PER_MILS;
861 
862  // Prepare to painless double -> int conversion.
863  customSizeX = Clamp( double( INT_MIN ), customSizeX, double( INT_MAX ) );
864  customSizeY = Clamp( double( INT_MIN ), customSizeY, double( INT_MAX ) );
865  m_layout_size = wxSize( KiROUND( customSizeX ), KiROUND( customSizeY ) );
866 }
867 
868 
869 void DIALOG_PAGES_SETTINGS::OnWksFileSelection( wxCommandEvent& event )
870 {
871  wxFileName fn = GetWksFileName();
872  wxString name = GetWksFileName();
873  wxString path;
874 
875  if( fn.IsAbsolute() )
876  {
877  path = fn.GetPath();
878  name = fn.GetFullName();
879  }
880  else
881  {
882  path = m_projectPath;
883  }
884 
885  // Display a file picker dialog
886  wxFileDialog fileDialog( this, _( "Select Page Layout Description File" ),
888  wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST );
889 
890  if( fileDialog.ShowModal() != wxID_OK )
891  return;
892 
893  wxString fileName = fileDialog.GetPath();
894 
895  // Try to remove the path, if the path is the current working dir,
896  // or the dir of kicad.pro (template), and use a relative path
897  wxString shortFileName = WS_DATA_MODEL::MakeShortFileName( fileName, m_projectPath );
898 
899  // For Win/Linux/macOS compatibility, a relative path is a good idea
900  if( shortFileName != GetWksFileName() && shortFileName != fileName )
901  {
902  wxString msg = wxString::Format( _(
903  "The page layout description file name has changed.\n"
904  "Do you want to use the relative path:\n"
905  "\"%s\"\n"
906  "instead of\n"
907  "\"%s\"?" ), shortFileName, fileName );
908 
909  if( !IsOK( this, msg ) )
910  shortFileName = fileName;
911  }
912 
913  SetWksFileName( shortFileName );
914 
915  if( m_pagelayout == NULL )
917 
918  m_pagelayout->SetPageLayout( fileName );
919 
922 }
Store page-layout-specific render settings.
Definition: ws_painter.h:46
void OnDateApplyClick(wxCommandEvent &event) override
WS_DATA_MODEL handles the graphic items list to draw/plot the frame and title block.
Definition: ws_data_model.h:38
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)=0
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:118
static const wxChar A[]
Definition: page_info.h:70
wxString PageLayoutDescrFileWildcard()
SCH_SCREEN * GetNext()
void OnComment5TextUpdated(wxCommandEvent &event) override
wxSize m_maxPageSizeMils
Logical page layout size.
virtual const TITLE_BLOCK & GetTitleBlock() const =0
static int GetCustomHeightMils()
Function GetCustomHeightMils.
Definition: page_info.h:177
void OnPageOrientationChoice(wxCommandEvent &event) override
This file is part of the common library.
virtual void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)=0
void SetRevision(const wxString &aRevision)
Definition: title_block.h:84
const wxString & GetComment(int aIdx) const
Definition: title_block.h:110
int GetHeightMils() const
Definition: page_info.h:141
static const wxChar E[]
Definition: page_info.h:74
void OnComment3TextUpdated(wxCommandEvent &event) override
static const wxChar GERBER[]
Definition: page_info.h:75
void GRFilledRect(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:882
TITLE_BLOCK m_tb
true if the page selection is custom
static const wxChar A3[]
Definition: page_info.h:66
void OnComment7TextUpdated(wxCommandEvent &event) override
int GetVirtualPageNumber() const
Definition: base_screen.h:140
void SetWksFileName(const wxString &aFilename)
static void SetCustomWidthMils(int aWidthInMils)
Function SetCustomWidthMils sets the width of Custom page in mils, for any custom page constructed or...
Definition: page_info.cpp:231
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Function SetType sets the name of the page type and also the sizes and margins commonly associated wi...
Definition: page_info.cpp:119
virtual void SaveProjectSettings()
Save changes to the project settings to the project (.pro) file.
int GetPageCount() const
Definition: base_screen.h:137
void SetDate(const wxString &aDate)
Function SetDate sets the date field, and defaults to the current time and date.
Definition: title_block.h:74
static const char * emptyString
#define PL_EDITOR_FRAME_NAME
void SetPageLayout(const wxString &aFullFileName=wxEmptyString, bool Append=false)
Populates the list with a custom layout, or the default layout, if no custom layout available.
void OnUserPageSizeXTextUpdated(wxCommandEvent &event) override
static const wxChar Custom[]
"User" defined page type
Definition: page_info.h:79
const wxString & GetType() const
Definition: page_info.h:98
#define MAX_PAGE_EXAMPLE_SIZE
static const wxChar D[]
Definition: page_info.h:73
const wxString GetWksFileName()
bool m_initialized
list of page sizes (not translated)
The base class for create windows for drawing purpose.
#define MIN_PAGE_SIZE_MILS
Min and max page sizes for clamping, in mils.
Definition: page_info.h:39
TITLE_BLOCK holds the information shown in the lower right corner of a plot, printout,...
Definition: title_block.h:40
wxSize m_layout_size
Temporary bitmap for the page layout example.
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:122
const wxString & GetPageNumber() const
Definition: base_screen.cpp:79
static WS_DATA_MODEL & GetTheInstance()
static function: returns the instance of WS_DATA_MODEL used in the application
static void SetAltInstance(WS_DATA_MODEL *aLayout=NULL)
static function: Set an alternate instance of WS_DATA_MODEL mainly used in page setting dialog
wxBitmap * m_page_bitmap
the page layuout filename was changed
static wxString m_PageLayoutDescrFileName
the name of the page layout descr file, or emty to used the default pagelayout
Definition: base_screen.h:84
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:95
virtual const PAGE_INFO & GetPageSettings() const =0
void OnComment8TextUpdated(wxCommandEvent &event) override
void OnComment1TextUpdated(wxCommandEvent &event) override
static const wxChar USLegal[]
Definition: page_info.h:77
void OnComment9TextUpdated(wxCommandEvent &event) override
static const wxChar B[]
Definition: page_info.h:71
void SetComment(int aIdx, const wxString &aComment)
Definition: title_block.h:104
#define NULL
static const wxChar C[]
Definition: page_info.h:72
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
const wxString & GetRevision() const
Definition: title_block.h:89
static const wxString MakeShortFileName(const wxString &aFullFileName, const wxString &aProjectPath)
void PrintPageLayout(RENDER_SETTINGS *aSettings, const PAGE_INFO &aPageInfo, const wxString &aFullSheetName, const wxString &aFileName, const TITLE_BLOCK &aTitleBlock, int aSheetCount, const wxString &aPageNumber, double aMils2Iu, const PROJECT *aProject, const wxString &aSheetLayer, bool aIsFirstPage)
Print the border and title block.
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
const wxString & GetCompany() const
Definition: title_block.h:99
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
void SetCompany(const wxString &aCompany)
Definition: title_block.h:94
Definition of file extensions used in Kicad.
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Function SetLayerColor Changes the color used to draw a layer.
static const wxChar A4[]
Definition: page_info.h:65
const wxSize & GetSizeMils() const
Definition: page_info.h:143
void OnDateTextUpdated(wxCommandEvent &event) override
void SetCurrentPageSizeSelection(const wxString &aPaperSize)
void SetTitle(const wxString &aTitle)
Definition: title_block.h:60
Definition: color4d.h:60
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:257
static const wxChar USLedger[]
Definition: page_info.h:78
DIALOG_PAGES_SETTINGS(EDA_DRAW_FRAME *parent, wxSize aMaxUserSizeMils)
void OnWksFileSelection(wxCommandEvent &event) override
Class DIALOG_PAGES_SETTINGS_BASE.
Definition: color4d.h:49
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
static const wxChar A1[]
Definition: page_info.h:68
const wxString & GetDate() const
Definition: title_block.h:79
void OnComment6TextUpdated(wxCommandEvent &event) override
static const wxChar USLetter[]
Definition: page_info.h:76
void OnOkClick(wxCommandEvent &event) override
virtual void OnPageSettingsChange()
Called when modifying the page settings.
PAGE_INFO m_pageInfo
The max page size allowed by the caller frame.
const int scale
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Function Validate Validates the control against the given range, informing the user of any errors fou...
void OnComment4TextUpdated(wxCommandEvent &event) override
void OnUserPageSizeYTextUpdated(wxCommandEvent &event) override
static const wxString MakeFullFileName(const wxString &aShortFileName, const wxString &aProjectPath)
Static function.
const char * name
Definition: DXF_plotter.cpp:59
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
bool IsPortrait() const
Definition: page_info.h:122
#define _(s)
Definition: 3d_actions.cpp:33
static const wxString pageFmts[]
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:243
static const wxChar A5[]
Definition: page_info.h:64
#define IU_PER_MILS
Definition: plotter.cpp:137
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: util.h:46
static int GetCustomWidthMils()
Function GetCustomWidthMils.
Definition: page_info.h:171
WS_DATA_MODEL * m_pagelayout
Temporary title block (basic inscriptions).
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
bool m_customFmt
Temporary page info.
static const wxChar A2[]
Definition: page_info.h:67
const wxString & GetTitle() const
Definition: title_block.h:65
SCH_SCREEN * GetFirst()
void OnComment2TextUpdated(wxCommandEvent &event) override
void OnPaperSizeChoice(wxCommandEvent &event) override
void OnTitleTextUpdated(wxCommandEvent &event) override
void OnCompanyTextUpdated(wxCommandEvent &event) override
void SetModify()
Definition: base_screen.h:120
void OnRevisionTextUpdated(wxCommandEvent &event) override
void SetDefaultPenWidth(int aWidth)
BASE_SCREEN class implementation.
#define _HKI(x)
void SetPortrait(bool aIsPortrait)
Function SetPortrait will rotate the paper page 90 degrees.
Definition: page_info.cpp:186
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:284
void SetPrintDC(wxDC *aDC)
virtual BASE_SCREEN * GetScreen() const
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SaveInString(wxString &aOutputString)
Save the description in a buffer.
void Enable(bool aEnable)
Function Enable Enables/diasables the label, widget and units label.
static void SetCustomHeightMils(int aHeightInMils)
Function SetCustomHeightMils sets the height of Custom page in mils, for any custom page constructed ...
Definition: page_info.cpp:237
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:521
int GetWidthMils() const
Definition: page_info.h:138
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100
static const wxChar A0[]
Definition: page_info.h:69