Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(984)

Side by Side Diff: chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm

Issue 7465090: [Mac] Replace the custom bookmark menus with native NSMenus. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h" 5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
6 6
7 #include "base/mac/mac_util.h" 7 #include "base/mac/mac_util.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/sys_string_conversions.h" 9 #include "base/sys_string_conversions.h"
10 #include "chrome/browser/bookmarks/bookmark_editor.h" 10 #include "chrome/browser/bookmarks/bookmark_editor.h"
11 #include "chrome/browser/bookmarks/bookmark_model.h" 11 #include "chrome/browser/bookmarks/bookmark_model.h"
12 #include "chrome/browser/bookmarks/bookmark_utils.h" 12 #include "chrome/browser/bookmarks/bookmark_utils.h"
13 #include "chrome/browser/extensions/extension_service.h" 13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/prefs/pref_service.h" 14 #include "chrome/browser/prefs/pref_service.h"
15 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
16 #import "chrome/browser/themes/theme_service.h" 16 #import "chrome/browser/themes/theme_service.h"
17 #import "chrome/browser/themes/theme_service_factory.h" 17 #import "chrome/browser/themes/theme_service_factory.h"
18 #include "chrome/browser/ui/browser.h" 18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_list.h" 19 #include "chrome/browser/ui/browser_list.h"
20 #import "chrome/browser/ui/cocoa/background_gradient_view.h" 20 #import "chrome/browser/ui/cocoa/background_gradient_view.h"
21 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge.h" 21 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_bridge.h"
22 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h" 22 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h"
23 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_window.h"
24 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h" 23 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_toolbar_view.h"
25 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h" 24 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_view.h"
26 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h" 25 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button.h"
27 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h" 26 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h"
28 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h" 27 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h"
29 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h" 28 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_folder_target.h"
30 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu.h" 29 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu.h"
31 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h" 30 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.h"
32 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h" 31 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_name_folder_controller.h"
33 #import "chrome/browser/ui/cocoa/browser_window_controller.h" 32 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 360
362 // When resized we may need to add new buttons, or remove them (if 361 // When resized we may need to add new buttons, or remove them (if
363 // no longer visible), or add/remove the "off the side" menu. 362 // no longer visible), or add/remove the "off the side" menu.
364 [[self view] setPostsFrameChangedNotifications:YES]; 363 [[self view] setPostsFrameChangedNotifications:YES];
365 [[NSNotificationCenter defaultCenter] 364 [[NSNotificationCenter defaultCenter]
366 addObserver:self 365 addObserver:self
367 selector:@selector(frameDidChange) 366 selector:@selector(frameDidChange)
368 name:NSViewFrameDidChangeNotification 367 name:NSViewFrameDidChangeNotification
369 object:[self view]]; 368 object:[self view]];
370 369
371 // Watch for things going to or from fullscreen.
372 [[NSNotificationCenter defaultCenter]
373 addObserver:self
374 selector:@selector(willEnterOrLeaveFullscreen:)
375 name:kWillEnterFullscreenNotification
376 object:nil];
377 [[NSNotificationCenter defaultCenter]
378 addObserver:self
379 selector:@selector(willEnterOrLeaveFullscreen:)
380 name:kWillLeaveFullscreenNotification
381 object:nil];
382
383 // Don't pass ourself along (as 'self') until our init is completely 370 // Don't pass ourself along (as 'self') until our init is completely
384 // done. Thus, this call is (almost) last. 371 // done. Thus, this call is (almost) last.
385 bridge_.reset(new BookmarkBarBridge(self, bookmarkModel_)); 372 bridge_.reset(new BookmarkBarBridge(self, bookmarkModel_));
386 } 373 }
387 374
388 // Called by our main view (a BookmarkBarView) when it gets moved to a 375 // Called by our main view (a BookmarkBarView) when it gets moved to a
389 // window. We perform operations which need to know the relevant 376 // window. We perform operations which need to know the relevant
390 // window (e.g. watch for a window close) so they can't be performed 377 // window (e.g. watch for a window close) so they can't be performed
391 // earlier (such as in awakeFromNib). 378 // earlier (such as in awakeFromNib).
392 - (void)viewDidMoveToWindow { 379 - (void)viewDidMoveToWindow {
(...skipping 10 matching lines...) Expand all
403 [defaultCenter addObserver:self 390 [defaultCenter addObserver:self
404 selector:@selector(parentWindowWillClose:) 391 selector:@selector(parentWindowWillClose:)
405 name:NSWindowWillCloseNotification 392 name:NSWindowWillCloseNotification
406 object:[[self view] window]]; 393 object:[[self view] window]];
407 [defaultCenter addObserver:self 394 [defaultCenter addObserver:self
408 selector:@selector(parentWindowDidResignMain:) 395 selector:@selector(parentWindowDidResignMain:)
409 name:NSWindowDidResignMainNotification 396 name:NSWindowDidResignMainNotification
410 object:[[self view] window]]; 397 object:[[self view] window]];
411 } 398 }
412 399
413 // When going fullscreen we can run into trouble. Our view is removed
414 // from the non-fullscreen window before the non-fullscreen window
415 // loses key, so our parentDidResignKey: callback never gets called.
416 // In addition, a bookmark folder controller needs to be autoreleased
417 // (in case it's in the event chain when closed), but the release
418 // implicitly needs to happen while it's connected to the original
419 // (non-fullscreen) window to "unlock bar visibility". Such a
420 // contract isn't honored when going fullscreen with the menu option
421 // (not with the keyboard shortcut). We fake it as best we can here.
422 // We have a similar problem leaving fullscreen.
423 - (void)willEnterOrLeaveFullscreen:(NSNotification*)notification {
424 if (folderController_) {
425 [self childFolderWillClose:folderController_];
426 [self closeFolderAndStopTrackingMenus];
427 }
428 }
429
430 // NSNotificationCenter callback. 400 // NSNotificationCenter callback.
431 - (void)parentWindowWillClose:(NSNotification*)notification { 401 - (void)parentWindowWillClose:(NSNotification*)notification {
432 [self closeFolderAndStopTrackingMenus]; 402 [self closeFolderAndStopTrackingMenus];
433 } 403 }
434 404
435 // NSNotificationCenter callback. 405 // NSNotificationCenter callback.
436 - (void)parentWindowDidResignMain:(NSNotification*)notification { 406 - (void)parentWindowDidResignMain:(NSNotification*)notification {
437 [self closeFolderAndStopTrackingMenus]; 407 [self closeFolderAndStopTrackingMenus];
438 } 408 }
439 409
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 if (node == nil || 510 if (node == nil ||
541 node == bookmarkModel_->bookmark_bar_node() || 511 node == bookmarkModel_->bookmark_bar_node() ||
542 node == bookmarkModel_->other_node() || 512 node == bookmarkModel_->other_node() ||
543 node == bookmarkModel_->synced_node()) 513 node == bookmarkModel_->synced_node())
544 return NO; 514 return NO;
545 return YES; 515 return YES;
546 } 516 }
547 517
548 #pragma mark Actions 518 #pragma mark Actions
549 519
550 // Helper methods called on the main thread by runMenuFlashThread.
551
552 - (void)setButtonFlashStateOn:(id)sender {
553 [sender highlight:YES];
554 }
555
556 - (void)setButtonFlashStateOff:(id)sender {
557 [sender highlight:NO];
558 }
559
560 -(void)cleanupAfterMenuFlashThread:(id)sender {
561 [self closeFolderAndStopTrackingMenus];
562
563 // Items retained by doMenuFlashOnSeparateThread below.
564 [sender release];
565 [self release];
566 }
567
568 // End runMenuFlashThread helper methods.
569
570 // This call is invoked only by doMenuFlashOnSeparateThread below.
571 // It makes the selected BookmarkButton (which is masquerading as a menu item)
572 // flash a few times to give confirmation feedback, then it closes the menu.
573 // It spends all its time sleeping or scheduling UI work on the main thread.
574 - (void)runMenuFlashThread:(id)sender {
575
576 // Check this is not running on the main thread, as it sleeps.
577 DCHECK(![NSThread isMainThread]);
578
579 // Duration of flash phases and number of flashes designed to evoke a
580 // slightly retro "more mac-like than the Mac" feel.
581 // Current Cocoa UI has a barely perceptible flash,probably because Apple
582 // doesn't fire the action til after the animation and so there's a hurry.
583 // As this code is fully asynchronous, it can take its time.
584 const float kBBOnFlashTime = 0.08;
585 const float kBBOffFlashTime = 0.08;
586 const int kBookmarkButtonMenuFlashes = 3;
587
588 for (int count = 0 ; count < kBookmarkButtonMenuFlashes ; count++) {
589 [self performSelectorOnMainThread:@selector(setButtonFlashStateOn:)
590 withObject:sender
591 waitUntilDone:NO];
592 [NSThread sleepForTimeInterval:kBBOnFlashTime];
593 [self performSelectorOnMainThread:@selector(setButtonFlashStateOff:)
594 withObject:sender
595 waitUntilDone:NO];
596 [NSThread sleepForTimeInterval:kBBOffFlashTime];
597 }
598 [self performSelectorOnMainThread:@selector(cleanupAfterMenuFlashThread:)
599 withObject:sender
600 waitUntilDone:NO];
601 }
602
603 // Non-blocking call which starts the process to make the selected menu item
604 // flash a few times to give confirmation feedback, after which it closes the
605 // menu. The item is of course actually a BookmarkButton masquerading as a menu
606 // item).
607 - (void)doMenuFlashOnSeparateThread:(id)sender {
608
609 // Ensure that self and sender don't go away before the animation completes.
610 // These retains are balanced in cleanupAfterMenuFlashThread above.
611 [self retain];
612 [sender retain];
613 [NSThread detachNewThreadSelector:@selector(runMenuFlashThread:)
614 toTarget:self
615 withObject:sender];
616 }
617
618 - (IBAction)openBookmark:(id)sender { 520 - (IBAction)openBookmark:(id)sender {
619 BOOL isMenuItem = [[sender cell] isFolderButtonCell]; 521 BOOL isMenuItem = [[sender cell] isFolderButtonCell];
620 BOOL animate = isMenuItem && [self animationEnabled]; 522 BOOL animate = isMenuItem && [self animationEnabled];
621 if (animate)
622 [self doMenuFlashOnSeparateThread:sender];
623 DCHECK([sender respondsToSelector:@selector(bookmarkNode)]); 523 DCHECK([sender respondsToSelector:@selector(bookmarkNode)]);
624 const BookmarkNode* node = [sender bookmarkNode]; 524 const BookmarkNode* node = [sender bookmarkNode];
625 WindowOpenDisposition disposition = 525 WindowOpenDisposition disposition =
626 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]); 526 event_utils::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
627 RecordAppLaunch(browser_->profile(), node->url()); 527 RecordAppLaunch(browser_->profile(), node->url());
628 [self openURL:node->url() disposition:disposition]; 528 [self openURL:node->url() disposition:disposition];
629 529
630 if (!animate) 530 if (!animate)
631 [self closeFolderAndStopTrackingMenus]; 531 [self closeFolderAndStopTrackingMenus];
632 } 532 }
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 bookmarks::kBookmarkHorizontalPadding)); 754 bookmarks::kBookmarkHorizontalPadding));
855 } else { 755 } else {
856 frame.origin.x = (NSMaxX([otherBookmarksButton_ frame]) - frame.size.width); 756 frame.origin.x = (NSMaxX([otherBookmarksButton_ frame]) - frame.size.width);
857 } 757 }
858 [offTheSideButton_ setFrame:frame]; 758 [offTheSideButton_ setFrame:frame];
859 } 759 }
860 760
861 // Configure the off-the-side button (e.g. specify the node range, 761 // Configure the off-the-side button (e.g. specify the node range,
862 // check if we should enable or disable it, etc). 762 // check if we should enable or disable it, etc).
863 - (void)configureOffTheSideButtonContentsAndVisibility { 763 - (void)configureOffTheSideButtonContentsAndVisibility {
864 // If deleting a button while off-the-side is open, buttons may be
865 // promoted from off-the-side to the bar. Accomodate.
866 if (folderController_ &&
867 ([folderController_ parentButton] == offTheSideButton_)) {
868 [folderController_ reconfigureMenu];
869 }
870
871 [[offTheSideButton_ cell] setStartingChildIndex:displayedButtonCount_]; 764 [[offTheSideButton_ cell] setStartingChildIndex:displayedButtonCount_];
872 [[offTheSideButton_ cell] 765 [[offTheSideButton_ cell]
873 setBookmarkNode:bookmarkModel_->bookmark_bar_node()]; 766 setBookmarkNode:bookmarkModel_->bookmark_bar_node()];
874 int bookmarkChildren = bookmarkModel_->bookmark_bar_node()->child_count(); 767 int bookmarkChildren = bookmarkModel_->bookmark_bar_node()->child_count();
875 if (bookmarkChildren > displayedButtonCount_) { 768 if (bookmarkChildren > displayedButtonCount_) {
876 [offTheSideButton_ setHidden:NO]; 769 [offTheSideButton_ setHidden:NO];
877 } else { 770 } else {
878 // If we just deleted the last item in an off-the-side menu so the 771 // If we just deleted the last item in an off-the-side menu so the
879 // button will be going away, make sure the menu goes away. 772 // button will be going away, make sure the menu goes away.
880 if (folderController_ && 773 if (folderController_ &&
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after
1814 // All other clicks on the bookmarks bar are counted as 'outside' 1707 // All other clicks on the bookmarks bar are counted as 'outside'
1815 // because they should close any open bookmark folder menu. 1708 // because they should close any open bookmark folder menu.
1816 if (eventWindow == myWindow) { 1709 if (eventWindow == myWindow) {
1817 NSView* hitView = 1710 NSView* hitView =
1818 [[eventWindow contentView] hitTest:[event locationInWindow]]; 1711 [[eventWindow contentView] hitTest:[event locationInWindow]];
1819 if (hitView == [folderController_ parentButton]) 1712 if (hitView == [folderController_ parentButton])
1820 return NO; 1713 return NO;
1821 if (![hitView isDescendantOf:[self view]] || hitView == buttonView_) 1714 if (![hitView isDescendantOf:[self view]] || hitView == buttonView_)
1822 return YES; 1715 return YES;
1823 } 1716 }
1824 // If a click in a bookmark bar folder window and that isn't
1825 // one of my bookmark bar folders, YES is click outside.
1826 if (![eventWindow isKindOfClass:[BookmarkBarFolderWindow
1827 class]]) {
1828 return YES;
1829 }
1830 break; 1717 break;
1831 case NSKeyDown: { 1718 case NSKeyDown: {
1832 // Event hooks often see the same keydown event twice due to the way key 1719 // Event hooks often see the same keydown event twice due to the way key
1833 // events get dispatched and redispatched, so ignore if this keydown 1720 // events get dispatched and redispatched, so ignore if this keydown
1834 // event has the EXACT same timestamp as the previous keydown. 1721 // event has the EXACT same timestamp as the previous keydown.
1835 static NSTimeInterval lastKeyDownEventTime; 1722 static NSTimeInterval lastKeyDownEventTime;
1836 NSTimeInterval thisTime = [event timestamp]; 1723 NSTimeInterval thisTime = [event timestamp];
1837 if (lastKeyDownEventTime != thisTime) { 1724 if (lastKeyDownEventTime != thisTime) {
1838 lastKeyDownEventTime = thisTime; 1725 lastKeyDownEventTime = thisTime;
1839 if ([event modifierFlags] & NSCommandKeyMask) 1726 if ([event modifierFlags] & NSCommandKeyMask)
1840 return YES; 1727 return YES;
1841 else if (folderController_)
1842 return [folderController_ handleInputText:[event characters]];
1843 } 1728 }
1844 return NO; 1729 return NO;
1845 } 1730 }
1846 case NSKeyUp: 1731 case NSKeyUp:
1847 return NO; 1732 return NO;
1848 case NSLeftMouseDragged: 1733 case NSLeftMouseDragged:
1849 // We can get here with the following sequence: 1734 // We can get here with the following sequence:
1850 // - open a bookmark folder 1735 // - open a bookmark folder
1851 // - right-click (and unclick) on it to open context menu 1736 // - right-click (and unclick) on it to open context menu
1852 // - move mouse to window titlebar then click-drag it by the titlebar 1737 // - move mouse to window titlebar then click-drag it by the titlebar
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 if (cellnode == node) { 2074 if (cellnode == node) {
2190 [[button cell] setBookmarkCellText:[button title] 2075 [[button cell] setBookmarkCellText:[button title]
2191 image:[self faviconForNode:node]]; 2076 image:[self faviconForNode:node]];
2192 // Adding an image means we might need more room for the 2077 // Adding an image means we might need more room for the
2193 // bookmark. Test for it by growing the button (if needed) 2078 // bookmark. Test for it by growing the button (if needed)
2194 // and shifting everything else over. 2079 // and shifting everything else over.
2195 [self checkForBookmarkButtonGrowth:button]; 2080 [self checkForBookmarkButtonGrowth:button];
2196 return; 2081 return;
2197 } 2082 }
2198 } 2083 }
2199
2200 if (folderController_)
2201 [folderController_ faviconLoadedForNode:node];
2202 } 2084 }
2203 2085
2204 // TODO(jrg): for now this is brute force. 2086 // TODO(jrg): for now this is brute force.
2205 - (void)nodeChildrenReordered:(BookmarkModel*)model 2087 - (void)nodeChildrenReordered:(BookmarkModel*)model
2206 node:(const BookmarkNode*)node { 2088 node:(const BookmarkNode*)node {
2207 [self loaded:model]; 2089 [self loaded:model];
2208 } 2090 }
2209 2091
2210 #pragma mark BookmarkBarState Protocol 2092 #pragma mark BookmarkBarState Protocol
2211 2093
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2300 // a subfolder menu. 2182 // a subfolder menu.
2301 if (!showFolderMenus_) 2183 if (!showFolderMenus_)
2302 return; 2184 return;
2303 2185
2304 // From here down: same logic as BookmarkBarFolderController. 2186 // From here down: same logic as BookmarkBarFolderController.
2305 // TODO(jrg): find a way to share these 4 non-comment lines? 2187 // TODO(jrg): find a way to share these 4 non-comment lines?
2306 // http://crbug.com/35966 2188 // http://crbug.com/35966
2307 // If already opened, then we exited but re-entered the button, so do nothing. 2189 // If already opened, then we exited but re-entered the button, so do nothing.
2308 if ([folderController_ parentButton] == sender) 2190 if ([folderController_ parentButton] == sender)
2309 return; 2191 return;
2310 // Else open a new one if it makes sense to do so.
2311 if ([sender bookmarkNode]->is_folder()) {
2312 // Update |hoverButton_| so that it corresponds to the open folder.
2313 hoverButton_.reset([sender retain]);
2314 [folderTarget_ openBookmarkFolderFromButton:sender];
2315 } else {
2316 // We're over a non-folder bookmark so close any old folders.
2317 [folderController_ close];
2318 folderController_ = nil;
2319 }
2320 } 2192 }
2321 2193
2322 // BookmarkButtonDelegate protocol implementation. 2194 // BookmarkButtonDelegate protocol implementation.
2323 - (void)mouseExitedButton:(id)sender event:(NSEvent*)event { 2195 - (void)mouseExitedButton:(id)sender event:(NSEvent*)event {
2324 // Don't care; do nothing. 2196 // Don't care; do nothing.
2325 // This is different behavior that the folder menus. 2197 // This is different behavior that the folder menus.
2326 } 2198 }
2327 2199
2328 - (NSWindow*)browserWindow { 2200 - (NSWindow*)browserWindow {
2329 return [[self view] window]; 2201 return [[self view] window];
(...skipping 21 matching lines...) Expand all
2351 [self resetAllButtonPositionsWithAnimation:YES]; 2223 [self resetAllButtonPositionsWithAnimation:YES];
2352 } 2224 }
2353 2225
2354 2226
2355 #pragma mark BookmarkButtonControllerProtocol 2227 #pragma mark BookmarkButtonControllerProtocol
2356 2228
2357 // Close all bookmark folders. "Folder" here is the fake menu for 2229 // Close all bookmark folders. "Folder" here is the fake menu for
2358 // bookmark folders, not a button context menu. 2230 // bookmark folders, not a button context menu.
2359 - (void)closeAllBookmarkFolders { 2231 - (void)closeAllBookmarkFolders {
2360 [self watchForExitEvent:NO]; 2232 [self watchForExitEvent:NO];
2361 [folderController_ close]; 2233 [folderController_ closeMenu];
2362 folderController_ = nil; 2234 folderController_ = nil;
2363 } 2235 }
2364 2236
2365 - (void)closeBookmarkFolder:(id)sender { 2237 - (void)closeBookmarkFolder:(id)sender {
2366 // We're the top level, so close one means close them all. 2238 // We're the top level, so close one means close them all.
2367 [self closeAllBookmarkFolders]; 2239 [self closeAllBookmarkFolders];
2368 } 2240 }
2369 2241
2370 - (BookmarkModel*)bookmarkModel { 2242 - (BookmarkModel*)bookmarkModel {
2371 return bookmarkModel_; 2243 return bookmarkModel_;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2406 target]]; 2278 target]];
2407 // Unlike BookmarkBarFolderController, we do not delay the close 2279 // Unlike BookmarkBarFolderController, we do not delay the close
2408 // of the previous one. Given the lack of diagonal movement, 2280 // of the previous one. Given the lack of diagonal movement,
2409 // there is no need, and it feels awkward to do so. See 2281 // there is no need, and it feels awkward to do so. See
2410 // comments about kDragHoverCloseDelay in 2282 // comments about kDragHoverCloseDelay in
2411 // bookmark_bar_folder_controller.mm for more details. 2283 // bookmark_bar_folder_controller.mm for more details.
2412 [[hoverButton_ target] closeBookmarkFolder:hoverButton_]; 2284 [[hoverButton_ target] closeBookmarkFolder:hoverButton_];
2413 hoverButton_.reset(); 2285 hoverButton_.reset();
2414 } 2286 }
2415 hoverButton_.reset([button retain]); 2287 hoverButton_.reset([button retain]);
2416 DCHECK([[hoverButton_ target]
2417 respondsToSelector:@selector(openBookmarkFolderFromButton:)]);
2418 [[hoverButton_ target]
2419 performSelector:@selector(openBookmarkFolderFromButton:)
2420 withObject:hoverButton_
2421 afterDelay:bookmarks::kDragHoverOpenDelay
2422 inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
2423 } 2288 }
2424 if (!button) { 2289 if (!button) {
2425 if (hoverButton_) { 2290 if (hoverButton_) {
2426 [NSObject cancelPreviousPerformRequestsWithTarget:[hoverButton_ target]];
2427 [[hoverButton_ target] closeBookmarkFolder:hoverButton_]; 2291 [[hoverButton_ target] closeBookmarkFolder:hoverButton_];
2428 hoverButton_.reset(); 2292 hoverButton_.reset();
2429 } 2293 }
2430 } 2294 }
2431 2295
2432 // Thrown away but kept to be consistent with the draggingEntered: interface. 2296 // Thrown away but kept to be consistent with the draggingEntered: interface.
2433 return NSDragOperationMove; 2297 return NSDragOperationMove;
2434 } 2298 }
2435 2299
2436 - (void)draggingExited:(id<NSDraggingInfo>)info { 2300 - (void)draggingExited:(id<NSDraggingInfo>)info {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2521 } else { 2385 } else {
2522 x = 0.5 * bookmarks::kBookmarkHorizontalPadding; 2386 x = 0.5 * bookmarks::kBookmarkHorizontalPadding;
2523 } 2387 }
2524 } else { 2388 } else {
2525 NOTREACHED(); 2389 NOTREACHED();
2526 } 2390 }
2527 2391
2528 return x; 2392 return x;
2529 } 2393 }
2530 2394
2531 - (void)childFolderWillShow:(id<BookmarkButtonControllerProtocol>)child {
2532 // If the bookmarkbar is not in detached mode, lock bar visibility, forcing
2533 // the overlay to stay open when in fullscreen mode.
2534 if (![self isInState:bookmarks::kDetachedState] &&
2535 ![self isAnimatingToState:bookmarks::kDetachedState]) {
2536 BrowserWindowController* browserController =
2537 [BrowserWindowController browserWindowControllerForView:[self view]];
2538 [browserController lockBarVisibilityForOwner:child
2539 withAnimation:NO
2540 delay:NO];
2541 }
2542 }
2543
2544 - (void)childFolderWillClose:(id<BookmarkButtonControllerProtocol>)child {
2545 // Release bar visibility, allowing the overlay to close if in fullscreen
2546 // mode.
2547 BrowserWindowController* browserController =
2548 [BrowserWindowController browserWindowControllerForView:[self view]];
2549 [browserController releaseBarVisibilityForOwner:child
2550 withAnimation:NO
2551 delay:NO];
2552 }
2553
2554 // Add a new folder controller as triggered by the given folder button. 2395 // Add a new folder controller as triggered by the given folder button.
2555 - (void)addNewFolderControllerWithParentButton:(BookmarkButton*)parentButton { 2396 - (void)addNewFolderControllerWithParentButton:(BookmarkButton*)parentButton {
2556 2397
2557 // If doing a close/open, make sure the fullscreen chrome doesn't 2398 // If doing a close/open, make sure the fullscreen chrome doesn't
2558 // have a chance to begin animating away in the middle of things. 2399 // have a chance to begin animating away in the middle of things.
2559 BrowserWindowController* browserController = 2400 BrowserWindowController* browserController =
2560 [BrowserWindowController browserWindowControllerForView:[self view]]; 2401 [BrowserWindowController browserWindowControllerForView:[self view]];
2561 // Confirm we're not re-locking with ourself as an owner before locking. 2402 // Confirm we're not re-locking with ourself as an owner before locking.
2562 DCHECK([browserController isBarVisibilityLockedForOwner:self] == NO); 2403 DCHECK([browserController isBarVisibilityLockedForOwner:self] == NO);
2563 [browserController lockBarVisibilityForOwner:self 2404 [browserController lockBarVisibilityForOwner:self
2564 withAnimation:NO 2405 withAnimation:NO
2565 delay:NO]; 2406 delay:NO];
2566 2407
2567 if (folderController_) 2408 if (folderController_)
2568 [self closeAllBookmarkFolders]; 2409 [self closeAllBookmarkFolders];
2569 2410
2570 // Folder controller, like many window controllers, owns itself. 2411 // Folder controller, like many window controllers, owns itself.
2571 folderController_ = 2412 folderController_ =
2572 [[BookmarkBarFolderController alloc] initWithParentButton:parentButton 2413 [[BookmarkBarFolderController alloc] initWithParentButton:parentButton
2573 parentController:nil 2414 bookmarkModel:bookmarkModel_
2574 barController:self]; 2415 barController:self];
2575 [folderController_ showWindow:self]; 2416 [folderController_ autorelease];
2417 [folderController_ openMenu];
2576 2418
2577 // Only BookmarkBarController has this; the 2419 // Only BookmarkBarController has this; the
2578 // BookmarkBarFolderController does not. 2420 // BookmarkBarFolderController does not.
2579 [self watchForExitEvent:YES]; 2421 [self watchForExitEvent:YES];
2580 2422
2581 // No longer need to hold the lock; the folderController_ now owns it. 2423 // No longer need to hold the lock; the folderController_ now owns it.
2582 [browserController releaseBarVisibilityForOwner:self 2424 [browserController releaseBarVisibilityForOwner:self
2583 withAnimation:NO 2425 withAnimation:NO
2584 delay:NO]; 2426 delay:NO];
2585 } 2427 }
(...skipping 24 matching lines...) Expand all
2610 ++displayedButtonCount_; 2452 ++displayedButtonCount_;
2611 [buttons_ insertObject:newButton atIndex:buttonIndex]; 2453 [buttons_ insertObject:newButton atIndex:buttonIndex];
2612 [buttonView_ addSubview:newButton]; 2454 [buttonView_ addSubview:newButton];
2613 [self resetAllButtonPositionsWithAnimation:NO]; 2455 [self resetAllButtonPositionsWithAnimation:NO];
2614 // See if any buttons need to be pushed off to or brought in from the side. 2456 // See if any buttons need to be pushed off to or brought in from the side.
2615 [self reconfigureBookmarkBar]; 2457 [self reconfigureBookmarkBar];
2616 } else { 2458 } else {
2617 // A button from somewhere else (not the bar) is being moved to the 2459 // A button from somewhere else (not the bar) is being moved to the
2618 // off-the-side so insure it gets redrawn if its showing. 2460 // off-the-side so insure it gets redrawn if its showing.
2619 [self reconfigureBookmarkBar]; 2461 [self reconfigureBookmarkBar];
2620 [folderController_ reconfigureMenu];
2621 } 2462 }
2622 } 2463 }
2623 2464
2624 // TODO(mrossetti): Duplicate code with BookmarkBarFolderController. 2465 // TODO(mrossetti): Duplicate code with BookmarkBarFolderController.
2625 // http://crbug.com/35966 2466 // http://crbug.com/35966
2626 - (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point { 2467 - (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point {
2627 DCHECK([urls count] == [titles count]); 2468 DCHECK([urls count] == [titles count]);
2628 BOOL nodesWereAdded = NO; 2469 BOOL nodesWereAdded = NO;
2629 // Figure out where these new bookmarks nodes are to be added. 2470 // Figure out where these new bookmarks nodes are to be added.
2630 BookmarkButton* button = [self buttonForDroppingOnAtPoint:point]; 2471 BookmarkButton* button = [self buttonForDroppingOnAtPoint:point];
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2678 [movedButton setHidden:NO]; 2519 [movedButton setHidden:NO];
2679 [self resetAllButtonPositionsWithAnimation:NO]; 2520 [self resetAllButtonPositionsWithAnimation:NO];
2680 } else if (fromIndex < buttonCount) { 2521 } else if (fromIndex < buttonCount) {
2681 // A button is being removed from the bar and added to off-the-side. 2522 // A button is being removed from the bar and added to off-the-side.
2682 // By now the node has already been inserted into the model so the 2523 // By now the node has already been inserted into the model so the
2683 // button to be added is represented by |toIndex|. Things get 2524 // button to be added is represented by |toIndex|. Things get
2684 // complicated because the off-the-side is showing and must be redrawn 2525 // complicated because the off-the-side is showing and must be redrawn
2685 // while possibly re-laying out the bookmark bar. 2526 // while possibly re-laying out the bookmark bar.
2686 [self removeButton:fromIndex animate:NO]; 2527 [self removeButton:fromIndex animate:NO];
2687 [self reconfigureBookmarkBar]; 2528 [self reconfigureBookmarkBar];
2688 [folderController_ reconfigureMenu];
2689 } else if (toIndex < buttonCount) { 2529 } else if (toIndex < buttonCount) {
2690 // A button is being added to the bar and removed from off-the-side. 2530 // A button is being added to the bar and removed from off-the-side.
2691 // By now the node has already been inserted into the model so the 2531 // By now the node has already been inserted into the model so the
2692 // button to be added is represented by |toIndex|. 2532 // button to be added is represented by |toIndex|.
2693 const BookmarkNode* node = bookmarkModel_->bookmark_bar_node(); 2533 const BookmarkNode* node = bookmarkModel_->bookmark_bar_node();
2694 const BookmarkNode* movedNode = node->GetChild(toIndex); 2534 const BookmarkNode* movedNode = node->GetChild(toIndex);
2695 DCHECK(movedNode); 2535 DCHECK(movedNode);
2696 [self addButtonForNode:movedNode atIndex:toIndex]; 2536 [self addButtonForNode:movedNode atIndex:toIndex];
2697 [self reconfigureBookmarkBar]; 2537 [self reconfigureBookmarkBar];
2698 } else {
2699 // A button is being moved within the off-the-side.
2700 fromIndex -= buttonCount;
2701 toIndex -= buttonCount;
2702 [folderController_ moveButtonFromIndex:fromIndex toIndex:toIndex];
2703 } 2538 }
2704 } 2539 }
2705 } 2540 }
2706 2541
2707 - (void)removeButton:(NSInteger)buttonIndex animate:(BOOL)animate { 2542 - (void)removeButton:(NSInteger)buttonIndex animate:(BOOL)animate {
2708 if (buttonIndex < (NSInteger)[buttons_ count]) { 2543 if (buttonIndex < (NSInteger)[buttons_ count]) {
2709 // The button being removed is showing in the bar. 2544 // The button being removed is showing in the bar.
2710 BookmarkButton* oldButton = [buttons_ objectAtIndex:buttonIndex]; 2545 BookmarkButton* oldButton = [buttons_ objectAtIndex:buttonIndex];
2711 if (oldButton == [folderController_ parentButton]) { 2546 if (oldButton == [folderController_ parentButton]) {
2712 // If we are deleting a button whose folder is currently open, close it! 2547 // If we are deleting a button whose folder is currently open, close it!
2713 [self closeAllBookmarkFolders]; 2548 [self closeAllBookmarkFolders];
2714 } 2549 }
2715 if (animate && !ignoreAnimations_ && [self isVisible] && 2550 if (animate && !ignoreAnimations_ && [self isVisible] &&
2716 [[self browserWindow] isMainWindow]) { 2551 [[self browserWindow] isMainWindow]) {
2717 NSPoint poofPoint = [oldButton screenLocationForRemoveAnimation]; 2552 NSPoint poofPoint = [oldButton screenLocationForRemoveAnimation];
2718 NSShowAnimationEffect(NSAnimationEffectDisappearingItemDefault, poofPoint, 2553 NSShowAnimationEffect(NSAnimationEffectDisappearingItemDefault, poofPoint,
2719 NSZeroSize, nil, nil, nil); 2554 NSZeroSize, nil, nil, nil);
2720 } 2555 }
2721 [oldButton setDelegate:nil]; 2556 [oldButton setDelegate:nil];
2722 [oldButton removeFromSuperview]; 2557 [oldButton removeFromSuperview];
2723 [buttons_ removeObjectAtIndex:buttonIndex]; 2558 [buttons_ removeObjectAtIndex:buttonIndex];
2724 --displayedButtonCount_; 2559 --displayedButtonCount_;
2725 [self resetAllButtonPositionsWithAnimation:YES]; 2560 [self resetAllButtonPositionsWithAnimation:YES];
2726 [self reconfigureBookmarkBar]; 2561 [self reconfigureBookmarkBar];
2727 } else if (folderController_ &&
2728 [folderController_ parentButton] == offTheSideButton_) {
2729 // The button being removed is in the OTS (off-the-side) and the OTS
2730 // menu is showing so we need to remove the button.
2731 NSInteger index = buttonIndex - displayedButtonCount_;
2732 [folderController_ removeButton:index animate:YES];
2733 } 2562 }
2734 } 2563 }
2735 2564
2736 - (id<BookmarkButtonControllerProtocol>)controllerForNode: 2565 - (id<BookmarkButtonControllerProtocol>)controllerForNode:
2737 (const BookmarkNode*)node { 2566 (const BookmarkNode*)node {
2738 // See if it's in the bar, then if it is in the hierarchy of visible 2567 // See if it's in the bar, then if it is in the hierarchy of visible
2739 // folder menus. 2568 // folder menus.
2740 if (bookmarkModel_->bookmark_bar_node() == node) 2569 if (bookmarkModel_->bookmark_bar_node() == node)
2741 return self; 2570 return self;
2742 return [folderController_ controllerForNode:node]; 2571 return nil;
2743 } 2572 }
2744 2573
2745 #pragma mark BookmarkButtonControllerProtocol 2574 #pragma mark BookmarkButtonControllerProtocol
2746 2575
2747 // NOT an override of a standard Cocoa call made to NSViewControllers. 2576 // NOT an override of a standard Cocoa call made to NSViewControllers.
2748 - (void)hookForEvent:(NSEvent*)theEvent { 2577 - (void)hookForEvent:(NSEvent*)theEvent {
2749 if ([self isEventAnExitEvent:theEvent]) 2578 if ([self isEventAnExitEvent:theEvent])
2750 [self closeFolderAndStopTrackingMenus]; 2579 [self closeFolderAndStopTrackingMenus];
2751 } 2580 }
2752 2581
2753 #pragma mark TestingAPI Only 2582 #pragma mark TestingAPI Only
2754 2583
2755 - (NSMenu*)buttonContextMenu { 2584 - (NSMenu*)buttonContextMenu {
2756 return buttonContextMenu_; 2585 return buttonContextMenu_;
2757 } 2586 }
2758 2587
2759 // Intentionally ignores ownership issues; used for testing and we try 2588 // Intentionally ignores ownership issues; used for testing and we try
2760 // to minimize touching the object passed in (likely a mock). 2589 // to minimize touching the object passed in (likely a mock).
2761 - (void)setButtonContextMenu:(id)menu { 2590 - (void)setButtonContextMenu:(id)menu {
2762 buttonContextMenu_ = menu; 2591 buttonContextMenu_ = menu;
2763 } 2592 }
2764 2593
2765 - (void)setIgnoreAnimations:(BOOL)ignore { 2594 - (void)setIgnoreAnimations:(BOOL)ignore {
2766 ignoreAnimations_ = ignore; 2595 ignoreAnimations_ = ignore;
2767 } 2596 }
2768 2597
2769 @end 2598 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698