/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkWidgetViews.h" #include "SkAnimator.h" #include "SkCanvas.h" #include "SkPaint.h" #include "SkStream.h" #include "SkSystemEventTypes.h" /* I have moved this to SkWidgetViews.h enum SkinEnum { kButton_SkinEnum, kProgress_SkinEnum, kScroll_SkinEnum, kStaticText_SkinEnum, kSkinEnumCount }; */ const char* get_skin_enum_path(SkinEnum se) { SkASSERT((unsigned)se < kSkinEnumCount); static const char* gSkinPaths[] = { "common/default/default/skins/border3.xml", "common/default/default/skins/button.xml", "common/default/default/skins/progressBar.xml", "common/default/default/skins/scrollBar.xml", "common/default/default/skins/statictextpaint.xml" }; return gSkinPaths[se]; } void init_skin_anim(const char path[], SkAnimator* anim) { SkASSERT(path && anim); SkAutoTDelete stream(SkStream::NewFromFile(path)); if (!stream.get()) { SkDEBUGF(("init_skin_anim: loading skin failed <%s>\n", path)); sk_throw(); } if (!anim->decodeStream(stream)) { SkDEBUGF(("init_skin_anim: decoding skin failed <%s>\n", path)); sk_throw(); } } void init_skin_anim(SkinEnum se, SkAnimator* anim) { init_skin_anim(get_skin_enum_path(se), anim); } void init_skin_paint(SkinEnum se, SkPaint* paint) { SkASSERT(paint); SkAnimator anim; SkCanvas canvas; init_skin_anim(se, &anim); anim.draw(&canvas, paint, 0); } void inflate_paint(const SkDOM& dom, const SkDOM::Node* node, SkPaint* paint) { SkASSERT(paint); SkAnimator anim; SkCanvas canvas; if (!anim.decodeDOM(dom, node)) { SkDEBUGF(("inflate_paint: decoding dom failed\n")); SkDEBUGCODE(dom.dump(node);) sk_throw(); } anim.draw(&canvas, paint, 0); } //////////////////////////////////////////////////////////////////////////////////////// SkWidgetView::SkWidgetView() : SkView(SkView::kFocusable_Mask | SkView::kEnabled_Mask) { } const char* SkWidgetView::getLabel() const { return fLabel.c_str(); } void SkWidgetView::getLabel(SkString* label) const { if (label) *label = fLabel; } void SkWidgetView::setLabel(const char label[]) { this->setLabel(label, label ? strlen(label) : 0); } void SkWidgetView::setLabel(const char label[], size_t len) { if ((label == nullptr && fLabel.size() != 0) || !fLabel.equals(label, len)) { SkString tmp(label, len); this->onLabelChange(fLabel.c_str(), tmp.c_str()); fLabel.swap(tmp); } } void SkWidgetView::setLabel(const SkString& label) { if (fLabel != label) { this->onLabelChange(fLabel.c_str(), label.c_str()); fLabel = label; } } bool SkWidgetView::postWidgetEvent() { if (!fEvent.isType("")) { SkEvent evt(fEvent); // make a copy since onPrepareWidgetEvent may edit the event if (this->onPrepareWidgetEvent(&evt)) { SkDEBUGCODE(evt.dump("SkWidgetView::postWidgetEvent");) this->postToListeners(evt); // wonder if this should return true if there are > 0 listeners... return true; } } return false; } /*virtual*/ void SkWidgetView::onInflate(const SkDOM& dom, const SkDOM::Node* node) { this->INHERITED::onInflate(dom, node); const char* label = dom.findAttr(node, "label"); if (label) this->setLabel(label); if ((node = dom.getFirstChild(node, "event")) != nullptr) fEvent.inflate(dom, node); } /*virtual*/ void SkWidgetView::onLabelChange(const char oldLabel[], const char newLabel[]) { this->inval(nullptr); } static const char gWidgetEventSinkIDSlotName[] = "sk-widget-sinkid-slot"; /*virtual*/ bool SkWidgetView::onPrepareWidgetEvent(SkEvent* evt) { evt->setS32(gWidgetEventSinkIDSlotName, this->getSinkID()); return true; } SkEventSinkID SkWidgetView::GetWidgetEventSinkID(const SkEvent& evt) { int32_t sinkID; return evt.findS32(gWidgetEventSinkIDSlotName, &sinkID) ? (SkEventSinkID)sinkID : 0; } /////////////////////////////////////////////////////////////////////////////////////////////////// /*virtual*/ bool SkButtonView::onEvent(const SkEvent& evt) { if (evt.isType(SK_EventType_Key) && evt.getFast32() == kOK_SkKey) { this->postWidgetEvent(); return true; } return this->INHERITED::onEvent(evt); } /////////////////////////////////////////////////////////////////////////////////////////////////// SkCheckButtonView::SkCheckButtonView() : fCheckState(kOff_CheckState) { } void SkCheckButtonView::setCheckState(CheckState state) { SkASSERT((unsigned)state <= kUnknown_CheckState); if (fCheckState != state) { this->onCheckStateChange(this->getCheckState(), state); fCheckState = SkToU8(state); } } /*virtual*/ void SkCheckButtonView::onCheckStateChange(CheckState oldState, CheckState newState) { this->inval(nullptr); } /*virtual*/ void SkCheckButtonView::onInflate(const SkDOM& dom, const SkDOM::Node* node) { this->INHERITED::onInflate(dom, node); int index = dom.findList(node, "check-state", "off,on,unknown"); if (index >= 0) this->setCheckState((CheckState)index); } static const char gCheckStateSlotName[] = "sk-checkbutton-check-slot"; /*virtual*/ bool SkCheckButtonView::onPrepareWidgetEvent(SkEvent* evt) { // could check if we're "disabled", and return false... evt->setS32(gCheckStateSlotName, this->getCheckState()); return true; } bool SkCheckButtonView::GetWidgetEventCheckState(const SkEvent& evt, CheckState* state) { int32_t state32; if (evt.findS32(gCheckStateSlotName, &state32)) { if (state) *state = (CheckState)state32; return true; } return false; } /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// #include "SkTime.h" #include class SkAnimButtonView : public SkButtonView { public: SkAnimButtonView() { fAnim.setHostEventSink(this); init_skin_anim(kButton_SkinEnum, &fAnim); } protected: virtual void onLabelChange(const char oldLabel[], const char newLabel[]) { this->INHERITED::onLabelChange(oldLabel, newLabel); SkEvent evt("user"); evt.setString("id", "setLabel"); evt.setString("LABEL", newLabel); fAnim.doUserEvent(evt); } virtual void onFocusChange(bool gainFocus) { this->INHERITED::onFocusChange(gainFocus); SkEvent evt("user"); evt.setString("id", "setFocus"); evt.setS32("FOCUS", gainFocus); fAnim.doUserEvent(evt); } virtual void onSizeChange() { this->INHERITED::onSizeChange(); SkEvent evt("user"); evt.setString("id", "setDim"); evt.setScalar("dimX", this->width()); evt.setScalar("dimY", this->height()); fAnim.doUserEvent(evt); } virtual void onDraw(SkCanvas* canvas) { SkPaint paint; SkAnimator::DifferenceType diff = fAnim.draw(canvas, &paint, SkTime::GetMSecs()); if (diff == SkAnimator::kDifferent) this->inval(nullptr); else if (diff == SkAnimator::kPartiallyDifferent) { SkRect bounds; fAnim.getInvalBounds(&bounds); this->inval(&bounds); } } virtual bool onEvent(const SkEvent& evt) { if (evt.isType(SK_EventType_Inval)) { this->inval(nullptr); return true; } if (evt.isType("recommendDim")) { SkScalar height; if (evt.findScalar("y", &height)) this->setHeight(height); return true; } return this->INHERITED::onEvent(evt); } virtual bool onPrepareWidgetEvent(SkEvent* evt) { if (this->INHERITED::onPrepareWidgetEvent(evt)) { SkEvent e("user"); e.setString("id", "handlePress"); (void)fAnim.doUserEvent(e); return true; } return false; } private: SkAnimator fAnim; typedef SkButtonView INHERITED; }; //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// SkView* SkWidgetFactory(const char name[]) { if (name == nullptr) return nullptr; // must be in the same order as the SkSkinWidgetEnum is declared static const char* gNames[] = { "sk-border", "sk-button", "sk-image", "sk-list", "sk-progress", "sk-scroll", "sk-text" }; for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); i++) if (!strcmp(gNames[i], name)) return SkWidgetFactory((SkWidgetEnum)i); return nullptr; } #include "SkImageView.h" #include "SkProgressBarView.h" #include "SkScrollBarView.h" #include "SkBorderView.h" SkView* SkWidgetFactory(SkWidgetEnum sw) { switch (sw) { case kBorder_WidgetEnum: return new SkBorderView; case kButton_WidgetEnum: return new SkAnimButtonView; case kImage_WidgetEnum: return new SkImageView; case kList_WidgetEnum: return new SkListView; case kProgress_WidgetEnum: return new SkProgressBarView; case kScroll_WidgetEnum: return new SkScrollBarView; case kText_WidgetEnum: return new SkStaticTextView; default: SkDEBUGFAIL("unknown enum passed to SkWidgetFactory"); break; } return nullptr; }