blob: 5cb6e4aff504808c9d091e19793a645cbbebe8d3 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkView_DEFINED
11#define SkView_DEFINED
12
13#include "SkEventSink.h"
14#include "SkRect.h"
15#include "SkDOM.h"
16#include "SkTDict.h"
17
18class SkCanvas;
19class SkLayerView;
20
21/** \class SkView
22
23 SkView is the base class for screen management. All widgets and controls inherit
24 from SkView.
25*/
26class SkView : public SkEventSink {
27public:
28 enum Flag_Shift {
29 kVisible_Shift,
30 kEnabled_Shift,
31 kFocusable_Shift,
32 kFlexH_Shift,
33 kFlexV_Shift,
reed@android.comf2b98d62010-12-20 18:26:13 +000034 kNoClip_Shift,
reed@android.com8a1c16f2008-12-17 15:59:43 +000035
36 kFlagShiftCount
37 };
38 enum Flag_Mask {
39 kVisible_Mask = 1 << kVisible_Shift, //!< set if the view is visible
40 kEnabled_Mask = 1 << kEnabled_Shift, //!< set if the view is enabled
41 kFocusable_Mask = 1 << kFocusable_Shift, //!< set if the view can receive focus
42 kFlexH_Mask = 1 << kFlexH_Shift, //!< set if the view's width is stretchable
43 kFlexV_Mask = 1 << kFlexV_Shift, //!< set if the view's height is stretchable
reed@android.comf2b98d62010-12-20 18:26:13 +000044 kNoClip_Mask = 1 << kNoClip_Shift, //!< set if the view is not clipped to its bounds
reed@android.com8a1c16f2008-12-17 15:59:43 +000045
46 kAllFlagMasks = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount)
47 };
48
49 SkView(uint32_t flags = 0);
50 virtual ~SkView();
51
52 /** Return the flags associated with the view
53 */
54 uint32_t getFlags() const { return fFlags; }
55 /** Set the flags associated with the view
56 */
57 void setFlags(uint32_t flags);
58
59 /** Helper that returns non-zero if the kVisible_Mask bit is set in the view's flags
60 */
61 int isVisible() const { return fFlags & kVisible_Mask; }
62 int isEnabled() const { return fFlags & kEnabled_Mask; }
63 int isFocusable() const { return fFlags & kFocusable_Mask; }
reed@android.comf2b98d62010-12-20 18:26:13 +000064 int isClipToBounds() const { return !(fFlags & kNoClip_Mask); }
reed@android.com8a1c16f2008-12-17 15:59:43 +000065 /** Helper to set/clear the view's kVisible_Mask flag */
66 void setVisibleP(bool);
67 void setEnabledP(bool);
68 void setFocusableP(bool);
reed@android.comf2b98d62010-12-20 18:26:13 +000069 void setClipToBounds(bool);
reed@android.com8a1c16f2008-12-17 15:59:43 +000070
71 /** Return the view's width */
72 SkScalar width() const { return fWidth; }
73 /** Return the view's height */
74 SkScalar height() const { return fHeight; }
75 /** Set the view's width and height. These must both be >= 0. This does not affect the view's loc */
76 void setSize(SkScalar width, SkScalar height);
77 void setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); }
78 void setWidth(SkScalar width) { this->setSize(width, fHeight); }
79 void setHeight(SkScalar height) { this->setSize(fWidth, height); }
80 /** Return a rectangle set to [0, 0, width, height] */
81 void getLocalBounds(SkRect* bounds) const;
82
83 /** Return the view's left edge */
84 SkScalar locX() const { return fLoc.fX; }
85 /** Return the view's top edge */
86 SkScalar locY() const { return fLoc.fY; }
87 /** Set the view's left and top edge. This does not affect the view's size */
88 void setLoc(SkScalar x, SkScalar y);
89 void setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); }
90 void setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); }
91 void setLocY(SkScalar y) { this->setLoc(fLoc.fX, y); }
92 /** Offset (move) the view by the specified dx and dy. This does not affect the view's size */
93 void offset(SkScalar dx, SkScalar dy);
94
95 /** Call this to have the view draw into the specified canvas. */
reed@android.come522ca52009-11-23 20:10:41 +000096 virtual void draw(SkCanvas* canvas);
97
reed@android.com8a1c16f2008-12-17 15:59:43 +000098 /** Call this to invalidate part of all of a view, requesting that the view's
99 draw method be called. The rectangle parameter specifies the part of the view
100 that should be redrawn. If it is null, it specifies the entire view bounds.
101 */
102 void inval(SkRect* rectOrNull);
103
104 // Focus management
105
106 SkView* getFocusView() const;
107 bool hasFocus() const;
108
109 enum FocusDirection {
110 kNext_FocusDirection,
111 kPrev_FocusDirection,
112
113 kFocusDirectionCount
114 };
115 bool acceptFocus();
116 SkView* moveFocus(FocusDirection);
117
118 // Click handling
119
120 class Click {
121 public:
122 Click(SkView* target);
123 virtual ~Click();
124
125 const char* getType() const { return fType; }
126 bool isType(const char type[]) const;
127 void setType(const char type[]); // does NOT make a copy of the string
128 void copyType(const char type[]); // makes a copy of the string
129
130 enum State {
131 kDown_State,
132 kMoved_State,
133 kUp_State
134 };
135 SkPoint fOrig, fPrev, fCurr;
136 SkIPoint fIOrig, fIPrev, fICurr;
137 State fState;
Scroggod3aed392011-06-22 13:26:56 +0000138 void* fOwner;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139 private:
140 SkEventSinkID fTargetID;
141 char* fType;
142 bool fWeOwnTheType;
143
144 void resetType();
145
146 friend class SkView;
147 };
148 Click* findClickHandler(SkScalar x, SkScalar y);
149
150 static void DoClickDown(Click*, int x, int y);
151 static void DoClickMoved(Click*, int x, int y);
152 static void DoClickUp(Click*, int x, int y);
153
154 /** Send the event to the view's parent, and its parent etc. until one of them
155 returns true from its onEvent call. This view is returned. If no parent handles
156 the event, null is returned.
reed@android.com34245c72009-11-03 04:00:48 +0000157 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158 SkView* sendEventToParents(const SkEvent&);
reed@android.com34245c72009-11-03 04:00:48 +0000159 /** Send the query to the view's parent, and its parent etc. until one of them
160 returns true from its onQuery call. This view is returned. If no parent handles
161 the query, null is returned.
162 */
163 SkView* sendQueryToParents(SkEvent*);
164
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165 // View hierarchy management
166
167 /** Return the view's parent, or null if it has none. This does not affect the parent's reference count. */
168 SkView* getParent() const { return fParent; }
169 SkView* attachChildToFront(SkView* child);
170 /** Attach the child view to this view, and increment the child's reference count. The child view is added
171 such that it will be drawn before all other child views.
172 The child view parameter is returned.
173 */
174 SkView* attachChildToBack(SkView* child);
175 /** If the view has a parent, detach the view from its parent and decrement the view's reference count.
176 If the parent was the only owner of the view, this will cause the view to be deleted.
177 */
178 void detachFromParent();
179 /** Attach the child view to this view, and increment the child's reference count. The child view is added
180 such that it will be drawn after all other child views.
181 The child view parameter is returned.
182 */
183 /** Detach all child views from this view. */
184 void detachAllChildren();
185
186 /** Convert the specified point from global coordinates into view-local coordinates
187 */
188 void globalToLocal(SkPoint* pt) const { if (pt) this->globalToLocal(pt->fX, pt->fY, pt); }
189 /** Convert the specified x,y from global coordinates into view-local coordinates, returning
190 the answer in the local parameter.
191 */
192 void globalToLocal(SkScalar globalX, SkScalar globalY, SkPoint* local) const;
193
194 /** \class F2BIter
195
196 Iterator that will return each of this view's children, in
197 front-to-back order (the order used for clicking). The first
198 call to next() returns the front-most child view. When
199 next() returns null, there are no more child views.
200 */
201 class F2BIter {
202 public:
203 F2BIter(const SkView* parent);
204 SkView* next();
205 private:
206 SkView* fFirstChild, *fChild;
207 };
208
209 /** \class B2FIter
210
211 Iterator that will return each of this view's children, in
212 back-to-front order (the order they are drawn). The first
213 call to next() returns the back-most child view. When
214 next() returns null, there are no more child views.
215 */
216 class B2FIter {
217 public:
218 B2FIter(const SkView* parent);
219 SkView* next();
220 private:
221 SkView* fFirstChild, *fChild;
222 };
223
224 /** \class Artist
225
226 Install a subclass of this in a view (calling setArtist()), and then the
227 default implementation of that view's onDraw() will invoke this object
228 automatically.
229 */
230 class Artist : public SkRefCnt {
231 public:
232 void draw(SkView*, SkCanvas*);
233 void inflate(const SkDOM&, const SkDOM::Node*);
234 protected:
235 virtual void onDraw(SkView*, SkCanvas*) = 0;
236 virtual void onInflate(const SkDOM&, const SkDOM::Node*);
237 };
238 /** Return the artist attached to this view (or null). The artist's reference
239 count is not affected.
240 */
241 Artist* getArtist() const;
242 /** Attach the specified artist (or null) to the view, replacing any existing
243 artist. If the new artist is not null, its reference count is incremented.
244 The artist parameter is returned.
245 */
246 Artist* setArtist(Artist* artist);
247
248 /** \class Layout
249
250 Install a subclass of this in a view (calling setLayout()), and then the
251 default implementation of that view's onLayoutChildren() will invoke
252 this object automatically.
253 */
254 class Layout : public SkRefCnt {
255 public:
256 void layoutChildren(SkView* parent);
257 void inflate(const SkDOM&, const SkDOM::Node*);
258 protected:
259 virtual void onLayoutChildren(SkView* parent) = 0;
260 virtual void onInflate(const SkDOM&, const SkDOM::Node*);
261 };
262
263 /** Return the layout attached to this view (or null). The layout's reference
264 count is not affected.
265 */
266 Layout* getLayout() const;
267 /** Attach the specified layout (or null) to the view, replacing any existing
268 layout. If the new layout is not null, its reference count is incremented.
269 The layout parameter is returned.
270 */
271 Layout* setLayout(Layout*, bool invokeLayoutNow = true);
272 /** If a layout is attached to this view, call its layoutChildren() method
273 */
274 void invokeLayout();
275
276 /** Call this to initialize this view based on the specified XML node
277 */
278 void inflate(const SkDOM& dom, const SkDOM::Node* node);
279 /** After a view hierarchy is inflated, this may be called with a dictionary
280 containing pairs of <name, view*>, where the name string was the view's
281 "id" attribute when it was inflated.
282
283 This will call the virtual onPostInflate for this view, and the recursively
284 call postInflate on all of the view's children.
285 */
286 void postInflate(const SkTDict<SkView*>& ids);
287
288 SkDEBUGCODE(void dump(bool recurse) const;)
289
290protected:
291 /** Override this to draw inside the view. Be sure to call the inherited version too */
292 virtual void onDraw(SkCanvas*);
293 /** Override this to be notified when the view's size changes. Be sure to call the inherited version too */
294 virtual void onSizeChange();
295 /** Override this if you want to handle an inval request from this view or one of its children.
296 Tyically this is only overridden by the by the "window". If your subclass does handle the
297 request, return true so the request will not continue to propogate to the parent.
298 */
reed@android.comf2b98d62010-12-20 18:26:13 +0000299 virtual bool handleInval(const SkRect*);
reed@android.com6c5f6f22009-08-14 16:08:38 +0000300 //! called once before all of the children are drawn (or clipped/translated)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000301 virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; }
reed@android.com6c5f6f22009-08-14 16:08:38 +0000302 //! called once after all of the children are drawn (or clipped/translated)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303 virtual void afterChildren(SkCanvas* orig) {}
reed@android.com6c5f6f22009-08-14 16:08:38 +0000304
305 //! called right before this child's onDraw is called
306 virtual void beforeChild(SkView* child, SkCanvas* canvas) {}
307 //! called right after this child's onDraw is called
308 virtual void afterChild(SkView* child, SkCanvas* canvas) {}
309
reed@android.com8a1c16f2008-12-17 15:59:43 +0000310 /** Override this if you might handle the click
311 */
reed@android.come72fee52009-11-16 14:52:01 +0000312 virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
313 /** Override this to decide if your children are targets for a click.
314 The default returns true, in which case your children views will be
315 candidates for onFindClickHandler. Returning false wil skip the children
316 and just call your onFindClickHandler.
317 */
318 virtual bool onSendClickToChildren(SkScalar x, SkScalar y);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000319 /** Override this to track clicks, returning true as long as you want to track
320 the pen/mouse.
321 */
322 virtual bool onClick(Click*);
323 /** Override this to initialize your subclass from the XML node. Be sure to call the inherited version too */
324 virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node);
325 /** Override this if you want to perform post initialization work based on the ID dictionary built
326 during XML parsing. Be sure to call the inherited version too.
327 */
328 virtual void onPostInflate(const SkTDict<SkView*>&);
329
330public:
331 // default action is to inval the view
332 virtual void onFocusChange(bool gainFocusP);
333protected:
334
335 // override these if you're acting as a layer/host
336 virtual bool onGetFocusView(SkView**) const { return false; }
337 virtual bool onSetFocusView(SkView*) { return false; }
338
339private:
340 SkScalar fWidth, fHeight;
341 SkPoint fLoc;
342 SkView* fParent;
343 SkView* fFirstChild;
344 SkView* fNextSibling;
345 SkView* fPrevSibling;
346 uint8_t fFlags;
347 uint8_t fContainsFocus;
348
349 friend class B2FIter;
350 friend class F2BIter;
351
352 friend class SkLayerView;
353
354 bool setFocusView(SkView* fvOrNull);
355 SkView* acceptFocus(FocusDirection);
356 void detachFromParent_NoLayout();
357};
358
359#endif
360