blob: 9c148dfac7b505b75284af083420e1a44c3350d0 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
reed9a878a02015-12-27 12:47:25 -08007
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkView.h"
9#include "SkCanvas.h"
Hal Canary20de6152017-02-23 13:24:49 -050010#include "SkDOM.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000011
reed9a878a02015-12-27 12:47:25 -080012static inline uint32_t SkSetClearShift(uint32_t bits, bool cond, unsigned shift) {
13 SkASSERT((int)cond == 0 || (int)cond == 1);
14 return (bits & ~(1 << shift)) | ((int)cond << shift);
15}
16
reed@android.com8a1c16f2008-12-17 15:59:43 +000017////////////////////////////////////////////////////////////////////////
18
reed9a878a02015-12-27 12:47:25 -080019SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags)) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +000020 fWidth = fHeight = 0;
21 fLoc.set(0, 0);
halcanary96fcdcc2015-08-27 07:41:13 -070022 fParent = fFirstChild = fNextSibling = fPrevSibling = nullptr;
reed@google.comf03bb562011-11-11 21:42:12 +000023 fMatrix.setIdentity();
robertphillips@google.coma22e2112012-08-16 14:58:06 +000024 fContainsFocus = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +000025}
26
reed9a878a02015-12-27 12:47:25 -080027SkView::~SkView() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +000028 this->detachAllChildren();
reed@android.com8a1c16f2008-12-17 15:59:43 +000029}
30
reed9a878a02015-12-27 12:47:25 -080031void SkView::setFlags(uint32_t flags) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +000032 SkASSERT((flags & ~kAllFlagMasks) == 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000033
robertphillips@google.coma22e2112012-08-16 14:58:06 +000034 uint32_t diff = fFlags ^ flags;
reed@android.com8a1c16f2008-12-17 15:59:43 +000035
robertphillips@google.coma22e2112012-08-16 14:58:06 +000036 if (diff & kVisible_Mask)
halcanary96fcdcc2015-08-27 07:41:13 -070037 this->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +000038
robertphillips@google.coma22e2112012-08-16 14:58:06 +000039 fFlags = SkToU8(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000040
reed9a878a02015-12-27 12:47:25 -080041 if (diff & kVisible_Mask) {
halcanary96fcdcc2015-08-27 07:41:13 -070042 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000043 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000044}
45
reed9a878a02015-12-27 12:47:25 -080046void SkView::setVisibleP(bool pred) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +000047 this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift));
reed@android.com8a1c16f2008-12-17 15:59:43 +000048}
49
reed9a878a02015-12-27 12:47:25 -080050void SkView::setEnabledP(bool pred) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +000051 this->setFlags(SkSetClearShift(fFlags, pred, kEnabled_Shift));
reed@android.com8a1c16f2008-12-17 15:59:43 +000052}
53
reed9a878a02015-12-27 12:47:25 -080054void SkView::setFocusableP(bool pred) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +000055 this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift));
reed@android.com8a1c16f2008-12-17 15:59:43 +000056}
57
reed@android.comf2b98d62010-12-20 18:26:13 +000058void SkView::setClipToBounds(bool pred) {
59 this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift));
60}
61
reed9a878a02015-12-27 12:47:25 -080062void SkView::setSize(SkScalar width, SkScalar height) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +000063 width = SkMaxScalar(0, width);
64 height = SkMaxScalar(0, height);
reed@android.com8a1c16f2008-12-17 15:59:43 +000065
robertphillips@google.coma22e2112012-08-16 14:58:06 +000066 if (fWidth != width || fHeight != height)
67 {
halcanary96fcdcc2015-08-27 07:41:13 -070068 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000069 fWidth = width;
70 fHeight = height;
halcanary96fcdcc2015-08-27 07:41:13 -070071 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000072 this->onSizeChange();
73 this->invokeLayout();
74 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000075}
76
reed9a878a02015-12-27 12:47:25 -080077void SkView::setLoc(SkScalar x, SkScalar y) {
78 if (fLoc.fX != x || fLoc.fY != y) {
halcanary96fcdcc2015-08-27 07:41:13 -070079 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000080 fLoc.set(x, y);
halcanary96fcdcc2015-08-27 07:41:13 -070081 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000082 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000083}
84
reed9a878a02015-12-27 12:47:25 -080085void SkView::offset(SkScalar dx, SkScalar dy) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +000086 if (dx || dy)
87 this->setLoc(fLoc.fX + dx, fLoc.fY + dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +000088}
89
reed9a878a02015-12-27 12:47:25 -080090void SkView::setLocalMatrix(const SkMatrix& matrix) {
halcanary96fcdcc2015-08-27 07:41:13 -070091 this->inval(nullptr);
reed@google.comf03bb562011-11-11 21:42:12 +000092 fMatrix = matrix;
halcanary96fcdcc2015-08-27 07:41:13 -070093 this->inval(nullptr);
reed@google.comf03bb562011-11-11 21:42:12 +000094}
95
reed9a878a02015-12-27 12:47:25 -080096void SkView::draw(SkCanvas* canvas) {
97 if (fWidth && fHeight && this->isVisible()) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000098 SkRect r;
robertphillips@google.coma22e2112012-08-16 14:58:06 +000099 r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight);
reed9a878a02015-12-27 12:47:25 -0800100 if (this->isClipToBounds() && canvas->quickReject(r)) {
101 return;
reed@android.comf2b98d62010-12-20 18:26:13 +0000102 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103
rmistry@google.comd6176b02012-08-23 18:14:13 +0000104 SkAutoCanvasRestore as(canvas, true);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105
reed@android.comf2b98d62010-12-20 18:26:13 +0000106 if (this->isClipToBounds()) {
107 canvas->clipRect(r);
108 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000109
110 canvas->translate(fLoc.fX, fLoc.fY);
reed@google.comf03bb562011-11-11 21:42:12 +0000111 canvas->concat(fMatrix);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000112
reed@android.com6c5f6f22009-08-14 16:08:38 +0000113 if (fParent) {
114 fParent->beforeChild(this, canvas);
115 }
reed@android.com562ea922010-02-08 21:45:03 +0000116
117 int sc = canvas->save();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000118 this->onDraw(canvas);
reed@android.com562ea922010-02-08 21:45:03 +0000119 canvas->restoreToCount(sc);
120
reed@android.com6c5f6f22009-08-14 16:08:38 +0000121 if (fParent) {
122 fParent->afterChild(this, canvas);
123 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000124
125 B2FIter iter(this);
126 SkView* child;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127
128 SkCanvas* childCanvas = this->beforeChildren(canvas);
129
halcanary96fcdcc2015-08-27 07:41:13 -0700130 while ((child = iter.next()) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000131 child->draw(childCanvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000132
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133 this->afterChildren(canvas);
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000134 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135}
136
reed@android.comf2b98d62010-12-20 18:26:13 +0000137void SkView::inval(SkRect* rect) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000138 SkView* view = this;
reed@android.comf2b98d62010-12-20 18:26:13 +0000139 SkRect storage;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000141 for (;;) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000142 if (!view->isVisible()) {
143 return;
144 }
145 if (view->isClipToBounds()) {
146 SkRect bounds;
147 view->getLocalBounds(&bounds);
148 if (rect && !bounds.intersect(*rect)) {
149 return;
150 }
151 storage = bounds;
152 rect = &storage;
153 }
154 if (view->handleInval(rect)) {
155 return;
156 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000158 SkView* parent = view->fParent;
halcanary96fcdcc2015-08-27 07:41:13 -0700159 if (parent == nullptr) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000160 return;
161 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162
reed@android.comf2b98d62010-12-20 18:26:13 +0000163 if (rect) {
164 rect->offset(view->fLoc.fX, view->fLoc.fY);
165 }
166 view = parent;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000167 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168}
169
170////////////////////////////////////////////////////////////////////////////
171
reed9a878a02015-12-27 12:47:25 -0800172bool SkView::setFocusView(SkView* fv) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000173 SkView* view = this;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000174
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000175 do {
reed9a878a02015-12-27 12:47:25 -0800176 if (view->onSetFocusView(fv)) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000177 return true;
reed9a878a02015-12-27 12:47:25 -0800178 }
halcanary96fcdcc2015-08-27 07:41:13 -0700179 } while ((view = view->fParent) != nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000180 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181}
182
reed9a878a02015-12-27 12:47:25 -0800183SkView* SkView::getFocusView() const {
184 SkView* focus = nullptr;
185 const SkView* view = this;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000186 do {
reed9a878a02015-12-27 12:47:25 -0800187 if (view->onGetFocusView(&focus)) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000188 break;
reed9a878a02015-12-27 12:47:25 -0800189 }
halcanary96fcdcc2015-08-27 07:41:13 -0700190 } while ((view = view->fParent) != nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000191 return focus;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192}
193
reed9a878a02015-12-27 12:47:25 -0800194bool SkView::hasFocus() const {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000195 return this == this->getFocusView();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196}
197
reed9a878a02015-12-27 12:47:25 -0800198bool SkView::acceptFocus() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000199 return this->isFocusable() && this->setFocusView(this);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200}
201
202/*
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000203 Try to give focus to this view, or its children
reed@android.com8a1c16f2008-12-17 15:59:43 +0000204*/
reed9a878a02015-12-27 12:47:25 -0800205SkView* SkView::acceptFocus(FocusDirection dir) {
206 if (dir == kNext_FocusDirection) {
207 if (this->acceptFocus()) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000208 return this;
reed9a878a02015-12-27 12:47:25 -0800209 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000210 B2FIter iter(this);
211 SkView* child, *focus;
reed9a878a02015-12-27 12:47:25 -0800212 while ((child = iter.next()) != nullptr) {
213 if ((focus = child->acceptFocus(dir)) != nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000214 return focus;
reed9a878a02015-12-27 12:47:25 -0800215 }
216 }
217 } else { // prev
rmistry@google.comd6176b02012-08-23 18:14:13 +0000218 F2BIter iter(this);
219 SkView* child, *focus;
reed9a878a02015-12-27 12:47:25 -0800220 while ((child = iter.next()) != nullptr) {
221 if ((focus = child->acceptFocus(dir)) != nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000222 return focus;
reed9a878a02015-12-27 12:47:25 -0800223 }
224 }
225 if (this->acceptFocus()) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000226 return this;
reed9a878a02015-12-27 12:47:25 -0800227 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000228 }
halcanary96fcdcc2015-08-27 07:41:13 -0700229 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230}
231
reed9a878a02015-12-27 12:47:25 -0800232SkView* SkView::moveFocus(FocusDirection dir) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000233 SkView* focus = this->getFocusView();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234
reed9a878a02015-12-27 12:47:25 -0800235 if (focus == nullptr) { // start with the root
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000236 focus = this;
reed9a878a02015-12-27 12:47:25 -0800237 while (focus->fParent) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000238 focus = focus->fParent;
reed9a878a02015-12-27 12:47:25 -0800239 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000240 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241
reed9a878a02015-12-27 12:47:25 -0800242 SkView* child, *parent;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000243
reed9a878a02015-12-27 12:47:25 -0800244 if (dir == kNext_FocusDirection) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000245 parent = focus;
246 child = focus->fFirstChild;
247 if (child)
248 goto FIRST_CHILD;
249 else
250 goto NEXT_SIB;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000252 do {
reed9a878a02015-12-27 12:47:25 -0800253 while (child != parent->fFirstChild) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000254 FIRST_CHILD:
halcanary96fcdcc2015-08-27 07:41:13 -0700255 if ((focus = child->acceptFocus(dir)) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000256 return focus;
257 child = child->fNextSibling;
258 }
259 NEXT_SIB:
260 child = parent->fNextSibling;
261 parent = parent->fParent;
halcanary96fcdcc2015-08-27 07:41:13 -0700262 } while (parent != nullptr);
reed9a878a02015-12-27 12:47:25 -0800263 } else { // prevfocus
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000264 parent = focus->fParent;
reed9a878a02015-12-27 12:47:25 -0800265 if (parent == nullptr) { // we're the root
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000266 return focus->acceptFocus(dir);
reed9a878a02015-12-27 12:47:25 -0800267 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000268 child = focus;
reed9a878a02015-12-27 12:47:25 -0800269 while (parent) {
270 while (child != parent->fFirstChild) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000271 child = child->fPrevSibling;
reed9a878a02015-12-27 12:47:25 -0800272 if ((focus = child->acceptFocus(dir)) != nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000273 return focus;
reed9a878a02015-12-27 12:47:25 -0800274 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000275 }
reed9a878a02015-12-27 12:47:25 -0800276 if (parent->acceptFocus()) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000277 return parent;
reed9a878a02015-12-27 12:47:25 -0800278 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000279 child = parent;
280 parent = parent->fParent;
281 }
282 }
283 }
halcanary96fcdcc2015-08-27 07:41:13 -0700284 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285}
286
reed9a878a02015-12-27 12:47:25 -0800287void SkView::onFocusChange(bool gainFocusP) {
halcanary96fcdcc2015-08-27 07:41:13 -0700288 this->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000289}
290
291////////////////////////////////////////////////////////////////////////////
292
reed9a878a02015-12-27 12:47:25 -0800293SkView::Click::Click(SkView* target) {
Scroggod3aed392011-06-22 13:26:56 +0000294 SkASSERT(target);
295 fTargetID = target->getSinkID();
halcanary96fcdcc2015-08-27 07:41:13 -0700296 fType = nullptr;
Scroggod3aed392011-06-22 13:26:56 +0000297 fWeOwnTheType = false;
halcanary96fcdcc2015-08-27 07:41:13 -0700298 fOwner = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000299}
300
reed9a878a02015-12-27 12:47:25 -0800301SkView::Click::~Click() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000302 this->resetType();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303}
304
reed9a878a02015-12-27 12:47:25 -0800305void SkView::Click::resetType() {
306 if (fWeOwnTheType) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000307 sk_free(fType);
308 fWeOwnTheType = false;
309 }
halcanary96fcdcc2015-08-27 07:41:13 -0700310 fType = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000311}
312
reed9a878a02015-12-27 12:47:25 -0800313bool SkView::Click::isType(const char type[]) const {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000314 const char* t = fType;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000315
reed9a878a02015-12-27 12:47:25 -0800316 if (type == t) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000317 return true;
reed9a878a02015-12-27 12:47:25 -0800318 }
319 if (type == nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000320 type = "";
reed9a878a02015-12-27 12:47:25 -0800321 }
322 if (t == nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000323 t = "";
reed9a878a02015-12-27 12:47:25 -0800324 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000325 return !strcmp(t, type);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326}
327
reed9a878a02015-12-27 12:47:25 -0800328void SkView::Click::setType(const char type[]) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000329 this->resetType();
330 fType = (char*)type;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000331}
332
reed9a878a02015-12-27 12:47:25 -0800333void SkView::Click::copyType(const char type[]) {
334 if (fType != type) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000335 this->resetType();
reed9a878a02015-12-27 12:47:25 -0800336 if (type) {
337 size_t len = strlen(type) + 1;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000338 fType = (char*)sk_malloc_throw(len);
339 memcpy(fType, type, len);
340 fWeOwnTheType = true;
341 }
342 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000343}
344
reed@google.com4d5c26d2013-01-08 16:17:50 +0000345SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y, unsigned modi) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000346 if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) {
halcanary96fcdcc2015-08-27 07:41:13 -0700347 return nullptr;
reed@android.come72fee52009-11-16 14:52:01 +0000348 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000349
reed@google.com4d5c26d2013-01-08 16:17:50 +0000350 if (this->onSendClickToChildren(x, y, modi)) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000351 F2BIter iter(this);
352 SkView* child;
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000353
reed1a9caff2015-09-02 19:05:10 -0700354 while ((child = iter.next()) != nullptr) {
reed@google.comf03bb562011-11-11 21:42:12 +0000355 SkPoint p;
reed1a9caff2015-09-02 19:05:10 -0700356#if 0
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000357 if (!child->globalToLocal(x, y, &p)) {
358 continue;
359 }
reed1a9caff2015-09-02 19:05:10 -0700360#else
361 // the above seems broken, so just respecting fLoc for now <reed>
362 p.set(x - child->fLoc.x(), y - child->fLoc.y());
363#endif
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000364
reed@google.com4d5c26d2013-01-08 16:17:50 +0000365 Click* click = child->findClickHandler(p.fX, p.fY, modi);
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000366
reed@android.come72fee52009-11-16 14:52:01 +0000367 if (click) {
368 return click;
369 }
370 }
371 }
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000372
reed@google.com4d5c26d2013-01-08 16:17:50 +0000373 return this->onFindClickHandler(x, y, modi);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000374}
375
reed9a878a02015-12-27 12:47:25 -0800376void SkView::DoClickDown(Click* click, int x, int y, unsigned modi) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000377 SkASSERT(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000378
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000379 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
halcanary96fcdcc2015-08-27 07:41:13 -0700380 if (nullptr == target) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000381 return;
382 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000383
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000384 click->fIOrig.set(x, y);
385 click->fICurr = click->fIPrev = click->fIOrig;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000386
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000387 click->fOrig.iset(x, y);
388 if (!target->globalToLocal(&click->fOrig)) {
389 // no history to let us recover from this failure
390 return;
391 }
392 click->fPrev = click->fCurr = click->fOrig;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000393
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000394 click->fState = Click::kDown_State;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000395 click->fModifierKeys = modi;
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000396 target->onClick(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397}
398
reed9a878a02015-12-27 12:47:25 -0800399void SkView::DoClickMoved(Click* click, int x, int y, unsigned modi) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000400 SkASSERT(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000401
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000402 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
halcanary96fcdcc2015-08-27 07:41:13 -0700403 if (nullptr == target) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000404 return;
405 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000406
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000407 click->fIPrev = click->fICurr;
408 click->fICurr.set(x, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000409
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000410 click->fPrev = click->fCurr;
411 click->fCurr.iset(x, y);
412 if (!target->globalToLocal(&click->fCurr)) {
413 // on failure pretend the mouse didn't move
414 click->fCurr = click->fPrev;
415 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000416
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000417 click->fState = Click::kMoved_State;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000418 click->fModifierKeys = modi;
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000419 target->onClick(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000420}
421
reed9a878a02015-12-27 12:47:25 -0800422void SkView::DoClickUp(Click* click, int x, int y, unsigned modi) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000423 SkASSERT(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000424
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000425 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
halcanary96fcdcc2015-08-27 07:41:13 -0700426 if (nullptr == target) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000427 return;
428 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000429
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000430 click->fIPrev = click->fICurr;
431 click->fICurr.set(x, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000432
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000433 click->fPrev = click->fCurr;
434 click->fCurr.iset(x, y);
435 if (!target->globalToLocal(&click->fCurr)) {
436 // on failure pretend the mouse didn't move
437 click->fCurr = click->fPrev;
438 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000439
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000440 click->fState = Click::kUp_State;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000441 click->fModifierKeys = modi;
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000442 target->onClick(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000443}
444
445//////////////////////////////////////////////////////////////////////
446
reed@android.come72fee52009-11-16 14:52:01 +0000447void SkView::invokeLayout() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000448 SkView::Layout* layout = this->getLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000449
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000450 if (layout) {
451 layout->layoutChildren(this);
reed@android.come72fee52009-11-16 14:52:01 +0000452 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000453}
454
reed@android.come72fee52009-11-16 14:52:01 +0000455void SkView::onDraw(SkCanvas* canvas) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000456 Artist* artist = this->getArtist();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000457
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000458 if (artist) {
459 artist->draw(this, canvas);
reed@android.come72fee52009-11-16 14:52:01 +0000460 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000461}
462
reed@android.come72fee52009-11-16 14:52:01 +0000463void SkView::onSizeChange() {}
464
reed@google.com4d5c26d2013-01-08 16:17:50 +0000465bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) {
reed@android.come72fee52009-11-16 14:52:01 +0000466 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000467}
468
reed@google.com4d5c26d2013-01-08 16:17:50 +0000469SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
halcanary96fcdcc2015-08-27 07:41:13 -0700470 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000471}
472
reed@android.come72fee52009-11-16 14:52:01 +0000473bool SkView::onClick(Click*) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000474 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475}
476
reed@android.comf2b98d62010-12-20 18:26:13 +0000477bool SkView::handleInval(const SkRect*) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000478 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479}
480
481//////////////////////////////////////////////////////////////////////
482
reed@google.coma25c94e2013-06-13 20:20:17 +0000483void SkView::getLocalBounds(SkRect* bounds) const {
484 if (bounds) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000485 bounds->set(0, 0, fWidth, fHeight);
reed@google.coma25c94e2013-06-13 20:20:17 +0000486 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000487}
488
489//////////////////////////////////////////////////////////////////////
490//////////////////////////////////////////////////////////////////////
491
reed@google.coma25c94e2013-06-13 20:20:17 +0000492void SkView::detachFromParent_NoLayout() {
493 this->validate();
halcanary96fcdcc2015-08-27 07:41:13 -0700494 if (fParent == nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000495 return;
reed@google.coma25c94e2013-06-13 20:20:17 +0000496 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000497
reed@google.coma25c94e2013-06-13 20:20:17 +0000498 if (fContainsFocus) {
halcanary96fcdcc2015-08-27 07:41:13 -0700499 (void)this->setFocusView(nullptr);
reed@google.coma25c94e2013-06-13 20:20:17 +0000500 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000501
halcanary96fcdcc2015-08-27 07:41:13 -0700502 this->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000503
halcanary96fcdcc2015-08-27 07:41:13 -0700504 SkView* next = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000505
reed@google.coma25c94e2013-06-13 20:20:17 +0000506 if (fNextSibling != this) { // do we have any siblings
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000507 fNextSibling->fPrevSibling = fPrevSibling;
508 fPrevSibling->fNextSibling = fNextSibling;
509 next = fNextSibling;
510 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000511
reed@google.coma25c94e2013-06-13 20:20:17 +0000512 if (fParent->fFirstChild == this) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000513 fParent->fFirstChild = next;
reed@google.coma25c94e2013-06-13 20:20:17 +0000514 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000515
halcanary96fcdcc2015-08-27 07:41:13 -0700516 fParent = fNextSibling = fPrevSibling = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000517
reed@google.coma25c94e2013-06-13 20:20:17 +0000518 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000519 this->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000520}
521
reed@google.coma25c94e2013-06-13 20:20:17 +0000522void SkView::detachFromParent() {
523 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000524 SkView* parent = fParent;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000525
reed@google.coma25c94e2013-06-13 20:20:17 +0000526 if (parent) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000527 this->detachFromParent_NoLayout();
528 parent->invokeLayout();
529 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000530}
531
reed@google.coma25c94e2013-06-13 20:20:17 +0000532SkView* SkView::attachChildToBack(SkView* child) {
533 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000534 SkASSERT(child != this);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000535
halcanary96fcdcc2015-08-27 07:41:13 -0700536 if (child == nullptr || fFirstChild == child)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000537 goto DONE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000538
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000539 child->ref();
540 child->detachFromParent_NoLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000541
halcanary96fcdcc2015-08-27 07:41:13 -0700542 if (fFirstChild == nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000543 child->fNextSibling = child;
544 child->fPrevSibling = child;
reed@google.coma25c94e2013-06-13 20:20:17 +0000545 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000546 child->fNextSibling = fFirstChild;
547 child->fPrevSibling = fFirstChild->fPrevSibling;
548 fFirstChild->fPrevSibling->fNextSibling = child;
549 fFirstChild->fPrevSibling = child;
550 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000551
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000552 fFirstChild = child;
553 child->fParent = this;
halcanary96fcdcc2015-08-27 07:41:13 -0700554 child->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000555
reed@google.coma25c94e2013-06-13 20:20:17 +0000556 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000557 this->invokeLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000558DONE:
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000559 return child;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000560}
561
reed@google.coma25c94e2013-06-13 20:20:17 +0000562SkView* SkView::attachChildToFront(SkView* child) {
563 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000564 SkASSERT(child != this);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000565
halcanary96fcdcc2015-08-27 07:41:13 -0700566 if (child == nullptr || (fFirstChild && fFirstChild->fPrevSibling == child))
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000567 goto DONE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000568
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000569 child->ref();
570 child->detachFromParent_NoLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000571
halcanary96fcdcc2015-08-27 07:41:13 -0700572 if (fFirstChild == nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000573 fFirstChild = child;
574 child->fNextSibling = child;
575 child->fPrevSibling = child;
reed@google.coma25c94e2013-06-13 20:20:17 +0000576 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000577 child->fNextSibling = fFirstChild;
578 child->fPrevSibling = fFirstChild->fPrevSibling;
579 fFirstChild->fPrevSibling->fNextSibling = child;
580 fFirstChild->fPrevSibling = child;
581 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000582
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000583 child->fParent = this;
halcanary96fcdcc2015-08-27 07:41:13 -0700584 child->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585
reed@google.coma25c94e2013-06-13 20:20:17 +0000586 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000587 this->invokeLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000588DONE:
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000589 return child;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590}
591
reed@google.coma25c94e2013-06-13 20:20:17 +0000592void SkView::detachAllChildren() {
593 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000594 while (fFirstChild)
595 fFirstChild->detachFromParent_NoLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000596}
597
reed@google.coma25c94e2013-06-13 20:20:17 +0000598void SkView::localToGlobal(SkMatrix* matrix) const {
reed@google.comf03bb562011-11-11 21:42:12 +0000599 if (matrix) {
600 matrix->reset();
601 const SkView* view = this;
602 while (view)
603 {
604 matrix->preConcat(view->getLocalMatrix());
605 matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY);
606 view = view->fParent;
607 }
608 }
609}
reed9a878a02015-12-27 12:47:25 -0800610
611bool SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const {
bsalomon49f085d2014-09-05 13:34:00 -0700612 if (local) {
reed@google.comf03bb562011-11-11 21:42:12 +0000613 SkMatrix m;
614 this->localToGlobal(&m);
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000615 if (!m.invert(&m)) {
616 return false;
617 }
reed@google.comf03bb562011-11-11 21:42:12 +0000618 SkPoint p;
reed@google.comf03bb562011-11-11 21:42:12 +0000619 m.mapXY(x, y, &p);
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000620 local->set(p.fX, p.fY);
621 }
622
623 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000624}
625
626//////////////////////////////////////////////////////////////////
627
rmistry@google.comd6176b02012-08-23 18:14:13 +0000628/* Even if the subclass overrides onInflate, they should always be
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000629 sure to call the inherited method, so that we get called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000630*/
reed@google.coma25c94e2013-06-13 20:20:17 +0000631void SkView::onInflate(const SkDOM& dom, const SkDOM::Node* node) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000632 SkScalar x, y;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000633
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000634 x = this->locX();
635 y = this->locY();
636 (void)dom.findScalar(node, "x", &x);
637 (void)dom.findScalar(node, "y", &y);
638 this->setLoc(x, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000639
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000640 x = this->width();
641 y = this->height();
642 (void)dom.findScalar(node, "width", &x);
643 (void)dom.findScalar(node, "height", &y);
644 this->setSize(x, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000645
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000646 // inflate the flags
reed@android.com8a1c16f2008-12-17 15:59:43 +0000647
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000648 static const char* gFlagNames[] = {
649 "visible", "enabled", "focusable", "flexH", "flexV"
650 };
651 SkASSERT(SK_ARRAY_COUNT(gFlagNames) == kFlagShiftCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000652
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000653 bool b;
654 uint32_t flags = this->getFlags();
reed9a878a02015-12-27 12:47:25 -0800655 for (unsigned i = 0; i < SK_ARRAY_COUNT(gFlagNames); i++) {
656 if (dom.findBool(node, gFlagNames[i], &b)) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000657 flags = SkSetClearShift(flags, b, i);
reed9a878a02015-12-27 12:47:25 -0800658 }
659 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000660 this->setFlags(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000661}
662
reed@google.coma25c94e2013-06-13 20:20:17 +0000663void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000664 this->onInflate(dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000665}
666
reed@android.com8a1c16f2008-12-17 15:59:43 +0000667//////////////////////////////////////////////////////////////////
668
reed@google.coma25c94e2013-06-13 20:20:17 +0000669SkView* SkView::sendEventToParents(const SkEvent& evt) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000670 SkView* parent = fParent;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000671
reed@google.coma25c94e2013-06-13 20:20:17 +0000672 while (parent) {
673 if (parent->doEvent(evt)) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000674 return parent;
reed@google.coma25c94e2013-06-13 20:20:17 +0000675 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000676 parent = parent->fParent;
677 }
halcanary96fcdcc2015-08-27 07:41:13 -0700678 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000679}
680
reed@android.com34245c72009-11-03 04:00:48 +0000681SkView* SkView::sendQueryToParents(SkEvent* evt) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000682 SkView* parent = fParent;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000683
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000684 while (parent) {
685 if (parent->doQuery(evt)) {
686 return parent;
reed@android.com34245c72009-11-03 04:00:48 +0000687 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000688 parent = parent->fParent;
689 }
halcanary96fcdcc2015-08-27 07:41:13 -0700690 return nullptr;
reed@android.com34245c72009-11-03 04:00:48 +0000691}
692
reed@android.com8a1c16f2008-12-17 15:59:43 +0000693//////////////////////////////////////////////////////////////////
694//////////////////////////////////////////////////////////////////
695
reed@google.coma25c94e2013-06-13 20:20:17 +0000696SkView::F2BIter::F2BIter(const SkView* parent) {
halcanary96fcdcc2015-08-27 07:41:13 -0700697 fFirstChild = parent ? parent->fFirstChild : nullptr;
698 fChild = fFirstChild ? fFirstChild->fPrevSibling : nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000699}
700
reed@google.coma25c94e2013-06-13 20:20:17 +0000701SkView* SkView::F2BIter::next() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000702 SkView* curr = fChild;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000703
reed@google.coma25c94e2013-06-13 20:20:17 +0000704 if (fChild) {
705 if (fChild == fFirstChild) {
halcanary96fcdcc2015-08-27 07:41:13 -0700706 fChild = nullptr;
reed@google.coma25c94e2013-06-13 20:20:17 +0000707 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000708 fChild = fChild->fPrevSibling;
reed@google.coma25c94e2013-06-13 20:20:17 +0000709 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000710 }
711 return curr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000712}
713
reed@google.coma25c94e2013-06-13 20:20:17 +0000714SkView::B2FIter::B2FIter(const SkView* parent) {
halcanary96fcdcc2015-08-27 07:41:13 -0700715 fFirstChild = parent ? parent->fFirstChild : nullptr;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000716 fChild = fFirstChild;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000717}
718
reed@google.coma25c94e2013-06-13 20:20:17 +0000719SkView* SkView::B2FIter::next() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000720 SkView* curr = fChild;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000721
reed@google.coma25c94e2013-06-13 20:20:17 +0000722 if (fChild) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000723 SkView* next = fChild->fNextSibling;
724 if (next == fFirstChild)
halcanary96fcdcc2015-08-27 07:41:13 -0700725 next = nullptr;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000726 fChild = next;
727 }
728 return curr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000729}
730
731//////////////////////////////////////////////////////////////////
732//////////////////////////////////////////////////////////////////
733
734#ifdef SK_DEBUG
735
reed@google.coma25c94e2013-06-13 20:20:17 +0000736void SkView::validate() const {
reed@google.com079813e2013-06-14 17:46:07 +0000737// SkASSERT(this->getRefCnt() > 0 && this->getRefCnt() < 100);
reed@google.coma25c94e2013-06-13 20:20:17 +0000738 if (fParent) {
739 SkASSERT(fNextSibling);
740 SkASSERT(fPrevSibling);
741 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700742 bool nextNull = nullptr == fNextSibling;
743 bool prevNull = nullptr == fNextSibling;
reed@google.com732c5d52013-06-13 20:48:09 +0000744 SkASSERT(nextNull == prevNull);
reed@google.coma25c94e2013-06-13 20:20:17 +0000745 }
746}
747
reed9a878a02015-12-27 12:47:25 -0800748static inline void show_if_nonzero(const char name[], SkScalar value) {
749 if (value) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000750 SkDebugf("%s=\"%g\"", name, value/65536.);
reed9a878a02015-12-27 12:47:25 -0800751 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000752}
753
reed9a878a02015-12-27 12:47:25 -0800754static void tab(int level) {
755 for (int i = 0; i < level; i++) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000756 SkDebugf(" ");
reed9a878a02015-12-27 12:47:25 -0800757 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000758}
759
reed9a878a02015-12-27 12:47:25 -0800760static void dumpview(const SkView* view, int level, bool recurse) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000761 tab(level);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000762
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000763 SkDebugf("<view");
764 show_if_nonzero(" x", view->locX());
765 show_if_nonzero(" y", view->locY());
766 show_if_nonzero(" width", view->width());
767 show_if_nonzero(" height", view->height());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000768
reed9a878a02015-12-27 12:47:25 -0800769 if (recurse) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000770 SkView::B2FIter iter(view);
771 SkView* child;
772 bool noChildren = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000773
reed9a878a02015-12-27 12:47:25 -0800774 while ((child = iter.next()) != nullptr) {
775 if (noChildren) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000776 SkDebugf(">\n");
reed9a878a02015-12-27 12:47:25 -0800777 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000778 noChildren = false;
779 dumpview(child, level + 1, true);
780 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000781
reed9a878a02015-12-27 12:47:25 -0800782 if (!noChildren) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000783 tab(level);
784 SkDebugf("</view>\n");
reed9a878a02015-12-27 12:47:25 -0800785 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000786 goto ONELINER;
reed9a878a02015-12-27 12:47:25 -0800787 }
788 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000789 ONELINER:
790 SkDebugf(" />\n");
791 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000792}
793
reed9a878a02015-12-27 12:47:25 -0800794void SkView::dump(bool recurse) const {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000795 dumpview(this, 0, recurse);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000796}
797
798#endif