diff options
-rw-r--r-- | chrome/browser/bookmarks/bookmark_context_menu.cc | 130 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_context_menu.h | 3 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_table_model.cc | 161 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_bubble_view.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_editor_view.cc | 44 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_editor_view.h | 32 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_editor_view_unittest.cc | 18 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_manager_view.cc | 139 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_manager_view.h | 28 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 9 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 1 |
11 files changed, 378 insertions, 189 deletions
diff --git a/chrome/browser/bookmarks/bookmark_context_menu.cc b/chrome/browser/bookmarks/bookmark_context_menu.cc index 4f033ac..0e45493 100644 --- a/chrome/browser/bookmarks/bookmark_context_menu.cc +++ b/chrome/browser/bookmarks/bookmark_context_menu.cc @@ -56,10 +56,11 @@ class EditFolderController : public InputWindowDelegate, static void Show(Profile* profile, HWND hwnd, BookmarkNode* node, - bool is_new) { + bool is_new, + bool show_in_manager) { // EditFolderController deletes itself when done. EditFolderController* controller = - new EditFolderController(profile, hwnd, node, is_new); + new EditFolderController(profile, hwnd, node, is_new, show_in_manager); controller->Show(); } @@ -67,11 +68,13 @@ class EditFolderController : public InputWindowDelegate, EditFolderController(Profile* profile, HWND hwnd, BookmarkNode* node, - bool is_new) + bool is_new, + bool show_in_manager) : profile_(profile), model_(profile->GetBookmarkModel()), node_(node), - is_new_(is_new) { + is_new_(is_new), + show_in_manager_(show_in_manager) { DCHECK(is_new_ || node); window_ = CreateInputWindow(hwnd, this); model_->AddObserver(this); @@ -97,10 +100,17 @@ class EditFolderController : public InputWindowDelegate, } virtual void InputAccepted(const std::wstring& text) { - if (is_new_) - model_->AddGroup(node_, node_->GetChildCount(), text); - else + if (is_new_) { + BookmarkNode* node = + model_->AddGroup(node_, node_->GetChildCount(), text); + if (show_in_manager_) { + BookmarkManagerView* manager = BookmarkManagerView::current(); + if (manager && manager->profile() == profile_) + manager->SelectInTree(node); + } + } else { model_->SetTitle(node_, text); + } } virtual void InputCanceled() { @@ -164,11 +174,38 @@ class EditFolderController : public InputWindowDelegate, BookmarkNode* node_; bool is_new_; + + // If is_new_ is true and a new node is created, it is selected in the + // bookmark manager. + bool show_in_manager_; views::Window* window_; DISALLOW_COPY_AND_ASSIGN(EditFolderController); }; +// SelectOnCreationHandler ---------------------------------------------------- + +// Used when adding a new bookmark. If a new bookmark is created it is selected +// in the bookmark manager. +class SelectOnCreationHandler : public BookmarkEditorView::Handler { + public: + explicit SelectOnCreationHandler(Profile* profile) : profile_(profile) { + } + + virtual void NodeCreated(BookmarkNode* new_node) { + BookmarkManagerView* manager = BookmarkManagerView::current(); + if (!manager || manager->profile() != profile_) + return; // Manager no longer showing, or showing a different profile. + + manager->SelectInTree(new_node); + } + + private: + Profile* profile_; + + DISALLOW_COPY_AND_ASSIGN(SelectOnCreationHandler); +}; + } // namespace // BookmarkContextMenu ------------------------------------------- @@ -192,36 +229,39 @@ BookmarkContextMenu::BookmarkContextMenu( DCHECK(profile_); DCHECK(model_->IsLoaded()); menu_.reset(new views::MenuItemView(this)); - if (selection.size() == 1 && selection[0]->is_url()) { - menu_->AppendMenuItemWithLabel( - IDS_BOOMARK_BAR_OPEN_ALL, - l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_TAB)); - menu_->AppendMenuItemWithLabel( - IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW, - l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_WINDOW)); - menu_->AppendMenuItemWithLabel( - IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO, - l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_INCOGNITO)); - } else { - menu_->AppendMenuItemWithLabel( - IDS_BOOMARK_BAR_OPEN_ALL, - l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL)); - menu_->AppendMenuItemWithLabel( - IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW, - l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); - menu_->AppendMenuItemWithLabel( - IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO, - l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + if (configuration != BOOKMARK_MANAGER_ORGANIZE_MENU) { + if (selection.size() == 1 && selection[0]->is_url()) { + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_TAB)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_WINDOW)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_INCOGNITO)); + } else { + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + } + menu_->AppendSeparator(); } - menu_->AppendSeparator(); menu_->AppendMenuItemWithLabel(IDS_BOOKMARK_BAR_EDIT, - l10n_util::GetString(IDS_BOOKMARK_BAR_EDIT)); + l10n_util::GetString(IDS_BOOKMARK_BAR_EDIT)); menu_->AppendMenuItemWithLabel( IDS_BOOKMARK_BAR_REMOVE, l10n_util::GetString(IDS_BOOKMARK_BAR_REMOVE)); - if (configuration != BOOKMARK_BAR) { + if (configuration == BOOKMARK_MANAGER_TABLE || + configuration == BOOKMARK_MANAGER_ORGANIZE_MENU) { menu_->AppendMenuItemWithLabel( IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER, l10n_util::GetString(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); @@ -239,10 +279,10 @@ BookmarkContextMenu::BookmarkContextMenu( if (configuration == BOOKMARK_BAR) { menu_->AppendSeparator(); menu_->AppendMenuItemWithLabel(IDS_BOOKMARK_MANAGER, - l10n_util::GetString(IDS_BOOKMARK_MANAGER)); + l10n_util::GetString(IDS_BOOKMARK_MANAGER)); menu_->AppendMenuItem(IDS_BOOMARK_BAR_ALWAYS_SHOW, - l10n_util::GetString(IDS_BOOMARK_BAR_ALWAYS_SHOW), - views::MenuItemView::CHECKBOX); + l10n_util::GetString(IDS_BOOMARK_BAR_ALWAYS_SHOW), + views::MenuItemView::CHECKBOX); } model_->AddObserver(this); } @@ -304,9 +344,10 @@ void BookmarkContextMenu::ExecuteCommand(int id) { else editor_config = BookmarkEditorView::NO_TREE; BookmarkEditorView::Show(hwnd_, profile_, NULL, selection_[0], - editor_config); + editor_config, NULL); } else { - EditFolderController::Show(profile_, hwnd_, selection_[0], false); + EditFolderController::Show(profile_, hwnd_, selection_[0], false, + false); } break; @@ -326,12 +367,16 @@ void BookmarkContextMenu::ExecuteCommand(int id) { UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Add", profile_); BookmarkEditorView::Configuration editor_config; - if (configuration_ == BOOKMARK_BAR) + BookmarkEditorView::Handler* handler = NULL; + if (configuration_ == BOOKMARK_BAR) { editor_config = BookmarkEditorView::SHOW_TREE; - else + } else { editor_config = BookmarkEditorView::NO_TREE; + // This is owned by the BookmarkEditorView. + handler = new SelectOnCreationHandler(profile_); + } BookmarkEditorView::Show(hwnd_, profile_, GetParentForNewNodes(), NULL, - editor_config); + editor_config, handler); break; } @@ -340,7 +385,7 @@ void BookmarkContextMenu::ExecuteCommand(int id) { profile_); EditFolderController::Show(profile_, hwnd_, GetParentForNewNodes(), - true); + true, (configuration_ != BOOKMARK_BAR)); break; } @@ -361,6 +406,10 @@ void BookmarkContextMenu::ExecuteCommand(int id) { BookmarkManagerView::current()->SelectInTree(selection_[0]); break; + case IDS_BOOKMARK_MANAGER: + BookmarkManagerView::Show(profile_); + break; + default: NOTREACHED(); } @@ -393,7 +442,8 @@ bool BookmarkContextMenu::IsCommandEnabled(int id) const { return !selection_.empty() && !is_root_node; case IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER: - return configuration_ == BOOKMARK_MANAGER_TABLE && + return (configuration_ == BOOKMARK_MANAGER_TABLE || + configuration_ == BOOKMARK_MANAGER_ORGANIZE_MENU) && selection_.size() == 1; case IDS_BOOMARK_BAR_NEW_FOLDER: diff --git a/chrome/browser/bookmarks/bookmark_context_menu.h b/chrome/browser/bookmarks/bookmark_context_menu.h index 5b48627..2991637 100644 --- a/chrome/browser/bookmarks/bookmark_context_menu.h +++ b/chrome/browser/bookmarks/bookmark_context_menu.h @@ -23,7 +23,8 @@ class BookmarkContextMenu : public views::MenuDelegate, enum ConfigurationType { BOOKMARK_BAR, BOOKMARK_MANAGER_TABLE, - BOOKMARK_MANAGER_TREE + BOOKMARK_MANAGER_TREE, + BOOKMARK_MANAGER_ORGANIZE_MENU }; // Creates the bookmark context menu. diff --git a/chrome/browser/bookmarks/bookmark_table_model.cc b/chrome/browser/bookmarks/bookmark_table_model.cc index c55f6ff..a9122fa 100644 --- a/chrome/browser/bookmarks/bookmark_table_model.cc +++ b/chrome/browser/bookmarks/bookmark_table_model.cc @@ -20,22 +20,72 @@ namespace { // Number of bookmarks shown in recently bookmarked. const int kRecentlyBookmarkedCount = 50; -// FolderBookmarkTableModel ---------------------------------------------------- +// VectorBackedBookmarkTableModel ---------------------------------------------- -class FolderBookmarkTableModel : public BookmarkTableModel { +class VectorBackedBookmarkTableModel : public BookmarkTableModel { public: - FolderBookmarkTableModel(BookmarkModel* model, BookmarkNode* root_node) - : BookmarkTableModel(model), - root_node_(root_node) { + explicit VectorBackedBookmarkTableModel(BookmarkModel* model) + : BookmarkTableModel(model) { + } + + virtual BookmarkNode* GetNodeForRow(int row) { + return nodes_[row]; } virtual int RowCount() { - return root_node_ ? root_node_->GetChildCount() : 0; + return static_cast<int>(nodes_.size()); } - virtual BookmarkNode* GetNodeForRow(int row) { - DCHECK(root_node_); - return root_node_->GetChild(row); + virtual void BookmarkNodeMoved(BookmarkModel* model, + BookmarkNode* old_parent, + int old_index, + BookmarkNode* new_parent, + int new_index) { + NotifyObserverOfChange(new_parent->GetChild(new_index)); + } + + virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, + BookmarkNode* node) { + NotifyObserverOfChange(node); + } + + virtual void BookmarkNodeChanged(BookmarkModel* model, + BookmarkNode* node) { + NotifyObserverOfChange(node); + } + + protected: + void NotifyObserverOfChange(BookmarkNode* node) { + if (!observer()) + return; + + int index = IndexOfNode(node); + if (index != -1) + observer()->OnItemsChanged(index, 1); + } + + typedef std::vector<BookmarkNode*> Nodes; + Nodes& nodes() { return nodes_; } + + private: + Nodes nodes_; + + DISALLOW_COPY_AND_ASSIGN(VectorBackedBookmarkTableModel); +}; + +// FolderBookmarkTableModel ---------------------------------------------------- + +// FolderBookmarkTableModel is a TableModel implementation backed by the +// contents of a bookmark folder. FolderBookmarkTableModel caches the contents +// of the folder so that it can send out the correct events when a bookmark +// node is moved. +class FolderBookmarkTableModel : public VectorBackedBookmarkTableModel { + public: + FolderBookmarkTableModel(BookmarkModel* model, BookmarkNode* root_node) + : VectorBackedBookmarkTableModel(model), + root_node_(root_node) { + for (int i = 0; i < root_node->GetChildCount(); ++i) + nodes().push_back(root_node->GetChild(i)); } virtual void BookmarkNodeMoved(BookmarkModel* model, @@ -43,15 +93,27 @@ class FolderBookmarkTableModel : public BookmarkTableModel { int old_index, BookmarkNode* new_parent, int new_index) { - if (observer() && (old_parent == root_node_ || new_parent == root_node_)) - observer()->OnModelChanged(); + if (old_parent == root_node_) { + nodes().erase(nodes().begin() + old_index); + if (observer()) + observer()->OnItemsRemoved(old_index, 1); + } + if (new_parent == root_node_) { + nodes().insert(nodes().begin() + new_index, + root_node_->GetChild(new_index)); + if (observer()) + observer()->OnItemsAdded(new_index, 1); + } } virtual void BookmarkNodeAdded(BookmarkModel* model, BookmarkNode* parent, int index) { - if (root_node_ == parent && observer()) - observer()->OnItemsAdded(index, 1); + if (root_node_ == parent) { + nodes().insert(nodes().begin() + index, parent->GetChild(index)); + if (observer()) + observer()->OnItemsAdded(index, 1); + } } virtual void BookmarkNodeRemoved(BookmarkModel* model, @@ -59,14 +121,18 @@ class FolderBookmarkTableModel : public BookmarkTableModel { int index, BookmarkNode* node) { if (root_node_->HasAncestor(node)) { - // We, our one of our ancestors was removed. + // We, or one of our ancestors was removed. root_node_ = NULL; + nodes().clear(); if (observer()) observer()->OnModelChanged(); return; } - if (root_node_ == parent && observer()) - observer()->OnItemsRemoved(index, 1); + if (root_node_ == parent) { + nodes().erase(nodes().begin() + index); + if (observer()) + observer()->OnItemsRemoved(index, 1); + } } virtual void BookmarkNodeChanged(BookmarkModel* model, @@ -92,57 +158,6 @@ class FolderBookmarkTableModel : public BookmarkTableModel { DISALLOW_COPY_AND_ASSIGN(FolderBookmarkTableModel); }; -// VectorBackedBookmarkTableModel ---------------------------------------------- - -class VectorBackedBookmarkTableModel : public BookmarkTableModel { - public: - explicit VectorBackedBookmarkTableModel(BookmarkModel* model) - : BookmarkTableModel(model) { - } - - virtual BookmarkNode* GetNodeForRow(int row) { - return nodes_[row]; - } - - virtual int RowCount() { - return static_cast<int>(nodes_.size()); - } - - virtual void BookmarkNodeMoved(BookmarkModel* model, - BookmarkNode* old_parent, - int old_index, - BookmarkNode* new_parent, - int new_index) { - NotifyObserverOfChange(new_parent->GetChild(new_index)); - } - - virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, - BookmarkNode* node) { - NotifyObserverOfChange(node); - } - - virtual void BookmarkNodeChanged(BookmarkModel* model, - BookmarkNode* node) { - NotifyObserverOfChange(node); - } - - protected: - void NotifyObserverOfChange(BookmarkNode* node) { - if (!observer()) - return; - - int index = IndexOfNode(node); - if (index != -1) - observer()->OnItemsChanged(index, 1); - } - - typedef std::vector<BookmarkNode*> Nodes; - Nodes nodes_; - - private: - DISALLOW_COPY_AND_ASSIGN(VectorBackedBookmarkTableModel); -}; - // RecentlyBookmarkedTableModel ------------------------------------------------ class RecentlyBookmarkedTableModel : public VectorBackedBookmarkTableModel { @@ -169,8 +184,8 @@ class RecentlyBookmarkedTableModel : public VectorBackedBookmarkTableModel { private: void UpdateRecentlyBookmarked() { - nodes_.clear(); - model()->GetMostRecentlyAddedEntries(kRecentlyBookmarkedCount, &nodes_); + nodes().clear(); + model()->GetMostRecentlyAddedEntries(kRecentlyBookmarkedCount, &nodes()); if (observer()) observer()->OnModelChanged(); } @@ -190,7 +205,7 @@ class BookmarkSearchTableModel : public VectorBackedBookmarkTableModel { model->GetBookmarksMatchingText(search_text, std::numeric_limits<int>::max(), &matches); for (size_t i = 0; i < matches.size(); ++i) - nodes_.push_back(matches[i].node); + nodes().push_back(matches[i].node); } virtual void BookmarkNodeAdded(BookmarkModel* model, @@ -198,9 +213,9 @@ class BookmarkSearchTableModel : public VectorBackedBookmarkTableModel { int index) { BookmarkNode* node = parent->GetChild(index); if (model->DoesBookmarkMatchText(search_text_, node)) { - nodes_.push_back(node); + nodes().push_back(node); if (observer()) - observer()->OnItemsAdded(static_cast<int>(nodes_.size() - 1), 1); + observer()->OnItemsAdded(static_cast<int>(nodes().size() - 1), 1); } } @@ -212,7 +227,7 @@ class BookmarkSearchTableModel : public VectorBackedBookmarkTableModel { if (internal_index == -1) return; - nodes_.erase(nodes_.begin() + static_cast<int>(internal_index)); + nodes().erase(nodes().begin() + static_cast<int>(internal_index)); if (observer()) observer()->OnItemsRemoved(internal_index, 1); } diff --git a/chrome/browser/views/bookmark_bubble_view.cc b/chrome/browser/views/bookmark_bubble_view.cc index 9136014..d32d3f3 100644 --- a/chrome/browser/views/bookmark_bubble_view.cc +++ b/chrome/browser/views/bookmark_bubble_view.cc @@ -359,7 +359,7 @@ void BookmarkBubbleView::ShowEditor() { if (node) BookmarkEditorView::Show(parent, profile_, NULL, node, - BookmarkEditorView::SHOW_TREE); + BookmarkEditorView::SHOW_TREE, NULL); } void BookmarkBubbleView::SetNodeTitleFromTextField() { diff --git a/chrome/browser/views/bookmark_editor_view.cc b/chrome/browser/views/bookmark_editor_view.cc index 1179037..db8d5ec 100644 --- a/chrome/browser/views/bookmark_editor_view.cc +++ b/chrome/browser/views/bookmark_editor_view.cc @@ -40,29 +40,19 @@ static const int kTreeWidth = 300; // ID for various children. static const int kNewGroupButtonID = 1002; -// static -void BookmarkEditorView::Show(HWND parent_hwnd, - Profile* profile, - BookmarkNode* parent, - BookmarkNode* node, - Configuration configuration) { - DCHECK(profile); - BookmarkEditorView* editor = - new BookmarkEditorView(profile, parent, node, configuration); - editor->Show(parent_hwnd); -} - BookmarkEditorView::BookmarkEditorView(Profile* profile, BookmarkNode* parent, BookmarkNode* node, - Configuration configuration) + Configuration configuration, + Handler* handler) : profile_(profile), tree_view_(NULL), new_group_button_(NULL), parent_(parent), node_(node), running_menu_for_root_(false), - show_tree_(configuration == SHOW_TREE) { + show_tree_(configuration == SHOW_TREE), + handler_(handler) { DCHECK(profile); Init(); } @@ -75,6 +65,19 @@ BookmarkEditorView::~BookmarkEditorView() { bb_model_->RemoveObserver(this); } +// static +void BookmarkEditorView::Show(HWND parent_hwnd, + Profile* profile, + BookmarkNode* parent, + BookmarkNode* node, + Configuration configuration, + Handler* handler) { + DCHECK(profile); + BookmarkEditorView* editor = + new BookmarkEditorView(profile, parent, node, configuration, handler); + editor->Show(parent_hwnd); +} + bool BookmarkEditorView::IsDialogButtonEnabled(DialogButton button) const { if (button == DIALOGBUTTON_OK) { const GURL url(GetInputURL()); @@ -480,7 +483,11 @@ void BookmarkEditorView::ApplyEdits(EditorNode* parent) { if (!show_tree_ ) { if (!node_) { - bb_model_->AddURL(parent_, parent_->GetChildCount(), new_title, new_url); + BookmarkNode* node = + bb_model_->AddURL(parent_, parent_->GetChildCount(), new_title, + new_url); + if (handler_.get()) + handler_->NodeCreated(node); return; } // If we're not showing the tree we only need to modify the node. @@ -535,8 +542,11 @@ void BookmarkEditorView::ApplyEdits(EditorNode* parent) { } } else { // We're adding a new URL. - bb_model_->AddURL(new_parent, new_parent->GetChildCount(), new_title, - new_url); + BookmarkNode* node = + bb_model_->AddURL(new_parent, new_parent->GetChildCount(), new_title, + new_url); + if (handler_.get()) + handler_->NodeCreated(node); } } diff --git a/chrome/browser/views/bookmark_editor_view.h b/chrome/browser/views/bookmark_editor_view.h index 4e6e317..2cd4b01 100644 --- a/chrome/browser/views/bookmark_editor_view.h +++ b/chrome/browser/views/bookmark_editor_view.h @@ -50,27 +50,39 @@ class BookmarkEditorView : public views::View, FRIEND_TEST(BookmarkEditorViewTest, ChangeURLNoTree); FRIEND_TEST(BookmarkEditorViewTest, ChangeTitleNoTree); public: + // Handler is notified when the BookmarkEditorView creates a new bookmark. + // Handler is owned by the BookmarkEditorView and deleted when it is deleted. + class Handler { + public: + virtual ~Handler() {} + virtual void NodeCreated(BookmarkNode* new_node) = 0; + }; + // An enumeration of the possible configurations offered. enum Configuration { SHOW_TREE, NO_TREE }; + BookmarkEditorView(Profile* profile, + BookmarkNode* parent, + BookmarkNode* node, + Configuration configuration, + Handler* handler); + + virtual ~BookmarkEditorView(); + // Shows the BookmarkEditorView editing |node|. If |node| is NULL a new entry // is created initially parented to |parent|. If |show_tree| is false the - // tree is not shown. + // tree is not shown. BookmarkEditorView takes ownership of |handler| and + // deletes it when done. |handler| may be null. See description of Handler + // for details. static void Show(HWND parent_window, Profile* profile, BookmarkNode* parent, BookmarkNode* node, - Configuration configuration); - - BookmarkEditorView(Profile* profile, - BookmarkNode* parent, - BookmarkNode* node, - Configuration configuration); - - virtual ~BookmarkEditorView(); + Configuration configuration, + Handler* handler); // DialogDelegate methods: virtual bool IsDialogButtonEnabled(DialogButton button) const; @@ -264,6 +276,8 @@ class BookmarkEditorView : public views::View, // Is the tree shown? bool show_tree_; + scoped_ptr<Handler> handler_; + DISALLOW_COPY_AND_ASSIGN(BookmarkEditorView); }; diff --git a/chrome/browser/views/bookmark_editor_view_unittest.cc b/chrome/browser/views/bookmark_editor_view_unittest.cc index 24fb05e..4024c34 100644 --- a/chrome/browser/views/bookmark_editor_view_unittest.cc +++ b/chrome/browser/views/bookmark_editor_view_unittest.cc @@ -80,7 +80,7 @@ class BookmarkEditorViewTest : public testing::Test { // Makes sure the tree model matches that of the bookmark bar model. TEST_F(BookmarkEditorViewTest, ModelsMatch) { BookmarkEditorView editor(profile_.get(), NULL, NULL, - BookmarkEditorView::SHOW_TREE); + BookmarkEditorView::SHOW_TREE, NULL); BookmarkEditorView::EditorNode* editor_root = editor.tree_model_->GetRoot(); // The root should have two children, one for the bookmark bar node, // the other for the 'other bookmarks' folder. @@ -105,7 +105,7 @@ TEST_F(BookmarkEditorViewTest, ModelsMatch) { // Changes the title and makes sure parent/visual order doesn't change. TEST_F(BookmarkEditorViewTest, EditTitleKeepsPosition) { BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE); + BookmarkEditorView::SHOW_TREE, NULL); editor.title_tf_.SetText(L"new_a"); editor.ApplyEdits(editor.tree_model_->GetRoot()->GetChild(0)); @@ -121,7 +121,7 @@ TEST_F(BookmarkEditorViewTest, EditURLKeepsPosition) { Time node_time = Time::Now() + TimeDelta::FromDays(2); GetNode("a")->date_added_ = node_time; BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE); + BookmarkEditorView::SHOW_TREE, NULL); editor.url_tf_.SetText(UTF8ToWide(GURL(base_path() + "new_a").spec())); @@ -137,7 +137,7 @@ TEST_F(BookmarkEditorViewTest, EditURLKeepsPosition) { // Moves 'a' to be a child of the other node. TEST_F(BookmarkEditorViewTest, ChangeParent) { BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE); + BookmarkEditorView::SHOW_TREE, NULL); editor.ApplyEdits(editor.tree_model_->GetRoot()->GetChild(1)); @@ -151,7 +151,7 @@ TEST_F(BookmarkEditorViewTest, ChangeParentAndURL) { Time node_time = Time::Now() + TimeDelta::FromDays(2); GetNode("a")->date_added_ = node_time; BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE); + BookmarkEditorView::SHOW_TREE, NULL); editor.url_tf_.SetText(UTF8ToWide(GURL(base_path() + "new_a").spec())); @@ -166,7 +166,7 @@ TEST_F(BookmarkEditorViewTest, ChangeParentAndURL) { // Creates a new folder and moves a node to it. TEST_F(BookmarkEditorViewTest, MoveToNewParent) { BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE); + BookmarkEditorView::SHOW_TREE, NULL); // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21". BookmarkEditorView::EditorNode* f2 = @@ -198,7 +198,7 @@ TEST_F(BookmarkEditorViewTest, MoveToNewParent) { // Brings up the editor, creating a new URL on the bookmark bar. TEST_F(BookmarkEditorViewTest, NewURL) { BookmarkEditorView editor(profile_.get(), NULL, NULL, - BookmarkEditorView::SHOW_TREE); + BookmarkEditorView::SHOW_TREE, NULL); editor.url_tf_.SetText(UTF8ToWide(GURL(base_path() + "a").spec())); editor.title_tf_.SetText(L"new_a"); @@ -218,7 +218,7 @@ TEST_F(BookmarkEditorViewTest, NewURL) { TEST_F(BookmarkEditorViewTest, ChangeURLNoTree) { BookmarkEditorView editor(profile_.get(), NULL, model_->other_node()->GetChild(0), - BookmarkEditorView::NO_TREE); + BookmarkEditorView::NO_TREE, NULL); editor.url_tf_.SetText(UTF8ToWide(GURL(base_path() + "a").spec())); editor.title_tf_.SetText(L"new_a"); @@ -238,7 +238,7 @@ TEST_F(BookmarkEditorViewTest, ChangeURLNoTree) { TEST_F(BookmarkEditorViewTest, ChangeTitleNoTree) { BookmarkEditorView editor(profile_.get(), NULL, model_->other_node()->GetChild(0), - BookmarkEditorView::NO_TREE); + BookmarkEditorView::NO_TREE, NULL); editor.title_tf_.SetText(L"new_a"); diff --git a/chrome/browser/views/bookmark_manager_view.cc b/chrome/browser/views/bookmark_manager_view.cc index 050323a..cccf012 100644 --- a/chrome/browser/views/bookmark_manager_view.cc +++ b/chrome/browser/views/bookmark_manager_view.cc @@ -8,7 +8,6 @@ #include "base/gfx/skia_utils.h" #include "chrome/app/locales/locale_settings.h" -#include "chrome/browser/bookmarks/bookmark_context_menu.h" #include "chrome/browser/bookmarks/bookmark_folder_tree_model.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/bookmarks/bookmark_table_model.h" @@ -26,6 +25,7 @@ #include "chrome/common/pref_service.h" #include "chrome/views/container_win.h" #include "chrome/views/grid_layout.h" +#include "chrome/views/menu_button.h" #include "chrome/views/single_split_view.h" #include "chrome/views/window.h" @@ -56,15 +56,21 @@ BookmarkManagerView::BookmarkManagerView(Profile* profile) tree_view_->SetController(this); tree_view_->SetContextMenuController(this); - views::SingleSplitView* split_view = - new views::SingleSplitView(tree_view_, table_view_); + views::MenuButton* organize_menu_button = new views::MenuButton( + l10n_util::GetString(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU), + this, true); + + split_view_ = new views::SingleSplitView(tree_view_, table_view_); views::GridLayout* layout = new views::GridLayout(this); SetLayoutManager(layout); - const int search_cs_id = 1; + const int top_id = 1; const int split_cs_id = 2; layout->SetInsets(kPanelVertMargin, 0, 0, 0); - views::ColumnSet* column_set = layout->AddColumnSet(search_cs_id); + views::ColumnSet* column_set = layout->AddColumnSet(top_id); + column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, + 1, views::GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(1, kUnrelatedControlHorizontalSpacing); column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, 1, views::GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kButtonHEdgeMargin); @@ -73,13 +79,14 @@ BookmarkManagerView::BookmarkManagerView(Profile* profile) column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, views::GridLayout::USE_PREF, 0, 0); - layout->StartRow(0, search_cs_id); + layout->StartRow(0, top_id); + layout->AddView(organize_menu_button); layout->AddView(search_tf_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(1, split_cs_id); - layout->AddView(split_view); + layout->AddView(split_view_); BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); if (!bookmark_model->IsLoaded()) @@ -103,6 +110,7 @@ BookmarkManagerView::~BookmarkManagerView() { // static void BookmarkManagerView::RegisterPrefs(PrefService* prefs) { prefs->RegisterDictionaryPref(prefs::kBookmarkManagerPlacement); + prefs->RegisterIntegerPref(prefs::kBookmarkManagerSplitLocation, -1); } // static @@ -148,9 +156,14 @@ void BookmarkManagerView::SelectInTree(BookmarkNode* node) { int index = table_model_->IndexOfNode(node); if (index != -1) table_view_->Select(index); + // TODO(sky): this doesn't work when invoked from add page. + table_view_->RequestFocus(); } } +BookmarkNode* BookmarkManagerView::GetSelectedFolder() { + return tree_view_->GetSelectedBookmarkNode(); +} std::vector<BookmarkNode*> BookmarkManagerView::GetSelectedTableNodes() { std::vector<BookmarkNode*> nodes; @@ -196,6 +209,11 @@ bool BookmarkManagerView::RestoreWindowPosition(CRect* bounds, bounds, maximized, always_on_top); } +void BookmarkManagerView::WindowClosing() { + g_browser_process->local_state()->SetInteger( + prefs::kBookmarkManagerSplitLocation, split_view_->divider_x()); +} + void BookmarkManagerView::OnDoubleClick() { std::vector<BookmarkNode*> nodes = GetSelectedTableNodes(); if (nodes.empty()) @@ -222,6 +240,26 @@ void BookmarkManagerView::OnTableViewDelete(views::TableView* table) { } } +void BookmarkManagerView::OnKeyDown(unsigned short virtual_keycode) { + switch (virtual_keycode) { + case VK_RETURN: { + std::vector<BookmarkNode*> selected_nodes = GetSelectedTableNodes(); + if (selected_nodes.size() == 1 && selected_nodes[0]->is_folder()) + SelectInTree(selected_nodes[0]); + break; + } + + case VK_BACK: { + BookmarkNode* selected_folder = GetSelectedFolder(); + if (selected_folder != NULL && + selected_folder->GetParent() != GetBookmarkModel()->root_node()) { + SelectInTree(selected_folder->GetParent()); + } + break; + } + } +} + void BookmarkManagerView::OnTreeViewSelectionChanged( views::TreeView* tree_view) { views::TreeModelNode* node = tree_view_->GetSelectedNode(); @@ -285,30 +323,21 @@ void BookmarkManagerView::ShowContextMenu(views::View* source, int x, int y, bool is_mouse_gesture) { - if (!GetBookmarkModel()->IsLoaded()) - return; - - if (source == table_view_) { - std::vector<BookmarkNode*> nodes = GetSelectedTableNodes(); - if (nodes.empty()) - return; + DCHECK(source == table_view_ || source == tree_view_); + bool is_table = (source == table_view_); + ShowMenu(GetContainer()->GetHWND(), x, y, + is_table ? BookmarkContextMenu::BOOKMARK_MANAGER_TABLE : + BookmarkContextMenu::BOOKMARK_MANAGER_TREE); +} - BookmarkNode* parent = tree_view_->GetSelectedBookmarkNode(); - BookmarkContextMenu menu(GetContainer()->GetHWND(), profile_, NULL, NULL, - parent, nodes, - BookmarkContextMenu::BOOKMARK_MANAGER_TABLE); - menu.RunMenuAt(x, y); - } else if (source == tree_view_) { - BookmarkNode* node = tree_view_->GetSelectedBookmarkNode(); - if (!node) - return; - std::vector<BookmarkNode*> nodes; - nodes.push_back(node); - BookmarkContextMenu menu(GetContainer()->GetHWND(), profile_, NULL, NULL, - node, nodes, - BookmarkContextMenu::BOOKMARK_MANAGER_TREE); - menu.RunMenuAt(x, y); - } +void BookmarkManagerView::RunMenu(views::View* source, + const CPoint& pt, + HWND hwnd) { + // TODO(glen): when you change the buttons around and what not, futz with + // this to make it look good. If you end up keeping padding numbers make them + // constants. + ShowMenu(hwnd, pt.x - source->width() + 5, pt.y + 2, + BookmarkContextMenu::BOOKMARK_MANAGER_ORGANIZE_MENU); } BookmarkTableModel* BookmarkManagerView::CreateSearchTableModel() { @@ -342,10 +371,20 @@ void BookmarkManagerView::PerformSearch() { } void BookmarkManagerView::PrepareForShow() { - views::SingleSplitView* split_view = - static_cast<views::SingleSplitView*>(table_view_->GetParent()); - // Give a third of the space to the tree. - split_view->set_divider_x(split_view->width() / 3); + // Restore the split location, but don't let it get too small (or big), + // otherwise users might inadvertently not see the divider. + int split_x = g_browser_process->local_state()->GetInteger( + prefs::kBookmarkManagerSplitLocation); + if (split_x == -1) { + // First time running the bookmark manager, give a third of the width to + // the tree. + split_x = split_view_->width() / 3; + } + int min_split_size = split_view_->width() / 8; + // Make sure the user can see both the tree/table. + split_x = std::min(split_view_->width() - min_split_size, + std::max(min_split_size, split_x)); + split_view_->set_divider_x(split_x); if (!GetBookmarkModel()->IsLoaded()) { search_tf_->SetReadOnly(true); return; @@ -381,3 +420,35 @@ void BookmarkManagerView::LoadedImpl() { BookmarkModel* BookmarkManagerView::GetBookmarkModel() const { return profile_->GetBookmarkModel(); } + +void BookmarkManagerView::ShowMenu( + HWND host, + int x, + int y, + BookmarkContextMenu::ConfigurationType config) { + if (!GetBookmarkModel()->IsLoaded()) + return; + + if (config == BookmarkContextMenu::BOOKMARK_MANAGER_TABLE || + (config == BookmarkContextMenu::BOOKMARK_MANAGER_ORGANIZE_MENU && + table_view_->HasFocus())) { + std::vector<BookmarkNode*> nodes = GetSelectedTableNodes(); + if (nodes.empty()) + return; + + BookmarkNode* parent = GetSelectedFolder(); + BookmarkContextMenu menu(host, profile_, NULL, NULL, parent, nodes, + config); + menu.RunMenuAt(x, y); + } else { + BookmarkNode* node = GetSelectedFolder(); + if (!node) + return; + + std::vector<BookmarkNode*> nodes; + nodes.push_back(node); + BookmarkContextMenu menu(GetContainer()->GetHWND(), profile_, NULL, NULL, + node, nodes, config); + menu.RunMenuAt(x, y); + } +} diff --git a/chrome/browser/views/bookmark_manager_view.h b/chrome/browser/views/bookmark_manager_view.h index c397b33..8a28eac 100644 --- a/chrome/browser/views/bookmark_manager_view.h +++ b/chrome/browser/views/bookmark_manager_view.h @@ -6,11 +6,13 @@ #define CHROME_BROWSER_VIEWS_BOOKMARK_MANAGER_VIEW_H_ #include "base/task.h" +#include "chrome/browser/bookmarks/bookmark_context_menu.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/views/table_view.h" #include "chrome/views/text_field.h" #include "chrome/views/tree_view.h" #include "chrome/views/view.h" +#include "chrome/views/view_menu_delegate.h" #include "chrome/views/window_delegate.h" #include "webkit/glue/window_open_disposition.h" @@ -21,6 +23,9 @@ class BookmarkTableView; class PrefService; class Profile; +namespace views { +class SingleSplitView; +} // A view that lets the user manage their bookmarks. The bookmark manager // shows a tree on the left with a table on the right. The tree shows the // folder nodes and the table the contents of the selected tree node. The @@ -33,7 +38,8 @@ class BookmarkManagerView : public views::View, public views::TableViewObserver, public views::TextField::Controller, public BookmarkModelObserver, - public views::ContextMenuController { + public views::ContextMenuController, + public views::ViewMenuDelegate { public: explicit BookmarkManagerView(Profile* profile); virtual ~BookmarkManagerView(); @@ -50,6 +56,9 @@ class BookmarkManagerView : public views::View, // selected and node is selected in the table. void SelectInTree(BookmarkNode* node); + // Returns the selected folder, which may be null. + BookmarkNode* GetSelectedFolder(); + // Returns the selection of the table. std::vector<BookmarkNode*> GetSelectedTableNodes(); @@ -57,7 +66,7 @@ class BookmarkManagerView : public views::View, virtual gfx::Size GetPreferredSize(); - // WindowDelegate. + // WindowDelegate methods. virtual bool CanResize() const { return true; } virtual bool CanMaximize() const { return true; } virtual std::wstring GetWindowTitle() const; @@ -71,6 +80,9 @@ class BookmarkManagerView : public views::View, // TODO(sky): implement these when we have an icon. //virtual SkBitmap GetWindowIcon(); //virtual bool ShouldShowWindowIcon() const { return true; } + virtual void WindowClosing(); + + Profile* profile() const { return profile_; } private: // TableViewObserver methods. @@ -78,6 +90,7 @@ class BookmarkManagerView : public views::View, // Overriden to open the selected table nodes in the current browser. virtual void OnDoubleClick(); virtual void OnTableViewDelete(views::TableView* table); + virtual void OnKeyDown(unsigned short virtual_keycode); // TreeViewController method. virtual void OnTreeViewSelectionChanged(views::TreeView* tree_view); @@ -121,6 +134,9 @@ class BookmarkManagerView : public views::View, int y, bool is_mouse_gesture); + // ViewMenuDelegate. + virtual void RunMenu(views::View* source, const CPoint& pt, HWND hwnd); + // Creates the table model to use when searching. This returns NULL if there // is no search text. BookmarkTableModel* CreateSearchTableModel(); @@ -144,12 +160,20 @@ class BookmarkManagerView : public views::View, // Returns the BookmarkModel. BookmarkModel* GetBookmarkModel() const; + // Shows the menu. This is invoked to show the context menu for table/tree + // as well as to show the menu from the organize button. + void ShowMenu(HWND host, + int x, + int y, + BookmarkContextMenu::ConfigurationType config); + Profile* profile_; BookmarkTableView* table_view_; BookmarkFolderTreeView* tree_view_; scoped_ptr<BookmarkTableModel> table_model_; scoped_ptr<BookmarkFolderTreeModel> tree_model_; views::TextField* search_tf_; + views::SingleSplitView* split_view_; // Factory used for delaying search. ScopedRunnableMethodFactory<BookmarkManagerView> search_factory_; diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 0cb1b2c..d44ce18 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -216,13 +216,16 @@ const wchar_t kBookmarkTableNameWidth2[] = L"bookmark_table.name_width_2"; const wchar_t kBookmarkTableURLWidth2[] = L"bookmark_table.url_width_2"; const wchar_t kBookmarkTablePathWidth[] = L"bookmark_table.path_width"; -// Boolean pref to define the default values for using spellchecker. -const wchar_t kEnableSpellCheck[] = L"browser.enable_spellchecking"; - // Bounds of the bookmark manager. const wchar_t kBookmarkManagerPlacement[] = L"bookmark_manager.window_placement"; +// Integer location of the split bar in the bookmark manager. +const wchar_t kBookmarkManagerSplitLocation[] = + L"bookmark_manager.split_location"; + +// Boolean pref to define the default values for using spellchecker. +const wchar_t kEnableSpellCheck[] = L"browser.enable_spellchecking"; // *************** LOCAL STATE *************** // These are attached to the machine/installation diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index e5ce12b..7db0d1b 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -76,6 +76,7 @@ extern const wchar_t kBookmarkTableNameWidth2[]; extern const wchar_t kBookmarkTableURLWidth2[]; extern const wchar_t kBookmarkTablePathWidth[]; extern const wchar_t kBookmarkManagerPlacement[]; +extern const wchar_t kBookmarkManagerSplitLocation[]; extern const wchar_t kEnableSpellCheck[]; extern const wchar_t kDeleteTimePeriod[]; |