blob: ec75d610aaf6ec24f69bdb99c5b45943e1f96456 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkView.h"
9#include "SkCanvas.h"
10
11////////////////////////////////////////////////////////////////////////
12
13SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags))
14{
robertphillips@google.coma22e2112012-08-16 14:58:06 +000015 fWidth = fHeight = 0;
16 fLoc.set(0, 0);
halcanary96fcdcc2015-08-27 07:41:13 -070017 fParent = fFirstChild = fNextSibling = fPrevSibling = nullptr;
reed@google.comf03bb562011-11-11 21:42:12 +000018 fMatrix.setIdentity();
robertphillips@google.coma22e2112012-08-16 14:58:06 +000019 fContainsFocus = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +000020}
21
22SkView::~SkView()
23{
robertphillips@google.coma22e2112012-08-16 14:58:06 +000024 this->detachAllChildren();
reed@android.com8a1c16f2008-12-17 15:59:43 +000025}
26
27void SkView::setFlags(uint32_t flags)
28{
robertphillips@google.coma22e2112012-08-16 14:58:06 +000029 SkASSERT((flags & ~kAllFlagMasks) == 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000030
robertphillips@google.coma22e2112012-08-16 14:58:06 +000031 uint32_t diff = fFlags ^ flags;
reed@android.com8a1c16f2008-12-17 15:59:43 +000032
robertphillips@google.coma22e2112012-08-16 14:58:06 +000033 if (diff & kVisible_Mask)
halcanary96fcdcc2015-08-27 07:41:13 -070034 this->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +000035
robertphillips@google.coma22e2112012-08-16 14:58:06 +000036 fFlags = SkToU8(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000037
robertphillips@google.coma22e2112012-08-16 14:58:06 +000038 if (diff & kVisible_Mask)
39 {
halcanary96fcdcc2015-08-27 07:41:13 -070040 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000041 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000042}
43
44void SkView::setVisibleP(bool pred)
45{
robertphillips@google.coma22e2112012-08-16 14:58:06 +000046 this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift));
reed@android.com8a1c16f2008-12-17 15:59:43 +000047}
48
49void SkView::setEnabledP(bool pred)
50{
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
54void SkView::setFocusableP(bool pred)
55{
robertphillips@google.coma22e2112012-08-16 14:58:06 +000056 this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift));
reed@android.com8a1c16f2008-12-17 15:59:43 +000057}
58
reed@android.comf2b98d62010-12-20 18:26:13 +000059void SkView::setClipToBounds(bool pred) {
60 this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift));
61}
62
reed@android.com8a1c16f2008-12-17 15:59:43 +000063void SkView::setSize(SkScalar width, SkScalar height)
64{
robertphillips@google.coma22e2112012-08-16 14:58:06 +000065 width = SkMaxScalar(0, width);
66 height = SkMaxScalar(0, height);
reed@android.com8a1c16f2008-12-17 15:59:43 +000067
robertphillips@google.coma22e2112012-08-16 14:58:06 +000068 if (fWidth != width || fHeight != height)
69 {
halcanary96fcdcc2015-08-27 07:41:13 -070070 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000071 fWidth = width;
72 fHeight = height;
halcanary96fcdcc2015-08-27 07:41:13 -070073 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000074 this->onSizeChange();
75 this->invokeLayout();
76 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000077}
78
79void SkView::setLoc(SkScalar x, SkScalar y)
80{
robertphillips@google.coma22e2112012-08-16 14:58:06 +000081 if (fLoc.fX != x || fLoc.fY != y)
82 {
halcanary96fcdcc2015-08-27 07:41:13 -070083 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000084 fLoc.set(x, y);
halcanary96fcdcc2015-08-27 07:41:13 -070085 this->inval(nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +000086 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000087}
88
89void SkView::offset(SkScalar dx, SkScalar dy)
90{
robertphillips@google.coma22e2112012-08-16 14:58:06 +000091 if (dx || dy)
92 this->setLoc(fLoc.fX + dx, fLoc.fY + dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +000093}
94
rmistry@google.comd6176b02012-08-23 18:14:13 +000095void SkView::setLocalMatrix(const SkMatrix& matrix)
reed@google.comf03bb562011-11-11 21:42:12 +000096{
halcanary96fcdcc2015-08-27 07:41:13 -070097 this->inval(nullptr);
reed@google.comf03bb562011-11-11 21:42:12 +000098 fMatrix = matrix;
halcanary96fcdcc2015-08-27 07:41:13 -070099 this->inval(nullptr);
reed@google.comf03bb562011-11-11 21:42:12 +0000100}
101
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102void SkView::draw(SkCanvas* canvas)
103{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000104 if (fWidth && fHeight && this->isVisible())
105 {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000106 SkRect r;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000107 r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight);
108 if (this->isClipToBounds() &&
reed@google.com3b3e8952012-08-16 20:53:31 +0000109 canvas->quickReject(r)) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000110 return;
111 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112
rmistry@google.comd6176b02012-08-23 18:14:13 +0000113 SkAutoCanvasRestore as(canvas, true);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114
reed@android.comf2b98d62010-12-20 18:26:13 +0000115 if (this->isClipToBounds()) {
116 canvas->clipRect(r);
117 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000118
119 canvas->translate(fLoc.fX, fLoc.fY);
reed@google.comf03bb562011-11-11 21:42:12 +0000120 canvas->concat(fMatrix);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000121
reed@android.com6c5f6f22009-08-14 16:08:38 +0000122 if (fParent) {
123 fParent->beforeChild(this, canvas);
124 }
reed@android.com562ea922010-02-08 21:45:03 +0000125
126 int sc = canvas->save();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000127 this->onDraw(canvas);
reed@android.com562ea922010-02-08 21:45:03 +0000128 canvas->restoreToCount(sc);
129
reed@android.com6c5f6f22009-08-14 16:08:38 +0000130 if (fParent) {
131 fParent->afterChild(this, canvas);
132 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000133
134 B2FIter iter(this);
135 SkView* child;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136
137 SkCanvas* childCanvas = this->beforeChildren(canvas);
138
halcanary96fcdcc2015-08-27 07:41:13 -0700139 while ((child = iter.next()) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000140 child->draw(childCanvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000141
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142 this->afterChildren(canvas);
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000143 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144}
145
reed@android.comf2b98d62010-12-20 18:26:13 +0000146void SkView::inval(SkRect* rect) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000147 SkView* view = this;
reed@android.comf2b98d62010-12-20 18:26:13 +0000148 SkRect storage;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000150 for (;;) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000151 if (!view->isVisible()) {
152 return;
153 }
154 if (view->isClipToBounds()) {
155 SkRect bounds;
156 view->getLocalBounds(&bounds);
157 if (rect && !bounds.intersect(*rect)) {
158 return;
159 }
160 storage = bounds;
161 rect = &storage;
162 }
163 if (view->handleInval(rect)) {
164 return;
165 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000167 SkView* parent = view->fParent;
halcanary96fcdcc2015-08-27 07:41:13 -0700168 if (parent == nullptr) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000169 return;
170 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171
reed@android.comf2b98d62010-12-20 18:26:13 +0000172 if (rect) {
173 rect->offset(view->fLoc.fX, view->fLoc.fY);
174 }
175 view = parent;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000176 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000177}
178
179////////////////////////////////////////////////////////////////////////////
180
181bool SkView::setFocusView(SkView* fv)
182{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000183 SkView* view = this;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000184
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000185 do {
186 if (view->onSetFocusView(fv))
187 return true;
halcanary96fcdcc2015-08-27 07:41:13 -0700188 } while ((view = view->fParent) != nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000189 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000190}
191
192SkView* SkView::getFocusView() const
193{
halcanary96fcdcc2015-08-27 07:41:13 -0700194 SkView* focus = nullptr;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000195 const SkView* view = this;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000196 do {
197 if (view->onGetFocusView(&focus))
198 break;
halcanary96fcdcc2015-08-27 07:41:13 -0700199 } while ((view = view->fParent) != nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000200 return focus;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000201}
202
203bool SkView::hasFocus() const
204{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000205 return this == this->getFocusView();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000206}
207
208bool SkView::acceptFocus()
209{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000210 return this->isFocusable() && this->setFocusView(this);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000211}
212
213/*
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000214 Try to give focus to this view, or its children
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215*/
216SkView* SkView::acceptFocus(FocusDirection dir)
217{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000218 if (dir == kNext_FocusDirection)
219 {
220 if (this->acceptFocus())
221 return this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222
rmistry@google.comd6176b02012-08-23 18:14:13 +0000223 B2FIter iter(this);
224 SkView* child, *focus;
halcanary96fcdcc2015-08-27 07:41:13 -0700225 while ((child = iter.next()) != nullptr)
226 if ((focus = child->acceptFocus(dir)) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000227 return focus;
228 }
229 else // prev
230 {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000231 F2BIter iter(this);
232 SkView* child, *focus;
halcanary96fcdcc2015-08-27 07:41:13 -0700233 while ((child = iter.next()) != nullptr)
234 if ((focus = child->acceptFocus(dir)) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000235 return focus;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000237 if (this->acceptFocus())
238 return this;
239 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000240
halcanary96fcdcc2015-08-27 07:41:13 -0700241 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242}
243
244SkView* SkView::moveFocus(FocusDirection dir)
245{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000246 SkView* focus = this->getFocusView();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000247
halcanary96fcdcc2015-08-27 07:41:13 -0700248 if (focus == nullptr)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000249 { // start with the root
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000250 focus = this;
251 while (focus->fParent)
252 focus = focus->fParent;
253 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000254
rmistry@google.comd6176b02012-08-23 18:14:13 +0000255 SkView* child, *parent;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000257 if (dir == kNext_FocusDirection)
258 {
259 parent = focus;
260 child = focus->fFirstChild;
261 if (child)
262 goto FIRST_CHILD;
263 else
264 goto NEXT_SIB;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000265
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000266 do {
267 while (child != parent->fFirstChild)
268 {
269 FIRST_CHILD:
halcanary96fcdcc2015-08-27 07:41:13 -0700270 if ((focus = child->acceptFocus(dir)) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000271 return focus;
272 child = child->fNextSibling;
273 }
274 NEXT_SIB:
275 child = parent->fNextSibling;
276 parent = parent->fParent;
halcanary96fcdcc2015-08-27 07:41:13 -0700277 } while (parent != nullptr);
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000278 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000279 else // prevfocus
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000280 {
281 parent = focus->fParent;
halcanary96fcdcc2015-08-27 07:41:13 -0700282 if (parent == nullptr) // we're the root
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000283 return focus->acceptFocus(dir);
284 else
285 {
286 child = focus;
287 while (parent)
288 {
289 while (child != parent->fFirstChild)
290 {
291 child = child->fPrevSibling;
halcanary96fcdcc2015-08-27 07:41:13 -0700292 if ((focus = child->acceptFocus(dir)) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000293 return focus;
294 }
295 if (parent->acceptFocus())
296 return parent;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000297
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000298 child = parent;
299 parent = parent->fParent;
300 }
301 }
302 }
halcanary96fcdcc2015-08-27 07:41:13 -0700303 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304}
305
306void SkView::onFocusChange(bool gainFocusP)
307{
halcanary96fcdcc2015-08-27 07:41:13 -0700308 this->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309}
310
311////////////////////////////////////////////////////////////////////////////
312
313SkView::Click::Click(SkView* target)
314{
Scroggod3aed392011-06-22 13:26:56 +0000315 SkASSERT(target);
316 fTargetID = target->getSinkID();
halcanary96fcdcc2015-08-27 07:41:13 -0700317 fType = nullptr;
Scroggod3aed392011-06-22 13:26:56 +0000318 fWeOwnTheType = false;
halcanary96fcdcc2015-08-27 07:41:13 -0700319 fOwner = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320}
321
322SkView::Click::~Click()
323{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000324 this->resetType();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000325}
326
327void SkView::Click::resetType()
328{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000329 if (fWeOwnTheType)
330 {
331 sk_free(fType);
332 fWeOwnTheType = false;
333 }
halcanary96fcdcc2015-08-27 07:41:13 -0700334 fType = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335}
336
337bool SkView::Click::isType(const char type[]) const
338{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000339 const char* t = fType;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000341 if (type == t)
342 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000343
halcanary96fcdcc2015-08-27 07:41:13 -0700344 if (type == nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000345 type = "";
halcanary96fcdcc2015-08-27 07:41:13 -0700346 if (t == nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000347 t = "";
348 return !strcmp(t, type);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000349}
350
351void SkView::Click::setType(const char type[])
352{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000353 this->resetType();
354 fType = (char*)type;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000355}
356
357void SkView::Click::copyType(const char type[])
358{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000359 if (fType != type)
360 {
361 this->resetType();
362 if (type)
363 {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000364 size_t len = strlen(type) + 1;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000365 fType = (char*)sk_malloc_throw(len);
366 memcpy(fType, type, len);
367 fWeOwnTheType = true;
368 }
369 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000370}
371
reed@google.com4d5c26d2013-01-08 16:17:50 +0000372SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y, unsigned modi) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000373 if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) {
halcanary96fcdcc2015-08-27 07:41:13 -0700374 return nullptr;
reed@android.come72fee52009-11-16 14:52:01 +0000375 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000376
reed@google.com4d5c26d2013-01-08 16:17:50 +0000377 if (this->onSendClickToChildren(x, y, modi)) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000378 F2BIter iter(this);
379 SkView* child;
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000380
reed1a9caff2015-09-02 19:05:10 -0700381 while ((child = iter.next()) != nullptr) {
reed@google.comf03bb562011-11-11 21:42:12 +0000382 SkPoint p;
reed1a9caff2015-09-02 19:05:10 -0700383#if 0
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000384 if (!child->globalToLocal(x, y, &p)) {
385 continue;
386 }
reed1a9caff2015-09-02 19:05:10 -0700387#else
388 // the above seems broken, so just respecting fLoc for now <reed>
389 p.set(x - child->fLoc.x(), y - child->fLoc.y());
390#endif
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000391
reed@google.com4d5c26d2013-01-08 16:17:50 +0000392 Click* click = child->findClickHandler(p.fX, p.fY, modi);
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000393
reed@android.come72fee52009-11-16 14:52:01 +0000394 if (click) {
395 return click;
396 }
397 }
398 }
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000399
reed@google.com4d5c26d2013-01-08 16:17:50 +0000400 return this->onFindClickHandler(x, y, modi);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000401}
402
reed@google.com4d5c26d2013-01-08 16:17:50 +0000403void SkView::DoClickDown(Click* click, int x, int y, unsigned modi)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000404{
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000405 SkASSERT(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000406
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000407 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
halcanary96fcdcc2015-08-27 07:41:13 -0700408 if (nullptr == target) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000409 return;
410 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000411
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000412 click->fIOrig.set(x, y);
413 click->fICurr = click->fIPrev = click->fIOrig;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000414
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000415 click->fOrig.iset(x, y);
416 if (!target->globalToLocal(&click->fOrig)) {
417 // no history to let us recover from this failure
418 return;
419 }
420 click->fPrev = click->fCurr = click->fOrig;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000422 click->fState = Click::kDown_State;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000423 click->fModifierKeys = modi;
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000424 target->onClick(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000425}
426
reed@google.com4d5c26d2013-01-08 16:17:50 +0000427void SkView::DoClickMoved(Click* click, int x, int y, unsigned modi)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428{
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000429 SkASSERT(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000430
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000431 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
halcanary96fcdcc2015-08-27 07:41:13 -0700432 if (nullptr == target) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000433 return;
434 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000435
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000436 click->fIPrev = click->fICurr;
437 click->fICurr.set(x, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000438
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000439 click->fPrev = click->fCurr;
440 click->fCurr.iset(x, y);
441 if (!target->globalToLocal(&click->fCurr)) {
442 // on failure pretend the mouse didn't move
443 click->fCurr = click->fPrev;
444 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000445
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000446 click->fState = Click::kMoved_State;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000447 click->fModifierKeys = modi;
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000448 target->onClick(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000449}
450
reed@google.com4d5c26d2013-01-08 16:17:50 +0000451void SkView::DoClickUp(Click* click, int x, int y, unsigned modi)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000452{
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000453 SkASSERT(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000454
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000455 SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID);
halcanary96fcdcc2015-08-27 07:41:13 -0700456 if (nullptr == target) {
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000457 return;
458 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000459
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000460 click->fIPrev = click->fICurr;
461 click->fICurr.set(x, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000462
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000463 click->fPrev = click->fCurr;
464 click->fCurr.iset(x, y);
465 if (!target->globalToLocal(&click->fCurr)) {
466 // on failure pretend the mouse didn't move
467 click->fCurr = click->fPrev;
468 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000469
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000470 click->fState = Click::kUp_State;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000471 click->fModifierKeys = modi;
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000472 target->onClick(click);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000473}
474
475//////////////////////////////////////////////////////////////////////
476
reed@android.come72fee52009-11-16 14:52:01 +0000477void SkView::invokeLayout() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000478 SkView::Layout* layout = this->getLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000480 if (layout) {
481 layout->layoutChildren(this);
reed@android.come72fee52009-11-16 14:52:01 +0000482 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000483}
484
reed@android.come72fee52009-11-16 14:52:01 +0000485void SkView::onDraw(SkCanvas* canvas) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000486 Artist* artist = this->getArtist();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000487
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000488 if (artist) {
489 artist->draw(this, canvas);
reed@android.come72fee52009-11-16 14:52:01 +0000490 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000491}
492
reed@android.come72fee52009-11-16 14:52:01 +0000493void SkView::onSizeChange() {}
494
reed@google.com4d5c26d2013-01-08 16:17:50 +0000495bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) {
reed@android.come72fee52009-11-16 14:52:01 +0000496 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000497}
498
reed@google.com4d5c26d2013-01-08 16:17:50 +0000499SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) {
halcanary96fcdcc2015-08-27 07:41:13 -0700500 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000501}
502
reed@android.come72fee52009-11-16 14:52:01 +0000503bool SkView::onClick(Click*) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000504 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000505}
506
reed@android.comf2b98d62010-12-20 18:26:13 +0000507bool SkView::handleInval(const SkRect*) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000508 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000509}
510
511//////////////////////////////////////////////////////////////////////
512
reed@google.coma25c94e2013-06-13 20:20:17 +0000513void SkView::getLocalBounds(SkRect* bounds) const {
514 if (bounds) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000515 bounds->set(0, 0, fWidth, fHeight);
reed@google.coma25c94e2013-06-13 20:20:17 +0000516 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000517}
518
519//////////////////////////////////////////////////////////////////////
520//////////////////////////////////////////////////////////////////////
521
reed@google.coma25c94e2013-06-13 20:20:17 +0000522void SkView::detachFromParent_NoLayout() {
523 this->validate();
halcanary96fcdcc2015-08-27 07:41:13 -0700524 if (fParent == nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000525 return;
reed@google.coma25c94e2013-06-13 20:20:17 +0000526 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000527
reed@google.coma25c94e2013-06-13 20:20:17 +0000528 if (fContainsFocus) {
halcanary96fcdcc2015-08-27 07:41:13 -0700529 (void)this->setFocusView(nullptr);
reed@google.coma25c94e2013-06-13 20:20:17 +0000530 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000531
halcanary96fcdcc2015-08-27 07:41:13 -0700532 this->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000533
halcanary96fcdcc2015-08-27 07:41:13 -0700534 SkView* next = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000535
reed@google.coma25c94e2013-06-13 20:20:17 +0000536 if (fNextSibling != this) { // do we have any siblings
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000537 fNextSibling->fPrevSibling = fPrevSibling;
538 fPrevSibling->fNextSibling = fNextSibling;
539 next = fNextSibling;
540 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000541
reed@google.coma25c94e2013-06-13 20:20:17 +0000542 if (fParent->fFirstChild == this) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000543 fParent->fFirstChild = next;
reed@google.coma25c94e2013-06-13 20:20:17 +0000544 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000545
halcanary96fcdcc2015-08-27 07:41:13 -0700546 fParent = fNextSibling = fPrevSibling = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000547
reed@google.coma25c94e2013-06-13 20:20:17 +0000548 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000549 this->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000550}
551
reed@google.coma25c94e2013-06-13 20:20:17 +0000552void SkView::detachFromParent() {
553 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000554 SkView* parent = fParent;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000555
reed@google.coma25c94e2013-06-13 20:20:17 +0000556 if (parent) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000557 this->detachFromParent_NoLayout();
558 parent->invokeLayout();
559 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000560}
561
reed@google.coma25c94e2013-06-13 20:20:17 +0000562SkView* SkView::attachChildToBack(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 == 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 child->fNextSibling = child;
574 child->fPrevSibling = child;
reed@google.coma25c94e2013-06-13 20:20:17 +0000575 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000576 child->fNextSibling = fFirstChild;
577 child->fPrevSibling = fFirstChild->fPrevSibling;
578 fFirstChild->fPrevSibling->fNextSibling = child;
579 fFirstChild->fPrevSibling = child;
580 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000581
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000582 fFirstChild = child;
583 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 +0000592SkView* SkView::attachChildToFront(SkView* child) {
593 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000594 SkASSERT(child != this);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000595
halcanary96fcdcc2015-08-27 07:41:13 -0700596 if (child == nullptr || (fFirstChild && fFirstChild->fPrevSibling == child))
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000597 goto DONE;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000598
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000599 child->ref();
600 child->detachFromParent_NoLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000601
halcanary96fcdcc2015-08-27 07:41:13 -0700602 if (fFirstChild == nullptr) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000603 fFirstChild = child;
604 child->fNextSibling = child;
605 child->fPrevSibling = child;
reed@google.coma25c94e2013-06-13 20:20:17 +0000606 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000607 child->fNextSibling = fFirstChild;
608 child->fPrevSibling = fFirstChild->fPrevSibling;
609 fFirstChild->fPrevSibling->fNextSibling = child;
610 fFirstChild->fPrevSibling = child;
611 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000612
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000613 child->fParent = this;
halcanary96fcdcc2015-08-27 07:41:13 -0700614 child->inval(nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000615
reed@google.coma25c94e2013-06-13 20:20:17 +0000616 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000617 this->invokeLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000618DONE:
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000619 return child;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000620}
621
reed@google.coma25c94e2013-06-13 20:20:17 +0000622void SkView::detachAllChildren() {
623 this->validate();
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000624 while (fFirstChild)
625 fFirstChild->detachFromParent_NoLayout();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000626}
627
reed@google.coma25c94e2013-06-13 20:20:17 +0000628void SkView::localToGlobal(SkMatrix* matrix) const {
reed@google.comf03bb562011-11-11 21:42:12 +0000629 if (matrix) {
630 matrix->reset();
631 const SkView* view = this;
632 while (view)
633 {
634 matrix->preConcat(view->getLocalMatrix());
635 matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY);
636 view = view->fParent;
637 }
638 }
639}
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000640bool SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const
reed@android.com8a1c16f2008-12-17 15:59:43 +0000641{
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000642 SkASSERT(this);
643
bsalomon49f085d2014-09-05 13:34:00 -0700644 if (local) {
reed@google.comf03bb562011-11-11 21:42:12 +0000645 SkMatrix m;
646 this->localToGlobal(&m);
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000647 if (!m.invert(&m)) {
648 return false;
649 }
reed@google.comf03bb562011-11-11 21:42:12 +0000650 SkPoint p;
reed@google.comf03bb562011-11-11 21:42:12 +0000651 m.mapXY(x, y, &p);
robertphillips@google.com07ef9112012-06-04 13:22:14 +0000652 local->set(p.fX, p.fY);
653 }
654
655 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000656}
657
658//////////////////////////////////////////////////////////////////
659
rmistry@google.comd6176b02012-08-23 18:14:13 +0000660/* Even if the subclass overrides onInflate, they should always be
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000661 sure to call the inherited method, so that we get called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000662*/
reed@google.coma25c94e2013-06-13 20:20:17 +0000663void SkView::onInflate(const SkDOM& dom, const SkDOM::Node* node) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000664 SkScalar x, y;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000665
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000666 x = this->locX();
667 y = this->locY();
668 (void)dom.findScalar(node, "x", &x);
669 (void)dom.findScalar(node, "y", &y);
670 this->setLoc(x, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000671
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000672 x = this->width();
673 y = this->height();
674 (void)dom.findScalar(node, "width", &x);
675 (void)dom.findScalar(node, "height", &y);
676 this->setSize(x, y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000677
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000678 // inflate the flags
reed@android.com8a1c16f2008-12-17 15:59:43 +0000679
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000680 static const char* gFlagNames[] = {
681 "visible", "enabled", "focusable", "flexH", "flexV"
682 };
683 SkASSERT(SK_ARRAY_COUNT(gFlagNames) == kFlagShiftCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000684
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000685 bool b;
686 uint32_t flags = this->getFlags();
687 for (unsigned i = 0; i < SK_ARRAY_COUNT(gFlagNames); i++)
688 if (dom.findBool(node, gFlagNames[i], &b))
689 flags = SkSetClearShift(flags, b, i);
690 this->setFlags(flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000691}
692
reed@google.coma25c94e2013-06-13 20:20:17 +0000693void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000694 this->onInflate(dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000695}
696
reed@google.coma25c94e2013-06-13 20:20:17 +0000697void SkView::onPostInflate(const SkTDict<SkView*>&) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000698 // override in subclass as needed
reed@android.com8a1c16f2008-12-17 15:59:43 +0000699}
700
reed@google.coma25c94e2013-06-13 20:20:17 +0000701void SkView::postInflate(const SkTDict<SkView*>& dict) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000702 this->onPostInflate(dict);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000703
rmistry@google.comd6176b02012-08-23 18:14:13 +0000704 B2FIter iter(this);
705 SkView* child;
halcanary96fcdcc2015-08-27 07:41:13 -0700706 while ((child = iter.next()) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000707 child->postInflate(dict);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000708}
709
710//////////////////////////////////////////////////////////////////
711
reed@google.coma25c94e2013-06-13 20:20:17 +0000712SkView* SkView::sendEventToParents(const SkEvent& evt) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000713 SkView* parent = fParent;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000714
reed@google.coma25c94e2013-06-13 20:20:17 +0000715 while (parent) {
716 if (parent->doEvent(evt)) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000717 return parent;
reed@google.coma25c94e2013-06-13 20:20:17 +0000718 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000719 parent = parent->fParent;
720 }
halcanary96fcdcc2015-08-27 07:41:13 -0700721 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000722}
723
reed@android.com34245c72009-11-03 04:00:48 +0000724SkView* SkView::sendQueryToParents(SkEvent* evt) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000725 SkView* parent = fParent;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000726
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000727 while (parent) {
728 if (parent->doQuery(evt)) {
729 return parent;
reed@android.com34245c72009-11-03 04:00:48 +0000730 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000731 parent = parent->fParent;
732 }
halcanary96fcdcc2015-08-27 07:41:13 -0700733 return nullptr;
reed@android.com34245c72009-11-03 04:00:48 +0000734}
735
reed@android.com8a1c16f2008-12-17 15:59:43 +0000736//////////////////////////////////////////////////////////////////
737//////////////////////////////////////////////////////////////////
738
reed@google.coma25c94e2013-06-13 20:20:17 +0000739SkView::F2BIter::F2BIter(const SkView* parent) {
halcanary96fcdcc2015-08-27 07:41:13 -0700740 fFirstChild = parent ? parent->fFirstChild : nullptr;
741 fChild = fFirstChild ? fFirstChild->fPrevSibling : nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000742}
743
reed@google.coma25c94e2013-06-13 20:20:17 +0000744SkView* SkView::F2BIter::next() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000745 SkView* curr = fChild;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000746
reed@google.coma25c94e2013-06-13 20:20:17 +0000747 if (fChild) {
748 if (fChild == fFirstChild) {
halcanary96fcdcc2015-08-27 07:41:13 -0700749 fChild = nullptr;
reed@google.coma25c94e2013-06-13 20:20:17 +0000750 } else {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000751 fChild = fChild->fPrevSibling;
reed@google.coma25c94e2013-06-13 20:20:17 +0000752 }
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000753 }
754 return curr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000755}
756
reed@google.coma25c94e2013-06-13 20:20:17 +0000757SkView::B2FIter::B2FIter(const SkView* parent) {
halcanary96fcdcc2015-08-27 07:41:13 -0700758 fFirstChild = parent ? parent->fFirstChild : nullptr;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000759 fChild = fFirstChild;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000760}
761
reed@google.coma25c94e2013-06-13 20:20:17 +0000762SkView* SkView::B2FIter::next() {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000763 SkView* curr = fChild;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000764
reed@google.coma25c94e2013-06-13 20:20:17 +0000765 if (fChild) {
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000766 SkView* next = fChild->fNextSibling;
767 if (next == fFirstChild)
halcanary96fcdcc2015-08-27 07:41:13 -0700768 next = nullptr;
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000769 fChild = next;
770 }
771 return curr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000772}
773
774//////////////////////////////////////////////////////////////////
775//////////////////////////////////////////////////////////////////
776
777#ifdef SK_DEBUG
778
reed@google.coma25c94e2013-06-13 20:20:17 +0000779void SkView::validate() const {
reed@google.com079813e2013-06-14 17:46:07 +0000780// SkASSERT(this->getRefCnt() > 0 && this->getRefCnt() < 100);
reed@google.coma25c94e2013-06-13 20:20:17 +0000781 if (fParent) {
782 SkASSERT(fNextSibling);
783 SkASSERT(fPrevSibling);
784 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700785 bool nextNull = nullptr == fNextSibling;
786 bool prevNull = nullptr == fNextSibling;
reed@google.com732c5d52013-06-13 20:48:09 +0000787 SkASSERT(nextNull == prevNull);
reed@google.coma25c94e2013-06-13 20:20:17 +0000788 }
789}
790
reed@android.com8a1c16f2008-12-17 15:59:43 +0000791static inline void show_if_nonzero(const char name[], SkScalar value)
792{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000793 if (value)
794 SkDebugf("%s=\"%g\"", name, value/65536.);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000795}
796
797static void tab(int level)
798{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000799 for (int i = 0; i < level; i++)
800 SkDebugf(" ");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000801}
802
803static void dumpview(const SkView* view, int level, bool recurse)
804{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000805 tab(level);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000806
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000807 SkDebugf("<view");
808 show_if_nonzero(" x", view->locX());
809 show_if_nonzero(" y", view->locY());
810 show_if_nonzero(" width", view->width());
811 show_if_nonzero(" height", view->height());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000812
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000813 if (recurse)
814 {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000815 SkView::B2FIter iter(view);
816 SkView* child;
817 bool noChildren = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000818
halcanary96fcdcc2015-08-27 07:41:13 -0700819 while ((child = iter.next()) != nullptr)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000820 {
821 if (noChildren)
822 SkDebugf(">\n");
823 noChildren = false;
824 dumpview(child, level + 1, true);
825 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000826
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000827 if (!noChildren)
828 {
829 tab(level);
830 SkDebugf("</view>\n");
831 }
832 else
833 goto ONELINER;
834 }
835 else
836 {
837 ONELINER:
838 SkDebugf(" />\n");
839 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000840}
841
842void SkView::dump(bool recurse) const
843{
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000844 dumpview(this, 0, recurse);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000845}
846
847#endif