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