• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkKey.h"
11 #include "SkParsePaint.h"
12 #include "SkSystemEventTypes.h"
13 #include "SkTextBox.h"
14 
15 #if 0
16 
17 #ifdef SK_DEBUG
18     static void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
19     {
20         const char* value = dom.findAttr(node, attr);
21         if (value)
22             SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
23     }
24 #else
25     #define assert_no_attr(dom, node, attr)
26 #endif
27 
28 #include "SkAnimator.h"
29 #include "SkTime.h"
30 
31 ///////////////////////////////////////////////////////////////////////////////
32 
33 enum SkinType {
34     kPushButton_SkinType,
35     kStaticText_SkinType,
36 
37     kSkinTypeCount
38 };
39 
40 struct SkinSuite {
41     SkinSuite();
42     ~SkinSuite()
43     {
44         for (int i = 0; i < kSkinTypeCount; i++)
45             delete fAnimators[i];
46     }
47 
48     SkAnimator*    get(SkinType);
49 
50 private:
51     SkAnimator*    fAnimators[kSkinTypeCount];
52 };
53 
54 SkinSuite::SkinSuite()
55 {
56     static const char kSkinPath[] = "skins/";
57 
58     static const char* gSkinNames[] = {
59         "pushbutton_skin.xml",
60         "statictext_skin.xml"
61     };
62 
63     for (unsigned i = 0; i < SK_ARRAY_COUNT(gSkinNames); i++)
64     {
65         size_t        len = strlen(gSkinNames[i]);
66         SkString    path(sizeof(kSkinPath) - 1 + len);
67 
68         memcpy(path.writable_str(), kSkinPath, sizeof(kSkinPath) - 1);
69         memcpy(path.writable_str() + sizeof(kSkinPath) - 1, gSkinNames[i], len);
70 
71         fAnimators[i] = new SkAnimator;
72         if (!fAnimators[i]->decodeURI(path.c_str()))
73         {
74             delete fAnimators[i];
75             fAnimators[i] = NULL;
76         }
77     }
78 }
79 
80 SkAnimator* SkinSuite::get(SkinType st)
81 {
82     SkASSERT((unsigned)st < kSkinTypeCount);
83     return fAnimators[st];
84 }
85 
86 static SkinSuite* gSkinSuite;
87 
88 static SkAnimator* get_skin_animator(SkinType st)
89 {
90 #if 0
91     if (gSkinSuite == NULL)
92         gSkinSuite = new SkinSuite;
93     return gSkinSuite->get(st);
94 #else
95     return NULL;
96 #endif
97 }
98 
99 ///////////////////////////////////////////////////////////////////////////////
100 
101 void SkWidget::Init()
102 {
103 }
104 
105 void SkWidget::Term()
106 {
107     delete gSkinSuite;
108 }
109 
110 void SkWidget::onEnabledChange()
111 {
112     this->inval(NULL);
113 }
114 
115 void SkWidget::postWidgetEvent()
116 {
117     if (!fEvent.isType("") && this->hasListeners())
118     {
119         this->prepareWidgetEvent(&fEvent);
120         this->postToListeners(fEvent);
121     }
122 }
123 
124 void SkWidget::prepareWidgetEvent(SkEvent*)
125 {
126     // override in subclass to add any additional fields before posting
127 }
128 
129 void SkWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
130 {
131     this->INHERITED::onInflate(dom, node);
132 
133     if ((node = dom.getFirstChild(node, "event")) != NULL)
134         fEvent.inflate(dom, node);
135 }
136 
137 ///////////////////////////////////////////////////////////////////////////////
138 
139 size_t SkHasLabelWidget::getLabel(SkString* str) const
140 {
141     if (str)
142         *str = fLabel;
143     return fLabel.size();
144 }
145 
146 size_t SkHasLabelWidget::getLabel(char buffer[]) const
147 {
148     if (buffer)
149         memcpy(buffer, fLabel.c_str(), fLabel.size());
150     return fLabel.size();
151 }
152 
153 void SkHasLabelWidget::setLabel(const SkString& str)
154 {
155     this->setLabel(str.c_str(), str.size());
156 }
157 
158 void SkHasLabelWidget::setLabel(const char label[])
159 {
160     this->setLabel(label, strlen(label));
161 }
162 
163 void SkHasLabelWidget::setLabel(const char label[], size_t len)
164 {
165     if (!fLabel.equals(label, len))
166     {
167         fLabel.set(label, len);
168         this->onLabelChange();
169     }
170 }
171 
172 void SkHasLabelWidget::onLabelChange()
173 {
174     // override in subclass
175 }
176 
177 void SkHasLabelWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
178 {
179     this->INHERITED::onInflate(dom, node);
180 
181     const char* text = dom.findAttr(node, "label");
182     if (text)
183         this->setLabel(text);
184 }
185 
186 /////////////////////////////////////////////////////////////////////////////////////
187 
188 void SkButtonWidget::setButtonState(State state)
189 {
190     if (fState != state)
191     {
192         fState = state;
193         this->onButtonStateChange();
194     }
195 }
196 
197 void SkButtonWidget::onButtonStateChange()
198 {
199     this->inval(NULL);
200 }
201 
202 void SkButtonWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
203 {
204     this->INHERITED::onInflate(dom, node);
205 
206     int    index;
207     if ((index = dom.findList(node, "buttonState", "off,on,unknown")) >= 0)
208         this->setButtonState((State)index);
209 }
210 
211 /////////////////////////////////////////////////////////////////////////////////////
212 
213 bool SkPushButtonWidget::onEvent(const SkEvent& evt)
214 {
215     if (evt.isType(SK_EventType_Key) && evt.getFast32() == kOK_SkKey)
216     {
217         this->postWidgetEvent();
218         return true;
219     }
220     return this->INHERITED::onEvent(evt);
221 }
222 
223 static const char* computeAnimatorState(int enabled, int focused, SkButtonWidget::State state)
224 {
225     if (!enabled)
226         return "disabled";
227     if (state == SkButtonWidget::kOn_State)
228     {
229         SkASSERT(focused);
230         return "enabled-pressed";
231     }
232     if (focused)
233         return "enabled-focused";
234     return "enabled";
235 }
236 
237 #include "SkBlurMask.h"
238 #include "SkBlurMaskFilter.h"
239 #include "SkEmbossMaskFilter.h"
240 
241 static void create_emboss(SkPaint* paint, SkScalar radius, bool focus, bool pressed)
242 {
243     SkEmbossMaskFilter::Light    light;
244 
245     light.fDirection[0] = SK_Scalar1/2;
246     light.fDirection[1] = SK_Scalar1/2;
247     light.fDirection[2] = SK_Scalar1/3;
248     light.fAmbient        = 0x48;
249     light.fSpecular        = 0x80;
250 
251     if (pressed)
252     {
253         light.fDirection[0] = -light.fDirection[0];
254         light.fDirection[1] = -light.fDirection[1];
255     }
256     if (focus)
257         light.fDirection[2] += SK_Scalar1/4;
258 
259     SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
260     paint->setMaskFilter(new SkEmbossMaskFilter(sigma, light))->unref();
261 }
262 
263 void SkPushButtonWidget::onDraw(SkCanvas* canvas)
264 {
265     this->INHERITED::onDraw(canvas);
266 
267     SkString label;
268     this->getLabel(&label);
269 
270     SkAnimator* anim = get_skin_animator(kPushButton_SkinType);
271 
272     if (anim)
273     {
274         SkEvent    evt("user");
275 
276         evt.setString("id", "prime");
277         evt.setScalar("prime-width", this->width());
278         evt.setScalar("prime-height", this->height());
279         evt.setString("prime-text", label);
280         evt.setString("prime-state", computeAnimatorState(this->isEnabled(), this->hasFocus(), this->getButtonState()));
281 
282         (void)anim->doUserEvent(evt);
283         SkPaint paint;
284         anim->draw(canvas, &paint, SkTime::GetMSecs());
285     }
286     else
287     {
288         SkRect    r;
289         SkPaint    p;
290 
291         r.set(0, 0, this->width(), this->height());
292         p.setAntiAliasOn(true);
293         p.setColor(SK_ColorBLUE);
294         create_emboss(&p, SkIntToScalar(12)/5, this->hasFocus(), this->getButtonState() == kOn_State);
295         canvas->drawRoundRect(r, SkScalarHalf(this->height()), SkScalarHalf(this->height()), p);
296         p.setMaskFilter(NULL);
297 
298         p.setTextAlign(SkPaint::kCenter_Align);
299 
300         SkTextBox    box;
301         box.setMode(SkTextBox::kOneLine_Mode);
302         box.setSpacingAlign(SkTextBox::kCenter_SpacingAlign);
303         box.setBox(0, 0, this->width(), this->height());
304 
305 //        if (this->getButtonState() == kOn_State)
306 //            p.setColor(SK_ColorRED);
307 //        else
308             p.setColor(SK_ColorWHITE);
309 
310         box.draw(canvas, label.c_str(), label.size(), p);
311     }
312 }
313 
314 SkView::Click* SkPushButtonWidget::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi)
315 {
316     this->acceptFocus();
317     return new Click(this);
318 }
319 
320 bool SkPushButtonWidget::onClick(Click* click)
321 {
322     SkRect    r;
323     State    state = kOff_State;
324 
325     this->getLocalBounds(&r);
326     if (r.contains(click->fCurr))
327     {
328         if (click->fState == Click::kUp_State)
329             this->postWidgetEvent();
330         else
331             state = kOn_State;
332     }
333     this->setButtonState(state);
334     return true;
335 }
336 
337 //////////////////////////////////////////////////////////////////////////////////////////
338 
339 SkStaticTextView::SkStaticTextView(U32 flags) : SkView(flags)
340 {
341     fMargin.set(0, 0);
342     fMode = kFixedSize_Mode;
343     fSpacingAlign = SkTextBox::kStart_SpacingAlign;
344 }
345 
346 SkStaticTextView::~SkStaticTextView()
347 {
348 }
349 
350 void SkStaticTextView::computeSize()
351 {
352     if (fMode == kAutoWidth_Mode)
353     {
354         SkScalar width = fPaint.measureText(fText.c_str(), fText.size(), NULL, NULL);
355         this->setWidth(width + fMargin.fX * 2);
356     }
357     else if (fMode == kAutoHeight_Mode)
358     {
359         SkScalar width = this->width() - fMargin.fX * 2;
360         int lines = width > 0 ? SkTextLineBreaker::CountLines(fText.c_str(), fText.size(), fPaint, width) : 0;
361 
362         SkScalar    before, after;
363         (void)fPaint.measureText(0, NULL, &before, &after);
364 
365         this->setHeight(lines * (after - before) + fMargin.fY * 2);
366     }
367 }
368 
369 void SkStaticTextView::setMode(Mode mode)
370 {
371     SkASSERT((unsigned)mode < kModeCount);
372 
373     if (fMode != mode)
374     {
375         fMode = SkToU8(mode);
376         this->computeSize();
377     }
378 }
379 
380 void SkStaticTextView::setSpacingAlign(SkTextBox::SpacingAlign align)
381 {
382     fSpacingAlign = SkToU8(align);
383     this->inval(NULL);
384 }
385 
386 void SkStaticTextView::getMargin(SkPoint* margin) const
387 {
388     if (margin)
389         *margin = fMargin;
390 }
391 
392 void SkStaticTextView::setMargin(SkScalar dx, SkScalar dy)
393 {
394     if (fMargin.fX != dx || fMargin.fY != dy)
395     {
396         fMargin.set(dx, dy);
397         this->computeSize();
398         this->inval(NULL);
399     }
400 }
401 
402 size_t SkStaticTextView::getText(SkString* text) const
403 {
404     if (text)
405         *text = fText;
406     return fText.size();
407 }
408 
409 size_t SkStaticTextView::getText(char text[]) const
410 {
411     if (text)
412         memcpy(text, fText.c_str(), fText.size());
413     return fText.size();
414 }
415 
416 void SkStaticTextView::setText(const SkString& text)
417 {
418     this->setText(text.c_str(), text.size());
419 }
420 
421 void SkStaticTextView::setText(const char text[])
422 {
423     this->setText(text, strlen(text));
424 }
425 
426 void SkStaticTextView::setText(const char text[], size_t len)
427 {
428     if (!fText.equals(text, len))
429     {
430         fText.set(text, len);
431         this->computeSize();
432         this->inval(NULL);
433     }
434 }
435 
436 void SkStaticTextView::getPaint(SkPaint* paint) const
437 {
438     if (paint)
439         *paint = fPaint;
440 }
441 
442 void SkStaticTextView::setPaint(const SkPaint& paint)
443 {
444     if (fPaint != paint)
445     {
446         fPaint = paint;
447         this->computeSize();
448         this->inval(NULL);
449     }
450 }
451 
452 void SkStaticTextView::onDraw(SkCanvas* canvas)
453 {
454     this->INHERITED::onDraw(canvas);
455 
456     if (fText.isEmpty())
457         return;
458 
459     SkTextBox    box;
460 
461     box.setMode(fMode == kAutoWidth_Mode ? SkTextBox::kOneLine_Mode : SkTextBox::kLineBreak_Mode);
462     box.setSpacingAlign(this->getSpacingAlign());
463     box.setBox(fMargin.fX, fMargin.fY, this->width() - fMargin.fX, this->height() - fMargin.fY);
464     box.draw(canvas, fText.c_str(), fText.size(), fPaint);
465 }
466 
467 void SkStaticTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
468 {
469     this->INHERITED::onInflate(dom, node);
470 
471     int    index;
472     if ((index = dom.findList(node, "mode", "fixed,auto-width,auto-height")) >= 0)
473         this->setMode((Mode)index);
474     else
475         assert_no_attr(dom, node, "mode");
476 
477     if ((index = dom.findList(node, "spacing-align", "start,center,end")) >= 0)
478         this->setSpacingAlign((SkTextBox::SpacingAlign)index);
479     else
480         assert_no_attr(dom, node, "mode");
481 
482     SkScalar s[2];
483     if (dom.findScalars(node, "margin", s, 2))
484         this->setMargin(s[0], s[1]);
485     else
486         assert_no_attr(dom, node, "margin");
487 
488     const char* text = dom.findAttr(node, "text");
489     if (text)
490         this->setText(text);
491 
492     if ((node = dom.getFirstChild(node, "paint")) != NULL)
493         SkPaint_Inflate(&fPaint, dom, node);
494 }
495 
496 /////////////////////////////////////////////////////////////////////////////////////////////////////
497 
498 #include "SkImageDecoder.h"
499 
500 SkBitmapView::SkBitmapView(U32 flags) : SkView(flags)
501 {
502 }
503 
504 SkBitmapView::~SkBitmapView()
505 {
506 }
507 
508 bool SkBitmapView::getBitmap(SkBitmap* bitmap) const
509 {
510     if (bitmap)
511         *bitmap = fBitmap;
512     return fBitmap.colorType() != kUnknown_SkColorType;
513 }
514 
515 void SkBitmapView::setBitmap(const SkBitmap* bitmap, bool viewOwnsPixels)
516 {
517     if (bitmap)
518     {
519         fBitmap = *bitmap;
520         fBitmap.setOwnsPixels(viewOwnsPixels);
521     }
522 }
523 
524 bool SkBitmapView::loadBitmapFromFile(const char path[])
525 {
526     SkBitmap    bitmap;
527 
528     if (SkImageDecoder::DecodeFile(path, &bitmap))
529     {
530         this->setBitmap(&bitmap, true);
531         bitmap.setOwnsPixels(false);
532         return true;
533     }
534     return false;
535 }
536 
537 void SkBitmapView::onDraw(SkCanvas* canvas)
538 {
539     if (fBitmap.colorType() != kUnknown_SkColorType &&
540         fBitmap.width() && fBitmap.height())
541     {
542         SkAutoCanvasRestore    restore(canvas, true);
543         SkPaint                p;
544 
545         p.setFilterType(SkPaint::kBilinear_FilterType);
546         canvas->scale(    this->width() / fBitmap.width(),
547                         this->height() / fBitmap.height(),
548                         0, 0);
549         canvas->drawBitmap(fBitmap, 0, 0, p);
550     }
551 }
552 
553 void SkBitmapView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
554 {
555     this->INHERITED::onInflate(dom, node);
556 
557     const char* src = dom.findAttr(node, "src");
558     if (src)
559         (void)this->loadBitmapFromFile(src);
560 }
561 
562 #endif
563