OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/views/bookmark_manager_view.h" | 5 #include "chrome/browser/views/bookmark_manager_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/gfx/skia_utils.h" | 9 #include "base/gfx/skia_utils.h" |
10 #include "chrome/app/locales/locale_settings.h" | 10 #include "chrome/app/locales/locale_settings.h" |
11 #include "chrome/browser/bookmarks/bookmark_folder_tree_model.h" | 11 #include "chrome/browser/bookmarks/bookmark_folder_tree_model.h" |
| 12 #include "chrome/browser/bookmarks/bookmark_html_writer.h" |
12 #include "chrome/browser/bookmarks/bookmark_model.h" | 13 #include "chrome/browser/bookmarks/bookmark_model.h" |
13 #include "chrome/browser/bookmarks/bookmark_table_model.h" | 14 #include "chrome/browser/bookmarks/bookmark_table_model.h" |
14 #include "chrome/browser/bookmarks/bookmark_utils.h" | 15 #include "chrome/browser/bookmarks/bookmark_utils.h" |
15 #include "chrome/browser/browser_list.h" | 16 #include "chrome/browser/browser_list.h" |
16 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
| 18 #include "chrome/browser/importer/importer.h" |
17 #include "chrome/browser/profile.h" | 19 #include "chrome/browser/profile.h" |
| 20 #include "chrome/browser/user_metrics.h" |
18 #include "chrome/browser/views/bookmark_editor_view.h" | 21 #include "chrome/browser/views/bookmark_editor_view.h" |
19 #include "chrome/browser/views/bookmark_folder_tree_view.h" | 22 #include "chrome/browser/views/bookmark_folder_tree_view.h" |
20 #include "chrome/browser/views/bookmark_table_view.h" | 23 #include "chrome/browser/views/bookmark_table_view.h" |
21 #include "chrome/browser/views/standard_layout.h" | 24 #include "chrome/browser/views/standard_layout.h" |
22 #include "chrome/common/gfx/chrome_canvas.h" | 25 #include "chrome/common/gfx/chrome_canvas.h" |
23 #include "chrome/common/gfx/color_utils.h" | 26 #include "chrome/common/gfx/color_utils.h" |
24 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
25 #include "chrome/common/pref_service.h" | 28 #include "chrome/common/pref_service.h" |
26 #include "chrome/views/container_win.h" | 29 #include "chrome/views/container_win.h" |
27 #include "chrome/views/grid_layout.h" | 30 #include "chrome/views/grid_layout.h" |
28 #include "chrome/views/menu_button.h" | 31 #include "chrome/views/menu_button.h" |
29 #include "chrome/views/single_split_view.h" | 32 #include "chrome/views/single_split_view.h" |
30 #include "chrome/views/window.h" | 33 #include "chrome/views/window.h" |
31 | 34 |
32 #include "generated_resources.h" | 35 #include "generated_resources.h" |
33 | 36 |
34 // If non-null, there is an open editor and this is the window it is contained | 37 // If non-null, there is an open editor and this is the window it is contained |
35 // in it. | 38 // in it. |
36 static views::Window* open_window = NULL; | 39 static views::Window* open_window = NULL; |
37 // And this is the manager contained in it. | 40 // And this is the manager contained in it. |
38 static BookmarkManagerView* manager = NULL; | 41 static BookmarkManagerView* manager = NULL; |
39 | 42 |
40 // Delay, in ms, between when the user types and when we run the search. | 43 // Delay, in ms, between when the user types and when we run the search. |
41 static const int kSearchDelayMS = 200; | 44 static const int kSearchDelayMS = 200; |
42 | 45 |
| 46 static const int kOrganizeMenuButtonID = 1; |
| 47 static const int kToolsMenuButtonID = 2; |
| 48 |
| 49 namespace { |
| 50 |
| 51 // Observer installed on the importer. When done importing the newly created |
| 52 // folder is selected in the bookmark manager. |
| 53 class ImportObserverImpl : public ImportObserver { |
| 54 public: |
| 55 explicit ImportObserverImpl(Profile* profile) : profile_(profile) { |
| 56 BookmarkModel* model = profile->GetBookmarkModel(); |
| 57 initial_other_count_ = model->other_node()->GetChildCount(); |
| 58 } |
| 59 |
| 60 virtual void ImportCanceled() { |
| 61 delete this; |
| 62 } |
| 63 |
| 64 virtual void ImportComplete() { |
| 65 // We aren't needed anymore. |
| 66 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 67 |
| 68 BookmarkManagerView* manager = BookmarkManagerView::current(); |
| 69 if (!manager || manager->profile() != profile_) |
| 70 return; |
| 71 |
| 72 BookmarkModel* model = profile_->GetBookmarkModel(); |
| 73 int other_count = model->other_node()->GetChildCount(); |
| 74 if (other_count == initial_other_count_ + 1) { |
| 75 BookmarkNode* imported_node = |
| 76 model->other_node()->GetChild(initial_other_count_); |
| 77 manager->SelectInTree(imported_node); |
| 78 manager->ExpandAll(imported_node); |
| 79 } |
| 80 } |
| 81 |
| 82 private: |
| 83 Profile* profile_; |
| 84 // Number of children in the other bookmarks folder at the time we were |
| 85 // created. |
| 86 int initial_other_count_; |
| 87 |
| 88 DISALLOW_COPY_AND_ASSIGN(ImportObserverImpl); |
| 89 }; |
| 90 |
| 91 } // namespace |
| 92 |
43 BookmarkManagerView::BookmarkManagerView(Profile* profile) | 93 BookmarkManagerView::BookmarkManagerView(Profile* profile) |
44 : profile_(profile->GetOriginalProfile()), | 94 : profile_(profile->GetOriginalProfile()), |
45 table_view_(NULL), | 95 table_view_(NULL), |
46 tree_view_(NULL), | 96 tree_view_(NULL), |
47 search_factory_(this) { | 97 search_factory_(this) { |
48 search_tf_ = new views::TextField(); | 98 search_tf_ = new views::TextField(); |
49 search_tf_->set_default_width_in_chars(40); | 99 search_tf_->set_default_width_in_chars(40); |
50 | 100 |
51 table_view_ = new BookmarkTableView(profile_, NULL); | 101 table_view_ = new BookmarkTableView(profile_, NULL); |
52 table_view_->SetObserver(this); | 102 table_view_->SetObserver(this); |
53 table_view_->SetContextMenuController(this); | 103 table_view_->SetContextMenuController(this); |
54 | 104 |
55 tree_view_ = new BookmarkFolderTreeView(profile_, NULL); | 105 tree_view_ = new BookmarkFolderTreeView(profile_, NULL); |
56 tree_view_->SetController(this); | 106 tree_view_->SetController(this); |
57 tree_view_->SetContextMenuController(this); | 107 tree_view_->SetContextMenuController(this); |
58 | 108 |
59 views::MenuButton* organize_menu_button = new views::MenuButton( | 109 views::MenuButton* organize_menu_button = new views::MenuButton( |
60 l10n_util::GetString(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU), | 110 l10n_util::GetString(IDS_BOOKMARK_MANAGER_ORGANIZE_MENU), |
61 this, true); | 111 this, true); |
| 112 organize_menu_button->SetID(kOrganizeMenuButtonID); |
| 113 |
| 114 views::MenuButton* tools_menu_button = new views::MenuButton( |
| 115 l10n_util::GetString(IDS_BOOKMARK_MANAGER_TOOLS_MENU), |
| 116 this, true); |
| 117 tools_menu_button->SetID(kToolsMenuButtonID); |
62 | 118 |
63 split_view_ = new views::SingleSplitView(tree_view_, table_view_); | 119 split_view_ = new views::SingleSplitView(tree_view_, table_view_); |
64 | 120 |
65 views::GridLayout* layout = new views::GridLayout(this); | 121 views::GridLayout* layout = new views::GridLayout(this); |
66 SetLayoutManager(layout); | 122 SetLayoutManager(layout); |
67 const int top_id = 1; | 123 const int top_id = 1; |
68 const int split_cs_id = 2; | 124 const int split_cs_id = 2; |
69 layout->SetInsets(kPanelVertMargin, 0, 0, 0); | 125 layout->SetInsets(2, 0, 0, 0); |
70 views::ColumnSet* column_set = layout->AddColumnSet(top_id); | 126 views::ColumnSet* column_set = layout->AddColumnSet(top_id); |
71 column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, | 127 column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, |
72 1, views::GridLayout::USE_PREF, 0, 0); | 128 0, views::GridLayout::USE_PREF, 0, 0); |
| 129 column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); |
| 130 column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, |
| 131 0, views::GridLayout::USE_PREF, 0, 0); |
73 column_set->AddPaddingColumn(1, kUnrelatedControlHorizontalSpacing); | 132 column_set->AddPaddingColumn(1, kUnrelatedControlHorizontalSpacing); |
74 column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, | 133 column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, |
75 1, views::GridLayout::USE_PREF, 0, 0); | 134 1, views::GridLayout::USE_PREF, 0, 0); |
76 column_set->AddPaddingColumn(0, kButtonHEdgeMargin); | 135 column_set->AddPaddingColumn(0, kButtonHEdgeMargin); |
77 | 136 |
78 column_set = layout->AddColumnSet(split_cs_id); | 137 column_set = layout->AddColumnSet(split_cs_id); |
79 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, | 138 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, |
80 views::GridLayout::USE_PREF, 0, 0); | 139 views::GridLayout::USE_PREF, 0, 0); |
81 | 140 |
82 layout->StartRow(0, top_id); | 141 layout->StartRow(0, top_id); |
83 layout->AddView(organize_menu_button); | 142 layout->AddView(organize_menu_button); |
| 143 layout->AddView(tools_menu_button); |
84 layout->AddView(search_tf_); | 144 layout->AddView(search_tf_); |
85 | 145 |
86 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); | 146 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); |
87 | 147 |
88 layout->StartRow(1, split_cs_id); | 148 layout->StartRow(1, split_cs_id); |
89 layout->AddView(split_view_); | 149 layout->AddView(split_view_); |
90 | 150 |
91 BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); | 151 BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); |
92 if (!bookmark_model->IsLoaded()) | 152 if (!bookmark_model->IsLoaded()) |
93 bookmark_model->AddObserver(this); | 153 bookmark_model->AddObserver(this); |
94 } | 154 } |
95 | 155 |
96 BookmarkManagerView::~BookmarkManagerView() { | 156 BookmarkManagerView::~BookmarkManagerView() { |
| 157 if (select_file_dialog_.get()) |
| 158 select_file_dialog_->ListenerDestroyed(); |
| 159 |
97 if (!GetBookmarkModel()->IsLoaded()) { | 160 if (!GetBookmarkModel()->IsLoaded()) { |
98 GetBookmarkModel()->RemoveObserver(this); | 161 GetBookmarkModel()->RemoveObserver(this); |
99 } else { | 162 } else { |
100 // The models are deleted before the views. Make sure we set the models of | 163 // The models are deleted before the views. Make sure we set the models of |
101 // the views to NULL so that they aren't left holding a reference to a | 164 // the views to NULL so that they aren't left holding a reference to a |
102 // deleted model. | 165 // deleted model. |
103 table_view_->SetModel(NULL); | 166 table_view_->SetModel(NULL); |
104 tree_view_->SetModel(NULL); | 167 tree_view_->SetModel(NULL); |
105 } | 168 } |
106 manager = NULL; | 169 manager = NULL; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 | 220 |
158 if (node->is_url()) { | 221 if (node->is_url()) { |
159 int index = table_model_->IndexOfNode(node); | 222 int index = table_model_->IndexOfNode(node); |
160 if (index != -1) | 223 if (index != -1) |
161 table_view_->Select(index); | 224 table_view_->Select(index); |
162 // TODO(sky): this doesn't work when invoked from add page. | 225 // TODO(sky): this doesn't work when invoked from add page. |
163 table_view_->RequestFocus(); | 226 table_view_->RequestFocus(); |
164 } | 227 } |
165 } | 228 } |
166 | 229 |
| 230 void BookmarkManagerView::ExpandAll(BookmarkNode* node) { |
| 231 BookmarkNode* parent = node->is_url() ? node->GetParent() : node; |
| 232 FolderNode* folder_node = tree_model_->GetFolderNodeForBookmarkNode(parent); |
| 233 if (!folder_node) { |
| 234 NOTREACHED(); |
| 235 return; |
| 236 } |
| 237 tree_view_->ExpandAll(folder_node); |
| 238 } |
| 239 |
167 BookmarkNode* BookmarkManagerView::GetSelectedFolder() { | 240 BookmarkNode* BookmarkManagerView::GetSelectedFolder() { |
168 return tree_view_->GetSelectedBookmarkNode(); | 241 return tree_view_->GetSelectedBookmarkNode(); |
169 } | 242 } |
170 | 243 |
171 std::vector<BookmarkNode*> BookmarkManagerView::GetSelectedTableNodes() { | 244 std::vector<BookmarkNode*> BookmarkManagerView::GetSelectedTableNodes() { |
172 std::vector<BookmarkNode*> nodes; | 245 std::vector<BookmarkNode*> nodes; |
173 for (views::TableView::iterator i = table_view_->SelectionBegin(); | 246 for (views::TableView::iterator i = table_view_->SelectionBegin(); |
174 i != table_view_->SelectionEnd(); ++i) { | 247 i != table_view_->SelectionEnd(); ++i) { |
175 nodes.push_back(table_model_->GetNodeForRow(*i)); | 248 nodes.push_back(table_model_->GetNodeForRow(*i)); |
176 } | 249 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 is_table ? BookmarkContextMenu::BOOKMARK_MANAGER_TABLE : | 405 is_table ? BookmarkContextMenu::BOOKMARK_MANAGER_TABLE : |
333 BookmarkContextMenu::BOOKMARK_MANAGER_TREE); | 406 BookmarkContextMenu::BOOKMARK_MANAGER_TREE); |
334 } | 407 } |
335 | 408 |
336 void BookmarkManagerView::RunMenu(views::View* source, | 409 void BookmarkManagerView::RunMenu(views::View* source, |
337 const CPoint& pt, | 410 const CPoint& pt, |
338 HWND hwnd) { | 411 HWND hwnd) { |
339 // TODO(glen): when you change the buttons around and what not, futz with | 412 // TODO(glen): when you change the buttons around and what not, futz with |
340 // this to make it look good. If you end up keeping padding numbers make them | 413 // this to make it look good. If you end up keeping padding numbers make them |
341 // constants. | 414 // constants. |
342 ShowMenu(hwnd, pt.x - source->width() + 5, pt.y + 2, | 415 if (!GetBookmarkModel()->IsLoaded()) |
343 BookmarkContextMenu::BOOKMARK_MANAGER_ORGANIZE_MENU); | 416 return; |
| 417 |
| 418 if (source->GetID() == kOrganizeMenuButtonID) { |
| 419 ShowMenu(hwnd, pt.x - source->width() + 5, pt.y + 2, |
| 420 BookmarkContextMenu::BOOKMARK_MANAGER_ORGANIZE_MENU); |
| 421 } else if (source->GetID() == kToolsMenuButtonID) { |
| 422 ShowToolsMenu(hwnd, pt.x - source->width() + 5, pt.y + 2); |
| 423 } else { |
| 424 NOTREACHED(); |
| 425 } |
| 426 } |
| 427 |
| 428 void BookmarkManagerView::ExecuteCommand(int id) { |
| 429 switch (id) { |
| 430 case IDS_BOOKMARK_MANAGER_IMPORT_MENU: |
| 431 UserMetrics::RecordAction(L"BookmarkManager_Import", profile_); |
| 432 ShowImportBookmarksFileChooser(); |
| 433 break; |
| 434 |
| 435 case IDS_BOOKMARK_MANAGER_EXPORT_MENU: |
| 436 UserMetrics::RecordAction(L"BookmarkManager_Export", profile_); |
| 437 ShowExportBookmarksFileChooser(); |
| 438 break; |
| 439 |
| 440 default: |
| 441 NOTREACHED(); |
| 442 break; |
| 443 } |
| 444 } |
| 445 |
| 446 void BookmarkManagerView::FileSelected(const std::wstring& path, |
| 447 void* params) { |
| 448 int id = reinterpret_cast<int>(params); |
| 449 if (id == IDS_BOOKMARK_MANAGER_IMPORT_MENU) { |
| 450 // ImporterHost is ref counted and will delete itself when done. |
| 451 ImporterHost* host = new ImporterHost(); |
| 452 ProfileInfo profile_info; |
| 453 profile_info.browser_type = BOOKMARKS_HTML; |
| 454 profile_info.source_path = path; |
| 455 StartImportingWithUI(GetContainer()->GetHWND(), FAVORITES, host, |
| 456 profile_info, profile_, |
| 457 new ImportObserverImpl(profile()), false); |
| 458 } else if (id == IDS_BOOKMARK_MANAGER_EXPORT_MENU) { |
| 459 if (g_browser_process->io_thread()) { |
| 460 bookmark_html_writer::WriteBookmarks( |
| 461 g_browser_process->io_thread()->message_loop(), GetBookmarkModel(), |
| 462 path); |
| 463 } |
| 464 } else { |
| 465 NOTREACHED(); |
| 466 } |
| 467 } |
| 468 |
| 469 void BookmarkManagerView::FileSelectionCanceled(void* params) { |
| 470 select_file_dialog_ = NULL; |
344 } | 471 } |
345 | 472 |
346 BookmarkTableModel* BookmarkManagerView::CreateSearchTableModel() { | 473 BookmarkTableModel* BookmarkManagerView::CreateSearchTableModel() { |
347 std::wstring search_text = search_tf_->GetText(); | 474 std::wstring search_text = search_tf_->GetText(); |
348 if (search_text.empty()) | 475 if (search_text.empty()) |
349 return NULL; | 476 return NULL; |
350 return BookmarkTableModel::CreateSearchTableModel(GetBookmarkModel(), | 477 return BookmarkTableModel::CreateSearchTableModel(GetBookmarkModel(), |
351 search_text); | 478 search_text); |
352 } | 479 } |
353 | 480 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 } else { | 576 } else { |
450 BookmarkNode* node = GetSelectedFolder(); | 577 BookmarkNode* node = GetSelectedFolder(); |
451 std::vector<BookmarkNode*> nodes; | 578 std::vector<BookmarkNode*> nodes; |
452 if (node) | 579 if (node) |
453 nodes.push_back(node); | 580 nodes.push_back(node); |
454 BookmarkContextMenu menu(GetContainer()->GetHWND(), profile_, NULL, NULL, | 581 BookmarkContextMenu menu(GetContainer()->GetHWND(), profile_, NULL, NULL, |
455 node, nodes, config); | 582 node, nodes, config); |
456 menu.RunMenuAt(x, y); | 583 menu.RunMenuAt(x, y); |
457 } | 584 } |
458 } | 585 } |
| 586 |
| 587 void BookmarkManagerView::ShowToolsMenu(HWND host, int x, int y) { |
| 588 views::MenuItemView menu(this); |
| 589 menu.AppendMenuItemWithLabel( |
| 590 IDS_BOOKMARK_MANAGER_IMPORT_MENU, |
| 591 l10n_util::GetString(IDS_BOOKMARK_MANAGER_IMPORT_MENU)); |
| 592 menu.AppendMenuItemWithLabel( |
| 593 IDS_BOOKMARK_MANAGER_EXPORT_MENU, |
| 594 l10n_util::GetString(IDS_BOOKMARK_MANAGER_EXPORT_MENU)); |
| 595 menu.RunMenuAt(GetContainer()->GetHWND(), gfx::Rect(x, y, 0, 0), |
| 596 views::MenuItemView::TOPLEFT, true); |
| 597 } |
| 598 |
| 599 void BookmarkManagerView::ShowImportBookmarksFileChooser() { |
| 600 if (select_file_dialog_.get()) |
| 601 select_file_dialog_->ListenerDestroyed(); |
| 602 |
| 603 // TODO(sky): need a textual description here once we can add new |
| 604 // strings. |
| 605 std::wstring filter_string(L"*.html\0*.html\0\0"); |
| 606 select_file_dialog_ = SelectFileDialog::Create(this); |
| 607 select_file_dialog_->SelectFile( |
| 608 SelectFileDialog::SELECT_OPEN_FILE, std::wstring(), std::wstring(), |
| 609 filter_string, GetContainer()->GetHWND(), |
| 610 reinterpret_cast<void*>(IDS_BOOKMARK_MANAGER_IMPORT_MENU)); |
| 611 } |
| 612 |
| 613 void BookmarkManagerView::ShowExportBookmarksFileChooser() { |
| 614 if (select_file_dialog_.get()) |
| 615 select_file_dialog_->ListenerDestroyed(); |
| 616 |
| 617 select_file_dialog_ = SelectFileDialog::Create(this); |
| 618 select_file_dialog_->SelectFile( |
| 619 SelectFileDialog::SELECT_SAVEAS_FILE, std::wstring(), std::wstring(), |
| 620 std::wstring(), GetContainer()->GetHWND(), |
| 621 reinterpret_cast<void*>(IDS_BOOKMARK_MANAGER_EXPORT_MENU)); |
| 622 } |
OLD | NEW |