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