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