| Index: ui/aura_shell/app_list/results_view.cc
|
| diff --git a/ui/aura_shell/app_list/results_view.cc b/ui/aura_shell/app_list/results_view.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..40940f083b576b6b18f009d606546f9efdd440ba
|
| --- /dev/null
|
| +++ b/ui/aura_shell/app_list/results_view.cc
|
| @@ -0,0 +1,239 @@
|
| +// 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 "ui/aura_shell/app_list/results_view.h"
|
| +
|
| +#include "base/utf_string_conversions.h"
|
| +#include "ui/aura_shell/app_list/app_list_item_group_model.h"
|
| +#include "ui/aura_shell/app_list/app_list_model.h"
|
| +#include "ui/aura_shell/app_list/tile_view.h"
|
| +#include "ui/aura_shell/app_list/tiles_page_view.h"
|
| +#include "ui/base/resource/resource_bundle.h"
|
| +#include "ui/views/animation/bounds_animator.h"
|
| +#include "ui/views/controls/button/text_button.h"
|
| +#include "ui/views/layout/box_layout.h"
|
| +#include "third_party/skia/include/core/SkColor.h"
|
| +
|
| +namespace aura_shell {
|
| +
|
| +namespace {
|
| +
|
| +const SkColor kPageHeaderColor = SkColorSetARGB(0xFF, 0xB2, 0xB2, 0xB2);
|
| +const SkColor kSelectedPageHeaderColor = SK_ColorWHITE;
|
| +
|
| +// Creates page headers view that hosts page title buttons.
|
| +views::View* CreatePageHeader() {
|
| + views::View* header = new views::View;
|
| + header->SetLayoutManager(
|
| + new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
|
| + return header;
|
| +}
|
| +
|
| +// Creates page header button view that shows page title.
|
| +views::View* CreatePageHeaderButton(views::ButtonListener* listener,
|
| + const std::string& title ) {
|
| + views::TextButton* button = new views::TextButton(listener,
|
| + UTF8ToUTF16(title));
|
| +
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + button->SetFont(rb.GetFont(ResourceBundle::BaseFont).DeriveFont(
|
| + 2, gfx::Font::BOLD));
|
| + button->SetEnabledColor(kPageHeaderColor);
|
| + return button;
|
| +}
|
| +
|
| +// Gets preferred bounds of buttons and page.
|
| +void GetPageAndHeaderBounds(views::View* parent,
|
| + views::View* buttons,
|
| + views::View* page,
|
| + gfx::Rect* buttons_bounds,
|
| + gfx::Rect* page_bounds) {
|
| + gfx::Rect content_bounds = parent->GetContentsBounds();
|
| +
|
| + if (buttons) {
|
| + gfx::Size buttons_size = buttons->GetPreferredSize();
|
| + if (buttons_bounds) {
|
| + buttons_bounds->SetRect(
|
| + (content_bounds.width() - buttons_size.width()) / 2,
|
| + content_bounds.bottom() - buttons_size.height(),
|
| + buttons_size.width(), buttons_size.height());
|
| + }
|
| +
|
| + content_bounds.set_height(
|
| + std::max(0, content_bounds.height() - buttons_size.height()));
|
| + }
|
| +
|
| + if (page_bounds) {
|
| + gfx::Size page_size = page->GetPreferredSize();
|
| + *page_bounds = content_bounds.Center(page_size);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +ResultsView::ResultsView(AppListModel* model)
|
| + : model_(model),
|
| + page_buttons_(NULL),
|
| + current_page_(0) {
|
| + animator_.reset(new views::BoundsAnimator(this));
|
| + model_->AddObserver(this);
|
| + Update();
|
| +}
|
| +
|
| +ResultsView::~ResultsView() {
|
| + model_->RemoveObserver(this);
|
| +}
|
| +
|
| +views::View* ResultsView::GetFocusedTile() const {
|
| + TilesPageView* page = GetCurrentPageView();
|
| + return page ? page->GetFocusedTile() : NULL;
|
| +}
|
| +
|
| +void ResultsView::Update() {
|
| + current_page_ = 0;
|
| + page_buttons_ = NULL;
|
| + RemoveAllChildViews(true);
|
| +
|
| + int page_count = model_->item_count();
|
| + if (!page_count)
|
| + return;
|
| +
|
| + if (page_count > 1)
|
| + AddChildView(page_buttons_ = CreatePageHeader());
|
| +
|
| + for (int i = 0; i < page_count; ++i) {
|
| + AppListItemGroupModel* group = model_->item_at(i);
|
| + AddPage(group->title(), new TilesPageView(group));
|
| + }
|
| +
|
| + Layout();
|
| + SetCurrentPage(0);
|
| +}
|
| +
|
| +void ResultsView::AddPage(const std::string& title, TilesPageView* page) {
|
| + pages_.push_back(page);
|
| + AddChildView(page);
|
| +
|
| + if (page_buttons_)
|
| + page_buttons_->AddChildView(CreatePageHeaderButton(this, title));
|
| +}
|
| +
|
| +int ResultsView::GetPreferredTilesPerRow() const {
|
| + return std::max(1, width() / TileView::kTileSize);
|
| +}
|
| +
|
| +TilesPageView* ResultsView::GetCurrentPageView() const {
|
| + return static_cast<size_t>(current_page_) < pages_.size() ?
|
| + pages_[current_page_] : NULL;
|
| +}
|
| +
|
| +void ResultsView::SetCurrentPage(int page) {
|
| + int previous_page = current_page_;
|
| + current_page_ = page;
|
| +
|
| + // Swiches focus to focused tile on new page (if any).
|
| + TilesPageView* current_view = GetCurrentPageView();
|
| + current_view->SetTilesPerRow(GetPreferredTilesPerRow());
|
| + views::View* tile = current_view->GetFocusedTile();
|
| + if (tile)
|
| + tile->RequestFocus();
|
| +
|
| + // Updates page buttons.
|
| + if (page_buttons_) {
|
| + for (int i = 0; i < page_buttons_->child_count(); ++i) {
|
| + views::TextButton* button = static_cast<views::TextButton*>(
|
| + page_buttons_->child_at(i));
|
| +
|
| + button->SetEnabledColor(i == current_page_ ?
|
| + kSelectedPageHeaderColor : kPageHeaderColor);
|
| + }
|
| + page_buttons_->SchedulePaint();
|
| + }
|
| +
|
| + // Gets sliding animation direction.
|
| + int dir = previous_page < current_page_ ? -1 :
|
| + previous_page > current_page_ ? 1 : 0;
|
| + if (dir == 0)
|
| + return;
|
| +
|
| + int view_width = bounds().size().width();
|
| +
|
| + animator_->Cancel();
|
| +
|
| + // Set current page's bounds before animation.
|
| + gfx::Rect current_page_bounds;
|
| + GetPageAndHeaderBounds(this, page_buttons_, current_view,
|
| + NULL, ¤t_page_bounds);
|
| + current_page_bounds.Offset(- dir * view_width, 0);
|
| + current_view->SetBoundsRect(current_page_bounds);
|
| +
|
| + // Setup animations to slide out previous page and slide in current page.
|
| + TilesPageView* previous_view = pages_[previous_page];
|
| + gfx::Rect previous_page_bounds = previous_view->bounds();
|
| + previous_page_bounds.Offset(dir * view_width, 0);
|
| + animator_->AnimateViewTo(previous_view, previous_page_bounds);
|
| +
|
| + current_page_bounds.Offset(dir * view_width, 0);
|
| + animator_->AnimateViewTo(current_view, current_page_bounds);
|
| +}
|
| +
|
| +void ResultsView::Layout() {
|
| + TilesPageView* page = GetCurrentPageView();
|
| + if (!page)
|
| + return;
|
| +
|
| + page->SetTilesPerRow(GetPreferredTilesPerRow());
|
| +
|
| + gfx::Rect buttons_bounds;
|
| + gfx::Rect page_bounds;
|
| + GetPageAndHeaderBounds(this, page_buttons_, page,
|
| + &buttons_bounds, &page_bounds);
|
| +
|
| + if (page_buttons_)
|
| + page_buttons_->SetBoundsRect(buttons_bounds);
|
| +
|
| + page->SetBoundsRect(page_bounds);
|
| +}
|
| +
|
| +bool ResultsView::OnKeyPressed(const views::KeyEvent& event) {
|
| + if (event.IsControlDown()) {
|
| + switch (event.key_code()) {
|
| + case ui::VKEY_LEFT:
|
| + if (current_page_ > 0)
|
| + SetCurrentPage(current_page_ - 1);
|
| + return true;
|
| + case ui::VKEY_RIGHT:
|
| + if (static_cast<size_t>(current_page_ + 1) < pages_.size())
|
| + SetCurrentPage(current_page_ + 1);
|
| + return true;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +void ResultsView::ButtonPressed(views::Button* sender,
|
| + const views::Event& event) {
|
| + DCHECK(page_buttons_);
|
| + for (int i = 0; i < page_buttons_->child_count(); ++i) {
|
| + if (page_buttons_->child_at(i) == sender)
|
| + SetCurrentPage(i);
|
| + }
|
| +}
|
| +
|
| +void ResultsView::ListItemsAdded(int start, int count) {
|
| + Update();
|
| +}
|
| +
|
| +void ResultsView::ListItemsRemoved(int start, int count) {
|
| + Update();
|
| +}
|
| +
|
| +void ResultsView::ListItemsChanged(int start, int count) {
|
| + NOTREACHED();
|
| +}
|
| +
|
| +} // namespace aura_shell
|
|
|