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