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