| 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
|
|
|