summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-14 18:06:18 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-14 18:06:18 +0000
commitefa71ab24691126e8a1d11f177b64c674a5c9f68 (patch)
treea6aabe7e82cba21727a0506d4f0f783db20eae9b /chrome/browser
parentfac9a45d0e29394b6445a4a1a8ec20dc9e917a3d (diff)
downloadchromium_src-efa71ab24691126e8a1d11f177b64c674a5c9f68.zip
chromium_src-efa71ab24691126e8a1d11f177b64c674a5c9f68.tar.gz
chromium_src-efa71ab24691126e8a1d11f177b64c674a5c9f68.tar.bz2
GTK: expand status bar when user hovers over a link for long enough.
BUG=43192 TEST=none Review URL: http://codereview.chromium.org/2033010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47285 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/cocoa/status_bubble_mac.h1
-rw-r--r--chrome/browser/cocoa/status_bubble_mac.mm4
-rw-r--r--chrome/browser/gtk/status_bubble_gtk.cc88
-rw-r--r--chrome/browser/gtk/status_bubble_gtk.h64
-rw-r--r--chrome/browser/status_bubble.h8
-rw-r--r--chrome/browser/views/status_bubble_views.cc4
-rw-r--r--chrome/browser/views/status_bubble_views.h3
7 files changed, 118 insertions, 54 deletions
diff --git a/chrome/browser/cocoa/status_bubble_mac.h b/chrome/browser/cocoa/status_bubble_mac.h
index d01aee2..e1dadb9 100644
--- a/chrome/browser/cocoa/status_bubble_mac.h
+++ b/chrome/browser/cocoa/status_bubble_mac.h
@@ -38,7 +38,6 @@ class StatusBubbleMac : public StatusBubble {
virtual void Hide();
virtual void MouseMoved(const gfx::Point& location, bool left_content);
virtual void UpdateDownloadShelfVisibility(bool visible);
- virtual void SetBubbleWidth(int width);
// Mac-specific method: Update the size and position of the status bubble to
// match the parent window. Safe to call even when the status bubble does not
diff --git a/chrome/browser/cocoa/status_bubble_mac.mm b/chrome/browser/cocoa/status_bubble_mac.mm
index 62b0ae0..7906243 100644
--- a/chrome/browser/cocoa/status_bubble_mac.mm
+++ b/chrome/browser/cocoa/status_bubble_mac.mm
@@ -292,10 +292,6 @@ void StatusBubbleMac::MouseMoved(
void StatusBubbleMac::UpdateDownloadShelfVisibility(bool visible) {
}
-void StatusBubbleMac::SetBubbleWidth(int width) {
- NOTIMPLEMENTED();
-}
-
void StatusBubbleMac::Create() {
if (window_)
return;
diff --git a/chrome/browser/gtk/status_bubble_gtk.cc b/chrome/browser/gtk/status_bubble_gtk.cc
index 960797f..56670dd 100644
--- a/chrome/browser/gtk/status_bubble_gtk.cc
+++ b/chrome/browser/gtk/status_bubble_gtk.cc
@@ -18,7 +18,6 @@
#include "chrome/browser/gtk/slide_animator_gtk.h"
#include "chrome/common/notification_service.h"
#include "gfx/gtk_util.h"
-#include "googleurl/src/gurl.h"
namespace {
@@ -42,7 +41,6 @@ StatusBubbleGtk::StatusBubbleGtk(Profile* profile)
: theme_provider_(GtkThemeProvider::GetFrom(profile)),
padding_(NULL),
label_(NULL),
- timer_factory_(this),
flip_horizontally_(false),
y_offset_(0),
download_shelf_is_visible_(false),
@@ -75,6 +73,9 @@ void StatusBubbleGtk::SetStatus(const std::wstring& status_text_wide) {
}
void StatusBubbleGtk::SetURL(const GURL& url, const std::wstring& languages) {
+ url_ = url;
+ languages_ = languages;
+
// If we want to clear a displayed URL but there is a status still to
// display, display that status instead.
if (url.is_empty() && !status_text_.empty()) {
@@ -83,21 +84,32 @@ void StatusBubbleGtk::SetURL(const GURL& url, const std::wstring& languages) {
return;
}
- // Set Elided Text corresponding to the GURL object. We limit the width of
- // the URL to a third of the width of the browser window (matching the width
- // on Windows).
+ SetStatusTextToURL();
+}
+
+void StatusBubbleGtk::SetStatusTextToURL() {
GtkWidget* parent = gtk_widget_get_parent(container_.get());
- int window_width = parent->allocation.width;
+ int desired_width = parent->allocation.width;
+ if (!expanded()) {
+ expand_timer_.Stop();
+ expand_timer_.Start(base::TimeDelta::FromMilliseconds(kExpandHoverDelay),
+ this, &StatusBubbleGtk::ExpandURL);
+ // When not expanded, we limit the size to one third the browser's
+ // width.
+ desired_width /= 3;
+ }
+
// TODO(tc): We don't actually use gfx::Font as the font in the status
// bubble. We should extend gfx::ElideUrl to take some sort of pango font.
- url_text_ = WideToUTF8(gfx::ElideUrl(url, gfx::Font(), window_width / 3,
- languages));
+ url_text_ = WideToUTF8(gfx::ElideUrl(url_, gfx::Font(), desired_width,
+ languages_));
SetStatusTextTo(url_text_);
}
+
void StatusBubbleGtk::Show() {
// If we were going to hide, stop.
- timer_factory_.RevokeAll();
+ hide_timer_.Stop();
gtk_widget_show_all(container_.get());
if (container_->window)
@@ -105,14 +117,26 @@ void StatusBubbleGtk::Show() {
}
void StatusBubbleGtk::Hide() {
+ // If we were going to expand the bubble, stop.
+ expand_timer_.Stop();
+ expand_animation_.reset();
+
gtk_widget_hide_all(container_.get());
}
void StatusBubbleGtk::SetStatusTextTo(const std::string& status_utf8) {
if (status_utf8.empty()) {
- HideInASecond();
+ hide_timer_.Stop();
+ hide_timer_.Start(base::TimeDelta::FromMilliseconds(kHideDelay),
+ this, &StatusBubbleGtk::Hide);
} else {
gtk_label_set_text(GTK_LABEL(label_), status_utf8.c_str());
+ GtkRequisition req;
+ gtk_widget_size_request(label_, &req);
+ desired_width_ = req.width;
+
+ UpdateLabelSizeRequest();
+
if (!last_mouse_left_content_) {
// Show the padding and label to update our requisition and then
// re-process the last mouse event -- if the label was empty before or the
@@ -125,15 +149,6 @@ void StatusBubbleGtk::SetStatusTextTo(const std::string& status_utf8) {
}
}
-void StatusBubbleGtk::HideInASecond() {
- if (!timer_factory_.empty())
- timer_factory_.RevokeAll();
-
- MessageLoop::current()->PostDelayedTask(FROM_HERE,
- timer_factory_.NewRunnableMethod(&StatusBubbleGtk::Hide),
- kHideDelay);
-}
-
void StatusBubbleGtk::MouseMoved(
const gfx::Point& location, bool left_content) {
last_mouse_location_ = location;
@@ -210,10 +225,6 @@ void StatusBubbleGtk::UpdateDownloadShelfVisibility(bool visible) {
download_shelf_is_visible_ = visible;
}
-void StatusBubbleGtk::SetBubbleWidth(int width) {
- NOTIMPLEMENTED();
-}
-
void StatusBubbleGtk::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
@@ -298,7 +309,36 @@ void StatusBubbleGtk::SetFlipHorizontally(bool flip_horizontally) {
gtk_widget_queue_draw(container_.get());
}
-gboolean StatusBubbleGtk::HandleMotionNotify(GdkEventMotion* event) {
+void StatusBubbleGtk::ExpandURL() {
+ start_width_ = label_->allocation.width;
+ expand_animation_.reset(new SlideAnimation(this));
+ expand_animation_->SetTweenType(Tween::LINEAR);
+ expand_animation_->Show();
+
+ SetStatusTextToURL();
+}
+
+void StatusBubbleGtk::UpdateLabelSizeRequest() {
+ if (!expanded() || !expand_animation_->is_animating()) {
+ gtk_widget_set_size_request(label_, -1, -1);
+ return;
+ }
+
+ int new_width = start_width_ +
+ (desired_width_ - start_width_) * expand_animation_->GetCurrentValue();
+ gtk_widget_set_size_request(label_, new_width, -1);
+}
+
+gboolean StatusBubbleGtk::HandleMotionNotify(GtkWidget* sender,
+ GdkEventMotion* event) {
MouseMoved(gfx::Point(event->x_root, event->y_root), false);
return FALSE;
}
+
+void StatusBubbleGtk::AnimationEnded(const Animation* animation) {
+ UpdateLabelSizeRequest();
+}
+
+void StatusBubbleGtk::AnimationProgressed(const Animation* animation) {
+ UpdateLabelSizeRequest();
+}
diff --git a/chrome/browser/gtk/status_bubble_gtk.h b/chrome/browser/gtk/status_bubble_gtk.h
index c648b8e..497d67e 100644
--- a/chrome/browser/gtk/status_bubble_gtk.h
+++ b/chrome/browser/gtk/status_bubble_gtk.h
@@ -9,16 +9,18 @@
#include <string>
+#include "app/gtk_signal.h"
+#include "app/slide_animation.h"
#include "base/scoped_ptr.h"
-#include "base/task.h"
+#include "base/timer.h"
#include "chrome/browser/status_bubble.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/owned_widget_gtk.h"
#include "gfx/point.h"
+#include "googleurl/src/gurl.h"
class GtkThemeProvider;
-class GURL;
class Profile;
// GTK implementation of StatusBubble. Unlike Windows, our status bubble
@@ -26,7 +28,8 @@ class Profile;
// window manager to not try to be "helpful" and center our popups, etc.
// We therefore position it absolutely in a GtkFixed, that we don't own.
class StatusBubbleGtk : public StatusBubble,
- public NotificationObserver {
+ public NotificationObserver,
+ public AnimationDelegate {
public:
explicit StatusBubbleGtk(Profile* profile);
virtual ~StatusBubbleGtk();
@@ -40,13 +43,15 @@ class StatusBubbleGtk : public StatusBubble,
virtual void Hide();
virtual void MouseMoved(const gfx::Point& location, bool left_content);
+ // AnimationDelegate implementation.
+ virtual void AnimationEnded(const Animation* animation);
+ virtual void AnimationProgressed(const Animation* animation);
+
// Called when the download shelf becomes visible or invisible.
// This is used by to ensure that the status bubble does not obscure
// the download shelf, when it is visible.
virtual void UpdateDownloadShelfVisibility(bool visible);
- virtual void SetBubbleWidth(int width);
-
// Overridden from NotificationObserver:
void Observe(NotificationType type,
const NotificationSource& source,
@@ -62,13 +67,14 @@ class StatusBubbleGtk : public StatusBubble,
// with setting the current status or URL text, which may be ignored for now).
void SetStatusTextTo(const std::string& status_utf8);
+ // Sets the status text to the current value of |url_|, eliding it as
+ // necessary.
+ void SetStatusTextToURL();
+
// Sets the status bubble's location in the parent GtkFixed, shows the widget
// and makes sure that the status bubble has the highest z-order.
void Show();
- // Sets an internal timer to hide the status bubble after a delay.
- void HideInASecond();
-
// Builds the widgets, containers, etc.
void InitWidgets();
@@ -80,13 +86,22 @@ class StatusBubbleGtk : public StatusBubble,
// redraw if necessary.
void SetFlipHorizontally(bool flip_horizontally);
- static gboolean HandleMotionNotifyThunk(GtkWidget* widget,
- GdkEventMotion* event,
- gpointer user_data) {
- return reinterpret_cast<StatusBubbleGtk*>(user_data)->
- HandleMotionNotify(event);
+ // Expand the bubble up to the full width of the browser, so that the entire
+ // URL may be seen. Called after the user hovers over a link for sufficient
+ // time.
+ void ExpandURL();
+
+ // Adjust the actual size of the bubble by changing the label's size request.
+ void UpdateLabelSizeRequest();
+
+ // Returns true if the status bubble is in the expand-state (i.e., is
+ // currently expanded or in the process of expanding).
+ bool expanded() {
+ return expand_animation_.get();
}
- gboolean HandleMotionNotify(GdkEventMotion* event);
+
+ CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleMotionNotify,
+ GdkEventMotion*);
NotificationRegistrar registrar_;
@@ -105,11 +120,28 @@ class StatusBubbleGtk : public StatusBubble,
// The status text we want to display when there are no URLs to display.
std::string status_text_;
- // The url we want to display when there is no status text to display.
+ // The URL we are displaying for.
+ GURL url_;
+
+ // The possibly elided url text we want to display.
std::string url_text_;
+ // Used to determine the character set that the user can read (for eliding
+ // the url text).
+ std::wstring languages_;
+
// A timer that hides our window after a delay.
- ScopedRunnableMethodFactory<StatusBubbleGtk> timer_factory_;
+ base::OneShotTimer<StatusBubbleGtk> hide_timer_;
+
+ // A timer that expands our window after a delay.
+ base::OneShotTimer<StatusBubbleGtk> expand_timer_;
+
+ // The animation for resizing the status bubble on long hovers.
+ scoped_ptr<SlideAnimation> expand_animation_;
+
+ // The start and end width of the current resize animation.
+ int start_width_;
+ int desired_width_;
// Should the bubble be flipped horizontally (e.g. displayed on the right for
// an LTR language)? We move the bubble to the other side of the tab contents
diff --git a/chrome/browser/status_bubble.h b/chrome/browser/status_bubble.h
index 43851be..8ed364f 100644
--- a/chrome/browser/status_bubble.h
+++ b/chrome/browser/status_bubble.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
@@ -19,6 +19,9 @@ class Point;
//
class StatusBubble {
public:
+ // On hover, expand status bubble to fit long URL after this delay.
+ static const int kExpandHoverDelay = 1600;
+
virtual ~StatusBubble() {}
// Sets the bubble contents to a specific string and causes the bubble
@@ -49,9 +52,6 @@ class StatusBubble {
// This is used by to ensure that the status bubble does not obscure
// the download shelf, when it is visible.
virtual void UpdateDownloadShelfVisibility(bool visible) = 0;
-
- // Allow StatusView animation to set width of StatusBubble.
- virtual void SetBubbleWidth(int width) = 0;
};
#endif // CHROME_BROWSER_STATUS_BUBBLE_H_
diff --git a/chrome/browser/views/status_bubble_views.cc b/chrome/browser/views/status_bubble_views.cc
index 1a238026..bd93609 100644
--- a/chrome/browser/views/status_bubble_views.cc
+++ b/chrome/browser/views/status_bubble_views.cc
@@ -468,7 +468,7 @@ void StatusBubbleViews::StatusView::Paint(gfx::Canvas* canvas) {
class StatusBubbleViews::StatusViewExpander : public LinearAnimation,
public AnimationDelegate {
public:
- StatusViewExpander(StatusBubble* status_bubble,
+ StatusViewExpander(StatusBubbleViews* status_bubble,
StatusView* status_view)
: ALLOW_THIS_IN_INITIALIZER_LIST(LinearAnimation(kFramerate, this)),
status_bubble_(status_bubble),
@@ -492,7 +492,7 @@ class StatusBubbleViews::StatusViewExpander : public LinearAnimation,
void AnimationEnded(const Animation* animation);
// Manager that owns us.
- StatusBubble* status_bubble_;
+ StatusBubbleViews* status_bubble_;
// Change the bounds and text of this view.
StatusView* status_view_;
diff --git a/chrome/browser/views/status_bubble_views.h b/chrome/browser/views/status_bubble_views.h
index 4ff9544..4e0b414 100644
--- a/chrome/browser/views/status_bubble_views.h
+++ b/chrome/browser/views/status_bubble_views.h
@@ -31,9 +31,6 @@ class StatusBubbleViews : public StatusBubble {
// The combined vertical padding above and below the text.
static const int kTotalVerticalPadding = 7;
- // On hover, expand status bubble to fit long URL after this delay.
- static const int kExpandHoverDelay = 1600;
-
explicit StatusBubbleViews(views::Widget* frame);
~StatusBubbleViews();