1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <vcl/treelistentry.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/settings.hxx>
24 #include <tools/debug.hxx>
25 
ClearChildren()26 void SvTreeListEntry::ClearChildren()
27 {
28     m_Children.clear();
29 }
30 
SetListPositions()31 void SvTreeListEntry::SetListPositions()
32 {
33     sal_uLong nCur = 0;
34     for (auto const& pEntry : m_Children)
35     {
36         SvTreeListEntry& rEntry = *pEntry;
37         rEntry.nListPos &= 0x80000000;
38         rEntry.nListPos |= nCur;
39         ++nCur;
40     }
41 
42     nListPos &= (~0x80000000); // remove the invalid bit.
43 }
44 
InvalidateChildrensListPositions()45 void SvTreeListEntry::InvalidateChildrensListPositions()
46 {
47     nListPos |= 0x80000000;
48 }
49 
SvTreeListEntry()50 SvTreeListEntry::SvTreeListEntry()
51     : pParent(nullptr)
52     , nAbsPos(0)
53     , nListPos(0)
54     , pUserData(nullptr)
55     , nEntryFlags(SvTLEntryFlags::NONE)
56     , maBackColor(Application::GetSettings().GetStyleSettings().GetWindowColor())
57 {
58 }
59 
~SvTreeListEntry()60 SvTreeListEntry::~SvTreeListEntry()
61 {
62 #ifdef DBG_UTIL
63     pParent     = nullptr;
64 #endif
65 
66     m_Children.clear();
67     m_Items.clear();
68 }
69 
HasChildren() const70 bool SvTreeListEntry::HasChildren() const
71 {
72     return !m_Children.empty();
73 }
74 
HasChildListPos() const75 bool SvTreeListEntry::HasChildListPos() const
76 {
77     return pParent && !(pParent->nListPos & 0x80000000);
78 }
79 
GetChildListPos() const80 sal_uLong SvTreeListEntry::GetChildListPos() const
81 {
82     if( pParent && (pParent->nListPos & 0x80000000) )
83         pParent->SetListPositions();
84     return ( nListPos & 0x7fffffff );
85 }
86 
87 
Clone(SvTreeListEntry * pSource)88 void SvTreeListEntry::Clone(SvTreeListEntry* pSource)
89 {
90     nListPos &= 0x80000000;
91     nListPos |= ( pSource->nListPos & 0x7fffffff);
92     nAbsPos     = pSource->nAbsPos;
93 
94     m_Items.clear();
95     for (auto const& it : pSource->m_Items)
96     {
97         SvLBoxItem* pItem = &(*it);
98         std::unique_ptr<SvLBoxItem> pNewItem(pItem->Clone(pItem));
99         m_Items.push_back(std::move(pNewItem));
100     }
101 
102     pUserData = pSource->GetUserData();
103     nEntryFlags = pSource->nEntryFlags;
104 }
105 
ItemCount() const106 size_t SvTreeListEntry::ItemCount() const
107 {
108     return m_Items.size();
109 }
110 
AddItem(std::unique_ptr<SvLBoxItem> pItem)111 void SvTreeListEntry::AddItem(std::unique_ptr<SvLBoxItem> pItem)
112 {
113     m_Items.push_back(std::move(pItem));
114 }
115 
EnableChildrenOnDemand(bool bEnable)116 void SvTreeListEntry::EnableChildrenOnDemand( bool bEnable )
117 {
118     if ( bEnable )
119         nEntryFlags |= SvTLEntryFlags::CHILDREN_ON_DEMAND;
120     else
121         nEntryFlags &= ~SvTLEntryFlags::CHILDREN_ON_DEMAND;
122 }
123 
ReplaceItem(std::unique_ptr<SvLBoxItem> pNewItem,size_t const nPos)124 void SvTreeListEntry::ReplaceItem(std::unique_ptr<SvLBoxItem> pNewItem, size_t const nPos)
125 {
126     DBG_ASSERT(pNewItem,"ReplaceItem:No Item");
127     if (nPos >= m_Items.size())
128     {
129         // Out of bound. Bail out.
130         pNewItem.reset();
131         return;
132     }
133 
134     m_Items.erase(m_Items.begin()+nPos);
135     m_Items.insert(m_Items.begin()+nPos, std::move(pNewItem));
136 }
137 
GetItem(size_t nPos) const138 const SvLBoxItem& SvTreeListEntry::GetItem( size_t nPos ) const
139 {
140     return *m_Items[nPos];
141 }
142 
GetItem(size_t nPos)143 SvLBoxItem& SvTreeListEntry::GetItem( size_t nPos )
144 {
145     return *m_Items[nPos];
146 }
147 
148 namespace {
149 
150 class FindByType
151 {
152     SvLBoxItemType const meType;
153 public:
FindByType(SvLBoxItemType eType)154     explicit FindByType(SvLBoxItemType eType) : meType(eType) {}
operator ()(const std::unique_ptr<SvLBoxItem> & rpItem) const155     bool operator() (const std::unique_ptr<SvLBoxItem>& rpItem) const
156     {
157         return rpItem->GetType() == meType;
158     }
159 };
160 
161 class FindByPointer
162 {
163     const SvLBoxItem* mpItem;
164 public:
FindByPointer(const SvLBoxItem * p)165     explicit FindByPointer(const SvLBoxItem* p) : mpItem(p) {}
operator ()(const std::unique_ptr<SvLBoxItem> & rpItem) const166     bool operator() (const std::unique_ptr<SvLBoxItem>& rpItem) const
167     {
168         return rpItem.get() == mpItem;
169     }
170 };
171 
172 }
173 
GetFirstItem(SvLBoxItemType eType) const174 const SvLBoxItem* SvTreeListEntry::GetFirstItem(SvLBoxItemType eType) const
175 {
176     ItemsType::const_iterator it = std::find_if(m_Items.begin(), m_Items.end(), FindByType(eType));
177     return (it == m_Items.end()) ? nullptr : (*it).get();
178 }
179 
GetFirstItem(SvLBoxItemType eType)180 SvLBoxItem* SvTreeListEntry::GetFirstItem(SvLBoxItemType eType)
181 {
182     ItemsType::iterator it = std::find_if(m_Items.begin(), m_Items.end(), FindByType(eType));
183     return (it == m_Items.end()) ? nullptr : (*it).get();
184 }
185 
GetPos(const SvLBoxItem * pItem) const186 size_t SvTreeListEntry::GetPos( const SvLBoxItem* pItem ) const
187 {
188     ItemsType::const_iterator it = std::find_if(m_Items.begin(), m_Items.end(), FindByPointer(pItem));
189     return it == m_Items.end() ? ITEM_NOT_FOUND : std::distance(m_Items.begin(), it);
190 }
191 
192 
SetUserData(void * pPtr)193 void SvTreeListEntry::SetUserData( void* pPtr )
194 {
195     pUserData = pPtr;
196 }
197 
HasChildrenOnDemand() const198 bool SvTreeListEntry::HasChildrenOnDemand() const
199 {
200     return static_cast<bool>(nEntryFlags & SvTLEntryFlags::CHILDREN_ON_DEMAND);
201 }
202 
SetFlags(SvTLEntryFlags nFlags)203 void SvTreeListEntry::SetFlags( SvTLEntryFlags nFlags )
204 {
205     nEntryFlags = nFlags;
206 }
207 
NextSibling() const208 SvTreeListEntry* SvTreeListEntry::NextSibling() const
209 {
210     SvTreeListEntries& rList = pParent->m_Children;
211     sal_uLong nPos = GetChildListPos();
212     nPos++;
213     return (nPos < rList.size()) ? rList[nPos].get() : nullptr;
214 }
215 
PrevSibling() const216 SvTreeListEntry* SvTreeListEntry::PrevSibling() const
217 {
218     SvTreeListEntries& rList = pParent->m_Children;
219     sal_uLong nPos = GetChildListPos();
220     if ( nPos == 0 )
221         return nullptr;
222     nPos--;
223     return rList[nPos].get();
224 }
225 
226 
LastSibling() const227 SvTreeListEntry* SvTreeListEntry::LastSibling() const
228 {
229     SvTreeListEntries& rChildren = pParent->m_Children;
230     return (rChildren.empty()) ? nullptr : rChildren.back().get();
231 }
232 
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
234