/*
* 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