SkWidgetViews.cpp revision 2880df2609eba09b555ca37be04b6ad89290c765
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
27const 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
42void 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
57void init_skin_anim(SkinEnum se, SkAnimator* anim)
58{
59    init_skin_anim(get_skin_enum_path(se), anim);
60}
61
62void 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
73void 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
91SkWidgetView::SkWidgetView() : SkView(SkView::kFocusable_Mask | SkView::kEnabled_Mask)
92{
93}
94
95const char* SkWidgetView::getLabel() const
96{
97    return fLabel.c_str();
98}
99
100void SkWidgetView::getLabel(SkString* label) const
101{
102    if (label)
103        *label = fLabel;
104}
105
106void SkWidgetView::setLabel(const char label[])
107{
108    this->setLabel(label, label ? strlen(label) : 0);
109}
110
111void 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
122void 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
131bool 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
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
160/*virtual*/ void SkWidgetView::onLabelChange(const char oldLabel[], const char newLabel[])
161{
162    this->inval(nullptr);
163}
164
165static const char gWidgetEventSinkIDSlotName[] = "sk-widget-sinkid-slot";
166
167/*virtual*/ bool SkWidgetView::onPrepareWidgetEvent(SkEvent* evt)
168{
169    evt->setS32(gWidgetEventSinkIDSlotName, this->getSinkID());
170    return true;
171}
172
173SkEventSinkID SkWidgetView::GetWidgetEventSinkID(const SkEvent& evt)
174{
175    int32_t    sinkID;
176
177    return evt.findS32(gWidgetEventSinkIDSlotName, &sinkID) ? (SkEventSinkID)sinkID : 0;
178}
179
180///////////////////////////////////////////////////////////////////////////////////////////////////
181
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
194SkCheckButtonView::SkCheckButtonView() : fCheckState(kOff_CheckState)
195{
196}
197
198void 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
209/*virtual*/ void SkCheckButtonView::onCheckStateChange(CheckState oldState, CheckState newState)
210{
211    this->inval(nullptr);
212}
213
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
223static const char gCheckStateSlotName[] = "sk-checkbutton-check-slot";
224
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
233bool 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
253class SkAnimButtonView : public SkButtonView {
254public:
255    SkAnimButtonView()
256    {
257        fAnim.setHostEventSink(this);
258        init_skin_anim(kButton_SkinEnum, &fAnim);
259    }
260
261protected:
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
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
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
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
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
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
338private:
339    SkAnimator    fAnim;
340
341    typedef SkButtonView INHERITED;
342};
343
344////////////////////////////////////////////////////////////////////////////////////////////
345////////////////////////////////////////////////////////////////////////////////////////////
346
347SkView* 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
376SkView* 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