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