1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file.
4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/ui/views/autofill/decorated_textfield.h"
6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/views/autofill/tooltip_icon.h"
9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/gfx/canvas.h"
10a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/views/background.h"
11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/views/controls/button/label_button.h"
12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/views/controls/focusable_border.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/views/controls/textfield/textfield_controller.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/views/view_targeter.h"
15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace {
17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Padding around icons inside DecoratedTextfields.
19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const int kTextfieldIconPadding = 3;
20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace
22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace autofill {
24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char DecoratedTextfield::kViewClassName[] = "autofill/DecoratedTextfield";
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DecoratedTextfield::DecoratedTextfield(
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const base::string16& default_value,
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const base::string16& placeholder,
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    views::TextfieldController* controller)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : invalid_(false),
338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      editable_(true) {
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  UpdateBackground();
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateBorder();
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  set_placeholder_text(placeholder);
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SetText(default_value);
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  set_controller(controller);
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetEventTargeter(
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)DecoratedTextfield::~DecoratedTextfield() {}
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DecoratedTextfield::SetInvalid(bool invalid) {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (invalid_ == invalid)
498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  invalid_ = invalid;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateBorder();
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SchedulePaint();
54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DecoratedTextfield::SetEditable(bool editable) {
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (editable_ == editable)
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  editable_ = editable;
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  UpdateBackground();
628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  SetEnabled(editable);
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  IconChanged();
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DecoratedTextfield::SetIcon(const gfx::Image& icon) {
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!icon_view_ && icon.IsEmpty())
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (icon_view_)
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    RemoveChildView(icon_view_.get());
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!icon.IsEmpty()) {
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    icon_view_.reset(new views::ImageView());
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    icon_view_->set_owned_by_client();
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    icon_view_->SetImage(icon.ToImageSkia());
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddChildView(icon_view_.get());
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  IconChanged();
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DecoratedTextfield::SetTooltipIcon(const base::string16& text) {
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!icon_view_ && text.empty())
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (icon_view_)
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    RemoveChildView(icon_view_.get());
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!text.empty()) {
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    icon_view_.reset(new TooltipIcon(text));
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddChildView(icon_view_.get());
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  IconChanged();
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)base::string16 DecoratedTextfield::GetPlaceholderText() const {
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return editable_ ? views::Textfield::GetPlaceholderText() : base::string16();
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char* DecoratedTextfield::GetClassName() const {
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return kViewClassName;
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size DecoratedTextfield::GetPreferredSize() const {
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const int height =
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      views::LabelButton(NULL, base::string16()).GetPreferredSize().height();
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Size size = views::Textfield::GetPreferredSize();
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return gfx::Size(size.width(), std::max(size.height(), height));
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DecoratedTextfield::Layout() {
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  views::Textfield::Layout();
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (icon_view_ && icon_view_->visible()) {
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    gfx::Rect bounds = GetContentsBounds();
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    gfx::Size icon_size = icon_view_->GetPreferredSize();
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int x = base::i18n::IsRTL() ?
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        bounds.x() - icon_size.width() - kTextfieldIconPadding :
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        bounds.right() + kTextfieldIconPadding;
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Vertically centered.
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int y = bounds.y() + (bounds.height() - icon_size.height()) / 2;
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    gfx::Rect icon_bounds(x, y, icon_size.width(), icon_size.height());
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    icon_bounds.set_x(GetMirroredXForRect(icon_bounds));
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    icon_view_->SetBoundsRect(icon_bounds);
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)views::View* DecoratedTextfield::TargetForRect(views::View* root,
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                               const gfx::Rect& rect) {
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK_EQ(root, this);
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  views::View* handler = views::ViewTargeterDelegate::TargetForRect(root, rect);
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (handler->GetClassName() == TooltipIcon::kViewClassName)
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return handler;
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return this;
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void DecoratedTextfield::UpdateBackground() {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (editable_)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UseDefaultBackgroundColor();
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetBackgroundColor(SK_ColorTRANSPARENT);
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  set_background(
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      views::Background::CreateSolidBackground(GetBackgroundColor()));
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DecoratedTextfield::UpdateBorder() {
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<views::FocusableBorder> border(new views::FocusableBorder());
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (invalid_)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    border->SetColor(kWarningColor);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (!editable_)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    border->SetColor(SK_ColorTRANSPARENT);
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Adjust the border insets to include the icon and its padding.
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (icon_view_ && icon_view_->visible()) {
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int w = icon_view_->GetPreferredSize().width() + 2 * kTextfieldIconPadding;
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gfx::Insets insets = border->GetInsets();
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int left = insets.left() + (base::i18n::IsRTL() ? w : 0);
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    int right = insets.right() + (base::i18n::IsRTL() ? 0 : w);
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    border->SetInsets(insets.top(), left, insets.bottom(), right);
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBorder(border.PassAs<views::Border>());
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DecoratedTextfield::IconChanged() {
1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Don't show the icon if nothing else is showing.
1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  icon_view_->SetVisible(editable_ || !text().empty());
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  UpdateBorder();
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Layout();
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} // namespace autofill
176