This source file includes following definitions.
- touch_dragging_
- SetIconSize
- UpdateIcon
- UpdateTooltip
- SetUIState
- SetTouchDragging
- OnMouseDragTimer
- Prerender
- CancelContextMenu
- GetDragImage
- OnDragEnded
- GetDragImageOffset
- SetAsAttemptedFolderTarget
- ItemIconChanged
- ItemNameChanged
- ItemHighlightedChanged
- ItemIsInstallingChanged
- ItemPercentDownloadedChanged
- GetClassName
- Layout
- OnPaint
- ShowContextMenuForView
- StateChanged
- ShouldEnterPushedState
- OnMousePressed
- OnKeyPressed
- OnMouseReleased
- OnMouseCaptureLost
- OnMouseDragged
- OnGestureEvent
- OnSyncDragEnd
- GetIconBounds
- SetDragUIState
- GetIconBoundsForTargetViewBounds
#include "ui/app_list/views/app_list_item_view.h"
#include <algorithm>
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/app_list/app_list_constants.h"
#include "ui/app_list/app_list_item.h"
#include "ui/app_list/app_list_switches.h"
#include "ui/app_list/views/apps_grid_view.h"
#include "ui/app_list/views/cached_label.h"
#include "ui/app_list/views/progress_bar_view.h"
#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/point.h"
#include "ui/gfx/transform_util.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/drag_controller.h"
namespace app_list {
namespace {
const int kTopPadding = 20;
const int kIconTitleSpacing = 7;
const int kProgressBarHorizontalPadding = 12;
const int kFolderPreviewRadius = 40;
const int kLeftRightPaddingChars = 1;
const float kDraggingIconScale = 1.5f;
const int kMouseDragUIDelayInMs = 200;
}  
const char AppListItemView::kViewClassName[] = "ui/app_list/AppListItemView";
AppListItemView::AppListItemView(AppsGridView* apps_grid_view,
                                 AppListItem* item)
    : CustomButton(apps_grid_view),
      item_(item),
      apps_grid_view_(apps_grid_view),
      icon_(new views::ImageView),
      title_(new CachedLabel),
      progress_bar_(new ProgressBarView),
      ui_state_(UI_STATE_NORMAL),
      touch_dragging_(false) {
  icon_->set_interactive(false);
  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  title_->SetBackgroundColor(0);
  title_->SetAutoColorReadabilityEnabled(false);
  title_->SetEnabledColor(kGridTitleColor);
  title_->SetFontList(rb.GetFontList(kItemTextFontStyle));
  title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  title_->SetVisible(!item_->is_installing());
  title_->Invalidate();
  const gfx::ShadowValue kIconShadows[] = {
    gfx::ShadowValue(gfx::Point(0, 2), 2, SkColorSetARGB(0x24, 0, 0, 0)),
  };
  icon_shadows_.assign(kIconShadows, kIconShadows + arraysize(kIconShadows));
  AddChildView(icon_);
  AddChildView(title_);
  AddChildView(progress_bar_);
  ItemIconChanged();
  ItemNameChanged();
  ItemIsInstallingChanged();
  item_->AddObserver(this);
  set_context_menu_controller(this);
  set_request_focus_on_press(false);
  SetAnimationDuration(0);
}
AppListItemView::~AppListItemView() {
  item_->RemoveObserver(this);
}
void AppListItemView::SetIconSize(const gfx::Size& size) {
  if (icon_size_ == size)
    return;
  icon_size_ = size;
  UpdateIcon();
}
void AppListItemView::UpdateIcon() {
  
  if (icon_size_.IsEmpty())
    return;
  gfx::ImageSkia icon = item_->icon();
  
  if (icon.isNull()) {
    icon_->SetImage(NULL);
    return;
  }
  gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(icon,
      skia::ImageOperations::RESIZE_BEST, icon_size_));
  if (item_->has_shadow()) {
    gfx::ImageSkia shadow(
        gfx::ImageSkiaOperations::CreateImageWithDropShadow(resized,
                                                            icon_shadows_));
    icon_->SetImage(shadow);
    return;
  }
  icon_->SetImage(resized);
}
void AppListItemView::UpdateTooltip() {
  std::string display_name = item_->GetDisplayName();
  title_->SetTooltipText(display_name == item_->name() ? base::string16()
                         : base::UTF8ToUTF16(item_->name()));
}
void AppListItemView::SetUIState(UIState state) {
  if (ui_state_ == state)
    return;
  ui_state_ = state;
#if defined(USE_AURA)
  switch (ui_state_) {
    case UI_STATE_NORMAL:
      title_->SetVisible(!item_->is_installing());
      progress_bar_->SetVisible(item_->is_installing());
      break;
    case UI_STATE_DRAGGING:
      title_->SetVisible(false);
      progress_bar_->SetVisible(false);
      break;
    case UI_STATE_DROPPING_IN_FOLDER:
      break;
  }
#if !defined(OS_WIN)
  ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
  switch (ui_state_) {
    case UI_STATE_NORMAL:
      layer()->SetTransform(gfx::Transform());
      break;
    case UI_STATE_DRAGGING: {
      const gfx::Rect bounds(layer()->bounds().size());
      layer()->SetTransform(gfx::GetScaleTransform(
          bounds.CenterPoint(),
          kDraggingIconScale));
      break;
    }
    case UI_STATE_DROPPING_IN_FOLDER:
      break;
  }
  SchedulePaint();
#endif  
#endif  
}
void AppListItemView::SetTouchDragging(bool touch_dragging) {
  if (touch_dragging_ == touch_dragging)
    return;
  touch_dragging_ = touch_dragging;
  SetUIState(touch_dragging_ ? UI_STATE_DRAGGING : UI_STATE_NORMAL);
}
void AppListItemView::OnMouseDragTimer() {
  DCHECK(apps_grid_view_->IsDraggedView(this));
  SetUIState(UI_STATE_DRAGGING);
}
void AppListItemView::Prerender() {
  title_->PaintToBackingImage();
}
void AppListItemView::CancelContextMenu() {
  if (context_menu_runner_)
    context_menu_runner_->Cancel();
}
gfx::ImageSkia AppListItemView::GetDragImage() {
  return icon_->GetImage();
}
void AppListItemView::OnDragEnded() {
  mouse_drag_timer_.Stop();
  SetUIState(UI_STATE_NORMAL);
}
gfx::Point AppListItemView::GetDragImageOffset() {
  gfx::Point image = icon_->GetImageBounds().origin();
  return gfx::Point(icon_->x() + image.x(), icon_->y() + image.y());
}
void AppListItemView::SetAsAttemptedFolderTarget(bool is_target_folder) {
  if (is_target_folder)
    SetUIState(UI_STATE_DROPPING_IN_FOLDER);
  else
    SetUIState(UI_STATE_NORMAL);
}
void AppListItemView::ItemIconChanged() {
  UpdateIcon();
}
void AppListItemView::ItemNameChanged() {
  title_->SetText(base::UTF8ToUTF16(item_->GetDisplayName()));
  title_->Invalidate();
  UpdateTooltip();
  
  SetAccessibleName(base::UTF8ToUTF16(item_->name()));
  Layout();
}
void AppListItemView::ItemHighlightedChanged() {
  apps_grid_view_->EnsureViewVisible(this);
  SchedulePaint();
}
void AppListItemView::ItemIsInstallingChanged() {
  if (item_->is_installing())
    apps_grid_view_->EnsureViewVisible(this);
  title_->SetVisible(!item_->is_installing());
  progress_bar_->SetVisible(item_->is_installing());
  SchedulePaint();
}
void AppListItemView::ItemPercentDownloadedChanged() {
  
  
  
  if (item_->percent_downloaded() == -1)
    return;
  progress_bar_->SetValue(item_->percent_downloaded() / 100.0);
}
const char* AppListItemView::GetClassName() const {
  return kViewClassName;
}
void AppListItemView::Layout() {
  gfx::Rect rect(GetContentsBounds());
  const int left_right_padding =
      title_->font_list().GetExpectedTextWidth(kLeftRightPaddingChars);
  rect.Inset(left_right_padding, kTopPadding, left_right_padding, 0);
  const int y = rect.y();
  icon_->SetBoundsRect(GetIconBoundsForTargetViewBounds(GetContentsBounds()));
  const gfx::Size title_size = title_->GetPreferredSize();
  gfx::Rect title_bounds(rect.x() + (rect.width() - title_size.width()) / 2,
                         y + icon_size_.height() + kIconTitleSpacing,
                         title_size.width(),
                         title_size.height());
  title_bounds.Intersect(rect);
  title_->SetBoundsRect(title_bounds);
  gfx::Rect progress_bar_bounds(progress_bar_->GetPreferredSize());
  progress_bar_bounds.set_x(GetContentsBounds().x() +
                            kProgressBarHorizontalPadding);
  progress_bar_bounds.set_y(title_bounds.y());
  progress_bar_->SetBoundsRect(progress_bar_bounds);
}
void AppListItemView::OnPaint(gfx::Canvas* canvas) {
  if (apps_grid_view_->IsDraggedView(this))
    return;
  gfx::Rect rect(GetContentsBounds());
  if (item_->highlighted() && !item_->is_installing()) {
    canvas->FillRect(rect, kHighlightedColor);
    return;
  } else if (apps_grid_view_->IsSelectedView(this)) {
      canvas->FillRect(rect, kSelectedColor);
  }
  if (!switches::IsFolderUIEnabled()) {
    if (apps_grid_view_->IsSelectedView(this)) {
      canvas->FillRect(rect, kSelectedColor);
    } else if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
      canvas->FillRect(rect, kHighlightedColor);
    }
  } else if (ui_state_ == UI_STATE_DROPPING_IN_FOLDER) {
    
    gfx::Point center = gfx::Point(icon_->x() + icon_->size().width() / 2,
                                   icon_->y() + icon_->size().height() / 2);
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setAntiAlias(true);
    paint.setColor(kFolderBubbleColor);
    canvas->DrawCircle(center, kFolderPreviewRadius, paint);
  }
}
void AppListItemView::ShowContextMenuForView(views::View* source,
                                             const gfx::Point& point,
                                             ui::MenuSourceType source_type) {
  ui::MenuModel* menu_model = item_->GetContextMenuModel();
  if (!menu_model)
    return;
  context_menu_runner_.reset(new views::MenuRunner(menu_model));
  if (context_menu_runner_->RunMenuAt(
          GetWidget(), NULL, gfx::Rect(point, gfx::Size()),
          views::MenuItemView::TOPLEFT, source_type,
          views::MenuRunner::HAS_MNEMONICS) ==
      views::MenuRunner::MENU_DELETED)
    return;
}
void AppListItemView::StateChanged() {
  const bool is_folder_ui_enabled = switches::IsFolderUIEnabled();
  if (is_folder_ui_enabled)
    apps_grid_view_->ClearAnySelectedView();
  if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
    if (!is_folder_ui_enabled)
      apps_grid_view_->SetSelectedView(this);
    title_->SetEnabledColor(kGridTitleHoverColor);
  } else {
    if (!is_folder_ui_enabled)
      apps_grid_view_->ClearSelectedView(this);
    item_->SetHighlighted(false);
    title_->SetEnabledColor(kGridTitleColor);
  }
  title_->Invalidate();
}
bool AppListItemView::ShouldEnterPushedState(const ui::Event& event) {
  
  
  if (event.type() == ui::ET_GESTURE_TAP_DOWN)
    return false;
  return views::CustomButton::ShouldEnterPushedState(event);
}
bool AppListItemView::OnMousePressed(const ui::MouseEvent& event) {
  CustomButton::OnMousePressed(event);
  if (!ShouldEnterPushedState(event))
    return true;
  apps_grid_view_->InitiateDrag(this, AppsGridView::MOUSE, event);
  if (apps_grid_view_->IsDraggedView(this)) {
    mouse_drag_timer_.Start(FROM_HERE,
        base::TimeDelta::FromMilliseconds(kMouseDragUIDelayInMs),
        this, &AppListItemView::OnMouseDragTimer);
  }
  return true;
}
bool AppListItemView::OnKeyPressed(const ui::KeyEvent& event) {
  
  
  
  
  if (event.key_code() == ui::VKEY_SPACE)
    return false;
  return CustomButton::OnKeyPressed(event);
}
void AppListItemView::OnMouseReleased(const ui::MouseEvent& event) {
  CustomButton::OnMouseReleased(event);
  apps_grid_view_->EndDrag(false);
}
void AppListItemView::OnMouseCaptureLost() {
  
  
  
#if !defined(OS_WIN)
  CustomButton::OnMouseCaptureLost();
  apps_grid_view_->EndDrag(true);
#endif
}
bool AppListItemView::OnMouseDragged(const ui::MouseEvent& event) {
  CustomButton::OnMouseDragged(event);
  if (apps_grid_view_->IsDraggedView(this)) {
    
    
    
    
    if (!apps_grid_view_->UpdateDragFromItem(AppsGridView::MOUSE, event))
      return true;
  }
  
  if (ui_state_ != UI_STATE_DRAGGING &&
      apps_grid_view_->dragging() &&
      apps_grid_view_->IsDraggedView(this)) {
    mouse_drag_timer_.Stop();
    SetUIState(UI_STATE_DRAGGING);
  }
  return true;
}
void AppListItemView::OnGestureEvent(ui::GestureEvent* event) {
  switch (event->type()) {
    case ui::ET_GESTURE_SCROLL_BEGIN:
      if (touch_dragging_) {
        apps_grid_view_->InitiateDrag(this, AppsGridView::TOUCH, *event);
        event->SetHandled();
      }
      break;
    case ui::ET_GESTURE_SCROLL_UPDATE:
      if (touch_dragging_ && apps_grid_view_->IsDraggedView(this)) {
        apps_grid_view_->UpdateDragFromItem(AppsGridView::TOUCH, *event);
        event->SetHandled();
      }
      break;
    case ui::ET_GESTURE_SCROLL_END:
    case ui::ET_SCROLL_FLING_START:
      if (touch_dragging_) {
        SetTouchDragging(false);
        apps_grid_view_->EndDrag(false);
        event->SetHandled();
      }
      break;
    case ui::ET_GESTURE_LONG_PRESS:
      if (!apps_grid_view_->has_dragged_view())
        SetTouchDragging(true);
      event->SetHandled();
      break;
    case ui::ET_GESTURE_LONG_TAP:
    case ui::ET_GESTURE_END:
      if (touch_dragging_)
        SetTouchDragging(false);
      break;
    default:
      break;
  }
  if (!event->handled())
    CustomButton::OnGestureEvent(event);
}
void AppListItemView::OnSyncDragEnd() {
  SetUIState(UI_STATE_NORMAL);
}
const gfx::Rect& AppListItemView::GetIconBounds() const {
  return icon_->bounds();
}
void AppListItemView::SetDragUIState() {
  SetUIState(UI_STATE_DRAGGING);
}
gfx::Rect AppListItemView::GetIconBoundsForTargetViewBounds(
    const gfx::Rect& target_bounds) {
  gfx::Rect rect(target_bounds);
  const int left_right_padding =
      title_->font_list().GetExpectedTextWidth(kLeftRightPaddingChars);
  rect.Inset(left_right_padding, kTopPadding, left_right_padding, 0);
  gfx::Rect icon_bounds(rect.x(), rect.y(), rect.width(), icon_size_.height());
  icon_bounds.Inset(gfx::ShadowValue::GetMargin(icon_shadows_));
  return icon_bounds;
}
}