// Copyright (c) 2010 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. #ifndef CHROME_BROWSER_GTK_GTK_TREE_H_ #define CHROME_BROWSER_GTK_GTK_TREE_H_ #pragma once #include #include #include #include "app/table_model_observer.h" #include "app/tree_model.h" #include "base/basictypes.h" #include "chrome/browser/remove_rows_table_model.h" class TableModel; namespace gtk_tree { // Get the row number corresponding to |path|. gint GetRowNumForPath(GtkTreePath* path); // Get the row number corresponding to |iter|. gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter); // Get the row number in the child tree model corresponding to |sort_path| in // the parent tree model. gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model, GtkTreePath* sort_path); // Select the given row by number. void SelectAndFocusRowNum(int row, GtkTreeView* tree_view); // Remove the row and all its children from the |tree_store|. If there is a // following row, |iter| will be updated to point to the it and the return value // will be true, otherwise the return will be false and |iter| is no longer // valid. bool RemoveRecursively(GtkTreeStore* tree_store, GtkTreeIter* iter); // Writes all the indexes of selected rows into |out|. void GetSelectedIndices(GtkTreeSelection* selection, std::set* out); // A helper class for populating a GtkListStore from a TableModel. class TableAdapter : public TableModelObserver { public: enum ColumnID { COL_TITLE = 0, COL_IS_HEADER, COL_IS_SEPARATOR, COL_GROUP_ID, COL_WEIGHT, COL_WEIGHT_SET, COL_LAST_ID }; class Delegate { public: // Should fill in the column and row. virtual void SetColumnValues(int row, GtkTreeIter* iter) = 0; // Called after any change to the TableModel but before the corresponding // change to the GtkListStore. virtual void OnAnyModelUpdateStart() {} // Called after any change to the TableModel. virtual void OnAnyModelUpdate() {} // When the TableModel has been completely changed, called by OnModelChanged // after clearing the list store. Can be overriden by the delegate if it // needs to do extra initialization before the list store is populated. virtual void OnModelChanged() {} protected: virtual ~Delegate() {} }; // |table_model| may be NULL. TableAdapter(Delegate* delegate, GtkListStore* list_store, TableModel* table_model); virtual ~TableAdapter() {} // Replace the TableModel with a different one. If the list store currenty // has items this would cause weirdness, so this should generally only be // called during the Delegate's OnModelChanged call, or if the adapter was // created with a NULL |table_model|. void SetModel(TableModel* table_model); // Add all model rows corresponding to the given list store indices to |rows|. void MapListStoreIndicesToModelRows(const std::set& list_store_indices, RemoveRowsTableModel::Rows* model_rows); // GtkTreeModel callbacks: // Callback checking whether a row should be drawn as a separator. static gboolean OnCheckRowIsSeparator(GtkTreeModel* model, GtkTreeIter* iter, gpointer user_data); // Callback checking whether a row may be selected. We use some rows in the // table as headers/separators for the groups, which should not be selectable. static gboolean OnSelectionFilter(GtkTreeSelection* selection, GtkTreeModel* model, GtkTreePath* path, gboolean path_currently_selected, gpointer user_data); // TableModelObserver implementation. virtual void OnModelChanged(); virtual void OnItemsChanged(int start, int length); virtual void OnItemsAdded(int start, int length); virtual void OnItemsRemoved(int start, int length); private: // Return whether the row pointed to by |iter| is a group row, i.e. a group // header, or a separator. bool IsGroupRow(GtkTreeIter* iter) const; // Return the index into the list store for the given model row. int GetListStoreIndexForModelRow(int model_row) const; // Add the values from |row| of the TableModel. void AddNodeToList(int row); Delegate* delegate_; GtkListStore* list_store_; TableModel* table_model_; DISALLOW_COPY_AND_ASSIGN(TableAdapter); }; // A helper class for populating a GtkTreeStore from a TreeModel. // TODO(mattm): support SetRootShown(true) class TreeAdapter : public TreeModelObserver { public: // Column ids for |tree_store_|. enum { COL_ICON, COL_TITLE, COL_NODE_PTR, COL_COUNT, }; class Delegate { public: // Called after any change to the TreeModel but before the corresponding // change to the GtkTreeStore. virtual void OnAnyModelUpdateStart() {} // Called after any change to the GtkTreeStore. virtual void OnAnyModelUpdate() {} protected: virtual ~Delegate() {} }; TreeAdapter(Delegate* delegate, TreeModel* tree_model); virtual ~TreeAdapter(); // Populate the tree store from the |tree_model_|. void Init(); // Return the tree store. GtkTreeStore* tree_store() { return tree_store_; } // Get the TreeModelNode corresponding to iter in the tree store. TreeModelNode* GetNode(GtkTreeIter* iter); // Begin TreeModelObserver implementation. virtual void TreeNodesAdded(TreeModel* model, TreeModelNode* parent, int start, int count); virtual void TreeNodesRemoved(TreeModel* model, TreeModelNode* parent, int start, int count); virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node); // End TreeModelObserver implementation. private: // Fill the tree store values for a given node. void FillRow(GtkTreeIter* iter, TreeModelNode* node); // Fill the tree store for a row and all its descendants. void Fill(GtkTreeIter* parent_iter, TreeModelNode* parent_node); // Get the GtkTreePath in the tree store for the given node. // The returned path should be freed with gtk_tree_path_free. GtkTreePath* GetTreePath(TreeModelNode* node); // Get the GtkTreeIter in the tree store for the given node. bool GetTreeIter(TreeModelNode* node, GtkTreeIter* iter); Delegate* delegate_; GtkTreeStore* tree_store_; TreeModel* tree_model_; std::vector pixbufs_; DISALLOW_COPY_AND_ASSIGN(TreeAdapter); }; } // namespace gtk_tree #endif // CHROME_BROWSER_GTK_GTK_TREE_H_