| Index: chrome/browser/ui/views/sidebar/browser_sidebar_tab_strip_controller.cc
|
| ===================================================================
|
| --- chrome/browser/ui/views/sidebar/browser_sidebar_tab_strip_controller.cc (revision 0)
|
| +++ chrome/browser/ui/views/sidebar/browser_sidebar_tab_strip_controller.cc (revision 0)
|
| @@ -0,0 +1,222 @@
|
| +// Copyright (c) 2010 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 "chrome/browser/ui/views/sidebar/browser_sidebar_tab_strip_controller.h"
|
| +
|
| +#include "chrome/browser/sidebar/sidebar_container.h"
|
| +#include "chrome/browser/sidebar/sidebar_model.h"
|
| +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
|
| +#include "chrome/browser/ui/views/sidebar/sidebar_base_tab.h"
|
| +#include "chrome/browser/ui/views/sidebar/sidebar_base_tab_strip.h"
|
| +#include "chrome/browser/ui/views/sidebar/sidebar_tab_renderer_data.h"
|
| +#include "chrome/browser/ui/views/sidebar/sidebar_tab_strip_controller.h"
|
| +#include "chrome/browser/ui/views/sidebar/sidebar_tab_strip_host.h"
|
| +#include "views/widget/widget.h"
|
| +
|
| +// TODO(alekseys): Add context menu, paint badge text, limit maximum tab strip
|
| +// height to 4 tabs + chevron, paint tabs programmatically instead of using
|
| +// images from resources.
|
| +
|
| +namespace {
|
| +
|
| +// The number of milliseconds between loading animation frames.
|
| +const int kLoadingAnimationFrameTimeMs = 30;
|
| +
|
| +// Maps |contents|'s current state to SidebarTabRendererData::NetworkState.
|
| +SidebarTabRendererData::NetworkState TabContentsNetworkState(
|
| + const TabContents* contents) {
|
| + if (!contents || !contents->is_loading())
|
| + return SidebarTabRendererData::NETWORK_STATE_NONE;
|
| + if (contents->waiting_for_response())
|
| + return SidebarTabRendererData::NETWORK_STATE_WAITING;
|
| + return SidebarTabRendererData::NETWORK_STATE_LOADING;
|
| +}
|
| +
|
| +// Comparator for sidebar tab ordering.
|
| +// Tabs are ordered by sidebar's content id and since content id is not
|
| +// controlled by the extension, tabs will always appear in the same order.
|
| +bool CompareContentIds(SidebarContainer* a, SidebarContainer* b) {
|
| + return a->content_id() < b->content_id();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// BrowserSidebarTabStripController, public:
|
| +
|
| +BrowserSidebarTabStripController::BrowserSidebarTabStripController(
|
| + SidebarModel* model, Delegate* delegate)
|
| + : model_(model),
|
| + delegate_(delegate),
|
| + tab_strip_(NULL),
|
| + tab_(NULL) {
|
| + DCHECK(model_);
|
| + DCHECK(delegate_);
|
| +}
|
| +
|
| +BrowserSidebarTabStripController::~BrowserSidebarTabStripController() {
|
| +}
|
| +
|
| +bool BrowserSidebarTabStripController::IsSidebarExpanded() {
|
| + SidebarContainer* active_sidebar =
|
| + model()->GetActiveSidebarContainerFor(tab_);
|
| + return active_sidebar != NULL;
|
| +}
|
| +
|
| +bool BrowserSidebarTabStripController::IsTabSelected(int model_index) {
|
| + SidebarContainer* active_sidebar =
|
| + model()->GetActiveSidebarContainerFor(tab_);
|
| + return active_sidebar &&
|
| + active_sidebar->content_id() == model_index_[model_index];
|
| +}
|
| +
|
| +void BrowserSidebarTabStripController::SelectTab(int model_index) {
|
| + model()->ToggleSidebar(tab_, model_index_[model_index]);
|
| +}
|
| +
|
| +void BrowserSidebarTabStripController::UpdateTabs(TabContentsWrapper* tab) {
|
| + // Do not animate tab insertions/removals when we switch to the different
|
| + // tab_contents, it means that user switched tabs and all we need to do is
|
| + // to show sidebar tabs for the current page.
|
| + bool animate = tab_ == tab;
|
| + tab_ = tab;
|
| +
|
| + // Get the new model state (list of mini tabs sorted by content id).
|
| + std::vector<SidebarContainer*> new_model_index =
|
| + model()->GetAllSidebarsFor(tab_);
|
| + std::sort(new_model_index.begin(), new_model_index.end(), CompareContentIds);
|
| +
|
| + SidebarContainer* active_sidebar =
|
| + model()->GetActiveSidebarContainerFor(tab_);
|
| +
|
| + // Synchronize model index with the new state.
|
| + int model_index = 0;
|
| + int selected_model_index = -1;
|
| + std::vector<SidebarContainer*>::const_iterator it_new =
|
| + new_model_index.begin();
|
| + for (; it_new != new_model_index.end(); ++it_new, ++model_index) {
|
| + SidebarTabRendererData data;
|
| + SetSidebarTabRendererDataFromModel(*it_new, &data);
|
| +
|
| + bool selected = *it_new == active_sidebar;
|
| + if (selected)
|
| + selected_model_index = model_index;
|
| +
|
| + if (model_index >= static_cast<int>(model_index_.size())) {
|
| + // There're more tabs than in the model index, add the new one to the end.
|
| + model_index_.push_back((*it_new)->content_id());
|
| + tab_strip_->AddTabAt(model_index, animate, data);
|
| + } else if (model_index_[model_index] > (*it_new)->content_id()) {
|
| + // New tab should be inserted before the current one.
|
| + model_index_.insert(model_index_.begin() + model_index,
|
| + (*it_new)->content_id());
|
| + tab_strip_->AddTabAt(model_index, animate, data);
|
| + } else if (model_index_[model_index] < (*it_new)->content_id()) {
|
| + // The current tab is not in the model anymore and should be deleted.
|
| + tab_strip_->RemoveTabAt(model_index, animate);
|
| + model_index_.erase(model_index_.begin() + model_index);
|
| + } else {
|
| + // The same content id, nothing to update here.
|
| + }
|
| + }
|
| +
|
| + // Remove excess tabs, model_index is now equal to the size of the new model.
|
| + if (static_cast<int>(model_index_.size()) > model_index) {
|
| + for (int i = model_index_.size(); i > model_index; --i)
|
| + tab_strip_->RemoveTabAt(i - 1, animate);
|
| + model_index_.erase(model_index_.begin() + model_index, model_index_.end());
|
| + }
|
| +
|
| + if (selected_model_index >= 0)
|
| + tab_strip_->SelectTabAt(selected_model_index);
|
| +
|
| + // In this case, no updates were issued yet, update view bounds only once.
|
| + if (!animate)
|
| + tab_strip_->SetToIdealBounds();
|
| + else
|
| + tab_strip_->SchedulePaint();
|
| +}
|
| +
|
| +void BrowserSidebarTabStripController::UpdateState(
|
| + const SidebarContainer* sidebar) {
|
| + int model_index = 0;
|
| + std::vector<std::string>::const_iterator it = model_index_.begin();
|
| + for (; it != model_index_.end(); ++it, ++model_index) {
|
| + if (sidebar->content_id() == *it)
|
| + break;
|
| + }
|
| + // We might receive an update request too early and it's ok to ignore it,
|
| + // changes will be picked up when tab strip is going to be synched.
|
| + if (it == model_index_.end())
|
| + return;
|
| +
|
| + SidebarTabRendererData data;
|
| + SetSidebarTabRendererDataFromModel(sidebar, &data);
|
| +
|
| + tab_strip_->SetTabData(model_index, data);
|
| + tab_strip_->SchedulePaint();
|
| +}
|
| +
|
| +void BrowserSidebarTabStripController::UpdateLoadingState(
|
| + const SidebarContainer* sidebar) {
|
| + UpdateLoadingAnimations();
|
| +}
|
| +
|
| +void BrowserSidebarTabStripController::TabStripBoundsChanged(
|
| + bool is_animating) {
|
| + delegate_->OnSidebarTabStripBoundsChanged(is_animating);
|
| +}
|
| +
|
| +// BrowserSidebarTabStripController, private:
|
| +
|
| +void BrowserSidebarTabStripController::UpdateLoadingAnimations() {
|
| + bool should_animate = false;
|
| +
|
| + // Check whether network state has changed for any tab or not.
|
| + int model_index = 0;
|
| + std::vector<std::string>::const_iterator it = model_index_.begin();
|
| + for (; it != model_index_.end(); ++it, ++model_index) {
|
| + SidebarBaseTab* tab = tab_strip_->GetBaseTabAtModelIndex(model_index);
|
| + SidebarContainer* sidebar =
|
| + model()->GetSidebarContainerFor(tab_, *it);
|
| + if (sidebar) {
|
| + TabContents* contents = sidebar->sidebar_contents();
|
| + if (tab->UpdateLoadingAnimation(TabContentsNetworkState(contents)))
|
| + should_animate = true;
|
| + }
|
| + }
|
| +
|
| + if (should_animate) {
|
| + if (!loading_animation_timer_.IsRunning()) {
|
| + // Loads are happening, and the timer isn't running, so start it.
|
| + loading_animation_timer_.Start(
|
| + base::TimeDelta::FromMilliseconds(kLoadingAnimationFrameTimeMs), this,
|
| + &BrowserSidebarTabStripController::LoadingAnimationCallback);
|
| + }
|
| + } else {
|
| + if (loading_animation_timer_.IsRunning())
|
| + loading_animation_timer_.Stop();
|
| + }
|
| +}
|
| +
|
| +void BrowserSidebarTabStripController::LoadingAnimationCallback() {
|
| + UpdateLoadingAnimations();
|
| +}
|
| +
|
| +void BrowserSidebarTabStripController::SetTabDataAt(SidebarContainer* sidebar,
|
| + int model_index) {
|
| + SidebarTabRendererData data;
|
| + SetSidebarTabRendererDataFromModel(sidebar, &data);
|
| + tab_strip_->SetTabData(model_index, data);
|
| +}
|
| +
|
| +void BrowserSidebarTabStripController::SetSidebarTabRendererDataFromModel(
|
| + const SidebarContainer* sidebar,
|
| + SidebarTabRendererData* data) {
|
| + data->icon = sidebar->icon();
|
| + data->title = sidebar->title();
|
| + data->badge_text = sidebar->badge_text();
|
| + data->network_state = TabContentsNetworkState(sidebar->sidebar_contents());
|
| + data->crashed = sidebar->sidebar_contents()->is_crashed();
|
| +}
|
| +
|
|
|
| Property changes on: chrome\browser\ui\views\sidebar\browser_sidebar_tab_strip_controller.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|