1 /* 2 * Copyright 2014 Stephan Aßmus <superstippi@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT license. 4 */ 5 6 7 #include <stdio.h> 8 #include <string.h> 9 10 #include <Application.h> 11 #include <Message.h> 12 #include <Picture.h> 13 #include <LayoutBuilder.h> 14 #include <List.h> 15 #include <PopUpMenu.h> 16 #include <ScrollView.h> 17 #include <String.h> 18 #include <StringView.h> 19 #include <View.h> 20 #include <Window.h> 21 22 23 static const char* kAppSignature = "application/x.vnd-Haiku.ClipToPicture"; 24 25 26 class TestRenderer { 27 public: 28 virtual void Draw(BView* view, BRect updateRect) = 0; 29 }; 30 31 32 class Test { 33 public: 34 Test(const char* name, 35 TestRenderer* clippingTest, 36 TestRenderer* validateTest); 37 ~Test(); 38 39 const char* Name() const 40 { return fName.String(); } 41 42 TestRenderer* ClippingTest() const 43 { return fClippingTest; } 44 TestRenderer* ValidateTest() const 45 { return fValidateTest; } 46 47 private: 48 BString fName; 49 TestRenderer* fClippingTest; 50 TestRenderer* fValidateTest; 51 }; 52 53 54 Test::Test(const char* name, TestRenderer* clippingTest, 55 TestRenderer* validateTest) 56 : 57 fName(name), 58 fClippingTest(clippingTest), 59 fValidateTest(validateTest) 60 { 61 } 62 63 64 Test::~Test() 65 { 66 delete fClippingTest; 67 delete fValidateTest; 68 } 69 70 71 // #pragma mark - TestView 72 73 74 class TestView : public BView { 75 public: 76 TestView(); 77 virtual ~TestView(); 78 79 virtual void Draw(BRect updateRect); 80 81 void SetTestRenderer(TestRenderer* renderer); 82 83 private: 84 TestRenderer* fTestRenderer; 85 }; 86 87 88 TestView::TestView() 89 : 90 BView(NULL, B_WILL_DRAW), 91 fTestRenderer(NULL) 92 { 93 } 94 95 96 TestView::~TestView() 97 { 98 } 99 100 101 void 102 TestView::Draw(BRect updateRect) 103 { 104 if (fTestRenderer != NULL) 105 fTestRenderer->Draw(this, updateRect); 106 } 107 108 109 void 110 TestView::SetTestRenderer(TestRenderer* renderer) 111 { 112 fTestRenderer = renderer; 113 Invalidate(); 114 } 115 116 117 // #pragma mark - TestWindow 118 119 120 enum { 121 MSG_SELECT_TEST = 'stst' 122 }; 123 124 125 class TestWindow : public BWindow { 126 public: 127 TestWindow(); 128 virtual ~TestWindow(); 129 130 virtual void MessageReceived(BMessage* message); 131 132 void AddTest(Test* test); 133 void SetToTest(int32 index); 134 135 private: 136 TestView* fClippingTestView; 137 TestView* fValidateTestView; 138 139 BMenuField* fTestSelectionField; 140 141 BList fTests; 142 }; 143 144 145 TestWindow::TestWindow() 146 : 147 BWindow(BRect(50.0, 50.0, 450.0, 250.0), "ClipToPicture Test", 148 B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE 149 | B_AUTO_UPDATE_SIZE_LIMITS) 150 { 151 fClippingTestView = new TestView(); 152 fValidateTestView = new TestView(); 153 154 BGroupView* group = new BGroupView(B_HORIZONTAL); 155 BLayoutBuilder::Group<>(group, B_HORIZONTAL, 0.0f) 156 .Add(fClippingTestView) 157 .Add(fValidateTestView) 158 ; 159 160 BScrollView* scrollView = new BScrollView("scroll", group, 0, true, true); 161 162 BStringView* leftLabel = new BStringView("left label", 163 "ClipToPicture:"); 164 leftLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 165 166 BStringView* rightLabel = new BStringView("right label", 167 "Validation:"); 168 rightLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 169 170 fTestSelectionField = new BMenuField("test selection", 171 "Select test:", new BPopUpMenu("select")); 172 173 BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f) 174 .AddGroup(B_HORIZONTAL) 175 .Add(fTestSelectionField) 176 .AddGlue() 177 .SetInsets(B_USE_DEFAULT_SPACING) 178 .End() 179 .AddGroup(B_HORIZONTAL) 180 .Add(leftLabel) 181 .Add(rightLabel) 182 .SetInsets(B_USE_DEFAULT_SPACING) 183 .End() 184 .Add(scrollView) 185 ; 186 } 187 188 189 TestWindow::~TestWindow() 190 { 191 for (int32 i = fTests.CountItems() - 1; i >= 0; i++) 192 delete (Test*)fTests.ItemAt(i); 193 } 194 195 196 void 197 TestWindow::MessageReceived(BMessage* message) 198 { 199 switch (message->what) { 200 case MSG_SELECT_TEST: 201 { 202 int32 index; 203 if (message->FindInt32("index", &index) == B_OK) 204 SetToTest(index); 205 break; 206 } 207 208 default: 209 BWindow::MessageReceived(message); 210 } 211 } 212 213 214 void 215 TestWindow::AddTest(Test* test) 216 { 217 if (test == NULL || fTests.HasItem(test)) 218 return; 219 220 if (!fTests.AddItem(test)) { 221 delete test; 222 return; 223 } 224 225 BMessage* message = new BMessage(MSG_SELECT_TEST); 226 message->AddInt32("index", fTests.CountItems() - 1); 227 228 BMenuItem* item = new BMenuItem(test->Name(), message); 229 if (!fTestSelectionField->Menu()->AddItem(item)) { 230 fTests.RemoveItem(fTests.CountItems() - 1); 231 delete test; 232 delete item; 233 return; 234 } 235 236 if (fTests.CountItems() == 1) 237 SetToTest(0); 238 } 239 240 241 void 242 TestWindow::SetToTest(int32 index) 243 { 244 Test* test = (Test*)fTests.ItemAt(index); 245 if (test == NULL) 246 return; 247 248 fTestSelectionField->Menu()->ItemAt(index)->SetMarked(true); 249 250 fClippingTestView->SetTestRenderer(test->ClippingTest()); 251 fValidateTestView->SetTestRenderer(test->ValidateTest()); 252 } 253 254 255 // #pragma mark - Test1 256 257 258 class Test1Clipping : public TestRenderer { 259 virtual void Draw(BView* view, BRect updateRect) 260 { 261 BPicture picture; 262 view->BeginPicture(&picture); 263 view->SetDrawingMode(B_OP_ALPHA); 264 view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); 265 view->DrawString("Clipping to text.", BPoint(20, 30)); 266 view->EndPicture(); 267 268 view->ClipToPicture(&picture); 269 270 view->FillRect(view->Bounds()); 271 } 272 }; 273 274 275 class Test1Validate : public TestRenderer { 276 virtual void Draw(BView* view, BRect updateRect) 277 { 278 view->DrawString("Clipping to text.", BPoint(20, 30)); 279 } 280 }; 281 282 283 // #pragma mark - Test2 284 285 286 class Test2Clipping : public TestRenderer { 287 virtual void Draw(BView* view, BRect updateRect) 288 { 289 view->PushState(); 290 291 BPicture picture; 292 view->BeginPicture(&picture); 293 view->SetDrawingMode(B_OP_ALPHA); 294 view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); 295 view->SetScale(2.0); 296 view->DrawString("Scaled clipping", BPoint(10, 15)); 297 view->DrawString("to text.", BPoint(10, 25)); 298 view->EndPicture(); 299 300 view->PopState(); 301 302 view->ClipToPicture(&picture); 303 304 view->FillRect(view->Bounds()); 305 } 306 }; 307 308 309 class Test2Validate : public TestRenderer { 310 virtual void Draw(BView* view, BRect updateRect) 311 { 312 view->SetScale(2.0); 313 view->DrawString("Scaled clipping", BPoint(10, 15)); 314 view->DrawString("to text.", BPoint(10, 25)); 315 } 316 }; 317 318 319 // #pragma mark - Test2 320 321 322 class Test3Clipping : public TestRenderer { 323 virtual void Draw(BView* view, BRect updateRect) 324 { 325 BPicture picture; 326 view->BeginPicture(&picture); 327 view->SetDrawingMode(B_OP_ALPHA); 328 view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); 329 view->DrawString("Scaled picture", BPoint(10, 15)); 330 view->EndPicture(); 331 332 view->SetScale(2.0); 333 view->ClipToPicture(&picture); 334 335 view->SetScale(1.0); 336 view->FillRect(view->Bounds()); 337 } 338 }; 339 340 341 class Test3Validate : public TestRenderer { 342 virtual void Draw(BView* view, BRect updateRect) 343 { 344 view->SetScale(2.0); 345 view->DrawString("Scaled picture", BPoint(10, 15)); 346 } 347 }; 348 349 350 // #pragma mark - Test2 351 352 353 class Test4Clipping : public TestRenderer { 354 virtual void Draw(BView* view, BRect updateRect) 355 { 356 view->SetDrawingMode(B_OP_ALPHA); 357 view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); 358 359 BPicture rect; 360 view->BeginPicture(&rect); 361 view->FillRect(BRect(20, 20, 50, 50)); 362 view->EndPicture(); 363 364 view->ClipToPicture(&rect); 365 366 view->PushState(); 367 BPicture circle; 368 view->BeginPicture(&circle); 369 view->FillEllipse(BRect(20, 20, 50, 50)); 370 view->EndPicture(); 371 372 view->ClipToInversePicture(&circle); 373 374 view->FillRect(view->Bounds()); 375 376 view->PopState(); 377 } 378 }; 379 380 381 class Test4Validate : public TestRenderer { 382 virtual void Draw(BView* view, BRect updateRect) 383 { 384 view->FillRect(BRect(20, 20, 50, 50)); 385 view->FillEllipse(BRect(20, 20, 50, 50), B_SOLID_LOW); 386 } 387 }; 388 389 390 // #pragma mark - 391 392 393 int 394 main(int argc, char** argv) 395 { 396 BApplication app(kAppSignature); 397 398 TestWindow* window = new TestWindow(); 399 400 window->AddTest(new Test("Simple clipping", 401 new Test1Clipping(), new Test1Validate())); 402 403 window->AddTest(new Test("Scaled clipping 1", 404 new Test2Clipping(), new Test2Validate())); 405 406 window->AddTest(new Test("Scaled clipping 2", 407 new Test3Clipping(), new Test3Validate())); 408 409 window->AddTest(new Test("Nested states", 410 new Test4Clipping(), new Test4Validate())); 411 412 window->SetToTest(3); 413 window->Show(); 414 415 app.Run(); 416 return 0; 417 } 418