diff options
Diffstat (limited to 'chrome/browser/cocoa/bookmark_bar_controller.mm')
-rw-r--r-- | chrome/browser/cocoa/bookmark_bar_controller.mm | 195 |
1 files changed, 121 insertions, 74 deletions
diff --git a/chrome/browser/cocoa/bookmark_bar_controller.mm b/chrome/browser/cocoa/bookmark_bar_controller.mm index 4d70f0a..312e3b8 100644 --- a/chrome/browser/cocoa/bookmark_bar_controller.mm +++ b/chrome/browser/cocoa/bookmark_bar_controller.mm @@ -159,12 +159,22 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; // the animation, NO if not (and hence it should be done instantly). - (BOOL)doBookmarkBarAnimation; -// Returns the index in the model for a drag of the given button to the given -// location; currently, only the x-coordinate of |point| is considered. I -// reserve the right to check for errors, in which case this would return -// negative value; callers should check for this. -- (int)indexForDragOfButton:(BookmarkButton*)sourceButton - toPoint:(NSPoint)point; +// |point| is in the base coordinate system of the destination window; +// it comes from an id<NSDraggingInfo>. |copy| is YES if a copy is to be +// made and inserted into the new location while leaving the bookmark in +// the old location, otherwise move the bookmark by removing from its old +// location and inserting into the new location. +- (BOOL)dragBookmark:(const BookmarkNode*)sourceNode + to:(NSPoint)point + copy:(BOOL)copy; + +// Returns the index in the model for a drag to the location given by +// |point|. This is determined by finding the first button before the center +// of which |point| falls, scanning left to right. Note that, currently, only +// the x-coordinate of |point| is considered. Though not currently implemented, +// we may check for errors, in which case this would return negative value; +// callers should check for this. +- (int)indexForDragToPoint:(NSPoint)point; // Add or remove buttons to/from the bar until it is filled but not overflowed. - (void)redistributeButtonsOnBarAsNeeded; @@ -174,16 +184,6 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; // then show the no items label. - (void)reconfigureBookmarkBar; -// Used for situations where the bookmark bar folder menus should no longer -// be actively popping up. Called when the window loses focus, a click has -// occured outside the menus or a bookmark has been activated. (Note that this -// differs from the behavior of the -[BookmarkButtonControllerProtocol -// closeAllBookmarkFolders] method in that the latter does not terminate menu -// tracking since it may be being called in response to actions (such as -// dragging) where a 'stale' menu presentation should first be collapsed before -// presenting a new menu.) -- (void)closeFolderAndStopTrackingMenus; - - (void)addNode:(const BookmarkNode*)child toMenu:(NSMenu*)menu; - (void)addFolderNode:(const BookmarkNode*)node toMenu:(NSMenu*)menu; - (void)tagEmptyMenu:(NSMenu*)menu; @@ -393,7 +393,7 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; - (void)configureOffTheSideButtonContentsAndVisibility { [[offTheSideButton_ cell] setStartingChildIndex:displayedButtonCount_]; [[offTheSideButton_ cell] - setBookmarkNode:bookmarkModel_->GetBookmarkBarNode()]; + setBookmarkNode:bookmarkModel_->GetBookmarkBarNode()]; int bookmarkChildren = bookmarkModel_->GetBookmarkBarNode()->GetChildCount(); if (bookmarkChildren > displayedButtonCount_) { [offTheSideButton_ setHidden:NO]; @@ -497,7 +497,7 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; // focus. - (void)watchForExitEvent:(BOOL)watch { CrApplication* app = static_cast<CrApplication*>([NSApplication - sharedApplication]); + sharedApplication]); DCHECK([app isKindOfClass:[CrApplication class]]); if (watch) { if (!watchingForExitEvent_) @@ -542,7 +542,7 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; // If a click in a bookmark bar folder window and that isn't // one of my bookmark bar folders, YES is click outside. if (![eventWindow isKindOfClass:[BookmarkBarFolderWindow - class]]) { + class]]) { return YES; } break; @@ -573,7 +573,7 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; // The textfield sits in the itemcontainer, so to center it we maintain // equal vertical padding on the top and bottom. int yoffset = (NSHeight([[buttonView_ noItemTextfield] frame]) - - NSHeight([[buttonView_ noItemContainer] frame])) / 2; + NSHeight([[buttonView_ noItemContainer] frame])) / 2; [[buttonView_ noItemContainer] setFrameOrigin:NSMakePoint(0, yoffset)]; } @@ -721,44 +721,54 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; return [self isInState:bookmarks::kShowingState] ? 0 : 1; } +// TODO(mrossetti): Duplicate code with BookmarkBarFolderController. +// http://crbug.com/35966 - (BOOL)addURLs:(NSArray*)urls withTitles:(NSArray*)titles at:(NSPoint)point { - // TODO(jrg): Support drops on folders etc - // TODO(jrg): Use |point|. DCHECK([urls count] == [titles count]); - const BookmarkNode* node = bookmarkModel_->GetBookmarkBarNode(); - int added = 0; - - for (size_t i = 0; i < [urls count]; ++i) { - // URLs come in several forms (see NSPasteboard+Utils.mm). - GURL gurl; - const char* string = [[urls objectAtIndex:i] UTF8String]; - if (string) - gurl = GURL(string); - if (!gurl.is_valid() && string) { - gurl = GURL([[NSString stringWithFormat:@"file://%s", string] - UTF8String]); - } + BOOL nodesWereAdded = NO; + // Figure out where these new bookmarks nodes are to be added. + BookmarkButton* button = [self buttonForDroppingOnAtPoint:point]; + const BookmarkNode* destParent = NULL; + int destIndex = 0; + if ([button isFolder]) { + destParent = [button bookmarkNode]; + // Drop it at the end. + destIndex = [button bookmarkNode]->GetChildCount(); + } else { + // Else we're dropping somewhere on the bar, so find the right spot. + destParent = bookmarkModel_->GetBookmarkBarNode(); + destIndex = [self indexForDragToPoint:point]; + } - DCHECK(gurl.is_valid()); - if (gurl.is_valid()) { - bookmarkModel_->AddURL( - node, - node->GetChildCount(), - base::SysNSStringToWide([titles objectAtIndex:i]), - gurl); - added++; + // Don't add the bookmarks if the destination index shows an error. + if (destIndex >= 0) { + // Create and add the new bookmark nodes. + size_t urlCount = [urls count]; + for (size_t i = 0; i < urlCount; ++i) { + // URLs come in several forms (see NSPasteboard+Utils.mm). + GURL gurl; + const char* string = [[urls objectAtIndex:i] UTF8String]; + if (string) + gurl = GURL(string); + if (!gurl.is_valid() && string) { + gurl = GURL([[NSString stringWithFormat:@"file://%s", string] + UTF8String]); + } + DCHECK(gurl.is_valid()); + if (gurl.is_valid()) { + bookmarkModel_->AddURL(destParent, + destIndex++, + base::SysNSStringToWide([titles + objectAtIndex:i]), + gurl); + nodesWereAdded = YES; + } } } - return (added ? YES : NO); + return nodesWereAdded; } -- (int)indexForDragOfButton:(BookmarkButton*)sourceButton - toPoint:(NSPoint)point { - DCHECK([sourceButton isKindOfClass:[BookmarkButton class]]); - - // Identify which buttons we are between. For now, assume a button - // location is at the center point of its view, and that an exact - // match means "place before". +- (int)indexForDragToPoint:(NSPoint)point { // TODO(jrg): revisit position info based on UI team feedback. // dropLocation is in bar local coordinates. NSPoint dropLocation = @@ -785,14 +795,22 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; return displayedButtonCount_; } +// TODO(mrossetti,jrg): Yet more code dup with BookmarkBarFolderController. +// http://crbug.com/35966 - (BOOL)dragButton:(BookmarkButton*)sourceButton to:(NSPoint)point copy:(BOOL)copy { DCHECK([sourceButton isKindOfClass:[BookmarkButton class]]); - const BookmarkNode* sourceNode = [sourceButton bookmarkNode]; - DCHECK(sourceNode); + return [self dragBookmark:sourceNode to:point copy:copy]; +} +// TODO(mrossetti,jrg): Yet more duplicated code. +// http://crbug.com/35966 +- (BOOL)dragBookmark:(const BookmarkNode*)sourceNode + to:(NSPoint)point + copy:(BOOL)copy { + DCHECK(sourceNode); // Drop destination. const BookmarkNode* destParent = NULL; int destIndex = 0; @@ -807,7 +825,7 @@ const NSTimeInterval kBookmarkBarAnimationDuration = 0.12; } else { // Else we're dropping somewhere on the bar, so find the right spot. destParent = bookmarkModel_->GetBookmarkBarNode(); - destIndex = [self indexForDragOfButton:sourceButton toPoint:point]; + destIndex = [self indexForDragToPoint:point]; } // Be sure we don't try and drop a folder into itself. @@ -841,8 +859,7 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { fromArray:(NSArray*)array { for (BookmarkButton* button in array) { // Break early if we've gone too far. - if ((NSMinX([button frame]) > point.x) || - (![button superview])) + if ((NSMinX([button frame]) > point.x) || (![button superview])) return nil; // Careful -- this only applies to the bar with horiz buttons. // Intentionally NOT using NSPointInRect() so that scrolling into @@ -876,6 +893,8 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { // none. Works with both the bookmark buttons and the "Other // Bookmarks" button. Point is in [self view] coordinates. - (BookmarkButton*)buttonForDroppingOnAtPoint:(NSPoint)point { + point = [[self view] convertPoint:point + fromView:[[[self view] window] contentView]]; BookmarkButton* button = [self buttonForDroppingOnAtPoint:point fromArray:buttons_.get()]; // One more chance -- try "Other Bookmarks" and "off the side" (if visible). @@ -919,7 +938,7 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { if (hoverButton_) { // Oops, another one triggered or open. [NSObject cancelPreviousPerformRequestsWithTarget:[hoverButton_ - target]]; + target]]; // Unlike BookmarkBarFolderController, we do not delay the close // of the previous one. Given the lack of diagonal movement, // there is no need, and it feels awkward to do so. See @@ -930,7 +949,7 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { } hoverButton_.reset([button retain]); DCHECK([[hoverButton_ target] - respondsToSelector:@selector(openBookmarkFolderFromButton:)]); + respondsToSelector:@selector(openBookmarkFolderFromButton:)]); [[hoverButton_ target] performSelector:@selector(openBookmarkFolderFromButton:) withObject:hoverButton_ @@ -956,16 +975,19 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { } } +- (void)draggingEnded:(id<NSDraggingInfo>)info { + [self closeFolderAndStopTrackingMenus]; +} + // Return YES if we should show the drop indicator, else NO. - (BOOL)shouldShowIndicatorShownForPoint:(NSPoint)point { return ![self buttonForDroppingOnAtPoint:point]; } // Return the x position for a drop indicator. -- (CGFloat)indicatorPosForDragOfButton:(BookmarkButton*)sourceButton - toPoint:(NSPoint)point { +- (CGFloat)indicatorPosForDragToPoint:(NSPoint)point { CGFloat x = 0; - int destIndex = [self indexForDragOfButton:sourceButton toPoint:point]; + int destIndex = [self indexForDragToPoint:point]; int numButtons = displayedButtonCount_; // If it's a drop strictly between existing buttons ... @@ -986,8 +1008,7 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { [buttons_ objectAtIndex:static_cast<NSUInteger>(destIndex - 1)]; DCHECK(button); NSRect buttonFrame = [button frame]; - x = buttonFrame.origin.x + buttonFrame.size.width + - 0.5 * bookmarks::kBookmarkHorizontalPadding; + x = NSMaxX(buttonFrame) + 0.5 * bookmarks::kBookmarkHorizontalPadding; // Otherwise, put it right at the beginning. } else { @@ -1038,6 +1059,33 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { ![self isAnimatingToState:bookmarks::kDetachedState]; } +- (std::vector<const BookmarkNode*>)retrieveBookmarkDragDataNodes { + std::vector<const BookmarkNode*> dragDataNodes; + BookmarkDragData dragData; + if(dragData.ReadFromDragClipboard()) { + BookmarkModel* bookmarkModel = [self bookmarkModel]; + Profile* profile = bookmarkModel->profile(); + std::vector<const BookmarkNode*> nodes(dragData.GetNodes(profile)); + dragDataNodes.assign(nodes.begin(), nodes.end()); + } + return dragDataNodes; +} + +- (BOOL)dragBookmarkData:(id<NSDraggingInfo>)info { + BOOL dragged = NO; + std::vector<const BookmarkNode*> nodes([self retrieveBookmarkDragDataNodes]); + if (nodes.size()) { + BOOL copy = !([info draggingSourceOperationMask] & NSDragOperationMove); + NSPoint dropPoint = [info draggingLocation]; + for (std::vector<const BookmarkNode*>::const_iterator it = nodes.begin(); + it != nodes.end(); ++it) { + const BookmarkNode* sourceNode = *it; + dragged = [self dragBookmark:sourceNode to:dropPoint copy:copy]; + } + } + return dragged; +} + - (NSWindow*)browserWindow { return [[self view] window]; } @@ -1201,8 +1249,8 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { // Add a tooltip std::string url_string = child->GetURL().possibly_invalid_spec(); NSString* tooltip = [NSString stringWithFormat:@"%@\n%s", - base::SysWideToNSString(child->GetTitle()), - url_string.c_str()]; + base::SysWideToNSString(child->GetTitle()), + url_string.c_str()]; [item setToolTip:tooltip]; } } @@ -1438,11 +1486,11 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { newIndex = parent->IndexOfChild(senderNode) + 1; } BookmarkNameFolderController* controller = - [[BookmarkNameFolderController alloc] - initWithParentWindow:[[self view] window] - profile:browser_->profile() - parent:parent - newIndex:newIndex]; + [[BookmarkNameFolderController alloc] + initWithParentWindow:[[self view] window] + profile:browser_->profile() + parent:parent + newIndex:newIndex]; [controller runAsModalSheet]; } @@ -1461,7 +1509,7 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { // Make sure there are no stale pointers in the pasteboard. This // can be important if a bookmark is deleted (via bookmark sync) // while in the middle of a drag. The "drag completed" code - // (e.g. [BookmarkBarView performDragOperationForBookmark:]) is + // (e.g. [BookmarkBarView performDragOperationForBookmarkButton:]) is // careful enough to bail if there is no data found at "drop" time. // // Unfortunately the clearContents selector is 10.6 only. The best @@ -1633,7 +1681,7 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { NSMutableArray* buttons = [self buttons]; for (NSButton* button in buttons) { if (NSMaxX([button frame]) > (NSMinX([offTheSideButton_ frame]) - - bookmarks::kBookmarkHorizontalPadding)) + bookmarks::kBookmarkHorizontalPadding)) break; [buttonView_ addSubview:button]; ++displayedButtonCount_; @@ -1641,8 +1689,7 @@ static BOOL ValueInRangeInclusive(CGFloat low, CGFloat value, CGFloat high) { NSUInteger removalCount = [buttons count] - (NSUInteger)displayedButtonCount_; if (removalCount > 0) { - NSRange removalRange = - NSMakeRange(displayedButtonCount_, removalCount); + NSRange removalRange = NSMakeRange(displayedButtonCount_, removalCount); [buttons removeObjectsInRange:removalRange]; } } |