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.

643 lines
19 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018-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. #include <kiway.h>
  24. #include <kiway_player.h>
  25. #include <dialog_shim.h>
  26. #include <fields_grid_table.h>
  27. #include <sch_base_frame.h>
  28. #include <sch_field.h>
  29. #include <sch_validators.h>
  30. #include <validators.h>
  31. #include <class_library.h>
  32. #include <template_fieldnames.h>
  33. #include <widgets/grid_icon_text_helpers.h>
  34. #include <widgets/grid_text_button_helpers.h>
  35. #include <wildcards_and_files_ext.h>
  36. #include <project/project_file.h>
  37. #include "eda_doc.h"
  38. enum
  39. {
  40. MYID_SELECT_FOOTPRINT = 991, // must be within GRID_TRICKS' enum range
  41. MYID_SHOW_DATASHEET
  42. };
  43. template <class T>
  44. FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* aFrame,
  45. LIB_PART* aPart ) :
  46. m_frame( aFrame ),
  47. m_userUnits( aDialog->GetUserUnits() ),
  48. m_parentType( SCH_COMPONENT_T ),
  49. m_mandatoryFieldCount( MANDATORY_FIELDS ),
  50. m_part( aPart ),
  51. m_fieldNameValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_NAME ),
  52. m_referenceValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), REFERENCE ),
  53. m_valueValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), VALUE ),
  54. m_libIdValidator( LIB_ID::ID_PCB ),
  55. m_urlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
  56. m_nonUrlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
  57. m_filepathValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), SHEETFILENAME )
  58. {
  59. initGrid( aDialog );
  60. }
  61. template <class T>
  62. FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* aFrame,
  63. SCH_SHEET* aSheet ) :
  64. m_frame( aFrame ),
  65. m_userUnits( aDialog->GetUserUnits() ),
  66. m_parentType( SCH_SHEET_T ),
  67. m_mandatoryFieldCount( SHEET_MANDATORY_FIELDS ),
  68. m_part( nullptr ),
  69. m_fieldNameValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_NAME ),
  70. m_referenceValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), SHEETNAME_V ),
  71. m_valueValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), VALUE ),
  72. m_libIdValidator( LIB_ID::ID_PCB ),
  73. m_urlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
  74. m_nonUrlValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), FIELD_VALUE ),
  75. m_filepathValidator( aFrame->IsType( FRAME_SCH_LIB_EDITOR ), SHEETFILENAME_V )
  76. {
  77. initGrid( aDialog );
  78. }
  79. template <class T>
  80. void FIELDS_GRID_TABLE<T>::initGrid( DIALOG_SHIM* aDialog )
  81. {
  82. // Build the various grid cell attributes.
  83. // NOTE: validators and cellAttrs are member variables to get the destruction order
  84. // right. wxGrid is VERY cranky about this.
  85. m_readOnlyAttr = new wxGridCellAttr;
  86. m_readOnlyAttr->SetReadOnly( true );
  87. m_fieldNameAttr = new wxGridCellAttr;
  88. GRID_CELL_TEXT_EDITOR* nameEditor = new GRID_CELL_TEXT_EDITOR();
  89. nameEditor->SetValidator( m_fieldNameValidator );
  90. m_fieldNameAttr->SetEditor( nameEditor );
  91. m_referenceAttr = new wxGridCellAttr;
  92. GRID_CELL_TEXT_EDITOR* referenceEditor = new GRID_CELL_TEXT_EDITOR();
  93. referenceEditor->SetValidator( m_referenceValidator );
  94. m_referenceAttr->SetEditor( referenceEditor );
  95. m_valueAttr = new wxGridCellAttr;
  96. GRID_CELL_TEXT_EDITOR* valueEditor = new GRID_CELL_TEXT_EDITOR();
  97. valueEditor->SetValidator( m_valueValidator );
  98. m_valueAttr->SetEditor( valueEditor );
  99. m_footprintAttr = new wxGridCellAttr;
  100. GRID_CELL_FOOTPRINT_ID_EDITOR* fpIdEditor = new GRID_CELL_FOOTPRINT_ID_EDITOR( aDialog );
  101. fpIdEditor->SetValidator( m_libIdValidator );
  102. m_footprintAttr->SetEditor( fpIdEditor );
  103. m_urlAttr = new wxGridCellAttr;
  104. GRID_CELL_URL_EDITOR* urlEditor = new GRID_CELL_URL_EDITOR( aDialog );
  105. urlEditor->SetValidator( m_urlValidator );
  106. m_urlAttr->SetEditor( urlEditor );
  107. m_nonUrlAttr = new wxGridCellAttr;
  108. GRID_CELL_TEXT_EDITOR* nonUrlEditor = new GRID_CELL_TEXT_EDITOR();
  109. nonUrlEditor->SetValidator( m_nonUrlValidator );
  110. m_nonUrlAttr->SetEditor( nonUrlEditor );
  111. m_curdir = m_frame->Prj().GetProjectPath();
  112. m_filepathAttr = new wxGridCellAttr;
  113. // Create a wild card using wxFileDialog syntax.
  114. wxString wildCard( _( "Schematic Files" ) );
  115. std::vector<std::string> exts;
  116. exts.push_back( KiCadSchematicFileExtension );
  117. wildCard += AddFileExtListToFilter( exts );
  118. GRID_CELL_PATH_EDITOR* filepathEditor =
  119. new GRID_CELL_PATH_EDITOR( aDialog, &m_curdir, wildCard );
  120. filepathEditor->SetValidator( m_filepathValidator );
  121. m_filepathAttr->SetEditor( filepathEditor );
  122. m_boolAttr = new wxGridCellAttr;
  123. m_boolAttr->SetRenderer( new wxGridCellBoolRenderer() );
  124. m_boolAttr->SetEditor( new wxGridCellBoolEditor() );
  125. m_boolAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
  126. wxArrayString vAlignNames;
  127. vAlignNames.Add( _( "Top" ) );
  128. vAlignNames.Add( _( "Center" ) );
  129. vAlignNames.Add( _( "Bottom" ) );
  130. m_vAlignAttr = new wxGridCellAttr;
  131. m_vAlignAttr->SetEditor( new wxGridCellChoiceEditor( vAlignNames ) );
  132. m_vAlignAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
  133. wxArrayString hAlignNames;
  134. hAlignNames.Add( _( "Left" ) );
  135. hAlignNames.Add(_( "Center" ) );
  136. hAlignNames.Add(_( "Right" ) );
  137. m_hAlignAttr = new wxGridCellAttr;
  138. m_hAlignAttr->SetEditor( new wxGridCellChoiceEditor( hAlignNames ) );
  139. m_hAlignAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
  140. wxArrayString orientationNames;
  141. orientationNames.Add( _( "Horizontal" ) );
  142. orientationNames.Add(_( "Vertical" ) );
  143. m_orientationAttr = new wxGridCellAttr;
  144. m_orientationAttr->SetEditor( new wxGridCellChoiceEditor( orientationNames ) );
  145. m_orientationAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
  146. }
  147. template <class T>
  148. FIELDS_GRID_TABLE<T>::~FIELDS_GRID_TABLE()
  149. {
  150. m_readOnlyAttr->DecRef();
  151. m_fieldNameAttr->DecRef();
  152. m_boolAttr->DecRef();
  153. m_referenceAttr->DecRef();
  154. m_valueAttr->DecRef();
  155. m_footprintAttr->DecRef();
  156. m_urlAttr->DecRef();
  157. m_nonUrlAttr->DecRef();
  158. m_filepathAttr->DecRef();
  159. m_vAlignAttr->DecRef();
  160. m_hAlignAttr->DecRef();
  161. m_orientationAttr->DecRef();
  162. }
  163. template <class T>
  164. wxString FIELDS_GRID_TABLE<T>::GetColLabelValue( int aCol )
  165. {
  166. switch( aCol )
  167. {
  168. case FDC_NAME: return _( "Name" );
  169. case FDC_VALUE: return _( "Value" );
  170. case FDC_SHOWN: return _( "Show" );
  171. case FDC_H_ALIGN: return _( "H Align" );
  172. case FDC_V_ALIGN: return _( "V Align" );
  173. case FDC_ITALIC: return _( "Italic" );
  174. case FDC_BOLD: return _( "Bold" );
  175. case FDC_TEXT_SIZE: return _( "Text Size" );
  176. case FDC_ORIENTATION: return _( "Orientation" );
  177. case FDC_POSX: return _( "X Position" );
  178. case FDC_POSY: return _( "Y Position" );
  179. default: wxFAIL; return wxEmptyString;
  180. }
  181. }
  182. template <class T>
  183. bool FIELDS_GRID_TABLE<T>::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
  184. {
  185. switch( aCol )
  186. {
  187. case FDC_NAME:
  188. case FDC_VALUE:
  189. case FDC_H_ALIGN:
  190. case FDC_V_ALIGN:
  191. case FDC_TEXT_SIZE:
  192. case FDC_ORIENTATION:
  193. case FDC_POSX:
  194. case FDC_POSY:
  195. return aTypeName == wxGRID_VALUE_STRING;
  196. case FDC_SHOWN:
  197. case FDC_ITALIC:
  198. case FDC_BOLD:
  199. return aTypeName == wxGRID_VALUE_BOOL;
  200. default:
  201. wxFAIL;
  202. return false;
  203. }
  204. }
  205. template <class T>
  206. bool FIELDS_GRID_TABLE<T>::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
  207. {
  208. return CanGetValueAs( aRow, aCol, aTypeName );
  209. }
  210. template <class T>
  211. wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind )
  212. {
  213. wxGridCellAttr* tmp;
  214. switch( aCol )
  215. {
  216. case FDC_NAME:
  217. if( aRow < m_mandatoryFieldCount )
  218. {
  219. tmp = m_fieldNameAttr->Clone();
  220. tmp->SetReadOnly( true );
  221. return tmp;
  222. }
  223. else
  224. {
  225. m_fieldNameAttr->IncRef();
  226. return m_fieldNameAttr;
  227. }
  228. case FDC_VALUE:
  229. if( m_parentType == SCH_COMPONENT_T && aRow == REFERENCE )
  230. {
  231. m_referenceAttr->IncRef();
  232. return m_referenceAttr;
  233. }
  234. else if( m_parentType == SCH_COMPONENT_T && aRow == VALUE )
  235. {
  236. // For power symbols, the value is not editable, because value and pin name must
  237. // be the same and can be edited only in library editor.
  238. if( ( m_part && m_part->IsPower() && !m_frame->IsType( FRAME_SCH_LIB_EDITOR ) ) )
  239. {
  240. tmp = m_readOnlyAttr->Clone();
  241. tmp->SetReadOnly( true );
  242. tmp->SetTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
  243. return tmp;
  244. }
  245. else
  246. {
  247. m_valueAttr->IncRef();
  248. return m_valueAttr;
  249. }
  250. }
  251. else if( m_parentType == SCH_COMPONENT_T && aRow == FOOTPRINT )
  252. {
  253. m_footprintAttr->IncRef();
  254. return m_footprintAttr;
  255. }
  256. else if( m_parentType == SCH_COMPONENT_T && aRow == DATASHEET )
  257. {
  258. m_urlAttr->IncRef();
  259. return m_urlAttr;
  260. }
  261. else if( m_parentType == SCH_SHEET_T && aRow == SHEETNAME )
  262. {
  263. m_referenceAttr->IncRef();
  264. return m_referenceAttr;
  265. }
  266. else if( m_parentType == SCH_SHEET_T && aRow == SHEETFILENAME )
  267. {
  268. m_filepathAttr->IncRef();
  269. return m_filepathAttr;
  270. }
  271. else
  272. {
  273. wxString fn = GetValue( aRow, FDC_NAME );
  274. SCHEMATIC_SETTINGS* settings = m_frame->Prj().GetProjectFile().m_SchematicSettings;
  275. const TEMPLATE_FIELDNAME* templateFn = settings->m_TemplateFieldNames.GetFieldName( fn );
  276. if( templateFn && templateFn->m_URL )
  277. {
  278. m_urlAttr->IncRef();
  279. return m_urlAttr;
  280. }
  281. else
  282. {
  283. m_nonUrlAttr->IncRef();
  284. return m_nonUrlAttr;
  285. }
  286. }
  287. return nullptr;
  288. case FDC_TEXT_SIZE:
  289. case FDC_POSX:
  290. case FDC_POSY:
  291. return nullptr;
  292. case FDC_H_ALIGN:
  293. m_hAlignAttr->IncRef();
  294. return m_hAlignAttr;
  295. case FDC_V_ALIGN:
  296. m_vAlignAttr->IncRef();
  297. return m_vAlignAttr;
  298. case FDC_ORIENTATION:
  299. m_orientationAttr->IncRef();
  300. return m_orientationAttr;
  301. case FDC_SHOWN:
  302. case FDC_ITALIC:
  303. case FDC_BOLD:
  304. m_boolAttr->IncRef();
  305. return m_boolAttr;
  306. default:
  307. wxFAIL;
  308. return nullptr;
  309. }
  310. }
  311. template <class T>
  312. wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
  313. {
  314. wxCHECK( aRow < GetNumberRows(), wxEmptyString );
  315. const T& field = this->at( (size_t) aRow );
  316. switch( aCol )
  317. {
  318. case FDC_NAME:
  319. // Use default field name for mandatory fields, because they are translated
  320. // according to the current locale
  321. if( aRow < m_mandatoryFieldCount )
  322. {
  323. if( m_parentType == SCH_COMPONENT_T )
  324. return TEMPLATE_FIELDNAME::GetDefaultFieldName( aRow );
  325. else if( m_parentType == SCH_SHEET_T )
  326. return SCH_SHEET::GetDefaultFieldName( aRow );
  327. }
  328. return field.GetName( false );
  329. case FDC_VALUE:
  330. return field.GetText();
  331. case FDC_SHOWN:
  332. return StringFromBool( field.IsVisible() );
  333. case FDC_H_ALIGN:
  334. switch ( field.GetHorizJustify() )
  335. {
  336. case GR_TEXT_HJUSTIFY_LEFT: return _( "Left" );
  337. case GR_TEXT_HJUSTIFY_CENTER: return _( "Center" );
  338. case GR_TEXT_HJUSTIFY_RIGHT: return _( "Right" );
  339. }
  340. break;
  341. case FDC_V_ALIGN:
  342. switch ( field.GetVertJustify() )
  343. {
  344. case GR_TEXT_VJUSTIFY_TOP: return _( "Top" );
  345. case GR_TEXT_VJUSTIFY_CENTER: return _( "Center" );
  346. case GR_TEXT_VJUSTIFY_BOTTOM: return _( "Bottom" );
  347. }
  348. break;
  349. case FDC_ITALIC:
  350. return StringFromBool( field.IsItalic() );
  351. case FDC_BOLD:
  352. return StringFromBool( field.IsBold() );
  353. case FDC_TEXT_SIZE:
  354. return StringFromValue( m_userUnits, field.GetTextSize().GetHeight(), true, true );
  355. case FDC_ORIENTATION:
  356. switch ( (int) field.GetTextAngle() )
  357. {
  358. case TEXT_ANGLE_HORIZ: return _( "Horizontal" );
  359. case TEXT_ANGLE_VERT: return _( "Vertical" );
  360. }
  361. break;
  362. case FDC_POSX:
  363. return StringFromValue( m_userUnits, field.GetTextPos().x, true );
  364. case FDC_POSY:
  365. return StringFromValue( m_userUnits, field.GetTextPos().y, true );
  366. default:
  367. // we can't assert here because wxWidgets sometimes calls this without checking
  368. // the column type when trying to see if there's an overflow
  369. break;
  370. }
  371. return wxT( "bad wxWidgets!" );
  372. }
  373. template <class T>
  374. bool FIELDS_GRID_TABLE<T>::GetValueAsBool( int aRow, int aCol )
  375. {
  376. wxCHECK( aRow < GetNumberRows(), false );
  377. const T& field = this->at( (size_t) aRow );
  378. switch( aCol )
  379. {
  380. case FDC_SHOWN: return field.IsVisible();
  381. case FDC_ITALIC: return field.IsItalic();
  382. case FDC_BOLD: return field.IsBold();
  383. default:
  384. wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
  385. return false;
  386. }
  387. }
  388. template <class T>
  389. void FIELDS_GRID_TABLE<T>::SetValue( int aRow, int aCol, const wxString &aValue )
  390. {
  391. wxCHECK( aRow < GetNumberRows(), /*void*/ );
  392. T& field = this->at( (size_t) aRow );
  393. wxPoint pos;
  394. switch( aCol )
  395. {
  396. case FDC_NAME:
  397. field.SetName( aValue );
  398. break;
  399. case FDC_VALUE:
  400. field.SetText( aValue );
  401. break;
  402. case FDC_SHOWN:
  403. field.SetVisible( BoolFromString( aValue ) );
  404. break;
  405. case FDC_H_ALIGN:
  406. if( aValue == _( "Left" ) )
  407. field.SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
  408. else if( aValue == _( "Center" ) )
  409. field.SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER );
  410. else if( aValue == _( "Right" ) )
  411. field.SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
  412. else
  413. wxFAIL_MSG( wxT( "unknown horizontal alignment: " ) + aValue );
  414. break;
  415. case FDC_V_ALIGN:
  416. if( aValue == _( "Top" ) )
  417. field.SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
  418. else if( aValue == _( "Center" ) )
  419. field.SetVertJustify( GR_TEXT_VJUSTIFY_CENTER );
  420. else if( aValue == _( "Bottom" ) )
  421. field.SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
  422. else
  423. wxFAIL_MSG( wxT( "unknown vertical alignment: " ) + aValue);
  424. break;
  425. case FDC_ITALIC:
  426. field.SetItalic( BoolFromString( aValue ) );
  427. break;
  428. case FDC_BOLD:
  429. field.SetBold( BoolFromString( aValue ) );
  430. break;
  431. case FDC_TEXT_SIZE:
  432. field.SetTextSize( wxSize( ValueFromString( m_userUnits, aValue, true ),
  433. ValueFromString( m_userUnits, aValue, true ) ) );
  434. break;
  435. case FDC_ORIENTATION:
  436. if( aValue == _( "Horizontal" ) )
  437. field.SetTextAngle( TEXT_ANGLE_HORIZ );
  438. else if( aValue == _( "Vertical" ) )
  439. field.SetTextAngle( TEXT_ANGLE_VERT );
  440. else
  441. wxFAIL_MSG( wxT( "unknown orientation: " ) + aValue );
  442. break;
  443. case FDC_POSX:
  444. case FDC_POSY:
  445. pos = field.GetTextPos();
  446. if( aCol == FDC_POSX )
  447. pos.x = ValueFromString( m_userUnits, aValue );
  448. else
  449. pos.y = ValueFromString( m_userUnits, aValue );
  450. field.SetTextPos( pos );
  451. break;
  452. default:
  453. wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
  454. break;
  455. }
  456. GetView()->Refresh();
  457. }
  458. template <class T>
  459. void FIELDS_GRID_TABLE<T>::SetValueAsBool( int aRow, int aCol, bool aValue )
  460. {
  461. wxCHECK( aRow < GetNumberRows(), /*void*/ );
  462. T& field = this->at( (size_t) aRow );
  463. switch( aCol )
  464. {
  465. case FDC_SHOWN:
  466. field.SetVisible( aValue );
  467. break;
  468. case FDC_ITALIC:
  469. field.SetItalic( aValue );
  470. break;
  471. case FDC_BOLD:
  472. field.SetBold( aValue );
  473. break;
  474. default:
  475. wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
  476. break;
  477. }
  478. }
  479. // Explicit Instantiations
  480. template class FIELDS_GRID_TABLE<SCH_FIELD>;
  481. template class FIELDS_GRID_TABLE<LIB_FIELD>;
  482. void FIELDS_GRID_TRICKS::showPopupMenu( wxMenu& menu )
  483. {
  484. if( m_grid->GetGridCursorRow() == FOOTPRINT && m_grid->GetGridCursorCol() == FDC_VALUE )
  485. {
  486. menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ),
  487. _( "Browse for footprint" ) );
  488. menu.AppendSeparator();
  489. }
  490. else if( m_grid->GetGridCursorRow() == DATASHEET && m_grid->GetGridCursorCol() == FDC_VALUE )
  491. {
  492. menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ),
  493. _( "Show datasheet in browser" ) );
  494. menu.AppendSeparator();
  495. }
  496. GRID_TRICKS::showPopupMenu( menu );
  497. }
  498. void FIELDS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
  499. {
  500. if( event.GetId() == MYID_SELECT_FOOTPRINT )
  501. {
  502. // pick a footprint using the footprint picker.
  503. wxString fpid = m_grid->GetCellValue( FOOTPRINT, FDC_VALUE );
  504. KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true, m_dlg );
  505. if( frame->ShowModal( &fpid, m_dlg ) )
  506. m_grid->SetCellValue( FOOTPRINT, FDC_VALUE, fpid );
  507. frame->Destroy();
  508. }
  509. else if (event.GetId() == MYID_SHOW_DATASHEET )
  510. {
  511. wxString datasheet_uri = m_grid->GetCellValue( DATASHEET, FDC_VALUE );
  512. GetAssociatedDocument( m_dlg, datasheet_uri, &m_dlg->Prj() );
  513. }
  514. else
  515. {
  516. GRID_TRICKS::doPopupSelection( event );
  517. }
  518. }
  519. template <class T>
  520. wxString FIELDS_GRID_TABLE<T>::StringFromBool( bool aValue )
  521. {
  522. if( aValue )
  523. return wxT( "1" );
  524. else
  525. return wxT( "0" );
  526. }
  527. template <class T>
  528. bool FIELDS_GRID_TABLE<T>::BoolFromString( wxString aValue )
  529. {
  530. if( aValue == "1" )
  531. {
  532. return true;
  533. }
  534. else if( aValue == "0" )
  535. {
  536. return false;
  537. }
  538. else
  539. {
  540. wxFAIL_MSG( wxString::Format( "string \"%s\" can't be converted to boolean "
  541. "correctly, it will have been perceived as FALSE", aValue ) );
  542. return false;
  543. }
  544. }