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

Unified Diff: chrome/browser/ui/views/sidebar/sidebar_base_tab.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/sidebar_base_tab.cc
===================================================================
--- chrome/browser/ui/views/sidebar/sidebar_base_tab.cc (revision 0)
+++ chrome/browser/ui/views/sidebar/sidebar_base_tab.cc (revision 0)
@@ -0,0 +1,321 @@
+// 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/sidebar_base_tab.h"
+
+#include <limits>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/view_ids.h"
+#include "chrome/browser/ui/views/sidebar/sidebar_tab_controller.h"
+#include "gfx/canvas_skia.h"
+#include "gfx/favicon_size.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/animation/animation_container.h"
+#include "ui/base/animation/linear_animation.h"
+#include "ui/base/animation/slide_animation.h"
+#include "ui/base/animation/throb_animation.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+
+namespace {
+
+// How long the pulse throb takes.
+const int kPulseDurationMs = 200;
+
+// How long the hover state takes.
+const int kHoverDurationMs = 90;
+
+// How opaque to make the hover state (out of 1).
+const double kHoverOpacity = 0.33;
+
+} // namespace
+
+// A custom animation subclass to manage the icon crash animation.
+class SidebarBaseTab::IconCrashAnimation : public ui::LinearAnimation,
+ public ui::AnimationDelegate {
+ public:
+ explicit IconCrashAnimation(SidebarBaseTab* target)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(LinearAnimation(1000, 25, this)),
+ target_(target) {
+ }
+ virtual ~IconCrashAnimation() {}
+
+ // ui::AnimationDelegate overrides:
+ virtual void AnimateToState(double state) {
+ const double kHidingOffset = 27;
+
+ if (state < .5) {
+ target_->SetIconHidingOffset(
+ static_cast<int>(floor(kHidingOffset * 2.0 * state)));
+ } else {
+ target_->DisplayCrashedIcon();
+ target_->SetIconHidingOffset(
+ static_cast<int>(
+ floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset))));
+ }
+ }
+
+ // ui::AnimationDelegate overrides:
+ virtual void AnimationCanceled(const ui::Animation* animation) {
+ target_->SetIconHidingOffset(0);
+ }
+
+ private:
+ SidebarBaseTab* const target_;
+
+ DISALLOW_COPY_AND_ASSIGN(IconCrashAnimation);
+};
+
+SidebarBaseTab::SidebarBaseTab(SidebarTabController* controller)
+ : controller_(controller),
+ closing_(false),
+ icon_hiding_offset_(0),
+ should_display_crashed_icon_(false),
+ loading_animation_frame_(0) {
+ DCHECK(controller_);
+
+ SetID(VIEW_ID_SIDEBAR_TAB);
+}
+
+SidebarBaseTab::~SidebarBaseTab() {
+}
+
+// views::View overrides.
+
+void SidebarBaseTab::OnMouseEntered(const views::MouseEvent& e) {
+ if (!hover_animation_.get()) {
+ hover_animation_.reset(new ui::SlideAnimation(this));
+ hover_animation_->SetContainer(animation_container_.get());
+ hover_animation_->SetSlideDuration(kHoverDurationMs);
+ }
+ hover_animation_->SetTweenType(ui::Tween::EASE_OUT);
+ hover_animation_->Show();
+}
+
+void SidebarBaseTab::OnMouseExited(const views::MouseEvent& e) {
+ hover_animation_->SetTweenType(ui::Tween::EASE_IN);
+ hover_animation_->Hide();
+}
+
+bool SidebarBaseTab::OnMousePressed(const views::MouseEvent& event) {
+ if (event.IsOnlyLeftMouseButton())
+ controller_->SelectTab(this);
+ return true;
+}
+
+bool SidebarBaseTab::GetTooltipText(const gfx::Point& p,
+ std::wstring* tooltip) {
+ if (data_.title.empty())
+ return false;
+ *tooltip = UTF16ToWide(data_.title);
+ return true;
+}
+
+AccessibilityTypes::Role SidebarBaseTab::GetAccessibleRole() {
+ return AccessibilityTypes::ROLE_PAGETAB;
+}
+
+// SidebarBaseTab, public.
+
+void SidebarBaseTab::SetData(const SidebarTabRendererData& data) {
+ SidebarTabRendererData old(data_);
+ data_ = data;
+
+ bool is_performing_crash_animation =
+ crash_animation_.get() && crash_animation_->is_animating();
+ if (data_.crashed) {
+ if (!should_display_crashed_icon_ && !is_performing_crash_animation)
+ StartCrashAnimation();
+ } else {
+ if (is_performing_crash_animation)
+ StopCrashAnimation();
+ ResetCrashedIcon();
+ }
+
+ // Sets the accessible name for the tab.
+ SetAccessibleName(data_.title);
+
+ DCHECK(data_.icon.isNull() ||
+ (data_.icon.width() == kFavIconSize &&
+ data_.icon.height() == kFavIconSize));
+
+ DataChanged(old);
+
+ Layout();
+}
+
+bool SidebarBaseTab::UpdateLoadingAnimation(
+ SidebarTabRendererData::NetworkState state) {
+ if (state == data_.network_state &&
+ state == SidebarTabRendererData::NETWORK_STATE_NONE) {
+ // If the network state is none and hasn't changed, do nothing. Otherwise
+ // we need to advance the animation frame.
+ return false;
+ }
+
+ SidebarTabRendererData::NetworkState old_state = data_.network_state;
+ data_.network_state = state;
+ AdvanceLoadingAnimation(old_state, state);
+ return true;
+}
+
+void SidebarBaseTab::StartPulse() {
+ if (!pulse_animation_.get()) {
+ pulse_animation_.reset(new ui::ThrobAnimation(this));
+ pulse_animation_->SetSlideDuration(kPulseDurationMs);
+ if (animation_container_.get())
+ pulse_animation_->SetContainer(animation_container_.get());
+ }
+ pulse_animation_->Reset();
+ pulse_animation_->StartThrobbing(std::numeric_limits<int>::max());
+}
+
+void SidebarBaseTab::StopPulse() {
+ if (!pulse_animation_.get())
+ return;
+
+ pulse_animation_->Stop(); // Do stop so we get notified.
+ pulse_animation_.reset(NULL);
+}
+
+bool SidebarBaseTab::IsSelected() const {
+ return controller_->IsTabSelected(this);
+}
+
+bool SidebarBaseTab::IsExpanded() const {
+ return controller_->IsSidebarExpanded();
+}
+
+// SidebarBaseTab, protected.
+
+void SidebarBaseTab::AdvanceLoadingAnimation(
+ SidebarTabRendererData::NetworkState old_state,
+ SidebarTabRendererData::NetworkState state) {
+ static bool initialized = false;
+ static int loading_animation_frame_count = 0;
+ static int waiting_animation_frame_count = 0;
+ static int waiting_to_loading_frame_count_ratio = 0;
+ if (!initialized) {
+ initialized = true;
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ SkBitmap loading_animation(*rb.GetBitmapNamed(IDR_THROBBER));
+ loading_animation_frame_count =
+ loading_animation.width() / loading_animation.height();
+ SkBitmap waiting_animation(*rb.GetBitmapNamed(IDR_THROBBER_WAITING));
+ waiting_animation_frame_count =
+ waiting_animation.width() / waiting_animation.height();
+ waiting_to_loading_frame_count_ratio =
+ waiting_animation_frame_count / loading_animation_frame_count;
+ }
+
+ // The waiting animation is the reverse of the loading animation, but at a
+ // different rate - the following reverses and scales the animation_frame_
+ // so that the frame is at an equivalent position when going from one
+ // animation to the other.
+ if (state != old_state) {
+ loading_animation_frame_ = loading_animation_frame_count -
+ (loading_animation_frame_ / waiting_to_loading_frame_count_ratio);
+ }
+
+ if (state != SidebarTabRendererData::NETWORK_STATE_NONE) {
+ loading_animation_frame_ = (loading_animation_frame_ + 1) %
+ ((state == SidebarTabRendererData::NETWORK_STATE_WAITING) ?
+ waiting_animation_frame_count : loading_animation_frame_count);
+ } else {
+ loading_animation_frame_ = 0;
+ }
+ SchedulePaint();
+}
+
+double SidebarBaseTab::GetThrobValue() {
+ if (pulse_animation_.get() && pulse_animation_->is_animating())
+ return pulse_animation_->GetCurrentValue() * kHoverOpacity;
+
+ return hover_animation_.get() ?
+ kHoverOpacity * hover_animation_->GetCurrentValue() : 0;
+}
+
+void SidebarBaseTab::PaintIcon(gfx::Canvas* canvas, int x, int y, int alpha) {
+ SkPaint paint;
+ paint.setAlpha(alpha);
+ if (data().network_state != SidebarTabRendererData::NETWORK_STATE_NONE) {
+ ThemeProvider* tp = GetThemeProvider();
+ SkBitmap frames(*tp->GetBitmapNamed(
+ data().network_state == SidebarTabRendererData::NETWORK_STATE_WAITING ?
+ IDR_THROBBER_WAITING : IDR_THROBBER));
+ int image_size = frames.height();
+ int image_offset = loading_animation_frame_ * image_size;
+ int dst_y = (height() - image_size) / 2;
+ canvas->DrawBitmapInt(frames, image_offset, 0, image_size,
+ image_size, x, dst_y, image_size, image_size,
+ false, paint);
+ } else {
+ canvas->Save();
+ canvas->ClipRectInt(0, 0, width(), height());
+ if (should_display_crashed_icon_) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ SkBitmap crashed_icon(*rb.GetBitmapNamed(IDR_SAD_FAVICON));
+ canvas->DrawBitmapInt(crashed_icon, 0, 0, crashed_icon.width(),
+ crashed_icon.height(), x,
+ (height() - crashed_icon.height()) / 2 + icon_hiding_offset_,
+ kFavIconSize, kFavIconSize, true, paint);
+ } else {
+ if (!data().icon.isNull()) {
+ int size = data().icon.width();
+ canvas->DrawBitmapInt(data().icon, 0, 0,
+ data().icon.width(),
+ data().icon.height(),
+ x, y + icon_hiding_offset_, size, size,
+ true, paint);
+ }
+ }
+ canvas->Restore();
+ }
+}
+
+// ui::AnimationDelegate overrides.
+
+void SidebarBaseTab::AnimationProgressed(const ui::Animation* animation) {
+ SchedulePaint();
+}
+
+void SidebarBaseTab::AnimationCanceled(const ui::Animation* animation) {
+ SchedulePaint();
+}
+
+void SidebarBaseTab::AnimationEnded(const ui::Animation* animation) {
+ SchedulePaint();
+}
+
+// SidebarBaseTab, private.
+
+void SidebarBaseTab::SetIconHidingOffset(int offset) {
+ icon_hiding_offset_ = offset;
+ SchedulePaint();
+}
+
+void SidebarBaseTab::DisplayCrashedIcon() {
+ should_display_crashed_icon_ = true;
+}
+
+void SidebarBaseTab::ResetCrashedIcon() {
+ should_display_crashed_icon_ = false;
+}
+
+void SidebarBaseTab::StartCrashAnimation() {
+ if (!crash_animation_.get())
+ crash_animation_.reset(new IconCrashAnimation(this));
+ crash_animation_->Stop();
+ crash_animation_->Start();
+}
+
+void SidebarBaseTab::StopCrashAnimation() {
+ if (crash_animation_.get())
+ crash_animation_->Stop();
+}
+
Property changes on: chrome\browser\ui\views\sidebar\sidebar_base_tab.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « chrome/browser/ui/views/sidebar/sidebar_base_tab.h ('k') | chrome/browser/ui/views/sidebar/sidebar_base_tab_strip.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698