summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk/gtk_tree.cc
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-02 09:16:44 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-02 09:16:44 +0000
commit16d51df40992e767f4df3cd8a0d50fcf15a20c4c (patch)
treee7d032e5ccf51e42dc95f89c403d1921d70d2b03 /chrome/browser/gtk/gtk_tree.cc
parent88301f32ceb483810043b4d426d1a853d00f3035 (diff)
downloadchromium_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.cc294
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