user_image_view.cc revision 513209b27ff55e2841eac0e4120199c23acce758
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/user_image_view.h"
6
7#include <algorithm>
8
9#include "app/l10n_util.h"
10#include "app/resource_bundle.h"
11#include "base/callback.h"
12#include "chrome/browser/chromeos/login/helper.h"
13#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
14#include "chrome/browser/chromeos/login/wizard_accessibility_helper.h"
15#include "chrome/browser/profile_manager.h"
16#include "gfx/canvas.h"
17#include "grit/generated_resources.h"
18#include "grit/theme_resources.h"
19#include "skia/ext/image_operations.h"
20#include "views/controls/button/image_button.h"
21#include "views/controls/button/native_button.h"
22#include "views/controls/image_view.h"
23#include "views/controls/label.h"
24#include "views/grid_layout.h"
25
26namespace {
27
28// Margin in pixels from the left and right borders of screen's contents.
29const int kHorizontalMargin = 10;
30// Margin in pixels from the top and bottom borders of screen's contents.
31const int kVerticalMargin = 10;
32// Padding between horizontally neighboring elements.
33const int kHorizontalPadding = 10;
34// Padding between vertically neighboring elements.
35const int kVerticalPadding = 10;
36
37// IDs of column sets for grid layout manager.
38enum ColumnSets {
39  kTitleRow,    // Column set for screen title.
40  kImageRow,    // Column set for image from camera and snapshot button.
41  kButtonsRow,  // Column set for Skip and OK buttons.
42};
43
44}  // namespace
45
46namespace chromeos {
47
48using login::kUserImageSize;
49
50UserImageView::UserImageView(Delegate* delegate)
51    : title_label_(NULL),
52      ok_button_(NULL),
53      skip_button_(NULL),
54      snapshot_button_(NULL),
55      user_image_(NULL),
56      delegate_(delegate),
57      is_capturing_(true) {
58}
59
60UserImageView::~UserImageView() {
61}
62
63void UserImageView::Init() {
64  // Use rounded rect background.
65  set_border(CreateWizardBorder(&BorderDefinition::kScreenBorder));
66  views::Painter* painter = CreateWizardPainter(
67      &BorderDefinition::kScreenBorder);
68  set_background(views::Background::CreateBackgroundPainter(true, painter));
69
70  title_label_ =
71      new views::Label(l10n_util::GetString(IDS_USER_IMAGE_SCREEN_TITLE));
72  title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
73  title_label_->SetMultiLine(true);
74
75  user_image_ = new views::ImageView();
76  user_image_->SetImageSize(
77      gfx::Size(kUserImageSize, kUserImageSize));
78  user_image_->SetImage(
79      ResourceBundle::GetSharedInstance().GetBitmapNamed(
80          IDR_USER_IMAGE_NO_VIDEO));
81
82  snapshot_button_ = new views::ImageButton(this);
83  snapshot_button_->SetFocusable(true);
84  snapshot_button_->SetImage(views::CustomButton::BS_NORMAL,
85                             ResourceBundle::GetSharedInstance().GetBitmapNamed(
86                                IDR_USER_IMAGE_CAPTURE));
87
88  ok_button_ = new views::NativeButton(this, l10n_util::GetString(IDS_OK));
89  ok_button_->SetEnabled(!is_capturing_);
90
91  skip_button_ = new views::NativeButton(this, l10n_util::GetString(IDS_SKIP));
92  skip_button_->SetEnabled(true);
93
94  InitLayout();
95  // Request focus only after the button is added to views hierarchy.
96  snapshot_button_->RequestFocus();
97}
98
99void UserImageView::InitLayout() {
100  views::GridLayout* layout = new views::GridLayout(this);
101  layout->SetInsets(GetInsets());
102  SetLayoutManager(layout);
103
104  // The title is left-top aligned.
105  views::ColumnSet* column_set = layout->AddColumnSet(kTitleRow);
106  column_set->AddPaddingColumn(0, kHorizontalMargin);
107  column_set->AddColumn(views::GridLayout::LEADING,
108                        views::GridLayout::LEADING,
109                        1,
110                        views::GridLayout::USE_PREF, 0, 0);
111  column_set->AddPaddingColumn(0, kHorizontalMargin);
112
113  // User image and snapshot button are centered horizontally.
114  column_set = layout->AddColumnSet(kImageRow);
115  column_set->AddPaddingColumn(0, kHorizontalMargin);
116  column_set->AddColumn(views::GridLayout::CENTER,
117                        views::GridLayout::LEADING,
118                        1,
119                        views::GridLayout::USE_PREF, 0, 0);
120  column_set->AddPaddingColumn(0, kHorizontalMargin);
121
122  // OK and Skip buttons are in the right bottom corner of the view.
123  column_set = layout->AddColumnSet(kButtonsRow);
124  column_set->AddPaddingColumn(0, kHorizontalMargin);
125  // This column takes the empty space to the left of the buttons.
126  column_set->AddPaddingColumn(1, 1);
127  column_set->AddColumn(views::GridLayout::TRAILING,
128                        views::GridLayout::TRAILING,
129                        0,
130                        views::GridLayout::USE_PREF, 0, 0);
131  column_set->AddPaddingColumn(0, kHorizontalPadding);
132  column_set->AddColumn(views::GridLayout::TRAILING,
133                        views::GridLayout::TRAILING,
134                        0,
135                        views::GridLayout::USE_PREF, 0, 0);
136  column_set->AddPaddingColumn(0, kHorizontalMargin);
137
138  // Fill the layout with rows and views now.
139  layout->StartRowWithPadding(0, kTitleRow, 0, kVerticalMargin);
140  layout->AddView(title_label_);
141  layout->StartRowWithPadding(0, kImageRow, 0, kVerticalPadding);
142  layout->AddView(user_image_);
143  layout->StartRowWithPadding(1, kImageRow, 0, kVerticalPadding);
144  layout->AddView(snapshot_button_);
145  layout->StartRowWithPadding(0, kButtonsRow, 0, kVerticalPadding);
146  layout->AddView(skip_button_);
147  layout->AddView(ok_button_);
148  layout->AddPaddingRow(0, kVerticalMargin);
149}
150
151void UserImageView::UpdateVideoFrame(const SkBitmap& frame) {
152  if (!is_capturing_)
153    return;
154
155  if (!snapshot_button_->IsEnabled()) {
156    snapshot_button_->SetEnabled(true);
157    snapshot_button_->RequestFocus();
158  }
159  SkBitmap user_image =
160      skia::ImageOperations::Resize(
161          frame,
162          skia::ImageOperations::RESIZE_BOX,
163          kUserImageSize,
164          kUserImageSize);
165
166  user_image_->SetImage(&user_image);
167}
168
169void UserImageView::ShowCameraError() {
170  if (!is_capturing_ || !snapshot_button_->IsEnabled())
171    return;
172  snapshot_button_->SetEnabled(false);
173  user_image_->SetImage(
174      ResourceBundle::GetSharedInstance().GetBitmapNamed(
175          IDR_USER_IMAGE_NO_VIDEO));
176}
177
178void UserImageView::ViewHierarchyChanged(bool is_add,
179                                         views::View* parent,
180                                         views::View* child) {
181  if (is_add && this == child)
182    WizardAccessibilityHelper::GetInstance()->MaybeEnableAccessibility(this);
183}
184
185gfx::Size UserImageView::GetPreferredSize() {
186  return gfx::Size(width(), height());
187}
188
189void UserImageView::ButtonPressed(
190    views::Button* sender, const views::Event& event) {
191  DCHECK(delegate_);
192  if (sender == snapshot_button_) {
193    if (is_capturing_) {
194      ok_button_->SetEnabled(true);
195      ok_button_->RequestFocus();
196      snapshot_button_->SetImage(
197          views::CustomButton::BS_NORMAL,
198          ResourceBundle::GetSharedInstance().GetBitmapNamed(
199              IDR_USER_IMAGE_RECYCLE));
200    } else {
201      ok_button_->SetEnabled(false);
202      snapshot_button_->SetImage(
203          views::CustomButton::BS_NORMAL,
204          ResourceBundle::GetSharedInstance().GetBitmapNamed(
205              IDR_USER_IMAGE_CAPTURE));
206    }
207    snapshot_button_->SchedulePaint();
208    is_capturing_ = !is_capturing_;
209  } else if (sender == ok_button_) {
210    delegate_->OnOK(user_image_->GetImage());
211  } else if (sender == skip_button_) {
212    delegate_->OnSkip();
213  } else {
214    NOTREACHED();
215  }
216}
217
218}  // namespace chromeos
219
220