include/vcl/toolkit/treelist.hxx | 165 ++------------- include/vcl/toolkit/treelistbox.hxx | 130 ++++++++++- include/vcl/toolkit/treelistentry.hxx | 1 vcl/source/treelist/treelist.cxx | 373 ++-------------------------------- vcl/source/treelist/treelistbox.cxx | 322 +++++++++++++++++++++++++++++ 5 files changed, 482 insertions(+), 509 deletions(-)
New commits: commit cb37288c6d39915b7fd1128d24cffcfc3710cfc4 Author: Michael Weghorn <[email protected]> AuthorDate: Mon Mar 16 15:49:51 2026 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Tue Mar 17 10:12:54 2026 +0100 vcl: Make SvTreeListBox::ModelNotification non-virtual There is no (more) override, so no need for it to be virtual. Change-Id: I205f3e07bc00af168dc659b2fb008bc9f46c29ce Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201859 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/include/vcl/toolkit/treelistbox.hxx b/include/vcl/toolkit/treelistbox.hxx index 5e6cb790ac26..88c7dd1e15a6 100644 --- a/include/vcl/toolkit/treelistbox.hxx +++ b/include/vcl/toolkit/treelistbox.hxx @@ -727,7 +727,7 @@ public: sal_Int32 DefaultCompare(const SvLBoxString* pLeftText, const SvLBoxString* pRightText); DECL_DLLPRIVATE_LINK( DefaultCompare, const SvSortData&, sal_Int32 ); - virtual void ModelNotification(SvListAction nActionId, SvTreeListEntry* pEntry); + void ModelNotification(SvListAction nActionId, SvTreeListEntry* pEntry); SvTreeListEntry* GetFirstEntryInView() const; SvTreeListEntry* GetNextEntryInView(SvTreeListEntry*) const; commit 366e9c4ec294cb5d050b61112e63b4cddf22efda Author: Michael Weghorn <[email protected]> AuthorDate: Mon Mar 16 15:25:50 2026 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Tue Mar 17 10:12:41 2026 +0100 vcl: Merge SvTreeListBox with SvListView base class Merge the SvListView base class into its only direct subclass, SvTreeListBox. Rename SvListView::Clear to SvTreeListBox::Reset to avoid a name clash with the existing SvTreeListBox::Clear. Move the call to `m_DataTable.clear();` from the SvListView dtor to SvTreeListBox::dispose to address this clang plugin warning/error seen otherwise: /home/michi/development/git/libreoffice/vcl/source/treelist/treelistbox.cxx:1615:1: error: VclReferenceBase subclass should have nothing in its destructor but a call to disposeOnce() [loplugin:vclwidgets] 1615 | SvTreeListBox::~SvTreeListBox() | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1616 | { | ~ 1617 | disposeOnce(); | ~~~~~~~~~~~~~~ 1618 | 1619 | m_DataTable.clear(); | ~~~~~~~~~~~~~~~~~~~~ 1620 | } | ~ 1 error generated. No change in behavior intended. Further simplification may follow. Change-Id: Ib94f28c56536fb5c59c26c445e74827bfbbe1228 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201858 Reviewed-by: Michael Weghorn <[email protected]> Tested-by: Jenkins diff --git a/include/vcl/toolkit/treelist.hxx b/include/vcl/toolkit/treelist.hxx index 947f4adba3f0..f3e9d88ff564 100644 --- a/include/vcl/toolkit/treelist.hxx +++ b/include/vcl/toolkit/treelist.hxx @@ -48,8 +48,8 @@ enum class SvListAction CLEARED = 11 }; +class SvTreeListBox; class SvTreeListEntry; -class SvListView; class SvViewDataEntry; enum class SvSortMode { Ascending, Descending, None }; @@ -65,9 +65,9 @@ struct SvSortData class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeList final { - friend class SvListView; + friend class SvTreeListBox; - SvListView& mrOwnerListView; + SvTreeListBox& mrOwnerListView; sal_uInt32 nEntryCount; Link<SvTreeListEntry*, SvTreeListEntry*> aCloneLink; @@ -79,22 +79,25 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeList final bool mbEnableInvalidate; SvTreeListEntry* FirstVisible() const { return First(); } - SvTreeListEntry* NextVisible( const SvListView*,SvTreeListEntry* pEntry, sal_uInt16* pDepth=nullptr ) const; - SvTreeListEntry* PrevVisible( const SvListView*,SvTreeListEntry* pEntry ) const; - SvTreeListEntry* LastVisible( const SvListView* ) const; - SvTreeListEntry* NextVisible( const SvListView*,SvTreeListEntry* pEntry, sal_uInt16& rDelta ) const; - SvTreeListEntry* PrevVisible( const SvListView*,SvTreeListEntry* pEntry, sal_uInt16& rDelta ) const; - - bool IsEntryVisible( const SvListView*,SvTreeListEntry* pEntry ) const; - SvTreeListEntry* GetEntryAtVisPos( const SvListView*, sal_uInt32 nVisPos ) const; - sal_uInt32 GetVisiblePos( const SvListView*,SvTreeListEntry const * pEntry ) const; - sal_uInt32 GetVisibleCount( SvListView* ) const; - sal_uInt32 GetVisibleChildCount( const SvListView*,SvTreeListEntry* pParent ) const; - - SvTreeListEntry* FirstSelected( const SvListView*) const; - SvTreeListEntry* NextSelected( const SvListView*,SvTreeListEntry* pEntry ) const; - - sal_uInt32 GetChildSelectionCount( const SvListView*,SvTreeListEntry* pParent ) const; + SvTreeListEntry* NextVisible(const SvTreeListBox*, SvTreeListEntry* pEntry, + sal_uInt16* pDepth = nullptr) const; + SvTreeListEntry* PrevVisible(const SvTreeListBox*, SvTreeListEntry* pEntry) const; + SvTreeListEntry* LastVisible(const SvTreeListBox*) const; + SvTreeListEntry* NextVisible(const SvTreeListBox*, SvTreeListEntry* pEntry, + sal_uInt16& rDelta) const; + SvTreeListEntry* PrevVisible(const SvTreeListBox*, SvTreeListEntry* pEntry, + sal_uInt16& rDelta) const; + + bool IsEntryVisible(const SvTreeListBox*, SvTreeListEntry* pEntry) const; + SvTreeListEntry* GetEntryAtVisPos(const SvTreeListBox*, sal_uInt32 nVisPos) const; + sal_uInt32 GetVisiblePos(const SvTreeListBox*, SvTreeListEntry const* pEntry) const; + sal_uInt32 GetVisibleCount(SvTreeListBox*) const; + sal_uInt32 GetVisibleChildCount(const SvTreeListBox*, SvTreeListEntry* pParent) const; + + SvTreeListEntry* FirstSelected(const SvTreeListBox*) const; + SvTreeListEntry* NextSelected(const SvTreeListBox*, SvTreeListEntry* pEntry) const; + + sal_uInt32 GetChildSelectionCount(const SvTreeListBox*, SvTreeListEntry* pParent) const; SAL_DLLPRIVATE void SetAbsolutePositions(); @@ -124,7 +127,7 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeList final public: SvTreeList() = delete; - SvTreeList(SvListView&); + SvTreeList(SvTreeListBox&); ~SvTreeList(); void Broadcast(SvListAction nActionId, SvTreeListEntry* pEntry = nullptr); @@ -197,126 +200,4 @@ public: void Resort(); }; -class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvListView -{ - friend class SvTreeList; - - using SvDataTable = std::unordered_map<SvTreeListEntry*, std::unique_ptr<SvViewDataEntry>>; - SvDataTable m_DataTable; // Mapping SvTreeListEntry -> ViewData - - sal_uInt32 m_nVisibleCount; - sal_uInt32 m_nSelectionCount; - bool m_bVisPositionsValid; - -protected: - std::unique_ptr<SvTreeList> m_pModel; - - void ExpandListEntry( SvTreeListEntry* pParent ); - void CollapseListEntry( SvTreeListEntry* pParent ); - bool SelectListEntry( SvTreeListEntry* pEntry, bool bSelect ); - -public: - SvListView(); // Sets the Model to 0 - void dispose(); - virtual ~SvListView(); - void Clear(); - virtual void ModelNotification(SvListAction nActionId, SvTreeListEntry* pEntry); - - sal_uInt32 GetVisibleCount() const - { - return m_pModel->GetVisibleCount(const_cast<SvListView*>(this)); - } - - SvTreeListEntry* FirstVisible() const { return m_pModel->FirstVisible(); } - - SvTreeListEntry* NextVisible( SvTreeListEntry* pEntry ) const - { - return m_pModel->NextVisible(this, pEntry); - } - - SvTreeListEntry* PrevVisible( SvTreeListEntry* pEntry ) const - { - return m_pModel->PrevVisible(this, pEntry); - } - - SvTreeListEntry* LastVisible() const { return m_pModel->LastVisible(this); } - - SvTreeListEntry* NextVisible( SvTreeListEntry* pEntry, sal_uInt16& rDelta ) const - { - return m_pModel->NextVisible(this, pEntry, rDelta); - } - - SvTreeListEntry* PrevVisible( SvTreeListEntry* pEntry, sal_uInt16& rDelta ) const - { - return m_pModel->PrevVisible(this, pEntry, rDelta); - } - - sal_uInt32 GetSelectionCount() const; - - SvTreeListEntry* FirstSelected() const { return m_pModel->FirstSelected(this); } - - SvTreeListEntry* NextSelected( SvTreeListEntry* pEntry ) const - { - return m_pModel->NextSelected(this, pEntry); - } - - SvTreeListEntry* GetEntryAtAbsPos( sal_uInt32 nAbsPos ) const - { - return m_pModel->GetEntryAtAbsPos(nAbsPos); - } - - SvTreeListEntry* GetEntryAtVisPos( sal_uInt32 nVisPos ) const - { - return m_pModel->GetEntryAtVisPos(this, nVisPos); - } - - sal_uInt32 GetAbsPos( SvTreeListEntry const * pEntry ) const - { - return m_pModel->GetAbsPos(pEntry); - } - - sal_uInt32 GetVisiblePos( SvTreeListEntry const * pEntry ) const - { - return m_pModel->GetVisiblePos(this, pEntry); - } - - sal_uInt32 GetVisibleChildCount(SvTreeListEntry* pParent ) const - { - return m_pModel->GetVisibleChildCount(this, pParent); - } - - bool IsEntryVisible( SvTreeListEntry* pEntry ) const - { - return m_pModel->IsEntryVisible(this, pEntry); - } - - bool IsExpanded( SvTreeListEntry* pEntry ) const; - bool IsAllExpanded( SvTreeListEntry* pEntry) const; - bool IsSelected(const SvTreeListEntry* pEntry) const; - void SetEntryFocus( SvTreeListEntry* pEntry, bool bFocus ); - const SvViewDataEntry* GetViewData( const SvTreeListEntry* pEntry ) const; - SvViewDataEntry* GetViewData( SvTreeListEntry* pEntry ); - bool HasViewData() const; - - virtual void InitViewData( SvViewDataEntry*, SvTreeListEntry* pEntry ) = 0; - - virtual void ModelHasCleared() = 0; - virtual void ModelHasInserted( SvTreeListEntry* pEntry ) = 0; - virtual void ModelHasInsertedTree( SvTreeListEntry* pEntry ) = 0; - virtual void ModelIsMoving( SvTreeListEntry* pSource ) = 0; - virtual void ModelHasMoved( SvTreeListEntry* pSource ) = 0; - virtual void ModelIsRemoving( SvTreeListEntry* pEntry ) = 0; - virtual void ModelHasRemoved( SvTreeListEntry* pEntry ) = 0; - virtual void ModelHasEntryInvalidated( SvTreeListEntry* pEntry ) = 0; - -private: - void RemoveViewData(SvTreeListEntry* pParent); - - void ActionMoving(SvTreeListEntry* pEntry); - void ActionMoved(); - void ActionInserted(SvTreeListEntry* pEntry); - void ActionInsertedTree(SvTreeListEntry* pEntry); - void ActionRemoving(SvTreeListEntry* pEntry); -}; - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/toolkit/treelistbox.hxx b/include/vcl/toolkit/treelistbox.hxx index edf53bbebeb3..5e6cb790ac26 100644 --- a/include/vcl/toolkit/treelistbox.hxx +++ b/include/vcl/toolkit/treelistbox.hxx @@ -176,12 +176,10 @@ typedef std::pair<vcl::RenderContext&, const SvTreeListEntry&> svtree_measure_ar typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, const SvTreeListEntry&> svtree_render_args; typedef std::pair<SvTreeListEntry*, OUString> IterString; -class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListBox - :public Control - ,public SvListView - ,public DropTargetHelper - ,public DragSourceHelper - ,public vcl::ISearchableStringList +class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListBox : public Control, + public DropTargetHelper, + public DragSourceHelper, + public vcl::ISearchableStringList { friend class SvImpLBox; friend class SvLBoxString; @@ -190,8 +188,18 @@ class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListBox friend class SalInstanceIconView; friend class SalInstanceTreeView; friend class SalInstanceEntryTreeView; + friend class SvTreeList; friend class JSTreeView; + using SvDataTable = std::unordered_map<SvTreeListEntry*, std::unique_ptr<SvViewDataEntry>>; + SvDataTable m_DataTable; // Mapping SvTreeListEntry -> ViewData + + sal_uInt32 m_nVisibleCount; + sal_uInt32 m_nSelectionCount; + bool m_bVisPositionsValid; + + std::unique_ptr<SvTreeList> m_pModel; + std::unique_ptr<SvTreeListBoxImpl> mpImpl; Link<SvTreeListBox*,void> aScrolledHdl; Link<SvTreeListBox*,void> aExpandedHdl; @@ -260,6 +268,20 @@ private: // Handler that is called by TreeList to clone an Entry DECL_DLLPRIVATE_LINK( CloneHdl_Impl, SvTreeListEntry*, SvTreeListEntry* ); + void ExpandListEntry(SvTreeListEntry* pParent); + void CollapseListEntry(SvTreeListEntry* pParent); + bool SelectListEntry(SvTreeListEntry* pEntry, bool bSelect); + + void Reset(); + + void RemoveViewData(SvTreeListEntry* pParent); + + void ActionMoving(SvTreeListEntry* pEntry); + void ActionMoved(); + void ActionInserted(SvTreeListEntry* pEntry); + void ActionInsertedTree(SvTreeListEntry* pEntry); + void ActionRemoving(SvTreeListEntry* pEntry); + // Handler and methods for Drag - finished handler. // The Handle retrieved by GetDragFinishedHdl can be set on the // TransferDataContainer. This link is a callback for the DragFinished @@ -311,7 +333,7 @@ protected: // InitViewData is called right after CreateViewData // The Entry is has not yet been added to the View in InitViewData! - virtual void InitViewData( SvViewDataEntry*, SvTreeListEntry* pEntry ) override; + virtual void InitViewData(SvViewDataEntry*, SvTreeListEntry* pEntry); // Calls InitViewData for all Items void RecalcViewData(); @@ -339,6 +361,82 @@ public: virtual ~SvTreeListBox() override; virtual void dispose() override; + sal_uInt32 GetVisibleCount() const + { + return m_pModel->GetVisibleCount(const_cast<SvTreeListBox*>(this)); + } + + SvTreeListEntry* FirstVisible() const { return m_pModel->FirstVisible(); } + + SvTreeListEntry* NextVisible(SvTreeListEntry* pEntry) const + { + return m_pModel->NextVisible(this, pEntry); + } + + SvTreeListEntry* PrevVisible(SvTreeListEntry* pEntry) const + { + return m_pModel->PrevVisible(this, pEntry); + } + + SvTreeListEntry* LastVisible() const { return m_pModel->LastVisible(this); } + + SvTreeListEntry* NextVisible(SvTreeListEntry* pEntry, sal_uInt16& rDelta) const + { + return m_pModel->NextVisible(this, pEntry, rDelta); + } + + SvTreeListEntry* PrevVisible(SvTreeListEntry* pEntry, sal_uInt16& rDelta) const + { + return m_pModel->PrevVisible(this, pEntry, rDelta); + } + + sal_uInt32 GetSelectionCount() const; + + SvTreeListEntry* FirstSelected() const { return m_pModel->FirstSelected(this); } + + SvTreeListEntry* NextSelected(SvTreeListEntry* pEntry) const + { + return m_pModel->NextSelected(this, pEntry); + } + + SvTreeListEntry* GetEntryAtAbsPos(sal_uInt32 nAbsPos) const + { + return m_pModel->GetEntryAtAbsPos(nAbsPos); + } + + SvTreeListEntry* GetEntryAtVisPos(sal_uInt32 nVisPos) const + { + return m_pModel->GetEntryAtVisPos(this, nVisPos); + } + + sal_uInt32 GetAbsPos(SvTreeListEntry const* pEntry) const + { + return m_pModel->GetAbsPos(pEntry); + } + + sal_uInt32 GetVisiblePos(SvTreeListEntry const* pEntry) const + { + return m_pModel->GetVisiblePos(this, pEntry); + } + + sal_uInt32 GetVisibleChildCount(SvTreeListEntry* pParent) const + { + return m_pModel->GetVisibleChildCount(this, pParent); + } + + bool IsEntryVisible(SvTreeListEntry* pEntry) const + { + return m_pModel->IsEntryVisible(this, pEntry); + } + + bool IsExpanded(SvTreeListEntry* pEntry) const; + bool IsAllExpanded(SvTreeListEntry* pEntry) const; + bool IsSelected(const SvTreeListEntry* pEntry) const; + void SetEntryFocus(SvTreeListEntry* pEntry, bool bFocus); + const SvViewDataEntry* GetViewData(const SvTreeListEntry* pEntry) const; + SvViewDataEntry* GetViewData(SvTreeListEntry* pEntry); + bool HasViewData() const; + SvTreeList* GetModel() const { return m_pModel.get(); } sal_uInt32 GetEntryCount() const { return m_pModel ? m_pModel->GetEntryCount() : 0; } @@ -576,14 +674,14 @@ public: virtual void LoseFocus() override; void SetUpdateMode( bool ); - virtual void ModelHasCleared() override; - virtual void ModelHasInserted( SvTreeListEntry* pEntry ) override; - virtual void ModelHasInsertedTree( SvTreeListEntry* pEntry ) override; - virtual void ModelIsMoving(SvTreeListEntry* pSource ) override; - virtual void ModelHasMoved(SvTreeListEntry* pSource ) override; - virtual void ModelIsRemoving( SvTreeListEntry* pEntry ) override; - virtual void ModelHasRemoved( SvTreeListEntry* pEntry ) override; - void ModelHasEntryInvalidated( SvTreeListEntry* pEntry ) override; + virtual void ModelHasCleared(); + virtual void ModelHasInserted(SvTreeListEntry* pEntry); + virtual void ModelHasInsertedTree(SvTreeListEntry* pEntry); + virtual void ModelIsMoving(SvTreeListEntry* pSource); + virtual void ModelHasMoved(SvTreeListEntry* pSource); + virtual void ModelIsRemoving(SvTreeListEntry* pEntry); + virtual void ModelHasRemoved(SvTreeListEntry* pEntry); + void ModelHasEntryInvalidated(SvTreeListEntry* pEntry); void ScrollOutputArea( short nDeltaEntries ); @@ -629,7 +727,7 @@ public: sal_Int32 DefaultCompare(const SvLBoxString* pLeftText, const SvLBoxString* pRightText); DECL_DLLPRIVATE_LINK( DefaultCompare, const SvSortData&, sal_Int32 ); - virtual void ModelNotification(SvListAction nActionId, SvTreeListEntry* pEntry) override; + virtual void ModelNotification(SvListAction nActionId, SvTreeListEntry* pEntry); SvTreeListEntry* GetFirstEntryInView() const; SvTreeListEntry* GetNextEntryInView(SvTreeListEntry*) const; diff --git a/include/vcl/toolkit/treelistentry.hxx b/include/vcl/toolkit/treelistentry.hxx index 56481e39babb..d586e7acdc07 100644 --- a/include/vcl/toolkit/treelistentry.hxx +++ b/include/vcl/toolkit/treelistentry.hxx @@ -56,7 +56,6 @@ namespace o3tl class UNLESS_MERGELIBS_MORE(VCL_DLLPUBLIC) SvTreeListEntry { friend class SvTreeList; - friend class SvListView; friend class SvTreeListBox; typedef std::vector<std::unique_ptr<SvLBoxItem>> ItemsType; diff --git a/vcl/source/treelist/treelist.cxx b/vcl/source/treelist/treelist.cxx index e2012e4e1aad..6c4f49c745b9 100644 --- a/vcl/source/treelist/treelist.cxx +++ b/vcl/source/treelist/treelist.cxx @@ -27,9 +27,9 @@ #include <memory> #include <utility> -SvTreeList::SvTreeList(SvListView& listView) : - mrOwnerListView(listView), - mbEnableInvalidate(true) +SvTreeList::SvTreeList(SvTreeListBox& rTreeListBox) + : mrOwnerListView(rTreeListBox) + , mbEnableInvalidate(true) { nEntryCount = 0; bAbsPositionsValid = false; @@ -47,7 +47,7 @@ void SvTreeList::Broadcast(SvListAction nActionId, SvTreeListEntry* pEntry) } // an entry is visible if all parents are expanded -bool SvTreeList::IsEntryVisible( const SvListView* pView, SvTreeListEntry* pEntry ) const +bool SvTreeList::IsEntryVisible(const SvTreeListBox* pView, SvTreeListEntry* pEntry) const { assert(pView && pEntry && "IsVisible:Invalid Params"); bool bRetVal = false; @@ -378,7 +378,8 @@ sal_uInt32 SvTreeList::GetChildCount( const SvTreeListEntry* pParent ) const return nCount - 1; } -sal_uInt32 SvTreeList::GetVisibleChildCount(const SvListView* pView, SvTreeListEntry* pParent) const +sal_uInt32 SvTreeList::GetVisibleChildCount(const SvTreeListBox* pView, + SvTreeListEntry* pParent) const { assert(pView && "GetVisChildCount:No View"); if ( !pParent ) @@ -400,7 +401,8 @@ sal_uInt32 SvTreeList::GetVisibleChildCount(const SvListView* pView, SvTreeListE return nCount - 1; } -sal_uInt32 SvTreeList::GetChildSelectionCount(const SvListView* pView,SvTreeListEntry* pParent) const +sal_uInt32 SvTreeList::GetChildSelectionCount(const SvTreeListBox* pView, + SvTreeListEntry* pParent) const { assert(pView && "GetChildSelCount:No View"); if ( !pParent ) @@ -498,7 +500,8 @@ SvTreeListEntry* SvTreeList::Last() const return pEntry; } -sal_uInt32 SvTreeList::GetVisiblePos( const SvListView* pView, SvTreeListEntry const * pEntry ) const +sal_uInt32 SvTreeList::GetVisiblePos(const SvTreeListBox* pView, + SvTreeListEntry const* pEntry) const { assert(pView && "View?"); DBG_ASSERT(pEntry,"Entry?"); @@ -506,8 +509,8 @@ sal_uInt32 SvTreeList::GetVisiblePos( const SvListView* pView, SvTreeListEntry c if (!pView->m_bVisPositionsValid) { // to make GetVisibleCount refresh the positions - const_cast<SvListView*>(pView)->m_nVisibleCount = 0; - GetVisibleCount( const_cast<SvListView*>(pView) ); + const_cast<SvTreeListBox*>(pView)->m_nVisibleCount = 0; + GetVisibleCount(const_cast<SvTreeListBox*>(pView)); } const SvViewDataEntry* pViewData = pView->GetViewData( pEntry ); if (!pViewData) @@ -515,7 +518,7 @@ sal_uInt32 SvTreeList::GetVisiblePos( const SvListView* pView, SvTreeListEntry c return pViewData->nVisPos; } -sal_uInt32 SvTreeList::GetVisibleCount( SvListView* pView ) const +sal_uInt32 SvTreeList::GetVisibleCount(SvTreeListBox* pView) const { assert(pView && "GetVisCount:No View"); if( !pView->HasViewData() ) @@ -546,7 +549,8 @@ sal_uInt32 SvTreeList::GetVisibleCount( SvListView* pView ) const // For performance reasons, this function assumes that the passed entry is // already visible. -SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pActEntry,sal_uInt16* pActDepth) const +SvTreeListEntry* SvTreeList::NextVisible(const SvTreeListBox* pView, SvTreeListEntry* pActEntry, + sal_uInt16* pActDepth) const { if ( !pActEntry ) return nullptr; @@ -608,7 +612,8 @@ SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry // For performance reasons, this function assumes that the passed entry is // already visible. -SvTreeListEntry* SvTreeList::PrevVisible(const SvListView* pView, SvTreeListEntry* pActEntry) const +SvTreeListEntry* SvTreeList::PrevVisible(const SvTreeListBox* pView, + SvTreeListEntry* pActEntry) const { assert(pView && pActEntry && "PrevVis:View/Entry?"); @@ -637,7 +642,7 @@ SvTreeListEntry* SvTreeList::PrevVisible(const SvListView* pView, SvTreeListEntr return nullptr; } -SvTreeListEntry* SvTreeList::LastVisible( const SvListView* pView) const +SvTreeListEntry* SvTreeList::LastVisible(const SvTreeListBox* pView) const { DBG_ASSERT(pView,"LastVis:No View"); SvTreeListEntry* pEntry = Last(); @@ -646,7 +651,8 @@ SvTreeListEntry* SvTreeList::LastVisible( const SvListView* pView) const return pEntry; } -SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pEntry,sal_uInt16& nDelta) const +SvTreeListEntry* SvTreeList::NextVisible(const SvTreeListBox* pView, SvTreeListEntry* pEntry, + sal_uInt16& nDelta) const { assert(pView && pEntry && "NextVis:Wrong Prms!"); DBG_ASSERT(IsEntryVisible(pView,pEntry), "NextVis:Wrong Vis"); @@ -670,7 +676,8 @@ SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry return pEntry; } -SvTreeListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvTreeListEntry* pEntry, sal_uInt16& nDelta ) const +SvTreeListEntry* SvTreeList::PrevVisible(const SvTreeListBox* pView, SvTreeListEntry* pEntry, + sal_uInt16& nDelta) const { DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis"); @@ -690,7 +697,7 @@ SvTreeListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvTreeListEnt return pEntry; } -SvTreeListEntry* SvTreeList::FirstSelected( const SvListView* pView) const +SvTreeListEntry* SvTreeList::FirstSelected(const SvTreeListBox* pView) const { DBG_ASSERT(pView,"FirstSel:No View"); if( !pView ) @@ -713,7 +720,7 @@ SvTreeListEntry* SvTreeList::FirstChild(const SvTreeListEntry* pParent) const return pResult; } -SvTreeListEntry* SvTreeList::NextSelected( const SvListView* pView, SvTreeListEntry* pEntry ) const +SvTreeListEntry* SvTreeList::NextSelected(const SvTreeListBox* pView, SvTreeListEntry* pEntry) const { assert(pView && pEntry && "NextSel:View/Entry?"); pEntry = Next( pEntry ); @@ -780,81 +787,6 @@ void SvTreeList::SetAbsolutePositions() bAbsPositionsValid = true; } -void SvListView::ExpandListEntry( SvTreeListEntry* pEntry ) -{ - assert(pEntry && "Expand:View/Entry?"); - SvViewDataEntry* pViewData = GetViewData(pEntry); - if (!pViewData) - return; - - if (pViewData->IsExpanded()) - return; - - DBG_ASSERT(!pEntry->m_Children.empty(), "SvTreeList::Expand: We expected to have child entries."); - - pViewData->SetExpanded(true); - SvTreeListEntry* pParent = pEntry->pParent; - // if parent is visible, invalidate status data - if ( IsExpanded( pParent ) ) - { - m_bVisPositionsValid = false; - m_nVisibleCount = 0; - } -} - -void SvListView::CollapseListEntry( SvTreeListEntry* pEntry ) -{ - assert(pEntry && "Collapse:View/Entry?"); - SvViewDataEntry* pViewData = GetViewData( pEntry ); - if (!pViewData) - return; - - if (!pViewData->IsExpanded()) - return; - - DBG_ASSERT(!pEntry->m_Children.empty(), "SvTreeList::Collapse: We expected to have child entries."); - - pViewData->SetExpanded(false); - - SvTreeListEntry* pParent = pEntry->pParent; - if ( IsExpanded(pParent) ) - { - m_nVisibleCount = 0; - m_bVisPositionsValid = false; - } -} - -bool SvListView::SelectListEntry( SvTreeListEntry* pEntry, bool bSelect ) -{ - DBG_ASSERT(pEntry,"Select:View/Entry?"); - - SvViewDataEntry* pViewData = GetViewData( pEntry ); - if (!pViewData) - return false; - - if ( bSelect ) - { - if ( pViewData->IsSelected() || !pViewData->IsSelectable() ) - return false; - else - { - pViewData->SetSelected(true); - m_nSelectionCount++; - } - } - else - { - if ( !pViewData->IsSelected() ) - return false; - else - { - pViewData->SetSelected(false); - m_nSelectionCount--; - } - } - return true; -} - bool SvTreeList::Remove( const SvTreeListEntry* pEntry ) { assert(pEntry && "Cannot remove root, use clear"); @@ -921,7 +853,7 @@ SvTreeListEntry* SvTreeList::GetEntryAtAbsPos( sal_uInt32 nAbsPos ) const return pEntry; } -SvTreeListEntry* SvTreeList::GetEntryAtVisPos( const SvListView* pView, sal_uInt32 nVisPos ) const +SvTreeListEntry* SvTreeList::GetEntryAtVisPos(const SvTreeListBox* pView, sal_uInt32 nVisPos) const { DBG_ASSERT(pView,"GetEntryAtVisPos:No View"); SvTreeListEntry* pEntry = First(); @@ -956,261 +888,6 @@ void SvTreeList::InvalidateEntry( SvTreeListEntry* pEntry ) Broadcast( SvListAction::INVALIDATE_ENTRY, pEntry ); } -SvListView::SvListView() - : m_nVisibleCount(0) - , m_nSelectionCount(0) - , m_bVisPositionsValid(false) -{ - m_pModel.reset(new SvTreeList(*this)); - - // insert root entry - SvTreeListEntry* pEntry = m_pModel->pRootItem.get(); - std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry); - pViewData->SetExpanded(true); - m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData))); -} - -void SvListView::dispose() { m_pModel.reset(); } - -SvListView::~SvListView() -{ - m_DataTable.clear(); -} - -sal_uInt32 SvListView::GetSelectionCount() const { return m_nSelectionCount; } - -bool SvListView::HasViewData() const { return m_DataTable.size() > 1; } // There's always a ROOT - -void SvListView::Clear() -{ - m_DataTable.clear(); - m_nSelectionCount = 0; - m_nVisibleCount = 0; - m_bVisPositionsValid = false; - if (m_pModel) - { - // insert root entry - SvTreeListEntry* pEntry = m_pModel->pRootItem.get(); - std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry); - pViewData->SetExpanded(true); - m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData))); - } -} - -void SvListView::ActionMoving(SvTreeListEntry* pEntry) -{ - SvTreeListEntry* pParent = pEntry->pParent; - assert(pParent && "Model not consistent"); - if (pParent != m_pModel->pRootItem.get() && pParent->m_Children.size() == 1) - { - const auto iter = m_DataTable.find(pParent); - assert(iter != m_DataTable.end()); - SvViewDataEntry* pViewData = iter->second.get(); - pViewData->SetExpanded(false); - } - // preliminary - m_nVisibleCount = 0; - m_bVisPositionsValid = false; -} - -void SvListView::ActionMoved() -{ - m_nVisibleCount = 0; - m_bVisPositionsValid = false; -} - -void SvListView::ActionInserted(SvTreeListEntry* pEntry) -{ - DBG_ASSERT(pEntry,"Insert:No Entry"); - std::unique_ptr<SvViewDataEntry> pData(new SvViewDataEntry()); - InitViewData(pData.get(), pEntry); - std::pair<SvDataTable::iterator, bool> aSuccess = - m_DataTable.insert(std::make_pair(pEntry, std::move(pData))); - DBG_ASSERT(aSuccess.second,"Entry already in View"); - if (m_nVisibleCount && m_pModel->IsEntryVisible(this, pEntry)) - { - m_nVisibleCount = 0; - m_bVisPositionsValid = false; - } -} - -void SvListView::ActionInsertedTree(SvTreeListEntry* pEntry) -{ - if (m_pModel->IsEntryVisible(this, pEntry)) - { - m_nVisibleCount = 0; - m_bVisPositionsValid = false; - } - // iterate over entry and its children - SvTreeListEntry* pCurEntry = pEntry; - sal_uInt16 nRefDepth = m_pModel->GetDepth(pCurEntry); - while( pCurEntry ) - { - DBG_ASSERT(m_DataTable.find(pCurEntry) != m_DataTable.end(),"Entry already in Table"); - std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry()); - InitViewData(pViewData.get(), pEntry); - m_DataTable.insert(std::make_pair(pCurEntry, std::move(pViewData))); - pCurEntry = m_pModel->Next(pCurEntry); - if (pCurEntry && m_pModel->GetDepth(pCurEntry) <= nRefDepth) - pCurEntry = nullptr; - } -} - -void SvListView::RemoveViewData(SvTreeListEntry* pParent) -{ - for (auto const& it : pParent->m_Children) - { - SvTreeListEntry& rEntry = *it; - m_DataTable.erase(&rEntry); - if (rEntry.HasChildren()) - RemoveViewData(&rEntry); - } -} - -void SvListView::ActionRemoving(SvTreeListEntry* pEntry) -{ - assert(pEntry && "Remove:No Entry"); - const auto iter = m_DataTable.find(pEntry); - assert(iter != m_DataTable.end()); - SvViewDataEntry* pViewData = iter->second.get(); - sal_uInt32 nSelRemoved = 0; - if ( pViewData->IsSelected() ) - nSelRemoved = 1 + m_pModel->GetChildSelectionCount(this, pEntry); - m_nSelectionCount -= nSelRemoved; - sal_uInt32 nVisibleRemoved = 0; - if (m_pModel->IsEntryVisible(this, pEntry)) - nVisibleRemoved = 1 + m_pModel->GetVisibleChildCount(this, pEntry); - if( m_nVisibleCount ) - { -#ifdef DBG_UTIL - if (m_nVisibleCount < nVisibleRemoved) - { - OSL_FAIL("nVisibleRemoved bad"); - } -#endif - m_nVisibleCount -= nVisibleRemoved; - } - m_bVisPositionsValid = false; - - m_DataTable.erase(pEntry); - RemoveViewData( pEntry ); - - SvTreeListEntry* pCurEntry = pEntry->pParent; - if (pCurEntry && pCurEntry != m_pModel->pRootItem.get() - && pCurEntry->m_Children.size() == 1) - { - SvDataTable::iterator itr = m_DataTable.find(pCurEntry); - assert(itr != m_DataTable.end() && "Entry not in Table"); - pViewData = itr->second.get(); - pViewData->SetExpanded(false); - } -} - -void SvListView::ModelNotification(SvListAction nActionId, SvTreeListEntry* pEntry) -{ - - switch( nActionId ) - { - case SvListAction::INSERTED: - ActionInserted(pEntry); - ModelHasInserted(pEntry); - break; - case SvListAction::INSERTED_TREE: - ActionInsertedTree(pEntry); - ModelHasInsertedTree(pEntry); - break; - case SvListAction::REMOVING: - ModelIsRemoving(pEntry); - ActionRemoving(pEntry); - break; - case SvListAction::REMOVED: - ModelHasRemoved(pEntry); - break; - case SvListAction::MOVING: - ModelIsMoving(pEntry); - ActionMoving(pEntry); - break; - case SvListAction::MOVED: - ActionMoved(); - ModelHasMoved(pEntry); - break; - case SvListAction::CLEARING: - Clear(); - ModelHasCleared(); // sic! for compatibility reasons! - break; - case SvListAction::CLEARED: - break; - case SvListAction::INVALIDATE_ENTRY: - // no action for the base class - ModelHasEntryInvalidated(pEntry); - break; - case SvListAction::RESORTED: - m_bVisPositionsValid = false; - break; - case SvListAction::RESORTING: - break; - default: - OSL_FAIL("unknown ActionId"); - } -} - -bool SvListView::IsExpanded( SvTreeListEntry* pEntry ) const -{ - DBG_ASSERT(pEntry,"IsExpanded:No Entry"); - SvDataTable::const_iterator itr = m_DataTable.find(pEntry); - if (itr == m_DataTable.end()) - return false; - return itr->second->IsExpanded(); -} - -bool SvListView::IsAllExpanded( SvTreeListEntry* pEntry ) const -{ - DBG_ASSERT(pEntry,"IsAllExpanded:No Entry"); - if (!IsExpanded(pEntry)) - return false; - const SvTreeListEntries& rChildren = pEntry->GetChildEntries(); - for (auto& rChild : rChildren) - { - if (rChild->HasChildren() || rChild->HasChildrenOnDemand()) - { - if (!IsAllExpanded(rChild.get())) - return false; - } - } - return true; -} - -bool SvListView::IsSelected(const SvTreeListEntry* pEntry) const -{ - DBG_ASSERT(pEntry,"IsExpanded:No Entry"); - SvDataTable::const_iterator itr = m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry)); - if (itr == m_DataTable.end()) - return false; - return itr->second->IsSelected(); -} - -void SvListView::SetEntryFocus( SvTreeListEntry* pEntry, bool bFocus ) -{ - DBG_ASSERT(pEntry,"SetEntryFocus:No Entry"); - SvDataTable::iterator itr = m_DataTable.find(pEntry); - assert(itr != m_DataTable.end() && "Entry not in Table"); - itr->second->SetFocus(bFocus); -} - -const SvViewDataEntry* SvListView::GetViewData( const SvTreeListEntry* pEntry ) const -{ - SvDataTable::const_iterator itr = m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry)); - assert(itr != m_DataTable.end() && "Entry not in model or wrong view"); - if (itr == m_DataTable.end()) - return nullptr; - return itr->second.get(); -} - -SvViewDataEntry* SvListView::GetViewData( SvTreeListEntry* pEntry ) -{ - return const_cast<SvViewDataEntry*>(std::as_const(*this).GetViewData(pEntry)); -} - sal_Int32 SvTreeList::Compare(const SvTreeListEntry* pLeft, const SvTreeListEntry* pRight) const { if( aCompareLink.IsSet()) diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx index 260672efd358..5cb5d9102314 100644 --- a/vcl/source/treelist/treelistbox.cxx +++ b/vcl/source/treelist/treelistbox.cxx @@ -404,6 +404,9 @@ SvTreeListBox::SvTreeListBox(vcl::Window* pParent, WinBits nWinStyle) : Control(pParent, nWinStyle | WB_CLIPCHILDREN), DropTargetHelper(this), DragSourceHelper(this), + m_nVisibleCount(0), + m_nSelectionCount(0), + m_bVisPositionsValid(false), mpImpl(new SvTreeListBoxImpl(*this)), mbContextBmpExpanded(false), mbQuickSearch(false), @@ -418,6 +421,14 @@ SvTreeListBox::SvTreeListBox(vcl::Window* pParent, WinBits nWinStyle) : mnDragAction(DND_ACTION_COPYMOVE | DND_ACTION_LINK), mbCenterAndClipText(false) { + m_pModel.reset(new SvTreeList(*this)); + + // insert root entry + SvTreeListEntry* pEntry = m_pModel->pRootItem.get(); + std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry); + pViewData->SetExpanded(true); + m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData))); + nImpFlags = SvTreeListBoxFlags::NONE; pTargetEntry = nullptr; nDragDropMode = DragDropMode::NONE; @@ -557,6 +568,268 @@ TriState SvTreeListBox::NotifyCopying( return NotifyMoving(pTarget,pEntry,rpNewParent,rNewChildPos); } +sal_uInt32 SvTreeListBox::GetSelectionCount() const { return m_nSelectionCount; } + +bool SvTreeListBox::HasViewData() const { return m_DataTable.size() > 1; } // There's always a ROOT + +void SvTreeListBox::ExpandListEntry(SvTreeListEntry* pEntry) +{ + assert(pEntry && "Expand:View/Entry?"); + SvViewDataEntry* pViewData = GetViewData(pEntry); + if (!pViewData) + return; + + if (pViewData->IsExpanded()) + return; + + DBG_ASSERT(!pEntry->m_Children.empty(), + "SvTreeList::Expand: We expected to have child entries."); + + pViewData->SetExpanded(true); + SvTreeListEntry* pParent = pEntry->pParent; + // if parent is visible, invalidate status data + if (IsExpanded(pParent)) + { + m_bVisPositionsValid = false; + m_nVisibleCount = 0; + } +} + +void SvTreeListBox::CollapseListEntry(SvTreeListEntry* pEntry) +{ + assert(pEntry && "Collapse:View/Entry?"); + SvViewDataEntry* pViewData = GetViewData(pEntry); + if (!pViewData) + return; + + if (!pViewData->IsExpanded()) + return; + + DBG_ASSERT(!pEntry->m_Children.empty(), + "SvTreeList::Collapse: We expected to have child entries."); + + pViewData->SetExpanded(false); + + SvTreeListEntry* pParent = pEntry->pParent; + if (IsExpanded(pParent)) + { + m_nVisibleCount = 0; + m_bVisPositionsValid = false; + } +} + +bool SvTreeListBox::SelectListEntry(SvTreeListEntry* pEntry, bool bSelect) +{ + DBG_ASSERT(pEntry, "Select:View/Entry?"); + + SvViewDataEntry* pViewData = GetViewData(pEntry); + if (!pViewData) + return false; + + if (bSelect) + { + if (pViewData->IsSelected() || !pViewData->IsSelectable()) + return false; + else + { + pViewData->SetSelected(true); + m_nSelectionCount++; + } + } + else + { + if (!pViewData->IsSelected()) + return false; + else + { + pViewData->SetSelected(false); + m_nSelectionCount--; + } + } + return true; +} + +void SvTreeListBox::Reset() +{ + m_DataTable.clear(); + m_nSelectionCount = 0; + m_nVisibleCount = 0; + m_bVisPositionsValid = false; + if (m_pModel) + { + // insert root entry + SvTreeListEntry* pEntry = m_pModel->pRootItem.get(); + std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry); + pViewData->SetExpanded(true); + m_DataTable.insert(std::make_pair(pEntry, std::move(pViewData))); + } +} + +void SvTreeListBox::ActionMoving(SvTreeListEntry* pEntry) +{ + SvTreeListEntry* pParent = pEntry->pParent; + assert(pParent && "Model not consistent"); + if (pParent != m_pModel->pRootItem.get() && pParent->m_Children.size() == 1) + { + const auto iter = m_DataTable.find(pParent); + assert(iter != m_DataTable.end()); + SvViewDataEntry* pViewData = iter->second.get(); + pViewData->SetExpanded(false); + } + // preliminary + m_nVisibleCount = 0; + m_bVisPositionsValid = false; +} + +void SvTreeListBox::ActionMoved() +{ + m_nVisibleCount = 0; + m_bVisPositionsValid = false; +} + +void SvTreeListBox::ActionInserted(SvTreeListEntry* pEntry) +{ + DBG_ASSERT(pEntry, "Insert:No Entry"); + std::unique_ptr<SvViewDataEntry> pData(new SvViewDataEntry()); + InitViewData(pData.get(), pEntry); + std::pair<SvDataTable::iterator, bool> aSuccess + = m_DataTable.insert(std::make_pair(pEntry, std::move(pData))); + DBG_ASSERT(aSuccess.second, "Entry already in View"); + if (m_nVisibleCount && m_pModel->IsEntryVisible(this, pEntry)) + { + m_nVisibleCount = 0; + m_bVisPositionsValid = false; + } +} + +void SvTreeListBox::ActionInsertedTree(SvTreeListEntry* pEntry) +{ + if (m_pModel->IsEntryVisible(this, pEntry)) + { + m_nVisibleCount = 0; + m_bVisPositionsValid = false; + } + // iterate over entry and its children + SvTreeListEntry* pCurEntry = pEntry; + sal_uInt16 nRefDepth = m_pModel->GetDepth(pCurEntry); + while (pCurEntry) + { + DBG_ASSERT(m_DataTable.find(pCurEntry) != m_DataTable.end(), "Entry already in Table"); + std::unique_ptr<SvViewDataEntry> pViewData(new SvViewDataEntry()); + InitViewData(pViewData.get(), pEntry); + m_DataTable.insert(std::make_pair(pCurEntry, std::move(pViewData))); + pCurEntry = m_pModel->Next(pCurEntry); + if (pCurEntry && m_pModel->GetDepth(pCurEntry) <= nRefDepth) + pCurEntry = nullptr; + } +} + +void SvTreeListBox::RemoveViewData(SvTreeListEntry* pParent) +{ + for (auto const& it : pParent->m_Children) + { + SvTreeListEntry& rEntry = *it; + m_DataTable.erase(&rEntry); + if (rEntry.HasChildren()) + RemoveViewData(&rEntry); + } +} + +void SvTreeListBox::ActionRemoving(SvTreeListEntry* pEntry) +{ + assert(pEntry && "Remove:No Entry"); + const auto iter = m_DataTable.find(pEntry); + assert(iter != m_DataTable.end()); + SvViewDataEntry* pViewData = iter->second.get(); + sal_uInt32 nSelRemoved = 0; + if (pViewData->IsSelected()) + nSelRemoved = 1 + m_pModel->GetChildSelectionCount(this, pEntry); + m_nSelectionCount -= nSelRemoved; + sal_uInt32 nVisibleRemoved = 0; + if (m_pModel->IsEntryVisible(this, pEntry)) + nVisibleRemoved = 1 + m_pModel->GetVisibleChildCount(this, pEntry); + if (m_nVisibleCount) + { +#ifdef DBG_UTIL + if (m_nVisibleCount < nVisibleRemoved) + { + OSL_FAIL("nVisibleRemoved bad"); + } +#endif + m_nVisibleCount -= nVisibleRemoved; + } + m_bVisPositionsValid = false; + + m_DataTable.erase(pEntry); + RemoveViewData(pEntry); + + SvTreeListEntry* pCurEntry = pEntry->pParent; + if (pCurEntry && pCurEntry != m_pModel->pRootItem.get() && pCurEntry->m_Children.size() == 1) + { + SvDataTable::iterator itr = m_DataTable.find(pCurEntry); + assert(itr != m_DataTable.end() && "Entry not in Table"); + pViewData = itr->second.get(); + pViewData->SetExpanded(false); + } +} + +bool SvTreeListBox::IsExpanded(SvTreeListEntry* pEntry) const +{ + DBG_ASSERT(pEntry, "IsExpanded:No Entry"); + SvDataTable::const_iterator itr = m_DataTable.find(pEntry); + if (itr == m_DataTable.end()) + return false; + return itr->second->IsExpanded(); +} + +bool SvTreeListBox::IsAllExpanded(SvTreeListEntry* pEntry) const +{ + DBG_ASSERT(pEntry, "IsAllExpanded:No Entry"); + if (!IsExpanded(pEntry)) + return false; + const SvTreeListEntries& rChildren = pEntry->GetChildEntries(); + for (auto& rChild : rChildren) + { + if (rChild->HasChildren() || rChild->HasChildrenOnDemand()) + { + if (!IsAllExpanded(rChild.get())) + return false; + } + } + return true; +} + +bool SvTreeListBox::IsSelected(const SvTreeListEntry* pEntry) const +{ + DBG_ASSERT(pEntry, "IsExpanded:No Entry"); + SvDataTable::const_iterator itr = m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry)); + if (itr == m_DataTable.end()) + return false; + return itr->second->IsSelected(); +} + +void SvTreeListBox::SetEntryFocus(SvTreeListEntry* pEntry, bool bFocus) +{ + DBG_ASSERT(pEntry, "SetEntryFocus:No Entry"); + SvDataTable::iterator itr = m_DataTable.find(pEntry); + assert(itr != m_DataTable.end() && "Entry not in Table"); + itr->second->SetFocus(bFocus); +} + +const SvViewDataEntry* SvTreeListBox::GetViewData(const SvTreeListEntry* pEntry) const +{ + SvDataTable::const_iterator itr = m_DataTable.find(const_cast<SvTreeListEntry*>(pEntry)); + assert(itr != m_DataTable.end() && "Entry not in model or wrong view"); + if (itr == m_DataTable.end()) + return nullptr; + return itr->second.get(); +} + +SvViewDataEntry* SvTreeListBox::GetViewData(SvTreeListEntry* pEntry) +{ + return const_cast<SvViewDataEntry*>(std::as_const(*this).GetViewData(pEntry)); +} + SvTreeListEntry* SvTreeListBox::FirstChild(const SvTreeListEntry* pParent) const { return m_pModel->FirstChild(pParent); @@ -1361,7 +1634,7 @@ void SvTreeListBox::dispose() pEdCtrl.reset(); - SvListView::dispose(); + m_pModel.reset(); SvTreeListBox::RemoveBoxFromDDList_Impl( *this ); @@ -1372,6 +1645,8 @@ void SvTreeListBox::dispose() mpImpl.reset(); } + m_DataTable.clear(); + DropTargetHelper::dispose(); DragSourceHelper::dispose(); Control::dispose(); @@ -3391,7 +3666,50 @@ void SvTreeListBox::ModelNotification(SvListAction nActionId, SvTreeListEntry* p if( nActionId == SvListAction::CLEARING ) CancelTextEditing(); - SvListView::ModelNotification(nActionId, pEntry); + switch (nActionId) + { + case SvListAction::INSERTED: + ActionInserted(pEntry); + ModelHasInserted(pEntry); + break; + case SvListAction::INSERTED_TREE: + ActionInsertedTree(pEntry); + ModelHasInsertedTree(pEntry); + break; + case SvListAction::REMOVING: + ModelIsRemoving(pEntry); + ActionRemoving(pEntry); + break; + case SvListAction::REMOVED: + ModelHasRemoved(pEntry); + break; + case SvListAction::MOVING: + ModelIsMoving(pEntry); + ActionMoving(pEntry); + break; + case SvListAction::MOVED: + ActionMoved(); + ModelHasMoved(pEntry); + break; + case SvListAction::CLEARING: + Reset(); + ModelHasCleared(); // sic! for compatibility reasons! + break; + case SvListAction::CLEARED: + break; + case SvListAction::INVALIDATE_ENTRY: + // no action for the base class + ModelHasEntryInvalidated(pEntry); + break; + case SvListAction::RESORTED: + m_bVisPositionsValid = false; + break; + case SvListAction::RESORTING: + break; + default: + OSL_FAIL("unknown ActionId"); + } + switch( nActionId ) { case SvListAction::INSERTED:
