You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

831 lines
25 KiB

4 years ago
// Dick Hollenbeck's KiROUND R&D // This provides better project control over rounding to int from double // than wxRound() did. This scheme provides better logging in Debug builds // and it provides for compile time calculation of constants. #include <stdio.h> #include <assert.h> #include <limits.h> //-----<KiROUND KIT>------------------------------------------------------------ /** * KiROUND * rounds a floating point number to an int using * "round halfway cases away from zero". * In Debug build an assert fires if will not fit into an int. */ #if defined( DEBUG ) // DEBUG: a macro to capture line and file, then calls this inline static inline int KiRound( double v, int line, const char* filename ) { v = v < 0 ? v - 0.5 : v + 0.5; if( v > INT_MAX + 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v ); } else if( v < INT_MIN - 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v ); } return int( v ); } #define KiROUND( v ) KiRound( v, __LINE__, __FILE__ ) #else // RELEASE: a macro so compile can pre-compute constants. #define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 ) #endif //-----</KiROUND KIT>----------------------------------------------------------- // Only a macro is compile time calculated, an inline function causes a static constructor // in a situation like this. // Therefore the Release build is best done with a MACRO not an inline function. int Computed = KiROUND( 14.3 * 8 ); int main( int argc, char** argv ) { for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 ) { int i = KiROUND( d ); printf( "t: %d %.16g\n", i, d ); } return 0; }
14 years ago
// Dick Hollenbeck's KiROUND R&D // This provides better project control over rounding to int from double // than wxRound() did. This scheme provides better logging in Debug builds // and it provides for compile time calculation of constants. #include <stdio.h> #include <assert.h> #include <limits.h> //-----<KiROUND KIT>------------------------------------------------------------ /** * KiROUND * rounds a floating point number to an int using * "round halfway cases away from zero". * In Debug build an assert fires if will not fit into an int. */ #if defined( DEBUG ) // DEBUG: a macro to capture line and file, then calls this inline static inline int KiRound( double v, int line, const char* filename ) { v = v < 0 ? v - 0.5 : v + 0.5; if( v > INT_MAX + 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v ); } else if( v < INT_MIN - 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v ); } return int( v ); } #define KiROUND( v ) KiRound( v, __LINE__, __FILE__ ) #else // RELEASE: a macro so compile can pre-compute constants. #define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 ) #endif //-----</KiROUND KIT>----------------------------------------------------------- // Only a macro is compile time calculated, an inline function causes a static constructor // in a situation like this. // Therefore the Release build is best done with a MACRO not an inline function. int Computed = KiROUND( 14.3 * 8 ); int main( int argc, char** argv ) { for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 ) { int i = KiROUND( d ); printf( "t: %d %.16g\n", i, d ); } return 0; }
14 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or (at your
  9. * option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <env_paths.h>
  20. #include <pgm_base.h>
  21. #include <bitmaps.h>
  22. #include <base_screen.h>
  23. #include <common.h> // ExpandEnvVarSubstitutions
  24. #include <confirm.h>
  25. #include <core/arraydim.h>
  26. #include <dialogs/dialog_page_settings.h>
  27. #include <eda_draw_frame.h>
  28. #include <eda_item.h>
  29. #include <gr_basic.h>
  30. #include <kiface_base.h>
  31. #include <macros.h>
  32. #include <math/util.h> // for KiROUND, Clamp
  33. #include <project.h>
  34. #include <tool/actions.h>
  35. #include <tool/tool_manager.h>
  36. #include <wildcards_and_files_ext.h>
  37. #include <drawing_sheet/ds_data_model.h>
  38. #include <drawing_sheet/ds_painter.h>
  39. #include <string_utils.h>
  40. #include <widgets/std_bitmap_button.h>
  41. #include <wx/valgen.h>
  42. #include <wx/tokenzr.h>
  43. #include <wx/filedlg.h>
  44. #include <wx/dcmemory.h>
  45. #define MAX_PAGE_EXAMPLE_SIZE 200
  46. // List of page formats.
  47. // they are prefixed by "_HKI" (already in use for hotkeys) instead of "_",
  48. // because we need both the translated and the not translated version.
  49. // when displayed in dialog we should explicitly call wxGetTranslation()
  50. // to show the translated version.
  51. // See hotkeys_basic.h for more info
  52. #define _HKI( x ) wxT( x )
  53. static const wxString pageFmts[] =
  54. {
  55. _HKI("A5 148x210mm"),
  56. _HKI("A4 210x297mm"),
  57. _HKI("A3 297x420mm"),
  58. _HKI("A2 420x594mm"),
  59. _HKI("A1 594x841mm"),
  60. _HKI("A0 841x1189mm"),
  61. _HKI("A 8.5x11in"),
  62. _HKI("B 11x17in"),
  63. _HKI("C 17x22in"),
  64. _HKI("D 22x34in"),
  65. _HKI("E 34x44in"),
  66. _HKI("USLetter 8.5x11in"), // USLetter without space is correct
  67. _HKI("USLegal 8.5x14in"), // USLegal without space is correct
  68. _HKI("USLedger 11x17in"), // USLedger without space is correct
  69. _HKI("User (Custom)"), // size defined by user. The string must contain "Custom"
  70. // to be recognized in code
  71. };
  72. DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, double aIuPerMils,
  73. const VECTOR2D& aMaxUserSizeMils ) :
  74. DIALOG_PAGES_SETTINGS_BASE( aParent ),
  75. m_parent( aParent ),
  76. m_screen( m_parent->GetScreen() ),
  77. m_initialized( false ),
  78. m_pageBitmap( nullptr ),
  79. m_iuPerMils( aIuPerMils ),
  80. m_customSizeX( aParent, m_userSizeXLabel, m_userSizeXCtrl, m_userSizeXUnits ),
  81. m_customSizeY( aParent, m_userSizeYLabel, m_userSizeYCtrl, m_userSizeYUnits )
  82. {
  83. m_projectPath = Prj().GetProjectPath();
  84. m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
  85. m_maxPageSizeMils = aMaxUserSizeMils;
  86. m_tb = m_parent->GetTitleBlock();
  87. m_customFmt = false;
  88. m_localPrjConfigChanged = false;
  89. m_drawingSheet = new DS_DATA_MODEL;
  90. wxString serialization;
  91. DS_DATA_MODEL::GetTheInstance().SaveInString( &serialization );
  92. m_drawingSheet->SetPageLayout( TO_UTF8( serialization ) );
  93. m_PickDate->SetValue( wxDateTime::Now() );
  94. if( m_parent->GetName() == PL_EDITOR_FRAME_NAME )
  95. {
  96. SetTitle( _( "Preview Settings" ) );
  97. m_staticTextPaper->SetLabel( _( "Preview Paper" ) );
  98. m_staticTextTitleBlock->SetLabel( _( "Preview Title Block Data" ) );
  99. }
  100. else
  101. {
  102. SetTitle( _( "Page Settings" ) );
  103. m_staticTextPaper->SetLabel( _( "Paper" ) );
  104. m_staticTextTitleBlock->SetLabel( _( "Title Block" ) );
  105. }
  106. SetupStandardButtons();
  107. Centre();
  108. }
  109. DIALOG_PAGES_SETTINGS::~DIALOG_PAGES_SETTINGS()
  110. {
  111. delete m_pageBitmap;
  112. delete m_drawingSheet;
  113. }
  114. bool DIALOG_PAGES_SETTINGS::TransferDataToWindow()
  115. {
  116. // initialize page format choice box and page format list.
  117. // The first shows translated strings, the second contains not translated strings
  118. m_paperSizeComboBox->Clear();
  119. for( const wxString& pageFmt : pageFmts )
  120. {
  121. m_pageFmt.Add( pageFmt );
  122. m_paperSizeComboBox->Append( wxGetTranslation( pageFmt ) );
  123. }
  124. // initialize the drawing sheet filename
  125. SetWksFileName( BASE_SCREEN::m_DrawingSheetFileName );
  126. m_pageInfo = m_parent->GetPageSettings();
  127. SetCurrentPageSizeSelection( m_pageInfo.GetType() );
  128. m_orientationComboBox->SetSelection( m_pageInfo.IsPortrait() );
  129. // only a click fires the "selection changed" event, so have to fabricate this check
  130. wxCommandEvent dummy;
  131. OnPaperSizeChoice( dummy );
  132. if( m_customFmt )
  133. {
  134. m_customSizeX.SetDoubleValue( m_pageInfo.GetWidthMils() * m_iuPerMils );
  135. m_customSizeY.SetDoubleValue( m_pageInfo.GetHeightMils() * m_iuPerMils );
  136. }
  137. else
  138. {
  139. m_customSizeX.SetDoubleValue( m_pageInfo.GetCustomWidthMils() * m_iuPerMils );
  140. m_customSizeY.SetDoubleValue( m_pageInfo.GetCustomHeightMils() * m_iuPerMils );
  141. }
  142. m_TextRevision->SetValue( m_tb.GetRevision() );
  143. m_TextDate->SetValue( m_tb.GetDate() );
  144. m_TextTitle->SetValue( m_tb.GetTitle() );
  145. m_TextCompany->SetValue( m_tb.GetCompany() );
  146. m_TextComment1->SetValue( m_tb.GetComment( 0 ) );
  147. m_TextComment2->SetValue( m_tb.GetComment( 1 ) );
  148. m_TextComment3->SetValue( m_tb.GetComment( 2 ) );
  149. m_TextComment4->SetValue( m_tb.GetComment( 3 ) );
  150. m_TextComment5->SetValue( m_tb.GetComment( 4 ) );
  151. m_TextComment6->SetValue( m_tb.GetComment( 5 ) );
  152. m_TextComment7->SetValue( m_tb.GetComment( 6 ) );
  153. m_TextComment8->SetValue( m_tb.GetComment( 7 ) );
  154. m_TextComment9->SetValue( m_tb.GetComment( 8 ) );
  155. // The default is to disable aall these fields for the "generic" dialog
  156. m_TextSheetCount->Show( false );
  157. m_TextSheetNumber->Show( false );
  158. m_PaperExport->Show( false );
  159. m_RevisionExport->Show( false );
  160. m_DateExport->Show( false );
  161. m_TitleExport->Show( false );
  162. m_CompanyExport->Show( false );
  163. m_Comment1Export->Show( false );
  164. m_Comment2Export->Show( false );
  165. m_Comment3Export->Show( false );
  166. m_Comment4Export->Show( false );
  167. m_Comment5Export->Show( false );
  168. m_Comment6Export->Show( false );
  169. m_Comment7Export->Show( false );
  170. m_Comment8Export->Show( false );
  171. m_Comment9Export->Show( false );
  172. onTransferDataToWindow();
  173. GetPageLayoutInfoFromDialog();
  174. UpdateDrawingSheetExample();
  175. GetSizer()->SetSizeHints( this );
  176. m_initialized = true;
  177. return true;
  178. }
  179. bool DIALOG_PAGES_SETTINGS::TransferDataFromWindow()
  180. {
  181. int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 );
  182. const wxString paperType = m_pageFmt[idx];
  183. if( paperType.Contains( PAGE_INFO::Custom ) )
  184. {
  185. if( !m_customSizeX.Validate( MIN_PAGE_SIZE_MILS, m_maxPageSizeMils.x, EDA_UNITS::MILS ) )
  186. return false;
  187. if( !m_customSizeY.Validate( MIN_PAGE_SIZE_MILS, m_maxPageSizeMils.y, EDA_UNITS::MILS ) )
  188. return false;
  189. }
  190. if( SavePageSettings() )
  191. {
  192. m_screen->SetContentModified();
  193. if( LocalPrjConfigChanged() )
  194. m_parent->OnModify();
  195. // Call the post processing (if any) after changes
  196. m_parent->OnPageSettingsChange();
  197. }
  198. return true;
  199. }
  200. void DIALOG_PAGES_SETTINGS::OnPaperSizeChoice( wxCommandEvent& event )
  201. {
  202. int idx = m_paperSizeComboBox->GetSelection();
  203. if( idx < 0 )
  204. idx = 0;
  205. const wxString paperType = m_pageFmt[idx];
  206. if( paperType.Contains( PAGE_INFO::Custom ) )
  207. {
  208. m_staticTextOrient->Enable( false );
  209. m_orientationComboBox->Enable( false );
  210. m_staticTextCustSize->Enable( true );
  211. m_customSizeX.Enable( true );
  212. m_customSizeY.Enable( true );
  213. m_customFmt = true;
  214. }
  215. else
  216. {
  217. m_staticTextOrient->Enable( true );
  218. m_orientationComboBox->Enable( true );
  219. m_staticTextCustSize->Enable( false );
  220. m_customSizeX.Enable( false );
  221. m_customSizeY.Enable( false );
  222. m_customFmt = false;
  223. }
  224. GetPageLayoutInfoFromDialog();
  225. UpdateDrawingSheetExample();
  226. }
  227. void DIALOG_PAGES_SETTINGS::OnUserPageSizeXTextUpdated( wxCommandEvent& event )
  228. {
  229. if( m_initialized )
  230. {
  231. GetPageLayoutInfoFromDialog();
  232. UpdateDrawingSheetExample();
  233. }
  234. }
  235. void DIALOG_PAGES_SETTINGS::OnUserPageSizeYTextUpdated( wxCommandEvent& event )
  236. {
  237. if( m_initialized )
  238. {
  239. GetPageLayoutInfoFromDialog();
  240. UpdateDrawingSheetExample();
  241. }
  242. }
  243. void DIALOG_PAGES_SETTINGS::OnPageOrientationChoice( wxCommandEvent& event )
  244. {
  245. if( m_initialized )
  246. {
  247. GetPageLayoutInfoFromDialog();
  248. UpdateDrawingSheetExample();
  249. }
  250. }
  251. void DIALOG_PAGES_SETTINGS::OnRevisionTextUpdated( wxCommandEvent& event )
  252. {
  253. if( m_initialized && m_TextRevision->IsModified() )
  254. {
  255. GetPageLayoutInfoFromDialog();
  256. m_tb.SetRevision( m_TextRevision->GetValue() );
  257. UpdateDrawingSheetExample();
  258. }
  259. }
  260. void DIALOG_PAGES_SETTINGS::OnDateTextUpdated( wxCommandEvent& event )
  261. {
  262. if( m_initialized && m_TextDate->IsModified() )
  263. {
  264. GetPageLayoutInfoFromDialog();
  265. m_tb.SetDate( m_TextDate->GetValue() );
  266. UpdateDrawingSheetExample();
  267. }
  268. }
  269. void DIALOG_PAGES_SETTINGS::OnTitleTextUpdated( wxCommandEvent& event )
  270. {
  271. if( m_initialized && m_TextTitle->IsModified() )
  272. {
  273. GetPageLayoutInfoFromDialog();
  274. m_tb.SetTitle( m_TextTitle->GetValue() );
  275. UpdateDrawingSheetExample();
  276. }
  277. }
  278. void DIALOG_PAGES_SETTINGS::OnCompanyTextUpdated( wxCommandEvent& event )
  279. {
  280. if( m_initialized && m_TextCompany->IsModified() )
  281. {
  282. GetPageLayoutInfoFromDialog();
  283. m_tb.SetCompany( m_TextCompany->GetValue() );
  284. UpdateDrawingSheetExample();
  285. }
  286. }
  287. void DIALOG_PAGES_SETTINGS::OnComment1TextUpdated( wxCommandEvent& event )
  288. {
  289. if( m_initialized && m_TextComment1->IsModified() )
  290. {
  291. GetPageLayoutInfoFromDialog();
  292. m_tb.SetComment( 0, m_TextComment1->GetValue() );
  293. UpdateDrawingSheetExample();
  294. }
  295. }
  296. void DIALOG_PAGES_SETTINGS::OnComment2TextUpdated( wxCommandEvent& event )
  297. {
  298. if( m_initialized && m_TextComment2->IsModified() )
  299. {
  300. GetPageLayoutInfoFromDialog();
  301. m_tb.SetComment( 1, m_TextComment2->GetValue() );
  302. UpdateDrawingSheetExample();
  303. }
  304. }
  305. void DIALOG_PAGES_SETTINGS::OnComment3TextUpdated( wxCommandEvent& event )
  306. {
  307. if( m_initialized && m_TextComment3->IsModified() )
  308. {
  309. GetPageLayoutInfoFromDialog();
  310. m_tb.SetComment( 2, m_TextComment3->GetValue() );
  311. UpdateDrawingSheetExample();
  312. }
  313. }
  314. void DIALOG_PAGES_SETTINGS::OnComment4TextUpdated( wxCommandEvent& event )
  315. {
  316. if( m_initialized && m_TextComment4->IsModified() )
  317. {
  318. GetPageLayoutInfoFromDialog();
  319. m_tb.SetComment( 3, m_TextComment4->GetValue() );
  320. UpdateDrawingSheetExample();
  321. }
  322. }
  323. void DIALOG_PAGES_SETTINGS::OnComment5TextUpdated( wxCommandEvent& event )
  324. {
  325. if( m_initialized && m_TextComment5->IsModified() )
  326. {
  327. GetPageLayoutInfoFromDialog();
  328. m_tb.SetComment( 4, m_TextComment5->GetValue() );
  329. UpdateDrawingSheetExample();
  330. }
  331. }
  332. void DIALOG_PAGES_SETTINGS::OnComment6TextUpdated( wxCommandEvent& event )
  333. {
  334. if( m_initialized && m_TextComment6->IsModified() )
  335. {
  336. GetPageLayoutInfoFromDialog();
  337. m_tb.SetComment( 5, m_TextComment6->GetValue() );
  338. UpdateDrawingSheetExample();
  339. }
  340. }
  341. void DIALOG_PAGES_SETTINGS::OnComment7TextUpdated( wxCommandEvent& event )
  342. {
  343. if( m_initialized && m_TextComment7->IsModified() )
  344. {
  345. GetPageLayoutInfoFromDialog();
  346. m_tb.SetComment( 6, m_TextComment7->GetValue() );
  347. UpdateDrawingSheetExample();
  348. }
  349. }
  350. void DIALOG_PAGES_SETTINGS::OnComment8TextUpdated( wxCommandEvent& event )
  351. {
  352. if( m_initialized && m_TextComment8->IsModified() )
  353. {
  354. GetPageLayoutInfoFromDialog();
  355. m_tb.SetComment( 7, m_TextComment8->GetValue() );
  356. UpdateDrawingSheetExample();
  357. }
  358. }
  359. void DIALOG_PAGES_SETTINGS::OnComment9TextUpdated( wxCommandEvent& event )
  360. {
  361. if( m_initialized && m_TextComment9->IsModified() )
  362. {
  363. GetPageLayoutInfoFromDialog();
  364. m_tb.SetComment( 8, m_TextComment9->GetValue() );
  365. UpdateDrawingSheetExample();
  366. }
  367. }
  368. void DIALOG_PAGES_SETTINGS::OnDateApplyClick( wxCommandEvent& event )
  369. {
  370. wxDateTime datetime = m_PickDate->GetValue();
  371. wxString date =
  372. // We can choose different formats. Should probably be kept in sync with CURRENT_DATE
  373. // formatting in TITLE_BLOCK.
  374. //
  375. // datetime.Format( wxLocale::GetInfo( wxLOCALE_SHORT_DATE_FMT ) );
  376. // datetime.Format( wxLocale::GetInfo( wxLOCALE_LONG_DATE_FMT ) );
  377. // datetime.Format( wxT("%Y-%b-%d") );
  378. datetime.FormatISODate();
  379. m_TextDate->SetValue( date );
  380. }
  381. bool DIALOG_PAGES_SETTINGS::SavePageSettings()
  382. {
  383. bool success = false;
  384. wxString fileName = GetWksFileName();
  385. if( fileName != BASE_SCREEN::m_DrawingSheetFileName )
  386. {
  387. wxString fullFileName = DS_DATA_MODEL::ResolvePath( fileName, m_projectPath );
  388. if( !fullFileName.IsEmpty() && !wxFileExists( fullFileName ) )
  389. {
  390. wxString msg;
  391. msg.Printf( _( "Drawing sheet file '%s' not found." ), fullFileName );
  392. wxMessageBox( msg );
  393. return false;
  394. }
  395. BASE_SCREEN::m_DrawingSheetFileName = fileName;
  396. DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( fullFileName );
  397. m_localPrjConfigChanged = true;
  398. }
  399. int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 );
  400. const wxString paperType = m_pageFmt[idx];
  401. if( paperType.Contains( PAGE_INFO::Custom ) )
  402. {
  403. GetCustomSizeMilsFromDialog();
  404. success = m_pageInfo.SetType( PAGE_INFO::Custom );
  405. if( success )
  406. {
  407. PAGE_INFO::SetCustomWidthMils( m_layout_size.x );
  408. PAGE_INFO::SetCustomHeightMils( m_layout_size.y );
  409. m_pageInfo.SetWidthMils( m_layout_size.x );
  410. m_pageInfo.SetHeightMils( m_layout_size.y );
  411. }
  412. }
  413. else
  414. {
  415. // search for longest common string first, e.g. A4 before A
  416. if( paperType.Contains( PAGE_INFO::USLetter ) )
  417. success = m_pageInfo.SetType( PAGE_INFO::USLetter );
  418. else if( paperType.Contains( PAGE_INFO::USLegal ) )
  419. success = m_pageInfo.SetType( PAGE_INFO::USLegal );
  420. else if( paperType.Contains( PAGE_INFO::USLedger ) )
  421. success = m_pageInfo.SetType( PAGE_INFO::USLedger );
  422. else if( paperType.Contains( PAGE_INFO::GERBER ) )
  423. success = m_pageInfo.SetType( PAGE_INFO::GERBER );
  424. else if( paperType.Contains( PAGE_INFO::A5 ) )
  425. success = m_pageInfo.SetType( PAGE_INFO::A5 );
  426. else if( paperType.Contains( PAGE_INFO::A4 ) )
  427. success = m_pageInfo.SetType( PAGE_INFO::A4 );
  428. else if( paperType.Contains( PAGE_INFO::A3 ) )
  429. success = m_pageInfo.SetType( PAGE_INFO::A3 );
  430. else if( paperType.Contains( PAGE_INFO::A2 ) )
  431. success = m_pageInfo.SetType( PAGE_INFO::A2 );
  432. else if( paperType.Contains( PAGE_INFO::A1 ) )
  433. success = m_pageInfo.SetType( PAGE_INFO::A1 );
  434. else if( paperType.Contains( PAGE_INFO::A0 ) )
  435. success = m_pageInfo.SetType( PAGE_INFO::A0 );
  436. else if( paperType.Contains( PAGE_INFO::A ) )
  437. success = m_pageInfo.SetType( PAGE_INFO::A );
  438. else if( paperType.Contains( PAGE_INFO::B ) )
  439. success = m_pageInfo.SetType( PAGE_INFO::B );
  440. else if( paperType.Contains( PAGE_INFO::C ) )
  441. success = m_pageInfo.SetType( PAGE_INFO::C );
  442. else if( paperType.Contains( PAGE_INFO::D ) )
  443. success = m_pageInfo.SetType( PAGE_INFO::D );
  444. else if( paperType.Contains( PAGE_INFO::E ) )
  445. success = m_pageInfo.SetType( PAGE_INFO::E );
  446. if( success )
  447. {
  448. int choice = m_orientationComboBox->GetSelection();
  449. m_pageInfo.SetPortrait( choice != 0 );
  450. }
  451. }
  452. if( !success )
  453. {
  454. wxFAIL_MSG( "The translation for paper size must preserve original spellings" );
  455. m_pageInfo.SetType( PAGE_INFO::A4 );
  456. }
  457. m_parent->SetPageSettings( m_pageInfo );
  458. m_tb.SetRevision( m_TextRevision->GetValue() );
  459. m_tb.SetDate( m_TextDate->GetValue() );
  460. m_tb.SetCompany( m_TextCompany->GetValue() );
  461. m_tb.SetTitle( m_TextTitle->GetValue() );
  462. m_tb.SetComment( 0, m_TextComment1->GetValue() );
  463. m_tb.SetComment( 1, m_TextComment2->GetValue() );
  464. m_tb.SetComment( 2, m_TextComment3->GetValue() );
  465. m_tb.SetComment( 3, m_TextComment4->GetValue() );
  466. m_tb.SetComment( 4, m_TextComment5->GetValue() );
  467. m_tb.SetComment( 5, m_TextComment6->GetValue() );
  468. m_tb.SetComment( 6, m_TextComment7->GetValue() );
  469. m_tb.SetComment( 7, m_TextComment8->GetValue() );
  470. m_tb.SetComment( 8, m_TextComment9->GetValue() );
  471. m_parent->SetTitleBlock( m_tb );
  472. return onSavePageSettings();
  473. }
  474. void DIALOG_PAGES_SETTINGS::SetCurrentPageSizeSelection( const wxString& aPaperSize )
  475. {
  476. // search all the not translated label list containing our paper type
  477. for( unsigned i = 0; i < m_pageFmt.GetCount(); ++i )
  478. {
  479. // parse each label looking for aPaperSize within it
  480. wxStringTokenizer st( m_pageFmt[i] );
  481. while( st.HasMoreTokens() )
  482. {
  483. if( st.GetNextToken() == aPaperSize )
  484. {
  485. m_paperSizeComboBox->SetSelection( i );
  486. return;
  487. }
  488. }
  489. }
  490. }
  491. void DIALOG_PAGES_SETTINGS::UpdateDrawingSheetExample()
  492. {
  493. int lyWidth, lyHeight;
  494. VECTOR2D clamped_layout_size( Clamp( (double)MIN_PAGE_SIZE_MILS, m_layout_size.x, m_maxPageSizeMils.x ),
  495. Clamp( (double)MIN_PAGE_SIZE_MILS, m_layout_size.y, m_maxPageSizeMils.y ) );
  496. double lyRatio = clamped_layout_size.x < clamped_layout_size.y ?
  497. (double) clamped_layout_size.y / clamped_layout_size.x :
  498. (double) clamped_layout_size.x / clamped_layout_size.y;
  499. if( clamped_layout_size.x < clamped_layout_size.y )
  500. {
  501. lyHeight = MAX_PAGE_EXAMPLE_SIZE;
  502. lyWidth = KiROUND( (double) lyHeight / lyRatio );
  503. }
  504. else
  505. {
  506. lyWidth = MAX_PAGE_EXAMPLE_SIZE;
  507. lyHeight = KiROUND( (double) lyWidth / lyRatio );
  508. }
  509. if( m_pageBitmap )
  510. {
  511. m_PageLayoutExampleBitmap->SetBitmap( wxNullBitmap );
  512. delete m_pageBitmap;
  513. }
  514. m_pageBitmap = new wxBitmap( lyWidth + 1, lyHeight + 1 );
  515. if( m_pageBitmap->IsOk() )
  516. {
  517. double scaleW = (double) lyWidth / clamped_layout_size.x;
  518. double scaleH = (double) lyHeight / clamped_layout_size.y;
  519. double scale = std::min( scaleW, scaleH );
  520. // Prepare DC.
  521. wxSize example_size( lyWidth + 1, lyHeight + 1 );
  522. wxMemoryDC memDC;
  523. memDC.SelectObject( *m_pageBitmap );
  524. memDC.SetClippingRegion( wxPoint( 0, 0 ), example_size );
  525. memDC.Clear();
  526. memDC.SetUserScale( scale, scale );
  527. // Get logical page size and margins.
  528. PAGE_INFO pageDUMMY;
  529. // Get page type
  530. int idx = m_paperSizeComboBox->GetSelection();
  531. if( idx < 0 )
  532. idx = 0;
  533. wxString pageFmtName = m_pageFmt[idx].BeforeFirst( ' ' );
  534. bool portrait = clamped_layout_size.x < clamped_layout_size.y;
  535. pageDUMMY.SetType( pageFmtName, portrait );
  536. if( m_customFmt )
  537. {
  538. pageDUMMY.SetWidthMils( clamped_layout_size.x );
  539. pageDUMMY.SetHeightMils( clamped_layout_size.y );
  540. }
  541. // Draw layout preview.
  542. KIGFX::DS_RENDER_SETTINGS renderSettings;
  543. COLOR_SETTINGS* colorSettings = m_parent->GetColorSettings();
  544. COLOR4D bgColor = m_parent->GetDrawBgColor();
  545. wxString emptyString;
  546. DS_DATA_MODEL::SetAltInstance( m_drawingSheet );
  547. {
  548. GRResetPenAndBrush( &memDC );
  549. renderSettings.SetDefaultPenWidth( 1 );
  550. renderSettings.LoadColors( colorSettings );
  551. renderSettings.SetPrintDC( &memDC );
  552. if( m_parent->IsType( FRAME_SCH )
  553. || m_parent->IsType( FRAME_SCH_SYMBOL_EDITOR )
  554. || m_parent->IsType( FRAME_SCH_VIEWER ) )
  555. {
  556. COLOR4D color = renderSettings.GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET );
  557. renderSettings.SetLayerColor( LAYER_DRAWINGSHEET, color );
  558. }
  559. GRFilledRect( &memDC, VECTOR2I( 0, 0 ), m_layout_size, 0, bgColor, bgColor );
  560. PrintDrawingSheet( &renderSettings, pageDUMMY, emptyString, emptyString, emptyString,
  561. m_tb, nullptr, m_screen->GetPageCount(), m_screen->GetPageNumber(),
  562. 1, &Prj(), wxEmptyString, m_screen->GetVirtualPageNumber() == 1 );
  563. memDC.SelectObject( wxNullBitmap );
  564. m_PageLayoutExampleBitmap->SetBitmap( *m_pageBitmap );
  565. }
  566. DS_DATA_MODEL::SetAltInstance( nullptr );
  567. // Refresh the dialog.
  568. Layout();
  569. Refresh();
  570. }
  571. }
  572. void DIALOG_PAGES_SETTINGS::GetPageLayoutInfoFromDialog()
  573. {
  574. int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 );
  575. const wxString paperType = m_pageFmt[idx];
  576. // here we assume translators will keep original paper size spellings
  577. if( paperType.Contains( PAGE_INFO::Custom ) )
  578. {
  579. GetCustomSizeMilsFromDialog();
  580. if( m_layout_size.x && m_layout_size.y )
  581. {
  582. if( m_layout_size.x < m_layout_size.y )
  583. m_orientationComboBox->SetStringSelection( _( "Portrait" ) );
  584. else
  585. m_orientationComboBox->SetStringSelection( _( "Landscape" ) );
  586. }
  587. }
  588. else
  589. {
  590. PAGE_INFO pageInfo; // SetType() later to lookup size
  591. static const wxChar* papers[] = {
  592. // longest common string first, since sequential search below
  593. PAGE_INFO::A5,
  594. PAGE_INFO::A4,
  595. PAGE_INFO::A3,
  596. PAGE_INFO::A2,
  597. PAGE_INFO::A1,
  598. PAGE_INFO::A0,
  599. PAGE_INFO::A,
  600. PAGE_INFO::B,
  601. PAGE_INFO::C,
  602. PAGE_INFO::D,
  603. PAGE_INFO::E,
  604. PAGE_INFO::USLetter,
  605. PAGE_INFO::USLegal,
  606. PAGE_INFO::USLedger,
  607. };
  608. unsigned i;
  609. for( i=0; i < arrayDim( papers ); ++i )
  610. {
  611. if( paperType.Contains( papers[i] ) )
  612. {
  613. pageInfo.SetType( papers[i] );
  614. break;
  615. }
  616. }
  617. wxASSERT( i != arrayDim(papers) ); // dialog UI match the above list?
  618. VECTOR2D sz = pageInfo.GetSizeMils();
  619. m_layout_size = VECTOR2D( sz.x, sz.y );
  620. // swap sizes to match orientation
  621. bool isPortrait = (bool) m_orientationComboBox->GetSelection();
  622. if( ( isPortrait && m_layout_size.x >= m_layout_size.y ) ||
  623. ( !isPortrait && m_layout_size.x < m_layout_size.y ) )
  624. {
  625. std::swap( m_layout_size.x, m_layout_size.y );
  626. }
  627. }
  628. }
  629. void DIALOG_PAGES_SETTINGS::GetCustomSizeMilsFromDialog()
  630. {
  631. double customSizeX = (double) m_customSizeX.GetDoubleValue() / m_iuPerMils;
  632. double customSizeY = (double) m_customSizeY.GetDoubleValue() / m_iuPerMils;
  633. // Ensure layout size can be converted to int coordinates later
  634. customSizeX = Clamp( double( INT_MIN ), customSizeX, double( INT_MAX ) );
  635. customSizeY = Clamp( double( INT_MIN ), customSizeY, double( INT_MAX ) );
  636. m_layout_size = VECTOR2D( customSizeX, customSizeY );
  637. }
  638. void DIALOG_PAGES_SETTINGS::OnWksFileSelection( wxCommandEvent& event )
  639. {
  640. wxFileName fn = GetWksFileName();
  641. wxString name = fn.GetFullName();
  642. wxString path;
  643. if( fn.IsAbsolute() )
  644. {
  645. path = fn.GetPath();
  646. }
  647. else
  648. {
  649. wxFileName expanded( ExpandEnvVarSubstitutions( GetWksFileName(), &m_parentFrame->Prj() ) );
  650. if( expanded.IsAbsolute() )
  651. path = expanded.GetPath();
  652. else
  653. path = m_projectPath;
  654. }
  655. // Display a file picker dialog
  656. wxFileDialog fileDialog( this, _( "Drawing Sheet File" ), path, name,
  657. FILEEXT::DrawingSheetFileWildcard(),
  658. wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST );
  659. if( fileDialog.ShowModal() != wxID_OK )
  660. return;
  661. wxString fileName = fileDialog.GetPath();
  662. wxString shortFileName;
  663. // Try to use a project-relative path first:
  664. if( !m_projectPath.IsEmpty() && fileName.StartsWith( m_projectPath ) )
  665. {
  666. fn = wxFileName( fileName );
  667. fn.MakeRelativeTo( m_projectPath );
  668. shortFileName = fn.GetFullPath();
  669. }
  670. else
  671. {
  672. // Failing that see if we can shorten it with env vars:
  673. shortFileName = NormalizePath( fileName, &Pgm().GetLocalEnvVariables(), nullptr );
  674. }
  675. std::unique_ptr<DS_DATA_MODEL> ws = std::make_unique<DS_DATA_MODEL>();
  676. if( ws->LoadDrawingSheet( fileName ) )
  677. {
  678. delete m_drawingSheet;
  679. m_drawingSheet = ws.release();
  680. SetWksFileName( shortFileName );
  681. GetPageLayoutInfoFromDialog();
  682. UpdateDrawingSheetExample();
  683. }
  684. }