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.

919 lines
28 KiB

3 years ago
3 years ago
3 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018-2022 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_label.h>
  30. #include <sch_validators.h>
  31. #include <validators.h>
  32. #include <sch_edit_frame.h>
  33. #include <netclass.h>
  34. #include <symbol_library.h>
  35. #include <schematic.h>
  36. #include <template_fieldnames.h>
  37. #include <widgets/grid_text_button_helpers.h>
  38. #include <wildcards_and_files_ext.h>
  39. #include <project/project_file.h>
  40. #include <project/net_settings.h>
  41. #include "eda_doc.h"
  42. #include "widgets/grid_color_swatch_helpers.h"
  43. #include "font/fontconfig.h"
  44. #include "font/kicad_font_name.h"
  45. #include <wx/settings.h>
  46. #include <string_utils.h>
  47. #include <widgets/grid_combobox.h>
  48. #include <pgm_base.h>
  49. enum
  50. {
  51. MYID_SELECT_FOOTPRINT = GRIDTRICKS_FIRST_CLIENT_ID,
  52. MYID_SHOW_DATASHEET
  53. };
  54. #define DEFAULT_FONT_NAME _( "Default Font" )
  55. static wxString netList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH& aSheetPath )
  56. {
  57. /*
  58. * Symbol netlist format:
  59. * library:footprint
  60. * reference
  61. * value
  62. * pinName,netName,pinFunction,pinType
  63. * pinName,netName,pinFunction,pinType
  64. * ...
  65. */
  66. wxString netlist;
  67. netlist << EscapeString( aSymbol->GetFootprintFieldText( true ), CTX_LINE ) << wxS( "\r" );
  68. netlist << EscapeString( aSymbol->GetRef( &aSheetPath ), CTX_LINE ) << wxS( "\r" );
  69. netlist << EscapeString( aSymbol->GetValueFieldText( true ), CTX_LINE );
  70. for( SCH_PIN* pin : aSymbol->GetPins( &aSheetPath ) )
  71. {
  72. netlist << wxS( "\r" );
  73. netlist << EscapeString( pin->GetNumber(), CTX_CSV ) << wxS( "," );
  74. netlist << EscapeString( pin->GetDefaultNetName( aSheetPath ), CTX_CSV ) << wxS( "," );
  75. netlist << EscapeString( pin->GetName(), CTX_CSV ) << wxS( "," );
  76. netlist << EscapeString( pin->GetCanonicalElectricalTypeName(), CTX_CSV );
  77. }
  78. return netlist;
  79. }
  80. template <class T>
  81. FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* aFrame,
  82. WX_GRID* aGrid, LIB_SYMBOL* aSymbol ) :
  83. m_frame( aFrame ),
  84. m_dialog( aDialog ),
  85. m_grid( aGrid ),
  86. m_parentType( SCH_SYMBOL_T ),
  87. m_mandatoryFieldCount( MANDATORY_FIELDS ),
  88. m_part( aSymbol ),
  89. m_fieldNameValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_NAME ),
  90. m_referenceValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), REFERENCE_FIELD ),
  91. m_valueValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), VALUE_FIELD ),
  92. m_libIdValidator(),
  93. m_urlValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_VALUE ),
  94. m_nonUrlValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_VALUE ),
  95. m_filepathValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), SHEETFILENAME )
  96. {
  97. initGrid( aGrid );
  98. }
  99. template <class T>
  100. FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_EDIT_FRAME* aFrame,
  101. WX_GRID* aGrid, SCH_SYMBOL* aSymbol ) :
  102. m_frame( aFrame ),
  103. m_dialog( aDialog ),
  104. m_grid( aGrid ),
  105. m_parentType( SCH_SYMBOL_T ),
  106. m_mandatoryFieldCount( MANDATORY_FIELDS ),
  107. m_part( aSymbol->GetLibSymbolRef().get() ),
  108. m_symbolNetlist( netList( aSymbol, aFrame->GetCurrentSheet() ) ),
  109. m_fieldNameValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_NAME ),
  110. m_referenceValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), REFERENCE_FIELD ),
  111. m_valueValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), VALUE_FIELD ),
  112. m_libIdValidator(),
  113. m_urlValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_VALUE ),
  114. m_nonUrlValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_VALUE ),
  115. m_filepathValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), SHEETFILENAME )
  116. {
  117. initGrid( aGrid );
  118. }
  119. template <class T>
  120. FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_EDIT_FRAME* aFrame,
  121. WX_GRID* aGrid, SCH_SHEET* aSheet ) :
  122. m_frame( aFrame ),
  123. m_dialog( aDialog ),
  124. m_grid( aGrid ),
  125. m_parentType( SCH_SHEET_T ),
  126. m_mandatoryFieldCount( SHEET_MANDATORY_FIELDS ),
  127. m_part( nullptr ),
  128. m_fieldNameValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_NAME ),
  129. m_referenceValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), SHEETNAME_V ),
  130. m_valueValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), VALUE_FIELD ),
  131. m_libIdValidator(),
  132. m_urlValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_VALUE ),
  133. m_nonUrlValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_VALUE ),
  134. m_filepathValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), SHEETFILENAME_V )
  135. {
  136. initGrid( aGrid );
  137. }
  138. template <class T>
  139. FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_EDIT_FRAME* aFrame,
  140. WX_GRID* aGrid, SCH_LABEL_BASE* aLabel ) :
  141. m_frame( aFrame ),
  142. m_dialog( aDialog ),
  143. m_grid( aGrid ),
  144. m_parentType( SCH_LABEL_LOCATE_ANY_T ),
  145. m_mandatoryFieldCount( aLabel->GetMandatoryFieldCount() ),
  146. m_part( nullptr ),
  147. m_fieldNameValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_NAME ),
  148. m_referenceValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), 0 ),
  149. m_valueValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), 0 ),
  150. m_libIdValidator(),
  151. m_urlValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_VALUE ),
  152. m_nonUrlValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), FIELD_VALUE ),
  153. m_filepathValidator( aFrame->IsType( FRAME_SCH_SYMBOL_EDITOR ), 0 )
  154. {
  155. initGrid( aGrid );
  156. }
  157. template <class T>
  158. void FIELDS_GRID_TABLE<T>::initGrid( WX_GRID* aGrid )
  159. {
  160. // Build the various grid cell attributes.
  161. // NOTE: validators and cellAttrs are member variables to get the destruction order
  162. // right. wxGrid is VERY cranky about this.
  163. m_readOnlyAttr = new wxGridCellAttr;
  164. m_readOnlyAttr->SetReadOnly( true );
  165. m_fieldNameAttr = new wxGridCellAttr;
  166. GRID_CELL_TEXT_EDITOR* nameEditor = new GRID_CELL_TEXT_EDITOR();
  167. nameEditor->SetValidator( m_fieldNameValidator );
  168. m_fieldNameAttr->SetEditor( nameEditor );
  169. m_referenceAttr = new wxGridCellAttr;
  170. GRID_CELL_TEXT_EDITOR* referenceEditor = new GRID_CELL_TEXT_EDITOR();
  171. referenceEditor->SetValidator( m_referenceValidator );
  172. m_referenceAttr->SetEditor( referenceEditor );
  173. m_valueAttr = new wxGridCellAttr;
  174. GRID_CELL_TEXT_EDITOR* valueEditor = new GRID_CELL_TEXT_EDITOR();
  175. valueEditor->SetValidator( m_valueValidator );
  176. m_valueAttr->SetEditor( valueEditor );
  177. m_footprintAttr = new wxGridCellAttr;
  178. GRID_CELL_FPID_EDITOR* fpIdEditor = new GRID_CELL_FPID_EDITOR( m_dialog, m_symbolNetlist );
  179. fpIdEditor->SetValidator( m_libIdValidator );
  180. m_footprintAttr->SetEditor( fpIdEditor );
  181. m_urlAttr = new wxGridCellAttr;
  182. GRID_CELL_URL_EDITOR* urlEditor = new GRID_CELL_URL_EDITOR( m_dialog,
  183. m_frame->Prj().SchSearchS() );
  184. urlEditor->SetValidator( m_urlValidator );
  185. m_urlAttr->SetEditor( urlEditor );
  186. m_nonUrlAttr = new wxGridCellAttr;
  187. GRID_CELL_TEXT_EDITOR* nonUrlEditor = new GRID_CELL_TEXT_EDITOR();
  188. nonUrlEditor->SetValidator( m_nonUrlValidator );
  189. m_nonUrlAttr->SetEditor( nonUrlEditor );
  190. m_curdir = m_frame->Prj().GetProjectPath();
  191. m_filepathAttr = new wxGridCellAttr;
  192. // Create a wild card using wxFileDialog syntax.
  193. wxString wildCard( _( "Schematic Files" ) );
  194. std::vector<std::string> exts;
  195. exts.push_back( KiCadSchematicFileExtension );
  196. wildCard += AddFileExtListToFilter( exts );
  197. auto filepathEditor = new GRID_CELL_PATH_EDITOR( m_dialog, aGrid, &m_curdir, wildCard );
  198. filepathEditor->SetValidator( m_filepathValidator );
  199. m_filepathAttr->SetEditor( filepathEditor );
  200. m_boolAttr = new wxGridCellAttr;
  201. m_boolAttr->SetRenderer( new wxGridCellBoolRenderer() );
  202. m_boolAttr->SetEditor( new wxGridCellBoolEditor() );
  203. m_boolAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
  204. wxArrayString vAlignNames;
  205. vAlignNames.Add( _( "Top" ) );
  206. vAlignNames.Add( _( "Center" ) );
  207. vAlignNames.Add( _( "Bottom" ) );
  208. m_vAlignAttr = new wxGridCellAttr;
  209. m_vAlignAttr->SetEditor( new wxGridCellChoiceEditor( vAlignNames ) );
  210. m_vAlignAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
  211. wxArrayString hAlignNames;
  212. hAlignNames.Add( _( "Left" ) );
  213. hAlignNames.Add(_( "Center" ) );
  214. hAlignNames.Add(_( "Right" ) );
  215. m_hAlignAttr = new wxGridCellAttr;
  216. m_hAlignAttr->SetEditor( new wxGridCellChoiceEditor( hAlignNames ) );
  217. m_hAlignAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
  218. wxArrayString orientationNames;
  219. orientationNames.Add( _( "Horizontal" ) );
  220. orientationNames.Add(_( "Vertical" ) );
  221. m_orientationAttr = new wxGridCellAttr;
  222. m_orientationAttr->SetEditor( new wxGridCellChoiceEditor( orientationNames ) );
  223. m_orientationAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_BOTTOM );
  224. SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
  225. wxArrayString existingNetclasses;
  226. if( editFrame )
  227. {
  228. // Load the combobox with existing existingNetclassNames
  229. PROJECT_FILE& projectFile = editFrame->Prj().GetProjectFile();
  230. const std::shared_ptr<NET_SETTINGS>& settings = projectFile.NetSettings();
  231. existingNetclasses.push_back( settings->m_DefaultNetClass->GetName() );
  232. for( const auto& [ name, netclass ] : settings->m_NetClasses )
  233. existingNetclasses.push_back( name );
  234. }
  235. m_netclassAttr = new wxGridCellAttr;
  236. m_netclassAttr->SetEditor( new GRID_CELL_COMBOBOX( existingNetclasses ) );
  237. wxArrayString fonts;
  238. std::vector<std::string> fontNames;
  239. Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ) );
  240. for( const std::string& name : fontNames )
  241. fonts.Add( wxString( name ) );
  242. fonts.Sort();
  243. fonts.Insert( KICAD_FONT_NAME, 0 );
  244. fonts.Insert( DEFAULT_FONT_NAME, 0 );
  245. m_fontAttr = new wxGridCellAttr;
  246. m_fontAttr->SetEditor( new GRID_CELL_COMBOBOX( fonts ) );
  247. m_colorAttr = new wxGridCellAttr;
  248. m_colorAttr->SetRenderer( new GRID_CELL_COLOR_RENDERER( m_dialog ) );
  249. m_colorAttr->SetEditor( new GRID_CELL_COLOR_SELECTOR( m_dialog, aGrid ) );
  250. m_eval = std::make_unique<NUMERIC_EVALUATOR>( m_frame->GetUserUnits() );
  251. m_frame->Bind( UNITS_CHANGED, &FIELDS_GRID_TABLE<T>::onUnitsChanged, this );
  252. }
  253. template <class T>
  254. FIELDS_GRID_TABLE<T>::~FIELDS_GRID_TABLE()
  255. {
  256. m_readOnlyAttr->DecRef();
  257. m_fieldNameAttr->DecRef();
  258. m_boolAttr->DecRef();
  259. m_referenceAttr->DecRef();
  260. m_valueAttr->DecRef();
  261. m_footprintAttr->DecRef();
  262. m_urlAttr->DecRef();
  263. m_nonUrlAttr->DecRef();
  264. m_filepathAttr->DecRef();
  265. m_vAlignAttr->DecRef();
  266. m_hAlignAttr->DecRef();
  267. m_orientationAttr->DecRef();
  268. m_netclassAttr->DecRef();
  269. m_fontAttr->DecRef();
  270. m_colorAttr->DecRef();
  271. m_frame->Unbind( UNITS_CHANGED, &FIELDS_GRID_TABLE<T>::onUnitsChanged, this );
  272. }
  273. template <class T>
  274. void FIELDS_GRID_TABLE<T>::onUnitsChanged( wxCommandEvent& aEvent )
  275. {
  276. if( GetView() )
  277. GetView()->ForceRefresh();
  278. aEvent.Skip();
  279. }
  280. template <class T>
  281. wxString FIELDS_GRID_TABLE<T>::GetColLabelValue( int aCol )
  282. {
  283. switch( aCol )
  284. {
  285. case FDC_NAME: return _( "Name" );
  286. case FDC_VALUE: return _( "Value" );
  287. case FDC_SHOWN: return _( "Show" );
  288. case FDC_SHOW_NAME: return _( "Show Name" );
  289. case FDC_H_ALIGN: return _( "H Align" );
  290. case FDC_V_ALIGN: return _( "V Align" );
  291. case FDC_ITALIC: return _( "Italic" );
  292. case FDC_BOLD: return _( "Bold" );
  293. case FDC_TEXT_SIZE: return _( "Text Size" );
  294. case FDC_ORIENTATION: return _( "Orientation" );
  295. case FDC_POSX: return _( "X Position" );
  296. case FDC_POSY: return _( "Y Position" );
  297. case FDC_FONT: return _( "Font" );
  298. case FDC_COLOR: return _( "Color" );
  299. case FDC_ALLOW_AUTOPLACE: return _( "Allow Autoplacement" );
  300. default: wxFAIL; return wxEmptyString;
  301. }
  302. }
  303. template <class T>
  304. bool FIELDS_GRID_TABLE<T>::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
  305. {
  306. switch( aCol )
  307. {
  308. case FDC_NAME:
  309. case FDC_VALUE:
  310. case FDC_H_ALIGN:
  311. case FDC_V_ALIGN:
  312. case FDC_TEXT_SIZE:
  313. case FDC_ORIENTATION:
  314. case FDC_POSX:
  315. case FDC_POSY:
  316. case FDC_FONT:
  317. case FDC_COLOR:
  318. return aTypeName == wxGRID_VALUE_STRING;
  319. case FDC_SHOWN:
  320. case FDC_SHOW_NAME:
  321. case FDC_ITALIC:
  322. case FDC_BOLD:
  323. case FDC_ALLOW_AUTOPLACE:
  324. return aTypeName == wxGRID_VALUE_BOOL;
  325. default:
  326. wxFAIL;
  327. return false;
  328. }
  329. }
  330. template <class T>
  331. bool FIELDS_GRID_TABLE<T>::CanSetValueAs( int aRow, int aCol, const wxString& aTypeName )
  332. {
  333. return CanGetValueAs( aRow, aCol, aTypeName );
  334. }
  335. template <class T>
  336. wxGridCellAttr* FIELDS_GRID_TABLE<T>::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind )
  337. {
  338. wxGridCellAttr* tmp;
  339. switch( aCol )
  340. {
  341. case FDC_NAME:
  342. if( aRow < m_mandatoryFieldCount )
  343. {
  344. tmp = m_fieldNameAttr->Clone();
  345. tmp->SetReadOnly( true );
  346. return tmp;
  347. }
  348. else
  349. {
  350. m_fieldNameAttr->IncRef();
  351. return m_fieldNameAttr;
  352. }
  353. case FDC_VALUE:
  354. if( m_parentType == SCH_SYMBOL_T && aRow == REFERENCE_FIELD )
  355. {
  356. m_referenceAttr->IncRef();
  357. return m_referenceAttr;
  358. }
  359. else if( m_parentType == SCH_SYMBOL_T && aRow == VALUE_FIELD )
  360. {
  361. m_valueAttr->IncRef();
  362. return m_valueAttr;
  363. }
  364. else if( m_parentType == SCH_SYMBOL_T && aRow == FOOTPRINT_FIELD )
  365. {
  366. m_footprintAttr->IncRef();
  367. return m_footprintAttr;
  368. }
  369. else if( m_parentType == SCH_SYMBOL_T && aRow == DATASHEET_FIELD )
  370. {
  371. m_urlAttr->IncRef();
  372. return m_urlAttr;
  373. }
  374. else if( m_parentType == SCH_SHEET_T && aRow == SHEETNAME )
  375. {
  376. m_referenceAttr->IncRef();
  377. return m_referenceAttr;
  378. }
  379. else if( m_parentType == SCH_SHEET_T && aRow == SHEETFILENAME )
  380. {
  381. m_filepathAttr->IncRef();
  382. return m_filepathAttr;
  383. }
  384. else if( ( m_parentType == SCH_LABEL_LOCATE_ANY_T )
  385. && this->at( (size_t) aRow ).GetCanonicalName() == wxT( "Netclass" ) )
  386. {
  387. m_netclassAttr->IncRef();
  388. return m_netclassAttr;
  389. }
  390. else
  391. {
  392. wxString fn = GetValue( aRow, FDC_NAME );
  393. SCHEMATIC_SETTINGS* settings = m_frame->Prj().GetProjectFile().m_SchematicSettings;
  394. const TEMPLATE_FIELDNAME* templateFn =
  395. settings ? settings->m_TemplateFieldNames.GetFieldName( fn ) : nullptr;
  396. if( templateFn && templateFn->m_URL )
  397. {
  398. m_urlAttr->IncRef();
  399. return m_urlAttr;
  400. }
  401. else
  402. {
  403. m_nonUrlAttr->IncRef();
  404. return m_nonUrlAttr;
  405. }
  406. }
  407. case FDC_TEXT_SIZE:
  408. case FDC_POSX:
  409. case FDC_POSY:
  410. return nullptr;
  411. case FDC_H_ALIGN:
  412. m_hAlignAttr->IncRef();
  413. return m_hAlignAttr;
  414. case FDC_V_ALIGN:
  415. m_vAlignAttr->IncRef();
  416. return m_vAlignAttr;
  417. case FDC_ORIENTATION:
  418. m_orientationAttr->IncRef();
  419. return m_orientationAttr;
  420. case FDC_SHOWN:
  421. case FDC_SHOW_NAME:
  422. case FDC_ITALIC:
  423. case FDC_BOLD:
  424. case FDC_ALLOW_AUTOPLACE:
  425. m_boolAttr->IncRef();
  426. return m_boolAttr;
  427. case FDC_FONT:
  428. m_fontAttr->IncRef();
  429. return m_fontAttr;
  430. case FDC_COLOR:
  431. m_colorAttr->IncRef();
  432. return m_colorAttr;
  433. default:
  434. wxFAIL;
  435. return nullptr;
  436. }
  437. }
  438. template <class T>
  439. wxString FIELDS_GRID_TABLE<T>::GetValue( int aRow, int aCol )
  440. {
  441. wxCHECK( aRow < GetNumberRows(), wxEmptyString );
  442. wxGrid* grid = GetView();
  443. const T& field = this->at( (size_t) aRow );
  444. if( grid->GetGridCursorRow() == aRow && grid->GetGridCursorCol() == aCol
  445. && grid->IsCellEditControlShown() )
  446. {
  447. auto it = m_evalOriginal.find( { aRow, aCol } );
  448. if( it != m_evalOriginal.end() )
  449. return it->second;
  450. }
  451. switch( aCol )
  452. {
  453. case FDC_NAME:
  454. // Use default field names for mandatory and system fields because they are translated
  455. // according to the current locale
  456. if( m_parentType == SCH_SYMBOL_T )
  457. {
  458. if( aRow < m_mandatoryFieldCount )
  459. return TEMPLATE_FIELDNAME::GetDefaultFieldName( aRow, DO_TRANSLATE );
  460. else
  461. return field.GetName( false );
  462. }
  463. else if( m_parentType == SCH_SHEET_T )
  464. {
  465. if( aRow < m_mandatoryFieldCount )
  466. return SCH_SHEET::GetDefaultFieldName( aRow );
  467. else
  468. return field.GetName( false );
  469. }
  470. else if( m_parentType == SCH_LABEL_LOCATE_ANY_T )
  471. {
  472. return SCH_LABEL_BASE::GetDefaultFieldName( field.GetCanonicalName(), false );
  473. }
  474. else
  475. {
  476. wxFAIL_MSG( wxS( "Unhandled field owner type." ) );
  477. return field.GetName( false );
  478. }
  479. case FDC_VALUE:
  480. return UnescapeString( field.GetText() );
  481. case FDC_SHOWN:
  482. return StringFromBool( field.IsVisible() );
  483. case FDC_SHOW_NAME:
  484. return StringFromBool( field.IsNameShown() );
  485. case FDC_H_ALIGN:
  486. switch ( field.GetHorizJustify() )
  487. {
  488. case GR_TEXT_H_ALIGN_LEFT: return _( "Left" );
  489. case GR_TEXT_H_ALIGN_CENTER: return _( "Center" );
  490. case GR_TEXT_H_ALIGN_RIGHT: return _( "Right" );
  491. }
  492. break;
  493. case FDC_V_ALIGN:
  494. switch ( field.GetVertJustify() )
  495. {
  496. case GR_TEXT_V_ALIGN_TOP: return _( "Top" );
  497. case GR_TEXT_V_ALIGN_CENTER: return _( "Center" );
  498. case GR_TEXT_V_ALIGN_BOTTOM: return _( "Bottom" );
  499. }
  500. break;
  501. case FDC_ITALIC:
  502. return StringFromBool( field.IsItalic() );
  503. case FDC_BOLD:
  504. return StringFromBool( field.IsBold() );
  505. case FDC_TEXT_SIZE:
  506. return m_frame->StringFromValue( field.GetTextHeight(), true );
  507. case FDC_ORIENTATION:
  508. if( field.GetTextAngle().IsHorizontal() )
  509. return _( "Horizontal" );
  510. else
  511. return _( "Vertical" );
  512. case FDC_POSX:
  513. return m_frame->StringFromValue( field.GetTextPos().x, true );
  514. case FDC_POSY:
  515. return m_frame->StringFromValue( field.GetTextPos().y, true );
  516. case FDC_FONT:
  517. if( field.GetFont() )
  518. return field.GetFont()->GetName();
  519. else
  520. return DEFAULT_FONT_NAME;
  521. case FDC_COLOR:
  522. return field.GetTextColor().ToCSSString();
  523. case FDC_ALLOW_AUTOPLACE:
  524. return StringFromBool( field.CanAutoplace() );
  525. default:
  526. // we can't assert here because wxWidgets sometimes calls this without checking
  527. // the column type when trying to see if there's an overflow
  528. break;
  529. }
  530. return wxT( "bad wxWidgets!" );
  531. }
  532. template <class T>
  533. bool FIELDS_GRID_TABLE<T>::GetValueAsBool( int aRow, int aCol )
  534. {
  535. wxCHECK( aRow < GetNumberRows(), false );
  536. const T& field = this->at( (size_t) aRow );
  537. switch( aCol )
  538. {
  539. case FDC_SHOWN: return field.IsVisible();
  540. case FDC_SHOW_NAME: return field.IsNameShown();
  541. case FDC_ITALIC: return field.IsItalic();
  542. case FDC_BOLD: return field.IsBold();
  543. case FDC_ALLOW_AUTOPLACE: return field.CanAutoplace();
  544. default:
  545. wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
  546. return false;
  547. }
  548. }
  549. template <class T>
  550. void FIELDS_GRID_TABLE<T>::SetValue( int aRow, int aCol, const wxString &aValue )
  551. {
  552. wxCHECK( aRow < GetNumberRows(), /*void*/ );
  553. T& field = this->at( (size_t) aRow );
  554. VECTOR2I pos;
  555. wxString value = aValue;
  556. switch( aCol )
  557. {
  558. case FDC_TEXT_SIZE:
  559. case FDC_POSX:
  560. case FDC_POSY:
  561. m_eval->SetDefaultUnits( m_frame->GetUserUnits() );
  562. if( m_eval->Process( value ) )
  563. {
  564. m_evalOriginal[ { aRow, aCol } ] = value;
  565. value = m_eval->Result();
  566. }
  567. break;
  568. default:
  569. break;
  570. }
  571. switch( aCol )
  572. {
  573. case FDC_NAME:
  574. field.SetName( value );
  575. break;
  576. case FDC_VALUE:
  577. {
  578. if( m_parentType == SCH_SHEET_T && aRow == SHEETFILENAME )
  579. {
  580. wxFileName fn( value );
  581. // It's annoying to throw up nag dialogs when the extension isn't right. Just
  582. // fix it.
  583. if( fn.GetExt().CmpNoCase( KiCadSchematicFileExtension ) != 0 )
  584. {
  585. fn.SetExt( KiCadSchematicFileExtension );
  586. value = fn.GetFullPath();
  587. }
  588. }
  589. else if( m_parentType == LIB_SYMBOL_T && aRow == VALUE_FIELD )
  590. {
  591. value = EscapeString( value, CTX_LIBID );
  592. }
  593. field.SetText( value );
  594. break;
  595. }
  596. case FDC_SHOWN:
  597. field.SetVisible( BoolFromString( value ) );
  598. break;
  599. case FDC_SHOW_NAME:
  600. field.SetNameShown( BoolFromString( value ) );
  601. break;
  602. case FDC_H_ALIGN:
  603. if( value == _( "Left" ) )
  604. field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
  605. else if( value == _( "Center" ) )
  606. field.SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
  607. else if( value == _( "Right" ) )
  608. field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
  609. else
  610. wxFAIL_MSG( wxT( "unknown horizontal alignment: " ) + value );
  611. break;
  612. case FDC_V_ALIGN:
  613. if( value == _( "Top" ) )
  614. field.SetVertJustify( GR_TEXT_V_ALIGN_TOP );
  615. else if( value == _( "Center" ) )
  616. field.SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
  617. else if( value == _( "Bottom" ) )
  618. field.SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
  619. else
  620. wxFAIL_MSG( wxT( "unknown vertical alignment: " ) + value);
  621. break;
  622. case FDC_ITALIC:
  623. field.SetItalic( BoolFromString( value ) );
  624. break;
  625. case FDC_BOLD:
  626. field.SetBold( BoolFromString( value ) );
  627. break;
  628. case FDC_TEXT_SIZE:
  629. field.SetTextSize( VECTOR2I( m_frame->ValueFromString( value ),
  630. m_frame->ValueFromString( value ) ) );
  631. break;
  632. case FDC_ORIENTATION:
  633. if( value == _( "Horizontal" ) )
  634. field.SetTextAngle( ANGLE_HORIZONTAL );
  635. else if( value == _( "Vertical" ) )
  636. field.SetTextAngle( ANGLE_VERTICAL );
  637. else
  638. wxFAIL_MSG( wxT( "unknown orientation: " ) + value );
  639. break;
  640. case FDC_POSX:
  641. case FDC_POSY:
  642. pos = field.GetTextPos();
  643. if( aCol == FDC_POSX )
  644. pos.x = m_frame->ValueFromString( value );
  645. else
  646. pos.y = m_frame->ValueFromString( value );
  647. field.SetTextPos( pos );
  648. break;
  649. case FDC_FONT:
  650. if( value == DEFAULT_FONT_NAME )
  651. field.SetFont( nullptr );
  652. else if( value == KICAD_FONT_NAME )
  653. field.SetFont( KIFONT::FONT::GetFont( wxEmptyString, field.IsBold(), field.IsItalic() ) );
  654. else
  655. field.SetFont( KIFONT::FONT::GetFont( aValue, field.IsBold(), field.IsItalic() ) );
  656. break;
  657. case FDC_COLOR:
  658. field.SetTextColor( wxColor( value ) );
  659. break;
  660. case FDC_ALLOW_AUTOPLACE:
  661. field.SetCanAutoplace( BoolFromString( value ) );
  662. break;
  663. default:
  664. wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a string value" ), aCol ) );
  665. break;
  666. }
  667. m_dialog->OnModify();
  668. GetView()->Refresh();
  669. }
  670. template <class T>
  671. void FIELDS_GRID_TABLE<T>::SetValueAsBool( int aRow, int aCol, bool aValue )
  672. {
  673. wxCHECK( aRow < GetNumberRows(), /*void*/ );
  674. T& field = this->at( (size_t) aRow );
  675. switch( aCol )
  676. {
  677. case FDC_SHOWN:
  678. field.SetVisible( aValue );
  679. break;
  680. case FDC_SHOW_NAME:
  681. field.SetNameShown( aValue );
  682. break;
  683. case FDC_ITALIC:
  684. field.SetItalic( aValue );
  685. break;
  686. case FDC_BOLD:
  687. field.SetBold( aValue );
  688. break;
  689. case FDC_ALLOW_AUTOPLACE:
  690. field.SetCanAutoplace( aValue );
  691. break;
  692. default:
  693. wxFAIL_MSG( wxString::Format( wxT( "column %d doesn't hold a bool value" ), aCol ) );
  694. break;
  695. }
  696. m_dialog->OnModify();
  697. }
  698. // Explicit Instantiations
  699. template class FIELDS_GRID_TABLE<SCH_FIELD>;
  700. template class FIELDS_GRID_TABLE<LIB_FIELD>;
  701. void FIELDS_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
  702. {
  703. if( m_grid->GetGridCursorRow() == FOOTPRINT_FIELD && m_grid->GetGridCursorCol() == FDC_VALUE )
  704. {
  705. menu.Append( MYID_SELECT_FOOTPRINT, _( "Select Footprint..." ),
  706. _( "Browse for footprint" ) );
  707. menu.AppendSeparator();
  708. }
  709. else if( m_grid->GetGridCursorRow() == DATASHEET_FIELD && m_grid->GetGridCursorCol() == FDC_VALUE )
  710. {
  711. menu.Append( MYID_SHOW_DATASHEET, _( "Show Datasheet" ),
  712. _( "Show datasheet in browser" ) );
  713. menu.AppendSeparator();
  714. }
  715. GRID_TRICKS::showPopupMenu( menu, aEvent );
  716. }
  717. void FIELDS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
  718. {
  719. if( event.GetId() == MYID_SELECT_FOOTPRINT )
  720. {
  721. // pick a footprint using the footprint picker.
  722. wxString fpid = m_grid->GetCellValue( FOOTPRINT_FIELD, FDC_VALUE );
  723. KIWAY_PLAYER* frame = m_dlg->Kiway().Player( FRAME_FOOTPRINT_VIEWER_MODAL, true, m_dlg );
  724. if( frame->ShowModal( &fpid, m_dlg ) )
  725. m_grid->SetCellValue( FOOTPRINT_FIELD, FDC_VALUE, fpid );
  726. frame->Destroy();
  727. }
  728. else if (event.GetId() == MYID_SHOW_DATASHEET )
  729. {
  730. wxString datasheet_uri = m_grid->GetCellValue( DATASHEET_FIELD, FDC_VALUE );
  731. GetAssociatedDocument( m_dlg, datasheet_uri, &m_dlg->Prj(), m_dlg->Prj().SchSearchS() );
  732. }
  733. else
  734. {
  735. GRID_TRICKS::doPopupSelection( event );
  736. }
  737. }
  738. template <class T>
  739. wxString FIELDS_GRID_TABLE<T>::StringFromBool( bool aValue ) const
  740. {
  741. if( aValue )
  742. return wxT( "1" );
  743. else
  744. return wxT( "0" );
  745. }
  746. template <class T>
  747. bool FIELDS_GRID_TABLE<T>::BoolFromString( wxString aValue ) const
  748. {
  749. if( aValue == wxS( "1" ) )
  750. {
  751. return true;
  752. }
  753. else if( aValue == wxS( "0" ) )
  754. {
  755. return false;
  756. }
  757. else
  758. {
  759. wxFAIL_MSG( wxString::Format( "string '%s' can't be converted to boolean correctly and "
  760. "will be perceived as FALSE", aValue ) );
  761. return false;
  762. }
  763. }