password_generation_popup_view_views.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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
17namespace autofill {
18
19namespace {
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.
23const int kHelpVerticalOffset = 3;
24
25// Class that shows the password and the suggestion side-by-side.
26class 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  virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE {
54    // Have parent do event handling.
55    return false;
56  }
57
58 private:
59  // Child views. Not owned.
60  views::Label* suggestion_label_;
61  views::Label* password_label_;
62
63  DISALLOW_COPY_AND_ASSIGN(PasswordRow);
64};
65
66}  // namespace
67
68PasswordGenerationPopupViewViews::PasswordGenerationPopupViewViews(
69    PasswordGenerationPopupController* controller,
70    views::Widget* observing_widget)
71    : AutofillPopupBaseView(controller, observing_widget),
72      password_view_(NULL),
73      controller_(controller) {
74  if (controller_->display_password())
75    CreatePasswordView();
76
77  help_label_ = new views::StyledLabel(controller_->HelpText(), this);
78  help_label_->SetBaseFontList(controller_->font_list());
79  views::StyledLabel::RangeStyleInfo default_style;
80  default_style.color = kExplanatoryTextColor;
81  help_label_->SetDefaultStyle(default_style);
82
83  views::StyledLabel::RangeStyleInfo link_style =
84      views::StyledLabel::RangeStyleInfo::CreateForLink();
85  link_style.color = kLinkColor;
86  help_label_->AddStyleRange(controller_->HelpTextLinkRange(), link_style);
87
88  help_label_->SetBoundsRect(controller_->help_bounds());
89  help_label_->set_background(
90      views::Background::CreateSolidBackground(
91          kExplanatoryTextBackgroundColor));
92  help_label_->SetBorder(views::Border::CreateEmptyBorder(
93      controller_->kHelpVerticalPadding - kHelpVerticalOffset,
94      controller_->kHorizontalPadding,
95      0,
96      controller_->kHorizontalPadding));
97  AddChildView(help_label_);
98
99  set_background(views::Background::CreateSolidBackground(kPopupBackground));
100}
101
102PasswordGenerationPopupViewViews::~PasswordGenerationPopupViewViews() {}
103
104void PasswordGenerationPopupViewViews::CreatePasswordView() {
105  if (password_view_)
106    return;
107
108  password_view_ = new PasswordRow(controller_->password(),
109                                   controller_->SuggestedText(),
110                                   controller_->font_list(),
111                                   controller_->kHorizontalPadding);
112  AddChildView(password_view_);
113}
114
115void PasswordGenerationPopupViewViews::Show() {
116  DoShow();
117}
118
119void PasswordGenerationPopupViewViews::Hide() {
120  // The controller is no longer valid after it hides us.
121  controller_ = NULL;
122
123  DoHide();
124}
125
126void PasswordGenerationPopupViewViews::UpdateBoundsAndRedrawPopup() {
127  // Currently the UI can change from not offering a password to offering
128  // a password (e.g. the user is editing a generated password and deletes it),
129  // but it can't change the other way around.
130  if (controller_->display_password())
131    CreatePasswordView();
132
133  DoUpdateBoundsAndRedrawPopup();
134}
135
136void PasswordGenerationPopupViewViews::PasswordSelectionUpdated() {
137  if (!password_view_)
138    return;
139
140  password_view_->set_background(
141      views::Background::CreateSolidBackground(
142          controller_->password_selected() ?
143          kHoveredBackgroundColor :
144          kPopupBackground));
145}
146
147void PasswordGenerationPopupViewViews::Layout() {
148  if (password_view_)
149    password_view_->SetBoundsRect(controller_->password_bounds());
150
151  help_label_->SetBoundsRect(controller_->help_bounds());
152}
153
154void PasswordGenerationPopupViewViews::OnPaint(gfx::Canvas* canvas) {
155  if (!controller_)
156    return;
157
158  // Draw border and background.
159  views::View::OnPaint(canvas);
160
161  // Divider line needs to be drawn after OnPaint() otherwise the background
162  // will overwrite the divider.
163  if (password_view_)
164    canvas->FillRect(controller_->divider_bounds(), kDividerColor);
165}
166
167void PasswordGenerationPopupViewViews::StyledLabelLinkClicked(
168    const gfx::Range& range, int event_flags) {
169  controller_->OnSavedPasswordsLinkClicked();
170}
171
172PasswordGenerationPopupView* PasswordGenerationPopupView::Create(
173    PasswordGenerationPopupController* controller) {
174  views::Widget* observing_widget =
175      views::Widget::GetTopLevelWidgetForNativeView(
176          controller->container_view());
177
178  // If the top level widget can't be found, cancel the popup since we can't
179  // fully set it up.
180  if (!observing_widget)
181    return NULL;
182
183  return new PasswordGenerationPopupViewViews(controller, observing_widget);
184}
185
186}  // namespace autofill
187