• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
~ModelChangedListener()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.
GetProfile()98   Profile* GetProfile() { return profile_; }
99 
100   // Returns the current browser.
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.
set_infobar_visible(bool infobar_visible)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.
SetModelChangedListener(ModelChangedListener * 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.
ClearModelChangedListenerIfEquals(ModelChangedListener * listener)155   void ClearModelChangedListenerIfEquals(ModelChangedListener* listener) {
156     if (model_changed_listener_ == listener)
157       model_changed_listener_ = NULL;
158   }
159 
160   // Returns the model change listener.
GetModelChangedListener()161   ModelChangedListener* GetModelChangedListener() {
162     return model_changed_listener_;
163   }
164 
165   // Returns the page navigator.
GetPageNavigator()166   PageNavigator* GetPageNavigator() { return page_navigator_; }
167 
168   // Returns the model.
GetModel()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.
other_bookmarked_button()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.
overflow_button()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:
ShowFolderDropMenuTask(BookmarkBarView * view,const BookmarkNode * node)265     ShowFolderDropMenuTask(BookmarkBarView* view, const BookmarkNode* node)
266       : view_(view),
267         node_(node) {
268     }
269 
Cancel()270     void Cancel() {
271       view_->show_folder_drop_menu_task_ = NULL;
272       view_ = NULL;
273     }
274 
Run()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