1 /* 2 * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz 3 * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz 4 * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de> 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "ALMLayout.h" 10 11 12 #include <vector> 13 14 #include <AutoDeleter.h> 15 #include <ControlLook.h> 16 17 #include "RowColumnManager.h" 18 #include "SharedSolver.h" 19 #include "ViewLayoutItem.h" 20 21 22 using BPrivate::AutoDeleter; 23 using namespace LinearProgramming; 24 25 26 const BSize kUnsetSize(B_SIZE_UNSET, B_SIZE_UNSET); 27 28 29 namespace BALM { 30 31 32 template <class T> 33 struct BALMLayout::TabAddTransaction { 34 ~TabAddTransaction() 35 { 36 if (fTab) 37 fLayout->_RemoveSelfFromTab(fTab); 38 if (fIndex > 0) 39 _TabList()->RemoveItemAt(fIndex); 40 } 41 42 TabAddTransaction(BALMLayout* layout) 43 : 44 fTab(NULL), 45 fLayout(layout), 46 fIndex(-1) 47 { 48 } 49 50 bool AttempAdd(T* tab) 51 { 52 if (fLayout->_HasTabInLayout(tab)) 53 return true; 54 if (!fLayout->_AddedTab(tab)) 55 return false; 56 fTab = tab; 57 58 BObjectList<T>* tabList = _TabList(); 59 int32 index = tabList->CountItems(); 60 if (!tabList->AddItem(tab, index)) 61 return false; 62 fIndex = index; 63 return true; 64 } 65 66 void Commit() 67 { 68 fTab = NULL; 69 fIndex = -1; 70 } 71 72 private: 73 BObjectList<T>* _TabList(); 74 75 T* fTab; 76 BALMLayout* fLayout; 77 int32 fIndex; 78 }; 79 80 81 template <> 82 BObjectList<XTab>* 83 BALMLayout::TabAddTransaction<XTab>::_TabList() 84 { 85 return &fLayout->fXTabList; 86 } 87 88 89 template <> 90 BObjectList<YTab>* 91 BALMLayout::TabAddTransaction<YTab>::_TabList() 92 { 93 return &fLayout->fYTabList; 94 } 95 96 97 }; // end namespace BALM 98 99 100 BALM::BALMLayout::BadLayoutPolicy::~BadLayoutPolicy() 101 { 102 } 103 104 105 BALM::BALMLayout::DefaultPolicy::~DefaultPolicy() 106 { 107 } 108 109 110 bool 111 BALM::BALMLayout::DefaultPolicy::OnBadLayout(BALMLayout* layout) 112 { 113 if (layout->Solver()->Result() == kInfeasible) { 114 debugger("BALMLayout failed to solve your layout!"); 115 return false; 116 } else 117 return true; 118 } 119 120 121 /*! 122 * Constructor. 123 * Creates new layout engine. 124 * 125 * If friendLayout is not NULL the solver of the friend layout is used. 126 */ 127 BALMLayout::BALMLayout(float hSpacing, float vSpacing, BALMLayout* friendLayout) 128 : 129 fLeftInset(0), 130 fRightInset(0), 131 fTopInset(0), 132 fBottomInset(0), 133 fHSpacing(BControlLook::ComposeSpacing(hSpacing)), 134 fVSpacing(BControlLook::ComposeSpacing(vSpacing)), 135 fBadLayoutPolicy(new DefaultPolicy()) 136 { 137 fSolver = friendLayout ? friendLayout->fSolver : new SharedSolver(); 138 fSolver->AcquireReference(); 139 fSolver->RegisterLayout(this); 140 fRowColumnManager = new RowColumnManager(Solver()); 141 142 fLeft = AddXTab(); 143 fRight = AddXTab(); 144 fTop = AddYTab(); 145 fBottom = AddYTab(); 146 147 // the Left tab is always at x-position 0, and the Top tab is always at 148 // y-position 0 149 fLeft->SetRange(0, 0); 150 fTop->SetRange(0, 0); 151 152 // cached layout values 153 // need to be invalidated whenever the layout specification is changed 154 fMinSize = kUnsetSize; 155 fMaxSize = kUnsetSize; 156 fPreferredSize = kUnsetSize; 157 } 158 159 160 BALMLayout::~BALMLayout() 161 { 162 delete fRowColumnManager; 163 delete fBadLayoutPolicy; 164 165 fSolver->LayoutLeaving(this); 166 fSolver->ReleaseReference(); 167 } 168 169 170 /** 171 * Adds a new x-tab to the specification. 172 * 173 * @return the new x-tab 174 */ 175 BReference<XTab> 176 BALMLayout::AddXTab() 177 { 178 BReference<XTab> tab(new(std::nothrow) XTab(this), true); 179 if (!tab) 180 return NULL; 181 if (!Solver()->AddVariable(tab)) 182 return NULL; 183 184 fXTabList.AddItem(tab); 185 if (!tab->AddedToLayout(this)) { 186 fXTabList.RemoveItem(tab); 187 return NULL; 188 } 189 return tab; 190 } 191 192 193 void 194 BALMLayout::AddXTabs(BReference<XTab>* tabs, uint32 count) 195 { 196 for (uint32 i = 0; i < count; i++) 197 tabs[i] = AddXTab(); 198 } 199 200 201 void 202 BALMLayout::AddYTabs(BReference<YTab>* tabs, uint32 count) 203 { 204 for (uint32 i = 0; i < count; i++) 205 tabs[i] = AddYTab(); 206 } 207 208 209 /** 210 * Adds a new y-tab to the specification. 211 * 212 * @return the new y-tab 213 */ 214 BReference<YTab> 215 BALMLayout::AddYTab() 216 { 217 BReference<YTab> tab(new(std::nothrow) YTab(this), true); 218 if (tab.Get() == NULL) 219 return NULL; 220 if (!Solver()->AddVariable(tab)) 221 return NULL; 222 223 fYTabList.AddItem(tab); 224 if (!tab->AddedToLayout(this)) { 225 fYTabList.RemoveItem(tab); 226 return NULL; 227 } 228 return tab; 229 } 230 231 232 int32 233 BALMLayout::CountXTabs() const 234 { 235 return fXTabList.CountItems(); 236 } 237 238 239 int32 240 BALMLayout::CountYTabs() const 241 { 242 return fYTabList.CountItems(); 243 } 244 245 246 XTab* 247 BALMLayout::XTabAt(int32 index) const 248 { 249 return fXTabList.ItemAt(index); 250 } 251 252 253 YTab* 254 BALMLayout::YTabAt(int32 index) const 255 { 256 return fYTabList.ItemAt(index); 257 } 258 259 260 static int 261 compare_x_tab_func(const XTab* tab1, const XTab* tab2) 262 { 263 if (tab1->Value() < tab2->Value()) 264 return -1; 265 else if (tab1->Value() == tab2->Value()) 266 return 0; 267 return 1; 268 } 269 270 271 static int 272 compare_y_tab_func(const YTab* tab1, const YTab* tab2) 273 { 274 if (tab1->Value() < tab2->Value()) 275 return -1; 276 else if (tab1->Value() == tab2->Value()) 277 return 0; 278 return 1; 279 } 280 281 282 const XTabList& 283 BALMLayout::OrderedXTabs() 284 { 285 fXTabList.SortItems(compare_x_tab_func); 286 return fXTabList; 287 } 288 289 290 const YTabList& 291 BALMLayout::OrderedYTabs() 292 { 293 fYTabList.SortItems(compare_y_tab_func); 294 return fYTabList; 295 } 296 297 298 /** 299 * Adds a new row to the specification that is glued to the given y-tabs. 300 * 301 * @param top 302 * @param bottom 303 * @return the new row 304 */ 305 Row* 306 BALMLayout::AddRow(YTab* _top, YTab* _bottom) 307 { 308 BReference<YTab> top = _top; 309 BReference<YTab> bottom = _bottom; 310 if (_top == NULL) 311 top = AddYTab(); 312 if (_bottom == NULL) 313 bottom = AddYTab(); 314 return new(std::nothrow) Row(Solver(), top, bottom); 315 } 316 317 318 /** 319 * Adds a new column to the specification that is glued to the given x-tabs. 320 * 321 * @param left 322 * @param right 323 * @return the new column 324 */ 325 Column* 326 BALMLayout::AddColumn(XTab* _left, XTab* _right) 327 { 328 BReference<XTab> left = _left; 329 BReference<XTab> right = _right; 330 if (_left == NULL) 331 left = AddXTab(); 332 if (_right == NULL) 333 right = AddXTab(); 334 return new(std::nothrow) Column(Solver(), left, right); 335 } 336 337 338 Area* 339 BALMLayout::AreaFor(int32 id) const 340 { 341 int32 areaCount = CountAreas(); 342 for (int32 i = 0; i < areaCount; i++) { 343 Area* area = AreaAt(i); 344 if (area->ID() == id) 345 return area; 346 } 347 return NULL; 348 } 349 350 351 /** 352 * Finds the area that contains the given control. 353 * 354 * @param control the control to look for 355 * @return the area that contains the control 356 */ 357 Area* 358 BALMLayout::AreaFor(const BView* control) const 359 { 360 return AreaFor(ItemAt(IndexOfView(const_cast<BView*>(control)))); 361 } 362 363 364 Area* 365 BALMLayout::AreaFor(const BLayoutItem* item) const 366 { 367 if (!item) 368 return NULL; 369 return static_cast<Area*>(item->LayoutData()); 370 } 371 372 373 int32 374 BALMLayout::CountAreas() const 375 { 376 return CountItems(); 377 } 378 379 380 Area* 381 BALMLayout::AreaAt(int32 index) const 382 { 383 return AreaFor(ItemAt(index)); 384 } 385 386 387 XTab* 388 BALMLayout::LeftOf(const BView* view) const 389 { 390 Area* area = AreaFor(view); 391 if (!area) 392 return NULL; 393 return area->Left(); 394 } 395 396 397 XTab* 398 BALMLayout::LeftOf(const BLayoutItem* item) const 399 { 400 Area* area = AreaFor(item); 401 if (!area) 402 return NULL; 403 return area->Left(); 404 } 405 406 407 XTab* 408 BALMLayout::RightOf(const BView* view) const 409 { 410 Area* area = AreaFor(view); 411 if (!area) 412 return NULL; 413 return area->Right(); 414 } 415 416 417 XTab* 418 BALMLayout::RightOf(const BLayoutItem* item) const 419 { 420 Area* area = AreaFor(item); 421 if (!area) 422 return NULL; 423 return area->Right(); 424 } 425 426 427 YTab* 428 BALMLayout::TopOf(const BView* view) const 429 { 430 Area* area = AreaFor(view); 431 if (!area) 432 return NULL; 433 return area->Top(); 434 } 435 436 437 YTab* 438 BALMLayout::TopOf(const BLayoutItem* item) const 439 { 440 Area* area = AreaFor(item); 441 if (!area) 442 return NULL; 443 return area->Top(); 444 } 445 446 447 YTab* 448 BALMLayout::BottomOf(const BView* view) const 449 { 450 Area* area = AreaFor(view); 451 if (!area) 452 return NULL; 453 return area->Bottom(); 454 } 455 456 457 YTab* 458 BALMLayout::BottomOf(const BLayoutItem* item) const 459 { 460 Area* area = AreaFor(item); 461 if (!area) 462 return NULL; 463 return area->Bottom(); 464 } 465 466 467 BLayoutItem* 468 BALMLayout::AddView(BView* child) 469 { 470 return AddView(-1, child); 471 } 472 473 474 BLayoutItem* 475 BALMLayout::AddView(int32 index, BView* child) 476 { 477 return BAbstractLayout::AddView(index, child); 478 } 479 480 481 /** 482 * Adds a new area to the specification, automatically setting preferred size constraints. 483 * 484 * @param left left border 485 * @param top top border 486 * @param right right border 487 * @param bottom bottom border 488 * @param content the control which is the area content 489 * @return the new area 490 */ 491 Area* 492 BALMLayout::AddView(BView* view, XTab* left, YTab* top, XTab* right, 493 YTab* bottom) 494 { 495 BLayoutItem* item = _LayoutItemToAdd(view); 496 Area* area = AddItem(item, left, top, right, bottom); 497 if (!area) { 498 if (item != view->GetLayout()) 499 delete item; 500 return NULL; 501 } 502 return area; 503 } 504 505 506 /** 507 * Adds a new area to the specification, automatically setting preferred size constraints. 508 * 509 * @param row the row that defines the top and bottom border 510 * @param column the column that defines the left and right border 511 * @param content the control which is the area content 512 * @return the new area 513 */ 514 Area* 515 BALMLayout::AddView(BView* view, Row* row, Column* column) 516 { 517 BLayoutItem* item = _LayoutItemToAdd(view); 518 Area* area = AddItem(item, row, column); 519 if (!area) { 520 if (item != view->GetLayout()) 521 delete item; 522 return NULL; 523 } 524 return area; 525 } 526 527 528 bool 529 BALMLayout::AddItem(BLayoutItem* item) 530 { 531 return AddItem(-1, item); 532 } 533 534 535 bool 536 BALMLayout::AddItem(int32 index, BLayoutItem* item) 537 { 538 if (!item) 539 return false; 540 541 // simply add the item at the upper right corner of the previous item 542 // TODO maybe find a more elegant solution 543 XTab* left = Left(); 544 YTab* top = Top(); 545 546 // check range 547 if (index < 0 || index > CountItems()) 548 index = CountItems(); 549 550 // for index = 0 we already have set the right tabs 551 if (index != 0) { 552 BLayoutItem* prevItem = ItemAt(index - 1); 553 Area* area = AreaFor(prevItem); 554 if (area) { 555 left = area->Right(); 556 top = area->Top(); 557 } 558 } 559 Area* area = AddItem(item, left, top); 560 return area ? true : false; 561 } 562 563 564 Area* 565 BALMLayout::AddItem(BLayoutItem* item, XTab* left, YTab* top, XTab* _right, 566 YTab* _bottom) 567 { 568 if (!left->IsSuitableFor(this) || !top->IsSuitableFor(this) 569 || (_right && !_right->IsSuitableFor(this)) 570 || (_bottom && !_bottom->IsSuitableFor(this))) 571 debugger("Tab added to unfriendly layout!"); 572 573 BReference<XTab> right = _right; 574 if (right.Get() == NULL) 575 right = AddXTab(); 576 BReference<YTab> bottom = _bottom; 577 if (bottom.Get() == NULL) 578 bottom = AddYTab(); 579 580 TabAddTransaction<XTab> leftTabAdd(this); 581 if (!leftTabAdd.AttempAdd(left)) 582 return NULL; 583 584 TabAddTransaction<YTab> topTabAdd(this); 585 if (!topTabAdd.AttempAdd(top)) 586 return NULL; 587 588 TabAddTransaction<XTab> rightTabAdd(this); 589 if (!rightTabAdd.AttempAdd(right)) 590 return NULL; 591 592 TabAddTransaction<YTab> bottomTabAdd(this); 593 if (!bottomTabAdd.AttempAdd(bottom)) 594 return NULL; 595 596 // Area is added in ItemAdded 597 if (!BAbstractLayout::AddItem(-1, item)) 598 return NULL; 599 Area* area = AreaFor(item); 600 if (!area) { 601 RemoveItem(item); 602 return NULL; 603 } 604 605 area->_Init(Solver(), left, top, right, bottom, fRowColumnManager); 606 fRowColumnManager->AddArea(area); 607 608 leftTabAdd.Commit(); 609 topTabAdd.Commit(); 610 rightTabAdd.Commit(); 611 bottomTabAdd.Commit(); 612 return area; 613 } 614 615 616 Area* 617 BALMLayout::AddItem(BLayoutItem* item, Row* row, Column* column) 618 { 619 if (!BAbstractLayout::AddItem(-1, item)) 620 return NULL; 621 Area* area = AreaFor(item); 622 if (!area) 623 return NULL; 624 625 area->_Init(Solver(), row, column, fRowColumnManager); 626 627 fRowColumnManager->AddArea(area); 628 return area; 629 } 630 631 632 enum { 633 kLeftBorderIndex = -2, 634 kTopBorderIndex = -3, 635 kRightBorderIndex = -4, 636 kBottomBorderIndex = -5, 637 }; 638 639 640 bool 641 BALMLayout::SaveLayout(BMessage* archive) const 642 { 643 archive->MakeEmpty(); 644 645 archive->AddInt32("nXTabs", CountXTabs()); 646 archive->AddInt32("nYTabs", CountYTabs()); 647 648 XTabList xTabs = fXTabList; 649 xTabs.RemoveItem(fLeft); 650 xTabs.RemoveItem(fRight); 651 YTabList yTabs = fYTabList; 652 yTabs.RemoveItem(fTop); 653 yTabs.RemoveItem(fBottom); 654 655 int32 nAreas = CountAreas(); 656 for (int32 i = 0; i < nAreas; i++) { 657 Area* area = AreaAt(i); 658 if (area->Left() == fLeft) 659 archive->AddInt32("left", kLeftBorderIndex); 660 else 661 archive->AddInt32("left", xTabs.IndexOf(area->Left())); 662 if (area->Top() == fTop) 663 archive->AddInt32("top", kTopBorderIndex); 664 else 665 archive->AddInt32("top", yTabs.IndexOf(area->Top())); 666 if (area->Right() == fRight) 667 archive->AddInt32("right", kRightBorderIndex); 668 else 669 archive->AddInt32("right", xTabs.IndexOf(area->Right())); 670 if (area->Bottom() == fBottom) 671 archive->AddInt32("bottom", kBottomBorderIndex); 672 else 673 archive->AddInt32("bottom", yTabs.IndexOf(area->Bottom())); 674 } 675 return true; 676 } 677 678 679 bool 680 BALMLayout::RestoreLayout(const BMessage* archive) 681 { 682 int32 neededXTabs; 683 int32 neededYTabs; 684 if (archive->FindInt32("nXTabs", &neededXTabs) != B_OK) 685 return false; 686 if (archive->FindInt32("nYTabs", &neededYTabs) != B_OK) 687 return false; 688 // First store a reference to all needed tabs otherwise they might get lost 689 // while editing the layout 690 std::vector<BReference<XTab> > newXTabs; 691 std::vector<BReference<YTab> > newYTabs; 692 int32 existingXTabs = fXTabList.CountItems(); 693 for (int32 i = 0; i < neededXTabs; i++) { 694 if (i < existingXTabs) 695 newXTabs.push_back(BReference<XTab>(fXTabList.ItemAt(i))); 696 else 697 newXTabs.push_back(AddXTab()); 698 } 699 int32 existingYTabs = fYTabList.CountItems(); 700 for (int32 i = 0; i < neededYTabs; i++) { 701 if (i < existingYTabs) 702 newYTabs.push_back(BReference<YTab>(fYTabList.ItemAt(i))); 703 else 704 newYTabs.push_back(AddYTab()); 705 } 706 707 XTabList xTabs = fXTabList; 708 xTabs.RemoveItem(fLeft); 709 xTabs.RemoveItem(fRight); 710 YTabList yTabs = fYTabList; 711 yTabs.RemoveItem(fTop); 712 yTabs.RemoveItem(fBottom); 713 714 int32 nAreas = CountAreas(); 715 for (int32 i = 0; i < nAreas; i++) { 716 Area* area = AreaAt(i); 717 if (area == NULL) 718 return false; 719 int32 left = -1; 720 if (archive->FindInt32("left", i, &left) != B_OK) 721 break; 722 int32 top = archive->FindInt32("top", i); 723 int32 right = archive->FindInt32("right", i); 724 int32 bottom = archive->FindInt32("bottom", i); 725 726 XTab* leftTab = NULL; 727 YTab* topTab = NULL; 728 XTab* rightTab = NULL; 729 YTab* bottomTab = NULL; 730 731 if (left == kLeftBorderIndex) 732 leftTab = fLeft; 733 else 734 leftTab = xTabs.ItemAt(left); 735 if (top == kTopBorderIndex) 736 topTab = fTop; 737 else 738 topTab = yTabs.ItemAt(top); 739 if (right == kRightBorderIndex) 740 rightTab = fRight; 741 else 742 rightTab = xTabs.ItemAt(right); 743 if (bottom == kBottomBorderIndex) 744 bottomTab = fBottom; 745 else 746 bottomTab = yTabs.ItemAt(bottom); 747 if (leftTab == NULL || topTab == NULL || rightTab == NULL 748 || bottomTab == NULL) 749 return false; 750 751 area->SetLeft(leftTab); 752 area->SetTop(topTab); 753 area->SetRight(rightTab); 754 area->SetBottom(bottomTab); 755 } 756 return true; 757 } 758 759 760 /** 761 * Gets the left variable. 762 */ 763 XTab* 764 BALMLayout::Left() const 765 { 766 return fLeft; 767 } 768 769 770 /** 771 * Gets the right variable. 772 */ 773 XTab* 774 BALMLayout::Right() const 775 { 776 return fRight; 777 } 778 779 780 /** 781 * Gets the top variable. 782 */ 783 YTab* 784 BALMLayout::Top() const 785 { 786 return fTop; 787 } 788 789 790 /** 791 * Gets the bottom variable. 792 */ 793 YTab* 794 BALMLayout::Bottom() const 795 { 796 return fBottom; 797 } 798 799 800 void 801 BALMLayout::SetBadLayoutPolicy(BadLayoutPolicy* policy) 802 { 803 if (fBadLayoutPolicy != policy) 804 delete fBadLayoutPolicy; 805 if (policy == NULL) 806 policy = new DefaultPolicy(); 807 fBadLayoutPolicy = policy; 808 } 809 810 811 struct BALMLayout::BadLayoutPolicy* 812 BALMLayout::GetBadLayoutPolicy() const 813 { 814 return fBadLayoutPolicy; 815 } 816 817 818 /** 819 * Gets minimum size. 820 */ 821 BSize 822 BALMLayout::BaseMinSize() 823 { 824 fSolver->ValidateMinSize(); 825 return fMinSize; 826 } 827 828 829 /** 830 * Gets maximum size. 831 */ 832 BSize 833 BALMLayout::BaseMaxSize() 834 { 835 fSolver->ValidateMaxSize(); 836 return fMaxSize; 837 } 838 839 840 /** 841 * Gets preferred size. 842 */ 843 BSize 844 BALMLayout::BasePreferredSize() 845 { 846 fSolver->ValidateMinSize(); 847 return fMinSize; 848 } 849 850 851 /** 852 * Gets the alignment. 853 */ 854 BAlignment 855 BALMLayout::BaseAlignment() 856 { 857 BAlignment alignment; 858 alignment.SetHorizontal(B_ALIGN_HORIZONTAL_CENTER); 859 alignment.SetVertical(B_ALIGN_VERTICAL_CENTER); 860 return alignment; 861 } 862 863 864 /** 865 * Invalidates the layout. 866 * Resets minimum/maximum/preferred size. 867 */ 868 void 869 BALMLayout::LayoutInvalidated(bool children) 870 { 871 fMinSize = kUnsetSize; 872 fMaxSize = kUnsetSize; 873 fPreferredSize = kUnsetSize; 874 875 fSolver->Invalidate(children); 876 } 877 878 879 bool 880 BALMLayout::ItemAdded(BLayoutItem* item, int32 atIndex) 881 { 882 item->SetLayoutData(new(std::nothrow) Area(item)); 883 return item->LayoutData() != NULL; 884 } 885 886 887 void 888 BALMLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex) 889 { 890 if (Area* area = AreaFor(item)) { 891 fRowColumnManager->RemoveArea(area); 892 item->SetLayoutData(NULL); 893 delete area; 894 } 895 } 896 897 898 /** 899 * Calculate and set the layout. 900 * If no layout specification is given, a specification is reverse engineered automatically. 901 */ 902 void 903 BALMLayout::DoLayout() 904 { 905 fSolver->ValidateLayout(LayoutContext()); 906 907 // set the calculated positions and sizes for every area 908 for (int32 i = 0; i < CountItems(); i++) 909 AreaFor(ItemAt(i))->_DoLayout(LayoutArea().LeftTop()); 910 } 911 912 913 LinearSpec* 914 BALMLayout::Solver() const 915 { 916 return fSolver->Solver(); 917 } 918 919 920 void 921 BALMLayout::SetInsets(float left, float top, float right, 922 float bottom) 923 { 924 fLeftInset = BControlLook::ComposeSpacing(left); 925 fTopInset = BControlLook::ComposeSpacing(top); 926 fRightInset = BControlLook::ComposeSpacing(right); 927 fBottomInset = BControlLook::ComposeSpacing(bottom); 928 929 InvalidateLayout(); 930 } 931 932 933 void 934 BALMLayout::SetInsets(float horizontal, float vertical) 935 { 936 fLeftInset = BControlLook::ComposeSpacing(horizontal); 937 fRightInset = fLeftInset; 938 939 fTopInset = BControlLook::ComposeSpacing(vertical); 940 fBottomInset = fTopInset; 941 942 InvalidateLayout(); 943 } 944 945 946 void 947 BALMLayout::SetInsets(float insets) 948 { 949 fLeftInset = BControlLook::ComposeSpacing(insets); 950 fRightInset = fLeftInset; 951 fTopInset = fLeftInset; 952 fBottomInset = fLeftInset; 953 954 InvalidateLayout(); 955 } 956 957 958 void 959 BALMLayout::GetInsets(float* left, float* top, float* right, 960 float* bottom) const 961 { 962 if (left) 963 *left = fLeftInset; 964 if (top) 965 *top = fTopInset; 966 if (right) 967 *right = fRightInset; 968 if (bottom) 969 *bottom = fBottomInset; 970 } 971 972 973 void 974 BALMLayout::SetSpacing(float hSpacing, float vSpacing) 975 { 976 fHSpacing = BControlLook::ComposeSpacing(hSpacing); 977 fVSpacing = BControlLook::ComposeSpacing(vSpacing); 978 } 979 980 981 void 982 BALMLayout::GetSpacing(float *_hSpacing, float *_vSpacing) const 983 { 984 if (_hSpacing) 985 *_hSpacing = fHSpacing; 986 if (_vSpacing) 987 *_vSpacing = fVSpacing; 988 } 989 990 991 float 992 BALMLayout::InsetForTab(XTab* tab) const 993 { 994 if (tab == fLeft.Get()) 995 return fLeftInset; 996 if (tab == fRight.Get()) 997 return fRightInset; 998 return fHSpacing / 2; 999 } 1000 1001 1002 float 1003 BALMLayout::InsetForTab(YTab* tab) const 1004 { 1005 if (tab == fTop.Get()) 1006 return fTopInset; 1007 if (tab == fBottom.Get()) 1008 return fBottomInset; 1009 return fVSpacing / 2; 1010 } 1011 1012 1013 void 1014 BALMLayout::UpdateConstraints(BLayoutContext* context) 1015 { 1016 for (int i = 0; i < CountItems(); i++) 1017 AreaFor(ItemAt(i))->InvalidateSizeConstraints(); 1018 fRowColumnManager->UpdateConstraints(); 1019 1020 if (context) { 1021 BSize size(LayoutArea().Size()); 1022 Right()->SetRange(size.width, size.width); 1023 Bottom()->SetRange(size.height, size.height); 1024 } 1025 } 1026 1027 1028 void BALMLayout::_RemoveSelfFromTab(XTab* tab) { tab->LayoutLeaving(this); } 1029 void BALMLayout::_RemoveSelfFromTab(YTab* tab) { tab->LayoutLeaving(this); } 1030 1031 bool BALMLayout::_HasTabInLayout(XTab* tab) { return tab->IsInLayout(this); } 1032 bool BALMLayout::_HasTabInLayout(YTab* tab) { return tab->IsInLayout(this); } 1033 1034 bool BALMLayout::_AddedTab(XTab* tab) { return tab->AddedToLayout(this); } 1035 bool BALMLayout::_AddedTab(YTab* tab) { return tab->AddedToLayout(this); } 1036 1037 1038 BLayoutItem* 1039 BALMLayout::_LayoutItemToAdd(BView* view) 1040 { 1041 if (view->GetLayout()) 1042 return view->GetLayout(); 1043 return new(std::nothrow) BViewLayoutItem(view); 1044 } 1045 1046 1047 status_t 1048 BALMLayout::Perform(perform_code d, void* arg) 1049 { 1050 return BAbstractLayout::Perform(d, arg); 1051 } 1052 1053 1054 void BALMLayout::_ReservedALMLayout1() {} 1055 void BALMLayout::_ReservedALMLayout2() {} 1056 void BALMLayout::_ReservedALMLayout3() {} 1057 void BALMLayout::_ReservedALMLayout4() {} 1058 void BALMLayout::_ReservedALMLayout5() {} 1059 void BALMLayout::_ReservedALMLayout6() {} 1060 void BALMLayout::_ReservedALMLayout7() {} 1061 void BALMLayout::_ReservedALMLayout8() {} 1062 void BALMLayout::_ReservedALMLayout9() {} 1063 void BALMLayout::_ReservedALMLayout10() {} 1064 1065