Chromium Code Reviews| OLD | NEW |
|---|---|
| 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_bubble_controller.h" | 5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h" |
| 6 | 6 |
| 7 #include "base/mac/bundle_locations.h" | 7 #include "base/mac/bundle_locations.h" |
| 8 #include "base/mac/mac_util.h" | 8 #include "base/mac/mac_util.h" |
| 9 #include "base/sys_string_conversions.h" | 9 #include "base/sys_string_conversions.h" |
| 10 #include "chrome/browser/bookmarks/bookmark_model.h" | 10 #include "chrome/browser/bookmarks/bookmark_model.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 // An object to represent the ChooseAnotherFolder item in the pop up. | 63 // An object to represent the ChooseAnotherFolder item in the pop up. |
| 64 @interface ChooseAnotherFolder : NSObject | 64 @interface ChooseAnotherFolder : NSObject |
| 65 @end | 65 @end |
| 66 | 66 |
| 67 @implementation ChooseAnotherFolder | 67 @implementation ChooseAnotherFolder |
| 68 @end | 68 @end |
| 69 | 69 |
| 70 @interface BookmarkBubbleController (PrivateAPI) | 70 @interface BookmarkBubbleController (PrivateAPI) |
| 71 - (void)updateBookmarkNode; | 71 - (void)updateBookmarkNode; |
| 72 - (void)fillInFolderList; | 72 - (void)fillInFolderList; |
| 73 - (void)parentWindowWillClose:(NSNotification*)notification; | |
| 74 @end | 73 @end |
| 75 | 74 |
| 76 @implementation BookmarkBubbleController | 75 @implementation BookmarkBubbleController |
| 77 | 76 |
| 78 @synthesize node = node_; | 77 @synthesize node = node_; |
| 79 | 78 |
| 80 + (id)chooseAnotherFolderObject { | 79 + (id)chooseAnotherFolderObject { |
| 81 // Singleton object to act as a representedObject for the "choose another | 80 // Singleton object to act as a representedObject for the "choose another |
| 82 // folder" item in the pop up. | 81 // folder" item in the pop up. |
| 83 static ChooseAnotherFolder* object = nil; | 82 static ChooseAnotherFolder* object = nil; |
| 84 if (!object) { | 83 if (!object) { |
| 85 object = [[ChooseAnotherFolder alloc] init]; | 84 object = [[ChooseAnotherFolder alloc] init]; |
| 86 } | 85 } |
| 87 return object; | 86 return object; |
| 88 } | 87 } |
| 89 | 88 |
| 90 - (id)initWithParentWindow:(NSWindow*)parentWindow | 89 - (id)initWithParentWindow:(NSWindow*)parentWindow |
| 91 model:(BookmarkModel*)model | 90 model:(BookmarkModel*)model |
| 92 node:(const BookmarkNode*)node | 91 node:(const BookmarkNode*)node |
| 93 alreadyBookmarked:(BOOL)alreadyBookmarked { | 92 alreadyBookmarked:(BOOL)alreadyBookmarked { |
| 94 NSString* nibPath = | 93 if ((self = [super initWithWindowNibPath:@"BookmarkBubble" |
| 95 [base::mac::FrameworkBundle() pathForResource:@"BookmarkBubble" | 94 parentWindow:parentWindow |
| 96 ofType:@"nib"]; | 95 anchoredAt:NSZeroPoint])) { |
| 97 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { | |
| 98 parentWindow_ = parentWindow; | |
| 99 model_ = model; | 96 model_ = model; |
| 100 node_ = node; | 97 node_ = node; |
| 101 alreadyBookmarked_ = alreadyBookmarked; | 98 alreadyBookmarked_ = alreadyBookmarked; |
| 102 | |
| 103 // Watch to see if the parent window closes, and if so, close this one. | |
| 104 NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; | |
| 105 [center addObserver:self | |
| 106 selector:@selector(parentWindowWillClose:) | |
| 107 name:NSWindowWillCloseNotification | |
| 108 object:parentWindow_]; | |
| 109 } | 99 } |
| 110 return self; | 100 return self; |
| 111 } | 101 } |
| 112 | 102 |
| 113 - (void)awakeFromNib { | 103 - (void)awakeFromNib { |
| 104 [super awakeFromNib]; | |
| 105 | |
| 114 // Check if NSTextFieldCell supports the method. This check is in place as | 106 // Check if NSTextFieldCell supports the method. This check is in place as |
| 115 // only 10.6 and greater support the setUsesSingleLineMode method. | 107 // only 10.6 and greater support the setUsesSingleLineMode method. |
| 116 // TODO(kushi.p): Remove this when the project hits a 10.6+ only state. | 108 // TODO(kushi.p): Remove this when the project hits a 10.6+ only state. |
| 117 NSTextFieldCell* nameFieldCell_ = [nameTextField_ cell]; | 109 NSTextFieldCell* nameFieldCell_ = [nameTextField_ cell]; |
| 118 if ([nameFieldCell_ | 110 if ([nameFieldCell_ |
| 119 respondsToSelector:@selector(setUsesSingleLineMode:)]) { | 111 respondsToSelector:@selector(setUsesSingleLineMode:)]) { |
| 120 [nameFieldCell_ setUsesSingleLineMode:YES]; | 112 [nameFieldCell_ setUsesSingleLineMode:YES]; |
| 121 } | 113 } |
| 122 } | 114 } |
| 123 | 115 |
| 124 - (void)dealloc { | |
| 125 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
| 126 [super dealloc]; | |
| 127 } | |
| 128 | |
| 129 // If this is a new bookmark somewhere visible (e.g. on the bookmark | 116 // If this is a new bookmark somewhere visible (e.g. on the bookmark |
| 130 // bar), pulse it. Else, call ourself recursively with our parent | 117 // bar), pulse it. Else, call ourself recursively with our parent |
| 131 // until we find something visible to pulse. | 118 // until we find something visible to pulse. |
| 132 - (void)startPulsingBookmarkButton:(const BookmarkNode*)node { | 119 - (void)startPulsingBookmarkButton:(const BookmarkNode*)node { |
| 133 while (node) { | 120 while (node) { |
| 134 if ((node->parent() == model_->bookmark_bar_node()) || | 121 if ((node->parent() == model_->bookmark_bar_node()) || |
| 135 (node == model_->other_node())) { | 122 (node == model_->other_node())) { |
| 136 pulsingBookmarkNode_ = node; | 123 pulsingBookmarkNode_ = node; |
| 137 NSValue *value = [NSValue valueWithPointer:node]; | 124 NSValue *value = [NSValue valueWithPointer:node]; |
| 138 NSDictionary *dict = [NSDictionary | 125 NSDictionary *dict = [NSDictionary |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 | 157 |
| 171 // Close the bookmark bubble without changing anything. Unlike a | 158 // Close the bookmark bubble without changing anything. Unlike a |
| 172 // typical dialog's OK/Cancel, where Cancel is "do nothing", all | 159 // typical dialog's OK/Cancel, where Cancel is "do nothing", all |
| 173 // buttons on the bubble have the capacity to change the bookmark | 160 // buttons on the bubble have the capacity to change the bookmark |
| 174 // model. This is an IBOutlet-looking entry point to remove the | 161 // model. This is an IBOutlet-looking entry point to remove the |
| 175 // dialog without touching the model. | 162 // dialog without touching the model. |
| 176 - (void)dismissWithoutEditing:(id)sender { | 163 - (void)dismissWithoutEditing:(id)sender { |
| 177 [self close]; | 164 [self close]; |
| 178 } | 165 } |
| 179 | 166 |
| 180 - (void)parentWindowWillClose:(NSNotification*)notification { | |
| 181 [self close]; | |
| 182 } | |
| 183 | |
| 184 - (void)windowWillClose:(NSNotification*)notification { | 167 - (void)windowWillClose:(NSNotification*)notification { |
| 185 // We caught a close so we don't need to watch for the parent closing. | 168 // We caught a close so we don't need to watch for the parent closing. |
| 186 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
| 187 bookmark_observer_.reset(NULL); | 169 bookmark_observer_.reset(NULL); |
| 188 chrome_observer_.reset(NULL); | 170 chrome_observer_.reset(NULL); |
| 189 [self stopPulsingBookmarkButton]; | 171 [self stopPulsingBookmarkButton]; |
| 190 [self autorelease]; | 172 [super windowWillClose:notification]; |
| 191 } | 173 } |
| 192 | 174 |
| 193 // We want this to be a child of a browser window. addChildWindow: | 175 // We want this to be a child of a browser window. addChildWindow: |
| 194 // (called from this function) will bring the window on-screen; | 176 // (called from this function) will bring the window on-screen; |
| 195 // unfortunately, [NSWindowController showWindow:] will also bring it | 177 // unfortunately, [NSWindowController showWindow:] will also bring it |
|
Nico
2012/03/15 21:21:34
Is this comment still needed? Maybe just "Override
Robert Sesek
2012/03/16 15:31:08
Done.
| |
| 196 // on-screen (but will cause unexpected changes to the window's | 178 // on-screen (but will cause unexpected changes to the window's |
| 197 // position). We cannot have an addChildWindow: and a subsequent | 179 // position). We cannot have an addChildWindow: and a subsequent |
| 198 // showWindow:. Thus, we have our own version. | 180 // showWindow:. Thus, we have our own version. |
| 199 - (void)showWindow:(id)sender { | 181 - (void)showWindow:(id)sender { |
| 182 NSWindow* window = [self window]; // Force load the NIB. | |
| 183 NSWindow* parentWindow = self.parentWindow; | |
| 200 BrowserWindowController* bwc = | 184 BrowserWindowController* bwc = |
| 201 [BrowserWindowController browserWindowControllerForWindow:parentWindow_]; | 185 [BrowserWindowController browserWindowControllerForWindow:parentWindow]; |
| 202 [bwc lockBarVisibilityForOwner:self withAnimation:NO delay:NO]; | 186 [bwc lockBarVisibilityForOwner:self withAnimation:NO delay:NO]; |
| 203 NSWindow* window = [self window]; // completes nib load | 187 |
| 204 [bubble_ setArrowLocation:info_bubble::kTopRight]; | 188 InfoBubbleView* bubble = self.bubble; |
| 189 [bubble setArrowLocation:info_bubble::kTopRight]; | |
| 190 | |
| 205 // Insure decent positioning even in the absence of a browser controller, | 191 // Insure decent positioning even in the absence of a browser controller, |
| 206 // which will occur for some unit tests. | 192 // which will occur for some unit tests. |
| 207 NSPoint arrowtip = bwc ? [bwc bookmarkBubblePoint] : | 193 NSPoint arrowTip = bwc ? [bwc bookmarkBubblePoint] : |
| 208 NSMakePoint([window frame].size.width, [window frame].size.height); | 194 NSMakePoint([window frame].size.width, [window frame].size.height); |
| 209 NSPoint origin = [parentWindow_ convertBaseToScreen:arrowtip]; | 195 arrowTip = [parentWindow convertBaseToScreen:arrowTip]; |
| 210 NSPoint bubbleArrowtip = [bubble_ arrowTip]; | 196 NSPoint bubbleArrowTip = [bubble arrowTip]; |
| 211 bubbleArrowtip = [bubble_ convertPoint:bubbleArrowtip toView:nil]; | 197 bubbleArrowTip = [bubble convertPoint:bubbleArrowTip toView:nil]; |
| 212 origin.y -= bubbleArrowtip.y; | 198 arrowTip.y -= bubbleArrowTip.y; |
| 213 origin.x -= bubbleArrowtip.x; | 199 arrowTip.x -= bubbleArrowTip.x; |
| 214 [window setFrameOrigin:origin]; | 200 [window setFrameOrigin:arrowTip]; |
| 215 [parentWindow_ addChildWindow:window ordered:NSWindowAbove]; | 201 |
| 216 // Default is IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK; "Bookmark". | 202 // Default is IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK; "Bookmark". |
| 217 // If adding for the 1st time the string becomes "Bookmark Added!" | 203 // If adding for the 1st time the string becomes "Bookmark Added!" |
| 218 if (!alreadyBookmarked_) { | 204 if (!alreadyBookmarked_) { |
| 219 NSString* title = | 205 NSString* title = |
| 220 l10n_util::GetNSString(IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED); | 206 l10n_util::GetNSString(IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED); |
| 221 [bigTitle_ setStringValue:title]; | 207 [bigTitle_ setStringValue:title]; |
| 222 } | 208 } |
| 223 | 209 |
| 224 [self fillInFolderList]; | 210 [self fillInFolderList]; |
| 225 | 211 |
| 226 // Ping me when things change out from under us. Unlike a normal | 212 // Ping me when things change out from under us. Unlike a normal |
| 227 // dialog, the bookmark bubble's cancel: means "don't add this as a | 213 // dialog, the bookmark bubble's cancel: means "don't add this as a |
| 228 // bookmark", not "cancel editing". We must take extra care to not | 214 // bookmark", not "cancel editing". We must take extra care to not |
| 229 // touch the bookmark in this selector. | 215 // touch the bookmark in this selector. |
| 230 bookmark_observer_.reset(new BookmarkModelObserverForCocoa( | 216 bookmark_observer_.reset(new BookmarkModelObserverForCocoa( |
| 231 node_, model_, | 217 node_, model_, |
| 232 self, | 218 self, |
| 233 @selector(dismissWithoutEditing:))); | 219 @selector(dismissWithoutEditing:))); |
| 234 chrome_observer_.reset(new BookmarkBubbleNotificationBridge( | 220 chrome_observer_.reset(new BookmarkBubbleNotificationBridge( |
| 235 self, @selector(dismissWithoutEditing:))); | 221 self, @selector(dismissWithoutEditing:))); |
| 236 | 222 |
| 237 // Pulse something interesting on the bookmark bar. | 223 // Pulse something interesting on the bookmark bar. |
| 238 [self startPulsingBookmarkButton:node_]; | 224 [self startPulsingBookmarkButton:node_]; |
| 239 | 225 |
| 226 [parentWindow addChildWindow:window ordered:NSWindowAbove]; | |
| 240 [window makeKeyAndOrderFront:self]; | 227 [window makeKeyAndOrderFront:self]; |
| 241 } | 228 } |
| 242 | 229 |
| 243 - (void)close { | 230 - (void)close { |
| 244 [[BrowserWindowController browserWindowControllerForWindow:parentWindow_] | 231 [[BrowserWindowController browserWindowControllerForWindow:self.parentWindow] |
| 245 releaseBarVisibilityForOwner:self withAnimation:YES delay:NO]; | 232 releaseBarVisibilityForOwner:self withAnimation:YES delay:NO]; |
| 246 [parentWindow_ removeChildWindow:[self window]]; | |
| 247 | |
| 248 // If you quit while the bubble is open, sometimes we get a | |
| 249 // DidResignKey before we get our parent's WindowWillClose and | |
| 250 // sometimes not. We protect against a multiple close (or reference | |
| 251 // to parentWindow_ at a bad time) by clearing it out once we're | |
| 252 // done, and by removing ourself from future notifications. | |
| 253 [[NSNotificationCenter defaultCenter] | |
| 254 removeObserver:self | |
| 255 name:NSWindowWillCloseNotification | |
| 256 object:parentWindow_]; | |
| 257 parentWindow_ = nil; | |
| 258 | 233 |
| 259 [super close]; | 234 [super close]; |
| 260 } | 235 } |
| 261 | 236 |
| 262 // Shows the bookmark editor sheet for more advanced editing. | 237 // Shows the bookmark editor sheet for more advanced editing. |
| 263 - (void)showEditor { | 238 - (void)showEditor { |
| 264 [self ok:self]; | 239 [self ok:self]; |
| 265 // Send the action up through the responder chain. | 240 // Send the action up through the responder chain. |
| 266 [NSApp sendAction:@selector(editBookmarkNode:) to:nil from:self]; | 241 [NSApp sendAction:@selector(editBookmarkNode:) to:nil from:self]; |
| 267 } | 242 } |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 297 [self ok:sender]; | 272 [self ok:sender]; |
| 298 } | 273 } |
| 299 | 274 |
| 300 // The controller is the target of the pop up button box action so it can | 275 // The controller is the target of the pop up button box action so it can |
| 301 // handle when "choose another folder" was picked. | 276 // handle when "choose another folder" was picked. |
| 302 - (IBAction)folderChanged:(id)sender { | 277 - (IBAction)folderChanged:(id)sender { |
| 303 DCHECK([sender isEqual:folderPopUpButton_]); | 278 DCHECK([sender isEqual:folderPopUpButton_]); |
| 304 // It is possible that due to model change our parent window has been closed | 279 // It is possible that due to model change our parent window has been closed |
| 305 // but the popup is still showing and able to notify the controller of a | 280 // but the popup is still showing and able to notify the controller of a |
| 306 // folder change. We ignore the sender in this case. | 281 // folder change. We ignore the sender in this case. |
| 307 if (!parentWindow_) | 282 if (!self.parentWindow) |
| 308 return; | 283 return; |
| 309 NSMenuItem* selected = [folderPopUpButton_ selectedItem]; | 284 NSMenuItem* selected = [folderPopUpButton_ selectedItem]; |
| 310 ChooseAnotherFolder* chooseItem = [[self class] chooseAnotherFolderObject]; | 285 ChooseAnotherFolder* chooseItem = [[self class] chooseAnotherFolderObject]; |
| 311 if ([[selected representedObject] isEqual:chooseItem]) { | 286 if ([[selected representedObject] isEqual:chooseItem]) { |
| 312 content::RecordAction( | 287 content::RecordAction( |
| 313 UserMetricsAction("BookmarkBubble_EditFromCombobox")); | 288 UserMetricsAction("BookmarkBubble_EditFromCombobox")); |
| 314 [self showEditor]; | 289 [self showEditor]; |
| 315 } | 290 } |
| 316 } | 291 } |
| 317 | 292 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 [item setRepresentedObject:obj]; | 350 [item setRepresentedObject:obj]; |
| 376 // Finally, select the current parent. | 351 // Finally, select the current parent. |
| 377 NSValue* parentValue = [NSValue valueWithPointer:node_->parent()]; | 352 NSValue* parentValue = [NSValue valueWithPointer:node_->parent()]; |
| 378 NSInteger idx = [menu indexOfItemWithRepresentedObject:parentValue]; | 353 NSInteger idx = [menu indexOfItemWithRepresentedObject:parentValue]; |
| 379 [folderPopUpButton_ selectItemAtIndex:idx]; | 354 [folderPopUpButton_ selectItemAtIndex:idx]; |
| 380 } | 355 } |
| 381 | 356 |
| 382 @end // BookmarkBubbleController | 357 @end // BookmarkBubbleController |
| 383 | 358 |
| 384 | 359 |
| 385 @implementation BookmarkBubbleController(ExposedForUnitTesting) | 360 @implementation BookmarkBubbleController (ExposedForUnitTesting) |
| 386 | 361 |
| 387 + (NSString*)chooseAnotherFolderString { | 362 + (NSString*)chooseAnotherFolderString { |
| 388 return l10n_util::GetNSStringWithFixup( | 363 return l10n_util::GetNSStringWithFixup( |
| 389 IDS_BOOKMARK_BUBBLE_CHOOSER_ANOTHER_FOLDER); | 364 IDS_BOOKMARK_BUBBLE_CHOOSER_ANOTHER_FOLDER); |
| 390 } | 365 } |
| 391 | 366 |
| 392 // For the given folder node, walk the tree and add folder names to | 367 // For the given folder node, walk the tree and add folder names to |
| 393 // the given pop up button. | 368 // the given pop up button. |
| 394 - (void)addFolderNodes:(const BookmarkNode*)parent | 369 - (void)addFolderNodes:(const BookmarkNode*)parent |
| 395 toPopUpButton:(NSPopUpButton*)button | 370 toPopUpButton:(NSPopUpButton*)button |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 428 NSInteger idx = [menu indexOfItemWithRepresentedObject:parentValue]; | 403 NSInteger idx = [menu indexOfItemWithRepresentedObject:parentValue]; |
| 429 DCHECK(idx != -1); | 404 DCHECK(idx != -1); |
| 430 [folderPopUpButton_ selectItemAtIndex:idx]; | 405 [folderPopUpButton_ selectItemAtIndex:idx]; |
| 431 } | 406 } |
| 432 | 407 |
| 433 - (NSPopUpButton*)folderPopUpButton { | 408 - (NSPopUpButton*)folderPopUpButton { |
| 434 return folderPopUpButton_; | 409 return folderPopUpButton_; |
| 435 } | 410 } |
| 436 | 411 |
| 437 @end // implementation BookmarkBubbleController(ExposedForUnitTesting) | 412 @end // implementation BookmarkBubbleController(ExposedForUnitTesting) |
| OLD | NEW |