Home | History | Annotate | Download | only in views
      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, 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 
    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)
    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 
    397 void 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 
    416 void 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 
    435 void 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 
    456 void SkView::invokeLayout() {
    457 	SkView::Layout* layout = this->getLayout();
    458 
    459 	if (layout) {
    460 		layout->layoutChildren(this);
    461     }
    462 }
    463 
    464 void SkView::onDraw(SkCanvas* canvas) {
    465 	Artist* artist = this->getArtist();
    466 
    467 	if (artist) {
    468 		artist->draw(this, canvas);
    469     }
    470 }
    471 
    472 void SkView::onSizeChange() {}
    473 
    474 bool SkView::onSendClickToChildren(SkScalar x, SkScalar y) {
    475     return true;
    476 }
    477 
    478 SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y) {
    479 	return NULL;
    480 }
    481 
    482 bool SkView::onClick(Click*) {
    483 	return false;
    484 }
    485 
    486 bool SkView::handleInval(const SkRect*) {
    487 	return false;
    488 }
    489 
    490 //////////////////////////////////////////////////////////////////////
    491 
    492 void SkView::getLocalBounds(SkRect* bounds) const
    493 {
    494 	if (bounds)
    495 		bounds->set(0, 0, fWidth, fHeight);
    496 }
    497 
    498 //////////////////////////////////////////////////////////////////////
    499 //////////////////////////////////////////////////////////////////////
    500 
    501 void 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 
    528 void SkView::detachFromParent()
    529 {
    530 	SkView* parent = fParent;
    531 
    532 	if (parent)
    533 	{
    534 		this->detachFromParent_NoLayout();
    535 		parent->invokeLayout();
    536 	}
    537 }
    538 
    539 SkView* 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();
    567 DONE:
    568 	return child;
    569 }
    570 
    571 SkView* 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();
    599 DONE:
    600 	return child;
    601 }
    602 
    603 void SkView::detachAllChildren()
    604 {
    605 	while (fFirstChild)
    606 		fFirstChild->detachFromParent_NoLayout();
    607 }
    608 
    609 void 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 }
    622 void 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 */
    641 void 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 
    672 void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node)
    673 {
    674 	this->onInflate(dom, node);
    675 }
    676 
    677 void SkView::onPostInflate(const SkTDict<SkView*>&)
    678 {
    679 	// override in subclass as needed
    680 }
    681 
    682 void 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 
    694 SkView* 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 
    707 SkView* 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 
    722 SkView::F2BIter::F2BIter(const SkView* parent)
    723 {
    724 	fFirstChild = parent ? parent->fFirstChild : NULL;
    725 	fChild = fFirstChild ? fFirstChild->fPrevSibling : NULL;
    726 }
    727 
    728 SkView*	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 
    742 SkView::B2FIter::B2FIter(const SkView* parent)
    743 {
    744 	fFirstChild = parent ? parent->fFirstChild : NULL;
    745 	fChild = fFirstChild;
    746 }
    747 
    748 SkView*	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 
    767 static inline void show_if_nonzero(const char name[], SkScalar value)
    768 {
    769 	if (value)
    770 		SkDebugf("%s=\"%g\"", name, value/65536.);
    771 }
    772 
    773 static void tab(int level)
    774 {
    775 	for (int i = 0; i < level; i++)
    776 		SkDebugf("    ");
    777 }
    778 
    779 static 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 
    818 void SkView::dump(bool recurse) const
    819 {
    820 	dumpview(this, 0, recurse);
    821 }
    822 
    823 #endif
    824