~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to third_party/skia/src/views/SkWidgets.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

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