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