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