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