screen_lock_view.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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/chromeos/login/screen_lock_view.h"
6
7#include "app/l10n_util.h"
8#include "app/resource_bundle.h"
9#include "base/utf_string_conversions.h"
10#include "chrome/browser/chromeos/login/helper.h"
11#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
12#include "chrome/browser/chromeos/login/screen_locker.h"
13#include "chrome/browser/chromeos/login/user_manager.h"
14#include "chrome/browser/chromeos/login/user_view.h"
15#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
16#include "chrome/browser/profile_manager.h"
17#include "chrome/common/notification_service.h"
18#include "grit/generated_resources.h"
19#include "grit/theme_resources.h"
20#include "views/background.h"
21#include "views/border.h"
22#include "views/controls/button/text_button.h"
23#include "views/controls/image_view.h"
24#include "views/controls/label.h"
25#include "views/grid_layout.h"
26
27namespace chromeos {
28
29namespace {
30
31const int kCornerRadius = 5;
32
33// A Textfield for password, which also sets focus to itself
34// when a mouse is clicked on it. This is necessary in screen locker
35// as mouse events are grabbed in the screen locker.
36class PasswordField : public views::Textfield {
37 public:
38  PasswordField()
39      : views::Textfield(views::Textfield::STYLE_PASSWORD) {
40    set_text_to_display_when_empty(
41        l10n_util::GetStringUTF16(IDS_LOGIN_EMPTY_PASSWORD_TEXT));
42  }
43
44  // views::View overrides.
45  virtual bool OnMousePressed(const views::MouseEvent& e) {
46    RequestFocus();
47    return false;
48  }
49
50 private:
51  DISALLOW_COPY_AND_ASSIGN(PasswordField);
52};
53
54}  // namespace
55
56using views::GridLayout;
57using login::kBorderSize;
58
59ScreenLockView::ScreenLockView(ScreenLocker* screen_locker)
60    : user_view_(NULL),
61      password_field_(NULL),
62      unlock_button_(NULL),
63      screen_locker_(screen_locker) {
64  DCHECK(screen_locker_);
65}
66
67void ScreenLockView::Init() {
68  registrar_.Add(this,
69                 NotificationType::LOGIN_USER_IMAGE_CHANGED,
70                 NotificationService::AllSources());
71
72  user_view_ = new UserView(this,
73                            false,  // is_login
74                            true);  // need_background
75  views::View* main = new views::View();
76  // Use rounded rect background.
77  views::Painter* painter =
78      CreateWizardPainter(&BorderDefinition::kUserBorder);
79
80  main->set_background(
81      views::Background::CreateBackgroundPainter(true, painter));
82  main->set_border(CreateWizardBorder(&BorderDefinition::kUserBorder));
83
84  // Password field.
85  password_field_ = new PasswordField();
86  password_field_->SetController(this);
87
88  // Unlock button.
89  unlock_button_ = new views::TextButton(
90      this, l10n_util::GetString(IDS_UNLOCK_BUTTON));
91  unlock_button_->set_tag(login::UNLOCK);
92
93  // User icon.
94  UserManager::User user = screen_locker_->user();
95  user_view_->SetImage(user.image());
96
97  // User name.
98  std::wstring text = UTF8ToWide(user.GetDisplayName());
99  views::Label* label = new views::Label(text);
100  label->SetColor(login::kTextColor);
101  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
102  const gfx::Font& font =
103      rb.GetFont(ResourceBundle::LargeFont).DeriveFont(0, gfx::Font::BOLD);
104  label->SetFont(font);
105
106  // Layouts image, textfield and button components.
107  GridLayout* layout = new GridLayout(main);
108  main->SetLayoutManager(layout);
109  views::ColumnSet* column_set = layout->AddColumnSet(0);
110  column_set->AddPaddingColumn(0, kBorderSize);
111  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
112                        GridLayout::USE_PREF, 0, 0);
113  column_set->AddPaddingColumn(0, kBorderSize);
114
115  column_set = layout->AddColumnSet(1);
116  column_set->AddPaddingColumn(0, 5);
117  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
118                        GridLayout::USE_PREF, 0, 0);
119  column_set->AddPaddingColumn(0, 5);
120  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
121                        GridLayout::USE_PREF, 0, 0);
122  column_set->AddPaddingColumn(0, 5);
123
124  layout->AddPaddingRow(0, kBorderSize);
125  layout->StartRow(0, 0);
126  layout->AddView(user_view_);
127  layout->AddPaddingRow(0, kBorderSize);
128  layout->StartRow(0, 1);
129  layout->AddView(password_field_);
130  layout->AddView(unlock_button_);
131  layout->AddPaddingRow(0, 5);
132
133  unlock_button_->SetFocusable(true);
134
135  // Layouts the main view and the account label.
136  layout = new GridLayout(this);
137  SetLayoutManager(layout);
138  column_set = layout->AddColumnSet(0);
139  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
140                        GridLayout::USE_PREF, 0, 0);
141
142  column_set = layout->AddColumnSet(1);
143  column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
144                        GridLayout::USE_PREF, 0, 0);
145
146  layout->StartRow(0, 0);
147  layout->AddView(main);
148  layout->StartRow(0, 1);
149  layout->AddView(label);
150}
151
152void ScreenLockView::ClearAndSetFocusToPassword() {
153  password_field_->RequestFocus();
154  password_field_->SetText(string16());
155}
156
157void ScreenLockView::SetSignoutEnabled(bool enabled) {
158  user_view_->SetSignoutEnabled(enabled);
159}
160
161gfx::Rect ScreenLockView::GetPasswordBoundsRelativeTo(const views::View* view) {
162  gfx::Point p;
163  views::View::ConvertPointToView(password_field_, view, &p);
164  return gfx::Rect(p, size());
165}
166
167void ScreenLockView::SetEnabled(bool enabled) {
168  views::View::SetEnabled(enabled);
169
170  if (!enabled) {
171    user_view_->StartThrobber();
172    // TODO(oshima): Re-enabling does not move the focus to the view
173    // that had a focus (issue http://crbug.com/43131).
174    // Move the focus to other field as a workaround.
175    unlock_button_->RequestFocus();
176  } else {
177    user_view_->StopThrobber();
178  }
179  unlock_button_->SetEnabled(enabled);
180  password_field_->SetEnabled(enabled);
181}
182
183void ScreenLockView::ButtonPressed(views::Button* sender,
184                                   const views::Event& event) {
185  if (sender->tag() == login::UNLOCK)
186    screen_locker_->Authenticate(password_field_->text());
187  else
188    NOTREACHED();
189}
190
191void ScreenLockView::OnSignout() {
192  screen_locker_->Signout();
193}
194
195bool ScreenLockView::HandleKeystroke(
196    views::Textfield* sender,
197    const views::Textfield::Keystroke& keystroke) {
198  screen_locker_->ClearErrors();
199  if (keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
200    screen_locker_->Authenticate(password_field_->text());
201    return true;
202  }
203  return false;
204}
205
206void ScreenLockView::Observe(
207    NotificationType type,
208    const NotificationSource& source,
209    const NotificationDetails& details) {
210  if (type != NotificationType::LOGIN_USER_IMAGE_CHANGED || !user_view_)
211    return;
212
213  UserManager::User* user = Details<UserManager::User>(details).ptr();
214  if (screen_locker_->user().email() != user->email())
215    return;
216
217  user_view_->SetImage(user->image());
218}
219
220void ScreenLockView::ViewHierarchyChanged(bool is_add,
221                                          views::View* parent,
222                                          views::View* child) {
223  if (is_add && this == child)
224    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
225}
226}  // namespace chromeos
227