diff options
author | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-07 17:53:09 +0000 |
---|---|---|
committer | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-07 17:53:09 +0000 |
commit | fafc8a4203d4308251f17fc18a61cfec71a9a27c (patch) | |
tree | dfee81ebce10c148f4dfa13b4621bc8fd40473fb | |
parent | 8bc886faa6a178f51bf094efe491ab1da9595d14 (diff) | |
download | chromium_src-fafc8a4203d4308251f17fc18a61cfec71a9a27c.zip chromium_src-fafc8a4203d4308251f17fc18a61cfec71a9a27c.tar.gz chromium_src-fafc8a4203d4308251f17fc18a61cfec71a9a27c.tar.bz2 |
Adds cut/copy/paste support to the bookmark manager tree/table and
context menus.
BUG=4186
TEST=try cut/copy/paste from table/tree in the bookmark manager as
well as context menus in bookmark manager.
Review URL: http://codereview.chromium.org/9481
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4993 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/bookmarks/bookmark_context_menu.cc | 42 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_drag_data.cc | 5 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_drag_data.h | 2 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_utils.cc | 53 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_utils.h | 17 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_manager_view.cc | 98 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_manager_view.h | 16 | ||||
-rw-r--r-- | chrome/views/tree_view.cc | 8 | ||||
-rw-r--r-- | chrome/views/tree_view.h | 3 |
9 files changed, 239 insertions, 5 deletions
diff --git a/chrome/browser/bookmarks/bookmark_context_menu.cc b/chrome/browser/bookmarks/bookmark_context_menu.cc index 1841f2b..9cdacbf 100644 --- a/chrome/browser/bookmarks/bookmark_context_menu.cc +++ b/chrome/browser/bookmarks/bookmark_context_menu.cc @@ -269,6 +269,20 @@ BookmarkContextMenu::BookmarkContextMenu( l10n_util::GetString(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); } + if (configuration == BOOKMARK_MANAGER_TABLE || + configuration == BOOKMARK_MANAGER_TABLE_OTHER || + configuration == BOOKMARK_MANAGER_TREE || + configuration == BOOKMARK_MANAGER_ORGANIZE_MENU || + configuration == BOOKMARK_MANAGER_ORGANIZE_MENU_OTHER) { + menu_->AppendSeparator(); + menu_->AppendMenuItemWithLabel( + IDS_CUT, l10n_util::GetString(IDS_CUT)); + menu_->AppendMenuItemWithLabel( + IDS_COPY, l10n_util::GetString(IDS_COPY)); + menu_->AppendMenuItemWithLabel( + IDS_PASTE, l10n_util::GetString(IDS_PASTE)); + } + menu_->AppendSeparator(); menu_->AppendMenuItemWithLabel( @@ -413,6 +427,26 @@ void BookmarkContextMenu::ExecuteCommand(int id) { BookmarkManagerView::Show(profile_); break; + case IDS_COPY: + case IDS_CUT: + bookmark_utils::CopyToClipboard(profile_->GetBookmarkModel(), + selection_, id == IDS_CUT); + break; + + case IDS_PASTE: { + // Always paste to parent. + if (!parent_) + return; + + int index = (selection_.size() == 1) ? + parent_->IndexOfChild(selection_[0]) : -1; + if (index != -1) + index++; + bookmark_utils::PasteFromClipboard(profile_->GetBookmarkModel(), + parent_, index); + break; + } + default: NOTREACHED(); } @@ -452,6 +486,14 @@ bool BookmarkContextMenu::IsCommandEnabled(int id) const { case IDS_BOOMARK_BAR_NEW_FOLDER: case IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK: return GetParentForNewNodes() != NULL; + + case IDS_COPY: + case IDS_CUT: + return selection_.size() > 0 && !is_root_node; + + case IDS_PASTE: + // Always paste to parent. + return bookmark_utils::CanPasteFromClipboard(parent_); } return true; } diff --git a/chrome/browser/bookmarks/bookmark_drag_data.cc b/chrome/browser/bookmarks/bookmark_drag_data.cc index c55d24f..2e7285a 100644 --- a/chrome/browser/bookmarks/bookmark_drag_data.cc +++ b/chrome/browser/bookmarks/bookmark_drag_data.cc @@ -92,7 +92,7 @@ void BookmarkDragData::Write(Profile* profile, OSExchangeData* data) const { } Pickle data_pickle; - data_pickle.WriteWString(profile->GetPath()); + data_pickle.WriteWString(profile ? profile->GetPath() : std::wstring()); data_pickle.WriteSize(elements.size()); for (size_t i = 0; i < elements.size(); ++i) @@ -162,5 +162,6 @@ BookmarkNode* BookmarkDragData::GetFirstNode(Profile* profile) const { } bool BookmarkDragData::IsFromProfile(Profile* profile) const { - return (profile->GetPath() == profile_path_); + // An empty path means the data is not associated with any profile. + return (!profile_path_.empty() && profile->GetPath() == profile_path_); } diff --git a/chrome/browser/bookmarks/bookmark_drag_data.h b/chrome/browser/bookmarks/bookmark_drag_data.h index 263bf8d..b02be0c 100644 --- a/chrome/browser/bookmarks/bookmark_drag_data.h +++ b/chrome/browser/bookmarks/bookmark_drag_data.h @@ -74,6 +74,8 @@ struct BookmarkDragData { // Writes elements to data. If there is only one element and it is a URL // the URL and title are written to the clipboard in a format other apps can // use. + // |profile| is used to identify which profile the data came from. Use a + // value of null to indicate the data is not associated with any profile. void Write(Profile* profile, OSExchangeData* data) const; // Restores this data from the clipboard, returning true on success. diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc index bf2576f..8aad4f1 100644 --- a/chrome/browser/bookmarks/bookmark_utils.cc +++ b/chrome/browser/bookmarks/bookmark_utils.cc @@ -12,6 +12,7 @@ #include "chrome/browser/tab_contents.h" #include "chrome/common/drag_drop_types.h" #include "chrome/common/l10n_util.h" +#include "chrome/common/os_exchange_data.h" #include "chrome/views/event.h" #include "chromium_strings.h" @@ -237,4 +238,56 @@ void OpenAll(HWND parent, OpenAll(parent, profile, navigator, nodes, initial_disposition); } +void CopyToClipboard(BookmarkModel* model, + const std::vector<BookmarkNode*>& nodes, + bool remove_nodes) { + if (nodes.empty()) + return; + + OSExchangeData* data = new OSExchangeData(); + BookmarkDragData(nodes).Write(NULL, data); + OleSetClipboard(data); + // OLE takes ownership of OSExchangeData. + + if (remove_nodes) { + for (size_t i = 0; i < nodes.size(); ++i) { + model->Remove(nodes[i]->GetParent(), + nodes[i]->GetParent()->IndexOfChild(nodes[i])); + } + } +} + +void PasteFromClipboard(BookmarkModel* model, + BookmarkNode* parent, + int index) { + if (!parent) + return; + + IDataObject* data; + if (OleGetClipboard(&data) != S_OK) + return; + + OSExchangeData data_wrapper(data); + BookmarkDragData bookmark_data; + if (!bookmark_data.Read(data_wrapper)) + return; + + if (index == -1) + index = parent->GetChildCount(); + bookmark_utils::CloneDragData(model, bookmark_data.elements, parent, index); +} + +bool CanPasteFromClipboard(BookmarkNode* node) { + if (!node) + return false; + + IDataObject* data; + if (OleGetClipboard(&data) != S_OK) + return false; + + OSExchangeData data_wrapper(data); + BookmarkDragData bookmark_data; + return bookmark_data.Read(data_wrapper); +} + } // namespace bookmark_utils diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h index 281cf8c..3a72fbb 100644 --- a/chrome/browser/bookmarks/bookmark_utils.h +++ b/chrome/browser/bookmarks/bookmark_utils.h @@ -58,6 +58,23 @@ void OpenAll(HWND parent, BookmarkNode* node, WindowOpenDisposition initial_disposition); +// Copies nodes onto the clipboard. If |remove_nodes| is true the nodes are +// removed after copied to the clipboard. The nodes are copied in such a way +// that if pasted again copies are made. +void CopyToClipboard(BookmarkModel* model, + const std::vector<BookmarkNode*>& nodes, + bool remove_nodes); + +// Pastes from the clipboard. The new nodes are added to |parent|, unless +// |parent| is null in which case this does nothing. The nodes are inserted +// at |index|. If |index| is -1 the nodes are added to the end. +void PasteFromClipboard(BookmarkModel* model, + BookmarkNode* parent, + int index); + +// Returns true if the user can copy from the pasteboard. +bool CanPasteFromClipboard(BookmarkNode* node); + } // namespace bookmark_utils #endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_UTILS_H_ diff --git a/chrome/browser/views/bookmark_manager_view.cc b/chrome/browser/views/bookmark_manager_view.cc index 76ac3d7..0c967a5 100644 --- a/chrome/browser/views/bookmark_manager_view.cc +++ b/chrome/browser/views/bookmark_manager_view.cc @@ -88,6 +88,42 @@ class ImportObserverImpl : public ImportObserver { DISALLOW_COPY_AND_ASSIGN(ImportObserverImpl); }; +// Converts a virtual keycode into the CutCopyPasteType. +BookmarkManagerView::CutCopyPasteType KeyCodeToCutCopyPaste( + unsigned short virtual_keycode) { + switch (virtual_keycode) { + case VK_INSERT: + if (GetKeyState(VK_CONTROL) < 0) + return BookmarkManagerView::COPY; + if (GetKeyState(VK_SHIFT) < 0) + return BookmarkManagerView::PASTE; + return BookmarkManagerView::NONE; + + case VK_DELETE: + if (GetKeyState(VK_SHIFT) < 0) + return BookmarkManagerView::CUT; + return BookmarkManagerView::NONE; + + case 'C': + if (GetKeyState(VK_CONTROL) < 0) + return BookmarkManagerView::COPY; + return BookmarkManagerView::NONE; + + case 'V': + if (GetKeyState(VK_CONTROL) < 0) + return BookmarkManagerView::PASTE; + return BookmarkManagerView::NONE; + + case 'X': + if (GetKeyState(VK_CONTROL) < 0) + return BookmarkManagerView::CUT; + return BookmarkManagerView::NONE; + + default: + return BookmarkManagerView::NONE; + } +} + } // namespace BookmarkManagerView::BookmarkManagerView(Profile* profile) @@ -320,8 +356,13 @@ 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()) + if (selected_nodes.size() == 1 && selected_nodes[0]->is_folder()) { SelectInTree(selected_nodes[0]); + } else { + bookmark_utils::OpenAll( + GetContainer()->GetHWND(), profile_, NULL, selected_nodes, + CURRENT_TAB); + } break; } @@ -333,6 +374,10 @@ void BookmarkManagerView::OnKeyDown(unsigned short virtual_keycode) { } break; } + + default: + OnCutCopyPaste(KeyCodeToCutCopyPaste(virtual_keycode), true); + break; } } @@ -372,6 +417,24 @@ void BookmarkManagerView::OnTreeViewSelectionChanged( SetTableModel(new_table_model, table_parent_node); } +void BookmarkManagerView::OnTreeViewKeyDown(unsigned short virtual_keycode) { + switch (virtual_keycode) { + case VK_DELETE: { + BookmarkNode* node = GetSelectedFolder(); + if (!node || node->GetParent() == GetBookmarkModel()->root_node()) + return; + + BookmarkNode* parent = node->GetParent(); + GetBookmarkModel()->Remove(parent, parent->IndexOfChild(node)); + break; + } + + default: + OnCutCopyPaste(KeyCodeToCutCopyPaste(virtual_keycode), false); + break; + } +} + void BookmarkManagerView::Loaded(BookmarkModel* model) { model->RemoveObserver(this); LoadedImpl(); @@ -401,6 +464,14 @@ void BookmarkManagerView::ShowContextMenu(views::View* source, bool is_mouse_gesture) { DCHECK(source == table_view_ || source == tree_view_); bool is_table = (source == table_view_); + if (is_table && x == -1 && y == -1) { + // TODO(sky): promote code to tableview that determines the location based + // on the selection. This is temporary until I fix that. + gfx::Point location(table_view_->width() / 2, table_view_->height() / 2); + View::ConvertPointToScreen(table_view_, &location); + x = location.x(); + y = location.y(); + } ShowMenu(GetContainer()->GetHWND(), x, y, is_table ? BookmarkContextMenu::BOOKMARK_MANAGER_TABLE : BookmarkContextMenu::BOOKMARK_MANAGER_TREE); @@ -584,6 +655,31 @@ void BookmarkManagerView::ShowMenu( } } +void BookmarkManagerView::OnCutCopyPaste(CutCopyPasteType type, + bool from_table) { + if (type == CUT || type == COPY) { + std::vector<BookmarkNode*> nodes; + if (from_table) { + nodes = GetSelectedTableNodes(); + } else { + BookmarkNode* node = GetSelectedFolder(); + if (!node || node->GetParent() == GetBookmarkModel()->root_node()) + return; + nodes.push_back(node); + } + if (nodes.empty()) + return; + + bookmark_utils::CopyToClipboard(GetBookmarkModel(), nodes, type == CUT); + } else if (type == PASTE) { + int index = from_table ? table_view_->FirstSelectedRow() : -1; + if (index != -1) + index++; + bookmark_utils::PasteFromClipboard(GetBookmarkModel(), GetSelectedFolder(), + index); + } +} + void BookmarkManagerView::ShowToolsMenu(HWND host, int x, int y) { views::MenuItemView menu(this); menu.AppendMenuItemWithLabel( diff --git a/chrome/browser/views/bookmark_manager_view.h b/chrome/browser/views/bookmark_manager_view.h index 0aa83dd..be99a16 100644 --- a/chrome/browser/views/bookmark_manager_view.h +++ b/chrome/browser/views/bookmark_manager_view.h @@ -45,6 +45,13 @@ class BookmarkManagerView : public views::View, public views::MenuDelegate, public SelectFileDialog::Listener { public: + enum CutCopyPasteType { + CUT, + COPY, + PASTE, + NONE + }; + explicit BookmarkManagerView(Profile* profile); virtual ~BookmarkManagerView(); @@ -63,7 +70,7 @@ class BookmarkManagerView : public views::View, // Expands all the children of the selected folder. void ExpandAll(BookmarkNode* node); - // Returns the selected folder, which may be null. + // Returns the selected folder in the tree, which may be null. BookmarkNode* GetSelectedFolder(); // Returns the selection of the table. @@ -99,8 +106,9 @@ class BookmarkManagerView : public views::View, virtual void OnTableViewDelete(views::TableView* table); virtual void OnKeyDown(unsigned short virtual_keycode); - // TreeViewController method. + // TreeViewController methods. virtual void OnTreeViewSelectionChanged(views::TreeView* tree_view); + virtual void OnTreeViewKeyDown(unsigned short virtual_keycode); // BookmarkModelObserver. We're only installed as an observer until the // bookmarks are loaded. @@ -181,6 +189,10 @@ class BookmarkManagerView : public views::View, int y, BookmarkContextMenu::ConfigurationType config); + // Invoked to handle cut/copy/paste from the table or tree. If |from_table| + // is true the source is the table. + void OnCutCopyPaste(CutCopyPasteType type, bool from_table); + // Shows the tools menu. void ShowToolsMenu(HWND host, int x, int y); diff --git a/chrome/views/tree_view.cc b/chrome/views/tree_view.cc index 913b845..cbf577a 100644 --- a/chrome/views/tree_view.cc +++ b/chrome/views/tree_view.cc @@ -395,6 +395,14 @@ LRESULT TreeView::OnNotify(int w_param, LPNMHDR l_param) { return 0; } + case TVN_KEYDOWN: + if (controller_) { + NMTVKEYDOWN* key_down_message = + reinterpret_cast<NMTVKEYDOWN*>(l_param); + controller_->OnTreeViewKeyDown(key_down_message->wVKey); + } + break; + default: break; } diff --git a/chrome/views/tree_view.h b/chrome/views/tree_view.h index d0d083e..a385c60 100644 --- a/chrome/views/tree_view.h +++ b/chrome/views/tree_view.h @@ -97,6 +97,9 @@ class TreeViewController { virtual bool CanEdit(TreeView* tree_view, TreeModelNode* node) { return true; } + + // Invoked when a key is pressed on the tree view. + virtual void OnTreeViewKeyDown(unsigned short virtual_keycode) {} }; // TreeView ------------------------------------------------------------------- |