decorated_textfield.cc revision f2477e01787aa58f445919b809d89e252beef54f
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 27const int DecoratedTextfield::kMagicInsetNumber = 6; 28 29DecoratedTextfield::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 48DecoratedTextfield::~DecoratedTextfield() {} 49 50void 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 62void 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 80void 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 97void 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 112base::string16 DecoratedTextfield::GetPlaceholderText() const { 113 if (!editable_) 114 return base::string16(); 115 116 return views::Textfield::GetPlaceholderText(); 117} 118 119const char* DecoratedTextfield::GetClassName() const { 120 return kViewClassName; 121} 122 123views::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 130void DecoratedTextfield::OnFocus() { 131 border_->set_has_focus(true); 132 views::Textfield::OnFocus(); 133 SchedulePaint(); 134} 135 136void DecoratedTextfield::OnBlur() { 137 border_->set_has_focus(false); 138 views::Textfield::OnBlur(); 139 SchedulePaint(); 140} 141 142gfx::Size DecoratedTextfield::GetPreferredSize() { 143 int w = views::Textfield::GetPreferredSize().width(); 144 views::LabelButton button(NULL, string16()); 145 button.SetStyle(views::Button::STYLE_BUTTON); 146 int h = button.GetPreferredSize().height(); 147 return gfx::Size(w, h - kMagicInsetNumber); 148} 149 150void DecoratedTextfield::Layout() { 151 views::Textfield::Layout(); 152 153 if (icon_view_ && icon_view_->visible()) { 154 gfx::Rect bounds = GetContentsBounds(); 155 gfx::Size icon_size = icon_view_->GetPreferredSize(); 156 int x = base::i18n::IsRTL() ? 157 kTextfieldIconPadding : 158 bounds.right() - icon_size.width() - kTextfieldIconPadding; 159 // Vertically centered. 160 int y = bounds.y() + (bounds.height() - icon_size.height()) / 2; 161 icon_view_->SetBounds(x, 162 y, 163 icon_size.width(), 164 icon_size.height()); 165 } 166} 167 168void DecoratedTextfield::UpdateBackground() { 169 set_background( 170 views::Background::CreateSolidBackground(GetBackgroundColor())); 171} 172 173void DecoratedTextfield::IconChanged() { 174 // Don't show the icon if nothing else is showing. 175 icon_view_->SetVisible(editable_ || !text().empty()); 176 177 int icon_space = icon_view_ ? 178 icon_view_->GetPreferredSize().width() + 2 * kTextfieldIconPadding : 0; 179 180 bool is_rtl = base::i18n::IsRTL(); 181 SetHorizontalMargins(is_rtl ? icon_space : 0, is_rtl ? 0 : icon_space); 182 183 Layout(); 184 SchedulePaint(); 185} 186 187} // namespace autofill 188