Index: ash/app_list/app_list_item_view.cc |
=================================================================== |
--- ash/app_list/app_list_item_view.cc (revision 135932) |
+++ ash/app_list/app_list_item_view.cc (working copy) |
@@ -1,403 +0,0 @@ |
-// Copyright (c) 2012 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 "ash/app_list/app_list_item_view.h" |
- |
-#include "ash/app_list/app_list.h" |
-#include "ash/app_list/app_list_item_model.h" |
-#include "ash/app_list/app_list_model_view.h" |
-#include "ash/app_list/drop_shadow_label.h" |
-#include "ash/app_list/icon_cache.h" |
-#include "base/bind.h" |
-#include "base/message_loop.h" |
-#include "base/synchronization/cancellation_flag.h" |
-#include "base/threading/worker_pool.h" |
-#include "base/utf_string_conversions.h" |
-#include "ui/base/accessibility/accessible_view_state.h" |
-#include "ui/base/animation/throb_animation.h" |
-#include "ui/base/resource/resource_bundle.h" |
-#include "ui/gfx/canvas.h" |
-#include "ui/gfx/font.h" |
-#include "ui/gfx/shadow_value.h" |
-#include "ui/gfx/skbitmap_operations.h" |
-#include "ui/views/controls/image_view.h" |
-#include "ui/views/controls/menu/menu_item_view.h" |
-#include "ui/views/controls/menu/menu_model_adapter.h" |
-#include "ui/views/controls/menu/menu_runner.h" |
- |
-namespace ash { |
- |
-namespace { |
- |
-const int kTopBottomPadding = 10; |
-const int kIconTitleSpacing = 10; |
- |
-const SkColor kTitleColor = SK_ColorWHITE; |
-const SkColor kTitleColorV2 = SkColorSetARGB(0xFF, 0x88, 0x88, 0x88); |
- |
-// 0.33 black |
-const SkColor kHoverAndPushedColor = SkColorSetARGB(0x55, 0x00, 0x00, 0x00); |
- |
-// 0.16 black |
-const SkColor kSelectedColor = SkColorSetARGB(0x2A, 0x00, 0x00, 0x00); |
- |
-const SkColor kHighlightedColor = kHoverAndPushedColor; |
- |
-// FontSize/IconSize ratio = 24 / 128, which means we should get 24 font size |
-// when icon size is 128. |
-const float kFontSizeToIconSizeRatio = 0.1875f; |
- |
-// Font smaller than kBoldFontSize needs to be bold. |
-const int kBoldFontSize = 14; |
- |
-const int kMinFontSize = 12; |
- |
-const int kMinTitleChars = 15; |
- |
-const int kLeftRightPaddingChars = 1; |
- |
-const gfx::Font& GetTitleFontForIconSize(const gfx::Size& size) { |
- static int icon_height; |
- static gfx::Font* font = NULL; |
- |
- if (font && icon_height == size.height()) |
- return *font; |
- |
- delete font; |
- |
- icon_height = size.height(); |
- int font_size = std::max( |
- static_cast<int>(icon_height * kFontSizeToIconSizeRatio), |
- kMinFontSize); |
- |
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
- gfx::Font title_font(rb.GetFont(ui::ResourceBundle::BaseFont).GetFontName(), |
- font_size); |
- if (font_size <= kBoldFontSize) |
- title_font = title_font.DeriveFont(0, gfx::Font::BOLD); |
- font = new gfx::Font(title_font); |
- return *font; |
-} |
- |
-// An image view that is not interactive. |
-class StaticImageView : public views::ImageView { |
- public: |
- StaticImageView() : ImageView() { |
- } |
- |
- private: |
- // views::View overrides: |
- virtual bool HitTest(const gfx::Point& l) const OVERRIDE { |
- return false; |
- } |
- |
- DISALLOW_COPY_AND_ASSIGN(StaticImageView); |
-}; |
- |
-// A minimum title width set by test to override the default logic that derives |
-// the min width from font. |
-int g_min_title_width = 0; |
- |
-} // namespace |
- |
-// static |
-const char AppListItemView::kViewClassName[] = "ash/app_list/AppListItemView"; |
- |
-// AppListItemView::IconOperation wraps background icon processing. |
-class AppListItemView::IconOperation |
- : public base::RefCountedThreadSafe<AppListItemView::IconOperation> { |
- public: |
- IconOperation(const SkBitmap& bitmap, const gfx::Size& size) |
- : bitmap_(bitmap), |
- size_(size) { |
- } |
- |
- static void Run(scoped_refptr<IconOperation> op) { |
- op->ResizeAndGenerateShadow(); |
- } |
- |
- // Padding space around icon to contain its shadow. Note it should be at least |
- // the max size of shadow radius + shadow offset in shadow generation code. |
- static const int kShadowPadding = 15; |
- |
- void ResizeAndGenerateShadow() { |
- // If you change shadow radius and shadow offset, please also update |
- // kShadowPaddingAbove. |
- const SkColor kShadowColor[] = { |
- SkColorSetARGB(0xCC, 0, 0, 0), |
- SkColorSetARGB(0x33, 0, 0, 0), |
- SkColorSetARGB(0x4C, 0, 0, 0), |
- }; |
- const gfx::Point kShadowOffset[] = { |
- gfx::Point(0, 0), |
- gfx::Point(0, 4), |
- gfx::Point(0, 5), |
- }; |
- const SkScalar kShadowRadius[] = { |
- SkIntToScalar(2), |
- SkIntToScalar(4), |
- SkIntToScalar(10), |
- }; |
- |
- if (cancel_flag_.IsSet()) |
- return; |
- |
- if (size_ != gfx::Size(bitmap_.width(), bitmap_.height())) |
- bitmap_ = SkBitmapOperations::CreateResizedBitmap(bitmap_, size_); |
- |
- if (cancel_flag_.IsSet()) |
- return; |
- |
- bitmap_ = SkBitmapOperations::CreateDropShadow( |
- bitmap_, |
- arraysize(kShadowColor), |
- kShadowColor, |
- kShadowOffset, |
- kShadowRadius); |
- } |
- |
- void Cancel() { |
- cancel_flag_.Set(); |
- } |
- |
- const SkBitmap& bitmap() const { |
- return bitmap_; |
- } |
- |
- private: |
- friend class base::RefCountedThreadSafe<AppListItemView::IconOperation>; |
- |
- base::CancellationFlag cancel_flag_; |
- |
- SkBitmap bitmap_; |
- const gfx::Size size_; |
- |
- DISALLOW_COPY_AND_ASSIGN(IconOperation); |
-}; |
- |
-AppListItemView::AppListItemView(AppListModelView* list_model_view, |
- AppListItemModel* model, |
- views::ButtonListener* listener) |
- : CustomButton(listener), |
- model_(model), |
- list_model_view_(list_model_view), |
- icon_(new StaticImageView), |
- title_(new DropShadowLabel), |
- selected_(false), |
- ALLOW_THIS_IN_INITIALIZER_LIST(apply_shadow_factory_(this)) { |
- title_->SetBackgroundColor(0); |
- |
- if (internal::AppList::UseAppListV2()) { |
- title_->SetEnabledColor(kTitleColorV2); |
- } else { |
- title_->SetEnabledColor(kTitleColor); |
- const gfx::ShadowValue kTitleShadows[] = { |
- gfx::ShadowValue(gfx::Point(0, 0), 1, SkColorSetARGB(0x66, 0, 0, 0)), |
- gfx::ShadowValue(gfx::Point(0, 0), 10, SkColorSetARGB(0x66, 0, 0, 0)), |
- gfx::ShadowValue(gfx::Point(0, 2), 2, SkColorSetARGB(0x66, 0, 0, 0)), |
- gfx::ShadowValue(gfx::Point(0, 2), 4, SkColorSetARGB(0x66, 0, 0, 0)), |
- }; |
- title_->SetTextShadows(arraysize(kTitleShadows), kTitleShadows); |
- } |
- |
- AddChildView(icon_); |
- AddChildView(title_); |
- |
- ItemIconChanged(); |
- ItemTitleChanged(); |
- model_->AddObserver(this); |
- |
- set_context_menu_controller(this); |
- set_request_focus_on_press(false); |
- set_focusable(true); |
-} |
- |
-AppListItemView::~AppListItemView() { |
- model_->RemoveObserver(this); |
- CancelPendingIconOperation(); |
-} |
- |
-// static |
-gfx::Size AppListItemView::GetPreferredSizeForIconSize( |
- const gfx::Size& icon_size) { |
- int min_title_width = g_min_title_width; |
- // Fixed 20px is used for left/right padding before switching to padding |
- // based on number of chars. It is also a number used for test case |
- // AppList.ModelViewCalculateLayout. |
- int left_right_padding = 20; |
- if (min_title_width == 0) { |
- const gfx::Font& title_font = GetTitleFontForIconSize(icon_size); |
- // Use big char such as 'G' to calculate min title width. |
- min_title_width = kMinTitleChars * |
- title_font.GetStringWidth(ASCIIToUTF16("G")); |
- left_right_padding = kLeftRightPaddingChars * |
- title_font.GetAverageCharacterWidth(); |
- } |
- |
- int dimension = std::max(icon_size.width() * 2, min_title_width); |
- gfx::Size size(dimension, dimension); |
- size.Enlarge(left_right_padding, kTopBottomPadding); |
- return size; |
-} |
- |
-// static |
-void AppListItemView::SetMinTitleWidth(int width) { |
- g_min_title_width = width; |
-} |
- |
-void AppListItemView::SetIconSize(const gfx::Size& size) { |
- if (icon_size_ == size) |
- return; |
- |
- icon_size_ = size; |
- title_->SetFont(GetTitleFontForIconSize(size)); |
- UpdateIcon(); |
-} |
- |
-void AppListItemView::SetSelected(bool selected) { |
- if (selected == selected_) |
- return; |
- |
- RequestFocus(); |
- selected_ = selected; |
- SchedulePaint(); |
-} |
- |
-void AppListItemView::UpdateIcon() { |
- // Skip if |icon_size_| has not been determined. |
- if (icon_size_.IsEmpty()) |
- return; |
- |
- SkBitmap icon = model_->icon(); |
- // Clear icon and bail out if model icon is empty. |
- if (icon.empty()) { |
- icon_->SetImage(NULL); |
- return; |
- } |
- |
- CancelPendingIconOperation(); |
- |
- SkBitmap shadow; |
- if (IconCache::GetInstance()->Get(icon, icon_size_, &shadow)) { |
- icon_->SetImage(shadow); |
- } else { |
- // Schedule resize and shadow generation. |
- icon_op_ = new IconOperation(icon, icon_size_); |
- base::WorkerPool::PostTaskAndReply( |
- FROM_HERE, |
- base::Bind(&IconOperation::Run, icon_op_), |
- base::Bind(&AppListItemView::ApplyShadow, |
- apply_shadow_factory_.GetWeakPtr(), |
- icon_op_), |
- true /* task_is_slow */); |
- } |
-} |
- |
-void AppListItemView::CancelPendingIconOperation() { |
- // Set canceled flag of previous request to skip unneeded processing. |
- if (icon_op_.get()) |
- icon_op_->Cancel(); |
- |
- // Cancel reply callback for previous request. |
- apply_shadow_factory_.InvalidateWeakPtrs(); |
-} |
- |
-void AppListItemView::ApplyShadow(scoped_refptr<IconOperation> op) { |
- icon_->SetImage(op->bitmap()); |
- IconCache::GetInstance()->Put(model_->icon(), icon_size_, op->bitmap()); |
- |
- DCHECK(op.get() == icon_op_.get()); |
- icon_op_ = NULL; |
-} |
- |
-void AppListItemView::ItemIconChanged() { |
- UpdateIcon(); |
-} |
- |
-void AppListItemView::ItemTitleChanged() { |
- title_->SetText(UTF8ToUTF16(model_->title())); |
-} |
- |
-void AppListItemView::ItemHighlightedChanged() { |
- SchedulePaint(); |
-} |
- |
-std::string AppListItemView::GetClassName() const { |
- return kViewClassName; |
-} |
- |
-gfx::Size AppListItemView::GetPreferredSize() { |
- return GetPreferredSizeForIconSize(icon_size_); |
-} |
- |
-void AppListItemView::Layout() { |
- gfx::Rect rect(GetContentsBounds()); |
- |
- int left_right_padding = kLeftRightPaddingChars * |
- title_->font().GetAverageCharacterWidth(); |
- rect.Inset(left_right_padding, kTopBottomPadding); |
- |
- gfx::Size title_size = title_->GetPreferredSize(); |
- int height = icon_size_.height() + kIconTitleSpacing + |
- title_size.height(); |
- int y = rect.y() + (rect.height() - height) / 2; |
- |
- gfx::Rect icon_bounds(rect.x(), y, rect.width(), icon_size_.height()); |
- icon_bounds.Inset(0, -IconOperation::kShadowPadding); |
- icon_->SetBoundsRect(icon_bounds); |
- |
- title_->SetBounds(rect.x(), |
- y + icon_size_.height() + kIconTitleSpacing, |
- rect.width(), |
- title_size.height()); |
-} |
- |
-void AppListItemView::OnPaint(gfx::Canvas* canvas) { |
- gfx::Rect rect(GetContentsBounds()); |
- |
- if (model_->highlighted()) { |
- canvas->FillRect(rect, kHighlightedColor); |
- } else if (hover_animation_->is_animating()) { |
- int alpha = SkColorGetA(kHoverAndPushedColor) * |
- hover_animation_->GetCurrentValue(); |
- canvas->FillRect(rect, SkColorSetA(kHoverAndPushedColor, alpha)); |
- } else if (state() == BS_HOT || state() == BS_PUSHED) { |
- canvas->FillRect(rect, kHoverAndPushedColor); |
- } else if (selected_) { |
- canvas->FillRect(rect, kSelectedColor); |
- } |
-} |
- |
-void AppListItemView::GetAccessibleState(ui::AccessibleViewState* state) { |
- state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; |
- state->name = UTF8ToUTF16(model_->title()); |
-} |
- |
-void AppListItemView::ShowContextMenuForView(views::View* source, |
- const gfx::Point& point) { |
- ui::MenuModel* menu_model = model_->GetContextMenuModel(); |
- if (!menu_model) |
- return; |
- |
- views::MenuModelAdapter menu_adapter(menu_model); |
- context_menu_runner_.reset( |
- new views::MenuRunner(new views::MenuItemView(&menu_adapter))); |
- menu_adapter.BuildMenu(context_menu_runner_->GetMenu()); |
- if (context_menu_runner_->RunMenuAt( |
- GetWidget(), NULL, gfx::Rect(point, gfx::Size()), |
- views::MenuItemView::TOPLEFT, views::MenuRunner::HAS_MNEMONICS) == |
- views::MenuRunner::MENU_DELETED) |
- return; |
-} |
- |
-void AppListItemView::StateChanged() { |
- if (state() == BS_HOT || state() == BS_PUSHED) { |
- list_model_view_->SetSelectedItem(this); |
- } else { |
- list_model_view_->ClearSelectedItem(this); |
- model_->SetHighlighted(false); |
- } |
-} |
- |
-} // namespace ash |