bookmark_bar_view.h revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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_VIEWS_BOOKMARKS_BOOKMARK_BAR_VIEW_H_ 6#define CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_BAR_VIEW_H_ 7 8#include <set> 9#include <string> 10 11#include "base/basictypes.h" 12#include "base/compiler_specific.h" 13#include "base/gtest_prod_util.h" 14#include "base/memory/weak_ptr.h" 15#include "base/prefs/pref_change_registrar.h" 16#include "chrome/browser/bookmarks/bookmark_model_observer.h" 17#include "chrome/browser/bookmarks/bookmark_node_data.h" 18#include "chrome/browser/bookmarks/bookmark_utils.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/views/bookmarks/bookmark_bubble_view_observer.h" 22#include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h" 23#include "chrome/browser/ui/views/detachable_toolbar_view.h" 24#include "ui/base/animation/animation_delegate.h" 25#include "ui/views/context_menu_controller.h" 26#include "ui/views/controls/button/button.h" 27#include "ui/views/controls/button/menu_button_listener.h" 28#include "ui/views/drag_controller.h" 29 30class BookmarkContextMenu; 31class Browser; 32class BrowserView; 33 34namespace content { 35class PageNavigator; 36} 37 38namespace ui { 39class SlideAnimation; 40} 41 42namespace views { 43class CustomButton; 44class MenuButton; 45class MenuItemView; 46class TextButton; 47} 48 49// BookmarkBarView renders the BookmarkModel. Each starred entry on the 50// BookmarkBar is rendered as a MenuButton. An additional MenuButton aligned to 51// the right allows the user to quickly see recently starred entries. 52// 53// BookmarkBarView shows the bookmarks from a specific Profile. BookmarkBarView 54// waits until the HistoryService for the profile has been loaded before 55// creating the BookmarkModel. 56class BookmarkBarView : public DetachableToolbarView, 57 public BookmarkModelObserver, 58 public views::MenuButtonListener, 59 public views::ButtonListener, 60 public views::ContextMenuController, 61 public views::DragController, 62 public ui::AnimationDelegate, 63 public BookmarkMenuController::Observer, 64 public chrome::BookmarkBarInstructionsDelegate, 65 public BookmarkBubbleViewObserver { 66 public: 67 // The internal view class name. 68 static const char kViewClassName[]; 69 70 // Constants used in Browser View, as well as here. 71 // How inset the bookmarks bar is when displayed on the new tab page. 72 static const int kNewtabHorizontalPadding; 73 static const int kNewtabVerticalPadding; 74 75 // Maximum size of buttons on the bookmark bar. 76 static const int kMaxButtonWidth; 77 78 // Number of pixels the attached bookmark bar overlaps with the toolbar. 79 static const int kToolbarAttachedBookmarkBarOverlap; 80 81 // |browser_view| can be NULL during tests. 82 BookmarkBarView(Browser* browser, BrowserView* browser_view); 83 virtual ~BookmarkBarView(); 84 85 static void DisableAnimationsForTesting(bool disabled); 86 87 // Returns the current browser. 88 Browser* browser() const { return browser_; } 89 90 // Sets the PageNavigator that is used when the user selects an entry on 91 // the bookmark bar. 92 void SetPageNavigator(content::PageNavigator* navigator); 93 94 // Sets whether the containing browser is showing an infobar. This affects 95 // layout during animation. 96 void set_infobar_visible(bool infobar_visible) { 97 infobar_visible_ = infobar_visible; 98 } 99 100 // Changes the state of the bookmark bar. 101 void SetBookmarkBarState(BookmarkBar::State state, 102 BookmarkBar::AnimateChangeType animate_type); 103 104 // How much we want the bookmark bar to overlap the toolbar. If |return_max| 105 // is true, we return the maximum overlap rather than the current overlap. 106 int GetToolbarOverlap(bool return_max) const; 107 108 // Whether or not we are animating. 109 bool is_animating(); 110 111 // If |loc| is over a bookmark button the node is returned corresponding to 112 // the button and |model_start_index| is set to 0. If a overflow button is 113 // showing and |loc| is over the overflow button, the bookmark bar node is 114 // returned and |model_start_index| is set to the index of the first node 115 // contained in the overflow menu. 116 const BookmarkNode* GetNodeForButtonAtModelIndex(const gfx::Point& loc, 117 int* model_start_index); 118 119 // Returns the MenuButton for node. 120 views::MenuButton* GetMenuButtonForNode(const BookmarkNode* node); 121 122 // Returns the position to anchor the menu for |button| at. 123 void GetAnchorPositionForButton( 124 views::MenuButton* button, 125 views::MenuItemView::AnchorPosition* anchor); 126 127 // Returns the button responsible for showing bookmarks in the other bookmark 128 // folder. 129 views::MenuButton* other_bookmarked_button() const { 130 return other_bookmarked_button_; 131 } 132 133 // Returns the button used when not all the items on the bookmark bar fit. 134 views::MenuButton* overflow_button() const { return overflow_button_; } 135 136 // Returns the active MenuItemView, or NULL if a menu isn't showing. 137 views::MenuItemView* GetMenu(); 138 139 // Returns the context menu, or null if one isn't showing. 140 views::MenuItemView* GetContextMenu(); 141 142 // Returns the drop MenuItemView, or NULL if a menu isn't showing. 143 views::MenuItemView* GetDropMenu(); 144 145 // If a button is currently throbbing, it is stopped. If immediate is true 146 // the throb stops immediately, otherwise it stops after a couple more 147 // throbs. 148 void StopThrobbing(bool immediate); 149 150 // Returns the tooltip text for the specified url and title. The returned 151 // text is clipped to fit within the bounds of the monitor. |context| is 152 // used to determine which gfx::Screen is used to retrieve bounds. 153 // 154 // Note that we adjust the direction of both the URL and the title based on 155 // the locale so that pure LTR strings are displayed properly in RTL locales. 156 static string16 CreateToolTipForURLAndTitle(const gfx::Point& screen_loc, 157 const GURL& url, 158 const string16& title, 159 Profile* profile, 160 gfx::NativeView context); 161 162 // DetachableToolbarView methods: 163 virtual bool IsDetached() const OVERRIDE; 164 virtual double GetAnimationValue() const OVERRIDE; 165 virtual int GetToolbarOverlap() const OVERRIDE; 166 167 // View methods: 168 virtual gfx::Size GetPreferredSize() OVERRIDE; 169 virtual gfx::Size GetMinimumSize() OVERRIDE; 170 virtual void Layout() OVERRIDE; 171 virtual void ViewHierarchyChanged( 172 const ViewHierarchyChangedDetails& details) OVERRIDE; 173 virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE; 174 virtual bool GetDropFormats( 175 int* formats, 176 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE; 177 virtual bool AreDropTypesRequired() OVERRIDE; 178 virtual bool CanDrop(const ui::OSExchangeData& data) OVERRIDE; 179 virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE; 180 virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE; 181 virtual void OnDragExited() OVERRIDE; 182 virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE; 183 virtual void OnThemeChanged() OVERRIDE; 184 virtual const char* GetClassName() const OVERRIDE; 185 186 // AccessiblePaneView: 187 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; 188 189 // ui::AnimationDelegate: 190 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; 191 virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; 192 193 // BookmarkMenuController::Observer: 194 virtual void BookmarkMenuDeleted( 195 BookmarkMenuController* controller) OVERRIDE; 196 197 // chrome::BookmarkBarInstructionsDelegate: 198 virtual void ShowImportDialog() OVERRIDE; 199 200 // BookmarkBubbleViewObserver: 201 virtual void OnBookmarkBubbleShown(const GURL& url) OVERRIDE; 202 virtual void OnBookmarkBubbleHidden() OVERRIDE; 203 204 // BookmarkModelObserver: 205 virtual void Loaded(BookmarkModel* model, bool ids_reassigned) OVERRIDE; 206 virtual void BookmarkModelBeingDeleted(BookmarkModel* model) OVERRIDE; 207 virtual void BookmarkNodeMoved(BookmarkModel* model, 208 const BookmarkNode* old_parent, 209 int old_index, 210 const BookmarkNode* new_parent, 211 int new_index) OVERRIDE; 212 virtual void BookmarkNodeAdded(BookmarkModel* model, 213 const BookmarkNode* parent, 214 int index) OVERRIDE; 215 virtual void BookmarkNodeRemoved(BookmarkModel* model, 216 const BookmarkNode* parent, 217 int old_index, 218 const BookmarkNode* node) OVERRIDE; 219 virtual void BookmarkAllNodesRemoved(BookmarkModel* model) OVERRIDE; 220 virtual void BookmarkNodeChanged(BookmarkModel* model, 221 const BookmarkNode* node) OVERRIDE; 222 virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, 223 const BookmarkNode* node) OVERRIDE; 224 virtual void BookmarkNodeFaviconChanged(BookmarkModel* model, 225 const BookmarkNode* node) OVERRIDE; 226 227 // views::DragController: 228 virtual void WriteDragDataForView(views::View* sender, 229 const gfx::Point& press_pt, 230 ui::OSExchangeData* data) OVERRIDE; 231 virtual int GetDragOperationsForView(views::View* sender, 232 const gfx::Point& p) OVERRIDE; 233 virtual bool CanStartDragForView(views::View* sender, 234 const gfx::Point& press_pt, 235 const gfx::Point& p) OVERRIDE; 236 237 // views::MenuButtonListener: 238 virtual void OnMenuButtonClicked(views::View* view, 239 const gfx::Point& point) OVERRIDE; 240 241 // views::ButtonListener: 242 virtual void ButtonPressed(views::Button* sender, 243 const ui::Event& event) OVERRIDE; 244 245 // views::ContextMenuController: 246 virtual void ShowContextMenuForView(views::View* source, 247 const gfx::Point& point, 248 ui::MenuSourceType source_type) OVERRIDE; 249 250 private: 251 class ButtonSeparatorView; 252 struct DropInfo; 253 struct DropLocation; 254 255 friend class BookmarkBarViewEventTestBase; 256 FRIEND_TEST_ALL_PREFIXES(BookmarkBarViewTest, SwitchProfile); 257 FRIEND_TEST_ALL_PREFIXES(BookmarkBarViewTest, 258 NoAppsShortcutWithoutInstantExtended); 259 FRIEND_TEST_ALL_PREFIXES(BookmarkBarViewInstantExtendedTest, 260 AppsShortcutVisibility); 261 262 // Used to identify what the user is dropping onto. 263 enum DropButtonType { 264 DROP_BOOKMARK, 265 DROP_OTHER_FOLDER, 266 DROP_OVERFLOW 267 }; 268 269 // Creates recent bookmark button and when visible button as well as 270 // calculating the preferred height. 271 void Init(); 272 273 // NOTE: unless otherwise stated all methods that take an int for an index are 274 // in terms of the bookmark bar view. Typically the view index and model index 275 // are the same, but they may differ during animations or drag and drop. 276 // 277 // It's easy to get the mapping wrong. For this reason all these methods are 278 // private. 279 280 // Returns the number of buttons corresponding to starred urls/folders. This 281 // is equivalent to the number of children the bookmark bar node from the 282 // bookmark bar model has. 283 int GetBookmarkButtonCount(); 284 285 // Returns the button at the specified index. 286 views::TextButton* GetBookmarkButton(int index); 287 288 // Returns LAUNCH_DETACHED_BAR or LAUNCH_ATTACHED_BAR based on detached state. 289 bookmark_utils::BookmarkLaunchLocation GetBookmarkLaunchLocation() const; 290 291 // Returns the index of the first hidden bookmark button. If all buttons are 292 // visible, this returns GetBookmarkButtonCount(). 293 int GetFirstHiddenNodeIndex(); 294 295 // Creates the button showing the other bookmarked items. 296 views::MenuButton* CreateOtherBookmarkedButton(); 297 298 // Creates the button used when not all bookmark buttons fit. 299 views::MenuButton* CreateOverflowButton(); 300 301 // Creates the button for rendering the specified bookmark node. 302 views::View* CreateBookmarkButton(const BookmarkNode* node); 303 304 // Creates the button for rendering the apps page shortcut. 305 views::TextButton* CreateAppsPageShortcutButton(); 306 307 // Configures the button from the specified node. This sets the text, 308 // and icon. 309 void ConfigureButton(const BookmarkNode* node, views::TextButton* button); 310 311 // Implementation for BookmarkNodeAddedImpl. 312 void BookmarkNodeAddedImpl(BookmarkModel* model, 313 const BookmarkNode* parent, 314 int index); 315 316 // Implementation for BookmarkNodeRemoved. 317 void BookmarkNodeRemovedImpl(BookmarkModel* model, 318 const BookmarkNode* parent, 319 int index); 320 321 // If the node is a child of the root node, the button is updated 322 // appropriately. 323 void BookmarkNodeChangedImpl(BookmarkModel* model, const BookmarkNode* node); 324 325 // Shows the menu used during drag and drop for the specified node. 326 void ShowDropFolderForNode(const BookmarkNode* node); 327 328 // Cancels the timer used to show a drop menu. 329 void StopShowFolderDropMenuTimer(); 330 331 // Stars the timer used to show a drop menu for node. 332 void StartShowFolderDropMenuTimer(const BookmarkNode* node); 333 334 // Calculates the location for the drop in |location|. 335 void CalculateDropLocation(const ui::DropTargetEvent& event, 336 const BookmarkNodeData& data, 337 DropLocation* location); 338 339 // Writes a BookmarkNodeData for node to data. 340 void WriteBookmarkDragData(const BookmarkNode* node, 341 ui::OSExchangeData* data); 342 343 // This determines which view should throb and starts it 344 // throbbing (e.g when the bookmark bubble is showing). 345 // If |overflow_only| is true, start throbbing only if |node| is hidden in 346 // the overflow menu. 347 void StartThrobbing(const BookmarkNode* node, bool overflow_only); 348 349 // Returns the view to throb when a node is removed. |parent| is the parent of 350 // the node that was removed, and |old_index| the index of the node that was 351 // removed. 352 views::CustomButton* DetermineViewToThrobFromRemove( 353 const BookmarkNode* parent, 354 int old_index); 355 356 // Updates the colors for all the child objects in the bookmarks bar. 357 void UpdateColors(); 358 359 // Updates the visibility of |other_bookmarked_button_|. Also shows or hide 360 // the separator if required. 361 void UpdateOtherBookmarksVisibility(); 362 363 // Updates the visibility of |bookmarks_separator_view_|. 364 void UpdateBookmarksSeparatorVisibility(); 365 366 // This method computes the bounds for the bookmark bar items. If 367 // |compute_bounds_only| = TRUE, the bounds for the items are just computed, 368 // but are not set. This mode is used by GetPreferredSize() to obtain the 369 // desired bounds. If |compute_bounds_only| = FALSE, the bounds are set. 370 gfx::Size LayoutItems(bool compute_bounds_only); 371 372 // Updates the visibility of the apps shortcut based on the pref value. 373 void OnAppsPageShortcutVisibilityPrefChanged(); 374 375 // Needed to react to kShowAppsShortcutInBookmarkBar changes. 376 PrefChangeRegistrar profile_pref_registrar_; 377 378 // Used for opening urls. 379 content::PageNavigator* page_navigator_; 380 381 // Model providing details as to the starred entries/folders that should be 382 // shown. This is owned by the Profile. 383 BookmarkModel* model_; 384 385 // Used to manage showing a Menu, either for the most recently bookmarked 386 // entries, or for the starred folder. 387 BookmarkMenuController* bookmark_menu_; 388 389 // Used when showing a menu for drag and drop. That is, if the user drags 390 // over a folder this becomes non-null and manages the menu showing the 391 // contents of the node. 392 BookmarkMenuController* bookmark_drop_menu_; 393 394 // If non-NULL we're showing a context menu for one of the items on the 395 // bookmark bar. 396 scoped_ptr<BookmarkContextMenu> context_menu_; 397 398 // Shows the other bookmark entries. 399 views::MenuButton* other_bookmarked_button_; 400 401 // Shows the Apps page shortcut. 402 views::TextButton* apps_page_shortcut_; 403 404 // Task used to delay showing of the drop menu. 405 base::WeakPtrFactory<BookmarkBarView> show_folder_method_factory_; 406 407 // Used to track drops on the bookmark bar view. 408 scoped_ptr<DropInfo> drop_info_; 409 410 // Visible if not all the bookmark buttons fit. 411 views::MenuButton* overflow_button_; 412 413 // Shows a text and a link to import bookmarks if there are no bookmarks in 414 // the Bookmarks Bar. 415 views::View* instructions_; 416 417 ButtonSeparatorView* bookmarks_separator_view_; 418 419 Browser* browser_; 420 BrowserView* browser_view_; 421 422 // True if the owning browser is showing an infobar. 423 bool infobar_visible_; 424 425 // Animation controlling showing and hiding of the bar. 426 scoped_ptr<ui::SlideAnimation> size_animation_; 427 428 // If the bookmark bubble is showing, this is the visible ancestor of the URL. 429 // The visible ancestor is either the other_bookmarked_button_, 430 // overflow_button_ or a button on the bar. 431 views::CustomButton* throbbing_view_; 432 433 BookmarkBar::State bookmark_bar_state_; 434 435 // Are we animating to or from the detached state? 436 bool animating_detached_; 437 438 DISALLOW_COPY_AND_ASSIGN(BookmarkBarView); 439}; 440 441#endif // CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_BAR_VIEW_H_ 442