1// Copyright (c) 2011 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_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_GTK_H_
6#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_GTK_H_
7#pragma once
8
9#include <gtk/gtk.h>
10#include <map>
11#include <string>
12
13#include "base/basictypes.h"
14#include "base/memory/scoped_ptr.h"
15#include "chrome/browser/autocomplete/autocomplete_match.h"
16#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
17#include "content/common/notification_observer.h"
18#include "content/common/notification_registrar.h"
19#include "ui/gfx/font.h"
20#include "webkit/glue/window_open_disposition.h"
21
22class AutocompleteEditModel;
23class AutocompleteEditView;
24class AutocompletePopupModel;
25class GtkThemeService;
26class Profile;
27class SkBitmap;
28
29class AutocompletePopupViewGtk : public AutocompletePopupView,
30                                 public NotificationObserver {
31 public:
32  AutocompletePopupViewGtk(const gfx::Font& font,
33                           AutocompleteEditView* edit_view,
34                           AutocompleteEditModel* edit_model,
35                           Profile* profile,
36                           GtkWidget* location_bar);
37  ~AutocompletePopupViewGtk();
38
39  // Overridden from AutocompletePopupView:
40  virtual bool IsOpen() const;
41  virtual void InvalidateLine(size_t line);
42  virtual void UpdatePopupAppearance();
43  virtual gfx::Rect GetTargetBounds();
44  virtual void PaintUpdatesNow();
45  virtual void OnDragCanceled();
46
47  // Overridden from NotificationObserver:
48  virtual void Observe(NotificationType type,
49                       const NotificationSource& source,
50                       const NotificationDetails& details);
51
52 private:
53  // Be friendly for unit tests.
54  friend class AutocompletePopupViewGtkTest;
55  static void SetupLayoutForMatch(
56      PangoLayout* layout,
57      const string16& text,
58      const AutocompleteMatch::ACMatchClassifications& classifications,
59      const GdkColor* base_color,
60      const GdkColor* dim_color,
61      const GdkColor* url_color,
62      const std::string& prefix_text);
63
64  void Show(size_t num_results);
65  void Hide();
66
67  // Restack the popup window directly above the browser's toplevel window.
68  void StackWindow();
69
70  // Convert a y-coordinate to the closest line / result.
71  size_t LineFromY(int y);
72
73  // Accept a line of the results, for example, when the user clicks a line.
74  void AcceptLine(size_t line, WindowOpenDisposition disposition);
75
76  GdkPixbuf* IconForMatch(const AutocompleteMatch& match, bool selected);
77
78  static gboolean HandleExposeThunk(GtkWidget* widget, GdkEventExpose* event,
79                                    gpointer userdata) {
80    return reinterpret_cast<AutocompletePopupViewGtk*>(userdata)->
81        HandleExpose(widget, event);
82  }
83  gboolean HandleExpose(GtkWidget* widget, GdkEventExpose* event);
84
85  static gboolean HandleMotionThunk(GtkWidget* widget, GdkEventMotion* event,
86                                    gpointer userdata) {
87    return reinterpret_cast<AutocompletePopupViewGtk*>(userdata)->
88        HandleMotion(widget, event);
89  }
90  gboolean HandleMotion(GtkWidget* widget, GdkEventMotion* event);
91
92  static gboolean HandleButtonPressThunk(GtkWidget* widget,
93                                         GdkEventButton* event,
94                                         gpointer userdata) {
95    return reinterpret_cast<AutocompletePopupViewGtk*>(userdata)->
96        HandleButtonPress(widget, event);
97  }
98  gboolean HandleButtonPress(GtkWidget* widget, GdkEventButton* event);
99
100  static gboolean HandleButtonReleaseThunk(GtkWidget* widget,
101                                           GdkEventButton* event,
102                                           gpointer userdata) {
103    return reinterpret_cast<AutocompletePopupViewGtk*>(userdata)->
104        HandleButtonRelease(widget, event);
105  }
106  gboolean HandleButtonRelease(GtkWidget* widget, GdkEventButton* event);
107
108  scoped_ptr<AutocompletePopupModel> model_;
109  AutocompleteEditView* edit_view_;
110  GtkWidget* location_bar_;
111
112  // Our popup window, which is the only widget used, and we paint it on our
113  // own.  This widget shouldn't be exposed outside of this class.
114  GtkWidget* window_;
115  // The pango layout object created from the window, cached across exposes.
116  PangoLayout* layout_;
117
118  GtkThemeService* theme_service_;
119  NotificationRegistrar registrar_;
120
121  // Font used for suggestions after being derived from the constructor's
122  // |font|.
123  gfx::Font font_;
124
125  // Used to cache GdkPixbufs and map them from the SkBitmaps they were created
126  // from.
127  typedef std::map<const SkBitmap*, GdkPixbuf*> PixbufMap;
128  PixbufMap pixbufs_;
129
130  // A list of colors which we should use for drawing the popup. These change
131  // between gtk and normal mode.
132  GdkColor border_color_;
133  GdkColor background_color_;
134  GdkColor selected_background_color_;
135  GdkColor hovered_background_color_;
136  GdkColor content_text_color_;
137  GdkColor selected_content_text_color_;
138  GdkColor content_dim_text_color_;
139  GdkColor selected_content_dim_text_color_;
140  GdkColor url_text_color_;
141  GdkColor url_selected_text_color_;
142
143  // If the user cancels a dragging action (i.e. by pressing ESC), we don't have
144  // a convenient way to release mouse capture. Instead we use this flag to
145  // simply ignore all remaining drag events, and the eventual mouse release
146  // event. Since OnDragCanceled() can be called when we're not dragging, this
147  // flag is reset to false on a mouse pressed event, to make sure we don't
148  // erroneously ignore the next drag.
149  bool ignore_mouse_drag_;
150
151  // Whether our popup is currently open / shown, or closed / hidden.
152  bool opened_;
153
154  DISALLOW_COPY_AND_ASSIGN(AutocompletePopupViewGtk);
155};
156
157#endif  // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_GTK_H_
158