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