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