1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_VIEWS_H_ 6 #define UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_VIEWS_H_ 7 8 #include <vector> 9 10 #include "base/memory/scoped_ptr.h" 11 #include "ui/base/models/list_selection_model.h" 12 #include "ui/base/models/table_model.h" 13 #include "ui/base/models/table_model_observer.h" 14 #include "ui/gfx/font.h" 15 #include "ui/views/view.h" 16 #include "ui/views/views_export.h" 17 18 // A TableView is a view that displays multiple rows with any number of columns. 19 // TableView is driven by a TableModel. The model returns the contents 20 // to display. TableModel also has an Observer which is used to notify 21 // TableView of changes to the model so that the display may be updated 22 // appropriately. 23 // 24 // TableView itself has an observer that is notified when the selection 25 // changes. 26 // 27 // When a table is sorted the model coordinates do not necessarily match the 28 // view coordinates. All table methods are in terms of the model. If you need to 29 // convert to view coordinates use ModelToView(). 30 // 31 // Sorting is done by a locale sensitive string sort. You can customize the 32 // sort by way of overriding TableModel::CompareValues(). 33 namespace views { 34 35 struct GroupRange; 36 class TableGrouper; 37 class TableHeader; 38 class TableViewObserver; 39 class TableViewRowBackgroundPainter; 40 class TableViewTestHelper; 41 42 // The cells in the first column of a table can contain: 43 // - only text 44 // - a small icon (16x16) and some text 45 // - a check box and some text 46 enum TableTypes { 47 TEXT_ONLY = 0, 48 ICON_AND_TEXT, 49 }; 50 51 class VIEWS_EXPORT TableView 52 : public views::View, 53 public ui::TableModelObserver { 54 public: 55 // Used to track a visible column. Useful only for the header. 56 struct VIEWS_EXPORT VisibleColumn { 57 VisibleColumn(); 58 ~VisibleColumn(); 59 60 // The column. 61 ui::TableColumn column; 62 63 // Starting x-coordinate of the column. 64 int x; 65 66 // Width of the column. 67 int width; 68 }; 69 70 // Describes a sorted column. 71 struct VIEWS_EXPORT SortDescriptor { 72 SortDescriptor() : column_id(-1), ascending(true) {} 73 SortDescriptor(int column_id, bool ascending) 74 : column_id(column_id), 75 ascending(ascending) {} 76 77 // ID of the sorted column. 78 int column_id; 79 80 // Is the sort ascending? 81 bool ascending; 82 }; 83 84 typedef std::vector<SortDescriptor> SortDescriptors; 85 86 // Creates a new table using the model and columns specified. 87 // The table type applies to the content of the first column (text, icon and 88 // text, checkbox and text). 89 TableView(ui::TableModel* model, 90 const std::vector<ui::TableColumn>& columns, 91 TableTypes table_type, 92 bool single_selection); 93 virtual ~TableView(); 94 95 // Assigns a new model to the table view, detaching the old one if present. 96 // If |model| is NULL, the table view cannot be used after this call. This 97 // should be called in the containing view's destructor to avoid destruction 98 // issues when the model needs to be deleted before the table. 99 void SetModel(ui::TableModel* model); 100 ui::TableModel* model() const { return model_; } 101 102 // Returns a new ScrollView that contains the receiver. 103 View* CreateParentIfNecessary(); 104 105 void SetRowBackgroundPainter( 106 scoped_ptr<TableViewRowBackgroundPainter> painter); 107 108 // Sets the TableGrouper. TableView does not own |grouper| (common use case is 109 // to have TableModel implement TableGrouper). 110 void SetGrouper(TableGrouper* grouper); 111 112 // Returns the number of rows in the TableView. 113 int RowCount() const; 114 115 // Returns the number of selected rows. 116 // TODO(sky): remove this and force callers to use selection_model(). 117 int SelectedRowCount(); 118 119 // Selects the specified item, making sure it's visible. 120 void Select(int model_row); 121 122 // Returns the first selected row in terms of the model. 123 int FirstSelectedRow(); 124 125 const ui::ListSelectionModel& selection_model() const { 126 return selection_model_; 127 } 128 129 // Changes the visibility of the specified column (by id). 130 void SetColumnVisibility(int id, bool is_visible); 131 bool IsColumnVisible(int id) const; 132 133 // Adds the specified column. |col| is not made visible. 134 void AddColumn(const ui::TableColumn& col); 135 136 // Returns true if the column with the specified id is known (either visible 137 // or not). 138 bool HasColumn(int id) const; 139 140 // TODO(sky): rename to set_observer(). 141 void SetObserver(TableViewObserver* observer) { 142 table_view_observer_ = observer; 143 } 144 TableViewObserver* observer() const { return table_view_observer_; } 145 146 const std::vector<VisibleColumn>& visible_columns() const { 147 return visible_columns_; 148 } 149 150 // Sets the width of the column. |index| is in terms of |visible_columns_|. 151 void SetVisibleColumnWidth(int index, int width); 152 153 // Toggles the sort order of the specified visible column index. 154 void ToggleSortOrder(int visible_column_index); 155 156 const SortDescriptors& sort_descriptors() const { return sort_descriptors_; } 157 bool is_sorted() const { return !sort_descriptors_.empty(); } 158 159 // Maps from the index in terms of the model to that of the view. 160 int ModelToView(int model_index) const; 161 162 // Maps from the index in terms of the view to that of the model. 163 int ViewToModel(int view_index) const; 164 165 int row_height() const { return row_height_; } 166 167 // View overrides: 168 virtual void Layout() OVERRIDE; 169 virtual gfx::Size GetPreferredSize() OVERRIDE; 170 virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE; 171 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 172 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; 173 virtual bool GetTooltipText(const gfx::Point& p, 174 string16* tooltip) const OVERRIDE; 175 virtual bool GetTooltipTextOrigin(const gfx::Point& p, 176 gfx::Point* loc) const OVERRIDE; 177 178 // ui::TableModelObserver overrides: 179 virtual void OnModelChanged() OVERRIDE; 180 virtual void OnItemsChanged(int start, int length) OVERRIDE; 181 virtual void OnItemsAdded(int start, int length) OVERRIDE; 182 virtual void OnItemsRemoved(int start, int length) OVERRIDE; 183 184 protected: 185 // View overrides: 186 virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE; 187 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 188 virtual void OnFocus() OVERRIDE; 189 virtual void OnBlur() OVERRIDE; 190 191 private: 192 friend class TableViewTestHelper; 193 struct GroupSortHelper; 194 struct SortHelper; 195 196 // Used during painting to determine the range of cells that need to be 197 // painted. 198 // NOTE: the row indices returned by this are in terms of the view and column 199 // indices in terms of |visible_columns_|. 200 struct VIEWS_EXPORT PaintRegion { 201 PaintRegion(); 202 ~PaintRegion(); 203 204 int min_row; 205 int max_row; 206 int min_column; 207 int max_column; 208 }; 209 210 // Used by AdvanceSelection() to determine the direction to change the 211 // selection. 212 enum AdvanceDirection { 213 ADVANCE_DECREMENT, 214 ADVANCE_INCREMENT, 215 }; 216 217 // Invoked when the number of rows changes in some way. 218 void NumRowsChanged(); 219 220 // Resets the sort descriptions. 221 void SetSortDescriptors(const SortDescriptors& sort_descriptors); 222 223 // Does the actual sort and updates the mappings (|view_to_model_| and 224 // |model_to_view_|) appropriately. 225 void SortItemsAndUpdateMapping(); 226 227 // Used to sort the two rows. Returns a value < 0, == 0 or > 0 indicating 228 // whether the row2 comes before row1, row2 is the same as row1 or row1 comes 229 // after row2. This invokes CompareValues on the model with the sorted column. 230 int CompareRows(int model_row1, int model_row2); 231 232 // Returns the bounds of the specified row. 233 gfx::Rect GetRowBounds(int row) const; 234 235 // Returns the bounds of the specified cell. |visible_column_index| indexes 236 // into |visible_columns_|. 237 gfx::Rect GetCellBounds(int row, int visible_column_index) const; 238 239 // Adjusts |bounds| based on where the text should be painted. |bounds| comes 240 // from GetCellBounds() and |visible_column_index| is the corresponding column 241 // (in terms of |visible_columns_|). 242 void AdjustCellBoundsForText(int visible_column_index, 243 gfx::Rect* bounds) const; 244 245 // Creates |header_| if necessary. 246 void CreateHeaderIfNecessary(); 247 248 // Updates the |x| and |width| of each of the columns in |visible_columns_|. 249 void UpdateVisibleColumnSizes(); 250 251 // Returns the cells that need to be painted for the specified region. 252 // |bounds| is in terms of |this|. 253 PaintRegion GetPaintRegion(const gfx::Rect& bounds) const; 254 255 // Returns the bounds that need to be painted based on the clip set on 256 // |canvas|. 257 gfx::Rect GetPaintBounds(gfx::Canvas* canvas) const; 258 259 // Invokes SchedulePaint() for the selected rows. 260 void SchedulePaintForSelection(); 261 262 // Returns the TableColumn matching the specified id. 263 ui::TableColumn FindColumnByID(int id) const; 264 265 // Sets the selection to the specified index (in terms of the view). 266 void SelectByViewIndex(int view_index); 267 268 // Sets the selection model to |new_selection|. 269 void SetSelectionModel(const ui::ListSelectionModel& new_selection); 270 271 // Advances the selection (from the active index) in the specified direction. 272 void AdvanceSelection(AdvanceDirection direction); 273 274 // Sets |model| appropriately based on a event. 275 void ConfigureSelectionModelForEvent(const ui::LocatedEvent& event, 276 ui::ListSelectionModel* model) const; 277 278 // Set the selection state of row at |view_index| to |select|, additionally 279 // any other rows in the GroupRange containing |view_index| are updated as 280 // well. This does not change the anchor or active index of |model|. 281 void SelectRowsInRangeFrom(int view_index, 282 bool select, 283 ui::ListSelectionModel* model) const; 284 285 // Returns the range of the specified model index. If a TableGrouper has not 286 // been set this returns a group with a start of |model_index| and length of 287 // 1. 288 GroupRange GetGroupRange(int model_index) const; 289 290 // Used by both GetTooltipText methods. Returns true if there is a tooltip and 291 // sets |tooltip| and/or |tooltip_origin| as appropriate, each of which may be 292 // NULL. 293 bool GetTooltipImpl(const gfx::Point& location, 294 string16* tooltip, 295 gfx::Point* tooltip_origin) const; 296 297 ui::TableModel* model_; 298 299 std::vector<ui::TableColumn> columns_; 300 301 // The set of visible columns. The values of these point to |columns_|. This 302 // may contain a subset of |columns_|. 303 std::vector<VisibleColumn> visible_columns_; 304 305 // The header. This is only created if more than one column is specified or 306 // the first column has a non-empty title. 307 TableHeader* header_; 308 309 const TableTypes table_type_; 310 311 const bool single_selection_; 312 313 // TODO(sky): rename to observer_. 314 TableViewObserver* table_view_observer_; 315 316 // The selection, in terms of the model. 317 ui::ListSelectionModel selection_model_; 318 319 gfx::Font font_; 320 321 int row_height_; 322 323 // Width of the ScrollView last time Layout() was invoked. Used to determine 324 // when we should invoke UpdateVisibleColumnSizes(). 325 int last_parent_width_; 326 327 // The width we layout to. This may differ from |last_parent_width_|. 328 int layout_width_; 329 330 // Current sort. 331 SortDescriptors sort_descriptors_; 332 333 // Mappings used when sorted. 334 std::vector<int> view_to_model_; 335 std::vector<int> model_to_view_; 336 337 scoped_ptr<TableViewRowBackgroundPainter> row_background_painter_; 338 339 TableGrouper* grouper_; 340 341 // True if in SetVisibleColumnWidth(). 342 bool in_set_visible_column_width_; 343 344 DISALLOW_COPY_AND_ASSIGN(TableView); 345 }; 346 347 } // namespace views 348 349 #endif // UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_VIEWS_H_ 350