xref: /haiku/src/kits/interface/GridLayout.cpp (revision 50e2057db04e8ed0d98982462fe0fb56195cdc6a)
1 /*
2  * Copyright 2010-2011 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 <GridLayout.h>
10 
11 #include <algorithm>
12 #include <new>
13 #include <string.h>
14 
15 #include <ControlLook.h>
16 #include <LayoutItem.h>
17 #include <List.h>
18 #include <Message.h>
19 
20 #include "ViewLayoutItem.h"
21 
22 
23 using std::nothrow;
24 using std::swap;
25 
26 
27 enum {
28 	MAX_COLUMN_ROW_COUNT	= 1024,
29 };
30 
31 
32 namespace {
33 	// a placeholder we put in our grid array to make a cell occupied
34 	BLayoutItem* const OCCUPIED_GRID_CELL = (BLayoutItem*)0x1;
35 
36 	const char* const kRowSizesField = "BGridLayout:rowsizes";
37 		// kRowSizesField = {min, max}
38 	const char* const kRowWeightField = "BGridLayout:rowweight";
39 	const char* const kColumnSizesField = "BGridLayout:columnsizes";
40 		// kColumnSizesField = {min, max}
41 	const char* const kColumnWeightField = "BGridLayout:columnweight";
42 	const char* const kItemDimensionsField = "BGridLayout:item:dimensions";
43 		// kItemDimensionsField = {x, y, width, height}
44 }
45 
46 
47 struct BGridLayout::ItemLayoutData {
48 	Dimensions	dimensions;
49 
ItemLayoutDataBGridLayout::ItemLayoutData50 	ItemLayoutData()
51 	{
52 		dimensions.x = 0;
53 		dimensions.y = 0;
54 		dimensions.width = 1;
55 		dimensions.height = 1;
56 	}
57 };
58 
59 
60 class BGridLayout::RowInfoArray {
61 public:
RowInfoArray()62 	RowInfoArray()
63 	{
64 	}
65 
~RowInfoArray()66 	~RowInfoArray()
67 	{
68 		for (int32 i = 0; Info* info = (Info*)fInfos.ItemAt(i); i++)
69 			delete info;
70 	}
71 
Count() const72 	int32 Count() const
73 	{
74 		return fInfos.CountItems();
75 	}
76 
Weight(int32 index) const77 	float Weight(int32 index) const
78 	{
79 		if (Info* info = _InfoAt(index))
80 			return info->weight;
81 		return 1;
82 	}
83 
SetWeight(int32 index,float weight)84 	void SetWeight(int32 index, float weight)
85 	{
86 		if (Info* info = _InfoAt(index, true))
87 			info->weight = weight;
88 	}
89 
MinSize(int32 index) const90 	float MinSize(int32 index) const
91 	{
92 		if (Info* info = _InfoAt(index))
93 			return info->minSize;
94 		return B_SIZE_UNSET;
95 	}
96 
SetMinSize(int32 index,float size)97 	void SetMinSize(int32 index, float size)
98 	{
99 		if (Info* info = _InfoAt(index, true))
100 			info->minSize = size;
101 	}
102 
MaxSize(int32 index) const103 	float MaxSize(int32 index) const
104 	{
105 		if (Info* info = _InfoAt(index))
106 			return info->maxSize;
107 		return B_SIZE_UNSET;
108 	}
109 
SetMaxSize(int32 index,float size)110 	void SetMaxSize(int32 index, float size)
111 	{
112 		if (Info* info = _InfoAt(index, true))
113 			info->maxSize = size;
114 	}
115 
116 private:
117 	struct Info {
118 		float	weight;
119 		float	minSize;
120 		float	maxSize;
121 	};
122 
_InfoAt(int32 index) const123 	Info* _InfoAt(int32 index) const
124 	{
125 		return (Info*)fInfos.ItemAt(index);
126 	}
127 
_InfoAt(int32 index,bool resize)128 	Info* _InfoAt(int32 index, bool resize)
129 	{
130 		if (index < 0 || index >= MAX_COLUMN_ROW_COUNT)
131 			return NULL;
132 
133 		// resize, if necessary and desired
134 		int32 count = Count();
135 		if (index >= count) {
136 			if (!resize)
137 				return NULL;
138 
139 			for (int32 i = count; i <= index; i++) {
140 				Info* info = new Info;
141 				info->weight = 1;
142 				info->minSize = B_SIZE_UNSET;
143 				info->maxSize = B_SIZE_UNSET;
144 				fInfos.AddItem(info);
145 			}
146 		}
147 
148 		return _InfoAt(index);
149 	}
150 
151 	BList		fInfos;
152 };
153 
154 
BGridLayout(float horizontal,float vertical)155 BGridLayout::BGridLayout(float horizontal, float vertical)
156 	:
157 	fGrid(NULL),
158 	fColumnCount(0),
159 	fRowCount(0),
160 	fRowInfos(new RowInfoArray),
161 	fColumnInfos(new RowInfoArray),
162 	fMultiColumnItems(0),
163 	fMultiRowItems(0)
164 {
165 	SetSpacing(horizontal, vertical);
166 }
167 
168 
BGridLayout(BMessage * from)169 BGridLayout::BGridLayout(BMessage* from)
170 	:
171 	BTwoDimensionalLayout(BUnarchiver::PrepareArchive(from)),
172 	fGrid(NULL),
173 	fColumnCount(0),
174 	fRowCount(0),
175 	fRowInfos(new RowInfoArray),
176 	fColumnInfos(new RowInfoArray),
177 	fMultiColumnItems(0),
178 	fMultiRowItems(0)
179 {
180 	BUnarchiver unarchiver(from);
181 	int32 columns;
182 	from->GetInfo(kColumnWeightField, NULL, &columns);
183 
184 	int32 rows;
185 	from->GetInfo(kRowWeightField, NULL, &rows);
186 
187 	// sets fColumnCount && fRowCount on success
188 	if (!_ResizeGrid(columns, rows)) {
189 		unarchiver.Finish(B_NO_MEMORY);
190 		return;
191 	}
192 
193 	for (int32 i = 0; i < fRowCount; i++) {
194 		float getter;
195 		if (from->FindFloat(kRowWeightField, i, &getter) == B_OK)
196 			fRowInfos->SetWeight(i, getter);
197 
198 		if (from->FindFloat(kRowSizesField, i * 2, &getter) == B_OK)
199 			fRowInfos->SetMinSize(i, getter);
200 
201 		if (from->FindFloat(kRowSizesField, i * 2 + 1, &getter) == B_OK)
202 			fRowInfos->SetMaxSize(i, getter);
203 	}
204 
205 	for (int32 i = 0; i < fColumnCount; i++) {
206 		float getter;
207 		if (from->FindFloat(kColumnWeightField, i, &getter) == B_OK)
208 			fColumnInfos->SetWeight(i, getter);
209 
210 		if (from->FindFloat(kColumnSizesField, i * 2, &getter) == B_OK)
211 			fColumnInfos->SetMinSize(i, getter);
212 
213 		if (from->FindFloat(kColumnSizesField, i * 2 + 1, &getter) == B_OK)
214 			fColumnInfos->SetMaxSize(i, getter);
215 	}
216 }
217 
218 
~BGridLayout()219 BGridLayout::~BGridLayout()
220 {
221 	delete fRowInfos;
222 	delete fColumnInfos;
223 
224 	for (int32 i = 0; i < fColumnCount; i++)
225 		delete[] fGrid[i];
226 	delete[] fGrid;
227 }
228 
229 
230 int32
CountColumns() const231 BGridLayout::CountColumns() const
232 {
233 	return fColumnCount;
234 }
235 
236 
237 int32
CountRows() const238 BGridLayout::CountRows() const
239 {
240 	return fRowCount;
241 }
242 
243 
244 float
HorizontalSpacing() const245 BGridLayout::HorizontalSpacing() const
246 {
247 	return fHSpacing;
248 }
249 
250 
251 float
VerticalSpacing() const252 BGridLayout::VerticalSpacing() const
253 {
254 	return fVSpacing;
255 }
256 
257 
258 void
SetHorizontalSpacing(float spacing)259 BGridLayout::SetHorizontalSpacing(float spacing)
260 {
261 	spacing = BControlLook::ComposeSpacing(spacing);
262 	if (spacing != fHSpacing) {
263 		fHSpacing = spacing;
264 
265 		InvalidateLayout();
266 	}
267 }
268 
269 
270 void
SetVerticalSpacing(float spacing)271 BGridLayout::SetVerticalSpacing(float spacing)
272 {
273 	spacing = BControlLook::ComposeSpacing(spacing);
274 	if (spacing != fVSpacing) {
275 		fVSpacing = spacing;
276 
277 		InvalidateLayout();
278 	}
279 }
280 
281 
282 void
SetSpacing(float horizontal,float vertical)283 BGridLayout::SetSpacing(float horizontal, float vertical)
284 {
285 	horizontal = BControlLook::ComposeSpacing(horizontal);
286 	vertical = BControlLook::ComposeSpacing(vertical);
287 	if (horizontal != fHSpacing || vertical != fVSpacing) {
288 		fHSpacing = horizontal;
289 		fVSpacing = vertical;
290 
291 		InvalidateLayout();
292 	}
293 }
294 
295 
296 float
ColumnWeight(int32 column) const297 BGridLayout::ColumnWeight(int32 column) const
298 {
299 	return fColumnInfos->Weight(column);
300 }
301 
302 
303 void
SetColumnWeight(int32 column,float weight)304 BGridLayout::SetColumnWeight(int32 column, float weight)
305 {
306 	fColumnInfos->SetWeight(column, weight);
307 }
308 
309 
310 float
MinColumnWidth(int32 column) const311 BGridLayout::MinColumnWidth(int32 column) const
312 {
313 	return fColumnInfos->MinSize(column);
314 }
315 
316 
317 void
SetMinColumnWidth(int32 column,float width)318 BGridLayout::SetMinColumnWidth(int32 column, float width)
319 {
320 	fColumnInfos->SetMinSize(column, width);
321 }
322 
323 
324 float
MaxColumnWidth(int32 column) const325 BGridLayout::MaxColumnWidth(int32 column) const
326 {
327 	return fColumnInfos->MaxSize(column);
328 }
329 
330 
331 void
SetMaxColumnWidth(int32 column,float width)332 BGridLayout::SetMaxColumnWidth(int32 column, float width)
333 {
334 	fColumnInfos->SetMaxSize(column, width);
335 }
336 
337 
338 float
RowWeight(int32 row) const339 BGridLayout::RowWeight(int32 row) const
340 {
341 	return fRowInfos->Weight(row);
342 }
343 
344 
345 void
SetRowWeight(int32 row,float weight)346 BGridLayout::SetRowWeight(int32 row, float weight)
347 {
348 	fRowInfos->SetWeight(row, weight);
349 }
350 
351 
352 float
MinRowHeight(int row) const353 BGridLayout::MinRowHeight(int row) const
354 {
355 	return fRowInfos->MinSize(row);
356 }
357 
358 
359 void
SetMinRowHeight(int32 row,float height)360 BGridLayout::SetMinRowHeight(int32 row, float height)
361 {
362 	fRowInfos->SetMinSize(row, height);
363 }
364 
365 
366 float
MaxRowHeight(int32 row) const367 BGridLayout::MaxRowHeight(int32 row) const
368 {
369 	return fRowInfos->MaxSize(row);
370 }
371 
372 
373 void
SetMaxRowHeight(int32 row,float height)374 BGridLayout::SetMaxRowHeight(int32 row, float height)
375 {
376 	fRowInfos->SetMaxSize(row, height);
377 }
378 
379 
380 BLayoutItem*
ItemAt(int32 column,int32 row) const381 BGridLayout::ItemAt(int32 column, int32 row) const
382 {
383 	if (column < 0 || column >= CountColumns()
384 		|| row < 0 || row >= CountRows())
385 		return NULL;
386 
387 	return fGrid[column][row];
388 }
389 
390 
391 BLayoutItem*
AddView(BView * child)392 BGridLayout::AddView(BView* child)
393 {
394 	return BTwoDimensionalLayout::AddView(child);
395 }
396 
397 
398 BLayoutItem*
AddView(int32 index,BView * child)399 BGridLayout::AddView(int32 index, BView* child)
400 {
401 	return BTwoDimensionalLayout::AddView(index, child);
402 }
403 
404 
405 BLayoutItem*
AddView(BView * child,int32 column,int32 row,int32 columnCount,int32 rowCount)406 BGridLayout::AddView(BView* child, int32 column, int32 row, int32 columnCount,
407 	int32 rowCount)
408 {
409 	if (!child)
410 		return NULL;
411 
412 	BLayoutItem* item = new BViewLayoutItem(child);
413 	if (!AddItem(item, column, row, columnCount, rowCount)) {
414 		delete item;
415 		return NULL;
416 	}
417 
418 	return item;
419 }
420 
421 
422 bool
AddItem(BLayoutItem * item)423 BGridLayout::AddItem(BLayoutItem* item)
424 {
425 	// find a free spot
426 	for (int32 row = 0; row < fRowCount; row++) {
427 		for (int32 column = 0; column < fColumnCount; column++) {
428 			if (_IsGridCellEmpty(column, row))
429 				return AddItem(item, column, row, 1, 1);
430 		}
431 	}
432 
433 	// no free spot, start a new column
434 	return AddItem(item, fColumnCount, 0, 1, 1);
435 }
436 
437 
438 bool
AddItem(int32 index,BLayoutItem * item)439 BGridLayout::AddItem(int32 index, BLayoutItem* item)
440 {
441 	return AddItem(item);
442 }
443 
444 
445 bool
AddItem(BLayoutItem * item,int32 column,int32 row,int32 columnCount,int32 rowCount)446 BGridLayout::AddItem(BLayoutItem* item, int32 column, int32 row,
447 	int32 columnCount, int32 rowCount)
448 {
449 	if (!_AreGridCellsEmpty(column, row, columnCount, rowCount))
450 		return false;
451 
452 	bool success = BTwoDimensionalLayout::AddItem(-1, item);
453 	if (!success)
454 		return false;
455 
456 	// set item dimensions
457 	if (ItemLayoutData* data = _LayoutDataForItem(item)) {
458 		data->dimensions.x = column;
459 		data->dimensions.y = row;
460 		data->dimensions.width = columnCount;
461 		data->dimensions.height = rowCount;
462 	}
463 
464 	if (!_InsertItemIntoGrid(item)) {
465 		RemoveItem(item);
466 		return false;
467 	}
468 
469 	if (columnCount > 1)
470 		fMultiColumnItems++;
471 	if (rowCount > 1)
472 		fMultiRowItems++;
473 
474 	return success;
475 }
476 
477 
478 status_t
Archive(BMessage * into,bool deep) const479 BGridLayout::Archive(BMessage* into, bool deep) const
480 {
481 	BArchiver archiver(into);
482 	status_t result = BTwoDimensionalLayout::Archive(into, deep);
483 
484 	for (int32 i = 0; i < fRowCount && result == B_OK; i++) {
485 		result = into->AddFloat(kRowWeightField, fRowInfos->Weight(i));
486 		if (result == B_OK)
487 			result = into->AddFloat(kRowSizesField, fRowInfos->MinSize(i));
488 		if (result == B_OK)
489 			result = into->AddFloat(kRowSizesField, fRowInfos->MaxSize(i));
490 	}
491 
492 	for (int32 i = 0; i < fColumnCount && result == B_OK; i++) {
493 		result = into->AddFloat(kColumnWeightField, fColumnInfos->Weight(i));
494 		if (result == B_OK)
495 			result = into->AddFloat(kColumnSizesField, fColumnInfos->MinSize(i));
496 		if (result == B_OK)
497 			result = into->AddFloat(kColumnSizesField, fColumnInfos->MaxSize(i));
498 	}
499 
500 	return archiver.Finish(result);
501 }
502 
503 
504 status_t
AllArchived(BMessage * into) const505 BGridLayout::AllArchived(BMessage* into) const
506 {
507 	return BTwoDimensionalLayout::AllArchived(into);
508 }
509 
510 
511 status_t
AllUnarchived(const BMessage * from)512 BGridLayout::AllUnarchived(const BMessage* from)
513 {
514 	return BTwoDimensionalLayout::AllUnarchived(from);
515 }
516 
517 
518 BArchivable*
Instantiate(BMessage * from)519 BGridLayout::Instantiate(BMessage* from)
520 {
521 	if (validate_instantiation(from, "BGridLayout"))
522 		return new BGridLayout(from);
523 	return NULL;
524 }
525 
526 
527 status_t
ItemArchived(BMessage * into,BLayoutItem * item,int32 index) const528 BGridLayout::ItemArchived(BMessage* into, BLayoutItem* item, int32 index) const
529 {
530 	ItemLayoutData* data =	_LayoutDataForItem(item);
531 
532 	status_t result = into->AddInt32(kItemDimensionsField, data->dimensions.x);
533 	if (result == B_OK)
534 		result = into->AddInt32(kItemDimensionsField, data->dimensions.y);
535 
536 	if (result == B_OK)
537 		result = into->AddInt32(kItemDimensionsField, data->dimensions.width);
538 
539 	if (result == B_OK)
540 		result = into->AddInt32(kItemDimensionsField, data->dimensions.height);
541 
542 	return result;
543 }
544 
545 
546 status_t
ItemUnarchived(const BMessage * from,BLayoutItem * item,int32 index)547 BGridLayout::ItemUnarchived(const BMessage* from,
548 	BLayoutItem* item, int32 index)
549 {
550 	ItemLayoutData* data = _LayoutDataForItem(item);
551 	Dimensions& dimensions = data->dimensions;
552 
553 	index *= 4;
554 		// each item stores 4 int32s into kItemDimensionsField
555 	status_t result = from->FindInt32(kItemDimensionsField, index, &dimensions.x);
556 	if (result == B_OK)
557 		result = from->FindInt32(kItemDimensionsField, ++index, &dimensions.y);
558 
559 	if (result == B_OK)
560 		result = from->FindInt32(kItemDimensionsField, ++index, &dimensions.width);
561 
562 	if (result == B_OK) {
563 		result = from->FindInt32(kItemDimensionsField,
564 			++index, &dimensions.height);
565 	}
566 
567 	if (result != B_OK)
568 		return result;
569 
570 	if (!_AreGridCellsEmpty(dimensions.x, dimensions.y,
571 		dimensions.width, dimensions.height))
572 		return B_BAD_DATA;
573 
574 	if (!_InsertItemIntoGrid(item))
575 		return B_NO_MEMORY;
576 
577 	if (dimensions.width > 1)
578 		fMultiColumnItems++;
579 
580 	if (dimensions.height > 1)
581 		fMultiRowItems++;
582 
583 	return result;
584 }
585 
586 
587 bool
ItemAdded(BLayoutItem * item,int32 atIndex)588 BGridLayout::ItemAdded(BLayoutItem* item, int32 atIndex)
589 {
590 	item->SetLayoutData(new(nothrow) ItemLayoutData);
591 	return item->LayoutData() != NULL;
592 }
593 
594 
595 void
ItemRemoved(BLayoutItem * item,int32 fromIndex)596 BGridLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
597 {
598 	ItemLayoutData* data = _LayoutDataForItem(item);
599 	Dimensions itemDimensions = data->dimensions;
600 	item->SetLayoutData(NULL);
601 	delete data;
602 
603 	if (itemDimensions.width > 1)
604 		fMultiColumnItems--;
605 
606 	if (itemDimensions.height > 1)
607 		fMultiRowItems--;
608 
609 	// remove the item from the grid
610 	for (int x = 0; x < itemDimensions.width; x++) {
611 		for (int y = 0; y < itemDimensions.height; y++)
612 			fGrid[itemDimensions.x + x][itemDimensions.y + y] = NULL;
613 	}
614 
615 	// check whether we can shrink the grid
616 	if (itemDimensions.x + itemDimensions.width == fColumnCount
617 		|| itemDimensions.y + itemDimensions.height == fRowCount) {
618 		int32 columnCount = fColumnCount;
619 		int32 rowCount = fRowCount;
620 
621 		// check for empty columns
622 		bool empty = true;
623 		for (; columnCount > 0; columnCount--) {
624 			for (int32 row = 0; empty && row < rowCount; row++)
625 				empty &= (fGrid[columnCount - 1][row] == NULL);
626 
627 			if (!empty)
628 				break;
629 		}
630 
631 		// check for empty rows
632 		empty = true;
633 		for (; rowCount > 0; rowCount--) {
634 			for (int32 column = 0; empty && column < columnCount; column++)
635 				empty &= (fGrid[column][rowCount - 1] == NULL);
636 
637 			if (!empty)
638 				break;
639 		}
640 
641 		// resize the grid
642 		if (columnCount != fColumnCount || rowCount != fRowCount)
643 			_ResizeGrid(columnCount, rowCount);
644 	}
645 }
646 
647 
648 bool
HasMultiColumnItems()649 BGridLayout::HasMultiColumnItems()
650 {
651 	return fMultiColumnItems > 0;
652 }
653 
654 
655 bool
HasMultiRowItems()656 BGridLayout::HasMultiRowItems()
657 {
658 	return fMultiRowItems > 0;
659 }
660 
661 
662 int32
InternalCountColumns()663 BGridLayout::InternalCountColumns()
664 {
665 	return fColumnCount;
666 }
667 
668 
669 int32
InternalCountRows()670 BGridLayout::InternalCountRows()
671 {
672 	return fRowCount;
673 }
674 
675 
676 void
GetColumnRowConstraints(orientation orientation,int32 index,ColumnRowConstraints * constraints)677 BGridLayout::GetColumnRowConstraints(orientation orientation, int32 index,
678 	ColumnRowConstraints* constraints)
679 {
680 	if (orientation == B_HORIZONTAL) {
681 		constraints->min = MinColumnWidth(index);
682 		constraints->max = MaxColumnWidth(index);
683 		constraints->weight = ColumnWeight(index);
684 	} else {
685 		constraints->min = MinRowHeight(index);
686 		constraints->max = MaxRowHeight(index);
687 		constraints->weight = RowWeight(index);
688 	}
689 }
690 
691 
692 void
GetItemDimensions(BLayoutItem * item,Dimensions * dimensions)693 BGridLayout::GetItemDimensions(BLayoutItem* item, Dimensions* dimensions)
694 {
695 	if (ItemLayoutData* data = _LayoutDataForItem(item))
696 		*dimensions = data->dimensions;
697 }
698 
699 
700 bool
_IsGridCellEmpty(int32 column,int32 row)701 BGridLayout::_IsGridCellEmpty(int32 column, int32 row)
702 {
703 	if (column < 0 || row < 0)
704 		return false;
705 
706 	if (column >= fColumnCount || row >= fRowCount)
707 		return true;
708 
709 	return (fGrid[column][row] == NULL);
710 }
711 
712 
713 bool
_AreGridCellsEmpty(int32 column,int32 row,int32 columnCount,int32 rowCount)714 BGridLayout::_AreGridCellsEmpty(int32 column, int32 row, int32 columnCount,
715 	int32 rowCount)
716 {
717 	if (column < 0 || row < 0)
718 		return false;
719 	int32 toColumn = min_c(column + columnCount, fColumnCount);
720 	int32 toRow = min_c(row + rowCount, fRowCount);
721 
722 	for (int32 x = column; x < toColumn; x++) {
723 		for (int32 y = row; y < toRow; y++) {
724 			if (fGrid[x][y] != NULL)
725 				return false;
726 		}
727 	}
728 
729 	return true;
730 }
731 
732 
733 bool
_InsertItemIntoGrid(BLayoutItem * item)734 BGridLayout::_InsertItemIntoGrid(BLayoutItem* item)
735 {
736 	BGridLayout::ItemLayoutData* data = _LayoutDataForItem(item);
737 	int32 column = data->dimensions.x;
738 	int32 columnCount = data->dimensions.width;
739 	int32 row = data->dimensions.y;
740 	int32 rowCount = data->dimensions.height;
741 
742 	// resize the grid, if necessary
743 	int32 newColumnCount = max_c(fColumnCount, column + columnCount);
744 	int32 newRowCount = max_c(fRowCount, row + rowCount);
745 	if (newColumnCount > fColumnCount || newRowCount > fRowCount) {
746 		if (!_ResizeGrid(newColumnCount, newRowCount))
747 			return false;
748 	}
749 
750 	// enter the item in the grid
751 	for (int32 x = 0; x < columnCount; x++) {
752 		for (int32 y = 0; y < rowCount; y++) {
753 			if (x == 0 && y == 0)
754 				fGrid[column + x][row + y] = item;
755 			else
756 				fGrid[column + x][row + y] = OCCUPIED_GRID_CELL;
757 		}
758 	}
759 
760 	return true;
761 }
762 
763 
764 bool
_ResizeGrid(int32 columnCount,int32 rowCount)765 BGridLayout::_ResizeGrid(int32 columnCount, int32 rowCount)
766 {
767 	if (columnCount == fColumnCount && rowCount == fRowCount)
768 		return true;
769 
770 	int32 rowsToKeep = min_c(rowCount, fRowCount);
771 
772 	// allocate new grid
773 	BLayoutItem*** grid = new(nothrow) BLayoutItem**[columnCount];
774 	if (grid == NULL)
775 		return false;
776 
777 	memset(grid, 0, sizeof(BLayoutItem**) * columnCount);
778 
779 	bool success = true;
780 	for (int32 i = 0; i < columnCount; i++) {
781 		BLayoutItem** column = new(nothrow) BLayoutItem*[rowCount];
782 		if (!column) {
783 			success = false;
784 			break;
785 		}
786 		grid[i] = column;
787 
788 		memset(column, 0, sizeof(BLayoutItem*) * rowCount);
789 		if (i < fColumnCount && rowsToKeep > 0)
790 			memcpy(column, fGrid[i], sizeof(BLayoutItem*) * rowsToKeep);
791 	}
792 
793 	// if everything went fine, set the new grid
794 	if (success) {
795 		swap(grid, fGrid);
796 		swap(columnCount, fColumnCount);
797 		swap(rowCount, fRowCount);
798 	}
799 
800 	// delete the old, respectively on error the partially created grid
801 	for (int32 i = 0; i < columnCount; i++)
802 		delete[] grid[i];
803 
804 	delete[] grid;
805 
806 	return success;
807 }
808 
809 
810 BGridLayout::ItemLayoutData*
_LayoutDataForItem(BLayoutItem * item) const811 BGridLayout::_LayoutDataForItem(BLayoutItem* item) const
812 {
813 	if (!item)
814 		return NULL;
815 	return (ItemLayoutData*)item->LayoutData();
816 }
817 
818 
819 status_t
Perform(perform_code d,void * arg)820 BGridLayout::Perform(perform_code d, void* arg)
821 {
822 	return BTwoDimensionalLayout::Perform(d, arg);
823 }
824 
825 
_ReservedGridLayout1()826 void BGridLayout::_ReservedGridLayout1() {}
_ReservedGridLayout2()827 void BGridLayout::_ReservedGridLayout2() {}
_ReservedGridLayout3()828 void BGridLayout::_ReservedGridLayout3() {}
_ReservedGridLayout4()829 void BGridLayout::_ReservedGridLayout4() {}
_ReservedGridLayout5()830 void BGridLayout::_ReservedGridLayout5() {}
_ReservedGridLayout6()831 void BGridLayout::_ReservedGridLayout6() {}
_ReservedGridLayout7()832 void BGridLayout::_ReservedGridLayout7() {}
_ReservedGridLayout8()833 void BGridLayout::_ReservedGridLayout8() {}
_ReservedGridLayout9()834 void BGridLayout::_ReservedGridLayout9() {}
_ReservedGridLayout10()835 void BGridLayout::_ReservedGridLayout10() {}
836