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 18 using std::nothrow; 19 20 21 namespace { 22 const char* const kItemWeightField = "BGroupLayout:item:weight"; 23 const char* const kVerticalField = "BGroupLayout:vertical"; 24 } 25 26 27 struct BGroupLayout::ItemLayoutData { 28 float weight; 29 30 ItemLayoutData() 31 : weight(1) 32 { 33 } 34 }; 35 36 37 BGroupLayout::BGroupLayout(orientation orientation, float spacing) 38 : 39 BTwoDimensionalLayout(), 40 fOrientation(orientation) 41 { 42 SetSpacing(spacing); 43 } 44 45 46 BGroupLayout::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 57 BGroupLayout::~BGroupLayout() 58 { 59 } 60 61 62 float 63 BGroupLayout::Spacing() const 64 { 65 return fHSpacing; 66 } 67 68 69 void 70 BGroupLayout::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 81 orientation 82 BGroupLayout::Orientation() const 83 { 84 return fOrientation; 85 } 86 87 88 void 89 BGroupLayout::SetOrientation(orientation orientation) 90 { 91 if (orientation != fOrientation) { 92 fOrientation = orientation; 93 94 InvalidateLayout(); 95 } 96 } 97 98 99 float 100 BGroupLayout::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 110 void 111 BGroupLayout::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 123 BLayoutItem* 124 BGroupLayout::AddView(BView* child) 125 { 126 return BTwoDimensionalLayout::AddView(child); 127 } 128 129 130 BLayoutItem* 131 BGroupLayout::AddView(int32 index, BView* child) 132 { 133 return BTwoDimensionalLayout::AddView(index, child); 134 } 135 136 137 BLayoutItem* 138 BGroupLayout::AddView(BView* child, float weight) 139 { 140 return AddView(-1, child, weight); 141 } 142 143 144 BLayoutItem* 145 BGroupLayout::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 155 bool 156 BGroupLayout::AddItem(BLayoutItem* item) 157 { 158 return BTwoDimensionalLayout::AddItem(item); 159 } 160 161 162 bool 163 BGroupLayout::AddItem(int32 index, BLayoutItem* item) 164 { 165 return BTwoDimensionalLayout::AddItem(index, item); 166 } 167 168 169 bool 170 BGroupLayout::AddItem(BLayoutItem* item, float weight) 171 { 172 return AddItem(-1, item, weight); 173 } 174 175 176 bool 177 BGroupLayout::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 189 status_t 190 BGroupLayout::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 202 status_t 203 BGroupLayout::AllArchived(BMessage* into) const 204 { 205 return BTwoDimensionalLayout::AllArchived(into); 206 } 207 208 209 status_t 210 BGroupLayout::AllUnarchived(const BMessage* from) 211 { 212 return BTwoDimensionalLayout::AllUnarchived(from); 213 } 214 215 216 BArchivable* 217 BGroupLayout::Instantiate(BMessage* from) 218 { 219 if (validate_instantiation(from, "BGroupLayout")) 220 return new(nothrow) BGroupLayout(from); 221 return NULL; 222 } 223 224 225 status_t 226 BGroupLayout::ItemArchived(BMessage* into, 227 BLayoutItem* item, int32 index) const 228 { 229 return into->AddFloat(kItemWeightField, _LayoutDataForItem(item)->weight); 230 } 231 232 233 status_t 234 BGroupLayout::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 247 bool 248 BGroupLayout::ItemAdded(BLayoutItem* item, int32 atIndex) 249 { 250 item->SetLayoutData(new(nothrow) ItemLayoutData); 251 return item->LayoutData() != NULL; 252 } 253 254 255 void 256 BGroupLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex) 257 { 258 if (ItemLayoutData* data = _LayoutDataForItem(item)) { 259 item->SetLayoutData(NULL); 260 delete data; 261 } 262 } 263 264 265 void 266 BGroupLayout::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 279 int32 280 BGroupLayout::InternalCountColumns() 281 { 282 return (fOrientation == B_HORIZONTAL ? fVisibleItems.CountItems() : 1); 283 } 284 285 286 int32 287 BGroupLayout::InternalCountRows() 288 { 289 return (fOrientation == B_VERTICAL ? fVisibleItems.CountItems() : 1); 290 } 291 292 293 void 294 BGroupLayout::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 309 void 310 BGroupLayout::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 330 BGroupLayout::ItemLayoutData* 331 BGroupLayout::_LayoutDataForItem(BLayoutItem* item) const 332 { 333 return item == NULL ? NULL : (ItemLayoutData*)item->LayoutData(); 334 } 335 336 337 status_t 338 BGroupLayout::Perform(perform_code code, void* _data) 339 { 340 return BTwoDimensionalLayout::Perform(code, _data); 341 } 342 343 344 void BGroupLayout::_ReservedGroupLayout1() {} 345 void BGroupLayout::_ReservedGroupLayout2() {} 346 void BGroupLayout::_ReservedGroupLayout3() {} 347 void BGroupLayout::_ReservedGroupLayout4() {} 348 void BGroupLayout::_ReservedGroupLayout5() {} 349 void BGroupLayout::_ReservedGroupLayout6() {} 350 void BGroupLayout::_ReservedGroupLayout7() {} 351 void BGroupLayout::_ReservedGroupLayout8() {} 352 void BGroupLayout::_ReservedGroupLayout9() {} 353 void BGroupLayout::_ReservedGroupLayout10() {} 354