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