Line data Source code
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 <svtools/treelist.hxx>
21 : #include <svtools/treelistentry.hxx>
22 : #include <svtools/viewdataentry.hxx>
23 : #include <osl/diagnose.h>
24 :
25 30 : SvTreeList::SvTreeList() :
26 30 : mbEnableInvalidate(true)
27 : {
28 30 : nEntryCount = 0;
29 30 : bAbsPositionsValid = false;
30 30 : nRefCount = 1;
31 30 : pRootItem = new SvTreeListEntry;
32 30 : eSortMode = SortNone;
33 30 : }
34 :
35 84 : SvTreeList::~SvTreeList()
36 : {
37 28 : Clear();
38 28 : delete pRootItem;
39 : #ifdef DBG_UTIL
40 : pRootItem = 0;
41 : #endif
42 56 : }
43 :
44 344 : void SvTreeList::Broadcast(
45 : SvListAction nActionId,
46 : SvTreeListEntry* pEntry1,
47 : SvTreeListEntry* pEntry2,
48 : sal_uLong nPos
49 : ) {
50 344 : sal_uLong nViewCount = aViewList.size();
51 580 : for( sal_uLong nCurView = 0; nCurView < nViewCount; nCurView++ )
52 : {
53 236 : SvListView* pView = aViewList[ nCurView ];
54 236 : if( pView )
55 236 : pView->ModelNotification( nActionId, pEntry1, pEntry2, nPos );
56 : }
57 344 : }
58 :
59 59 : void SvTreeList::InsertView( SvListView* pView )
60 : {
61 59 : for ( sal_uLong i = 0, n = aViewList.size(); i < n; ++i ) {
62 29 : if ( aViewList[ i ] == pView ) {
63 88 : return;
64 : }
65 : }
66 30 : aViewList.push_back( pView );
67 30 : nRefCount++;
68 : }
69 :
70 29 : void SvTreeList::RemoveView( SvListView* pView )
71 : {
72 29 : for ( ListViewsType::iterator it = aViewList.begin(); it != aViewList.end(); ++it )
73 : {
74 28 : if ( *it == pView )
75 : {
76 28 : aViewList.erase( it );
77 28 : --nRefCount;
78 28 : break;
79 : }
80 : }
81 29 : }
82 :
83 :
84 : // an entry is visible if all parents are expanded
85 81 : bool SvTreeList::IsEntryVisible( const SvListView* pView, SvTreeListEntry* pEntry ) const
86 : {
87 : DBG_ASSERT(pView&&pEntry,"IsVisible:Invalid Params");
88 81 : bool bRetVal = false;
89 91 : do
90 : {
91 162 : if ( pEntry == pRootItem )
92 : {
93 71 : bRetVal = true;
94 71 : break;
95 : }
96 91 : pEntry = pEntry->pParent;
97 : } while( pView->IsExpanded( pEntry ) );
98 81 : return bRetVal;
99 : }
100 :
101 406 : sal_uInt16 SvTreeList::GetDepth( const SvTreeListEntry* pEntry ) const
102 : {
103 : DBG_ASSERT(pEntry&&pEntry!=pRootItem,"GetDepth:Bad Entry");
104 406 : sal_uInt16 nDepth = 0;
105 978 : while( pEntry->pParent != pRootItem )
106 : {
107 166 : nDepth++;
108 166 : pEntry = pEntry->pParent;
109 : }
110 406 : return nDepth;
111 : }
112 :
113 0 : bool SvTreeList::IsAtRootDepth( const SvTreeListEntry* pEntry ) const
114 : {
115 0 : return pEntry->pParent == pRootItem;
116 : }
117 :
118 118 : void SvTreeList::Clear()
119 : {
120 118 : Broadcast( SvListAction::CLEARING );
121 118 : pRootItem->ClearChildren();
122 118 : nEntryCount = 0;
123 118 : Broadcast( SvListAction::CLEARED );
124 118 : }
125 :
126 0 : bool SvTreeList::IsChild(const SvTreeListEntry* pParent, const SvTreeListEntry* pChild) const
127 : {
128 0 : if ( !pParent )
129 0 : pParent = pRootItem;
130 :
131 0 : if (pParent->maChildren.empty())
132 0 : return false;
133 :
134 0 : SvTreeListEntries::const_iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
135 0 : for (; it != itEnd; ++it)
136 : {
137 0 : const SvTreeListEntry* pThis = &(*it);
138 0 : if (pThis == pChild)
139 0 : return true;
140 : else
141 : {
142 0 : bool bIsChild = IsChild(pThis, pChild);
143 0 : if (bIsChild)
144 0 : return true;
145 : }
146 : }
147 0 : return false;
148 : }
149 :
150 : namespace {
151 :
152 : class FindByPointer : std::unary_function<SvTreeListEntry, bool>
153 : {
154 : const SvTreeListEntry* mpEntry;
155 : public:
156 0 : explicit FindByPointer(const SvTreeListEntry* p) : mpEntry(p) {}
157 :
158 0 : bool operator() (const SvTreeListEntry& rEntry) const
159 : {
160 0 : return mpEntry == &rEntry;
161 : }
162 : };
163 :
164 0 : sal_uLong findEntryPosition(const SvTreeListEntries& rDst, const SvTreeListEntry* pEntry)
165 : {
166 0 : SvTreeListEntries::const_iterator itPos = std::find_if(rDst.begin(), rDst.end(), FindByPointer(pEntry));
167 0 : if (itPos == rDst.end())
168 0 : return static_cast<sal_uLong>(~0);
169 :
170 0 : return static_cast<sal_uLong>(std::distance(rDst.begin(), itPos));
171 : }
172 :
173 : }
174 :
175 0 : sal_uLong SvTreeList::Move(SvTreeListEntry* pSrcEntry,SvTreeListEntry* pTargetParent,sal_uLong nListPos)
176 : {
177 : // pDest may be 0!
178 : DBG_ASSERT(pSrcEntry,"Entry?");
179 0 : if ( !pTargetParent )
180 0 : pTargetParent = pRootItem;
181 : DBG_ASSERT(pSrcEntry!=pTargetParent,"Move:Source=Target");
182 :
183 0 : Broadcast( SvListAction::MOVING, pSrcEntry, pTargetParent, nListPos );
184 :
185 0 : if ( pSrcEntry == pTargetParent )
186 : // You can't move an entry onto itself as the parent. Just return its
187 : // position and bail out.
188 0 : return pSrcEntry->GetChildListPos();
189 :
190 0 : bAbsPositionsValid = false;
191 :
192 0 : SvTreeListEntries& rDst = pTargetParent->maChildren;
193 0 : SvTreeListEntries& rSrc = pSrcEntry->pParent->maChildren;
194 :
195 0 : bool bSameParent = pTargetParent == pSrcEntry->pParent;
196 :
197 : // Find the position of the entry being moved in the source container.
198 0 : SvTreeListEntries::iterator itSrcPos = rSrc.begin(), itEnd = rSrc.end();
199 0 : for (; itSrcPos != itEnd; ++itSrcPos)
200 : {
201 0 : const SvTreeListEntry* p = &(*itSrcPos);
202 0 : if (p == pSrcEntry)
203 : // Found
204 0 : break;
205 : }
206 :
207 0 : if (itSrcPos == itEnd)
208 : {
209 : OSL_FAIL("Source entry not found! This should never happen.");
210 0 : return pSrcEntry->GetChildListPos();
211 : }
212 :
213 0 : if (bSameParent)
214 : {
215 : // Moving within the same parent.
216 :
217 0 : size_t nSrcPos = std::distance(rSrc.begin(), itSrcPos);
218 0 : if (nSrcPos == nListPos)
219 : // Nothing to move here.
220 0 : return pSrcEntry->GetChildListPos();
221 :
222 0 : if (nSrcPos < nListPos)
223 : // Destination position shifts left after removing the original.
224 0 : --nListPos;
225 :
226 : // Release the original.
227 0 : SvTreeListEntries::auto_type p = rSrc.release(itSrcPos);
228 : // Determine the insertion position.
229 0 : SvTreeListEntries::iterator itDstPos = rSrc.end();
230 0 : if (nListPos < rSrc.size())
231 : {
232 0 : itDstPos = rSrc.begin();
233 0 : std::advance(itDstPos, nListPos);
234 : }
235 0 : rSrc.insert(itDstPos, p.release());
236 : }
237 : else
238 : {
239 : // Moving from one parent to another.
240 0 : SvTreeListEntries::iterator itDstPos = rDst.end();
241 0 : if (nListPos < rDst.size())
242 : {
243 0 : itDstPos = rDst.begin();
244 0 : std::advance(itDstPos, nListPos);
245 : }
246 0 : SvTreeListEntries::auto_type p = rSrc.release(itSrcPos);
247 0 : rDst.insert(itDstPos, p.release());
248 : }
249 :
250 : // move parent umsetzen (do this only now, because we need the parent for
251 : // deleting the old child list!)
252 0 : pSrcEntry->pParent = pTargetParent;
253 :
254 : // correct list position in target list
255 0 : SetListPositions(rDst);
256 0 : if (!bSameParent)
257 0 : SetListPositions(rSrc);
258 :
259 0 : sal_uLong nRetVal = findEntryPosition(rDst, pSrcEntry);
260 : OSL_ENSURE(nRetVal == pSrcEntry->GetChildListPos(), "ListPos not valid");
261 0 : Broadcast( SvListAction::MOVED,pSrcEntry,pTargetParent,nRetVal);
262 0 : return nRetVal;
263 : }
264 :
265 0 : sal_uLong SvTreeList::Copy(SvTreeListEntry* pSrcEntry,SvTreeListEntry* pTargetParent,sal_uLong nListPos)
266 : {
267 : // pDest may be 0!
268 : DBG_ASSERT(pSrcEntry,"Entry?");
269 0 : if ( !pTargetParent )
270 0 : pTargetParent = pRootItem;
271 :
272 0 : bAbsPositionsValid = false;
273 :
274 0 : sal_uLong nCloneCount = 0;
275 0 : SvTreeListEntry* pClonedEntry = Clone( pSrcEntry, nCloneCount );
276 0 : nEntryCount += nCloneCount;
277 :
278 0 : SvTreeListEntries& rDst = pTargetParent->maChildren;
279 :
280 0 : pClonedEntry->pParent = pTargetParent; // move parent
281 :
282 0 : if (nListPos < rDst.size())
283 : {
284 0 : SvTreeListEntries::iterator itPos = rDst.begin(); // insertion position.
285 0 : std::advance(itPos, nListPos);
286 0 : rDst.insert(itPos, pClonedEntry);
287 : }
288 : else
289 0 : rDst.push_back(pClonedEntry);
290 :
291 0 : SetListPositions(rDst); // correct list position in target list
292 :
293 0 : Broadcast( SvListAction::INSERTED_TREE, pClonedEntry );
294 0 : sal_uLong nRetVal = findEntryPosition(rDst, pClonedEntry);
295 0 : return nRetVal;
296 : }
297 :
298 0 : void SvTreeList::Move( SvTreeListEntry* pSrcEntry, SvTreeListEntry* pDstEntry )
299 : {
300 : SvTreeListEntry* pParent;
301 : sal_uLong nPos;
302 :
303 0 : if ( !pDstEntry )
304 : {
305 0 : pParent = pRootItem;
306 0 : nPos = 0UL;
307 : }
308 : else
309 : {
310 0 : pParent = pDstEntry->pParent;
311 0 : nPos = pDstEntry->GetChildListPos();
312 0 : nPos++; // (On screen:) insert _below_ pDstEntry
313 : }
314 0 : Move( pSrcEntry, pParent, nPos );
315 0 : }
316 :
317 0 : void SvTreeList::InsertTree(SvTreeListEntry* pSrcEntry,
318 : SvTreeListEntry* pTargetParent,sal_uLong nListPos)
319 : {
320 : DBG_ASSERT(pSrcEntry,"InsertTree:Entry?");
321 0 : if ( !pSrcEntry )
322 0 : return;
323 :
324 0 : if ( !pTargetParent )
325 0 : pTargetParent = pRootItem;
326 :
327 : // take sorting into account
328 0 : GetInsertionPos( pSrcEntry, pTargetParent, nListPos );
329 :
330 0 : bAbsPositionsValid = false;
331 :
332 0 : pSrcEntry->pParent = pTargetParent; // move parent
333 0 : SvTreeListEntries& rDst = pTargetParent->maChildren;
334 :
335 0 : if (nListPos < rDst.size())
336 : {
337 0 : SvTreeListEntries::iterator itPos = rDst.begin();
338 0 : std::advance(itPos, nListPos);
339 0 : rDst.insert(itPos, pSrcEntry);
340 : }
341 : else
342 0 : rDst.push_back(pSrcEntry);
343 :
344 0 : SetListPositions(rDst); // correct list position in target list
345 0 : nEntryCount += GetChildCount( pSrcEntry );
346 0 : nEntryCount++; // the parent is new, too
347 :
348 0 : Broadcast(SvListAction::INSERTED_TREE, pSrcEntry );
349 : }
350 :
351 0 : SvTreeListEntry* SvTreeList::CloneEntry( SvTreeListEntry* pSource ) const
352 : {
353 0 : if( aCloneLink.IsSet() )
354 0 : return reinterpret_cast<SvTreeListEntry*>(aCloneLink.Call( pSource ));
355 0 : SvTreeListEntry* pEntry = CreateEntry();
356 0 : pEntry->Clone(pSource);
357 0 : return pEntry;
358 : }
359 :
360 0 : SvTreeListEntry* SvTreeList::CreateEntry()
361 : {
362 0 : return new SvTreeListEntry;
363 : }
364 :
365 0 : SvTreeListEntry* SvTreeList::Clone( SvTreeListEntry* pEntry, sal_uLong& nCloneCount ) const
366 : {
367 0 : SvTreeListEntry* pClonedEntry = CloneEntry( pEntry );
368 0 : nCloneCount = 1;
369 0 : if (!pEntry->maChildren.empty())
370 : // Clone the child entries.
371 0 : CloneChildren(pClonedEntry->maChildren, nCloneCount, pEntry->maChildren, pClonedEntry);
372 :
373 0 : return pClonedEntry;
374 : }
375 :
376 0 : void SvTreeList::CloneChildren(
377 : SvTreeListEntries& rDst, sal_uLong& rCloneCount, SvTreeListEntries& rSrc, SvTreeListEntry* pNewParent) const
378 : {
379 0 : SvTreeListEntries aClone;
380 0 : SvTreeListEntries::iterator it = rSrc.begin(), itEnd = rSrc.end();
381 0 : for (; it != itEnd; ++it)
382 : {
383 0 : SvTreeListEntry& rEntry = *it;
384 0 : SvTreeListEntry* pNewEntry = CloneEntry(&rEntry);
385 0 : ++rCloneCount;
386 0 : pNewEntry->pParent = pNewParent;
387 0 : if (!rEntry.maChildren.empty())
388 : // Clone entries recursively.
389 0 : CloneChildren(pNewEntry->maChildren, rCloneCount, rEntry.maChildren, pNewEntry);
390 :
391 0 : aClone.push_back(pNewEntry);
392 : }
393 :
394 0 : rDst.swap(aClone);
395 0 : }
396 :
397 93 : sal_uLong SvTreeList::GetChildCount( const SvTreeListEntry* pParent ) const
398 : {
399 93 : if ( !pParent )
400 0 : return GetEntryCount();
401 :
402 93 : if (!pParent || pParent->maChildren.empty())
403 93 : return 0;
404 :
405 0 : sal_uLong nCount = 0;
406 0 : sal_uInt16 nRefDepth = GetDepth( pParent );
407 0 : sal_uInt16 nActDepth = nRefDepth;
408 0 : do
409 : {
410 0 : pParent = Next(const_cast<SvTreeListEntry*>(pParent), &nActDepth);
411 0 : nCount++;
412 0 : } while( pParent && nRefDepth < nActDepth );
413 0 : nCount--;
414 0 : return nCount;
415 : }
416 :
417 0 : sal_uLong SvTreeList::GetVisibleChildCount(const SvListView* pView, SvTreeListEntry* pParent) const
418 : {
419 : DBG_ASSERT(pView,"GetVisChildCount:No View");
420 0 : if ( !pParent )
421 0 : pParent = pRootItem;
422 :
423 0 : if (!pParent || !pView->IsExpanded(pParent) || pParent->maChildren.empty())
424 0 : return 0;
425 :
426 0 : sal_uLong nCount = 0;
427 0 : sal_uInt16 nRefDepth = GetDepth( pParent );
428 0 : sal_uInt16 nActDepth = nRefDepth;
429 0 : do
430 : {
431 0 : pParent = NextVisible( pView, pParent, &nActDepth );
432 0 : nCount++;
433 0 : } while( pParent && nRefDepth < nActDepth );
434 0 : nCount--;
435 0 : return nCount;
436 : }
437 :
438 2 : sal_uLong SvTreeList::GetChildSelectionCount(const SvListView* pView,SvTreeListEntry* pParent) const
439 : {
440 : DBG_ASSERT(pView,"GetChildSelCount:No View");
441 2 : if ( !pParent )
442 0 : pParent = pRootItem;
443 :
444 2 : if (!pParent || pParent->maChildren.empty())
445 2 : return 0;
446 :
447 0 : sal_uLong nCount = 0;
448 0 : sal_uInt16 nRefDepth = GetDepth( pParent );
449 0 : sal_uInt16 nActDepth = nRefDepth;
450 0 : do
451 : {
452 0 : pParent = Next( pParent, &nActDepth );
453 0 : if( pParent && pView->IsSelected( pParent ) && nRefDepth < nActDepth)
454 0 : nCount++;
455 0 : } while( pParent && nRefDepth < nActDepth );
456 : // nCount--;
457 0 : return nCount;
458 : }
459 :
460 938 : SvTreeListEntry* SvTreeList::First() const
461 : {
462 938 : if ( nEntryCount )
463 176 : return &pRootItem->maChildren[0];
464 : else
465 762 : return 0;
466 : }
467 :
468 605 : SvTreeListEntry* SvTreeList::Next( SvTreeListEntry* pActEntry, sal_uInt16* pDepth ) const
469 : {
470 : DBG_ASSERT( pActEntry && pActEntry->pParent, "SvTreeList::Next: invalid entry/parent!" );
471 605 : if ( !pActEntry || !pActEntry->pParent )
472 0 : return NULL;
473 :
474 605 : sal_uInt16 nDepth = 0;
475 605 : bool bWithDepth = false;
476 605 : if ( pDepth )
477 : {
478 0 : nDepth = *pDepth;
479 0 : bWithDepth = true;
480 : }
481 :
482 : // Get the list where the current entry belongs to (from its parent).
483 605 : SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
484 605 : sal_uLong nActualPos = pActEntry->GetChildListPos();
485 :
486 605 : if (!pActEntry->maChildren.empty())
487 : {
488 : // The current entry has children. Get its first child entry.
489 14 : nDepth++;
490 14 : pActEntry = &pActEntry->maChildren[0];
491 14 : if ( bWithDepth )
492 0 : *pDepth = nDepth;
493 14 : return pActEntry;
494 : }
495 :
496 591 : if (pActualList->size() > (nActualPos+1))
497 : {
498 : // Get the next sibling of the current entry.
499 526 : pActEntry = &(*pActualList)[nActualPos+1];
500 526 : if ( bWithDepth )
501 0 : *pDepth = nDepth;
502 526 : return pActEntry;
503 : }
504 :
505 : // Move up level(s) until we find the level where the next sibling exists.
506 65 : SvTreeListEntry* pParent = pActEntry->pParent;
507 65 : nDepth--;
508 144 : while( pParent != pRootItem && pParent != 0 )
509 : {
510 : DBG_ASSERT(pParent!=0,"TreeData corrupt!");
511 14 : pActualList = &pParent->pParent->maChildren;
512 14 : nActualPos = pParent->GetChildListPos();
513 14 : if (pActualList->size() > (nActualPos+1))
514 : {
515 0 : pActEntry = &(*pActualList)[nActualPos+1];
516 0 : if ( bWithDepth )
517 0 : *pDepth = nDepth;
518 0 : return pActEntry;
519 : }
520 14 : pParent = pParent->pParent;
521 14 : nDepth--;
522 : }
523 65 : return 0;
524 : }
525 :
526 0 : SvTreeListEntry* SvTreeList::Prev( SvTreeListEntry* pActEntry, sal_uInt16* pDepth ) const
527 : {
528 : DBG_ASSERT(pActEntry!=0,"Entry?");
529 :
530 0 : sal_uInt16 nDepth = 0;
531 0 : bool bWithDepth = false;
532 0 : if ( pDepth )
533 : {
534 0 : nDepth = *pDepth;
535 0 : bWithDepth = true;
536 : }
537 :
538 0 : SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
539 0 : sal_uLong nActualPos = pActEntry->GetChildListPos();
540 :
541 0 : if ( nActualPos > 0 )
542 : {
543 0 : pActEntry = &(*pActualList)[nActualPos-1];
544 0 : while (!pActEntry->maChildren.empty())
545 : {
546 0 : pActualList = &pActEntry->maChildren;
547 0 : nDepth++;
548 0 : pActEntry = &pActualList->back();
549 : }
550 0 : if ( bWithDepth )
551 0 : *pDepth = nDepth;
552 0 : return pActEntry;
553 : }
554 0 : if ( pActEntry->pParent == pRootItem )
555 0 : return 0;
556 :
557 0 : pActEntry = pActEntry->pParent;
558 :
559 0 : if ( pActEntry )
560 : {
561 0 : nDepth--;
562 0 : if ( bWithDepth )
563 0 : *pDepth = nDepth;
564 0 : return pActEntry;
565 : }
566 0 : return 0;
567 : }
568 :
569 19 : SvTreeListEntry* SvTreeList::Last() const
570 : {
571 19 : SvTreeListEntries* pActList = &pRootItem->maChildren;
572 19 : SvTreeListEntry* pEntry = NULL;
573 65 : while (!pActList->empty())
574 : {
575 27 : pEntry = &pActList->back();
576 27 : pActList = &pEntry->maChildren;
577 : }
578 19 : return pEntry;
579 : }
580 :
581 182 : sal_uLong SvTreeList::GetVisiblePos( const SvListView* pView, SvTreeListEntry* pEntry ) const
582 : {
583 : DBG_ASSERT(pView&&pEntry,"View/Entry?");
584 :
585 182 : if ( !pView->bVisPositionsValid )
586 : {
587 : // to make GetVisibleCount refresh the positions
588 2 : const_cast<SvListView*>(pView)->nVisibleCount = 0;
589 2 : GetVisibleCount( const_cast<SvListView*>(pView) );
590 : }
591 182 : const SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
592 182 : return pViewData->nVisPos;
593 : }
594 :
595 830 : sal_uLong SvTreeList::GetVisibleCount( SvListView* pView ) const
596 : {
597 : assert(pView && "GetVisCount:No View");
598 830 : if( !pView->HasViewData() )
599 729 : return 0;
600 101 : if ( pView->nVisibleCount )
601 89 : return pView->nVisibleCount;
602 :
603 12 : sal_uLong nPos = 0;
604 12 : SvTreeListEntry* pEntry = First(); // first entry is always visible
605 129 : while ( pEntry )
606 : {
607 105 : SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
608 105 : pViewData->nVisPos = nPos;
609 105 : nPos++;
610 105 : pEntry = NextVisible( pView, pEntry );
611 : }
612 : #ifdef DBG_UTIL
613 : if( nPos > 10000000 )
614 : {
615 : OSL_FAIL("nVisibleCount bad");
616 : }
617 : #endif
618 12 : pView->nVisibleCount = nPos;
619 12 : pView->bVisPositionsValid = true;
620 12 : return nPos;
621 : }
622 :
623 :
624 : // For performance reasons, this function assumes that the passed entry is
625 : // already visible.
626 460 : SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pActEntry,sal_uInt16* pActDepth) const
627 : {
628 : DBG_ASSERT(pView,"NextVisible:No View");
629 460 : if ( !pActEntry )
630 0 : return 0;
631 :
632 460 : sal_uInt16 nDepth = 0;
633 460 : bool bWithDepth = false;
634 460 : if ( pActDepth )
635 : {
636 0 : nDepth = *pActDepth;
637 0 : bWithDepth = true;
638 : }
639 :
640 460 : SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
641 460 : sal_uLong nActualPos = pActEntry->GetChildListPos();
642 :
643 460 : if ( pView->IsExpanded(pActEntry) )
644 : {
645 : OSL_ENSURE(!pActEntry->maChildren.empty(), "Pass entry is supposed to have child entries.");
646 :
647 29 : nDepth++;
648 29 : pActEntry = &pActEntry->maChildren[0];
649 29 : if ( bWithDepth )
650 0 : *pActDepth = nDepth;
651 29 : return pActEntry;
652 : }
653 :
654 431 : nActualPos++;
655 431 : if ( pActualList->size() > nActualPos )
656 : {
657 370 : pActEntry = &(*pActualList)[nActualPos];
658 370 : if ( bWithDepth )
659 0 : *pActDepth = nDepth;
660 370 : return pActEntry;
661 : }
662 :
663 61 : SvTreeListEntry* pParent = pActEntry->pParent;
664 61 : nDepth--;
665 151 : while( pParent != pRootItem )
666 : {
667 29 : pActualList = &pParent->pParent->maChildren;
668 29 : nActualPos = pParent->GetChildListPos();
669 29 : nActualPos++;
670 29 : if ( pActualList->size() > nActualPos )
671 : {
672 0 : pActEntry = &(*pActualList)[nActualPos];
673 0 : if ( bWithDepth )
674 0 : *pActDepth = nDepth;
675 0 : return pActEntry;
676 : }
677 29 : pParent = pParent->pParent;
678 29 : nDepth--;
679 : }
680 61 : return 0;
681 : }
682 :
683 :
684 : // For performance reasons, this function assumes that the passed entry is
685 : // already visible.
686 :
687 19 : SvTreeListEntry* SvTreeList::PrevVisible(const SvListView* pView, SvTreeListEntry* pActEntry, sal_uInt16* pActDepth) const
688 : {
689 : DBG_ASSERT(pView&&pActEntry,"PrevVis:View/Entry?");
690 :
691 19 : sal_uInt16 nDepth = 0;
692 19 : bool bWithDepth = false;
693 19 : if ( pActDepth )
694 : {
695 0 : nDepth = *pActDepth;
696 0 : bWithDepth = true;
697 : }
698 :
699 19 : SvTreeListEntries* pActualList = &pActEntry->pParent->maChildren;
700 19 : sal_uLong nActualPos = pActEntry->GetChildListPos();
701 :
702 19 : if ( nActualPos > 0 )
703 : {
704 2 : pActEntry = &(*pActualList)[nActualPos-1];
705 4 : while( pView->IsExpanded(pActEntry) )
706 : {
707 0 : pActualList = &pActEntry->maChildren;
708 0 : nDepth++;
709 0 : pActEntry = &pActualList->back();
710 : }
711 2 : if ( bWithDepth )
712 0 : *pActDepth = nDepth;
713 2 : return pActEntry;
714 : }
715 :
716 17 : if ( pActEntry->pParent == pRootItem )
717 15 : return 0;
718 :
719 2 : pActEntry = pActEntry->pParent;
720 2 : if ( pActEntry )
721 : {
722 2 : nDepth--;
723 2 : if ( bWithDepth )
724 0 : *pActDepth = nDepth;
725 2 : return pActEntry;
726 : }
727 0 : return 0;
728 : }
729 :
730 19 : SvTreeListEntry* SvTreeList::LastVisible( const SvListView* pView, sal_uInt16* pDepth) const
731 : {
732 : DBG_ASSERT(pView,"LastVis:No View");
733 19 : SvTreeListEntry* pEntry = Last();
734 42 : while( pEntry && !IsEntryVisible( pView, pEntry ) )
735 4 : pEntry = PrevVisible( pView, pEntry );
736 19 : if ( pEntry && pDepth )
737 0 : *pDepth = GetDepth( pEntry );
738 19 : return pEntry;
739 : }
740 :
741 0 : SvTreeListEntry* SvTreeList::NextVisible(const SvListView* pView,SvTreeListEntry* pEntry,sal_uInt16& nDelta) const
742 : {
743 : DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"NextVis:Wrong Prms/!Vis");
744 :
745 0 : sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
746 : // nDelta entries existent?
747 : // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=5 nDelta=7
748 : // nNewDelta = 10-nVisPos-1 == 4
749 0 : if ( nVisPos+nDelta >= pView->nVisibleCount )
750 : {
751 0 : nDelta = (sal_uInt16)(pView->nVisibleCount-nVisPos);
752 0 : nDelta--;
753 : }
754 0 : sal_uInt16 nDeltaTmp = nDelta;
755 0 : while( nDeltaTmp )
756 : {
757 0 : pEntry = NextVisible( pView, pEntry );
758 0 : nDeltaTmp--;
759 : DBG_ASSERT(pEntry,"Entry?");
760 : }
761 0 : return pEntry;
762 : }
763 :
764 0 : SvTreeListEntry* SvTreeList::PrevVisible( const SvListView* pView, SvTreeListEntry* pEntry, sal_uInt16& nDelta ) const
765 : {
766 : DBG_ASSERT(pView&&pEntry&&IsEntryVisible(pView,pEntry),"PrevVis:Parms/!Vis");
767 :
768 0 : sal_uLong nVisPos = GetVisiblePos( pView, pEntry );
769 : // nDelta entries existent?
770 : // example: 0,1,2,3,4,5,6,7,8,9 nVisPos=8 nDelta=20
771 : // nNewDelta = nNewVisPos
772 0 : if ( nDelta > nVisPos )
773 0 : nDelta = (sal_uInt16)nVisPos;
774 0 : sal_uInt16 nDeltaTmp = nDelta;
775 0 : while( nDeltaTmp )
776 : {
777 0 : pEntry = PrevVisible( pView, pEntry );
778 0 : nDeltaTmp--;
779 : DBG_ASSERT(pEntry,"Entry?");
780 : }
781 0 : return pEntry;
782 : }
783 :
784 198 : SvTreeListEntry* SvTreeList::FirstSelected( const SvListView* pView) const
785 : {
786 : DBG_ASSERT(pView,"FirstSel:No View");
787 198 : if( !pView )
788 0 : return 0;
789 198 : SvTreeListEntry* pActSelEntry = First();
790 468 : while( pActSelEntry && !pView->IsSelected(pActSelEntry) )
791 72 : pActSelEntry = NextVisible( pView, pActSelEntry );
792 198 : return pActSelEntry;
793 : }
794 :
795 :
796 155 : SvTreeListEntry* SvTreeList::FirstChild( SvTreeListEntry* pParent ) const
797 : {
798 155 : if ( !pParent )
799 73 : pParent = pRootItem;
800 : SvTreeListEntry* pResult;
801 155 : if (!pParent->maChildren.empty())
802 83 : pResult = &pParent->maChildren[0];
803 : else
804 72 : pResult = 0;
805 155 : return pResult;
806 : }
807 :
808 31 : SvTreeListEntry* SvTreeList::NextSibling( SvTreeListEntry* pEntry )
809 : {
810 : DBG_ASSERT(pEntry,"Entry?");
811 31 : if( !pEntry )
812 0 : return 0;
813 :
814 31 : SvTreeListEntries& rList = pEntry->pParent->maChildren;
815 31 : sal_uLong nPos = pEntry->GetChildListPos();
816 31 : nPos++;
817 31 : return nPos < rList.size() ? &rList[nPos] : NULL;
818 : }
819 :
820 0 : SvTreeListEntry* SvTreeList::PrevSibling( SvTreeListEntry* pEntry )
821 : {
822 : DBG_ASSERT(pEntry,"Entry?");
823 0 : if( !pEntry )
824 0 : return 0;
825 :
826 0 : SvTreeListEntries& rList = pEntry->pParent->maChildren;
827 0 : sal_uLong nPos = pEntry->GetChildListPos();
828 0 : if ( nPos == 0 )
829 0 : return 0;
830 0 : nPos--;
831 0 : pEntry = &rList[nPos];
832 0 : return pEntry;
833 : }
834 :
835 :
836 18 : SvTreeListEntry* SvTreeList::LastSibling( SvTreeListEntry* pEntry )
837 : {
838 : DBG_ASSERT(pEntry,"LastSibling:Entry?");
839 18 : if( !pEntry )
840 0 : return 0;
841 :
842 18 : SvTreeListEntries& rChildren = pEntry->pParent->maChildren;
843 18 : return rChildren.empty() ? NULL : &rChildren.back();
844 : }
845 :
846 1 : SvTreeListEntry* SvTreeList::NextSelected( const SvListView* pView, SvTreeListEntry* pEntry ) const
847 : {
848 : DBG_ASSERT(pView&&pEntry,"NextSel:View/Entry?");
849 1 : pEntry = Next( pEntry );
850 2 : while( pEntry && !pView->IsSelected(pEntry) )
851 0 : pEntry = Next( pEntry );
852 1 : return pEntry;
853 : }
854 :
855 0 : SvTreeListEntry* SvTreeList::PrevSelected( const SvListView* pView, SvTreeListEntry* pEntry) const
856 : {
857 : DBG_ASSERT(pView&&pEntry,"PrevSel:View/Entry?");
858 0 : pEntry = Prev( pEntry );
859 0 : while( pEntry && !pView->IsSelected(pEntry) )
860 0 : pEntry = Prev( pEntry );
861 :
862 0 : return pEntry;
863 : }
864 :
865 0 : SvTreeListEntry* SvTreeList::LastSelected( const SvListView* pView ) const
866 : {
867 : DBG_ASSERT(pView,"LastSel:No View");
868 0 : SvTreeListEntry* pEntry = Last();
869 0 : while( pEntry && !pView->IsSelected(pEntry) )
870 0 : pEntry = Prev( pEntry );
871 0 : return pEntry;
872 : }
873 :
874 101 : sal_uLong SvTreeList::Insert( SvTreeListEntry* pEntry,SvTreeListEntry* pParent,sal_uLong nPos )
875 : {
876 : DBG_ASSERT( pEntry,"Entry?");
877 :
878 101 : if ( !pParent )
879 0 : pParent = pRootItem;
880 :
881 :
882 101 : SvTreeListEntries& rList = pParent->maChildren;
883 :
884 : // take sorting into account
885 101 : GetInsertionPos( pEntry, pParent, nPos );
886 :
887 101 : bAbsPositionsValid = false;
888 101 : pEntry->pParent = pParent;
889 :
890 101 : if (nPos < rList.size())
891 : {
892 0 : SvTreeListEntries::iterator itPos = rList.begin();
893 0 : std::advance(itPos, nPos);
894 0 : rList.insert(itPos, pEntry);
895 : }
896 : else
897 101 : rList.push_back(pEntry);
898 :
899 101 : nEntryCount++;
900 101 : if (nPos != TREELIST_APPEND && (nPos != (rList.size()-1)))
901 0 : SetListPositions(rList);
902 : else
903 101 : pEntry->nListPos = rList.size()-1;
904 :
905 101 : Broadcast( SvListAction::INSERTED, pEntry );
906 101 : return nPos; // pEntry->nListPos;
907 : }
908 :
909 0 : sal_uLong SvTreeList::GetAbsPos( const SvTreeListEntry* pEntry) const
910 : {
911 0 : if ( !bAbsPositionsValid )
912 0 : const_cast<SvTreeList*>(this)->SetAbsolutePositions();
913 0 : return pEntry->nAbsPos;
914 : }
915 :
916 0 : sal_uLong SvTreeList::GetRelPos( const SvTreeListEntry* pChild )
917 : {
918 0 : return pChild->GetChildListPos();
919 : }
920 :
921 0 : void SvTreeList::SetAbsolutePositions()
922 : {
923 0 : sal_uLong nPos = 0;
924 0 : SvTreeListEntry* pEntry = First();
925 0 : while ( pEntry )
926 : {
927 0 : pEntry->nAbsPos = nPos;
928 0 : nPos++;
929 0 : pEntry = Next( pEntry );
930 : }
931 0 : bAbsPositionsValid = true;
932 0 : }
933 :
934 2 : void SvTreeList::Expand( SvListView* pView, SvTreeListEntry* pEntry )
935 : {
936 : DBG_ASSERT(pEntry&&pView,"Expand:View/Entry?");
937 2 : if ( pView->IsExpanded(pEntry) )
938 2 : return;
939 :
940 : DBG_ASSERT(!pEntry->maChildren.empty(), "SvTreeList::Expand: We expected to have child entries.");
941 :
942 2 : SvViewDataEntry* pViewData = pView->GetViewData(pEntry);
943 2 : pViewData->SetExpanded(true);
944 2 : SvTreeListEntry* pParent = pEntry->pParent;
945 : // if parent is visible, invalidate status data
946 2 : if ( pView->IsExpanded( pParent ) )
947 : {
948 2 : pView->bVisPositionsValid = false;
949 2 : pView->nVisibleCount = 0;
950 : }
951 : }
952 :
953 0 : void SvTreeList::Collapse( SvListView* pView, SvTreeListEntry* pEntry )
954 : {
955 : DBG_ASSERT(pView&&pEntry,"Collapse:View/Entry?");
956 0 : if ( !pView->IsExpanded(pEntry) )
957 0 : return;
958 :
959 : DBG_ASSERT(!pEntry->maChildren.empty(), "SvTreeList::Collapse: We expected have child entries.");
960 :
961 0 : SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
962 0 : pViewData->SetExpanded(false);
963 :
964 0 : SvTreeListEntry* pParent = pEntry->pParent;
965 0 : if ( pView->IsExpanded(pParent) )
966 : {
967 0 : pView->nVisibleCount = 0;
968 0 : pView->bVisPositionsValid = false;
969 : }
970 : }
971 :
972 13 : bool SvTreeList::Select( SvListView* pView, SvTreeListEntry* pEntry, bool bSelect )
973 : {
974 : DBG_ASSERT(pView&&pEntry,"Select:View/Entry?");
975 13 : SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
976 13 : if ( bSelect )
977 : {
978 12 : if ( pViewData->IsSelected() || !pViewData->IsSelectable() )
979 2 : return false;
980 : else
981 : {
982 10 : pViewData->SetSelected(true);
983 10 : pView->nSelectionCount++;
984 : }
985 : }
986 : else
987 : {
988 1 : if ( !pViewData->IsSelected() )
989 0 : return false;
990 : else
991 : {
992 1 : pViewData->SetSelected(false);
993 1 : pView->nSelectionCount--;
994 : }
995 : }
996 11 : return true;
997 : }
998 :
999 0 : bool SvTreeList::Remove( const SvTreeListEntry* pEntry )
1000 : {
1001 : DBG_ASSERT(pEntry,"Cannot remove root, use clear");
1002 :
1003 0 : if( !pEntry->pParent )
1004 : {
1005 : OSL_FAIL("Removing entry not in model!");
1006 : // Under certain circumstances (which?), the explorer deletes entries
1007 : // from the view that it hasn't inserted into the view. We don't want
1008 : // to crash, so we catch this case here.
1009 0 : return false;
1010 : }
1011 :
1012 0 : Broadcast(SvListAction::REMOVING, const_cast<SvTreeListEntry*>(pEntry));
1013 0 : sal_uLong nRemoved = 1 + GetChildCount(pEntry);
1014 0 : bAbsPositionsValid = false;
1015 :
1016 0 : SvTreeListEntry* pParent = pEntry->pParent;
1017 0 : SvTreeListEntries& rList = pParent->maChildren;
1018 0 : bool bLastEntry = false;
1019 :
1020 : // Since we need the live instance of SvTreeListEntry for broadcasting,
1021 : // we first need to pop it from the container, broadcast it, then delete
1022 : // the instance manually at the end.
1023 :
1024 0 : if ( pEntry->HasChildListPos() )
1025 : {
1026 0 : size_t nListPos = pEntry->GetChildListPos();
1027 0 : bLastEntry = (nListPos == (rList.size()-1));
1028 0 : SvTreeListEntries::iterator it = rList.begin();
1029 0 : std::advance(it, nListPos);
1030 0 : rList.release(it).release();
1031 : }
1032 : else
1033 : {
1034 : SvTreeListEntries::iterator it =
1035 0 : std::find_if(rList.begin(), rList.end(), FindByPointer(pEntry));
1036 0 : if (it != rList.end())
1037 0 : rList.release(it).release();
1038 : }
1039 :
1040 0 : if (!rList.empty() && !bLastEntry)
1041 0 : SetListPositions(rList);
1042 :
1043 0 : nEntryCount -= nRemoved;
1044 0 : Broadcast(SvListAction::REMOVED, const_cast<SvTreeListEntry*>(pEntry));
1045 0 : delete pEntry;
1046 :
1047 0 : return true;
1048 : }
1049 :
1050 0 : void SvTreeList::SelectAll( SvListView* pView, bool bSelect )
1051 : {
1052 : assert(pView && "SelectAll:NoView");
1053 0 : SvTreeListEntry* pEntry = First();
1054 0 : while ( pEntry )
1055 : {
1056 0 : SvViewDataEntry* pViewData = pView->GetViewData( pEntry );
1057 0 : pViewData->SetSelected(bSelect);
1058 0 : pEntry = Next( pEntry );
1059 : }
1060 0 : if ( bSelect )
1061 0 : pView->nSelectionCount = nEntryCount;
1062 : else
1063 0 : pView->nSelectionCount = 0;
1064 0 : }
1065 :
1066 :
1067 0 : SvTreeListEntry* SvTreeList::GetEntryAtAbsPos( sal_uLong nAbsPos ) const
1068 : {
1069 0 : SvTreeListEntry* pEntry = First();
1070 0 : while ( nAbsPos && pEntry )
1071 : {
1072 0 : pEntry = Next( pEntry );
1073 0 : nAbsPos--;
1074 : }
1075 0 : return pEntry;
1076 : }
1077 :
1078 165 : SvTreeListEntry* SvTreeList::GetEntryAtVisPos( const SvListView* pView, sal_uLong nVisPos ) const
1079 : {
1080 : DBG_ASSERT(pView,"GetEntryAtVisPos:No View");
1081 165 : SvTreeListEntry* pEntry = First();
1082 330 : while ( nVisPos && pEntry )
1083 : {
1084 0 : pEntry = NextVisible( pView, pEntry );
1085 0 : nVisPos--;
1086 : }
1087 165 : return pEntry;
1088 : }
1089 :
1090 0 : void SvTreeList::SetListPositions( SvTreeListEntries& rEntries )
1091 : {
1092 0 : if (rEntries.empty())
1093 0 : return;
1094 :
1095 0 : SvTreeListEntry& rFirst = rEntries.front();
1096 0 : if (rFirst.pParent)
1097 0 : rFirst.pParent->InvalidateChildrensListPositions();
1098 : }
1099 :
1100 0 : void SvTreeList::EnableInvalidate( bool bEnable )
1101 : {
1102 0 : mbEnableInvalidate = bEnable;
1103 0 : }
1104 :
1105 7 : void SvTreeList::InvalidateEntry( SvTreeListEntry* pEntry )
1106 : {
1107 7 : if (!mbEnableInvalidate)
1108 7 : return;
1109 :
1110 7 : Broadcast( SvListAction::INVALIDATE_ENTRY, pEntry );
1111 : }
1112 :
1113 6 : SvTreeListEntry* SvTreeList::GetRootLevelParent( SvTreeListEntry* pEntry ) const
1114 : {
1115 : DBG_ASSERT(pEntry,"GetRootLevelParent:No Entry");
1116 6 : SvTreeListEntry* pCurParent = 0;
1117 6 : if ( pEntry )
1118 : {
1119 6 : pCurParent = pEntry->pParent;
1120 6 : if ( pCurParent == pRootItem )
1121 1 : return pEntry; // is its own parent
1122 11 : while( pCurParent && pCurParent->pParent != pRootItem )
1123 1 : pCurParent = pCurParent->pParent;
1124 : }
1125 5 : return pCurParent;
1126 : }
1127 :
1128 : std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator>
1129 4 : SvTreeList::GetChildIterators(SvTreeListEntry* pParent)
1130 : {
1131 : typedef std::pair<SvTreeListEntries::iterator, SvTreeListEntries::iterator> IteratorPair;
1132 :
1133 4 : static SvTreeListEntries dummy; // prevent singular iterator asserts
1134 4 : IteratorPair aRet(dummy.begin(), dummy.end());
1135 :
1136 4 : if (!pParent)
1137 2 : pParent = pRootItem;
1138 :
1139 4 : if (pParent->maChildren.empty())
1140 : // This entry has no children.
1141 1 : return aRet;
1142 :
1143 3 : aRet.first = pParent->maChildren.begin();
1144 3 : aRet.second = pParent->maChildren.end();
1145 :
1146 3 : return aRet;
1147 : }
1148 :
1149 :
1150 28 : SvListView::SvListView()
1151 : {
1152 28 : pModel = 0;
1153 28 : nSelectionCount = 0;
1154 28 : nVisibleCount = 0;
1155 28 : bVisPositionsValid = false;
1156 28 : }
1157 :
1158 :
1159 52 : SvListView::~SvListView()
1160 : {
1161 26 : maDataTable.clear();
1162 26 : }
1163 :
1164 30 : void SvListView::InitTable()
1165 : {
1166 : DBG_ASSERT(pModel,"InitTable:No Model");
1167 : DBG_ASSERT(!nSelectionCount&&!nVisibleCount&&!bVisPositionsValid,"InitTable: Not cleared!");
1168 :
1169 30 : if( maDataTable.size() )
1170 : {
1171 : DBG_ASSERT(maDataTable.size()==1,"InitTable: TableCount != 1");
1172 : // Delete the view data allocated to the Clear in the root.
1173 : // Attention: The model belonging to the root entry (and thus the entry
1174 : // itself) might already be deleted.
1175 2 : maDataTable.clear();
1176 : }
1177 :
1178 : SvTreeListEntry* pEntry;
1179 : SvViewDataEntry* pViewData;
1180 :
1181 : // insert root entry
1182 30 : pEntry = pModel->pRootItem;
1183 30 : pViewData = new SvViewDataEntry;
1184 30 : pViewData->SetExpanded(true);
1185 30 : maDataTable.insert( pEntry, pViewData );
1186 : // now all the other entries
1187 30 : pEntry = pModel->First();
1188 60 : while( pEntry )
1189 : {
1190 0 : pViewData = CreateViewData( pEntry );
1191 : DBG_ASSERT(pViewData,"InitTable:No ViewData");
1192 0 : InitViewData( pViewData, pEntry );
1193 0 : maDataTable.insert( pEntry, pViewData );
1194 0 : pEntry = pModel->Next( pEntry );
1195 : }
1196 30 : }
1197 :
1198 0 : SvViewDataEntry* SvListView::CreateViewData( SvTreeListEntry* )
1199 : {
1200 0 : return new SvViewDataEntry;
1201 : }
1202 :
1203 66 : void SvListView::Clear()
1204 : {
1205 66 : maDataTable.clear();
1206 66 : nSelectionCount = 0;
1207 66 : nVisibleCount = 0;
1208 66 : bVisPositionsValid = false;
1209 66 : if( pModel )
1210 : {
1211 : // insert root entry
1212 66 : SvTreeListEntry* pEntry = pModel->pRootItem;
1213 66 : SvViewDataEntry* pViewData = new SvViewDataEntry;
1214 66 : pViewData->SetExpanded(true);
1215 66 : maDataTable.insert( pEntry, pViewData );
1216 : }
1217 66 : }
1218 :
1219 30 : void SvListView::SetModel( SvTreeList* pNewModel )
1220 : {
1221 30 : bool bBroadcastCleared = false;
1222 30 : if ( pModel )
1223 : {
1224 2 : pModel->RemoveView( this );
1225 2 : bBroadcastCleared = true;
1226 2 : ModelNotification( SvListAction::CLEARING,0,0,0 );
1227 2 : if ( pModel->GetRefCount() == 0 )
1228 1 : delete pModel;
1229 : }
1230 30 : pModel = pNewModel;
1231 30 : InitTable();
1232 30 : pNewModel->InsertView( this );
1233 30 : if( bBroadcastCleared )
1234 2 : ModelNotification( SvListAction::CLEARED,0,0,0 );
1235 30 : }
1236 :
1237 :
1238 66 : void SvListView::ModelHasCleared()
1239 : {
1240 66 : }
1241 :
1242 0 : void SvListView::ModelHasInserted( SvTreeListEntry* )
1243 : {
1244 0 : }
1245 :
1246 0 : void SvListView::ModelHasInsertedTree( SvTreeListEntry* )
1247 : {
1248 0 : }
1249 :
1250 0 : void SvListView::ModelIsMoving( SvTreeListEntry* /* pSource */ ,
1251 : SvTreeListEntry* /* pTargetParent */ , sal_uLong /* nPos */ )
1252 : {
1253 0 : }
1254 :
1255 :
1256 0 : void SvListView::ModelHasMoved( SvTreeListEntry* )
1257 : {
1258 0 : }
1259 :
1260 0 : void SvListView::ModelIsRemoving( SvTreeListEntry* )
1261 : {
1262 0 : }
1263 :
1264 0 : void SvListView::ModelHasRemoved( SvTreeListEntry* )
1265 : {
1266 : //WARNING WARNING WARNING
1267 : //The supplied pointer should have been deleted
1268 : //before this call. Be careful not to use it!!!
1269 0 : }
1270 :
1271 0 : void SvListView::ModelHasEntryInvalidated( SvTreeListEntry*)
1272 : {
1273 0 : }
1274 :
1275 0 : void SvListView::ActionMoving( SvTreeListEntry* pEntry,SvTreeListEntry*,sal_uLong)
1276 : {
1277 0 : SvTreeListEntry* pParent = pEntry->pParent;
1278 : DBG_ASSERT(pParent,"Model not consistent");
1279 0 : if (pParent != pModel->pRootItem && pParent->maChildren.size() == 1)
1280 : {
1281 0 : SvViewDataEntry* pViewData = maDataTable.find( pParent )->second;
1282 0 : pViewData->SetExpanded(false);
1283 : }
1284 : // vorlaeufig
1285 0 : nVisibleCount = 0;
1286 0 : bVisPositionsValid = false;
1287 0 : }
1288 :
1289 0 : void SvListView::ActionMoved( SvTreeListEntry* /* pEntry */ ,
1290 : SvTreeListEntry* /* pTargetPrnt */ ,
1291 : sal_uLong /* nChildPos */ )
1292 : {
1293 0 : nVisibleCount = 0;
1294 0 : bVisPositionsValid = false;
1295 0 : }
1296 :
1297 101 : void SvListView::ActionInserted( SvTreeListEntry* pEntry )
1298 : {
1299 : DBG_ASSERT(pEntry,"Insert:No Entry");
1300 101 : SvViewDataEntry* pData = CreateViewData( pEntry );
1301 101 : InitViewData( pData, pEntry );
1302 : #ifdef DBG_UTIL
1303 : std::pair<SvDataTable::iterator, bool> aSuccess =
1304 : #endif
1305 101 : maDataTable.insert( pEntry, pData );
1306 : DBG_ASSERT(aSuccess.second,"Entry already in View");
1307 101 : if ( nVisibleCount && pModel->IsEntryVisible( this, pEntry ))
1308 : {
1309 0 : nVisibleCount = 0;
1310 0 : bVisPositionsValid = false;
1311 : }
1312 101 : }
1313 :
1314 0 : void SvListView::ActionInsertedTree( SvTreeListEntry* pEntry )
1315 : {
1316 0 : if ( pModel->IsEntryVisible( this, pEntry ))
1317 : {
1318 0 : nVisibleCount = 0;
1319 0 : bVisPositionsValid = false;
1320 : }
1321 : // iterate over entry and its children
1322 0 : SvTreeListEntry* pCurEntry = pEntry;
1323 0 : sal_uInt16 nRefDepth = pModel->GetDepth( pCurEntry );
1324 0 : while( pCurEntry )
1325 : {
1326 : DBG_ASSERT(maDataTable.find(pCurEntry) != maDataTable.end(),"Entry already in Table");
1327 0 : SvViewDataEntry* pViewData = CreateViewData( pCurEntry );
1328 : DBG_ASSERT(pViewData,"No ViewData");
1329 0 : InitViewData( pViewData, pEntry );
1330 0 : maDataTable.insert( pCurEntry, pViewData );
1331 0 : pCurEntry = pModel->Next( pCurEntry );
1332 0 : if ( pCurEntry && pModel->GetDepth(pCurEntry) <= nRefDepth)
1333 0 : pCurEntry = 0;
1334 : }
1335 0 : }
1336 :
1337 0 : void SvListView::RemoveViewData( SvTreeListEntry* pParent )
1338 : {
1339 0 : SvTreeListEntries::iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
1340 0 : for (; it != itEnd; ++it)
1341 : {
1342 0 : SvTreeListEntry& rEntry = *it;
1343 0 : maDataTable.erase(&rEntry);
1344 0 : if (rEntry.HasChildren())
1345 0 : RemoveViewData(&rEntry);
1346 : }
1347 0 : }
1348 :
1349 :
1350 :
1351 0 : void SvListView::ActionRemoving( SvTreeListEntry* pEntry )
1352 : {
1353 : DBG_ASSERT(pEntry,"Remove:No Entry");
1354 :
1355 0 : SvViewDataEntry* pViewData = maDataTable.find( pEntry )->second;
1356 0 : sal_uLong nSelRemoved = 0;
1357 0 : if ( pViewData->IsSelected() )
1358 0 : nSelRemoved = 1 + pModel->GetChildSelectionCount( this, pEntry );
1359 0 : nSelectionCount -= nSelRemoved;
1360 0 : sal_uLong nVisibleRemoved = 0;
1361 0 : if ( pModel->IsEntryVisible( this, pEntry ) )
1362 0 : nVisibleRemoved = 1 + pModel->GetVisibleChildCount( this, pEntry );
1363 0 : if( nVisibleCount )
1364 : {
1365 : #ifdef DBG_UTIL
1366 : if( nVisibleCount < nVisibleRemoved )
1367 : {
1368 : OSL_FAIL("nVisibleRemoved bad");
1369 : }
1370 : #endif
1371 0 : nVisibleCount -= nVisibleRemoved;
1372 : }
1373 0 : bVisPositionsValid = false;
1374 :
1375 0 : maDataTable.erase(pEntry);
1376 0 : RemoveViewData( pEntry );
1377 :
1378 0 : SvTreeListEntry* pCurEntry = pEntry->pParent;
1379 0 : if (pCurEntry && pCurEntry != pModel->pRootItem && pCurEntry->maChildren.size() == 1)
1380 : {
1381 0 : pViewData = maDataTable.find(pCurEntry)->second;
1382 0 : pViewData->SetExpanded(false);
1383 : }
1384 0 : }
1385 :
1386 66 : void SvListView::ActionClear()
1387 : {
1388 66 : Clear();
1389 66 : }
1390 :
1391 240 : void SvListView::ModelNotification( SvListAction nActionId, SvTreeListEntry* pEntry1,
1392 : SvTreeListEntry* pEntry2, sal_uLong nPos )
1393 : {
1394 240 : switch( nActionId )
1395 : {
1396 : case SvListAction::INSERTED:
1397 101 : ActionInserted( pEntry1 );
1398 101 : ModelHasInserted( pEntry1 );
1399 101 : break;
1400 : case SvListAction::INSERTED_TREE:
1401 0 : ActionInsertedTree( pEntry1 );
1402 0 : ModelHasInsertedTree( pEntry1 );
1403 0 : break;
1404 : case SvListAction::REMOVING:
1405 0 : ModelIsRemoving( pEntry1 );
1406 0 : ActionRemoving( pEntry1 );
1407 0 : break;
1408 : case SvListAction::REMOVED:
1409 0 : ModelHasRemoved( pEntry1 );
1410 0 : break;
1411 : case SvListAction::MOVING:
1412 0 : ModelIsMoving( pEntry1, pEntry2, nPos );
1413 0 : ActionMoving( pEntry1, pEntry2, nPos );
1414 0 : break;
1415 : case SvListAction::MOVED:
1416 0 : ActionMoved( pEntry1, pEntry2, nPos );
1417 0 : ModelHasMoved( pEntry1 );
1418 0 : break;
1419 : case SvListAction::CLEARING:
1420 66 : ActionClear();
1421 66 : ModelHasCleared(); // sic! for compatibility reasons!
1422 66 : break;
1423 : case SvListAction::CLEARED:
1424 66 : break;
1425 : case SvListAction::INVALIDATE_ENTRY:
1426 : // no action for the base class
1427 7 : ModelHasEntryInvalidated( pEntry1 );
1428 7 : break;
1429 : case SvListAction::RESORTED:
1430 0 : bVisPositionsValid = false;
1431 0 : break;
1432 : case SvListAction::RESORTING:
1433 0 : break;
1434 : case SvListAction::REVERSING:
1435 0 : break;
1436 : case SvListAction::REVERSED:
1437 0 : bVisPositionsValid = false;
1438 0 : break;
1439 : default:
1440 : OSL_FAIL("unknown ActionId");
1441 : }
1442 240 : }
1443 :
1444 0 : void SvListView::InitViewData( SvViewDataEntry*, SvTreeListEntry* )
1445 : {
1446 0 : }
1447 :
1448 1011 : bool SvListView::IsExpanded( SvTreeListEntry* pEntry ) const
1449 : {
1450 : DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1451 1011 : SvDataTable::const_iterator itr = maDataTable.find(pEntry);
1452 : DBG_ASSERT(itr != maDataTable.end(),"Entry not in Table");
1453 1011 : if (itr == maDataTable.end())
1454 0 : return false;
1455 1011 : return itr->second->IsExpanded();
1456 : }
1457 :
1458 119 : bool SvListView::IsSelected( SvTreeListEntry* pEntry ) const
1459 : {
1460 : DBG_ASSERT(pEntry,"IsExpanded:No Entry");
1461 119 : SvDataTable::const_iterator itr = maDataTable.find(pEntry );
1462 119 : if (itr == maDataTable.end())
1463 0 : return false;
1464 119 : return itr->second->IsSelected();
1465 : }
1466 :
1467 7 : void SvListView::SetEntryFocus( SvTreeListEntry* pEntry, bool bFocus )
1468 : {
1469 : DBG_ASSERT(pEntry,"SetEntryFocus:No Entry");
1470 7 : SvDataTable::iterator itr = maDataTable.find(pEntry);
1471 : DBG_ASSERT(itr != maDataTable.end(),"Entry not in Table");
1472 7 : itr->second->SetFocus(bFocus);
1473 7 : }
1474 :
1475 974 : const SvViewDataEntry* SvListView::GetViewData( const SvTreeListEntry* pEntry ) const
1476 : {
1477 974 : SvDataTable::const_iterator itr = maDataTable.find( const_cast<SvTreeListEntry*>(pEntry) );
1478 974 : if (itr == maDataTable.end())
1479 0 : return NULL;
1480 974 : return itr->second;
1481 : }
1482 :
1483 120 : SvViewDataEntry* SvListView::GetViewData( SvTreeListEntry* pEntry )
1484 : {
1485 120 : SvDataTable::iterator itr = maDataTable.find( pEntry );
1486 : DBG_ASSERT(itr != maDataTable.end(),"Entry not in model or wrong view");
1487 120 : return itr->second;
1488 : }
1489 :
1490 1 : sal_Int32 SvTreeList::Compare(const SvTreeListEntry* pLeft, const SvTreeListEntry* pRight) const
1491 : {
1492 1 : if( aCompareLink.IsSet())
1493 : {
1494 : SvSortData aSortData;
1495 1 : aSortData.pLeft = pLeft;
1496 1 : aSortData.pRight = pRight;
1497 1 : return aCompareLink.Call( &aSortData );
1498 : }
1499 0 : return 0;
1500 : }
1501 :
1502 0 : void SvTreeList::Resort()
1503 : {
1504 0 : Broadcast( SvListAction::RESORTING );
1505 0 : bAbsPositionsValid = false;
1506 0 : ResortChildren( pRootItem );
1507 0 : Broadcast( SvListAction::RESORTED );
1508 0 : }
1509 :
1510 : namespace {
1511 :
1512 : class SortComparator : public std::binary_function<SvTreeListEntry,SvTreeListEntry,bool>
1513 : {
1514 : SvTreeList& mrList;
1515 : public:
1516 :
1517 0 : explicit SortComparator( SvTreeList& rList ) : mrList(rList) {}
1518 :
1519 0 : bool operator() ( const SvTreeListEntry& rLeft, const SvTreeListEntry& rRight ) const
1520 : {
1521 0 : return mrList.Compare(&rLeft, &rRight) < 0;
1522 : }
1523 : };
1524 :
1525 : }
1526 :
1527 0 : void SvTreeList::ResortChildren( SvTreeListEntry* pParent )
1528 : {
1529 : DBG_ASSERT(pParent,"Parent not set");
1530 :
1531 0 : if (pParent->maChildren.empty())
1532 0 : return;
1533 :
1534 0 : SortComparator aComp(*this);
1535 0 : pParent->maChildren.sort(aComp);
1536 :
1537 : // Recursively sort child entries.
1538 0 : SvTreeListEntries::iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
1539 0 : for (; it != itEnd; ++it)
1540 : {
1541 0 : SvTreeListEntry& r = *it;
1542 0 : ResortChildren(&r);
1543 : }
1544 :
1545 0 : SetListPositions(pParent->maChildren); // correct list position in target list
1546 : }
1547 :
1548 0 : void SvTreeList::Reverse()
1549 : {
1550 0 : Broadcast(SvListAction::REVERSING);
1551 0 : bAbsPositionsValid = false;
1552 0 : ReverseChildren(pRootItem);
1553 0 : Broadcast(SvListAction::REVERSED);
1554 0 : }
1555 :
1556 0 : void SvTreeList::ReverseChildren( SvTreeListEntry* pParent )
1557 : {
1558 : DBG_ASSERT(pParent,"Parent not set");
1559 :
1560 0 : if (pParent->maChildren.empty())
1561 0 : return;
1562 :
1563 0 : std::reverse(pParent->maChildren.base().begin(), pParent->maChildren.base().end());
1564 : // Recursively sort child entries.
1565 0 : SvTreeListEntries::iterator it = pParent->maChildren.begin(), itEnd = pParent->maChildren.end();
1566 0 : for (; it != itEnd; ++it)
1567 : {
1568 0 : SvTreeListEntry& r = *it;
1569 0 : ReverseChildren(&r);
1570 : }
1571 :
1572 0 : SetListPositions(pParent->maChildren); // correct list position in target list
1573 : }
1574 :
1575 101 : void SvTreeList::GetInsertionPos( SvTreeListEntry* pEntry, SvTreeListEntry* pParent,
1576 : sal_uLong& rPos )
1577 : {
1578 : DBG_ASSERT(pEntry,"No Entry");
1579 :
1580 101 : if( eSortMode == SortNone )
1581 198 : return;
1582 :
1583 4 : rPos = TREELIST_ENTRY_NOTFOUND;
1584 4 : const SvTreeListEntries& rChildList = GetChildList(pParent);
1585 :
1586 4 : if (!rChildList.empty())
1587 : {
1588 1 : long i = 0;
1589 1 : long j = rChildList.size()-1;
1590 : long k;
1591 1 : sal_Int32 nCompare = 1;
1592 :
1593 1 : do
1594 : {
1595 1 : k = (i+j)/2;
1596 1 : const SvTreeListEntry* pTempEntry = &rChildList[k];
1597 1 : nCompare = Compare( pEntry, pTempEntry );
1598 1 : if( eSortMode == SortDescending && nCompare != 0 )
1599 : {
1600 0 : if( nCompare < 0 )
1601 0 : nCompare = 1;
1602 : else
1603 0 : nCompare = -1;
1604 : }
1605 1 : if( nCompare > 0 )
1606 1 : i = k + 1;
1607 : else
1608 0 : j = k - 1;
1609 1 : } while( (nCompare != 0) && (i <= j) );
1610 :
1611 1 : if( nCompare != 0 )
1612 : {
1613 1 : if (i > static_cast<long>(rChildList.size()-1)) // not found, end of list
1614 1 : rPos = TREELIST_ENTRY_NOTFOUND;
1615 : else
1616 0 : rPos = i; // not found, middle of list
1617 : }
1618 : else
1619 0 : rPos = k;
1620 : }
1621 : }
1622 :
1623 0 : bool SvTreeList::HasChildren( const SvTreeListEntry* pEntry ) const
1624 : {
1625 0 : if ( !pEntry )
1626 0 : pEntry = pRootItem;
1627 :
1628 0 : return !pEntry->maChildren.empty();
1629 : }
1630 :
1631 0 : bool SvTreeList::HasParent( const SvTreeListEntry* pEntry ) const
1632 : {
1633 0 : return pEntry->pParent != pRootItem;
1634 : }
1635 :
1636 409 : SvTreeListEntry* SvTreeList::GetEntry( SvTreeListEntry* pParent, sal_uLong nPos ) const
1637 409 : { if ( !pParent )
1638 342 : pParent = pRootItem;
1639 409 : SvTreeListEntry* pRet = 0;
1640 409 : if (nPos < pParent->maChildren.size())
1641 407 : pRet = &pParent->maChildren[nPos];
1642 409 : return pRet;
1643 : }
1644 :
1645 129 : SvTreeListEntry* SvTreeList::GetEntry( sal_uLong nRootPos ) const
1646 : {
1647 129 : SvTreeListEntry* pRet = 0;
1648 129 : if ( nEntryCount && nRootPos < pRootItem->maChildren.size())
1649 129 : pRet = &pRootItem->maChildren[nRootPos];
1650 129 : return pRet;
1651 : }
1652 :
1653 0 : const SvTreeListEntries& SvTreeList::GetChildList( SvTreeListEntry* pParent ) const
1654 : {
1655 0 : if ( !pParent )
1656 0 : pParent = pRootItem;
1657 0 : return pParent->maChildren;
1658 : }
1659 :
1660 9 : SvTreeListEntries& SvTreeList::GetChildList( SvTreeListEntry* pParent )
1661 : {
1662 9 : if ( !pParent )
1663 0 : pParent = pRootItem;
1664 9 : return pParent->maChildren;
1665 : }
1666 :
1667 0 : const SvTreeListEntry* SvTreeList::GetParent( const SvTreeListEntry* pEntry ) const
1668 : {
1669 0 : const SvTreeListEntry* pParent = pEntry->pParent;
1670 0 : if (pParent == pRootItem)
1671 0 : pParent = NULL;
1672 0 : return pParent;
1673 : }
1674 :
1675 518 : SvTreeListEntry* SvTreeList::GetParent( SvTreeListEntry* pEntry )
1676 : {
1677 518 : SvTreeListEntry* pParent = pEntry->pParent;
1678 518 : if (pParent == pRootItem)
1679 504 : pParent = NULL;
1680 518 : return pParent;
1681 798 : }
1682 :
1683 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|