172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/tabs/side_tab_strip.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/view_ids.h" 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/tabs/side_tab.h" 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/views/tabs/tab_strip_controller.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/background.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/button/image_button.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "views/controls/button/text_button.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kVerticalTabSpacing = 2; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTabStripWidth = 140; 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkColor kBackgroundColor = SkColorSetARGB(255, 209, 220, 248); 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkColor kSeparatorColor = SkColorSetARGB(255, 151, 159, 179); 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Height of the scroll buttons. 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kScrollButtonHeight = 20; 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Height of the separator. 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kSeparatorHeight = 1; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Padding between tabs and scroll button. 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kScrollButtonVerticalPadding = 2; 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The new tab button is rendered using a SideTab. 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SideTabNewTabButton : public SideTab { 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit SideTabNewTabButton(TabStripController* controller); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool ShouldPaintHighlight() const OVERRIDE { return false; } 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool IsSelected() const OVERRIDE { return false; } 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE; 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void OnMouseReleased(const views::MouseEvent& event) OVERRIDE; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabStripController* controller_; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(SideTabNewTabButton); 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSideTabNewTabButton::SideTabNewTabButton(TabStripController* controller) 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : SideTab(NULL), 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_(controller) { 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Never show a close button for the new tab button. 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button()->SetVisible(false); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabRendererData data; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data.favicon = *ResourceBundle::GetSharedInstance().GetBitmapNamed( 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDR_SIDETABS_NEW_TAB); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data.title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetData(data); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SideTabNewTabButton::OnMousePressed(const views::MouseEvent& event) { 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabNewTabButton::OnMouseReleased(const views::MouseEvent& event) { 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (event.IsOnlyLeftMouseButton() && HitTest(event.location())) 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_->CreateNewTab(); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Button class used for the scroll buttons. 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass ScrollButton : public views::TextButton { 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enum Type { 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UP, 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DOWN 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen explicit ScrollButton(views::ButtonListener* listener, Type type); 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen protected: 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // views::View overrides. 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const Type type_; 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DISALLOW_COPY_AND_ASSIGN(ScrollButton); 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenScrollButton::ScrollButton(views::ButtonListener* listener, 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Type type) 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : views::TextButton(listener, std::wstring()), 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen type_(type) { 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ScrollButton::OnPaint(gfx::Canvas* canvas) { 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TextButton::OnPaint(canvas); 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Draw the arrow. 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkColor arrow_color = IsEnabled() ? SK_ColorBLACK : SK_ColorGRAY; 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int arrow_height = 5; 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int x = width() / 2; 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int y = (height() - arrow_height) / 2; 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int delta_y = 1; 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (type_ == DOWN) { 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delta_y = -1; 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen y += arrow_height; 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < arrow_height; ++i, --x, y += delta_y) 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen canvas->FillRectInt(arrow_color, x, y, (i * 2) + 1, 1); 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int SideTabStrip::kTabStripInset = 3; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SideTabStrip, public: 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSideTabStrip::SideTabStrip(TabStripController* controller) 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : BaseTabStrip(controller, BaseTabStrip::VERTICAL_TAB_STRIP), 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch newtab_button_(new SideTabNewTabButton(controller)), 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_up_button_(NULL), 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_down_button_(NULL), 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen separator_(new views::View()), 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen first_tab_y_offset_(0), 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ideal_height_(0) { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetID(VIEW_ID_TAB_STRIP); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_background(views::Background::CreateSolidBackground(kBackgroundColor)); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(newtab_button_); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch separator_->set_background( 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::Background::CreateSolidBackground(kSeparatorColor)); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddChildView(separator_); 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_up_button_ = new ScrollButton(this, ScrollButton::UP); 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AddChildView(scroll_up_button_); 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_down_button_ = new ScrollButton(this, ScrollButton::DOWN); 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AddChildView(scroll_down_button_); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSideTabStrip::~SideTabStrip() { 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DestroyDragController(); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// SideTabStrip, AbstractTabStripView implementation: 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SideTabStrip::IsPositionInWindowCaption(const gfx::Point& point) { 151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return GetEventHandlerForPoint(point) == this; 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabStrip::SetBackgroundOffset(const gfx::Point& offset) { 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//////////////////////////////////////////////////////////////////////////////// 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// SideTabStrip, BaseTabStrip implementation: 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SideTabStrip::StartHighlight(int model_index) { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SideTabStrip::StopAllHighlighting() { 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTab* SideTabStrip::CreateTabForDragging() { 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SideTab* tab = new SideTab(NULL); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure the dragged tab shares our theme provider. We need to explicitly 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // do this as during dragging there isn't a theme provider. 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->set_theme_provider(GetThemeProvider()); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return tab; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SideTabStrip::RemoveTabAt(int model_index) { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartRemoveTabAnimation(model_index); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SideTabStrip::SelectTabAt(int old_model_index, int new_model_index) { 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetBaseTabAtModelIndex(new_model_index)->SchedulePaint(); 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (controller()->IsActiveTab(new_model_index)) 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MakeTabVisible(ModelIndexToTabIndex(new_model_index)); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SideTabStrip::TabTitleChangedNotLoading(int model_index) { 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size SideTabStrip::GetPreferredSize() { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Size(kTabStripWidth, 0); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SideTabStrip::PaintChildren(gfx::Canvas* canvas) { 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make sure any tabs being dragged appear on top of all others by painting 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // them last. 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<BaseTab*> dragging_tabs; 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Make sure nothing draws on top of the scroll buttons. 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen canvas->Save(); 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen canvas->ClipRectInt(kTabStripInset, kTabStripInset, 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen width() - kTabStripInset - kTabStripInset, 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetMaxTabY() - kTabStripInset); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Paint the new tab and separator first so that any tabs animating appear on 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // top. 205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen separator_->Paint(canvas); 206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen newtab_button_->Paint(canvas); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = tab_count() - 1; i >= 0; --i) { 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab = base_tab_at_tab_index(i); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab->dragging()) 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dragging_tabs.push_back(tab); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen tab->Paint(canvas); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < dragging_tabs.size(); ++i) 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dragging_tabs[i]->Paint(canvas); 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen canvas->Restore(); 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_down_button_->Paint(canvas); 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_up_button_->Paint(canvas); 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenviews::View* SideTabStrip::GetEventHandlerForPoint(const gfx::Point& point) { 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Check the scroll buttons first as they visually appear on top of everything 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // else. 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (scroll_down_button_->IsVisible()) { 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Point local_point(point); 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen View::ConvertPointToView(this, scroll_down_button_, &local_point); 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (scroll_down_button_->HitTest(local_point)) 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return scroll_down_button_->GetEventHandlerForPoint(local_point); 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (scroll_up_button_->IsVisible()) { 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Point local_point(point); 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen View::ConvertPointToView(this, scroll_up_button_, &local_point); 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (scroll_up_button_->HitTest(local_point)) 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return scroll_up_button_->GetEventHandlerForPoint(local_point); 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return views::View::GetEventHandlerForPoint(point); 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabStrip::ButtonPressed(views::Button* sender, 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const views::Event& event) { 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int max_offset = GetMaxOffset(); 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (max_offset == 0) { 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // All the tabs fit, no need to scroll. 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Determine the index of the first visible tab. 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int initial_y = kTabStripInset; 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int first_vis_index = -1; 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < tab_count(); ++i) { 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (ideal_bounds(i).bottom() > initial_y) { 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen first_vis_index = i; 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (first_vis_index == -1) 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int delta = 0; 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (sender == scroll_up_button_) { 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delta = initial_y - ideal_bounds(first_vis_index).y(); 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (delta <= 0) { 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (first_vis_index == 0) { 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delta = -first_tab_y_offset_; 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delta = initial_y - ideal_bounds(first_vis_index - 1).y(); 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_NE(0, delta); // Not fatal, but indicates we aren't scrolling. 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(sender, scroll_down_button_); 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (ideal_bounds(first_vis_index).y() > initial_y) { 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delta = initial_y - ideal_bounds(first_vis_index).y(); 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (first_vis_index + 1 == tab_count()) { 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delta = -first_tab_y_offset_; 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delta = initial_y - ideal_bounds(first_vis_index + 1).y(); 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetFirstTabYOffset(first_tab_y_offset_ + delta); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTab* SideTabStrip::CreateTab() { 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SideTab(this); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SideTabStrip::GenerateIdealBounds() { 29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen gfx::Rect layout_rect = GetContentsBounds(); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch layout_rect.Inset(kTabStripInset, kTabStripInset); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int y = layout_rect.y() + first_tab_y_offset_; 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool last_was_mini = true; 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_non_closing_tab = false; 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch separator_bounds_.SetRect(0, -kSeparatorHeight, width(), kSeparatorHeight); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_count(); ++i) { 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab = base_tab_at_tab_index(i); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tab->closing()) { 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (last_was_mini != tab->data().mini) { 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_non_closing_tab) { 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch separator_bounds_.SetRect(0, y, width(), kSeparatorHeight); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y += kSeparatorHeight + kVerticalTabSpacing; 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch newtab_button_bounds_.SetRect( 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch layout_rect.x(), y, layout_rect.width(), 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch newtab_button_->GetPreferredSize().height()); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y = newtab_button_bounds_.bottom() + kVerticalTabSpacing; 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_was_mini = tab->data().mini; 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounds = gfx::Rect(layout_rect.x(), y, layout_rect.width(), 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->GetPreferredSize().height()); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set_ideal_bounds(i, bounds); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y = bounds.bottom() + kVerticalTabSpacing; 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_non_closing_tab = true; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (last_was_mini) { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_non_closing_tab) { 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch separator_bounds_.SetRect(0, y, width(), kSeparatorHeight); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch y += kSeparatorHeight + kVerticalTabSpacing; 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch newtab_button_bounds_ = 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect(layout_rect.x(), y, layout_rect.width(), 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch newtab_button_->GetPreferredSize().height()); 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen y += newtab_button_->GetPreferredSize().height(); 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ideal_height_ = y - layout_rect.y() - first_tab_y_offset_; 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_up_button_->SetEnabled(first_tab_y_offset_ != 0); 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_down_button_->SetEnabled(GetMaxOffset() != 0 && 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen first_tab_y_offset_ != GetMaxOffset()); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabStrip::StartInsertTabAnimation(int model_index) { 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrepareForAnimation(); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GenerateIdealBounds(); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_data_index = ModelIndexToTabIndex(model_index); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab = base_tab_at_tab_index(tab_data_index); 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_index == 0) { 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->SetBounds(ideal_bounds(tab_data_index).x(), 0, 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ideal_bounds(tab_data_index).width(), 0); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* last_tab = base_tab_at_tab_index(tab_data_index - 1); 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab->SetBounds(last_tab->x(), last_tab->bounds().bottom(), 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ideal_bounds(tab_data_index).width(), 0); 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimateToIdealBounds(); 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SideTabStrip::AnimateToIdealBounds() { 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < tab_count(); ++i) { 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTab* tab = base_tab_at_tab_index(i); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tab->closing() && !tab->dragging()) 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds_animator().AnimateViewTo(tab, ideal_bounds(i)); 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds_animator().AnimateViewTo(newtab_button_, newtab_button_bounds_); 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds_animator().AnimateViewTo(separator_, separator_bounds_); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 371731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SideTabStrip::DoLayout() { 372731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BaseTabStrip::DoLayout(); 37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen newtab_button_->SetBoundsRect(newtab_button_bounds_); 37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen separator_->SetBoundsRect(separator_bounds_); 375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int scroll_button_y = height() - kScrollButtonHeight; 376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_up_button_->SetBounds(0, scroll_button_y, width() / 2, 377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kScrollButtonHeight); 378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scroll_down_button_->SetBounds(width() / 2, scroll_button_y, width() / 2, 379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kScrollButtonHeight); 380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabStrip::LayoutDraggedTabsAt(const std::vector<BaseTab*>& tabs, 383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BaseTab* active_tab, 384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const gfx::Point& location, 385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool initial_drag) { 386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO: add support for initial_drag (see TabStrip's implementation). 387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect layout_rect = GetContentsBounds(); 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen layout_rect.Inset(kTabStripInset, kTabStripInset); 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int y = location.y(); 390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < tabs.size(); ++i) { 391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BaseTab* tab = tabs[i]; 392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab->SchedulePaint(); 393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab->SetBounds(layout_rect.x(), y, layout_rect.width(), 394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab->GetPreferredSize().height()); 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab->SchedulePaint(); 396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen y += tab->height() + kVerticalTabSpacing; 397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabStrip::CalculateBoundsForDraggedTabs( 401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<BaseTab*>& tabs, 402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<gfx::Rect>* bounds) { 403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int y = 0; 404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < tabs.size(); ++i) { 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BaseTab* tab = tabs[i]; 406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Rect tab_bounds(tab->bounds()); 407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_bounds.set_y(y); 408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen y += tab->height() + kVerticalTabSpacing; 409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bounds->push_back(tab_bounds); 410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint SideTabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { 414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return static_cast<int>(tabs.size()) * SideTab::GetPreferredHeight(); 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabStrip::OnBoundsChanged(const gfx::Rect& previous_bounds) { 418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // When our height changes we may be able to show more. 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen first_tab_y_offset_ = std::max(GetMaxOffset(), 420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::min(0, first_tab_y_offset_)); 421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < controller()->GetCount(); ++i) { 422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (controller()->IsActiveTab(i)) { 423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MakeTabVisible(ModelIndexToTabIndex(i)); 424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabStrip::SetFirstTabYOffset(int new_offset) { 430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int max_offset = GetMaxOffset(); 431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (max_offset == 0) { 432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // All the tabs fit, no need to scroll. 433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_offset = std::max(max_offset, std::min(0, new_offset)); 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (new_offset == first_tab_y_offset_) 437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StopAnimating(false); 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen first_tab_y_offset_ = new_offset; 441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GenerateIdealBounds(); 442ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoLayout(); 443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 444ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint SideTabStrip::GetMaxOffset() const { 447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int available_height = GetMaxTabY() - kTabStripInset; 448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return std::min(0, available_height - ideal_height_); 449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint SideTabStrip::GetMaxTabY() const { 452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return height() - kTabStripInset - kScrollButtonVerticalPadding - 453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kScrollButtonHeight; 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SideTabStrip::MakeTabVisible(int tab_index) { 457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (height() == 0) 458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (ideal_bounds(tab_index).y() < kTabStripInset) { 461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetFirstTabYOffset(first_tab_y_offset_ - ideal_bounds(tab_index).y() + 462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kTabStripInset); 463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (ideal_bounds(tab_index).bottom() > GetMaxTabY()) { 464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetFirstTabYOffset(GetMaxTabY() - (ideal_bounds(tab_index).bottom() - 465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen first_tab_y_offset_)); 466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 468