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