1 //-------------------------------------------------------------------- 2 // 3 // ViewLayoutFactory.cpp 4 // 5 // Written by: Owen Smith 6 // 7 //-------------------------------------------------------------------- 8 9 /* 10 Copyright 1999, Be Incorporated. All Rights Reserved. 11 This file may be used under the terms of the Be Sample Code License. 12 */ 13 14 #include "ViewLayoutFactory.h" 15 16 #include <Button.h> 17 #include <CheckBox.h> 18 #include <TextControl.h> 19 #include <View.h> 20 #include <List.h> 21 #include <algorithm> 22 #include <assert.h> 23 #include <stdio.h> 24 25 template <class T> 26 inline T average(const T& x, const T& y) 27 { 28 return (x + y) / 2; 29 } 30 31 32 //-------------------------------------------------------------------- 33 // ViewLayoutFactory factory generators 34 35 BButton* ViewLayoutFactory::MakeButton(const char* name, const char* label, 36 uint32 msgID, BPoint pos, corner posRef) 37 { 38 BRect dummyFrame(0,0,0,0); 39 BButton* pButton = new BButton(dummyFrame, name, label, 40 new BMessage(msgID)); 41 pButton->ResizeToPreferred(); 42 MoveViewCorner(*pButton, pos, posRef); 43 return pButton; 44 } 45 46 BCheckBox* ViewLayoutFactory::MakeCheckBox(const char* name, 47 const char* label, uint32 msgID, BPoint pos, corner posRef) 48 { 49 BRect dummyFrame(0,0,0,0); 50 BCheckBox* pCheckBox = new BCheckBox(dummyFrame, name, label, 51 new BMessage(msgID)); 52 pCheckBox->ResizeToPreferred(); 53 MoveViewCorner(*pCheckBox, pos, posRef); 54 return pCheckBox; 55 } 56 57 BTextControl* ViewLayoutFactory::MakeTextControl(const char* name, 58 const char* label, const char* text, BPoint pos, float controlWidth, 59 corner posRef) 60 { 61 // Note: this function is almost identical to the regular 62 // BTextControl constructor, but it minimizes the label 63 // width and maximizes the field width, instead of divvying 64 // them up half-&-half or 2 : 3, and gives the standard 65 // flexibility of corner positioning. 66 BRect dummyFrame(0,0,0,0); 67 BTextControl* pCtrl = new BTextControl(dummyFrame, name, label, 68 text, NULL); 69 LayoutTextControl(*pCtrl, pos, controlWidth, posRef); 70 return pCtrl; 71 } 72 73 void ViewLayoutFactory::LayoutTextControl(BTextControl& control, 74 BPoint pos, float controlWidth, corner posRef) 75 { 76 control.ResizeToPreferred(); 77 BTextView* pTextView = control.TextView(); 78 float widthExpand = controlWidth; 79 widthExpand -= control.Bounds().Width(); 80 if (widthExpand > 0) { 81 control.ResizeBy(widthExpand, 0); 82 pTextView->ResizeBy(widthExpand, 0); 83 } 84 MoveViewCorner(control, pos, posRef); 85 } 86 87 88 89 //-------------------------------------------------------------------- 90 // ViewLayoutFactory implementation member functions 91 92 void ViewLayoutFactory::MoveViewCorner(BView& view, BPoint pos, corner posRef) 93 { 94 BRect frame = view.Frame(); 95 BPoint topLeft; 96 switch (posRef) { 97 case CORNER_TOPLEFT: 98 topLeft = pos; 99 break; 100 case CORNER_BOTTOMLEFT: 101 topLeft.x = pos.x; 102 topLeft.y = pos.y - frame.Height(); 103 break; 104 case CORNER_TOPRIGHT: 105 topLeft.x = pos.x - frame.Width(); 106 topLeft.y = pos.y; 107 break; 108 case CORNER_BOTTOMRIGHT: 109 topLeft.x = pos.x - frame.Width(); 110 topLeft.y = pos.y - frame.Height(); 111 break; 112 } 113 114 view.MoveTo(topLeft); 115 } 116 117 void ViewLayoutFactory::Align(BList& viewList, align_side side, 118 float alignLen) 119 { 120 int32 i, len = viewList.CountItems(); 121 if (len <= 1) { 122 return; 123 } 124 125 // make sure alignment is recognized 126 if ((side != ALIGN_LEFT) && (side != ALIGN_TOP) 127 && (side != ALIGN_RIGHT) && (side != ALIGN_BOTTOM) 128 && (side != ALIGN_HCENTER) && (side != ALIGN_VCENTER)) 129 { 130 return; 131 } 132 133 // find initial location for placement, based on head item 134 BPoint viewLoc; 135 BView* pView = reinterpret_cast<BView*>(viewList.ItemAt(0)); 136 if (! pView) { 137 return; 138 } 139 140 BRect frame = pView->Frame(); 141 switch (side) { 142 case ALIGN_LEFT: 143 case ALIGN_TOP: 144 viewLoc.Set(frame.left, frame.top); 145 break; 146 case ALIGN_RIGHT: 147 viewLoc.Set(frame.right, frame.top); 148 break; 149 case ALIGN_BOTTOM: 150 viewLoc.Set(frame.left, frame.bottom); 151 break; 152 case ALIGN_HCENTER: 153 viewLoc.Set(frame.left, average(frame.top, frame.bottom)); 154 break; 155 case ALIGN_VCENTER: 156 viewLoc.Set(average(frame.left, frame.right), frame.top); 157 printf("Aligning along vcenter\nInitial position: "); 158 viewLoc.PrintToStream(); 159 break; 160 } 161 162 // align items relative to head item 163 for (i=1; i<len; i++) { 164 BView* pView = reinterpret_cast<BView*>(viewList.ItemAt(i)); 165 if (pView) { 166 switch (side) { 167 case ALIGN_LEFT: 168 viewLoc.y += alignLen; 169 MoveViewCorner(*pView, viewLoc, CORNER_TOPLEFT); 170 break; 171 case ALIGN_TOP: 172 viewLoc.x += alignLen; 173 MoveViewCorner(*pView, viewLoc, CORNER_TOPLEFT); 174 break; 175 case ALIGN_RIGHT: 176 viewLoc.y += alignLen; 177 MoveViewCorner(*pView, viewLoc, CORNER_TOPRIGHT); 178 break; 179 case ALIGN_BOTTOM: 180 viewLoc.x += alignLen; 181 MoveViewCorner(*pView, viewLoc, CORNER_BOTTOMLEFT); 182 break; 183 case ALIGN_HCENTER: 184 { 185 viewLoc.x += alignLen; 186 BPoint moveLoc = viewLoc; 187 BRect r = pView->Frame(); 188 moveLoc.y -= (r.bottom - r.top) / 2; 189 MoveViewCorner(*pView, moveLoc, CORNER_TOPLEFT); 190 break; 191 } 192 case ALIGN_VCENTER: 193 { 194 viewLoc.y += alignLen; 195 BPoint moveLoc = viewLoc; 196 BRect r = pView->Frame(); 197 moveLoc.x -= (r.right - r.left) / 2; 198 MoveViewCorner(*pView, moveLoc, CORNER_TOPLEFT); 199 break; 200 } 201 } 202 } 203 } 204 } 205 206 void ViewLayoutFactory::ResizeToListMax(BList& viewList, rect_dim resizeDim, 207 corner anchor) 208 { 209 int32 i, len = viewList.CountItems(); 210 float maxWidth = 0.0f, maxHeight = 0.0f; 211 float curWidth = 0.0f, curHeight = 0.0f; 212 213 // find maximum dimensions 214 for (i=0; i<len; i++) { 215 BView* pView = reinterpret_cast<BView*>(viewList.ItemAt(i)); 216 if (pView) { 217 BRect frame = pView->Frame(); 218 curWidth = frame.Width(); 219 curHeight = frame.Height(); 220 if (curWidth > maxWidth) { 221 maxWidth = curWidth; 222 } 223 if (curHeight > maxHeight) { 224 maxHeight = curHeight; 225 } 226 } 227 } 228 229 // now resize everything in the list based on selected dimension 230 for (i=0; i<len; i++) { 231 BView* pView = reinterpret_cast<BView*>(viewList.ItemAt(i)); 232 if (pView) { 233 float newWidth, newHeight; 234 BRect frame = pView->Frame(); 235 newWidth = (resizeDim & RECT_WIDTH) 236 ? maxWidth : frame.Width(); 237 newHeight = (resizeDim & RECT_HEIGHT) 238 ? maxHeight : frame.Height(); 239 pView->ResizeTo(newWidth, newHeight); 240 } 241 } 242 } 243 244 void ViewLayoutFactory::ResizeAroundChildren(BView& view, BPoint margin) 245 { 246 float fMax_x = 0.0f, fMax_y = 0.0f; 247 int32 numChild = view.CountChildren(); 248 for (int32 i = 0; i < numChild; i++) 249 { 250 BView* childView = view.ChildAt(i); 251 if (childView) { 252 BRect r = childView->Frame(); 253 fMax_x = std::max(fMax_x, r.right); 254 fMax_y = std::max(fMax_y, r.bottom); 255 } 256 } 257 258 fMax_x += margin.x; 259 fMax_y += margin.y; 260 view.ResizeTo(fMax_x, fMax_y); 261 } 262