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