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 SK_DEFINE_INST_COUNT(SkView::Artist) 12 SK_DEFINE_INST_COUNT(SkView::Layout) 13 14 //////////////////////////////////////////////////////////////////////// 15 16 SkView::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 25 SkView::~SkView() 26 { 27 this->detachAllChildren(); 28 } 29 30 void 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 47 void SkView::setVisibleP(bool pred) 48 { 49 this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift)); 50 } 51 52 void SkView::setEnabledP(bool pred) 53 { 54 this->setFlags(SkSetClearShift(fFlags, pred, kEnabled_Shift)); 55 } 56 57 void SkView::setFocusableP(bool pred) 58 { 59 this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift)); 60 } 61 62 void SkView::setClipToBounds(bool pred) { 63 this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift)); 64 } 65 66 void 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 82 void 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 92 void SkView::offset(SkScalar dx, SkScalar dy) 93 { 94 if (dx || dy) 95 this->setLoc(fLoc.fX + dx, fLoc.fY + dy); 96 } 97 98 void SkView::setLocalMatrix(const SkMatrix& matrix) 99 { 100 this->inval(NULL); 101 fMatrix = matrix; 102 this->inval(NULL); 103 } 104 105 void 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 149 void 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 184 bool 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 195 SkView* 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 206 bool SkView::hasFocus() const 207 { 208 return this == this->getFocusView(); 209 } 210 211 bool 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 */ 219 SkView* 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 247 SkView* 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 309 void SkView::onFocusChange(bool gainFocusP) 310 { 311 this->inval(NULL); 312 } 313 314 //////////////////////////////////////////////////////////////////////////// 315 316 SkView::Click::Click(SkView* target) 317 { 318 SkASSERT(target); 319 fTargetID = target->getSinkID(); 320 fType = NULL; 321 fWeOwnTheType = false; 322 fOwner = NULL; 323 } 324 325 SkView::Click::~Click() 326 { 327 this->resetType(); 328 } 329 330 void SkView::Click::resetType() 331 { 332 if (fWeOwnTheType) 333 { 334 sk_free(fType); 335 fWeOwnTheType = false; 336 } 337 fType = NULL; 338 } 339 340 bool 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 354 void SkView::Click::setType(const char type[]) 355 { 356 this->resetType(); 357 fType = (char*)type; 358 } 359 360 void 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 375 SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y, unsigned modi) { 376 if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) { 377 return NULL; 378 } 379 380 if (this->onSendClickToChildren(x, y, modi)) { 381 F2BIter iter(this); 382 SkView* child; 383 384 while ((child = iter.next()) != NULL) 385 { 386 SkPoint p; 387 if (!child->globalToLocal(x, y, &p)) { 388 continue; 389 } 390 391 Click* click = child->findClickHandler(p.fX, p.fY, modi); 392 393 if (click) { 394 return click; 395 } 396 } 397 } 398 399 return this->onFindClickHandler(x, y, modi); 400 } 401 402 void SkView::DoClickDown(Click* click, int x, int y, unsigned modi) 403 { 404 SkASSERT(click); 405 406 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID); 407 if (NULL == target) { 408 return; 409 } 410 411 click->fIOrig.set(x, y); 412 click->fICurr = click->fIPrev = click->fIOrig; 413 414 click->fOrig.iset(x, y); 415 if (!target->globalToLocal(&click->fOrig)) { 416 // no history to let us recover from this failure 417 return; 418 } 419 click->fPrev = click->fCurr = click->fOrig; 420 421 click->fState = Click::kDown_State; 422 click->fModifierKeys = modi; 423 target->onClick(click); 424 } 425 426 void SkView::DoClickMoved(Click* click, int x, int y, unsigned modi) 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 click->fModifierKeys = modi; 447 target->onClick(click); 448 } 449 450 void SkView::DoClickUp(Click* click, int x, int y, unsigned modi) 451 { 452 SkASSERT(click); 453 454 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID); 455 if (NULL == target) { 456 return; 457 } 458 459 click->fIPrev = click->fICurr; 460 click->fICurr.set(x, y); 461 462 click->fPrev = click->fCurr; 463 click->fCurr.iset(x, y); 464 if (!target->globalToLocal(&click->fCurr)) { 465 // on failure pretend the mouse didn't move 466 click->fCurr = click->fPrev; 467 } 468 469 click->fState = Click::kUp_State; 470 click->fModifierKeys = modi; 471 target->onClick(click); 472 } 473 474 ////////////////////////////////////////////////////////////////////// 475 476 void SkView::invokeLayout() { 477 SkView::Layout* layout = this->getLayout(); 478 479 if (layout) { 480 layout->layoutChildren(this); 481 } 482 } 483 484 void SkView::onDraw(SkCanvas* canvas) { 485 Artist* artist = this->getArtist(); 486 487 if (artist) { 488 artist->draw(this, canvas); 489 } 490 } 491 492 void SkView::onSizeChange() {} 493 494 bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) { 495 return true; 496 } 497 498 SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) { 499 return NULL; 500 } 501 502 bool SkView::onClick(Click*) { 503 return false; 504 } 505 506 bool SkView::handleInval(const SkRect*) { 507 return false; 508 } 509 510 ////////////////////////////////////////////////////////////////////// 511 512 void SkView::getLocalBounds(SkRect* bounds) const 513 { 514 if (bounds) 515 bounds->set(0, 0, fWidth, fHeight); 516 } 517 518 ////////////////////////////////////////////////////////////////////// 519 ////////////////////////////////////////////////////////////////////// 520 521 void SkView::detachFromParent_NoLayout() 522 { 523 if (fParent == NULL) 524 return; 525 526 if (fContainsFocus) 527 (void)this->setFocusView(NULL); 528 529 this->inval(NULL); 530 531 SkView* next = NULL; 532 533 if (fNextSibling != this) // do we have any siblings 534 { 535 fNextSibling->fPrevSibling = fPrevSibling; 536 fPrevSibling->fNextSibling = fNextSibling; 537 next = fNextSibling; 538 } 539 540 if (fParent->fFirstChild == this) 541 fParent->fFirstChild = next; 542 543 fParent = fNextSibling = fPrevSibling = NULL; 544 545 this->unref(); 546 } 547 548 void SkView::detachFromParent() 549 { 550 SkView* parent = fParent; 551 552 if (parent) 553 { 554 this->detachFromParent_NoLayout(); 555 parent->invokeLayout(); 556 } 557 } 558 559 SkView* SkView::attachChildToBack(SkView* child) 560 { 561 SkASSERT(child != this); 562 563 if (child == NULL || fFirstChild == child) 564 goto DONE; 565 566 child->ref(); 567 child->detachFromParent_NoLayout(); 568 569 if (fFirstChild == NULL) 570 { 571 child->fNextSibling = child; 572 child->fPrevSibling = child; 573 } 574 else 575 { 576 child->fNextSibling = fFirstChild; 577 child->fPrevSibling = fFirstChild->fPrevSibling; 578 fFirstChild->fPrevSibling->fNextSibling = child; 579 fFirstChild->fPrevSibling = child; 580 } 581 582 fFirstChild = child; 583 child->fParent = this; 584 child->inval(NULL); 585 586 this->invokeLayout(); 587 DONE: 588 return child; 589 } 590 591 SkView* SkView::attachChildToFront(SkView* child) 592 { 593 SkASSERT(child != this); 594 595 if (child == NULL || (fFirstChild && fFirstChild->fPrevSibling == child)) 596 goto DONE; 597 598 child->ref(); 599 child->detachFromParent_NoLayout(); 600 601 if (fFirstChild == NULL) 602 { 603 fFirstChild = child; 604 child->fNextSibling = child; 605 child->fPrevSibling = child; 606 } 607 else 608 { 609 child->fNextSibling = fFirstChild; 610 child->fPrevSibling = fFirstChild->fPrevSibling; 611 fFirstChild->fPrevSibling->fNextSibling = child; 612 fFirstChild->fPrevSibling = child; 613 } 614 615 child->fParent = this; 616 child->inval(NULL); 617 618 this->invokeLayout(); 619 DONE: 620 return child; 621 } 622 623 void SkView::detachAllChildren() 624 { 625 while (fFirstChild) 626 fFirstChild->detachFromParent_NoLayout(); 627 } 628 629 void SkView::localToGlobal(SkMatrix* matrix) const 630 { 631 if (matrix) { 632 matrix->reset(); 633 const SkView* view = this; 634 while (view) 635 { 636 matrix->preConcat(view->getLocalMatrix()); 637 matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY); 638 view = view->fParent; 639 } 640 } 641 } 642 bool SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const 643 { 644 SkASSERT(this); 645 646 if (NULL != local) { 647 SkMatrix m; 648 this->localToGlobal(&m); 649 if (!m.invert(&m)) { 650 return false; 651 } 652 SkPoint p; 653 m.mapXY(x, y, &p); 654 local->set(p.fX, p.fY); 655 } 656 657 return true; 658 } 659 660 ////////////////////////////////////////////////////////////////// 661 662 /* Even if the subclass overrides onInflate, they should always be 663 sure to call the inherited method, so that we get called. 664 */ 665 void SkView::onInflate(const SkDOM& dom, const SkDOM::Node* node) 666 { 667 SkScalar x, y; 668 669 x = this->locX(); 670 y = this->locY(); 671 (void)dom.findScalar(node, "x", &x); 672 (void)dom.findScalar(node, "y", &y); 673 this->setLoc(x, y); 674 675 x = this->width(); 676 y = this->height(); 677 (void)dom.findScalar(node, "width", &x); 678 (void)dom.findScalar(node, "height", &y); 679 this->setSize(x, y); 680 681 // inflate the flags 682 683 static const char* gFlagNames[] = { 684 "visible", "enabled", "focusable", "flexH", "flexV" 685 }; 686 SkASSERT(SK_ARRAY_COUNT(gFlagNames) == kFlagShiftCount); 687 688 bool b; 689 uint32_t flags = this->getFlags(); 690 for (unsigned i = 0; i < SK_ARRAY_COUNT(gFlagNames); i++) 691 if (dom.findBool(node, gFlagNames[i], &b)) 692 flags = SkSetClearShift(flags, b, i); 693 this->setFlags(flags); 694 } 695 696 void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node) 697 { 698 this->onInflate(dom, node); 699 } 700 701 void SkView::onPostInflate(const SkTDict<SkView*>&) 702 { 703 // override in subclass as needed 704 } 705 706 void SkView::postInflate(const SkTDict<SkView*>& dict) 707 { 708 this->onPostInflate(dict); 709 710 B2FIter iter(this); 711 SkView* child; 712 while ((child = iter.next()) != NULL) 713 child->postInflate(dict); 714 } 715 716 ////////////////////////////////////////////////////////////////// 717 718 SkView* SkView::sendEventToParents(const SkEvent& evt) 719 { 720 SkView* parent = fParent; 721 722 while (parent) 723 { 724 if (parent->doEvent(evt)) 725 return parent; 726 parent = parent->fParent; 727 } 728 return NULL; 729 } 730 731 SkView* SkView::sendQueryToParents(SkEvent* evt) { 732 SkView* parent = fParent; 733 734 while (parent) { 735 if (parent->doQuery(evt)) { 736 return parent; 737 } 738 parent = parent->fParent; 739 } 740 return NULL; 741 } 742 743 ////////////////////////////////////////////////////////////////// 744 ////////////////////////////////////////////////////////////////// 745 746 SkView::F2BIter::F2BIter(const SkView* parent) 747 { 748 fFirstChild = parent ? parent->fFirstChild : NULL; 749 fChild = fFirstChild ? fFirstChild->fPrevSibling : NULL; 750 } 751 752 SkView* SkView::F2BIter::next() 753 { 754 SkView* curr = fChild; 755 756 if (fChild) 757 { 758 if (fChild == fFirstChild) 759 fChild = NULL; 760 else 761 fChild = fChild->fPrevSibling; 762 } 763 return curr; 764 } 765 766 SkView::B2FIter::B2FIter(const SkView* parent) 767 { 768 fFirstChild = parent ? parent->fFirstChild : NULL; 769 fChild = fFirstChild; 770 } 771 772 SkView* SkView::B2FIter::next() 773 { 774 SkView* curr = fChild; 775 776 if (fChild) 777 { 778 SkView* next = fChild->fNextSibling; 779 if (next == fFirstChild) 780 next = NULL; 781 fChild = next; 782 } 783 return curr; 784 } 785 786 ////////////////////////////////////////////////////////////////// 787 ////////////////////////////////////////////////////////////////// 788 789 #ifdef SK_DEBUG 790 791 static inline void show_if_nonzero(const char name[], SkScalar value) 792 { 793 if (value) 794 SkDebugf("%s=\"%g\"", name, value/65536.); 795 } 796 797 static void tab(int level) 798 { 799 for (int i = 0; i < level; i++) 800 SkDebugf(" "); 801 } 802 803 static void dumpview(const SkView* view, int level, bool recurse) 804 { 805 tab(level); 806 807 SkDebugf("<view"); 808 show_if_nonzero(" x", view->locX()); 809 show_if_nonzero(" y", view->locY()); 810 show_if_nonzero(" width", view->width()); 811 show_if_nonzero(" height", view->height()); 812 813 if (recurse) 814 { 815 SkView::B2FIter iter(view); 816 SkView* child; 817 bool noChildren = true; 818 819 while ((child = iter.next()) != NULL) 820 { 821 if (noChildren) 822 SkDebugf(">\n"); 823 noChildren = false; 824 dumpview(child, level + 1, true); 825 } 826 827 if (!noChildren) 828 { 829 tab(level); 830 SkDebugf("</view>\n"); 831 } 832 else 833 goto ONELINER; 834 } 835 else 836 { 837 ONELINER: 838 SkDebugf(" />\n"); 839 } 840 } 841 842 void SkView::dump(bool recurse) const 843 { 844 dumpview(this, 0, recurse); 845 } 846 847 #endif 848