summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-06 21:30:27 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-06 21:30:27 +0000
commitb2204fb914f96e9cc505c640aeb7986b25124ca0 (patch)
treed9b7ac644fd6e38d2570c5daf501fc2a6ae7ea6b /chrome
parentb62b752c86847826f3fd20b9aaf09a409ebac61d (diff)
downloadchromium_src-b2204fb914f96e9cc505c640aeb7986b25124ca0.zip
chromium_src-b2204fb914f96e9cc505c640aeb7986b25124ca0.tar.gz
chromium_src-b2204fb914f96e9cc505c640aeb7986b25124ca0.tar.bz2
Implement loading animations. I've ignored the app mode and popup cases since I don't think the Linux port supports those modes yet. I also ignored RTL. I've made some minor lint/style cleanups along the way.
BUG=9380 Review URL: http://codereview.chromium.org/60104 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13195 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc41
-rw-r--r--chrome/browser/gtk/browser_window_gtk.h11
-rw-r--r--chrome/browser/gtk/tabs/tab_renderer_gtk.cc107
-rw-r--r--chrome/browser/gtk/tabs/tab_renderer_gtk.h96
-rw-r--r--chrome/browser/gtk/tabs/tab_renderer_gtk_unittest.cc77
-rw-r--r--chrome/browser/gtk/tabs/tab_strip_gtk.cc23
-rw-r--r--chrome/browser/gtk/tabs/tab_strip_gtk.h15
-rw-r--r--chrome/chrome.gyp3
8 files changed, 340 insertions, 33 deletions
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index 478eda4..7613f69 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -13,6 +13,7 @@
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
+#include "base/time.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/browser.h"
@@ -37,6 +38,9 @@
namespace {
+// The number of milliseconds between loading animation frames.
+const int kLoadingAnimationFrameTimeMs = 30;
+
const GdkColor kBorderColor = GDK_COLOR_RGB(0xbe, 0xc8, 0xd4);
class DummyButtonListener : public views::ButtonListener {
@@ -336,15 +340,42 @@ void BrowserWindowGtk::SelectedTabToolbarSizeChanged(bool is_animating) {
void BrowserWindowGtk::UpdateTitleBar() {
std::wstring title = browser_->GetCurrentPageTitle();
gtk_window_set_title(window_, WideToUTF8(title).c_str());
- if (browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR)) {
+ if (ShouldShowWindowIcon()) {
// If we're showing a title bar, we should update the app icon.
NOTIMPLEMENTED();
}
}
void BrowserWindowGtk::UpdateLoadingAnimations(bool should_animate) {
- // Need to implement loading animations.
- // http://code.google.com/p/chromium/issues/detail?id=9380
+ 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,
+ &BrowserWindowGtk::LoadingAnimationCallback);
+ }
+ } else {
+ if (loading_animation_timer_.IsRunning()) {
+ loading_animation_timer_.Stop();
+ // Loads are now complete, update the state if a task was scheduled.
+ LoadingAnimationCallback();
+ }
+ }
+}
+
+void BrowserWindowGtk::LoadingAnimationCallback() {
+ if (browser_->type() == Browser::TYPE_NORMAL) {
+ // Loading animations are shown in the tab for tabbed windows. We check the
+ // browser type instead of calling IsTabStripVisible() because the latter
+ // will return false for fullscreen windows, but we still need to update
+ // their animations (so that when they come out of fullscreen mode they'll
+ // be correct).
+ tabstrip_->UpdateLoadingAnimations();
+ } else if (ShouldShowWindowIcon()) {
+ // ... or in the window icon area for popups and app windows.
+ // http://code.google.com/p/chromium/issues/detail?id=9380
+ NOTIMPLEMENTED();
+ }
}
void BrowserWindowGtk::SetStarredState(bool is_starred) {
@@ -585,6 +616,10 @@ bool BrowserWindowGtk::CanClose() const {
return true;
}
+bool BrowserWindowGtk::ShouldShowWindowIcon() const {
+ return browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR);
+}
+
void BrowserWindowGtk::ConnectAccelerators() {
GtkAccelGroup* accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(window_, accel_group);
diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h
index f435202..4305dac 100644
--- a/chrome/browser/gtk/browser_window_gtk.h
+++ b/chrome/browser/gtk/browser_window_gtk.h
@@ -10,6 +10,7 @@
#include "base/gfx/rect.h"
#include "base/scoped_ptr.h"
#include "base/task.h"
+#include "base/timer.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/common/notification_observer.h"
@@ -102,6 +103,8 @@ class BrowserWindowGtk : public BrowserWindow,
// onbeforeunload handler that prevents us from closing.
bool CanClose() const;
+ bool ShouldShowWindowIcon() const;
+
protected:
virtual void DestroyBrowser();
GtkWindow* window_;
@@ -135,6 +138,9 @@ class BrowserWindowGtk : public BrowserWindow,
// A small shim for browser_->ExecuteCommand.
void ExecuteBrowserCommand(int id);
+ // Callback for the loading animation(s) associated with this window.
+ void LoadingAnimationCallback();
+
gfx::Rect bounds_;
GdkWindowState state_;
@@ -169,6 +175,11 @@ class BrowserWindowGtk : public BrowserWindow,
// Experiment with using views for gtk.
scoped_ptr<views::WidgetGtk> experimental_widget_;
+
+ // The timer used to update frames for the Loading Animation.
+ base::RepeatingTimer<BrowserWindowGtk> loading_animation_timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserWindowGtk);
};
#endif // CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc
index 1e55ae2..2e22487 100644
--- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc
+++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc
@@ -52,6 +52,41 @@ GdkFont* load_default_font() {
return font;
}
+TabRendererGtk::LoadingAnimation::Data loading_animation_data;
+
+// Loads the loading animation images and data.
+void InitializeLoadingAnimationData(
+ ResourceBundle* rb, TabRendererGtk::LoadingAnimation::Data* data) {
+ // The loading animation image is a strip of states. Each state must be
+ // square, so the height must divide the width evenly.
+ data->loading_animation_frames = rb->GetBitmapNamed(IDR_THROBBER);
+ DCHECK(data->loading_animation_frames);
+ DCHECK_EQ(data->loading_animation_frames->width() %
+ data->loading_animation_frames->height(), 0);
+ data->loading_animation_frame_count =
+ data->loading_animation_frames->width() /
+ data->loading_animation_frames->height();
+
+ data->waiting_animation_frames =
+ rb->GetBitmapNamed(IDR_THROBBER_WAITING);
+ DCHECK(data->waiting_animation_frames);
+ DCHECK_EQ(data->waiting_animation_frames->width() %
+ data->waiting_animation_frames->height(), 0);
+ data->waiting_animation_frame_count =
+ data->waiting_animation_frames->width() /
+ data->waiting_animation_frames->height();
+
+ data->waiting_to_loading_frame_count_ratio =
+ data->waiting_animation_frame_count /
+ data->loading_animation_frame_count;
+ // TODO(beng): eventually remove this when we have a proper themeing system.
+ // themes not supporting IDR_THROBBER_WAITING are causing this
+ // value to be 0 which causes DIV0 crashes. The value of 5
+ // matches the current bitmaps in our source.
+ if (data->waiting_to_loading_frame_count_ratio == 0)
+ data->waiting_to_loading_frame_count_ratio = 5;
+}
+
} // namespace
bool TabRendererGtk::initialized_ = false;
@@ -68,6 +103,38 @@ int TabRendererGtk::download_icon_width_ = 0;
int TabRendererGtk::download_icon_height_ = 0;
////////////////////////////////////////////////////////////////////////////////
+// TabRendererGtk::LoadingAnimation, public:
+//
+TabRendererGtk::LoadingAnimation::LoadingAnimation(const Data* data)
+ : data_(data), animation_state_(ANIMATION_NONE), animation_frame_(0) {
+}
+
+void TabRendererGtk::LoadingAnimation::ValidateLoadingAnimation(
+ AnimationState animation_state) {
+ if (animation_state_ != animation_state) {
+ // 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 (animation_state_ == ANIMATION_WAITING &&
+ animation_state == ANIMATION_LOADING) {
+ animation_frame_ = data_->loading_animation_frame_count -
+ (animation_frame_ / data_->waiting_to_loading_frame_count_ratio);
+ }
+ animation_state_ = animation_state;
+ }
+
+ if (animation_state_ != ANIMATION_NONE) {
+ animation_frame_ = ++animation_frame_ %
+ ((animation_state_ == ANIMATION_WAITING) ?
+ data_->waiting_animation_frame_count :
+ data_->loading_animation_frame_count);
+ } else {
+ animation_frame_ = 0;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
// TabRendererGtk, public:
TabRendererGtk::TabRendererGtk()
@@ -76,7 +143,8 @@ TabRendererGtk::TabRendererGtk()
showing_close_button_(false),
fav_icon_hiding_offset_(0),
should_display_crashed_favicon_(false),
- hovering_(false) {
+ hovering_(false),
+ loading_animation_(&loading_animation_data) {
InitResources();
}
@@ -108,6 +176,10 @@ bool TabRendererGtk::IsSelected() const {
return true;
}
+void TabRendererGtk::ValidateLoadingAnimation(AnimationState animation_state) {
+ loading_animation_.ValidateLoadingAnimation(animation_state);
+}
+
// static
gfx::Size TabRendererGtk::GetMinimumUnselectedSize() {
InitResources();
@@ -218,9 +290,13 @@ void TabRendererGtk::Paint(ChromeCanvasPaint* canvas) {
PaintTabBackground(canvas);
- if (show_icon && !data_.favicon.isNull()) {
- canvas->DrawBitmapInt(data_.favicon, favicon_bounds_.x(),
- favicon_bounds_.y() + fav_icon_hiding_offset_);
+ if (show_icon) {
+ if (loading_animation_.animation_state() != ANIMATION_NONE) {
+ PaintLoadingAnimation(canvas);
+ } else if (!data_.favicon.isNull()) {
+ canvas->DrawBitmapInt(data_.favicon, favicon_bounds_.x(),
+ favicon_bounds_.y() + fav_icon_hiding_offset_);
+ }
}
if (show_download_icon) {
@@ -380,6 +456,27 @@ void TabRendererGtk::PaintActiveTabBackground(ChromeCanvasPaint* canvas) {
bounds_.y());
}
+void TabRendererGtk::PaintLoadingAnimation(ChromeCanvasPaint* canvas) {
+ const SkBitmap* frames =
+ (loading_animation_.animation_state() == ANIMATION_WAITING) ?
+ loading_animation_.waiting_animation_frames() :
+ loading_animation_.loading_animation_frames();
+ const int image_size = frames->height();
+ const int image_offset = loading_animation_.animation_frame() * image_size;
+ const int dst_y = (height() - image_size) / 2;
+
+ // Just like with the Tab's title and favicon, the position for the page
+ // loading animation also needs to be mirrored if the UI layout is RTL.
+ // TODO(willchan): Handle RTL.
+ // dst_x = x() + width() - kLeftPadding - image_size;
+ int dst_x = x() + kLeftPadding;
+
+
+ canvas->DrawBitmapInt(*frames, image_offset, 0, image_size,
+ image_size, dst_x, dst_y, image_size, image_size,
+ false);
+}
+
int TabRendererGtk::IconCapacity() const {
if (height() < GetMinimumUnselectedSize().height())
return 0;
@@ -413,5 +510,7 @@ void TabRendererGtk::InitResources() {
title_font_ = new ChromeFont(rb.GetFont(ResourceBundle::BaseFont));
title_font_height_ = title_font_->height();
+ InitializeLoadingAnimationData(&rb, &loading_animation_data);
+
initialized_ = true;
}
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/gtk/tabs/tab_renderer_gtk.h
index 3ccd3ea..07c7614 100644
--- a/chrome/browser/gtk/tabs/tab_renderer_gtk.h
+++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.h
@@ -15,12 +15,57 @@
namespace gfx {
class Size;
-}
+} // namespace gfx
class TabContents;
class TabRendererGtk {
public:
+ // Possible animation states.
+ enum AnimationState {
+ ANIMATION_NONE,
+ ANIMATION_WAITING,
+ ANIMATION_LOADING
+ };
+
+ class LoadingAnimation {
+ public:
+ struct Data {
+ SkBitmap* waiting_animation_frames;
+ SkBitmap* loading_animation_frames;
+ int loading_animation_frame_count;
+ int waiting_animation_frame_count;
+ int waiting_to_loading_frame_count_ratio;
+ };
+
+ explicit LoadingAnimation(const Data* data);
+
+ // Advance the loading animation to the next frame, or hide the animation if
+ // the tab isn't loading.
+ void ValidateLoadingAnimation(AnimationState animation_state);
+
+ AnimationState animation_state() const { return animation_state_; }
+ int animation_frame() const { return animation_frame_; }
+
+ const SkBitmap* waiting_animation_frames() const {
+ return data_->waiting_animation_frames;
+ }
+ const SkBitmap* loading_animation_frames() const {
+ return data_->loading_animation_frames;
+ }
+
+ private:
+ const Data* const data_;
+
+ // Current state of the animation.
+ AnimationState animation_state_;
+
+ // The current index into the Animation image strip.
+ int animation_frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(LoadingAnimation);
+ };
+
TabRendererGtk();
virtual ~TabRendererGtk();
@@ -35,6 +80,10 @@ class TabRendererGtk {
// Returns true if the Tab is selected, false otherwise.
virtual bool IsSelected() const;
+ // Advance the loading animation to the next frame, or hide the animation if
+ // the tab isn't loading.
+ void ValidateLoadingAnimation(AnimationState animation_state);
+
// Returns the minimum possible size of a single unselected Tab.
static gfx::Size GetMinimumUnselectedSize();
// Returns the minimum possible size of a selected Tab. Selected tabs must
@@ -70,6 +119,28 @@ class TabRendererGtk {
std::wstring GetTitle() const;
private:
+ // Model data. We store this here so that we don't need to ask the underlying
+ // model, which is tricky since instances of this object can outlive the
+ // corresponding objects in the underlying model.
+ struct TabData {
+ SkBitmap favicon;
+ std::wstring title;
+ bool loading;
+ bool crashed;
+ bool off_the_record;
+ bool show_icon;
+ bool show_download_icon;
+ };
+
+ // TODO(jhawkins): Move into TabResources class.
+ struct TabImage {
+ SkBitmap* image_l;
+ SkBitmap* image_c;
+ SkBitmap* image_r;
+ int l_width;
+ int r_width;
+ };
+
// Generates the bounds for the interior items of the tab.
void Layout();
@@ -103,28 +174,8 @@ class TabRendererGtk {
gfx::Rect title_bounds_;
gfx::Rect close_button_bounds_;
- // Model data. We store this here so that we don't need to ask the underlying
- // model, which is tricky since instances of this object can outlive the
- // corresponding objects in the underlying model.
- struct TabData {
- SkBitmap favicon;
- std::wstring title;
- bool loading;
- bool crashed;
- bool off_the_record;
- bool show_icon;
- bool show_download_icon;
- };
TabData data_;
- // TODO(jhawkins): Move into TabResources class.
- struct TabImage {
- SkBitmap* image_l;
- SkBitmap* image_c;
- SkBitmap* image_r;
- int l_width;
- int r_width;
- };
static TabImage tab_active_;
static TabImage tab_inactive_;
static TabImage tab_inactive_otr_;
@@ -170,6 +221,9 @@ class TabRendererGtk {
// Set when the mouse is hovering over this tab and the tab is not selected.
bool hovering_;
+ // Contains the loading animation state.
+ LoadingAnimation loading_animation_;
+
DISALLOW_COPY_AND_ASSIGN(TabRendererGtk);
};
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk_unittest.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk_unittest.cc
new file mode 100644
index 0000000..0304d26
--- /dev/null
+++ b/chrome/browser/gtk/tabs/tab_renderer_gtk_unittest.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2009 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/gtk/tabs/tab_renderer_gtk.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+typedef TabRendererGtk::LoadingAnimation LoadingAnimation;
+
+const int kTestLoadingAnimationFrameCount = 10;
+const int kTestWaitingAnimationFrameCount = 40;
+const int kTestWaitingToLoadingFrameCountRatio = 4;
+
+const LoadingAnimation::Data kMockAnimationData = {
+ NULL, // waiting_animation_frames
+ NULL, // loading_animation_frames
+ kTestLoadingAnimationFrameCount,
+ kTestWaitingAnimationFrameCount,
+ kTestWaitingToLoadingFrameCountRatio,
+};
+
+TEST(LoadingAnimationTest, InitialState) {
+ LoadingAnimation loading_animation(&kMockAnimationData);
+ EXPECT_EQ(TabRendererGtk::ANIMATION_NONE,
+ loading_animation.animation_state());
+ EXPECT_EQ(0, loading_animation.animation_frame());
+}
+
+TEST(LoadingAnimationTest, AdvanceWaitingFrames) {
+ LoadingAnimation loading_animation(&kMockAnimationData);
+ loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
+ EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+ loading_animation.animation_state());
+ EXPECT_EQ(1, loading_animation.animation_frame());
+ loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
+ EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+ loading_animation.animation_state());
+ EXPECT_EQ(2, loading_animation.animation_frame());
+
+ for (int i = 2; i < kTestWaitingAnimationFrameCount - 1; ++i) {
+ loading_animation.ValidateLoadingAnimation(
+ TabRendererGtk::ANIMATION_WAITING);
+ }
+ EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+ loading_animation.animation_state());
+ EXPECT_EQ(kTestWaitingAnimationFrameCount - 1,
+ loading_animation.animation_frame());
+
+ loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_WAITING);
+ EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+ loading_animation.animation_state());
+ EXPECT_EQ(0, loading_animation.animation_frame()) <<
+ "The animation frame should have wrapped around to 0.";
+}
+
+TEST(LoadingAnimationTest, AdvanceFromWaitingToLoading) {
+ LoadingAnimation loading_animation(&kMockAnimationData);
+ for (int i = 0; i < 2 * kTestWaitingToLoadingFrameCountRatio; ++i) {
+ loading_animation.ValidateLoadingAnimation(
+ TabRendererGtk::ANIMATION_WAITING);
+ }
+ EXPECT_EQ(TabRendererGtk::ANIMATION_WAITING,
+ loading_animation.animation_state());
+ EXPECT_EQ(2 * kTestWaitingToLoadingFrameCountRatio,
+ loading_animation.animation_frame());
+
+ loading_animation.ValidateLoadingAnimation(TabRendererGtk::ANIMATION_LOADING);
+ EXPECT_EQ(TabRendererGtk::ANIMATION_LOADING,
+ loading_animation.animation_state());
+ EXPECT_EQ(kTestLoadingAnimationFrameCount - 1,
+ loading_animation.animation_frame());
+}
+
+} // namespace
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
index 7e9a153..1c0e5c4 100644
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc
+++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
@@ -102,6 +102,26 @@ void TabStripGtk::Layout() {
gtk_widget_queue_draw(tabstrip_.get());
}
+void TabStripGtk::UpdateLoadingAnimations() {
+ for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
+ TabGtk* current_tab = GetTabAt(i);
+ if (current_tab->closing()) {
+ --index;
+ } else {
+ TabContents* contents = model_->GetTabContentsAt(index);
+ if (!contents || !contents->is_loading()) {
+ current_tab->ValidateLoadingAnimation(TabGtk::ANIMATION_NONE);
+ } else if (contents->waiting_for_response()) {
+ current_tab->ValidateLoadingAnimation(TabGtk::ANIMATION_WAITING);
+ } else {
+ current_tab->ValidateLoadingAnimation(TabGtk::ANIMATION_LOADING);
+ }
+ }
+ }
+
+ gtk_widget_queue_draw(tabstrip_.get());
+}
+
////////////////////////////////////////////////////////////////////////////////
// TabStripGtk, TabStripModelObserver implementation:
@@ -294,7 +314,8 @@ int TabStripGtk::GetIndexOfTab(const TabGtk* tab) const {
}
TabGtk* TabStripGtk::GetTabAt(int index) const {
- DCHECK(index >= 0 && index < GetTabCount());
+ DCHECK_GE(index, 0);
+ DCHECK_LT(index, GetTabCount());
return tab_data_.at(index).tab;
}
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.h b/chrome/browser/gtk/tabs/tab_strip_gtk.h
index be93e07..6d8f17f 100644
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.h
+++ b/chrome/browser/gtk/tabs/tab_strip_gtk.h
@@ -8,6 +8,7 @@
#include <gtk/gtk.h>
#include <vector>
+#include "base/basictypes.h"
#include "base/gfx/rect.h"
#include "chrome/browser/gtk/tabs/tab_gtk.h"
#include "chrome/browser/tabs/tab_strip_model.h"
@@ -32,6 +33,9 @@ class TabStripGtk : public TabStripModelObserver,
// Sets the bounds of the tabstrip.
void SetBounds(const gfx::Rect& bounds) { bounds_ = bounds; }
+ // Updates loading animations for the TabStrip.
+ void UpdateLoadingAnimations();
+
protected:
// TabStripModelObserver implementation:
virtual void TabInsertedAt(TabContents* contents,
@@ -63,6 +67,11 @@ class TabStripGtk : public TabStripModelObserver,
virtual bool HasAvailableDragActions() const;
private:
+ struct TabData {
+ TabGtk* tab;
+ gfx::Rect ideal_bounds;
+ };
+
// expose-event handler that redraws the tabstrip
static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e,
TabStripGtk* tabstrip);
@@ -119,10 +128,6 @@ class TabStripGtk : public TabStripModelObserver,
void GenerateIdealBounds();
// The Tabs we contain, and their last generated "good" bounds.
- struct TabData {
- TabGtk* tab;
- gfx::Rect ideal_bounds;
- };
std::vector<TabData> tab_data_;
// The current widths of various types of tabs. We save these so that, as
@@ -157,6 +162,8 @@ class TabStripGtk : public TabStripModelObserver,
// The index of the tab the mouse is currently over. -1 if not over a tab.
int hover_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(TabStripGtk);
};
#endif // CHROME_BROWSER_GTK_TABS_TAB_STRIP_GTK_H_
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index f5c7e39..939b49c 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -2094,6 +2094,7 @@
'browser/extensions/extensions_service_unittest.cc',
'browser/extensions/user_script_master_unittest.cc',
'browser/google_url_tracker_unittest.cc',
+ 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc',
'browser/history/expire_history_backend_unittest.cc',
'browser/history/history_backend_unittest.cc',
'browser/history/history_querying_unittest.cc',
@@ -2232,6 +2233,7 @@
'sources!': [
'browser/back_forward_menu_model_unittest.cc',
'browser/download/download_manager_unittest.cc',
+ 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc',
'browser/navigation_controller_unittest.cc',
'browser/sessions/session_backend_unittest.cc',
'browser/sessions/session_service_test_helper.cc',
@@ -2252,6 +2254,7 @@
'third_party/wtl/include',
],
'sources!': [
+ 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc',
'common/file_descriptor_set_unittest.cc',
'common/net/url_util_unittest.cc',
],