Restoring the previous performance of COMPONENT_TREE widget
It turns out the fastest way to update wxDataViewCtrl is to nuke the model and rebuild it from scratch rather than via ItemAdded()/ItemDeleted() update notifications. Fixes: lp:1734773 * https://bugs.launchpad.net/kicad/+bug/1734773
This commit is contained in:
parent
a240f88785
commit
45bf919923
|
@ -105,7 +105,6 @@ int CMP_TREE_NODE::Compare( CMP_TREE_NODE const& aNode1, CMP_TREE_NODE const& aN
|
|||
CMP_TREE_NODE::CMP_TREE_NODE()
|
||||
: Parent( nullptr ),
|
||||
Type( INVALID ),
|
||||
InTree( false ),
|
||||
IntrinsicRank( 0 ),
|
||||
Score( kLowestDefaultScore ),
|
||||
Unit( 0 )
|
||||
|
@ -178,7 +177,6 @@ CMP_TREE_NODE_LIB_ID::CMP_TREE_NODE_LIB_ID( CMP_TREE_NODE* aParent, LIB_ALIAS* a
|
|||
CMP_TREE_NODE_UNIT& CMP_TREE_NODE_LIB_ID::AddUnit( int aUnit )
|
||||
{
|
||||
CMP_TREE_NODE_UNIT* unit = new CMP_TREE_NODE_UNIT( this, aUnit );
|
||||
unit->InTree = true;
|
||||
Children.push_back( std::unique_ptr<CMP_TREE_NODE>( unit ) );
|
||||
return *unit;
|
||||
}
|
||||
|
@ -245,7 +243,6 @@ CMP_TREE_NODE_LIB::CMP_TREE_NODE_LIB( CMP_TREE_NODE* aParent, wxString const& aN
|
|||
CMP_TREE_NODE_LIB_ID& CMP_TREE_NODE_LIB::AddAlias( LIB_ALIAS* aAlias )
|
||||
{
|
||||
CMP_TREE_NODE_LIB_ID* alias = new CMP_TREE_NODE_LIB_ID( this, aAlias );
|
||||
alias->InTree = true;
|
||||
Children.push_back( std::unique_ptr<CMP_TREE_NODE>( alias ) );
|
||||
return *alias;
|
||||
}
|
||||
|
@ -272,7 +269,6 @@ CMP_TREE_NODE_ROOT::CMP_TREE_NODE_ROOT()
|
|||
CMP_TREE_NODE_LIB& CMP_TREE_NODE_ROOT::AddLib( wxString const& aName )
|
||||
{
|
||||
CMP_TREE_NODE_LIB* lib = new CMP_TREE_NODE_LIB( this, aName );
|
||||
lib->InTree = true;
|
||||
Children.push_back( std::unique_ptr<CMP_TREE_NODE>( lib ) );
|
||||
return *lib;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,6 @@ public:
|
|||
CMP_TREE_NODE* Parent; ///< Parent node or null
|
||||
PTR_VECTOR Children; ///< List of child nodes
|
||||
enum TYPE Type; ///< Node type
|
||||
bool InTree; ///< Flag indicating whether the node is added to the tree
|
||||
|
||||
/**
|
||||
* The rank of the item before any search terms are applied. This is
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
|
||||
CMP_TREE_MODEL_ADAPTER_BASE::WIDTH_CACHE CMP_TREE_MODEL_ADAPTER_BASE::m_width_cache;
|
||||
|
@ -61,7 +62,7 @@ unsigned int CMP_TREE_MODEL_ADAPTER_BASE::IntoArray(
|
|||
|
||||
for( auto const& child: aNode.Children )
|
||||
{
|
||||
if( child->Score > 0 && child->InTree )
|
||||
if( child->Score > 0 )
|
||||
{
|
||||
aChildren.Add( ToItem( &*child ) );
|
||||
++n;
|
||||
|
@ -144,7 +145,7 @@ void CMP_TREE_MODEL_ADAPTER_BASE::AddAliasList(
|
|||
|
||||
void CMP_TREE_MODEL_ADAPTER_BASE::UpdateSearchString( wxString const& aSearch )
|
||||
{
|
||||
m_widget->Freeze();
|
||||
wxWindowUpdateLocker updateLock( m_widget );
|
||||
m_tree.ResetScore();
|
||||
|
||||
wxStringTokenizer tokenizer( aSearch );
|
||||
|
@ -157,16 +158,23 @@ void CMP_TREE_MODEL_ADAPTER_BASE::UpdateSearchString( wxString const& aSearch )
|
|||
m_tree.UpdateScore( matcher );
|
||||
}
|
||||
|
||||
filterContents();
|
||||
m_tree.SortNodes();
|
||||
Cleared();
|
||||
#ifndef __WINDOWS__
|
||||
// The fastest method to update wxDataViewCtrl is to rebuild from scratch by calling Cleared().
|
||||
// Linux requires to reassociate model to display data, but Windows will create multiple
|
||||
// associations.
|
||||
AttachTo( m_widget );
|
||||
#endif
|
||||
|
||||
ShowResults() || ShowPreselect() || ShowSingleLibrary();
|
||||
m_widget->Thaw();
|
||||
}
|
||||
|
||||
|
||||
void CMP_TREE_MODEL_ADAPTER_BASE::AttachTo( wxDataViewCtrl* aDataViewCtrl )
|
||||
{
|
||||
wxWindowUpdateLocker updateLock( aDataViewCtrl );
|
||||
m_widget = aDataViewCtrl;
|
||||
aDataViewCtrl->Freeze();
|
||||
aDataViewCtrl->SetIndent( kDataViewIndent );
|
||||
aDataViewCtrl->AssociateModel( this );
|
||||
aDataViewCtrl->ClearColumns();
|
||||
|
@ -179,7 +187,6 @@ void CMP_TREE_MODEL_ADAPTER_BASE::AttachTo( wxDataViewCtrl* aDataViewCtrl )
|
|||
m_col_desc = aDataViewCtrl->AppendTextColumn( desc_head, 1, wxDATAVIEW_CELL_INERT,
|
||||
ColWidth( m_tree, 1, desc_head ) );
|
||||
m_col_part->SetSortOrder( 0 );
|
||||
aDataViewCtrl->Thaw();
|
||||
}
|
||||
|
||||
|
||||
|
@ -464,53 +471,3 @@ bool CMP_TREE_MODEL_ADAPTER_BASE::ShowSingleLibrary()
|
|||
n->Parent->Parent->Children.size() == 1;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
void CMP_TREE_MODEL_ADAPTER_BASE::filterContents()
|
||||
{
|
||||
// Rebuild the tree using only the filtered nodes
|
||||
for( auto& lib : m_tree.Children )
|
||||
{
|
||||
lib->InTree = false;
|
||||
|
||||
for( auto& alias : lib->Children )
|
||||
{
|
||||
alias->InTree = false;
|
||||
|
||||
for( auto& unit : lib->Children )
|
||||
unit->InTree = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_tree.SortNodes();
|
||||
Cleared();
|
||||
|
||||
for( auto& lib : m_tree.Children )
|
||||
{
|
||||
if( lib->Score <= 0 )
|
||||
continue;
|
||||
|
||||
wxDataViewItem libItem = ToItem( lib.get() );
|
||||
lib->InTree = true;
|
||||
ItemAdded( wxDataViewItem( nullptr ), libItem );
|
||||
|
||||
for( auto& alias : lib->Children )
|
||||
{
|
||||
if( alias->Score > 0 )
|
||||
{
|
||||
alias->InTree = true;
|
||||
wxDataViewItem aliasItem = ToItem( alias.get() );
|
||||
ItemAdded( libItem, aliasItem );
|
||||
|
||||
if( !m_show_units )
|
||||
continue;
|
||||
|
||||
for( auto& unit : alias->Children )
|
||||
{
|
||||
unit->InTree = true;
|
||||
ItemAdded( aliasItem, ToItem( unit.get() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -395,11 +395,6 @@ private:
|
|||
* Find and expand a library if there is only one
|
||||
*/
|
||||
bool ShowSingleLibrary();
|
||||
|
||||
/**
|
||||
* Filters the items shown in the view according to the score.
|
||||
*/
|
||||
void filterContents();
|
||||
};
|
||||
|
||||
#endif // _CMP_TREE_MODEL_ADAPTER_BASE_H
|
||||
|
|
|
@ -358,7 +358,7 @@ bool LIB_MANAGER::UpdatePart( LIB_PART* aPart, const wxString& aLibrary, wxStrin
|
|||
screen->SetModify();
|
||||
}
|
||||
|
||||
getAdapter()->UpdateLibrary( aLibrary );
|
||||
m_frame.SyncLibraries( false );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ bool LIB_MANAGER::RevertLibrary( const wxString& aLibrary )
|
|||
return false;
|
||||
|
||||
m_libs.erase( it );
|
||||
getAdapter()->UpdateLibrary( aLibrary );
|
||||
m_frame.SyncLibraries( false );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -414,7 +414,7 @@ bool LIB_MANAGER::RemovePart( const wxString& aAlias, const wxString& aLibrary )
|
|||
wxCHECK( partBuf, false );
|
||||
|
||||
bool res = libBuf.DeleteBuffer( partBuf );
|
||||
getAdapter()->UpdateLibrary( aLibrary );
|
||||
m_frame.SyncLibraries( false );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -549,7 +549,7 @@ bool LIB_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate, SYMBOL_LI
|
|||
aTable->CreateSymbolLib( libName );
|
||||
}
|
||||
|
||||
getAdapter()->AddLibrary( libName );
|
||||
m_frame.SyncLibraries( false );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -37,32 +37,6 @@ CMP_TREE_MODEL_ADAPTER_BASE::PTR LIB_MANAGER_ADAPTER::Create( LIB_MANAGER* aLibM
|
|||
|
||||
void LIB_MANAGER_ADAPTER::AddLibrary( const wxString& aLibNickname )
|
||||
{
|
||||
auto& lib_node = m_tree.AddLib( aLibNickname );
|
||||
ItemAdded( wxDataViewItem( nullptr ), ToItem( &lib_node ) );
|
||||
updateLibrary( lib_node );
|
||||
finishUpdate();
|
||||
}
|
||||
|
||||
|
||||
void LIB_MANAGER_ADAPTER::RemoveLibrary( const wxString& aLibNickname )
|
||||
{
|
||||
auto it = std::find_if( m_tree.Children.begin(), m_tree.Children.end(),
|
||||
[&] ( std::unique_ptr<CMP_TREE_NODE>& node ) { return node->Name == aLibNickname; } );
|
||||
|
||||
if( it != m_tree.Children.end() )
|
||||
deleteLibrary( it );
|
||||
}
|
||||
|
||||
|
||||
void LIB_MANAGER_ADAPTER::UpdateLibrary( const wxString& aLibraryName )
|
||||
{
|
||||
CMP_TREE_NODE* node = findLibrary( aLibraryName );
|
||||
|
||||
if( !node )
|
||||
return;
|
||||
|
||||
updateLibrary( *(CMP_TREE_NODE_LIB*) node );
|
||||
finishUpdate();
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,7 +89,9 @@ void LIB_MANAGER_ADAPTER::Sync( bool aForce, std::function<void(int, int, const
|
|||
if( m_libHashes.count( libName ) == 0 )
|
||||
{
|
||||
aProgressCallback( i++, max, libName );
|
||||
AddLibrary( libName );
|
||||
auto& lib_node = m_tree.AddLib( libName );
|
||||
updateLibrary( lib_node );
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,22 +116,15 @@ void LIB_MANAGER_ADAPTER::updateLibrary( CMP_TREE_NODE_LIB& aLibNode )
|
|||
if( m_libHashes.count( aLibNode.Name ) == 0 )
|
||||
{
|
||||
// add a new library
|
||||
wxDataViewItem parent = ToItem( &aLibNode );
|
||||
|
||||
for( auto alias : m_libMgr->GetAliases( aLibNode.Name ) )
|
||||
{
|
||||
auto& aliasNode = aLibNode.AddAlias( alias );
|
||||
ItemAdded( parent, ToItem( &aliasNode ) );
|
||||
}
|
||||
aLibNode.AddAlias( alias );
|
||||
}
|
||||
else
|
||||
{
|
||||
// update an existing libary
|
||||
std::list<LIB_ALIAS*> aliases = m_libMgr->GetAliases( aLibNode.Name );
|
||||
wxDataViewItem parent = ToItem( &aLibNode );
|
||||
|
||||
// remove the common part from the aliases list
|
||||
//for( const auto& node : aLibNode.Children )
|
||||
for( auto nodeIt = aLibNode.Children.begin(); nodeIt != aLibNode.Children.end(); /**/ )
|
||||
{
|
||||
auto aliasIt = std::find_if( aliases.begin(), aliases.end(),
|
||||
|
@ -173,17 +142,13 @@ void LIB_MANAGER_ADAPTER::updateLibrary( CMP_TREE_NODE_LIB& aLibNode )
|
|||
else
|
||||
{
|
||||
// node does not exist in the library manager, remove the corresponding node
|
||||
ItemDeleted( parent, ToItem( nodeIt->get() ) );
|
||||
nodeIt = aLibNode.Children.erase( nodeIt );
|
||||
}
|
||||
}
|
||||
|
||||
// now the aliases list contains only new aliases that need to be added to the tree
|
||||
for( auto alias : aliases )
|
||||
{
|
||||
auto& aliasNode = aLibNode.AddAlias( alias );
|
||||
ItemAdded( parent, ToItem( &aliasNode ) );
|
||||
}
|
||||
aLibNode.AddAlias( alias );
|
||||
}
|
||||
|
||||
aLibNode.AssignIntrinsicRanks();
|
||||
|
@ -195,19 +160,12 @@ CMP_TREE_NODE::PTR_VECTOR::iterator LIB_MANAGER_ADAPTER::deleteLibrary(
|
|||
CMP_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt )
|
||||
{
|
||||
CMP_TREE_NODE* node = aLibNodeIt->get();
|
||||
ItemDeleted( wxDataViewItem( nullptr ), ToItem( node ) );
|
||||
m_libHashes.erase( node->Name );
|
||||
auto it = m_tree.Children.erase( aLibNodeIt );
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
void LIB_MANAGER_ADAPTER::finishUpdate()
|
||||
{
|
||||
m_tree.AssignIntrinsicRanks();
|
||||
}
|
||||
|
||||
|
||||
CMP_TREE_NODE* LIB_MANAGER_ADAPTER::findLibrary( const wxString& aLibNickName )
|
||||
{
|
||||
for( auto& lib : m_tree.Children )
|
||||
|
|
|
@ -37,14 +37,10 @@ public:
|
|||
|
||||
void AddLibrary( const wxString& aLibNickname ) override;
|
||||
|
||||
void RemoveLibrary( const wxString& aLibNickname );
|
||||
|
||||
void AddAliasList( const wxString& aNodeName, const wxArrayString& aAliasNameList ) override;
|
||||
|
||||
bool IsContainer( const wxDataViewItem& aItem ) const override;
|
||||
|
||||
void UpdateLibrary( const wxString& aLibraryName );
|
||||
|
||||
void Sync( bool aForce = false, std::function<void(int, int, const wxString&)> aProgressCallback
|
||||
= [](int, int, const wxString&){} );
|
||||
|
||||
|
@ -56,8 +52,6 @@ protected:
|
|||
CMP_TREE_NODE::PTR_VECTOR::iterator deleteLibrary(
|
||||
CMP_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt );
|
||||
|
||||
void finishUpdate();
|
||||
|
||||
CMP_TREE_NODE* findLibrary( const wxString& aLibNickName );
|
||||
|
||||
bool GetAttr( wxDataViewItem const& aItem, unsigned int aCol,
|
||||
|
|
|
@ -253,7 +253,7 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
|||
m_canvas->SetEnableBlockCommands( true );
|
||||
|
||||
m_libMgr = new LIB_MANAGER( *this );
|
||||
SyncLibraries();
|
||||
SyncLibraries( true );
|
||||
m_treePane = new CMP_TREE_PANE( this, m_libMgr );
|
||||
|
||||
ReCreateMenuBar();
|
||||
|
@ -485,7 +485,7 @@ void LIB_EDIT_FRAME::OnToggleSearchTree( wxCommandEvent& event )
|
|||
void LIB_EDIT_FRAME::OnEditSymbolLibTable( wxCommandEvent& aEvent )
|
||||
{
|
||||
SCH_BASE_FRAME::OnEditSymbolLibTable( aEvent );
|
||||
SyncLibraries();
|
||||
SyncLibraries( true );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1614,23 +1614,24 @@ wxString LIB_EDIT_FRAME::getTargetLib() const
|
|||
}
|
||||
|
||||
|
||||
void LIB_EDIT_FRAME::SyncLibraries()
|
||||
void LIB_EDIT_FRAME::SyncLibraries( bool aProgress )
|
||||
{
|
||||
auto tree = m_treePane ? m_treePane->GetCmpTree() : nullptr;
|
||||
wxBusyCursor cursor;
|
||||
if( aProgress )
|
||||
{
|
||||
wxProgressDialog progressDlg( _( "Loading symbol libraries" ),
|
||||
wxEmptyString, m_libMgr->GetAdapter()->GetLibrariesCount(), this );
|
||||
|
||||
if( tree )
|
||||
tree->Freeze();
|
||||
m_libMgr->Sync( true, [&]( int progress, int max, const wxString& libName ) {
|
||||
progressDlg.Update( progress, wxString::Format( _( "Loading library '%s'" ), libName ) );
|
||||
} );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_libMgr->Sync( true );
|
||||
}
|
||||
|
||||
wxProgressDialog progressDlg( _( "Loading symbol libraries" ),
|
||||
wxEmptyString, m_libMgr->GetAdapter()->GetLibrariesCount(), this );
|
||||
|
||||
m_libMgr->Sync( true, [&]( int progress, int max, const wxString& libName ) {
|
||||
progressDlg.Update( progress, wxString::Format( _( "Loading library '%s'" ), libName ) );
|
||||
} );
|
||||
|
||||
if( tree )
|
||||
tree->Thaw();
|
||||
if( m_treePane )
|
||||
m_treePane->Regenerate();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -689,7 +689,7 @@ public:
|
|||
/**
|
||||
* Synchronize the library manager and the symbol library table. Displays a progress dialog.
|
||||
*/
|
||||
void SyncLibraries();
|
||||
void SyncLibraries( bool aLoad );
|
||||
|
||||
private:
|
||||
///> Helper screen used when no part is loaded
|
||||
|
|
|
@ -30,20 +30,18 @@
|
|||
#include <libeditframe.h>
|
||||
#include <symbol_lib_table.h>
|
||||
|
||||
|
||||
CMP_TREE_PANE::CMP_TREE_PANE( LIB_EDIT_FRAME* aParent, LIB_MANAGER* aLibMgr )
|
||||
: wxPanel( aParent ),
|
||||
m_libEditFrame( aParent ),
|
||||
m_libMgr( aLibMgr )
|
||||
m_libEditFrame( aParent ), m_tree( nullptr ), m_libMgr( aLibMgr )
|
||||
{
|
||||
// Create widgets
|
||||
wxBoxSizer* boxSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_tree = new COMPONENT_TREE( this, &SYMBOL_LIB_TABLE::GetGlobalLibTable(),
|
||||
m_libMgr->GetAdapter(), COMPONENT_TREE::SEARCH );
|
||||
|
||||
boxSizer->Add( m_tree, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
SetSizer( boxSizer );
|
||||
SetSizer( boxSizer ); // should remove the previous sizer according to wxWidgets docs
|
||||
Layout();
|
||||
boxSizer->Fit( this );
|
||||
|
||||
|
@ -87,7 +85,14 @@ CMP_TREE_PANE::CMP_TREE_PANE( LIB_EDIT_FRAME* aParent, LIB_MANAGER* aLibMgr )
|
|||
|
||||
CMP_TREE_PANE::~CMP_TREE_PANE()
|
||||
{
|
||||
delete m_tree;
|
||||
m_tree->Destroy();
|
||||
}
|
||||
|
||||
|
||||
void CMP_TREE_PANE::Regenerate()
|
||||
{
|
||||
if( m_tree )
|
||||
m_tree->Regenerate();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,10 +26,13 @@
|
|||
#define CMP_TREE_PANE_H
|
||||
|
||||
#include <wx/panel.h>
|
||||
#include <wx/dataview.h>
|
||||
#include <vector>
|
||||
|
||||
class COMPONENT_TREE;
|
||||
class LIB_EDIT_FRAME;
|
||||
class LIB_MANAGER;
|
||||
class wxBoxSizer;
|
||||
|
||||
/**
|
||||
* Library Editor pane with component tree and symbol library table selector.
|
||||
|
@ -45,6 +48,9 @@ public:
|
|||
return m_tree;
|
||||
}
|
||||
|
||||
///> Updates the component tree
|
||||
void Regenerate();
|
||||
|
||||
protected:
|
||||
void onComponentSelected( wxCommandEvent& aEvent );
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <wx/sizer.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/html/htmlwin.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include <symbol_lib_table.h>
|
||||
|
||||
|
@ -138,6 +139,25 @@ void COMPONENT_TREE::SelectLibId( const LIB_ID& aLibId )
|
|||
}
|
||||
|
||||
|
||||
void COMPONENT_TREE::Regenerate()
|
||||
{
|
||||
STATE current;
|
||||
|
||||
// Store the state
|
||||
if( !m_filtering )
|
||||
m_unfilteredState = getState();
|
||||
else
|
||||
current = getState();
|
||||
|
||||
m_adapter->UpdateSearchString( m_query_ctrl->GetLineText( 0 ) );
|
||||
m_filtering = !m_query_ctrl->IsEmpty();
|
||||
postPreselectEvent();
|
||||
|
||||
// Restore the state
|
||||
setState( m_filtering ? current : m_unfilteredState );
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_TREE::selectIfValid( const wxDataViewItem& aTreeId )
|
||||
{
|
||||
if( aTreeId.IsOk() )
|
||||
|
@ -163,25 +183,42 @@ void COMPONENT_TREE::postSelectEvent()
|
|||
}
|
||||
|
||||
|
||||
COMPONENT_TREE::STATE COMPONENT_TREE::getState() const
|
||||
{
|
||||
STATE state;
|
||||
wxDataViewItemArray items;
|
||||
m_adapter->GetChildren( wxDataViewItem( nullptr ), items );
|
||||
|
||||
for( const auto& item : items )
|
||||
{
|
||||
if( m_tree_ctrl->IsExpanded( item ) )
|
||||
state.expanded.push_back( item );
|
||||
}
|
||||
|
||||
state.selection = m_tree_ctrl->GetSelection();
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_TREE::setState( const STATE& aState )
|
||||
{
|
||||
wxWindowUpdateLocker updateLock( m_tree_ctrl );
|
||||
|
||||
for( const auto& item : aState.expanded )
|
||||
m_tree_ctrl->Expand( item );
|
||||
|
||||
if( aState.selection.IsOk() )
|
||||
{
|
||||
m_tree_ctrl->ExpandAncestors( aState.selection );
|
||||
m_tree_ctrl->SetCurrentItem( aState.selection );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_TREE::onQueryText( wxCommandEvent& aEvent )
|
||||
{
|
||||
// Store the state
|
||||
if( !m_filtering )
|
||||
{
|
||||
m_selection = m_tree_ctrl->GetSelection();
|
||||
saveExpandFlag();
|
||||
}
|
||||
|
||||
m_adapter->UpdateSearchString( m_query_ctrl->GetLineText( 0 ) );
|
||||
m_filtering = !m_query_ctrl->IsEmpty();
|
||||
postPreselectEvent();
|
||||
|
||||
// Restore the state
|
||||
if( !m_filtering )
|
||||
{
|
||||
selectIfValid( m_selection );
|
||||
restoreExpandFlag();
|
||||
}
|
||||
Regenerate();
|
||||
|
||||
// Required to avoid interaction with SetHint()
|
||||
// See documentation for wxTextEntry::SetHint
|
||||
|
@ -276,32 +313,5 @@ void COMPONENT_TREE::onContextMenu( wxDataViewEvent& aEvent )
|
|||
}
|
||||
|
||||
|
||||
void COMPONENT_TREE::saveExpandFlag()
|
||||
{
|
||||
wxDataViewItemArray items;
|
||||
m_adapter->GetChildren( wxDataViewItem( nullptr ), items );
|
||||
m_expanded.clear();
|
||||
|
||||
for( const auto& item : items )
|
||||
{
|
||||
if( m_tree_ctrl->IsExpanded( item ) )
|
||||
m_expanded.push_back( item );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void COMPONENT_TREE::restoreExpandFlag()
|
||||
{
|
||||
m_tree_ctrl->Freeze();
|
||||
|
||||
for( const auto& item : m_expanded )
|
||||
{
|
||||
m_tree_ctrl->Expand( item );
|
||||
}
|
||||
|
||||
m_tree_ctrl->Thaw();
|
||||
}
|
||||
|
||||
|
||||
wxDEFINE_EVENT( COMPONENT_PRESELECTED, wxCommandEvent );
|
||||
wxDEFINE_EVENT( COMPONENT_SELECTED, wxCommandEvent );
|
||||
|
|
|
@ -86,6 +86,11 @@ public:
|
|||
return m_menuActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerates the tree.
|
||||
*/
|
||||
void Regenerate();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* If a wxDataViewitem is valid, select it and post a selection event.
|
||||
|
@ -103,6 +108,28 @@ protected:
|
|||
*/
|
||||
void postSelectEvent();
|
||||
|
||||
/**
|
||||
* Structure storing state of the component tree widget.
|
||||
*/
|
||||
struct STATE
|
||||
{
|
||||
///> List of expanded nodes
|
||||
std::vector<wxDataViewItem> expanded;
|
||||
|
||||
///> Current selection, might be not valid if nothing was selected
|
||||
wxDataViewItem selection;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the component tree widget state.
|
||||
*/
|
||||
STATE getState() const;
|
||||
|
||||
/**
|
||||
* Restores the component tree widget state from an object.
|
||||
*/
|
||||
void setState( const STATE& aState );
|
||||
|
||||
void onQueryText( wxCommandEvent& aEvent );
|
||||
void onQueryEnter( wxCommandEvent& aEvent );
|
||||
void onQueryCharHook( wxKeyEvent& aEvent );
|
||||
|
@ -114,16 +141,6 @@ protected:
|
|||
void onPreselect( wxCommandEvent& aEvent );
|
||||
void onContextMenu( wxDataViewEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Store the list of expanded nodes in the tree widget.
|
||||
*/
|
||||
void saveExpandFlag();
|
||||
|
||||
/**
|
||||
* Restore the expanded nodes in the tree widget.
|
||||
*/
|
||||
void restoreExpandFlag();
|
||||
|
||||
SYMBOL_LIB_TABLE* m_sym_lib_table;
|
||||
CMP_TREE_MODEL_ADAPTER_BASE::PTR m_adapter;
|
||||
|
||||
|
@ -137,11 +154,11 @@ protected:
|
|||
///> Flag indicating whether a right-click context menu is active
|
||||
bool m_menuActive;
|
||||
|
||||
///> Flag indicating whether the results are filtered using the search query
|
||||
bool m_filtering;
|
||||
|
||||
///> List of expanded nodes
|
||||
std::vector<wxDataViewItem> m_expanded;
|
||||
wxDataViewItem m_selection;
|
||||
///> State of the widget before any filters applied
|
||||
STATE m_unfilteredState;
|
||||
};
|
||||
|
||||
///> Custom event sent when a new component is preselected
|
||||
|
|
Loading…
Reference in New Issue