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