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