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