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