| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/cocoa/bookmark_bar_folder_controller.h" | 5 #import "chrome/browser/cocoa/bookmark_bar_folder_controller.h" |
| 6 #include "base/mac_util.h" | 6 #include "base/mac_util.h" |
| 7 #include "base/nsimage_cache_mac.h" |
| 7 #include "base/sys_string_conversions.h" | 8 #include "base/sys_string_conversions.h" |
| 8 #include "chrome/browser/bookmarks/bookmark_model.h" | 9 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 9 #include "chrome/browser/bookmarks/bookmark_utils.h" | 10 #include "chrome/browser/bookmarks/bookmark_utils.h" |
| 10 #import "chrome/browser/browser_theme_provider.h" | 11 #import "chrome/browser/browser_theme_provider.h" |
| 11 #import "chrome/browser/cocoa/bookmark_bar_constants.h" // namespace bookmarks | 12 #import "chrome/browser/cocoa/bookmark_bar_constants.h" // namespace bookmarks |
| 12 #import "chrome/browser/cocoa/bookmark_bar_controller.h" // namespace bookmarks | 13 #import "chrome/browser/cocoa/bookmark_bar_controller.h" // namespace bookmarks |
| 13 #import "chrome/browser/cocoa/bookmark_bar_folder_view.h" | 14 #import "chrome/browser/cocoa/bookmark_bar_folder_view.h" |
| 14 #import "chrome/browser/cocoa/bookmark_bar_folder_button_cell.h" | 15 #import "chrome/browser/cocoa/bookmark_bar_folder_button_cell.h" |
| 15 #import "chrome/browser/cocoa/bookmark_bar_folder_hover_state.h" | 16 #import "chrome/browser/cocoa/bookmark_bar_folder_hover_state.h" |
| 16 #import "chrome/browser/cocoa/bookmark_folder_target.h" | 17 #import "chrome/browser/cocoa/bookmark_folder_target.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 33 1 * (bookmarks::kBookmarkButtonHeight + | 34 1 * (bookmarks::kBookmarkButtonHeight + |
| 34 bookmarks::kBookmarkVerticalPadding); | 35 bookmarks::kBookmarkVerticalPadding); |
| 35 | 36 |
| 36 // Our NSScrollView is supposed to be just barely big enough to fit its | 37 // Our NSScrollView is supposed to be just barely big enough to fit its |
| 37 // contentView. It is actually a hair too small. | 38 // contentView. It is actually a hair too small. |
| 38 // This turns on horizontal scrolling which, although slight, is awkward. | 39 // This turns on horizontal scrolling which, although slight, is awkward. |
| 39 // Make sure our window (and NSScrollView) are wider than its documentView | 40 // Make sure our window (and NSScrollView) are wider than its documentView |
| 40 // by at least this much. | 41 // by at least this much. |
| 41 const CGFloat kScrollViewContentWidthMargin = 2; | 42 const CGFloat kScrollViewContentWidthMargin = 2; |
| 42 | 43 |
| 43 | |
| 44 // When constraining a scrolling bookmark bar folder window to the | 44 // When constraining a scrolling bookmark bar folder window to the |
| 45 // screen, shrink the "constrain" by this much vertically. Currently | 45 // screen, shrink the "constrain" by this much vertically. Currently |
| 46 // this is 0.0 to avoid a problem with tracking areas leaving the | 46 // this is 0.0 to avoid a problem with tracking areas leaving the |
| 47 // window, but should probably be 8.0 or something. | 47 // window, but should probably be 8.0 or something. |
| 48 // TODO(jrg): http://crbug.com/36225 | 48 // TODO(jrg): http://crbug.com/36225 |
| 49 const CGFloat kScrollWindowVerticalMargin = 0.0; | 49 const CGFloat kScrollWindowVerticalMargin = 0.0; |
| 50 | 50 |
| 51 } // namespace | 51 } // namespace |
| 52 | 52 |
| 53 @interface BookmarkBarFolderController(Private) | 53 @interface BookmarkBarFolderController(Private) |
| 54 - (void)configureWindow; | 54 - (void)configureWindow; |
| 55 - (void)addOrUpdateScrollTracking; | 55 - (void)addOrUpdateScrollTracking; |
| 56 - (void)removeScrollTracking; | 56 - (void)removeScrollTracking; |
| 57 - (void)endScroll; | 57 - (void)endScroll; |
| 58 - (void)addScrollTimerWithDelta:(CGFloat)delta; | 58 - (void)addScrollTimerWithDelta:(CGFloat)delta; |
| 59 | 59 |
| 60 // Determine the best button width (which will be the widest button or the | 60 // Determine the best button width (which will be the widest button or the |
| 61 // maximum allowable button width, whichever is less) and resize all buttons. | 61 // maximum allowable button width, whichever is less) and resize all buttons. |
| 62 // Return the new width (so that the window can be adjusted, if necessary). | 62 // Return the new width (so that the window can be adjusted, if necessary). |
| 63 - (CGFloat)adjustButtonWidths; | 63 - (CGFloat)adjustButtonWidths; |
| 64 | 64 |
| 65 // Show or hide the scroll arrows at the top/bottom of the window. |
| 66 - (void)showOrHideScrollArrows; |
| 67 |
| 65 @end | 68 @end |
| 66 | 69 |
| 67 @implementation BookmarkBarFolderController | 70 @implementation BookmarkBarFolderController |
| 68 | 71 |
| 69 - (id)initWithParentButton:(BookmarkButton*)button | 72 - (id)initWithParentButton:(BookmarkButton*)button |
| 70 parentController:(BookmarkBarFolderController*)parentController | 73 parentController:(BookmarkBarFolderController*)parentController |
| 71 barController:(BookmarkBarController*)barController { | 74 barController:(BookmarkBarController*)barController { |
| 72 NSString* nibPath = | 75 NSString* nibPath = |
| 73 [mac_util::MainAppBundle() pathForResource:@"BookmarkBarFolderWindow" | 76 [mac_util::MainAppBundle() pathForResource:@"BookmarkBarFolderWindow" |
| 74 ofType:@"nib"]; | 77 ofType:@"nib"]; |
| 75 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { | 78 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { |
| 76 parentButton_.reset([button retain]); | 79 parentButton_.reset([button retain]); |
| 77 parentController_.reset([parentController retain]); | 80 parentController_.reset([parentController retain]); |
| 78 barController_ = barController; // WEAK | 81 barController_ = barController; // WEAK |
| 79 buttons_.reset([[NSMutableArray alloc] init]); | 82 buttons_.reset([[NSMutableArray alloc] init]); |
| 80 folderTarget_.reset([[BookmarkFolderTarget alloc] initWithController:self]); | 83 folderTarget_.reset([[BookmarkFolderTarget alloc] initWithController:self]); |
| 84 NSImage* image = nsimage_cache::ImageNamed(@"menu_overflow_up.pdf"); |
| 85 DCHECK(image); |
| 86 verticalScrollArrowHeight_ = [image size].height; |
| 81 [self configureWindow]; | 87 [self configureWindow]; |
| 82 hoverState_.reset([[BookmarkBarFolderHoverState alloc] init]); | 88 hoverState_.reset([[BookmarkBarFolderHoverState alloc] init]); |
| 83 if (scrollable_) | 89 if (scrollable_) |
| 84 [self addOrUpdateScrollTracking]; | 90 [self addOrUpdateScrollTracking]; |
| 85 } | 91 } |
| 86 return self; | 92 return self; |
| 87 } | 93 } |
| 88 | 94 |
| 89 - (void)dealloc { | 95 - (void)dealloc { |
| 90 [self removeScrollTracking]; | 96 [self removeScrollTracking]; |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 if (!NSContainsRect(screenFrame, windowFrame)) { | 333 if (!NSContainsRect(screenFrame, windowFrame)) { |
| 328 scrollable_ = YES; | 334 scrollable_ = YES; |
| 329 windowFrame = NSIntersectionRect(screenFrame, windowFrame); | 335 windowFrame = NSIntersectionRect(screenFrame, windowFrame); |
| 330 } | 336 } |
| 331 [[self window] setFrame:windowFrame display:YES]; | 337 [[self window] setFrame:windowFrame display:YES]; |
| 332 if (scrollable_) { | 338 if (scrollable_) { |
| 333 [mainView_ scrollPoint:NSMakePoint(0, (NSHeight(mainViewFrame) - | 339 [mainView_ scrollPoint:NSMakePoint(0, (NSHeight(mainViewFrame) - |
| 334 NSHeight(windowFrame)))]; | 340 NSHeight(windowFrame)))]; |
| 335 } | 341 } |
| 336 | 342 |
| 343 // If scrollable, show the arrows. |
| 344 if (scrollable_) { |
| 345 [self showOrHideScrollArrows]; |
| 346 } |
| 347 |
| 337 // Finally pop me up. | 348 // Finally pop me up. |
| 338 [self configureWindowLevel]; | 349 [self configureWindowLevel]; |
| 339 } | 350 } |
| 340 | 351 |
| 341 - (void)offsetFolderMenuWindow:(NSSize)offset { | 352 - (void)offsetFolderMenuWindow:(NSSize)offset { |
| 342 NSWindow* window = [self window]; | 353 NSWindow* window = [self window]; |
| 343 NSRect windowFrame = [window frame]; | 354 NSRect windowFrame = [window frame]; |
| 344 windowFrame.origin.x -= offset.width; | 355 windowFrame.origin.x -= offset.width; |
| 345 windowFrame.origin.y += offset.height; // Yes, in the opposite direction! | 356 windowFrame.origin.y += offset.height; // Yes, in the opposite direction! |
| 346 [window setFrame:windowFrame display:YES]; | 357 [window setFrame:windowFrame display:YES]; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 357 // Things look and feel more menu-like if all the buttons are the | 368 // Things look and feel more menu-like if all the buttons are the |
| 358 // full width of the window, especially if there are submenus. | 369 // full width of the window, especially if there are submenus. |
| 359 for (BookmarkButton* button in buttons_.get()) { | 370 for (BookmarkButton* button in buttons_.get()) { |
| 360 NSRect buttonFrame = [button frame]; | 371 NSRect buttonFrame = [button frame]; |
| 361 buttonFrame.size.width = width; | 372 buttonFrame.size.width = width; |
| 362 [button setFrame:buttonFrame]; | 373 [button setFrame:buttonFrame]; |
| 363 } | 374 } |
| 364 return width; | 375 return width; |
| 365 } | 376 } |
| 366 | 377 |
| 378 - (BOOL)canScrollUp { |
| 379 // If removal of an arrow would make things "finished", state as |
| 380 // such. |
| 381 CGFloat scrollY = [scrollView_ documentVisibleRect].origin.y; |
| 382 if (scrollUpArrowShown_) |
| 383 scrollY -= verticalScrollArrowHeight_; |
| 384 |
| 385 if (scrollY <= 0) |
| 386 return NO; |
| 387 return YES; |
| 388 } |
| 389 |
| 390 - (BOOL)canScrollDown { |
| 391 CGFloat arrowAdjustment = 0.0; |
| 392 |
| 393 // We do NOT adjust based on the scrollDOWN arrow. This keeps |
| 394 // things from "jumping"; if removal of the down arrow (at the top |
| 395 // of the window) would cause a scroll to end, we'll end. |
| 396 if (scrollUpArrowShown_) |
| 397 arrowAdjustment += verticalScrollArrowHeight_; |
| 398 |
| 399 NSPoint scrollPosition = [scrollView_ documentVisibleRect].origin; |
| 400 NSRect documentRect = [[scrollView_ documentView] frame]; |
| 401 |
| 402 // If we are exactly the right height, return no. We need this |
| 403 // extra conditional in the case where we've just scrolled/grown |
| 404 // into position. |
| 405 if (NSHeight([[self window] frame]) == NSHeight(documentRect)) |
| 406 return NO; |
| 407 |
| 408 if ((scrollPosition.y + NSHeight([[self window] frame])) >= |
| 409 (NSHeight(documentRect) + arrowAdjustment)) { |
| 410 return NO; |
| 411 } |
| 412 return YES; |
| 413 } |
| 414 |
| 415 - (void)showOrHideScrollArrows { |
| 416 NSRect frame = [scrollView_ frame]; |
| 417 CGFloat scrollDelta = 0.0; |
| 418 BOOL canScrollDown = [self canScrollDown]; |
| 419 BOOL canScrollUp = [self canScrollUp]; |
| 420 |
| 421 if (canScrollUp != scrollUpArrowShown_) { |
| 422 if (scrollUpArrowShown_) { |
| 423 frame.origin.y -= verticalScrollArrowHeight_; |
| 424 frame.size.height += verticalScrollArrowHeight_; |
| 425 scrollDelta = verticalScrollArrowHeight_; |
| 426 } else { |
| 427 frame.origin.y += verticalScrollArrowHeight_; |
| 428 frame.size.height -= verticalScrollArrowHeight_; |
| 429 scrollDelta = -verticalScrollArrowHeight_; |
| 430 } |
| 431 } |
| 432 if (canScrollDown != scrollDownArrowShown_) { |
| 433 if (scrollDownArrowShown_) { |
| 434 frame.size.height += verticalScrollArrowHeight_; |
| 435 } else { |
| 436 frame.size.height -= verticalScrollArrowHeight_; |
| 437 } |
| 438 } |
| 439 scrollUpArrowShown_ = canScrollUp; |
| 440 scrollDownArrowShown_ = canScrollDown; |
| 441 [scrollView_ setFrame:frame]; |
| 442 |
| 443 // Adjust scroll based on new frame. For example, if we make room |
| 444 // for an arrow at the bottom, adjust the scroll so the topmost item |
| 445 // is still fully visible. |
| 446 if (scrollDelta) { |
| 447 NSPoint scrollPosition = [scrollView_ documentVisibleRect].origin; |
| 448 scrollPosition.y -= scrollDelta; |
| 449 [[scrollView_ documentView] scrollPoint:scrollPosition]; |
| 450 } |
| 451 } |
| 452 |
| 367 #pragma mark BookmarkButtonControllerProtocol | 453 #pragma mark BookmarkButtonControllerProtocol |
| 368 | 454 |
| 369 - (void)addButtonForNode:(const BookmarkNode*)node | 455 - (void)addButtonForNode:(const BookmarkNode*)node |
| 370 atIndex:(NSInteger)buttonIndex { | 456 atIndex:(NSInteger)buttonIndex { |
| 371 if (buttonIndex == -1) | 457 if (buttonIndex == -1) |
| 372 buttonIndex = [buttons_ count]; | 458 buttonIndex = [buttons_ count]; |
| 373 | 459 |
| 374 // Remember the last moved button's frame or the default. | 460 // Remember the last moved button's frame or the default. |
| 375 NSRect buttonFrame = NSMakeRect(bookmarks::kBookmarkHorizontalPadding, | 461 NSRect buttonFrame = NSMakeRect(bookmarks::kBookmarkHorizontalPadding, |
| 376 NSHeight([mainView_ frame]) + bookmarks::kBookmarkBarHeight + | 462 NSHeight([mainView_ frame]) + bookmarks::kBookmarkBarHeight + |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 if (delta) { | 638 if (delta) { |
| 553 // If we can, grow the window (up). | 639 // If we can, grow the window (up). |
| 554 if (NSHeight(windowFrame) < screenHeightMinusMargin) { | 640 if (NSHeight(windowFrame) < screenHeightMinusMargin) { |
| 555 CGFloat growAmount = delta; | 641 CGFloat growAmount = delta; |
| 556 // Don't scroll more than enough to "finish". | 642 // Don't scroll more than enough to "finish". |
| 557 if (scrollPosition.y < 0) | 643 if (scrollPosition.y < 0) |
| 558 growAmount += scrollPosition.y; | 644 growAmount += scrollPosition.y; |
| 559 windowFrame.size.height += growAmount; | 645 windowFrame.size.height += growAmount; |
| 560 windowFrame.size.height = std::min(NSHeight(windowFrame), | 646 windowFrame.size.height = std::min(NSHeight(windowFrame), |
| 561 screenHeightMinusMargin); | 647 screenHeightMinusMargin); |
| 648 // Watch out for a finish that isn't the full height of the screen. |
| 649 // We get here if using the scroll wheel to scroll by small amounts. |
| 650 windowFrame.size.height = std::min(NSHeight(windowFrame), |
| 651 NSHeight([mainView_ frame])); |
| 562 // Don't allow scrolling to make the window smaller, ever. This | 652 // Don't allow scrolling to make the window smaller, ever. This |
| 563 // conditional is important when processing scrollWheel events. | 653 // conditional is important when processing scrollWheel events. |
| 564 if (windowFrame.size.height > [[self window] frame].size.height) { | 654 if (windowFrame.size.height > [[self window] frame].size.height) { |
| 565 [[self window] setFrame:windowFrame display:YES]; | 655 [[self window] setFrame:windowFrame display:YES]; |
| 566 [self addOrUpdateScrollTracking]; | 656 [self addOrUpdateScrollTracking]; |
| 567 } | 657 } |
| 568 } | 658 } |
| 569 } | 659 } |
| 570 | 660 |
| 571 // If we're at either end, happiness. | 661 // If we're at either end, happiness. |
| 572 if ((scrollPosition.y <= 0) || | 662 if ((scrollPosition.y <= 0) || |
| 573 ((scrollPosition.y + NSHeight(windowFrame) >= | 663 ((scrollPosition.y + NSHeight(windowFrame) >= |
| 574 NSHeight([mainView_ frame])) && | 664 NSHeight([mainView_ frame])) && |
| 575 (windowFrame.size.height == screenHeightMinusMargin))) { | 665 (windowFrame.size.height == screenHeightMinusMargin))) { |
| 576 [self endScroll]; | 666 [self endScroll]; |
| 577 | 667 |
| 578 // If the entire view is now visible the window is no longer scrollable. | 668 // If we can't scroll either up or down we are completely done. |
| 579 if (NSHeight([mainView_ visibleRect]) == NSHeight([mainView_ bounds])) { | 669 // For example, perhaps we've scrolled a little and grown the |
| 670 // window on-screen until there is now room for everything. |
| 671 if (![self canScrollUp] && ![self canScrollDown]) { |
| 580 scrollable_ = NO; | 672 scrollable_ = NO; |
| 581 [self removeScrollTracking]; | 673 [self removeScrollTracking]; |
| 582 } | 674 } |
| 583 } | 675 } |
| 676 |
| 677 [self showOrHideScrollArrows]; |
| 584 } | 678 } |
| 585 | 679 |
| 586 // Perform a scroll of the window on the screen. | 680 // Perform a scroll of the window on the screen. |
| 587 // Called by a timer when scrolling. | 681 // Called by a timer when scrolling. |
| 588 - (void)performScroll:(NSTimer*)timer { | 682 - (void)performScroll:(NSTimer*)timer { |
| 589 DCHECK(verticalScrollDelta_); | 683 DCHECK(verticalScrollDelta_); |
| 590 [self performOneScroll:verticalScrollDelta_]; | 684 [self performOneScroll:verticalScrollDelta_]; |
| 591 } | 685 } |
| 592 | 686 |
| 593 | 687 |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 - (IBAction)openBookmarkInNewForegroundTab:(id)sender { | 1179 - (IBAction)openBookmarkInNewForegroundTab:(id)sender { |
| 1086 [barController_ openBookmarkInNewForegroundTab:sender]; | 1180 [barController_ openBookmarkInNewForegroundTab:sender]; |
| 1087 } | 1181 } |
| 1088 | 1182 |
| 1089 - (IBAction)openBookmarkInNewWindow:(id)sender { | 1183 - (IBAction)openBookmarkInNewWindow:(id)sender { |
| 1090 [barController_ openBookmarkInNewWindow:sender]; | 1184 [barController_ openBookmarkInNewWindow:sender]; |
| 1091 } | 1185 } |
| 1092 | 1186 |
| 1093 | 1187 |
| 1094 @end // BookmarkBarFolderController | 1188 @end // BookmarkBarFolderController |
| OLD | NEW |