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
23static const rgb_color kBlack	= {0, 0, 0, 255};
24static const rgb_color kRed		= {255, 0, 0, 255};
25
26// message what codes
27enum {
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
40enum {
41	FIXED_SUM,
42	FIXED_PRODUCT,
43	FIXED_ASPECT_RATIO,
44};
45
46
47// TestView
48class TestView : public BView {
49public:
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
85private:
86	rgb_color	fColor;
87};
88
89
90// HeightForWidthTestView
91class HeightForWidthTestView : public TestView {
92public:
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
157private:
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
285private:
286	HeightForWidthType*	fType;
287};
288
289
290// Test
291struct 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
315struct 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
384private:
385	BButton*	toggleRowButton;
386	BButton*	toggleViewButton;
387	BGroupLayout* toggledRow;
388	TestView*	toggledView;
389};
390
391
392// GroupAlignedLayoutTest1
393struct 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
485private:
486	BButton*	toggleRowButton;
487	BButton*	toggleViewButton;
488	BGroupView*	toggledRow;
489	TestView*	toggledView;
490};
491
492
493// GridLayoutTest1
494struct 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
579private:
580	BButton*	toggleView1Button;
581	BButton*	toggleView2Button;
582	TestView*	toggledView1;
583	TestView*	toggledView2;
584};
585
586
587// SplitterGroupLayoutTest1
588struct 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
664private:
665	BButton*	toggleRowButton;
666	BButton*	toggleViewButton;
667	BView*		toggledRow;
668	TestView*	toggledView;
669};
670
671
672// SplitterGroupLayoutTest2
673struct 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
700struct 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
814private:
815	BButton*	toggleView1Button;
816	BButton*	toggleView2Button;
817	TestView*	toggledView1;
818	TestView*	toggledView2;
819};
820
821
822// SplitterGridLayoutTest2
823struct 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
925private:
926	BButton*	toggleView1Button;
927	BButton*	toggleView2Button;
928	TestView*	toggledView1;
929	TestView*	toggledView2;
930};
931
932
933// GroupLayoutHeightForWidthTestHorizontal1
934struct 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
1014private:
1015	BRadioButton*			aspectRatioButton;
1016	BRadioButton*			sumButton;
1017	BRadioButton*			productButton;
1018	HeightForWidthTestView*	heightForWidthView;
1019};
1020
1021
1022// GroupLayoutHeightForWidthTestVertical1
1023struct 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
1103private:
1104	BRadioButton*			aspectRatioButton;
1105	BRadioButton*			sumButton;
1106	BRadioButton*			productButton;
1107	HeightForWidthTestView*	heightForWidthView;
1108};
1109
1110
1111// GridLayoutHeightForWidthTest1
1112struct 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
1204private:
1205	BRadioButton*			aspectRatioButton;
1206	BRadioButton*			sumButton;
1207	BRadioButton*			productButton;
1208	HeightForWidthTestView*	heightForWidthView;
1209};
1210
1211
1212// SplitterGroupLayoutHeightForWidthTest1
1213struct 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
1296private:
1297	BRadioButton*			aspectRatioButton;
1298	BRadioButton*			sumButton;
1299	BRadioButton*			productButton;
1300	HeightForWidthTestView*	heightForWidthView;
1301};
1302
1303
1304// SplitterGridLayoutHeightForWidthTest1
1305struct 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
1422private:
1423	BRadioButton*			aspectRatioButton;
1424	BRadioButton*			sumButton;
1425	BRadioButton*			productButton;
1426	HeightForWidthTestView*	heightForWidthView;
1427};
1428
1429
1430// LabelTest1
1431struct 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
1539private:
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
1551class TestWindow : public BWindow {
1552public:
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
1603private:
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
1655private:
1656	BListView*		fTestList;
1657	BCardLayout*	fTestCardLayout;
1658};
1659
1660
1661int
1662main()
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