diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-02 09:16:44 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-02 09:16:44 +0000 |
commit | 16d51df40992e767f4df3cd8a0d50fcf15a20c4c (patch) | |
tree | e7d032e5ccf51e42dc95f89c403d1921d70d2b03 /chrome/browser/gtk/gtk_tree.cc | |
parent | 88301f32ceb483810043b4d426d1a853d00f3035 (diff) | |
download | chromium_src-16d51df40992e767f4df3cd8a0d50fcf15a20c4c.zip chromium_src-16d51df40992e767f4df3cd8a0d50fcf15a20c4c.tar.gz chromium_src-16d51df40992e767f4df3cd8a0d50fcf15a20c4c.tar.bz2 |
Next part of bad dependency removal (chrome/common -> chrome/browser)
This change introduces one more dependency on chrome/browser,
but it seems simpler to move gtk_util first and then fix it.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/661271
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40369 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk/gtk_tree.cc')
-rw-r--r-- | chrome/browser/gtk/gtk_tree.cc | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/chrome/browser/gtk/gtk_tree.cc b/chrome/browser/gtk/gtk_tree.cc new file mode 100644 index 0000000..b638027 --- /dev/null +++ b/chrome/browser/gtk/gtk_tree.cc @@ -0,0 +1,294 @@ +// Copyright (c) 2009 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/gtk/gtk_tree.h" + +#include "app/gfx/gtk_util.h" +#include "app/table_model.h" +#include "base/logging.h" +#include "base/string_util.h" +#include "chrome/browser/gtk/gtk_theme_provider.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace gtk_tree { + +gint GetRowNumForPath(GtkTreePath* path) { + gint* indices = gtk_tree_path_get_indices(path); + if (!indices) { + NOTREACHED(); + return -1; + } + return indices[0]; +} + +gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter) { + GtkTreePath* path = gtk_tree_model_get_path(model, iter); + int row = GetRowNumForPath(path); + gtk_tree_path_free(path); + return row; +} + +gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model, + GtkTreePath* sort_path) { + GtkTreePath *child_path = gtk_tree_model_sort_convert_path_to_child_path( + GTK_TREE_MODEL_SORT(sort_model), sort_path); + int row = GetRowNumForPath(child_path); + gtk_tree_path_free(child_path); + return row; +} + +void SelectAndFocusRowNum(int row, GtkTreeView* tree_view) { + GtkTreeModel* model = gtk_tree_view_get_model(tree_view); + if (!model) { + NOTREACHED(); + return; + } + GtkTreeIter iter; + if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) { + NOTREACHED(); + return; + } + GtkTreePath* path = gtk_tree_model_get_path(model, &iter); + gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE); + gtk_tree_path_free(path); +} + +bool RemoveRecursively(GtkTreeStore* tree_store, GtkTreeIter* iter) { + GtkTreeIter child; + if (gtk_tree_model_iter_children(GTK_TREE_MODEL(tree_store), &child, iter)) { + while (true) { + if (!RemoveRecursively(tree_store, &child)) + break; + } + } + return gtk_tree_store_remove(tree_store, iter); +} + +void GetSelectedIndicies(GtkTreeSelection* selection, std::set<int>* out) { + GList* list = gtk_tree_selection_get_selected_rows( + selection, NULL); + GList* node; + for (node = list; node != NULL; node = node->next) { + out->insert( + gtk_tree::GetRowNumForPath(static_cast<GtkTreePath*>(node->data))); + } + g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); + g_list_free(list); +} + +//////////////////////////////////////////////////////////////////////////////// +// TableAdapter + +TableAdapter::TableAdapter(Delegate* delegate, GtkListStore* list_store, + TableModel* table_model) + : delegate_(delegate), list_store_(list_store), table_model_(table_model) { + if (table_model) + table_model->SetObserver(this); +} + +void TableAdapter::SetModel(TableModel* table_model) { + table_model_ = table_model; + table_model_->SetObserver(this); +} + +void TableAdapter::AddNodeToList(int row) { + GtkTreeIter iter; + if (row == 0) { + gtk_list_store_prepend(list_store_, &iter); + } else { + GtkTreeIter sibling; + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &sibling, NULL, + row - 1); + gtk_list_store_insert_after(list_store_, &iter, &sibling); + } + + delegate_->SetColumnValues(row, &iter); +} + +void TableAdapter::OnModelChanged() { + delegate_->OnAnyModelUpdateStart(); + gtk_list_store_clear(list_store_); + delegate_->OnModelChanged(); + for (int i = 0; i < table_model_->RowCount(); ++i) + AddNodeToList(i); + delegate_->OnAnyModelUpdate(); +} + +void TableAdapter::OnItemsChanged(int start, int length) { + delegate_->OnAnyModelUpdateStart(); + GtkTreeIter iter; + bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &iter, + NULL, start); + for (int i = 0; i < length; ++i) { + if (!rv) { + NOTREACHED(); + return; + } + delegate_->SetColumnValues(start + i, &iter); + rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store_), &iter); + } + delegate_->OnAnyModelUpdate(); +} + +void TableAdapter::OnItemsAdded(int start, int length) { + delegate_->OnAnyModelUpdateStart(); + for (int i = 0; i < length; ++i) { + AddNodeToList(start + i); + } + delegate_->OnAnyModelUpdate(); +} + +void TableAdapter::OnItemsRemoved(int start, int length) { + delegate_->OnAnyModelUpdateStart(); + GtkTreeIter iter; + bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store_), &iter, + NULL, start); + for (int i = 0; i < length; ++i) { + if (!rv) { + NOTREACHED(); + return; + } + rv = gtk_list_store_remove(list_store_, &iter); + } + delegate_->OnAnyModelUpdate(); +} + +//////////////////////////////////////////////////////////////////////////////// +// TreeAdapter + +TreeAdapter::TreeAdapter(Delegate* delegate, TreeModel* tree_model) + : delegate_(delegate), + tree_model_(tree_model) { + tree_store_ = gtk_tree_store_new(COL_COUNT, + GDK_TYPE_PIXBUF, + G_TYPE_STRING, + G_TYPE_POINTER); + tree_model->AddObserver(this); + + std::vector<SkBitmap> icons; + tree_model->GetIcons(&icons); + for (size_t i = 0; i < icons.size(); ++i) { + pixbufs_.push_back(gfx::GdkPixbufFromSkBitmap(&icons[i])); + } +} + +TreeAdapter::~TreeAdapter() { + g_object_unref(tree_store_); + for (size_t i = 0; i < pixbufs_.size(); ++i) + g_object_unref(pixbufs_[i]); +} + +void TreeAdapter::Init() { + gtk_tree_store_clear(tree_store_); + Fill(NULL, tree_model_->GetRoot()); +} + + +TreeModelNode* TreeAdapter::GetNode(GtkTreeIter* iter) { + TreeModelNode* node; + gtk_tree_model_get(GTK_TREE_MODEL(tree_store_), iter, + COL_NODE_PTR, &node, + -1); + return node; +} + +void TreeAdapter::FillRow(GtkTreeIter* iter, TreeModelNode* node) { + GdkPixbuf* pixbuf = NULL; + int icon_index = tree_model_->GetIconIndex(node); + if (icon_index >= 0 && icon_index < static_cast<int>(pixbufs_.size())) + pixbuf = pixbufs_[icon_index]; + else + pixbuf = GtkThemeProvider::GetFolderIcon(true); + gtk_tree_store_set(tree_store_, iter, + COL_ICON, pixbuf, + COL_TITLE, WideToUTF8(node->GetTitle()).c_str(), + COL_NODE_PTR, node, + -1); +} + +void TreeAdapter::Fill(GtkTreeIter* parent_iter, TreeModelNode* parent_node) { + if (parent_iter) + FillRow(parent_iter, parent_node); + GtkTreeIter iter; + int child_count = tree_model_->GetChildCount(parent_node); + for (int i = 0; i < child_count; ++i) { + TreeModelNode* node = tree_model_->GetChild(parent_node, i); + gtk_tree_store_append(tree_store_, &iter, parent_iter); + Fill(&iter, node); + } +} + +GtkTreePath* TreeAdapter::GetTreePath(TreeModelNode* node) { + GtkTreePath* path = gtk_tree_path_new(); + TreeModelNode* parent = node; + while (parent) { + parent = tree_model_->GetParent(parent); + if (parent) { + int idx = tree_model_->IndexOfChild(parent, node); + gtk_tree_path_prepend_index(path, idx); + node = parent; + } + } + return path; +} + +bool TreeAdapter::GetTreeIter(TreeModelNode* node, GtkTreeIter* iter) { + GtkTreePath* path = GetTreePath(node); + bool rv = false; + // Check the path ourselves since gtk_tree_model_get_iter prints a warning if + // given an empty path. The path will be empty when it points to the root + // node and we are using SetRootShown(false). + if (gtk_tree_path_get_depth(path) > 0) + rv = gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), iter, path); + gtk_tree_path_free(path); + return rv; +} + +void TreeAdapter::TreeNodesAdded(TreeModel* model, + TreeModelNode* parent, + int start, + int count) { + delegate_->OnAnyModelUpdateStart(); + GtkTreeIter parent_iter; + GtkTreeIter* parent_iter_ptr = NULL; + GtkTreeIter iter; + if (GetTreeIter(parent, &parent_iter)) + parent_iter_ptr = &parent_iter; + for (int i = 0; i < count; ++i) { + gtk_tree_store_insert(tree_store_, &iter, parent_iter_ptr, start + i); + Fill(&iter, tree_model_->GetChild(parent, start + i)); + } + delegate_->OnAnyModelUpdate(); +} + +void TreeAdapter::TreeNodesRemoved(TreeModel* model, + TreeModelNode* parent, + int start, + int count) { + delegate_->OnAnyModelUpdateStart(); + GtkTreeIter iter; + GtkTreePath* path = GetTreePath(parent); + gtk_tree_path_append_index(path, start); + gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store_), &iter, path); + gtk_tree_path_free(path); + for (int i = 0; i < count; ++i) { + RemoveRecursively(tree_store_, &iter); + } + delegate_->OnAnyModelUpdate(); +} + +void TreeAdapter::TreeNodeChildrenReordered(TreeModel* model, + TreeModelNode* parent) { + NOTIMPLEMENTED(); +} + +void TreeAdapter::TreeNodeChanged(TreeModel* model, TreeModelNode* node) { + delegate_->OnAnyModelUpdateStart(); + GtkTreeIter iter; + if (GetTreeIter(node, &iter)) + FillRow(&iter, node); + delegate_->OnAnyModelUpdate(); +} + +} // namespace gtk_tree |