From 14c9ed1fdae7eb8a69c3efd2d49bcbb36e645000 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 24 Jul 2025 17:55:00 +0100 Subject: [PATCH] Prevent stale selection when deleting grid rows. --- .../dialog_design_block_properties.cpp | 26 +--- common/dialogs/dialog_plugin_options.cpp | 17 +-- common/dialogs/panel_embedded_files.cpp | 21 +-- common/widgets/wx_grid.cpp | 51 +++++++ eeschema/dialogs/dialog_label_properties.cpp | 83 ++++-------- .../dialogs/dialog_lib_edit_pin_table.cpp | 56 +++----- .../dialogs/dialog_lib_symbol_properties.cpp | 60 +++------ eeschema/dialogs/dialog_pin_properties.cpp | 26 +--- eeschema/dialogs/dialog_sheet_properties.cpp | 99 +++++--------- eeschema/dialogs/dialog_symbol_properties.cpp | 80 ++++------- .../dialogs/dialog_user_defined_signals.cpp | 15 +-- eeschema/dialogs/panel_bom_presets.cpp | 28 ++-- eeschema/dialogs/panel_setup_buses.cpp | 27 ++-- .../dialogs/panel_template_fieldnames.cpp | 28 +--- include/widgets/wx_grid.h | 9 ++ kicad/dialogs/panel_jobset.cpp | 35 +---- .../dialogs/dialog_footprint_properties.cpp | 87 +++++------- .../dialog_footprint_properties_fp_editor.cpp | 127 +++++------------- pcbnew/dialogs/panel_display_options.cpp | 31 +---- .../panel_fp_editor_field_defaults.cpp | 31 +---- .../dialogs/panel_setup_tracks_and_vias.cpp | 42 +----- pcbnew/sel_layer.cpp | 15 +-- 22 files changed, 326 insertions(+), 668 deletions(-) diff --git a/common/dialogs/dialog_design_block_properties.cpp b/common/dialogs/dialog_design_block_properties.cpp index f62a2e1f1e..49c907c579 100644 --- a/common/dialogs/dialog_design_block_properties.cpp +++ b/common/dialogs/dialog_design_block_properties.cpp @@ -138,27 +138,11 @@ void DIALOG_DESIGN_BLOCK_PROPERTIES::OnAddField( wxCommandEvent& event ) void DIALOG_DESIGN_BLOCK_PROPERTIES::OnDeleteField( wxCommandEvent& event ) { - if( !m_fieldsGrid->CommitPendingChanges() ) - return; - - wxArrayInt selectedRows = m_fieldsGrid->GetSelectedRows(); - - if( selectedRows.empty() && m_fieldsGrid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_fieldsGrid->GetGridCursorRow() ); - - if( selectedRows.empty() ) - return; - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } ); - - for( int row : selectedRows ) - { - m_fieldsGrid->DeleteRows( row ); - - m_fieldsGrid->MakeCellVisible( std::max( 0, row - 1 ), m_fieldsGrid->GetGridCursorCol() ); - m_fieldsGrid->SetGridCursor( std::max( 0, row - 1 ), m_fieldsGrid->GetGridCursorCol() ); - } + m_fieldsGrid->OnDeleteRows( + [&]( int row ) + { + m_fieldsGrid->DeleteRows( row ); + } ); } diff --git a/common/dialogs/dialog_plugin_options.cpp b/common/dialogs/dialog_plugin_options.cpp index bb7438487d..7ebb9dc263 100644 --- a/common/dialogs/dialog_plugin_options.cpp +++ b/common/dialogs/dialog_plugin_options.cpp @@ -229,17 +229,12 @@ void DIALOG_PLUGIN_OPTIONS::onAppendRow( wxCommandEvent& ) void DIALOG_PLUGIN_OPTIONS::onDeleteRow( wxCommandEvent& ) { - if( !m_grid->CommitPendingChanges() ) - return; - - int curRow = m_grid->GetGridCursorRow(); - - m_grid->DeleteRows( curRow ); - m_grid_widths_dirty = true; - - curRow = std::max( 0, curRow - 1 ); - m_grid->MakeCellVisible( curRow, m_grid->GetGridCursorCol() ); - m_grid->SetGridCursor( curRow, m_grid->GetGridCursorCol() ); + m_grid->OnDeleteRows( + [&]( int row ) + { + m_grid->DeleteRows( row ); + m_grid_widths_dirty = true; + } ); } diff --git a/common/dialogs/panel_embedded_files.cpp b/common/dialogs/panel_embedded_files.cpp index 05e855178b..f17d6a7975 100644 --- a/common/dialogs/panel_embedded_files.cpp +++ b/common/dialogs/panel_embedded_files.cpp @@ -365,21 +365,14 @@ bool PANEL_EMBEDDED_FILES::RemoveEmbeddedFile( const wxString& aFileName ) void PANEL_EMBEDDED_FILES::onDeleteEmbeddedFile( wxCommandEvent& event ) { - int row = m_files_grid->GetGridCursorRow(); + m_files_grid->OnDeleteRows( + [&]( int row ) + { + wxString name = m_files_grid->GetCellValue( row, 0 ); - if( row < 0 ) - return; - - wxString name = m_files_grid->GetCellValue( row, 0 ); - - m_localFiles->RemoveFile( name ); - - m_files_grid->DeleteRows( row ); - - if( row < m_files_grid->GetNumberRows() ) - m_files_grid->SetGridCursor( row, 0 ); - else if( m_files_grid->GetNumberRows() > 0 ) - m_files_grid->SetGridCursor( m_files_grid->GetNumberRows() - 1, 0 ); + m_localFiles->RemoveFile( name ); + m_files_grid->DeleteRows( row ); + } ); } diff --git a/common/widgets/wx_grid.cpp b/common/widgets/wx_grid.cpp index e38bfc0581..8b1df7395b 100644 --- a/common/widgets/wx_grid.cpp +++ b/common/widgets/wx_grid.cpp @@ -694,6 +694,57 @@ bool WX_GRID::CommitPendingChanges( bool aQuietMode ) } +void WX_GRID::OnDeleteRows( const std::function& aDeleter ) +{ + OnDeleteRows( + []( int row ) + { + return true; + }, + aDeleter ); +} + + +void WX_GRID::OnDeleteRows( const std::function& aFilter, + const std::function& aDeleter ) +{ + wxArrayInt selectedRows = GetSelectedRows(); + + if( selectedRows.empty() && GetGridCursorRow() >= 0 ) + selectedRows.push_back( GetGridCursorRow() ); + + if( selectedRows.empty() ) + return; + + for( int row : selectedRows ) + { + if( !aFilter( row ) ) + return; + } + + if( !CommitPendingChanges() ) + return; + + // Reverse sort so deleting a row doesn't change the indexes of the other rows. + selectedRows.Sort( + []( int* first, int* second ) + { + return *second - *first; + } ); + + int nextSelRow = selectedRows.back() - 1; + + if( nextSelRow >= 0 ) + { + GoToCell( nextSelRow, GetGridCursorCol() ); + SetGridCursor( nextSelRow, GetGridCursorCol() ); + } + + for( int row : selectedRows ) + aDeleter( row ); +} + + void WX_GRID::SetUnitsProvider( UNITS_PROVIDER* aProvider, int aCol ) { m_unitsProviders[ aCol ] = aProvider; diff --git a/eeschema/dialogs/dialog_label_properties.cpp b/eeschema/dialogs/dialog_label_properties.cpp index c1810ab651..f0cd5c0d6e 100644 --- a/eeschema/dialogs/dialog_label_properties.cpp +++ b/eeschema/dialogs/dialog_label_properties.cpp @@ -42,8 +42,7 @@ #include -DIALOG_LABEL_PROPERTIES::DIALOG_LABEL_PROPERTIES( SCH_EDIT_FRAME* aParent, - SCH_LABEL_BASE* aLabel, +DIALOG_LABEL_PROPERTIES::DIALOG_LABEL_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_LABEL_BASE* aLabel, bool aNew ) : DIALOG_LABEL_PROPERTIES_BASE( aParent ), m_Parent( aParent ), @@ -219,8 +218,7 @@ DIALOG_LABEL_PROPERTIES::DIALOG_LABEL_PROPERTIES( SCH_EDIT_FRAME* aParent, m_formattingGB->Detach( m_fontCtrl ); m_formattingGB->Detach( m_iconBar ); - m_formattingGB->Add( m_iconBar, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), - wxEXPAND | wxRIGHT, 5 ); + m_formattingGB->Add( m_iconBar, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxEXPAND | wxRIGHT, 5 ); } else { @@ -438,7 +436,9 @@ void DIALOG_LABEL_PROPERTIES::OnCBValueCharHook( wxKeyEvent& aEvent ) // the key event because the default action is to show the m_valueCombo dropdown list, // and we only want to accept the entered string. if( aEvent.GetKeyCode() == WXK_RETURN ) + { wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) ); + } else if( aEvent.GetKeyCode() == WXK_SPACE ) { // our FILTER_COMBOBOX uses the space as special command, not wanted here, @@ -448,7 +448,9 @@ void DIALOG_LABEL_PROPERTIES::OnCBValueCharHook( wxKeyEvent& aEvent ) m_activeTextEntry->WriteText( wxT(" " ) ); } else + { aEvent.Skip(); + } } @@ -555,8 +557,7 @@ bool DIALOG_LABEL_PROPERTIES::TransferDataFromWindow() { if( field.IsVisible() != m_Parent->Schematic().Settings().m_IntersheetRefsShow ) { - DisplayInfoMessage( this, _( "Intersheet reference visibility is " - "controlled globally from " + DisplayInfoMessage( this, _( "Intersheet reference visibility is controlled globally from " "Schematic Setup > General > Formatting" ) ); } @@ -637,15 +638,13 @@ bool DIALOG_LABEL_PROPERTIES::TransferDataFromWindow() if( m_fontCtrl->HaveFontSelection() ) { - m_currentLabel->SetFont( m_fontCtrl->GetFontSelection( m_bold->IsChecked(), - m_italic->IsChecked() ) ); + m_currentLabel->SetFont( m_fontCtrl->GetFontSelection( m_bold->IsChecked(), m_italic->IsChecked() ) ); } if( m_currentLabel->Type() == SCH_DIRECTIVE_LABEL_T ) static_cast( m_currentLabel )->SetPinLength( m_textSize.GetIntValue() ); else if( m_currentLabel->GetTextWidth() != m_textSize.GetIntValue() ) - m_currentLabel->SetTextSize( VECTOR2I( m_textSize.GetIntValue(), - m_textSize.GetIntValue() ) ); + m_currentLabel->SetTextSize( VECTOR2I( m_textSize.GetIntValue(), m_textSize.GetIntValue() ) ); // Must come after SetTextSize() m_currentLabel->SetBold( m_bold->IsChecked() ); @@ -671,11 +670,8 @@ bool DIALOG_LABEL_PROPERTIES::TransferDataFromWindow() m_currentLabel->SetAutoRotateOnPlacement( false ); } - if( !m_currentLabel->AutoRotateOnPlacement() - && m_currentLabel->GetSpinStyle() != selectedSpinStyle ) - { + if( !m_currentLabel->AutoRotateOnPlacement() && m_currentLabel->GetSpinStyle() != selectedSpinStyle ) m_currentLabel->SetSpinStyle( selectedSpinStyle ); - } AUTOPLACE_ALGO fieldsAutoplaced = m_currentLabel->GetFieldsAutoplaced(); @@ -733,8 +729,7 @@ bool DIALOG_LABEL_PROPERTIES::TransferDataFromWindow() } else if( m_labelList && m_currentLabel->Type() == SCH_DIRECTIVE_LABEL_T ) { - SCH_DIRECTIVE_LABEL* label = - new SCH_DIRECTIVE_LABEL( *static_cast( m_currentLabel ) ); + SCH_DIRECTIVE_LABEL* label = new SCH_DIRECTIVE_LABEL( *static_cast( m_currentLabel ) ); m_labelList->push_back( std::unique_ptr( label ) ); } @@ -806,47 +801,25 @@ void DIALOG_LABEL_PROPERTIES::OnAddField( wxCommandEvent& event ) void DIALOG_LABEL_PROPERTIES::OnDeleteField( wxCommandEvent& event ) { - wxArrayInt selectedRows = m_grid->GetSelectedRows(); + m_grid->OnDeleteRows( + [&]( int row ) + { + if( row < m_currentLabel->GetMandatoryFieldCount() ) + { + DisplayError( this, _( "The first field is mandatory." ) ); + return false; + } - if( selectedRows.empty() && m_grid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_grid->GetGridCursorRow() ); + return true; + }, + [&]( int row ) + { + m_fields->erase( m_fields->begin() + row ); - if( selectedRows.empty() ) - return; - - for( int row : selectedRows ) - { - if( row < m_currentLabel->GetMandatoryFieldCount() ) - { - DisplayError( this, _( "The first field is mandatory." ) ); - return; - } - } - - m_grid->CommitPendingChanges( true /* quiet mode */ ); - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( []( int* first, int* second ) - { - return *second - *first; - } ); - - for( int row : selectedRows ) - { - //avoids an assert if we deselect early here - m_grid->ClearSelection(); - m_fields->erase( m_fields->begin() + row ); - - // notify the grid - wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); - m_grid->ProcessTableMessage( msg ); - - if( m_grid->GetNumberRows() > 0 ) - { - m_grid->MakeCellVisible( std::max( 0, row-1 ), m_grid->GetGridCursorCol() ); - m_grid->SetGridCursor( std::max( 0, row-1 ), m_grid->GetGridCursorCol() ); - } - } + // notify the grid + wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); + m_grid->ProcessTableMessage( msg ); + } ); } diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp index 36b7a37636..45aced69e4 100644 --- a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp +++ b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp @@ -367,7 +367,7 @@ void getSelectedArea( WX_GRID* aGrid, int* aRowStart, int* aRowCount ) } -class PIN_TABLE_DATA_MODEL : public wxGridTableBase +class PIN_TABLE_DATA_MODEL : public WX_GRID_TABLE_BASE { public: PIN_TABLE_DATA_MODEL( SYMBOL_EDIT_FRAME* aFrame, @@ -819,7 +819,7 @@ public: m_rows.erase( m_rows.begin() + aRow ); - if ( GetView() ) + if( GetView() ) { wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aRow, 1 ); GetView()->ProcessTableMessage( msg ); @@ -1056,6 +1056,7 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( SYMBOL_EDIT_FRAME* parent, { OnAddRow( aEvent ); } ) ); + m_grid->SetSelectionMode( wxGrid::wxGridSelectRows ); // Show/hide columns according to the user's preference if( SYMBOL_EDITOR_SETTINGS* cfg = parent->GetSettings() ) @@ -1180,8 +1181,8 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( SYMBOL_EDIT_FRAME* parent, m_modified = false; // Connect Events - m_grid->Connect( wxEVT_GRID_COL_SORT, - wxGridEventHandler( DIALOG_LIB_EDIT_PIN_TABLE::OnColSort ), nullptr, this ); + m_grid->Connect( wxEVT_GRID_COL_SORT, wxGridEventHandler( DIALOG_LIB_EDIT_PIN_TABLE::OnColSort ), nullptr, + this ); } @@ -1191,8 +1192,8 @@ DIALOG_LIB_EDIT_PIN_TABLE::~DIALOG_LIB_EDIT_PIN_TABLE() cfg->m_PinTableVisibleColumns = m_grid->GetShownColumnsAsString(); // Disconnect Events - m_grid->Disconnect( wxEVT_GRID_COL_SORT, - wxGridEventHandler( DIALOG_LIB_EDIT_PIN_TABLE::OnColSort ), nullptr, this ); + m_grid->Disconnect( wxEVT_GRID_COL_SORT, wxGridEventHandler( DIALOG_LIB_EDIT_PIN_TABLE::OnColSort ), nullptr, + this ); // Prevents crash bug in wxGrid's d'tor m_grid->DestroyTable( m_dataModel ); @@ -1334,29 +1335,14 @@ void DIALOG_LIB_EDIT_PIN_TABLE::AddPin( SCH_PIN* pin ) void DIALOG_LIB_EDIT_PIN_TABLE::OnDeleteRow( wxCommandEvent& event ) { - // TODO: handle delete of multiple rows.... - if( !m_grid->CommitPendingChanges() ) - return; + m_grid->OnDeleteRows( + [&]( int row ) + { + std::vector removedRow = m_dataModel->RemoveRow( row ); - if( m_pins.size() == 0 ) // empty table - return; - - int curRow = m_grid->GetGridCursorRow(); - - if( curRow < 0 ) - return; - - // move the selection first because wx internally will try to reselect the row we deleted in - // out of order events - int nextSelRow = std::max( curRow-1, 0 ); - m_grid->GoToCell( nextSelRow, m_grid->GetGridCursorCol() ); - m_grid->SetGridCursor( nextSelRow, m_grid->GetGridCursorCol() ); - m_grid->SelectRow( nextSelRow ); - - std::vector removedRow = m_dataModel->RemoveRow( curRow ); - - for( SCH_PIN* pin : removedRow ) - m_pins.erase( std::find( m_pins.begin(), m_pins.end(), pin ) ); + for( SCH_PIN* pin : removedRow ) + m_pins.erase( std::find( m_pins.begin(), m_pins.end(), pin ) ); + } ); updateSummary(); } @@ -1446,9 +1432,7 @@ void DIALOG_LIB_EDIT_PIN_TABLE::OnFilterCheckBox( wxCommandEvent& event ) if( event.IsChecked() ) { if( m_unitFilter->GetSelection() == -1 ) - { m_unitFilter->SetSelection( 0 ); - } m_dataModel->SetUnitFilter( m_unitFilter->GetSelection() ); } @@ -1463,9 +1447,7 @@ void DIALOG_LIB_EDIT_PIN_TABLE::OnFilterCheckBox( wxCommandEvent& event ) if( event.IsChecked() ) { if( m_bodyStyleFilter->GetSelection() == -1 ) - { m_bodyStyleFilter->SetSelection( 0 ); - } m_dataModel->SetBodyStyleFilter( m_bodyStyleFilter->GetSelection() ); } @@ -1521,22 +1503,19 @@ void DIALOG_LIB_EDIT_PIN_TABLE::OnImportButtonClick( wxCommandEvent& event ) } if( !newPins.size() ) - { return; - } if( replaceAll ) { // This is quite a dance with a segfault without smart pointers for( SCH_PIN* pin : m_pins ) delete pin; + m_pins.clear(); } for( auto& newPin : newPins ) - { m_pins.push_back( newPin.release() ); - } m_cbGroup->SetValue( false ); m_dataModel->RebuildRows( m_pins, false, false ); @@ -1572,9 +1551,7 @@ void DIALOG_LIB_EDIT_PIN_TABLE::OnExportButtonClick( wxCommandEvent& event ) for( int i = 0; i < m_dataModel->GetNumberRows(); ++i ) { for( SCH_PIN* pin : m_dataModel->GetRowPins( i ) ) - { pinsToExport.push_back( pin ); - } } } else @@ -1582,7 +1559,6 @@ void DIALOG_LIB_EDIT_PIN_TABLE::OnExportButtonClick( wxCommandEvent& event ) pinsToExport = m_pins; } - PIN_TABLE_EXPORT exporter( *m_editFrame ); exporter.ExportData( pinsToExport, filePath ); } @@ -1704,8 +1680,6 @@ void DIALOG_LIB_EDIT_PIN_TABLE::OnClose( wxCloseEvent& event ) EndQuasiModal( retval ); else EndDialog( retval ); - - return; } diff --git a/eeschema/dialogs/dialog_lib_symbol_properties.cpp b/eeschema/dialogs/dialog_lib_symbol_properties.cpp index 7d0266daa0..75dee17091 100644 --- a/eeschema/dialogs/dialog_lib_symbol_properties.cpp +++ b/eeschema/dialogs/dialog_lib_symbol_properties.cpp @@ -133,10 +133,8 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a if( m_lastLayout != DIALOG_LIB_SYMBOL_PROPERTIES::LAST_LAYOUT::NONE ) { - if( ( m_lastLayout == DIALOG_LIB_SYMBOL_PROPERTIES::LAST_LAYOUT::ALIAS - && aLibEntry->IsRoot() ) - || ( m_lastLayout == DIALOG_LIB_SYMBOL_PROPERTIES::LAST_LAYOUT::PARENT - && aLibEntry->IsDerived() ) ) + if( ( m_lastLayout == DIALOG_LIB_SYMBOL_PROPERTIES::LAST_LAYOUT::ALIAS && aLibEntry->IsRoot() ) + || ( m_lastLayout == DIALOG_LIB_SYMBOL_PROPERTIES::LAST_LAYOUT::PARENT && aLibEntry->IsDerived() ) ) { resetSize(); } @@ -676,44 +674,26 @@ void DIALOG_LIB_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event ) void DIALOG_LIB_SYMBOL_PROPERTIES::OnDeleteField( wxCommandEvent& event ) { - wxArrayInt selectedRows = m_grid->GetSelectedRows(); + m_grid->OnDeleteRows( + [&]( int row ) + { + if( row < m_fields->GetMandatoryRowCount() ) + { + DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), + m_fields->GetMandatoryRowCount() ) ); + return false; + } - if( selectedRows.empty() && m_grid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_grid->GetGridCursorRow() ); + return true; + }, + [&]( int row ) + { + m_fields->erase( m_fields->begin() + row ); - if( selectedRows.empty() ) - return; - - for( int row : selectedRows ) - { - if( row < m_fields->GetMandatoryRowCount() ) - { - DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), - m_fields->GetMandatoryRowCount() ) ); - return; - } - } - - m_grid->CommitPendingChanges( true /* quiet mode */ ); - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } ); - - for( int row : selectedRows ) - { - m_grid->ClearSelection(); - m_fields->erase( m_fields->begin() + row ); - - // notify the grid - wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); - m_grid->ProcessTableMessage( msg ); - - if( m_grid->GetNumberRows() > 0 ) - { - m_grid->MakeCellVisible( std::max( 0, row-1 ), m_grid->GetGridCursorCol() ); - m_grid->SetGridCursor( std::max( 0, row-1 ), m_grid->GetGridCursorCol() ); - } - } + // notify the grid + wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); + m_grid->ProcessTableMessage( msg ); + } ); OnModify(); } diff --git a/eeschema/dialogs/dialog_pin_properties.cpp b/eeschema/dialogs/dialog_pin_properties.cpp index 24a61b0139..e5f1f691ff 100644 --- a/eeschema/dialogs/dialog_pin_properties.cpp +++ b/eeschema/dialogs/dialog_pin_properties.cpp @@ -37,7 +37,7 @@ #include #include -class ALT_PIN_DATA_MODEL : public wxGridTableBase, public std::vector +class ALT_PIN_DATA_MODEL : public WX_GRID_TABLE_BASE, public std::vector { public: ALT_PIN_DATA_MODEL( EDA_UNITS aUserUnits ) @@ -213,6 +213,7 @@ DIALOG_PIN_PROPERTIES::DIALOG_PIN_PROPERTIES( SYMBOL_EDIT_FRAME* parent, SCH_PIN { OnAddAlternate( aEvent ); } ) ); + m_alternatesGrid->SetSelectionMode( wxGrid::wxGridSelectRows ); if( aPin->GetParentSymbol()->HasAlternateBodyStyle() ) { @@ -452,24 +453,11 @@ void DIALOG_PIN_PROPERTIES::OnAddAlternate( wxCommandEvent& event ) void DIALOG_PIN_PROPERTIES::OnDeleteAlternate( wxCommandEvent& event ) { - if( !m_alternatesGrid->CommitPendingChanges() ) - return; - - if( m_alternatesDataModel->size() == 0 ) // empty table - return; - - int curRow = m_alternatesGrid->GetGridCursorRow(); - - if( curRow < 0 ) - return; - - // move the selection first because wx internally will try to reselect the row we deleted in - // out of order events - int nextSelRow = std::max( curRow-1, 0 ); - m_alternatesGrid->GoToCell( nextSelRow, m_alternatesGrid->GetGridCursorCol() ); - m_alternatesGrid->SetGridCursor( nextSelRow, m_alternatesGrid->GetGridCursorCol() ); - - m_alternatesDataModel->RemoveRow( curRow ); + m_alternatesGrid->OnDeleteRows( + [&]( int row ) + { + m_alternatesDataModel->RemoveRow( row ); + } ); } diff --git a/eeschema/dialogs/dialog_sheet_properties.cpp b/eeschema/dialogs/dialog_sheet_properties.cpp index 4ef5c2060f..5c46bc951f 100644 --- a/eeschema/dialogs/dialog_sheet_properties.cpp +++ b/eeschema/dialogs/dialog_sheet_properties.cpp @@ -105,8 +105,7 @@ DIALOG_SHEET_PROPERTIES::DIALOG_SHEET_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_S m_hierarchicalPath->SetFont( KIUI::GetSmallInfoFont( this ) ); // wxFormBuilder doesn't include this event... - m_grid->Connect( wxEVT_GRID_CELL_CHANGING, - wxGridEventHandler( DIALOG_SHEET_PROPERTIES::OnGridCellChanging ), + m_grid->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_SHEET_PROPERTIES::OnGridCellChanging ), nullptr, this ); } @@ -123,8 +122,7 @@ DIALOG_SHEET_PROPERTIES::~DIALOG_SHEET_PROPERTIES() // Prevents crash bug in wxGrid's d'tor m_grid->DestroyTable( m_fields ); - m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING, - wxGridEventHandler( DIALOG_SHEET_PROPERTIES::OnGridCellChanging ), + m_grid->Disconnect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_SHEET_PROPERTIES::OnGridCellChanging ), nullptr, this ); // Delete the GRID_TRICKS. @@ -196,8 +194,6 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataToWindow() bool DIALOG_SHEET_PROPERTIES::Validate() { - LIB_ID id; - if( !m_grid->CommitPendingChanges() || !m_grid->Validate() ) return false; @@ -244,17 +240,11 @@ static bool positioningChanged( const SCH_FIELD& a, const SCH_FIELD& b ) static bool positioningChanged( FIELDS_GRID_TABLE* a, SCH_SHEET* b ) { - if( positioningChanged( a->GetField( FIELD_T::SHEET_NAME ), - b->GetField( FIELD_T::SHEET_NAME ) ) ) - { + if( positioningChanged( a->GetField( FIELD_T::SHEET_NAME ), b->GetField( FIELD_T::SHEET_NAME ) ) ) return true; - } - if( positioningChanged( a->GetField( FIELD_T::SHEET_FILENAME ), - b->GetField( FIELD_T::SHEET_FILENAME ) ) ) - { + if( positioningChanged( a->GetField( FIELD_T::SHEET_FILENAME ), b->GetField( FIELD_T::SHEET_FILENAME ) ) ) return true; - } return false; } @@ -451,8 +441,7 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow() bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilename ) { wxString msg; - wxFileName sheetFileName( EnsureFileExtension( aNewFilename, - FILEEXT::KiCadSchematicFileExtension ) ); + wxFileName sheetFileName( EnsureFileExtension( aNewFilename, FILEEXT::KiCadSchematicFileExtension ) ); // Sheet file names are relative to the path of the current sheet. This allows for // nesting of schematic files in subfolders. Screen file names are always absolute. @@ -467,8 +456,7 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena // SCH_SCREEN file names are always absolute. wxFileName currentScreenFileName = currentScreen->GetFileName(); - if( !screenFileName.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, - currentScreenFileName.GetPath() ) ) + if( !screenFileName.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS, currentScreenFileName.GetPath() ) ) { msg = wxString::Format( _( "Cannot normalize new sheet schematic file path:\n" "'%s'\n" @@ -505,19 +493,16 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena if( m_sheet->GetScreen() == nullptr ) // New just created sheet. { - if( !m_frame->AllowCaseSensitiveFileNameClashes( m_sheet->GetFileName(), - newAbsoluteFilename ) ) + if( !m_frame->AllowCaseSensitiveFileNameClashes( m_sheet->GetFileName(), newAbsoluteFilename ) ) return false; if( useScreen || loadFromFile ) // Load from existing file. { clearAnnotation = true; - if( !IsOK( this, wxString::Format( _( "'%s' already exists." ), - sheetFileName.GetFullName() ) + if( !IsOK( this, wxString::Format( _( "'%s' already exists." ), sheetFileName.GetFullName() ) + wxT( "\n\n" ) - + wxString::Format( _( "Link '%s' to this file?" ), - newAbsoluteFilename ) ) ) + + wxString::Format( _( "Link '%s' to this file?" ), newAbsoluteFilename ) ) ) { return false; } @@ -547,8 +532,7 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena { isExistingSheet = true; - if( !m_frame->AllowCaseSensitiveFileNameClashes( m_sheet->GetFileName(), - newAbsoluteFilename ) ) + if( !m_frame->AllowCaseSensitiveFileNameClashes( m_sheet->GetFileName(), newAbsoluteFilename ) ) return false; // We are always using here a case insensitive comparison to avoid issues @@ -623,12 +607,10 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena } catch( const IO_ERROR& ioe ) { - msg = wxString::Format( _( "Error occurred saving schematic file '%s'." ), - newAbsoluteFilename ); + msg = wxString::Format( _( "Error occurred saving schematic file '%s'." ), newAbsoluteFilename ); DisplayErrorMessage( this, msg, ioe.What() ); - msg = wxString::Format( _( "Failed to save schematic '%s'" ), - newAbsoluteFilename ); + msg = wxString::Format( _( "Failed to save schematic '%s'" ), newAbsoluteFilename ); m_frame->SetMsgPanel( wxEmptyString, msg ); return false; } @@ -665,8 +647,7 @@ bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilena SCH_SHEET_LIST sheetHierarchy( m_sheet ); // The hierarchy of the loaded file. sheetHierarchy.AddNewSymbolInstances( currentSheet, m_frame->Prj().GetProjectName() ); - sheetHierarchy.AddNewSheetInstances( currentSheet, - fullHierarchy.GetLastVirtualPageNumber() ); + sheetHierarchy.AddNewSheetInstances( currentSheet, fullHierarchy.GetLastVirtualPageNumber() ); } else if( loadFromFile ) { @@ -754,44 +735,26 @@ void DIALOG_SHEET_PROPERTIES::OnAddField( wxCommandEvent& event ) void DIALOG_SHEET_PROPERTIES::OnDeleteField( wxCommandEvent& event ) { - wxArrayInt selectedRows = m_grid->GetSelectedRows(); + m_grid->OnDeleteRows( + [&]( int row ) + { + if( row < m_fields->GetMandatoryRowCount() ) + { + DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), + m_fields->GetMandatoryRowCount() ) ); + return false; + } - if( selectedRows.empty() && m_grid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_grid->GetGridCursorRow() ); + return true; + }, + [&]( int row ) + { + m_fields->erase( m_fields->begin() + row ); - if( selectedRows.empty() ) - return; - - for( int row : selectedRows ) - { - if( row < m_fields->GetMandatoryRowCount() ) - { - DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), - m_fields->GetMandatoryRowCount() ) ); - return; - } - } - - m_grid->CommitPendingChanges( true /* quiet mode */ ); - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } ); - - for( int row : selectedRows ) - { - m_grid->ClearSelection(); - m_fields->erase( m_fields->begin() + row ); - - // notify the grid - wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); - m_grid->ProcessTableMessage( msg ); - - if( m_grid->GetNumberRows() > 0 ) - { - m_grid->MakeCellVisible( std::max( 0, row-1 ), m_grid->GetGridCursorCol() ); - m_grid->SetGridCursor( std::max( 0, row-1 ), m_grid->GetGridCursorCol() ); - } - } + // notify the grid + wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); + m_grid->ProcessTableMessage( msg ); + } ); } diff --git a/eeschema/dialogs/dialog_symbol_properties.cpp b/eeschema/dialogs/dialog_symbol_properties.cpp index a45b32040d..e311efb0ca 100644 --- a/eeschema/dialogs/dialog_symbol_properties.cpp +++ b/eeschema/dialogs/dialog_symbol_properties.cpp @@ -128,16 +128,14 @@ public: m_typeAttr->DecRef(); m_typeAttr = new wxGridCellAttr; - m_typeAttr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinTypeIcons(), - PinTypeNames() ) ); + m_typeAttr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinTypeIcons(), PinTypeNames() ) ); m_typeAttr->SetReadOnly( true ); if( m_shapeAttr ) m_shapeAttr->DecRef(); m_shapeAttr = new wxGridCellAttr; - m_shapeAttr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinShapeIcons(), - PinShapeNames() ) ); + m_shapeAttr->SetRenderer( new GRID_CELL_ICON_TEXT_RENDERER( PinShapeIcons(), PinShapeNames() ) ); m_shapeAttr->SetReadOnly( true ); } @@ -307,8 +305,7 @@ protected: }; -DIALOG_SYMBOL_PROPERTIES::DIALOG_SYMBOL_PROPERTIES( SCH_EDIT_FRAME* aParent, - SCH_SYMBOL* aSymbol ) : +DIALOG_SYMBOL_PROPERTIES::DIALOG_SYMBOL_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_SYMBOL* aSymbol ) : DIALOG_SYMBOL_PROPERTIES_BASE( aParent ), m_symbol( nullptr ), m_part( nullptr ), @@ -351,8 +348,7 @@ DIALOG_SYMBOL_PROPERTIES::DIALOG_SYMBOL_PROPERTIES( SCH_EDIT_FRAME* aParent, // free-form alternate assignments as well. (We won't know how to map the alternates // back and forth when the conversion is changed.) m_pinTablePage->Disable(); - m_pinTablePage->SetToolTip( _( "Alternate pin assignments are not available for De Morgan " - "symbols." ) ); + m_pinTablePage->SetToolTip( _( "Alternate pin assignments are not available for De Morgan symbols." ) ); } else { @@ -751,8 +747,7 @@ bool DIALOG_SYMBOL_PROPERTIES::TransferDataFromWindow() // Reference has a specific initialization, depending on the current active sheet // because for a given symbol, in a complex hierarchy, there are more than one // reference. - m_symbol->SetRef( &GetParent()->GetCurrentSheet(), - m_fields->GetField( FIELD_T::REFERENCE )->GetText() ); + m_symbol->SetRef( &GetParent()->GetCurrentSheet(), m_fields->GetField( FIELD_T::REFERENCE )->GetText() ); // Similar for Value and Footprint, except that the GUI behavior is that they are kept // in sync between multiple instances. @@ -876,44 +871,26 @@ void DIALOG_SYMBOL_PROPERTIES::OnAddField( wxCommandEvent& event ) void DIALOG_SYMBOL_PROPERTIES::OnDeleteField( wxCommandEvent& event ) { - wxArrayInt selectedRows = m_fieldsGrid->GetSelectedRows(); + m_fieldsGrid->OnDeleteRows( + [&]( int row ) + { + if( row < m_fields->GetMandatoryRowCount() ) + { + DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), + m_fields->GetMandatoryRowCount() ) ); + return false; + } - if( selectedRows.empty() && m_fieldsGrid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_fieldsGrid->GetGridCursorRow() ); + return true; + }, + [&]( int row ) + { + m_fields->erase( m_fields->begin() + row ); - if( selectedRows.empty() ) - return; - - for( int row : selectedRows ) - { - if( row < m_fields->GetMandatoryRowCount() ) - { - DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), - m_fields->GetMandatoryRowCount() ) ); - return; - } - } - - m_fieldsGrid->CommitPendingChanges( true /* quiet mode */ ); - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } ); - - for( int row : selectedRows ) - { - m_fieldsGrid->ClearSelection(); - m_fields->erase( m_fields->begin() + row ); - - // notify the grid - wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); - m_fieldsGrid->ProcessTableMessage( msg ); - - if( m_fieldsGrid->GetNumberRows() > 0 ) - { - m_fieldsGrid->MakeCellVisible( std::max( 0, row-1 ), m_fieldsGrid->GetGridCursorCol() ); - m_fieldsGrid->SetGridCursor( std::max( 0, row-1 ), m_fieldsGrid->GetGridCursorCol() ); - } - } + // notify the grid + wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); + m_fieldsGrid->ProcessTableMessage( msg ); + } ); OnModify(); } @@ -934,8 +911,7 @@ void DIALOG_SYMBOL_PROPERTIES::OnMoveUp( wxCommandEvent& event ) m_fieldsGrid->ForceRefresh(); m_fieldsGrid->SetGridCursor( i - 1, m_fieldsGrid->GetGridCursorCol() ); - m_fieldsGrid->MakeCellVisible( m_fieldsGrid->GetGridCursorRow(), - m_fieldsGrid->GetGridCursorCol() ); + m_fieldsGrid->MakeCellVisible( m_fieldsGrid->GetGridCursorRow(), m_fieldsGrid->GetGridCursorCol() ); OnModify(); } @@ -961,8 +937,7 @@ void DIALOG_SYMBOL_PROPERTIES::OnMoveDown( wxCommandEvent& event ) m_fieldsGrid->ForceRefresh(); m_fieldsGrid->SetGridCursor( i + 1, m_fieldsGrid->GetGridCursorCol() ); - m_fieldsGrid->MakeCellVisible( m_fieldsGrid->GetGridCursorRow(), - m_fieldsGrid->GetGridCursorCol() ); + m_fieldsGrid->MakeCellVisible( m_fieldsGrid->GetGridCursorRow(), m_fieldsGrid->GetGridCursorCol() ); OnModify(); } @@ -1005,11 +980,8 @@ void DIALOG_SYMBOL_PROPERTIES::OnPinTableCellEdited( wxGridEvent& aEvent ) { int row = aEvent.GetRow(); - if( m_pinGrid->GetCellValue( row, COL_ALT_NAME ) - == m_dataModel->GetValue( row, COL_BASE_NAME ) ) - { + if( m_pinGrid->GetCellValue( row, COL_ALT_NAME ) == m_dataModel->GetValue( row, COL_BASE_NAME ) ) m_dataModel->SetValue( row, COL_ALT_NAME, wxEmptyString ); - } // These are just to get the cells refreshed m_dataModel->SetValue( row, COL_TYPE, m_dataModel->GetValue( row, COL_TYPE ) ); diff --git a/eeschema/dialogs/dialog_user_defined_signals.cpp b/eeschema/dialogs/dialog_user_defined_signals.cpp index c9d8618f63..a05ae32a8d 100644 --- a/eeschema/dialogs/dialog_user_defined_signals.cpp +++ b/eeschema/dialogs/dialog_user_defined_signals.cpp @@ -123,16 +123,11 @@ void DIALOG_USER_DEFINED_SIGNALS::onAddSignal( wxCommandEvent& event ) void DIALOG_USER_DEFINED_SIGNALS::onDeleteSignal( wxCommandEvent& event ) { - int curRow = m_grid->GetGridCursorRow(); - - if( curRow < 0 || m_grid->GetNumberRows() <= curRow ) - return; - - m_grid->CommitPendingChanges( true /* silent mode; we don't care if it's valid */ ); - m_grid->DeleteRows( curRow, 1 ); - - m_grid->MakeCellVisible( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() ); - m_grid->SetGridCursor( std::max( 0, curRow-1 ), m_grid->GetGridCursorCol() ); + m_grid->OnDeleteRows( + [&]( int row ) + { + m_grid->DeleteRows( row, 1 ); + } ); } diff --git a/eeschema/dialogs/panel_bom_presets.cpp b/eeschema/dialogs/panel_bom_presets.cpp index 68b56f69a0..de94bbdec9 100644 --- a/eeschema/dialogs/panel_bom_presets.cpp +++ b/eeschema/dialogs/panel_bom_presets.cpp @@ -82,27 +82,23 @@ void PANEL_BOM_PRESETS::BuildGrid() void PANEL_BOM_PRESETS::OnDeleteBomPreset( wxCommandEvent& event ) { - int curRow = m_bomPresetsGrid->GetGridCursorRow(); - - if( curRow < 0 || m_bomPresetsGrid->GetNumberRows() <= curRow ) - return; - - m_bomPresetsGrid->DeleteRows( curRow, 1 ); - m_bomPresets.erase( m_bomPresets.begin() + curRow ); + m_bomPresetsGrid->OnDeleteRows( + [&]( int row ) + { + m_bomPresetsGrid->DeleteRows( row, 1 ); + m_bomPresets.erase( m_bomPresets.begin() + row ); + } ); } void PANEL_BOM_PRESETS::OnDeleteBomFmtPreset( wxCommandEvent& event ) { - int curRow = m_bomFmtPresetsGrid->GetGridCursorRow(); - - if( curRow < 0 || m_bomFmtPresetsGrid->GetNumberRows() <= curRow ) - return; - - m_bomFmtPresetsGrid->DeleteRows( curRow, 1 ); - - // Erase the bom preset from the bom presets list. - m_bomFmtPresets.erase( m_bomFmtPresets.begin() + curRow ); + m_bomFmtPresetsGrid->OnDeleteRows( + [&]( int row ) + { + m_bomFmtPresetsGrid->DeleteRows( row, 1 ); + m_bomFmtPresets.erase( m_bomFmtPresets.begin() + row ); + } ); } diff --git a/eeschema/dialogs/panel_setup_buses.cpp b/eeschema/dialogs/panel_setup_buses.cpp index 69d6e6d628..15e3cadd38 100644 --- a/eeschema/dialogs/panel_setup_buses.cpp +++ b/eeschema/dialogs/panel_setup_buses.cpp @@ -204,25 +204,18 @@ void PANEL_SETUP_BUSES::OnDeleteAlias( wxCommandEvent& aEvent ) if( !m_aliasesGrid->CommitPendingChanges() || !m_membersGrid->CommitPendingChanges() ) return; - int curRow = m_aliasesGrid->GetGridCursorRow(); + m_aliasesGrid->OnDeleteRows( + [&]( int row ) + { + // Clear the members grid first so we don't try to write it back to a deleted alias + m_membersGrid->ClearRows(); + m_lastAlias = -1; + m_lastAliasName = wxEmptyString; - if( curRow < 0 ) - return; + m_aliases.erase( m_aliases.begin() + row ); - // Clear the members grid first so we don't try to write it back to a deleted alias - m_membersGrid->ClearRows(); - m_lastAlias = -1; - m_lastAliasName = wxEmptyString; - - m_aliases.erase( m_aliases.begin() + curRow ); - - m_aliasesGrid->DeleteRows( curRow, 1 ); - - if( m_aliasesGrid->GetNumberRows() > 0 ) - { - m_aliasesGrid->MakeCellVisible( std::max( 0, curRow-1 ), 0 ); - m_aliasesGrid->SelectRow( std::max( 0, curRow-1 ) ); - } + m_aliasesGrid->DeleteRows( row, 1 ); + } ); } diff --git a/eeschema/dialogs/panel_template_fieldnames.cpp b/eeschema/dialogs/panel_template_fieldnames.cpp index 0cdb53dd4e..d96c9123ae 100644 --- a/eeschema/dialogs/panel_template_fieldnames.cpp +++ b/eeschema/dialogs/panel_template_fieldnames.cpp @@ -115,32 +115,12 @@ void PANEL_TEMPLATE_FIELDNAMES::OnAddButtonClick( wxCommandEvent& event ) void PANEL_TEMPLATE_FIELDNAMES::OnDeleteButtonClick( wxCommandEvent& event ) { - if( !m_grid->CommitPendingChanges() ) - return; - - wxArrayInt selectedRows = m_grid->GetSelectedRows(); - - if( selectedRows.empty() && m_grid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_grid->GetGridCursorRow() ); - - if( selectedRows.empty() ) - return; - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( - []( int* first, int* second ) + m_grid->OnDeleteRows( + [&]( int row ) { - return *second - *first; + m_fields.erase( m_fields.begin() + row ); + m_grid->DeleteRows( row ); } ); - - for( int row : selectedRows ) - { - m_fields.erase( m_fields.begin() + row ); - m_grid->DeleteRows( row ); - - m_grid->MakeCellVisible( std::max( 0, row-1 ), m_grid->GetGridCursorCol() ); - m_grid->SetGridCursor( std::max( 0, row-1 ), m_grid->GetGridCursorCol() ); - } } diff --git a/include/widgets/wx_grid.h b/include/widgets/wx_grid.h index 7931d6020c..d10e4c65cb 100644 --- a/include/widgets/wx_grid.h +++ b/include/widgets/wx_grid.h @@ -118,6 +118,15 @@ public: bool CommitPendingChanges( bool aQuietMode = false ); bool CancelPendingChanges(); + /** + * Handles a row deletion event. This is a bit tricky due to the potential for stale + * selections, so we code it only once here. + */ + void OnDeleteRows( const std::function& aDeleter ); + + void OnDeleteRows( const std::function& aFilter, + const std::function& aDeleter ); + /** * Set a EUNITS_PROVIDER to enable use of unit- and eval-based Getters. * diff --git a/kicad/dialogs/panel_jobset.cpp b/kicad/dialogs/panel_jobset.cpp index a3e9346fae..2ae8052ddc 100644 --- a/kicad/dialogs/panel_jobset.cpp +++ b/kicad/dialogs/panel_jobset.cpp @@ -759,35 +759,12 @@ void PANEL_JOBSET::OnAddJobClick( wxCommandEvent& aEvent ) void PANEL_JOBSET::OnJobButtonDelete( wxCommandEvent& aEvent ) { - if( !m_jobsGrid->CommitPendingChanges() ) - return; - - wxArrayInt selectedRows = m_jobsGrid->GetSelectedRows(); - - if( selectedRows.empty() ) - return; - - m_jobsGrid->CommitPendingChanges( true /* quiet mode */ ); - m_jobsGrid->ClearSelection(); - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( []( int* first, int* second ) - { - return *second - *first; - } ); - - int select = selectedRows[0]; - - for( int row : selectedRows ) - m_jobsFile->RemoveJob( row ); - - rebuildJobList(); - - if( m_jobsGrid->GetNumberRows() ) - { - m_jobsGrid->MakeCellVisible( std::max( 0, select-1 ), m_jobsGrid->GetGridCursorCol() ); - m_jobsGrid->SetGridCursor( std::max( 0, select-1 ), m_jobsGrid->GetGridCursorCol() ); - } + m_jobsGrid->OnDeleteRows( + [&]( int row ) + { + m_jobsFile->RemoveJob( row ); + m_jobsGrid->DeleteRows( row, 1 ); + } ); } diff --git a/pcbnew/dialogs/dialog_footprint_properties.cpp b/pcbnew/dialogs/dialog_footprint_properties.cpp index 690c26ecbb..b7f623e33c 100644 --- a/pcbnew/dialogs/dialog_footprint_properties.cpp +++ b/pcbnew/dialogs/dialog_footprint_properties.cpp @@ -267,8 +267,7 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataToWindow() } // notify the grid - wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, - m_fields->GetNumberRows() ); + wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() ); m_itemsGrid->ProcessTableMessage( tmsg ); // Footprint Properties @@ -282,9 +281,8 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataToWindow() m_orientation.SetAngleValue( orientation.Normalize180() ); m_cbLocked->SetValue( m_footprint->IsLocked() ); - m_cbLocked->SetToolTip( _( "Locked footprints cannot be freely moved and oriented on the " - "canvas and can only be selected when the 'Locked items' checkbox " - "is checked in the selection filter." ) ); + m_cbLocked->SetToolTip( _( "Locked footprints cannot be freely moved or oriented on the canvas and can only be " + "selected when the 'Locked items' checkbox is checked in the selection filter." ) ); if( m_footprint->GetAttributes() & FP_THROUGH_HOLE ) m_componentType->SetSelection( 0 ); @@ -492,8 +490,7 @@ bool DIALOG_FOOTPRINT_PROPERTIES::Validate() m_itemsGrid->SetCellValue( i, PFC_THICKNESS, clamped ); m_delayedFocusGrid = m_itemsGrid; - m_delayedErrorMessage = wxString::Format( _( "Text thickness is too large for the " - "text size.\n" + m_delayedErrorMessage = wxString::Format( _( "Text thickness is too large for the text size.\n" "It will be clamped at %s." ), clamped ); m_delayedFocusColumn = PFC_THICKNESS; @@ -652,19 +649,19 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataFromWindow() // Set component side, that also have effect on the fields positions on board bool change_layer = false; + if( m_BoardSideCtrl->GetSelection() == 0 ) // layer req = COMPONENT { if( m_footprint->GetLayer() == B_Cu ) change_layer = true; } else if( m_footprint->GetLayer() == F_Cu ) + { change_layer = true; + } if( change_layer ) - { - m_footprint->Flip( m_footprint->GetPosition(), - m_frame->GetPcbNewSettings()->m_FlipDirection ); - } + m_footprint->Flip( m_footprint->GetPosition(), m_frame->GetPcbNewSettings()->m_FlipDirection ); // Copy the models from the panel to the footprint std::vector& panelList = m_3dPanel->GetModelList(); @@ -686,8 +683,7 @@ void DIALOG_FOOTPRINT_PROPERTIES::OnAddField( wxCommandEvent& ) if( !m_itemsGrid->CommitPendingChanges() ) return; - PCB_FIELD newField( m_footprint, FIELD_T::USER, - GetUserFieldName( m_fields->GetNumberRows(), DO_TRANSLATE ) ); + PCB_FIELD newField( m_footprint, FIELD_T::USER, GetUserFieldName( m_fields->GetNumberRows(), DO_TRANSLATE ) ); newField.SetVisible( false ); newField.SetLayer( m_footprint->GetLayer() == F_Cu ? F_Fab : B_Fab ); @@ -713,48 +709,26 @@ void DIALOG_FOOTPRINT_PROPERTIES::OnAddField( wxCommandEvent& ) void DIALOG_FOOTPRINT_PROPERTIES::OnDeleteField( wxCommandEvent& ) { - if( !m_itemsGrid->CommitPendingChanges() ) - return; + m_itemsGrid->OnDeleteRows( + [&]( int row ) + { + if( row < m_fields->GetMandatoryRowCount() ) + { + DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), + m_fields->GetMandatoryRowCount() ) ); + return false; + } - wxArrayInt selectedRows = m_itemsGrid->GetSelectedRows(); + return true; + }, + [&]( int row ) + { + m_fields->erase( m_fields->begin() + row ); - if( selectedRows.empty() && m_itemsGrid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_itemsGrid->GetGridCursorRow() ); - - if( selectedRows.empty() ) - return; - - for( int row : selectedRows ) - { - - if( row < m_fields->GetMandatoryRowCount() ) - { - DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), - m_fields->GetMandatoryRowCount() ) ); - return; - } - } - - m_itemsGrid->CommitPendingChanges( true /* quiet mode */ ); - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } ); - - for( int row : selectedRows ) - { - m_itemsGrid->ClearSelection(); - m_fields->erase( m_fields->begin() + row ); - - // notify the grid - wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); - m_itemsGrid->ProcessTableMessage( msg ); - - if( m_itemsGrid->GetNumberRows() > 0 ) - { - m_itemsGrid->MakeCellVisible( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() ); - m_itemsGrid->SetGridCursor( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() ); - } - } + // notify the grid + wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); + m_itemsGrid->ProcessTableMessage( msg ); + } ); OnModify(); } @@ -775,8 +749,7 @@ void DIALOG_FOOTPRINT_PROPERTIES::adjustGridColumns() itemsWidth -= m_itemsGrid->GetColSize( i ); } - m_itemsGrid->SetColSize( - 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) ); + m_itemsGrid->SetColSize( 1, std::max( itemsWidth, m_itemsGrid->GetVisibleWidth( 0, true, false ) ) ); // Update the width of the 3D panel m_3dPanel->AdjustGridColumnWidths(); @@ -828,9 +801,9 @@ void DIALOG_FOOTPRINT_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& ) if( grid == m_itemsGrid && row == 0 && col == 0 ) { - auto referenceEditor = grid->GetCellEditor( 0, 0 ); + wxGridCellEditor* referenceEditor = grid->GetCellEditor( 0, 0 ); - if( auto textEntry = dynamic_cast( referenceEditor->GetControl() ) ) + if( wxTextEntry* textEntry = dynamic_cast( referenceEditor->GetControl() ) ) KIUI::SelectReferenceNumber( textEntry ); referenceEditor->DecRef(); diff --git a/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp b/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp index 7656f5860e..5bc1abb9aa 100644 --- a/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp +++ b/pcbnew/dialogs/dialog_footprint_properties_fp_editor.cpp @@ -88,8 +88,7 @@ bool PRIVATE_LAYERS_GRID_TABLE::CanSetValueAs( int aRow, int aCol, const wxStrin } -wxGridCellAttr* PRIVATE_LAYERS_GRID_TABLE::GetAttr( int aRow, int aCol, - wxGridCellAttr::wxAttrKind aKind ) +wxGridCellAttr* PRIVATE_LAYERS_GRID_TABLE::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind ) { m_layerColAttr->IncRef(); return enhanceAttr( m_layerColAttr, aRow, aCol, aKind ); @@ -283,8 +282,7 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::TransferDataToWindow() m_fields->push_back( *field ); // Notify the grid - wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, - m_fields->GetNumberRows() ); + wxGridTableMessage tmsg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_fields->GetNumberRows() ); m_itemsGrid->ProcessTableMessage( tmsg ); if( m_footprint->GetAttributes() & FP_THROUGH_HOLE ) @@ -513,8 +511,7 @@ bool DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::Validate() if( field.GetTextThickness() > maxPenWidth ) { - m_itemsGrid->SetCellValue( i, PFC_THICKNESS, - m_frame->StringFromValue( maxPenWidth, true ) ); + m_itemsGrid->SetCellValue( i, PFC_THICKNESS, m_frame->StringFromValue( maxPenWidth, true ) ); m_delayedFocusGrid = m_itemsGrid; m_delayedErrorMessage = _( "The text thickness is too large for the text size.\n" @@ -729,8 +726,7 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnAddField( wxCommandEvent& event ) const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings(); - PCB_FIELD newField( m_footprint, FIELD_T::USER, - GetUserFieldName( m_fields->GetNumberRows(), DO_TRANSLATE ) ); + PCB_FIELD newField( m_footprint, FIELD_T::USER, GetUserFieldName( m_fields->GetNumberRows(), DO_TRANSLATE ) ); // Set active layer if legal; otherwise copy layer from previous text item if( LSET::AllTechMask().test( m_frame->GetActiveLayer() ) ) @@ -761,50 +757,26 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnAddField( wxCommandEvent& event ) void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnDeleteField( wxCommandEvent& event ) { - if( !m_itemsGrid->CommitPendingChanges() ) - return; + m_itemsGrid->OnDeleteRows( + [&]( int row ) + { + if( row < m_fields->GetMandatoryRowCount() ) + { + DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), + m_fields->GetMandatoryRowCount() ) ); + return false; + } - wxArrayInt selectedRows = m_itemsGrid->GetSelectedRows(); + return true; + }, + [&]( int row ) + { + m_fields->erase( m_fields->begin() + row ); - if( selectedRows.empty() && m_itemsGrid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_itemsGrid->GetGridCursorRow() ); - - if( selectedRows.empty() ) - return; - - for( int row : selectedRows ) - { - if( row < m_fields->GetMandatoryRowCount() ) - { - DisplayError( this, wxString::Format( _( "The first %d fields are mandatory." ), - m_fields->GetMandatoryRowCount() ) ); - return; - } - } - - m_itemsGrid->CommitPendingChanges( true /* quiet mode */ ); - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( []( int* first, int* second ) - { - return *second - *first; - } ); - - for( int row : selectedRows ) - { - m_itemsGrid->ClearSelection(); - m_fields->erase( m_fields->begin() + row ); - - // notify the grid - wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); - m_itemsGrid->ProcessTableMessage( msg ); - - if( m_itemsGrid->GetNumberRows() > 0 ) - { - m_itemsGrid->MakeCellVisible( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() ); - m_itemsGrid->SetGridCursor( std::max( 0, row-1 ), m_itemsGrid->GetGridCursorCol() ); - } - } + // notify the grid + wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); + m_itemsGrid->ProcessTableMessage( msg ); + } ); OnModify(); } @@ -836,30 +808,17 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnAddLayer( wxCommandEvent& event ) void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::OnDeleteLayer( wxCommandEvent& event ) { - if( !m_privateLayersGrid->CommitPendingChanges() ) - return; + m_privateLayersGrid->OnDeleteRows( + [&]( int row ) + { + m_privateLayers->erase( m_privateLayers->begin() + row ); - int curRow = m_privateLayersGrid->GetGridCursorRow(); + // notify the grid + wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_DELETED, row, 1 ); + m_privateLayersGrid->ProcessTableMessage( msg ); - if( curRow < 0 ) - return; - - m_privateLayersGrid->ClearSelection(); - m_privateLayers->erase( m_privateLayers->begin() + curRow ); - - // notify the grid - wxGridTableMessage msg( m_privateLayers, wxGRIDTABLE_NOTIFY_ROWS_DELETED, curRow, 1 ); - m_privateLayersGrid->ProcessTableMessage( msg ); - - if( m_privateLayersGrid->GetNumberRows() > 0 ) - { - m_privateLayersGrid->MakeCellVisible( std::max( 0, curRow-1 ), - m_privateLayersGrid->GetGridCursorCol() ); - m_privateLayersGrid->SetGridCursor( std::max( 0, curRow-1 ), - m_privateLayersGrid->GetGridCursorCol() ); - } - - OnModify(); + OnModify(); + } ); } @@ -907,25 +866,11 @@ void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::onAddGroup( WX_GRID* aGrid ) void DIALOG_FOOTPRINT_PROPERTIES_FP_EDITOR::onRemoveGroup( WX_GRID* aGrid ) { - if( !aGrid->CommitPendingChanges() ) - return; - - wxArrayInt selectedRows = aGrid->GetSelectedRows(); - int curRow = aGrid->GetGridCursorRow(); - - if( selectedRows.empty() && curRow >= 0 && curRow < aGrid->GetNumberRows() ) - selectedRows.Add( curRow ); - - for( int ii = (int) selectedRows.Count() - 1; ii >= 0; --ii ) - { - int row = selectedRows.Item( ii ); - aGrid->DeleteRows( row, 1 ); - curRow = std::min( curRow, row ); - } - - curRow = std::max( 0, curRow - 1 ); - aGrid->MakeCellVisible( curRow, aGrid->GetGridCursorCol() ); - aGrid->SetGridCursor( curRow, aGrid->GetGridCursorCol() ); + aGrid->OnDeleteRows( + [&]( int row ) + { + aGrid->DeleteRows( row, 1 ); + } ); OnModify(); } diff --git a/pcbnew/dialogs/panel_display_options.cpp b/pcbnew/dialogs/panel_display_options.cpp index fbf62409dc..6ddd949a01 100644 --- a/pcbnew/dialogs/panel_display_options.cpp +++ b/pcbnew/dialogs/panel_display_options.cpp @@ -321,36 +321,11 @@ void PANEL_DISPLAY_OPTIONS::OnAddLayerItem( wxCommandEvent& event ) void PANEL_DISPLAY_OPTIONS::OnDeleteLayerItem( wxCommandEvent& event ) { - wxArrayInt selectedRows = m_layerNameitemsGrid->GetSelectedRows(); - - if( selectedRows.empty() && m_layerNameitemsGrid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_layerNameitemsGrid->GetGridCursorRow() ); - - if( selectedRows.empty() ) - return; - - if( !m_layerNameitemsGrid->CommitPendingChanges() ) - return; - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( - []( int* first, int* second ) + m_layerNameitemsGrid->OnDeleteRows( + [&]( int row ) { - return *second - *first; + m_layerNameitemsGrid->GetTable()->DeleteRows( row, 1 ); } ); - - for( int row : selectedRows ) - { - m_layerNameitemsGrid->GetTable()->DeleteRows( row, 1 ); - - if( m_layerNameitemsGrid->GetNumberRows() > 0 ) - { - m_layerNameitemsGrid->MakeCellVisible( std::max( 0, row - 1 ), - m_layerNameitemsGrid->GetGridCursorCol() ); - m_layerNameitemsGrid->SetGridCursor( std::max( 0, row - 1 ), - m_layerNameitemsGrid->GetGridCursorCol() ); - } - } } diff --git a/pcbnew/dialogs/panel_fp_editor_field_defaults.cpp b/pcbnew/dialogs/panel_fp_editor_field_defaults.cpp index 7667ef0350..960a8e63c5 100644 --- a/pcbnew/dialogs/panel_fp_editor_field_defaults.cpp +++ b/pcbnew/dialogs/panel_fp_editor_field_defaults.cpp @@ -340,36 +340,11 @@ void PANEL_FP_EDITOR_FIELD_DEFAULTS::OnAddTextItem( wxCommandEvent& event ) void PANEL_FP_EDITOR_FIELD_DEFAULTS::OnDeleteTextItem( wxCommandEvent& event ) { - wxArrayInt selectedRows = m_textItemsGrid->GetSelectedRows(); - - if( selectedRows.empty() && m_textItemsGrid->GetGridCursorRow() >= 0 ) - selectedRows.push_back( m_textItemsGrid->GetGridCursorRow() ); - - if( selectedRows.empty() ) - return; - - if( !m_textItemsGrid->CommitPendingChanges() ) - return; - - // Reverse sort so deleting a row doesn't change the indexes of the other rows. - selectedRows.Sort( - []( int* first, int* second ) + m_textItemsGrid->OnDeleteRows( + [&]( int row ) { - return *second - *first; + m_textItemsGrid->GetTable()->DeleteRows( row, 1 ); } ); - - for( int row : selectedRows ) - { - m_textItemsGrid->GetTable()->DeleteRows( row, 1 ); - - if( m_textItemsGrid->GetNumberRows() > 0 ) - { - m_textItemsGrid->MakeCellVisible( std::max( 0, row - 1 ), - m_textItemsGrid->GetGridCursorCol() ); - m_textItemsGrid->SetGridCursor( std::max( 0, row - 1 ), - m_textItemsGrid->GetGridCursorCol() ); - } - } } diff --git a/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp b/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp index 73485aaeb8..1f03be9dd4 100644 --- a/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp +++ b/pcbnew/dialogs/panel_setup_tracks_and_vias.cpp @@ -437,22 +437,11 @@ void PANEL_SETUP_TRACKS_AND_VIAS::AppendDiffPairs( int aWidth, int aGap, int aVi void removeSelectedRows( WX_GRID* aGrid ) { - wxArrayInt selectedRows = aGrid->GetSelectedRows(); - int curRow = aGrid->GetGridCursorRow(); - - if( selectedRows.empty() && curRow >= 0 && curRow < aGrid->GetNumberRows() ) - selectedRows.Add( curRow ); - - for( int ii = (int) selectedRows.Count() - 1; ii >= 0; --ii ) - { - int row = selectedRows.Item( ii ); - aGrid->DeleteRows( row, 1 ); - curRow = std::min( curRow, row ); - } - - curRow = std::max( 0, curRow - 1 ); - aGrid->MakeCellVisible( curRow, aGrid->GetGridCursorCol() ); - aGrid->SetGridCursor( curRow, aGrid->GetGridCursorCol() ); + aGrid->OnDeleteRows( + [&]( int row ) + { + aGrid->DeleteRows( row, 1 ); + } ); } @@ -477,13 +466,6 @@ void PANEL_SETUP_TRACKS_AND_VIAS::OnAddTrackWidthsClick( wxCommandEvent& aEvent void PANEL_SETUP_TRACKS_AND_VIAS::OnRemoveTrackWidthsClick( wxCommandEvent& event ) { - if( !m_trackWidthsGrid->CommitPendingChanges() - || !m_viaSizesGrid->CommitPendingChanges() - || !m_diffPairsGrid->CommitPendingChanges() ) - { - return; - } - removeSelectedRows( m_trackWidthsGrid ); } @@ -509,13 +491,6 @@ void PANEL_SETUP_TRACKS_AND_VIAS::OnAddViaSizesClick( wxCommandEvent& event ) void PANEL_SETUP_TRACKS_AND_VIAS::OnRemoveViaSizesClick( wxCommandEvent& event ) { - if( !m_trackWidthsGrid->CommitPendingChanges() - || !m_viaSizesGrid->CommitPendingChanges() - || !m_diffPairsGrid->CommitPendingChanges() ) - { - return; - } - removeSelectedRows( m_viaSizesGrid ); } @@ -541,13 +516,6 @@ void PANEL_SETUP_TRACKS_AND_VIAS::OnAddDiffPairsClick( wxCommandEvent& event ) void PANEL_SETUP_TRACKS_AND_VIAS::OnRemoveDiffPairsClick( wxCommandEvent& event ) { - if( !m_trackWidthsGrid->CommitPendingChanges() - || !m_viaSizesGrid->CommitPendingChanges() - || !m_diffPairsGrid->CommitPendingChanges() ) - { - return; - } - removeSelectedRows( m_diffPairsGrid ); } diff --git a/pcbnew/sel_layer.cpp b/pcbnew/sel_layer.cpp index 7d8b469b2f..bc3e0b38ca 100644 --- a/pcbnew/sel_layer.cpp +++ b/pcbnew/sel_layer.cpp @@ -395,15 +395,14 @@ public: void OnDeleteSelectedLayerPairs() { - int row = m_grid.GetGridCursorRow(); + m_grid.OnDeleteRows( + [&]( int row ) + { + const LAYER_PAIR_INFO& layerPairInfo = m_layerPairSettings.GetLayerPairs()[row]; - const LAYER_PAIR_INFO& layerPairInfo = m_layerPairSettings.GetLayerPairs()[row]; - const bool removed = m_layerPairSettings.RemoveLayerPair( layerPairInfo.GetLayerPair() ); - - if( removed ) - { - m_grid.DeleteRows( row ); - } + if( m_layerPairSettings.RemoveLayerPair( layerPairInfo.GetLayerPair() ) ) + m_grid.DeleteRows( row ); + } ); } private: