reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame^] | 1 | #include "SkWidget.h" |
| 2 | #include "SkCanvas.h" |
| 3 | #include "SkInterpolator.h" |
| 4 | #include "SkTime.h" |
| 5 | #include "SkParsePaint.h" |
| 6 | |
| 7 | #if 0 |
| 8 | SkWidgetView::SkWidgetView(U32 flags) : SkView(flags) |
| 9 | { |
| 10 | } |
| 11 | |
| 12 | SkWidgetView::~SkWidgetView() |
| 13 | { |
| 14 | } |
| 15 | |
| 16 | const char* SkWidgetView::GetEventType() |
| 17 | { |
| 18 | return "SkWidgetView"; |
| 19 | } |
| 20 | |
| 21 | ///////////////////////////////////////////////////////////////////////////// |
| 22 | ///////////////////////////////////////////////////////////////////////////// |
| 23 | |
| 24 | class SkTextView::Interp { |
| 25 | public: |
| 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 | |
| 66 | private: |
| 67 | SkString fOldText; |
| 68 | SkInterpolator fInterp; |
| 69 | }; |
| 70 | |
| 71 | SkTextView::SkTextView(U32 flags) : SkView(flags), fInterp(nil), fDoInterp(false) |
| 72 | { |
| 73 | fMargin.set(0, 0); |
| 74 | } |
| 75 | |
| 76 | SkTextView::~SkTextView() |
| 77 | { |
| 78 | delete fInterp; |
| 79 | } |
| 80 | |
| 81 | void SkTextView::getText(SkString* str) const |
| 82 | { |
| 83 | if (str) |
| 84 | str->set(fText); |
| 85 | } |
| 86 | |
| 87 | void 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 | |
| 96 | void 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 | |
| 105 | void SkTextView::setText(const SkString& src, AnimaDir dir) |
| 106 | { |
| 107 | if (fText != src) |
| 108 | this->privSetText(src, dir); |
| 109 | } |
| 110 | |
| 111 | void 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 | |
| 127 | void SkTextView::getMargin(SkPoint* margin) const |
| 128 | { |
| 129 | if (margin) |
| 130 | *margin = fMargin; |
| 131 | } |
| 132 | |
| 133 | void SkTextView::setMargin(const SkPoint& margin) |
| 134 | { |
| 135 | if (fMargin != margin) |
| 136 | { |
| 137 | fMargin = margin; |
| 138 | this->inval(nil); |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | void 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 | |
| 184 | void 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 | |
| 202 | SkSliderView::SkSliderView(U32 flags) : SkWidgetView(flags) |
| 203 | { |
| 204 | fValue = 0; |
| 205 | fMax = 0; |
| 206 | } |
| 207 | |
| 208 | static U16 actual_value(U16CPU value, U16CPU max) |
| 209 | { |
| 210 | return SkToU16(SkMax32(0, SkMin32(value, max))); |
| 211 | } |
| 212 | |
| 213 | void 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 | |
| 223 | void 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 | |
| 250 | static 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 | |
| 268 | void 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 | |
| 305 | SkView::Click* SkSliderView::onFindClickHandler(SkScalar x, SkScalar y) |
| 306 | { |
| 307 | return new Click(this); |
| 308 | } |
| 309 | |
| 310 | bool 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 | |