1 /* 2 * Copyright 2010, Haiku, Inc. 3 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>. 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <GroupLayout.h> 9 10 #include <ControlLook.h> 11 #include <LayoutItem.h> 12 #include <Message.h> 13 14 #include <new> 15 16 17 using std::nothrow; 18 19 20 namespace { 21 const char* const kItemWeightField = "BGroupLayout:item:weight"; 22 const char* const kVerticalField = "BGroupLayout:vertical"; 23 } 24 25 26 struct BGroupLayout::ItemLayoutData { 27 float weight; 28 29 ItemLayoutData() 30 : weight(1) 31 { 32 } 33 }; 34 35 36 BGroupLayout::BGroupLayout(enum orientation orientation, float spacing) 37 : 38 BTwoDimensionalLayout(), 39 fOrientation(orientation) 40 { 41 SetSpacing(spacing); 42 } 43 44 45 BGroupLayout::BGroupLayout(BMessage* from) 46 : 47 BTwoDimensionalLayout(from) 48 { 49 bool isVertical; 50 if (from->FindBool(kVerticalField, &isVertical) != B_OK) 51 isVertical = false; 52 fOrientation = isVertical ? B_VERTICAL : B_HORIZONTAL; 53 } 54 55 56 BGroupLayout::~BGroupLayout() 57 { 58 } 59 60 61 float 62 BGroupLayout::Spacing() const 63 { 64 return fHSpacing; 65 } 66 67 68 void 69 BGroupLayout::SetSpacing(float spacing) 70 { 71 spacing = BControlLook::ComposeSpacing(spacing); 72 if (spacing != fHSpacing) { 73 fHSpacing = spacing; 74 fVSpacing = spacing; 75 InvalidateLayout(); 76 } 77 } 78 79 80 orientation 81 BGroupLayout::Orientation() const 82 { 83 return fOrientation; 84 } 85 86 87 void 88 BGroupLayout::SetOrientation(enum orientation orientation) 89 { 90 if (orientation != fOrientation) { 91 fOrientation = orientation; 92 93 InvalidateLayout(); 94 } 95 } 96 97 98 float 99 BGroupLayout::ItemWeight(int32 index) const 100 { 101 if (index < 0 || index >= CountItems()) 102 return 0; 103 104 ItemLayoutData* data = _LayoutDataForItem(ItemAt(index)); 105 return (data ? data->weight : 0); 106 } 107 108 109 void 110 BGroupLayout::SetItemWeight(int32 index, float weight) 111 { 112 if (index < 0 || index >= CountItems()) 113 return; 114 115 if (ItemLayoutData* data = _LayoutDataForItem(ItemAt(index))) 116 data->weight = weight; 117 118 InvalidateLayout(); 119 } 120 121 122 BLayoutItem* 123 BGroupLayout::AddView(BView* child) 124 { 125 return BTwoDimensionalLayout::AddView(child); 126 } 127 128 129 BLayoutItem* 130 BGroupLayout::AddView(int32 index, BView* child) 131 { 132 return BTwoDimensionalLayout::AddView(index, child); 133 } 134 135 136 BLayoutItem* 137 BGroupLayout::AddView(BView* child, float weight) 138 { 139 return AddView(-1, child, weight); 140 } 141 142 143 BLayoutItem* 144 BGroupLayout::AddView(int32 index, BView* child, float weight) 145 { 146 BLayoutItem* item = AddView(index, child); 147 if (ItemLayoutData* data = _LayoutDataForItem(item)) 148 data->weight = weight; 149 150 return item; 151 } 152 153 154 bool 155 BGroupLayout::AddItem(BLayoutItem* item) 156 { 157 return BTwoDimensionalLayout::AddItem(item); 158 } 159 160 161 bool 162 BGroupLayout::AddItem(int32 index, BLayoutItem* item) 163 { 164 return BTwoDimensionalLayout::AddItem(index, item); 165 } 166 167 168 bool 169 BGroupLayout::AddItem(BLayoutItem* item, float weight) 170 { 171 return AddItem(-1, item, weight); 172 } 173 174 175 bool 176 BGroupLayout::AddItem(int32 index, BLayoutItem* item, float weight) 177 { 178 bool success = AddItem(index, item); 179 if (success) { 180 if (ItemLayoutData* data = _LayoutDataForItem(item)) 181 data->weight = weight; 182 } 183 184 return success; 185 } 186 187 188 status_t 189 BGroupLayout::Archive(BMessage* into, bool deep) const 190 { 191 BArchiver archiver(into); 192 status_t err = BTwoDimensionalLayout::Archive(into, deep); 193 194 if (err == B_OK) 195 err = into->AddBool(kVerticalField, fOrientation == B_VERTICAL); 196 197 return archiver.Finish(err); 198 } 199 200 201 status_t 202 BGroupLayout::AllArchived(BMessage* into) const 203 { 204 return BTwoDimensionalLayout::AllArchived(into); 205 } 206 207 208 status_t 209 BGroupLayout::AllUnarchived(const BMessage* from) 210 { 211 return BTwoDimensionalLayout::AllUnarchived(from); 212 } 213 214 215 BArchivable* 216 BGroupLayout::Instantiate(BMessage* from) 217 { 218 if (validate_instantiation(from, "BGroupLayout")) 219 return new(nothrow) BGroupLayout(from); 220 return NULL; 221 } 222 223 224 status_t 225 BGroupLayout::ItemArchived(BMessage* into, 226 BLayoutItem* item, int32 index) const 227 { 228 return into->AddFloat(kItemWeightField, _LayoutDataForItem(item)->weight); 229 } 230 231 232 status_t 233 BGroupLayout::ItemUnarchived(const BMessage* from, 234 BLayoutItem* item, int32 index) 235 { 236 float weight; 237 status_t err = from->FindFloat(kItemWeightField, index, &weight); 238 239 if (err == B_OK) 240 _LayoutDataForItem(item)->weight = weight; 241 242 return err; 243 } 244 245 246 bool 247 BGroupLayout::ItemAdded(BLayoutItem* item, int32 atIndex) 248 { 249 item->SetLayoutData(new(nothrow) ItemLayoutData); 250 return item->LayoutData() != NULL; 251 } 252 253 254 void 255 BGroupLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex) 256 { 257 if (ItemLayoutData* data = _LayoutDataForItem(item)) { 258 item->SetLayoutData(NULL); 259 delete data; 260 } 261 } 262 263 264 void 265 BGroupLayout::PrepareItems(enum orientation orientation) 266 { 267 // filter the visible items 268 fVisibleItems.MakeEmpty(); 269 int32 itemCount = CountItems(); 270 for (int i = 0; i < itemCount; i++) { 271 BLayoutItem* item = ItemAt(i); 272 if (item->IsVisible()) 273 fVisibleItems.AddItem(item); 274 } 275 } 276 277 278 int32 279 BGroupLayout::InternalCountColumns() 280 { 281 return (fOrientation == B_HORIZONTAL ? fVisibleItems.CountItems() : 1); 282 } 283 284 285 int32 286 BGroupLayout::InternalCountRows() 287 { 288 return (fOrientation == B_VERTICAL ? fVisibleItems.CountItems() : 1); 289 } 290 291 292 void 293 BGroupLayout::GetColumnRowConstraints(enum orientation orientation, int32 index, 294 ColumnRowConstraints* constraints) 295 { 296 if (index >= 0 && index < fVisibleItems.CountItems()) { 297 BLayoutItem* item = (BLayoutItem*)fVisibleItems.ItemAt(index); 298 constraints->min = -1; 299 constraints->max = B_SIZE_UNLIMITED; 300 if (ItemLayoutData* data = _LayoutDataForItem(item)) 301 constraints->weight = data->weight; 302 else 303 constraints->weight = 1; 304 } 305 } 306 307 308 void 309 BGroupLayout::GetItemDimensions(BLayoutItem* item, Dimensions* dimensions) 310 { 311 int32 index = fVisibleItems.IndexOf(item); 312 if (index < 0) 313 return; 314 315 if (fOrientation == B_HORIZONTAL) { 316 dimensions->x = index; 317 dimensions->y = 0; 318 dimensions->width = 1; 319 dimensions->height = 1; 320 } else { 321 dimensions->x = 0; 322 dimensions->y = index; 323 dimensions->width = 1; 324 dimensions->height = 1; 325 } 326 } 327 328 329 BGroupLayout::ItemLayoutData* 330 BGroupLayout::_LayoutDataForItem(BLayoutItem* item) const 331 { 332 if (!item) 333 return NULL; 334 return (ItemLayoutData*)item->LayoutData(); 335 } 336 337 338 status_t 339 BGroupLayout::Perform(perform_code code, void* _data) 340 { 341 return BTwoDimensionalLayout::Perform(code, _data); 342 } 343 344 345 void BGroupLayout::_ReservedGroupLayout1() {} 346 void BGroupLayout::_ReservedGroupLayout2() {} 347 void BGroupLayout::_ReservedGroupLayout3() {} 348 void BGroupLayout::_ReservedGroupLayout4() {} 349 void BGroupLayout::_ReservedGroupLayout5() {} 350 void BGroupLayout::_ReservedGroupLayout6() {} 351 void BGroupLayout::_ReservedGroupLayout7() {} 352 void BGroupLayout::_ReservedGroupLayout8() {} 353 void BGroupLayout::_ReservedGroupLayout9() {} 354 void BGroupLayout::_ReservedGroupLayout10() {} 355 356