Select best-matching component when filtering.

This also fixes the old bug of scrolling to the selected best
match.

Fixes: lp:1774110
* https://bugs.launchpad.net/kicad/+bug/1774110

Fixes: lp:1744703
* https://bugs.launchpad.net/kicad/+bug/1744703
This commit is contained in:
Jeff Young 2018-06-10 23:20:06 +01:00
parent 0e3be5776c
commit 9edfd25b95
3 changed files with 67 additions and 44 deletions

View File

@ -193,7 +193,20 @@ void CMP_TREE_MODEL_ADAPTER_BASE::UpdateSearchString( wxString const& aSearch )
#endif #endif
} }
ShowResults() || ShowPreselect() || ShowSingleLibrary(); CMP_TREE_NODE* bestMatch = ShowResults();
if( !bestMatch )
bestMatch = ShowPreselect();
if( !bestMatch )
bestMatch = ShowSingleLibrary();
if( bestMatch )
{
auto item = wxDataViewItem( bestMatch );
m_widget->Select( item );
m_widget->EnsureVisible( item );
}
} }
@ -442,47 +455,51 @@ int CMP_TREE_MODEL_ADAPTER_BASE::WidthFor( wxString const& aHeading, int aCol )
} }
bool CMP_TREE_MODEL_ADAPTER_BASE::FindAndExpand( void CMP_TREE_MODEL_ADAPTER_BASE::FindAndExpand( CMP_TREE_NODE& aNode,
CMP_TREE_NODE& aNode, std::function<bool( CMP_TREE_NODE const* )> aFunc,
std::function<bool( CMP_TREE_NODE const* )> aFunc ) CMP_TREE_NODE** aHighScore )
{ {
for( auto& node: aNode.Children ) for( auto& node: aNode.Children )
{ {
if( aFunc( &*node ) ) if( aFunc( &*node ) )
{ {
auto item = wxDataViewItem( auto item = wxDataViewItem( &*node );
const_cast<void*>( static_cast<void const*>( &*node ) ) );
m_widget->ExpandAncestors( item ); m_widget->ExpandAncestors( item );
m_widget->EnsureVisible( item );
m_widget->Select( item ); if( !(*aHighScore) || node->Score > (*aHighScore)->Score )
return true; (*aHighScore) = &*node;
} }
else if( FindAndExpand( *node, aFunc ) ) else
{ {
return true; FindAndExpand( *node, aFunc, aHighScore );
} }
} }
return false;
} }
bool CMP_TREE_MODEL_ADAPTER_BASE::ShowResults() CMP_TREE_NODE* CMP_TREE_MODEL_ADAPTER_BASE::ShowResults()
{ {
return FindAndExpand( m_tree, CMP_TREE_NODE* highScore = nullptr;
[]( CMP_TREE_NODE const* n )
{ FindAndExpand( m_tree,
return n->Type == CMP_TREE_NODE::TYPE::LIBID && n->Score > 1; []( CMP_TREE_NODE const* n )
} ); {
return n->Type == CMP_TREE_NODE::TYPE::LIBID && n->Score > 1;
},
&highScore );
return highScore;
} }
bool CMP_TREE_MODEL_ADAPTER_BASE::ShowPreselect() CMP_TREE_NODE* CMP_TREE_MODEL_ADAPTER_BASE::ShowPreselect()
{ {
CMP_TREE_NODE* highScore = nullptr;
if( !m_preselect_lib_id.IsValid() ) if( !m_preselect_lib_id.IsValid() )
return false; return highScore;
return FindAndExpand( m_tree, FindAndExpand( m_tree,
[&]( CMP_TREE_NODE const* n ) [&]( CMP_TREE_NODE const* n )
{ {
if( n->Type == CMP_TREE_NODE::LIBID && ( n->Children.empty() || !m_preselect_unit ) ) if( n->Type == CMP_TREE_NODE::LIBID && ( n->Children.empty() || !m_preselect_unit ) )
@ -491,16 +508,24 @@ bool CMP_TREE_MODEL_ADAPTER_BASE::ShowPreselect()
return m_preselect_lib_id == n->Parent->LibId && m_preselect_unit == n->Unit; return m_preselect_lib_id == n->Parent->LibId && m_preselect_unit == n->Unit;
else else
return false; return false;
} ); },
&highScore );
return highScore;
} }
bool CMP_TREE_MODEL_ADAPTER_BASE::ShowSingleLibrary() CMP_TREE_NODE* CMP_TREE_MODEL_ADAPTER_BASE::ShowSingleLibrary()
{ {
return FindAndExpand( m_tree, CMP_TREE_NODE* highScore = nullptr;
[]( CMP_TREE_NODE const* n )
{ FindAndExpand( m_tree,
return n->Type == CMP_TREE_NODE::TYPE::LIBID && []( CMP_TREE_NODE const* n )
n->Parent->Parent->Children.size() == 1; {
} ); return n->Type == CMP_TREE_NODE::TYPE::LIBID &&
n->Parent->Parent->Children.size() == 1;
},
&highScore );
return highScore;
} }

View File

@ -389,27 +389,26 @@ private:
/** /**
* Find any results worth highlighting and expand them, according to given * Find any results worth highlighting and expand them, according to given
* criteria (f(CMP_TREE_NODE const*) -> bool) * criteria (f(CMP_TREE_NODE const*) -> bool)
* * The highest-scoring node is written to aHighScore
* @return whether a node was expanded
*/ */
bool FindAndExpand( void FindAndExpand( CMP_TREE_NODE& aNode,
CMP_TREE_NODE& aNode, std::function<bool( CMP_TREE_NODE const* )> aFunc,
std::function<bool( CMP_TREE_NODE const* )> aFunc ); CMP_TREE_NODE** aHighScore );
/** /**
* Find and expand successful search results * Find and expand successful search results. Return the best match (if any).
*/ */
bool ShowResults(); CMP_TREE_NODE* ShowResults();
/** /**
* Find and expand preselected node * Find and expand preselected node. Return the best match (if any).
*/ */
bool ShowPreselect(); CMP_TREE_NODE* ShowPreselect();
/** /**
* Find and expand a library if there is only one * Find and expand a library if there is only one. Return the best match (if any).
*/ */
bool ShowSingleLibrary(); CMP_TREE_NODE* ShowSingleLibrary();
}; };
#endif // _CMP_TREE_MODEL_ADAPTER_BASE_H #endif // _CMP_TREE_MODEL_ADAPTER_BASE_H

View File

@ -169,8 +169,6 @@ void COMPONENT_TREE::Regenerate()
// Store the state // Store the state
if( !m_filtering ) if( !m_filtering )
m_unfilteredState = getState(); m_unfilteredState = getState();
else
current = getState();
wxString filter = m_query_ctrl->GetValue(); wxString filter = m_query_ctrl->GetValue();
m_adapter->UpdateSearchString( filter ); m_adapter->UpdateSearchString( filter );
@ -178,7 +176,8 @@ void COMPONENT_TREE::Regenerate()
postPreselectEvent(); postPreselectEvent();
// Restore the state // Restore the state
setState( m_filtering ? current : m_unfilteredState ); if( !m_filtering )
setState( m_unfilteredState );
} }