| |
| /* |
| * 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 "SkWidget.h" |
| #include "SkCanvas.h" |
| #include "SkInterpolator.h" |
| #include "SkTime.h" |
| #include "SkParsePaint.h" |
| |
| #if 0 |
| SkWidgetView::SkWidgetView(U32 flags) : SkView(flags) |
| { |
| } |
| |
| SkWidgetView::~SkWidgetView() |
| { |
| } |
| |
| const char* SkWidgetView::GetEventType() |
| { |
| return "SkWidgetView"; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| ///////////////////////////////////////////////////////////////////////////// |
| |
| class SkTextView::Interp { |
| public: |
| Interp(const SkString& old, SkMSec now, SkMSec dur, AnimaDir dir) : fOldText(old), fInterp(1, 2) |
| { |
| SkScalar x = 0; |
| fInterp.setKeyFrame(0, now, &x, 0); |
| x = SK_Scalar1; |
| if (dir == kBackward_AnimDir) |
| x = -x; |
| fInterp.setKeyFrame(1, now + dur, &x); |
| } |
| bool draw(SkCanvas* canvas, const SkString& newText, SkScalar x, SkScalar y, SkPaint& paint) |
| { |
| SkScalar scale; |
| |
| if (fInterp.timeToValues(SkTime::GetMSecs(), &scale) == SkInterpolator::kFreezeEnd_Result) |
| { |
| canvas->drawText(newText.c_str(), newText.size(), x, y, paint); |
| return false; |
| } |
| else |
| { |
| U8 alpha = paint.getAlpha(); |
| SkScalar above, below; |
| (void)paint.measureText(NULL, 0, &above, &below); |
| SkScalar height = below - above; |
| SkScalar dy = SkScalarMul(height, scale); |
| if (scale < 0) |
| height = -height; |
| |
| // draw the old |
| paint.setAlpha((U8)SkScalarMul(alpha, SK_Scalar1 - SkScalarAbs(scale))); |
| canvas->drawText(fOldText.c_str(), fOldText.size(), x, y - dy, paint); |
| // draw the new |
| paint.setAlpha((U8)SkScalarMul(alpha, SkScalarAbs(scale))); |
| canvas->drawText(newText.c_str(), newText.size(), x, y + height - dy, paint); |
| // restore the paint |
| paint.setAlpha(alpha); |
| return true; |
| } |
| } |
| |
| private: |
| SkString fOldText; |
| SkInterpolator fInterp; |
| }; |
| |
| SkTextView::SkTextView(U32 flags) : SkView(flags), fInterp(NULL), fDoInterp(false) |
| { |
| fMargin.set(0, 0); |
| } |
| |
| SkTextView::~SkTextView() |
| { |
| delete fInterp; |
| } |
| |
| void SkTextView::getText(SkString* str) const |
| { |
| if (str) |
| str->set(fText); |
| } |
| |
| void SkTextView::setText(const char text[], AnimaDir dir) |
| { |
| if (!fText.equals(text)) |
| { |
| SkString tmp(text); |
| this->privSetText(tmp, dir); |
| } |
| } |
| |
| void SkTextView::setText(const char text[], size_t len, AnimaDir dir) |
| { |
| if (!fText.equals(text)) |
| { |
| SkString tmp(text, len); |
| this->privSetText(tmp, dir); |
| } |
| } |
| |
| void SkTextView::setText(const SkString& src, AnimaDir dir) |
| { |
| if (fText != src) |
| this->privSetText(src, dir); |
| } |
| |
| void SkTextView::privSetText(const SkString& src, AnimaDir dir) |
| { |
| SkASSERT(fText != src); |
| |
| if (fDoInterp) |
| { |
| if (fInterp) |
| delete fInterp; |
| fInterp = new Interp(fText, SkTime::GetMSecs(), 500, dir); |
| } |
| fText = src; |
| this->inval(NULL); |
| } |
| |
| ///////////////////////////////////////////////////////////////// |
| |
| void SkTextView::getMargin(SkPoint* margin) const |
| { |
| if (margin) |
| *margin = fMargin; |
| } |
| |
| void SkTextView::setMargin(const SkPoint& margin) |
| { |
| if (fMargin != margin) |
| { |
| fMargin = margin; |
| this->inval(NULL); |
| } |
| } |
| |
| void SkTextView::onDraw(SkCanvas* canvas) |
| { |
| this->INHERITED::onDraw(canvas); |
| |
| if (fText.size() == 0) |
| return; |
| |
| SkPaint::Align align = fPaint.getTextAlign(); |
| SkScalar x, y; |
| |
| switch (align) { |
| case SkPaint::kLeft_Align: |
| x = fMargin.fX; |
| break; |
| case SkPaint::kCenter_Align: |
| x = SkScalarHalf(this->width()); |
| break; |
| default: |
| SkASSERT(align == SkPaint::kRight_Align); |
| x = this->width() - fMargin.fX; |
| break; |
| } |
| |
| fPaint.measureText(NULL, 0, &y, NULL); |
| y = fMargin.fY - y; |
| |
| if (fInterp) |
| { |
| if (fInterp->draw(canvas, fText, x, y, fPaint)) |
| this->inval(NULL); |
| else |
| { |
| delete fInterp; |
| fInterp = NULL; |
| } |
| } |
| else |
| canvas->drawText(fText.c_str(), fText.size(), x, y, fPaint); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////////////// |
| |
| void SkTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node) |
| { |
| this->INHERITED::onInflate(dom, node); |
| |
| const char* text = dom.findAttr(node, "text"); |
| if (text) |
| this->setText(text); |
| |
| SkPoint margin; |
| if (dom.findScalars(node, "margin", (SkScalar*)&margin, 2)) |
| this->setMargin(margin); |
| (void)dom.findBool(node, "do-interp", &fDoInterp); |
| |
| SkPaint_Inflate(&fPaint, dom, node); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////////////// |
| |
| SkSliderView::SkSliderView(U32 flags) : SkWidgetView(flags) |
| { |
| fValue = 0; |
| fMax = 0; |
| } |
| |
| static U16 actual_value(U16CPU value, U16CPU max) |
| { |
| return SkToU16(SkMax32(0, SkMin32(value, max))); |
| } |
| |
| void SkSliderView::setMax(U16CPU max) |
| { |
| if (fMax != max) |
| { |
| fMax = SkToU16(max); |
| if (fValue > 0) |
| this->inval(NULL); |
| } |
| } |
| |
| void SkSliderView::setValue(U16CPU value) |
| { |
| if (fValue != value) |
| { |
| U16 prev = actual_value(fValue, fMax); |
| U16 next = actual_value(value, fMax); |
| |
| fValue = SkToU16(value); |
| if (prev != next) |
| { |
| this->inval(NULL); |
| |
| if (this->hasListeners()) |
| { |
| SkEvent evt; |
| |
| evt.setType(SkWidgetView::GetEventType()); |
| evt.setFast32(this->getSinkID()); |
| evt.setS32("sliderValue", next); |
| this->postToListeners(evt); |
| } |
| } |
| } |
| } |
| |
| #include "SkGradientShader.h" |
| |
| static void setgrad(SkPaint* paint, const SkRect& r) |
| { |
| SkPoint pts[2]; |
| SkColor colors[2]; |
| |
| #if 0 |
| pts[0].set(r.fLeft, r.fTop); |
| pts[1].set(r.fLeft + r.height(), r.fBottom); |
| #else |
| pts[0].set(r.fRight, r.fBottom); |
| pts[1].set(r.fRight - r.height(), r.fTop); |
| #endif |
| colors[0] = SK_ColorBLUE; |
| colors[1] = SK_ColorWHITE; |
| |
| paint->setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kMirror_TileMode))->unref(); |
| } |
| |
| void SkSliderView::onDraw(SkCanvas* canvas) |
| { |
| this->INHERITED::onDraw(canvas); |
| |
| U16CPU value = SkMax32(0, SkMin32(fValue, fMax)); |
| |
| SkRect r; |
| SkPaint p; |
| |
| r.set(0, 0, this->width(), this->height()); |
| |
| p.setAntiAliasOn(true); |
| p.setStyle(SkPaint::kStroke_Style); |
| p.setStrokeWidth(SK_Scalar1); |
| r.inset(SK_Scalar1/2, SK_Scalar1/2); |
| canvas->drawRect(r, p); |
| |
| if (fMax) |
| { |
| SkFixed percent = SkFixedDiv(value, fMax); |
| |
| r.inset(SK_Scalar1/2, SK_Scalar1/2); |
| r.fRight = r.fLeft + SkScalarMul(r.width(), SkFixedToScalar(percent)); |
| p.setStyle(SkPaint::kFill_Style); |
| setgrad(&p, r); |
| canvas->drawRect(r, p); |
| } |
| |
| #if 0 |
| r.set(0, 0, this->width(), this->height()); |
| r.inset(SK_Scalar1, SK_Scalar1); |
| r.inset(r.width()/2, 0); |
| p.setColor(SK_ColorBLACK); |
| canvas->drawLine(*(SkPoint*)&r.fLeft, *(SkPoint*)&r.fRight, p); |
| #endif |
| } |
| |
| SkView::Click* SkSliderView::onFindClickHandler(SkScalar x, SkScalar y) |
| { |
| return new Click(this); |
| } |
| |
| bool SkSliderView::onClick(Click* click) |
| { |
| if (fMax) |
| { |
| SkScalar percent = SkScalarDiv(click->fCurr.fX + SK_Scalar1, this->width() - SK_Scalar1*2); |
| percent = SkMaxScalar(0, SkMinScalar(percent, SK_Scalar1)); |
| this->setValue(SkScalarRound(percent * fMax)); |
| return true; |
| } |
| return false; |
| } |
| |
| #endif |
| |