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 
     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 const int DecoratedTextfield::kMagicInsetNumber = 6;
     28 
     29 DecoratedTextfield::DecoratedTextfield(
     30     const base::string16& default_value,
     31     const base::string16& placeholder,
     32     views::TextfieldController* controller)
     33     : border_(new views::FocusableBorder()),
     34       invalid_(false),
     35       editable_(true) {
     36   UpdateBackground();
     37 
     38   set_border(border_);
     39   // Removes the border from |native_wrapper_|.
     40   RemoveBorder();
     41 
     42   set_placeholder_text(placeholder);
     43   SetText(default_value);
     44   SetController(controller);
     45   SetHorizontalMargins(0, 0);
     46 }
     47 
     48 DecoratedTextfield::~DecoratedTextfield() {}
     49 
     50 void DecoratedTextfield::SetInvalid(bool invalid) {
     51   invalid_ = invalid;
     52   if (!editable_)
     53     return;
     54 
     55   if (invalid)
     56     border_->SetColor(kWarningColor);
     57   else
     58     border_->UseDefaultColor();
     59   SchedulePaint();
     60 }
     61 
     62 void DecoratedTextfield::SetEditable(bool editable) {
     63   if (editable_ == editable)
     64     return;
     65 
     66   editable_ = editable;
     67   if (editable) {
     68     SetInvalid(invalid_);
     69     UseDefaultBackgroundColor();
     70   } else {
     71     border_->SetColor(SK_ColorTRANSPARENT);
     72     SetBackgroundColor(SK_ColorTRANSPARENT);
     73   }
     74 
     75   UpdateBackground();
     76   SetEnabled(editable);
     77   IconChanged();
     78 }
     79 
     80 void DecoratedTextfield::SetIcon(const gfx::Image& icon) {
     81   if (!icon_view_ && icon.IsEmpty())
     82     return;
     83 
     84   if (icon_view_)
     85     RemoveChildView(icon_view_.get());
     86 
     87   if (!icon.IsEmpty()) {
     88     icon_view_.reset(new views::ImageView());
     89     icon_view_->set_owned_by_client();
     90     icon_view_->SetImage(icon.ToImageSkia());
     91     AddChildView(icon_view_.get());
     92   }
     93 
     94   IconChanged();
     95 }
     96 
     97 void DecoratedTextfield::SetTooltipIcon(const base::string16& text) {
     98   if (!icon_view_ && text.empty())
     99     return;
    100 
    101   if (icon_view_)
    102     RemoveChildView(icon_view_.get());
    103 
    104   if (!text.empty()) {
    105     icon_view_.reset(new TooltipIcon(text));
    106     AddChildView(icon_view_.get());
    107   }
    108 
    109   IconChanged();
    110 }
    111 
    112 base::string16 DecoratedTextfield::GetPlaceholderText() const {
    113   if (!editable_)
    114     return base::string16();
    115 
    116   return views::Textfield::GetPlaceholderText();
    117 }
    118 
    119 const char* DecoratedTextfield::GetClassName() const {
    120   return kViewClassName;
    121 }
    122 
    123 views::View* DecoratedTextfield::GetEventHandlerForRect(const gfx::Rect& rect) {
    124   views::View* handler = views::Textfield::GetEventHandlerForRect(rect);
    125   if (handler->GetClassName() == TooltipIcon::kViewClassName)
    126     return handler;
    127   return native_wrapper_->GetView();
    128 }
    129 
    130 void DecoratedTextfield::OnFocus() {
    131   views::Textfield::OnFocus();
    132   SchedulePaint();
    133 }
    134 
    135 void DecoratedTextfield::OnBlur() {
    136   views::Textfield::OnBlur();
    137   SchedulePaint();
    138 }
    139 
    140 gfx::Size DecoratedTextfield::GetPreferredSize() {
    141   int w = views::Textfield::GetPreferredSize().width();
    142   views::LabelButton button(NULL, base::string16());
    143   button.SetStyle(views::Button::STYLE_BUTTON);
    144   int h = button.GetPreferredSize().height();
    145   return gfx::Size(w, h - kMagicInsetNumber);
    146 }
    147 
    148 void DecoratedTextfield::Layout() {
    149   views::Textfield::Layout();
    150 
    151   if (icon_view_ && icon_view_->visible()) {
    152     gfx::Rect bounds = GetContentsBounds();
    153     gfx::Size icon_size = icon_view_->GetPreferredSize();
    154     int x = base::i18n::IsRTL() ?
    155         kTextfieldIconPadding :
    156         bounds.right() - icon_size.width() - kTextfieldIconPadding;
    157     // Vertically centered.
    158     int y = bounds.y() + (bounds.height() - icon_size.height()) / 2;
    159     icon_view_->SetBounds(x,
    160                           y,
    161                           icon_size.width(),
    162                           icon_size.height());
    163   }
    164 }
    165 
    166 void DecoratedTextfield::UpdateBackground() {
    167   set_background(
    168       views::Background::CreateSolidBackground(GetBackgroundColor()));
    169 }
    170 
    171 void DecoratedTextfield::IconChanged() {
    172   // Don't show the icon if nothing else is showing.
    173   icon_view_->SetVisible(editable_ || !text().empty());
    174 
    175   int icon_space = icon_view_ ?
    176       icon_view_->GetPreferredSize().width() + 2 * kTextfieldIconPadding : 0;
    177 
    178   bool is_rtl = base::i18n::IsRTL();
    179   SetHorizontalMargins(is_rtl ? icon_space : 0, is_rtl ? 0 : icon_space);
    180 
    181   Layout();
    182   SchedulePaint();
    183 }
    184 
    185 } // namespace autofill
    186