Index: chrome/browser/cocoa/bookmark_editor_controller.mm |
=================================================================== |
--- chrome/browser/cocoa/bookmark_editor_controller.mm (revision 30403) |
+++ chrome/browser/cocoa/bookmark_editor_controller.mm (working copy) |
@@ -2,27 +2,47 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "app/l10n_util.h" |
#include "base/logging.h" |
#include "base/mac_util.h" |
#include "base/sys_string_conversions.h" |
#include "chrome/browser/bookmarks/bookmark_editor.h" |
#include "chrome/browser/bookmarks/bookmark_model.h" |
#include "chrome/browser/profile.h" |
+#import "chrome/browser/cocoa/bookmark_tree_browser_cell.h" |
#import "chrome/browser/cocoa/bookmark_editor_controller.h" |
+#include "grit/generated_resources.h" |
@interface BookmarkEditorController (Private) |
// Grab the url from the text field and convert. |
- (GURL)GURLFromUrlField; |
+// Given a cell in the folder browser, make that cell editable so that the |
+// bookmark folder name can be modified by the user. |
+- (void)editFolderNameInCell:(BookmarkTreeBrowserCell*)cell; |
+ |
+// The action called by the bookmark folder name cell being edited by |
+// the user when editing has been completed (such as by pressing <return>). |
+- (void)cellEditingCompleted:(id)sender; |
+ |
+// Update the folder name from the current edit in the given cell |
+// and return the focus to the folder tree browser. |
+- (void)saveFolderNameForCell:(BookmarkTreeBrowserCell*)cell; |
+ |
+// A custom action handler called by the bookmark folder browser when the |
+// user has double-clicked on a folder name. |
+- (void)browserDoubleClicked:(id)sender; |
+ |
// Determine and returns the rightmost selected/highlighted element (node) |
// in the bookmark tree view if the tree view is showing, otherwise returns |
// the original parentNode_. If the tree view is showing but nothing is |
-// selected then return the root node. |
-- (const BookmarkNode*)selectedParentNode; |
+// selected then return the root node. This assumes that leaf nodes (pure |
+// bookmarks) are not being presented. |
+- (const BookmarkNode*)selectedNode; |
// Select/highlight the given node within the browser tree view. If the |
-// node is not found then the selection will not be changed. |
+// node is nil then select the bookmark bar. |
- (void)selectNodeInBrowser:(const BookmarkNode*)node; |
@end |
@@ -131,42 +151,23 @@ |
// Remember the NSBrowser's height; we will shrink our frame by that |
// much. |
NSRect frame = [[self window] frame]; |
- CGFloat browserHeight = [browser_ frame].size.height; |
+ CGFloat browserHeight = [folderBrowser_ frame].size.height; |
frame.size.height -= browserHeight; |
frame.origin.y += browserHeight; |
// Remove the NSBrowser and "new folder" button. |
- [browser_ removeFromSuperview]; |
+ [folderBrowser_ removeFromSuperview]; |
[newFolderButton_ removeFromSuperview]; |
// Finally, commit the size change. |
[[self window] setFrame:frame display:YES]; |
} |
-} |
-- (void)selectNodeInBrowser:(const BookmarkNode*)node { |
- DCHECK(configuration_ == BookmarkEditor::SHOW_TREE); |
- // Find and select the node in the browser by walking |
- // back to the root node, then selecting forward. |
- std::deque<NSInteger> rowsToSelect; |
- const BookmarkNode* nodeParent = node->GetParent(); |
- // There should always be a parent node. |
- DCHECK(nodeParent); |
- while (nodeParent) { |
- int nodeRow = IndexOfFolderChild(node); |
- rowsToSelect.push_front(nodeRow); |
- node = nodeParent; |
- nodeParent = nodeParent->GetParent(); |
- } |
- for (std::deque<NSInteger>::size_type column = 0; |
- column < rowsToSelect.size(); |
- ++column) { |
- [browser_ selectRow:rowsToSelect[column] inColumn:column]; |
- } |
- [self controlTextDidChange:nil]; |
+ [folderBrowser_ setCellClass:[BookmarkTreeBrowserCell class]]; |
+ [folderBrowser_ setDoubleAction:@selector(browserDoubleClicked:)]; |
} |
- (void)windowDidLoad { |
if (configuration_ == BookmarkEditor::SHOW_TREE) { |
- // Find and select the |parent| bookmark node. |
+ // Find and select the |parent| bookmark node in the folder tree browser. |
[self selectNodeInBrowser:parentNode_]; |
} |
} |
@@ -191,15 +192,115 @@ |
contextInfo:nil]; |
} |
-// TODO(jrg) |
-- (IBAction)newFolder:(id)sender { |
- NOTIMPLEMENTED(); |
+- (void)selectNodeInBrowser:(const BookmarkNode*)node { |
+ DCHECK(configuration_ == BookmarkEditor::SHOW_TREE); |
+ std::deque<NSInteger> rowsToSelect; |
+ const BookmarkNode* nodeParent = nil; |
+ if (node) { |
+ nodeParent = node->GetParent(); |
+ // There should always be a parent node. |
+ DCHECK(nodeParent); |
+ while (nodeParent) { |
+ int nodeRow = IndexOfFolderChild(node); |
+ rowsToSelect.push_front(nodeRow); |
+ node = nodeParent; |
+ nodeParent = nodeParent->GetParent(); |
+ } |
+ } else { |
+ BookmarkModel* model = profile_->GetBookmarkModel(); |
+ nodeParent = model->GetBookmarkBarNode(); |
+ rowsToSelect.push_front(0); |
+ } |
+ for (std::deque<NSInteger>::size_type column = 0; |
+ column < rowsToSelect.size(); |
+ ++column) { |
+ [folderBrowser_ selectRow:rowsToSelect[column] inColumn:column]; |
+ } |
+ [self controlTextDidChange:nil]; |
} |
-- (IBAction)cancel:(id)sender { |
- [NSApp endSheet:[self window]]; |
+- (const BookmarkNode*)selectedNode { |
+ BookmarkModel* model = profile_->GetBookmarkModel(); |
+ const BookmarkNode* selectedNode = NULL; |
+ // Determine a new parent node only if the browser is showing. |
+ if (configuration_ == BookmarkEditor::SHOW_TREE) { |
+ selectedNode = model->root_node(); |
+ NSInteger column = 0; |
+ NSInteger selectedRow = [folderBrowser_ selectedRowInColumn:column]; |
+ while (selectedRow >= 0) { |
+ selectedNode = GetFolderChildForParent(selectedNode, |
+ selectedRow); |
+ ++column; |
+ selectedRow = [folderBrowser_ selectedRowInColumn:column]; |
+ } |
+ } else { |
+ // If the tree is not showing then we use the original parent. |
+ selectedNode = parentNode_; |
+ } |
+ return selectedNode; |
} |
+#pragma mark New Folder Handler & Folder Cell Editing |
+ |
+- (void)editFolderNameInCell:(BookmarkTreeBrowserCell*)cell { |
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); |
+ [cell setEditable:YES]; |
+ [cell setTarget:self]; |
+ [cell setAction:@selector(cellEditingCompleted:)]; |
+ [cell setSendsActionOnEndEditing:YES]; |
+ currentEditCell_.reset([cell retain]); |
+ NSMatrix* matrix = [cell matrix]; |
+ // Set the delegate so that we get called when editing wants to complete. |
+ [matrix setDelegate:self]; |
+ [matrix selectText:self]; |
+} |
+ |
+- (void)cellEditingCompleted:(id)sender { |
+ DCHECK([sender isKindOfClass:[NSMatrix class]]); |
+ BookmarkTreeBrowserCell* cell = [sender selectedCell]; |
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); |
+ [self saveFolderNameForCell:cell]; |
+} |
+ |
+- (void)saveFolderNameForCell:(BookmarkTreeBrowserCell*)cell { |
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); |
+ // It's possible that the cell can get reused so clean things up |
+ // to prevent inadvertant notifications. |
+ [cell setTarget:nil]; |
+ [cell setAction:nil]; |
+ [cell setEditable:NO]; |
+ [cell setSendsActionOnEndEditing:NO]; |
+ // Force a responder change here to force the editing of the cell's text |
+ // to complete otherwise the call to -[cell title] could return stale text. |
+ [[folderBrowser_ window] makeFirstResponder:folderBrowser_]; |
+ const BookmarkNode* bookmarkNode = [cell bookmarkNode]; |
+ BookmarkModel* model = profile_->GetBookmarkModel(); |
+ NSString* newTitle = [cell title]; |
+ model->SetTitle(bookmarkNode, base::SysNSStringToWide(newTitle)); |
+ currentEditCell_.reset(); |
+} |
+ |
+- (void)browserDoubleClicked:(id)sender { |
+ BookmarkTreeBrowserCell* cell = [folderBrowser_ selectedCell]; |
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); |
+ [self editFolderNameInCell:cell]; |
+} |
+ |
+- (IBAction)newFolder:(id)sender { |
+ BookmarkModel* model = profile_->GetBookmarkModel(); |
+ const BookmarkNode* newParentNode = [self selectedNode]; |
+ int newIndex = newParentNode->GetChildCount(); |
+ std::wstring newFolderString = |
+ l10n_util::GetString(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME); |
+ const BookmarkNode* newFolder = model->AddGroup(newParentNode, newIndex, |
+ newFolderString); |
+ [self selectNodeInBrowser:newFolder]; |
+ BookmarkTreeBrowserCell* cell = [folderBrowser_ selectedCell]; |
+ [self editFolderNameInCell:cell]; |
+} |
+ |
+#pragma mark Bookmark Editing |
+ |
// If possible, return a valid GURL from the URL text field. |
- (GURL)GURLFromUrlField { |
NSString* url = [urlField_ stringValue]; |
@@ -211,27 +312,6 @@ |
return newURL; |
} |
-- (const BookmarkNode*)selectedParentNode { |
- BookmarkModel* model = profile_->GetBookmarkModel(); |
- const BookmarkNode* selectedParentNode = NULL; |
- // Determine a new parent node only if the browser is showing. |
- if (configuration_ == BookmarkEditor::SHOW_TREE) { |
- selectedParentNode = model->root_node(); |
- NSInteger column = 0; |
- NSInteger selectedRow = [browser_ selectedRowInColumn:column]; |
- while (selectedRow >= 0) { |
- selectedParentNode = GetFolderChildForParent(selectedParentNode, |
- selectedRow); |
- ++column; |
- selectedRow = [browser_ selectedRowInColumn:column]; |
- } |
- } else { |
- // If the tree is not showing then we use the original parent. |
- selectedParentNode = parentNode_; |
- } |
- return selectedParentNode; |
-} |
- |
// Enable the OK button if there is a bookmark name and there is a valid URL. |
// We set ourselves as the delegate of urlField_ so this gets called. |
// (Yes, setting ourself as a delegate automatically registers us for |
@@ -261,7 +341,7 @@ |
} |
// Determine where the new/replacement bookmark is to go. |
- const BookmarkNode* newParentNode = [self selectedParentNode]; |
+ const BookmarkNode* newParentNode = [self selectedNode]; |
BookmarkModel* model = profile_->GetBookmarkModel(); |
int newIndex = newParentNode->GetChildCount(); |
if (node_ && parentNode_) { |
@@ -281,9 +361,20 @@ |
[NSApp endSheet:[self window]]; |
} |
+- (IBAction)cancel:(id)sender { |
+ [NSApp endSheet:[self window]]; |
+} |
+ |
- (void)didEndSheet:(NSWindow*)sheet |
returnCode:(int)returnCode |
contextInfo:(void*)contextInfo { |
+ // If a folder name cell is being edited then force it to end editing |
+ // so that any changes are recorded. |
+ BookmarkTreeBrowserCell* currentEditCell = currentEditCell_.get(); |
+ if (currentEditCell) { |
+ [self saveFolderNameForCell:currentEditCell]; |
+ currentEditCell_.reset(); |
+ } |
// This is probably unnecessary but it feels cleaner since the |
// delegate of a text field can be automatically registered for |
// notifications. |
@@ -336,8 +427,8 @@ |
BookmarkModel* model = profile_->GetBookmarkModel(); |
const BookmarkNode* node = model->root_node(); |
for (NSInteger i = 0; i < column; ++i) { |
- NSInteger selectedRowInColumn = [browser_ selectedRowInColumn:i]; |
- node = node->GetChild(selectedRowInColumn); |
+ NSInteger selectedRowInColumn = [folderBrowser_ selectedRowInColumn:i]; |
+ node = GetFolderChildForParent(node, selectedRowInColumn); |
} |
return node; |
} |
@@ -363,14 +454,18 @@ |
- (void)browser:(NSBrowser*)sender |
willDisplayCell:(NSBrowserCell*)cell |
atRow:(NSInteger)row |
- column:(NSInteger)column { |
+ column:(NSInteger)column { |
DCHECK(row >= 0); // Trust AppKit, but verify. |
DCHECK(column >= 0); |
+ DCHECK([cell isKindOfClass:[BookmarkTreeBrowserCell class]]); |
const BookmarkNode* parentNode = [self parentNodeForColumn:column]; |
const BookmarkNode* childNode = GetFolderChildForParent(parentNode, row); |
DCHECK(childNode); |
- [cell setTitle:base::SysWideToNSString(childNode->GetTitle())]; |
- [cell setLeaf:childNode->GetChildCount() == 0]; |
+ BookmarkTreeBrowserCell* browserCell = |
+ static_cast<BookmarkTreeBrowserCell*>(cell); |
+ [browserCell setTitle:base::SysWideToNSString(childNode->GetTitle())]; |
+ [browserCell setBookmarkNode:childNode]; |
+ [browserCell setMatrix:[folderBrowser_ matrixInColumn:column]]; |
} |
@end // BookmarkEditorController |