Home | History | Annotate | Download | only in bookmarks
      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_VIEWS_BOOKMARKS_BOOKMARK_BAR_VIEW_H_
      6 #define CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_BAR_VIEW_H_
      7 #pragma once
      8 
      9 #include <set>
     10 
     11 #include "base/compiler_specific.h"
     12 #include "chrome/browser/bookmarks/bookmark_model_observer.h"
     13 #include "chrome/browser/bookmarks/bookmark_node_data.h"
     14 #include "chrome/browser/sync/profile_sync_service.h"
     15 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.h"
     16 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h"
     17 #include "chrome/browser/ui/views/detachable_toolbar_view.h"
     18 #include "content/common/notification_registrar.h"
     19 #include "ui/base/animation/animation_delegate.h"
     20 #include "views/controls/button/button.h"
     21 #include "views/controls/menu/view_menu_delegate.h"
     22 
     23 class Browser;
     24 class PageNavigator;
     25 class PrefService;
     26 
     27 namespace ui {
     28 class SlideAnimation;
     29 }
     30 
     31 namespace views {
     32 class CustomButton;
     33 class MenuButton;
     34 class MenuItemView;
     35 class TextButton;
     36 }
     37 
     38 // BookmarkBarView renders the BookmarkModel.  Each starred entry on the
     39 // BookmarkBar is rendered as a MenuButton. An additional MenuButton aligned to
     40 // the right allows the user to quickly see recently starred entries.
     41 //
     42 // BookmarkBarView shows the bookmarks from a specific Profile. BookmarkBarView
     43 // waits until the HistoryService for the profile has been loaded before
     44 // creating the BookmarkModel.
     45 class BookmarkBarView : public DetachableToolbarView,
     46                         public ProfileSyncServiceObserver,
     47                         public BookmarkModelObserver,
     48                         public views::ViewMenuDelegate,
     49                         public views::ButtonListener,
     50                         public NotificationObserver,
     51                         public views::ContextMenuController,
     52                         public views::DragController,
     53                         public ui::AnimationDelegate,
     54                         public BookmarkMenuController::Observer,
     55                         public BookmarkBarInstructionsView::Delegate {
     56   friend class ShowFolderMenuTask;
     57 
     58  public:
     59   // Constants used in Browser View, as well as here.
     60   // How inset the bookmarks bar is when displayed on the new tab page.
     61   static const int kNewtabHorizontalPadding;
     62   static const int kNewtabVerticalPadding;
     63 
     64   // Maximum size of buttons on the bookmark bar.
     65   static const int kMaxButtonWidth;
     66 
     67   // Interface implemented by controllers/views that need to be notified any
     68   // time the model changes, typically to cancel an operation that is showing
     69   // data from the model such as a menu. This isn't intended as a general
     70   // way to be notified of changes, rather for cases where a controller/view is
     71   // showing data from the model in a modal like setting and needs to cleanly
     72   // exit the modal loop if the model changes out from under it.
     73   //
     74   // A controller/view that needs this notification should install itself as the
     75   // ModelChangeListener via the SetModelChangedListener method when shown and
     76   // reset the ModelChangeListener of the BookmarkBarView when it closes by way
     77   // of either the SetModelChangedListener method or the
     78   // ClearModelChangedListenerIfEquals method.
     79   class ModelChangedListener {
     80    public:
     81     virtual ~ModelChangedListener() {}
     82 
     83     // Invoked when the model changes. Should cancel the edit and close any
     84     // dialogs.
     85     virtual void ModelChanged() = 0;
     86   };
     87 
     88   static const int kNewtabBarHeight;
     89 
     90   BookmarkBarView(Profile* profile, Browser* browser);
     91   virtual ~BookmarkBarView();
     92 
     93   // Resets the profile. This removes any buttons for the current profile and
     94   // recreates the models.
     95   void SetProfile(Profile* profile);
     96 
     97   // Returns the current profile.
     98   Profile* GetProfile() { return profile_; }
     99 
    100   // Returns the current browser.
    101   Browser* browser() const { return browser_; }
    102 
    103   // Sets the PageNavigator that is used when the user selects an entry on
    104   // the bookmark bar.
    105   void SetPageNavigator(PageNavigator* navigator);
    106 
    107   // Sets whether the containing browser is showing an infobar.  This affects
    108   // layout during animation.
    109   void set_infobar_visible(bool infobar_visible) {
    110     infobar_visible_ = infobar_visible;
    111   }
    112 
    113   virtual bool IsOnTop() const;
    114 
    115   // DetachableToolbarView methods:
    116   virtual bool IsDetached() const OVERRIDE;
    117   virtual double GetAnimationValue() const OVERRIDE;
    118   virtual int GetToolbarOverlap() const OVERRIDE;
    119 
    120   // View methods:
    121   virtual gfx::Size GetPreferredSize() OVERRIDE;
    122   virtual gfx::Size GetMinimumSize() OVERRIDE;
    123   virtual void Layout() OVERRIDE;
    124   virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child)
    125       OVERRIDE;
    126   virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
    127   virtual bool GetDropFormats(
    128       int* formats,
    129       std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE;
    130   virtual bool AreDropTypesRequired() OVERRIDE;
    131   virtual bool CanDrop(const ui::OSExchangeData& data) OVERRIDE;
    132   virtual void OnDragEntered(const views::DropTargetEvent& event) OVERRIDE;
    133   virtual int OnDragUpdated(const views::DropTargetEvent& event) OVERRIDE;
    134   virtual void OnDragExited() OVERRIDE;
    135   virtual int OnPerformDrop(const views::DropTargetEvent& event) OVERRIDE;
    136   virtual void ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture)
    137       OVERRIDE;
    138 
    139   // AccessiblePaneView methods:
    140   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
    141 
    142   // ProfileSyncServiceObserver method.
    143   virtual void OnStateChanged();
    144 
    145   // Called when fullscreen mode toggles on or off; this affects our layout.
    146   void OnFullscreenToggled(bool fullscreen);
    147 
    148   // Sets the model change listener to listener.
    149   void SetModelChangedListener(ModelChangedListener* listener) {
    150     model_changed_listener_ = listener;
    151   }
    152 
    153   // If the ModelChangedListener is listener, ModelChangeListener is set to
    154   // NULL.
    155   void ClearModelChangedListenerIfEquals(ModelChangedListener* listener) {
    156     if (model_changed_listener_ == listener)
    157       model_changed_listener_ = NULL;
    158   }
    159 
    160   // Returns the model change listener.
    161   ModelChangedListener* GetModelChangedListener() {
    162     return model_changed_listener_;
    163   }
    164 
    165   // Returns the page navigator.
    166   PageNavigator* GetPageNavigator() { return page_navigator_; }
    167 
    168   // Returns the model.
    169   BookmarkModel* GetModel() { return model_; }
    170 
    171   // Returns true if the bookmarks bar preference is set to 'always show'.
    172   bool IsAlwaysShown() const;
    173 
    174   // True if we're on a page where the bookmarks bar is always visible.
    175   bool OnNewTabPage() const;
    176 
    177   // How much we want the bookmark bar to overlap the toolbar.  If |return_max|
    178   // is true, we return the maximum overlap rather than the current overlap.
    179   int GetToolbarOverlap(bool return_max) const;
    180 
    181   // Whether or not we are animating.
    182   bool is_animating();
    183 
    184   // SlideAnimationDelegate implementation.
    185   virtual void AnimationProgressed(const ui::Animation* animation);
    186   virtual void AnimationEnded(const ui::Animation* animation);
    187 
    188   // BookmarkMenuController::Observer
    189   virtual void BookmarkMenuDeleted(BookmarkMenuController* controller);
    190 
    191   // Returns the button at the specified index.
    192   views::TextButton* GetBookmarkButton(int index);
    193 
    194   // Returns the button responsible for showing bookmarks in the other bookmark
    195   // folder.
    196   views::MenuButton* other_bookmarked_button() const {
    197     return other_bookmarked_button_;
    198   }
    199 
    200   // Returns the active MenuItemView, or NULL if a menu isn't showing.
    201   views::MenuItemView* GetMenu();
    202 
    203   // Returns the drop MenuItemView, or NULL if a menu isn't showing.
    204   views::MenuItemView* GetDropMenu();
    205 
    206   // Returns the context menu, or null if one isn't showing.
    207   views::MenuItemView* GetContextMenu();
    208 
    209   // Returns the button used when not all the items on the bookmark bar fit.
    210   views::MenuButton* overflow_button() const { return overflow_button_; }
    211 
    212   // If |loc| is over a bookmark button the node is returned corresponding
    213   // to the button and |start_index| is set to 0. If a overflow button is
    214   // showing and |loc| is over the overflow button, the bookmark bar node is
    215   // returned and |start_index| is set to the index of the first node
    216   // contained in the overflow menu.
    217   const BookmarkNode* GetNodeForButtonAt(const gfx::Point& loc,
    218                                          int* start_index);
    219 
    220   // Returns the MenuButton for node.
    221   views::MenuButton* GetMenuButtonForNode(const BookmarkNode* node);
    222 
    223   // Returns the position to anchor the menu for |button| at, the index of the
    224   // first child of the node to build the menu from.
    225   void GetAnchorPositionAndStartIndexForButton(
    226       views::MenuButton* button,
    227       views::MenuItemView::AnchorPosition* anchor,
    228       int* start_index);
    229 
    230   // BookmarkBarInstructionsView::Delegate.
    231   virtual void ShowImportDialog();
    232 
    233   // If a button is currently throbbing, it is stopped. If immediate is true
    234   // the throb stops immediately, otherwise it stops after a couple more
    235   // throbs.
    236   void StopThrobbing(bool immediate);
    237 
    238   // Returns the number of buttons corresponding to starred urls/folders. This
    239   // is equivalent to the number of children the bookmark bar node from the
    240   // bookmark bar model has.
    241   int GetBookmarkButtonCount();
    242 
    243   // Returns the tooltip text for the specified url and title. The returned
    244   // text is clipped to fit within the bounds of the monitor.
    245   //
    246   // Note that we adjust the direction of both the URL and the title based on
    247   // the locale so that pure LTR strings are displayed properly in RTL locales.
    248   static std::wstring CreateToolTipForURLAndTitle(
    249       const gfx::Point& screen_loc,
    250       const GURL& url,
    251       const std::wstring& title,
    252       Profile* profile);
    253 
    254   // If true we're running tests. This short circuits a couple of animations.
    255   static bool testing_;
    256 
    257  private:
    258   class ButtonSeparatorView;
    259   struct DropInfo;
    260 
    261   // Task that invokes ShowDropFolderForNode when run. ShowFolderDropMenuTask
    262   // deletes itself once run.
    263   class ShowFolderDropMenuTask : public Task {
    264    public:
    265     ShowFolderDropMenuTask(BookmarkBarView* view, const BookmarkNode* node)
    266       : view_(view),
    267         node_(node) {
    268     }
    269 
    270     void Cancel() {
    271       view_->show_folder_drop_menu_task_ = NULL;
    272       view_ = NULL;
    273     }
    274 
    275     virtual void Run() {
    276       if (view_) {
    277         view_->show_folder_drop_menu_task_ = NULL;
    278         view_->ShowDropFolderForNode(node_);
    279       }
    280       // MessageLoop deletes us.
    281     }
    282 
    283    private:
    284     BookmarkBarView* view_;
    285     const BookmarkNode* node_;
    286 
    287     DISALLOW_COPY_AND_ASSIGN(ShowFolderDropMenuTask);
    288   };
    289 
    290   // Creates recent bookmark button and when visible button as well as
    291   // calculating the preferred height.
    292   void Init();
    293 
    294   // Creates the button showing the other bookmarked items.
    295   views::MenuButton* CreateOtherBookmarkedButton();
    296 
    297   // Creates the button used when not all bookmark buttons fit.
    298   views::MenuButton* CreateOverflowButton();
    299 
    300   // Invoked when the bookmark bar model has finished loading. Creates a button
    301   // for each of the children of the root node from the model.
    302   virtual void Loaded(BookmarkModel* model);
    303 
    304   // Invoked when the model is being deleted.
    305   virtual void BookmarkModelBeingDeleted(BookmarkModel* model);
    306 
    307   // Invokes added followed by removed.
    308   virtual void BookmarkNodeMoved(BookmarkModel* model,
    309                                  const BookmarkNode* old_parent,
    310                                  int old_index,
    311                                  const BookmarkNode* new_parent,
    312                                  int new_index);
    313 
    314   // Notifies ModelChangeListener of change.
    315   // If the node was added to the root node, a button is created and added to
    316   // this bookmark bar view.
    317   virtual void BookmarkNodeAdded(BookmarkModel* model,
    318                                  const BookmarkNode* parent,
    319                                  int index);
    320 
    321   // Implementation for BookmarkNodeAddedImpl.
    322   void BookmarkNodeAddedImpl(BookmarkModel* model,
    323                              const BookmarkNode* parent,
    324                              int index);
    325 
    326   // Notifies ModelChangeListener of change.
    327   // If the node was a child of the root node, the button corresponding to it
    328   // is removed.
    329   virtual void BookmarkNodeRemoved(BookmarkModel* model,
    330                                    const BookmarkNode* parent,
    331                                    int old_index,
    332                                    const BookmarkNode* node);
    333 
    334   // Implementation for BookmarkNodeRemoved.
    335   void BookmarkNodeRemovedImpl(BookmarkModel* model,
    336                                const BookmarkNode* parent,
    337                                int index);
    338 
    339   // Notifies ModelChangedListener and invokes BookmarkNodeChangedImpl.
    340   virtual void BookmarkNodeChanged(BookmarkModel* model,
    341                                    const BookmarkNode* node);
    342 
    343   // If the node is a child of the root node, the button is updated
    344   // appropriately.
    345   void BookmarkNodeChangedImpl(BookmarkModel* model, const BookmarkNode* node);
    346 
    347   virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
    348                                              const BookmarkNode* node);
    349 
    350   // Invoked when the favicon is available. If the node is a child of the
    351   // root node, the appropriate button is updated. If a menu is showing, the
    352   // call is forwarded to the menu to allow for it to update the icon.
    353   virtual void BookmarkNodeFaviconLoaded(BookmarkModel* model,
    354                                          const BookmarkNode* node);
    355 
    356   // DragController method. Determines the node representing sender and invokes
    357   // WriteDragData to write the actual data.
    358   virtual void WriteDragDataForView(views::View* sender,
    359                                     const gfx::Point& press_pt,
    360                                     ui::OSExchangeData* data) OVERRIDE;
    361 
    362   virtual int GetDragOperationsForView(views::View* sender,
    363                                        const gfx::Point& p) OVERRIDE;
    364 
    365   virtual bool CanStartDragForView(views::View* sender,
    366                                    const gfx::Point& press_pt,
    367                                    const gfx::Point& p) OVERRIDE;
    368 
    369   // Writes a BookmarkNodeData for node to data.
    370   void WriteBookmarkDragData(const BookmarkNode* node,
    371                              ui::OSExchangeData* data);
    372 
    373   // ViewMenuDelegate method. Ends up creating a BookmarkMenuController to
    374   // show the menu.
    375   virtual void RunMenu(views::View* view, const gfx::Point& pt);
    376 
    377   // Invoked when a star entry corresponding to a URL on the bookmark bar is
    378   // pressed. Forwards to the PageNavigator to open the URL.
    379   virtual void ButtonPressed(views::Button* sender, const views::Event& event);
    380 
    381   // Invoked for this View, one of the buttons or the 'other' button. Shows the
    382   // appropriate context menu.
    383   virtual void ShowContextMenuForView(views::View* source,
    384                                       const gfx::Point& p,
    385                                       bool is_mouse_gesture);
    386 
    387   // Creates the button for rendering the specified bookmark node.
    388   views::View* CreateBookmarkButton(const BookmarkNode* node);
    389 
    390   // COnfigures the button from the specified node. This sets the text,
    391   // and icon.
    392   void ConfigureButton(const BookmarkNode* node, views::TextButton* button);
    393 
    394   // Used when showing the menu allowing the user to choose when the bar is
    395   // visible. Return value corresponds to the users preference for when the
    396   // bar is visible.
    397   virtual bool IsItemChecked(int id) const;
    398 
    399   // Used when showing the menu allowing the user to choose when the bar is
    400   // visible. Updates the preferences to match the users choice as appropriate.
    401   virtual void ExecuteCommand(int id);
    402 
    403   // NotificationService method.
    404   virtual void Observe(NotificationType type,
    405                        const NotificationSource& source,
    406                        const NotificationDetails& details);
    407 
    408   // Overridden from views::View.
    409   virtual void OnThemeChanged();
    410 
    411   // If the ModelChangedListener is non-null, ModelChanged is invoked on it.
    412   void NotifyModelChanged();
    413 
    414   // Shows the menu used during drag and drop for the specified node.
    415   void ShowDropFolderForNode(const BookmarkNode* node);
    416 
    417   // Cancels the timer used to show a drop menu.
    418   void StopShowFolderDropMenuTimer();
    419 
    420   // Stars the timer used to show a drop menu for node.
    421   void StartShowFolderDropMenuTimer(const BookmarkNode* node);
    422 
    423   // Returns the drop operation and index for the drop based on the event
    424   // and data. Returns ui::DragDropTypes::DRAG_NONE if not a valid location.
    425   int CalculateDropOperation(const views::DropTargetEvent& event,
    426                              const BookmarkNodeData& data,
    427                              int* index,
    428                              bool* drop_on,
    429                              bool* is_over_overflow,
    430                              bool* is_over_other);
    431 
    432   // Returns the index of the first hidden bookmark button. If all buttons are
    433   // visible, this returns GetBookmarkButtonCount().
    434   int GetFirstHiddenNodeIndex();
    435 
    436   // This determines which view should throb and starts it
    437   // throbbing (e.g when the bookmark bubble is showing).
    438   // If |overflow_only| is true, start throbbing only if |node| is hidden in
    439   // the overflow menu.
    440   void StartThrobbing(const BookmarkNode* node, bool overflow_only);
    441 
    442   // Returns the view to throb when a node is removed. |parent| is the parent of
    443   // the node that was removed, and |old_index| the index of the node that was
    444   // removed.
    445   views::CustomButton* DetermineViewToThrobFromRemove(
    446       const BookmarkNode* parent,
    447       int old_index);
    448 
    449   // Updates the colors for all the child objects in the bookmarks bar.
    450   void UpdateColors();
    451 
    452   // Updates the visibility of |other_bookmarked_button_| and
    453   // |bookmarks_separator_view_|.
    454   void UpdateOtherBookmarksVisibility();
    455 
    456   // This method computes the bounds for the bookmark bar items. If
    457   // |compute_bounds_only| = TRUE, the bounds for the items are just computed,
    458   // but are not set. This mode is used by GetPreferredSize() to obtain the
    459   // desired bounds. If |compute_bounds_only| = FALSE, the bounds are set.
    460   gfx::Size LayoutItems(bool compute_bounds_only);
    461 
    462   // Creates the sync error button and adds it as a child view.
    463   views::TextButton* CreateSyncErrorButton();
    464 
    465   NotificationRegistrar registrar_;
    466 
    467   Profile* profile_;
    468 
    469   // Used for opening urls.
    470   PageNavigator* page_navigator_;
    471 
    472   // Model providing details as to the starred entries/folders that should be
    473   // shown. This is owned by the Profile.
    474   BookmarkModel* model_;
    475 
    476   // Used to manage showing a Menu, either for the most recently bookmarked
    477   // entries, or for the starred folder.
    478   BookmarkMenuController* bookmark_menu_;
    479 
    480   // Used when showing a menu for drag and drop. That is, if the user drags
    481   // over a folder this becomes non-null and manages the menu showing the
    482   // contents of the node.
    483   BookmarkMenuController* bookmark_drop_menu_;
    484 
    485   // Shows the other bookmark entries.
    486   views::MenuButton* other_bookmarked_button_;
    487 
    488   // ModelChangeListener.
    489   ModelChangedListener* model_changed_listener_;
    490 
    491   // Task used to delay showing of the drop menu.
    492   ShowFolderDropMenuTask* show_folder_drop_menu_task_;
    493 
    494   // Used to track drops on the bookmark bar view.
    495   scoped_ptr<DropInfo> drop_info_;
    496 
    497   // The sync re-login indicator which appears when the user needs to re-enter
    498   // credentials in order to continue syncing.
    499   views::TextButton* sync_error_button_;
    500 
    501   // A pointer to the ProfileSyncService instance if one exists.
    502   ProfileSyncService* sync_service_;
    503 
    504   // Visible if not all the bookmark buttons fit.
    505   views::MenuButton* overflow_button_;
    506 
    507   // BookmarkBarInstructionsView that is visible if there are no bookmarks on
    508   // the bookmark bar.
    509   views::View* instructions_;
    510 
    511   ButtonSeparatorView* bookmarks_separator_view_;
    512 
    513   // Owning browser. This is NULL during testing.
    514   Browser* browser_;
    515 
    516   // True if the owning browser is showing an infobar.
    517   bool infobar_visible_;
    518 
    519   // Animation controlling showing and hiding of the bar.
    520   scoped_ptr<ui::SlideAnimation> size_animation_;
    521 
    522   // If the bookmark bubble is showing, this is the visible ancestor of the URL.
    523   // The visible ancestor is either the other_bookmarked_button_,
    524   // overflow_button_ or a button on the bar.
    525   views::CustomButton* throbbing_view_;
    526 
    527   // Background for extension toolstrips.
    528   SkBitmap toolstrip_background_;
    529 
    530   DISALLOW_COPY_AND_ASSIGN(BookmarkBarView);
    531 };
    532 
    533 #endif  // CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_BAR_VIEW_H_
    534