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