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