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.

620 lines
20 KiB

14 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2015 Dick Hollenbeck, dick@softplc.com
  6. * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
  7. * Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, you may find one here:
  21. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  22. * or you may search the http://www.gnu.org website for the version 2 license,
  23. * or you may write to the Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. #include <confirm.h>
  27. #include <dialogs/dialog_text_entry.h>
  28. #include <3d_viewer/eda_3d_viewer_frame.h>
  29. #include <validators.h>
  30. #include <board_design_settings.h>
  31. #include <board_commit.h>
  32. #include <bitmaps.h>
  33. #include <widgets/grid_text_button_helpers.h>
  34. #include <widgets/wx_grid.h>
  35. #include <widgets/text_ctrl_eval.h>
  36. #include <footprint.h>
  37. #include <footprint_edit_frame.h>
  38. #include <footprint_editor_settings.h>
  39. #include <dialog_footprint_properties_fp_editor.h>
  40. #include <panel_fp_properties_3d_model.h>
  41. #include "3d_rendering/opengl/3d_model.h"
  42. #include "filename_resolver.h"
  43. #include <pgm_base.h>
  44. #include "dialogs/panel_preview_3d_model.h"
  45. #include "dialogs/3d_cache_dialogs.h"
  46. #include <settings/settings_manager.h>
  47. #include <tool/tool_manager.h>
  48. #include <tools/pcb_selection_tool.h>
  49. #include <fp_lib_table.h>
  50. // Remember the last open page during session.
  51. NOTEBOOK_PAGES DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::m_page = NOTEBOOK_PAGES::PAGE_GENERAL;
  52. DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR(
  53. FOOTPRINT_EDIT_FRAME* aParent,
  54. FOOTPRINT* aFootprint ) :
  55. DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR_BASE( aParent ),
  56. m_frame( aParent ),
  57. m_footprint( aFootprint ),
  58. m_netClearance( aParent, m_NetClearanceLabel, m_NetClearanceCtrl, m_NetClearanceUnits ),
  59. m_solderMask( aParent, m_SolderMaskMarginLabel, m_SolderMaskMarginCtrl,
  60. m_SolderMaskMarginUnits ),
  61. m_solderPaste( aParent, m_SolderPasteMarginLabel, m_SolderPasteMarginCtrl,
  62. m_SolderPasteMarginUnits ),
  63. m_solderPasteRatio( aParent, m_PasteMarginRatioLabel, m_PasteMarginRatioCtrl,
  64. m_PasteMarginRatioUnits )
  65. {
  66. // Create the 3D models page
  67. m_3dPanel = new PANEL_FP_PROPERTIES_3D_MODEL( m_frame, m_footprint, this, m_NoteBook );
  68. m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
  69. m_texts = new FP_TEXT_GRID_TABLE( m_units, m_frame );
  70. m_delayedErrorMessage = wxEmptyString;
  71. m_delayedFocusCtrl = nullptr;
  72. m_delayedFocusGrid = nullptr;
  73. m_delayedFocusRow = -1;
  74. m_delayedFocusColumn = -1;
  75. m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
  76. // Give an icon
  77. wxIcon icon;
  78. icon.CopyFromBitmap( KiBitmap( BITMAPS::icon_modedit ) );
  79. SetIcon( icon );
  80. // Give a bit more room for combobox editors
  81. m_itemsGrid->SetDefaultRowSize( m_itemsGrid->GetDefaultRowSize() + 4 );
  82. m_itemsGrid->SetTable( m_texts );
  83. m_itemsGrid->PushEventHandler( new GRID_TRICKS( m_itemsGrid ) );
  84. // Show/hide columns according to the user's preference
  85. m_itemsGrid->ShowHideColumns( m_frame->GetSettings()->m_FootprintTextShownColumns );
  86. m_FootprintNameCtrl->SetValidator( FOOTPRINT_NAME_VALIDATOR() );
  87. // Set font sizes
  88. wxFont infoFont = KIUI::GetInfoFont( this );
  89. #if __WXMAC__
  90. m_allow90Label->SetFont( infoFont );
  91. m_allow180Label->SetFont( infoFont );
  92. #endif
  93. infoFont.SetStyle( wxFONTSTYLE_ITALIC );
  94. m_staticTextInfoValNeg->SetFont( infoFont );
  95. m_staticTextInfoValPos->SetFont( infoFont );
  96. m_staticTextInfoCopper->SetFont( infoFont );
  97. m_staticTextInfoPaste->SetFont( infoFont );
  98. if( static_cast<int>( m_page ) >= 0 )
  99. m_NoteBook->SetSelection( (unsigned) m_page );
  100. if( m_page == NOTEBOOK_PAGES::PAGE_GENERAL )
  101. {
  102. m_delayedFocusGrid = m_itemsGrid;
  103. m_delayedFocusRow = 0;
  104. m_delayedFocusColumn = 0;
  105. m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
  106. }
  107. else if( m_page == NOTEBOOK_PAGES::PAGE_CLEARANCES )
  108. {
  109. SetInitialFocus( m_NetClearanceCtrl );
  110. }
  111. m_solderPaste.SetNegativeZero();
  112. m_solderPasteRatio.SetUnits( EDA_UNITS::PERCENT );
  113. m_solderPasteRatio.SetNegativeZero();
  114. m_sdbSizerStdButtonsOK->SetDefault();
  115. // Configure button logos
  116. m_bpAdd->SetBitmap( KiBitmap( BITMAPS::small_plus ) );
  117. m_bpDelete->SetBitmap( KiBitmap( BITMAPS::small_trash ) );
  118. // wxFormBuilder doesn't include this event...
  119. m_itemsGrid->Connect( wxEVT_GRID_CELL_CHANGING,
  120. wxGridEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnGridCellChanging ),
  121. nullptr, this );
  122. finishDialogSettings();
  123. }
  124. DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::~DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR()
  125. {
  126. m_frame->GetSettings()->m_FootprintTextShownColumns =
  127. m_itemsGrid->GetShownColumns().ToStdString();
  128. // Prevents crash bug in wxGrid's d'tor
  129. m_itemsGrid->DestroyTable( m_texts );
  130. m_itemsGrid->Disconnect( wxEVT_GRID_CELL_CHANGING,
  131. wxGridEventHandler( DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnGridCellChanging ),
  132. nullptr, this );
  133. // Delete the GRID_TRICKS.
  134. m_itemsGrid->PopEventHandler( true );
  135. m_page = static_cast<NOTEBOOK_PAGES>( m_NoteBook->GetSelection() );
  136. // the GL canvas on the 3D models page has to be visible before it is destroyed
  137. m_NoteBook->SetSelection( static_cast<int>( NOTEBOOK_PAGES::PAGE_3D_MODELS ) );
  138. }
  139. bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::TransferDataToWindow()
  140. {
  141. LIB_ID fpID = m_footprint->GetFPID();
  142. wxString footprintName = fpID.GetLibItemName();
  143. m_FootprintNameCtrl->ChangeValue( footprintName );
  144. m_DocCtrl->SetValue( m_footprint->GetDescription() );
  145. m_KeywordCtrl->SetValue( m_footprint->GetKeywords() );
  146. if( !wxDialog::TransferDataToWindow() )
  147. return false;
  148. if( !m_PanelGeneral->TransferDataToWindow() )
  149. return false;
  150. // Add the models to the panel
  151. if( !m_3dPanel->TransferDataToWindow() )
  152. return false;
  153. // Footprint Texts
  154. m_texts->push_back( m_footprint->Reference() );
  155. m_texts->push_back( m_footprint->Value() );
  156. for( auto item : m_footprint->GraphicalItems() )
  157. {
  158. auto textItem = dyn_cast<FP_TEXT*>( item );
  159. if( textItem )
  160. m_texts->push_back( *textItem );
  161. }
  162. // Notify the grid
  163. wxGridTableMessage tmsg( m_texts, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_texts->GetNumberRows() );
  164. m_itemsGrid->ProcessTableMessage( tmsg );
  165. // Footprint Properties
  166. m_CostRot90Ctrl->SetValue( m_footprint->GetPlacementCost90() );
  167. m_CostRot180Ctrl->SetValue( m_footprint->GetPlacementCost180() );
  168. if( m_footprint->GetAttributes() & FP_THROUGH_HOLE )
  169. m_componentType->SetSelection( 0 );
  170. else if( m_footprint->GetAttributes() & FP_SMD )
  171. m_componentType->SetSelection( 1 );
  172. else
  173. m_componentType->SetSelection( 2 );
  174. m_boardOnly->SetValue( m_footprint->GetAttributes() & FP_BOARD_ONLY );
  175. m_excludeFromPosFiles->SetValue( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_POS_FILES );
  176. m_excludeFromBOM->SetValue( m_footprint->GetAttributes() & FP_EXCLUDE_FROM_BOM );
  177. // Local Clearances
  178. m_netClearance.SetValue( m_footprint->GetLocalClearance() );
  179. m_solderMask.SetValue( m_footprint->GetLocalSolderMaskMargin() );
  180. m_solderPaste.SetValue( m_footprint->GetLocalSolderPasteMargin() );
  181. m_solderPasteRatio.SetDoubleValue( m_footprint->GetLocalSolderPasteMarginRatio() * 100.0 );
  182. switch( m_footprint->GetZoneConnection() )
  183. {
  184. default:
  185. case ZONE_CONNECTION::INHERITED: m_ZoneConnectionChoice->SetSelection( 0 ); break;
  186. case ZONE_CONNECTION::FULL: m_ZoneConnectionChoice->SetSelection( 1 ); break;
  187. case ZONE_CONNECTION::THERMAL: m_ZoneConnectionChoice->SetSelection( 2 ); break;
  188. case ZONE_CONNECTION::NONE: m_ZoneConnectionChoice->SetSelection( 3 ); break;
  189. }
  190. // Items grid
  191. for( int col = 0; col < m_itemsGrid->GetNumberCols(); col++ )
  192. {
  193. // Adjust min size to the column label size
  194. m_itemsGrid->SetColMinimalWidth( col, m_itemsGrid->GetVisibleWidth( col, true, false,
  195. false ) );
  196. // Adjust the column size.
  197. int col_size = m_itemsGrid->GetVisibleWidth( col, true, true, false );
  198. if( col == FPT_LAYER ) // This one's a drop-down. Check all possible values.
  199. {
  200. BOARD* board = m_footprint->GetBoard();
  201. for( PCB_LAYER_ID layer : board->GetEnabledLayers().Seq() )
  202. col_size = std::max( col_size, GetTextExtent( board->GetLayerName( layer ) ).x );
  203. // And the swatch:
  204. col_size += 20;
  205. }
  206. if( m_itemsGrid->IsColShown( col ) )
  207. m_itemsGrid->SetColSize( col, col_size );
  208. }
  209. m_itemsGrid->SetRowLabelSize( m_itemsGrid->GetVisibleWidth( -1, true, true, true ) );
  210. Layout();
  211. adjustGridColumns( m_itemsGrid->GetRect().GetWidth() );
  212. return true;
  213. }
  214. bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::checkFootprintName( const wxString& aFootprintName )
  215. {
  216. if( aFootprintName.IsEmpty() )
  217. {
  218. m_delayedErrorMessage = _( "Footprint must have a name." );
  219. return false;
  220. }
  221. else if( !FOOTPRINT::IsLibNameValid( aFootprintName ) )
  222. {
  223. m_delayedErrorMessage.Printf( _( "Footprint name may not contain '%s'." ),
  224. FOOTPRINT::StringLibNameInvalidChars( true ) );
  225. return false;
  226. }
  227. return true;
  228. }
  229. bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::Validate()
  230. {
  231. if( !m_itemsGrid->CommitPendingChanges() )
  232. return false;
  233. if( !DIALOG_SHIM::Validate() )
  234. return false;
  235. // First, test for invalid chars in footprint name
  236. wxString footprintName = m_FootprintNameCtrl->GetValue();
  237. if( !checkFootprintName( footprintName ) )
  238. {
  239. if( m_NoteBook->GetSelection() != 0 )
  240. m_NoteBook->SetSelection( 0 );
  241. m_delayedFocusCtrl = m_FootprintNameCtrl;
  242. m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_GENERAL;
  243. return false;
  244. }
  245. // Check for empty texts.
  246. for( size_t i = 2; i < m_texts->size(); ++i )
  247. {
  248. FP_TEXT& text = m_texts->at( i );
  249. if( text.GetText().IsEmpty() )
  250. {
  251. if( m_NoteBook->GetSelection() != 0 )
  252. m_NoteBook->SetSelection( 0 );
  253. m_delayedErrorMessage = _( "Text items must have some content." );
  254. m_delayedFocusGrid = m_itemsGrid;
  255. m_delayedFocusColumn = FPT_TEXT;
  256. m_delayedFocusRow = i;
  257. return false;
  258. }
  259. }
  260. if( !m_netClearance.Validate( 0, INT_MAX ) )
  261. return false;
  262. return true;
  263. }
  264. bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::TransferDataFromWindow()
  265. {
  266. if( !Validate() )
  267. return false;
  268. if( !DIALOG_SHIM::TransferDataFromWindow() )
  269. return false;
  270. if( !m_itemsGrid->CommitPendingChanges() )
  271. return false;
  272. // This only commits the editor, model updating is done below so it is inside
  273. // the commit
  274. if( !m_3dPanel->TransferDataFromWindow() )
  275. return false;
  276. auto view = m_frame->GetCanvas()->GetView();
  277. BOARD_COMMIT commit( m_frame );
  278. commit.Modify( m_footprint );
  279. LIB_ID fpID = m_footprint->GetFPID();
  280. fpID.SetLibItemName( m_FootprintNameCtrl->GetValue() );
  281. m_footprint->SetFPID( fpID );
  282. m_footprint->SetDescription( m_DocCtrl->GetValue() );
  283. m_footprint->SetKeywords( m_KeywordCtrl->GetValue() );
  284. // copy reference and value
  285. m_footprint->Reference() = m_texts->at( 0 );
  286. m_footprint->Value() = m_texts->at( 1 );
  287. size_t i = 2;
  288. std::vector<FP_TEXT*> items_to_remove;
  289. for( BOARD_ITEM* item : m_footprint->GraphicalItems() )
  290. {
  291. FP_TEXT* textItem = dynamic_cast<FP_TEXT*>( item );
  292. if( textItem )
  293. {
  294. // copy grid table entries till we run out, then delete any remaining texts
  295. if( i < m_texts->size() )
  296. *textItem = m_texts->at( i++ );
  297. else // store this item to remove and delete it later,
  298. // after the graphic list is explored:
  299. items_to_remove.push_back( textItem );
  300. }
  301. }
  302. // Remove text items:
  303. PCB_SELECTION_TOOL* selTool = m_frame->GetToolManager()->GetTool<PCB_SELECTION_TOOL>();
  304. for( FP_TEXT* item: items_to_remove )
  305. {
  306. selTool->RemoveItemFromSel( item );
  307. view->Remove( item );
  308. item->DeleteStructure();
  309. }
  310. // if there are still grid table entries, create new texts for them
  311. while( i < m_texts->size() )
  312. {
  313. FP_TEXT* newText = new FP_TEXT( m_texts->at( i++ ) );
  314. m_footprint->Add( newText, ADD_MODE::APPEND );
  315. view->Add( newText );
  316. }
  317. int attributes = 0;
  318. switch( m_componentType->GetSelection() )
  319. {
  320. case 0: attributes |= FP_THROUGH_HOLE; break;
  321. case 1: attributes |= FP_SMD; break;
  322. default: break;
  323. }
  324. if( m_boardOnly->GetValue() )
  325. attributes |= FP_BOARD_ONLY;
  326. if( m_excludeFromPosFiles->GetValue() )
  327. attributes |= FP_EXCLUDE_FROM_POS_FILES;
  328. if( m_excludeFromBOM->GetValue() )
  329. attributes |= FP_EXCLUDE_FROM_BOM;
  330. m_footprint->SetAttributes( attributes );
  331. m_footprint->SetPlacementCost90( m_CostRot90Ctrl->GetValue() );
  332. m_footprint->SetPlacementCost180( m_CostRot180Ctrl->GetValue() );
  333. // Initialize masks clearances
  334. m_footprint->SetLocalClearance( m_netClearance.GetValue() );
  335. m_footprint->SetLocalSolderMaskMargin( m_solderMask.GetValue() );
  336. m_footprint->SetLocalSolderPasteMargin( m_solderPaste.GetValue() );
  337. m_footprint->SetLocalSolderPasteMarginRatio( m_solderPasteRatio.GetDoubleValue() / 100.0 );
  338. switch( m_ZoneConnectionChoice->GetSelection() )
  339. {
  340. default:
  341. case 0: m_footprint->SetZoneConnection( ZONE_CONNECTION::INHERITED ); break;
  342. case 1: m_footprint->SetZoneConnection( ZONE_CONNECTION::FULL ); break;
  343. case 2: m_footprint->SetZoneConnection( ZONE_CONNECTION::THERMAL ); break;
  344. case 3: m_footprint->SetZoneConnection( ZONE_CONNECTION::NONE ); break;
  345. }
  346. // Copy the models from the panel to the footprint
  347. std::vector<FP_3DMODEL>& panelList = m_3dPanel->GetModelList();
  348. std::list<FP_3DMODEL>* fpList = &m_footprint->Models();
  349. fpList->clear();
  350. fpList->insert( fpList->end(), panelList.begin(), panelList.end() );
  351. commit.Push( _( "Modify footprint properties" ) );
  352. return true;
  353. }
  354. static bool footprintIsFromBoard( FOOTPRINT* aFootprint )
  355. {
  356. return aFootprint->GetLink() != niluuid;
  357. }
  358. void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnGridCellChanging( wxGridEvent& event )
  359. {
  360. // Currently: nothing to do
  361. }
  362. void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnFootprintNameText( wxCommandEvent& event )
  363. {
  364. if( !footprintIsFromBoard( m_footprint ) )
  365. {
  366. // Currently: nothing to do
  367. }
  368. }
  369. void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnAddField( wxCommandEvent& event )
  370. {
  371. if( !m_itemsGrid->CommitPendingChanges() )
  372. return;
  373. const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
  374. FP_TEXT textItem( m_footprint );
  375. // Set active layer if legal; otherwise copy layer from previous text item
  376. if( LSET::AllTechMask().test( m_frame->GetActiveLayer() ) )
  377. textItem.SetLayer( m_frame->GetActiveLayer() );
  378. else
  379. textItem.SetLayer( m_texts->at( m_texts->size() - 1 ).GetLayer() );
  380. textItem.SetTextSize( dsnSettings.GetTextSize( textItem.GetLayer() ) );
  381. textItem.SetTextThickness( dsnSettings.GetTextThickness( textItem.GetLayer() ) );
  382. textItem.SetItalic( dsnSettings.GetTextItalic( textItem.GetLayer() ) );
  383. m_texts->push_back( textItem );
  384. // notify the grid
  385. wxGridTableMessage msg( m_texts, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
  386. m_itemsGrid->ProcessTableMessage( msg );
  387. m_itemsGrid->SetFocus();
  388. m_itemsGrid->MakeCellVisible( m_texts->size() - 1, 0 );
  389. m_itemsGrid->SetGridCursor( m_texts->size() - 1, 0 );
  390. m_itemsGrid->EnableCellEditControl( true );
  391. m_itemsGrid->ShowCellEditControl();
  392. }
  393. void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnDeleteField( wxCommandEvent& event )
  394. {
  395. if( !m_itemsGrid->CommitPendingChanges() )
  396. return;
  397. int curRow = m_itemsGrid->GetGridCursorRow();
  398. if( curRow < 0 )
  399. {
  400. return;
  401. }
  402. else if( curRow < 2 )
  403. {
  404. DisplayError( nullptr, _( "Reference and value are mandatory." ) );
  405. return;
  406. }
  407. m_texts->erase( m_texts->begin() + curRow );
  408. // notify the grid
  409. wxGridTableMessage msg( m_texts, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 );
  410. m_itemsGrid->ProcessTableMessage( msg );
  411. if( m_itemsGrid->GetNumberRows() > 0 )
  412. {
  413. m_itemsGrid->MakeCellVisible( std::max( 0, curRow-1 ), m_itemsGrid->GetGridCursorCol() );
  414. m_itemsGrid->SetGridCursor( std::max( 0, curRow-1 ), m_itemsGrid->GetGridCursorCol() );
  415. }
  416. }
  417. void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::adjustGridColumns( int aWidth )
  418. {
  419. // Account for scroll bars
  420. int itemsWidth = aWidth - ( m_itemsGrid->GetSize().x - m_itemsGrid->GetClientSize().x );
  421. itemsWidth -= m_itemsGrid->GetRowLabelSize();
  422. for( int i = 1; i < m_itemsGrid->GetNumberCols(); i++ )
  423. itemsWidth -= m_itemsGrid->GetColSize( i );
  424. if( itemsWidth > 0 )
  425. {
  426. m_itemsGrid->SetColSize( 0, std::max( itemsWidth,
  427. m_itemsGrid->GetVisibleWidth( 0, true, false, false ) ) );
  428. }
  429. // Update the width of the 3D panel
  430. m_3dPanel->AdjustGridColumnWidths( aWidth );
  431. }
  432. void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnUpdateUI( wxUpdateUIEvent& event )
  433. {
  434. if( !m_itemsGrid->IsCellEditControlShown() )
  435. adjustGridColumns( m_itemsGrid->GetRect().GetWidth() );
  436. // Handle a delayed focus. The delay allows us to:
  437. // a) change focus when the error was triggered from within a killFocus handler
  438. // b) show the correct notebook page in the background before the error dialog comes up
  439. // when triggered from an OK or a notebook page change
  440. if( static_cast<int>( m_delayedFocusPage ) >= 0 )
  441. {
  442. if( m_NoteBook->GetSelection() != static_cast<int>( m_delayedFocusPage ) )
  443. m_NoteBook->SetSelection( static_cast<int>( m_delayedFocusPage ) );
  444. m_delayedFocusPage = NOTEBOOK_PAGES::PAGE_UNKNOWN;
  445. }
  446. if( !m_delayedErrorMessage.IsEmpty() )
  447. {
  448. // We will re-enter this routine when the error dialog is displayed, so make
  449. // sure we don't keep putting up more dialogs.
  450. wxString msg = m_delayedErrorMessage;
  451. m_delayedErrorMessage = wxEmptyString;
  452. // Do not use DisplayErrorMessage(); it screws up window order on Mac
  453. DisplayError( nullptr, msg );
  454. }
  455. if( m_delayedFocusCtrl )
  456. {
  457. m_delayedFocusCtrl->SetFocus();
  458. if( auto textEntry = dynamic_cast<wxTextEntry*>( m_delayedFocusCtrl ) )
  459. textEntry->SelectAll();
  460. m_delayedFocusCtrl = nullptr;
  461. }
  462. else if( m_delayedFocusGrid )
  463. {
  464. m_delayedFocusGrid->SetFocus();
  465. m_delayedFocusGrid->MakeCellVisible( m_delayedFocusRow, m_delayedFocusColumn );
  466. m_delayedFocusGrid->SetGridCursor( m_delayedFocusRow, m_delayedFocusColumn );
  467. m_delayedFocusGrid->EnableCellEditControl( true );
  468. m_delayedFocusGrid->ShowCellEditControl();
  469. m_delayedFocusGrid = nullptr;
  470. m_delayedFocusRow = -1;
  471. m_delayedFocusColumn = -1;
  472. }
  473. }
  474. void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnGridSize( wxSizeEvent& event )
  475. {
  476. adjustGridColumns( event.GetSize().GetX() );
  477. event.Skip();
  478. }