1 /*
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  */
7 
8 #ifndef SampleCode_DEFINED
9 #define SampleCode_DEFINED
10 
11 #include "Registry.h"
12 #include "SkColor.h"
13 #include "SkMacros.h"
14 #include "SkMetaData.h"
15 #include "SkPoint.h"
16 #include "SkRefCnt.h"
17 #include "SkString.h"
18 
19 class SkAnimTimer;
20 class SkCanvas;
21 class Sample;
22 
23 using SampleFactory = Sample* (*)();
24 using SampleRegistry = sk_tools::Registry<SampleFactory>;
25 
26 #define DEF_SAMPLE(code) \
27     static Sample*          SK_MACRO_APPEND_LINE(F_)() { code } \
28     static SampleRegistry   SK_MACRO_APPEND_LINE(R_)(SK_MACRO_APPEND_LINE(F_));
29 
30 ///////////////////////////////////////////////////////////////////////////////
31 
32 class Sample : public SkRefCnt {
33 public:
Sample()34     Sample()
35         : fBGColor(SK_ColorWHITE)
36         , fWidth(0), fHeight(0)
37         , fHaveCalledOnceBeforeDraw(false)
38     {}
39 
width()40     SkScalar    width() const { return fWidth; }
height()41     SkScalar    height() const { return fHeight; }
42     void        setSize(SkScalar width, SkScalar height);
setSize(const SkPoint & size)43     void        setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); }
setWidth(SkScalar width)44     void        setWidth(SkScalar width) { this->setSize(width, fHeight); }
setHeight(SkScalar height)45     void        setHeight(SkScalar height) { this->setSize(fWidth, height); }
46 
47     /** Call this to have the view draw into the specified canvas. */
48     virtual void draw(SkCanvas* canvas);
49 
50     //  Click handling
51     class Click {
52     public:
53         Click(Sample* target);
54         virtual ~Click();
55 
56         enum State {
57             kDown_State,
58             kMoved_State,
59             kUp_State
60         };
61         enum ModifierKeys {
62             kShift_ModifierKey    = 1 << 0,
63             kControl_ModifierKey  = 1 << 1,
64             kOption_ModifierKey   = 1 << 2,   // same as ALT
65             kCommand_ModifierKey  = 1 << 3,
66         };
67         SkPoint     fOrig, fPrev, fCurr;
68         SkIPoint    fIOrig, fIPrev, fICurr;
69         State       fState;
70         unsigned    fModifierKeys;
71 
72         SkMetaData  fMeta;
73     private:
74         sk_sp<Sample> fTarget;
75 
76         friend class Sample;
77     };
78     Click* findClickHandler(SkScalar x, SkScalar y, unsigned modifierKeys);
79     static void DoClickDown(Click*, int x, int y, unsigned modi);
80     static void DoClickMoved(Click*, int x, int y, unsigned modi);
81     static void DoClickUp(Click*, int x, int y, unsigned modi);
82 
setBGColor(SkColor color)83     void setBGColor(SkColor color) { fBGColor = color; }
animate(const SkAnimTimer & timer)84     bool animate(const SkAnimTimer& timer) { return this->onAnimate(timer); }
85 
86     class Event {
87     public:
88         Event();
89         explicit Event(const char type[]);
90         Event(const Event& src);
91         ~Event();
92 
93         /** Returns true if the event's type matches exactly the specified type (case sensitive) */
94         bool isType(const char type[]) const;
95 
96         /** Return the event's unnamed 32bit field. Default value is 0 */
getFast32()97         uint32_t getFast32() const { return f32; }
98 
99         /** Set the event's unnamed 32bit field. */
setFast32(uint32_t x)100         void setFast32(uint32_t x) { f32 = x; }
101 
102         /** Return true if the event contains the named 32bit field, and return the field
103             in value (if value is non-null). If there is no matching named field, return false
104             and ignore the value parameter.
105         */
106         bool findS32(const char name[], int32_t* value = nullptr) const {
107             return fMeta.findS32(name, value);
108         }
109         /** Return true if the event contains the named SkScalar field, and return the field
110             in value (if value is non-null). If there is no matching named field, return false
111             and ignore the value parameter.
112         */
113         bool findScalar(const char name[], SkScalar* value = nullptr) const {
114             return fMeta.findScalar(name, value);
115         }
116         /** Return true if the event contains the named SkScalar field, and return the fields
117             in value[] (if value is non-null), and return the number of SkScalars in count
118             (if count is non-null). If there is no matching named field, return false
119             and ignore the value and count parameters.
120         */
121         const SkScalar* findScalars(const char name[], int* count, SkScalar values[]=nullptr) const{
122             return fMeta.findScalars(name, count, values);
123         }
124         /** Return the value of the named string field, or nullptr. */
findString(const char name[])125         const char* findString(const char name[]) const { return fMeta.findString(name); }
126         /** Return true if the event contains the named pointer field, and return the field
127             in value (if value is non-null). If there is no matching named field, return false
128             and ignore the value parameter.
129         */
findPtr(const char name[],void ** value)130         bool findPtr(const char name[], void** value) const { return fMeta.findPtr(name, value); }
findBool(const char name[],bool * value)131         bool findBool(const char name[], bool* value) const { return fMeta.findBool(name, value); }
132         const void* findData(const char name[], size_t* byteCount = nullptr) const {
133             return fMeta.findData(name, byteCount);
134         }
135 
136         /** Returns true if ethe event contains the named 32bit field, and if it equals the specified value */
hasS32(const char name[],int32_t value)137         bool hasS32(const char name[], int32_t value) const { return fMeta.hasS32(name, value); }
138         /** Returns true if ethe event contains the named SkScalar field, and if it equals the specified value */
hasScalar(const char name[],SkScalar value)139         bool hasScalar(const char name[], SkScalar value) const { return fMeta.hasScalar(name, value); }
140         /** Returns true if ethe event contains the named string field, and if it equals (using strcmp) the specified value */
hasString(const char name[],const char value[])141         bool hasString(const char name[], const char value[]) const { return fMeta.hasString(name, value); }
142         /** Returns true if ethe event contains the named pointer field, and if it equals the specified value */
hasPtr(const char name[],void * value)143         bool hasPtr(const char name[], void* value) const { return fMeta.hasPtr(name, value); }
hasBool(const char name[],bool value)144         bool hasBool(const char name[], bool value) const { return fMeta.hasBool(name, value); }
hasData(const char name[],const void * data,size_t byteCount)145         bool hasData(const char name[], const void* data, size_t byteCount) const {
146             return fMeta.hasData(name, data, byteCount);
147         }
148 
149         /** Add/replace the named 32bit field to the event. */
setS32(const char name[],int32_t value)150         void setS32(const char name[], int32_t value) { fMeta.setS32(name, value); }
151         /** Add/replace the named SkScalar field to the event. */
setScalar(const char name[],SkScalar value)152         void setScalar(const char name[], SkScalar value) { fMeta.setScalar(name, value); }
153         /** Add/replace the named SkScalar[] field to the event. */
154         SkScalar* setScalars(const char name[], int count, const SkScalar values[] = nullptr) {
155             return fMeta.setScalars(name, count, values);
156         }
157         /** Add/replace the named string field to the event. */
setString(const char name[],const char value[])158         void setString(const char name[], const char value[]) { fMeta.setString(name, value); }
159         /** Add/replace the named pointer field to the event. */
setPtr(const char name[],void * value)160         void setPtr(const char name[], void* value) { fMeta.setPtr(name, value); }
setBool(const char name[],bool value)161         void setBool(const char name[], bool value) { fMeta.setBool(name, value); }
setData(const char name[],const void * data,size_t byteCount)162         void setData(const char name[], const void* data, size_t byteCount) {
163             fMeta.setData(name, data, byteCount);
164         }
165 
166         /** Return the underlying metadata object */
getMetaData()167         SkMetaData& getMetaData() { return fMeta; }
168         /** Return the underlying metadata object */
getMetaData()169         const SkMetaData& getMetaData() const { return fMeta; }
170 
171         ///////////////////////////////////////////////////////////////////////////
172 
173     private:
174         SkMetaData      fMeta;
175         SkString        fType;
176         uint32_t        f32;
177     };
178 
179     /** Pass an event to this object for processing. Returns true if the event was handled. */
180     bool doEvent(const Event&);
181 
182     /** Returns true if the sink (or one of its subclasses) understands the event as a query.
183         If so, the sink may modify the event to communicate its "answer".
184     */
185     bool doQuery(Event* query);
186 
187     static const char* kCharEvtName;
188     static const char* kTitleEvtName;
189     static bool CharQ(const Event&, SkUnichar* outUni);
190     static bool TitleQ(const Event&);
191     static void TitleR(Event*, const char title[]);
192     static bool RequestTitle(Sample* view, SkString* title);
193 
194 protected:
195     /** Override to handle events in your subclass.
196      *  Overriders must call the super class for unhandled events.
197      */
198     virtual bool onEvent(const Event&);
199     virtual bool onQuery(Event*);
200 
201     /** Override to be notified of size changes. Overriders must call the super class. */
202     virtual void onSizeChange();
203 
204     /** Override this if you might handle the click */
205     virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi);
206 
207     /** Override to track clicks. Return true as long as you want to track the pen/mouse. */
208     virtual bool onClick(Click*);
209 
210     virtual void onDrawBackground(SkCanvas*);
211     virtual void onDrawContent(SkCanvas*) = 0;
onAnimate(const SkAnimTimer &)212     virtual bool onAnimate(const SkAnimTimer&) { return false; }
onOnceBeforeDraw()213     virtual void onOnceBeforeDraw() {}
214 
215 private:
216     SkColor fBGColor;
217     SkScalar fWidth, fHeight;
218     bool fHaveCalledOnceBeforeDraw;
219 };
220 
221 #endif
222