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