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.

906 lines
28 KiB

// 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
// 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) 1992-2018 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. #include <base_screen.h>
  24. #include <base_struct.h>
  25. #include <common.h>
  26. #include <confirm.h>
  27. #include <dialog_page_settings.h>
  28. #include <eda_draw_frame.h>
  29. #include <fctsys.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>
  37. #include <wildcards_and_files_ext.h>
  38. #include <ws_data_model.h>
  39. #include <ws_painter.h>
  40. #include <wx/valgen.h>
  41. #include <wx/tokenzr.h>
  42. #ifdef EESCHEMA
  43. #include <general.h>
  44. #include <sch_screen.h>
  45. #include <eeschema_settings.h>
  46. #endif
  47. #define MAX_PAGE_EXAMPLE_SIZE 200
  48. // List of page formats.
  49. // they are prefixed by "_HKI" (already in use for hotkeys) instead of "_",
  50. // because we need both the translated and the not translated version.
  51. // when displayed in dialog we should explicitly call wxGetTranslation()
  52. // to show the translated version.
  53. // See hotkeys_basic.h for more info
  54. #define _HKI( x ) wxT( x )
  55. static const wxString pageFmts[] =
  56. {
  57. _HKI("A4 210x297mm"),
  58. _HKI("A3 297x420mm"),
  59. _HKI("A2 420x594mm"),
  60. _HKI("A1 594x841mm"),
  61. _HKI("A0 841x1189mm"),
  62. _HKI("A 8.5x11in"),
  63. _HKI("B 11x17in"),
  64. _HKI("C 17x22in"),
  65. _HKI("D 22x34in"),
  66. _HKI("E 34x44in"),
  67. _HKI("USLetter 8.5x11in"), // USLetter without space is correct
  68. _HKI("USLegal 8.5x14in"), // USLegal without space is correct
  69. _HKI("USLedger 11x17in"), // USLedger without space is correct
  70. _HKI("User (Custom)"), // size defined by user. The string must contain "Custom"
  71. // to be recognized in code
  72. };
  73. DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* parent, wxSize aMaxUserSizeMils ) :
  74. DIALOG_PAGES_SETTINGS_BASE( parent ),
  75. m_initialized( false ),
  76. m_customSizeX( parent, m_userSizeXLabel, m_userSizeXCtrl, m_userSizeXUnits, false ),
  77. m_customSizeY( parent, m_userSizeYLabel, m_userSizeYCtrl, m_userSizeYUnits, false )
  78. {
  79. m_parent = parent;
  80. m_screen = m_parent->GetScreen();
  81. m_projectPath = Prj().GetProjectPath();
  82. m_page_bitmap = NULL;
  83. m_maxPageSizeMils = aMaxUserSizeMils;
  84. m_tb = m_parent->GetTitleBlock();
  85. m_customFmt = false;
  86. m_localPrjConfigChanged = false;
  87. m_pagelayout = new WS_DATA_MODEL;
  88. wxString serialization;
  89. WS_DATA_MODEL::GetTheInstance().SaveInString( serialization );
  90. m_pagelayout->SetPageLayout( TO_UTF8( serialization ) );
  91. m_PickDate->SetValue( wxDateTime::Now() );
  92. if( parent->GetName() == PL_EDITOR_FRAME_NAME )
  93. {
  94. SetTitle( _( "Preview Settings" ) );
  95. m_staticTextPaper->SetLabel( _( "Preview Paper" ) );
  96. m_staticTextTitleBlock->SetLabel( _( "Preview Title Block Data" ) );
  97. }
  98. else
  99. {
  100. SetTitle( _( "Page Settings" ) );
  101. m_staticTextPaper->SetLabel( _( "Paper" ) );
  102. m_staticTextTitleBlock->SetLabel( _( "Title Block" ) );
  103. }
  104. initDialog();
  105. GetSizer()->SetSizeHints( this );
  106. Centre();
  107. }
  108. DIALOG_PAGES_SETTINGS::~DIALOG_PAGES_SETTINGS()
  109. {
  110. #ifdef EESCHEMA
  111. auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
  112. wxASSERT( cfg );
  113. cfg->m_PageSettings.export_revision = m_RevisionExport->GetValue();
  114. cfg->m_PageSettings.export_date = m_DateExport->GetValue();
  115. cfg->m_PageSettings.export_title = m_TitleExport->GetValue();
  116. cfg->m_PageSettings.export_company = m_CompanyExport->GetValue();
  117. cfg->m_PageSettings.export_comment1 = m_Comment1Export->GetValue();
  118. cfg->m_PageSettings.export_comment2 = m_Comment2Export->GetValue();
  119. cfg->m_PageSettings.export_comment3 = m_Comment3Export->GetValue();
  120. cfg->m_PageSettings.export_comment4 = m_Comment4Export->GetValue();
  121. cfg->m_PageSettings.export_comment5 = m_Comment5Export->GetValue();
  122. cfg->m_PageSettings.export_comment6 = m_Comment6Export->GetValue();
  123. cfg->m_PageSettings.export_comment7 = m_Comment7Export->GetValue();
  124. cfg->m_PageSettings.export_comment8 = m_Comment8Export->GetValue();
  125. cfg->m_PageSettings.export_comment9 = m_Comment9Export->GetValue();
  126. #endif
  127. delete m_page_bitmap;
  128. delete m_pagelayout;
  129. }
  130. void DIALOG_PAGES_SETTINGS::initDialog()
  131. {
  132. wxString msg;
  133. // initialize page format choice box and page format list.
  134. // The first shows translated strings, the second contains not translated strings
  135. m_paperSizeComboBox->Clear();
  136. for( const wxString& pageFmt : pageFmts )
  137. {
  138. m_pageFmt.Add( pageFmt );
  139. m_paperSizeComboBox->Append( wxGetTranslation( pageFmt ) );
  140. }
  141. // initialize the page layout descr filename
  142. SetWksFileName( BASE_SCREEN::m_PageLayoutDescrFileName );
  143. #ifdef EESCHEMA
  144. // Init display value for schematic sub-sheet number
  145. wxString format = m_TextSheetCount->GetLabel();
  146. msg.Printf( format, m_screen->m_NumberOfScreens );
  147. m_TextSheetCount->SetLabel( msg );
  148. format = m_TextSheetNumber->GetLabel();
  149. msg.Printf( format, m_screen->m_ScreenNumber );
  150. m_TextSheetNumber->SetLabel( msg );
  151. #else
  152. m_TextSheetCount->Show( false );
  153. m_TextSheetNumber->Show( false );
  154. #endif
  155. m_pageInfo = m_parent->GetPageSettings();
  156. SetCurrentPageSizeSelection( m_pageInfo.GetType() );
  157. m_orientationComboBox->SetSelection( m_pageInfo.IsPortrait() );
  158. // only a click fires the "selection changed" event, so have to fabricate this check
  159. wxCommandEvent dummy;
  160. OnPaperSizeChoice( dummy );
  161. if( m_customFmt )
  162. {
  163. m_customSizeX.SetValue( m_pageInfo.GetWidthMils() * IU_PER_MILS );
  164. m_customSizeY.SetValue( m_pageInfo.GetHeightMils() * IU_PER_MILS );
  165. }
  166. else
  167. {
  168. m_customSizeX.SetValue( m_pageInfo.GetCustomWidthMils() * IU_PER_MILS );
  169. m_customSizeY.SetValue( m_pageInfo.GetCustomHeightMils() * IU_PER_MILS );
  170. }
  171. m_TextRevision->SetValue( m_tb.GetRevision() );
  172. m_TextDate->SetValue( m_tb.GetDate() );
  173. m_TextTitle->SetValue( m_tb.GetTitle() );
  174. m_TextCompany->SetValue( m_tb.GetCompany() );
  175. m_TextComment1->SetValue( m_tb.GetComment( 0 ) );
  176. m_TextComment2->SetValue( m_tb.GetComment( 1 ) );
  177. m_TextComment3->SetValue( m_tb.GetComment( 2 ) );
  178. m_TextComment4->SetValue( m_tb.GetComment( 3 ) );
  179. m_TextComment5->SetValue( m_tb.GetComment( 4 ) );
  180. m_TextComment6->SetValue( m_tb.GetComment( 5 ) );
  181. m_TextComment7->SetValue( m_tb.GetComment( 6 ) );
  182. m_TextComment8->SetValue( m_tb.GetComment( 7 ) );
  183. m_TextComment9->SetValue( m_tb.GetComment( 8 ) );
  184. #ifdef EESCHEMA
  185. auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
  186. wxASSERT( cfg );
  187. m_RevisionExport->SetValue( cfg->m_PageSettings.export_revision );
  188. m_DateExport->SetValue( cfg->m_PageSettings.export_date );
  189. m_TitleExport->SetValue( cfg->m_PageSettings.export_title );
  190. m_CompanyExport->SetValue( cfg->m_PageSettings.export_company );
  191. m_Comment1Export->SetValue( cfg->m_PageSettings.export_comment1 );
  192. m_Comment2Export->SetValue( cfg->m_PageSettings.export_comment2 );
  193. m_Comment3Export->SetValue( cfg->m_PageSettings.export_comment3 );
  194. m_Comment4Export->SetValue( cfg->m_PageSettings.export_comment4 );
  195. m_Comment5Export->SetValue( cfg->m_PageSettings.export_comment5 );
  196. m_Comment6Export->SetValue( cfg->m_PageSettings.export_comment6 );
  197. m_Comment7Export->SetValue( cfg->m_PageSettings.export_comment7 );
  198. m_Comment8Export->SetValue( cfg->m_PageSettings.export_comment8 );
  199. m_Comment9Export->SetValue( cfg->m_PageSettings.export_comment9 );
  200. #else
  201. m_RevisionExport->Show( false );
  202. m_DateExport->Show( false );
  203. m_TitleExport->Show( false );
  204. m_CompanyExport->Show( false );
  205. m_Comment1Export->Show( false );
  206. m_Comment2Export->Show( false );
  207. m_Comment3Export->Show( false );
  208. m_Comment4Export->Show( false );
  209. m_Comment5Export->Show( false );
  210. m_Comment6Export->Show( false );
  211. m_Comment7Export->Show( false );
  212. m_Comment8Export->Show( false );
  213. m_Comment9Export->Show( false );
  214. #endif
  215. GetPageLayoutInfoFromDialog();
  216. UpdatePageLayoutExample();
  217. // Make the OK button the default.
  218. m_sdbSizerOK->SetDefault();
  219. m_initialized = true;
  220. }
  221. void DIALOG_PAGES_SETTINGS::OnOkClick( wxCommandEvent& event )
  222. {
  223. if( !m_customSizeX.Validate( Mils2iu( MIN_PAGE_SIZE ), Mils2iu( m_maxPageSizeMils.x ) ) )
  224. return;
  225. if( !m_customSizeY.Validate( Mils2iu( MIN_PAGE_SIZE ), Mils2iu( m_maxPageSizeMils.y ) ) )
  226. return;
  227. if( SavePageSettings() )
  228. {
  229. m_screen->SetModify();
  230. if( LocalPrjConfigChanged() )
  231. m_parent->SaveProjectSettings();
  232. // Call the post processing (if any) after changes
  233. m_parent->OnPageSettingsChange();
  234. }
  235. event.Skip();
  236. }
  237. void DIALOG_PAGES_SETTINGS::OnPaperSizeChoice( wxCommandEvent& event )
  238. {
  239. int idx = m_paperSizeComboBox->GetSelection();
  240. if( idx < 0 )
  241. idx = 0;
  242. const wxString paperType = m_pageFmt[idx];
  243. if( paperType.Contains( PAGE_INFO::Custom ) )
  244. {
  245. m_orientationComboBox->Enable( false );
  246. m_customSizeX.Enable( true );
  247. m_customSizeY.Enable( true );
  248. m_customFmt = true;
  249. }
  250. else
  251. {
  252. m_orientationComboBox->Enable( true );
  253. #if 0
  254. // ForcePortrait() does not exist, but could be useful.
  255. // so I leave these lines, which could be seen as a todo feature
  256. if( paperType.ForcePortrait() )
  257. {
  258. m_orientationComboBox->SetStringSelection( _( "Portrait" ) );
  259. m_orientationComboBox->Enable( false );
  260. }
  261. #endif
  262. m_customSizeX.Enable( false );
  263. m_customSizeY.Enable( false );
  264. m_customFmt = false;
  265. }
  266. GetPageLayoutInfoFromDialog();
  267. UpdatePageLayoutExample();
  268. }
  269. void DIALOG_PAGES_SETTINGS::OnUserPageSizeXTextUpdated( wxCommandEvent& event )
  270. {
  271. if( m_initialized )
  272. {
  273. GetPageLayoutInfoFromDialog();
  274. UpdatePageLayoutExample();
  275. }
  276. }
  277. void DIALOG_PAGES_SETTINGS::OnUserPageSizeYTextUpdated( wxCommandEvent& event )
  278. {
  279. if( m_initialized )
  280. {
  281. GetPageLayoutInfoFromDialog();
  282. UpdatePageLayoutExample();
  283. }
  284. }
  285. void DIALOG_PAGES_SETTINGS::OnPageOrientationChoice( wxCommandEvent& event )
  286. {
  287. if( m_initialized )
  288. {
  289. GetPageLayoutInfoFromDialog();
  290. UpdatePageLayoutExample();
  291. }
  292. }
  293. void DIALOG_PAGES_SETTINGS::OnRevisionTextUpdated( wxCommandEvent& event )
  294. {
  295. if( m_initialized && m_TextRevision->IsModified() )
  296. {
  297. GetPageLayoutInfoFromDialog();
  298. m_tb.SetRevision( m_TextRevision->GetValue() );
  299. UpdatePageLayoutExample();
  300. }
  301. }
  302. void DIALOG_PAGES_SETTINGS::OnDateTextUpdated( wxCommandEvent& event )
  303. {
  304. if( m_initialized && m_TextDate->IsModified() )
  305. {
  306. GetPageLayoutInfoFromDialog();
  307. m_tb.SetDate( m_TextDate->GetValue() );
  308. UpdatePageLayoutExample();
  309. }
  310. }
  311. void DIALOG_PAGES_SETTINGS::OnTitleTextUpdated( wxCommandEvent& event )
  312. {
  313. if( m_initialized && m_TextTitle->IsModified() )
  314. {
  315. GetPageLayoutInfoFromDialog();
  316. m_tb.SetTitle( m_TextTitle->GetValue() );
  317. UpdatePageLayoutExample();
  318. }
  319. }
  320. void DIALOG_PAGES_SETTINGS::OnCompanyTextUpdated( wxCommandEvent& event )
  321. {
  322. if( m_initialized && m_TextCompany->IsModified() )
  323. {
  324. GetPageLayoutInfoFromDialog();
  325. m_tb.SetCompany( m_TextCompany->GetValue() );
  326. UpdatePageLayoutExample();
  327. }
  328. }
  329. void DIALOG_PAGES_SETTINGS::OnComment1TextUpdated( wxCommandEvent& event )
  330. {
  331. if( m_initialized && m_TextComment1->IsModified() )
  332. {
  333. GetPageLayoutInfoFromDialog();
  334. m_tb.SetComment( 0, m_TextComment1->GetValue() );
  335. UpdatePageLayoutExample();
  336. }
  337. }
  338. void DIALOG_PAGES_SETTINGS::OnComment2TextUpdated( wxCommandEvent& event )
  339. {
  340. if( m_initialized && m_TextComment2->IsModified() )
  341. {
  342. GetPageLayoutInfoFromDialog();
  343. m_tb.SetComment( 1, m_TextComment2->GetValue() );
  344. UpdatePageLayoutExample();
  345. }
  346. }
  347. void DIALOG_PAGES_SETTINGS::OnComment3TextUpdated( wxCommandEvent& event )
  348. {
  349. if( m_initialized && m_TextComment3->IsModified() )
  350. {
  351. GetPageLayoutInfoFromDialog();
  352. m_tb.SetComment( 2, m_TextComment3->GetValue() );
  353. UpdatePageLayoutExample();
  354. }
  355. }
  356. void DIALOG_PAGES_SETTINGS::OnComment4TextUpdated( wxCommandEvent& event )
  357. {
  358. if( m_initialized && m_TextComment4->IsModified() )
  359. {
  360. GetPageLayoutInfoFromDialog();
  361. m_tb.SetComment( 3, m_TextComment4->GetValue() );
  362. UpdatePageLayoutExample();
  363. }
  364. }
  365. void DIALOG_PAGES_SETTINGS::OnComment5TextUpdated( wxCommandEvent& event )
  366. {
  367. if( m_initialized && m_TextComment5->IsModified() )
  368. {
  369. GetPageLayoutInfoFromDialog();
  370. m_tb.SetComment( 4, m_TextComment5->GetValue() );
  371. UpdatePageLayoutExample();
  372. }
  373. }
  374. void DIALOG_PAGES_SETTINGS::OnComment6TextUpdated( wxCommandEvent& event )
  375. {
  376. if( m_initialized && m_TextComment6->IsModified() )
  377. {
  378. GetPageLayoutInfoFromDialog();
  379. m_tb.SetComment( 5, m_TextComment6->GetValue() );
  380. UpdatePageLayoutExample();
  381. }
  382. }
  383. void DIALOG_PAGES_SETTINGS::OnComment7TextUpdated( wxCommandEvent& event )
  384. {
  385. if( m_initialized && m_TextComment7->IsModified() )
  386. {
  387. GetPageLayoutInfoFromDialog();
  388. m_tb.SetComment( 6, m_TextComment7->GetValue() );
  389. UpdatePageLayoutExample();
  390. }
  391. }
  392. void DIALOG_PAGES_SETTINGS::OnComment8TextUpdated( wxCommandEvent& event )
  393. {
  394. if( m_initialized && m_TextComment8->IsModified() )
  395. {
  396. GetPageLayoutInfoFromDialog();
  397. m_tb.SetComment( 7, m_TextComment8->GetValue() );
  398. UpdatePageLayoutExample();
  399. }
  400. }
  401. void DIALOG_PAGES_SETTINGS::OnComment9TextUpdated( wxCommandEvent& event )
  402. {
  403. if( m_initialized && m_TextComment9->IsModified() )
  404. {
  405. GetPageLayoutInfoFromDialog();
  406. m_tb.SetComment( 8, m_TextComment9->GetValue() );
  407. UpdatePageLayoutExample();
  408. }
  409. }
  410. void DIALOG_PAGES_SETTINGS::OnDateApplyClick( wxCommandEvent& event )
  411. {
  412. wxDateTime datetime = m_PickDate->GetValue();
  413. wxString date =
  414. // We can choose different formats. Only one must be uncommented
  415. //
  416. // datetime.Format( wxLocale::GetInfo( wxLOCALE_SHORT_DATE_FMT ) );
  417. // datetime.Format( wxLocale::GetInfo( wxLOCALE_LONG_DATE_FMT ) );
  418. // datetime.Format( wxT("%Y-%b-%d") );
  419. datetime.FormatISODate();
  420. m_TextDate->SetValue( date );
  421. }
  422. bool DIALOG_PAGES_SETTINGS::SavePageSettings()
  423. {
  424. bool success = false;
  425. wxString fileName = GetWksFileName();
  426. if( fileName != BASE_SCREEN::m_PageLayoutDescrFileName )
  427. {
  428. wxString fullFileName = WS_DATA_MODEL::MakeFullFileName( fileName, m_projectPath );
  429. if( !fullFileName.IsEmpty() && !wxFileExists( fullFileName ) )
  430. {
  431. wxString msg;
  432. msg.Printf( _( "Page layout description file \"%s\" not found." ),
  433. GetChars( fullFileName ) );
  434. wxMessageBox( msg );
  435. return false;
  436. }
  437. BASE_SCREEN::m_PageLayoutDescrFileName = fileName;
  438. WS_DATA_MODEL& pglayout = WS_DATA_MODEL::GetTheInstance();
  439. pglayout.SetPageLayout( fullFileName );
  440. m_localPrjConfigChanged = true;
  441. }
  442. int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 );
  443. const wxString paperType = m_pageFmt[idx];
  444. if( paperType.Contains( PAGE_INFO::Custom ) )
  445. {
  446. GetCustomSizeMilsFromDialog();
  447. success = m_pageInfo.SetType( PAGE_INFO::Custom );
  448. if( success )
  449. {
  450. PAGE_INFO::SetCustomWidthMils( m_layout_size.x );
  451. PAGE_INFO::SetCustomHeightMils( m_layout_size.y );
  452. m_pageInfo.SetWidthMils( m_layout_size.x );
  453. m_pageInfo.SetHeightMils( m_layout_size.y );
  454. }
  455. }
  456. else
  457. {
  458. // search for longest common string first, e.g. A4 before A
  459. if( paperType.Contains( PAGE_INFO::USLetter ) )
  460. success = m_pageInfo.SetType( PAGE_INFO::USLetter );
  461. else if( paperType.Contains( PAGE_INFO::USLegal ) )
  462. success = m_pageInfo.SetType( PAGE_INFO::USLegal );
  463. else if( paperType.Contains( PAGE_INFO::USLedger ) )
  464. success = m_pageInfo.SetType( PAGE_INFO::USLedger );
  465. else if( paperType.Contains( PAGE_INFO::GERBER ) )
  466. success = m_pageInfo.SetType( PAGE_INFO::GERBER );
  467. else if( paperType.Contains( PAGE_INFO::A4 ) )
  468. success = m_pageInfo.SetType( PAGE_INFO::A4 );
  469. else if( paperType.Contains( PAGE_INFO::A3 ) )
  470. success = m_pageInfo.SetType( PAGE_INFO::A3 );
  471. else if( paperType.Contains( PAGE_INFO::A2 ) )
  472. success = m_pageInfo.SetType( PAGE_INFO::A2 );
  473. else if( paperType.Contains( PAGE_INFO::A1 ) )
  474. success = m_pageInfo.SetType( PAGE_INFO::A1 );
  475. else if( paperType.Contains( PAGE_INFO::A0 ) )
  476. success = m_pageInfo.SetType( PAGE_INFO::A0 );
  477. else if( paperType.Contains( PAGE_INFO::A ) )
  478. success = m_pageInfo.SetType( PAGE_INFO::A );
  479. else if( paperType.Contains( PAGE_INFO::B ) )
  480. success = m_pageInfo.SetType( PAGE_INFO::B );
  481. else if( paperType.Contains( PAGE_INFO::C ) )
  482. success = m_pageInfo.SetType( PAGE_INFO::C );
  483. else if( paperType.Contains( PAGE_INFO::D ) )
  484. success = m_pageInfo.SetType( PAGE_INFO::D );
  485. else if( paperType.Contains( PAGE_INFO::E ) )
  486. success = m_pageInfo.SetType( PAGE_INFO::E );
  487. if( success )
  488. {
  489. int choice = m_orientationComboBox->GetSelection();
  490. m_pageInfo.SetPortrait( choice != 0 );
  491. }
  492. }
  493. if( !success )
  494. {
  495. wxASSERT_MSG( false, _( "the translation for paper size must preserve original spellings" ) );
  496. m_pageInfo.SetType( PAGE_INFO::A4 );
  497. }
  498. m_parent->SetPageSettings( m_pageInfo );
  499. m_tb.SetRevision( m_TextRevision->GetValue() );
  500. m_tb.SetDate( m_TextDate->GetValue() );
  501. m_tb.SetCompany( m_TextCompany->GetValue() );
  502. m_tb.SetTitle( m_TextTitle->GetValue() );
  503. m_tb.SetComment( 0, m_TextComment1->GetValue() );
  504. m_tb.SetComment( 1, m_TextComment2->GetValue() );
  505. m_tb.SetComment( 2, m_TextComment3->GetValue() );
  506. m_tb.SetComment( 3, m_TextComment4->GetValue() );
  507. m_tb.SetComment( 4, m_TextComment5->GetValue() );
  508. m_tb.SetComment( 5, m_TextComment6->GetValue() );
  509. m_tb.SetComment( 6, m_TextComment7->GetValue() );
  510. m_tb.SetComment( 7, m_TextComment8->GetValue() );
  511. m_tb.SetComment( 8, m_TextComment9->GetValue() );
  512. m_parent->SetTitleBlock( m_tb );
  513. #ifdef EESCHEMA
  514. // Exports settings to other sheets if requested:
  515. SCH_SCREEN* screen;
  516. // Build the screen list
  517. SCH_SCREENS ScreenList;
  518. // Update title blocks for all screens
  519. for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
  520. {
  521. if( screen == m_screen )
  522. continue;
  523. TITLE_BLOCK tb2 = screen->GetTitleBlock();
  524. if( m_RevisionExport->IsChecked() )
  525. tb2.SetRevision( m_tb.GetRevision() );
  526. if( m_DateExport->IsChecked() )
  527. tb2.SetDate( m_tb.GetDate() );
  528. if( m_TitleExport->IsChecked() )
  529. tb2.SetTitle( m_tb.GetTitle() );
  530. if( m_CompanyExport->IsChecked() )
  531. tb2.SetCompany( m_tb.GetCompany() );
  532. if( m_Comment1Export->IsChecked() )
  533. tb2.SetComment( 0, m_tb.GetComment( 0 ) );
  534. if( m_Comment2Export->IsChecked() )
  535. tb2.SetComment( 1, m_tb.GetComment( 1 ) );
  536. if( m_Comment3Export->IsChecked() )
  537. tb2.SetComment( 2, m_tb.GetComment( 2 ) );
  538. if( m_Comment4Export->IsChecked() )
  539. tb2.SetComment( 3, m_tb.GetComment( 3 ) );
  540. if( m_Comment5Export->IsChecked() )
  541. tb2.SetComment( 4, m_tb.GetComment( 4 ) );
  542. if( m_Comment6Export->IsChecked() )
  543. tb2.SetComment( 5, m_tb.GetComment( 5 ) );
  544. if( m_Comment7Export->IsChecked() )
  545. tb2.SetComment( 6, m_tb.GetComment( 6 ) );
  546. if( m_Comment8Export->IsChecked() )
  547. tb2.SetComment( 7, m_tb.GetComment( 7 ) );
  548. if( m_Comment9Export->IsChecked() )
  549. tb2.SetComment( 8, m_tb.GetComment( 8 ) );
  550. screen->SetTitleBlock( tb2 );
  551. }
  552. #endif
  553. return true;
  554. }
  555. void DIALOG_PAGES_SETTINGS::SetCurrentPageSizeSelection( const wxString& aPaperSize )
  556. {
  557. // search all the not translated label list containing our paper type
  558. for( unsigned i = 0; i < m_pageFmt.GetCount(); ++i )
  559. {
  560. // parse each label looking for aPaperSize within it
  561. wxStringTokenizer st( m_pageFmt[i] );
  562. while( st.HasMoreTokens() )
  563. {
  564. if( st.GetNextToken() == aPaperSize )
  565. {
  566. m_paperSizeComboBox->SetSelection( i );
  567. return;
  568. }
  569. }
  570. }
  571. }
  572. void DIALOG_PAGES_SETTINGS::UpdatePageLayoutExample()
  573. {
  574. int lyWidth, lyHeight;
  575. wxSize clamped_layout_size( Clamp( MIN_PAGE_SIZE, m_layout_size.x, m_maxPageSizeMils.x ),
  576. Clamp( MIN_PAGE_SIZE, m_layout_size.y, m_maxPageSizeMils.y ) );
  577. double lyRatio = clamped_layout_size.x < clamped_layout_size.y ?
  578. (double) clamped_layout_size.y / clamped_layout_size.x :
  579. (double) clamped_layout_size.x / clamped_layout_size.y;
  580. if( clamped_layout_size.x < clamped_layout_size.y )
  581. {
  582. lyHeight = MAX_PAGE_EXAMPLE_SIZE;
  583. lyWidth = KiROUND( (double) lyHeight / lyRatio );
  584. }
  585. else
  586. {
  587. lyWidth = MAX_PAGE_EXAMPLE_SIZE;
  588. lyHeight = KiROUND( (double) lyWidth / lyRatio );
  589. }
  590. if( m_page_bitmap )
  591. {
  592. m_PageLayoutExampleBitmap->SetBitmap( wxNullBitmap );
  593. delete m_page_bitmap;
  594. }
  595. m_page_bitmap = new wxBitmap( lyWidth + 1, lyHeight + 1 );
  596. if( m_page_bitmap->IsOk() )
  597. {
  598. double scaleW = (double) lyWidth / clamped_layout_size.x;
  599. double scaleH = (double) lyHeight / clamped_layout_size.y;
  600. // Prepare DC.
  601. wxSize example_size( lyWidth + 1, lyHeight + 1 );
  602. wxMemoryDC memDC;
  603. memDC.SelectObject( *m_page_bitmap );
  604. memDC.SetClippingRegion( wxPoint( 0, 0 ), example_size );
  605. memDC.Clear();
  606. memDC.SetUserScale( scaleW, scaleH );
  607. // Get logical page size and margins.
  608. PAGE_INFO pageDUMMY;
  609. // Get page type
  610. int idx = m_paperSizeComboBox->GetSelection();
  611. if( idx < 0 )
  612. idx = 0;
  613. wxString pageFmtName = m_pageFmt[idx].BeforeFirst( ' ' );
  614. bool portrait = clamped_layout_size.x < clamped_layout_size.y;
  615. pageDUMMY.SetType( pageFmtName, portrait );
  616. if( m_customFmt )
  617. {
  618. pageDUMMY.SetWidthMils( clamped_layout_size.x );
  619. pageDUMMY.SetHeightMils( clamped_layout_size.y );
  620. }
  621. // Draw layout preview.
  622. wxString emptyString;
  623. GRResetPenAndBrush( &memDC );
  624. WS_DATA_MODEL::SetAltInstance( m_pagelayout );
  625. GRFilledRect( NULL, &memDC, 0, 0, m_layout_size.x, m_layout_size.y, WHITE, WHITE );
  626. PrintPageLayout( &memDC, pageDUMMY, emptyString, emptyString, m_tb,
  627. m_screen->m_NumberOfScreens, m_screen->m_ScreenNumber, 1, 1, RED,
  628. &Prj() );
  629. memDC.SelectObject( wxNullBitmap );
  630. m_PageLayoutExampleBitmap->SetBitmap( *m_page_bitmap );
  631. WS_DATA_MODEL::SetAltInstance( NULL );
  632. // Refresh the dialog.
  633. Layout();
  634. Refresh();
  635. }
  636. }
  637. void DIALOG_PAGES_SETTINGS::GetPageLayoutInfoFromDialog()
  638. {
  639. int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 );
  640. const wxString paperType = m_pageFmt[idx];
  641. // here we assume translators will keep original paper size spellings
  642. if( paperType.Contains( PAGE_INFO::Custom ) )
  643. {
  644. GetCustomSizeMilsFromDialog();
  645. if( m_layout_size.x && m_layout_size.y )
  646. {
  647. if( m_layout_size.x < m_layout_size.y )
  648. m_orientationComboBox->SetStringSelection( _( "Portrait" ) );
  649. else
  650. m_orientationComboBox->SetStringSelection( _( "Landscape" ) );
  651. }
  652. }
  653. else
  654. {
  655. PAGE_INFO pageInfo; // SetType() later to lookup size
  656. static const wxChar* papers[] = {
  657. // longest common string first, since sequential search below
  658. PAGE_INFO::A4,
  659. PAGE_INFO::A3,
  660. PAGE_INFO::A2,
  661. PAGE_INFO::A1,
  662. PAGE_INFO::A0,
  663. PAGE_INFO::A,
  664. PAGE_INFO::B,
  665. PAGE_INFO::C,
  666. PAGE_INFO::D,
  667. PAGE_INFO::E,
  668. PAGE_INFO::USLetter,
  669. PAGE_INFO::USLegal,
  670. PAGE_INFO::USLedger,
  671. };
  672. unsigned i;
  673. for( i=0; i < arrayDim( papers ); ++i )
  674. {
  675. if( paperType.Contains( papers[i] ) )
  676. {
  677. pageInfo.SetType( papers[i] );
  678. break;
  679. }
  680. }
  681. wxASSERT( i != arrayDim(papers) ); // dialog UI match the above list?
  682. m_layout_size = pageInfo.GetSizeMils();
  683. // swap sizes to match orientation
  684. bool isPortrait = (bool) m_orientationComboBox->GetSelection();
  685. if( ( isPortrait && m_layout_size.x >= m_layout_size.y ) ||
  686. ( !isPortrait && m_layout_size.x < m_layout_size.y ) )
  687. {
  688. m_layout_size.Set( m_layout_size.y, m_layout_size.x );
  689. }
  690. }
  691. }
  692. void DIALOG_PAGES_SETTINGS::GetCustomSizeMilsFromDialog()
  693. {
  694. double customSizeX = (double) m_customSizeX.GetValue() / IU_PER_MILS;
  695. double customSizeY = (double) m_customSizeY.GetValue() / IU_PER_MILS;
  696. // Prepare to painless double -> int conversion.
  697. customSizeX = Clamp( double( INT_MIN ), customSizeX, double( INT_MAX ) );
  698. customSizeY = Clamp( double( INT_MIN ), customSizeY, double( INT_MAX ) );
  699. m_layout_size = wxSize( KiROUND( customSizeX ), KiROUND( customSizeY ) );
  700. }
  701. void DIALOG_PAGES_SETTINGS::OnWksFileSelection( wxCommandEvent& event )
  702. {
  703. wxFileName fn = GetWksFileName();
  704. wxString name = GetWksFileName();
  705. wxString path;
  706. if( fn.IsAbsolute() )
  707. {
  708. path = fn.GetPath();
  709. name = fn.GetFullName();
  710. }
  711. else
  712. {
  713. path = m_projectPath;
  714. }
  715. // Display a file picker dialog
  716. wxFileDialog fileDialog( this, _( "Select Page Layout Description File" ),
  717. path, name, PageLayoutDescrFileWildcard(),
  718. wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST );
  719. if( fileDialog.ShowModal() != wxID_OK )
  720. return;
  721. wxString fileName = fileDialog.GetPath();
  722. // Try to remove the path, if the path is the current working dir,
  723. // or the dir of kicad.pro (template), and use a relative path
  724. wxString shortFileName = WS_DATA_MODEL::MakeShortFileName( fileName, m_projectPath );
  725. // For Win/Linux/macOS compatibility, a relative path is a good idea
  726. if( shortFileName != GetWksFileName() && shortFileName != fileName )
  727. {
  728. wxString msg = wxString::Format( _(
  729. "The page layout description file name has changed.\n"
  730. "Do you want to use the relative path:\n"
  731. "\"%s\"\n"
  732. "instead of\n"
  733. "\"%s\"?" ), GetChars( shortFileName ), GetChars( fileName ) );
  734. if( !IsOK( this, msg ) )
  735. shortFileName = fileName;
  736. }
  737. SetWksFileName( shortFileName );
  738. if( m_pagelayout == NULL )
  739. m_pagelayout = new WS_DATA_MODEL;
  740. m_pagelayout->SetPageLayout( fileName );
  741. GetPageLayoutInfoFromDialog();
  742. UpdatePageLayoutExample();
  743. }