// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_UI_GTK_BOOKMARKS_BOOKMARK_BAR_GTK_H_ #define CHROME_BROWSER_UI_GTK_BOOKMARKS_BOOKMARK_BAR_GTK_H_ #pragma once #include <gtk/gtk.h> #include <vector> #include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/bookmarks/bookmark_context_menu_controller.h" #include "chrome/browser/bookmarks/bookmark_model_observer.h" #include "chrome/browser/prefs/pref_member.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/ui/gtk/bookmarks/bookmark_bar_instructions_gtk.h" #include "chrome/browser/ui/gtk/menu_bar_helper.h" #include "chrome/browser/ui/gtk/owned_widget_gtk.h" #include "chrome/browser/ui/gtk/view_id_util.h" #include "content/common/notification_observer.h" #include "content/common/notification_registrar.h" #include "ui/base/animation/animation.h" #include "ui/base/animation/animation_delegate.h" #include "ui/base/animation/slide_animation.h" #include "ui/base/gtk/gtk_signal.h" #include "ui/gfx/point.h" #include "ui/gfx/size.h" class BookmarkMenuController; class Browser; class BrowserWindowGtk; class CustomContainerButton; class GtkThemeService; class MenuGtk; class PageNavigator; class Profile; class TabstripOriginProvider; class BookmarkBarGtk : public ui::AnimationDelegate, public ProfileSyncServiceObserver, public BookmarkModelObserver, public MenuBarHelper::Delegate, public NotificationObserver, public BookmarkBarInstructionsGtk::Delegate, public BookmarkContextMenuControllerDelegate { public: BookmarkBarGtk(BrowserWindowGtk* window, Profile* profile, Browser* browser, TabstripOriginProvider* tabstrip_origin_provider); virtual ~BookmarkBarGtk(); // Resets the profile. This removes any buttons for the current profile and // recreates the models. void SetProfile(Profile* profile); // Returns the current profile. Profile* GetProfile() { return profile_; } // Returns the current browser. Browser* browser() const { return browser_; } // Returns the top level widget. GtkWidget* widget() const { return event_box_.get(); } // Sets the PageNavigator that is used when the user selects an entry on // the bookmark bar. void SetPageNavigator(PageNavigator* navigator); // Create the contents of the bookmark bar. void Init(Profile* profile); // Whether the current page is the New Tag Page (which requires different // rendering). bool OnNewTabPage(); // Change the visibility of the bookmarks bar. (Starts out hidden, per GTK's // default behaviour). There are three visiblity states: // // Showing - bookmark bar is fully visible. // Hidden - bookmark bar is hidden except for a few pixels that give // extra padding to the bottom of the toolbar. Buttons are not // clickable. // Fullscreen - bookmark bar is fully hidden. void Show(bool animate); void Hide(bool animate); void EnterFullscreen(); // Get the current height of the bookmark bar. int GetHeight(); // Returns true if the bookmark bar is showing an animation. bool IsAnimating(); // Returns true if the bookmarks bar preference is set to 'always show'. bool IsAlwaysShown(); // ui::AnimationDelegate implementation -------------------------------------- virtual void AnimationProgressed(const ui::Animation* animation); virtual void AnimationEnded(const ui::Animation* animation); // MenuBarHelper::Delegate implementation ------------------------------------ virtual void PopupForButton(GtkWidget* button); virtual void PopupForButtonNextTo(GtkWidget* button, GtkMenuDirectionType dir); // The NTP needs to have access to this. static const int kBookmarkBarNTPHeight; // BookmarkContextMenuController::Delegate implementation -------------------- virtual void CloseMenu(); const ui::Animation* animation() { return &slide_animation_; } private: FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, DisplaysHelpMessageOnEmpty); FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, HidesHelpMessageWithBookmark); FRIEND_TEST_ALL_PREFIXES(BookmarkBarGtkUnittest, BuildsButtons); // Helper function which generates GtkToolItems for |bookmark_toolbar_|. void CreateAllBookmarkButtons(); // Sets the visibility of the instructional text based on whether there are // any bookmarks in the bookmark bar node. void SetInstructionState(); // Sets the visibility of the overflow chevron. void SetChevronState(); // Helper function which destroys all the bookmark buttons in the GtkToolbar. void RemoveAllBookmarkButtons(); // Returns the number of buttons corresponding to starred urls/folders. This // is equivalent to the number of children the bookmark bar node from the // bookmark bar model has. int GetBookmarkButtonCount(); // Set the appearance of the overflow button appropriately (either chromium // style or GTK style). void SetOverflowButtonAppearance(); // Returns the index of the first bookmark that is not visible on the bar. // Returns -1 if they are all visible. // |extra_space| is how much extra space to give the toolbar during the // calculation (for the purposes of determining if ditching the chevron // would be a good idea). // If non-NULL, |showing_folders| will be packed with all the folders that are // showing on the bar. int GetFirstHiddenBookmark(int extra_space, std::vector<GtkWidget*>* showing_folders); // Returns true if the bookmark bar should be floating on the page (for // NTP). bool ShouldBeFloating(); // Update the floating state (either enable or disable it, or do nothing). void UpdateFloatingState(); // Turns on or off the app_paintable flag on |event_box_|, depending on our // state. void UpdateEventBoxPaintability(); // Queue a paint on the event box. void PaintEventBox(); // Finds the size of the current tab contents, if it exists and sets |size| // to the correct value. Returns false if there isn't a TabContents, a // condition that can happen during testing. bool GetTabContentsSize(gfx::Size* size); // Connects to the "size-allocate" signal on the given widget, and causes it // to throb after allocation. This is called when a new item is added to the // bar. We can't call StartThrobbing directly because we don't know if it's // visible or not until after the widget is allocated. void StartThrobbingAfterAllocation(GtkWidget* item); // Used by StartThrobbingAfterAllocation. CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnItemAllocate, GtkAllocation*); // Makes the appropriate widget on the bookmark bar stop throbbing // (a folder, the overflow chevron, or nothing). void StartThrobbing(const BookmarkNode* node); // Set |throbbing_widget_| to |widget|. Also makes sure that // |throbbing_widget_| doesn't become stale. void SetThrobbingWidget(GtkWidget* widget); // An item has been dragged over the toolbar, update the drag context // and toolbar UI appropriately. gboolean ItemDraggedOverToolbar( GdkDragContext* context, int index, guint time); // When dragging in the middle of a folder, assume the user wants to drop // on the folder. Towards the edges, assume the user wants to drop on the // toolbar. This makes it possible to drop between two folders. This function // returns the index on the toolbar the drag should target, or -1 if the // drag should hit the folder. int GetToolbarIndexForDragOverFolder(GtkWidget* button, gint x); void ClearToolbarDropHighlighting(); // Overridden from BookmarkModelObserver: // Invoked when the bookmark model has finished loading. Creates a button // for each of the children of the root node from the model. virtual void Loaded(BookmarkModel* model); // Invoked when the model is being deleted. virtual void BookmarkModelBeingDeleted(BookmarkModel* model); // Invoked when a node has moved. virtual void BookmarkNodeMoved(BookmarkModel* model, const BookmarkNode* old_parent, int old_index, const BookmarkNode* new_parent, int new_index); virtual void BookmarkNodeAdded(BookmarkModel* model, const BookmarkNode* parent, int index); virtual void BookmarkNodeRemoved(BookmarkModel* model, const BookmarkNode* parent, int old_index, const BookmarkNode* node); virtual void BookmarkNodeChanged(BookmarkModel* model, const BookmarkNode* node); // Invoked when a favicon has finished loading. virtual void BookmarkNodeFaviconLoaded(BookmarkModel* model, const BookmarkNode* node); virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, const BookmarkNode* node); // Overridden from NotificationObserver: virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); GtkWidget* CreateBookmarkButton(const BookmarkNode* node); GtkToolItem* CreateBookmarkToolItem(const BookmarkNode* node); void ConnectFolderButtonEvents(GtkWidget* widget, bool is_tool_item); // Finds the BookmarkNode from the model associated with |button|. const BookmarkNode* GetNodeForToolButton(GtkWidget* button); // Creates and displays a popup menu for BookmarkNode |node|. void PopupMenuForNode(GtkWidget* sender, const BookmarkNode* node, GdkEventButton* event); // GtkButton callbacks. CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnButtonPressed, GdkEventButton*); CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnSyncErrorButtonPressed, GdkEventButton*); CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnClicked); CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragBegin, GdkDragContext*); CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnButtonDragEnd, GdkDragContext*); CHROMEGTK_CALLBACK_4(BookmarkBarGtk, void, OnButtonDragGet, GdkDragContext*, GtkSelectionData*, guint, guint); // GtkButton callbacks for folder buttons. CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnFolderClicked); // GtkToolbar callbacks. CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnToolbarDragMotion, GdkDragContext*, gint, gint, guint); CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnToolbarSizeAllocate, GtkAllocation*); // Used for both folder buttons and the toolbar. CHROMEGTK_CALLBACK_6(BookmarkBarGtk, void, OnDragReceived, GdkDragContext*, gint, gint, GtkSelectionData*, guint, guint); CHROMEGTK_CALLBACK_2(BookmarkBarGtk, void, OnDragLeave, GdkDragContext*, guint); // Used for folder buttons. CHROMEGTK_CALLBACK_4(BookmarkBarGtk, gboolean, OnFolderDragMotion, GdkDragContext*, gint, gint, guint); // GtkEventBox callbacks. CHROMEGTK_CALLBACK_1(BookmarkBarGtk, gboolean, OnEventBoxExpose, GdkEventExpose*); CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnEventBoxDestroy); // Callbacks on our parent widget. CHROMEGTK_CALLBACK_1(BookmarkBarGtk, void, OnParentSizeAllocate, GtkAllocation*); // |throbbing_widget_| callback. CHROMEGTK_CALLBACK_0(BookmarkBarGtk, void, OnThrobbingWidgetDestroy); // ProfileSyncServiceObserver method. virtual void OnStateChanged(); // Overriden from BookmarkBarInstructionsGtk::Delegate. virtual void ShowImportDialog(); // Updates the drag&drop state when |edit_bookmarks_enabled_| changes. void OnEditBookmarksEnabledChanged(); Profile* profile_; // Used for opening urls. PageNavigator* page_navigator_; Browser* browser_; BrowserWindowGtk* window_; // Provides us with the offset into the background theme image. TabstripOriginProvider* tabstrip_origin_provider_; // Model providing details as to the starred entries/folders that should be // shown. This is owned by the Profile. BookmarkModel* model_; // Contains |bookmark_hbox_|. Event box exists to prevent leakage of // background color from the toplevel application window's GDK window. OwnedWidgetGtk event_box_; // Used to float the bookmark bar when on the NTP. GtkWidget* ntp_padding_box_; // Used to paint the background of the bookmark bar when in floating mode. GtkWidget* paint_box_; // Used to position all children. GtkWidget* bookmark_hbox_; // Alignment widget that is visible if there are no bookmarks on // the bookmar bar. GtkWidget* instructions_; // BookmarkBarInstructionsGtk that holds the label and the link for importing // bookmarks when there are no bookmarks on the bookmark bar. scoped_ptr<BookmarkBarInstructionsGtk> instructions_gtk_; // GtkToolbar which contains all the bookmark buttons. OwnedWidgetGtk bookmark_toolbar_; // The button that shows extra bookmarks that don't fit on the bookmark // bar. GtkWidget* overflow_button_; // The other bookmarks button. GtkWidget* other_bookmarks_button_; // The sync error button. GtkWidget* sync_error_button_; // A pointer to the ProfileSyncService instance if one exists. ProfileSyncService* sync_service_; // The BookmarkNode from the model being dragged. NULL when we aren't // dragging. const BookmarkNode* dragged_node_; // The visual representation that follows the cursor during drags. GtkWidget* drag_icon_; // We create a GtkToolbarItem from |dragged_node_| ;or display. GtkToolItem* toolbar_drop_item_; // Theme provider for building buttons. GtkThemeService* theme_service_; // Whether we should show the instructional text in the bookmark bar. bool show_instructions_; MenuBarHelper menu_bar_helper_; // The last displayed right click menu, or NULL if no menus have been // displayed yet. // The controller. scoped_ptr<BookmarkContextMenuController> current_context_menu_controller_; // The view. scoped_ptr<MenuGtk> current_context_menu_; // The last displayed left click menu, or NULL if no menus have been // displayed yet. scoped_ptr<BookmarkMenuController> current_menu_; ui::SlideAnimation slide_animation_; // Whether we are currently configured as floating (detached from the // toolbar). This reflects our actual state, and can be out of sync with // what ShouldShowFloating() returns. bool floating_; // Used to optimize out |bookmark_toolbar_| size-allocate events we don't // need to respond to. int last_allocation_width_; NotificationRegistrar registrar_; // The size of the tab contents last time we forced a paint. We keep track // of this so we don't force too many paints. gfx::Size last_tab_contents_size_; // The last coordinates recorded by OnButtonPress; used to line up the // drag icon during bookmark drags. gfx::Point last_pressed_coordinates_; // The currently throbbing widget. This is NULL if no widget is throbbing. // We track it because we only want to allow one widget to throb at a time. GtkWidget* throbbing_widget_; // Tracks whether bookmarks can be modified. BooleanPrefMember edit_bookmarks_enabled_; ScopedRunnableMethodFactory<BookmarkBarGtk> method_factory_; }; #endif // CHROME_BROWSER_UI_GTK_BOOKMARKS_BOOKMARK_BAR_GTK_H_