Home | History | Annotate | Download | only in table
      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 bool GetTooltipText(const gfx::Point& p,
    173                               string16* tooltip) const OVERRIDE;
    174   virtual bool GetTooltipTextOrigin(const gfx::Point& p,
    175                                     gfx::Point* loc) const OVERRIDE;
    176 
    177   // ui::TableModelObserver overrides:
    178   virtual void OnModelChanged() OVERRIDE;
    179   virtual void OnItemsChanged(int start, int length) OVERRIDE;
    180   virtual void OnItemsAdded(int start, int length) OVERRIDE;
    181   virtual void OnItemsRemoved(int start, int length) OVERRIDE;
    182 
    183  protected:
    184   // View overrides:
    185   virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE;
    186   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
    187   virtual void OnFocus() OVERRIDE;
    188   virtual void OnBlur() OVERRIDE;
    189 
    190  private:
    191   friend class TableViewTestHelper;
    192   struct GroupSortHelper;
    193   struct SortHelper;
    194 
    195   // Used during painting to determine the range of cells that need to be
    196   // painted.
    197   // NOTE: the row indices returned by this are in terms of the view and column
    198   // indices in terms of |visible_columns_|.
    199   struct VIEWS_EXPORT PaintRegion {
    200     PaintRegion();
    201     ~PaintRegion();
    202 
    203     int min_row;
    204     int max_row;
    205     int min_column;
    206     int max_column;
    207   };
    208 
    209   // Used by AdvanceSelection() to determine the direction to change the
    210   // selection.
    211   enum AdvanceDirection {
    212     ADVANCE_DECREMENT,
    213     ADVANCE_INCREMENT,
    214   };
    215 
    216   // Invoked when the number of rows changes in some way.
    217   void NumRowsChanged();
    218 
    219   // Resets the sort descriptions.
    220   void SetSortDescriptors(const SortDescriptors& sort_descriptors);
    221 
    222   // Does the actual sort and updates the mappings (|view_to_model_| and
    223   // |model_to_view_|) appropriately.
    224   void SortItemsAndUpdateMapping();
    225 
    226   // Used to sort the two rows. Returns a value < 0, == 0 or > 0 indicating
    227   // whether the row2 comes before row1, row2 is the same as row1 or row1 comes
    228   // after row2. This invokes CompareValues on the model with the sorted column.
    229   int CompareRows(int model_row1, int model_row2);
    230 
    231   // Returns the bounds of the specified row.
    232   gfx::Rect GetRowBounds(int row) const;
    233 
    234   // Returns the bounds of the specified cell. |visible_column_index| indexes
    235   // into |visible_columns_|.
    236   gfx::Rect GetCellBounds(int row, int visible_column_index) const;
    237 
    238   // Adjusts |bounds| based on where the text should be painted. |bounds| comes
    239   // from GetCellBounds() and |visible_column_index| is the corresponding column
    240   // (in terms of |visible_columns_|).
    241   void AdjustCellBoundsForText(int visible_column_index,
    242                                gfx::Rect* bounds) const;
    243 
    244   // Creates |header_| if necessary.
    245   void CreateHeaderIfNecessary();
    246 
    247   // Updates the |x| and |width| of each of the columns in |visible_columns_|.
    248   void UpdateVisibleColumnSizes();
    249 
    250   // Returns the cells that need to be painted for the specified region.
    251   // |bounds| is in terms of |this|.
    252   PaintRegion GetPaintRegion(const gfx::Rect& bounds) const;
    253 
    254   // Returns the bounds that need to be painted based on the clip set on
    255   // |canvas|.
    256   gfx::Rect GetPaintBounds(gfx::Canvas* canvas) const;
    257 
    258   // Invokes SchedulePaint() for the selected rows.
    259   void SchedulePaintForSelection();
    260 
    261   // Returns the TableColumn matching the specified id.
    262   ui::TableColumn FindColumnByID(int id) const;
    263 
    264   // Sets the selection to the specified index (in terms of the view).
    265   void SelectByViewIndex(int view_index);
    266 
    267   // Sets the selection model to |new_selection|.
    268   void SetSelectionModel(const ui::ListSelectionModel& new_selection);
    269 
    270   // Advances the selection (from the active index) in the specified direction.
    271   void AdvanceSelection(AdvanceDirection direction);
    272 
    273   // Sets |model| appropriately based on a mouse event.
    274   void ConfigureSelectionModelForEvent(const ui::MouseEvent& event,
    275                                        ui::ListSelectionModel* model) const;
    276 
    277   // Set the selection state of row at |view_index| to |select|, additionally
    278   // any other rows in the GroupRange containing |view_index| are updated as
    279   // well. This does not change the anchor or active index of |model|.
    280   void SelectRowsInRangeFrom(int view_index,
    281                              bool select,
    282                              ui::ListSelectionModel* model) const;
    283 
    284   // Returns the range of the specified model index. If a TableGrouper has not
    285   // been set this returns a group with a start of |model_index| and length of
    286   // 1.
    287   GroupRange GetGroupRange(int model_index) const;
    288 
    289   // Used by both GetTooltipText methods. Returns true if there is a tooltip and
    290   // sets |tooltip| and/or |tooltip_origin| as appropriate, each of which may be
    291   // NULL.
    292   bool GetTooltipImpl(const gfx::Point& location,
    293                       string16* tooltip,
    294                       gfx::Point* tooltip_origin) const;
    295 
    296   ui::TableModel* model_;
    297 
    298   std::vector<ui::TableColumn> columns_;
    299 
    300   // The set of visible columns. The values of these point to |columns_|. This
    301   // may contain a subset of |columns_|.
    302   std::vector<VisibleColumn> visible_columns_;
    303 
    304   // The header. This is only created if more than one column is specified or
    305   // the first column has a non-empty title.
    306   TableHeader* header_;
    307 
    308   const TableTypes table_type_;
    309 
    310   const bool single_selection_;
    311 
    312   // TODO(sky): rename to observer_.
    313   TableViewObserver* table_view_observer_;
    314 
    315   // The selection, in terms of the model.
    316   ui::ListSelectionModel selection_model_;
    317 
    318   gfx::Font font_;
    319 
    320   int row_height_;
    321 
    322   // Width of the ScrollView last time Layout() was invoked. Used to determine
    323   // when we should invoke UpdateVisibleColumnSizes().
    324   int last_parent_width_;
    325 
    326   // The width we layout to. This may differ from |last_parent_width_|.
    327   int layout_width_;
    328 
    329   // Current sort.
    330   SortDescriptors sort_descriptors_;
    331 
    332   // Mappings used when sorted.
    333   std::vector<int> view_to_model_;
    334   std::vector<int> model_to_view_;
    335 
    336   scoped_ptr<TableViewRowBackgroundPainter> row_background_painter_;
    337 
    338   TableGrouper* grouper_;
    339 
    340   // True if in SetVisibleColumnWidth().
    341   bool in_set_visible_column_width_;
    342 
    343   DISALLOW_COPY_AND_ASSIGN(TableView);
    344 };
    345 
    346 }  // namespace views
    347 
    348 #endif  // UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_VIEWS_H_
    349