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