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 "SkWidgetViews.h"
9#include "SkTextBox.h"
10
11#ifdef SK_DEBUG
12static void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
13{
14    const char* value = dom.findAttr(node, attr);
15    if (value)
16        SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
17}
18#else
19    #define assert_no_attr(dom, node, attr)
20#endif
21
22SkStaticTextView::SkStaticTextView()
23{
24    fMargin.set(0, 0);
25    fMode = kFixedSize_Mode;
26    fSpacingAlign = SkTextBox::kStart_SpacingAlign;
27
28//    init_skin_paint(kStaticText_SkinEnum, &fPaint);
29}
30
31SkStaticTextView::~SkStaticTextView()
32{
33}
34
35void SkStaticTextView::computeSize()
36{
37    if (fMode == kAutoWidth_Mode)
38    {
39        SkScalar width = fPaint.measureText(fText.c_str(), fText.size());
40        this->setWidth(width + fMargin.fX * 2);
41    }
42    else if (fMode == kAutoHeight_Mode)
43    {
44        SkScalar width = this->width() - fMargin.fX * 2;
45        int lines = width > 0 ? SkTextLineBreaker::CountLines(fText.c_str(), fText.size(), fPaint, width) : 0;
46
47        this->setHeight(lines * fPaint.getFontSpacing() + fMargin.fY * 2);
48    }
49}
50
51void SkStaticTextView::setMode(Mode mode)
52{
53    SkASSERT((unsigned)mode < kModeCount);
54
55    if (fMode != mode)
56    {
57        fMode = SkToU8(mode);
58        this->computeSize();
59    }
60}
61
62void SkStaticTextView::setSpacingAlign(SkTextBox::SpacingAlign align)
63{
64    fSpacingAlign = SkToU8(align);
65    this->inval(NULL);
66}
67
68void SkStaticTextView::getMargin(SkPoint* margin) const
69{
70    if (margin)
71        *margin = fMargin;
72}
73
74void SkStaticTextView::setMargin(SkScalar dx, SkScalar dy)
75{
76    if (fMargin.fX != dx || fMargin.fY != dy)
77    {
78        fMargin.set(dx, dy);
79        this->computeSize();
80        this->inval(NULL);
81    }
82}
83
84size_t SkStaticTextView::getText(SkString* text) const
85{
86    if (text)
87        *text = fText;
88    return fText.size();
89}
90
91size_t SkStaticTextView::getText(char text[]) const
92{
93    if (text)
94        memcpy(text, fText.c_str(), fText.size());
95    return fText.size();
96}
97
98void SkStaticTextView::setText(const SkString& text)
99{
100    this->setText(text.c_str(), text.size());
101}
102
103void SkStaticTextView::setText(const char text[])
104{
105    if (text == NULL)
106        text = "";
107    this->setText(text, strlen(text));
108}
109
110void SkStaticTextView::setText(const char text[], size_t len)
111{
112    if (!fText.equals(text, len))
113    {
114        fText.set(text, len);
115        this->computeSize();
116        this->inval(NULL);
117    }
118}
119
120void SkStaticTextView::getPaint(SkPaint* paint) const
121{
122    if (paint)
123        *paint = fPaint;
124}
125
126void SkStaticTextView::setPaint(const SkPaint& paint)
127{
128    if (fPaint != paint)
129    {
130        fPaint = paint;
131        this->computeSize();
132        this->inval(NULL);
133    }
134}
135
136void SkStaticTextView::onDraw(SkCanvas* canvas)
137{
138    this->INHERITED::onDraw(canvas);
139
140    if (fText.isEmpty())
141        return;
142
143    SkTextBox    box;
144
145    box.setMode(fMode == kAutoWidth_Mode ? SkTextBox::kOneLine_Mode : SkTextBox::kLineBreak_Mode);
146    box.setSpacingAlign(this->getSpacingAlign());
147    box.setBox(fMargin.fX, fMargin.fY, this->width() - fMargin.fX, this->height() - fMargin.fY);
148    box.draw(canvas, fText.c_str(), fText.size(), fPaint);
149}
150
151void SkStaticTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
152{
153if (false) { // avoid bit rot, suppress warning
154    this->INHERITED::onInflate(dom, node);
155
156    int    index;
157    if ((index = dom.findList(node, "mode", "fixed,auto-width,auto-height")) >= 0) {
158        this->setMode((Mode)index);
159    } else {
160        assert_no_attr(dom, node, "mode");
161    }
162
163    if ((index = dom.findList(node, "spacing-align", "start,center,end")) >= 0) {
164        this->setSpacingAlign((SkTextBox::SpacingAlign)index);
165    } else {
166        assert_no_attr(dom, node, "spacing-align");
167    }
168
169    SkScalar s[2];
170    if (dom.findScalars(node, "margin", s, 2)) {
171        this->setMargin(s[0], s[1]);
172    } else {
173        assert_no_attr(dom, node, "margin");
174    }
175
176    const char* text = dom.findAttr(node, "text");
177    if (text) {
178        this->setText(text);
179    }
180
181    if ((node = dom.getFirstChild(node, "paint")) != NULL &&
182        (node = dom.getFirstChild(node, "screenplay")) != NULL)
183    {
184// FIXME: Including inflate_paint causes Windows build to fail -- it complains
185//  that SKListView::SkListView is undefined.
186#if 0
187        inflate_paint(dom, node, &fPaint);
188#endif
189    }
190}
191}
192