Home | History | Annotate | Download | only in gtk
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_
      6 #define CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_
      7 
      8 #include <gtk/gtk.h>
      9 
     10 #include <string>
     11 
     12 #include "base/compiler_specific.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/timer/timer.h"
     15 #include "chrome/browser/ui/status_bubble.h"
     16 #include "content/public/browser/notification_observer.h"
     17 #include "content/public/browser/notification_registrar.h"
     18 #include "ui/base/gtk/gtk_signal.h"
     19 #include "ui/base/gtk/owned_widget_gtk.h"
     20 #include "ui/gfx/animation/animation_delegate.h"
     21 #include "ui/gfx/point.h"
     22 #include "url/gurl.h"
     23 
     24 class GtkThemeService;
     25 class Profile;
     26 
     27 namespace gfx {
     28 class SlideAnimation;
     29 }
     30 
     31 // GTK implementation of StatusBubble. Unlike Windows, our status bubble
     32 // doesn't have the nice leave-the-window effect since we can't rely on the
     33 // window manager to not try to be "helpful" and center our popups, etc.
     34 // We therefore position it absolutely in a GtkFixed, that we don't own.
     35 class StatusBubbleGtk : public StatusBubble,
     36                         public content::NotificationObserver,
     37                         public gfx::AnimationDelegate {
     38  public:
     39   explicit StatusBubbleGtk(Profile* profile);
     40   virtual ~StatusBubbleGtk();
     41 
     42   bool flip_horizontally() const { return flip_horizontally_; }
     43   int y_offset() const { return y_offset_; }
     44 
     45   // StatusBubble implementation.
     46   virtual void SetStatus(const base::string16& status) OVERRIDE;
     47   virtual void SetURL(const GURL& url, const std::string& languages) OVERRIDE;
     48   virtual void Hide() OVERRIDE;
     49   virtual void MouseMoved(const gfx::Point& location,
     50                           bool left_content) OVERRIDE;
     51 
     52   // gfx::AnimationDelegate implementation.
     53   virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
     54   virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
     55 
     56   // Called when the download shelf becomes visible or invisible.
     57   // This is used by to ensure that the status bubble does not obscure
     58   // the download shelf, when it is visible.
     59   virtual void UpdateDownloadShelfVisibility(bool visible) OVERRIDE;
     60 
     61   // Overridden from content::NotificationObserver:
     62   virtual void Observe(int type,
     63                        const content::NotificationSource& source,
     64                        const content::NotificationDetails& details) OVERRIDE;
     65 
     66   // Top of the widget hierarchy for a StatusBubble. This top level widget is
     67   // guarenteed to have its gtk_widget_name set to "status-bubble" for
     68   // identification.
     69   GtkWidget* widget() { return container_.get(); }
     70 
     71  private:
     72   // Sets the text of the label widget and controls visibility. (As contrasted
     73   // with setting the current status or URL text, which may be ignored for now).
     74   void SetStatusTextTo(const std::string& status_utf8);
     75 
     76   // Sets the status text to the current value of |url_|, eliding it as
     77   // necessary.
     78   void SetStatusTextToURL();
     79 
     80   // Sets the status bubble's location in the parent GtkFixed, shows the widget
     81   // and makes sure that the status bubble has the highest z-order.
     82   void Show();
     83 
     84   // Builds the widgets, containers, etc.
     85   void InitWidgets();
     86 
     87   // Notification from the window that we should retheme ourself.
     88   void UserChangedTheme();
     89 
     90   // Sets whether the bubble should be flipped horizontally and displayed on the
     91   // opposite side of the tab contents.  Reshapes the container and queues a
     92   // redraw if necessary.
     93   void SetFlipHorizontally(bool flip_horizontally);
     94 
     95   // Expand the bubble up to the full width of the browser, so that the entire
     96   // URL may be seen. Called after the user hovers over a link for sufficient
     97   // time.
     98   void ExpandURL();
     99 
    100   // Adjust the actual size of the bubble by changing the label's size request.
    101   void UpdateLabelSizeRequest();
    102 
    103   // Returns true if the status bubble is in the expand-state (i.e., is
    104   // currently expanded or in the process of expanding).
    105   bool expanded() {
    106     return expand_animation_.get();
    107   }
    108 
    109   CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleMotionNotify,
    110                        GdkEventMotion*);
    111 
    112   CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleEnterNotify,
    113                        GdkEventCrossing*);
    114 
    115   content::NotificationRegistrar registrar_;
    116 
    117   // Provides colors.
    118   GtkThemeService* theme_service_;
    119 
    120   // The toplevel event box.
    121   ui::OwnedWidgetGtk container_;
    122 
    123   // The GtkAlignment holding |label_|.
    124   GtkWidget* padding_;
    125 
    126   // The GtkLabel holding the text.
    127   ui::OwnedWidgetGtk label_;
    128 
    129   // The status text we want to display when there are no URLs to display.
    130   std::string status_text_;
    131 
    132   // The URL we are displaying for.
    133   GURL url_;
    134 
    135   // The possibly elided url text we want to display.
    136   std::string url_text_;
    137 
    138   // Used to determine the character set that the user can read (for eliding
    139   // the url text).
    140   std::string languages_;
    141 
    142   // A timer that hides our window after a delay.
    143   base::OneShotTimer<StatusBubbleGtk> hide_timer_;
    144 
    145   // A timer that expands our window after a delay.
    146   base::OneShotTimer<StatusBubbleGtk> expand_timer_;
    147 
    148   // The animation for resizing the status bubble on long hovers.
    149   scoped_ptr<gfx::SlideAnimation> expand_animation_;
    150 
    151   // The start and end width of the current resize animation.
    152   int start_width_;
    153   int desired_width_;
    154 
    155   // Should the bubble be flipped horizontally (e.g. displayed on the right for
    156   // an LTR language)?  We move the bubble to the other side of the tab contents
    157   // rather than sliding it down when the download shelf is visible.
    158   bool flip_horizontally_;
    159 
    160   // Vertical offset used to hide the status bubble as the pointer nears it.
    161   int y_offset_;
    162 
    163   // If the download shelf is visible, do not obscure it.
    164   bool download_shelf_is_visible_;
    165 
    166   // 'location' and 'left_content' values from the last invocation of
    167   // MouseMoved().  We hang onto these so we can move the bubble if necessary
    168   // when its text changes, triggering a size change.
    169   gfx::Point last_mouse_location_;
    170   bool last_mouse_left_content_;
    171 
    172   // Shortly after the cursor enters the status bubble, we'll get a message
    173   // that the cursor left the content area. This lets us ignore that.
    174   bool ignore_next_left_content_;
    175 };
    176 
    177 #endif  // CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_
    178