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