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 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: 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::SetViewUIColor(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->SetViewUIColor(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 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 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: 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 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 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 255 void _UpdateSizeViews(StringView* widthView, StringView* heightView, 256 BSize size) 257 { 258 _UpdateSizeView(widthView, size.width); 259 _UpdateSizeView(heightView, size.height); 260 } 261 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 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 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