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