diff options
Diffstat (limited to 'chrome/views/table_view.h')
-rw-r--r-- | chrome/views/table_view.h | 181 |
1 files changed, 153 insertions, 28 deletions
diff --git a/chrome/views/table_view.h b/chrome/views/table_view.h index 30f28f8..a2cfc40 100644 --- a/chrome/views/table_view.h +++ b/chrome/views/table_view.h @@ -22,8 +22,22 @@ class SkBitmap; // 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. +// +// Tables may be sorted either by directly invoking SetSortDescriptors or by +// marking the column as sortable and the user doing a gesture to sort the +// contents. TableView itself maintains the sort so that the underlying model +// isn't effected. +// +// 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 model_to_view. +// +// Sorting is done by a locale sensitive string sort. You can customize the +// sort by way of overriding CompareValues. +// // TableView is a wrapper around the window type ListView in report mode. namespace ChromeViews { @@ -125,6 +139,14 @@ class TableModel { // Sets the observer for the model. The TableView should NOT take ownership // of the observer. virtual void SetObserver(TableModelObserver* observer) = 0; + + // Compares the values in the column with id |column_id| for the two rows. + // Returns a value < 0, == 0 or > 0 as to whether the first value is + // <, == or > the second value. + // + // This implementation does a case insensitive locale specific string + // comparison. + virtual int CompareValues(int row1, int row2, int column_id); }; // TableColumn specifies the title, alignment and size of a particular column. @@ -139,7 +161,8 @@ struct TableColumn { alignment(LEFT), width(-1), percent(), - min_visible_width(0) { + min_visible_width(0), + sortable(false) { } TableColumn(int id, const std::wstring title, Alignment alignment, int width) : id(id), @@ -147,7 +170,8 @@ struct TableColumn { alignment(alignment), width(width), percent(0), - min_visible_width(0) { + min_visible_width(0), + sortable(false) { } TableColumn(int id, const std::wstring title, Alignment alignment, int width, float percent) @@ -156,7 +180,8 @@ struct TableColumn { alignment(alignment), width(width), percent(percent), - min_visible_width(0) { + min_visible_width(0), + sortable(false) { } // It's common (but not required) to use the title's IDS_* tag as the column // id. In this case, the provided conveniences look up the title string on @@ -166,7 +191,8 @@ struct TableColumn { alignment(alignment), width(width), percent(0), - min_visible_width(0) { + min_visible_width(0), + sortable(false) { title = l10n_util::GetString(id); } TableColumn(int id, Alignment alignment, int width, float percent) @@ -174,7 +200,8 @@ struct TableColumn { alignment(alignment), width(width), percent(percent), - min_visible_width(0) { + min_visible_width(0), + sortable(false) { title = l10n_util::GetString(id); } @@ -207,12 +234,15 @@ struct TableColumn { // (including the header) // to be visible. int min_visible_width; + + // Is this column sortable? Default is false + bool sortable; }; // Returned from SelectionBegin/SelectionEnd class TableSelectionIterator { public: - TableSelectionIterator(TableView* view, int index); + TableSelectionIterator(TableView* view, int view_index); TableSelectionIterator& operator=(const TableSelectionIterator& other); bool operator==(const TableSelectionIterator& other); bool operator!=(const TableSelectionIterator& other); @@ -220,8 +250,14 @@ class TableSelectionIterator { int operator*(); private: + void UpdateModelIndexFromViewIndex(); + TableView* table_view_; - int index_; + int view_index_; + + // The index in terms of the model. This is returned from the * operator. This + // is cached to avoid dependencies on the view_to_model mapping. + int model_index_; }; // TableViewObserver is notified about the TableView selection. @@ -251,6 +287,22 @@ class TableView : public NativeControl, SkColor color; }; + // Describes a sorted column. + struct 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). @@ -276,6 +328,12 @@ class TableView : public NativeControl, // issues when the model needs to be deleted before the table. void SetModel(TableModel* model); + // Resorts the contents. + void SetSortDescriptors(const SortDescriptors& sort_descriptors); + + // Current sort. + const SortDescriptors& sort_descriptors() const { return sort_descriptors_; } + void DidChangeBounds(const CRect& previous, const CRect& current); // Returns the number of rows in the TableView. @@ -285,28 +343,30 @@ class TableView : public NativeControl, int SelectedRowCount(); // Selects the specified item, making sure it's visible. - void Select(int item); + void Select(int model_row); // Sets the selected state of an item (without sending any selection // notifications). Note that this routine does NOT set the focus to the // item at the given index. - void SetSelectedState(int item, bool state); + void SetSelectedState(int model_row, bool state); // Sets the focus to the item at the given index. - void SetFocusOnItem(int item); + void SetFocusOnItem(int model_row); - // Returns the first selected row. + // Returns the first selected row in terms of the model. int FirstSelectedRow(); // Returns true if the item at the specified index is selected. - bool IsItemSelected(int item); + bool IsItemSelected(int model_row); // Returns true if the item at the specified index has the focus. - bool ItemHasTheFocus(int item); + bool ItemHasTheFocus(int model_row); // Returns an iterator over the selection. The iterator proceeds from the - // last index to the first. Do NOT use the iterator after you've mutated - // the model. + // last index to the first. + // + // NOTE: the iterator iterates over the visual order (but returns coordinates + // in terms of the model). iterator SelectionBegin(); iterator SelectionEnd(); @@ -342,6 +402,19 @@ class TableView : public NativeControl, void SetPreferredSize(const CSize& preferred_size); virtual void GetPreferredSize(CSize* out); + // Is the table sorted? + bool is_sorted() const { return !sort_descriptors_.empty(); } + + // Maps from the index in terms of the model to that of the view. + int model_to_view(int model_index) const { + return model_to_view_.get() ? model_to_view_[model_index] : model_index; + } + + // Maps from the index in terms of the view to that of the model. + int view_to_model(int view_index) const { + return view_to_model_.get() ? view_to_model_[view_index] : view_index; + } + protected: // Subclasses that want to customize the colors of a particular row/column, // must invoke this passing in true. The default value is false, such that @@ -362,7 +435,7 @@ class TableView : public NativeControl, // Invoked to customize the colors or font at a particular cell. If you // change the colors or font, return true. This is only invoked if // SetCustomColorsEnabled(true) has been invoked. - virtual bool GetCellColors(int row, + virtual bool GetCellColors(int model_row, int column, ItemColor* foreground, ItemColor* background, @@ -373,7 +446,7 @@ class TableView : public NativeControl, // method. virtual bool ImplementPostPaint() { return false; } // Subclasses can implement in this method extra-painting for cells. - virtual void PostPaint(int row, int column, bool selected, + virtual void PostPaint(int model_row, int column, bool selected, const CRect& bounds, HDC device_context) { } virtual HWND CreateNativeControl(HWND parent_container); @@ -383,7 +456,23 @@ class TableView : public NativeControl, // Overriden to destroy the image list. virtual void OnDestroy(); + // 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. + virtual int CompareRows(int model_row1, int model_row2); + + // Called before sorting. This does nothing and is intended for subclasses + // that need to cache state used during sorting. + virtual void PrepareForSort() {} + private: + // Direction of a sort. + enum SortDirection { + ASCENDING_SORT, + DESCENDING_SORT, + NO_SORT + }; + // We need this wrapper to pass the table view to the windows proc handler // when subclassing the list view and list view header, as the reinterpret // cast from GetWindowLongPtr would break the pointer if it is pointing to a @@ -398,6 +487,34 @@ class TableView : public NativeControl, LRESULT OnCustomDraw(NMLVCUSTOMDRAW* draw_info); + // Invoked when the user clicks on a column to toggle the sort order. If + // column_id is the primary sorted column the direction of the sort is + // toggled, otherwise column_id is made the primary sorted column. + void ToggleSortOrder(int column_id); + + // Updates the lparam of each of the list view items to be the model index. + // If length is > 0, all items with an index >= start get offset by length. + // This is used during sorting to determine how the items were sorted. + void UpdateItemsLParams(int start, int length); + + // Does the actual sort and updates the mappings (view_to_model and + // model_to_view) appropriately. + void SortItemsAndUpdateMapping(); + + // Method invoked by ListView to compare the two values. Invokes CompareRows. + static int CALLBACK SortFunc(LPARAM model_index_1_p, + LPARAM model_index_2_p, + LPARAM table_view_param); + + // Method invoked by ListView when sorting back to natural state. Returns + // model_index_1_p - model_index_2_p. + static int CALLBACK NaturalSortFunc(LPARAM model_index_1_p, + LPARAM model_index_2_p, + LPARAM table_view_param); + + // Resets the sort image displayed for the specified column. + void ResetColumnSortImage(int column_id, SortDirection direction); + // Adds a new column. void InsertColumn(const TableColumn& tc, int index); @@ -418,15 +535,19 @@ class TableView : public NativeControl, // Notification from the ListView that the checked state of the item has // changed. - void OnCheckedStateChanged(int item, bool is_checked); + void OnCheckedStateChanged(int model_row, bool is_checked); - // Returns the index of the selected item before |item|, or -1 if |item| is - // the first selected item. - int PreviousSelectedIndex(int item); + // Returns the index of the selected item before |view_index|, or -1 if + // |view_index| is the first selected item. + // + // WARNING: this returns coordinates in terms of the view, NOT the model. + int PreviousSelectedViewIndex(int view_index); - // Returns the last selected index in the table view, or -1 if the table + // Returns the last selected view index in the table view, or -1 if the table // is empty, or nothing is selected. - int LastSelectedIndex(); + // + // WARNING: this returns coordinates in terms of the view, NOT the model. + int LastSelectedViewIndex(); // The TableColumn visible at position pos. const TableColumn& GetColumnAtPosition(int pos); @@ -460,10 +581,6 @@ class TableView : public NativeControl, // Cached value of columns_.size() int column_count_; - // Whether or not the data should be cached in the TableView. - // This is currently always true. - bool cache_data_; - // Selection mode. bool single_selection_; @@ -509,8 +626,16 @@ class TableView : public NativeControl, // The offset from the top of the client area to the start of the content. int content_offset_; + // Current sort. + SortDescriptors sort_descriptors_; + + // Mappings used when sorted. + scoped_array<int> view_to_model_; + scoped_array<int> model_to_view_; + DISALLOW_COPY_AND_ASSIGN(TableView); }; -} + +} // namespace #endif // CHROME_VIEWS_TABLE_VIEW_H_ |