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