1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkView.h" 9 #include "SkCanvas.h" 10 #include "SkDOM.h" 11 12 static inline uint32_t SkSetClearShift(uint32_t bits, bool cond, unsigned shift) { 13 SkASSERT((int)cond == 0 || (int)cond == 1); 14 return (bits & ~(1 << shift)) | ((int)cond << shift); 15 } 16 17 //////////////////////////////////////////////////////////////////////// 18 19 SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags)) { 20 fWidth = fHeight = 0; 21 fLoc.set(0, 0); 22 fParent = fFirstChild = fNextSibling = fPrevSibling = nullptr; 23 fMatrix.setIdentity(); 24 fContainsFocus = 0; 25 } 26 27 SkView::~SkView() { 28 this->detachAllChildren(); 29 } 30 31 void SkView::setFlags(uint32_t flags) { 32 SkASSERT((flags & ~kAllFlagMasks) == 0); 33 34 uint32_t diff = fFlags ^ flags; 35 36 if (diff & kVisible_Mask) 37 this->inval(nullptr); 38 39 fFlags = SkToU8(flags); 40 41 if (diff & kVisible_Mask) { 42 this->inval(nullptr); 43 } 44 } 45 46 void SkView::setVisibleP(bool pred) { 47 this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift)); 48 } 49 50 void SkView::setEnabledP(bool pred) { 51 this->setFlags(SkSetClearShift(fFlags, pred, kEnabled_Shift)); 52 } 53 54 void SkView::setFocusableP(bool pred) { 55 this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift)); 56 } 57 58 void SkView::setClipToBounds(bool pred) { 59 this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift)); 60 } 61 62 void SkView::setSize(SkScalar width, SkScalar height) { 63 width = SkMaxScalar(0, width); 64 height = SkMaxScalar(0, height); 65 66 if (fWidth != width || fHeight != height) 67 { 68 this->inval(nullptr); 69 fWidth = width; 70 fHeight = height; 71 this->inval(nullptr); 72 this->onSizeChange(); 73 this->invokeLayout(); 74 } 75 } 76 77 void SkView::setLoc(SkScalar x, SkScalar y) { 78 if (fLoc.fX != x || fLoc.fY != y) { 79 this->inval(nullptr); 80 fLoc.set(x, y); 81 this->inval(nullptr); 82 } 83 } 84 85 void SkView::offset(SkScalar dx, SkScalar dy) { 86 if (dx || dy) 87 this->setLoc(fLoc.fX + dx, fLoc.fY + dy); 88 } 89 90 void SkView::setLocalMatrix(const SkMatrix& matrix) { 91 this->inval(nullptr); 92 fMatrix = matrix; 93 this->inval(nullptr); 94 } 95 96 void SkView::draw(SkCanvas* canvas) { 97 if (fWidth && fHeight && this->isVisible()) { 98 SkRect r; 99 r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight); 100 if (this->isClipToBounds() && canvas->quickReject(r)) { 101 return; 102 } 103 104 SkAutoCanvasRestore as(canvas, true); 105 106 if (this->isClipToBounds()) { 107 canvas->clipRect(r); 108 } 109 110 canvas->translate(fLoc.fX, fLoc.fY); 111 canvas->concat(fMatrix); 112 113 if (fParent) { 114 fParent->beforeChild(this, canvas); 115 } 116 117 int sc = canvas->save(); 118 this->onDraw(canvas); 119 canvas->restoreToCount(sc); 120 121 if (fParent) { 122 fParent->afterChild(this, canvas); 123 } 124 125 B2FIter iter(this); 126 SkView* child; 127 128 SkCanvas* childCanvas = this->beforeChildren(canvas); 129 130 while ((child = iter.next()) != nullptr) 131 child->draw(childCanvas); 132 133 this->afterChildren(canvas); 134 } 135 } 136 137 void SkView::inval(SkRect* rect) { 138 SkView* view = this; 139 SkRect storage; 140 141 for (;;) { 142 if (!view->isVisible()) { 143 return; 144 } 145 if (view->isClipToBounds()) { 146 SkRect bounds; 147 view->getLocalBounds(&bounds); 148 if (rect && !bounds.intersect(*rect)) { 149 return; 150 } 151 storage = bounds; 152 rect = &storage; 153 } 154 if (view->handleInval(rect)) { 155 return; 156 } 157 158 SkView* parent = view->fParent; 159 if (parent == nullptr) { 160 return; 161 } 162 163 if (rect) { 164 rect->offset(view->fLoc.fX, view->fLoc.fY); 165 } 166 view = parent; 167 } 168 } 169 170 //////////////////////////////////////////////////////////////////////////// 171 172 bool SkView::setFocusView(SkView* fv) { 173 SkView* view = this; 174 175 do { 176 if (view->onSetFocusView(fv)) { 177 return true; 178 } 179 } while ((view = view->fParent) != nullptr); 180 return false; 181 } 182 183 SkView* SkView::getFocusView() const { 184 SkView* focus = nullptr; 185 const SkView* view = this; 186 do { 187 if (view->onGetFocusView(&focus)) { 188 break; 189 } 190 } while ((view = view->fParent) != nullptr); 191 return focus; 192 } 193 194 bool SkView::hasFocus() const { 195 return this == this->getFocusView(); 196 } 197 198 bool SkView::acceptFocus() { 199 return this->isFocusable() && this->setFocusView(this); 200 } 201 202 /* 203 Try to give focus to this view, or its children 204 */ 205 SkView* SkView::acceptFocus(FocusDirection dir) { 206 if (dir == kNext_FocusDirection) { 207 if (this->acceptFocus()) { 208 return this; 209 } 210 B2FIter iter(this); 211 SkView* child, *focus; 212 while ((child = iter.next()) != nullptr) { 213 if ((focus = child->acceptFocus(dir)) != nullptr) { 214 return focus; 215 } 216 } 217 } else { // prev 218 F2BIter iter(this); 219 SkView* child, *focus; 220 while ((child = iter.next()) != nullptr) { 221 if ((focus = child->acceptFocus(dir)) != nullptr) { 222 return focus; 223 } 224 } 225 if (this->acceptFocus()) { 226 return this; 227 } 228 } 229 return nullptr; 230 } 231 232 SkView* SkView::moveFocus(FocusDirection dir) { 233 SkView* focus = this->getFocusView(); 234 235 if (focus == nullptr) { // start with the root 236 focus = this; 237 while (focus->fParent) { 238 focus = focus->fParent; 239 } 240 } 241 242 SkView* child, *parent; 243 244 if (dir == kNext_FocusDirection) { 245 parent = focus; 246 child = focus->fFirstChild; 247 if (child) 248 goto FIRST_CHILD; 249 else 250 goto NEXT_SIB; 251 252 do { 253 while (child != parent->fFirstChild) { 254 FIRST_CHILD: 255 if ((focus = child->acceptFocus(dir)) != nullptr) 256 return focus; 257 child = child->fNextSibling; 258 } 259 NEXT_SIB: 260 child = parent->fNextSibling; 261 parent = parent->fParent; 262 } while (parent != nullptr); 263 } else { // prevfocus 264 parent = focus->fParent; 265 if (parent == nullptr) { // we're the root 266 return focus->acceptFocus(dir); 267 } else { 268 child = focus; 269 while (parent) { 270 while (child != parent->fFirstChild) { 271 child = child->fPrevSibling; 272 if ((focus = child->acceptFocus(dir)) != nullptr) { 273 return focus; 274 } 275 } 276 if (parent->acceptFocus()) { 277 return parent; 278 } 279 child = parent; 280 parent = parent->fParent; 281 } 282 } 283 } 284 return nullptr; 285 } 286 287 void SkView::onFocusChange(bool gainFocusP) { 288 this->inval(nullptr); 289 } 290 291 //////////////////////////////////////////////////////////////////////////// 292 293 SkView::Click::Click(SkView* target) { 294 SkASSERT(target); 295 fTargetID = target->getSinkID(); 296 fType = nullptr; 297 fWeOwnTheType = false; 298 fOwner = nullptr; 299 } 300 301 SkView::Click::~Click() { 302 this->resetType(); 303 } 304 305 void SkView::Click::resetType() { 306 if (fWeOwnTheType) { 307 sk_free(fType); 308 fWeOwnTheType = false; 309 } 310 fType = nullptr; 311 } 312 313 bool SkView::Click::isType(const char type[]) const { 314 const char* t = fType; 315 316 if (type == t) { 317 return true; 318 } 319 if (type == nullptr) { 320 type = ""; 321 } 322 if (t == nullptr) { 323 t = ""; 324 } 325 return !strcmp(t, type); 326 } 327 328 void SkView::Click::setType(const char type[]) { 329 this->resetType(); 330 fType = (char*)type; 331 } 332 333 void SkView::Click::copyType(const char type[]) { 334 if (fType != type) { 335 this->resetType(); 336 if (type) { 337 size_t len = strlen(type) + 1; 338 fType = (char*)sk_malloc_throw(len); 339 memcpy(fType, type, len); 340 fWeOwnTheType = true; 341 } 342 } 343 } 344 345 SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y, unsigned modi) { 346 if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) { 347 return nullptr; 348 } 349 350 if (this->onSendClickToChildren(x, y, modi)) { 351 F2BIter iter(this); 352 SkView* child; 353 354 while ((child = iter.next()) != nullptr) { 355 SkPoint p; 356 #if 0 357 if (!child->globalToLocal(x, y, &p)) { 358 continue; 359 } 360 #else 361 // the above seems broken, so just respecting fLoc for now <reed> 362 p.set(x - child->fLoc.x(), y - child->fLoc.y()); 363 #endif 364 365 Click* click = child->findClickHandler(p.fX, p.fY, modi); 366 367 if (click) { 368 return click; 369 } 370 } 371 } 372 373 return this->onFindClickHandler(x, y, modi); 374 } 375 376 void SkView::DoClickDown(Click* click, int x, int y, unsigned modi) { 377 SkASSERT(click); 378 379 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID); 380 if (nullptr == target) { 381 return; 382 } 383 384 click->fIOrig.set(x, y); 385 click->fICurr = click->fIPrev = click->fIOrig; 386 387 click->fOrig.iset(x, y); 388 if (!target->globalToLocal(&click->fOrig)) { 389 // no history to let us recover from this failure 390 return; 391 } 392 click->fPrev = click->fCurr = click->fOrig; 393 394 click->fState = Click::kDown_State; 395 click->fModifierKeys = modi; 396 target->onClick(click); 397 } 398 399 void SkView::DoClickMoved(Click* click, int x, int y, unsigned modi) { 400 SkASSERT(click); 401 402 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID); 403 if (nullptr == target) { 404 return; 405 } 406 407 click->fIPrev = click->fICurr; 408 click->fICurr.set(x, y); 409 410 click->fPrev = click->fCurr; 411 click->fCurr.iset(x, y); 412 if (!target->globalToLocal(&click->fCurr)) { 413 // on failure pretend the mouse didn't move 414 click->fCurr = click->fPrev; 415 } 416 417 click->fState = Click::kMoved_State; 418 click->fModifierKeys = modi; 419 target->onClick(click); 420 } 421 422 void SkView::DoClickUp(Click* click, int x, int y, unsigned modi) { 423 SkASSERT(click); 424 425 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID); 426 if (nullptr == target) { 427 return; 428 } 429 430 click->fIPrev = click->fICurr; 431 click->fICurr.set(x, y); 432 433 click->fPrev = click->fCurr; 434 click->fCurr.iset(x, y); 435 if (!target->globalToLocal(&click->fCurr)) { 436 // on failure pretend the mouse didn't move 437 click->fCurr = click->fPrev; 438 } 439 440 click->fState = Click::kUp_State; 441 click->fModifierKeys = modi; 442 target->onClick(click); 443 } 444 445 ////////////////////////////////////////////////////////////////////// 446 447 void SkView::invokeLayout() { 448 SkView::Layout* layout = this->getLayout(); 449 450 if (layout) { 451 layout->layoutChildren(this); 452 } 453 } 454 455 void SkView::onDraw(SkCanvas* canvas) { 456 Artist* artist = this->getArtist(); 457 458 if (artist) { 459 artist->draw(this, canvas); 460 } 461 } 462 463 void SkView::onSizeChange() {} 464 465 bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) { 466 return true; 467 } 468 469 SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) { 470 return nullptr; 471 } 472 473 bool SkView::onClick(Click*) { 474 return false; 475 } 476 477 bool SkView::handleInval(const SkRect*) { 478 return false; 479 } 480 481 ////////////////////////////////////////////////////////////////////// 482 483 void SkView::getLocalBounds(SkRect* bounds) const { 484 if (bounds) { 485 bounds->set(0, 0, fWidth, fHeight); 486 } 487 } 488 489 ////////////////////////////////////////////////////////////////////// 490 ////////////////////////////////////////////////////////////////////// 491 492 void SkView::detachFromParent_NoLayout() { 493 this->validate(); 494 if (fParent == nullptr) { 495 return; 496 } 497 498 if (fContainsFocus) { 499 (void)this->setFocusView(nullptr); 500 } 501 502 this->inval(nullptr); 503 504 SkView* next = nullptr; 505 506 if (fNextSibling != this) { // do we have any siblings 507 fNextSibling->fPrevSibling = fPrevSibling; 508 fPrevSibling->fNextSibling = fNextSibling; 509 next = fNextSibling; 510 } 511 512 if (fParent->fFirstChild == this) { 513 fParent->fFirstChild = next; 514 } 515 516 fParent = fNextSibling = fPrevSibling = nullptr; 517 518 this->validate(); 519 this->unref(); 520 } 521 522 void SkView::detachFromParent() { 523 this->validate(); 524 SkView* parent = fParent; 525 526 if (parent) { 527 this->detachFromParent_NoLayout(); 528 parent->invokeLayout(); 529 } 530 } 531 532 SkView* SkView::attachChildToBack(SkView* child) { 533 this->validate(); 534 SkASSERT(child != this); 535 536 if (child == nullptr || fFirstChild == child) 537 goto DONE; 538 539 child->ref(); 540 child->detachFromParent_NoLayout(); 541 542 if (fFirstChild == nullptr) { 543 child->fNextSibling = child; 544 child->fPrevSibling = child; 545 } else { 546 child->fNextSibling = fFirstChild; 547 child->fPrevSibling = fFirstChild->fPrevSibling; 548 fFirstChild->fPrevSibling->fNextSibling = child; 549 fFirstChild->fPrevSibling = child; 550 } 551 552 fFirstChild = child; 553 child->fParent = this; 554 child->inval(nullptr); 555 556 this->validate(); 557 this->invokeLayout(); 558 DONE: 559 return child; 560 } 561 562 SkView* SkView::attachChildToFront(SkView* child) { 563 this->validate(); 564 SkASSERT(child != this); 565 566 if (child == nullptr || (fFirstChild && fFirstChild->fPrevSibling == child)) 567 goto DONE; 568 569 child->ref(); 570 child->detachFromParent_NoLayout(); 571 572 if (fFirstChild == nullptr) { 573 fFirstChild = child; 574 child->fNextSibling = child; 575 child->fPrevSibling = child; 576 } else { 577 child->fNextSibling = fFirstChild; 578 child->fPrevSibling = fFirstChild->fPrevSibling; 579 fFirstChild->fPrevSibling->fNextSibling = child; 580 fFirstChild->fPrevSibling = child; 581 } 582 583 child->fParent = this; 584 child->inval(nullptr); 585 586 this->validate(); 587 this->invokeLayout(); 588 DONE: 589 return child; 590 } 591 592 void SkView::detachAllChildren() { 593 this->validate(); 594 while (fFirstChild) 595 fFirstChild->detachFromParent_NoLayout(); 596 } 597 598 void SkView::localToGlobal(SkMatrix* matrix) const { 599 if (matrix) { 600 matrix->reset(); 601 const SkView* view = this; 602 while (view) 603 { 604 matrix->preConcat(view->getLocalMatrix()); 605 matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY); 606 view = view->fParent; 607 } 608 } 609 } 610 611 bool SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const { 612 if (local) { 613 SkMatrix m; 614 this->localToGlobal(&m); 615 if (!m.invert(&m)) { 616 return false; 617 } 618 SkPoint p; 619 m.mapXY(x, y, &p); 620 local->set(p.fX, p.fY); 621 } 622 623 return true; 624 } 625 626 ////////////////////////////////////////////////////////////////// 627 628 /* Even if the subclass overrides onInflate, they should always be 629 sure to call the inherited method, so that we get called. 630 */ 631 void SkView::onInflate(const SkDOM& dom, const SkDOM::Node* node) { 632 SkScalar x, y; 633 634 x = this->locX(); 635 y = this->locY(); 636 (void)dom.findScalar(node, "x", &x); 637 (void)dom.findScalar(node, "y", &y); 638 this->setLoc(x, y); 639 640 x = this->width(); 641 y = this->height(); 642 (void)dom.findScalar(node, "width", &x); 643 (void)dom.findScalar(node, "height", &y); 644 this->setSize(x, y); 645 646 // inflate the flags 647 648 static const char* gFlagNames[] = { 649 "visible", "enabled", "focusable", "flexH", "flexV" 650 }; 651 SkASSERT(SK_ARRAY_COUNT(gFlagNames) == kFlagShiftCount); 652 653 bool b; 654 uint32_t flags = this->getFlags(); 655 for (unsigned i = 0; i < SK_ARRAY_COUNT(gFlagNames); i++) { 656 if (dom.findBool(node, gFlagNames[i], &b)) { 657 flags = SkSetClearShift(flags, b, i); 658 } 659 } 660 this->setFlags(flags); 661 } 662 663 void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node) { 664 this->onInflate(dom, node); 665 } 666 667 ////////////////////////////////////////////////////////////////// 668 669 SkView* SkView::sendEventToParents(const SkEvent& evt) { 670 SkView* parent = fParent; 671 672 while (parent) { 673 if (parent->doEvent(evt)) { 674 return parent; 675 } 676 parent = parent->fParent; 677 } 678 return nullptr; 679 } 680 681 SkView* SkView::sendQueryToParents(SkEvent* evt) { 682 SkView* parent = fParent; 683 684 while (parent) { 685 if (parent->doQuery(evt)) { 686 return parent; 687 } 688 parent = parent->fParent; 689 } 690 return nullptr; 691 } 692 693 ////////////////////////////////////////////////////////////////// 694 ////////////////////////////////////////////////////////////////// 695 696 SkView::F2BIter::F2BIter(const SkView* parent) { 697 fFirstChild = parent ? parent->fFirstChild : nullptr; 698 fChild = fFirstChild ? fFirstChild->fPrevSibling : nullptr; 699 } 700 701 SkView* SkView::F2BIter::next() { 702 SkView* curr = fChild; 703 704 if (fChild) { 705 if (fChild == fFirstChild) { 706 fChild = nullptr; 707 } else { 708 fChild = fChild->fPrevSibling; 709 } 710 } 711 return curr; 712 } 713 714 SkView::B2FIter::B2FIter(const SkView* parent) { 715 fFirstChild = parent ? parent->fFirstChild : nullptr; 716 fChild = fFirstChild; 717 } 718 719 SkView* SkView::B2FIter::next() { 720 SkView* curr = fChild; 721 722 if (fChild) { 723 SkView* next = fChild->fNextSibling; 724 if (next == fFirstChild) 725 next = nullptr; 726 fChild = next; 727 } 728 return curr; 729 } 730 731 ////////////////////////////////////////////////////////////////// 732 ////////////////////////////////////////////////////////////////// 733 734 #ifdef SK_DEBUG 735 736 void SkView::validate() const { 737 // SkASSERT(this->getRefCnt() > 0 && this->getRefCnt() < 100); 738 if (fParent) { 739 SkASSERT(fNextSibling); 740 SkASSERT(fPrevSibling); 741 } else { 742 bool nextNull = nullptr == fNextSibling; 743 bool prevNull = nullptr == fNextSibling; 744 SkASSERT(nextNull == prevNull); 745 } 746 } 747 748 static inline void show_if_nonzero(const char name[], SkScalar value) { 749 if (value) { 750 SkDebugf("%s=\"%g\"", name, value/65536.); 751 } 752 } 753 754 static void tab(int level) { 755 for (int i = 0; i < level; i++) { 756 SkDebugf(" "); 757 } 758 } 759 760 static void dumpview(const SkView* view, int level, bool recurse) { 761 tab(level); 762 763 SkDebugf("<view"); 764 show_if_nonzero(" x", view->locX()); 765 show_if_nonzero(" y", view->locY()); 766 show_if_nonzero(" width", view->width()); 767 show_if_nonzero(" height", view->height()); 768 769 if (recurse) { 770 SkView::B2FIter iter(view); 771 SkView* child; 772 bool noChildren = true; 773 774 while ((child = iter.next()) != nullptr) { 775 if (noChildren) { 776 SkDebugf(">\n"); 777 } 778 noChildren = false; 779 dumpview(child, level + 1, true); 780 } 781 782 if (!noChildren) { 783 tab(level); 784 SkDebugf("</view>\n"); 785 } else { 786 goto ONELINER; 787 } 788 } else { 789 ONELINER: 790 SkDebugf(" />\n"); 791 } 792 } 793 794 void SkView::dump(bool recurse) const { 795 dumpview(this, 0, recurse); 796 } 797 798 #endif 799