Maintain selection when sorting.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/17983
This commit is contained in:
Jeff Young 2024-05-11 16:20:09 +01:00
parent 5ba4900170
commit d9ff3c4485
7 changed files with 62 additions and 11 deletions

View File

@ -23,6 +23,7 @@
#include <vector> #include <vector>
#include <string_utils.h> #include <string_utils.h>
#include <wx/clipbrd.h> #include <wx/clipbrd.h>
#include <core/kicad_algo.h>
SEARCH_PANE_LISTVIEW::SEARCH_PANE_LISTVIEW( SEARCH_HANDLER* handler, wxWindow* parent, SEARCH_PANE_LISTVIEW::SEARCH_PANE_LISTVIEW( SEARCH_HANDLER* handler, wxWindow* parent,
wxWindowID winid, const wxPoint& pos, wxWindowID winid, const wxPoint& pos,
@ -134,7 +135,16 @@ void SEARCH_PANE_LISTVIEW::OnColClicked( wxListEvent& aEvent )
ShowSortIndicator( m_sortCol, m_sortAscending ); ShowSortIndicator( m_sortCol, m_sortAscending );
Sort(); std::vector<long> selection = Sort();
for( long row = 0; row < GetItemCount(); row++ )
{
if( alg::contains( selection, row ) )
SetItemState( row, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
else
SetItemState( row, 0, wxLIST_STATE_SELECTED );
}
Refresh(); Refresh();
} }
@ -177,9 +187,14 @@ void SEARCH_PANE_LISTVIEW::OnChar( wxKeyEvent& aEvent )
} }
void SEARCH_PANE_LISTVIEW::Sort() std::vector<long> SEARCH_PANE_LISTVIEW::Sort()
{ {
m_handler->Sort( m_sortCol, m_sortAscending ); std::vector<long> selection;
GetSelectRowsList( selection );
m_handler->Sort( m_sortCol, m_sortAscending, &selection );
return selection;
} }

View File

@ -65,8 +65,16 @@ void SCH_SEARCH_HANDLER::FindAll( const std::function<bool( SCH_ITEM*, SCH_SHEET
} }
void SCH_SEARCH_HANDLER::Sort( int aCol, bool aAscending ) void SCH_SEARCH_HANDLER::Sort( int aCol, bool aAscending, std::vector<long>* aSelection )
{ {
std::vector<SCH_ITEM*> selection;
for( long i = 0; i < (long) m_hitlist.size(); ++i )
{
if( alg::contains( *aSelection, i ) )
selection.push_back( m_hitlist[i].item );
}
int col = std::max( 0, aCol ); // Provide a stable order by sorting on first column if no int col = std::max( 0, aCol ); // Provide a stable order by sorting on first column if no
// sort column provided. // sort column provided.
@ -80,6 +88,14 @@ void SCH_SEARCH_HANDLER::Sort( int aCol, bool aAscending )
else else
return StrNumCmp( getResultCell( b, col ), getResultCell( a, col ), true ) < 0; return StrNumCmp( getResultCell( b, col ), getResultCell( a, col ), true ) < 0;
} ); } );
aSelection->clear();
for( long i = 0; i < (long) m_hitlist.size(); ++i )
{
if( alg::contains( selection, m_hitlist[i].item ) )
aSelection->push_back( i );
}
} }

View File

@ -60,7 +60,7 @@ public:
} }
void FindAll( const std::function<bool( SCH_ITEM*, SCH_SHEET_PATH* )>& aCollector ); void FindAll( const std::function<bool( SCH_ITEM*, SCH_SHEET_PATH* )>& aCollector );
void Sort( int aCol, bool aAscending ) override; void Sort( int aCol, bool aAscending, std::vector<long>* aSelection ) override;
void SelectItems( std::vector<long>& aItemRows ) override; void SelectItems( std::vector<long>& aItemRows ) override;
protected: protected:

View File

@ -43,7 +43,7 @@ public:
virtual int Search( const wxString& string ) = 0; virtual int Search( const wxString& string ) = 0;
virtual wxString GetResultCell( int row, int col ) = 0; virtual wxString GetResultCell( int row, int col ) = 0;
virtual void Sort( int aCol, bool aAscending ) = 0; virtual void Sort( int aCol, bool aAscending, std::vector<long>* aSelection ) = 0;
virtual void SelectItems( std::vector<long>& aItemRows ) {} virtual void SelectItems( std::vector<long>& aItemRows ) {}
virtual void ActivateItem( long aItemRow ) {} virtual void ActivateItem( long aItemRow ) {}

View File

@ -40,7 +40,7 @@ public:
void RefreshColumnNames(); void RefreshColumnNames();
void Sort(); std::vector<long> Sort();
protected: protected:
wxString OnGetItemText( long item, long column ) const override; wxString OnGetItemText( long item, long column ) const override;

View File

@ -42,18 +42,38 @@ void PCB_SEARCH_HANDLER::ActivateItem( long aItemRow )
} }
void PCB_SEARCH_HANDLER::Sort( int aCol, bool aAscending ) void PCB_SEARCH_HANDLER::Sort( int aCol, bool aAscending, std::vector<long>* aSelection )
{ {
std::vector<BOARD_ITEM*> selection;
for( long i = 0; i < (long) m_hitlist.size(); ++i )
{
if( alg::contains( *aSelection, i ) )
selection.push_back( m_hitlist[i] );
}
int col = std::max( 0, aCol ); // Provide a stable order by sorting on first column if no
// sort column provided.
std::sort( m_hitlist.begin(), m_hitlist.end(), std::sort( m_hitlist.begin(), m_hitlist.end(),
[&]( BOARD_ITEM* a, BOARD_ITEM* b ) -> bool [&]( BOARD_ITEM* a, BOARD_ITEM* b ) -> bool
{ {
// N.B. To meet the iterator sort conditions, we cannot simply invert the truth // N.B. To meet the iterator sort conditions, we cannot simply invert the truth
// to get the opposite sort. i.e. ~(a<b) != (a>b) // to get the opposite sort. i.e. ~(a<b) != (a>b)
if( aAscending ) if( aAscending )
return StrNumCmp( getResultCell( a, aCol ), getResultCell( b, aCol ), true ) < 0; return StrNumCmp( getResultCell( a, col ), getResultCell( b, col ), true ) < 0;
else else
return StrNumCmp( getResultCell( b, aCol ), getResultCell( a, aCol ), true ) < 0; return StrNumCmp( getResultCell( b, col ), getResultCell( a, col ), true ) < 0;
} ); } );
aSelection->clear();
for( long i = 0; i < (long) m_hitlist.size(); ++i )
{
if( alg::contains( selection, m_hitlist[i] ) )
aSelection->push_back( i );
}
} }

View File

@ -50,7 +50,7 @@ public:
return getResultCell( item, aCol ); return getResultCell( item, aCol );
} }
void Sort( int aCol, bool aAscending ) override; void Sort( int aCol, bool aAscending, std::vector<long>* aSelection ) override;
void SelectItems( std::vector<long>& aItemRows ) override; void SelectItems( std::vector<long>& aItemRows ) override;
void ActivateItem( long aItemRow ) override; void ActivateItem( long aItemRow ) override;