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 27 SK_DEFINE_INST_COUNT(SkListSource) 28 29 const 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 44 void 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 59 void init_skin_anim(SkinEnum se, SkAnimator* anim) 60 { 61 init_skin_anim(get_skin_enum_path(se), anim); 62 } 63 64 void 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 75 void 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 93 SkWidgetView::SkWidgetView() : SkView(SkView::kFocusable_Mask | SkView::kEnabled_Mask) 94 { 95 } 96 97 const char* SkWidgetView::getLabel() const 98 { 99 return fLabel.c_str(); 100 } 101 102 void SkWidgetView::getLabel(SkString* label) const 103 { 104 if (label) 105 *label = fLabel; 106 } 107 108 void SkWidgetView::setLabel(const char label[]) 109 { 110 this->setLabel(label, label ? strlen(label) : 0); 111 } 112 113 void 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 124 void 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 133 bool 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 167 static 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 175 SkEventSinkID 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 196 SkCheckButtonView::SkCheckButtonView() : fCheckState(kOff_CheckState) 197 { 198 } 199 200 void 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 225 static 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 235 bool 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 255 class SkAnimButtonView : public SkButtonView { 256 public: 257 SkAnimButtonView() 258 { 259 fAnim.setHostEventSink(this); 260 init_skin_anim(kButton_SkinEnum, &fAnim); 261 } 262 263 protected: 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 340 private: 341 SkAnimator fAnim; 342 343 typedef SkButtonView INHERITED; 344 }; 345 346 //////////////////////////////////////////////////////////////////////////////////////////// 347 //////////////////////////////////////////////////////////////////////////////////////////// 348 349 SkView* 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 378 SkView* 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