1 /* 2 * Copyright 2009-2010, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _LAYOUT_BUILDER_H 6 #define _LAYOUT_BUILDER_H 7 8 9 #include <GridLayout.h> 10 #include <GridView.h> 11 #include <GroupLayout.h> 12 #include <GroupView.h> 13 #include <MenuField.h> 14 #include <SpaceLayoutItem.h> 15 #include <SplitView.h> 16 #include <TextControl.h> 17 #include <Window.h> 18 19 20 namespace BLayoutBuilder { 21 22 template<typename ParentBuilder> class Base; 23 template<typename ParentBuilder = void*> class Group; 24 template<typename ParentBuilder = void*> class Grid; 25 template<typename ParentBuilder = void*> class Split; 26 27 28 template<typename ParentBuilder> 29 class Base { 30 protected: 31 inline Base(); 32 33 public: 34 inline void SetParent(ParentBuilder* parent); 35 // conceptually private 36 37 inline ParentBuilder& End(); 38 39 protected: 40 ParentBuilder* fParent; 41 }; 42 43 44 template<typename ParentBuilder> 45 class Group : public Base<ParentBuilder> { 46 public: 47 typedef Group<ParentBuilder> ThisBuilder; 48 typedef Group<ThisBuilder> GroupBuilder; 49 typedef Grid<ThisBuilder> GridBuilder; 50 typedef Split<ThisBuilder> SplitBuilder; 51 52 public: 53 inline Group(enum orientation orientation 54 = B_HORIZONTAL, 55 float spacing = 0.0f); 56 inline Group(BWindow* window, 57 enum orientation orientation = B_HORIZONTAL, 58 float spacing = 0.0f); 59 inline Group(BGroupLayout* layout); 60 inline Group(BGroupView* view); 61 62 inline BGroupLayout* Layout() const; 63 inline BView* View() const; 64 inline ThisBuilder& GetLayout(BGroupLayout** _layout); 65 inline ThisBuilder& GetView(BView** _view); 66 67 inline ThisBuilder& Add(BView* view); 68 inline ThisBuilder& Add(BView* view, float weight); 69 inline ThisBuilder& Add(BLayoutItem* item); 70 inline ThisBuilder& Add(BLayoutItem* item, float weight); 71 72 inline GroupBuilder AddGroup(enum orientation orientation, 73 float spacing = 0.0f, float weight = 1.0f); 74 inline GridBuilder AddGrid(float horizontalSpacing = 0.0f, 75 float verticalSpacing = 0.0f, 76 float weight = 1.0f); 77 inline SplitBuilder AddSplit(enum orientation orientation, 78 float spacing = 0.0f, float weight = 1.0f); 79 80 inline ThisBuilder& AddGlue(float weight = 1.0f); 81 inline ThisBuilder& AddStrut(float size); 82 83 inline ThisBuilder& SetInsets(float left, float top, float right, 84 float bottom); 85 86 inline operator BGroupLayout*(); 87 inline operator BView*(); 88 89 private: 90 BGroupLayout* fLayout; 91 }; 92 93 94 template<typename ParentBuilder> 95 class Grid : public Base<ParentBuilder> { 96 public: 97 typedef Grid<ParentBuilder> ThisBuilder; 98 typedef Group<ThisBuilder> GroupBuilder; 99 typedef Grid<ThisBuilder> GridBuilder; 100 typedef Split<ThisBuilder> SplitBuilder; 101 102 public: 103 inline Grid(float horizontalSpacing = 0.0f, 104 float verticalSpacing = 0.0f); 105 inline Grid(BWindow* window, 106 float horizontalSpacing = 0.0f, 107 float verticalSpacing = 0.0f); 108 inline Grid(BGridLayout* layout); 109 inline Grid(BGridView* view); 110 111 inline BGridLayout* Layout() const; 112 inline BView* View() const; 113 inline ThisBuilder& GetLayout(BGridLayout** _layout); 114 inline ThisBuilder& GetView(BView** _view); 115 116 inline ThisBuilder& Add(BView* view, int32 column, int32 row, 117 int32 columnCount = 1, int32 rowCount = 1); 118 inline ThisBuilder& Add(BLayoutItem* item, int32 column, int32 row, 119 int32 columnCount = 1, int32 rowCount = 1); 120 inline ThisBuilder& AddMenuField(BMenuField* menuField, 121 int32 column, int32 row, 122 alignment labelAlignment 123 = B_ALIGN_HORIZONTAL_UNSET, 124 int32 columnCount = 1, int32 rowCount = 1); 125 inline ThisBuilder& AddTextControl(BTextControl* textControl, 126 int32 column, int32 row, 127 alignment labelAlignment 128 = B_ALIGN_HORIZONTAL_UNSET, 129 int32 columnCount = 1, int32 rowCount = 1); 130 131 inline GroupBuilder AddGroup(enum orientation orientation, 132 float spacing, int32 column, int32 row, 133 int32 columnCount = 1, int32 rowCount = 1); 134 inline GridBuilder AddGrid(float horizontalSpacing, 135 float verticalSpacing, int32 column, 136 int32 row, int32 columnCount = 1, 137 int32 rowCount = 1); 138 inline SplitBuilder AddSplit(enum orientation orientation, 139 float spacing, int32 column, int32 row, 140 int32 columnCount = 1, int32 rowCount = 1); 141 142 inline ThisBuilder& SetColumnWeight(int32 column, float weight); 143 inline ThisBuilder& SetRowWeight(int32 row, float weight); 144 145 inline ThisBuilder& SetInsets(float left, float top, float right, 146 float bottom); 147 148 inline operator BGridLayout*(); 149 inline operator BView*(); 150 151 private: 152 BGridLayout* fLayout; 153 }; 154 155 156 template<typename ParentBuilder> 157 class Split : public Base<ParentBuilder> { 158 public: 159 typedef Split<ParentBuilder> ThisBuilder; 160 typedef Group<ThisBuilder> GroupBuilder; 161 typedef Grid<ThisBuilder> GridBuilder; 162 typedef Split<ThisBuilder> SplitBuilder; 163 164 public: 165 inline Split(enum orientation orientation 166 = B_HORIZONTAL, 167 float spacing = 0.0f); 168 inline Split(BSplitView* view); 169 170 inline BSplitView* View() const; 171 inline ThisBuilder& GetView(BSplitView** _view); 172 173 inline ThisBuilder& Add(BView* view); 174 inline ThisBuilder& Add(BView* view, float weight); 175 inline ThisBuilder& Add(BLayoutItem* item); 176 inline ThisBuilder& Add(BLayoutItem* item, float weight); 177 178 inline GroupBuilder AddGroup(enum orientation orientation, 179 float spacing = 0.0f, float weight = 1.0f); 180 inline GridBuilder AddGrid(float horizontalSpacing = 0.0f, 181 float verticalSpacing = 0.0f, 182 float weight = 1.0f); 183 inline SplitBuilder AddSplit(enum orientation orientation, 184 float spacing = 0.0f, float weight = 1.0f); 185 186 inline ThisBuilder& SetCollapsible(bool collapsible); 187 inline ThisBuilder& SetCollapsible(int32 index, bool collapsible); 188 inline ThisBuilder& SetCollapsible(int32 first, int32 last, 189 bool collapsible); 190 191 inline ThisBuilder& SetInsets(float left, float top, float right, 192 float bottom); 193 194 inline operator BSplitView*(); 195 196 private: 197 BSplitView* fView; 198 }; 199 200 201 // #pragma mark - Base 202 203 204 template<typename ParentBuilder> 205 Base<ParentBuilder>::Base() 206 : 207 fParent(NULL) 208 { 209 } 210 211 212 template<typename ParentBuilder> 213 void 214 Base<ParentBuilder>::SetParent(ParentBuilder* parent) 215 { 216 fParent = parent; 217 } 218 219 220 template<typename ParentBuilder> 221 ParentBuilder& 222 Base<ParentBuilder>::End() 223 { 224 return *fParent; 225 } 226 227 228 // #pragma mark - Group 229 230 231 template<typename ParentBuilder> 232 Group<ParentBuilder>::Group(enum orientation orientation, float spacing) 233 : 234 fLayout((new BGroupView(orientation, spacing))->GroupLayout()) 235 { 236 } 237 238 239 template<typename ParentBuilder> 240 Group<ParentBuilder>::Group(BWindow* window, enum orientation orientation, 241 float spacing) 242 : 243 fLayout(new BGroupLayout(orientation, spacing)) 244 { 245 window->SetLayout(fLayout); 246 247 fLayout->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 248 // TODO: we get a white background if we don't do this 249 } 250 251 252 template<typename ParentBuilder> 253 Group<ParentBuilder>::Group(BGroupLayout* layout) 254 : 255 fLayout(layout) 256 { 257 } 258 259 260 template<typename ParentBuilder> 261 Group<ParentBuilder>::Group(BGroupView* view) 262 : 263 fLayout(view->GroupLayout()) 264 { 265 } 266 267 268 template<typename ParentBuilder> 269 BGroupLayout* 270 Group<ParentBuilder>::Layout() const 271 { 272 return fLayout; 273 } 274 275 276 template<typename ParentBuilder> 277 BView* 278 Group<ParentBuilder>::View() const 279 { 280 return fLayout->View(); 281 } 282 283 284 template<typename ParentBuilder> 285 typename Group<ParentBuilder>::ThisBuilder& 286 Group<ParentBuilder>::GetLayout(BGroupLayout** _layout) 287 { 288 *_layout = fLayout; 289 return *this; 290 } 291 292 293 template<typename ParentBuilder> 294 typename Group<ParentBuilder>::ThisBuilder& 295 Group<ParentBuilder>::GetView(BView** _view) 296 { 297 *_view = fLayout->View(); 298 return *this; 299 } 300 301 302 template<typename ParentBuilder> 303 typename Group<ParentBuilder>::ThisBuilder& 304 Group<ParentBuilder>::Add(BView* view) 305 { 306 fLayout->AddView(view); 307 return *this; 308 } 309 310 311 template<typename ParentBuilder> 312 typename Group<ParentBuilder>::ThisBuilder& 313 Group<ParentBuilder>::Add(BView* view, float weight) 314 { 315 fLayout->AddView(view, weight); 316 return *this; 317 } 318 319 320 template<typename ParentBuilder> 321 typename Group<ParentBuilder>::ThisBuilder& 322 Group<ParentBuilder>::Add(BLayoutItem* item) 323 { 324 fLayout->AddItem(item); 325 return *this; 326 } 327 328 329 template<typename ParentBuilder> 330 typename Group<ParentBuilder>::ThisBuilder& 331 Group<ParentBuilder>::Add(BLayoutItem* item, float weight) 332 { 333 fLayout->AddItem(item, weight); 334 return *this; 335 } 336 337 338 template<typename ParentBuilder> 339 typename Group<ParentBuilder>::GroupBuilder 340 Group<ParentBuilder>::AddGroup(enum orientation orientation, float spacing, 341 float weight) 342 { 343 GroupBuilder builder(orientation, spacing); 344 builder.SetParent(this); 345 fLayout->AddView(builder.View(), weight); 346 return builder; 347 } 348 349 350 template<typename ParentBuilder> 351 typename Group<ParentBuilder>::GridBuilder 352 Group<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing, 353 float weight) 354 { 355 GridBuilder builder(horizontalSpacing, verticalSpacing); 356 builder.SetParent(this); 357 fLayout->AddView(builder.View(), weight); 358 return builder; 359 } 360 361 362 template<typename ParentBuilder> 363 typename Group<ParentBuilder>::SplitBuilder 364 Group<ParentBuilder>::AddSplit(enum orientation orientation, float spacing, 365 float weight) 366 { 367 SplitBuilder builder(orientation, spacing); 368 builder.SetParent(this); 369 fLayout->AddView(builder.View(), weight); 370 return builder; 371 } 372 373 374 template<typename ParentBuilder> 375 typename Group<ParentBuilder>::ThisBuilder& 376 Group<ParentBuilder>::AddGlue(float weight) 377 { 378 fLayout->AddItem(BSpaceLayoutItem::CreateGlue(), weight); 379 return *this; 380 } 381 382 383 template<typename ParentBuilder> 384 typename Group<ParentBuilder>::ThisBuilder& 385 Group<ParentBuilder>::AddStrut(float size) 386 { 387 if (fLayout->Orientation() == B_HORIZONTAL) 388 fLayout->AddItem(BSpaceLayoutItem::CreateHorizontalStrut(size)); 389 else 390 fLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(size)); 391 392 return *this; 393 } 394 395 396 template<typename ParentBuilder> 397 typename Group<ParentBuilder>::ThisBuilder& 398 Group<ParentBuilder>::SetInsets(float left, float top, float right, 399 float bottom) 400 { 401 fLayout->SetInsets(left, top, right, bottom); 402 return *this; 403 } 404 405 406 template<typename ParentBuilder> 407 Group<ParentBuilder>::operator BGroupLayout*() 408 { 409 return fLayout; 410 } 411 412 413 template<typename ParentBuilder> 414 Group<ParentBuilder>::operator BView*() 415 { 416 return fLayout->View(); 417 } 418 419 420 // #pragma mark - Grid 421 422 423 template<typename ParentBuilder> 424 Grid<ParentBuilder>::Grid(float horizontalSpacing, float verticalSpacing) 425 : 426 fLayout((new BGridView(horizontalSpacing, verticalSpacing))->GridLayout()) 427 { 428 } 429 430 431 template<typename ParentBuilder> 432 Grid<ParentBuilder>::Grid(BWindow* window, float horizontalSpacing, 433 float verticalSpacing) 434 : 435 fLayout(new BGridLayout(horizontalSpacing, verticalSpacing)) 436 { 437 window->SetLayout(fLayout); 438 439 fLayout->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 440 // TODO: we get a white background if we don't do this 441 } 442 443 444 template<typename ParentBuilder> 445 Grid<ParentBuilder>::Grid(BGridLayout* layout) 446 : 447 fLayout(layout) 448 { 449 } 450 451 452 template<typename ParentBuilder> 453 Grid<ParentBuilder>::Grid(BGridView* view) 454 : 455 fLayout(view->GridLayout()) 456 { 457 } 458 459 460 template<typename ParentBuilder> 461 BGridLayout* 462 Grid<ParentBuilder>::Layout() const 463 { 464 return fLayout; 465 } 466 467 468 template<typename ParentBuilder> 469 BView* 470 Grid<ParentBuilder>::View() const 471 { 472 return fLayout->View(); 473 } 474 475 476 template<typename ParentBuilder> 477 typename Grid<ParentBuilder>::ThisBuilder& 478 Grid<ParentBuilder>::GetLayout(BGridLayout** _layout) 479 { 480 *_layout = fLayout; 481 return *this; 482 } 483 484 485 template<typename ParentBuilder> 486 typename Grid<ParentBuilder>::ThisBuilder& 487 Grid<ParentBuilder>::GetView(BView** _view) 488 { 489 *_view = fLayout->View(); 490 return *this; 491 } 492 493 494 template<typename ParentBuilder> 495 typename Grid<ParentBuilder>::ThisBuilder& 496 Grid<ParentBuilder>::Add(BView* view, int32 column, int32 row, 497 int32 columnCount, int32 rowCount) 498 { 499 fLayout->AddView(view, column, row, columnCount, rowCount); 500 return *this; 501 } 502 503 504 template<typename ParentBuilder> 505 typename Grid<ParentBuilder>::ThisBuilder& 506 Grid<ParentBuilder>::Add(BLayoutItem* item, int32 column, int32 row, 507 int32 columnCount, int32 rowCount) 508 { 509 fLayout->AddItem(item, column, row, columnCount, rowCount); 510 return *this; 511 } 512 513 514 template<typename ParentBuilder> 515 typename Grid<ParentBuilder>::ThisBuilder& 516 Grid<ParentBuilder>::AddMenuField(BMenuField* menuField, int32 column, 517 int32 row, alignment labelAlignment, int32 columnCount, int32 rowCount) 518 { 519 BLayoutItem* item = menuField->CreateLabelLayoutItem(); 520 item->SetExplicitAlignment( 521 BAlignment(labelAlignment, B_ALIGN_VERTICAL_UNSET)); 522 fLayout->AddItem(item, column, row, columnCount, rowCount); 523 fLayout->AddItem(menuField->CreateMenuBarLayoutItem(), column + columnCount, 524 row, columnCount, rowCount); 525 return *this; 526 } 527 528 529 template<typename ParentBuilder> 530 typename Grid<ParentBuilder>::ThisBuilder& 531 Grid<ParentBuilder>::AddTextControl(BTextControl* textControl, int32 column, 532 int32 row, alignment labelAlignment, int32 columnCount, int32 rowCount) 533 { 534 BLayoutItem* item = textControl->CreateLabelLayoutItem(); 535 item->SetExplicitAlignment( 536 BAlignment(labelAlignment, B_ALIGN_VERTICAL_UNSET)); 537 fLayout->AddItem(item, column, row, columnCount, rowCount); 538 fLayout->AddItem(textControl->CreateTextViewLayoutItem(), 539 column + columnCount, row, columnCount, rowCount); 540 return *this; 541 } 542 543 544 template<typename ParentBuilder> 545 typename Grid<ParentBuilder>::GroupBuilder 546 Grid<ParentBuilder>::AddGroup(enum orientation orientation, float spacing, 547 int32 column, int32 row, int32 columnCount, int32 rowCount) 548 { 549 GroupBuilder builder(orientation, spacing); 550 builder.SetParent(this); 551 fLayout->AddView(builder.View(), column, row, columnCount, rowCount); 552 return builder; 553 } 554 555 556 template<typename ParentBuilder> 557 typename Grid<ParentBuilder>::GridBuilder 558 Grid<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing, 559 int32 column, int32 row, int32 columnCount, int32 rowCount) 560 { 561 GridBuilder builder(horizontalSpacing, verticalSpacing); 562 builder.SetParent(this); 563 fLayout->AddView(builder.View(), column, row, columnCount, rowCount); 564 return builder; 565 } 566 567 568 template<typename ParentBuilder> 569 typename Grid<ParentBuilder>::SplitBuilder 570 Grid<ParentBuilder>::AddSplit(enum orientation orientation, float spacing, 571 int32 column, int32 row, int32 columnCount, int32 rowCount) 572 { 573 SplitBuilder builder(orientation, spacing); 574 builder.SetParent(this); 575 fLayout->AddView(builder.View(), column, row, columnCount, rowCount); 576 return builder; 577 } 578 579 580 template<typename ParentBuilder> 581 typename Grid<ParentBuilder>::ThisBuilder& 582 Grid<ParentBuilder>::SetColumnWeight(int32 column, float weight) 583 { 584 fLayout->SetColumnWeight(column, weight); 585 return *this; 586 } 587 588 589 template<typename ParentBuilder> 590 typename Grid<ParentBuilder>::ThisBuilder& 591 Grid<ParentBuilder>::SetRowWeight(int32 row, float weight) 592 { 593 fLayout->SetRowWeight(row, weight); 594 return *this; 595 } 596 597 598 template<typename ParentBuilder> 599 typename Grid<ParentBuilder>::ThisBuilder& 600 Grid<ParentBuilder>::SetInsets(float left, float top, float right, 601 float bottom) 602 { 603 fLayout->SetInsets(left, top, right, bottom); 604 return *this; 605 } 606 607 608 template<typename ParentBuilder> 609 Grid<ParentBuilder>::operator BGridLayout*() 610 { 611 return fLayout; 612 } 613 614 615 template<typename ParentBuilder> 616 Grid<ParentBuilder>::operator BView*() 617 { 618 return fLayout->View(); 619 } 620 621 622 // #pragma mark - Split 623 624 625 template<typename ParentBuilder> 626 Split<ParentBuilder>::Split(enum orientation orientation, float spacing) 627 : 628 fView(new BSplitView(orientation, spacing)) 629 { 630 } 631 632 633 template<typename ParentBuilder> 634 Split<ParentBuilder>::Split(BSplitView* view) 635 : 636 fView(view) 637 { 638 } 639 640 641 template<typename ParentBuilder> 642 BSplitView* 643 Split<ParentBuilder>::View() const 644 { 645 return fView; 646 } 647 648 649 template<typename ParentBuilder> 650 typename Split<ParentBuilder>::ThisBuilder& 651 Split<ParentBuilder>::GetView(BSplitView** _view) 652 { 653 *_view = fView; 654 return *this; 655 } 656 657 658 template<typename ParentBuilder> 659 typename Split<ParentBuilder>::ThisBuilder& 660 Split<ParentBuilder>::Add(BView* view) 661 { 662 fView->AddChild(view); 663 return *this; 664 } 665 666 667 template<typename ParentBuilder> 668 typename Split<ParentBuilder>::ThisBuilder& 669 Split<ParentBuilder>::Add(BView* view, float weight) 670 { 671 fView->AddChild(view, weight); 672 return *this; 673 } 674 675 676 template<typename ParentBuilder> 677 typename Split<ParentBuilder>::ThisBuilder& 678 Split<ParentBuilder>::Add(BLayoutItem* item) 679 { 680 fView->AddChild(item); 681 return *this; 682 } 683 684 685 template<typename ParentBuilder> 686 typename Split<ParentBuilder>::ThisBuilder& 687 Split<ParentBuilder>::Add(BLayoutItem* item, float weight) 688 { 689 fView->AddChild(item, weight); 690 return *this; 691 } 692 693 694 template<typename ParentBuilder> 695 typename Split<ParentBuilder>::GroupBuilder 696 Split<ParentBuilder>::AddGroup(enum orientation orientation, float spacing, 697 float weight) 698 { 699 GroupBuilder builder(orientation, spacing); 700 builder.SetParent(this); 701 fView->AddChild(builder.View(), weight); 702 return builder; 703 } 704 705 706 template<typename ParentBuilder> 707 typename Split<ParentBuilder>::GridBuilder 708 Split<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing, 709 float weight) 710 { 711 GridBuilder builder(horizontalSpacing, verticalSpacing); 712 builder.SetParent(this); 713 fView->AddChild(builder.View(), weight); 714 return builder; 715 } 716 717 718 template<typename ParentBuilder> 719 typename Split<ParentBuilder>::SplitBuilder 720 Split<ParentBuilder>::AddSplit(enum orientation orientation, float spacing, 721 float weight) 722 { 723 SplitBuilder builder(orientation, spacing); 724 builder.SetParent(this); 725 fView->AddChild(builder.View(), weight); 726 return builder; 727 } 728 729 730 template<typename ParentBuilder> 731 typename Split<ParentBuilder>::ThisBuilder& 732 Split<ParentBuilder>::SetCollapsible(bool collapsible) 733 { 734 fView->SetCollapsible(collapsible); 735 return *this; 736 } 737 738 739 template<typename ParentBuilder> 740 typename Split<ParentBuilder>::ThisBuilder& 741 Split<ParentBuilder>::SetCollapsible(int32 index, bool collapsible) 742 { 743 fView->SetCollapsible(index, collapsible); 744 return *this; 745 } 746 747 748 template<typename ParentBuilder> 749 typename Split<ParentBuilder>::ThisBuilder& 750 Split<ParentBuilder>::SetCollapsible(int32 first, int32 last, bool collapsible) 751 { 752 fView->SetCollapsible(first, last, collapsible); 753 return *this; 754 } 755 756 757 template<typename ParentBuilder> 758 typename Split<ParentBuilder>::ThisBuilder& 759 Split<ParentBuilder>::SetInsets(float left, float top, float right, 760 float bottom) 761 { 762 fView->SetInsets(left, top, right, bottom); 763 return *this; 764 } 765 766 767 template<typename ParentBuilder> 768 Split<ParentBuilder>::operator BSplitView*() 769 { 770 return fView; 771 } 772 773 774 } // namespace BLayoutBuilder 775 776 777 #endif // _LAYOUT_BUILDER_H 778