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