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