3 * Copyright 2011 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
11 ////////////////////////////////////////////////////////////////////////
13 SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags))
17 fParent = fFirstChild = fNextSibling = fPrevSibling = NULL;
18 fMatrix.setIdentity();
24 this->detachAllChildren();
27 void SkView::setFlags(uint32_t flags)
29 SkASSERT((flags & ~kAllFlagMasks) == 0);
31 uint32_t diff = fFlags ^ flags;
33 if (diff & kVisible_Mask)
36 fFlags = SkToU8(flags);
38 if (diff & kVisible_Mask)
44 void SkView::setVisibleP(bool pred)
46 this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift));
49 void SkView::setEnabledP(bool pred)
51 this->setFlags(SkSetClearShift(fFlags, pred, kEnabled_Shift));
54 void SkView::setFocusableP(bool pred)
56 this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift));
59 void SkView::setClipToBounds(bool pred) {
60 this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift));
63 void SkView::setSize(SkScalar width, SkScalar height)
65 width = SkMaxScalar(0, width);
66 height = SkMaxScalar(0, height);
68 if (fWidth != width || fHeight != height)
79 void SkView::setLoc(SkScalar x, SkScalar y)
81 if (fLoc.fX != x || fLoc.fY != y)
89 void SkView::offset(SkScalar dx, SkScalar dy)
92 this->setLoc(fLoc.fX + dx, fLoc.fY + dy);
95 void SkView::setLocalMatrix(const SkMatrix& matrix)
102 void SkView::draw(SkCanvas* canvas)
104 if (fWidth && fHeight && this->isVisible())
107 r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight);
108 if (this->isClipToBounds() &&
109 canvas->quickReject(r)) {
113 SkAutoCanvasRestore as(canvas, true);
115 if (this->isClipToBounds()) {
119 canvas->translate(fLoc.fX, fLoc.fY);
120 canvas->concat(fMatrix);
123 fParent->beforeChild(this, canvas);
126 int sc = canvas->save();
127 this->onDraw(canvas);
128 canvas->restoreToCount(sc);
131 fParent->afterChild(this, canvas);
137 SkCanvas* childCanvas = this->beforeChildren(canvas);
139 while ((child = iter.next()) != NULL)
140 child->draw(childCanvas);
142 this->afterChildren(canvas);
146 void SkView::inval(SkRect* rect) {
151 if (!view->isVisible()) {
154 if (view->isClipToBounds()) {
156 view->getLocalBounds(&bounds);
157 if (rect && !bounds.intersect(*rect)) {
163 if (view->handleInval(rect)) {
167 SkView* parent = view->fParent;
168 if (parent == NULL) {
173 rect->offset(view->fLoc.fX, view->fLoc.fY);
179 ////////////////////////////////////////////////////////////////////////////
181 bool SkView::setFocusView(SkView* fv)
186 if (view->onSetFocusView(fv))
188 } while ((view = view->fParent) != NULL);
192 SkView* SkView::getFocusView() const
194 SkView* focus = NULL;
195 const SkView* view = this;
197 if (view->onGetFocusView(&focus))
199 } while ((view = view->fParent) != NULL);
203 bool SkView::hasFocus() const
205 return this == this->getFocusView();
208 bool SkView::acceptFocus()
210 return this->isFocusable() && this->setFocusView(this);
214 Try to give focus to this view, or its children
216 SkView* SkView::acceptFocus(FocusDirection dir)
218 if (dir == kNext_FocusDirection)
220 if (this->acceptFocus())
224 SkView* child, *focus;
225 while ((child = iter.next()) != NULL)
226 if ((focus = child->acceptFocus(dir)) != NULL)
232 SkView* child, *focus;
233 while ((child = iter.next()) != NULL)
234 if ((focus = child->acceptFocus(dir)) != NULL)
237 if (this->acceptFocus())
244 SkView* SkView::moveFocus(FocusDirection dir)
246 SkView* focus = this->getFocusView();
249 { // start with the root
251 while (focus->fParent)
252 focus = focus->fParent;
255 SkView* child, *parent;
257 if (dir == kNext_FocusDirection)
260 child = focus->fFirstChild;
267 while (child != parent->fFirstChild)
270 if ((focus = child->acceptFocus(dir)) != NULL)
272 child = child->fNextSibling;
275 child = parent->fNextSibling;
276 parent = parent->fParent;
277 } while (parent != NULL);
281 parent = focus->fParent;
282 if (parent == NULL) // we're the root
283 return focus->acceptFocus(dir);
289 while (child != parent->fFirstChild)
291 child = child->fPrevSibling;
292 if ((focus = child->acceptFocus(dir)) != NULL)
295 if (parent->acceptFocus())
299 parent = parent->fParent;
306 void SkView::onFocusChange(bool gainFocusP)
311 ////////////////////////////////////////////////////////////////////////////
313 SkView::Click::Click(SkView* target)
316 fTargetID = target->getSinkID();
318 fWeOwnTheType = false;
322 SkView::Click::~Click()
327 void SkView::Click::resetType()
332 fWeOwnTheType = false;
337 bool SkView::Click::isType(const char type[]) const
339 const char* t = fType;
348 return !strcmp(t, type);
351 void SkView::Click::setType(const char type[])
357 void SkView::Click::copyType(const char type[])
364 size_t len = strlen(type) + 1;
365 fType = (char*)sk_malloc_throw(len);
366 memcpy(fType, type, len);
367 fWeOwnTheType = true;
372 SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y, unsigned modi) {
373 if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) {
377 if (this->onSendClickToChildren(x, y, modi)) {
381 while ((child = iter.next()) != NULL)
384 if (!child->globalToLocal(x, y, &p)) {
388 Click* click = child->findClickHandler(p.fX, p.fY, modi);
396 return this->onFindClickHandler(x, y, modi);
399 void SkView::DoClickDown(Click* click, int x, int y, unsigned modi)
403 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
404 if (NULL == target) {
408 click->fIOrig.set(x, y);
409 click->fICurr = click->fIPrev = click->fIOrig;
411 click->fOrig.iset(x, y);
412 if (!target->globalToLocal(&click->fOrig)) {
413 // no history to let us recover from this failure
416 click->fPrev = click->fCurr = click->fOrig;
418 click->fState = Click::kDown_State;
419 click->fModifierKeys = modi;
420 target->onClick(click);
423 void SkView::DoClickMoved(Click* click, int x, int y, unsigned modi)
427 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
428 if (NULL == target) {
432 click->fIPrev = click->fICurr;
433 click->fICurr.set(x, y);
435 click->fPrev = click->fCurr;
436 click->fCurr.iset(x, y);
437 if (!target->globalToLocal(&click->fCurr)) {
438 // on failure pretend the mouse didn't move
439 click->fCurr = click->fPrev;
442 click->fState = Click::kMoved_State;
443 click->fModifierKeys = modi;
444 target->onClick(click);
447 void SkView::DoClickUp(Click* click, int x, int y, unsigned modi)
451 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
452 if (NULL == target) {
456 click->fIPrev = click->fICurr;
457 click->fICurr.set(x, y);
459 click->fPrev = click->fCurr;
460 click->fCurr.iset(x, y);
461 if (!target->globalToLocal(&click->fCurr)) {
462 // on failure pretend the mouse didn't move
463 click->fCurr = click->fPrev;
466 click->fState = Click::kUp_State;
467 click->fModifierKeys = modi;
468 target->onClick(click);
471 //////////////////////////////////////////////////////////////////////
473 void SkView::invokeLayout() {
474 SkView::Layout* layout = this->getLayout();
477 layout->layoutChildren(this);
481 void SkView::onDraw(SkCanvas* canvas) {
482 Artist* artist = this->getArtist();
485 artist->draw(this, canvas);
489 void SkView::onSizeChange() {}
491 bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) {
495 SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
499 bool SkView::onClick(Click*) {
503 bool SkView::handleInval(const SkRect*) {
507 //////////////////////////////////////////////////////////////////////
509 void SkView::getLocalBounds(SkRect* bounds) const {
511 bounds->set(0, 0, fWidth, fHeight);
515 //////////////////////////////////////////////////////////////////////
516 //////////////////////////////////////////////////////////////////////
518 void SkView::detachFromParent_NoLayout() {
520 if (fParent == NULL) {
524 if (fContainsFocus) {
525 (void)this->setFocusView(NULL);
532 if (fNextSibling != this) { // do we have any siblings
533 fNextSibling->fPrevSibling = fPrevSibling;
534 fPrevSibling->fNextSibling = fNextSibling;
538 if (fParent->fFirstChild == this) {
539 fParent->fFirstChild = next;
542 fParent = fNextSibling = fPrevSibling = NULL;
548 void SkView::detachFromParent() {
550 SkView* parent = fParent;
553 this->detachFromParent_NoLayout();
554 parent->invokeLayout();
558 SkView* SkView::attachChildToBack(SkView* child) {
560 SkASSERT(child != this);
562 if (child == NULL || fFirstChild == child)
566 child->detachFromParent_NoLayout();
568 if (fFirstChild == NULL) {
569 child->fNextSibling = child;
570 child->fPrevSibling = child;
572 child->fNextSibling = fFirstChild;
573 child->fPrevSibling = fFirstChild->fPrevSibling;
574 fFirstChild->fPrevSibling->fNextSibling = child;
575 fFirstChild->fPrevSibling = child;
579 child->fParent = this;
583 this->invokeLayout();
588 SkView* SkView::attachChildToFront(SkView* child) {
590 SkASSERT(child != this);
592 if (child == NULL || (fFirstChild && fFirstChild->fPrevSibling == child))
596 child->detachFromParent_NoLayout();
598 if (fFirstChild == NULL) {
600 child->fNextSibling = child;
601 child->fPrevSibling = child;
603 child->fNextSibling = fFirstChild;
604 child->fPrevSibling = fFirstChild->fPrevSibling;
605 fFirstChild->fPrevSibling->fNextSibling = child;
606 fFirstChild->fPrevSibling = child;
609 child->fParent = this;
613 this->invokeLayout();
618 void SkView::detachAllChildren() {
621 fFirstChild->detachFromParent_NoLayout();
624 void SkView::localToGlobal(SkMatrix* matrix) const {
627 const SkView* view = this;
630 matrix->preConcat(view->getLocalMatrix());
631 matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY);
632 view = view->fParent;
636 bool SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const
642 this->localToGlobal(&m);
648 local->set(p.fX, p.fY);
654 //////////////////////////////////////////////////////////////////
656 /* Even if the subclass overrides onInflate, they should always be
657 sure to call the inherited method, so that we get called.
659 void SkView::onInflate(const SkDOM& dom, const SkDOM::Node* node) {
664 (void)dom.findScalar(node, "x", &x);
665 (void)dom.findScalar(node, "y", &y);
670 (void)dom.findScalar(node, "width", &x);
671 (void)dom.findScalar(node, "height", &y);
676 static const char* gFlagNames[] = {
677 "visible", "enabled", "focusable", "flexH", "flexV"
679 SkASSERT(SK_ARRAY_COUNT(gFlagNames) == kFlagShiftCount);
682 uint32_t flags = this->getFlags();
683 for (unsigned i = 0; i < SK_ARRAY_COUNT(gFlagNames); i++)
684 if (dom.findBool(node, gFlagNames[i], &b))
685 flags = SkSetClearShift(flags, b, i);
686 this->setFlags(flags);
689 void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node) {
690 this->onInflate(dom, node);
693 void SkView::onPostInflate(const SkTDict<SkView*>&) {
694 // override in subclass as needed
697 void SkView::postInflate(const SkTDict<SkView*>& dict) {
698 this->onPostInflate(dict);
702 while ((child = iter.next()) != NULL)
703 child->postInflate(dict);
706 //////////////////////////////////////////////////////////////////
708 SkView* SkView::sendEventToParents(const SkEvent& evt) {
709 SkView* parent = fParent;
712 if (parent->doEvent(evt)) {
715 parent = parent->fParent;
720 SkView* SkView::sendQueryToParents(SkEvent* evt) {
721 SkView* parent = fParent;
724 if (parent->doQuery(evt)) {
727 parent = parent->fParent;
732 //////////////////////////////////////////////////////////////////
733 //////////////////////////////////////////////////////////////////
735 SkView::F2BIter::F2BIter(const SkView* parent) {
736 fFirstChild = parent ? parent->fFirstChild : NULL;
737 fChild = fFirstChild ? fFirstChild->fPrevSibling : NULL;
740 SkView* SkView::F2BIter::next() {
741 SkView* curr = fChild;
744 if (fChild == fFirstChild) {
747 fChild = fChild->fPrevSibling;
753 SkView::B2FIter::B2FIter(const SkView* parent) {
754 fFirstChild = parent ? parent->fFirstChild : NULL;
755 fChild = fFirstChild;
758 SkView* SkView::B2FIter::next() {
759 SkView* curr = fChild;
762 SkView* next = fChild->fNextSibling;
763 if (next == fFirstChild)
770 //////////////////////////////////////////////////////////////////
771 //////////////////////////////////////////////////////////////////
775 void SkView::validate() const {
776 // SkASSERT(this->getRefCnt() > 0 && this->getRefCnt() < 100);
778 SkASSERT(fNextSibling);
779 SkASSERT(fPrevSibling);
781 bool nextNull = NULL == fNextSibling;
782 bool prevNull = NULL == fNextSibling;
783 SkASSERT(nextNull == prevNull);
787 static inline void show_if_nonzero(const char name[], SkScalar value)
790 SkDebugf("%s=\"%g\"", name, value/65536.);
793 static void tab(int level)
795 for (int i = 0; i < level; i++)
799 static void dumpview(const SkView* view, int level, bool recurse)
804 show_if_nonzero(" x", view->locX());
805 show_if_nonzero(" y", view->locY());
806 show_if_nonzero(" width", view->width());
807 show_if_nonzero(" height", view->height());
811 SkView::B2FIter iter(view);
813 bool noChildren = true;
815 while ((child = iter.next()) != NULL)
820 dumpview(child, level + 1, true);
826 SkDebugf("</view>\n");
838 void SkView::dump(bool recurse) const
840 dumpview(this, 0, recurse);