xref: /haiku/src/tests/kits/interface/layout/LayoutTest1.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 
5 #include <typeinfo>
6 
7 #include <Application.h>
8 #include <Button.h>
9 #include <CardLayout.h>
10 #include <LayoutBuilder.h>
11 #include <LayoutUtils.h>
12 #include <ListView.h>
13 #include <MenuField.h>
14 #include <RadioButton.h>
15 #include <ScrollView.h>
16 #include <String.h>
17 #include <StringView.h>
18 #include <TextControl.h>
19 #include <View.h>
20 #include <Window.h>
21 
22 
23 static const rgb_color kBlack	= {0, 0, 0, 255};
24 static const rgb_color kRed		= {255, 0, 0, 255};
25 
26 // message what codes
27 enum {
28 	MSG_TEST_SELECTED		= 'tsts',
29 
30 	// used in tests
31 	MSG_TOGGLE_1			= 'tgl1',
32 	MSG_TOGGLE_2			= 'tgl2',
33 
34 	MSG_FIXED_ASPECT_RATIO	= 'hwas',
35 	MSG_FIXED_SUM			= 'hwfs',
36 	MSG_FIXED_PRODUCT		= 'hwfp',
37 };
38 
39 // HeightForWidthTestView types
40 enum {
41 	FIXED_SUM,
42 	FIXED_PRODUCT,
43 	FIXED_ASPECT_RATIO,
44 };
45 
46 
47 // TestView
48 class TestView : public BView {
49 public:
50 	TestView(const rgb_color& color = kBlack)
51 		: BView("test view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
52 		  fColor(color)
53 	{
54 	}
55 
56 	void SetColor(const rgb_color& color)
57 	{
58 		fColor = color;
59 		Invalidate();
60 	}
61 
62 	virtual void Draw(BRect updateRect)
63 	{
64 		SetHighColor(fColor);
65 
66 		BRect bounds(Bounds());
67 		StrokeRect(bounds);
68 
69 		BPoint rightBottom = bounds.RightBottom();
70 		StrokeLine(B_ORIGIN, rightBottom);
71 		StrokeLine(BPoint(rightBottom.x, 0), BPoint(0, rightBottom.y));
72 	}
73 
74 	virtual BSize MinSize()
75 	{
76 		return BLayoutUtils::ComposeSize(ExplicitMinSize(), BSize(10, 10));
77 	}
78 
79 	virtual BSize PreferredSize()
80 	{
81 		return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
82 			BSize(50, 50));
83 	}
84 
85 private:
86 	rgb_color	fColor;
87 };
88 
89 
90 // HeightForWidthTestView
91 class HeightForWidthTestView : public TestView {
92 public:
93 	HeightForWidthTestView(uint32 type, float value)
94 		: fType(NULL)
95 	{
96 		SetType(type, value);
97 	}
98 
99 	HeightForWidthTestView(const rgb_color& color, uint32 type, float value)
100 		: TestView(color),
101 		  fType(NULL)
102 	{
103 		SetType(type, value);
104 	}
105 
106 	~HeightForWidthTestView()
107 	{
108 		delete fType;
109 	}
110 
111 	void SetType(uint32 type, float value)
112 	{
113 		delete fType;
114 
115 		switch (type) {
116 			case FIXED_SUM:
117 				fType = new FixedSumType((int)value);
118 				break;
119 			case FIXED_PRODUCT:
120 				fType = new FixedProductType((int)value);
121 				break;
122 			case FIXED_ASPECT_RATIO:
123 			default:
124 				fType = new FixedAspectRatioType(value);
125 				break;
126 		}
127 
128 		InvalidateLayout();
129 	}
130 
131 	BSize MinSize() {
132 		return BLayoutUtils::ComposeSize(ExplicitMinSize(), fType->MinSize());
133 	}
134 
135 	BSize MaxSize() {
136 		return BLayoutUtils::ComposeSize(ExplicitMaxSize(), fType->MaxSize());
137 	}
138 
139 	BSize PreferredSize() {
140 		return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
141 			fType->PreferredSize());
142 	}
143 
144 	bool HasHeightForWidth() {
145 		return true;
146 	}
147 
148 	void GetHeightForWidth(float width, float* minHeight, float* maxHeight,
149 			float* preferredHeight) {
150 		float dummy;
151 		fType->GetHeightForWidth(width,
152 			minHeight ? minHeight : &dummy,
153 			maxHeight ? maxHeight : &dummy,
154 			preferredHeight ? preferredHeight : &dummy);
155 	}
156 
157 private:
158 	class HeightForWidthType {
159 	public:
160 		virtual ~HeightForWidthType()
161 		{
162 		}
163 
164 		virtual BSize MinSize() = 0;
165 		virtual BSize MaxSize() = 0;
166 		virtual BSize PreferredSize() = 0;
167 		virtual void GetHeightForWidth(float width, float* minHeight,
168 			float* maxHeight, float* preferredHeight) = 0;
169 	};
170 
171 	class FixedAspectRatioType : public HeightForWidthType {
172 	public:
173 		FixedAspectRatioType(float ratio)
174 			: fAspectRatio(ratio)
175 		{
176 		}
177 
178 		virtual BSize MinSize()
179 		{
180 			return BSize(-1, -1);
181 		}
182 
183 		virtual BSize MaxSize()
184 		{
185 			return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
186 		}
187 
188 		virtual BSize PreferredSize()
189 		{
190 			float preferredWidth = 49;
191 			float dummy, preferredHeight;
192 			GetHeightForWidth(preferredWidth, &dummy, &dummy, &preferredHeight);
193 			return BSize(preferredWidth, preferredHeight);
194 		}
195 
196 		virtual void GetHeightForWidth(float width, float* minHeight,
197 			float* maxHeight, float* preferredHeight)
198 		{
199 			float height = floor((width + 1) * fAspectRatio) - 1;
200 			*minHeight = height;
201 			*maxHeight = height;
202 			*preferredHeight = height;
203 		}
204 
205 	private:
206 		float	fAspectRatio;
207 	};
208 
209 	class FixedSumType : public HeightForWidthType {
210 	public:
211 		FixedSumType(float sum)
212 			: fSum(sum)
213 		{
214 		}
215 
216 		virtual BSize MinSize()
217 		{
218 			return BSize(0, 0);
219 		}
220 
221 		virtual BSize MaxSize()
222 		{
223 			return BSize(fSum - 2, fSum - 2);
224 		}
225 
226 		virtual BSize PreferredSize()
227 		{
228 			float preferredWidth = floor(fSum / 2) - 1;
229 			float dummy, preferredHeight;
230 			GetHeightForWidth(preferredWidth, &dummy, &dummy, &preferredHeight);
231 			return BSize(preferredWidth, preferredHeight);
232 		}
233 
234 		virtual void GetHeightForWidth(float width, float* minHeight,
235 			float* maxHeight, float* preferredHeight)
236 		{
237 			float height = fSum - (width + 1) - 1;
238 			*minHeight = height;
239 			*maxHeight = height;
240 			*preferredHeight = height;
241 		}
242 
243 	private:
244 		float	fSum;
245 	};
246 
247 	class FixedProductType : public HeightForWidthType {
248 	public:
249 		FixedProductType(float product)
250 			: fProduct(product)
251 		{
252 		}
253 
254 		virtual BSize MinSize()
255 		{
256 			return BSize(0, 0);
257 		}
258 
259 		virtual BSize MaxSize()
260 		{
261 			return BSize(fProduct - 1, fProduct - 1);
262 		}
263 
264 		virtual BSize PreferredSize()
265 		{
266 			float preferredWidth = floor(sqrt(fProduct));
267 			float dummy, preferredHeight;
268 			GetHeightForWidth(preferredWidth, &dummy, &dummy, &preferredHeight);
269 			return BSize(preferredWidth, preferredHeight);
270 		}
271 
272 		virtual void GetHeightForWidth(float width, float* minHeight,
273 			float* maxHeight, float* preferredHeight)
274 		{
275 			float height = floor(fProduct / (width + 1)) - 1;
276 			*minHeight = height;
277 			*maxHeight = height;
278 			*preferredHeight = height;
279 		}
280 
281 	private:
282 		float	fProduct;
283 	};
284 
285 private:
286 	HeightForWidthType*	fType;
287 };
288 
289 
290 // Test
291 struct Test : BHandler {
292 	BString	name;
293 	BView*	rootView;
294 	BString	description;
295 
296 	Test(const char* name, const char* description)
297 		: BHandler(name),
298 		  name(name),
299 		  rootView(new BView(name, 0)),
300 		  description(description)
301 	{
302 	}
303 
304 	virtual ~Test()
305 	{
306 	}
307 
308 	virtual void RegisterListeners()
309 	{
310 	}
311 };
312 
313 
314 // GroupLayoutTest1
315 struct GroupLayoutTest1 : public Test {
316 	GroupLayoutTest1()
317 		:
318 		Test("Group", "Simple BGroupLayout.")
319 	{
320 		 BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
321 			// controls
322 			.AddGroup(B_VERTICAL)
323 				.Add(toggleRowButton = new BButton("Toggle Row",
324 						new BMessage(MSG_TOGGLE_1)))
325 				.Add(toggleViewButton = new BButton("Toggle View",
326 						new BMessage(MSG_TOGGLE_2)))
327 				.AddGlue()
328 				.End()
329 
330 			// test views
331 			.AddGroup(B_VERTICAL)
332 				// row 1
333 				.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1)
334 					.Add(new TestView(), 1)
335 					.Add(toggledView = new TestView(), 2)
336 					.Add(new TestView(), 3)
337 					.End()
338 
339 				// row 2
340 				.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 2)
341 					.GetLayout(&toggledRow)
342 					.Add(new TestView())
343 					.Add(new TestView())
344 					.Add(new TestView())
345 					.End()
346 
347 				// row 3
348 				.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 3)
349 					.Add(new TestView(), 3)
350 					.Add(new TestView(), 2)
351 					.Add(new TestView(), 1);
352 	}
353 
354 	virtual void RegisterListeners()
355 	{
356 		toggleRowButton->SetTarget(this);
357 		toggleViewButton->SetTarget(this);
358 	}
359 
360 	virtual void MessageReceived(BMessage* message)
361 	{
362 		switch (message->what) {
363 			case MSG_TOGGLE_1:
364 			{
365 				toggledRow->SetVisible(!toggledRow->IsVisible());
366 				break;
367 			}
368 
369 			case MSG_TOGGLE_2:
370 			{
371 				if (toggledView->IsHidden(toggledView))
372 					toggledView->Show();
373 				else
374 					toggledView->Hide();
375 				break;
376 			}
377 
378 			default:
379 				BHandler::MessageReceived(message);
380 				break;
381 		}
382 	}
383 
384 private:
385 	BButton*	toggleRowButton;
386 	BButton*	toggleViewButton;
387 	BGroupLayout* toggledRow;
388 	TestView*	toggledView;
389 };
390 
391 
392 // GroupAlignedLayoutTest1
393 struct GroupAlignedLayoutTest1 : public Test {
394 	GroupAlignedLayoutTest1()
395 		: Test("Group aligned", "Simple BGroupLayout, rows 1 and 3 aligned.")
396 	{
397 		BGroupView* rootView  = new BGroupView(B_HORIZONTAL, 10);
398 		this->rootView = rootView;
399 
400 		// controls
401 
402 		BGroupView* controls = new BGroupView(B_VERTICAL, 10);
403 		rootView->AddChild(controls);
404 
405 		toggleRowButton = new BButton("Toggle Row", new BMessage(MSG_TOGGLE_1));
406 		controls->AddChild(toggleRowButton);
407 
408 		toggleViewButton = new BButton("Toggle View",
409 			new BMessage(MSG_TOGGLE_2));
410 		controls->AddChild(toggleViewButton);
411 
412 
413 		controls->AddChild(BSpaceLayoutItem::CreateGlue());
414 
415 		// test views
416 
417 		BGroupView* testViews = new BGroupView(B_VERTICAL, 10);
418 		rootView->AddChild(testViews);
419 
420 		// row 1
421 		BGroupView* row = new BGroupView(B_HORIZONTAL, 10);
422 		BGroupView* row1 = row;
423 		testViews->GroupLayout()->AddView(row, 1);
424 
425 		row->GroupLayout()->AddView(new TestView(), 1);
426 		toggledView = new TestView();
427 		row->GroupLayout()->AddView(toggledView, 2);
428 		row->GroupLayout()->AddView(new TestView(), 3);
429 
430 		// row 2
431 		row = new BGroupView(B_HORIZONTAL, 10);
432 		toggledRow = row;
433 		testViews->GroupLayout()->AddView(row, 2);
434 
435 		row->GroupLayout()->AddView(new TestView());
436 		row->GroupLayout()->AddView(new TestView());
437 		row->GroupLayout()->AddView(new TestView());
438 
439 		// row 3
440 		row = new BGroupView(B_HORIZONTAL, 10);
441 		BGroupView* row3 = row;
442 		testViews->GroupLayout()->AddView(row, 3);
443 
444 		row->GroupLayout()->AddView(new TestView(), 3);
445 		row->GroupLayout()->AddView(new TestView(), 2);
446 		row->GroupLayout()->AddView(new TestView(), 1);
447 
448 		// align rows 1 and 3
449 		row1->GroupLayout()->AlignLayoutWith(row3->GroupLayout(), B_HORIZONTAL);
450 	}
451 
452 	virtual void RegisterListeners()
453 	{
454 		toggleRowButton->SetTarget(this);
455 		toggleViewButton->SetTarget(this);
456 	}
457 
458 	virtual void MessageReceived(BMessage* message)
459 	{
460 		switch (message->what) {
461 			case MSG_TOGGLE_1:
462 			{
463 				if (toggledRow->IsHidden(toggledRow))
464 					toggledRow->Show();
465 				else
466 					toggledRow->Hide();
467 				break;
468 			}
469 
470 			case MSG_TOGGLE_2:
471 			{
472 				if (toggledView->IsHidden(toggledView))
473 					toggledView->Show();
474 				else
475 					toggledView->Hide();
476 				break;
477 			}
478 
479 			default:
480 				BHandler::MessageReceived(message);
481 				break;
482 		}
483 	}
484 
485 private:
486 	BButton*	toggleRowButton;
487 	BButton*	toggleViewButton;
488 	BGroupView*	toggledRow;
489 	TestView*	toggledView;
490 };
491 
492 
493 // GridLayoutTest1
494 struct GridLayoutTest1 : public Test {
495 	GridLayoutTest1()
496 		: Test("Grid", "Simple BGridLayout.")
497 	{
498 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
499 			// controls
500 			.AddGroup(B_VERTICAL)
501 				.Add(toggleView1Button = new BButton("Toggle View 1",
502 						new BMessage(MSG_TOGGLE_1)))
503 				.Add(toggleView2Button = new BButton("Toggle View 2",
504 						new BMessage(MSG_TOGGLE_2)))
505 				.AddGlue()
506 				.End()
507 
508 			// test views
509 			.AddGrid()
510 				// row 1
511 				.Add(toggledView1 = new TestView(), 0, 0, 3, 1)
512 				.Add(new TestView(), 3, 0)
513 				.Add(new TestView(), 4, 0)
514 
515 				// row 2
516 				.Add(new TestView(), 0, 1)
517 				.Add(new TestView(), 1, 1)
518 				.Add(new TestView(), 2, 1)
519 				.Add(new TestView(), 3, 1)
520 				.Add(new TestView(), 4, 1)
521 
522 				// row 3
523 				.Add(new TestView(), 0, 2)
524 				.Add(toggledView2 = new TestView(), 1, 2, 2, 2)
525 				.Add(new TestView(), 3, 2)
526 				.Add(new TestView(), 4, 2)
527 
528 				// row 4
529 				.Add(new TestView(), 0, 3)
530 				.Add(new TestView(), 3, 3)
531 				.Add(new TestView(), 4, 3)
532 
533 				// weights
534 				.SetColumnWeight(0, 1)
535 				.SetColumnWeight(1, 2)
536 				.SetColumnWeight(2, 3)
537 				.SetColumnWeight(3, 4)
538 				.SetColumnWeight(4, 5)
539 
540 				.SetRowWeight(0, 1)
541 				.SetRowWeight(1, 2)
542 				.SetRowWeight(2, 3)
543 				.SetRowWeight(3, 4);
544 	}
545 
546 	virtual void RegisterListeners()
547 	{
548 		toggleView1Button->SetTarget(this);
549 		toggleView2Button->SetTarget(this);
550 	}
551 
552 	virtual void MessageReceived(BMessage* message)
553 	{
554 		switch (message->what) {
555 			case MSG_TOGGLE_1:
556 			{
557 				if (toggledView1->IsHidden(toggledView1))
558 					toggledView1->Show();
559 				else
560 					toggledView1->Hide();
561 				break;
562 			}
563 
564 			case MSG_TOGGLE_2:
565 			{
566 				if (toggledView2->IsHidden(toggledView2))
567 					toggledView2->Show();
568 				else
569 					toggledView2->Hide();
570 				break;
571 			}
572 
573 			default:
574 				BHandler::MessageReceived(message);
575 				break;
576 		}
577 	}
578 
579 private:
580 	BButton*	toggleView1Button;
581 	BButton*	toggleView2Button;
582 	TestView*	toggledView1;
583 	TestView*	toggledView2;
584 };
585 
586 
587 // SplitterGroupLayoutTest1
588 struct SplitterGroupLayoutTest1 : public Test {
589 	SplitterGroupLayoutTest1()
590 		: Test("Group, splitters 1", "BGroupLayout with BSplitters.")
591 	{
592 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
593 			// controls
594 			.AddGroup(B_VERTICAL)
595 				.Add(toggleRowButton = new BButton("Toggle Row",
596 						new BMessage(MSG_TOGGLE_1)))
597 				.Add(toggleViewButton = new BButton("Toggle View",
598 						new BMessage(MSG_TOGGLE_2)))
599 				.AddGlue()
600 				.End()
601 
602 			// test views
603 			.AddSplit(B_VERTICAL)
604 				// row 1
605 				.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1)
606 					.Add(new TestView(), 1)
607 					.Add(toggledView = new TestView(), 2)
608 					.Add(new TestView(), 3)
609 					.End()
610 				// make the row uncollapsible
611 				.SetCollapsible(false)
612 
613 				// row 2
614 				.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 2)
615 					.GetView(&toggledRow)
616 					.Add(new TestView())
617 					.Add(new TestView())
618 					.Add(new TestView())
619 					.End()
620 
621 				// row 3
622 				.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 3)
623 					.Add(new TestView(), 3)
624 					.Add(new TestView(), 2)
625 					.Add(new TestView(), 1)
626 					.End()
627 				// make the row uncollapsible
628 				.SetCollapsible(false);
629 	}
630 
631 	virtual void RegisterListeners()
632 	{
633 		toggleRowButton->SetTarget(this);
634 		toggleViewButton->SetTarget(this);
635 	}
636 
637 	virtual void MessageReceived(BMessage* message)
638 	{
639 		switch (message->what) {
640 			case MSG_TOGGLE_1:
641 			{
642 				if (toggledRow->IsHidden(toggledRow))
643 					toggledRow->Show();
644 				else
645 					toggledRow->Hide();
646 				break;
647 			}
648 
649 			case MSG_TOGGLE_2:
650 			{
651 				if (toggledView->IsHidden(toggledView))
652 					toggledView->Show();
653 				else
654 					toggledView->Hide();
655 				break;
656 			}
657 
658 			default:
659 				BHandler::MessageReceived(message);
660 				break;
661 		}
662 	}
663 
664 private:
665 	BButton*	toggleRowButton;
666 	BButton*	toggleViewButton;
667 	BView*		toggledRow;
668 	TestView*	toggledView;
669 };
670 
671 
672 // SplitterGroupLayoutTest2
673 struct SplitterGroupLayoutTest2 : public Test {
674 	SplitterGroupLayoutTest2()
675 		: Test("Group, splitters 2",
676 			"BGroupLayout with BSplitters. Restricted maximum widths.")
677 	{
678 		TestView* testView1 = new TestView();
679 		TestView* testView2 = new TestView();
680 		TestView* testView3 = new TestView();
681 
682 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
683 			// test views
684 			.AddGroup(B_VERTICAL)
685 				// split view
686 				.AddSplit(B_HORIZONTAL)
687 					.Add(testView1, 0)
688 					.Add(testView2, 1)
689 					.Add(testView3, 2);
690 
691 		// set maximal width on the test views
692 		testView1->SetExplicitMaxSize(BSize(100, B_SIZE_UNSET));
693 		testView2->SetExplicitMaxSize(BSize(100, B_SIZE_UNSET));
694 		testView3->SetExplicitMaxSize(BSize(100, B_SIZE_UNSET));
695 	}
696 };
697 
698 
699 // SplitterGridLayoutTest1
700 struct SplitterGridLayoutTest1 : public Test {
701 	SplitterGridLayoutTest1()
702 		: Test("Grid, h splitters", "BGridLayout with horizontal BSplitters.")
703 	{
704 		BGridLayout* layouts[3];
705 
706 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
707 			// controls
708 			.AddGroup(B_VERTICAL)
709 				.Add(toggleView1Button = new BButton("Toggle View 1",
710 						new BMessage(MSG_TOGGLE_1)))
711 				.Add(toggleView2Button = new BButton("Toggle View 2",
712 						new BMessage(MSG_TOGGLE_2)))
713 				.AddGlue()
714 				.End()
715 
716 			// test views
717 			.AddSplit(B_HORIZONTAL)
718 				// splitter element 1
719 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 6)
720 					.GetLayout(&layouts[0])
721 					// row 1
722 					.Add(toggledView1 = new TestView(), 0, 0, 3, 1)
723 					// row 2
724 					.Add(new TestView(), 0, 1)
725 					.Add(new TestView(), 1, 1)
726 					.Add(new TestView(), 2, 1)
727 					// row 3
728 					.Add(new TestView(), 0, 2)
729 					.Add(toggledView2 = new TestView(), 1, 2, 2, 2)
730 					// row 4
731 					.Add(new TestView(), 0, 3)
732 
733 					// column weights
734 					.SetColumnWeight(0, 1)
735 					.SetColumnWeight(1, 2)
736 					.SetColumnWeight(2, 3)
737 					.End()
738 
739 				// splitter element 2
740 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 4)
741 					.GetLayout(&layouts[1])
742 					// row 1
743 					.Add(new TestView(), 0, 0)
744 					// row 2
745 					.Add(new TestView(), 0, 1)
746 					// row 3
747 					.Add(new TestView(), 0, 2)
748 					// row 4
749 					.Add(new TestView(), 0, 3)
750 					.End()
751 
752 				// splitter element 3
753 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 5)
754 					.GetLayout(&layouts[2])
755 					// row 1
756 					.Add(new TestView(), 0, 0)
757 					// row 2
758 					.Add(new TestView(), 0, 1)
759 					// row 3
760 					.Add(new TestView(), 0, 2)
761 					// row 4
762 					.Add(new TestView(), 0, 3);
763 
764 		// set row weights
765 		for (int i = 0; i < 3; i++) {
766 			layouts[i]->SetRowWeight(0, 1);
767 			layouts[i]->SetRowWeight(1, 2);
768 			layouts[i]->SetRowWeight(2, 3);
769 			layouts[i]->SetRowWeight(3, 4);
770 		}
771 
772 		// set explicit min/max heights for toggled views
773 		toggledView1->SetExplicitMinSize(BSize(B_SIZE_UNSET, 100));
774 		toggledView2->SetExplicitMaxSize(BSize(B_SIZE_UNSET, 200));
775 
776 		// align the layouts
777 		layouts[0]->AlignLayoutWith(layouts[1], B_VERTICAL);
778 		layouts[0]->AlignLayoutWith(layouts[2], B_VERTICAL);
779 	}
780 
781 	virtual void RegisterListeners()
782 	{
783 		toggleView1Button->SetTarget(this);
784 		toggleView2Button->SetTarget(this);
785 	}
786 
787 	virtual void MessageReceived(BMessage* message)
788 	{
789 		switch (message->what) {
790 			case MSG_TOGGLE_1:
791 			{
792 				if (toggledView1->IsHidden(toggledView1))
793 					toggledView1->Show();
794 				else
795 					toggledView1->Hide();
796 				break;
797 			}
798 
799 			case MSG_TOGGLE_2:
800 			{
801 				if (toggledView2->IsHidden(toggledView2))
802 					toggledView2->Show();
803 				else
804 					toggledView2->Hide();
805 				break;
806 			}
807 
808 			default:
809 				BHandler::MessageReceived(message);
810 				break;
811 		}
812 	}
813 
814 private:
815 	BButton*	toggleView1Button;
816 	BButton*	toggleView2Button;
817 	TestView*	toggledView1;
818 	TestView*	toggledView2;
819 };
820 
821 
822 // SplitterGridLayoutTest2
823 struct SplitterGridLayoutTest2 : public Test {
824 	SplitterGridLayoutTest2()
825 		: Test("Grid, v splitters", "BGridLayout with vertical BSplitters.")
826 	{
827 		BGridLayout* layouts[3];
828 
829 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
830 			// controls
831 			.AddGroup(B_VERTICAL)
832 				.Add(toggleView1Button = new BButton("Toggle View 1",
833 						new BMessage(MSG_TOGGLE_1)))
834 				.Add(toggleView2Button = new BButton("Toggle View 2",
835 						new BMessage(MSG_TOGGLE_2)))
836 				.AddGlue()
837 			.End()
838 
839 			// test views
840 			.AddSplit(B_VERTICAL)
841 				// splitter element 1
842 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 1)
843 					.GetLayout(&layouts[0])
844 					// row 1
845 					.Add(toggledView1 = new TestView(), 0, 0, 3, 1)
846 					.Add(new TestView(), 3, 0)
847 					.Add(new TestView(), 4, 0)
848 					.End()
849 
850 				// splitter element 2
851 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 2)
852 					.GetLayout(&layouts[1])
853 					// row 2
854 					.Add(new TestView(), 0, 0)
855 					.Add(new TestView(), 1, 0)
856 					.Add(new TestView(), 2, 0)
857 					.Add(new TestView(), 3, 0)
858 					.Add(new TestView(), 4, 0)
859 					.End()
860 
861 				// splitter element 3
862 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 7)
863 					.GetLayout(&layouts[2])
864 					// row 3
865 					.Add(new TestView(), 0, 0)
866 					.Add(toggledView2 = new TestView(), 1, 0, 2, 2)
867 					.Add(new TestView(), 3, 0)
868 					.Add(new TestView(), 4, 0)
869 					// row 4
870 					.Add(new TestView(), 0, 1)
871 					.Add(new TestView(), 3, 1)
872 					.Add(new TestView(), 4, 1)
873 
874 					// row weights
875 					.SetRowWeight(0, 3)
876 					.SetRowWeight(1, 4);
877 
878 		// set column weights
879 		for (int i = 0; i < 3; i++) {
880 			layouts[i]->SetColumnWeight(0, 1);
881 			layouts[i]->SetColumnWeight(1, 2);
882 			layouts[i]->SetColumnWeight(2, 3);
883 			layouts[i]->SetColumnWeight(3, 4);
884 			layouts[i]->SetColumnWeight(4, 5);
885 		}
886 
887 		// align the layouts
888 		layouts[0]->AlignLayoutWith(layouts[1], B_HORIZONTAL);
889 		layouts[0]->AlignLayoutWith(layouts[2], B_HORIZONTAL);
890 	}
891 
892 	virtual void RegisterListeners()
893 	{
894 		toggleView1Button->SetTarget(this);
895 		toggleView2Button->SetTarget(this);
896 	}
897 
898 	virtual void MessageReceived(BMessage* message)
899 	{
900 		switch (message->what) {
901 			case MSG_TOGGLE_1:
902 			{
903 				if (toggledView1->IsHidden(toggledView1))
904 					toggledView1->Show();
905 				else
906 					toggledView1->Hide();
907 				break;
908 			}
909 
910 			case MSG_TOGGLE_2:
911 			{
912 				if (toggledView2->IsHidden(toggledView2))
913 					toggledView2->Show();
914 				else
915 					toggledView2->Hide();
916 				break;
917 			}
918 
919 			default:
920 				BHandler::MessageReceived(message);
921 				break;
922 		}
923 	}
924 
925 private:
926 	BButton*	toggleView1Button;
927 	BButton*	toggleView2Button;
928 	TestView*	toggledView1;
929 	TestView*	toggledView2;
930 };
931 
932 
933 // GroupLayoutHeightForWidthTestHorizontal1
934 struct GroupLayoutHeightForWidthTestHorizontal1 : public Test {
935 	GroupLayoutHeightForWidthTestHorizontal1()
936 		: Test("Group, height for width, h",
937 			"Horizontal BGroupLayout with height for width view.")
938 	{
939 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
940 			// controls
941 			.AddGroup(B_VERTICAL, 10, 0)
942 				.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
943 						new BMessage(MSG_FIXED_ASPECT_RATIO)))
944 				.Add(sumButton = new BRadioButton("fixed sum",
945 						new BMessage(MSG_FIXED_SUM)))
946 				.Add(productButton = new BRadioButton("fixed product",
947 						new BMessage(MSG_FIXED_PRODUCT)))
948 				.AddGlue()
949 			.End()
950 
951 			// test views
952 			.AddGroup(B_VERTICAL, 10)
953 				// row 1
954 				.AddGroup(B_HORIZONTAL, 10)
955 					.Add(new TestView())
956 					.Add(new TestView())
957 					.Add(new TestView())
958 				.End()
959 
960 				// row 2
961 				.AddGroup(B_HORIZONTAL, 10)
962 					.Add(new TestView())
963 					.Add(heightForWidthView = new HeightForWidthTestView(kRed,
964 							FIXED_ASPECT_RATIO, 0.5f))
965 					.Add(new TestView())
966 				.End()
967 
968 				// row 3
969 				.AddGroup(B_HORIZONTAL, 10)
970 					.Add(new TestView())
971 					.Add(new TestView())
972 					.Add(new TestView())
973 				.End()
974 			.End()
975 		;
976 
977 		aspectRatioButton->SetValue(1);
978 	}
979 
980 	virtual void RegisterListeners()
981 	{
982 		aspectRatioButton->SetTarget(this);
983 		sumButton->SetTarget(this);
984 		productButton->SetTarget(this);
985 	}
986 
987 	virtual void MessageReceived(BMessage* message)
988 	{
989 		switch (message->what) {
990 			case MSG_FIXED_ASPECT_RATIO:
991 			{
992 				heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
993 				break;
994 			}
995 
996 			case MSG_FIXED_SUM:
997 			{
998 				heightForWidthView->SetType(FIXED_SUM, 200);
999 				break;
1000 			}
1001 
1002 			case MSG_FIXED_PRODUCT:
1003 			{
1004 				heightForWidthView->SetType(FIXED_PRODUCT, 40000);
1005 				break;
1006 			}
1007 
1008 			default:
1009 				BHandler::MessageReceived(message);
1010 				break;
1011 		}
1012 	}
1013 
1014 private:
1015 	BRadioButton*			aspectRatioButton;
1016 	BRadioButton*			sumButton;
1017 	BRadioButton*			productButton;
1018 	HeightForWidthTestView*	heightForWidthView;
1019 };
1020 
1021 
1022 // GroupLayoutHeightForWidthTestVertical1
1023 struct GroupLayoutHeightForWidthTestVertical1 : public Test {
1024 	GroupLayoutHeightForWidthTestVertical1()
1025 		: Test("Group, height for width, v",
1026 			"Vertical BGroupLayout with height for width view.")
1027 	{
1028 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
1029 			// controls
1030 			.AddGroup(B_VERTICAL, 10, 0)
1031 				.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
1032 						new BMessage(MSG_FIXED_ASPECT_RATIO)))
1033 				.Add(sumButton = new BRadioButton("fixed sum",
1034 						new BMessage(MSG_FIXED_SUM)))
1035 				.Add(productButton = new BRadioButton("fixed product",
1036 						new BMessage(MSG_FIXED_PRODUCT)))
1037 				.AddGlue()
1038 			.End()
1039 
1040 			// test views
1041 			.AddGroup(B_HORIZONTAL, 10)
1042 				// column 1
1043 				.AddGroup(B_VERTICAL, 10)
1044 					.Add(new TestView())
1045 					.Add(new TestView())
1046 					.Add(new TestView())
1047 				.End()
1048 
1049 				// column 2
1050 				.AddGroup(B_VERTICAL, 10)
1051 					.Add(new TestView())
1052 					.Add(heightForWidthView = new HeightForWidthTestView(kRed,
1053 							FIXED_ASPECT_RATIO, 0.5f))
1054 					.Add(new TestView())
1055 				.End()
1056 
1057 				// column 3
1058 				.AddGroup(B_VERTICAL, 10)
1059 					.Add(new TestView())
1060 					.Add(new TestView())
1061 					.Add(new TestView())
1062 				.End()
1063 			.End()
1064 		;
1065 
1066 		aspectRatioButton->SetValue(1);
1067 	}
1068 
1069 	virtual void RegisterListeners()
1070 	{
1071 		aspectRatioButton->SetTarget(this);
1072 		sumButton->SetTarget(this);
1073 		productButton->SetTarget(this);
1074 	}
1075 
1076 	virtual void MessageReceived(BMessage* message)
1077 	{
1078 		switch (message->what) {
1079 			case MSG_FIXED_ASPECT_RATIO:
1080 			{
1081 				heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
1082 				break;
1083 			}
1084 
1085 			case MSG_FIXED_SUM:
1086 			{
1087 				heightForWidthView->SetType(FIXED_SUM, 200);
1088 				break;
1089 			}
1090 
1091 			case MSG_FIXED_PRODUCT:
1092 			{
1093 				heightForWidthView->SetType(FIXED_PRODUCT, 40000);
1094 				break;
1095 			}
1096 
1097 			default:
1098 				BHandler::MessageReceived(message);
1099 				break;
1100 		}
1101 	}
1102 
1103 private:
1104 	BRadioButton*			aspectRatioButton;
1105 	BRadioButton*			sumButton;
1106 	BRadioButton*			productButton;
1107 	HeightForWidthTestView*	heightForWidthView;
1108 };
1109 
1110 
1111 // GridLayoutHeightForWidthTest1
1112 struct GridLayoutHeightForWidthTest1 : public Test {
1113 	GridLayoutHeightForWidthTest1()
1114 		: Test("Grid, height for width",
1115 			"BGridLayout with height for width view.")
1116 	{
1117 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
1118 			// controls
1119 			.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING, 0)
1120 				.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
1121 						new BMessage(MSG_FIXED_ASPECT_RATIO)))
1122 				.Add(sumButton = new BRadioButton("fixed sum",
1123 						new BMessage(MSG_FIXED_SUM)))
1124 				.Add(productButton = new BRadioButton("fixed product",
1125 						new BMessage(MSG_FIXED_PRODUCT)))
1126 				.AddGlue()
1127 			.End()
1128 
1129 			// test views
1130 			.AddGrid()
1131 				// row 1
1132 				.Add(new TestView(), 0, 0, 3, 1)
1133 				.Add(new TestView(), 3, 0)
1134 				.Add(new TestView(), 4, 0)
1135 
1136 				// row 2
1137 				.Add(new TestView(), 0, 1)
1138 				.Add(new TestView(), 1, 1)
1139 				.Add(new TestView(), 2, 1)
1140 				.Add(new TestView(), 3, 1)
1141 				.Add(new TestView(), 4, 1)
1142 
1143 				// row 3
1144 				.Add(new TestView(), 0, 2)
1145 				.Add(heightForWidthView = new HeightForWidthTestView(kRed,
1146 						FIXED_ASPECT_RATIO, 0.5f), 1, 2, 2, 2)
1147 				.Add(new TestView(), 3, 2)
1148 				.Add(new TestView(), 4, 2)
1149 
1150 				// row 4
1151 				.Add(new TestView(), 0, 3)
1152 				.Add(new TestView(), 3, 3)
1153 				.Add(new TestView(), 4, 3)
1154 
1155 				// weights
1156 				.SetColumnWeight(0, 1)
1157 				.SetColumnWeight(1, 2)
1158 				.SetColumnWeight(2, 3)
1159 				.SetColumnWeight(3, 4)
1160 				.SetColumnWeight(4, 5)
1161 
1162 				.SetRowWeight(0, 1)
1163 				.SetRowWeight(1, 2)
1164 				.SetRowWeight(2, 3)
1165 				.SetRowWeight(3, 4);
1166 
1167 		aspectRatioButton->SetValue(1);
1168 	}
1169 
1170 	virtual void RegisterListeners()
1171 	{
1172 		aspectRatioButton->SetTarget(this);
1173 		sumButton->SetTarget(this);
1174 		productButton->SetTarget(this);
1175 	}
1176 
1177 	virtual void MessageReceived(BMessage* message)
1178 	{
1179 		switch (message->what) {
1180 			case MSG_FIXED_ASPECT_RATIO:
1181 			{
1182 				heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
1183 				break;
1184 			}
1185 
1186 			case MSG_FIXED_SUM:
1187 			{
1188 				heightForWidthView->SetType(FIXED_SUM, 200);
1189 				break;
1190 			}
1191 
1192 			case MSG_FIXED_PRODUCT:
1193 			{
1194 				heightForWidthView->SetType(FIXED_PRODUCT, 40000);
1195 				break;
1196 			}
1197 
1198 			default:
1199 				BHandler::MessageReceived(message);
1200 				break;
1201 		}
1202 	}
1203 
1204 private:
1205 	BRadioButton*			aspectRatioButton;
1206 	BRadioButton*			sumButton;
1207 	BRadioButton*			productButton;
1208 	HeightForWidthTestView*	heightForWidthView;
1209 };
1210 
1211 
1212 // SplitterGroupLayoutHeightForWidthTest1
1213 struct SplitterGroupLayoutHeightForWidthTest1 : public Test {
1214 	SplitterGroupLayoutHeightForWidthTest1()
1215 		: Test("Group, splitters, height for width",
1216 			"Horizontal BGroupLayout with height for width view and "
1217 				"BSplitters.")
1218 	{
1219 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL)
1220 			// controls
1221 			.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING, 0)
1222 				.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
1223 						new BMessage(MSG_FIXED_ASPECT_RATIO)))
1224 				.Add(sumButton = new BRadioButton("fixed sum",
1225 						new BMessage(MSG_FIXED_SUM)))
1226 				.Add(productButton = new BRadioButton("fixed product",
1227 						new BMessage(MSG_FIXED_PRODUCT)))
1228 				.AddGlue()
1229 			.End()
1230 
1231 			// test views
1232 			.AddSplit(B_VERTICAL, B_USE_DEFAULT_SPACING, 1)
1233 				// row 1
1234 				.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 1)
1235 					.Add(new TestView(), 1)
1236 					.Add(new TestView(), 2)
1237 					.Add(new TestView(), 3)
1238 					.End()
1239 				// make the row uncollapsible
1240 				.SetCollapsible(false)
1241 
1242 				// row 2
1243 				.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 2)
1244 					.Add(new TestView())
1245 					.Add(heightForWidthView = new HeightForWidthTestView(kRed,
1246 							FIXED_ASPECT_RATIO, 0.5f))
1247 					.Add(new TestView())
1248 					.End()
1249 
1250 				// row 3
1251 				.AddSplit(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 3)
1252 					.Add(new TestView(), 3)
1253 					.Add(new TestView(), 2)
1254 					.Add(new TestView(), 1)
1255 					.End()
1256 				// make the row uncollapsible
1257 				.SetCollapsible(false);
1258 
1259 		aspectRatioButton->SetValue(1);
1260 	}
1261 
1262 	virtual void RegisterListeners()
1263 	{
1264 		aspectRatioButton->SetTarget(this);
1265 		sumButton->SetTarget(this);
1266 		productButton->SetTarget(this);
1267 	}
1268 
1269 	virtual void MessageReceived(BMessage* message)
1270 	{
1271 		switch (message->what) {
1272 			case MSG_FIXED_ASPECT_RATIO:
1273 			{
1274 				heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
1275 				break;
1276 			}
1277 
1278 			case MSG_FIXED_SUM:
1279 			{
1280 				heightForWidthView->SetType(FIXED_SUM, 200);
1281 				break;
1282 			}
1283 
1284 			case MSG_FIXED_PRODUCT:
1285 			{
1286 				heightForWidthView->SetType(FIXED_PRODUCT, 40000);
1287 				break;
1288 			}
1289 
1290 			default:
1291 				BHandler::MessageReceived(message);
1292 				break;
1293 		}
1294 	}
1295 
1296 private:
1297 	BRadioButton*			aspectRatioButton;
1298 	BRadioButton*			sumButton;
1299 	BRadioButton*			productButton;
1300 	HeightForWidthTestView*	heightForWidthView;
1301 };
1302 
1303 
1304 // SplitterGridLayoutHeightForWidthTest1
1305 struct SplitterGridLayoutHeightForWidthTest1 : public Test {
1306 	SplitterGridLayoutHeightForWidthTest1()
1307 		: Test("Grid, splitters, height for width",
1308 			"BGridLayout with height for width view and horizontal BSplitters.")
1309 	{
1310 		BGridLayout* layouts[3];
1311 
1312 		BLayoutBuilder::Group<>(rootView, B_HORIZONTAL, B_USE_DEFAULT_SPACING)
1313 			// controls
1314 			.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING, 0)
1315 				.Add(aspectRatioButton = new BRadioButton("fixed aspect ratio",
1316 						new BMessage(MSG_FIXED_ASPECT_RATIO)))
1317 				.Add(sumButton = new BRadioButton("fixed sum",
1318 						new BMessage(MSG_FIXED_SUM)))
1319 				.Add(productButton = new BRadioButton("fixed product",
1320 						new BMessage(MSG_FIXED_PRODUCT)))
1321 				.AddGlue()
1322 			.End()
1323 
1324 			// test views
1325 			.AddSplit(B_HORIZONTAL)
1326 				// splitter element 1
1327 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 6)
1328 					.GetLayout(&layouts[0])
1329 					// row 1
1330 					.Add(new TestView(), 0, 0, 3, 1)
1331 					// row 2
1332 					.Add(new TestView(), 0, 1)
1333 					.Add(new TestView(), 1, 1)
1334 					.Add(new TestView(), 2, 1)
1335 					// row 3
1336 					.Add(new TestView(), 0, 2)
1337 					.Add(heightForWidthView = new HeightForWidthTestView(kRed,
1338 							FIXED_ASPECT_RATIO, 0.5f), 1, 2, 2, 2)
1339 					// row 4
1340 					.Add(new TestView(), 0, 3)
1341 
1342 					// column weights
1343 					.SetColumnWeight(0, 1)
1344 					.SetColumnWeight(1, 2)
1345 					.SetColumnWeight(2, 3)
1346 					.End()
1347 
1348 				// splitter element 2
1349 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 4)
1350 					.GetLayout(&layouts[1])
1351 					// row 1
1352 					.Add(new TestView(), 0, 0)
1353 					// row 2
1354 					.Add(new TestView(), 0, 1)
1355 					// row 3
1356 					.Add(new TestView(), 0, 2)
1357 					// row 4
1358 					.Add(new TestView(), 0, 3)
1359 					.End()
1360 
1361 				// splitter element 3
1362 				.AddGrid(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, 5)
1363 					.GetLayout(&layouts[2])
1364 					// row 1
1365 					.Add(new TestView(), 0, 0)
1366 					// row 2
1367 					.Add(new TestView(), 0, 1)
1368 					// row 3
1369 					.Add(new TestView(), 0, 2)
1370 					// row 4
1371 					.Add(new TestView(), 0, 3);
1372 
1373 		// set row weights
1374 		for (int i = 0; i < 3; i++) {
1375 			layouts[i]->SetRowWeight(0, 1);
1376 			layouts[i]->SetRowWeight(1, 2);
1377 			layouts[i]->SetRowWeight(2, 3);
1378 			layouts[i]->SetRowWeight(3, 4);
1379 		}
1380 
1381 		// align the layouts
1382 		layouts[0]->AlignLayoutWith(layouts[1], B_VERTICAL);
1383 		layouts[0]->AlignLayoutWith(layouts[2], B_VERTICAL);
1384 
1385 		aspectRatioButton->SetValue(1);
1386 	}
1387 
1388 	virtual void RegisterListeners()
1389 	{
1390 		aspectRatioButton->SetTarget(this);
1391 		sumButton->SetTarget(this);
1392 		productButton->SetTarget(this);
1393 	}
1394 
1395 	virtual void MessageReceived(BMessage* message)
1396 	{
1397 		switch (message->what) {
1398 			case MSG_FIXED_ASPECT_RATIO:
1399 			{
1400 				heightForWidthView->SetType(FIXED_ASPECT_RATIO, 0.5f);
1401 				break;
1402 			}
1403 
1404 			case MSG_FIXED_SUM:
1405 			{
1406 				heightForWidthView->SetType(FIXED_SUM, 200);
1407 				break;
1408 			}
1409 
1410 			case MSG_FIXED_PRODUCT:
1411 			{
1412 				heightForWidthView->SetType(FIXED_PRODUCT, 40000);
1413 				break;
1414 			}
1415 
1416 			default:
1417 				BHandler::MessageReceived(message);
1418 				break;
1419 		}
1420 	}
1421 
1422 private:
1423 	BRadioButton*			aspectRatioButton;
1424 	BRadioButton*			sumButton;
1425 	BRadioButton*			productButton;
1426 	HeightForWidthTestView*	heightForWidthView;
1427 };
1428 
1429 
1430 // LabelTest1
1431 struct LabelTest1 : public Test {
1432 	LabelTest1()
1433 		: Test("BTextControl, BMenuField, grid",
1434 			"Aligning BTextControl/BMenuField labels using a 2 column "
1435 			"BGridLayout.")
1436 	{
1437 		textControl1 = new BTextControl("Label", NULL, NULL);
1438 		textControl2 = new BTextControl("Long Label", NULL, NULL);
1439 		textControl3 = new BTextControl("Very Long Label", NULL, NULL);
1440 
1441 		menuField1 = new BMenuField("Label", new BMenu("Options"));
1442 		menuField2 = new BMenuField("Long Label",
1443 			new BMenu("More Options"));
1444 		menuField3 = new BMenuField("Very Long Label",
1445 			new BMenu("Obscure Options"));
1446 
1447 		BLayoutBuilder::Group<>(rootView, B_VERTICAL)
1448 			// controls
1449 			.AddGroup(B_HORIZONTAL)
1450 				.Add(changeLabelsButton = new BButton("Random Labels",
1451 						new BMessage(MSG_TOGGLE_1)))
1452 				.AddGlue()
1453 				.End()
1454 
1455 			.AddGlue()
1456 
1457 			// test views
1458 			.AddGrid()
1459 				// padding
1460 				.Add(BSpaceLayoutItem::CreateGlue(), 0, 0)
1461 				.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
1462 
1463 				// row 1
1464 				.Add(textControl1->CreateLabelLayoutItem(), 0, 1)
1465 				.Add(textControl1->CreateTextViewLayoutItem(), 1, 1)
1466 
1467 				// row 2
1468 				.Add(textControl2->CreateLabelLayoutItem(), 0, 2)
1469 				.Add(textControl2->CreateTextViewLayoutItem(), 1, 2)
1470 
1471 				// row 3
1472 				.Add(textControl3->CreateLabelLayoutItem(), 0, 3)
1473 				.Add(textControl3->CreateTextViewLayoutItem(), 1, 3)
1474 
1475 				// row 4
1476 				.Add(menuField1->CreateLabelLayoutItem(), 0, 4)
1477 				.Add(menuField1->CreateMenuBarLayoutItem(), 1, 4)
1478 
1479 				// row 5
1480 				.Add(menuField2->CreateLabelLayoutItem(), 0, 5)
1481 				.Add(menuField2->CreateMenuBarLayoutItem(), 1, 5)
1482 
1483 				// row 6
1484 				.Add(menuField3->CreateLabelLayoutItem(), 0, 6)
1485 				.Add(menuField3->CreateMenuBarLayoutItem(), 1, 6)
1486 
1487 				// padding
1488 				.Add(BSpaceLayoutItem::CreateGlue(), 0, 7)
1489 				.Add(BSpaceLayoutItem::CreateGlue(), 1, 7)
1490 				.End()
1491 			.AddGlue();
1492 	}
1493 
1494 	virtual void RegisterListeners()
1495 	{
1496 		changeLabelsButton->SetTarget(this);
1497 	}
1498 
1499 	virtual void MessageReceived(BMessage* message)
1500 	{
1501 		switch (message->what) {
1502 			case MSG_TOGGLE_1:
1503 			{
1504 				BTextControl* textControls[] = {
1505 					textControl1, textControl2, textControl3
1506 				};
1507 
1508 				BMenuField* menuFields[] = {
1509 					menuField1, menuField2, menuField3
1510 				};
1511 
1512 				for (int i = 0; i < 3; i++) {
1513 					BTextControl* textControl = textControls[i];
1514 					BMenuField* menuField = menuFields[i];
1515 
1516 					textControl->SetLabel(_RandomLabel().String());
1517 					menuField->SetLabel(_RandomLabel().String());
1518 				}
1519 			}
1520 
1521 			default:
1522 				BHandler::MessageReceived(message);
1523 				break;
1524 		}
1525 	}
1526 
1527 	BString _RandomLabel() const
1528 	{
1529 		const char* digits = "0123456789";
1530 
1531 		int length = rand() % 20;
1532 		BString label("Random ");
1533 		for (int k = 0; k < length; k++)
1534 			label.Append(digits[k % 10], 1);
1535 
1536 		return label;
1537 	}
1538 
1539 private:
1540 	BButton*		changeLabelsButton;
1541 	BTextControl*	textControl1;
1542 	BTextControl*	textControl2;
1543 	BTextControl*	textControl3;
1544 	BMenuField*		menuField1;
1545 	BMenuField*		menuField2;
1546 	BMenuField*		menuField3;
1547 };
1548 
1549 
1550 // TestWindow
1551 class TestWindow : public BWindow {
1552 public:
1553 	TestWindow()
1554 		: BWindow(BRect(100, 100, 700, 500), "LayoutTest1",
1555 			B_TITLED_WINDOW,
1556 			B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE
1557 				| B_AUTO_UPDATE_SIZE_LIMITS)
1558 	{
1559 		fTestList = new BListView(BRect(0, 0, 10, 10), "test list",
1560 			B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL);
1561 		BView* scrollView = new BScrollView("test scroll view", fTestList);
1562 		scrollView->SetExplicitMaxSize(BSize(190, B_SIZE_UNLIMITED));
1563 
1564 		fTestCardLayout = new BCardLayout();
1565 		BView* cardView = new BView("card view", 0, fTestCardLayout);
1566 
1567 		BLayoutBuilder::Group<>(this, B_HORIZONTAL)
1568 			.SetInsets(B_USE_WINDOW_INSETS)
1569 			.Add(scrollView)
1570 			.Add(cardView);
1571 
1572 		// add the tests
1573 		_AddTest(new GroupLayoutTest1());
1574 		_AddTest(new GroupAlignedLayoutTest1());
1575 		_AddTest(new GridLayoutTest1());
1576 		_AddTest(new SplitterGroupLayoutTest1());
1577 		_AddTest(new SplitterGroupLayoutTest2());
1578 		_AddTest(new SplitterGridLayoutTest1());
1579 		_AddTest(new SplitterGridLayoutTest2());
1580 		_AddTest(new GroupLayoutHeightForWidthTestHorizontal1());
1581 		_AddTest(new GroupLayoutHeightForWidthTestVertical1());
1582 		_AddTest(new GridLayoutHeightForWidthTest1());
1583 		_AddTest(new SplitterGroupLayoutHeightForWidthTest1());
1584 		_AddTest(new SplitterGridLayoutHeightForWidthTest1());
1585 		_AddTest(new LabelTest1());
1586 
1587 		fTestList->SetSelectionMessage(new BMessage(MSG_TEST_SELECTED));
1588 		_DumpViewHierarchy(GetLayout()->Owner());
1589 	}
1590 
1591 	virtual void MessageReceived(BMessage* message)
1592 	{
1593 		switch (message->what) {
1594 			case MSG_TEST_SELECTED:
1595 				fTestCardLayout->SetVisibleItem(fTestList->CurrentSelection());
1596 				break;
1597 			default:
1598 				BWindow::MessageReceived(message);
1599 				break;
1600 		}
1601 	}
1602 
1603 private:
1604 	void _AddTest(Test* test) {
1605 		fTestList->AddItem(new BStringItem(test->name.String()));
1606 
1607 		BGroupView* containerView = new BGroupView(B_VERTICAL, 0);
1608 
1609 		BStringView* descriptionView = new BStringView("test description",
1610 			test->description.String());
1611 
1612 		descriptionView->SetExplicitMinSize(BSize(0, B_SIZE_UNSET));
1613 		containerView->AddChild(descriptionView);
1614 
1615 		// spacing/glue
1616 		containerView->GroupLayout()->AddItem(
1617 			BSpaceLayoutItem::CreateVerticalStrut(10));
1618 		containerView->GroupLayout()->AddItem(
1619 			BSpaceLayoutItem::CreateGlue(), 0);
1620 
1621 		// the test view: wrap it, so we can have unlimited size
1622 		BGroupView* wrapperView = new BGroupView(B_HORIZONTAL, 0);
1623 		containerView->AddChild(wrapperView);
1624 		wrapperView->AddChild(test->rootView);
1625 
1626 		// glue
1627 		containerView->GroupLayout()->AddItem(
1628 			BSpaceLayoutItem::CreateGlue(), 0);
1629 
1630 		wrapperView->SetExplicitMaxSize(
1631 			BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
1632 		containerView->SetExplicitMaxSize(
1633 			BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
1634 
1635 		fTestCardLayout->AddView(containerView);
1636 
1637 		AddHandler(test);
1638 		test->RegisterListeners();
1639 	}
1640 
1641 	void _DumpViewHierarchy(BView* view, int32 indent = 0)
1642 	{
1643 		for (int32 i = 0; i < indent; i++)
1644 			printf("  ");
1645 		printf("view: %p", view);
1646 		for (int32 i = 0; i < 15 - indent; i++)
1647 			printf("  ");
1648 		printf("(%s)\n", typeid(*view).name());
1649 
1650 		int32 count = view->CountChildren();
1651 		for (int32 i = 0; i < count; i++)
1652 			_DumpViewHierarchy(view->ChildAt(i), indent + 1);
1653 	}
1654 
1655 private:
1656 	BListView*		fTestList;
1657 	BCardLayout*	fTestCardLayout;
1658 };
1659 
1660 
1661 int
1662 main()
1663 {
1664 	BApplication app("application/x-vnd.haiku.layout-test1");
1665 
1666 	BWindow* window = new TestWindow;
1667 	window->Show();
1668 
1669 	app.Run();
1670 
1671 	return 0;
1672 }
1673