diff options
Diffstat (limited to 'chrome/browser/cocoa/bookmark_editor_base_controller.mm')
-rw-r--r-- | chrome/browser/cocoa/bookmark_editor_base_controller.mm | 138 |
1 files changed, 132 insertions, 6 deletions
diff --git a/chrome/browser/cocoa/bookmark_editor_base_controller.mm b/chrome/browser/cocoa/bookmark_editor_base_controller.mm index 59b8913..c467e09 100644 --- a/chrome/browser/cocoa/bookmark_editor_base_controller.mm +++ b/chrome/browser/cocoa/bookmark_editor_base_controller.mm @@ -17,13 +17,23 @@ #include "chrome/browser/profile.h" #include "grit/generated_resources.h" -@interface BookmarkEditorBaseController (Private) +@interface BookmarkEditorBaseController () @property (retain, readwrite) NSArray* folderTreeArray; // Return the folder tree object for the given path. - (BookmarkFolderInfo*)folderForIndexPath:(NSIndexPath*)path; +// (Re)build the folder tree from the BookmarkModel's current state. +- (void)buildFolderTree; + +// Notifies the controller that the bookmark model has changed. +- (void)modelChanged; + +// Notifies the controller that a node has been removed. +- (void)nodeRemoved:(const BookmarkNode*)node + fromParent:(const BookmarkNode*)parent; + // Given a folder node, collect an array containing BookmarkFolderInfos // describing its subchildren which are also folders. - (NSMutableArray*)addChildFoldersFromNode:(const BookmarkNode*)node; @@ -66,6 +76,79 @@ void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, [controller runAsModalSheet]; } +// Adapter to tell BookmarkEditorBaseController when bookmarks change. +class BookmarkEditorBaseControllerBridge : public BookmarkModelObserver { + public: + BookmarkEditorBaseControllerBridge(BookmarkEditorBaseController* controller) + : controller_(controller), + importing_(false) + { } + + virtual void Loaded(BookmarkModel* model) { + [controller_ modelChanged]; + } + + virtual void BookmarkNodeMoved(BookmarkModel* model, + const BookmarkNode* old_parent, + int old_index, + const BookmarkNode* new_parent, + int new_index) { + if (!importing_ && new_parent->GetChild(new_index)->is_folder()) + [controller_ modelChanged]; + } + + virtual void BookmarkNodeAdded(BookmarkModel* model, + const BookmarkNode* parent, + int index) { + if (!importing_ && parent->GetChild(index)->is_folder()) + [controller_ modelChanged]; + } + + virtual void BookmarkNodeRemoved(BookmarkModel* model, + const BookmarkNode* parent, + int old_index, + const BookmarkNode* node) { + [controller_ nodeRemoved:node fromParent:parent]; + if (node->is_folder()) + [controller_ modelChanged]; + } + + virtual void BookmarkNodeChanged(BookmarkModel* model, + const BookmarkNode* node) { + if (!importing_ && node->is_folder()) + [controller_ modelChanged]; + } + + virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, + const BookmarkNode* node) { + if (!importing_) + [controller_ modelChanged]; + } + + virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, + const BookmarkNode* node) { + // I care nothing for these 'favicons': I only show folders. + } + + virtual void BookmarkImportBeginning(BookmarkModel* model) { + importing_ = true; + } + + // Invoked after a batch import finishes. This tells observers to update + // themselves if they were waiting for the update to finish. + virtual void BookmarkImportEnding(BookmarkModel* model) { + importing_ = false; + [controller_ modelChanged]; + } + + private: + BookmarkEditorBaseController* controller_; // weak + bool importing_; +}; + + +#pragma mark - + @implementation BookmarkEditorBaseController @synthesize initialName = initialName_; @@ -88,11 +171,14 @@ void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, configuration_ = configuration; handler_.reset(handler); initialName_ = [@"" retain]; + observer_.reset(new BookmarkEditorBaseControllerBridge(self)); + [self bookmarkModel]->AddObserver(observer_.get()); } return self; } - (void)dealloc { + [self bookmarkModel]->RemoveObserver(observer_.get()); [initialName_ release]; [displayName_ release]; [super dealloc]; @@ -115,11 +201,7 @@ void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, } // Build up a tree of the current folder configuration. - BookmarkModel* model = profile_->GetBookmarkModel(); - const BookmarkNode* rootNode = model->root_node(); - NSMutableArray* baseArray = [self addChildFoldersFromNode:rootNode]; - DCHECK(baseArray); - [self setFolderTreeArray:baseArray]; + [self buildFolderTree]; } - (void)windowDidLoad { @@ -284,6 +366,7 @@ void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, const BookmarkNode* rootNode = model->root_node(); const BookmarkNode* node = desiredNode; while (node != rootNode) { + DCHECK(node); nodeStack.push(node); node = node->GetParent(); } @@ -332,6 +415,42 @@ void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, return childFolders; } +- (void)buildFolderTree { + // Build up a tree of the current folder configuration. + BookmarkModel* model = profile_->GetBookmarkModel(); + const BookmarkNode* rootNode = model->root_node(); + NSMutableArray* baseArray = [self addChildFoldersFromNode:rootNode]; + DCHECK(baseArray); + [self setFolderTreeArray:baseArray]; +} + +- (void)modelChanged { + const BookmarkNode* selectedNode = [self selectedNode]; + [self buildFolderTree]; + if (selectedNode && configuration_ == BookmarkEditor::SHOW_TREE) + [self selectNodeInBrowser:selectedNode]; +} + +- (void)nodeRemoved:(const BookmarkNode*)node + fromParent:(const BookmarkNode*)parent { + if (node->is_folder()) { + if (parentNode_ == node || parentNode_->HasAncestor(node)) { + parentNode_ = [self bookmarkModel]->GetBookmarkBarNode(); + if (configuration_ != BookmarkEditor::SHOW_TREE) { + // The user can't select a different folder, so just close up shop. + [self cancel:self]; + return; + } + } + + if (configuration_ == BookmarkEditor::SHOW_TREE) { + // For safety's sake, in case deleted node was an ancestor of selection, + // go back to a known safe place. + [self selectNodeInBrowser:parentNode_]; + } + } +} + #pragma mark New Folder Handler - (void)createNewFoldersForFolder:(BookmarkFolderInfo*)folderInfo { @@ -464,4 +583,11 @@ void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd, [super dealloc]; } +// Implementing isEqual: allows the NSTreeController to preserve the selection +// and open/shut state of outline items when the data changes. +- (BOOL)isEqual:(id)other { + return [other isKindOfClass:[BookmarkFolderInfo class]] && + folderNode_ == [(BookmarkFolderInfo*)other folderNode]; +} + @end |