• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/take_photo_view.h"
6 
7 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/chromeos/login/helper.h"
9 #include "grit/generated_resources.h"
10 #include "grit/theme_resources.h"
11 #include "skia/ext/image_operations.h"
12 #include "ui/base/l10n/l10n_util.h"
13 #include "ui/base/resource/resource_bundle.h"
14 #include "ui/gfx/canvas.h"
15 #include "views/background.h"
16 #include "views/border.h"
17 #include "views/controls/button/image_button.h"
18 #include "views/controls/image_view.h"
19 #include "views/controls/label.h"
20 #include "views/controls/throbber.h"
21 #include "views/layout/grid_layout.h"
22 
23 namespace {
24 
25 // Padding between horizontally neighboring elements.
26 const int kHorizontalPadding = 10;
27 // Padding between vertically neighboring elements.
28 const int kVerticalPadding = 10;
29 // Color of image view border.
30 const SkColor kImageBorderColor = SkColorSetARGB(38, 0, 0, 0);
31 
32 // IDs of column sets for grid layout manager.
33 enum ColumnSets {
34   kTitleRow,    // Column set for screen title.
35   kImageRow,    // Column set for image from camera and snapshot button.
36 };
37 
38 }  // namespace
39 
40 namespace chromeos {
41 
42 // Image view that can show center throbber above itself or a message at its
43 // bottom.
44 class CameraImageView : public views::ImageView {
45  public:
CameraImageView()46   CameraImageView()
47       : throbber_(NULL),
48         message_(NULL) {}
49 
~CameraImageView()50   ~CameraImageView() {}
51 
Init()52   void Init() {
53     DCHECK(NULL == throbber_);
54     DCHECK(NULL == message_);
55 
56     set_border(views::Border::CreateSolidBorder(1, kImageBorderColor));
57     set_background(views::Background::CreateSolidBackground(SK_ColorWHITE));
58 
59     throbber_ = CreateDefaultSmoothedThrobber();
60     throbber_->SetVisible(false);
61     AddChildView(throbber_);
62 
63     message_ = new views::Label();
64     message_->SetMultiLine(true);
65     message_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
66     message_->SetVisible(false);
67     CorrectLabelFontSize(message_);
68     AddChildView(message_);
69   }
70 
SetInitializingState()71   void SetInitializingState() {
72     ShowThrobber();
73     SetMessage(std::wstring());
74     SetImage(
75         ResourceBundle::GetSharedInstance().GetBitmapNamed(
76             IDR_USER_IMAGE_INITIALIZING));
77   }
78 
SetNormalState()79   void SetNormalState() {
80     HideThrobber();
81     SetMessage(std::wstring());
82   }
83 
SetErrorState()84   void SetErrorState() {
85     HideThrobber();
86     SetMessage(UTF16ToWide(l10n_util::GetStringUTF16(IDS_USER_IMAGE_NO_VIDEO)));
87     SetImage(
88         ResourceBundle::GetSharedInstance().GetBitmapNamed(
89             IDR_USER_IMAGE_NO_VIDEO));
90   }
91 
92  private:
ShowThrobber()93   void ShowThrobber() {
94     DCHECK(throbber_);
95     throbber_->SetVisible(true);
96     throbber_->Start();
97   }
98 
HideThrobber()99   void HideThrobber() {
100     DCHECK(throbber_);
101     throbber_->Stop();
102     throbber_->SetVisible(false);
103   }
104 
SetMessage(const std::wstring & message)105   void SetMessage(const std::wstring& message) {
106     DCHECK(message_);
107     message_->SetText(message);
108     message_->SetVisible(!message.empty());
109     Layout();
110   }
111 
112   // views::View override:
Layout()113   virtual void Layout() {
114     gfx::Size size = GetPreferredSize();
115     if (throbber_->IsVisible()) {
116       gfx::Size throbber_size = throbber_->GetPreferredSize();
117       int throbber_x = (size.width() - throbber_size.width()) / 2;
118       int throbber_y = (size.height() - throbber_size.height()) / 2;
119       throbber_->SetBounds(throbber_x,
120                            throbber_y,
121                            throbber_size.width(),
122                            throbber_size.height());
123     }
124     if (message_->IsVisible()) {
125       message_->SizeToFit(size.width() - kHorizontalPadding * 2);
126       gfx::Size message_size = message_->GetPreferredSize();
127       int message_y = size.height() - kVerticalPadding - message_size.height();
128       message_->SetBounds(kHorizontalPadding,
129                           message_y,
130                           message_size.width(),
131                           message_size.height());
132     }
133   }
134 
135   // Throbber centered within the view.
136   views::Throbber* throbber_;
137 
138   // Message, multiline, aligned to the bottom of the view.
139   views::Label* message_;
140 
141   DISALLOW_COPY_AND_ASSIGN(CameraImageView);
142 };
143 
144 
TakePhotoView(Delegate * delegate)145 TakePhotoView::TakePhotoView(Delegate* delegate)
146     : title_label_(NULL),
147       snapshot_button_(NULL),
148       user_image_(NULL),
149       is_capturing_(false),
150       show_title_(true),
151       delegate_(delegate) {
152 }
153 
~TakePhotoView()154 TakePhotoView::~TakePhotoView() {
155 }
156 
Init()157 void TakePhotoView::Init() {
158   if (show_title_) {
159     title_label_ = new views::Label(
160         UTF16ToWide(l10n_util::GetStringUTF16(IDS_USER_IMAGE_SCREEN_TITLE)));
161     title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
162     title_label_->SetMultiLine(true);
163     CorrectLabelFontSize(title_label_);
164   }
165 
166   user_image_ = new CameraImageView();
167   user_image_->SetImageSize(
168       gfx::Size(login::kUserImageSize, login::kUserImageSize));
169   user_image_->Init();
170 
171   snapshot_button_ = new views::ImageButton(this);
172   snapshot_button_->SetFocusable(true);
173   snapshot_button_->SetImage(views::CustomButton::BS_NORMAL,
174                              ResourceBundle::GetSharedInstance().GetBitmapNamed(
175                                  IDR_USER_IMAGE_CAPTURE));
176   snapshot_button_->SetImage(views::CustomButton::BS_DISABLED,
177                              ResourceBundle::GetSharedInstance().GetBitmapNamed(
178                                  IDR_USER_IMAGE_CAPTURE_DISABLED));
179   snapshot_button_->SetAccessibleName(l10n_util::GetStringUTF16(
180       IDS_CHROMEOS_ACC_ACCOUNT_PICTURE));
181 
182   InitLayout();
183   // Request focus only after the button is added to views hierarchy.
184   snapshot_button_->RequestFocus();
185 }
186 
InitLayout()187 void TakePhotoView::InitLayout() {
188   views::GridLayout* layout = new views::GridLayout(this);
189   layout->SetInsets(GetInsets());
190   SetLayoutManager(layout);
191 
192   // The title is left-top aligned.
193   if (show_title_) {
194     views::ColumnSet* column_set = layout->AddColumnSet(kTitleRow);
195     column_set->AddColumn(views::GridLayout::FILL,
196                           views::GridLayout::LEADING,
197                           1,
198                           views::GridLayout::USE_PREF, 0, 0);
199   }
200 
201   // User image and snapshot button are centered horizontally.
202   views::ColumnSet* column_set = layout->AddColumnSet(kImageRow);
203   column_set->AddColumn(views::GridLayout::CENTER,
204                         views::GridLayout::LEADING,
205                         1,
206                         views::GridLayout::USE_PREF, 0, 0);
207 
208   // Fill the layout with rows and views now.
209   if (show_title_) {
210     layout->StartRow(0, kTitleRow);
211     layout->AddView(title_label_);
212   }
213   layout->StartRowWithPadding(0, kImageRow, 0, kVerticalPadding);
214   layout->AddView(user_image_);
215   layout->StartRowWithPadding(1, kImageRow, 0, kVerticalPadding);
216   layout->AddView(snapshot_button_);
217 }
218 
UpdateVideoFrame(const SkBitmap & frame)219 void TakePhotoView::UpdateVideoFrame(const SkBitmap& frame) {
220   if (!is_capturing_)
221     return;
222 
223   if (!snapshot_button_->IsEnabled()) {
224     user_image_->SetNormalState();
225     snapshot_button_->SetEnabled(true);
226     snapshot_button_->RequestFocus();
227   }
228   SkBitmap user_image =
229       skia::ImageOperations::Resize(
230           frame,
231           skia::ImageOperations::RESIZE_BOX,
232           login::kUserImageSize,
233           login::kUserImageSize);
234 
235   user_image_->SetImage(&user_image);
236 }
237 
ShowCameraInitializing()238 void TakePhotoView::ShowCameraInitializing() {
239   is_capturing_ = true;
240   snapshot_button_->SetImage(views::CustomButton::BS_NORMAL,
241                              ResourceBundle::GetSharedInstance().GetBitmapNamed(
242                                  IDR_USER_IMAGE_CAPTURE));
243   snapshot_button_->SetVisible(true);
244   snapshot_button_->SetEnabled(false);
245   user_image_->SetInitializingState();
246 }
247 
ShowCameraError()248 void TakePhotoView::ShowCameraError() {
249   if (!is_capturing_)
250     return;
251   snapshot_button_->SetEnabled(false);
252   user_image_->SetErrorState();
253 }
254 
GetImage() const255 const SkBitmap& TakePhotoView::GetImage() const {
256   return user_image_->GetImage();
257 }
258 
SetImage(SkBitmap * image)259 void TakePhotoView::SetImage(SkBitmap* image) {
260   is_capturing_ = false;
261   snapshot_button_->SetVisible(false);
262   user_image_->SetNormalState();
263   user_image_->SetImage(image);
264 }
265 
GetPreferredSize()266 gfx::Size TakePhotoView::GetPreferredSize() {
267   return gfx::Size(width(), height());
268 }
269 
ButtonPressed(views::Button * sender,const views::Event & event)270 void TakePhotoView::ButtonPressed(
271     views::Button* sender, const views::Event& event) {
272   DCHECK(delegate_);
273   DCHECK(sender == snapshot_button_);
274   is_capturing_ = !is_capturing_;
275   if (is_capturing_) {
276     snapshot_button_->SetImage(
277         views::CustomButton::BS_NORMAL,
278         ResourceBundle::GetSharedInstance().GetBitmapNamed(
279             IDR_USER_IMAGE_CAPTURE));
280     delegate_->OnCapturingStarted();
281   } else {
282     snapshot_button_->SetImage(
283         views::CustomButton::BS_NORMAL,
284         ResourceBundle::GetSharedInstance().GetBitmapNamed(
285             IDR_USER_IMAGE_RECYCLE));
286     delegate_->OnCapturingStopped();
287   }
288   snapshot_button_->SchedulePaint();
289 }
290 
291 }  // namespace chromeos
292