diff --git a/common/lib_tree_model.h b/common/lib_tree_model.h index 970cc0dfa5..98b21fdbd7 100644 --- a/common/lib_tree_model.h +++ b/common/lib_tree_model.h @@ -104,6 +104,7 @@ public: LIB_ID LibId; ///< LIB_ID determined by the parent library nickname and alias name. int Unit; ///< Actual unit, or zero bool IsRoot; ///< Indicates if the symbol is a root symbol instead of an alias. + int VisLen; ///< Length of the string as shown on screen /** * Update the score for this part. This is accumulative - it will be diff --git a/common/lib_tree_model_adapter.cpp b/common/lib_tree_model_adapter.cpp index d7c15240b7..f433f1cf81 100644 --- a/common/lib_tree_model_adapter.cpp +++ b/common/lib_tree_model_adapter.cpp @@ -28,8 +28,6 @@ #include <wx/wupdlock.h> -LIB_TREE_MODEL_ADAPTER::WIDTH_CACHE LIB_TREE_MODEL_ADAPTER::m_width_cache; - static const int kDataViewIndent = 20; @@ -99,6 +97,17 @@ void LIB_TREE_MODEL_ADAPTER::ShowUnits( bool aShow ) } +void LIB_TREE_MODEL_ADAPTER::UpdateWidth( int aCol ) +{ + auto col = m_widget->GetColumn( aCol ); + + if( col ) + { + col->SetWidth( ColWidth( m_tree, aCol, col->GetTitle() ) ); + } +} + + void LIB_TREE_MODEL_ADAPTER::SetPreselectNode( LIB_ID const& aLibId, int aUnit ) { m_preselect_lib_id = aLibId; @@ -112,10 +121,15 @@ void LIB_TREE_MODEL_ADAPTER::DoAddLibrary( wxString const& aNodeName, wxString c { auto& lib_node = m_tree.AddLib( aNodeName, aDesc ); + lib_node.VisLen = wxTheApp->GetTopWindow()->GetTextExtent( lib_node.Name ).x; + for( auto item: aItemList ) { if( item ) - lib_node.AddItem( item ); + { + auto& child_node = lib_node.AddItem( item ); + child_node.VisLen = wxTheApp->GetTopWindow()->GetTextExtent( child_node.Name ).x; + } } lib_node.AssignIntrinsicRanks( presorted ); @@ -170,6 +184,8 @@ void LIB_TREE_MODEL_ADAPTER::UpdateSearchString( wxString const& aSearch ) m_widget->Select( item ); m_widget->EnsureVisible( item ); } + + UpdateWidth( 0 ); } @@ -183,10 +199,8 @@ void LIB_TREE_MODEL_ADAPTER::AttachTo( wxDataViewCtrl* aDataViewCtrl ) wxString part_head = _( "Item" ); wxString desc_head = _( "Description" ); - m_col_part = aDataViewCtrl->AppendTextColumn( part_head, 0, wxDATAVIEW_CELL_INERT, - ColWidth( m_tree, 0, part_head ) ); - m_col_desc = aDataViewCtrl->AppendTextColumn( desc_head, 1, wxDATAVIEW_CELL_INERT, - ColWidth( m_tree, 1, desc_head ) ); + m_col_part = aDataViewCtrl->AppendTextColumn( part_head, 0, wxDATAVIEW_CELL_INERT, 360 ); + m_col_desc = aDataViewCtrl->AppendTextColumn( desc_head, 1, wxDATAVIEW_CELL_INERT, 2000 ); } @@ -349,10 +363,33 @@ bool LIB_TREE_MODEL_ADAPTER::GetAttr( wxDataViewItem const& aItem, int LIB_TREE_MODEL_ADAPTER::ColWidth( LIB_TREE_NODE& aTree, int aCol, wxString const& aHeading ) { - // It's too expensive to calculate widths on really big trees, and the user probably - // wants it left where they dragged it anyway. if( aCol == 0 ) - return 360; + { + int padding = m_widget->GetTextExtent( "MM" ).x; + int longest = m_widget->GetTextExtent( aHeading ).x; + + for( auto& node : aTree.Children ) + { + auto item = ToItem( &*node ); + + if( !item.IsOk() ) + continue; + + if( node->Score > 0 ) + longest = std::max( longest, node->VisLen + padding ); + + if( !m_widget->IsExpanded( item ) ) + continue; + + for( auto& childNode : node->Children ) + { + if( childNode->Score > 0 ) + longest = std::max( longest, childNode->VisLen + 2 * padding ); + } + } + + return longest; + } else return 2000; } diff --git a/common/lib_tree_model_adapter.h b/common/lib_tree_model_adapter.h index fc1b74bed8..1446cd70ce 100644 --- a/common/lib_tree_model_adapter.h +++ b/common/lib_tree_model_adapter.h @@ -28,6 +28,7 @@ #include <wx/hashmap.h> #include <wx/dataview.h> +#include <wx/headerctrl.h> #include <vector> #include <functional> @@ -133,6 +134,13 @@ public: */ void ShowUnits( bool aShow ); + /** + * Update the column size based on the displayed contents + * + * @param aCol Which column to resize + */ + void UpdateWidth( int aCol ); + /** * Set the component name to be selected if there are no search results. * May be set at any time; updates at the next UpdateSearchString(). @@ -327,10 +335,6 @@ private: wxDataViewColumn* m_col_desc; wxDataViewCtrl* m_widget; - WX_DECLARE_STRING_HASH_MAP( std::vector<int>, WIDTH_CACHE ); - - static WIDTH_CACHE m_width_cache; - /** * Compute the width required for the given column of a node and its * children. diff --git a/common/widgets/lib_tree.cpp b/common/widgets/lib_tree.cpp index effd8bec3b..2810a26851 100644 --- a/common/widgets/lib_tree.cpp +++ b/common/widgets/lib_tree.cpp @@ -41,8 +41,7 @@ LIB_TREE::LIB_TREE( wxWindow* aParent, LIB_TABLE* aLibTable, LIB_TREE_MODEL_ADAP m_adapter( aAdapter ), m_query_ctrl( nullptr ), m_details_ctrl( nullptr ), - m_menuActive( false ), - m_filtering( false ) + m_menuActive( false ) { // create space for context menu pointers, INVALID is the max value m_menus.resize( LIB_TREE_NODE::TYPE::INVALID + 1 ); @@ -114,6 +113,8 @@ LIB_TREE::LIB_TREE( wxWindow* aParent, LIB_TABLE* aLibTable, LIB_TREE_MODEL_ADAP m_tree_ctrl->Bind( wxEVT_DATAVIEW_ITEM_ACTIVATED, &LIB_TREE::onTreeActivate, this ); m_tree_ctrl->Bind( wxEVT_DATAVIEW_SELECTION_CHANGED, &LIB_TREE::onTreeSelect, this ); m_tree_ctrl->Bind( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, &LIB_TREE::onContextMenu, this ); + m_tree_ctrl->Bind( wxEVT_DATAVIEW_ITEM_EXPANDED, &LIB_TREE::onExpandCollapse, this ); + m_tree_ctrl->Bind( wxEVT_DATAVIEW_ITEM_COLLAPSED, &LIB_TREE::onExpandCollapse, this ); Bind( COMPONENT_PRESELECTED, &LIB_TREE::onPreselect, this ); @@ -129,6 +130,7 @@ LIB_TREE::LIB_TREE( wxWindow* aParent, LIB_TABLE* aLibTable, LIB_TREE_MODEL_ADAP // There may be a part preselected in the model. Make sure it is displayed. postPreselectEvent(); + m_adapter->UpdateWidth( 0 ); Layout(); sizer->Fit( this ); @@ -193,7 +195,6 @@ void LIB_TREE::Regenerate( bool aKeepState ) wxString filter = m_query_ctrl->GetValue(); m_adapter->UpdateSearchString( filter ); - m_filtering = !filter.IsEmpty(); postPreselectEvent(); // Restore the state @@ -228,6 +229,7 @@ void LIB_TREE::selectIfValid( const wxDataViewItem& aTreeId ) if( aTreeId.IsOk() ) { m_tree_ctrl->EnsureVisible( aTreeId ); + m_adapter->UpdateWidth( 0 ); m_tree_ctrl->Select( aTreeId ); postPreselectEvent(); } @@ -237,7 +239,10 @@ void LIB_TREE::selectIfValid( const wxDataViewItem& aTreeId ) void LIB_TREE::centerIfValid( const wxDataViewItem& aTreeId ) { if( aTreeId.IsOk() ) + { m_tree_ctrl->EnsureVisible( aTreeId ); + m_adapter->UpdateWidth( 0 ); + } } @@ -361,6 +366,12 @@ void LIB_TREE::onTreeSelect( wxDataViewEvent& aEvent ) } +void LIB_TREE::onExpandCollapse( wxDataViewEvent& aEvent ) +{ + m_adapter->UpdateWidth( 0 ); +} + + void LIB_TREE::onTreeActivate( wxDataViewEvent& aEvent ) { if( !GetSelectedLibId().IsValid() ) diff --git a/common/widgets/lib_tree.h b/common/widgets/lib_tree.h index 278a099dfe..9b0e01ee9c 100644 --- a/common/widgets/lib_tree.h +++ b/common/widgets/lib_tree.h @@ -169,6 +169,7 @@ protected: void onTreeSelect( wxDataViewEvent& aEvent ); void onTreeActivate( wxDataViewEvent& aEvent ); + void onExpandCollapse( wxDataViewEvent& aEvent ); void onUpdateUI( wxUpdateUIEvent& aEvent ); void onDetailsLink( wxHtmlLinkEvent& aEvent ); @@ -188,9 +189,6 @@ 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; - ///> State of the widget before any filters applied STATE m_unfilteredState; };