1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: OutlineListView.cpp 23 // Author: Marc Flerackers (mflerackers@androme.be) 24 // Description: BOutlineListView represents a "nestable" list view. 25 //------------------------------------------------------------------------------ 26 27 // Standard Includes ----------------------------------------------------------- 28 29 // System Includes ------------------------------------------------------------- 30 #include <OutlineListView.h> 31 #include <stdio.h> 32 33 // Project Includes ------------------------------------------------------------ 34 35 // Local Includes -------------------------------------------------------------- 36 37 // Local Defines --------------------------------------------------------------- 38 39 // Globals --------------------------------------------------------------------- 40 41 //------------------------------------------------------------------------------ 42 BOutlineListView::BOutlineListView(BRect frame, const char * name, 43 list_view_type type, uint32 resizeMask, 44 uint32 flags) 45 : BListView(frame, name, type, resizeMask, flags) 46 { 47 } 48 //------------------------------------------------------------------------------ 49 BOutlineListView::BOutlineListView(BMessage *archive) 50 : BListView(archive) 51 { 52 } 53 //------------------------------------------------------------------------------ 54 BOutlineListView::~BOutlineListView() 55 { 56 fullList.MakeEmpty(); 57 } 58 //------------------------------------------------------------------------------ 59 BArchivable *BOutlineListView::Instantiate(BMessage *archive) 60 { 61 if (validate_instantiation(archive, "BOutlineListView")) 62 return new BOutlineListView(archive); 63 else 64 return NULL; 65 } 66 //------------------------------------------------------------------------------ 67 status_t BOutlineListView::Archive(BMessage *data, bool deep) const 68 { 69 return BListView::Archive(data, deep); 70 } 71 //------------------------------------------------------------------------------ 72 void BOutlineListView::MouseDown(BPoint point) 73 { 74 MakeFocus(); 75 76 int32 index = IndexOf(point); 77 78 if (index != -1) 79 { 80 BListItem *item = ItemAt(index); 81 82 if (item->fHasSubitems && 83 LatchRect (ItemFrame(index ), item->fLevel).Contains(point)) 84 { 85 if (item->IsExpanded()) 86 Collapse(item); 87 else 88 Expand(item); 89 } 90 else BListView::MouseDown(point); 91 } 92 } 93 //------------------------------------------------------------------------------ 94 void BOutlineListView::KeyDown(const char *bytes, int32 numBytes) 95 { 96 if (numBytes == 1) 97 { 98 switch (bytes[0]) 99 { 100 case '+': 101 { 102 BListItem *item = ItemAt(CurrentSelection()); 103 104 if ( item && item->fHasSubitems) 105 Expand(item); 106 107 break; 108 } 109 case '-': 110 { 111 BListItem *item = ItemAt(CurrentSelection()); 112 113 if (item && item->fHasSubitems) 114 Collapse(item); 115 116 break; 117 } 118 default: 119 BListView::KeyDown(bytes, numBytes); 120 } 121 } 122 else 123 BListView::KeyDown(bytes, numBytes); 124 } 125 //------------------------------------------------------------------------------ 126 void BOutlineListView::FrameMoved(BPoint new_position) 127 { 128 BListView::FrameMoved(new_position); 129 } 130 //------------------------------------------------------------------------------ 131 void BOutlineListView::FrameResized(float new_width, float new_height) 132 { 133 BListView::FrameResized(new_width, new_height); 134 } 135 //------------------------------------------------------------------------------ 136 void BOutlineListView::MouseUp(BPoint where) 137 { 138 BListView::MouseUp(where); 139 } 140 //------------------------------------------------------------------------------ 141 bool BOutlineListView::AddUnder(BListItem *item, BListItem *superitem) 142 { 143 fullList.AddItem(item, FullListIndexOf(superitem) + 1); 144 145 item->fLevel = superitem->OutlineLevel() + 1; 146 superitem->fHasSubitems = true; 147 148 if (superitem->IsItemVisible() && superitem->IsExpanded()) 149 { 150 item->SetItemVisible(true); 151 152 int32 index = BListView::IndexOf(superitem); 153 154 BListView::AddItem(item, index + 1); 155 Invalidate(LatchRect(ItemFrame(index), superitem->OutlineLevel())); 156 } 157 else 158 item->SetItemVisible(false); 159 160 return true; 161 } 162 //------------------------------------------------------------------------------ 163 bool BOutlineListView::AddItem(BListItem *item) 164 { 165 bool result = fullList.AddItem(item); 166 167 if (!result) 168 return false; 169 170 return BListView::AddItem(item); 171 } 172 //------------------------------------------------------------------------------ 173 bool BOutlineListView::AddItem(BListItem *item, int32 fullListIndex) 174 { 175 if (fullListIndex < 0) 176 fullListIndex = 0; 177 else if (fullListIndex > CountItems()) 178 fullListIndex = CountItems(); 179 180 fullList.AddItem(item, fullListIndex); 181 182 if (item->fLevel > 0) 183 { 184 BListItem *super = SuperitemForIndex(fullListIndex, item->fLevel); 185 186 if (!super->IsItemVisible() || !super->IsExpanded()) 187 return true; 188 } 189 190 int32 list_index = FindPreviousVisibleIndex(fullListIndex); 191 192 return BListView::AddItem(item, IndexOf(FullListItemAt(list_index)) + 1); 193 } 194 //------------------------------------------------------------------------------ 195 bool BOutlineListView::AddList(BList *newItems) 196 { 197 printf("BOutlineListView::AddList Not implemented\n"); 198 return false; 199 } 200 //------------------------------------------------------------------------------ 201 bool BOutlineListView::AddList(BList *newItems, int32 fullListIndex) 202 { 203 printf("BOutlineListView::AddList Not implemented\n"); 204 return false; 205 } 206 //------------------------------------------------------------------------------ 207 bool BOutlineListView::RemoveItem(BListItem *item) 208 { 209 if (!FullListHasItem(item)) 210 return false; 211 212 fullList.RemoveItem(item); 213 if (item->fVisible) 214 BListView::RemoveItem(item); 215 216 // TODO: remove children 217 218 return true; 219 } 220 //------------------------------------------------------------------------------ 221 BListItem *BOutlineListView::RemoveItem(int32 fullListIndex) 222 { 223 BListItem *item = FullListItemAt(fullListIndex); 224 225 if (item == NULL) 226 return NULL; 227 228 fullList.RemoveItem(fullListIndex); 229 if (item->fVisible) 230 BListView::RemoveItem(item); 231 232 // TODO: remove children 233 234 return item; 235 } 236 //------------------------------------------------------------------------------ 237 bool BOutlineListView::RemoveItems(int32 fullListIndex, int32 count) 238 { 239 printf("BOutlineListView::RemoveItems Not implemented\n"); 240 241 return false; 242 } 243 //------------------------------------------------------------------------------ 244 BListItem *BOutlineListView::FullListItemAt(int32 fullListIndex) const 245 { 246 return (BListItem*)fullList.ItemAt(fullListIndex); 247 } 248 //------------------------------------------------------------------------------ 249 int32 BOutlineListView::FullListIndexOf(BPoint point) const 250 { 251 return BListView::IndexOf(point); 252 } 253 //------------------------------------------------------------------------------ 254 int32 BOutlineListView::FullListIndexOf(BListItem *item) const 255 { 256 return fullList.IndexOf(item); 257 } 258 //------------------------------------------------------------------------------ 259 BListItem *BOutlineListView::FullListFirstItem() const 260 { 261 return (BListItem*)fullList.FirstItem(); 262 } 263 //------------------------------------------------------------------------------ 264 BListItem *BOutlineListView::FullListLastItem() const 265 { 266 return (BListItem*)fullList.LastItem(); 267 } 268 //------------------------------------------------------------------------------ 269 bool BOutlineListView::FullListHasItem(BListItem *item) const 270 { 271 return fullList.HasItem(item); 272 } 273 //------------------------------------------------------------------------------ 274 int32 BOutlineListView::FullListCountItems() const 275 { 276 return fullList.CountItems(); 277 } 278 //------------------------------------------------------------------------------ 279 int32 BOutlineListView::FullListCurrentSelection(int32 index) const 280 { 281 int32 i = BListView::CurrentSelection(index); 282 BListItem *item = BListView::ItemAt(i); 283 284 if (item) 285 return fullList.IndexOf(item); 286 else 287 return -1; 288 } 289 //------------------------------------------------------------------------------ 290 void BOutlineListView::MakeEmpty() 291 { 292 fullList.MakeEmpty(); 293 BListView::MakeEmpty(); 294 } 295 //------------------------------------------------------------------------------ 296 bool BOutlineListView::FullListIsEmpty() const 297 { 298 return fullList.IsEmpty(); 299 } 300 //------------------------------------------------------------------------------ 301 void BOutlineListView::FullListDoForEach(bool(*func)(BListItem *)) 302 { 303 printf("BOutlineListView::fullListDoForEach Not implemented\n"); 304 //fullList.DoForEach(func); 305 } 306 //------------------------------------------------------------------------------ 307 void BOutlineListView::FullListDoForEach(bool (*func)(BListItem *, void *), 308 void *data) 309 { 310 printf("BOutlineListView::fullListDoForEach Not implemented\n"); 311 //fullList.DoForEach(func, data); 312 } 313 //------------------------------------------------------------------------------ 314 BListItem *BOutlineListView::Superitem(const BListItem *item) 315 { 316 int32 index = FullListIndexOf((BListItem*)item); 317 318 if (index == -1) 319 return NULL; 320 else 321 return SuperitemForIndex(index, item->OutlineLevel()); 322 } 323 //------------------------------------------------------------------------------ 324 void BOutlineListView::Expand(BListItem *item) 325 { 326 if (!FullListHasItem(item)) 327 return; 328 329 if (item->fExpanded) 330 return; 331 332 item->fExpanded = true; 333 334 uint32 level = item->fLevel, full_index = FullListIndexOf(item), 335 index = IndexOf(item) + 1, count = FullListCountItems() - full_index - 1; 336 BListItem **items = (BListItem**)fullList.Items() + full_index + 1; 337 338 BFont font; 339 GetFont(&font); 340 341 while (count-- > 0 && (*items)->fLevel > level) 342 { 343 if (!(*items)->IsItemVisible()) 344 { 345 //BListView::AddItem((*items), index++); 346 fList.AddItem((*items), index++); 347 (*items)->Update(this,&font); 348 (*items)->SetItemVisible(true); 349 } 350 351 // Skip hidden children 352 if ((*items)->HasSubitems() && !(*items)->IsExpanded()) 353 { 354 uint32 level = (*items)->fLevel; 355 items++; 356 357 while (--count > 0 && (*items)->fLevel > level) 358 items++; 359 } 360 else 361 items++; 362 } 363 364 FixupScrollBar(); 365 Invalidate(); 366 } 367 //------------------------------------------------------------------------------ 368 void BOutlineListView::Collapse(BListItem *item) 369 { 370 if (!FullListHasItem(item)) 371 return; 372 373 if (!item->fExpanded) 374 return; 375 376 item->fExpanded = false; 377 378 uint32 level = item->fLevel, full_index = FullListIndexOf(item), 379 count = FullListCountItems() - full_index - 1; 380 BListItem **items = (BListItem**)fullList.Items() + full_index + 1; 381 382 while (count-- > 0 && (*items)->fLevel > level) 383 { 384 if ((*items)->IsItemVisible()) 385 { 386 //BListView::RemoveItem ((*items)); 387 fList.RemoveItem((*items)); 388 (*items)->SetItemVisible(false); 389 } 390 391 items++; 392 } 393 394 FixupScrollBar(); 395 Invalidate(); 396 } 397 //------------------------------------------------------------------------------ 398 bool BOutlineListView::IsExpanded(int32 fullListIndex) 399 { 400 BListItem *item = FullListItemAt(fullListIndex); 401 402 if (!item) 403 return false; 404 405 return item->IsExpanded(); 406 } 407 //------------------------------------------------------------------------------ 408 BHandler *BOutlineListView::ResolveSpecifier(BMessage *msg, int32 index, 409 BMessage *specifier, int32 form, 410 const char *property) 411 { 412 return BListView::ResolveSpecifier(msg, index, specifier, form, property); 413 } 414 //------------------------------------------------------------------------------ 415 status_t BOutlineListView::GetSupportedSuites(BMessage *data) 416 { 417 return BListView::GetSupportedSuites(data); 418 } 419 //------------------------------------------------------------------------------ 420 status_t BOutlineListView::Perform(perform_code d, void *arg) 421 { 422 return BListView::Perform(d, arg); 423 } 424 //------------------------------------------------------------------------------ 425 void BOutlineListView::ResizeToPreferred() 426 { 427 BListView::ResizeToPreferred(); 428 } 429 //------------------------------------------------------------------------------ 430 void BOutlineListView::GetPreferredSize(float *width, float *height) 431 { 432 BListView::GetPreferredSize(width, height); 433 } 434 //------------------------------------------------------------------------------ 435 void BOutlineListView::MakeFocus(bool state) 436 { 437 BListView::MakeFocus(state); 438 } 439 //------------------------------------------------------------------------------ 440 void BOutlineListView::AllAttached() 441 { 442 BListView::AllAttached(); 443 } 444 //------------------------------------------------------------------------------ 445 void BOutlineListView::AllDetached() 446 { 447 BListView::AllDetached(); 448 } 449 //------------------------------------------------------------------------------ 450 void BOutlineListView::DetachedFromWindow() 451 { 452 BListView::DetachedFromWindow(); 453 } 454 //------------------------------------------------------------------------------ 455 void BOutlineListView::FullListSortItems(int (*compareFunc)(const BListItem *, 456 const BListItem *)) 457 { 458 //fullList.SortItems(compareFunc); 459 printf("BOutlineListView::FullListSortItems not implemented\n"); 460 } 461 //------------------------------------------------------------------------------ 462 void BOutlineListView::SortItemsUnder(BListItem *underItem, bool oneLevelOnly, 463 int (*compareFunc)(const BListItem *, const BListItem*)) 464 { 465 printf("BOutlineListView::SortItemsUnder not implemented\n"); 466 } 467 //------------------------------------------------------------------------------ 468 int32 BOutlineListView::CountItemsUnder(BListItem *underItem, 469 bool oneLevelOnly) const 470 { 471 int32 i = IndexOf(underItem); 472 473 if (i == -1) 474 return 0; 475 476 int32 count = 0; 477 478 if (oneLevelOnly) 479 { 480 while (i < FullListCountItems()) 481 { 482 BListItem *item = FullListItemAt(i); 483 484 // If we jump out of the subtree, return count 485 if (item->fLevel < underItem->OutlineLevel()) 486 return count; 487 488 // If the level matches, increase count 489 if (item->fLevel == underItem->OutlineLevel() + 1) 490 count++; 491 492 i++; 493 } 494 } 495 else 496 { 497 while (i < FullListCountItems()) 498 { 499 BListItem *item = FullListItemAt(i); 500 501 // If we jump out of the subtree, return count 502 if (item->fLevel < underItem->OutlineLevel()) 503 return count; 504 505 // Increase count 506 count++; 507 508 i++; 509 } 510 } 511 512 return count; 513 } 514 //------------------------------------------------------------------------------ 515 BListItem *BOutlineListView::EachItemUnder(BListItem *underItem, 516 bool oneLevelOnly, 517 BListItem *(*eachFunc)(BListItem *, 518 void *), void *) 519 { 520 printf("BOutlineListView::EachItemUnder Not implemented\n"); 521 522 return NULL; 523 } 524 //------------------------------------------------------------------------------ 525 BListItem *BOutlineListView::ItemUnderAt(BListItem *underItem, 526 bool oneLevelOnly, int32 index) const 527 { 528 int32 i = IndexOf(underItem); 529 530 if (i == -1) 531 return NULL; 532 533 if (oneLevelOnly) 534 { 535 while (i < FullListCountItems()) 536 { 537 BListItem *item = FullListItemAt(i); 538 539 // If we jump out of the subtree, return NULL 540 if (item->fLevel < underItem->OutlineLevel()) 541 return NULL; 542 543 // If the level matches, check the index 544 if (item->fLevel == underItem->OutlineLevel() + 1) 545 { 546 if (index == 0) 547 return item; 548 else 549 index--; 550 } 551 552 i++; 553 } 554 } 555 else 556 { 557 while (i < FullListCountItems()) 558 { 559 BListItem *item = FullListItemAt(i); 560 561 // If we jump out of the subtree, return NULL 562 if (item->fLevel < underItem->OutlineLevel()) 563 return NULL; 564 565 // Check the index 566 if (index == 0) 567 return item; 568 else 569 index--; 570 571 i++; 572 } 573 } 574 575 return NULL; 576 } 577 //------------------------------------------------------------------------------ 578 bool BOutlineListView::DoMiscellaneous(MiscCode code, MiscData * data) 579 { 580 return BListView::DoMiscellaneous(code, data); 581 } 582 //------------------------------------------------------------------------------ 583 void BOutlineListView::MessageReceived(BMessage *msg) 584 { 585 BListView::MessageReceived(msg); 586 } 587 //------------------------------------------------------------------------------ 588 void BOutlineListView::_ReservedOutlineListView1() {} 589 void BOutlineListView::_ReservedOutlineListView2() {} 590 void BOutlineListView::_ReservedOutlineListView3() {} 591 void BOutlineListView::_ReservedOutlineListView4() {} 592 //------------------------------------------------------------------------------ 593 int32 BOutlineListView::FullListIndex(int32 index) const 594 { 595 BListItem *item = ItemAt(index); 596 597 if (item == NULL) 598 return -1; 599 else 600 return FullListIndexOf(item); 601 } 602 //------------------------------------------------------------------------------ 603 int32 BOutlineListView::ListViewIndex(int32 index) const 604 { 605 BListItem *item = ItemAt(index); 606 607 if (item == NULL) 608 return -1; 609 else 610 return BListView::IndexOf(item); 611 } 612 //------------------------------------------------------------------------------ 613 void BOutlineListView::ExpandOrCollapse(BListItem *underItem, bool expand) 614 { 615 } 616 //------------------------------------------------------------------------------ 617 BRect BOutlineListView::LatchRect(BRect itemRect, int32 level) const 618 { 619 return BRect(itemRect.left, itemRect.top, itemRect.left + 620 (level * 10.0f + 15.0f), itemRect.bottom); 621 } 622 //------------------------------------------------------------------------------ 623 void BOutlineListView::DrawLatch(BRect itemRect, int32 level, bool collapsed, 624 bool highlighted, bool misTracked) 625 { 626 float left = level * 10.0f; 627 628 if (collapsed) 629 { 630 SetHighColor(192, 192, 192); 631 632 FillTriangle(itemRect.LeftTop() + BPoint(left + 4.0f, 2.0f), 633 itemRect.LeftTop() + BPoint(left + 4.0f, 10.0f), 634 itemRect.LeftTop() + BPoint(left + 8.0f, 6.0f)); 635 636 SetHighColor(0, 0, 0); 637 638 StrokeTriangle(itemRect.LeftTop() + BPoint(left + 4.0f, 2.0f), 639 itemRect.LeftTop() + BPoint(left + 4.0f, 10.0f), 640 itemRect.LeftTop() + BPoint(left + 8.0f, 6.0f)); 641 } 642 else 643 { 644 SetHighColor(192, 192, 192); 645 646 FillTriangle(itemRect.LeftTop() + BPoint(left + 2.0f, 4.0f), 647 itemRect.LeftTop() + BPoint(left + 10.0f, 4.0f), 648 itemRect.LeftTop() + BPoint(left + 6.0f, 8.0f)); 649 650 SetHighColor(0, 0, 0); 651 652 StrokeTriangle(itemRect.LeftTop() + BPoint(left + 2.0f, 4.0f), 653 itemRect.LeftTop() + BPoint(left + 10.0f, 4.0f), 654 itemRect.LeftTop() + BPoint(left + 6.0f, 8.0f)); 655 } 656 } 657 //------------------------------------------------------------------------------ 658 void BOutlineListView::DrawItem(BListItem *item, BRect itemRect, bool complete) 659 { 660 if (item->fHasSubitems) 661 DrawLatch(itemRect, item->fLevel, !item->IsExpanded(), false, false); 662 663 itemRect.left += (item->fLevel) * 10.0f + 15.0f; 664 665 item->DrawItem(this, itemRect, complete); 666 } 667 //------------------------------------------------------------------------------ 668 BListItem *BOutlineListView::RemoveCommon(int32 fullListIndex) 669 { 670 return NULL; 671 } 672 //------------------------------------------------------------------------------ 673 BListItem *BOutlineListView::RemoveOne(int32 fullListIndex) 674 { 675 return NULL; 676 } 677 //------------------------------------------------------------------------------ 678 void BOutlineListView::TrackInLatchItem(void *) 679 { 680 } 681 //------------------------------------------------------------------------------ 682 void BOutlineListView::TrackOutLatchItem(void *) 683 { 684 } 685 //------------------------------------------------------------------------------ 686 bool BOutlineListView::OutlineSwapItems(int32 a, int32 b) 687 { 688 return false; 689 } 690 //------------------------------------------------------------------------------ 691 bool BOutlineListView::OutlineMoveItem(int32 from, int32 to) 692 { 693 return false; 694 } 695 //------------------------------------------------------------------------------ 696 bool BOutlineListView::OutlineReplaceItem(int32 index, BListItem *item) 697 { 698 return false; 699 } 700 //------------------------------------------------------------------------------ 701 void BOutlineListView::CommonMoveItems(int32 from, int32 count, int32 to) 702 { 703 } 704 //------------------------------------------------------------------------------ 705 BListItem *BOutlineListView::SuperitemForIndex(int32 fullListIndex, int32 level) 706 { 707 BListItem *item; 708 fullListIndex--; 709 710 while (fullListIndex >= 0) 711 { 712 if ((item = FullListItemAt(fullListIndex))->OutlineLevel() < 713 (uint32)level) 714 return item; 715 716 fullListIndex--; 717 } 718 719 return NULL; 720 } 721 //------------------------------------------------------------------------------ 722 int32 BOutlineListView::FindPreviousVisibleIndex(int32 fullListIndex) 723 { 724 fullListIndex--; 725 726 while (fullListIndex >= 0) 727 { 728 if (FullListItemAt(fullListIndex)->fVisible) 729 return fullListIndex; 730 731 fullListIndex--; 732 } 733 734 return -1; 735 } 736 //------------------------------------------------------------------------------ 737 738 /* 739 * $Log $ 740 * 741 * $Id $ 742 * 743 */ 744