Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(916)

Unified Diff: chrome/browser/ui/views/sidebar/browser_sidebar_tab_strip_controller.cc

Issue 6250141: Sidebar mini tabs UI (views version).... Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698