普通文本  |  218行  |  7.45 KB

// 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/default_images_view.h"

#include "base/logging.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/login/default_user_images.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "grit/theme_resources.h"
#include "grit/generated_resources.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "views/border.h"
#include "views/background.h"
#include "views/controls/button/image_button.h"
#include "views/layout/grid_layout.h"

namespace chromeos {

namespace {

// Size of the default image within the view.
const int kDefaultImageSize = 64;
// Margin from left and right sides to the view contents.
const int kHorizontalMargin = 10;
// Margin from top and bottom sides to the view contents.
const int kVerticalMargin = 10;
// Padding between image columns.
const int kHorizontalPadding = 20;
// Padding between image rows.
const int kVerticalPadding = 15;
// Number of columns in a row of default images.
const int kColumnsCount = 5;
// Size of the border around default image.
const int kImageBorderSize = 1;
// Color of default image border.
const SkColor kImageBorderColor = SkColorSetARGB(38, 0, 0, 0);
// Color of default image background.
const SkColor kImageBackgroundColor = SK_ColorWHITE;
// We give each image control an ID so we could distinguish them. Since 0 is
// the default ID we want an offset for IDs we set.
const int kImageStartId = 100;
// ID for image control for video capture.
const int kCaptureButtonId = 1000;
// A number of the first buttons that don't correspond to any default image
// (i.e. button to take a photo).
const int kNonDefaultImageButtonsCount = 1;

}  // namespace

// Image button with border and background. Corrects view size by border
// insets as ImageButton ignores it.
class UserImageButton : public views::ImageButton {
 public:
  explicit UserImageButton(views::ButtonListener* listener);

  // Overridden from views::View:
  virtual gfx::Size GetPreferredSize();

 private:
  DISALLOW_COPY_AND_ASSIGN(UserImageButton);
};

UserImageButton::UserImageButton(views::ButtonListener* listener)
    : ImageButton(listener) {
  set_border(
      views::Border::CreateSolidBorder(kImageBorderSize, kImageBorderColor));
  set_background(
      views::Background::CreateSolidBackground(kImageBackgroundColor));
  SetImageAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
}

gfx::Size UserImageButton::GetPreferredSize() {
  gfx::Size size = views::ImageButton::GetPreferredSize();
  size.Enlarge(GetInsets().width(), GetInsets().height());
  return size;
}


DefaultImagesView::DefaultImagesView(Delegate* delegate)
    : selected_image_index_(-1),
      delegate_(delegate) {
}

void DefaultImagesView::Init() {
  UserImageButton* capture_button = new UserImageButton(this);
  capture_button->SetID(kCaptureButtonId);
  capture_button->SetTooltipText(UTF16ToWide(
      l10n_util::GetStringUTF16(IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO)));
  InitButton(IDR_BUTTON_USER_IMAGE_TAKE_PHOTO, capture_button);
  default_images_.push_back(capture_button);
  for (int i = 0; i < kDefaultImagesCount; ++i) {
    UserImageButton* image_button = new UserImageButton(this);
    image_button->SetID(i + kImageStartId);
    InitButton(kDefaultImageResources[i], image_button);
    default_images_.push_back(image_button);
  }
  InitLayout();
}

int DefaultImagesView::GetDefaultImageIndex() const {
  if (selected_image_index_ == -1)
    return -1;
  else
    return selected_image_index_ - kNonDefaultImageButtonsCount;
}

void DefaultImagesView::SetDefaultImageIndex(int image_index) {
  selected_image_index_ = image_index + kNonDefaultImageButtonsCount;
  if (delegate_)
    delegate_->OnImageSelected(image_index % kDefaultImagesCount);
}

void DefaultImagesView::ClearSelection() {
  selected_image_index_ = -1;
}

gfx::Size DefaultImagesView::GetPreferredSize() {
  int image_size_with_margin = (kDefaultImageSize + 2 * kImageBorderSize);
  int width = kColumnsCount * image_size_with_margin +
              (kColumnsCount - 1) * kHorizontalPadding;
  size_t image_count = default_images_.size();
  int rows_count = (image_count + kColumnsCount - 1) / kColumnsCount;
  int height = rows_count * image_size_with_margin +
               (rows_count - 1) * kVerticalPadding;
  return gfx::Size(width + 2 * kHorizontalMargin,
                   height + 2 * kVerticalMargin);
}

void DefaultImagesView::ButtonPressed(views::Button* sender,
                                      const views::Event& event) {
  if (selected_image_index_ != -1 &&
      default_images_[selected_image_index_] == sender)
    return;
  ClearSelection();

  if (sender->GetID() == kCaptureButtonId) {
    if (delegate_)
      delegate_->OnCaptureButtonClicked();
  } else {
    int image_index = sender->GetID() - kImageStartId;
    int images_count = static_cast<int>(default_images_.size());
    if (image_index < 0 || image_index >= images_count) {
      NOTREACHED() << "Got ButtonPressed event from a view with wrong id.";
      return;
    }
    SetDefaultImageIndex(image_index);
  }
}

void DefaultImagesView::InitButton(int resource_id,
                                   UserImageButton* button) const {
  const SkBitmap* original_image =
      ResourceBundle::GetSharedInstance().GetBitmapNamed(resource_id);
  SkBitmap resized_image = skia::ImageOperations::Resize(
      *original_image,
      skia::ImageOperations::RESIZE_BEST,
      kDefaultImageSize, kDefaultImageSize);
  button->SetImage(
      views::CustomButton::BS_NORMAL,
      &resized_image);
}

void DefaultImagesView::InitLayout() {
  views::GridLayout* layout = new views::GridLayout(this);
  layout->SetInsets(gfx::Insets(kVerticalMargin,
                                kHorizontalMargin,
                                kVerticalMargin,
                                kHorizontalMargin));
  SetLayoutManager(layout);

  size_t current_image = 0;
  size_t image_count = default_images_.size();
  int rows_count = (image_count + kColumnsCount - 1) / kColumnsCount;
  for (int row = 0; row < rows_count; ++row) {
    views::ColumnSet* column_set = layout->AddColumnSet(row);
    for (int column = 0; column < kColumnsCount; ++column) {
      if (column != 0)
        column_set->AddPaddingColumn(1, kHorizontalPadding);
      if (current_image < image_count) {
        column_set->AddColumn(
            views::GridLayout::LEADING,
            views::GridLayout::LEADING,
            1,
            views::GridLayout::USE_PREF,
            0,
            0);
      } else {
        int placeholders_count = kColumnsCount - column;
        int placeholders_width = placeholders_count *
                                 (kDefaultImageSize + 2 * kImageBorderSize);
        int padding_width = (placeholders_count - 1) * kHorizontalPadding;
        column_set->AddPaddingColumn(1, placeholders_width + padding_width);
        break;
      }
      ++current_image;
    }
  }
  current_image = 0;
  for (int row = 0; row < rows_count; ++row) {
    if (row != 0)
      layout->AddPaddingRow(1, kVerticalPadding);
    layout->StartRow(0, row);
    for (int column = 0; column < kColumnsCount; ++column) {
      if (current_image >= image_count)
        break;
      layout->AddView(default_images_[current_image]);
      ++current_image;
    }
  }
}

}  // namespace chromeos