diff options
Diffstat (limited to 'chrome/browser/views/bookmark_manager_view.cc')
-rw-r--r-- | chrome/browser/views/bookmark_manager_view.cc | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/chrome/browser/views/bookmark_manager_view.cc b/chrome/browser/views/bookmark_manager_view.cc new file mode 100644 index 0000000..050323a --- /dev/null +++ b/chrome/browser/views/bookmark_manager_view.cc @@ -0,0 +1,383 @@ +// Copyright (c) 2006-2008 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. + +#include "chrome/browser/views/bookmark_manager_view.h" + +#include <algorithm> + +#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" +#include "chrome/browser/bookmarks/bookmark_utils.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/views/bookmark_editor_view.h" +#include "chrome/browser/views/bookmark_folder_tree_view.h" +#include "chrome/browser/views/bookmark_table_view.h" +#include "chrome/browser/views/standard_layout.h" +#include "chrome/common/gfx/chrome_canvas.h" +#include "chrome/common/gfx/color_utils.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/views/container_win.h" +#include "chrome/views/grid_layout.h" +#include "chrome/views/single_split_view.h" +#include "chrome/views/window.h" + +#include "generated_resources.h" + +// If non-null, there is an open editor and this is the window it is contained +// in it. +static views::Window* open_window = NULL; +// And this is the manager contained in it. +static BookmarkManagerView* manager = NULL; + +// Delay, in ms, between when the user types and when we run the search. +static const int kSearchDelayMS = 200; + +BookmarkManagerView::BookmarkManagerView(Profile* profile) + : profile_(profile->GetOriginalProfile()), + table_view_(NULL), + tree_view_(NULL), + search_factory_(this) { + search_tf_ = new views::TextField(); + search_tf_->set_default_width_in_chars(40); + + table_view_ = new BookmarkTableView(profile_, NULL); + table_view_->SetObserver(this); + table_view_->SetContextMenuController(this); + + tree_view_ = new BookmarkFolderTreeView(profile_, NULL); + tree_view_->SetController(this); + tree_view_->SetContextMenuController(this); + + views::SingleSplitView* 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 split_cs_id = 2; + layout->SetInsets(kPanelVertMargin, 0, 0, 0); + views::ColumnSet* column_set = layout->AddColumnSet(search_cs_id); + column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, + 1, views::GridLayout::USE_PREF, 0, 0); + column_set->AddPaddingColumn(0, kButtonHEdgeMargin); + + column_set = layout->AddColumnSet(split_cs_id); + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, + views::GridLayout::USE_PREF, 0, 0); + + layout->StartRow(0, search_cs_id); + layout->AddView(search_tf_); + + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + + layout->StartRow(1, split_cs_id); + layout->AddView(split_view); + + BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); + if (!bookmark_model->IsLoaded()) + bookmark_model->AddObserver(this); +} + +BookmarkManagerView::~BookmarkManagerView() { + if (!GetBookmarkModel()->IsLoaded()) { + GetBookmarkModel()->RemoveObserver(this); + } else { + // The models are deleted before the views. Make sure we set the models of + // the views to NULL so that they aren't left holding a reference to a + // deleted model. + table_view_->SetModel(NULL); + tree_view_->SetModel(NULL); + } + manager = NULL; + open_window = NULL; +} + +// static +void BookmarkManagerView::RegisterPrefs(PrefService* prefs) { + prefs->RegisterDictionaryPref(prefs::kBookmarkManagerPlacement); +} + +// static +void BookmarkManagerView::Show(Profile* profile) { + if (!profile->GetBookmarkModel()) + return; + + if (open_window != NULL) { + open_window->MoveToFront(true); + return; + } + + // Both of these will be deleted when the dialog closes. + manager = new BookmarkManagerView(profile); + + // Create the window. + open_window = views::Window::CreateChromeWindow(NULL, gfx::Rect(), manager); + // Let the manager know it's parented. + manager->PrepareForShow(); + // And show it. + open_window->Show(); +} + +// static +BookmarkManagerView* BookmarkManagerView::current() { + return manager; +} + +void BookmarkManagerView::SelectInTree(BookmarkNode* node) { + if (!node) + return; + + BookmarkNode* parent = node->is_url() ? node->GetParent() : node; + FolderNode* folder_node = tree_model_->GetFolderNodeForBookmarkNode(parent); + if (!folder_node) { + NOTREACHED(); + return; + } + + tree_view_->SetSelectedNode(folder_node); + + if (node->is_url()) { + int index = table_model_->IndexOfNode(node); + if (index != -1) + table_view_->Select(index); + } +} + + +std::vector<BookmarkNode*> BookmarkManagerView::GetSelectedTableNodes() { + std::vector<BookmarkNode*> nodes; + for (views::TableView::iterator i = table_view_->SelectionBegin(); + i != table_view_->SelectionEnd(); ++i) { + nodes.push_back(table_model_->GetNodeForRow(*i)); + } + // TableViews iterator iterates in reverse order. Reverse the nodes so they + // are opened in visual order. + std::reverse(nodes.begin(), nodes.end()); + return nodes; +} + +void BookmarkManagerView::PaintBackground(ChromeCanvas* canvas) { + canvas->drawColor(color_utils::GetSysSkColor(COLOR_3DFACE), + SkPorterDuff::kSrc_Mode); +} + +gfx::Size BookmarkManagerView::GetPreferredSize() { + return gfx::Size(views::Window::GetLocalizedContentsSize( + IDS_BOOKMARK_MANAGER_DIALOG_WIDTH_CHARS, + IDS_BOOKMARK_MANAGER_DIALOG_HEIGHT_LINES)); +} + +std::wstring BookmarkManagerView::GetWindowTitle() const { + return l10n_util::GetString(IDS_BOOKMARK_MANAGER_TITLE); +} + +void BookmarkManagerView::SaveWindowPosition(const CRect& bounds, + bool maximized, + bool always_on_top) { + window()->SaveWindowPositionToPrefService(g_browser_process->local_state(), + prefs::kBookmarkManagerPlacement, + bounds, maximized, always_on_top); +} + +bool BookmarkManagerView::RestoreWindowPosition(CRect* bounds, + bool* maximized, + bool* always_on_top) { + return window()->RestoreWindowPositionFromPrefService( + g_browser_process->local_state(), + prefs::kBookmarkManagerPlacement, + bounds, maximized, always_on_top); +} + +void BookmarkManagerView::OnDoubleClick() { + std::vector<BookmarkNode*> nodes = GetSelectedTableNodes(); + if (nodes.empty()) + return; + if (nodes.size() == 1 && nodes[0]->is_folder()) { + // Double click on a folder descends into the folder. + SelectInTree(nodes[0]); + return; + } + // TODO(sky): OnDoubleClick needs a handle to the current mouse event so that + // we can use + // event_utils::DispositionFromEventFlags(sender->mouse_event_flags()) . + bookmark_utils::OpenAll( + GetContainer()->GetHWND(), profile_, NULL, nodes, CURRENT_TAB); +} + +void BookmarkManagerView::OnTableViewDelete(views::TableView* table) { + std::vector<BookmarkNode*> nodes = GetSelectedTableNodes(); + if (nodes.empty()) + return; + for (size_t i = 0; i < nodes.size(); ++i) { + GetBookmarkModel()->Remove(nodes[i]->GetParent(), + nodes[i]->GetParent()->IndexOfChild(nodes[i])); + } +} + +void BookmarkManagerView::OnTreeViewSelectionChanged( + views::TreeView* tree_view) { + views::TreeModelNode* node = tree_view_->GetSelectedNode(); + + BookmarkTableModel* new_table_model = NULL; + BookmarkNode* table_parent_node = NULL; + + if (node) { + switch (tree_model_->GetNodeType(node)) { + case BookmarkFolderTreeModel::BOOKMARK: + table_parent_node = tree_model_->TreeNodeAsBookmarkNode(node); + new_table_model = + BookmarkTableModel::CreateBookmarkTableModelForFolder( + profile_->GetBookmarkModel(), + table_parent_node); + break; + + case BookmarkFolderTreeModel::RECENTLY_BOOKMARKED: + new_table_model = BookmarkTableModel::CreateRecentlyBookmarkedModel( + profile_->GetBookmarkModel()); + break; + + case BookmarkFolderTreeModel::SEARCH: + search_factory_.RevokeAll(); + new_table_model = CreateSearchTableModel(); + break; + + default: + NOTREACHED(); + break; + } + } + + SetTableModel(new_table_model, table_parent_node); +} + +void BookmarkManagerView::Loaded(BookmarkModel* model) { + model->RemoveObserver(this); + LoadedImpl(); +} + +void BookmarkManagerView::ContentsChanged(views::TextField* sender, + const std::wstring& new_contents) { + search_factory_.RevokeAll(); + MessageLoop::current()->PostDelayedTask(FROM_HERE, + search_factory_.NewRunnableMethod(&BookmarkManagerView::PerformSearch), + kSearchDelayMS); +} + +void BookmarkManagerView::HandleKeystroke(views::TextField* sender, + UINT message, TCHAR key, + UINT repeat_count, + UINT flags) { + if (key == VK_RETURN) { + PerformSearch(); + search_tf_->SelectAll(); + } +} + +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; + + 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); + } +} + +BookmarkTableModel* BookmarkManagerView::CreateSearchTableModel() { + std::wstring search_text = search_tf_->GetText(); + if (search_text.empty()) + return NULL; + return BookmarkTableModel::CreateSearchTableModel(GetBookmarkModel(), + search_text); +} + +void BookmarkManagerView::SetTableModel(BookmarkTableModel* new_table_model, + BookmarkNode* parent_node) { + // Be sure and reset the model on the view before updating table_model_. + // Otherwise the view will attempt to use the deleted model when we set the + // new one. + table_view_->SetModel(NULL); + table_view_->SetShowPathColumn(!parent_node); + table_view_->SetModel(new_table_model); + table_view_->set_parent_node(parent_node); + table_model_.reset(new_table_model); +} + +void BookmarkManagerView::PerformSearch() { + search_factory_.RevokeAll(); + // Reset the controller, otherwise when we change the selection we'll get + // notified and update the model twice. + tree_view_->SetController(NULL); + tree_view_->SetSelectedNode(tree_model_->search_node()); + tree_view_->SetController(this); + SetTableModel(CreateSearchTableModel(), NULL); +} + +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); + if (!GetBookmarkModel()->IsLoaded()) { + search_tf_->SetReadOnly(true); + return; + } + + LoadedImpl(); +} + +void BookmarkManagerView::LoadedImpl() { + BookmarkModel* bookmark_model = GetBookmarkModel(); + BookmarkNode* bookmark_bar_node = bookmark_model->GetBookmarkBarNode(); + table_model_.reset( + BookmarkTableModel::CreateBookmarkTableModelForFolder(bookmark_model, + bookmark_bar_node)); + table_view_->SetModel(table_model_.get()); + table_view_->set_parent_node(bookmark_bar_node); + + tree_model_.reset(new BookmarkFolderTreeModel(bookmark_model)); + tree_view_->SetModel(tree_model_.get()); + + tree_view_->ExpandAll(); + + tree_view_->SetSelectedNode( + tree_model_->GetFolderNodeForBookmarkNode(bookmark_bar_node)); + + search_tf_->SetReadOnly(false); + search_tf_->SetController(this); + + Layout(); + SchedulePaint(); +} + +BookmarkModel* BookmarkManagerView::GetBookmarkModel() const { + return profile_->GetBookmarkModel(); +} |