xref: /haiku/src/tests/kits/interface/layout/widget_layout_test/WidgetLayoutTest.cpp (revision 2600324b57fa31cdea1627d584d314f2a579c4a8)
1 /*
2  * Copyright 2007, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include <stdio.h>
7 
8 #include <Application.h>
9 #include <Window.h>
10 
11 #include "BoxTest.h"
12 #include "ButtonTest.h"
13 #include "CheckBox.h"
14 #include "CheckBoxTest.h"
15 #include "GroupView.h"
16 #include "ListViewTest.h"
17 #include "MenuBarTest.h"
18 #include "MenuFieldTest.h"
19 #include "MenuTest.h"
20 #include "RadioButtonTest.h"
21 #include "ScrollBarTest.h"
22 #include "SliderTest.h"
23 #include "StringView.h"
24 #include "Test.h"
25 #include "TextControlTest.h"
26 #include "TextViewTest.h"
27 #include "TwoDimensionalSliderView.h"
28 #include "View.h"
29 #include "ViewContainer.h"
30 #include "WrapperView.h"
31 
32 
33 // internal messages
34 enum {
35 	MSG_2D_SLIDER_VALUE_CHANGED		= '2dsv',
36 	MSG_UNLIMITED_MAX_SIZE_CHANGED	= 'usch',
37 };
38 
39 
40 struct test_info {
41 	const char*	name;
42 	Test*		(*create)();
43 };
44 
45 const test_info kTestInfos[] = {
46 	{ "BBox",			BoxTest::CreateTest },
47 	{ "BButton",		ButtonTest::CreateTest },
48 	{ "BCheckBox",		CheckBoxTest::CreateTest },
49 	{ "BListView",		ListViewTest::CreateTest },
50 	{ "BMenu",			MenuTest::CreateTest },
51 	{ "BMenuBar",		MenuBarTest::CreateTest },
52 	{ "BMenuField",		MenuFieldTest::CreateTest },
53 	{ "BRadioButton",	RadioButtonTest::CreateTest },
54 	{ "BScrollBar",		ScrollBarTest::CreateTest },
55 	{ "BSlider",		SliderTest::CreateTest },
56 	{ "BTextControl",	TextControlTest::CreateTest },
57 	{ "BTextView",		TextViewTest::CreateTest },
58 	{ NULL, NULL }
59 };
60 
61 
62 // helpful operator
63 BPoint
64 operator+(const BPoint& p, const BSize& size)
65 {
66 	return BPoint(p.x + size.width, p.y + size.height);
67 }
68 
69 
70 // TestWindow
71 class TestWindow : public BWindow {
72 public:
73 	TestWindow(Test* test)
74 		: BWindow(BRect(50, 50, 750, 550), "Widget Layout",
75 			B_TITLED_WINDOW,
76 			B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE | B_NOT_RESIZABLE
77 			| B_NOT_ZOOMABLE),
78 		  fTest(test)
79 	{
80 		fViewContainer = new ViewContainer(Bounds());
81 		fViewContainer->View::SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
82 		AddChild(fViewContainer);
83 
84 		// container view for the tested BView
85 		BRect rect(10, 10, 400, 400);
86 		View* view = new View(rect);
87 		fViewContainer->View::AddChild(view);
88 		view->SetViewColor((rgb_color){200, 200, 240, 255});
89 
90 		// container for the test's controls
91 		fTestControlsView = new View(BRect(410, 10, 690, 400));
92 		fTestControlsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
93 		fViewContainer->View::AddChild(fTestControlsView);
94 
95 		// wrapper view
96 		fWrapperView = new WrapperView(fTest->GetView());
97 		fWrapperView->SetLocation(BPoint(10, 10));
98 		view->AddChild(fWrapperView);
99 		fWrapperView->SetSize(fWrapperView->PreferredSize());
100 
101 		// slider view
102 		fSliderView = new TwoDimensionalSliderView(
103 			new BMessage(MSG_2D_SLIDER_VALUE_CHANGED), this);
104 		fSliderView->SetLocationRange(BPoint(0, 0), BPoint(0, 0));
105 		view->AddChild(fSliderView);
106 
107 		_UpdateSliderConstraints();
108 
109 		// size views
110 		GroupView* sizeViewsGroup = new GroupView(B_VERTICAL, 6);
111 		sizeViewsGroup->SetSpacing(0, 8);
112 		fViewContainer->View::AddChild(sizeViewsGroup);
113 
114 		// min
115 		_CreateSizeViews(sizeViewsGroup, "min:  ", fMinWidthView,
116 			fMinHeightView);
117 
118 		// max (with checkbox)
119 		fUnlimitedMaxSizeCheckBox = new LabeledCheckBox("override",
120 			new BMessage(MSG_UNLIMITED_MAX_SIZE_CHANGED), this);
121 
122 		_CreateSizeViews(sizeViewsGroup, "max:  ", fMaxWidthView,
123 			fMaxHeightView, fUnlimitedMaxSizeCheckBox);
124 
125 		// preferred
126 		_CreateSizeViews(sizeViewsGroup, "preferred:  ", fPreferredWidthView,
127 			fPreferredHeightView);
128 
129 		// current
130 		_CreateSizeViews(sizeViewsGroup, "current:  ", fCurrentWidthView,
131 			fCurrentHeightView);
132 
133 		sizeViewsGroup->SetFrame(BRect(BPoint(rect.left, rect.bottom + 10),
134 			sizeViewsGroup->PreferredSize()));
135 
136 		_UpdateSizeViews();
137 
138 		// activate test
139 		AddHandler(fTest);
140 		fTest->ActivateTest(fTestControlsView);
141 	}
142 
143 	virtual void DispatchMessage(BMessage* message, BHandler* handler)
144 	{
145 		switch (message->what) {
146 			case B_LAYOUT_WINDOW:
147 				if (!fWrapperView->GetView()->IsLayoutValid()) {
148 					_UpdateSliderConstraints();
149 					_UpdateSizeViews();
150 				}
151 				break;
152 		}
153 
154 		BWindow::DispatchMessage(message, handler);
155 	}
156 
157 	virtual void MessageReceived(BMessage* message)
158 	{
159 		switch (message->what) {
160 			case MSG_2D_SLIDER_VALUE_CHANGED:
161 			{
162 				BPoint sliderLocation(fSliderView->Location());
163 				BPoint wrapperLocation(fWrapperView->Location());
164 				BSize size(sliderLocation.x - wrapperLocation.x - 1,
165 					sliderLocation.y - wrapperLocation.y - 1);
166 				fWrapperView->SetSize(size);
167 				_UpdateSizeViews();
168 				break;
169 			}
170 
171 			case MSG_UNLIMITED_MAX_SIZE_CHANGED:
172 				if (fUnlimitedMaxSizeCheckBox->IsSelected())  {
173 					fWrapperView->GetView()->SetExplicitMaxSize(
174 						BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
175 				} else {
176 					fWrapperView->GetView()->SetExplicitMaxSize(
177 						BSize(B_SIZE_UNSET, B_SIZE_UNSET));
178 				}
179 				break;
180 
181 			default:
182 				BWindow::MessageReceived(message);
183 				break;
184 		}
185 	}
186 
187 private:
188 	void _UpdateSliderConstraints()
189 	{
190 		BPoint wrapperLocation(fWrapperView->Location());
191 		BSize minWrapperSize(fWrapperView->MinSize());
192 		BSize maxWrapperSize(fWrapperView->MaxSize());
193 
194 		BPoint minSliderLocation = wrapperLocation + minWrapperSize
195 			+ BPoint(1, 1);
196 		BPoint maxSliderLocation = wrapperLocation + maxWrapperSize
197 			+ BPoint(1, 1);
198 
199 		BSize sliderSize(fSliderView->Size());
200 		BSize parentSize(fSliderView->Parent()->Size());
201 		if (maxSliderLocation.x + sliderSize.width > parentSize.width)
202 			maxSliderLocation.x = parentSize.width - sliderSize.width;
203 		if (maxSliderLocation.y + sliderSize.height > parentSize.height)
204 			maxSliderLocation.y = parentSize.height - sliderSize.height;
205 
206 		fSliderView->SetLocationRange(minSliderLocation, maxSliderLocation);
207 	}
208 
209 	void _CreateSizeViews(View* group, const char* labelText,
210 		StringView*& widthView, StringView*& heightView,
211 		View* additionalView = NULL)
212 	{
213 		// label
214 		StringView* label = new StringView(labelText);
215 		label->SetAlignment(B_ALIGN_RIGHT);
216 		group->AddChild(label);
217 
218 		// width view
219 		widthView = new StringView("9999999999.9");
220 		widthView->SetAlignment(B_ALIGN_RIGHT);
221 		group->AddChild(widthView);
222 		widthView->SetExplicitMinSize(widthView->PreferredSize());
223 
224 		// "," label
225 		StringView* labelView = new StringView(",  ");
226 		group->AddChild(labelView);
227 
228 		// height view
229 		heightView = new StringView("9999999999.9");
230 		heightView->SetAlignment(B_ALIGN_RIGHT);
231 		group->AddChild(heightView);
232 		heightView->SetExplicitMinSize(heightView->PreferredSize());
233 
234 		// spacing
235 		group->AddChild(new HStrut(20));
236 
237 		// glue or unlimited max size check box
238 		if (additionalView)
239 			group->AddChild(additionalView);
240 		else
241 			group->AddChild(new Glue());
242 	}
243 
244 	void _UpdateSizeView(StringView* view, float size)
245 	{
246 		char buffer[32];
247 		if (size < B_SIZE_UNLIMITED) {
248 			sprintf(buffer, "%.1f", size);
249 			view->SetString(buffer);
250 		} else
251 			view->SetString("unlimited");
252 	}
253 
254 	void _UpdateSizeViews(StringView* widthView, StringView* heightView,
255 		BSize size)
256 	{
257 		_UpdateSizeView(widthView, size.width);
258 		_UpdateSizeView(heightView, size.height);
259 	}
260 
261 	void _UpdateSizeViews()
262 	{
263 		_UpdateSizeViews(fMinWidthView, fMinHeightView,
264 			fWrapperView->GetView()->MinSize());
265 		_UpdateSizeViews(fMaxWidthView, fMaxHeightView,
266 			fWrapperView->GetView()->MaxSize());
267 		_UpdateSizeViews(fPreferredWidthView, fPreferredHeightView,
268 			fWrapperView->GetView()->PreferredSize());
269 		_UpdateSizeViews(fCurrentWidthView, fCurrentHeightView,
270 			fWrapperView->GetView()->Frame().Size());
271 	}
272 
273 private:
274 	Test*						fTest;
275 	ViewContainer*				fViewContainer;
276 	View*						fTestControlsView;
277 	WrapperView*				fWrapperView;
278 	TwoDimensionalSliderView*	fSliderView;
279 	StringView*					fMinWidthView;
280 	StringView*					fMinHeightView;
281 	StringView*					fMaxWidthView;
282 	StringView*					fMaxHeightView;
283 	StringView*					fPreferredWidthView;
284 	StringView*					fPreferredHeightView;
285 	StringView*					fCurrentWidthView;
286 	StringView*					fCurrentHeightView;
287 	LabeledCheckBox*			fUnlimitedMaxSizeCheckBox;
288 };
289 
290 
291 static void
292 print_test_list(bool error)
293 {
294 	FILE* out = (error ? stderr : stdout);
295 
296 	fprintf(out, "available tests:\n");
297 
298 	for (int32 i = 0; kTestInfos[i].name; i++)
299 		fprintf(out, "  %s\n", kTestInfos[i].name);
300 }
301 
302 
303 int
304 main(int argc, const char* const* argv)
305 {
306 	// get test name
307 	const char* testName;
308 	if (argc < 2) {
309 		fprintf(stderr, "Usage: %s <test name>\n", argv[0]);
310 		print_test_list(true);
311 		exit(1);
312 	}
313 	testName = argv[1];
314 
315 	// create app
316 	BApplication app("application/x-vnd.haiku.widget-layout-test");
317 
318 	// find and create the test
319 	Test* test = NULL;
320 	for (int32 i = 0; kTestInfos[i].name; i++) {
321 		if (strcmp(testName, kTestInfos[i].name) == 0) {
322 			test = (kTestInfos[i].create)();
323 			break;
324 		}
325 	}
326 
327 	if (!test) {
328 		fprintf(stderr, "Error: Invalid test name: \"%s\"\n", testName);
329 		print_test_list(true);
330 		exit(1);
331 	}
332 
333 	// show test window
334 	BWindow* window = new TestWindow(test);
335 	window->Show();
336 
337 	app.Run();
338 
339 	return 0;
340 }
341