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 |