Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / bookmarks / bookmark_bar_gtk.h
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_BOOKMARKS_BOOKMARK_BAR_GTK_H_
6 #define CHROME_BROWSER_UI_GTK_BOOKMARKS_BOOKMARK_BAR_GTK_H_
7
8 #include <gtk/gtk.h>
9
10 #include <vector>
11
12 #include "base/compiler_specific.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/prefs/pref_member.h"
17 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
18 #include "chrome/browser/bookmarks/bookmark_stats.h"
19 #include "chrome/browser/ui/bookmarks/bookmark_bar.h"
20 #include "chrome/browser/ui/bookmarks/bookmark_bar_instructions_delegate.h"
21 #include "chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h"
22 #include "chrome/browser/ui/gtk/menu_bar_helper.h"
23 #include "content/public/browser/notification_observer.h"
24 #include "content/public/browser/notification_registrar.h"
25 #include "ui/base/gtk/gtk_signal.h"
26 #include "ui/base/gtk/owned_widget_gtk.h"
27 #include "ui/gfx/animation/animation.h"
28 #include "ui/gfx/animation/animation_delegate.h"
29 #include "ui/gfx/animation/slide_animation.h"
30 #include "ui/gfx/point.h"
31 #include "ui/gfx/size.h"
32
33 class BookmarkBarInstructionsGtk;
34 class BookmarkMenuController;
35 class Browser;
36 class BrowserWindowGtk;
37 class GtkThemeService;
38 class MenuGtk;
39 class TabstripOriginProvider;
40
41 namespace content {
42 class PageNavigator;
43 }
44
45 class BookmarkBarGtk : public gfx::AnimationDelegate,
46                        public BookmarkModelObserver,
47                        public MenuBarHelper::Delegate,
48                        public content::NotificationObserver,
49                        public BookmarkBarInstructionsDelegate,
50                        public BookmarkContextMenuControllerDelegate {
51  public:
52   BookmarkBarGtk(BrowserWindowGtk* window,
53                  Browser* browser,
54                  TabstripOriginProvider* tabstrip_origin_provider);
55   virtual ~BookmarkBarGtk();
56
57   // Returns the current browser.
58   Browser* browser() const { return browser_; }
59
60   // Returns the top level widget.
61   GtkWidget* widget() const { return event_box_.get(); }
62
63   // Sets the PageNavigator that is used when the user selects an entry on
64   // the bookmark bar.
65   void SetPageNavigator(content::PageNavigator* navigator);
66
67   // Create the contents of the bookmark bar.
68   void Init();
69
70   // Changes the state of the bookmark bar.
71   void SetBookmarkBarState(BookmarkBar::State state,
72                            BookmarkBar::AnimateChangeType animate_type);
73
74   // Get the current height of the bookmark bar.
75   int GetHeight();
76
77   // Returns true if the bookmark bar is showing an animation.
78   bool IsAnimating();
79
80   // gfx::AnimationDelegate implementation -------------------------------------
81   virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
82   virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
83
84   // MenuBarHelper::Delegate implementation ------------------------------------
85   virtual void PopupForButton(GtkWidget* button) OVERRIDE;
86   virtual void PopupForButtonNextTo(GtkWidget* button,
87                                     GtkMenuDirectionType dir) OVERRIDE;
88
89   // BookmarkContextMenuController::Delegate implementation --------------------
90   virtual void CloseMenu() OVERRIDE;
91
92   const gfx::Animation* animation() { return &slide_animation_; }
93
94   int max_height() const { return max_height_; }
95
96  private:
97   FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, DisplaysHelpMessageOnEmpty);
98   FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest,
99                            HidesHelpMessageWithBookmark);
100   FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, BuildsButtons);
101
102   // Change the visibility of the bookmarks bar. (Starts out hidden, per GTK's
103   // default behaviour). There are three visiblity states:
104   //
105   //   Showing    - bookmark bar is fully visible.
106   //   Hidden     - bookmark bar is hidden except for a few pixels that give
107   //                extra padding to the bottom of the toolbar. Buttons are not
108   //                clickable.
109   //   Fullscreen - bookmark bar is fully hidden.
110   void Show(BookmarkBar::State old_state,
111             BookmarkBar::AnimateChangeType animate_type);
112   void Hide(BookmarkBar::State old_state,
113             BookmarkBar::AnimateChangeType animate_type);
114
115   // Calculate maximum height of bookmark bar.
116   void CalculateMaxHeight();
117
118   // Helper function which generates GtkToolItems for |bookmark_toolbar_|.
119   void CreateAllBookmarkButtons();
120
121   // Sets the visibility of the instructional text based on whether there are
122   // any bookmarks in the bookmark bar node.
123   void SetInstructionState();
124
125   // Sets the visibility of the overflow chevron.
126   void SetChevronState();
127
128   // Shows or hides the other bookmarks button depending on whether there are
129   // bookmarks in it.
130   void UpdateOtherBookmarksVisibility();
131
132   // Destroys all the bookmark buttons in the GtkToolbar.
133   void RemoveAllButtons();
134
135   // Adds the "other bookmarks" and overflow buttons.
136   void AddCoreButtons();
137
138   // Removes and recreates all buttons in the bar.
139   void ResetButtons();
140
141   // Returns the number of buttons corresponding to starred urls/folders. This
142   // is equivalent to the number of children the bookmark bar node from the
143   // bookmark bar model has.
144   int GetBookmarkButtonCount();
145
146   // Returns BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR or
147   // BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR based on detached state.
148   BookmarkLaunchLocation GetBookmarkLaunchLocation() const;
149
150   // Set the appearance of the overflow button appropriately (either chromium
151   // style or GTK style).
152   void SetOverflowButtonAppearance();
153
154   // Returns the index of the first bookmark that is not visible on the bar.
155   // Returns -1 if they are all visible.
156   // |extra_space| is how much extra space to give the toolbar during the
157   // calculation (for the purposes of determining if ditching the chevron
158   // would be a good idea).
159   // If non-NULL, |showing_folders| will be packed with all the folders that are
160   // showing on the bar.
161   int GetFirstHiddenBookmark(int extra_space,
162                              std::vector<GtkWidget*>* showing_folders);
163
164   // Update the detached state (either enable or disable it, or do nothing).
165   void UpdateDetachedState(BookmarkBar::State old_state);
166
167   // Turns on or off the app_paintable flag on |event_box_|, depending on our
168   // state.
169   void UpdateEventBoxPaintability();
170
171   // Queue a paint on the event box.
172   void PaintEventBox();
173
174   // Finds the size of the current web contents, if it exists and sets |size|
175   // to the correct value. Returns false if there isn't a WebContents, a
176   // condition that can happen during testing.
177   bool GetWebContentsSize(gfx::Size* size);
178
179   // Connects to the "size-allocate" signal on the given widget, and causes it
180   // to throb after allocation. This is called when a new item is added to the
181   // bar. We can't call StartThrobbing directly because we don't know if it's
182   // visible or not until after the widget is allocated.
183   void StartThrobbingAfterAllocation(GtkWidget* item);
184
185   // Used by StartThrobbingAfterAllocation.
186   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnItemAllocate, GtkAllocation*);
187
188   // Makes the appropriate widget on the bookmark bar stop throbbing
189   // (a folder, the overflow chevron, or nothing).
190   void StartThrobbing(const BookmarkNode* node);
191
192   // Set |throbbing_widget_| to |widget|. Also makes sure that
193   // |throbbing_widget_| doesn't become stale.
194   void SetThrobbingWidget(GtkWidget* widget);
195
196   // An item has been dragged over the toolbar, update the drag context
197   // and toolbar UI appropriately.
198   gboolean ItemDraggedOverToolbar(
199       GdkDragContext* context, int index, guint time);
200
201   // When dragging in the middle of a folder, assume the user wants to drop
202   // on the folder. Towards the edges, assume the user wants to drop on the
203   // toolbar. This makes it possible to drop between two folders. This function
204   // returns the index on the toolbar the drag should target, or -1 if the
205   // drag should hit the folder.
206   int GetToolbarIndexForDragOverFolder(GtkWidget* button, gint x);
207
208   void ClearToolbarDropHighlighting();
209
210   // Overridden from BookmarkModelObserver:
211   virtual void BookmarkModelLoaded(BookmarkModel* model,
212                                    bool ids_reassigned) OVERRIDE;
213   virtual void BookmarkModelBeingDeleted(BookmarkModel* model) OVERRIDE;
214   virtual void BookmarkNodeMoved(BookmarkModel* model,
215                                  const BookmarkNode* old_parent,
216                                  int old_index,
217                                  const BookmarkNode* new_parent,
218                                  int new_index) OVERRIDE;
219   virtual void BookmarkNodeAdded(BookmarkModel* model,
220                                  const BookmarkNode* parent,
221                                  int index) OVERRIDE;
222   virtual void BookmarkNodeRemoved(BookmarkModel* model,
223                                    const BookmarkNode* parent,
224                                    int old_index,
225                                    const BookmarkNode* node) OVERRIDE;
226   virtual void BookmarkAllNodesRemoved(BookmarkModel* model) OVERRIDE;
227   virtual void BookmarkNodeChanged(BookmarkModel* model,
228                                    const BookmarkNode* node) OVERRIDE;
229   virtual void BookmarkNodeFaviconChanged(BookmarkModel* model,
230                                           const BookmarkNode* node) OVERRIDE;
231   virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
232                                              const BookmarkNode* node) OVERRIDE;
233
234   // Overridden from content::NotificationObserver:
235   virtual void Observe(int type,
236                        const content::NotificationSource& source,
237                        const content::NotificationDetails& details) OVERRIDE;
238
239   GtkWidget* CreateBookmarkButton(const BookmarkNode* node);
240   GtkToolItem* CreateBookmarkToolItem(const BookmarkNode* node);
241
242   void ConnectFolderButtonEvents(GtkWidget* widget, bool is_tool_item);
243
244   // Finds the BookmarkNode from the model associated with |button|.
245   const BookmarkNode* GetNodeForToolButton(GtkWidget* button);
246
247   // Creates and displays a popup menu for BookmarkNode |node|.
248   void PopupMenuForNode(GtkWidget* sender, const BookmarkNode* node,
249                         GdkEventButton* event);
250
251   // GtkButton callbacks.
252   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnButtonPressed,
253                        GdkEventButton*);
254   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnClicked);
255   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragBegin,
256                        GdkDragContext*);
257   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragEnd, GdkDragContext*);
258   CHROMEGTK_CALLBACK_4(BookmarkBarGtk, void, OnButtonDragGet,
259                        GdkDragContext*, GtkSelectionData*, guint, guint);
260
261   // GtkButton callbacks for folder buttons.
262   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnFolderClicked);
263
264   // GtkButton callback for apps button.
265   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnAppsButtonClicked);
266
267   // GtkToolbar callbacks.
268   CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnToolbarDragMotion,
269                        GdkDragContext*, gint, gint, guint);
270   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnToolbarSizeAllocate,
271                        GtkAllocation*);
272
273   // Used for both folder buttons and the toolbar.
274   CHROMEGTK_CALLBACK_6(BookmarkBarGtk, void, OnDragReceived,
275                        GdkDragContext*, gint, gint, GtkSelectionData*,
276                        guint, guint);
277   CHROMEGTK_CALLBACK_2(BookmarkBarGtk, void, OnDragLeave,
278                        GdkDragContext*, guint);
279
280   // Used for folder buttons.
281   CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnFolderDragMotion,
282                        GdkDragContext*, gint, gint, guint);
283
284   // GtkEventBox callbacks.
285   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnEventBoxExpose,
286                        GdkEventExpose*);
287   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnEventBoxDestroy);
288
289   // Callbacks on our parent widget.
290   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnParentSizeAllocate,
291                        GtkAllocation*);
292
293   // |throbbing_widget_| callback.
294   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnThrobbingWidgetDestroy);
295
296   // Overriden from BookmarkBarInstructionsDelegate:
297   virtual void ShowImportDialog() OVERRIDE;
298
299   // Updates the visibility of the apps shortcut button |apps_shortcut_visible_|
300   // changes.
301   void OnAppsPageShortcutVisibilityChanged();
302
303   // Updates the drag&drop state when |edit_bookmarks_enabled_| changes.
304   void OnEditBookmarksEnabledChanged();
305
306   // Used for opening urls.
307   content::PageNavigator* page_navigator_;
308
309   Browser* browser_;
310   BrowserWindowGtk* window_;
311
312   // Provides us with the offset into the background theme image.
313   TabstripOriginProvider* tabstrip_origin_provider_;
314
315   // Model providing details as to the starred entries/folders that should be
316   // shown. This is owned by the Profile.
317   BookmarkModel* model_;
318
319   // Contains |bookmark_hbox_|. Event box exists to prevent leakage of
320   // background color from the toplevel application window's GDK window.
321   ui::OwnedWidgetGtk event_box_;
322
323   // Used to detached the bookmark bar when on the NTP.
324   GtkWidget* ntp_padding_box_;
325
326   // Used to paint the background of the bookmark bar when in detached mode.
327   GtkWidget* paint_box_;
328
329   // Used to position all children.
330   GtkWidget* bookmark_hbox_;
331
332   // Alignment widget that is visible if there are no bookmarks on
333   // the bookmar bar.
334   GtkWidget* instructions_;
335
336   // BookmarkBarInstructionsGtk that holds the label and the link for importing
337   // bookmarks when there are no bookmarks on the bookmark bar.
338   scoped_ptr<BookmarkBarInstructionsGtk> instructions_gtk_;
339
340   // The apps page shortcut button.
341   GtkWidget* apps_shortcut_button_;
342
343   // GtkToolbar which contains all the bookmark buttons.
344   ui::OwnedWidgetGtk bookmark_toolbar_;
345
346   // The button that shows extra bookmarks that don't fit on the bookmark
347   // bar.
348   GtkWidget* overflow_button_;
349
350   // A separator between the main bookmark bar area and
351   // |other_bookmarks_button_|.
352   GtkWidget* other_bookmarks_separator_;
353
354   // The other bookmarks button.
355   GtkWidget* other_bookmarks_button_;
356
357   // Padding for the other bookmarks button.
358   GtkWidget* other_padding_;
359
360   // The BookmarkNode from the model being dragged. NULL when we aren't
361   // dragging.
362   const BookmarkNode* dragged_node_;
363
364   // The visual representation that follows the cursor during drags.
365   GtkWidget* drag_icon_;
366
367   // We create a GtkToolbarItem from |dragged_node_| ;or display.
368   GtkToolItem* toolbar_drop_item_;
369
370   // Theme provider for building buttons.
371   GtkThemeService* theme_service_;
372
373   // Whether we should show the instructional text in the bookmark bar.
374   bool show_instructions_;
375
376   MenuBarHelper menu_bar_helper_;
377
378   // The last displayed right click menu, or NULL if no menus have been
379   // displayed yet.
380   // The controller.
381   scoped_ptr<BookmarkContextMenuController> current_context_menu_controller_;
382   // The view.
383   scoped_ptr<MenuGtk> current_context_menu_;
384
385   // The last displayed left click menu, or NULL if no menus have been
386   // displayed yet.
387   scoped_ptr<BookmarkMenuController> current_menu_;
388
389   gfx::SlideAnimation slide_animation_;
390
391   // Used to optimize out |bookmark_toolbar_| size-allocate events we don't
392   // need to respond to.
393   int last_allocation_width_;
394
395   content::NotificationRegistrar registrar_;
396
397   // The size of the web contents last time we forced a paint. We keep track
398   // of this so we don't force too many paints.
399   gfx::Size last_web_contents_size_;
400
401   // The last coordinates recorded by OnButtonPress; used to line up the
402   // drag icon during bookmark drags.
403   gfx::Point last_pressed_coordinates_;
404
405   // The currently throbbing widget. This is NULL if no widget is throbbing.
406   // We track it because we only want to allow one widget to throb at a time.
407   GtkWidget* throbbing_widget_;
408
409   // Tracks whether the apps shortcut button should be shown.
410   BooleanPrefMember apps_shortcut_visible_;
411
412   // Tracks whether bookmarks can be modified.
413   BooleanPrefMember edit_bookmarks_enabled_;
414
415   BookmarkBar::State bookmark_bar_state_;
416
417   // Maximum height of the bookmark bar.
418   int max_height_;
419
420   base::WeakPtrFactory<BookmarkBarGtk> weak_factory_;
421
422   DISALLOW_COPY_AND_ASSIGN(BookmarkBarGtk);
423 };
424
425 #endif  // CHROME_BROWSER_UI_GTK_BOOKMARKS_BOOKMARK_BAR_GTK_H_