Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5435)

Unified Diff: chrome/browser/cocoa/bookmark_editor_base_controller.mm

Issue 357005: Implement Bookmark All Tabs... using the BookmarkEditorController and determi... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/cocoa/bookmark_editor_base_controller.mm
===================================================================
--- chrome/browser/cocoa/bookmark_editor_base_controller.mm (revision 0)
+++ chrome/browser/cocoa/bookmark_editor_base_controller.mm (revision 0)
@@ -0,0 +1,398 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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_base_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_model.h"
+#import "chrome/browser/cocoa/bookmark_all_tabs_controller.h"
+#import "chrome/browser/cocoa/bookmark_editor_controller.h"
+#import "chrome/browser/cocoa/bookmark_tree_browser_cell.h"
+#include "chrome/browser/profile.h"
+#include "grit/generated_resources.h"
+
+@interface BookmarkEditorBaseController (Private)
+
+// 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;
+
+@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) {
+ BookmarkEditorBaseController* controller = nil;
+ if (details.type == EditDetails::NEW_FOLDER) {
+ controller = [[BookmarkAllTabsController alloc]
+ initWithParentWindow:parent_hwnd
+ profile:profile
+ parent:parent
+ configuration:configuration
+ handler:handler];
+ } else {
+ 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 {
+
+// 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;
+}
+
+// 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;
+}
+
+} // namespace
+
+@implementation BookmarkEditorBaseController
+
+@synthesize initialName = initialName_;
+@synthesize displayName = displayName_;
+@synthesize okEnabled = okEnabled_;
+
+- (id)initWithParentWindow:(NSWindow*)parentWindow
+ nibName:(NSString*)nibName
+ profile:(Profile*)profile
+ parent:(const BookmarkNode*)parent
+ configuration:(BookmarkEditor::Configuration)configuration
+ handler:(BookmarkEditor::Handler*)handler {
+ NSString* nibpath = [mac_util::MainAppBundle()
+ pathForResource:nibName
+ ofType:@"nib"];
+ if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
+ parentWindow_ = parentWindow;
+ profile_ = profile;
+ parentNode_ = parent;
+ configuration_ = configuration;
+ handler_.reset(handler);
+ initialName_ = [@"" retain];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [initialName_ release];
+ [displayName_ release];
+ [super dealloc];
+}
+
+- (void)awakeFromNib {
+ [self setDisplayName:[self initialName]];
+
+ 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) {
+ [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];
+ [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];
+ }
+
+ // Force the OK button state to be re-evaluated.
+ [self willChangeValueForKey:@"okEnabled"];
+ [self didChangeValueForKey:@"okEnabled"];
+}
+
+- (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;
+}
+
+- (void)NotifyHandlerCreatedNode:(const BookmarkNode*)node {
+ if (handler_.get())
+ handler_->NodeCreated(node);
+}
+
+#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 completes.
+ [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.
+ // The focus does not automatically get reset to the browser when the
+ // cell gives up focus.
+ [[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];
+}
+
+- (BOOL)okEnabled {
+ return YES;
+}
+
+- (IBAction)ok:(id)sender {
+ [NSApp endSheet:[self window]];
+}
+
+- (IBAction)cancel:(id)sender {
+ [NSApp endSheet:[self window]];
+}
+
+- (void)didEndSheet:(NSWindow*)sheet
+ returnCode:(int)returnCode
+ contextInfo:(void*)contextInfo {
+ [sheet close];
+}
+
+- (BookmarkModel*)bookmarkModel {
+ return profile_->GetBookmarkModel();
+}
+
+- (const BookmarkNode*)parentNode {
+ return parentNode_;
+}
+
+#pragma mark For Unit Test Use Only
+
+- (BOOL)okButtonEnabled {
+ return [okButton_ isEnabled];
+}
+
+- (void)selectTestNodeInBrowser:(const BookmarkNode*)node {
+ [self selectNodeInBrowser:node];
+}
+
++ (const BookmarkNode*)folderChildForParent:(const BookmarkNode*)parent
+ withFolderIndex:(NSInteger)index {
+ return GetFolderChildForParent(parent, index);
+}
+
++ (int)indexOfFolderChild:(const BookmarkNode*)child {
+ return IndexOfFolderChild(child);
+}
+
+
+#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]];
+}
+
+@end // BookmarkEditorBaseController
+
Property changes on: chrome/browser/cocoa/bookmark_editor_base_controller.mm
___________________________________________________________________
Name: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698