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