// Copyright (c) 2012 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 UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_VIEWS_H_ #define UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_VIEWS_H_ #include <vector> #include "base/memory/scoped_ptr.h" #include "ui/base/models/list_selection_model.h" #include "ui/base/models/table_model.h" #include "ui/base/models/table_model_observer.h" #include "ui/gfx/font_list.h" #include "ui/views/view.h" #include "ui/views/views_export.h" // A TableView is a view that displays multiple rows with any number of columns. // TableView is driven by a TableModel. The model returns the contents // to display. TableModel also has an Observer which is used to notify // TableView of changes to the model so that the display may be updated // appropriately. // // TableView itself has an observer that is notified when the selection // changes. // // When a table is sorted the model coordinates do not necessarily match the // view coordinates. All table methods are in terms of the model. If you need to // convert to view coordinates use ModelToView(). // // Sorting is done by a locale sensitive string sort. You can customize the // sort by way of overriding TableModel::CompareValues(). namespace views { struct GroupRange; class TableGrouper; class TableHeader; class TableViewObserver; class TableViewRowBackgroundPainter; class TableViewTestHelper; // The cells in the first column of a table can contain: // - only text // - a small icon (16x16) and some text // - a check box and some text enum TableTypes { TEXT_ONLY = 0, ICON_AND_TEXT, }; class VIEWS_EXPORT TableView : public views::View, public ui::TableModelObserver { public: // Used to track a visible column. Useful only for the header. struct VIEWS_EXPORT VisibleColumn { VisibleColumn(); ~VisibleColumn(); // The column. ui::TableColumn column; // Starting x-coordinate of the column. int x; // Width of the column. int width; }; // Describes a sorted column. struct VIEWS_EXPORT SortDescriptor { SortDescriptor() : column_id(-1), ascending(true) {} SortDescriptor(int column_id, bool ascending) : column_id(column_id), ascending(ascending) {} // ID of the sorted column. int column_id; // Is the sort ascending? bool ascending; }; typedef std::vector<SortDescriptor> SortDescriptors; // Creates a new table using the model and columns specified. // The table type applies to the content of the first column (text, icon and // text, checkbox and text). TableView(ui::TableModel* model, const std::vector<ui::TableColumn>& columns, TableTypes table_type, bool single_selection); virtual ~TableView(); // Assigns a new model to the table view, detaching the old one if present. // If |model| is NULL, the table view cannot be used after this call. This // should be called in the containing view's destructor to avoid destruction // issues when the model needs to be deleted before the table. void SetModel(ui::TableModel* model); ui::TableModel* model() const { return model_; } // Returns a new ScrollView that contains the receiver. View* CreateParentIfNecessary(); void SetRowBackgroundPainter( scoped_ptr<TableViewRowBackgroundPainter> painter); // Sets the TableGrouper. TableView does not own |grouper| (common use case is // to have TableModel implement TableGrouper). void SetGrouper(TableGrouper* grouper); // Returns the number of rows in the TableView. int RowCount() const; // Returns the number of selected rows. // TODO(sky): remove this and force callers to use selection_model(). int SelectedRowCount(); // Selects the specified item, making sure it's visible. void Select(int model_row); // Returns the first selected row in terms of the model. int FirstSelectedRow(); const ui::ListSelectionModel& selection_model() const { return selection_model_; } // Changes the visibility of the specified column (by id). void SetColumnVisibility(int id, bool is_visible); bool IsColumnVisible(int id) const; // Adds the specified column. |col| is not made visible. void AddColumn(const ui::TableColumn& col); // Returns true if the column with the specified id is known (either visible // or not). bool HasColumn(int id) const; // TODO(sky): rename to set_observer(). void SetObserver(TableViewObserver* observer) { table_view_observer_ = observer; } TableViewObserver* observer() const { return table_view_observer_; } const std::vector<VisibleColumn>& visible_columns() const { return visible_columns_; } // Sets the width of the column. |index| is in terms of |visible_columns_|. void SetVisibleColumnWidth(int index, int width); // Toggles the sort order of the specified visible column index. void ToggleSortOrder(int visible_column_index); const SortDescriptors& sort_descriptors() const { return sort_descriptors_; } bool is_sorted() const { return !sort_descriptors_.empty(); } // Maps from the index in terms of the model to that of the view. int ModelToView(int model_index) const; // Maps from the index in terms of the view to that of the model. int ViewToModel(int view_index) const; int row_height() const { return row_height_; } // View overrides: virtual void Layout() OVERRIDE; virtual gfx::Size GetPreferredSize() OVERRIDE; virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE; virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; virtual bool GetTooltipText(const gfx::Point& p, base::string16* tooltip) const OVERRIDE; virtual bool GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* loc) const OVERRIDE; // ui::TableModelObserver overrides: virtual void OnModelChanged() OVERRIDE; virtual void OnItemsChanged(int start, int length) OVERRIDE; virtual void OnItemsAdded(int start, int length) OVERRIDE; virtual void OnItemsRemoved(int start, int length) OVERRIDE; protected: // View overrides: virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE; virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; virtual void OnFocus() OVERRIDE; virtual void OnBlur() OVERRIDE; private: friend class TableViewTestHelper; struct GroupSortHelper; struct SortHelper; // Used during painting to determine the range of cells that need to be // painted. // NOTE: the row indices returned by this are in terms of the view and column // indices in terms of |visible_columns_|. struct VIEWS_EXPORT PaintRegion { PaintRegion(); ~PaintRegion(); int min_row; int max_row; int min_column; int max_column; }; // Used by AdvanceSelection() to determine the direction to change the // selection. enum AdvanceDirection { ADVANCE_DECREMENT, ADVANCE_INCREMENT, }; // Invoked when the number of rows changes in some way. void NumRowsChanged(); // Resets the sort descriptions. void SetSortDescriptors(const SortDescriptors& sort_descriptors); // Does the actual sort and updates the mappings (|view_to_model_| and // |model_to_view_|) appropriately. void SortItemsAndUpdateMapping(); // Used to sort the two rows. Returns a value < 0, == 0 or > 0 indicating // whether the row2 comes before row1, row2 is the same as row1 or row1 comes // after row2. This invokes CompareValues on the model with the sorted column. int CompareRows(int model_row1, int model_row2); // Returns the bounds of the specified row. gfx::Rect GetRowBounds(int row) const; // Returns the bounds of the specified cell. |visible_column_index| indexes // into |visible_columns_|. gfx::Rect GetCellBounds(int row, int visible_column_index) const; // Adjusts |bounds| based on where the text should be painted. |bounds| comes // from GetCellBounds() and |visible_column_index| is the corresponding column // (in terms of |visible_columns_|). void AdjustCellBoundsForText(int visible_column_index, gfx::Rect* bounds) const; // Creates |header_| if necessary. void CreateHeaderIfNecessary(); // Updates the |x| and |width| of each of the columns in |visible_columns_|. void UpdateVisibleColumnSizes(); // Returns the cells that need to be painted for the specified region. // |bounds| is in terms of |this|. PaintRegion GetPaintRegion(const gfx::Rect& bounds) const; // Returns the bounds that need to be painted based on the clip set on // |canvas|. gfx::Rect GetPaintBounds(gfx::Canvas* canvas) const; // Invokes SchedulePaint() for the selected rows. void SchedulePaintForSelection(); // Returns the TableColumn matching the specified id. ui::TableColumn FindColumnByID(int id) const; // Sets the selection to the specified index (in terms of the view). void SelectByViewIndex(int view_index); // Sets the selection model to |new_selection|. void SetSelectionModel(const ui::ListSelectionModel& new_selection); // Advances the selection (from the active index) in the specified direction. void AdvanceSelection(AdvanceDirection direction); // Sets |model| appropriately based on a event. void ConfigureSelectionModelForEvent(const ui::LocatedEvent& event, ui::ListSelectionModel* model) const; // Set the selection state of row at |view_index| to |select|, additionally // any other rows in the GroupRange containing |view_index| are updated as // well. This does not change the anchor or active index of |model|. void SelectRowsInRangeFrom(int view_index, bool select, ui::ListSelectionModel* model) const; // Returns the range of the specified model index. If a TableGrouper has not // been set this returns a group with a start of |model_index| and length of // 1. GroupRange GetGroupRange(int model_index) const; // Used by both GetTooltipText methods. Returns true if there is a tooltip and // sets |tooltip| and/or |tooltip_origin| as appropriate, each of which may be // NULL. bool GetTooltipImpl(const gfx::Point& location, base::string16* tooltip, gfx::Point* tooltip_origin) const; ui::TableModel* model_; std::vector<ui::TableColumn> columns_; // The set of visible columns. The values of these point to |columns_|. This // may contain a subset of |columns_|. std::vector<VisibleColumn> visible_columns_; // The header. This is only created if more than one column is specified or // the first column has a non-empty title. TableHeader* header_; const TableTypes table_type_; const bool single_selection_; // TODO(sky): rename to observer_. TableViewObserver* table_view_observer_; // The selection, in terms of the model. ui::ListSelectionModel selection_model_; gfx::FontList font_list_; int row_height_; // Width of the ScrollView last time Layout() was invoked. Used to determine // when we should invoke UpdateVisibleColumnSizes(). int last_parent_width_; // The width we layout to. This may differ from |last_parent_width_|. int layout_width_; // Current sort. SortDescriptors sort_descriptors_; // Mappings used when sorted. std::vector<int> view_to_model_; std::vector<int> model_to_view_; scoped_ptr<TableViewRowBackgroundPainter> row_background_painter_; TableGrouper* grouper_; // True if in SetVisibleColumnWidth(). bool in_set_visible_column_width_; DISALLOW_COPY_AND_ASSIGN(TableView); }; } // namespace views #endif // UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_VIEWS_H_