Home | History | Annotate | Download | only in autofill
      1 // Copyright 2014 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/password_generation_popup_view_views.h"
      6 
      7 #include "base/strings/string16.h"
      8 #include "chrome/browser/ui/autofill/password_generation_popup_controller.h"
      9 #include "ui/gfx/canvas.h"
     10 #include "ui/views/background.h"
     11 #include "ui/views/border.h"
     12 #include "ui/views/controls/label.h"
     13 #include "ui/views/controls/styled_label.h"
     14 #include "ui/views/layout/box_layout.h"
     15 #include "ui/views/widget/widget.h"
     16 
     17 namespace autofill {
     18 
     19 namespace {
     20 
     21 // The amount of whitespace that is present when there is no padding. Used
     22 // to get the proper spacing in the help section.
     23 const int kHelpVerticalOffset = 3;
     24 
     25 // Class that shows the password and the suggestion side-by-side.
     26 class PasswordRow : public views::View {
     27  public:
     28   PasswordRow(const base::string16& password,
     29               const base::string16& suggestion,
     30               const gfx::FontList& font_list,
     31               int horizontal_border) {
     32     set_clip_insets(gfx::Insets(
     33         PasswordGenerationPopupView::kPasswordVerticalInset, 0,
     34         PasswordGenerationPopupView::kPasswordVerticalInset, 0));
     35     views::BoxLayout* box_layout = new views::BoxLayout(
     36         views::BoxLayout::kHorizontal, horizontal_border, 0, 0);
     37     box_layout->set_main_axis_alignment(
     38         views::BoxLayout::MAIN_AXIS_ALIGNMENT_FILL);
     39     SetLayoutManager(box_layout);
     40 
     41     password_label_ = new views::Label(password, font_list);
     42     password_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     43     AddChildView(password_label_);
     44 
     45     suggestion_label_ = new views::Label(suggestion, font_list);
     46     suggestion_label_->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
     47     suggestion_label_->SetEnabledColor(
     48         PasswordGenerationPopupView::kExplanatoryTextColor);
     49     AddChildView(suggestion_label_);
     50   }
     51   virtual ~PasswordRow() {}
     52 
     53   // views::View:
     54   virtual bool CanProcessEventsWithinSubtree() const OVERRIDE {
     55     // Send events to the parent view for handling.
     56     return false;
     57   }
     58 
     59  private:
     60   // Child views. Not owned.
     61   views::Label* suggestion_label_;
     62   views::Label* password_label_;
     63 
     64   DISALLOW_COPY_AND_ASSIGN(PasswordRow);
     65 };
     66 
     67 }  // namespace
     68 
     69 PasswordGenerationPopupViewViews::PasswordGenerationPopupViewViews(
     70     PasswordGenerationPopupController* controller,
     71     views::Widget* observing_widget)
     72     : AutofillPopupBaseView(controller, observing_widget),
     73       password_view_(NULL),
     74       controller_(controller) {
     75   if (controller_->display_password())
     76     CreatePasswordView();
     77 
     78   help_label_ = new views::StyledLabel(controller_->HelpText(), this);
     79   help_label_->SetBaseFontList(controller_->font_list());
     80   views::StyledLabel::RangeStyleInfo default_style;
     81   default_style.color = kExplanatoryTextColor;
     82   help_label_->SetDefaultStyle(default_style);
     83 
     84   views::StyledLabel::RangeStyleInfo link_style =
     85       views::StyledLabel::RangeStyleInfo::CreateForLink();
     86   link_style.color = kLinkColor;
     87   help_label_->AddStyleRange(controller_->HelpTextLinkRange(), link_style);
     88 
     89   help_label_->SetBoundsRect(controller_->help_bounds());
     90   help_label_->set_background(
     91       views::Background::CreateSolidBackground(
     92           kExplanatoryTextBackgroundColor));
     93   help_label_->SetBorder(views::Border::CreateEmptyBorder(
     94       controller_->kHelpVerticalPadding - kHelpVerticalOffset,
     95       controller_->kHorizontalPadding,
     96       0,
     97       controller_->kHorizontalPadding));
     98   AddChildView(help_label_);
     99 
    100   set_background(views::Background::CreateSolidBackground(kPopupBackground));
    101 }
    102 
    103 PasswordGenerationPopupViewViews::~PasswordGenerationPopupViewViews() {}
    104 
    105 void PasswordGenerationPopupViewViews::CreatePasswordView() {
    106   if (password_view_)
    107     return;
    108 
    109   password_view_ = new PasswordRow(controller_->password(),
    110                                    controller_->SuggestedText(),
    111                                    controller_->font_list(),
    112                                    controller_->kHorizontalPadding);
    113   AddChildView(password_view_);
    114 }
    115 
    116 void PasswordGenerationPopupViewViews::Show() {
    117   DoShow();
    118 }
    119 
    120 void PasswordGenerationPopupViewViews::Hide() {
    121   // The controller is no longer valid after it hides us.
    122   controller_ = NULL;
    123 
    124   DoHide();
    125 }
    126 
    127 void PasswordGenerationPopupViewViews::UpdateBoundsAndRedrawPopup() {
    128   // Currently the UI can change from not offering a password to offering
    129   // a password (e.g. the user is editing a generated password and deletes it),
    130   // but it can't change the other way around.
    131   if (controller_->display_password())
    132     CreatePasswordView();
    133 
    134   DoUpdateBoundsAndRedrawPopup();
    135 }
    136 
    137 void PasswordGenerationPopupViewViews::PasswordSelectionUpdated() {
    138   if (!password_view_)
    139     return;
    140 
    141   password_view_->set_background(
    142       views::Background::CreateSolidBackground(
    143           controller_->password_selected() ?
    144           kHoveredBackgroundColor :
    145           kPopupBackground));
    146 }
    147 
    148 void PasswordGenerationPopupViewViews::Layout() {
    149   if (password_view_)
    150     password_view_->SetBoundsRect(controller_->password_bounds());
    151 
    152   help_label_->SetBoundsRect(controller_->help_bounds());
    153 }
    154 
    155 void PasswordGenerationPopupViewViews::OnPaint(gfx::Canvas* canvas) {
    156   if (!controller_)
    157     return;
    158 
    159   // Draw border and background.
    160   views::View::OnPaint(canvas);
    161 
    162   // Divider line needs to be drawn after OnPaint() otherwise the background
    163   // will overwrite the divider.
    164   if (password_view_)
    165     canvas->FillRect(controller_->divider_bounds(), kDividerColor);
    166 }
    167 
    168 void PasswordGenerationPopupViewViews::StyledLabelLinkClicked(
    169     const gfx::Range& range, int event_flags) {
    170   controller_->OnSavedPasswordsLinkClicked();
    171 }
    172 
    173 PasswordGenerationPopupView* PasswordGenerationPopupView::Create(
    174     PasswordGenerationPopupController* controller) {
    175   views::Widget* observing_widget =
    176       views::Widget::GetTopLevelWidgetForNativeView(
    177           controller->container_view());
    178 
    179   // If the top level widget can't be found, cancel the popup since we can't
    180   // fully set it up.
    181   if (!observing_widget)
    182     return NULL;
    183 
    184   return new PasswordGenerationPopupViewViews(controller, observing_widget);
    185 }
    186 
    187 }  // namespace autofill
    188