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