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