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