Home | History | Annotate | Download | only in login
      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/default_images_view.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/utf_string_conversions.h"
      9 #include "chrome/browser/chromeos/login/default_user_images.h"
     10 #include "chrome/browser/chromeos/login/rounded_rect_painter.h"
     11 #include "grit/theme_resources.h"
     12 #include "grit/generated_resources.h"
     13 #include "skia/ext/image_operations.h"
     14 #include "third_party/skia/include/core/SkColor.h"
     15 #include "ui/base/l10n/l10n_util.h"
     16 #include "ui/base/resource/resource_bundle.h"
     17 #include "views/border.h"
     18 #include "views/background.h"
     19 #include "views/controls/button/image_button.h"
     20 #include "views/layout/grid_layout.h"
     21 
     22 namespace chromeos {
     23 
     24 namespace {
     25 
     26 // Size of the default image within the view.
     27 const int kDefaultImageSize = 64;
     28 // Margin from left and right sides to the view contents.
     29 const int kHorizontalMargin = 10;
     30 // Margin from top and bottom sides to the view contents.
     31 const int kVerticalMargin = 10;
     32 // Padding between image columns.
     33 const int kHorizontalPadding = 20;
     34 // Padding between image rows.
     35 const int kVerticalPadding = 15;
     36 // Number of columns in a row of default images.
     37 const int kColumnsCount = 5;
     38 // Size of the border around default image.
     39 const int kImageBorderSize = 1;
     40 // Color of default image border.
     41 const SkColor kImageBorderColor = SkColorSetARGB(38, 0, 0, 0);
     42 // Color of default image background.
     43 const SkColor kImageBackgroundColor = SK_ColorWHITE;
     44 // We give each image control an ID so we could distinguish them. Since 0 is
     45 // the default ID we want an offset for IDs we set.
     46 const int kImageStartId = 100;
     47 // ID for image control for video capture.
     48 const int kCaptureButtonId = 1000;
     49 // A number of the first buttons that don't correspond to any default image
     50 // (i.e. button to take a photo).
     51 const int kNonDefaultImageButtonsCount = 1;
     52 
     53 }  // namespace
     54 
     55 // Image button with border and background. Corrects view size by border
     56 // insets as ImageButton ignores it.
     57 class UserImageButton : public views::ImageButton {
     58  public:
     59   explicit UserImageButton(views::ButtonListener* listener);
     60 
     61   // Overridden from views::View:
     62   virtual gfx::Size GetPreferredSize();
     63 
     64  private:
     65   DISALLOW_COPY_AND_ASSIGN(UserImageButton);
     66 };
     67 
     68 UserImageButton::UserImageButton(views::ButtonListener* listener)
     69     : ImageButton(listener) {
     70   set_border(
     71       views::Border::CreateSolidBorder(kImageBorderSize, kImageBorderColor));
     72   set_background(
     73       views::Background::CreateSolidBackground(kImageBackgroundColor));
     74   SetImageAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
     75 }
     76 
     77 gfx::Size UserImageButton::GetPreferredSize() {
     78   gfx::Size size = views::ImageButton::GetPreferredSize();
     79   size.Enlarge(GetInsets().width(), GetInsets().height());
     80   return size;
     81 }
     82 
     83 
     84 DefaultImagesView::DefaultImagesView(Delegate* delegate)
     85     : selected_image_index_(-1),
     86       delegate_(delegate) {
     87 }
     88 
     89 void DefaultImagesView::Init() {
     90   UserImageButton* capture_button = new UserImageButton(this);
     91   capture_button->SetID(kCaptureButtonId);
     92   capture_button->SetTooltipText(UTF16ToWide(
     93       l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO)));
     94   InitButton(IDR_BUTTON_USER_IMAGE_TAKE_PHOTO, capture_button);
     95   default_images_.push_back(capture_button);
     96   for (int i = 0; i < kDefaultImagesCount; ++i) {
     97     UserImageButton* image_button = new UserImageButton(this);
     98     image_button->SetID(i + kImageStartId);
     99     InitButton(kDefaultImageResources[i], image_button);
    100     default_images_.push_back(image_button);
    101   }
    102   InitLayout();
    103 }
    104 
    105 int DefaultImagesView::GetDefaultImageIndex() const {
    106   if (selected_image_index_ == -1)
    107     return -1;
    108   else
    109     return selected_image_index_ - kNonDefaultImageButtonsCount;
    110 }
    111 
    112 void DefaultImagesView::SetDefaultImageIndex(int image_index) {
    113   selected_image_index_ = image_index + kNonDefaultImageButtonsCount;
    114   if (delegate_)
    115     delegate_->OnImageSelected(image_index % kDefaultImagesCount);
    116 }
    117 
    118 void DefaultImagesView::ClearSelection() {
    119   selected_image_index_ = -1;
    120 }
    121 
    122 gfx::Size DefaultImagesView::GetPreferredSize() {
    123   int image_size_with_margin = (kDefaultImageSize + 2 * kImageBorderSize);
    124   int width = kColumnsCount * image_size_with_margin +
    125               (kColumnsCount - 1) * kHorizontalPadding;
    126   size_t image_count = default_images_.size();
    127   int rows_count = (image_count + kColumnsCount - 1) / kColumnsCount;
    128   int height = rows_count * image_size_with_margin +
    129                (rows_count - 1) * kVerticalPadding;
    130   return gfx::Size(width + 2 * kHorizontalMargin,
    131                    height + 2 * kVerticalMargin);
    132 }
    133 
    134 void DefaultImagesView::ButtonPressed(views::Button* sender,
    135                                       const views::Event& event) {
    136   if (selected_image_index_ != -1 &&
    137       default_images_[selected_image_index_] == sender)
    138     return;
    139   ClearSelection();
    140 
    141   if (sender->GetID() == kCaptureButtonId) {
    142     if (delegate_)
    143       delegate_->OnCaptureButtonClicked();
    144   } else {
    145     int image_index = sender->GetID() - kImageStartId;
    146     int images_count = static_cast<int>(default_images_.size());
    147     if (image_index < 0 || image_index >= images_count) {
    148       NOTREACHED() << "Got ButtonPressed event from a view with wrong id.";
    149       return;
    150     }
    151     SetDefaultImageIndex(image_index);
    152   }
    153 }
    154 
    155 void DefaultImagesView::InitButton(int resource_id,
    156                                    UserImageButton* button) const {
    157   const SkBitmap* original_image =
    158       ResourceBundle::GetSharedInstance().GetBitmapNamed(resource_id);
    159   SkBitmap resized_image = skia::ImageOperations::Resize(
    160       *original_image,
    161       skia::ImageOperations::RESIZE_BEST,
    162       kDefaultImageSize, kDefaultImageSize);
    163   button->SetImage(
    164       views::CustomButton::BS_NORMAL,
    165       &resized_image);
    166 }
    167 
    168 void DefaultImagesView::InitLayout() {
    169   views::GridLayout* layout = new views::GridLayout(this);
    170   layout->SetInsets(gfx::Insets(kVerticalMargin,
    171                                 kHorizontalMargin,
    172                                 kVerticalMargin,
    173                                 kHorizontalMargin));
    174   SetLayoutManager(layout);
    175 
    176   size_t current_image = 0;
    177   size_t image_count = default_images_.size();
    178   int rows_count = (image_count + kColumnsCount - 1) / kColumnsCount;
    179   for (int row = 0; row < rows_count; ++row) {
    180     views::ColumnSet* column_set = layout->AddColumnSet(row);
    181     for (int column = 0; column < kColumnsCount; ++column) {
    182       if (column != 0)
    183         column_set->AddPaddingColumn(1, kHorizontalPadding);
    184       if (current_image < image_count) {
    185         column_set->AddColumn(
    186             views::GridLayout::LEADING,
    187             views::GridLayout::LEADING,
    188             1,
    189             views::GridLayout::USE_PREF,
    190             0,
    191             0);
    192       } else {
    193         int placeholders_count = kColumnsCount - column;
    194         int placeholders_width = placeholders_count *
    195                                  (kDefaultImageSize + 2 * kImageBorderSize);
    196         int padding_width = (placeholders_count - 1) * kHorizontalPadding;
    197         column_set->AddPaddingColumn(1, placeholders_width + padding_width);
    198         break;
    199       }
    200       ++current_image;
    201     }
    202   }
    203   current_image = 0;
    204   for (int row = 0; row < rows_count; ++row) {
    205     if (row != 0)
    206       layout->AddPaddingRow(1, kVerticalPadding);
    207     layout->StartRow(0, row);
    208     for (int column = 0; column < kColumnsCount; ++column) {
    209       if (current_image >= image_count)
    210         break;
    211       layout->AddView(default_images_[current_image]);
    212       ++current_image;
    213     }
    214   }
    215 }
    216 
    217 }  // namespace chromeos
    218