- add sources.
[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
212   // Invoked when the bookmark model has finished loading. Creates a button
213   // for each of the children of the root node from the model.
214   virtual void Loaded(BookmarkModel* model, bool ids_reassigned) OVERRIDE;
215
216   // Invoked when the model is being deleted.
217   virtual void BookmarkModelBeingDeleted(BookmarkModel* model) OVERRIDE;
218
219   // Invoked when a node has moved.
220   virtual void BookmarkNodeMoved(BookmarkModel* model,
221                                  const BookmarkNode* old_parent,
222                                  int old_index,
223                                  const BookmarkNode* new_parent,
224                                  int new_index) OVERRIDE;
225   virtual void BookmarkNodeAdded(BookmarkModel* model,
226                                  const BookmarkNode* parent,
227                                  int index) OVERRIDE;
228   virtual void BookmarkNodeRemoved(BookmarkModel* model,
229                                    const BookmarkNode* parent,
230                                    int old_index,
231                                    const BookmarkNode* node) OVERRIDE;
232   virtual void BookmarkAllNodesRemoved(BookmarkModel* model) OVERRIDE;
233   virtual void BookmarkNodeChanged(BookmarkModel* model,
234                                    const BookmarkNode* node) OVERRIDE;
235   // Invoked when a favicon has finished loading.
236   virtual void BookmarkNodeFaviconChanged(BookmarkModel* model,
237                                           const BookmarkNode* node) OVERRIDE;
238   virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
239                                              const BookmarkNode* node) OVERRIDE;
240
241   // Overridden from content::NotificationObserver:
242   virtual void Observe(int type,
243                        const content::NotificationSource& source,
244                        const content::NotificationDetails& details) OVERRIDE;
245
246   GtkWidget* CreateBookmarkButton(const BookmarkNode* node);
247   GtkToolItem* CreateBookmarkToolItem(const BookmarkNode* node);
248
249   void ConnectFolderButtonEvents(GtkWidget* widget, bool is_tool_item);
250
251   // Finds the BookmarkNode from the model associated with |button|.
252   const BookmarkNode* GetNodeForToolButton(GtkWidget* button);
253
254   // Creates and displays a popup menu for BookmarkNode |node|.
255   void PopupMenuForNode(GtkWidget* sender, const BookmarkNode* node,
256                         GdkEventButton* event);
257
258   // GtkButton callbacks.
259   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnButtonPressed,
260                        GdkEventButton*);
261   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnClicked);
262   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragBegin,
263                        GdkDragContext*);
264   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragEnd, GdkDragContext*);
265   CHROMEGTK_CALLBACK_4(BookmarkBarGtk, void, OnButtonDragGet,
266                        GdkDragContext*, GtkSelectionData*, guint, guint);
267
268   // GtkButton callbacks for folder buttons.
269   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnFolderClicked);
270
271   // GtkButton callback for apps button.
272   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnAppsButtonClicked);
273
274   // GtkToolbar callbacks.
275   CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnToolbarDragMotion,
276                        GdkDragContext*, gint, gint, guint);
277   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnToolbarSizeAllocate,
278                        GtkAllocation*);
279
280   // Used for both folder buttons and the toolbar.
281   CHROMEGTK_CALLBACK_6(BookmarkBarGtk, void, OnDragReceived,
282                        GdkDragContext*, gint, gint, GtkSelectionData*,
283                        guint, guint);
284   CHROMEGTK_CALLBACK_2(BookmarkBarGtk, void, OnDragLeave,
285                        GdkDragContext*, guint);
286
287   // Used for folder buttons.
288   CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnFolderDragMotion,
289                        GdkDragContext*, gint, gint, guint);
290
291   // GtkEventBox callbacks.
292   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnEventBoxExpose,
293                        GdkEventExpose*);
294   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnEventBoxDestroy);
295
296   // Callbacks on our parent widget.
297   CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnParentSizeAllocate,
298                        GtkAllocation*);
299
300   // |throbbing_widget_| callback.
301   CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnThrobbingWidgetDestroy);
302
303   // Overriden from BookmarkBarInstructionsDelegate:
304   virtual void ShowImportDialog() OVERRIDE;
305
306   // Updates the visibility of the apps shortcut button |apps_shortcut_visible_|
307   // changes.
308   void OnAppsPageShortcutVisibilityChanged();
309
310   // Updates the drag&drop state when |edit_bookmarks_enabled_| changes.
311   void OnEditBookmarksEnabledChanged();
312
313   // Used for opening urls.
314   content::PageNavigator* page_navigator_;
315
316   Browser* browser_;
317   BrowserWindowGtk* window_;
318
319   // Provides us with the offset into the background theme image.
320   TabstripOriginProvider* tabstrip_origin_provider_;
321
322   // Model providing details as to the starred entries/folders that should be
323   // shown. This is owned by the Profile.
324   BookmarkModel* model_;
325
326   // Contains |bookmark_hbox_|. Event box exists to prevent leakage of
327   // background color from the toplevel application window's GDK window.
328   ui::OwnedWidgetGtk event_box_;
329
330   // Used to detached the bookmark bar when on the NTP.
331   GtkWidget* ntp_padding_box_;
332
333   // Used to paint the background of the bookmark bar when in detached mode.
334   GtkWidget* paint_box_;
335
336   // Used to position all children.
337   GtkWidget* bookmark_hbox_;
338
339   // Alignment widget that is visible if there are no bookmarks on
340   // the bookmar bar.
341   GtkWidget* instructions_;
342
343   // BookmarkBarInstructionsGtk that holds the label and the link for importing
344   // bookmarks when there are no bookmarks on the bookmark bar.
345   scoped_ptr<BookmarkBarInstructionsGtk> instructions_gtk_;
346
347   // The apps page shortcut button.
348   GtkWidget* apps_shortcut_button_;
349
350   // GtkToolbar which contains all the bookmark buttons.
351   ui::OwnedWidgetGtk bookmark_toolbar_;
352
353   // The button that shows extra bookmarks that don't fit on the bookmark
354   // bar.
355   GtkWidget* overflow_button_;
356
357   // A separator between the main bookmark bar area and
358   // |other_bookmarks_button_|.
359   GtkWidget* other_bookmarks_separator_;
360
361   // The other bookmarks button.
362   GtkWidget* other_bookmarks_button_;
363
364   // Padding for the other bookmarks button.
365   GtkWidget* other_padding_;
366
367   // The BookmarkNode from the model being dragged. NULL when we aren't
368   // dragging.
369   const BookmarkNode* dragged_node_;
370
371   // The visual representation that follows the cursor during drags.
372   GtkWidget* drag_icon_;
373
374   // We create a GtkToolbarItem from |dragged_node_| ;or display.
375   GtkToolItem* toolbar_drop_item_;
376
377   // Theme provider for building buttons.
378   GtkThemeService* theme_service_;
379
380   // Whether we should show the instructional text in the bookmark bar.
381   bool show_instructions_;
382
383   MenuBarHelper menu_bar_helper_;
384
385   // The last displayed right click menu, or NULL if no menus have been
386   // displayed yet.
387   // The controller.
388   scoped_ptr<BookmarkContextMenuController> current_context_menu_controller_;
389   // The view.
390   scoped_ptr<MenuGtk> current_context_menu_;
391
392   // The last displayed left click menu, or NULL if no menus have been
393   // displayed yet.
394   scoped_ptr<BookmarkMenuController> current_menu_;
395
396   gfx::SlideAnimation slide_animation_;
397
398   // Used to optimize out |bookmark_toolbar_| size-allocate events we don't
399   // need to respond to.
400   int last_allocation_width_;
401
402   content::NotificationRegistrar registrar_;
403
404   // The size of the web contents last time we forced a paint. We keep track
405   // of this so we don't force too many paints.
406   gfx::Size last_web_contents_size_;
407
408   // The last coordinates recorded by OnButtonPress; used to line up the
409   // drag icon during bookmark drags.
410   gfx::Point last_pressed_coordinates_;
411
412   // The currently throbbing widget. This is NULL if no widget is throbbing.
413   // We track it because we only want to allow one widget to throb at a time.
414   GtkWidget* throbbing_widget_;
415
416   // Tracks whether the apps shortcut button should be shown.
417   BooleanPrefMember apps_shortcut_visible_;
418
419   // Tracks whether bookmarks can be modified.
420   BooleanPrefMember edit_bookmarks_enabled_;
421
422   BookmarkBar::State bookmark_bar_state_;
423
424   // Maximum height of the bookmark bar.
425   int max_height_;
426
427   base::WeakPtrFactory<BookmarkBarGtk> weak_factory_;
428
429   DISALLOW_COPY_AND_ASSIGN(BookmarkBarGtk);
430 };
431
432 #endif  // CHROME_BROWSER_UI_GTK_BOOKMARKS_BOOKMARK_BAR_GTK_H_