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
15SkWidgetView::SkWidgetView(U32 flags) : SkView(flags)
16{
17}
18
19SkWidgetView::~SkWidgetView()
20{
21}
22
23const char* SkWidgetView::GetEventType()
24{
25	return "SkWidgetView";
26}
27
28/////////////////////////////////////////////////////////////////////////////
29/////////////////////////////////////////////////////////////////////////////
30
31class SkTextView::Interp {
32public:
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
73private:
74	SkString		fOldText;
75	SkInterpolator	fInterp;
76};
77
78SkTextView::SkTextView(U32 flags) : SkView(flags), fInterp(NULL), fDoInterp(false)
79{
80	fMargin.set(0, 0);
81}
82
83SkTextView::~SkTextView()
84{
85	delete fInterp;
86}
87
88void SkTextView::getText(SkString* str) const
89{
90	if (str)
91		str->set(fText);
92}
93
94void 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
103void 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
112void SkTextView::setText(const SkString& src, AnimaDir dir)
113{
114	if (fText != src)
115		this->privSetText(src, dir);
116}
117
118void 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
134void SkTextView::getMargin(SkPoint* margin) const
135{
136	if (margin)
137		*margin = fMargin;
138}
139
140void SkTextView::setMargin(const SkPoint& margin)
141{
142	if (fMargin != margin)
143	{
144		fMargin = margin;
145		this->inval(NULL);
146	}
147}
148
149void 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
191void 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
209SkSliderView::SkSliderView(U32 flags) : SkWidgetView(flags)
210{
211	fValue = 0;
212	fMax = 0;
213}
214
215static U16 actual_value(U16CPU value, U16CPU max)
216{
217	return SkToU16(SkMax32(0, SkMin32(value, max)));
218}
219
220void 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
230void 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
257static 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
275void 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
312SkView::Click* SkSliderView::onFindClickHandler(SkScalar x, SkScalar y)
313{
314	return new Click(this);
315}
316
317bool 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