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_OMNIBOX_OMNIBOX_POPUP_VIEW_GTK_H_
6#define CHROME_BROWSER_UI_GTK_OMNIBOX_OMNIBOX_POPUP_VIEW_GTK_H_
7
8#include <gtk/gtk.h>
9
10#include <map>
11#include <string>
12
13#include "base/basictypes.h"
14#include "base/compiler_specific.h"
15#include "base/memory/scoped_ptr.h"
16#include "chrome/browser/autocomplete/autocomplete_match.h"
17#include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
18#include "content/public/browser/notification_observer.h"
19#include "content/public/browser/notification_registrar.h"
20#include "ui/base/gtk/gtk_signal.h"
21#include "ui/base/window_open_disposition.h"
22#include "ui/gfx/font.h"
23
24class GtkThemeService;
25class OmniboxEditModel;
26class OmniboxPopupModel;
27class OmniboxView;
28class SkBitmap;
29
30namespace gfx {
31class Image;
32}
33
34namespace ui {
35class GtkSignalRegistrar;
36}
37
38class OmniboxPopupViewGtk : public OmniboxPopupView,
39                            public content::NotificationObserver {
40 public:
41  OmniboxPopupViewGtk(const gfx::Font& font,
42                      OmniboxView* omnibox_view,
43                      OmniboxEditModel* edit_model,
44                      GtkWidget* location_bar);
45  virtual ~OmniboxPopupViewGtk();
46
47  // Overridden from OmniboxPopupView:
48  virtual bool IsOpen() const OVERRIDE;
49  virtual void InvalidateLine(size_t line) OVERRIDE;
50  virtual void UpdatePopupAppearance() OVERRIDE;
51  virtual gfx::Rect GetTargetBounds() OVERRIDE;
52  virtual void PaintUpdatesNow() OVERRIDE;
53  virtual void OnDragCanceled() OVERRIDE;
54
55  // Overridden from content::NotificationObserver:
56  virtual void Observe(int type,
57                       const content::NotificationSource& source,
58                       const content::NotificationDetails& details) OVERRIDE;
59
60 private:
61  // Be friendly for unit tests.
62  friend class OmniboxPopupViewGtkTest;
63
64  static void SetupLayoutForMatch(
65      PangoLayout* layout,
66      const string16& text,
67      const AutocompleteMatch::ACMatchClassifications& classifications,
68      const GdkColor* base_color,
69      const GdkColor* dim_color,
70      const GdkColor* url_color,
71      const std::string& prefix_text);
72
73  void Show(size_t num_results);
74  void Hide();
75
76  // Restack the popup window directly above the browser's toplevel window.
77  void StackWindow();
78
79  // Convert a y-coordinate to the closest line / result.
80  size_t LineFromY(int y);
81
82  // Accept a line of the results, for example, when the user clicks a line.
83  void AcceptLine(size_t line, WindowOpenDisposition disposition);
84
85  gfx::Image IconForMatch(const AutocompleteMatch& match,
86                          bool selected,
87                          bool is_selected_keyword);
88
89  // Returns the |index|th element of match, unless we're selected and showing
90  // the associated keyword match.
91  void GetVisibleMatchForInput(size_t index,
92                               const AutocompleteMatch** match,
93                               bool* is_selected_keyword);
94
95  CHROMEGTK_CALLBACK_1(OmniboxPopupViewGtk, gboolean, HandleMotion,
96                       GdkEventMotion*);
97
98  CHROMEGTK_CALLBACK_1(OmniboxPopupViewGtk, gboolean, HandleButtonPress,
99                       GdkEventButton*);
100
101  CHROMEGTK_CALLBACK_1(OmniboxPopupViewGtk, gboolean, HandleButtonRelease,
102                       GdkEventButton*);
103
104  CHROMEGTK_CALLBACK_1(OmniboxPopupViewGtk, gboolean, HandleExpose,
105                       GdkEventExpose*);
106
107  scoped_ptr<ui::GtkSignalRegistrar> signal_registrar_;
108  scoped_ptr<OmniboxPopupModel> model_;
109  OmniboxView* omnibox_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  content::NotificationRegistrar registrar_;
120
121  // Font used for suggestions after being derived from the constructor's
122  // |font|.
123  gfx::Font font_;
124
125  // A list of colors which we should use for drawing the popup. These change
126  // between gtk and normal mode.
127  GdkColor border_color_;
128  GdkColor background_color_;
129  GdkColor selected_background_color_;
130  GdkColor hovered_background_color_;
131  GdkColor content_text_color_;
132  GdkColor selected_content_text_color_;
133  GdkColor content_dim_text_color_;
134  GdkColor selected_content_dim_text_color_;
135  GdkColor url_text_color_;
136  GdkColor url_selected_text_color_;
137
138  // If the user cancels a dragging action (i.e. by pressing ESC), we don't have
139  // a convenient way to release mouse capture. Instead we use this flag to
140  // simply ignore all remaining drag events, and the eventual mouse release
141  // event. Since OnDragCanceled() can be called when we're not dragging, this
142  // flag is reset to false on a mouse pressed event, to make sure we don't
143  // erroneously ignore the next drag.
144  bool ignore_mouse_drag_;
145
146  // Whether our popup is currently open / shown, or closed / hidden.
147  bool opened_;
148
149  DISALLOW_COPY_AND_ASSIGN(OmniboxPopupViewGtk);
150};
151
152#endif  // CHROME_BROWSER_UI_GTK_OMNIBOX_OMNIBOX_POPUP_VIEW_GTK_H_
153