Home | History | Annotate | Download | only in views
      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 "SkWidget.h"
      9 #include "SkCanvas.h"
     10 #include "SkInterpolator.h"
     11 #include "SkTime.h"
     12 #include "SkParsePaint.h"
     13 
     14 #if 0
     15 SkWidgetView::SkWidgetView(U32 flags) : SkView(flags)
     16 {
     17 }
     18 
     19 SkWidgetView::~SkWidgetView()
     20 {
     21 }
     22 
     23 const char* SkWidgetView::GetEventType()
     24 {
     25 	return "SkWidgetView";
     26 }
     27 
     28 /////////////////////////////////////////////////////////////////////////////
     29 /////////////////////////////////////////////////////////////////////////////
     30 
     31 class SkTextView::Interp {
     32 public:
     33 	Interp(const SkString& old, SkMSec now, SkMSec dur, AnimaDir dir) : fOldText(old), fInterp(1, 2)
     34 	{
     35 		SkScalar x = 0;
     36 		fInterp.setKeyFrame(0, now, &x, 0);
     37 		x = SK_Scalar1;
     38 		if (dir == kBackward_AnimDir)
     39 			x = -x;
     40 		fInterp.setKeyFrame(1, now + dur, &x);
     41 	}
     42 	bool draw(SkCanvas* canvas, const SkString& newText, SkScalar x, SkScalar y, SkPaint& paint)
     43 	{
     44 		SkScalar scale;
     45 
     46 		if (fInterp.timeToValues(SkTime::GetMSecs(), &scale) == SkInterpolator::kFreezeEnd_Result)
     47 		{
     48 			canvas->drawText(newText.c_str(), newText.size(), x, y, paint);
     49 			return false;
     50 		}
     51 		else
     52 		{
     53 			U8 alpha = paint.getAlpha();
     54 			SkScalar above, below;
     55 			(void)paint.measureText(NULL, 0, &above, &below);
     56 			SkScalar height = below - above;
     57 			SkScalar dy = SkScalarMul(height, scale);
     58 			if (scale < 0)
     59 				height = -height;
     60 
     61 			// draw the old
     62 			paint.setAlpha((U8)SkScalarMul(alpha, SK_Scalar1 - SkScalarAbs(scale)));
     63 			canvas->drawText(fOldText.c_str(), fOldText.size(), x, y - dy, paint);
     64 			// draw the new
     65 			paint.setAlpha((U8)SkScalarMul(alpha, SkScalarAbs(scale)));
     66 			canvas->drawText(newText.c_str(), newText.size(), x, y + height - dy, paint);
     67 			// restore the paint
     68 			paint.setAlpha(alpha);
     69 			return true;
     70 		}
     71 	}
     72 
     73 private:
     74 	SkString		fOldText;
     75 	SkInterpolator	fInterp;
     76 };
     77 
     78 SkTextView::SkTextView(U32 flags) : SkView(flags), fInterp(NULL), fDoInterp(false)
     79 {
     80 	fMargin.set(0, 0);
     81 }
     82 
     83 SkTextView::~SkTextView()
     84 {
     85 	delete fInterp;
     86 }
     87 
     88 void SkTextView::getText(SkString* str) const
     89 {
     90 	if (str)
     91 		str->set(fText);
     92 }
     93 
     94 void SkTextView::setText(const char text[], AnimaDir dir)
     95 {
     96 	if (!fText.equals(text))
     97 	{
     98 		SkString tmp(text);
     99 		this->privSetText(tmp, dir);
    100 	}
    101 }
    102 
    103 void SkTextView::setText(const char text[], size_t len, AnimaDir dir)
    104 {
    105 	if (!fText.equals(text))
    106 	{
    107 		SkString tmp(text, len);
    108 		this->privSetText(tmp, dir);
    109 	}
    110 }
    111 
    112 void SkTextView::setText(const SkString& src, AnimaDir dir)
    113 {
    114 	if (fText != src)
    115 		this->privSetText(src, dir);
    116 }
    117 
    118 void SkTextView::privSetText(const SkString& src, AnimaDir dir)
    119 {
    120 	SkASSERT(fText != src);
    121 
    122 	if (fDoInterp)
    123 	{
    124 		if (fInterp)
    125 			delete fInterp;
    126 		fInterp = new Interp(fText, SkTime::GetMSecs(), 500, dir);
    127 	}
    128 	fText = src;
    129 	this->inval(NULL);
    130 }
    131 
    132 /////////////////////////////////////////////////////////////////
    133 
    134 void SkTextView::getMargin(SkPoint* margin) const
    135 {
    136 	if (margin)
    137 		*margin = fMargin;
    138 }
    139 
    140 void SkTextView::setMargin(const SkPoint& margin)
    141 {
    142 	if (fMargin != margin)
    143 	{
    144 		fMargin = margin;
    145 		this->inval(NULL);
    146 	}
    147 }
    148 
    149 void SkTextView::onDraw(SkCanvas* canvas)
    150 {
    151 	this->INHERITED::onDraw(canvas);
    152 
    153 	if (fText.size() == 0)
    154 		return;
    155 
    156 	SkPaint::Align	align = fPaint.getTextAlign();
    157 	SkScalar		x, y;
    158 
    159 	switch (align) {
    160 	case SkPaint::kLeft_Align:
    161 		x = fMargin.fX;
    162 		break;
    163 	case SkPaint::kCenter_Align:
    164 		x = SkScalarHalf(this->width());
    165 		break;
    166 	default:
    167 		SkASSERT(align == SkPaint::kRight_Align);
    168 		x = this->width() - fMargin.fX;
    169 		break;
    170 	}
    171 
    172 	fPaint.measureText(NULL, 0, &y, NULL);
    173 	y = fMargin.fY - y;
    174 
    175 	if (fInterp)
    176 	{
    177 		if (fInterp->draw(canvas, fText, x, y, fPaint))
    178 			this->inval(NULL);
    179 		else
    180 		{
    181 			delete fInterp;
    182 			fInterp = NULL;
    183 		}
    184 	}
    185 	else
    186 		canvas->drawText(fText.c_str(), fText.size(), x, y, fPaint);
    187 }
    188 
    189 //////////////////////////////////////////////////////////////////////////////////////
    190 
    191 void SkTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
    192 {
    193 	this->INHERITED::onInflate(dom, node);
    194 
    195 	const char* text = dom.findAttr(node, "text");
    196 	if (text)
    197 		this->setText(text);
    198 
    199 	SkPoint	margin;
    200 	if (dom.findScalars(node, "margin", (SkScalar*)&margin, 2))
    201 		this->setMargin(margin);
    202 	(void)dom.findBool(node, "do-interp", &fDoInterp);
    203 
    204 	SkPaint_Inflate(&fPaint, dom, node);
    205 }
    206 
    207 //////////////////////////////////////////////////////////////////////////////////////
    208 
    209 SkSliderView::SkSliderView(U32 flags) : SkWidgetView(flags)
    210 {
    211 	fValue = 0;
    212 	fMax = 0;
    213 }
    214 
    215 static U16 actual_value(U16CPU value, U16CPU max)
    216 {
    217 	return SkToU16(SkMax32(0, SkMin32(value, max)));
    218 }
    219 
    220 void SkSliderView::setMax(U16CPU max)
    221 {
    222 	if (fMax != max)
    223 	{
    224 		fMax = SkToU16(max);
    225 		if (fValue > 0)
    226 			this->inval(NULL);
    227 	}
    228 }
    229 
    230 void SkSliderView::setValue(U16CPU value)
    231 {
    232 	if (fValue != value)
    233 	{
    234 		U16 prev = actual_value(fValue, fMax);
    235 		U16 next = actual_value(value, fMax);
    236 
    237 		fValue = SkToU16(value);
    238 		if (prev != next)
    239 		{
    240 			this->inval(NULL);
    241 
    242 			if (this->hasListeners())
    243 			{
    244 				SkEvent	evt;
    245 
    246 				evt.setType(SkWidgetView::GetEventType());
    247 				evt.setFast32(this->getSinkID());
    248 				evt.setS32("sliderValue", next);
    249 				this->postToListeners(evt);
    250 			}
    251 		}
    252 	}
    253 }
    254 
    255 #include "SkGradientShader.h"
    256 
    257 static void setgrad(SkPaint* paint, const SkRect& r)
    258 {
    259 	SkPoint	pts[2];
    260 	SkColor	colors[2];
    261 
    262 #if 0
    263 	pts[0].set(r.fLeft, r.fTop);
    264 	pts[1].set(r.fLeft + r.height(), r.fBottom);
    265 #else
    266 	pts[0].set(r.fRight, r.fBottom);
    267 	pts[1].set(r.fRight - r.height(), r.fTop);
    268 #endif
    269 	colors[0] = SK_ColorBLUE;
    270 	colors[1] = SK_ColorWHITE;
    271 
    272 	paint->setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kMirror_TileMode))->unref();
    273 }
    274 
    275 void SkSliderView::onDraw(SkCanvas* canvas)
    276 {
    277 	this->INHERITED::onDraw(canvas);
    278 
    279 	U16CPU value = SkMax32(0, SkMin32(fValue, fMax));
    280 
    281 	SkRect	r;
    282 	SkPaint	p;
    283 
    284 	r.set(0, 0, this->width(), this->height());
    285 
    286 	p.setAntiAliasOn(true);
    287 	p.setStyle(SkPaint::kStroke_Style);
    288 	p.setStrokeWidth(SK_Scalar1);
    289 	r.inset(SK_Scalar1/2, SK_Scalar1/2);
    290 	canvas->drawRect(r, p);
    291 
    292 	if (fMax)
    293 	{
    294 		SkFixed percent = SkFixedDiv(value, fMax);
    295 
    296 		r.inset(SK_Scalar1/2, SK_Scalar1/2);
    297 		r.fRight = r.fLeft + SkScalarMul(r.width(), SkFixedToScalar(percent));
    298 		p.setStyle(SkPaint::kFill_Style);
    299 		setgrad(&p, r);
    300 		canvas->drawRect(r, p);
    301 	}
    302 
    303 #if 0
    304 	r.set(0, 0, this->width(), this->height());
    305 	r.inset(SK_Scalar1, SK_Scalar1);
    306 	r.inset(r.width()/2, 0);
    307 	p.setColor(SK_ColorBLACK);
    308 	canvas->drawLine(*(SkPoint*)&r.fLeft, *(SkPoint*)&r.fRight, p);
    309 #endif
    310 }
    311 
    312 SkView::Click* SkSliderView::onFindClickHandler(SkScalar x, SkScalar y)
    313 {
    314 	return new Click(this);
    315 }
    316 
    317 bool SkSliderView::onClick(Click* click)
    318 {
    319 	if (fMax)
    320 	{
    321 		SkScalar percent = SkScalarDiv(click->fCurr.fX + SK_Scalar1, this->width() - SK_Scalar1*2);
    322 		percent = SkMaxScalar(0, SkMinScalar(percent, SK_Scalar1));
    323 		this->setValue(SkScalarRound(percent * fMax));
    324 		return true;
    325 	}
    326 	return false;
    327 }
    328 
    329 #endif
    330 
    331