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