xref: /haiku/src/kits/interface/TwoDimensionalLayout.cpp (revision 3ecb7fb4415b319b6aac606551d51efad21037df)
1 /*
2  * Copyright 2006-2010, Ingo Weinhold <ingo_weinhold@gmx.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <TwoDimensionalLayout.h>
8 
9 #include <stdio.h>
10 
11 #include <ControlLook.h>
12 #include <LayoutContext.h>
13 #include <LayoutItem.h>
14 #include <LayoutUtils.h>
15 #include <List.h>
16 #include <Message.h>
17 #include <View.h>
18 
19 #include <Referenceable.h>
20 
21 #include "CollapsingLayouter.h"
22 
23 
24 
25 
26 // Some words of explanation:
27 //
28 // This class is the base class for BLayouts that organize their items
29 // on a grid, with each item covering one or more grid cells (always a
30 // rectangular area). The derived classes only need to implement the
31 // hooks reporting the constraints for the items and additional constraints
32 // for the rows and columns. This class does all the layouting.
33 //
34 // The basic idea of the layout process is simple. The horizontal and the
35 // vertical dimensions are laid out independently and the items are set to the
36 // resulting locations and sizes. The "height for width" feature makes the
37 // height depend on the width, which makes things a bit more complicated.
38 // The horizontal dimension must be laid out first and and the results are
39 // fed into the vertical layout process.
40 //
41 // The AlignLayoutWith() feature, which allows to align layouts for different
42 // views with each other, causes the need for the three inner *Layouter classes.
43 // For each set of layouts aligned with each other with respect to one
44 // dimension that dimension must be laid out together. The class responsible
45 // is CompoundLayouter; one instance exists per such set. The derived class
46 // VerticalCompoundLayouter is a specialization for the vertical dimension
47 // which additionally takes care of the "height for width" feature. Per layout
48 // a single LocalLayouter exists, which comprises the required glue layout
49 // code and serves as a proxy for the layout, providing service methods
50 // needed by the CompoundLayouter.
51 
52 // TODO: Check for memory leaks!
53 
54 //#define DEBUG_LAYOUT
55 
56 // CompoundLayouter
57 class BTwoDimensionalLayout::CompoundLayouter : public BReferenceable {
58 public:
59 								CompoundLayouter(orientation orientation);
60 	virtual						~CompoundLayouter();
61 
62 			orientation			Orientation();
63 
64 	virtual	Layouter*			GetLayouter(bool minMax);
65 
66 			LayoutInfo*			GetLayoutInfo();
67 
68 			void				AddLocalLayouter(LocalLayouter* localLayouter);
69 			void				RemoveLocalLayouter(
70 									LocalLayouter* localLayouter);
71 
72 			status_t			AddAlignedLayoutsToArchive(BArchiver* archiver,
73 									LocalLayouter* requestedBy);
74 
75 			void				AbsorbCompoundLayouter(CompoundLayouter* other);
76 
77 	virtual	void				InvalidateLayout();
78 			bool				IsMinMaxValid();
79 			void				ValidateMinMax();
80 			void				Layout(float size, LocalLayouter* localLayouter,
81 									BLayoutContext* context);
82 
83 protected:
84 	virtual	void				DoLayout(float size,
85 									LocalLayouter* localLayouter,
86 									BLayoutContext* context);
87 
88 			Layouter*			fLayouter;
89 			LayoutInfo*			fLayoutInfo;
90 			orientation			fOrientation;
91 			BList				fLocalLayouters;
92 			BLayoutContext*		fLayoutContext;
93 			float				fLastLayoutSize;
94 
95 			void				_PrepareItems();
96 
97 			int32				_CountElements();
98 			bool				_HasMultiElementItems();
99 
100 			void				_AddConstraints(Layouter* layouter);
101 
102 			float				_Spacing();
103 };
104 
105 // VerticalCompoundLayouter
106 class BTwoDimensionalLayout::VerticalCompoundLayouter
107 	: public CompoundLayouter, private BLayoutContextListener {
108 public:
109 								VerticalCompoundLayouter();
110 
111 	virtual	Layouter*			GetLayouter(bool minMax);
112 
113 	virtual	void				InvalidateLayout();
114 
115 			void				InvalidateHeightForWidth();
116 
117 			void				InternalGetHeightForWidth(
118 									LocalLayouter* localLayouter,
119 									BLayoutContext* context,
120 									bool realLayout, float* minHeight,
121 									float* maxHeight, float* preferredHeight);
122 
123 protected:
124 	virtual	void				DoLayout(float size,
125 									LocalLayouter* localLayouter,
126 									BLayoutContext* context);
127 
128 private:
129 			Layouter*			fHeightForWidthLayouter;
130 			float				fCachedMinHeightForWidth;
131 			float				fCachedMaxHeightForWidth;
132 			float				fCachedPreferredHeightForWidth;
133 			BLayoutContext*		fHeightForWidthLayoutContext;
134 
135 			bool				_HasHeightForWidth();
136 
137 			bool				_SetHeightForWidthLayoutContext(
138 									BLayoutContext* context);
139 
140 	// BLayoutContextListener
141 	virtual	void				LayoutContextLeft(BLayoutContext* context);
142 };
143 
144 // LocalLayouter
145 class BTwoDimensionalLayout::LocalLayouter : private BLayoutContextListener {
146 public:
147 								LocalLayouter(BTwoDimensionalLayout* layout);
148 								~LocalLayouter();
149 
150 	// interface for the BTwoDimensionalLayout class
151 
152 			BSize				MinSize();
153 			BSize				MaxSize();
154 			BSize				PreferredSize();
155 
156 			void				InvalidateLayout();
157 			void				Layout(BSize size);
158 
159 			BRect				ItemFrame(Dimensions itemDimensions);
160 
161 			void				ValidateMinMax();
162 
163 			void				DoHorizontalLayout(float width);
164 
165 			void				InternalGetHeightForWidth(float width,
166 									float* minHeight, float* maxHeight,
167 									float* preferredHeight);
168 
169 			void				AlignWith(LocalLayouter* other,
170 									orientation orientation);
171 
172 	// Archiving stuff
173 			status_t			AddAlignedLayoutsToArchive(BArchiver* archiver);
174 			status_t			AddOwnerToArchive(BArchiver* archiver,
175 									CompoundLayouter* requestedBy,
176 									bool& _wasAvailable);
177 			status_t			AlignLayoutsFromArchive(BUnarchiver* unarchiver,
178 									orientation posture);
179 
180 
181 	// interface for the compound layout context
182 
183 			void				PrepareItems(
184 									CompoundLayouter* compoundLayouter);
185 			int32				CountElements(
186 									CompoundLayouter* compoundLayouter);
187 			bool				HasMultiElementItems(
188 									CompoundLayouter* compoundLayouter);
189 
190 			void				AddConstraints(
191 									CompoundLayouter* compoundLayouter,
192 									Layouter* layouter);
193 
194 			float				Spacing(CompoundLayouter* compoundLayouter);
195 
196 			bool				HasHeightForWidth();
197 
198 			bool				AddHeightForWidthConstraints(
199 									VerticalCompoundLayouter* compoundLayouter,
200 									Layouter* layouter,
201 									BLayoutContext* context);
202 			void				SetHeightForWidthConstraintsAdded(bool added);
203 
204 			void				SetCompoundLayouter(
205 									CompoundLayouter* compoundLayouter,
206 									orientation orientation);
207 
208 			void				InternalInvalidateLayout(
209 									CompoundLayouter* compoundLayouter);
210 
211 	// implementation private
212 private:
213 			BTwoDimensionalLayout* fLayout;
214 			CompoundLayouter*	fHLayouter;
215 			VerticalCompoundLayouter* fVLayouter;
216 			BList				fHeightForWidthItems;
217 
218 	// active layout context when doing last horizontal layout
219 			BLayoutContext*		fHorizontalLayoutContext;
220 			float				fHorizontalLayoutWidth;
221 			bool				fHeightForWidthConstraintsAdded;
222 
223 			void				_SetHorizontalLayoutContext(
224 									BLayoutContext* context, float width);
225 
226 	// BLayoutContextListener
227 	virtual	void				LayoutContextLeft(BLayoutContext* context);
228 };
229 
230 
231 // #pragma mark -
232 
233 // archiving constants
234 namespace {
235 	const char* const kHAlignedLayoutField = "BTwoDimensionalLayout:"
236 		"halignedlayout";
237 	const char* const kVAlignedLayoutField = "BTwoDimensionalLayout:"
238 		"valignedlayout";
239 	const char* const kInsetsField = "BTwoDimensionalLayout:insets";
240 	const char* const kSpacingField = "BTwoDimensionalLayout:spacing";
241 		// kSpacingField = {fHSpacing, fVSpacing}
242 }
243 
244 
245 BTwoDimensionalLayout::BTwoDimensionalLayout()
246 	:
247 	fLeftInset(0),
248 	fRightInset(0),
249 	fTopInset(0),
250 	fBottomInset(0),
251 	fHSpacing(0),
252 	fVSpacing(0),
253 	fLocalLayouter(new LocalLayouter(this))
254 {
255 }
256 
257 
258 BTwoDimensionalLayout::BTwoDimensionalLayout(BMessage* from)
259 	:
260 	BAbstractLayout(from),
261 	fLeftInset(0),
262 	fRightInset(0),
263 	fTopInset(0),
264 	fBottomInset(0),
265 	fHSpacing(0),
266 	fVSpacing(0),
267 	fLocalLayouter(new LocalLayouter(this))
268 {
269 	BRect insets;
270 	from->FindRect(kInsetsField, &insets);
271 	SetInsets(insets.left, insets.top, insets.right, insets.bottom);
272 
273 	from->FindFloat(kSpacingField, 0, &fHSpacing);
274 	from->FindFloat(kSpacingField, 1, &fVSpacing);
275 }
276 
277 
278 BTwoDimensionalLayout::~BTwoDimensionalLayout()
279 {
280 	delete fLocalLayouter;
281 }
282 
283 
284 void
285 BTwoDimensionalLayout::SetInsets(float left, float top, float right,
286 	float bottom)
287 {
288 	fLeftInset = BControlLook::ComposeSpacing(left);
289 	fTopInset = BControlLook::ComposeSpacing(top);
290 	fRightInset = BControlLook::ComposeSpacing(right);
291 	fBottomInset = BControlLook::ComposeSpacing(bottom);
292 
293 	InvalidateLayout();
294 }
295 
296 
297 void
298 BTwoDimensionalLayout::SetInsets(float horizontal, float vertical)
299 {
300 	fLeftInset = BControlLook::ComposeSpacing(horizontal);
301 	fRightInset = fLeftInset;
302 
303 	fTopInset = BControlLook::ComposeSpacing(vertical);
304 	fBottomInset = fTopInset;
305 
306 	InvalidateLayout();
307 }
308 
309 
310 void
311 BTwoDimensionalLayout::SetInsets(float insets)
312 {
313 	fLeftInset = BControlLook::ComposeSpacing(insets);
314 	fRightInset = fLeftInset;
315 	fTopInset = fLeftInset;
316 	fBottomInset = fLeftInset;
317 
318 	InvalidateLayout();
319 }
320 
321 
322 void
323 BTwoDimensionalLayout::GetInsets(float* left, float* top, float* right,
324 	float* bottom) const
325 {
326 	if (left)
327 		*left = fLeftInset;
328 	if (top)
329 		*top = fTopInset;
330 	if (right)
331 		*right = fRightInset;
332 	if (bottom)
333 		*bottom = fBottomInset;
334 }
335 
336 
337 void
338 BTwoDimensionalLayout::AlignLayoutWith(BTwoDimensionalLayout* other,
339 	orientation orientation)
340 {
341 	if (!other || other == this)
342 		return;
343 
344 	fLocalLayouter->AlignWith(other->fLocalLayouter, orientation);
345 
346 	InvalidateLayout();
347 }
348 
349 
350 BSize
351 BTwoDimensionalLayout::BaseMinSize()
352 {
353 	_ValidateMinMax();
354 	return AddInsets(fLocalLayouter->MinSize());
355 }
356 
357 
358 BSize
359 BTwoDimensionalLayout::BaseMaxSize()
360 {
361 	_ValidateMinMax();
362 	return AddInsets(fLocalLayouter->MaxSize());
363 }
364 
365 
366 BSize
367 BTwoDimensionalLayout::BasePreferredSize()
368 {
369 	_ValidateMinMax();
370 	return AddInsets(fLocalLayouter->PreferredSize());
371 }
372 
373 
374 BAlignment
375 BTwoDimensionalLayout::BaseAlignment()
376 {
377 	return BAbstractLayout::BaseAlignment();
378 }
379 
380 
381 bool
382 BTwoDimensionalLayout::HasHeightForWidth()
383 {
384 	_ValidateMinMax();
385 	return fLocalLayouter->HasHeightForWidth();
386 }
387 
388 
389 void
390 BTwoDimensionalLayout::GetHeightForWidth(float width, float* min, float* max,
391 	float* preferred)
392 {
393 	if (!HasHeightForWidth())
394 		return;
395 
396 	float outerSpacing = fLeftInset + fRightInset - 1;
397 	fLocalLayouter->InternalGetHeightForWidth(BLayoutUtils::SubtractDistances(
398 		width, outerSpacing), min, max, preferred);
399 	AddInsets(min, max, preferred);
400 }
401 
402 
403 void
404 BTwoDimensionalLayout::SetFrame(BRect frame)
405 {
406 	BAbstractLayout::SetFrame(frame);
407 }
408 
409 
410 status_t
411 BTwoDimensionalLayout::Archive(BMessage* into, bool deep) const
412 {
413 	BArchiver archiver(into);
414 	status_t err = BAbstractLayout::Archive(into, deep);
415 
416 	if (err == B_OK) {
417 		BRect insets(fLeftInset, fTopInset, fRightInset, fBottomInset);
418 		err = into->AddRect(kInsetsField, insets);
419 	}
420 
421 	if (err == B_OK)
422 		err = into->AddFloat(kSpacingField, fHSpacing);
423 
424 	if (err == B_OK)
425 		err = into->AddFloat(kSpacingField, fVSpacing);
426 
427 	return archiver.Finish(err);
428 }
429 
430 
431 status_t
432 BTwoDimensionalLayout::AllArchived(BMessage* into) const
433 {
434 	BArchiver archiver(into);
435 
436 	status_t err = BLayout::AllArchived(into);
437 	if (err == B_OK)
438 		err = fLocalLayouter->AddAlignedLayoutsToArchive(&archiver);
439 	return err;
440 }
441 
442 
443 status_t
444 BTwoDimensionalLayout::AllUnarchived(const BMessage* from)
445 {
446 	status_t err = BLayout::AllUnarchived(from);
447 	if (err != B_OK)
448 		return err;
449 
450 	BUnarchiver unarchiver(from);
451 	err = fLocalLayouter->AlignLayoutsFromArchive(&unarchiver, B_HORIZONTAL);
452 	if (err == B_OK)
453 		err = fLocalLayouter->AlignLayoutsFromArchive(&unarchiver, B_VERTICAL);
454 
455 	return err;
456 }
457 
458 
459 status_t
460 BTwoDimensionalLayout::ItemArchived(BMessage* into, BLayoutItem* item,
461 	int32 index) const
462 {
463 	return BAbstractLayout::ItemArchived(into, item, index);
464 }
465 
466 
467 status_t
468 BTwoDimensionalLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item,
469 	int32 index)
470 {
471 	return BAbstractLayout::ItemUnarchived(from, item, index);
472 }
473 
474 
475 
476 
477 void
478 BTwoDimensionalLayout::LayoutInvalidated(bool children)
479 {
480 	fLocalLayouter->InvalidateLayout();
481 }
482 
483 
484 void
485 BTwoDimensionalLayout::DoLayout()
486 {
487 	_ValidateMinMax();
488 
489 	// layout the horizontal/vertical elements
490 	BSize size(SubtractInsets(LayoutArea().Size()));
491 
492 #ifdef DEBUG_LAYOUT
493 printf("BTwoDimensionalLayout::DerivedLayoutItems(): view: %p"
494 	" size: (%.1f, %.1f)\n", View(), size.Width(), size.Height());
495 #endif
496 
497 	fLocalLayouter->Layout(size);
498 
499 	// layout the items
500 	BPoint itemOffset(LayoutArea().LeftTop());
501 	int itemCount = CountItems();
502 	for (int i = 0; i < itemCount; i++) {
503 		BLayoutItem* item = ItemAt(i);
504 		if (item->IsVisible()) {
505 			Dimensions itemDimensions;
506 			GetItemDimensions(item, &itemDimensions);
507 			BRect frame = fLocalLayouter->ItemFrame(itemDimensions);
508 			frame.left += fLeftInset;
509 			frame.top += fTopInset;
510 			frame.right += fLeftInset;
511 			frame.bottom += fTopInset;
512 			frame.OffsetBy(itemOffset);
513 {
514 #ifdef DEBUG_LAYOUT
515 printf("  frame for item %2d (view: %p): ", i, item->View());
516 frame.PrintToStream();
517 #endif
518 //BSize min(item->MinSize());
519 //BSize max(item->MaxSize());
520 //printf("    min: (%.1f, %.1f), max: (%.1f, %.1f)\n", min.width, min.height,
521 //	max.width, max.height);
522 //if (item->HasHeightForWidth()) {
523 //float minHeight, maxHeight, preferredHeight;
524 //item->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight,
525 //	&preferredHeight);
526 //printf("    hfw: min: %.1f, max: %.1f, pref: %.1f\n", minHeight, maxHeight,
527 //	preferredHeight);
528 //}
529 }
530 
531 			item->AlignInFrame(frame);
532 		}
533 //else
534 //printf("  item %2d not visible", i);
535 	}
536 }
537 
538 
539 BSize
540 BTwoDimensionalLayout::AddInsets(BSize size)
541 {
542 	size.width = BLayoutUtils::AddDistances(size.width,
543 		fLeftInset + fRightInset - 1);
544 	size.height = BLayoutUtils::AddDistances(size.height,
545 		fTopInset + fBottomInset - 1);
546 	return size;
547 }
548 
549 
550 void
551 BTwoDimensionalLayout::AddInsets(float* minHeight, float* maxHeight,
552 	float* preferredHeight)
553 {
554 	float insets = fTopInset + fBottomInset - 1;
555 	if (minHeight)
556 		*minHeight = BLayoutUtils::AddDistances(*minHeight, insets);
557 	if (maxHeight)
558 		*maxHeight = BLayoutUtils::AddDistances(*maxHeight, insets);
559 	if (preferredHeight)
560 		*preferredHeight = BLayoutUtils::AddDistances(*preferredHeight, insets);
561 }
562 
563 
564 BSize
565 BTwoDimensionalLayout::SubtractInsets(BSize size)
566 {
567 	size.width = BLayoutUtils::SubtractDistances(size.width,
568 		fLeftInset + fRightInset - 1);
569 	size.height = BLayoutUtils::SubtractDistances(size.height,
570 		fTopInset + fBottomInset - 1);
571 	return size;
572 }
573 
574 
575 void
576 BTwoDimensionalLayout::PrepareItems(orientation orientation)
577 {
578 }
579 
580 
581 bool
582 BTwoDimensionalLayout::HasMultiColumnItems()
583 {
584 	return false;
585 }
586 
587 
588 bool
589 BTwoDimensionalLayout::HasMultiRowItems()
590 {
591 	return false;
592 }
593 
594 
595 void
596 BTwoDimensionalLayout::_ValidateMinMax()
597 {
598 	fLocalLayouter->ValidateMinMax();
599 }
600 
601 
602 // #pragma mark - CompoundLayouter
603 
604 
605 BTwoDimensionalLayout::CompoundLayouter::CompoundLayouter(
606 	orientation orientation)
607 	:
608 	fLayouter(NULL),
609 	fLayoutInfo(NULL),
610 	fOrientation(orientation),
611 	fLocalLayouters(10),
612 	fLayoutContext(NULL),
613 	fLastLayoutSize(-1)
614 {
615 }
616 
617 
618 BTwoDimensionalLayout::CompoundLayouter::~CompoundLayouter()
619 {
620 	delete fLayouter;
621 	delete fLayoutInfo;
622 }
623 
624 
625 orientation
626 BTwoDimensionalLayout::CompoundLayouter::Orientation()
627 {
628 	return fOrientation;
629 }
630 
631 
632 Layouter*
633 BTwoDimensionalLayout::CompoundLayouter::GetLayouter(bool minMax)
634 {
635 	return fLayouter;
636 }
637 
638 
639 LayoutInfo*
640 BTwoDimensionalLayout::CompoundLayouter::GetLayoutInfo()
641 {
642 	return fLayoutInfo;
643 }
644 
645 
646 void
647 BTwoDimensionalLayout::CompoundLayouter::AddLocalLayouter(
648 	LocalLayouter* localLayouter)
649 {
650 	if (localLayouter) {
651 		if (!fLocalLayouters.HasItem(localLayouter)) {
652 			fLocalLayouters.AddItem(localLayouter);
653 			InvalidateLayout();
654 		}
655 	}
656 }
657 
658 
659 void
660 BTwoDimensionalLayout::CompoundLayouter::RemoveLocalLayouter(
661 	LocalLayouter* localLayouter)
662 {
663 	if (fLocalLayouters.RemoveItem(localLayouter))
664 		InvalidateLayout();
665 }
666 
667 
668 status_t
669 BTwoDimensionalLayout::CompoundLayouter::AddAlignedLayoutsToArchive(
670 	BArchiver* archiver, LocalLayouter* requestedBy)
671 {
672 	// The LocalLayouter* that really owns us is at index 0, layouts
673 	// at other indices are aligned to this one.
674 	if (requestedBy != fLocalLayouters.ItemAt(0))
675 		return B_OK;
676 
677 	status_t err;
678 	for (int32 i = fLocalLayouters.CountItems() - 1; i > 0; i--) {
679 		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
680 
681 		bool wasAvailable;
682 		err = layouter->AddOwnerToArchive(archiver, this, wasAvailable);
683 		if (err != B_OK && wasAvailable)
684 			return err;
685 	}
686 	return B_OK;
687 }
688 
689 
690 void
691 BTwoDimensionalLayout::CompoundLayouter::AbsorbCompoundLayouter(
692 	CompoundLayouter* other)
693 {
694 	if (other == this)
695 		return;
696 
697 	int32 count = other->fLocalLayouters.CountItems();
698 	for (int32 i = count - 1; i >= 0; i--) {
699 		LocalLayouter* layouter
700 			= (LocalLayouter*)other->fLocalLayouters.ItemAt(i);
701 		AddLocalLayouter(layouter);
702 		layouter->SetCompoundLayouter(this, fOrientation);
703 	}
704 
705 	InvalidateLayout();
706 }
707 
708 
709 void
710 BTwoDimensionalLayout::CompoundLayouter::InvalidateLayout()
711 {
712 	if (!fLayouter)
713 		return;
714 
715 	delete fLayouter;
716 	delete fLayoutInfo;
717 
718 	fLayouter = NULL;
719 	fLayoutInfo = NULL;
720 	fLayoutContext = NULL;
721 
722 	// notify all local layouters to invalidate the respective views
723 	int32 count = fLocalLayouters.CountItems();
724 	for (int32 i = 0; i < count; i++) {
725 		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
726 		layouter->InternalInvalidateLayout(this);
727 	}
728 }
729 
730 
731 bool
732 BTwoDimensionalLayout::CompoundLayouter::IsMinMaxValid()
733 {
734 	return (fLayouter != NULL);
735 }
736 
737 
738 void
739 BTwoDimensionalLayout::CompoundLayouter::ValidateMinMax()
740 {
741 	if (IsMinMaxValid())
742 		return;
743 
744 	fLastLayoutSize = -1;
745 
746 	// create the layouter
747 	_PrepareItems();
748 
749 	int elementCount = _CountElements();
750 
751 	fLayouter = new CollapsingLayouter(elementCount, _Spacing());
752 
753 	// tell the layouter about our constraints
754 	// TODO: We should probably ignore local layouters whose view is hidden.
755 	// It's a bit tricky to find out, whether the view is hidden, though, since
756 	// this doesn't necessarily mean only hidden relative to the parent, but
757 	// hidden relative to a common parent.
758 	_AddConstraints(fLayouter);
759 
760 	fLayoutInfo = fLayouter->CreateLayoutInfo();
761 }
762 
763 
764 void
765 BTwoDimensionalLayout::CompoundLayouter::Layout(float size,
766 	LocalLayouter* localLayouter, BLayoutContext* context)
767 {
768 	ValidateMinMax();
769 
770 	if (context != fLayoutContext || fLastLayoutSize != size) {
771 		DoLayout(size, localLayouter, context);
772 		fLayoutContext = context;
773 		fLastLayoutSize = size;
774 	}
775 }
776 
777 
778 void
779 BTwoDimensionalLayout::CompoundLayouter::DoLayout(float size,
780 	LocalLayouter* localLayouter, BLayoutContext* context)
781 {
782 	fLayouter->Layout(fLayoutInfo, size);
783 }
784 
785 
786 void
787 BTwoDimensionalLayout::CompoundLayouter::_PrepareItems()
788 {
789 	int32 count = fLocalLayouters.CountItems();
790 	for (int32 i = 0; i < count; i++) {
791 		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
792 		layouter->PrepareItems(this);
793 	}
794 }
795 
796 
797 int32
798 BTwoDimensionalLayout::CompoundLayouter::_CountElements()
799 {
800 	int32 elementCount = 0;
801 	int32 count = fLocalLayouters.CountItems();
802 	for (int32 i = 0; i < count; i++) {
803 		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
804 		int32 layouterCount = layouter->CountElements(this);
805 		elementCount = max_c(elementCount, layouterCount);
806 	}
807 
808 	return elementCount;
809 }
810 
811 
812 bool
813 BTwoDimensionalLayout::CompoundLayouter::_HasMultiElementItems()
814 {
815 	int32 count = fLocalLayouters.CountItems();
816 	for (int32 i = 0; i < count; i++) {
817 		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
818 		if (layouter->HasMultiElementItems(this))
819 			return true;
820 	}
821 
822 	return false;
823 }
824 
825 
826 void
827 BTwoDimensionalLayout::CompoundLayouter::_AddConstraints(Layouter* layouter)
828 {
829 	int32 count = fLocalLayouters.CountItems();
830 	for (int32 i = 0; i < count; i++) {
831 		LocalLayouter* localLayouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
832 		localLayouter->AddConstraints(this, layouter);
833 	}
834 }
835 
836 
837 float
838 BTwoDimensionalLayout::CompoundLayouter::_Spacing()
839 {
840 	if (!fLocalLayouters.IsEmpty())
841 		return ((LocalLayouter*)fLocalLayouters.ItemAt(0))->Spacing(this);
842 	return 0;
843 }
844 
845 
846 // #pragma mark - VerticalCompoundLayouter
847 
848 
849 BTwoDimensionalLayout::VerticalCompoundLayouter::VerticalCompoundLayouter()
850 	:
851 	CompoundLayouter(B_VERTICAL),
852 	fHeightForWidthLayouter(NULL),
853 	fCachedMinHeightForWidth(0),
854 	fCachedMaxHeightForWidth(0),
855 	fCachedPreferredHeightForWidth(0),
856 	fHeightForWidthLayoutContext(NULL)
857 {
858 }
859 
860 
861 Layouter*
862 BTwoDimensionalLayout::VerticalCompoundLayouter::GetLayouter(bool minMax)
863 {
864 	return (minMax || !_HasHeightForWidth()
865 		? fLayouter : fHeightForWidthLayouter);
866 }
867 
868 
869 void
870 BTwoDimensionalLayout::VerticalCompoundLayouter::InvalidateLayout()
871 {
872 	CompoundLayouter::InvalidateLayout();
873 
874 	InvalidateHeightForWidth();
875 }
876 
877 
878 void
879 BTwoDimensionalLayout::VerticalCompoundLayouter::InvalidateHeightForWidth()
880 {
881 	if (fHeightForWidthLayouter != NULL) {
882 		delete fHeightForWidthLayouter;
883 		fHeightForWidthLayouter = NULL;
884 
885 		// also make sure we're not reusing the old layout info
886 		fLastLayoutSize = -1;
887 
888 		int32 count = fLocalLayouters.CountItems();
889 		for (int32 i = 0; i < count; i++) {
890 			LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
891 			layouter->SetHeightForWidthConstraintsAdded(false);
892 		}
893 	}
894 }
895 
896 
897 void
898 BTwoDimensionalLayout::VerticalCompoundLayouter::InternalGetHeightForWidth(
899 	LocalLayouter* localLayouter, BLayoutContext* context, bool realLayout,
900 	float* minHeight, float* maxHeight, float* preferredHeight)
901 {
902 	bool updateCachedInfo = false;
903 
904 	if (_SetHeightForWidthLayoutContext(context)
905 		|| fHeightForWidthLayouter == NULL) {
906 		// Either the layout context changed or we haven't initialized the
907 		// height for width layouter yet. We create it and init it now.
908 
909 		// clone the vertical layouter
910 		delete fHeightForWidthLayouter;
911 		delete fLayoutInfo;
912 		fHeightForWidthLayouter = fLayouter->CloneLayouter();
913 		fLayoutInfo = fHeightForWidthLayouter->CreateLayoutInfo();
914 
915 		// add the children's height for width constraints
916 		int32 count = fLocalLayouters.CountItems();
917 		for (int32 i = 0; i < count; i++) {
918 			LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
919 			if (layouter->HasHeightForWidth()) {
920 				layouter->AddHeightForWidthConstraints(this,
921 					fHeightForWidthLayouter, context);
922 			}
923 		}
924 
925 		updateCachedInfo = true;
926 
927 		// get the height for width info
928 		fCachedMinHeightForWidth = fHeightForWidthLayouter->MinSize();
929 		fCachedMaxHeightForWidth = fHeightForWidthLayouter->MaxSize();
930 		fCachedPreferredHeightForWidth
931 			= fHeightForWidthLayouter->PreferredSize();
932 
933 	} else if (localLayouter->HasHeightForWidth()) {
934 		// There is a height for width layouter and it has been initialized
935 		// in the current layout context. So we just add the height for width
936 		// constraints of the calling local layouter, if they haven't been
937 		// added yet.
938 		updateCachedInfo = localLayouter->AddHeightForWidthConstraints(this,
939 			fHeightForWidthLayouter, context);
940 	}
941 
942 	// update cached height for width info, if something changed
943 	if (updateCachedInfo) {
944 		// get the height for width info
945 		fCachedMinHeightForWidth = fHeightForWidthLayouter->MinSize();
946 		fCachedMaxHeightForWidth = fHeightForWidthLayouter->MaxSize();
947 		fCachedPreferredHeightForWidth
948 			= fHeightForWidthLayouter->PreferredSize();
949 	}
950 
951 	if (minHeight)
952 		*minHeight = fCachedMinHeightForWidth;
953 	if (maxHeight)
954 		*maxHeight = fCachedMaxHeightForWidth;
955 	if (preferredHeight)
956 		*preferredHeight = fCachedPreferredHeightForWidth;
957 }
958 
959 
960 void
961 BTwoDimensionalLayout::VerticalCompoundLayouter::DoLayout(float size,
962 	LocalLayouter* localLayouter, BLayoutContext* context)
963 {
964 	Layouter* layouter;
965 	if (_HasHeightForWidth()) {
966 		float minHeight, maxHeight, preferredHeight;
967 		InternalGetHeightForWidth(localLayouter, context, true, &minHeight,
968 			&maxHeight, &preferredHeight);
969 		size = max_c(size, minHeight);
970 		layouter = fHeightForWidthLayouter;
971 	} else
972 		layouter = fLayouter;
973 
974 	layouter->Layout(fLayoutInfo, size);
975 }
976 
977 
978 bool
979 BTwoDimensionalLayout::VerticalCompoundLayouter::_HasHeightForWidth()
980 {
981 	int32 count = fLocalLayouters.CountItems();
982 	for (int32 i = 0; i < count; i++) {
983 		LocalLayouter* layouter = (LocalLayouter*)fLocalLayouters.ItemAt(i);
984 		if (layouter->HasHeightForWidth())
985 			return true;
986 	}
987 
988 	return false;
989 }
990 
991 
992 bool
993 BTwoDimensionalLayout::VerticalCompoundLayouter
994 	::_SetHeightForWidthLayoutContext(BLayoutContext* context)
995 {
996 	if (context == fHeightForWidthLayoutContext)
997 		return false;
998 
999 	if (fHeightForWidthLayoutContext != NULL) {
1000 		fHeightForWidthLayoutContext->RemoveListener(this);
1001 		fHeightForWidthLayoutContext = NULL;
1002 	}
1003 
1004 	// We can ignore the whole context business, if we have no more than one
1005 	// local layouter. We use the layout context only to recognize when calls
1006 	// of different local layouters belong to the same context.
1007 	if (fLocalLayouters.CountItems() <= 1)
1008 		return false;
1009 
1010 	fHeightForWidthLayoutContext = context;
1011 
1012 	if (fHeightForWidthLayoutContext != NULL)
1013 		fHeightForWidthLayoutContext->AddListener(this);
1014 
1015 	InvalidateHeightForWidth();
1016 
1017 	return true;
1018 }
1019 
1020 
1021 void
1022 BTwoDimensionalLayout::VerticalCompoundLayouter::LayoutContextLeft(
1023 	BLayoutContext* context)
1024 {
1025 	fHeightForWidthLayoutContext = NULL;
1026 }
1027 
1028 
1029 // #pragma mark - LocalLayouter
1030 
1031 
1032 BTwoDimensionalLayout::LocalLayouter::LocalLayouter(
1033 		BTwoDimensionalLayout* layout)
1034 	:
1035 	fLayout(layout),
1036 	fHLayouter(new CompoundLayouter(B_HORIZONTAL)),
1037 	fVLayouter(new VerticalCompoundLayouter),
1038 	fHeightForWidthItems(),
1039 	fHorizontalLayoutContext(NULL),
1040 	fHorizontalLayoutWidth(0),
1041 	fHeightForWidthConstraintsAdded(false)
1042 {
1043 	fHLayouter->AddLocalLayouter(this);
1044 	fVLayouter->AddLocalLayouter(this);
1045 }
1046 
1047 
1048 BTwoDimensionalLayout::LocalLayouter::~LocalLayouter()
1049 {
1050 	if (fHLayouter != NULL) {
1051 		fHLayouter->RemoveLocalLayouter(this);
1052 		fHLayouter->ReleaseReference();
1053 	}
1054 
1055 	if (fVLayouter != NULL) {
1056 		fVLayouter->RemoveLocalLayouter(this);
1057 		fVLayouter->ReleaseReference();
1058 	}
1059 }
1060 
1061 
1062 BSize
1063 BTwoDimensionalLayout::LocalLayouter::MinSize()
1064 {
1065 	return BSize(fHLayouter->GetLayouter(true)->MinSize(),
1066 		fVLayouter->GetLayouter(true)->MinSize());
1067 }
1068 
1069 
1070 BSize
1071 BTwoDimensionalLayout::LocalLayouter::MaxSize()
1072 {
1073 	return BSize(fHLayouter->GetLayouter(true)->MaxSize(),
1074 		fVLayouter->GetLayouter(true)->MaxSize());
1075 }
1076 
1077 
1078 BSize
1079 BTwoDimensionalLayout::LocalLayouter::PreferredSize()
1080 {
1081 	return BSize(fHLayouter->GetLayouter(true)->PreferredSize(),
1082 		fVLayouter->GetLayouter(true)->PreferredSize());
1083 }
1084 
1085 
1086 void
1087 BTwoDimensionalLayout::LocalLayouter::InvalidateLayout()
1088 {
1089 	fHLayouter->InvalidateLayout();
1090 	fVLayouter->InvalidateLayout();
1091 }
1092 
1093 
1094 void
1095 BTwoDimensionalLayout::LocalLayouter::Layout(BSize size)
1096 {
1097 	DoHorizontalLayout(size.width);
1098 	fVLayouter->Layout(size.height, this, fLayout->LayoutContext());
1099 }
1100 
1101 
1102 BRect
1103 BTwoDimensionalLayout::LocalLayouter::ItemFrame(Dimensions itemDimensions)
1104 {
1105 	LayoutInfo* hLayoutInfo = fHLayouter->GetLayoutInfo();
1106 	LayoutInfo* vLayoutInfo = fVLayouter->GetLayoutInfo();
1107 	float x = hLayoutInfo->ElementLocation(itemDimensions.x);
1108 	float y = vLayoutInfo->ElementLocation(itemDimensions.y);
1109 	float width = hLayoutInfo->ElementRangeSize(itemDimensions.x,
1110 		itemDimensions.width);
1111 	float height = vLayoutInfo->ElementRangeSize(itemDimensions.y,
1112 		itemDimensions.height);
1113 	return BRect(x, y, x + width, y + height);
1114 }
1115 
1116 
1117 void
1118 BTwoDimensionalLayout::LocalLayouter::ValidateMinMax()
1119 {
1120 	if (fHLayouter->IsMinMaxValid() && fVLayouter->IsMinMaxValid())
1121 		return;
1122 
1123 	if (!fHLayouter->IsMinMaxValid())
1124 		fHeightForWidthItems.MakeEmpty();
1125 
1126 	_SetHorizontalLayoutContext(NULL, -1);
1127 
1128 	fHLayouter->ValidateMinMax();
1129 	fVLayouter->ValidateMinMax();
1130 	fLayout->ResetLayoutInvalidation();
1131 }
1132 
1133 
1134 void
1135 BTwoDimensionalLayout::LocalLayouter::DoHorizontalLayout(float width)
1136 {
1137 	BLayoutContext* context = fLayout->LayoutContext();
1138 	if (fHorizontalLayoutContext != context
1139 			|| width != fHorizontalLayoutWidth) {
1140 		_SetHorizontalLayoutContext(context, width);
1141 		fHLayouter->Layout(width, this, context);
1142 		fVLayouter->InvalidateHeightForWidth();
1143 	}
1144 }
1145 
1146 
1147 void
1148 BTwoDimensionalLayout::LocalLayouter::InternalGetHeightForWidth(float width,
1149 	float* minHeight, float* maxHeight, float* preferredHeight)
1150 {
1151 	DoHorizontalLayout(width);
1152 	fVLayouter->InternalGetHeightForWidth(this, fHorizontalLayoutContext, false,
1153 		minHeight, maxHeight, preferredHeight);
1154 }
1155 
1156 
1157 void
1158 BTwoDimensionalLayout::LocalLayouter::AlignWith(LocalLayouter* other,
1159 	orientation orientation)
1160 {
1161 	if (orientation == B_HORIZONTAL)
1162 		other->fHLayouter->AbsorbCompoundLayouter(fHLayouter);
1163 	else
1164 		other->fVLayouter->AbsorbCompoundLayouter(fVLayouter);
1165 }
1166 
1167 
1168 status_t
1169 BTwoDimensionalLayout::LocalLayouter::AddAlignedLayoutsToArchive(
1170 	BArchiver* archiver)
1171 {
1172 	status_t err = fHLayouter->AddAlignedLayoutsToArchive(archiver, this);
1173 
1174 	if (err == B_OK)
1175 		err = fVLayouter->AddAlignedLayoutsToArchive(archiver, this);
1176 
1177 	return err;
1178 }
1179 
1180 
1181 status_t
1182 BTwoDimensionalLayout::LocalLayouter::AddOwnerToArchive(BArchiver* archiver,
1183 	CompoundLayouter* requestedBy, bool& _wasAvailable)
1184 {
1185 	const char* field = kHAlignedLayoutField;
1186 	if (requestedBy == fVLayouter)
1187 		field = kVAlignedLayoutField;
1188 
1189 	if ((_wasAvailable = archiver->IsArchived(fLayout)))
1190 		return archiver->AddArchivable(field, fLayout);
1191 
1192 	return B_NAME_NOT_FOUND;
1193 }
1194 
1195 
1196 status_t
1197 BTwoDimensionalLayout::LocalLayouter::AlignLayoutsFromArchive(
1198 	BUnarchiver* unarchiver, orientation posture)
1199 {
1200 	const char* field = kHAlignedLayoutField;
1201 	if (posture == B_VERTICAL)
1202 		field = kVAlignedLayoutField;
1203 
1204 	int32 count;
1205 	status_t err = unarchiver->ArchiveMessage()->GetInfo(field, NULL, &count);
1206 	if (err == B_NAME_NOT_FOUND)
1207 		return B_OK;
1208 
1209 	BTwoDimensionalLayout* retriever;
1210 	for (int32 i = 0; i < count && err == B_OK; i++) {
1211 		err = unarchiver->FindObject(field, i,
1212 			BUnarchiver::B_DONT_ASSUME_OWNERSHIP, retriever);
1213 
1214 		if (err == B_OK)
1215 			retriever->AlignLayoutWith(fLayout, posture);
1216 	}
1217 
1218 	return err;
1219 }
1220 
1221 
1222 void
1223 BTwoDimensionalLayout::LocalLayouter::PrepareItems(
1224 	CompoundLayouter* compoundLayouter)
1225 {
1226 	fLayout->PrepareItems(compoundLayouter->Orientation());
1227 }
1228 
1229 
1230 int32
1231 BTwoDimensionalLayout::LocalLayouter::CountElements(
1232 	CompoundLayouter* compoundLayouter)
1233 {
1234 	if (compoundLayouter->Orientation() == B_HORIZONTAL)
1235 		return fLayout->InternalCountColumns();
1236 	else
1237 		return fLayout->InternalCountRows();
1238 }
1239 
1240 
1241 bool
1242 BTwoDimensionalLayout::LocalLayouter::HasMultiElementItems(
1243 	CompoundLayouter* compoundLayouter)
1244 {
1245 	if (compoundLayouter->Orientation() == B_HORIZONTAL)
1246 		return fLayout->HasMultiColumnItems();
1247 	else
1248 		return fLayout->HasMultiRowItems();
1249 }
1250 
1251 
1252 void
1253 BTwoDimensionalLayout::LocalLayouter::AddConstraints(
1254 	CompoundLayouter* compoundLayouter, Layouter* layouter)
1255 {
1256 	enum orientation orientation = compoundLayouter->Orientation();
1257 	int itemCount = fLayout->CountItems();
1258 	if (itemCount > 0) {
1259 		for (int i = 0; i < itemCount; i++) {
1260 			BLayoutItem* item = fLayout->ItemAt(i);
1261 			if (item->IsVisible()) {
1262 				Dimensions itemDimensions;
1263 				fLayout->GetItemDimensions(item, &itemDimensions);
1264 
1265 				BSize min = item->MinSize();
1266 				BSize max = item->MaxSize();
1267 				BSize preferred = item->PreferredSize();
1268 
1269 				if (orientation == B_HORIZONTAL) {
1270 					layouter->AddConstraints(
1271 						itemDimensions.x,
1272 						itemDimensions.width,
1273 						min.width,
1274 						max.width,
1275 						preferred.width);
1276 
1277 					if (item->HasHeightForWidth())
1278 						fHeightForWidthItems.AddItem(item);
1279 
1280 				} else {
1281 					layouter->AddConstraints(
1282 						itemDimensions.y,
1283 						itemDimensions.height,
1284 						min.height,
1285 						max.height,
1286 						preferred.height);
1287 				}
1288 			}
1289 		}
1290 
1291 		// add column/row constraints
1292 		ColumnRowConstraints constraints;
1293 		int elementCount = CountElements(compoundLayouter);
1294 		for (int element = 0; element < elementCount; element++) {
1295 			fLayout->GetColumnRowConstraints(orientation, element,
1296 				&constraints);
1297 			layouter->SetWeight(element, constraints.weight);
1298 			layouter->AddConstraints(element, 1, constraints.min,
1299 				constraints.max, constraints.min);
1300 		}
1301 	}
1302 }
1303 
1304 
1305 float
1306 BTwoDimensionalLayout::LocalLayouter::Spacing(
1307 	CompoundLayouter* compoundLayouter)
1308 {
1309 	return (compoundLayouter->Orientation() == B_HORIZONTAL
1310 		? fLayout->fHSpacing : fLayout->fVSpacing);
1311 }
1312 
1313 
1314 bool
1315 BTwoDimensionalLayout::LocalLayouter::HasHeightForWidth()
1316 {
1317 	return !fHeightForWidthItems.IsEmpty();
1318 }
1319 
1320 
1321 bool
1322 BTwoDimensionalLayout::LocalLayouter::AddHeightForWidthConstraints(
1323 	VerticalCompoundLayouter* compoundLayouter, Layouter* layouter,
1324 	BLayoutContext* context)
1325 {
1326 	if (context != fHorizontalLayoutContext)
1327 		return false;
1328 
1329 	if (fHeightForWidthConstraintsAdded)
1330 		return false;
1331 
1332 	LayoutInfo* hLayoutInfo = fHLayouter->GetLayoutInfo();
1333 
1334 	// add the children's height for width constraints
1335 	int32 itemCount = fHeightForWidthItems.CountItems();
1336 	for (int32 i = 0; i < itemCount; i++) {
1337 		BLayoutItem* item = (BLayoutItem*)fHeightForWidthItems.ItemAt(i);
1338 		Dimensions itemDimensions;
1339 		fLayout->GetItemDimensions(item, &itemDimensions);
1340 
1341 		float minHeight, maxHeight, preferredHeight;
1342 		item->GetHeightForWidth(
1343 			hLayoutInfo->ElementRangeSize(itemDimensions.x,
1344 				itemDimensions.width),
1345 			&minHeight, &maxHeight, &preferredHeight);
1346 		layouter->AddConstraints(
1347 			itemDimensions.y,
1348 			itemDimensions.height,
1349 			minHeight,
1350 			maxHeight,
1351 			preferredHeight);
1352 	}
1353 
1354 	SetHeightForWidthConstraintsAdded(true);
1355 
1356 	return true;
1357 }
1358 
1359 
1360 void
1361 BTwoDimensionalLayout::LocalLayouter::SetHeightForWidthConstraintsAdded(
1362 	bool added)
1363 {
1364 	fHeightForWidthConstraintsAdded = added;
1365 }
1366 
1367 
1368 void
1369 BTwoDimensionalLayout::LocalLayouter::SetCompoundLayouter(
1370 	CompoundLayouter* compoundLayouter, orientation orientation)
1371 {
1372 	CompoundLayouter* oldCompoundLayouter;
1373 	if (orientation == B_HORIZONTAL) {
1374 		oldCompoundLayouter = fHLayouter;
1375 		fHLayouter = compoundLayouter;
1376 	} else {
1377 		oldCompoundLayouter = fVLayouter;
1378 		fVLayouter = static_cast<VerticalCompoundLayouter*>(compoundLayouter);
1379 	}
1380 
1381 	if (compoundLayouter == oldCompoundLayouter)
1382 		return;
1383 
1384 	if (oldCompoundLayouter != NULL) {
1385 		oldCompoundLayouter->RemoveLocalLayouter(this);
1386 		oldCompoundLayouter->ReleaseReference();
1387 	}
1388 
1389 	if (compoundLayouter != NULL)
1390 		compoundLayouter->AcquireReference();
1391 
1392 	InternalInvalidateLayout(compoundLayouter);
1393 }
1394 
1395 
1396 void
1397 BTwoDimensionalLayout::LocalLayouter::InternalInvalidateLayout(
1398 	CompoundLayouter* compoundLayouter)
1399 {
1400 	_SetHorizontalLayoutContext(NULL, -1);
1401 
1402 	fLayout->BLayout::InvalidateLayout();
1403 }
1404 
1405 
1406 void
1407 BTwoDimensionalLayout::LocalLayouter::_SetHorizontalLayoutContext(
1408 	BLayoutContext* context, float width)
1409 {
1410 	if (context != fHorizontalLayoutContext) {
1411 		if (fHorizontalLayoutContext != NULL)
1412 			fHorizontalLayoutContext->RemoveListener(this);
1413 
1414 		fHorizontalLayoutContext = context;
1415 
1416 		if (fHorizontalLayoutContext != NULL)
1417 			fHorizontalLayoutContext->AddListener(this);
1418 	}
1419 
1420 	fHorizontalLayoutWidth = width;
1421 }
1422 
1423 
1424 void
1425 BTwoDimensionalLayout::LocalLayouter::LayoutContextLeft(BLayoutContext* context)
1426 {
1427 	fHorizontalLayoutContext = NULL;
1428 	fHorizontalLayoutWidth = -1;
1429 }
1430 
1431 
1432 status_t
1433 BTwoDimensionalLayout::Perform(perform_code code, void* _data)
1434 {
1435 	return BAbstractLayout::Perform(code, _data);
1436 }
1437 
1438 
1439 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout1() {}
1440 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout2() {}
1441 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout3() {}
1442 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout4() {}
1443 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout5() {}
1444 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout6() {}
1445 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout7() {}
1446 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout8() {}
1447 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout9() {}
1448 void BTwoDimensionalLayout::_ReservedTwoDimensionalLayout10() {}
1449 
1450