blob: 104429da575408117c7f4791730f97adadb75a36 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#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;
deanm@chromium.org1599a432009-06-04 15:37:11 +000055 (void)paint.measureText(NULL, 0, &above, &below);
reed@android.com8a1c16f2008-12-17 15:59:43 +000056 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
deanm@chromium.org1599a432009-06-04 15:37:11 +000078SkTextView::SkTextView(U32 flags) : SkView(flags), fInterp(NULL), fDoInterp(false)
reed@android.com8a1c16f2008-12-17 15:59:43 +000079{
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;
deanm@chromium.org1599a432009-06-04 15:37:11 +0000129 this->inval(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130}
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;
deanm@chromium.org1599a432009-06-04 15:37:11 +0000145 this->inval(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146 }
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
deanm@chromium.org1599a432009-06-04 15:37:11 +0000172 fPaint.measureText(NULL, 0, &y, NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000173 y = fMargin.fY - y;
174
175 if (fInterp)
176 {
177 if (fInterp->draw(canvas, fText, x, y, fPaint))
deanm@chromium.org1599a432009-06-04 15:37:11 +0000178 this->inval(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 else
180 {
181 delete fInterp;
deanm@chromium.org1599a432009-06-04 15:37:11 +0000182 fInterp = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183 }
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)
deanm@chromium.org1599a432009-06-04 15:37:11 +0000226 this->inval(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227 }
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 {
deanm@chromium.org1599a432009-06-04 15:37:11 +0000240 this->inval(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241
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
deanm@chromium.org1599a432009-06-04 15:37:11 +0000272 paint->setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kMirror_TileMode))->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000273}
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