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