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