Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / autofill / decorated_textfield.cc
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
15 namespace {
16
17 // Padding around icons inside DecoratedTextfields.
18 const int kTextfieldIconPadding = 3;
19
20 }  // namespace
21
22 namespace autofill {
23
24 // static
25 const char DecoratedTextfield::kViewClassName[] = "autofill/DecoratedTextfield";
26
27 DecoratedTextfield::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
41 DecoratedTextfield::~DecoratedTextfield() {}
42
43 void DecoratedTextfield::SetInvalid(bool invalid) {
44   if (invalid_ == invalid)
45     return;
46
47   invalid_ = invalid;
48   UpdateBorder();
49   SchedulePaint();
50 }
51
52 void DecoratedTextfield::SetEditable(bool editable) {
53   if (editable_ == editable)
54     return;
55
56   editable_ = editable;
57   UpdateBackground();
58   SetEnabled(editable);
59   IconChanged();
60 }
61
62 void DecoratedTextfield::SetIcon(const gfx::Image& icon) {
63   if (!icon_view_ && icon.IsEmpty())
64     return;
65
66   if (icon_view_)
67     RemoveChildView(icon_view_.get());
68
69   if (!icon.IsEmpty()) {
70     icon_view_.reset(new views::ImageView());
71     icon_view_->set_owned_by_client();
72     icon_view_->SetImage(icon.ToImageSkia());
73     AddChildView(icon_view_.get());
74   }
75
76   IconChanged();
77 }
78
79 void DecoratedTextfield::SetTooltipIcon(const base::string16& text) {
80   if (!icon_view_ && text.empty())
81     return;
82
83   if (icon_view_)
84     RemoveChildView(icon_view_.get());
85
86   if (!text.empty()) {
87     icon_view_.reset(new TooltipIcon(text));
88     AddChildView(icon_view_.get());
89   }
90
91   IconChanged();
92 }
93
94 base::string16 DecoratedTextfield::GetPlaceholderText() const {
95   return editable_ ? views::Textfield::GetPlaceholderText() : base::string16();
96 }
97
98 const char* DecoratedTextfield::GetClassName() const {
99   return kViewClassName;
100 }
101
102 views::View* DecoratedTextfield::GetEventHandlerForRect(const gfx::Rect& rect) {
103   views::View* handler = views::Textfield::GetEventHandlerForRect(rect);
104   if (handler->GetClassName() == TooltipIcon::kViewClassName)
105     return handler;
106   return this;
107 }
108
109 gfx::Size DecoratedTextfield::GetPreferredSize() {
110   static const int height =
111       views::LabelButton(NULL, base::string16()).GetPreferredSize().height();
112   const gfx::Size size = views::Textfield::GetPreferredSize();
113   return gfx::Size(size.width(), std::max(size.height(), height));
114 }
115
116 void DecoratedTextfield::Layout() {
117   views::Textfield::Layout();
118
119   if (icon_view_ && icon_view_->visible()) {
120     gfx::Rect bounds = GetContentsBounds();
121     gfx::Size icon_size = icon_view_->GetPreferredSize();
122     int x = base::i18n::IsRTL() ?
123         bounds.x() - icon_size.width() - kTextfieldIconPadding :
124         bounds.right() + kTextfieldIconPadding;
125     // Vertically centered.
126     int y = bounds.y() + (bounds.height() - icon_size.height()) / 2;
127     gfx::Rect icon_bounds(x, y, icon_size.width(), icon_size.height());
128     icon_bounds.set_x(GetMirroredXForRect(icon_bounds));
129     icon_view_->SetBoundsRect(icon_bounds);
130   }
131 }
132
133 void DecoratedTextfield::UpdateBackground() {
134   if (editable_)
135     UseDefaultBackgroundColor();
136   else
137     SetBackgroundColor(SK_ColorTRANSPARENT);
138   set_background(
139       views::Background::CreateSolidBackground(GetBackgroundColor()));
140 }
141
142 void DecoratedTextfield::UpdateBorder() {
143   scoped_ptr<views::FocusableBorder> border(new views::FocusableBorder());
144   if (invalid_)
145     border->SetColor(kWarningColor);
146   else if (!editable_)
147     border->SetColor(SK_ColorTRANSPARENT);
148
149   // Adjust the border insets to include the icon and its padding.
150   if (icon_view_ && icon_view_->visible()) {
151     int w = icon_view_->GetPreferredSize().width() + 2 * kTextfieldIconPadding;
152     gfx::Insets insets = border->GetInsets();
153     int left = insets.left() + (base::i18n::IsRTL() ? w : 0);
154     int right = insets.right() + (base::i18n::IsRTL() ? 0 : w);
155     border->SetInsets(insets.top(), left, insets.bottom(), right);
156   }
157
158   SetBorder(border.PassAs<views::Border>());
159 }
160
161 void DecoratedTextfield::IconChanged() {
162   // Don't show the icon if nothing else is showing.
163   icon_view_->SetVisible(editable_ || !text().empty());
164   UpdateBorder();
165   Layout();
166 }
167
168 } // namespace autofill