15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/app_list/views/page_switcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkPath.h"
10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "ui/app_list/app_list_constants.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/pagination_model.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/throb_animation.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/custom_button.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/box_layout.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace app_list {
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPreferredHeight = 57;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxButtonSpacing = 18;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinButtonSpacing = 4;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxButtonWidth = 68;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinButtonWidth = 28;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kButtonHeight = 6;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kButtonCornerRadius = 2;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kButtonStripPadding = 20;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PageSwitcherButton : public views::CustomButton {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit PageSwitcherButton(views::ButtonListener* listener)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : views::CustomButton(listener),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        button_width_(kMaxButtonWidth),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        selected_range_(0) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PageSwitcherButton() {}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetSelectedRange(double selected_range) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (selected_range_ == selected_range)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    selected_range_ = selected_range;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SchedulePaint();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_button_width(int button_width) { button_width_ = button_width; }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from views::View:
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gfx::Size(button_width_, kButtonHeight);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (state() == STATE_HOVERED)
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      PaintButton(canvas, kPagerHoverColor);
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    else
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      PaintButton(canvas, kPagerNormalColor);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Paints a button that has two rounded corner at bottom.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PaintButton(gfx::Canvas* canvas, SkColor base_color) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect rect(GetContentsBounds());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rect.ClampToCenteredSize(gfx::Size(button_width_, kButtonHeight));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPath path;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path.addRoundRect(gfx::RectToSkRect(rect),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      SkIntToScalar(kButtonCornerRadius),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      SkIntToScalar(kButtonCornerRadius));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPaint paint;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    paint.setAntiAlias(true);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    paint.setStyle(SkPaint::kFill_Style);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    paint.setColor(base_color);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canvas->DrawPath(path, paint);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int selected_start_x = 0;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int selected_width = 0;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (selected_range_ > 0) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_width = selected_range_ * rect.width();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (selected_range_ < 0) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_width =  -selected_range_ * rect.width();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_start_x = rect.right() - selected_width;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (selected_width) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Rect selected_rect(rect);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_rect.set_x(selected_start_x);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_rect.set_width(selected_width);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkPath selected_path;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_path.addRoundRect(gfx::RectToSkRect(selected_rect),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 SkIntToScalar(kButtonCornerRadius),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 SkIntToScalar(kButtonCornerRadius));
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      paint.setColor(kPagerSelectedColor);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      canvas->DrawPath(selected_path, paint);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int button_width_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [-1, 1] range that represents the portion of the button that should be
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // painted with kSelectedColor. Positive range starts from left side and
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // negative range starts from the right side.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double selected_range_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PageSwitcherButton);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets PageSwitcherButton at |index| in |buttons|.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PageSwitcherButton* GetButtonByIndex(views::View* buttons, int index) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<PageSwitcherButton*>(buttons->child_at(index));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PageSwitcher::PageSwitcher(PaginationModel* model)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : model_(model),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buttons_(new views::View) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(buttons_);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TotalPagesChanged();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectedPageChanged(-1, model->selected_page());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->AddObserver(this);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PageSwitcher::~PageSwitcher() {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->RemoveObserver(this);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PageSwitcher::GetPageForPoint(const gfx::Point& point) const {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buttons_->bounds().Contains(point))
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Point buttons_point(point);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View::ConvertPointToTarget(this, buttons_, &buttons_point);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < buttons_->child_count(); ++i) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const views::View* button = buttons_->child_at(i);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (button->bounds().Contains(buttons_point))
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return -1;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageSwitcher::UpdateUIForDragPoint(const gfx::Point& point) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int page = GetPageForPoint(point);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int button_count = buttons_->child_count();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (page >= 0 && page < button_count) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PageSwitcherButton* button =
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<PageSwitcherButton*>(buttons_->child_at(page));
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    button->SetState(views::CustomButton::STATE_HOVERED);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < button_count; ++i) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PageSwitcherButton* button =
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<PageSwitcherButton*>(buttons_->child_at(i));
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    button->SetState(views::CustomButton::STATE_NORMAL);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size PageSwitcher::GetPreferredSize() const {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always return a size with correct height so that container resize is not
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // needed when more pages are added.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Size(buttons_->GetPreferredSize().width(),
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   kPreferredHeight);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageSwitcher::Layout() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect rect(GetContentsBounds());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateButtonWidthAndSpacing(rect.width());
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Makes |buttons_| horizontally center and vertically fill.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size buttons_size(buttons_->GetPreferredSize());
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect buttons_bounds(rect.CenterPoint().x() - buttons_size.width() / 2,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           rect.y(),
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           buttons_size.width(),
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           rect.height());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buttons_->SetBoundsRect(gfx::IntersectRects(rect, buttons_bounds));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageSwitcher::CalculateButtonWidthAndSpacing(int contents_width) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int button_count = buttons_->child_count();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!button_count)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contents_width -= 2 * kButtonStripPadding;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int button_width = kMinButtonWidth;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int button_spacing = kMinButtonSpacing;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (button_count > 1) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    button_spacing = (contents_width - button_width * button_count) /
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (button_count - 1);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    button_spacing = std::min(kMaxButtonSpacing,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              std::max(kMinButtonSpacing, button_spacing));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button_width = (contents_width - (button_count - 1) * button_spacing) /
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_count;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button_width = std::min(kMaxButtonWidth,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::max(kMinButtonWidth, button_width));
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buttons_->SetLayoutManager(new views::BoxLayout(
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      views::BoxLayout::kHorizontal, kButtonStripPadding, 0, button_spacing));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < button_count; ++i) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PageSwitcherButton* button =
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<PageSwitcherButton*>(buttons_->child_at(i));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    button->set_button_width(button_width);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageSwitcher::ButtonPressed(views::Button* sender,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const ui::Event& event) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < buttons_->child_count(); ++i) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sender == static_cast<views::Button*>(buttons_->child_at(i))) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      model_->SelectPage(i, true /* animate */);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageSwitcher::TotalPagesChanged() {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buttons_->RemoveAllChildViews(true);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < model_->total_pages(); ++i) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PageSwitcherButton* button = new PageSwitcherButton(this);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    button->SetSelectedRange(i == model_->selected_page() ? 1 : 0);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buttons_->AddChildView(button);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buttons_->SetVisible(model_->total_pages() > 1);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layout();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageSwitcher::SelectedPageChanged(int old_selected, int new_selected) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_selected >= 0 && old_selected < buttons_->child_count())
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetButtonByIndex(buttons_, old_selected)->SetSelectedRange(0);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_selected >= 0 && new_selected < buttons_->child_count())
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetButtonByIndex(buttons_, new_selected)->SetSelectedRange(1);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PageSwitcher::TransitionStarted() {
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageSwitcher::TransitionChanged() {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int current_page = model_->selected_page();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int target_page = model_->transition().target_page;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double progress = model_->transition().progress;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double remaining = progress - 1;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_page > target_page) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remaining = -remaining;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    progress = -progress;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetButtonByIndex(buttons_, current_page)->SetSelectedRange(remaining);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model_->is_valid_page(target_page))
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetButtonByIndex(buttons_, target_page)->SetSelectedRange(progress);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace app_list
268