decorated_textfield.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/views/autofill/decorated_textfield.h"
6
7#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
8#include "chrome/browser/ui/views/autofill/tooltip_icon.h"
9#include "ui/gfx/canvas.h"
10#include "ui/views/background.h"
11#include "ui/views/controls/button/label_button.h"
12#include "ui/views/controls/focusable_border.h"
13#include "ui/views/controls/textfield/textfield_controller.h"
14
15namespace {
16
17// Padding around icons inside DecoratedTextfields.
18const int kTextfieldIconPadding = 3;
19
20}  // namespace
21
22namespace autofill {
23
24// static
25const char DecoratedTextfield::kViewClassName[] = "autofill/DecoratedTextfield";
26
27DecoratedTextfield::DecoratedTextfield(
28    const base::string16& default_value,
29    const base::string16& placeholder,
30    views::TextfieldController* controller)
31    : invalid_(false),
32      editable_(true) {
33  UpdateBackground();
34  UpdateBorder();
35
36  set_placeholder_text(placeholder);
37  SetText(default_value);
38  set_controller(controller);
39}
40
41DecoratedTextfield::~DecoratedTextfield() {}
42
43void DecoratedTextfield::SetInvalid(bool invalid) {
44  if (invalid_ == invalid)
45    return;
46
47  invalid_ = invalid;
48  UpdateBorder();
49  SchedulePaint();
50}
51
52void DecoratedTextfield::SetEditable(bool editable) {
53  if (editable_ == editable)
54    return;
55
56  editable_ = editable;
57  UpdateBorder();
58  UpdateBackground();
59  SetEnabled(editable);
60  IconChanged();
61}
62
63void DecoratedTextfield::SetIcon(const gfx::Image& icon) {
64  if (!icon_view_ && icon.IsEmpty())
65    return;
66
67  if (icon_view_)
68    RemoveChildView(icon_view_.get());
69
70  if (!icon.IsEmpty()) {
71    icon_view_.reset(new views::ImageView());
72    icon_view_->set_owned_by_client();
73    icon_view_->SetImage(icon.ToImageSkia());
74    AddChildView(icon_view_.get());
75  }
76
77  IconChanged();
78}
79
80void DecoratedTextfield::SetTooltipIcon(const base::string16& text) {
81  if (!icon_view_ && text.empty())
82    return;
83
84  if (icon_view_)
85    RemoveChildView(icon_view_.get());
86
87  if (!text.empty()) {
88    icon_view_.reset(new TooltipIcon(text));
89    AddChildView(icon_view_.get());
90  }
91
92  IconChanged();
93}
94
95base::string16 DecoratedTextfield::GetPlaceholderText() const {
96  return editable_ ? views::Textfield::GetPlaceholderText() : base::string16();
97}
98
99const char* DecoratedTextfield::GetClassName() const {
100  return kViewClassName;
101}
102
103views::View* DecoratedTextfield::GetEventHandlerForRect(const gfx::Rect& rect) {
104  views::View* handler = views::Textfield::GetEventHandlerForRect(rect);
105  if (handler->GetClassName() == TooltipIcon::kViewClassName)
106    return handler;
107  return this;
108}
109
110gfx::Size DecoratedTextfield::GetPreferredSize() {
111  static const int height =
112      views::LabelButton(NULL, base::string16()).GetPreferredSize().height();
113  const gfx::Size size = views::Textfield::GetPreferredSize();
114  return gfx::Size(size.width(), std::max(size.height(), height));
115}
116
117void DecoratedTextfield::Layout() {
118  views::Textfield::Layout();
119
120  if (icon_view_ && icon_view_->visible()) {
121    gfx::Rect bounds = GetContentsBounds();
122    gfx::Size icon_size = icon_view_->GetPreferredSize();
123    int x = base::i18n::IsRTL() ?
124        kTextfieldIconPadding :
125        bounds.right() - icon_size.width() - kTextfieldIconPadding;
126    // Vertically centered.
127    int y = bounds.y() + (bounds.height() - icon_size.height()) / 2;
128    icon_view_->SetBounds(x, y, icon_size.width(), icon_size.height());
129  }
130}
131
132void DecoratedTextfield::UpdateBackground() {
133  if (editable_)
134    UseDefaultBackgroundColor();
135  else
136    SetBackgroundColor(SK_ColorTRANSPARENT);
137  set_background(
138      views::Background::CreateSolidBackground(GetBackgroundColor()));
139}
140
141void DecoratedTextfield::UpdateBorder() {
142  scoped_ptr<views::FocusableBorder> border(new views::FocusableBorder());
143  if (invalid_)
144    border->SetColor(kWarningColor);
145  else if (!editable_)
146    border->SetColor(SK_ColorTRANSPARENT);
147  SetBorder(border.PassAs<views::Border>());
148}
149
150void DecoratedTextfield::IconChanged() {
151  // Don't show the icon if nothing else is showing.
152  icon_view_->SetVisible(editable_ || !text().empty());
153  Layout();
154}
155
156} // namespace autofill
157