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 "ui/gfx/canvas.h" 9 #include "ui/views/background.h" 10 #include "ui/views/controls/button/label_button.h" 11 #include "ui/views/controls/focusable_border.h" 12 #include "ui/views/controls/textfield/textfield_controller.h" 13 14 namespace { 15 16 // Padding around icons inside DecoratedTextfields. 17 const int kTextfieldIconPadding = 3; 18 19 // Size of the triangular mark that indicates an invalid textfield (in pixels). 20 const int kDogEarSize = 10; 21 22 } // namespace 23 24 namespace autofill { 25 26 // static 27 const char DecoratedTextfield::kViewClassName[] = "autofill/DecoratedTextfield"; 28 29 const int DecoratedTextfield::kMagicInsetNumber = 6; 30 31 DecoratedTextfield::DecoratedTextfield( 32 const base::string16& default_value, 33 const base::string16& placeholder, 34 views::TextfieldController* controller) 35 : border_(new views::FocusableBorder()), 36 invalid_(false) { 37 set_background( 38 views::Background::CreateSolidBackground(GetBackgroundColor())); 39 40 set_border(border_); 41 // Removes the border from |native_wrapper_|. 42 RemoveBorder(); 43 44 set_placeholder_text(placeholder); 45 SetText(default_value); 46 SetController(controller); 47 SetHorizontalMargins(0, 0); 48 } 49 50 DecoratedTextfield::~DecoratedTextfield() {} 51 52 void DecoratedTextfield::SetInvalid(bool invalid) { 53 invalid_ = invalid; 54 if (invalid) 55 border_->SetColor(kWarningColor); 56 else 57 border_->UseDefaultColor(); 58 SchedulePaint(); 59 } 60 61 void DecoratedTextfield::SetIcon(const gfx::Image& icon) { 62 int icon_space = icon.IsEmpty() ? 0 : 63 icon.Width() + 2 * kTextfieldIconPadding; 64 // Extra indent inside of textfield before text starts, in px. 65 const int kTextIndent = 6; 66 int left = base::i18n::IsRTL() ? icon_space : kTextIndent; 67 int right = base::i18n::IsRTL() ? kTextIndent : icon_space; 68 SetHorizontalMargins(left, right); 69 icon_ = icon; 70 71 PreferredSizeChanged(); 72 SchedulePaint(); 73 } 74 75 const char* DecoratedTextfield::GetClassName() const { 76 return kViewClassName; 77 } 78 79 void DecoratedTextfield::PaintChildren(gfx::Canvas* canvas) {} 80 81 void DecoratedTextfield::OnPaint(gfx::Canvas* canvas) { 82 // Draw the border and background. 83 border_->set_has_focus(HasFocus()); 84 views::View::OnPaint(canvas); 85 86 // Then the textfield. 87 views::View::PaintChildren(canvas); 88 89 // Then the icon. 90 if (!icon_.IsEmpty()) { 91 gfx::Rect bounds = GetContentsBounds(); 92 int x = base::i18n::IsRTL() ? 93 kTextfieldIconPadding : 94 bounds.right() - icon_.Width() - kTextfieldIconPadding; 95 canvas->DrawImageInt(icon_.AsImageSkia(), x, 96 bounds.y() + (bounds.height() - icon_.Height()) / 2); 97 } 98 99 // Then the invalid indicator. 100 if (invalid_) { 101 if (base::i18n::IsRTL()) { 102 canvas->Translate(gfx::Vector2d(width(), 0)); 103 canvas->Scale(-1, 1); 104 } 105 106 SkPath dog_ear; 107 dog_ear.moveTo(width() - kDogEarSize, 0); 108 dog_ear.lineTo(width(), 0); 109 dog_ear.lineTo(width(), kDogEarSize); 110 dog_ear.close(); 111 canvas->ClipPath(dog_ear); 112 canvas->DrawColor(kWarningColor); 113 } 114 } 115 116 gfx::Size DecoratedTextfield::GetPreferredSize() { 117 int w = views::Textfield::GetPreferredSize().width(); 118 views::LabelButton button(NULL, string16()); 119 button.SetStyle(views::Button::STYLE_BUTTON); 120 int h = button.GetPreferredSize().height(); 121 return gfx::Size(w, h - kMagicInsetNumber); 122 } 123 124 } // namespace autofill 125