1 /* 2 * Copyright 2009, 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 BGroupView(orientation, spacing))->GroupLayout()) 244 { 245 window->SetLayout(fLayout); 246 } 247 248 249 template<typename ParentBuilder> 250 Group<ParentBuilder>::Group(BGroupLayout* layout) 251 : 252 fLayout(layout) 253 { 254 } 255 256 257 template<typename ParentBuilder> 258 Group<ParentBuilder>::Group(BGroupView* view) 259 : 260 fLayout(view->GroupLayout()) 261 { 262 } 263 264 265 template<typename ParentBuilder> 266 BGroupLayout* 267 Group<ParentBuilder>::Layout() const 268 { 269 return fLayout; 270 } 271 272 273 template<typename ParentBuilder> 274 BView* 275 Group<ParentBuilder>::View() const 276 { 277 return fLayout->View(); 278 } 279 280 281 template<typename ParentBuilder> 282 typename Group<ParentBuilder>::ThisBuilder& 283 Group<ParentBuilder>::GetLayout(BGroupLayout** _layout) 284 { 285 *_layout = fLayout; 286 return *this; 287 } 288 289 290 template<typename ParentBuilder> 291 typename Group<ParentBuilder>::ThisBuilder& 292 Group<ParentBuilder>::GetView(BView** _view) 293 { 294 *_view = fLayout->View(); 295 return *this; 296 } 297 298 299 template<typename ParentBuilder> 300 typename Group<ParentBuilder>::ThisBuilder& 301 Group<ParentBuilder>::Add(BView* view) 302 { 303 fLayout->AddView(view); 304 return *this; 305 } 306 307 308 template<typename ParentBuilder> 309 typename Group<ParentBuilder>::ThisBuilder& 310 Group<ParentBuilder>::Add(BView* view, float weight) 311 { 312 fLayout->AddView(view, weight); 313 return *this; 314 } 315 316 317 template<typename ParentBuilder> 318 typename Group<ParentBuilder>::ThisBuilder& 319 Group<ParentBuilder>::Add(BLayoutItem* item) 320 { 321 fLayout->AddItem(item); 322 return *this; 323 } 324 325 326 template<typename ParentBuilder> 327 typename Group<ParentBuilder>::ThisBuilder& 328 Group<ParentBuilder>::Add(BLayoutItem* item, float weight) 329 { 330 fLayout->AddItem(item, weight); 331 return *this; 332 } 333 334 335 template<typename ParentBuilder> 336 typename Group<ParentBuilder>::GroupBuilder 337 Group<ParentBuilder>::AddGroup(enum orientation orientation, float spacing, 338 float weight) 339 { 340 GroupBuilder builder(orientation, spacing); 341 builder.SetParent(this); 342 fLayout->AddView(builder.View(), weight); 343 return builder; 344 } 345 346 347 template<typename ParentBuilder> 348 typename Group<ParentBuilder>::GridBuilder 349 Group<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing, 350 float weight) 351 { 352 GridBuilder builder(horizontalSpacing, verticalSpacing); 353 builder.SetParent(this); 354 fLayout->AddView(builder.View(), weight); 355 return builder; 356 } 357 358 359 template<typename ParentBuilder> 360 typename Group<ParentBuilder>::SplitBuilder 361 Group<ParentBuilder>::AddSplit(enum orientation orientation, float spacing, 362 float weight) 363 { 364 SplitBuilder builder(orientation, spacing); 365 builder.SetParent(this); 366 fLayout->AddView(builder.View(), weight); 367 return builder; 368 } 369 370 371 template<typename ParentBuilder> 372 typename Group<ParentBuilder>::ThisBuilder& 373 Group<ParentBuilder>::AddGlue(float weight) 374 { 375 fLayout->AddItem(BSpaceLayoutItem::CreateGlue(), weight); 376 return *this; 377 } 378 379 380 template<typename ParentBuilder> 381 typename Group<ParentBuilder>::ThisBuilder& 382 Group<ParentBuilder>::AddStrut(float size) 383 { 384 if (fLayout->Orientation() == B_HORIZONTAL) 385 fLayout->AddItem(BSpaceLayoutItem::CreateHorizontalStrut(size)); 386 else 387 fLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(size)); 388 389 return *this; 390 } 391 392 393 template<typename ParentBuilder> 394 typename Group<ParentBuilder>::ThisBuilder& 395 Group<ParentBuilder>::SetInsets(float left, float top, float right, 396 float bottom) 397 { 398 fLayout->SetInsets(left, top, right, bottom); 399 return *this; 400 } 401 402 403 template<typename ParentBuilder> 404 Group<ParentBuilder>::operator BGroupLayout*() 405 { 406 return fLayout; 407 } 408 409 410 template<typename ParentBuilder> 411 Group<ParentBuilder>::operator BView*() 412 { 413 return fLayout->View(); 414 } 415 416 417 // #pragma mark - Grid 418 419 420 template<typename ParentBuilder> 421 Grid<ParentBuilder>::Grid(float horizontalSpacing, float verticalSpacing) 422 : 423 fLayout((new BGridView(horizontalSpacing, verticalSpacing))->GridLayout()) 424 { 425 } 426 427 428 template<typename ParentBuilder> 429 Grid<ParentBuilder>::Grid(BWindow* window, float horizontalSpacing, 430 float verticalSpacing) 431 : 432 fLayout((new BGridView(horizontalSpacing, verticalSpacing))->GridLayout()) 433 { 434 window->SetLayout(fLayout); 435 } 436 437 438 template<typename ParentBuilder> 439 Grid<ParentBuilder>::Grid(BGridLayout* layout) 440 : 441 fLayout(layout) 442 { 443 } 444 445 446 template<typename ParentBuilder> 447 Grid<ParentBuilder>::Grid(BGridView* view) 448 : 449 fLayout(view->GridLayout()) 450 { 451 } 452 453 454 template<typename ParentBuilder> 455 BGridLayout* 456 Grid<ParentBuilder>::Layout() const 457 { 458 return fLayout; 459 } 460 461 462 template<typename ParentBuilder> 463 BView* 464 Grid<ParentBuilder>::View() const 465 { 466 return fLayout->View(); 467 } 468 469 470 template<typename ParentBuilder> 471 typename Grid<ParentBuilder>::ThisBuilder& 472 Grid<ParentBuilder>::GetLayout(BGridLayout** _layout) 473 { 474 *_layout = fLayout; 475 return *this; 476 } 477 478 479 template<typename ParentBuilder> 480 typename Grid<ParentBuilder>::ThisBuilder& 481 Grid<ParentBuilder>::GetView(BView** _view) 482 { 483 *_view = fLayout->View(); 484 return *this; 485 } 486 487 488 template<typename ParentBuilder> 489 typename Grid<ParentBuilder>::ThisBuilder& 490 Grid<ParentBuilder>::Add(BView* view, int32 column, int32 row, 491 int32 columnCount, int32 rowCount) 492 { 493 fLayout->AddView(view, column, row, columnCount, rowCount); 494 return *this; 495 } 496 497 498 template<typename ParentBuilder> 499 typename Grid<ParentBuilder>::ThisBuilder& 500 Grid<ParentBuilder>::Add(BLayoutItem* item, int32 column, int32 row, 501 int32 columnCount, int32 rowCount) 502 { 503 fLayout->AddItem(item, column, row, columnCount, rowCount); 504 return *this; 505 } 506 507 508 template<typename ParentBuilder> 509 typename Grid<ParentBuilder>::ThisBuilder& 510 Grid<ParentBuilder>::AddMenuField(BMenuField* menuField, int32 column, 511 int32 row, alignment labelAlignment, int32 columnCount, int32 rowCount) 512 { 513 BLayoutItem* item = menuField->CreateLabelLayoutItem(); 514 item->SetExplicitAlignment( 515 BAlignment(labelAlignment, B_ALIGN_VERTICAL_UNSET)); 516 fLayout->AddItem(item, column, row, columnCount, rowCount); 517 fLayout->AddItem(menuField->CreateMenuBarLayoutItem(), column + columnCount, 518 row, columnCount, rowCount); 519 return *this; 520 } 521 522 523 template<typename ParentBuilder> 524 typename Grid<ParentBuilder>::ThisBuilder& 525 Grid<ParentBuilder>::AddTextControl(BTextControl* textControl, int32 column, 526 int32 row, alignment labelAlignment, int32 columnCount, int32 rowCount) 527 { 528 BLayoutItem* item = textControl->CreateLabelLayoutItem(); 529 item->SetExplicitAlignment( 530 BAlignment(labelAlignment, B_ALIGN_VERTICAL_UNSET)); 531 fLayout->AddItem(item, column, row, columnCount, rowCount); 532 fLayout->AddItem(textControl->CreateTextViewLayoutItem(), 533 column + columnCount, row, columnCount, rowCount); 534 return *this; 535 } 536 537 538 template<typename ParentBuilder> 539 typename Grid<ParentBuilder>::GroupBuilder 540 Grid<ParentBuilder>::AddGroup(enum orientation orientation, float spacing, 541 int32 column, int32 row, int32 columnCount, int32 rowCount) 542 { 543 GroupBuilder builder(orientation, spacing); 544 builder.SetParent(this); 545 fLayout->AddView(builder.View(), column, row, columnCount, rowCount); 546 return builder; 547 } 548 549 550 template<typename ParentBuilder> 551 typename Grid<ParentBuilder>::GridBuilder 552 Grid<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing, 553 int32 column, int32 row, int32 columnCount, int32 rowCount) 554 { 555 GridBuilder builder(horizontalSpacing, verticalSpacing); 556 builder.SetParent(this); 557 fLayout->AddView(builder.View(), column, row, columnCount, rowCount); 558 return builder; 559 } 560 561 562 template<typename ParentBuilder> 563 typename Grid<ParentBuilder>::SplitBuilder 564 Grid<ParentBuilder>::AddSplit(enum orientation orientation, float spacing, 565 int32 column, int32 row, int32 columnCount, int32 rowCount) 566 { 567 SplitBuilder builder(orientation, spacing); 568 builder.SetParent(this); 569 fLayout->AddView(builder.View(), column, row, columnCount, rowCount); 570 return builder; 571 } 572 573 574 template<typename ParentBuilder> 575 typename Grid<ParentBuilder>::ThisBuilder& 576 Grid<ParentBuilder>::SetColumnWeight(int32 column, float weight) 577 { 578 fLayout->SetColumnWeight(column, weight); 579 return *this; 580 } 581 582 583 template<typename ParentBuilder> 584 typename Grid<ParentBuilder>::ThisBuilder& 585 Grid<ParentBuilder>::SetRowWeight(int32 row, float weight) 586 { 587 fLayout->SetRowWeight(row, weight); 588 return *this; 589 } 590 591 592 template<typename ParentBuilder> 593 typename Grid<ParentBuilder>::ThisBuilder& 594 Grid<ParentBuilder>::SetInsets(float left, float top, float right, 595 float bottom) 596 { 597 fLayout->SetInsets(left, top, right, bottom); 598 return *this; 599 } 600 601 602 template<typename ParentBuilder> 603 Grid<ParentBuilder>::operator BGridLayout*() 604 { 605 return fLayout; 606 } 607 608 609 template<typename ParentBuilder> 610 Grid<ParentBuilder>::operator BView*() 611 { 612 return fLayout->View(); 613 } 614 615 616 // #pragma mark - Split 617 618 619 template<typename ParentBuilder> 620 Split<ParentBuilder>::Split(enum orientation orientation, float spacing) 621 : 622 fView(new BSplitView(orientation, spacing)) 623 { 624 } 625 626 627 template<typename ParentBuilder> 628 Split<ParentBuilder>::Split(BSplitView* view) 629 : 630 fView(view) 631 { 632 } 633 634 635 template<typename ParentBuilder> 636 BSplitView* 637 Split<ParentBuilder>::View() const 638 { 639 return fView; 640 } 641 642 643 template<typename ParentBuilder> 644 typename Split<ParentBuilder>::ThisBuilder& 645 Split<ParentBuilder>::GetView(BSplitView** _view) 646 { 647 *_view = fView; 648 return *this; 649 } 650 651 652 template<typename ParentBuilder> 653 typename Split<ParentBuilder>::ThisBuilder& 654 Split<ParentBuilder>::Add(BView* view) 655 { 656 fView->AddChild(view); 657 return *this; 658 } 659 660 661 template<typename ParentBuilder> 662 typename Split<ParentBuilder>::ThisBuilder& 663 Split<ParentBuilder>::Add(BView* view, float weight) 664 { 665 fView->AddChild(view, weight); 666 return *this; 667 } 668 669 670 template<typename ParentBuilder> 671 typename Split<ParentBuilder>::ThisBuilder& 672 Split<ParentBuilder>::Add(BLayoutItem* item) 673 { 674 fView->AddChild(item); 675 return *this; 676 } 677 678 679 template<typename ParentBuilder> 680 typename Split<ParentBuilder>::ThisBuilder& 681 Split<ParentBuilder>::Add(BLayoutItem* item, float weight) 682 { 683 fView->AddChild(item, weight); 684 return *this; 685 } 686 687 688 template<typename ParentBuilder> 689 typename Split<ParentBuilder>::GroupBuilder 690 Split<ParentBuilder>::AddGroup(enum orientation orientation, float spacing, 691 float weight) 692 { 693 GroupBuilder builder(orientation, spacing); 694 builder.SetParent(this); 695 fView->AddChild(builder.View(), weight); 696 return builder; 697 } 698 699 700 template<typename ParentBuilder> 701 typename Split<ParentBuilder>::GridBuilder 702 Split<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing, 703 float weight) 704 { 705 GridBuilder builder(horizontalSpacing, verticalSpacing); 706 builder.SetParent(this); 707 fView->AddChild(builder.View(), weight); 708 return builder; 709 } 710 711 712 template<typename ParentBuilder> 713 typename Split<ParentBuilder>::SplitBuilder 714 Split<ParentBuilder>::AddSplit(enum orientation orientation, float spacing, 715 float weight) 716 { 717 SplitBuilder builder(orientation, spacing); 718 builder.SetParent(this); 719 fView->AddChild(builder.View(), weight); 720 return builder; 721 } 722 723 724 template<typename ParentBuilder> 725 typename Split<ParentBuilder>::ThisBuilder& 726 Split<ParentBuilder>::SetCollapsible(bool collapsible) 727 { 728 fView->SetCollapsible(collapsible); 729 return *this; 730 } 731 732 733 template<typename ParentBuilder> 734 typename Split<ParentBuilder>::ThisBuilder& 735 Split<ParentBuilder>::SetCollapsible(int32 index, bool collapsible) 736 { 737 fView->SetCollapsible(index, collapsible); 738 return *this; 739 } 740 741 742 template<typename ParentBuilder> 743 typename Split<ParentBuilder>::ThisBuilder& 744 Split<ParentBuilder>::SetCollapsible(int32 first, int32 last, bool collapsible) 745 { 746 fView->SetCollapsible(first, last, collapsible); 747 return *this; 748 } 749 750 751 template<typename ParentBuilder> 752 typename Split<ParentBuilder>::ThisBuilder& 753 Split<ParentBuilder>::SetInsets(float left, float top, float right, 754 float bottom) 755 { 756 fView->SetInsets(left, top, right, bottom); 757 return *this; 758 } 759 760 761 template<typename ParentBuilder> 762 Split<ParentBuilder>::operator BSplitView*() 763 { 764 return fView; 765 } 766 767 768 } // namespace BLayoutBuilder 769 770 771 #endif // _LAYOUT_BUILDER_H 772