| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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_editor_controller.h" |
| 5 #include "app/l10n_util.h" | 6 #include "app/l10n_util.h" |
| 6 #include "base/logging.h" | |
| 7 #include "base/mac_util.h" | |
| 8 #include "base/sys_string_conversions.h" | 7 #include "base/sys_string_conversions.h" |
| 9 #include "chrome/browser/bookmarks/bookmark_editor.h" | |
| 10 #include "chrome/browser/bookmarks/bookmark_model.h" | 8 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 11 #include "chrome/browser/profile.h" | |
| 12 #import "chrome/browser/cocoa/bookmark_tree_browser_cell.h" | |
| 13 #import "chrome/browser/cocoa/bookmark_editor_controller.h" | |
| 14 #include "grit/generated_resources.h" | |
| 15 | 9 |
| 16 @interface BookmarkEditorController (Private) | 10 @interface BookmarkEditorController (Private) |
| 17 | 11 |
| 18 // Grab the url from the text field and convert. | 12 // Grab the url from the text field and convert. |
| 19 - (GURL)GURLFromUrlField; | 13 - (GURL)GURLFromUrlField; |
| 20 | 14 |
| 21 // Given a cell in the folder browser, make that cell editable so that the | |
| 22 // bookmark folder name can be modified by the user. | |
| 23 - (void)editFolderNameInCell:(BookmarkTreeBrowserCell*)cell; | |
| 24 | |
| 25 // The action called by the bookmark folder name cell being edited by | |
| 26 // the user when editing has been completed (such as by pressing <return>). | |
| 27 - (void)cellEditingCompleted:(id)sender; | |
| 28 | |
| 29 // Update the folder name from the current edit in the given cell | |
| 30 // and return the focus to the folder tree browser. | |
| 31 - (void)saveFolderNameForCell:(BookmarkTreeBrowserCell*)cell; | |
| 32 | |
| 33 // A custom action handler called by the bookmark folder browser when the | |
| 34 // user has double-clicked on a folder name. | |
| 35 - (void)browserDoubleClicked:(id)sender; | |
| 36 | |
| 37 // Determine and returns the rightmost selected/highlighted element (node) | |
| 38 // in the bookmark tree view if the tree view is showing, otherwise returns | |
| 39 // the original parentNode_. If the tree view is showing but nothing is | |
| 40 // selected then return the root node. This assumes that leaf nodes (pure | |
| 41 // bookmarks) are not being presented. | |
| 42 - (const BookmarkNode*)selectedNode; | |
| 43 | |
| 44 // Select/highlight the given node within the browser tree view. If the | |
| 45 // node is nil then select the bookmark bar. | |
| 46 - (void)selectNodeInBrowser:(const BookmarkNode*)node; | |
| 47 | |
| 48 @end | 15 @end |
| 49 | 16 |
| 50 // static; implemented for each platform. | 17 @implementation BookmarkEditorController |
| 51 void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, | 18 |
| 52 Profile* profile, | 19 @synthesize displayURL = displayURL_; |
| 53 const BookmarkNode* parent, | 20 |
| 54 const EditDetails& details, | 21 + (NSSet*)keyPathsForValuesAffectingOkEnabled { |
| 55 Configuration configuration, | 22 return [NSSet setWithObject:@"displayURL"]; |
| 56 Handler* handler) { | |
| 57 if (details.type == EditDetails::NEW_FOLDER) { | |
| 58 // TODO(sky): implement this. | |
| 59 NOTIMPLEMENTED(); | |
| 60 return; | |
| 61 } | |
| 62 BookmarkEditorController* controller = [[BookmarkEditorController alloc] | |
| 63 initWithParentWindow:parent_hwnd | |
| 64 profile:profile | |
| 65 parent:parent | |
| 66 node:details.existing_node | |
| 67 configuration:configuration | |
| 68 handler:handler]; | |
| 69 [controller runAsModalSheet]; | |
| 70 } | 23 } |
| 71 | 24 |
| 72 #pragma mark Bookmark TreeNode Helpers | |
| 73 | |
| 74 namespace { | |
| 75 | |
| 76 // Find the index'th folder child of a parent, ignoring bookmarks (leafs). | |
| 77 const BookmarkNode* GetFolderChildForParent(const BookmarkNode* parent_node, | |
| 78 NSInteger folder_index) { | |
| 79 const BookmarkNode* child_node = nil; | |
| 80 int i = 0; | |
| 81 int child_count = parent_node->GetChildCount(); | |
| 82 do { | |
| 83 child_node = parent_node->GetChild(i); | |
| 84 if (child_node->type() != BookmarkNode::URL) | |
| 85 --folder_index; | |
| 86 ++i; | |
| 87 } while (folder_index >= 0 && i < child_count); | |
| 88 return child_node; | |
| 89 } | |
| 90 | |
| 91 // Determine the index of a child within its parent ignoring | |
| 92 // bookmarks (leafs). | |
| 93 int IndexOfFolderChild(const BookmarkNode* child_node) { | |
| 94 const BookmarkNode* node_parent = child_node->GetParent(); | |
| 95 int child_index = node_parent->IndexOfChild(child_node); | |
| 96 for (int i = child_index - 1; i >= 0; --i) { | |
| 97 const BookmarkNode* sibling = node_parent->GetChild(i); | |
| 98 if (sibling->type() == BookmarkNode::URL) | |
| 99 --child_index; | |
| 100 } | |
| 101 return child_index; | |
| 102 } | |
| 103 | |
| 104 } // namespace | |
| 105 | |
| 106 @implementation BookmarkEditorController | |
| 107 | |
| 108 - (id)initWithParentWindow:(NSWindow*)parentWindow | 25 - (id)initWithParentWindow:(NSWindow*)parentWindow |
| 109 profile:(Profile*)profile | 26 profile:(Profile*)profile |
| 110 parent:(const BookmarkNode*)parent | 27 parent:(const BookmarkNode*)parent |
| 111 node:(const BookmarkNode*)node | 28 node:(const BookmarkNode*)node |
| 112 configuration:(BookmarkEditor::Configuration)configuration | 29 configuration:(BookmarkEditor::Configuration)configuration |
| 113 handler:(BookmarkEditor::Handler*)handler { | 30 handler:(BookmarkEditor::Handler*)handler { |
| 114 NSString* nibpath = [mac_util::MainAppBundle() | 31 if ((self = [super initWithParentWindow:parentWindow |
| 115 pathForResource:@"BookmarkEditor" | 32 nibName:@"BookmarkEditor" |
| 116 ofType:@"nib"]; | 33 profile:profile |
| 117 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { | 34 parent:parent |
| 118 parentWindow_ = parentWindow; | 35 configuration:configuration |
| 119 profile_ = profile; | 36 handler:handler])) { |
| 120 parentNode_ = parent; | |
| 121 // "Add Page..." has no "node" so this may be NULL. | 37 // "Add Page..." has no "node" so this may be NULL. |
| 122 node_ = node; | 38 node_ = node; |
| 123 configuration_ = configuration; | |
| 124 handler_.reset(handler); | |
| 125 } | 39 } |
| 126 return self; | 40 return self; |
| 127 } | 41 } |
| 128 | 42 |
| 43 - (void)dealloc { |
| 44 [displayURL_ release]; |
| 45 [super dealloc]; |
| 46 } |
| 47 |
| 129 - (void)awakeFromNib { | 48 - (void)awakeFromNib { |
| 130 // Set text fields to match our bookmark. If the node is NULL we | 49 // Set text fields to match our bookmark. If the node is NULL we |
| 131 // arrived here from an "Add Page..." item in a context menu. | 50 // arrived here from an "Add Page..." item in a context menu. |
| 132 if (node_) { | 51 if (node_) { |
| 133 initialName_.reset([base::SysWideToNSString(node_->GetTitle()) retain]); | 52 [self setInitialName:base::SysWideToNSString(node_->GetTitle())]; |
| 134 std::string url_string = node_->GetURL().possibly_invalid_spec(); | 53 std::string url_string = node_->GetURL().possibly_invalid_spec(); |
| 135 initialUrl_.reset([[NSString stringWithUTF8String:url_string.c_str()] | 54 initialUrl_.reset([[NSString stringWithUTF8String:url_string.c_str()] |
| 136 retain]); | 55 retain]); |
| 137 } else { | 56 } else { |
| 138 initialName_.reset([@"" retain]); | |
| 139 initialUrl_.reset([@"" retain]); | 57 initialUrl_.reset([@"" retain]); |
| 140 } | 58 } |
| 141 [nameField_ setStringValue:initialName_]; | 59 [self setDisplayURL:initialUrl_]; |
| 142 [urlField_ setStringValue:initialUrl_]; | 60 [super awakeFromNib]; |
| 143 | |
| 144 // Get a ping when the URL or name text fields change; | |
| 145 // trigger an initial ping to set things up. | |
| 146 [nameField_ setDelegate:self]; | |
| 147 [urlField_ setDelegate:self]; | |
| 148 [self controlTextDidChange:nil]; | |
| 149 | |
| 150 if (configuration_ != BookmarkEditor::SHOW_TREE) { | |
| 151 // Remember the NSBrowser's height; we will shrink our frame by that | |
| 152 // much. | |
| 153 NSRect frame = [[self window] frame]; | |
| 154 CGFloat browserHeight = [folderBrowser_ frame].size.height; | |
| 155 frame.size.height -= browserHeight; | |
| 156 frame.origin.y += browserHeight; | |
| 157 // Remove the NSBrowser and "new folder" button. | |
| 158 [folderBrowser_ removeFromSuperview]; | |
| 159 [newFolderButton_ removeFromSuperview]; | |
| 160 // Finally, commit the size change. | |
| 161 [[self window] setFrame:frame display:YES]; | |
| 162 } | |
| 163 | |
| 164 [folderBrowser_ setCellClass:[BookmarkTreeBrowserCell class]]; | |
| 165 [folderBrowser_ setDoubleAction:@selector(browserDoubleClicked:)]; | |
| 166 } | |
| 167 | |
| 168 - (void)windowDidLoad { | |
| 169 if (configuration_ == BookmarkEditor::SHOW_TREE) { | |
| 170 // Find and select the |parent| bookmark node in the folder tree browser. | |
| 171 [self selectNodeInBrowser:parentNode_]; | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 - (void)windowWillClose:(NSNotification *)notification { | |
| 176 // If a folder name cell is being edited then force it to end editing | |
| 177 // so that any changes are recorded. | |
| 178 [[self window] makeFirstResponder:nil]; | |
| 179 | |
| 180 // This is probably unnecessary but it feels cleaner since the | |
| 181 // delegate of a text field can be automatically registered for | |
| 182 // notifications. | |
| 183 [nameField_ setDelegate:nil]; | |
| 184 [urlField_ setDelegate:nil]; | |
| 185 [self autorelease]; | |
| 186 } | |
| 187 | |
| 188 /* TODO(jrg): | |
| 189 // Implementing this informal protocol allows us to open the sheet | |
| 190 // somewhere other than at the top of the window. NOTE: this means | |
| 191 // that I, the controller, am also the window's delegate. | |
| 192 - (NSRect)window:(NSWindow*)window willPositionSheet:(NSWindow*)sheet | |
| 193 usingRect:(NSRect)rect { | |
| 194 // adjust rect.origin.y to be the bottom of the toolbar | |
| 195 return rect; | |
| 196 } | |
| 197 */ | |
| 198 | |
| 199 // TODO(jrg): consider NSModalSession. | |
| 200 - (void)runAsModalSheet { | |
| 201 [NSApp beginSheet:[self window] | |
| 202 modalForWindow:parentWindow_ | |
| 203 modalDelegate:self | |
| 204 didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) | |
| 205 contextInfo:nil]; | |
| 206 } | |
| 207 | |
| 208 - (void)selectNodeInBrowser:(const BookmarkNode*)node { | |
| 209 DCHECK(configuration_ == BookmarkEditor::SHOW_TREE); | |
| 210 std::deque<NSInteger> rowsToSelect; | |
| 211 const BookmarkNode* nodeParent = nil; | |
| 212 if (node) { | |
| 213 nodeParent = node->GetParent(); | |
| 214 // There should always be a parent node. | |
| 215 DCHECK(nodeParent); | |
| 216 while (nodeParent) { | |
| 217 int nodeRow = IndexOfFolderChild(node); | |
| 218 rowsToSelect.push_front(nodeRow); | |
| 219 node = nodeParent; | |
| 220 nodeParent = nodeParent->GetParent(); | |
| 221 } | |
| 222 } else { | |
| 223 BookmarkModel* model = profile_->GetBookmarkModel(); | |
| 224 nodeParent = model->GetBookmarkBarNode(); | |
| 225 rowsToSelect.push_front(0); | |
| 226 } | |
| 227 for (std::deque<NSInteger>::size_type column = 0; | |
| 228 column < rowsToSelect.size(); | |
| 229 ++column) { | |
| 230 [folderBrowser_ selectRow:rowsToSelect[column] inColumn:column]; | |
| 231 } | |
| 232 [self controlTextDidChange:nil]; | |
| 233 } | |
| 234 | |
| 235 - (const BookmarkNode*)selectedNode { | |
| 236 BookmarkModel* model = profile_->GetBookmarkModel(); | |
| 237 const BookmarkNode* selectedNode = NULL; | |
| 238 // Determine a new parent node only if the browser is showing. | |
| 239 if (configuration_ == BookmarkEditor::SHOW_TREE) { | |
| 240 selectedNode = model->root_node(); | |
| 241 NSInteger column = 0; | |
| 242 NSInteger selectedRow = [folderBrowser_ selectedRowInColumn:column]; | |
| 243 while (selectedRow >= 0) { | |
| 244 selectedNode = GetFolderChildForParent(selectedNode, | |
| 245 selectedRow); | |
| 246 ++column; | |
| 247 selectedRow = [folderBrowser_ selectedRowInColumn:column]; | |
| 248 } | |
| 249 } else { | |
| 250 // If the tree is not showing then we use the original parent. | |
| 251 selectedNode = parentNode_; | |
| 252 } | |
| 253 return selectedNode; | |
| 254 } | |
| 255 | |
| 256 #pragma mark New Folder Handler & Folder Cell Editing | |
| 257 | |
| 258 - (void)editFolderNameInCell:(BookmarkTreeBrowserCell*)cell { | |
| 259 DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); | |
| 260 [cell setEditable:YES]; | |
| 261 [cell setTarget:self]; | |
| 262 [cell setAction:@selector(cellEditingCompleted:)]; | |
| 263 [cell setSendsActionOnEndEditing:YES]; | |
| 264 NSMatrix* matrix = [cell matrix]; | |
| 265 // Set the delegate so that we get called when editing wants to complete. | |
| 266 [matrix setDelegate:self]; | |
| 267 [matrix selectText:self]; | |
| 268 } | |
| 269 | |
| 270 - (void)cellEditingCompleted:(id)sender { | |
| 271 DCHECK([sender isKindOfClass:[NSMatrix class]]); | |
| 272 BookmarkTreeBrowserCell* cell = [sender selectedCell]; | |
| 273 DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); | |
| 274 [self saveFolderNameForCell:cell]; | |
| 275 } | |
| 276 | |
| 277 - (void)saveFolderNameForCell:(BookmarkTreeBrowserCell*)cell { | |
| 278 DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); | |
| 279 // It's possible that the cell can get reused so clean things up | |
| 280 // to prevent inadvertant notifications. | |
| 281 [cell setTarget:nil]; | |
| 282 [cell setAction:nil]; | |
| 283 [cell setEditable:NO]; | |
| 284 [cell setSendsActionOnEndEditing:NO]; | |
| 285 // Force a responder change here to force the editing of the cell's text | |
| 286 // to complete otherwise the call to -[cell title] could return stale text. | |
| 287 [[folderBrowser_ window] makeFirstResponder:folderBrowser_]; | |
| 288 const BookmarkNode* bookmarkNode = [cell bookmarkNode]; | |
| 289 BookmarkModel* model = profile_->GetBookmarkModel(); | |
| 290 NSString* newTitle = [cell title]; | |
| 291 model->SetTitle(bookmarkNode, base::SysNSStringToWide(newTitle)); | |
| 292 } | |
| 293 | |
| 294 - (void)browserDoubleClicked:(id)sender { | |
| 295 BookmarkTreeBrowserCell* cell = [folderBrowser_ selectedCell]; | |
| 296 DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); | |
| 297 [self editFolderNameInCell:cell]; | |
| 298 } | |
| 299 | |
| 300 - (IBAction)newFolder:(id)sender { | |
| 301 BookmarkModel* model = profile_->GetBookmarkModel(); | |
| 302 const BookmarkNode* newParentNode = [self selectedNode]; | |
| 303 int newIndex = newParentNode->GetChildCount(); | |
| 304 std::wstring newFolderString = | |
| 305 l10n_util::GetString(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME); | |
| 306 const BookmarkNode* newFolder = model->AddGroup(newParentNode, newIndex, | |
| 307 newFolderString); | |
| 308 [self selectNodeInBrowser:newFolder]; | |
| 309 BookmarkTreeBrowserCell* cell = [folderBrowser_ selectedCell]; | |
| 310 [self editFolderNameInCell:cell]; | |
| 311 } | 61 } |
| 312 | 62 |
| 313 #pragma mark Bookmark Editing | 63 #pragma mark Bookmark Editing |
| 314 | 64 |
| 315 // If possible, return a valid GURL from the URL text field. | 65 // If possible, return a valid GURL from the URL text field. |
| 316 - (GURL)GURLFromUrlField { | 66 - (GURL)GURLFromUrlField { |
| 317 NSString* url = [urlField_ stringValue]; | 67 NSString* url = [self displayURL]; |
| 318 GURL newURL = GURL([url UTF8String]); | 68 GURL newURL = GURL([url UTF8String]); |
| 319 if (!newURL.is_valid()) { | 69 if (!newURL.is_valid()) { |
| 320 // Mimic observed friendliness from Windows | 70 // Mimic observed friendliness from Windows |
| 321 newURL = GURL([[NSString stringWithFormat:@"http://%@", url] UTF8String]); | 71 newURL = GURL([[NSString stringWithFormat:@"http://%@", url] UTF8String]); |
| 322 } | 72 } |
| 323 return newURL; | 73 return newURL; |
| 324 } | 74 } |
| 325 | 75 |
| 326 // Enable the OK button if there is a bookmark name and there is a valid URL. | 76 // Enable the OK button if there is a valid URL. |
| 327 // We set ourselves as the delegate of urlField_ so this gets called. | 77 - (BOOL)okEnabled { |
| 328 // (Yes, setting ourself as a delegate automatically registers us for | 78 BOOL okEnabled = NO; |
| 329 // the notification.) | 79 if ([[self displayURL] length]) { |
| 330 - (void)controlTextDidChange:(NSNotification*)aNotification { | 80 GURL newURL = [self GURLFromUrlField]; |
| 331 GURL newURL = [self GURLFromUrlField]; | 81 okEnabled = (newURL.is_valid()) ? YES : NO; |
| 332 [okButton_ setEnabled:(newURL.is_valid()) ? YES : NO]; | 82 } |
| 83 return okEnabled; |
| 333 } | 84 } |
| 334 | 85 |
| 335 // The ok: action is connected to the OK button in the Edit Bookmark window | 86 // The the bookmark's URL is assumed to be valid (otherwise the OK button |
| 336 // of the BookmarkEditor.xib. The the bookmark's name and URL are assumed | 87 // should not be enabled). If the bookmark previously existed then it is |
| 337 // to be valid (otherwise the OK button should not be enabled). If the | 88 // removed from its old folder. The bookmark is then added to its new |
| 338 // bookmark previously existed then it is removed from its old folder. | 89 // folder. If the folder has not changed then the bookmark stays in its |
| 339 // The bookmark is then added to its new folder. If the folder has not | 90 // original position (index) otherwise it is added to the end of the new folder. |
| 340 // changed then the bookmark stays in its original position (index) otherwise | |
| 341 // it is added to the end of the new folder. | |
| 342 - (IBAction)ok:(id)sender { | 91 - (IBAction)ok:(id)sender { |
| 343 NSString* name = [nameField_ stringValue]; | 92 NSString* name = [[self displayName] stringByTrimmingCharactersInSet: |
| 93 [NSCharacterSet newlineCharacterSet]]; |
| 344 std::wstring newTitle = base::SysNSStringToWide(name); | 94 std::wstring newTitle = base::SysNSStringToWide(name); |
| 95 const BookmarkNode* newParentNode = [self selectedNode]; |
| 96 BookmarkModel* model = [self bookmarkModel]; |
| 97 int newIndex = newParentNode->GetChildCount(); |
| 345 GURL newURL = [self GURLFromUrlField]; | 98 GURL newURL = [self GURLFromUrlField]; |
| 346 if (!newURL.is_valid()) { | 99 if (!newURL.is_valid()) { |
| 347 // Shouldn't be reached -- OK button disabled if not valid! | 100 // Shouldn't be reached -- OK button disabled if not valid! |
| 348 NOTREACHED(); | 101 NOTREACHED(); |
| 349 return; | 102 return; |
| 350 } | 103 } |
| 351 | 104 |
| 352 // Determine where the new/replacement bookmark is to go. | 105 // Determine where the new/replacement bookmark is to go. |
| 353 const BookmarkNode* newParentNode = [self selectedNode]; | 106 const BookmarkNode* parentNode = [self parentNode]; |
| 354 BookmarkModel* model = profile_->GetBookmarkModel(); | 107 if (node_ && parentNode) { |
| 355 int newIndex = newParentNode->GetChildCount(); | |
| 356 if (node_ && parentNode_) { | |
| 357 // Replace the old bookmark with the updated bookmark. | 108 // Replace the old bookmark with the updated bookmark. |
| 358 int oldIndex = parentNode_->IndexOfChild(node_); | 109 int oldIndex = parentNode->IndexOfChild(node_); |
| 359 if (oldIndex >= 0) | 110 if (oldIndex >= 0) |
| 360 model->Remove(parentNode_, oldIndex); | 111 model->Remove(parentNode, oldIndex); |
| 361 if (parentNode_ == newParentNode) | 112 if (parentNode == newParentNode) |
| 362 newIndex = oldIndex; | 113 newIndex = oldIndex; |
| 363 } | 114 } |
| 364 // Add bookmark as new node at the end of the newly selected folder. | 115 // Add bookmark as new node at the end of the newly selected folder. |
| 365 const BookmarkNode* node = model->AddURL(newParentNode, newIndex, | 116 const BookmarkNode* node = model->AddURL(newParentNode, newIndex, |
| 366 newTitle, newURL); | 117 newTitle, newURL); |
| 367 // Honor handler semantics: callback on node creation. | 118 // Honor handler semantics: callback on node creation. |
| 368 if (handler_.get()) | 119 [self NotifyHandlerCreatedNode:node]; |
| 369 handler_->NodeCreated(node); | 120 [super ok:sender]; |
| 370 [NSApp endSheet:[self window]]; | |
| 371 } | |
| 372 | |
| 373 - (IBAction)cancel:(id)sender { | |
| 374 [NSApp endSheet:[self window]]; | |
| 375 } | |
| 376 | |
| 377 - (void)didEndSheet:(NSWindow*)sheet | |
| 378 returnCode:(int)returnCode | |
| 379 contextInfo:(void*)contextInfo { | |
| 380 [sheet close]; | |
| 381 } | |
| 382 | |
| 383 #pragma mark For Unit Test Use Only | |
| 384 | |
| 385 - (NSString*)displayName { | |
| 386 return [nameField_ stringValue]; | |
| 387 } | |
| 388 | |
| 389 - (NSString*)displayURL { | |
| 390 return [urlField_ stringValue]; | |
| 391 } | |
| 392 | |
| 393 - (void)setDisplayName:(NSString*)name { | |
| 394 [nameField_ setStringValue:name]; | |
| 395 [self controlTextDidChange:nil]; | |
| 396 } | |
| 397 | |
| 398 - (void)setDisplayURL:(NSString*)name { | |
| 399 [urlField_ setStringValue:name]; | |
| 400 [self controlTextDidChange:nil]; | |
| 401 } | |
| 402 | |
| 403 - (BOOL)okButtonEnabled { | |
| 404 return [okButton_ isEnabled]; | |
| 405 } | |
| 406 | |
| 407 - (void)selectTestNodeInBrowser:(const BookmarkNode*)node { | |
| 408 [self selectNodeInBrowser:node]; | |
| 409 } | |
| 410 | |
| 411 #pragma mark NSBrowser delegate methods | |
| 412 | |
| 413 // Given a column number, determine the parent bookmark folder node for the | |
| 414 // bookmarks being shown in that column. This is done by scanning forward | |
| 415 // from column zero and following the selected row for each column up | |
| 416 // to the parent of the desired column. | |
| 417 - (const BookmarkNode*)parentNodeForColumn:(NSInteger)column { | |
| 418 DCHECK(column >= 0); | |
| 419 BookmarkModel* model = profile_->GetBookmarkModel(); | |
| 420 const BookmarkNode* node = model->root_node(); | |
| 421 for (NSInteger i = 0; i < column; ++i) { | |
| 422 NSInteger selectedRowInColumn = [folderBrowser_ selectedRowInColumn:i]; | |
| 423 node = GetFolderChildForParent(node, selectedRowInColumn); | |
| 424 } | |
| 425 return node; | |
| 426 } | |
| 427 | |
| 428 // This implementation returns the number of folders contained in the parent | |
| 429 // folder node for this column. | |
| 430 // TOTO(mrossetti): Decide if bookmark (i.e. non-folder) nodes should be | |
| 431 // shown, perhaps in gray. | |
| 432 - (NSInteger)browser:(NSBrowser*)sender numberOfRowsInColumn:(NSInteger)col { | |
| 433 NSInteger rowCount = 0; | |
| 434 const BookmarkNode* parentNode = [self parentNodeForColumn:col]; | |
| 435 if (parentNode) { | |
| 436 int childCount = parentNode->GetChildCount(); | |
| 437 for (int i = 0; i < childCount; ++i) { | |
| 438 const BookmarkNode* childNode = parentNode->GetChild(i); | |
| 439 if (childNode->type() != BookmarkNode::URL) | |
| 440 ++rowCount; | |
| 441 } | |
| 442 } | |
| 443 return rowCount; | |
| 444 } | |
| 445 | |
| 446 - (void)browser:(NSBrowser*)sender | |
| 447 willDisplayCell:(NSBrowserCell*)cell | |
| 448 atRow:(NSInteger)row | |
| 449 column:(NSInteger)column { | |
| 450 DCHECK(row >= 0); // Trust AppKit, but verify. | |
| 451 DCHECK(column >= 0); | |
| 452 DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); | |
| 453 const BookmarkNode* parentNode = [self parentNodeForColumn:column]; | |
| 454 const BookmarkNode* childNode = GetFolderChildForParent(parentNode, row); | |
| 455 DCHECK(childNode); | |
| 456 BookmarkTreeBrowserCell* browserCell = | |
| 457 static_cast<BookmarkTreeBrowserCell*>(cell); | |
| 458 [browserCell setTitle:base::SysWideToNSString(childNode->GetTitle())]; | |
| 459 [browserCell setBookmarkNode:childNode]; | |
| 460 [browserCell setMatrix:[folderBrowser_ matrixInColumn:column]]; | |
| 461 } | 121 } |
| 462 | 122 |
| 463 @end // BookmarkEditorController | 123 @end // BookmarkEditorController |
| 464 | 124 |
| OLD | NEW |