// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/chromeos/login/user_image_view.h" #include #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/default_images_view.h" #include "chrome/browser/chromeos/login/default_user_images.h" #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/rounded_rect_painter.h" #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/policy/browser_policy_connector.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" #include "views/background.h" #include "views/controls/button/text_button.h" #include "views/controls/label.h" #include "views/layout/grid_layout.h" namespace { // The delay of triggering initialization of the user policy subsystem // after the user image selection screen is initialized. This makes sure that // user policy network requests are made while the system is idle waiting for // user input. const int64 kPolicyServiceInitializationDelayMilliseconds = 400; // Margin in pixels from the left and right borders of screen's contents. const int kHorizontalMargin = 10; // Margin in pixels from the top and bottom borders of screen's contents. const int kVerticalMargin = 10; // Padding between horizontally neighboring elements. const int kHorizontalPadding = 10; // Padding between vertically neighboring elements. const int kVerticalPadding = 10; // Color for splitter separating contents from OK button. const SkColor kSplitterColor = SkColorSetRGB(187, 195, 200); // Height for the splitter. const int kSplitterHeight = 1; // IDs of column sets for grid layout manager. enum ColumnSets { kTitleRow, // Column set for screen title. kImagesRow, // Column set for image from camera and snapshot button. kSplitterRow, // Place for the splitter. kButtonsRow, // Column set for OK button. }; views::View* CreateSplitter(const SkColor& color) { views::View* splitter = new views::View(); splitter->set_background(views::Background::CreateSolidBackground(color)); return splitter; } } // namespace namespace chromeos { UserImageView::UserImageView(Delegate* delegate) : title_label_(NULL), default_images_view_(NULL), take_photo_view_(NULL), splitter_(NULL), ok_button_(NULL), delegate_(delegate) { } UserImageView::~UserImageView() { } void UserImageView::Init() { // Use rounded rect background. set_border(CreateWizardBorder(&BorderDefinition::kScreenBorder)); views::Painter* painter = CreateWizardPainter( &BorderDefinition::kScreenBorder); set_background(views::Background::CreateBackgroundPainter(true, painter)); title_label_ = new views::Label( l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_DIALOG_TEXT)); title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); title_label_->SetMultiLine(true); CorrectLabelFontSize(title_label_); default_images_view_ = new DefaultImagesView(this); take_photo_view_ = new TakePhotoView(this); take_photo_view_->set_show_title(false); splitter_ = CreateSplitter(kSplitterColor); ok_button_ = new login::WideButton( this, UTF16ToWide(l10n_util::GetStringUTF16(IDS_OK))); ok_button_->set_focusable(true); ok_button_->SetEnabled(false); accel_ok_ = views::Accelerator(ui::VKEY_RETURN, false, false, false); accel_up_ = views::Accelerator(ui::VKEY_UP, false, false, false); accel_down_ = views::Accelerator(ui::VKEY_DOWN, false, false, false); accel_left_ = views::Accelerator(ui::VKEY_LEFT, false, false, false); accel_right_ = views::Accelerator(ui::VKEY_RIGHT, false, false, false); AddAccelerator(accel_ok_); AddAccelerator(accel_up_); AddAccelerator(accel_down_); AddAccelerator(accel_left_); AddAccelerator(accel_right_); InitLayout(); default_images_view_->Init(); take_photo_view_->Init(); UserManager* user_manager = UserManager::Get(); const std::string& logged_in_user = user_manager->logged_in_user().email(); int image_index = user_manager->GetUserDefaultImageIndex(logged_in_user); default_images_view_->SetDefaultImageIndex(image_index); // Notify the policy subsystem that the system is idle enough now for a // policy fetch. (The policy fetch will happen after some delay, see // implementation.) g_browser_process->browser_policy_connector()->ScheduleServiceInitialization( kPolicyServiceInitializationDelayMilliseconds); } void UserImageView::InitLayout() { views::GridLayout* layout = new views::GridLayout(this); layout->SetInsets(GetInsets()); SetLayoutManager(layout); // The title, left-top aligned. views::ColumnSet* column_set = layout->AddColumnSet(kTitleRow); column_set->AddPaddingColumn(0, kHorizontalMargin); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::LEADING, 1, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kHorizontalMargin); // The view with default images and the one with image from camera and label. column_set = layout->AddColumnSet(kImagesRow); column_set->AddPaddingColumn(0, kHorizontalMargin); column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kHorizontalPadding); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::LEADING, 1, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kHorizontalMargin); // Splitter. column_set = layout->AddColumnSet(kSplitterRow); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::TRAILING, 1, views::GridLayout::USE_PREF, 0, 0); // OK button is in the right bottom corner of the view. column_set = layout->AddColumnSet(kButtonsRow); column_set->AddPaddingColumn(0, kHorizontalMargin); column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::TRAILING, 1, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kHorizontalMargin); // Fill the layout with rows and views now. layout->StartRowWithPadding(0, kTitleRow, 0, kVerticalMargin); layout->AddView(title_label_); layout->StartRowWithPadding(0, kImagesRow, 0, kVerticalPadding); layout->AddView(default_images_view_); layout->AddView(take_photo_view_); layout->StartRowWithPadding(1, kSplitterRow, 0, kVerticalPadding); // Set height for splitter view explicitly otherwise it's set to 0 // by default. layout->AddView(splitter_, 1, 1, views::GridLayout::FILL, views::GridLayout::TRAILING, 0, kSplitterHeight); layout->StartRowWithPadding(0, kButtonsRow, 0, kVerticalPadding); layout->AddView(ok_button_); layout->AddPaddingRow(0, kVerticalMargin); } void UserImageView::UpdateVideoFrame(const SkBitmap& frame) { DCHECK(take_photo_view_); take_photo_view_->UpdateVideoFrame(frame); } void UserImageView::ShowCameraInitializing() { DCHECK(take_photo_view_); take_photo_view_->ShowCameraInitializing(); } void UserImageView::ShowCameraError() { DCHECK(take_photo_view_); take_photo_view_->ShowCameraError(); } bool UserImageView::IsCapturing() const { DCHECK(default_images_view_); DCHECK(take_photo_view_); return default_images_view_->GetDefaultImageIndex() == -1 && take_photo_view_->is_capturing(); } gfx::Size UserImageView::GetPreferredSize() { return gfx::Size(width(), height()); } void UserImageView::NotifyDelegateOfImageSelected() { DCHECK(delegate_); DCHECK(default_images_view_); DCHECK(take_photo_view_); if (default_images_view_->GetDefaultImageIndex() == -1) { delegate_->OnPhotoTaken(take_photo_view_->GetImage()); } else { delegate_->OnDefaultImageSelected( default_images_view_->GetDefaultImageIndex()); } } void UserImageView::ButtonPressed( views::Button* sender, const views::Event& event) { DCHECK(delegate_); if (sender == ok_button_) NotifyDelegateOfImageSelected(); else NOTREACHED(); } bool UserImageView::AcceleratorPressed(const views::Accelerator& accel) { if (accel == accel_ok_) { if (IsCapturing()) take_photo_view_->CaptureImage(); else NotifyDelegateOfImageSelected(); } else if (accel == accel_up_) { default_images_view_->SelectPreviousRowImage(); } else if (accel == accel_down_) { default_images_view_->SelectNextRowImage(); } else if (accel == accel_left_) { default_images_view_->SelectPreviousImage(); } else if (accel == accel_right_) { default_images_view_->SelectNextImage(); } else { return false; } return true; } void UserImageView::OnCapturingStarted() { delegate_->StartCamera(); default_images_view_->ClearSelection(); ok_button_->SetEnabled(false); ShowCameraInitializing(); } void UserImageView::OnCapturingStopped() { delegate_->StopCamera(); default_images_view_->ClearSelection(); ok_button_->SetEnabled(true); ok_button_->RequestFocus(); } void UserImageView::OnCaptureButtonClicked() { if (!IsCapturing()) OnCapturingStarted(); } void UserImageView::OnImageSelected(int image_index) { // Can happen when user is not known, i.e. in tests. if (image_index < 0 || image_index >= kDefaultImagesCount) return; delegate_->StopCamera(); ok_button_->SetEnabled(true); ok_button_->RequestFocus(); take_photo_view_->SetImage( ResourceBundle::GetSharedInstance().GetBitmapNamed( kDefaultImageResources[image_index])); } } // namespace chromeos