summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/bookmark_editor_controller.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/cocoa/bookmark_editor_controller.mm')
-rw-r--r--chrome/browser/cocoa/bookmark_editor_controller.mm430
1 files changed, 45 insertions, 385 deletions
diff --git a/chrome/browser/cocoa/bookmark_editor_controller.mm b/chrome/browser/cocoa/bookmark_editor_controller.mm
index 2915094..8164d4b 100644
--- a/chrome/browser/cocoa/bookmark_editor_controller.mm
+++ b/chrome/browser/cocoa/bookmark_editor_controller.mm
@@ -2,319 +2,69 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#import "chrome/browser/cocoa/bookmark_editor_controller.h"
#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. 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 nil then select the bookmark bar.
-- (void)selectNodeInBrowser:(const BookmarkNode*)node;
-
@end
-// static; implemented for each platform.
-void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd,
- Profile* profile,
- const BookmarkNode* parent,
- const EditDetails& details,
- Configuration configuration,
- Handler* handler) {
- if (details.type == EditDetails::NEW_FOLDER) {
- // TODO(sky): implement this.
- NOTIMPLEMENTED();
- return;
- }
- BookmarkEditorController* controller = [[BookmarkEditorController alloc]
- initWithParentWindow:parent_hwnd
- profile:profile
- parent:parent
- node:details.existing_node
- configuration:configuration
- handler:handler];
- [controller runAsModalSheet];
-}
-
-#pragma mark Bookmark TreeNode Helpers
-
-namespace {
+@implementation BookmarkEditorController
-// Find the index'th folder child of a parent, ignoring bookmarks (leafs).
-const BookmarkNode* GetFolderChildForParent(const BookmarkNode* parent_node,
- NSInteger folder_index) {
- const BookmarkNode* child_node = nil;
- int i = 0;
- int child_count = parent_node->GetChildCount();
- do {
- child_node = parent_node->GetChild(i);
- if (child_node->type() != BookmarkNode::URL)
- --folder_index;
- ++i;
- } while (folder_index >= 0 && i < child_count);
- return child_node;
-}
+@synthesize displayURL = displayURL_;
-// Determine the index of a child within its parent ignoring
-// bookmarks (leafs).
-int IndexOfFolderChild(const BookmarkNode* child_node) {
- const BookmarkNode* node_parent = child_node->GetParent();
- int child_index = node_parent->IndexOfChild(child_node);
- for (int i = child_index - 1; i >= 0; --i) {
- const BookmarkNode* sibling = node_parent->GetChild(i);
- if (sibling->type() == BookmarkNode::URL)
- --child_index;
- }
- return child_index;
++ (NSSet*)keyPathsForValuesAffectingOkEnabled {
+ return [NSSet setWithObject:@"displayURL"];
}
-} // namespace
-
-@implementation BookmarkEditorController
-
- (id)initWithParentWindow:(NSWindow*)parentWindow
profile:(Profile*)profile
parent:(const BookmarkNode*)parent
node:(const BookmarkNode*)node
configuration:(BookmarkEditor::Configuration)configuration
handler:(BookmarkEditor::Handler*)handler {
- NSString* nibpath = [mac_util::MainAppBundle()
- pathForResource:@"BookmarkEditor"
- ofType:@"nib"];
- if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
- parentWindow_ = parentWindow;
- profile_ = profile;
- parentNode_ = parent;
+ if ((self = [super initWithParentWindow:parentWindow
+ nibName:@"BookmarkEditor"
+ profile:profile
+ parent:parent
+ configuration:configuration
+ handler:handler])) {
// "Add Page..." has no "node" so this may be NULL.
node_ = node;
- configuration_ = configuration;
- handler_.reset(handler);
}
return self;
}
+- (void)dealloc {
+ [displayURL_ release];
+ [super dealloc];
+}
+
- (void)awakeFromNib {
// Set text fields to match our bookmark. If the node is NULL we
// arrived here from an "Add Page..." item in a context menu.
if (node_) {
- initialName_.reset([base::SysWideToNSString(node_->GetTitle()) retain]);
+ [self setInitialName:base::SysWideToNSString(node_->GetTitle())];
std::string url_string = node_->GetURL().possibly_invalid_spec();
initialUrl_.reset([[NSString stringWithUTF8String:url_string.c_str()]
retain]);
} else {
- initialName_.reset([@"" retain]);
initialUrl_.reset([@"" retain]);
}
- [nameField_ setStringValue:initialName_];
- [urlField_ setStringValue:initialUrl_];
-
- // Get a ping when the URL or name text fields change;
- // trigger an initial ping to set things up.
- [nameField_ setDelegate:self];
- [urlField_ setDelegate:self];
- [self controlTextDidChange:nil];
-
- if (configuration_ != BookmarkEditor::SHOW_TREE) {
- // Remember the NSBrowser's height; we will shrink our frame by that
- // much.
- NSRect frame = [[self window] frame];
- CGFloat browserHeight = [folderBrowser_ frame].size.height;
- frame.size.height -= browserHeight;
- frame.origin.y += browserHeight;
- // Remove the NSBrowser and "new folder" button.
- [folderBrowser_ removeFromSuperview];
- [newFolderButton_ removeFromSuperview];
- // Finally, commit the size change.
- [[self window] setFrame:frame display:YES];
- }
-
- [folderBrowser_ setCellClass:[BookmarkTreeBrowserCell class]];
- [folderBrowser_ setDoubleAction:@selector(browserDoubleClicked:)];
-}
-
-- (void)windowDidLoad {
- if (configuration_ == BookmarkEditor::SHOW_TREE) {
- // Find and select the |parent| bookmark node in the folder tree browser.
- [self selectNodeInBrowser:parentNode_];
- }
-}
-
-- (void)windowWillClose:(NSNotification *)notification {
- // If a folder name cell is being edited then force it to end editing
- // so that any changes are recorded.
- [[self window] makeFirstResponder:nil];
-
- // This is probably unnecessary but it feels cleaner since the
- // delegate of a text field can be automatically registered for
- // notifications.
- [nameField_ setDelegate:nil];
- [urlField_ setDelegate:nil];
- [self autorelease];
-}
-
-/* TODO(jrg):
-// Implementing this informal protocol allows us to open the sheet
-// somewhere other than at the top of the window. NOTE: this means
-// that I, the controller, am also the window's delegate.
-- (NSRect)window:(NSWindow*)window willPositionSheet:(NSWindow*)sheet
- usingRect:(NSRect)rect {
- // adjust rect.origin.y to be the bottom of the toolbar
- return rect;
-}
-*/
-
-// TODO(jrg): consider NSModalSession.
-- (void)runAsModalSheet {
- [NSApp beginSheet:[self window]
- modalForWindow:parentWindow_
- modalDelegate:self
- didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
- contextInfo:nil];
-}
-
-- (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];
-}
-
-- (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];
- 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));
-}
-
-- (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];
+ [self setDisplayURL:initialUrl_];
+ [super awakeFromNib];
}
#pragma mark Bookmark Editing
// If possible, return a valid GURL from the URL text field.
- (GURL)GURLFromUrlField {
- NSString* url = [urlField_ stringValue];
+ NSString* url = [self displayURL];
GURL newURL = GURL([url UTF8String]);
if (!newURL.is_valid()) {
// Mimic observed friendliness from Windows
@@ -323,25 +73,28 @@ int IndexOfFolderChild(const BookmarkNode* child_node) {
return newURL;
}
-// 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
-// the notification.)
-- (void)controlTextDidChange:(NSNotification*)aNotification {
- GURL newURL = [self GURLFromUrlField];
- [okButton_ setEnabled:(newURL.is_valid()) ? YES : NO];
+// Enable the OK button if there is a valid URL.
+- (BOOL)okEnabled {
+ BOOL okEnabled = NO;
+ if ([[self displayURL] length]) {
+ GURL newURL = [self GURLFromUrlField];
+ okEnabled = (newURL.is_valid()) ? YES : NO;
+ }
+ return okEnabled;
}
-// The ok: action is connected to the OK button in the Edit Bookmark window
-// of the BookmarkEditor.xib. The the bookmark's name and URL are assumed
-// to be valid (otherwise the OK button should not be enabled). If the
-// bookmark previously existed then it is removed from its old folder.
-// The bookmark is then added to its new folder. If the folder has not
-// changed then the bookmark stays in its original position (index) otherwise
-// it is added to the end of the new folder.
+// The the bookmark's URL is assumed to be valid (otherwise the OK button
+// should not be enabled). If the bookmark previously existed then it is
+// removed from its old folder. The bookmark is then added to its new
+// folder. If the folder has not changed then the bookmark stays in its
+// original position (index) otherwise it is added to the end of the new folder.
- (IBAction)ok:(id)sender {
- NSString* name = [nameField_ stringValue];
+ NSString* name = [[self displayName] stringByTrimmingCharactersInSet:
+ [NSCharacterSet newlineCharacterSet]];
std::wstring newTitle = base::SysNSStringToWide(name);
+ const BookmarkNode* newParentNode = [self selectedNode];
+ BookmarkModel* model = [self bookmarkModel];
+ int newIndex = newParentNode->GetChildCount();
GURL newURL = [self GURLFromUrlField];
if (!newURL.is_valid()) {
// Shouldn't be reached -- OK button disabled if not valid!
@@ -350,114 +103,21 @@ int IndexOfFolderChild(const BookmarkNode* child_node) {
}
// Determine where the new/replacement bookmark is to go.
- const BookmarkNode* newParentNode = [self selectedNode];
- BookmarkModel* model = profile_->GetBookmarkModel();
- int newIndex = newParentNode->GetChildCount();
- if (node_ && parentNode_) {
+ const BookmarkNode* parentNode = [self parentNode];
+ if (node_ && parentNode) {
// Replace the old bookmark with the updated bookmark.
- int oldIndex = parentNode_->IndexOfChild(node_);
+ int oldIndex = parentNode->IndexOfChild(node_);
if (oldIndex >= 0)
- model->Remove(parentNode_, oldIndex);
- if (parentNode_ == newParentNode)
+ model->Remove(parentNode, oldIndex);
+ if (parentNode == newParentNode)
newIndex = oldIndex;
}
// Add bookmark as new node at the end of the newly selected folder.
const BookmarkNode* node = model->AddURL(newParentNode, newIndex,
newTitle, newURL);
// Honor handler semantics: callback on node creation.
- if (handler_.get())
- handler_->NodeCreated(node);
- [NSApp endSheet:[self window]];
-}
-
-- (IBAction)cancel:(id)sender {
- [NSApp endSheet:[self window]];
-}
-
-- (void)didEndSheet:(NSWindow*)sheet
- returnCode:(int)returnCode
- contextInfo:(void*)contextInfo {
- [sheet close];
-}
-
-#pragma mark For Unit Test Use Only
-
-- (NSString*)displayName {
- return [nameField_ stringValue];
-}
-
-- (NSString*)displayURL {
- return [urlField_ stringValue];
-}
-
-- (void)setDisplayName:(NSString*)name {
- [nameField_ setStringValue:name];
- [self controlTextDidChange:nil];
-}
-
-- (void)setDisplayURL:(NSString*)name {
- [urlField_ setStringValue:name];
- [self controlTextDidChange:nil];
-}
-
-- (BOOL)okButtonEnabled {
- return [okButton_ isEnabled];
-}
-
-- (void)selectTestNodeInBrowser:(const BookmarkNode*)node {
- [self selectNodeInBrowser:node];
-}
-
-#pragma mark NSBrowser delegate methods
-
-// Given a column number, determine the parent bookmark folder node for the
-// bookmarks being shown in that column. This is done by scanning forward
-// from column zero and following the selected row for each column up
-// to the parent of the desired column.
-- (const BookmarkNode*)parentNodeForColumn:(NSInteger)column {
- DCHECK(column >= 0);
- BookmarkModel* model = profile_->GetBookmarkModel();
- const BookmarkNode* node = model->root_node();
- for (NSInteger i = 0; i < column; ++i) {
- NSInteger selectedRowInColumn = [folderBrowser_ selectedRowInColumn:i];
- node = GetFolderChildForParent(node, selectedRowInColumn);
- }
- return node;
-}
-
-// This implementation returns the number of folders contained in the parent
-// folder node for this column.
-// TOTO(mrossetti): Decide if bookmark (i.e. non-folder) nodes should be
-// shown, perhaps in gray.
-- (NSInteger)browser:(NSBrowser*)sender numberOfRowsInColumn:(NSInteger)col {
- NSInteger rowCount = 0;
- const BookmarkNode* parentNode = [self parentNodeForColumn:col];
- if (parentNode) {
- int childCount = parentNode->GetChildCount();
- for (int i = 0; i < childCount; ++i) {
- const BookmarkNode* childNode = parentNode->GetChild(i);
- if (childNode->type() != BookmarkNode::URL)
- ++rowCount;
- }
- }
- return rowCount;
-}
-
-- (void)browser:(NSBrowser*)sender
- willDisplayCell:(NSBrowserCell*)cell
- atRow:(NSInteger)row
- 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);
- BookmarkTreeBrowserCell* browserCell =
- static_cast<BookmarkTreeBrowserCell*>(cell);
- [browserCell setTitle:base::SysWideToNSString(childNode->GetTitle())];
- [browserCell setBookmarkNode:childNode];
- [browserCell setMatrix:[folderBrowser_ matrixInColumn:column]];
+ [self NotifyHandlerCreatedNode:node];
+ [super ok:sender];
}
@end // BookmarkEditorController