180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkWidgetViews.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTextBox.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* value = dom.findAttr(node, attr);
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value)
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define assert_no_attr(dom, node, attr)
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkStaticTextView::SkStaticTextView()
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMargin.set(0, 0);
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fMode = kFixedSize_Mode;
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSpacingAlign = SkTextBox::kStart_SpacingAlign;
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//    init_skin_paint(kStaticText_SkinEnum, &fPaint);
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkStaticTextView::~SkStaticTextView()
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::computeSize()
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fMode == kAutoWidth_Mode)
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar width = fPaint.measureText(fText.c_str(), fText.size());
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setWidth(width + fMargin.fX * 2);
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else if (fMode == kAutoHeight_Mode)
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar width = this->width() - fMargin.fX * 2;
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int lines = width > 0 ? SkTextLineBreaker::CountLines(fText.c_str(), fText.size(), fPaint, width) : 0;
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setHeight(lines * fPaint.getFontSpacing() + fMargin.fY * 2);
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::setMode(Mode mode)
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((unsigned)mode < kModeCount);
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fMode != mode)
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMode = SkToU8(mode);
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->computeSize();
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::setSpacingAlign(SkTextBox::SpacingAlign align)
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSpacingAlign = SkToU8(align);
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->inval(NULL);
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::getMargin(SkPoint* margin) const
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (margin)
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *margin = fMargin;
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::setMargin(SkScalar dx, SkScalar dy)
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fMargin.fX != dx || fMargin.fY != dy)
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMargin.set(dx, dy);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->computeSize();
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->inval(NULL);
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkStaticTextView::getText(SkString* text) const
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (text)
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *text = fText;
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fText.size();
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querusize_t SkStaticTextView::getText(char text[]) const
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (text)
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(text, fText.c_str(), fText.size());
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fText.size();
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::setText(const SkString& text)
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setText(text.c_str(), text.size());
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::setText(const char text[])
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (text == NULL)
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        text = "";
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->setText(text, strlen(text));
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::setText(const char text[], size_t len)
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!fText.equals(text, len))
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fText.set(text, len);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->computeSize();
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->inval(NULL);
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::getPaint(SkPaint* paint) const
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (paint)
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *paint = fPaint;
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::setPaint(const SkPaint& paint)
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fPaint != paint)
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fPaint = paint;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->computeSize();
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->inval(NULL);
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::onDraw(SkCanvas* canvas)
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::onDraw(canvas);
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fText.isEmpty())
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTextBox    box;
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    box.setMode(fMode == kAutoWidth_Mode ? SkTextBox::kOneLine_Mode : SkTextBox::kLineBreak_Mode);
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    box.setSpacingAlign(this->getSpacingAlign());
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    box.setBox(fMargin.fX, fMargin.fY, this->width() - fMargin.fX, this->height() - fMargin.fY);
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    box.draw(canvas, fText.c_str(), fText.size(), fPaint);
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkStaticTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruif (false) { // avoid bit rot, suppress warning
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::onInflate(dom, node);
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int    index;
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((index = dom.findList(node, "mode", "fixed,auto-width,auto-height")) >= 0) {
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setMode((Mode)index);
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        assert_no_attr(dom, node, "mode");
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((index = dom.findList(node, "spacing-align", "start,center,end")) >= 0) {
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setSpacingAlign((SkTextBox::SpacingAlign)index);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        assert_no_attr(dom, node, "spacing-align");
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar s[2];
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (dom.findScalars(node, "margin", s, 2)) {
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setMargin(s[0], s[1]);
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        assert_no_attr(dom, node, "margin");
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* text = dom.findAttr(node, "text");
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (text) {
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->setText(text);
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((node = dom.getFirstChild(node, "paint")) != NULL &&
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        (node = dom.getFirstChild(node, "screenplay")) != NULL)
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// FIXME: Including inflate_paint causes Windows build to fail -- it complains
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  that SKListView::SkListView is undefined.
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        inflate_paint(dom, node, &fPaint);
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
192