1/* 2 * Copyright 2010-2015 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alex Wilson, yourpalal2@gmail.com 7 * Augustin Cavalier <waddlesplash> 8 */ 9 10 11/*! 12 \page layout_intro Introduction to the Layout API 13 14 Haiku's Layout API is centered around the BLayoutItem and BLayout classes. 15 The BLayoutItem class represents thing that can be managed by a BLayout, 16 which is itself a BLayoutItem. Before we go any further, it is a good idea 17 to familiarize yourself with the different BLayout classes available in 18 Haiku: 19 \li BGroupLayout 20 \li BGridLayout 21 \li BCardLayout 22 \li BSplitView 23 24 You'll notice that BSplitView is not actually a BLayout, but a BView. The 25 BSplitView class uses a custom BLayout behind the scenes, but because it 26 must also be able to draw, a BView is required. Other BLayout objects have 27 BView objects that can be used for convenience. 28 \li BGroupLayout : BGroupView 29 \li BGridLayout : BGridView 30 \li BCardLayout : BTabView (also provides on-screen tabs) 31 32 Although it is not necessary to use these classes to make use of the 33 corresponding layouts, it does make things easier. 34 35 Once you have an understanding of what each BLayout does, you can start 36 designing an interface with them. Let's consider a very simple window, 37 with a single item in the center. For this, any of the layouts mentioned 38 above would work, but we'll use a BGroupLayout, because it suits this 39 purpose the best. 40 41 The BGroupLayout constructor is: 42 43\code 44BGroupLayout(orientation orientation, float spacing = B_USE_DEFAULT_SPACING) 45\endcode 46 47 Because we only have one item in this layout, \c orientation and \c spacing 48 become irrelevant. Let's choose B_VERTICAL for \c orientation, and leave 49 \c spacing at its default. 50 51\code 52BGroupLayout* group = new BGroupLayout(B_VERTICAL); 53BWindow* window = MakeWindow(); 54window->SetLayout(group); 55\endcode 56 57 Before we can add anything to our layout, we must attach it to something, 58 and here we've used the BWindow::SetLayout() method to accomplish that. 59 By doing this, \c window takes ownership of \c group, so there is no need 60 to manually <tt>delete group</tt> when we're done with it. 61 62 Now that we've got our BGroupLayout in place, we can start adding things 63 to it, so let's add a BStringView. 64 65\code 66group->AddView(MakeStringView("Haiku rocks!")); 67\endcode 68 69 Now we've got a BWindow with a horizontal BGroupLayout holding 70 a single BView. However, if we want to ensure that our BStringView is always 71 centered in the window, we should give it an explicit BAlignment. So the 72 last line becomes: 73 74\code 75BLayoutItem* stringView = group->AddView(MakeStringView("Haiku rocks!")); 76stringView->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER, 77 B_ALIGN_VERTICAL_CENTER); 78\endcode 79 80 Now our BStringView will always be right in the middle of the space 81 allotted to it, which at the moment is the whole of \c window. 82 83 Now let's add a BMenuBar: 84 85\code 86group->AddView(0, MakeMenuBar()); 87group->SetInsets(0, 0, 0, 0); 88\endcode 89 90 Because we want our BMenuBar to appear at the very top of the window, we 91 have to insert it at index \c 0, above the BStringView we added earlier. 92 We also use BTwoDimensionalLayout::SetInsets() to make sure that our 93 BMenuBar is flush to the edges of \c window. We also want a bit of 94 space between our BMenuBar and our BStringView, but \c group's spacing has 95 already been set by the BGroupLayout constructor, so we don't need to do 96 that. 97 98 Now that we've put our BGroupLayout to good use, we can rest easy, assured 99 that GUI will always look nice, no matter what font is used, or how big or 100 little \c window is stretched. Of course, very few interfaces are as simple 101 as this one. 102 103 The layout classes can deal with complex layouts. Suppose, for 104 example, that we wanted to add a grid of BButtons under our BStringView. 105 We could use a BGridLayout for this. The BGridLayout constructor is: 106 107\code 108BGridLayout(float horizontal = B_USE_DEFAULT_SPACING, 109 float vertical = B_USE_DEFAULT_SPACING); 110\endcode 111 112 Because we want a bit of breathing room between our buttons, we'll leave 113 vertical and horizontal spacing as is. 114 115\code 116BGridLayout* grid = new BGridLayout(); 117group->AddItem(grid); 118\endcode 119 120 You'll notice that we've added \c grid directly to \c group. This means that 121 any BView objects we add to \c grid will become children of \c window, but 122 will be positioned by \c grid. 123 124\code 125grid->AddView(MakeSmallButton(), 0, 0); 126grid->AddView(MakeSmallButton(), 1, 0); 127grid->AddView(MakeBigButton(), 0, 1, 2, 1); 128grid->AddView(MakeSmallButton(), 1, 2); 129\endcode 130 131 Now we've got a nice grid of BButton objects, let's go over it quickly: 132 \li \c grid has two columns and three rows. 133 \li The cells (0, 0), (1, 0), and (1, 2) hold small buttons 134 \li The cells (0, 1) and (1, 1) hold a single button that spans both 135 cells. 136 \li The cell (0, 2) is empty. 137 138 One of the features you'll find incredibly handy in the layout API is the 139 builders in LayoutBuilder.h. Here's how our whole layout would look if it 140 were done with these builders: 141 142\code 143BLayoutBuilder::Group<>(window, B_VERTICAL) 144 .SetInsets(0, 0, 0, 0) 145 .Add(MakeMenuBar()) 146 .Add(MakeStringView("Haiku rocks!")) 147 .AddGrid() 148 .Add(MakeSmallButton(), 0, 0) 149 .Add(MakeSmallButton(), 1, 0) 150 .Add(MakeBigButton(), 0, 1, 2, 1) 151 .Add(MakeSmallButton(), 1, 2); 152\endcode 153 154 This is only one way that you could build this layout, but it is probably 155 the most succinct. Functionally, this is equivalent to all the previous 156 code in this introduction. 157 158\par Special Handling for BBox 159 BBox is a "container" view that can contain other views. 160 The use of the layout manager within an 161 instance of BBox is a special case. Code such as is shown below is 162 necessary to automatically layout views within a BBox. 163 164\code 165BBox *box = new BBox("box-example"); 166BGroupLayout *boxLayout = BLayoutBuilder::Group<>(B_HORIZONTAL) 167 .Add(button1) 168 .Add(button2); 169 170box->AddChild(boxLayout->View()); 171\endcode 172 173*/ 174