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