1 
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  */
8 #include "SkWidgetViews.h"
9 #include "SkAnimator.h"
10 #include "SkCanvas.h"
11 #include "SkPaint.h"
12 #include "SkStream.h"
13 #include "SkSystemEventTypes.h"
14 
15 /*
16 I have moved this to SkWidgetViews.h
17 enum SkinEnum {
18     kButton_SkinEnum,
19     kProgress_SkinEnum,
20     kScroll_SkinEnum,
21     kStaticText_SkinEnum,
22 
23     kSkinEnumCount
24 };
25 */
26 
get_skin_enum_path(SkinEnum se)27 const char* get_skin_enum_path(SkinEnum se)
28 {
29     SkASSERT((unsigned)se < kSkinEnumCount);
30 
31     static const char* gSkinPaths[] = {
32             "common/default/default/skins/border3.xml",
33             "common/default/default/skins/button.xml",
34             "common/default/default/skins/progressBar.xml",
35             "common/default/default/skins/scrollBar.xml",
36             "common/default/default/skins/statictextpaint.xml"
37     };
38 
39     return gSkinPaths[se];
40 }
41 
init_skin_anim(const char path[],SkAnimator * anim)42 void init_skin_anim(const char path[], SkAnimator* anim) {
43     SkASSERT(path && anim);
44 
45     SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
46     if (!stream.get()) {
47         SkDEBUGF(("init_skin_anim: loading skin failed <%s>\n", path));
48         sk_throw();
49     }
50 
51     if (!anim->decodeStream(stream)) {
52         SkDEBUGF(("init_skin_anim: decoding skin failed <%s>\n", path));
53         sk_throw();
54     }
55 }
56 
init_skin_anim(SkinEnum se,SkAnimator * anim)57 void init_skin_anim(SkinEnum se, SkAnimator* anim)
58 {
59     init_skin_anim(get_skin_enum_path(se), anim);
60 }
61 
init_skin_paint(SkinEnum se,SkPaint * paint)62 void init_skin_paint(SkinEnum se, SkPaint* paint)
63 {
64     SkASSERT(paint);
65 
66     SkAnimator    anim;
67     SkCanvas    canvas;
68 
69     init_skin_anim(se, &anim);
70     anim.draw(&canvas, paint, 0);
71 }
72 
inflate_paint(const SkDOM & dom,const SkDOM::Node * node,SkPaint * paint)73 void inflate_paint(const SkDOM& dom, const SkDOM::Node* node, SkPaint* paint)
74 {
75     SkASSERT(paint);
76 
77     SkAnimator    anim;
78     SkCanvas    canvas;
79 
80     if (!anim.decodeDOM(dom, node))
81     {
82         SkDEBUGF(("inflate_paint: decoding dom failed\n"));
83         SkDEBUGCODE(dom.dump(node);)
84         sk_throw();
85     }
86     anim.draw(&canvas, paint, 0);
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////////////
90 
SkWidgetView()91 SkWidgetView::SkWidgetView() : SkView(SkView::kFocusable_Mask | SkView::kEnabled_Mask)
92 {
93 }
94 
getLabel() const95 const char* SkWidgetView::getLabel() const
96 {
97     return fLabel.c_str();
98 }
99 
getLabel(SkString * label) const100 void SkWidgetView::getLabel(SkString* label) const
101 {
102     if (label)
103         *label = fLabel;
104 }
105 
setLabel(const char label[])106 void SkWidgetView::setLabel(const char label[])
107 {
108     this->setLabel(label, label ? strlen(label) : 0);
109 }
110 
setLabel(const char label[],size_t len)111 void SkWidgetView::setLabel(const char label[], size_t len)
112 {
113     if ((label == nullptr && fLabel.size() != 0) || !fLabel.equals(label, len))
114     {
115         SkString    tmp(label, len);
116 
117         this->onLabelChange(fLabel.c_str(), tmp.c_str());
118         fLabel.swap(tmp);
119     }
120 }
121 
setLabel(const SkString & label)122 void SkWidgetView::setLabel(const SkString& label)
123 {
124     if (fLabel != label)
125     {
126         this->onLabelChange(fLabel.c_str(), label.c_str());
127         fLabel = label;
128     }
129 }
130 
postWidgetEvent()131 bool SkWidgetView::postWidgetEvent()
132 {
133     if (!fEvent.isType(""))
134     {
135         SkEvent    evt(fEvent);    // make a copy since onPrepareWidgetEvent may edit the event
136 
137         if (this->onPrepareWidgetEvent(&evt))
138         {
139             SkDEBUGCODE(evt.dump("SkWidgetView::postWidgetEvent");)
140 
141             this->postToListeners(evt);    // wonder if this should return true if there are > 0 listeners...
142             return true;
143         }
144     }
145     return false;
146 }
147 
onInflate(const SkDOM & dom,const SkDOM::Node * node)148 /*virtual*/ void SkWidgetView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
149 {
150     this->INHERITED::onInflate(dom, node);
151 
152     const char* label = dom.findAttr(node, "label");
153     if (label)
154         this->setLabel(label);
155 
156     if ((node = dom.getFirstChild(node, "event")) != nullptr)
157         fEvent.inflate(dom, node);
158 }
159 
onLabelChange(const char oldLabel[],const char newLabel[])160 /*virtual*/ void SkWidgetView::onLabelChange(const char oldLabel[], const char newLabel[])
161 {
162     this->inval(nullptr);
163 }
164 
165 static const char gWidgetEventSinkIDSlotName[] = "sk-widget-sinkid-slot";
166 
onPrepareWidgetEvent(SkEvent * evt)167 /*virtual*/ bool SkWidgetView::onPrepareWidgetEvent(SkEvent* evt)
168 {
169     evt->setS32(gWidgetEventSinkIDSlotName, this->getSinkID());
170     return true;
171 }
172 
GetWidgetEventSinkID(const SkEvent & evt)173 SkEventSinkID SkWidgetView::GetWidgetEventSinkID(const SkEvent& evt)
174 {
175     int32_t    sinkID;
176 
177     return evt.findS32(gWidgetEventSinkIDSlotName, &sinkID) ? (SkEventSinkID)sinkID : 0;
178 }
179 
180 ///////////////////////////////////////////////////////////////////////////////////////////////////
181 
onEvent(const SkEvent & evt)182 /*virtual*/ bool SkButtonView::onEvent(const SkEvent& evt)
183 {
184     if (evt.isType(SK_EventType_Key) && evt.getFast32() == kOK_SkKey)
185     {
186         this->postWidgetEvent();
187         return true;
188     }
189     return this->INHERITED::onEvent(evt);
190 }
191 
192 ///////////////////////////////////////////////////////////////////////////////////////////////////
193 
SkCheckButtonView()194 SkCheckButtonView::SkCheckButtonView() : fCheckState(kOff_CheckState)
195 {
196 }
197 
setCheckState(CheckState state)198 void SkCheckButtonView::setCheckState(CheckState state)
199 {
200     SkASSERT((unsigned)state <= kUnknown_CheckState);
201 
202     if (fCheckState != state)
203     {
204         this->onCheckStateChange(this->getCheckState(), state);
205         fCheckState = SkToU8(state);
206     }
207 }
208 
onCheckStateChange(CheckState oldState,CheckState newState)209 /*virtual*/ void SkCheckButtonView::onCheckStateChange(CheckState oldState, CheckState newState)
210 {
211     this->inval(nullptr);
212 }
213 
onInflate(const SkDOM & dom,const SkDOM::Node * node)214 /*virtual*/ void SkCheckButtonView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
215 {
216     this->INHERITED::onInflate(dom, node);
217 
218     int index = dom.findList(node, "check-state", "off,on,unknown");
219     if (index >= 0)
220         this->setCheckState((CheckState)index);
221 }
222 
223 static const char gCheckStateSlotName[] = "sk-checkbutton-check-slot";
224 
onPrepareWidgetEvent(SkEvent * evt)225 /*virtual*/ bool SkCheckButtonView::onPrepareWidgetEvent(SkEvent* evt)
226 {
227     // could check if we're "disabled", and return false...
228 
229     evt->setS32(gCheckStateSlotName, this->getCheckState());
230     return true;
231 }
232 
GetWidgetEventCheckState(const SkEvent & evt,CheckState * state)233 bool SkCheckButtonView::GetWidgetEventCheckState(const SkEvent& evt, CheckState* state)
234 {
235     int32_t    state32;
236 
237     if (evt.findS32(gCheckStateSlotName, &state32))
238     {
239         if (state)
240             *state = (CheckState)state32;
241         return true;
242     }
243     return false;
244 }
245 
246 ///////////////////////////////////////////////////////////////////////////////////////////////////
247 ///////////////////////////////////////////////////////////////////////////////////////////////////
248 ///////////////////////////////////////////////////////////////////////////////////////////////////
249 
250 #include "SkTime.h"
251 #include <stdio.h>
252 
253 class SkAnimButtonView : public SkButtonView {
254 public:
SkAnimButtonView()255     SkAnimButtonView()
256     {
257         fAnim.setHostEventSink(this);
258         init_skin_anim(kButton_SkinEnum, &fAnim);
259     }
260 
261 protected:
onLabelChange(const char oldLabel[],const char newLabel[])262     virtual void onLabelChange(const char oldLabel[], const char newLabel[])
263     {
264         this->INHERITED::onLabelChange(oldLabel, newLabel);
265 
266         SkEvent evt("user");
267         evt.setString("id", "setLabel");
268         evt.setString("LABEL", newLabel);
269         fAnim.doUserEvent(evt);
270     }
271 
onFocusChange(bool gainFocus)272     virtual void onFocusChange(bool gainFocus)
273     {
274         this->INHERITED::onFocusChange(gainFocus);
275 
276         SkEvent evt("user");
277         evt.setString("id", "setFocus");
278         evt.setS32("FOCUS", gainFocus);
279         fAnim.doUserEvent(evt);
280     }
281 
onSizeChange()282     virtual void onSizeChange()
283     {
284         this->INHERITED::onSizeChange();
285 
286         SkEvent evt("user");
287         evt.setString("id", "setDim");
288         evt.setScalar("dimX", this->width());
289         evt.setScalar("dimY", this->height());
290         fAnim.doUserEvent(evt);
291     }
292 
onDraw(SkCanvas * canvas)293     virtual void onDraw(SkCanvas* canvas)
294     {
295         SkPaint                        paint;
296         SkAnimator::DifferenceType    diff = fAnim.draw(canvas, &paint, SkTime::GetMSecs());
297 
298         if (diff == SkAnimator::kDifferent)
299             this->inval(nullptr);
300         else if (diff == SkAnimator::kPartiallyDifferent)
301         {
302             SkRect    bounds;
303             fAnim.getInvalBounds(&bounds);
304             this->inval(&bounds);
305         }
306     }
307 
onEvent(const SkEvent & evt)308     virtual bool onEvent(const SkEvent& evt)
309     {
310         if (evt.isType(SK_EventType_Inval))
311         {
312             this->inval(nullptr);
313             return true;
314         }
315         if (evt.isType("recommendDim"))
316         {
317             SkScalar    height;
318 
319             if (evt.findScalar("y", &height))
320                 this->setHeight(height);
321             return true;
322         }
323         return this->INHERITED::onEvent(evt);
324     }
325 
onPrepareWidgetEvent(SkEvent * evt)326     virtual bool onPrepareWidgetEvent(SkEvent* evt)
327     {
328         if (this->INHERITED::onPrepareWidgetEvent(evt))
329         {
330             SkEvent    e("user");
331             e.setString("id", "handlePress");
332             (void)fAnim.doUserEvent(e);
333             return true;
334         }
335         return false;
336     }
337 
338 private:
339     SkAnimator    fAnim;
340 
341     typedef SkButtonView INHERITED;
342 };
343 
344 ////////////////////////////////////////////////////////////////////////////////////////////
345 ////////////////////////////////////////////////////////////////////////////////////////////
346 
SkWidgetFactory(const char name[])347 SkView* SkWidgetFactory(const char name[])
348 {
349     if (name == nullptr)
350         return nullptr;
351 
352     // must be in the same order as the SkSkinWidgetEnum is declared
353     static const char* gNames[] = {
354         "sk-border",
355         "sk-button",
356         "sk-image",
357         "sk-list",
358         "sk-progress",
359         "sk-scroll",
360         "sk-text"
361 
362     };
363 
364     for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); i++)
365         if (!strcmp(gNames[i], name))
366             return SkWidgetFactory((SkWidgetEnum)i);
367 
368     return nullptr;
369 }
370 
371 #include "SkImageView.h"
372 #include "SkProgressBarView.h"
373 #include "SkScrollBarView.h"
374 #include "SkBorderView.h"
375 
SkWidgetFactory(SkWidgetEnum sw)376 SkView* SkWidgetFactory(SkWidgetEnum sw)
377 {
378     switch (sw) {
379     case kBorder_WidgetEnum:
380         return new SkBorderView;
381     case kButton_WidgetEnum:
382         return new SkAnimButtonView;
383     case kImage_WidgetEnum:
384         return new SkImageView;
385     case kList_WidgetEnum:
386         return new SkListView;
387     case kProgress_WidgetEnum:
388         return new SkProgressBarView;
389     case kScroll_WidgetEnum:
390         return new SkScrollBarView;
391     case kText_WidgetEnum:
392         return new SkStaticTextView;
393     default:
394         SkDEBUGFAIL("unknown enum passed to SkWidgetFactory");
395         break;
396     }
397     return nullptr;
398 }
399