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