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_UI_GTK_BOOKMARKS_BOOKMARK_MENU_CONTROLLER_GTK_H_
6#define CHROME_BROWSER_UI_GTK_BOOKMARKS_BOOKMARK_MENU_CONTROLLER_GTK_H_
7#pragma once
8
9#include <map>
10
11#include "base/memory/scoped_ptr.h"
12#include "chrome/browser/bookmarks/base_bookmark_model_observer.h"
13#include "chrome/browser/bookmarks/bookmark_context_menu_controller.h"
14#include "chrome/browser/ui/gtk/owned_widget_gtk.h"
15#include "ui/base/gtk/gtk_integers.h"
16#include "ui/base/gtk/gtk_signal.h"
17#include "ui/base/gtk/gtk_signal_registrar.h"
18#include "webkit/glue/window_open_disposition.h"
19
20class Browser;
21class Profile;
22class Profiler;
23class PageNavigator;
24class BookmarkModel;
25class BookmarkNode;
26class MenuGtk;
27
28typedef struct _GdkDragContext GdkDragContext;
29typedef struct _GdkEventButton GdkEventButton;
30typedef struct _GtkSelectionData GtkSelectionData;
31typedef struct _GtkWidget GtkWidget;
32
33class BookmarkMenuController : public BaseBookmarkModelObserver,
34                               public BookmarkContextMenuControllerDelegate {
35 public:
36  // Creates a BookmarkMenuController showing the children of |node| starting
37  // at index |start_child_index|.
38  BookmarkMenuController(Browser* browser,
39                         Profile* profile,
40                         PageNavigator* page_navigator,
41                         GtkWindow* window,
42                         const BookmarkNode* node,
43                         int start_child_index);
44  virtual ~BookmarkMenuController();
45
46  GtkWidget* widget() { return menu_; }
47
48  // Pops up the menu. |widget| must be a GtkChromeButton.
49  void Popup(GtkWidget* widget, gint button_type, guint32 timestamp);
50
51  // Overridden from BaseBookmarkModelObserver:
52  virtual void BookmarkModelChanged();
53  virtual void BookmarkNodeFaviconLoaded(BookmarkModel* model,
54                                         const BookmarkNode* node);
55
56  // Overridden from BookmarkContextMenuController::Delegate:
57  virtual void WillExecuteCommand();
58  virtual void CloseMenu();
59
60 private:
61  // Recursively change the bookmark hierarchy rooted in |parent| into a set of
62  // gtk menus rooted in |menu|.
63  void BuildMenu(const BookmarkNode* parent,
64                 int start_child_index,
65                 GtkWidget* menu);
66
67  // Calls the page navigator to navigate to the node represented by
68  // |menu_item|.
69  void NavigateToMenuItem(GtkWidget* menu_item,
70                          WindowOpenDisposition disposition);
71
72  // Button press and release events for a GtkMenu.
73  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean,
74                       OnMenuButtonPressedOrReleased, GdkEventButton*);
75
76  // Button release event for a GtkMenuItem.
77  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean, OnButtonReleased,
78                       GdkEventButton*);
79
80  // We connect this handler to the button-press-event signal for folder nodes.
81  // It suppresses the normal behavior (popping up the submenu) to allow these
82  // nodes to be draggable. The submenu is instead popped up on a
83  // button-release-event.
84  CHROMEGTK_CALLBACK_1(BookmarkMenuController, gboolean, OnFolderButtonPressed,
85                       GdkEventButton*);
86
87  // We have to stop drawing |triggering_widget_| as active when the menu
88  // closes.
89  CHROMEGTK_CALLBACK_0(BookmarkMenuController, void, OnMenuHidden)
90
91  // We respond to the activate signal because things other than mouse button
92  // events can trigger it.
93  CHROMEGTK_CALLBACK_0(BookmarkMenuController, void, OnMenuItemActivated);
94
95  // The individual GtkMenuItems in the BookmarkMenu are all drag sources.
96  CHROMEGTK_CALLBACK_1(BookmarkMenuController, void, OnMenuItemDragBegin,
97                       GdkDragContext*);
98  CHROMEGTK_CALLBACK_1(BookmarkMenuController, void, OnMenuItemDragEnd,
99                       GdkDragContext*);
100  CHROMEGTK_CALLBACK_4(BookmarkMenuController, void, OnMenuItemDragGet,
101                       GdkDragContext*, GtkSelectionData*, guint, guint);
102
103  Browser* browser_;
104  Profile* profile_;
105  PageNavigator* page_navigator_;
106
107  // Parent window of this menu.
108  GtkWindow* parent_window_;
109
110  // The bookmark model.
111  BookmarkModel* model_;
112
113  // The node we're showing the contents of.
114  const BookmarkNode* node_;
115
116  // Our bookmark menus. We don't use the MenuGtk class because we have to do
117  // all sorts of weird non-standard things with this menu, like:
118  // - The menu is a drag target
119  // - The menu items have context menus.
120  GtkWidget* menu_;
121
122  // The visual representation that follows the cursor during drags.
123  GtkWidget* drag_icon_;
124
125  // Whether we should ignore the next button release event (because we were
126  // dragging).
127  bool ignore_button_release_;
128
129  // The widget we are showing for (i.e. the bookmark bar folder button).
130  GtkWidget* triggering_widget_;
131
132  // Mapping from node to GtkMenuItem menu id. This only contains entries for
133  // nodes of type URL.
134  std::map<const BookmarkNode*, GtkWidget*> node_to_menu_widget_map_;
135
136  // The controller and view for the right click context menu.
137  scoped_ptr<BookmarkContextMenuController> context_menu_controller_;
138  scoped_ptr<MenuGtk> context_menu_;
139
140  ui::GtkSignalRegistrar signals_;
141
142  DISALLOW_COPY_AND_ASSIGN(BookmarkMenuController);
143};
144
145#endif  // CHROME_BROWSER_UI_GTK_BOOKMARKS_BOOKMARK_MENU_CONTROLLER_GTK_H_
146