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