diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-10 23:21:15 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-10 23:21:15 +0000 |
commit | 7ea8d057c10b5ebf3fb28a1caa8af3ffc83e3cd6 (patch) | |
tree | 8a02fa5e51ea30b0089ce422447d7d52aea2ba85 /ui | |
parent | eaa406bbd5e2c92c307f1895befc00bb9c3386f4 (diff) | |
download | chromium_src-7ea8d057c10b5ebf3fb28a1caa8af3ffc83e3cd6.zip chromium_src-7ea8d057c10b5ebf3fb28a1caa8af3ffc83e3cd6.tar.gz chromium_src-7ea8d057c10b5ebf3fb28a1caa8af3ffc83e3cd6.tar.bz2 |
Shuffles around table classes and nukes tableview2.
BUG=109665
TEST=none
Review URL: http://codereview.chromium.org/9176001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117106 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
21 files changed, 1206 insertions, 3192 deletions
diff --git a/ui/views/controls/table/group_table_model.h b/ui/views/controls/table/group_table_model.h new file mode 100644 index 0000000..49e0b563 --- /dev/null +++ b/ui/views/controls/table/group_table_model.h @@ -0,0 +1,28 @@ +// Copyright (c) 2011 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_GROUP_TABLE_MODEL_H_ +#define UI_VIEWS_CONTROLS_TABLE_GROUP_TABLE_MODEL_H_ +#pragma once + +#include "ui/base/models/table_model.h" + +namespace views { + +struct GroupRange { + int start; + int length; +}; + +// The model driving the GroupTableView. +class GroupTableModel : public ui::TableModel { + public: + // Populates the passed range with the first row/last row (included) + // that this item belongs to. + virtual void GetGroupRangeForItem(int item, GroupRange* range) = 0; +}; + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_TABLE_GROUP_TABLE_MODEL_H_ diff --git a/ui/views/controls/table/group_table_view.h b/ui/views/controls/table/group_table_view.h index 796c9e9..4c4467d 100644 --- a/ui/views/controls/table/group_table_view.h +++ b/ui/views/controls/table/group_table_view.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -6,82 +6,8 @@ #define UI_VIEWS_CONTROLS_TABLE_GROUP_TABLE_VIEW_H_ #pragma once -#include "base/memory/weak_ptr.h" -#include "ui/base/models/table_model.h" -#include "ui/views/controls/table/table_view.h" - -namespace views { - -struct GroupRange { - int start; - int length; -}; - -// The model driving the GroupTableView. -class GroupTableModel : public ui::TableModel { - public: - // Populates the passed range with the first row/last row (included) - // that this item belongs to. - virtual void GetGroupRangeForItem(int item, GroupRange* range) = 0; -}; - -// GroupTableView adds grouping to the TableView class. -// It allows to have groups of rows that act as a single row from the selection -// perspective. Groups are visually separated by a horizontal line. -class VIEWS_EXPORT GroupTableView : public TableView { - public: - // The view class name. - static const char kViewClassName[]; - - GroupTableView(GroupTableModel* model, - const std::vector<ui::TableColumn>& columns, - TableTypes table_type, bool single_selection, - bool resizable_columns, bool autosize_columns, - bool draw_group_separators); - virtual ~GroupTableView(); - - virtual std::string GetClassName() const; - - protected: - // Notification from the ListView that the selected state of an item has - // changed. - void OnSelectedStateChanged(); - - // Extra-painting required to draw the separator line between groups. - virtual bool ImplementPostPaint() { return true; } - virtual void PostPaint(int model_row, int column, bool selected, - const gfx::Rect& bounds, HDC device_context); - - // In order to make keyboard navigation possible (using the Up and Down - // keys), we must take action when an arrow key is pressed. The reason we - // need to process this message has to do with the manner in which the focus - // needs to be set on a group item when a group is selected. - virtual bool OnKeyDown(ui::KeyboardCode virtual_keycode); - - // Overriden to make sure rows in the same group stay grouped together. - virtual int CompareRows(int model_row1, int model_row2); - - // Updates model_index_to_range_start_map_ from the model. - virtual void PrepareForSort(); - - private: - // Make the selection of group consistent. - void SyncSelection(); - - GroupTableModel* model_; - - // If true, draw separators between groups. - bool draw_group_separators_; - - // A factory to make the selection consistent among groups. - base::WeakPtrFactory<GroupTableView> sync_selection_factory_; - - // Maps from model row to start of group. - std::map<int,int> model_index_to_range_start_map_; - - DISALLOW_COPY_AND_ASSIGN(GroupTableView); -}; - -} // namespace views +#if defined(OS_WIN) +#include "ui/views/controls/table/group_table_view_win.h" +#endif #endif // UI_VIEWS_CONTROLS_TABLE_GROUP_TABLE_VIEW_H_ diff --git a/ui/views/controls/table/group_table_view_views.h b/ui/views/controls/table/group_table_view_views.h new file mode 100644 index 0000000..cccbfd5 --- /dev/null +++ b/ui/views/controls/table/group_table_view_views.h @@ -0,0 +1,76 @@ +// 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_GROUP_TABLE_VIEW_VIEWS_H_ +#define UI_VIEWS_CONTROLS_TABLE_GROUP_TABLE_VIEW_VIEWS_H_ +#pragma once + +#include "base/memory/weak_ptr.h" +#include "ui/base/models/table_model.h" +#include "ui/views/controls/table/table_view.h" + +namespace views { + +class GroupTableModel; + +// GroupTableView adds grouping to the TableView class. +// It allows to have groups of rows that act as a single row from the selection +// perspective. Groups are visually separated by a horizontal line. +class VIEWS_EXPORT GroupTableView : public TableView { + public: + // The view class name. + static const char kViewClassName[]; + + GroupTableView(GroupTableModel* model, + const std::vector<ui::TableColumn>& columns, + TableTypes table_type, bool single_selection, + bool resizable_columns, bool autosize_columns, + bool draw_group_separators); + virtual ~GroupTableView(); + + virtual std::string GetClassName() const; + + protected: + // Notification from the ListView that the selected state of an item has + // changed. + void OnSelectedStateChanged(); + + // Extra-painting required to draw the separator line between groups. + virtual bool ImplementPostPaint() { return true; } + virtual void PostPaint(int model_row, int column, bool selected, + const gfx::Rect& bounds, HDC device_context); + + // In order to make keyboard navigation possible (using the Up and Down + // keys), we must take action when an arrow key is pressed. The reason we + // need to process this message has to do with the manner in which the focus + // needs to be set on a group item when a group is selected. + virtual bool OnKeyDown(ui::KeyboardCode virtual_keycode); + + // Overriden to make sure rows in the same group stay grouped together. + virtual int CompareRows(int model_row1, int model_row2); + + // Updates model_index_to_range_start_map_ from the model. + virtual void PrepareForSort(); + + private: + // Make the selection of group consistent. + void SyncSelection(); + + GroupTableModel* model_; + + // If true, draw separators between groups. + bool draw_group_separators_; + + // A factory to make the selection consistent among groups. + base::WeakPtrFactory<GroupTableView> sync_selection_factory_; + + // Maps from model row to start of group. + std::map<int,int> model_index_to_range_start_map_; + + DISALLOW_COPY_AND_ASSIGN(GroupTableView); +}; + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_TABLE_GROUP_TABLE_VIEW_VIEWS_H_ diff --git a/ui/views/controls/table/group_table_view.cc b/ui/views/controls/table/group_table_view_win.cc index 9d3253f..b056bd2 100644 --- a/ui/views/controls/table/group_table_view.cc +++ b/ui/views/controls/table/group_table_view_win.cc @@ -1,13 +1,14 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. -#include "ui/views/controls/table/group_table_view.h" +#include "ui/views/controls/table/group_table_view_win.h" #include "base/bind.h" #include "base/compiler_specific.h" #include "base/message_loop.h" #include "ui/gfx/canvas.h" +#include "ui/views/controls/table/group_table_model.h" namespace views { diff --git a/ui/views/controls/table/group_table_view_win.h b/ui/views/controls/table/group_table_view_win.h new file mode 100644 index 0000000..34e6187 --- /dev/null +++ b/ui/views/controls/table/group_table_view_win.h @@ -0,0 +1,76 @@ +// 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_GROUP_TABLE_VIEW_WIN_H_ +#define UI_VIEWS_CONTROLS_TABLE_GROUP_TABLE_VIEW_WIN_H_ +#pragma once + +#include "base/memory/weak_ptr.h" +#include "ui/base/models/table_model.h" +#include "ui/views/controls/table/table_view.h" + +namespace views { + +class GroupTableModel; + +// GroupTableView adds grouping to the TableView class. +// It allows to have groups of rows that act as a single row from the selection +// perspective. Groups are visually separated by a horizontal line. +class VIEWS_EXPORT GroupTableView : public TableView { + public: + // The view class name. + static const char kViewClassName[]; + + GroupTableView(GroupTableModel* model, + const std::vector<ui::TableColumn>& columns, + TableTypes table_type, bool single_selection, + bool resizable_columns, bool autosize_columns, + bool draw_group_separators); + virtual ~GroupTableView(); + + virtual std::string GetClassName() const; + + protected: + // Notification from the ListView that the selected state of an item has + // changed. + void OnSelectedStateChanged(); + + // Extra-painting required to draw the separator line between groups. + virtual bool ImplementPostPaint() { return true; } + virtual void PostPaint(int model_row, int column, bool selected, + const gfx::Rect& bounds, HDC device_context); + + // In order to make keyboard navigation possible (using the Up and Down + // keys), we must take action when an arrow key is pressed. The reason we + // need to process this message has to do with the manner in which the focus + // needs to be set on a group item when a group is selected. + virtual bool OnKeyDown(ui::KeyboardCode virtual_keycode); + + // Overriden to make sure rows in the same group stay grouped together. + virtual int CompareRows(int model_row1, int model_row2); + + // Updates model_index_to_range_start_map_ from the model. + virtual void PrepareForSort(); + + private: + // Make the selection of group consistent. + void SyncSelection(); + + GroupTableModel* model_; + + // If true, draw separators between groups. + bool draw_group_separators_; + + // A factory to make the selection consistent among groups. + base::WeakPtrFactory<GroupTableView> sync_selection_factory_; + + // Maps from model row to start of group. + std::map<int,int> model_index_to_range_start_map_; + + DISALLOW_COPY_AND_ASSIGN(GroupTableView); +}; + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_TABLE_GROUP_TABLE_VIEW_WIN_H_ diff --git a/ui/views/controls/table/native_table_gtk.cc b/ui/views/controls/table/native_table_gtk.cc deleted file mode 100644 index 34a2e55..0000000 --- a/ui/views/controls/table/native_table_gtk.cc +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (c) 2011 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. - -#include "ui/views/controls/table/native_table_gtk.h" - -#include <string> - -#include "base/logging.h" -#include "base/utf_string_conversions.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/gtk_util.h" -#include "ui/views/controls/table/table_view2.h" -#include "ui/views/controls/table/table_view_observer.h" -#include "ui/views/widget/widget.h" - -namespace views { - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableGtk, public: - -NativeTableGtk::NativeTableGtk(TableView2* table) - : table_(table), - gtk_model_(NULL), - tree_view_(NULL), - tree_selection_(NULL) { - // Associates the actual GtkWidget with the table so the table is the one - // considered as having the focus (not the wrapper) when the HWND is - // focused directly (with a click for example). - set_focus_view(table); -} - -NativeTableGtk::~NativeTableGtk() { -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableGtk, NativeTableWrapper implementation: - -int NativeTableGtk::GetRowCount() const { - if (!tree_view_) - return 0; - - GtkTreeIter iter; - if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(gtk_model_), &iter)) - return 0; // Empty tree. - - int count = 1; - while (gtk_tree_model_iter_next(GTK_TREE_MODEL(gtk_model_), &iter)) - count++; - return count; -} - -View* NativeTableGtk::GetView() { - return this; -} - -void NativeTableGtk::SetFocus() { - // Focus the associated widget. - OnFocus(); -} - -gfx::NativeView NativeTableGtk::GetTestingHandle() const { - // Note that we are returning the tree view, not the scrolled window as - // arguably the tests need to access the tree view. - return GTK_WIDGET(tree_view_); -} - -void NativeTableGtk::InsertColumn(const ui::TableColumn& column, int index) { - NOTIMPLEMENTED(); -} - -void NativeTableGtk::RemoveColumn(int column_index) { - if (!native_view()) - return; - - GtkTreeViewColumn* column = gtk_tree_view_get_column(tree_view_, - column_index); - if (column) { - gtk_tree_view_remove_column(tree_view_, column); - - if (table_->model()->RowCount() > 0) - OnRowsChanged(0, table_->model()->RowCount() - 1); - } -} - -int NativeTableGtk::GetColumnWidth(int column_index) const { - GtkTreeViewColumn* column = gtk_tree_view_get_column(tree_view_, - column_index); - return column ? gtk_tree_view_column_get_width(column) : -1; -} - -void NativeTableGtk::SetColumnWidth(int column_index, int width) { - GtkTreeViewColumn* column = gtk_tree_view_get_column(tree_view_, - column_index); - column->width = width; - column->resized_width = width; - column->use_resized_width = TRUE; - // Needed for use_resized_width to be effective. - gtk_widget_queue_resize(GTK_WIDGET(tree_view_)); -} - -int NativeTableGtk::GetSelectedRowCount() const { - return gtk_tree_selection_count_selected_rows(tree_selection_); -} - -int NativeTableGtk::GetFirstSelectedRow() const { - int result = -1; - GList* selected_rows = - gtk_tree_selection_get_selected_rows(tree_selection_, NULL); - if (g_list_length(selected_rows) > 0) { - GtkTreePath* tree_path = - static_cast<GtkTreePath*>(g_list_first(selected_rows)->data); - gint* indices = gtk_tree_path_get_indices(tree_path); - CHECK(indices); - result = indices[0]; - } - - g_list_foreach(selected_rows, reinterpret_cast<GFunc>(gtk_tree_path_free), - NULL); - g_list_free(selected_rows); - return result; -} - -int NativeTableGtk::GetFirstFocusedRow() const { - NOTIMPLEMENTED(); - return -1; -} - -bool NativeTableGtk::IsRowFocused(int model_row) const { - NOTIMPLEMENTED(); - return false; -} - -void NativeTableGtk::ClearRowFocus() { - NOTIMPLEMENTED(); -} - -void NativeTableGtk::ClearSelection() { - gtk_tree_selection_unselect_all(tree_selection_); -} - -void NativeTableGtk::SetSelectedState(int model_row, bool state) { - GtkTreeIter iter; - if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(gtk_model_), &iter, NULL, - model_row)) { - NOTREACHED(); - return; - } - if (state) - gtk_tree_selection_select_iter(tree_selection_, &iter); - else - gtk_tree_selection_unselect_iter(tree_selection_, &iter); -} - -void NativeTableGtk::SetFocusState(int model_row, bool state) { - NOTIMPLEMENTED(); -} - -bool NativeTableGtk::IsRowSelected(int model_row) const { - GtkTreeIter iter; - if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(gtk_model_), &iter, NULL, - model_row)) { - NOTREACHED(); - return false; - } - return gtk_tree_selection_iter_is_selected(tree_selection_, &iter); -} - -void NativeTableGtk::OnRowsChanged(int start, int length) { - GtkTreeIter iter; - if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(gtk_model_), &iter, NULL, - start)) { - NOTREACHED(); - return; - } - for (int i = start; i < start + length; i++) { - GtkTreePath* tree_path = - gtk_tree_model_get_path(GTK_TREE_MODEL(gtk_model_), &iter); - gtk_tree_model_row_changed(GTK_TREE_MODEL(gtk_model_), tree_path, &iter); - gtk_tree_path_free(tree_path); - SetRowData(i, &iter); - gboolean r = gtk_tree_model_iter_next(GTK_TREE_MODEL(gtk_model_), &iter); - DCHECK(r || i == start + length - 1); // (start + length - 1) might be the - // last item, in which case we won't - // get a next iterator. - } -} - -void NativeTableGtk::OnRowsAdded(int start, int length) { - GtkTreeIter iter; - gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(gtk_model_), &iter, - NULL, start); - for (int i = start; i < start + length; i++) { - gtk_list_store_append(gtk_model_, &iter); - SetRowData(i, &iter); - } -} - -void NativeTableGtk::OnRowsRemoved(int start, int length) { - GtkTreeIter iter; - gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(gtk_model_), &iter, - NULL, start); - for (int i = start; i < start + length; i++) { - gboolean r = gtk_list_store_remove(gtk_model_, &iter); - DCHECK(r || i == start + length - 1); // (start + length - 1) might be the - // last item, in which case we won't - // get a next iterator. - } -} - -gfx::Rect NativeTableGtk::GetBounds() const { - NOTIMPLEMENTED(); - return gfx::Rect(); -} - -void NativeTableGtk::CreateNativeControl() { - if (table_->type() == CHECK_BOX_AND_TEXT) { - // We are not supporting checkbox in tables on Gtk yet, as it is not used - // in Chrome at this point in time - NOTREACHED(); - } - - tree_view_ = GTK_TREE_VIEW(gtk_tree_view_new()); - g_signal_connect(tree_view_, "cursor-changed", - G_CALLBACK(OnCursorChangedThunk), this); - - // The tree view must be wrapped in a scroll-view to be scrollable. - GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), - GTK_SHADOW_ETCHED_IN); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(tree_view_)); - NativeControlCreated(scrolled); - // native_view() is now available. - - // Set the selection mode, single or multiple. - tree_selection_ = gtk_tree_view_get_selection(tree_view_); - gtk_tree_selection_set_mode( - tree_selection_, table_->single_selection() ? GTK_SELECTION_SINGLE : - GTK_SELECTION_MULTIPLE); - - // Don't make the header clickable until we support sorting. - gtk_tree_view_set_headers_clickable(tree_view_, FALSE); - - // Show grid lines based on the options. - GtkTreeViewGridLines grid_lines = GTK_TREE_VIEW_GRID_LINES_NONE; - if (table_->horizontal_lines() && table_->vertical_lines()) { - grid_lines = GTK_TREE_VIEW_GRID_LINES_BOTH; - } else if (table_->horizontal_lines()) { - grid_lines = GTK_TREE_VIEW_GRID_LINES_HORIZONTAL; - } else if (table_->vertical_lines()) { - grid_lines = GTK_TREE_VIEW_GRID_LINES_VERTICAL; - } - gtk_tree_view_set_grid_lines(tree_view_, grid_lines); - - int gtk_column_index = 0; - size_t column_index = 0; - if (table_->type() == ICON_AND_TEXT) { - InsertIconAndTextColumn(table_->GetVisibleColumnAt(0), 0); - column_index = 1; - gtk_column_index = 2; - } - - for (; column_index < table_->GetVisibleColumnCount(); - ++column_index, gtk_column_index++) { - InsertTextColumn(table_->GetVisibleColumnAt(column_index), - gtk_column_index); - } - - // Now create the model. - int column_count = table_->GetVisibleColumnCount(); - scoped_array<GType> types( - new GType[column_count + 1]); // One extra column for the icon (if any). - for (int i = 0; i < column_count + 1; i++) - types[i] = G_TYPE_STRING; - - if (table_->type() == ICON_AND_TEXT) { - types[0] = GDK_TYPE_PIXBUF; - gtk_model_ = gtk_list_store_newv(column_count + 1, types.get()); - } else { - gtk_model_ = gtk_list_store_newv(column_count, types.get()); - } - - gtk_tree_view_set_model(tree_view_, GTK_TREE_MODEL(gtk_model_)); - g_object_unref(gtk_model_); // Now the tree owns the model. - - // Updates the gtk model with the actual model. - if (table_->model()) - OnRowsAdded(0, table_->model()->RowCount()); - - gtk_widget_show_all(native_view()); -} - -void NativeTableGtk::InsertTextColumn(const ui::TableColumn& column, - int index) { - GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(tree_view_, -1, - UTF16ToUTF8(column.title).c_str(), - renderer, "text", index, NULL); -} - -void NativeTableGtk::InsertIconAndTextColumn(const ui::TableColumn& column, - int index) { - // If necessary we could support more than 1 icon and text column and we could - // make it so it does not have to be the 1st column. - DCHECK_EQ(0, index) << "The icon and text column can only be the first column" - " at this point."; - - GtkTreeViewColumn* gtk_column = gtk_tree_view_column_new(); - gtk_tree_view_column_set_title(gtk_column, UTF16ToUTF8(column.title).c_str()); - GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start(gtk_column, renderer, FALSE); - // First we set the icon renderer at index 0. - gtk_tree_view_column_set_attributes(gtk_column, renderer, "pixbuf", 0, NULL); - - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(gtk_column, renderer, TRUE); - // Then we set the text renderer at index 1. - gtk_tree_view_column_set_attributes(gtk_column, renderer, "text", 1, NULL); - - gtk_tree_view_append_column(tree_view_, gtk_column); -} - -void NativeTableGtk::SetRowData(int row_index, GtkTreeIter* iter) { - int gtk_column_index = 0; - if (table_->type() == ICON_AND_TEXT) { - GdkPixbuf* icon = GetModelIcon(row_index); - gtk_list_store_set(gtk_model_, iter, 0, icon, -1); - g_object_unref(icon); - gtk_column_index++; - } - for (size_t i = 0; i < table_->GetVisibleColumnCount(); - ++i, ++gtk_column_index) { - std::string text = - UTF16ToUTF8(table_->model()->GetText(row_index, - table_->GetVisibleColumnAt(i).id)); - gtk_list_store_set(gtk_model_, iter, gtk_column_index, text.c_str(), -1); - } -} - -void NativeTableGtk::OnCursorChanged(GtkWidget* widget) { - // Ignore the signal if no row is selected. This can occur when GTK - // first opens a window (i.e. no row is selected but the cursor is set - // to the first row). When a user clicks on a row, the row is selected, - // and then "cursor-changed" signal is emitted, hence the selection - // count will be 1 here. - if (gtk_tree_selection_count_selected_rows(tree_selection_) == 0) { - return; - } - GtkTreePath *tree_path = NULL; - gtk_tree_view_get_cursor(tree_view_, &tree_path, NULL); - if (tree_path) { - const gint* indices = gtk_tree_path_get_indices(tree_path); - CHECK(indices); - table_->SelectRow(indices[0]); - gtk_tree_path_free(tree_path); - } -} - -GdkPixbuf* NativeTableGtk::GetModelIcon(int row) { - SkBitmap icon = table_->model()->GetIcon(row); - return gfx::GdkPixbufFromSkBitmap(&icon); -} - -// static -NativeTableWrapper* NativeTableWrapper::CreateNativeWrapper(TableView2* table) { - return new NativeTableGtk(table); -} - -} // namespace views diff --git a/ui/views/controls/table/native_table_gtk.h b/ui/views/controls/table/native_table_gtk.h deleted file mode 100644 index df63faf..0000000 --- a/ui/views/controls/table/native_table_gtk.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2011 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_NATIVE_TABLE_GTK_H_ -#define UI_VIEWS_CONTROLS_TABLE_NATIVE_TABLE_GTK_H_ -#pragma once - -#include "base/compiler_specific.h" -#include "ui/base/gtk/gtk_signal.h" -#include "ui/base/models/table_model.h" -#include "ui/views/controls/native_control_gtk.h" -#include "ui/views/controls/table/native_table_wrapper.h" - -namespace views { - -class TableView2; - -// A View that hosts a native GTK table. -// TODO: Note that the implementation is still incomplete. What remains to be -// done: -// - support resizable columns -// - support autosize columns -// - implement focus row methods. -class NativeTableGtk : public NativeControlGtk, public NativeTableWrapper { - public: - explicit NativeTableGtk(TableView2* table); - virtual ~NativeTableGtk(); - - // NativeTableWrapper implementation: - virtual int GetRowCount() const OVERRIDE; - virtual View* GetView() OVERRIDE; - virtual void SetFocus() OVERRIDE; - virtual gfx::NativeView GetTestingHandle() const OVERRIDE; - virtual void InsertColumn(const ui::TableColumn& column, int index) OVERRIDE; - virtual void RemoveColumn(int index) OVERRIDE; - virtual int GetColumnWidth(int column_index) const OVERRIDE; - virtual void SetColumnWidth(int column_index, int width) OVERRIDE; - virtual int GetSelectedRowCount() const OVERRIDE; - virtual int GetFirstSelectedRow() const OVERRIDE; - virtual int GetFirstFocusedRow() const OVERRIDE; - virtual void ClearSelection() OVERRIDE; - virtual void ClearRowFocus() OVERRIDE; - virtual void SetSelectedState(int model_row, bool state) OVERRIDE; - virtual void SetFocusState(int model_row, bool state) OVERRIDE; - virtual bool IsRowSelected(int model_row) const OVERRIDE; - virtual bool IsRowFocused(int model_row) const OVERRIDE; - virtual void OnRowsChanged(int start, int length) OVERRIDE; - virtual void OnRowsAdded(int start, int length) OVERRIDE; - virtual void OnRowsRemoved(int start, int length) OVERRIDE; - virtual gfx::Rect GetBounds() const OVERRIDE; - - protected: - // NativeControlGtk implementation: - virtual void CreateNativeControl() OVERRIDE; - - private: - void InsertTextColumn(const ui::TableColumn& column, int index); - void InsertIconAndTextColumn(const ui::TableColumn& column, int index); - - // Sets the content of the row pointed to by |iter| in the tree_view_, using - // the data in the model at row |index|. - void SetRowData(int index, GtkTreeIter* iter); - - // Handles the "cursor-changed" event. - CHROMEGTK_CALLBACK_0(NativeTableGtk, void, OnCursorChanged); - - // Returns the icon that should be displayed for the row at |row|. - GdkPixbuf* GetModelIcon(int row); - - // The Table we are bound to. - TableView2* table_; - - // The GtkTree model. - GtkListStore* gtk_model_; - - // The actual tree view. - GtkTreeView* tree_view_; - - // The selection for tree_view_. - GtkTreeSelection* tree_selection_; - - // Size (width and height) of images. - static const int kImageSize; - - DISALLOW_COPY_AND_ASSIGN(NativeTableGtk); -}; - -} // namespace views - -#endif // UI_VIEWS_CONTROLS_TABLE_NATIVE_TABLE_GTK_H_ diff --git a/ui/views/controls/table/native_table_win.cc b/ui/views/controls/table/native_table_win.cc deleted file mode 100644 index 07fac4d..0000000 --- a/ui/views/controls/table/native_table_win.cc +++ /dev/null @@ -1,913 +0,0 @@ -// Copyright (c) 2011 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. - -#include "ui/views/controls/table/native_table_win.h" - -#include <commctrl.h> -#include <windowsx.h> - -#include <algorithm> - -#include "base/logging.h" -#include "base/win/scoped_gdi_object.h" -#include "skia/ext/skia_utils_win.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/l10n/l10n_util_win.h" -#include "ui/base/models/table_model.h" -#include "ui/base/win/hwnd_util.h" -#include "ui/gfx/canvas_skia.h" -#include "ui/gfx/favicon_size.h" -#include "ui/gfx/icon_util.h" -#include "ui/views/controls/table/table_view2.h" -#include "ui/views/controls/table/table_view_observer.h" -#include "ui/views/widget/widget.h" - -namespace views { - -// Added to column width to prevent truncation. -const int kListViewTextPadding = 15; -// Additional column width necessary if column has icons. -const int kListViewIconWidthAndPadding = 18; - -// static -const int NativeTableWin::kImageSize = 18; - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableWin, public: - -NativeTableWin::NativeTableWin(TableView2* table) - : ignore_listview_change_(false), - table_(table), - content_offset_(0), - header_original_handler_(NULL), - original_handler_(NULL) { - // Associates the actual HWND with the table so the table is the one - // considered as having the focus (not the wrapper) when the HWND is - // focused directly (with a click for example). - set_focus_view(table); -} - -NativeTableWin::~NativeTableWin() { -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableWin, NativeTableWrapper implementation: - -int NativeTableWin::GetRowCount() const { - if (!native_view()) - return 0; - return ListView_GetItemCount(native_view()); -} - -void NativeTableWin::InsertColumn(const ui::TableColumn& tc, int index) { - if (!native_view()) - return; - - LVCOLUMN column = { 0 }; - column.mask = LVCF_TEXT|LVCF_FMT; - column.pszText = const_cast<LPWSTR>(tc.title.c_str()); - switch (tc.alignment) { - case ui::TableColumn::LEFT: - column.fmt = LVCFMT_LEFT; - break; - case ui::TableColumn::RIGHT: - column.fmt = LVCFMT_RIGHT; - break; - case ui::TableColumn::CENTER: - column.fmt = LVCFMT_CENTER; - break; - default: - NOTREACHED(); - } - if (tc.width != -1) { - column.mask |= LVCF_WIDTH; - column.cx = tc.width; - } - column.mask |= LVCF_SUBITEM; - // Sub-items are 1s indexed. - column.iSubItem = index + 1; - SendMessage(native_view(), LVM_INSERTCOLUMN, index, - reinterpret_cast<LPARAM>(&column)); -} - -void NativeTableWin::RemoveColumn(int index) { - if (!native_view()) - return; - SendMessage(native_view(), LVM_DELETECOLUMN, index, 0); - if (table_->model()->RowCount() > 0) - OnRowsChanged(0, table_->model()->RowCount() - 1); -} - -View* NativeTableWin::GetView() { - return this; -} - -void NativeTableWin::SetFocus() { - // Focus the associated HWND. - OnFocus(); -} - -gfx::NativeView NativeTableWin::GetTestingHandle() const { - return native_view(); -} - -int NativeTableWin::GetColumnWidth(int column_index) const { - if (!native_view()) - return 0; - return ListView_GetColumnWidth(native_view(), column_index); -} - -void NativeTableWin::SetColumnWidth(int column_index, int width) { - if (!native_view()) - return; - ListView_SetColumnWidth(native_view(), column_index, width); -} - -int NativeTableWin::GetSelectedRowCount() const { - if (!native_view()) - return 0; - return ListView_GetSelectedCount(native_view()); -} - -int NativeTableWin::GetFirstSelectedRow() const { - if (!native_view()) - return -1; - return ListView_GetNextItem(native_view(), -1, LVNI_ALL | LVIS_SELECTED); -} - -int NativeTableWin::GetFirstFocusedRow() const { - if (!native_view()) - return -1; - return ListView_GetNextItem(native_view(), -1, LVNI_ALL | LVIS_FOCUSED); -} - -void NativeTableWin::ClearSelection() { - if (native_view()) - ListView_SetItemState(native_view(), -1, 0, LVIS_SELECTED); -} - -void NativeTableWin::ClearRowFocus() { - if (native_view()) - ListView_SetItemState(native_view(), -1, 0, LVIS_FOCUSED); -} - -void NativeTableWin::SetSelectedState(int model_row, bool state) { - if (!native_view()) - return; - - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0); - ListView_SetItemState(native_view(), model_row, - state ? LVIS_SELECTED : 0, LVIS_SELECTED); - // Make the selected row visible. - ListView_EnsureVisible(native_view(), model_row, FALSE); - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0); -} - -void NativeTableWin::SetFocusState(int model_row, bool state) { - if (!native_view()) - return; - ListView_SetItemState(native_view(), model_row, - state ? LVIS_FOCUSED : 0, LVIS_FOCUSED) -} - -bool NativeTableWin::IsRowSelected(int model_row) const { - if (!native_view()) - return false; - return ListView_GetItemState(native_view(), model_row, LVIS_SELECTED) == - LVIS_SELECTED; -} - -bool NativeTableWin::IsRowFocused(int model_row) const { - if (!native_view()) - return false; - return ListView_GetItemState(native_view(), model_row, LVIS_FOCUSED) == - LVIS_FOCUSED; -} - -void NativeTableWin::OnRowsChanged(int start, int length) { - if (!native_view()) - return; - - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0); - UpdateListViewCache(start, length, false); - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0); -} - -void NativeTableWin::OnRowsAdded(int start, int length) { - if (!native_view()) - return; - - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0); - UpdateListViewCache(start, length, true); - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0); -} - -void NativeTableWin::OnRowsRemoved(int start, int length) { - if (!native_view()) - return; - - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0); - - bool had_selection = (GetSelectedRowCount() > 0); - int old_row_count = GetRowCount(); - if (start == 0 && length == GetRowCount()) { - // Everything was removed. - ListView_DeleteAllItems(native_view()); - } else { - for (int i = 0; i < length; ++i) - ListView_DeleteItem(native_view(), start); - } - - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0); - - // If the row count goes to zero and we had a selection LVN_ITEMCHANGED isn't - // invoked, so we handle it here. - // - // When the model is set to NULL all the rows are removed. We don't notify - // the delegate in this case as setting the model to NULL is usually done as - // the last step before being deleted and callers shouldn't have to deal with - // getting a selection change when the model is being reset. - if (table_->model() && table_->observer() && had_selection && - GetRowCount() == 0) { - table_->observer()->OnSelectionChanged(); - } -} - -gfx::Rect NativeTableWin::GetBounds() const { - RECT native_bounds; - if (!native_view() || GetClientRect(native_view(), &native_bounds)) - return gfx::Rect(); - return gfx::Rect(native_bounds); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableWin, View overrides: - -gfx::Size NativeTableWin::GetPreferredSize() { - SIZE sz = {0}; - SendMessage(native_view(), BCM_GETIDEALSIZE, 0, - reinterpret_cast<LPARAM>(&sz)); - - return gfx::Size(sz.cx, sz.cy); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableWin, NativeControlWin overrides: - -bool NativeTableWin::ProcessMessage(UINT message, WPARAM w_param, - LPARAM l_param, LRESULT* result) { - if (message == WM_NOTIFY) { - LPNMHDR hdr = reinterpret_cast<LPNMHDR>(l_param); - switch (hdr->code) { - case NM_CUSTOMDRAW: { - // Draw notification. dwDragState indicates the current stage of - // drawing. - *result = OnCustomDraw(reinterpret_cast<NMLVCUSTOMDRAW*>(hdr)); - return true; - } - - case LVN_ITEMCHANGED: { - // Notification that the state of an item has changed. The state - // includes such things as whether the item is selected. - NMLISTVIEW* state_change = reinterpret_cast<NMLISTVIEW*>(hdr); - if ((state_change->uChanged & LVIF_STATE) != 0) { - if ((state_change->uOldState & LVIS_SELECTED) != - (state_change->uNewState & LVIS_SELECTED)) { - // Selected state of the item changed. - OnSelectedStateChanged(); - } - } - break; - } - - case HDN_BEGINTRACKW: - case HDN_BEGINTRACKA: - // Prevent clicks so columns cannot be resized. - if (!table_->resizable_columns()) - return true; - break; - - case NM_DBLCLK: - OnDoubleClick(); - break; - - case LVN_COLUMNCLICK: { - const ui::TableColumn& column = table_->GetVisibleColumnAt( - reinterpret_cast<NMLISTVIEW*>(hdr)->iSubItem); - break; - } - - case LVN_MARQUEEBEGIN: // We don't want the marquee selection. - return true; - - case LVN_GETINFOTIP: { - // This is called when the user hovers items in column zero. - // * If the text in this column is not fully visible, the dwFlags - // field will be set to 0, and pszText will contain the full text. - // If you return without making any changes, this text will be - // displayed in a "labeltip" - a bubble that's overlaid (at the - // correct alignment!) on the item. If you return with a different - // pszText, it will be displayed as a tooltip if nonempty. - // * Otherwise, dwFlags will be LVGIT_UNFOLDED and pszText will be - // empty. On return, if pszText is nonempty, it will be displayed - // as a labeltip if dwFlags has been changed to 0 (even if it bears - // no resemblance to the item text), or as a tooltip otherwise. - // - // Once the tooltip for an item has been obtained, this will not be - // called again until the user hovers a different item. If after that - // the original item is hovered a second time, this will be called. - // - // When the user hovers items in other columns, they will be "unfolded" - // (displayed as labeltips) when necessary, but this function will - // never be called. - // - // Changing the LVS_EX_INFOTIP extended style to LVS_EX_LABELTIP will - // cause all of the above to be true except that this function will not - // be called when dwFlags would be LVGIT_UNFOLDED. Removing it entirely - // will disable all of the above behavior. - NMLVGETINFOTIP* info_tip = reinterpret_cast<NMLVGETINFOTIP*>(hdr); - string16 tooltip = table_->model()->GetTooltip(info_tip->iItem); - CHECK_GE(info_tip->cchTextMax, 2); - if (tooltip.length() >= static_cast<size_t>(info_tip->cchTextMax)) { - // Elide the tooltip if necessary. - tooltip.erase(info_tip->cchTextMax - 2); // Ellipsis + '\0' - const wchar_t kEllipsis = L'\x2026'; - tooltip += kEllipsis; - } - if (!tooltip.empty()) - wcscpy_s(info_tip->pszText, tooltip.length() + 1, tooltip.c_str()); - return true; - } - - default: - break; - } - } - - return NativeControlWin::ProcessMessage(message, w_param, l_param, result); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableWin, protected: - -void NativeTableWin::CreateNativeControl() { - int style = WS_CHILD | LVS_REPORT | LVS_SHOWSELALWAYS; - if (table_->single_selection()) - style |= LVS_SINGLESEL; - // If there's only one column and the title string is empty, don't show a - // header. - if (table_->GetVisibleColumnCount() == 1U) { - if (table_->GetVisibleColumnAt(1).title.empty()) - style |= LVS_NOCOLUMNHEADER; - } - HWND hwnd = ::CreateWindowEx(WS_EX_CLIENTEDGE | GetAdditionalRTLStyle(), - WC_LISTVIEW, - L"", - style, - 0, 0, width(), height(), - table_->GetWidget()->GetNativeView(), - NULL, NULL, NULL); - ui::CheckWindowCreated(hwnd); - - // Reduce overdraw/flicker artifacts by double buffering. Support tooltips - // and display elided items completely on hover (see comments in OnNotify() - // under LVN_GETINFOTIP). Make the selection extend across the row. - ListView_SetExtendedListViewStyle(hwnd, - LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT); - l10n_util::AdjustUIFontForWindow(hwnd); - - NativeControlCreated(hwnd); - // native_view() is now valid. - - // Add the columns. - for (size_t i = 0; i < table_->GetVisibleColumnCount(); ++i) - InsertColumn(table_->GetVisibleColumnAt(i), i); - - if (table_->model()) - UpdateListViewCache(0, table_->model()->RowCount(), true); - - if (table_->type() == ICON_AND_TEXT) { - HIMAGELIST image_list = - ImageList_Create(kImageSize, kImageSize, ILC_COLOR32, 2, 2); - // We create 2 phony images because we are going to switch images at every - // refresh in order to force a refresh of the icon area (somehow the clip - // rect does not include the icon). - gfx::CanvasSkia canvas(gfx::Size(kImageSize, kImageSize), false); - { - base::win::ScopedHICON empty_icon( - IconUtil::CreateHICONFromSkBitmap(canvas.ExtractBitmap())); - ImageList_AddIcon(image_list, empty_icon); - ImageList_AddIcon(image_list, empty_icon); - } - ListView_SetImageList(native_view(), image_list, LVSIL_SMALL); - } - - if (!table_->resizable_columns()) { - // To disable the resizing of columns we'll filter the events happening on - // the header. We also need to intercept the HDM_LAYOUT to size the header - // for the Chrome headers. - HWND header = ListView_GetHeader(native_view()); - DCHECK(header); - SetWindowLongPtr(header, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); - header_original_handler_ = - ui::SetWindowProc(header, &NativeTableWin::TableHeaderWndProc); - } - - SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); - original_handler_ = - ui::SetWindowProc(hwnd, &NativeTableWin::TableWndProc); - - // Bug 964884: detach the IME attached to this window. - // We should attach IMEs only when we need to input CJK strings. - ::ImmAssociateContextEx(hwnd, NULL, 0); - - UpdateContentOffset(); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableWin, private: - -void NativeTableWin::Select(int model_row) { - if (!native_view()) - return; - - DCHECK(model_row >= 0 && model_row < table_->model()->RowCount()); - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0); - ignore_listview_change_ = true; - - // Unselect everything. - ClearSelection(); - - // Select the specified item. - SetSelectedState(model_row, true); - SetFocusState(model_row, true); - - // Make it visible. - ListView_EnsureVisible(native_view(), model_row, FALSE); - ignore_listview_change_ = false; - SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0); - if (table_->observer()) - table_->observer()->OnSelectionChanged(); -} - -void NativeTableWin::OnSelectedStateChanged() { - if (!ignore_listview_change_ && table_->observer()) - table_->observer()->OnSelectionChanged(); -} - -void NativeTableWin::OnDoubleClick() { - if (!ignore_listview_change_ && table_->observer()) - table_->observer()->OnDoubleClick(); -} - -void NativeTableWin::OnMiddleClick() { - if (!ignore_listview_change_ && table_->observer()) - table_->observer()->OnMiddleClick(); -} - -bool NativeTableWin::OnKeyDown(ui::KeyboardCode virtual_keycode) { - if (!ignore_listview_change_ && table_->observer()) - table_->observer()->OnKeyDown(virtual_keycode); - return false; // Let the key event be processed as ususal. -} - -LRESULT NativeTableWin::OnCustomDraw(NMLVCUSTOMDRAW* draw_info) { - switch (draw_info->nmcd.dwDrawStage) { - case CDDS_PREPAINT: { - return CDRF_NOTIFYITEMDRAW; - } - case CDDS_ITEMPREPAINT: { - // The list-view is about to paint an item, tell it we want to - // notified when it paints every subitem. - LRESULT r = CDRF_NOTIFYSUBITEMDRAW; - if (table_->type() == ICON_AND_TEXT) - r |= CDRF_NOTIFYPOSTPAINT; - return r; - } - case CDDS_ITEMPREPAINT | CDDS_SUBITEM: { - // TODO(jcampan): implement custom colors and fonts. - return CDRF_DODEFAULT; - } - case CDDS_ITEMPOSTPAINT: { - DCHECK(table_->type() == ICON_AND_TEXT); - int view_index = static_cast<int>(draw_info->nmcd.dwItemSpec); - // We get notifications for empty items, just ignore them. - if (view_index >= table_->model()->RowCount()) - return CDRF_DODEFAULT; - LRESULT r = CDRF_DODEFAULT; - // First let's take care of painting the right icon. - if (table_->type() == ICON_AND_TEXT) { - SkBitmap image = table_->model()->GetIcon(view_index); - if (!image.isNull()) { - // Get the rect that holds the icon. - RECT icon_rect, client_rect; - if (ListView_GetItemRect(native_view(), view_index, &icon_rect, - LVIR_ICON) && - GetClientRect(native_view(), &client_rect)) { - RECT intersection; - // Client rect includes the header but we need to make sure we don't - // paint into it. - client_rect.top += content_offset_; - // Make sure the region need to paint is visible. - if (IntersectRect(&intersection, &icon_rect, &client_rect)) { - gfx::CanvasSkia canvas( - gfx::Size(icon_rect.right - icon_rect.left, - icon_rect.bottom - icon_rect.top), false); - - // It seems the state in nmcd.uItemState is not correct. - // We'll retrieve it explicitly. - int selected = ListView_GetItemState( - native_view(), view_index, LVIS_SELECTED | LVIS_DROPHILITED); - bool drop_highlight = ((selected & LVIS_DROPHILITED) != 0); - int bg_color_index; - if (!enabled()) - bg_color_index = COLOR_3DFACE; - else if (drop_highlight) - bg_color_index = COLOR_HIGHLIGHT; - else if (selected) - bg_color_index = HasFocus() ? COLOR_HIGHLIGHT : COLOR_3DFACE; - else - bg_color_index = COLOR_WINDOW; - // NOTE: This may be invoked without the ListView filling in the - // background (or rather windows paints background, then invokes - // this twice). As such, we always fill in the background. - canvas.sk_canvas()->drawColor( - skia::COLORREFToSkColor(GetSysColor(bg_color_index)), - SkXfermode::kSrc_Mode); - // + 1 for padding (we declared the image as 18x18 in the list- - // view when they are 16x16 so we get an extra pixel of padding). - canvas.DrawBitmapInt(image, 0, 0, - image.width(), image.height(), - 1, 1, - gfx::kFaviconSize, gfx::kFaviconSize, true); - - // Only paint the visible region of the icon. - RECT to_draw = { intersection.left - icon_rect.left, - intersection.top - icon_rect.top, - 0, 0 }; - to_draw.right = to_draw.left + - (intersection.right - intersection.left); - to_draw.bottom = to_draw.top + - (intersection.bottom - intersection.top); - skia::DrawToNativeContext(canvas.sk_canvas(), draw_info->nmcd.hdc, - intersection.left, intersection.top, - &to_draw); - r = CDRF_SKIPDEFAULT; - } - } - } - } - return r; - } - default: - return CDRF_DODEFAULT; - } -} - -void NativeTableWin::UpdateListViewCache(int start, int length, bool add) { - LVITEM item = {0}; - int start_column = 0; - int max_row = start + length; - if (add) { - item.mask |= LVIF_PARAM; - for (int i = start; i < max_row; ++i) { - item.iItem = i; - item.lParam = i; - ignore_listview_change_ = true; - ListView_InsertItem(native_view(), &item); - ignore_listview_change_ = false; - } - } - - memset(&item, 0, sizeof(LVITEM)); - item.stateMask = 0; - item.mask = LVIF_TEXT; - if (table_->type() == ICON_AND_TEXT) - item.mask |= LVIF_IMAGE; - - for (size_t j = start_column; j < table_->GetVisibleColumnCount(); ++j) { - ui::TableColumn col = table_->GetVisibleColumnAt(j); - int max_text_width = ListView_GetStringWidth(native_view(), - col.title.c_str()); - for (int i = start; i < max_row; ++i) { - item.iItem = i; - item.iSubItem = j; - string16 text = table_->model()->GetText(i, col.id); - item.pszText = const_cast<LPWSTR>(text.c_str()); - item.iImage = 0; - ListView_SetItem(native_view(), &item); - - // Compute width in px, using current font. - int string_width = ListView_GetStringWidth(native_view(), item.pszText); - // The width of an icon belongs to the first column. - if (j == 0 && table_->type() == ICON_AND_TEXT) - string_width += kListViewIconWidthAndPadding; - max_text_width = std::max(string_width, max_text_width); - } - - // ListView_GetStringWidth must be padded or else truncation will occur - // (MSDN). 15px matches the Win32/LVSCW_AUTOSIZE_USEHEADER behavior. - max_text_width += kListViewTextPadding; - - // Protect against partial update. - if (max_text_width > col.min_visible_width || - (start == 0 && length == table_->model()->RowCount())) { - col.min_visible_width = max_text_width; - } - } -} - -void NativeTableWin::UpdateContentOffset() { - content_offset_ = 0; - - if (!native_view()) - return; - - HWND header = ListView_GetHeader(native_view()); - if (!header) - return; - - POINT origin = {0, 0}; - MapWindowPoints(header, native_view(), &origin, 1); - - RECT header_bounds; - GetWindowRect(header, &header_bounds); - - content_offset_ = origin.y + header_bounds.bottom - header_bounds.top; -} - -static int GetViewIndexFromMouseEvent(HWND window, LPARAM l_param) { - int x = GET_X_LPARAM(l_param); - int y = GET_Y_LPARAM(l_param); - LVHITTESTINFO hit_info = {0}; - hit_info.pt.x = x; - hit_info.pt.y = y; - return ListView_HitTest(window, &hit_info); -} - -// static -LRESULT CALLBACK NativeTableWin::TableWndProc(HWND window, - UINT message, - WPARAM w_param, - LPARAM l_param) { - NativeTableWin* native_table_win = reinterpret_cast<NativeTableWin*>( - GetWindowLongPtr(window, GWLP_USERDATA)); - TableView2* table = native_table_win->table_; - - // Is the mouse down on the table? - static bool in_mouse_down = false; - // Should we select on mouse up? - static bool select_on_mouse_up = false; - - // If the mouse is down, this is the location of the mouse down message. - static int mouse_down_x, mouse_down_y; - - switch (message) { - case WM_CONTEXTMENU: { - // This addresses two problems seen with context menus in right to left - // locales: - // 1. The mouse coordinates in the l_param were occasionally wrong in - // weird ways. This is most often seen when right clicking on the - // list-view twice in a row. - // 2. Right clicking on the icon would show the scrollbar menu. - // - // As a work around this uses the position of the cursor and ignores - // the position supplied in the l_param. - if (base::i18n::IsRTL() && - (GET_X_LPARAM(l_param) != -1 || GET_Y_LPARAM(l_param) != -1)) { - POINT screen_point; - GetCursorPos(&screen_point); - POINT table_point = screen_point; - RECT client_rect; - if (ScreenToClient(window, &table_point) && - GetClientRect(window, &client_rect) && - PtInRect(&client_rect, table_point)) { - // The point is over the client area of the table, handle it ourself. - // But first select the row if it isn't already selected. - LVHITTESTINFO hit_info = {0}; - hit_info.pt.x = table_point.x; - hit_info.pt.y = table_point.y; - int view_index = ListView_HitTest(window, &hit_info); - // TODO(jcampan): fix code below - // if (view_index != -1 && table->IsItemSelected(view_index)) - // table->Select(view_index); - // table->OnContextMenu(screen_point); - return 0; // So that default processing doesn't occur. - } - } - // else case: default handling is fine, so break and let the default - // handler service the request (which will likely calls us back with - // OnContextMenu). - break; - } - - case WM_CANCELMODE: { - if (in_mouse_down) { - in_mouse_down = false; - return 0; - } - break; - } - - case WM_ERASEBKGND: - // We make WM_ERASEBKGND do nothing (returning 1 indicates we handled - // the request). We do this so that the table view doesn't flicker during - // resizing. - return 1; - - case WM_KEYDOWN: { - if (!table->single_selection() && w_param == 'A' && - GetKeyState(VK_CONTROL) < 0 && table->model()->RowCount() > 0) { - // Select everything. - ListView_SetItemState(window, -1, LVIS_SELECTED, LVIS_SELECTED); - // And make the first row focused. - ListView_SetItemState(window, 0, LVIS_FOCUSED, LVIS_FOCUSED); - return 0; - } else if (w_param == VK_DELETE && table->observer()) { - table->observer()->OnTableView2Delete(table); - return 0; - } - // else case: fall through to default processing. - break; - } - - case WM_LBUTTONDBLCLK: { - if (w_param == MK_LBUTTON) - native_table_win->OnDoubleClick(); - return 0; - } - - case WM_MBUTTONDOWN: { - if (w_param == MK_MBUTTON) { - int view_index = GetViewIndexFromMouseEvent(window, l_param); - if (view_index != -1) { - // Clear all and select the row that was middle clicked. - native_table_win->Select(view_index); - native_table_win->OnMiddleClick(); - } - } - return 0; - } - - case WM_LBUTTONUP: { - if (in_mouse_down) { - in_mouse_down = false; - ReleaseCapture(); - ::SetFocus(window); - if (select_on_mouse_up) { - int view_index = GetViewIndexFromMouseEvent(window, l_param); - if (view_index != -1) - native_table_win->Select(view_index); - } - return 0; - } - break; - } - - case WM_LBUTTONDOWN: { - // ListView treats clicking on an area outside the text of a column as - // drag to select. This is confusing when the selection is shown across - // the whole row. For this reason we override the default handling for - // mouse down/move/up and treat the whole row as draggable. That is, no - // matter where you click in the row we'll attempt to start dragging. - // - // Only do custom mouse handling if no other mouse buttons are down. - if ((w_param | (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) == - (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) { - if (in_mouse_down) - return 0; - - int view_index = GetViewIndexFromMouseEvent(window, l_param); - if (view_index != -1) { - native_table_win->ignore_listview_change_ = true; - in_mouse_down = true; - select_on_mouse_up = false; - mouse_down_x = GET_X_LPARAM(l_param); - mouse_down_y = GET_Y_LPARAM(l_param); - bool select = true; - if (w_param & MK_CONTROL) { - select = false; - if (!native_table_win->IsRowSelected(view_index)) { - if (table->single_selection()) { - // Single selection mode and the row isn't selected, select - // only it. - native_table_win->Select(view_index); - } else { - // Not single selection, add this row to the selection. - native_table_win->SetSelectedState(view_index, true); - } - } else { - // Remove this row from the selection. - native_table_win->SetSelectedState(view_index, false); - } - ListView_SetSelectionMark(window, view_index); - } else if (!table->single_selection() && w_param & MK_SHIFT) { - int mark_view_index = ListView_GetSelectionMark(window); - if (mark_view_index != -1) { - // Unselect everything. - ListView_SetItemState(window, -1, 0, LVIS_SELECTED); - select = false; - - // Select from mark to mouse down location. - for (int i = std::min(view_index, mark_view_index), - max_i = std::max(view_index, mark_view_index); i <= max_i; - ++i) { - native_table_win->SetSelectedState(i, true); - } - } - } - // Make the row the user clicked on the focused row. - ListView_SetItemState(window, view_index, LVIS_FOCUSED, - LVIS_FOCUSED); - if (select) { - if (!native_table_win->IsRowSelected(view_index)) { - // Clear all. - ListView_SetItemState(window, -1, 0, LVIS_SELECTED); - // And select the row the user clicked on. - native_table_win->SetSelectedState(view_index, true); - } else { - // The item is already selected, don't clear the state right away - // in case the user drags. Instead wait for mouse up, then only - // select the row the user clicked on. - select_on_mouse_up = true; - } - ListView_SetSelectionMark(window, view_index); - } - native_table_win->ignore_listview_change_ = false; - table->observer()->OnSelectionChanged(); - SetCapture(window); - return 0; - } - // else case, continue on to default handler - } - break; - } - - case WM_MOUSEMOVE: { - if (in_mouse_down) { - int x = GET_X_LPARAM(l_param); - int y = GET_Y_LPARAM(l_param); - if (View::ExceededDragThreshold(x - mouse_down_x, y - mouse_down_y)) { - // We're about to start drag and drop, which results in no mouse up. - // Release capture and reset state. - ReleaseCapture(); - in_mouse_down = false; - - NMLISTVIEW details; - memset(&details, 0, sizeof(details)); - details.hdr.code = LVN_BEGINDRAG; - SendMessage(::GetParent(window), WM_NOTIFY, 0, - reinterpret_cast<LPARAM>(&details)); - } - return 0; - } - break; - } - - default: - break; - } - - DCHECK(native_table_win->original_handler_); - return CallWindowProc(native_table_win->original_handler_, window, message, - w_param, l_param); -} - -LRESULT CALLBACK NativeTableWin::TableHeaderWndProc(HWND window, UINT message, - WPARAM w_param, - LPARAM l_param) { - NativeTableWin* native_table_win = reinterpret_cast<NativeTableWin*>( - GetWindowLongPtr(window, GWLP_USERDATA)); - - switch (message) { - case WM_SETCURSOR: - if (!native_table_win->table_->resizable_columns()) - // Prevents the cursor from changing to the resize cursor. - return TRUE; - break; - // TODO(jcampan): we should also block single click messages on the - // separator as right now columns can still be resized. - case WM_LBUTTONDBLCLK: - if (!native_table_win->table_->resizable_columns()) - // Prevents the double-click on the column separator from auto-resizing - // the column. - return TRUE; - break; - default: - break; - } - DCHECK(native_table_win->header_original_handler_); - return CallWindowProc(native_table_win->header_original_handler_, - window, message, w_param, l_param); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeTableWrapper, public: - -// static -NativeTableWrapper* NativeTableWrapper::CreateNativeWrapper(TableView2* table) { - return new NativeTableWin(table); -} - -} // namespace views diff --git a/ui/views/controls/table/native_table_win.h b/ui/views/controls/table/native_table_win.h deleted file mode 100644 index 432b30c..0000000 --- a/ui/views/controls/table/native_table_win.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2011 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_NATIVE_TABLE_WIN_H_ -#define UI_VIEWS_CONTROLS_TABLE_NATIVE_TABLE_WIN_H_ -#pragma once - -#include <windows.h> - -#include "ui/base/models/table_model.h" -#include "ui/views/controls/native_control_win.h" -#include "ui/views/controls/table/native_table_wrapper.h" - -typedef struct tagNMLVCUSTOMDRAW NMLVCUSTOMDRAW; - -namespace views { - -class TableView2; - -// A View that hosts a native Windows table. -class NativeTableWin : public NativeControlWin, public NativeTableWrapper { - public: - explicit NativeTableWin(TableView2* table); - virtual ~NativeTableWin(); - - // NativeTableWrapper implementation: - virtual int GetRowCount() const; - virtual View* GetView(); - virtual void SetFocus(); - virtual gfx::NativeView GetTestingHandle() const; - virtual void InsertColumn(const ui::TableColumn& column, int index); - virtual void RemoveColumn(int index); - virtual int GetColumnWidth(int column_index) const; - virtual void SetColumnWidth(int column_index, int width); - virtual int GetSelectedRowCount() const; - virtual int GetFirstSelectedRow() const; - virtual int GetFirstFocusedRow() const; - virtual void ClearSelection(); - virtual void ClearRowFocus(); - virtual void SetSelectedState(int model_row, bool state); - virtual void SetFocusState(int model_row, bool state); - virtual bool IsRowSelected(int model_row) const; - virtual bool IsRowFocused(int model_row) const; - virtual void OnRowsChanged(int start, int length); - virtual void OnRowsAdded(int start, int length); - virtual void OnRowsRemoved(int start, int length); - virtual gfx::Rect GetBounds() const; - - // Overridden from View: - virtual gfx::Size GetPreferredSize(); - - // Overridden from NativeControlWin: - virtual bool ProcessMessage(UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* result); - - protected: - virtual void CreateNativeControl(); - - private: - // Makes |model_row| the only selected and focused row. - void Select(int model_row); - - // Notification from the ListView that the selected state of an item has - // changed. - virtual void OnSelectedStateChanged(); - - // Notification from the ListView that the used double clicked the table. - virtual void OnDoubleClick(); - - // Notification from the ListView that the user middle clicked the table. - virtual void OnMiddleClick(); - - // Overridden from NativeControl. Notifies the observer. - virtual bool OnKeyDown(ui::KeyboardCode virtual_keycode); - - // Custom drawing of our icons. - LRESULT OnCustomDraw(NMLVCUSTOMDRAW* draw_info); - - void UpdateListViewCache(int start, int length, bool add); - - void UpdateContentOffset(); - - // Window procedure of the list view class. We subclass the list view to - // ignore WM_ERASEBKGND, which gives smoother painting during resizing. - static LRESULT CALLBACK TableWndProc(HWND window, - UINT message, - WPARAM w_param, - LPARAM l_param); - - // Window procedure of the header class. We subclass the header of the table - // to disable resizing of columns. - static LRESULT CALLBACK TableHeaderWndProc(HWND window, - UINT message, - WPARAM w_param, - LPARAM l_param); - - // If true, any events that would normally be propagated to the observer - // are ignored. For example, if this is true and the selection changes in - // the listview, the observer is not notified. - bool ignore_listview_change_; - - // The Table we are bound to. - TableView2* table_; - - // The Y offset from the top of the table to the actual content (passed the - // header if any). - int content_offset_; - - // The list view's header original proc handler. It is required when - // subclassing. - WNDPROC header_original_handler_; - - // Window procedure of the listview before we subclassed it. - WNDPROC original_handler_; - - // Size (width and height) of images. - static const int kImageSize; - - DISALLOW_COPY_AND_ASSIGN(NativeTableWin); -}; - -} // namespace views - -#endif // UI_VIEWS_CONTROLS_TABLE_NATIVE_TABLE_WIN_H_ diff --git a/ui/views/controls/table/native_table_wrapper.h b/ui/views/controls/table/native_table_wrapper.h deleted file mode 100644 index 451378b..0000000 --- a/ui/views/controls/table/native_table_wrapper.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2011 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_NATIVE_TABLE_WRAPPER_H_ -#define UI_VIEWS_CONTROLS_TABLE_NATIVE_TABLE_WRAPPER_H_ -#pragma once - -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/rect.h" - -namespace ui { -struct TableColumn; -} - -namespace views { - -class TableView2; -class View; - -// An interface implemented by an object that provides a platform-native -// table. -class NativeTableWrapper { - public: - // Returns the number of rows in the table. - virtual int GetRowCount() const = 0; - - // Inserts/removes a column at the specified index. - virtual void InsertColumn(const ui::TableColumn& column, int index) = 0; - virtual void RemoveColumn(int index) = 0; - - // Returns the number of rows that are selected. - virtual int GetSelectedRowCount() const = 0; - - // Returns the first row that is selected/focused in terms of the model. - virtual int GetFirstSelectedRow() const = 0; - virtual int GetFirstFocusedRow() const = 0; - - // Unselect all rows. - virtual void ClearSelection() = 0; - - virtual void ClearRowFocus() = 0; - - virtual void SetSelectedState(int model_row, bool state) = 0; - - virtual void SetFocusState(int model_row, bool state) = 0; - - // Returns true if the row at the specified index is selected. - virtual bool IsRowSelected(int model_row) const = 0; - - // Returns true if the row at the specified index has the focus. - virtual bool IsRowFocused(int model_row) const = 0; - - // Retrieves the views::View that hosts the native control. - virtual View* GetView() = 0; - - // Sets the focus to the table. - virtual void SetFocus() = 0; - - // Returns a handle to the underlying native view for testing. - virtual gfx::NativeView GetTestingHandle() const = 0; - - // Gets/sets the columns width. - virtual int GetColumnWidth(int column_index) const = 0; - virtual void SetColumnWidth(int column_index, int width) = 0; - - // Called by the table view to indicate that some rows have changed, been - // added or been removed. - virtual void OnRowsChanged(int start, int length) = 0; - virtual void OnRowsAdded(int start, int length) = 0; - virtual void OnRowsRemoved(int start, int length) = 0; - - // Returns the bounds of the native table. - virtual gfx::Rect GetBounds() const = 0; - - // Creates an appropriate NativeTableWrapper for the platform. - static NativeTableWrapper* CreateNativeWrapper(TableView2* table); - - protected: - virtual ~NativeTableWrapper() {} -}; - -} // namespace views - -#endif // UI_VIEWS_CONTROLS_TABLE_NATIVE_TABLE_WRAPPER_H_ diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h index f528200..c7f0845 100644 --- a/ui/views/controls/table/table_view.h +++ b/ui/views/controls/table/table_view.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -6,498 +6,8 @@ #define UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_H_ #pragma once -#include <map> -#include <vector> - -#include "base/gtest_prod_util.h" -#include "base/string16.h" -#include "build/build_config.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/models/table_model_observer.h" -#include "ui/views/views_export.h" - #if defined(OS_WIN) -#include <windows.h> - -// TODO(port): remove the ifdef when native_control.h is ported. -#include "ui/views/controls/native_control.h" - -typedef struct tagNMLVCUSTOMDRAW NMLVCUSTOMDRAW; -#endif // defined(OS_WIN) - -namespace gfx { -class Font; -} - -namespace ui { -struct TableColumn; -class TableModel; -} - -// 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. -// -// 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 views { - -class ListView; -class ListViewParent; -class TableView; -class TableViewObserver; - -// 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, - CHECK_BOX_AND_TEXT -}; - -// Returned from SelectionBegin/SelectionEnd -class VIEWS_EXPORT TableSelectionIterator { - public: - TableSelectionIterator(TableView* view, int view_index); - TableSelectionIterator& operator=(const TableSelectionIterator& other); - bool operator==(const TableSelectionIterator& other); - bool operator!=(const TableSelectionIterator& other); - TableSelectionIterator& operator++(); - int operator*(); - - private: - void UpdateModelIndexFromViewIndex(); - - TableView* table_view_; - 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_; -}; - -#if defined(OS_WIN) -// TODO(port): Port TableView. -class VIEWS_EXPORT TableView : public NativeControl, - public ui::TableModelObserver { - public: - typedef TableSelectionIterator iterator; - - // A helper struct for GetCellColors. Set |color_is_set| to true if color is - // set. See OnCustomDraw for more details on why we need this. - struct ItemColor { - bool color_is_set; - 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). - // When autosize_columns is true, columns always fill the available width. If - // false, columns are not resized when the table is resized. An extra empty - // column at the right fills the remaining space. - // When resizable_columns is true, users can resize columns by dragging the - // separator on the column header. NOTE: Right now this is always true. The - // code to set it false is still in place to be a base for future, better - // resizing behavior (see http://b/issue?id=874646 ), but no one uses or - // tests the case where this flag is false. - // Note that setting both resizable_columns and autosize_columns to false is - // probably not a good idea, as there is no way for the user to increase a - // column's size in that case. - TableView(ui::TableModel* model, const std::vector<ui::TableColumn>& columns, - TableTypes table_type, bool single_selection, - bool resizable_columns, bool autosize_columns); - 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_; } - - // Resorts the contents. - void SetSortDescriptors(const SortDescriptors& sort_descriptors); - - // Current sort. - const SortDescriptors& sort_descriptors() const { return sort_descriptors_; } - - // Returns the number of rows in the TableView. - int RowCount() const; - - // Returns the number of selected rows. - int SelectedRowCount(); - - // Selects the specified item, making sure it's visible. - 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 model_row, bool state); - - // Sets the focus to the item at the given index. - void SetFocusOnItem(int model_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 model_row); - - // Returns true if the item at the specified index has the focus. - bool ItemHasTheFocus(int model_row); - - // Returns an iterator over the selection. The iterator proceeds from the - // 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(); - - // ui::TableModelObserver methods. - virtual void OnModelChanged(); - virtual void OnItemsChanged(int start, int length); - virtual void OnItemsAdded(int start, int length); - virtual void OnItemsRemoved(int start, int length); - - void SetObserver(TableViewObserver* observer) { - table_view_observer_ = observer; - } - TableViewObserver* observer() const { return table_view_observer_; } - - // Replaces the set of known columns without changing the current visible - // columns. - void SetColumns(const std::vector<ui::TableColumn>& columns); - void AddColumn(const ui::TableColumn& col); - bool HasColumn(int id); - - // Sets which columns (by id) are displayed. All transient size and position - // information is lost. - void SetVisibleColumns(const std::vector<int>& columns); - void SetColumnVisibility(int id, bool is_visible); - bool IsColumnVisible(int id) const; - - // Resets the size of the columns based on the sizes passed to the - // constructor. Your normally needn't invoked this, it's done for you the - // first time the TableView is given a valid size. - void ResetColumnSizes(); - - // Sometimes we may want to size the TableView to a specific width and - // height. - virtual gfx::Size GetPreferredSize(); - void SetPreferredSize(const gfx::Size& size); - - // 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 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; - - // Sets the text to display on top of the table. This is useful if the table - // is empty and you want to inform the user why. - void SetAltText(const string16& alt_text); - - protected: - // Overriden to return the position of the first selected row. - virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE; - - // 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 - // GetCellColors is never invoked. - void SetCustomColorsEnabled(bool custom_colors_enabled); - - // Notification from the ListView that the selected state of an item has - // changed. - virtual void OnSelectedStateChanged(); - - // Notification from the ListView that the used double clicked the table. - virtual void OnDoubleClick(); - - // Notification from the ListView that the user middle clicked the table. - virtual void OnMiddleClick(); - - // Overridden from NativeControl. Notifies the observer. - virtual bool OnKeyDown(ui::KeyboardCode virtual_keycode) OVERRIDE; - - // View override. - virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; - - // 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 model_row, - int column, - ItemColor* foreground, - ItemColor* background, - LOGFONT* logfont); - - // Subclasses that want to perform some custom painting (on top of the regular - // list view painting) should return true here and implement the PostPaint - // method. - virtual bool ImplementPostPaint() { return false; } - // Subclasses can implement in this method extra-painting for cells. - virtual void PostPaint(int model_row, int column, bool selected, - const gfx::Rect& bounds, HDC device_context) { } - virtual void PostPaint() {} - - virtual HWND CreateNativeControl(HWND parent_container); - - virtual LRESULT OnNotify(int w_param, LPNMHDR l_param); - - // 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() {} - - // Returns the width of the specified column by id, or -1 if the column isn't - // visible. - int GetColumnWidth(int column_id); - - // Returns the offset from the top of the client area to the start of the - // content. - int content_offset() const { return content_offset_; } - - // Draws the alt_text_. Does nothing if there is no alt_text_. - void PaintAltText(); - - // Size (width and height) of images. - static const int kImageSize; - - 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 - // subclass (in the OO sense of TableView). - struct TableViewWrapper { - explicit TableViewWrapper(TableView* view) : table_view(view) { } - TableView* table_view; - }; - - friend class ListViewParent; - friend class TableSelectionIterator; - friend class GroupModelTableViewTest; - FRIEND_TEST_ALL_PREFIXES(GroupModelTableViewTest, ShiftSelectAcrossGroups); - FRIEND_TEST_ALL_PREFIXES(GroupModelTableViewTest, ShiftSelectSameGroup); - - 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(); - - // Selects multiple items from the current view row to the marked view row - // (implements shift-click behavior). |view_index| is the most recent row - // that the user clicked on, and so there is no guarantee that - // |view_index| > |mark_view_index| or vice-versa. Returns false if the - // selection attempt was rejected because it crossed group boundaries. - bool SelectMultiple(int view_index, int mark_view_index); - - // 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 ui::TableColumn& tc, int index); - - // Update headers and internal state after columns have changed - void OnColumnsChanged(); - - // Updates the ListView with values from the model. See UpdateListViewCache0 - // for a complete description. - // This turns off redrawing, and invokes UpdateListViewCache0 to do the - // actual updating. - void UpdateListViewCache(int start, int length, bool add); - - // Updates ListView with values from the model. - // If add is true, this adds length items starting at index start. - // If add is not true, the items are not added, the but the values in the - // range start - [start + length] are updated from the model. - void UpdateListViewCache0(int start, int length, bool add); - - // 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 view index in the table view, or -1 if the table - // is empty, or nothing is selected. - // - // WARNING: this returns coordinates in terms of the view, NOT the model. - int LastSelectedViewIndex(); - - // The TableColumn visible at position pos. - const ui::TableColumn& GetColumnAtPosition(int pos); - - // Window procedure of the list view class. We subclass the list view to - // ignore WM_ERASEBKGND, which gives smoother painting during resizing. - static LRESULT CALLBACK TableWndProc(HWND window, - UINT message, - WPARAM w_param, - LPARAM l_param); - - // Window procedure of the header class. We subclass the header of the table - // to disable resizing of columns. - static LRESULT CALLBACK TableHeaderWndProc(HWND window, UINT message, - WPARAM w_param, LPARAM l_param); - - // Updates content_offset_ from the position of the header. - void UpdateContentOffset(); - - // Reloads the groups from the model if there is one and it has groups. - void UpdateGroups(); - - // Returns the bounds of the alt text. - gfx::Rect GetAltTextBounds(); - - // Returns the font used for alt text. - gfx::Font GetAltTextFont(); - - // Overriden in order to update the column sizes, which can only be sized - // accurately when the native control is available. - virtual void VisibilityChanged(View* starting_from, bool is_visible); - - ui::TableModel* model_; - TableTypes table_type_; - TableViewObserver* table_view_observer_; - - // An ordered list of id's into |all_columns_| representing current visible - // columns. - std::vector<int> visible_columns_; - - // Mapping of an int id to a TableColumn representing all possible columns. - std::map<int, ui::TableColumn> all_columns_; - - // Cached value of columns_.size() - int column_count_; - - // Selection mode. - bool single_selection_; - - // If true, any events that would normally be propagated to the observer - // are ignored. For example, if this is true and the selection changes in - // the listview, the observer is not notified. - bool ignore_listview_change_; - - // Reflects the value passed to SetCustomColorsEnabled. - bool custom_colors_enabled_; - - // Whether or not columns should automatically be resized to fill the - // the available width when the list view is resized. - bool autosize_columns_; - - // Whether or not the user can resize columns. - bool resizable_columns_; - - // Whether the column sizes have been determined. - bool column_sizes_valid_; - - // NOTE: While this has the name View in it, it's not a view. Rather it's - // a wrapper around the List-View window. - HWND list_view_; - - // The list view's header original proc handler. It is required when - // subclassing. - WNDPROC header_original_handler_; - - // Window procedure of the listview before we subclassed it. - WNDPROC original_handler_; - - // A wrapper around 'this' used when "subclassing" the list view and header. - TableViewWrapper table_view_wrapper_; - - // A custom font we use when overriding the font type for a specific cell. - HFONT custom_cell_font_; - - // The preferred size of the table view. - gfx::Size preferred_size_; - - int content_offset_; - - // Current sort. - SortDescriptors sort_descriptors_; - - // Mappings used when sorted. - scoped_array<int> view_to_model_; - scoped_array<int> model_to_view_; - - string16 alt_text_; - - DISALLOW_COPY_AND_ASSIGN(TableView); -}; -#endif // defined(OS_WIN) - -} // namespace views +#include "ui/views/controls/table/table_view_win.h" +#endif #endif // UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_H_ diff --git a/ui/views/controls/table/table_view2.cc b/ui/views/controls/table/table_view2.cc deleted file mode 100644 index 4589fcd..0000000 --- a/ui/views/controls/table/table_view2.cc +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright (c) 2011 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. - -#include "ui/views/controls/table/table_view2.h" - -#include "base/logging.h" -#include "ui/base/models/table_model.h" -#include "ui/views/controls/native/native_view_host.h" -#include "ui/views/controls/table/table_view_observer.h" - -namespace views { - -TableView2::TableView2(ui::TableModel* model, - const std::vector<ui::TableColumn>& columns, - TableTypes table_type, - int options) - : model_(model), - table_type_(table_type), - table_view_observer_(NULL), - visible_columns_(), - all_columns_(), - column_count_(static_cast<int>(columns.size())), - single_selection_((options & SINGLE_SELECTION) != 0), - resizable_columns_((options & RESIZABLE_COLUMNS) != 0), - autosize_columns_((options & AUTOSIZE_COLUMNS) != 0), - horizontal_lines_((options & HORIZONTAL_LINES) != 0), - vertical_lines_((options & VERTICAL_LINES) != 0), - native_wrapper_(NULL) { - Init(columns); -} - -TableView2::~TableView2() { - if (model_) - model_->SetObserver(NULL); -} - -void TableView2::SetModel(ui::TableModel* model) { - if (model == model_) - return; - - if (model_) - model_->SetObserver(NULL); - model_ = model; - if (model_) - model_->SetObserver(this); - if (native_wrapper_) - OnModelChanged(); -} - -int TableView2::GetRowCount() { - if (!native_wrapper_) - return 0; - return native_wrapper_->GetRowCount(); -} - -int TableView2::SelectedRowCount() { - if (!native_wrapper_) - return 0; - return native_wrapper_->GetSelectedRowCount(); -} - -void TableView2::ClearSelection() { - if (native_wrapper_) - native_wrapper_->ClearSelection(); -} - -void TableView2::ClearRowFocus() { - if (native_wrapper_) - native_wrapper_->ClearRowFocus(); -} - -int TableView2::GetFirstSelectedRow() { - if (!native_wrapper_) - return -1; - return native_wrapper_->GetFirstSelectedRow(); -} - -int TableView2::GetFirstFocusedRow() { - if (!native_wrapper_) - return -1; - return native_wrapper_->GetFirstFocusedRow(); -} - -void TableView2::SelectRow(int model_row) { - if (!native_wrapper_) - return; - - native_wrapper_->ClearSelection(); - native_wrapper_->SetSelectedState(model_row, true); - if (table_view_observer_) - table_view_observer_->OnSelectionChanged(); -} - -void TableView2::FocusRow(int model_row) { - if (!native_wrapper_) - return; - - native_wrapper_->SetFocusState(model_row, true); -} - -bool TableView2::IsRowSelected(int model_row) { - if (!native_wrapper_) - return false; - - return native_wrapper_->IsRowSelected(model_row); -} - -bool TableView2::IsRowFocused(int model_row) { - if (!native_wrapper_) - return false; - - return native_wrapper_->IsRowFocused(model_row); -} - -void TableView2::OnModelChanged() { - if (!native_wrapper_) - return; - - int current_row_count = native_wrapper_->GetRowCount(); - if (current_row_count > 0) - OnItemsRemoved(0, current_row_count); - if (model_ && model_->RowCount()) - OnItemsAdded(0, model_->RowCount()); -} - -void TableView2::OnItemsChanged(int start, int length) { - if (!native_wrapper_) - return; - - if (length == -1) { - DCHECK_GE(start, 0); - length = model_->RowCount() - start; - } - native_wrapper_->OnRowsChanged(start, length); -} - -void TableView2::OnItemsAdded(int start, int length) { - if (!native_wrapper_) - return; - - DCHECK(start >= 0 && length >= 0 && start <= native_wrapper_->GetRowCount()); - - native_wrapper_->OnRowsAdded(start, length); -} - -void TableView2::OnItemsRemoved(int start, int length) { - if (!native_wrapper_) - return; - - DCHECK(start >= 0 && length >= 0 && - start + length <= native_wrapper_->GetRowCount()); - - native_wrapper_->OnRowsRemoved(start, length); -} - -void TableView2::AddColumn(const ui::TableColumn& col) { - DCHECK_EQ(0U, all_columns_.count(col.id)); - all_columns_[col.id] = col; -} - -void TableView2::SetColumns(const std::vector<ui::TableColumn>& columns) { - // Remove the currently visible columns. - while (!visible_columns_.empty()) - SetColumnVisibility(visible_columns_.front(), false); - - all_columns_.clear(); - for (std::vector<ui::TableColumn>::const_iterator i = columns.begin(); - i != columns.end(); ++i) { - AddColumn(*i); - } -} - -void TableView2::OnColumnsChanged() { - column_count_ = static_cast<int>(visible_columns_.size()); - ResetColumnSizes(); -} - -bool TableView2::HasColumn(int id) { - return all_columns_.count(id) > 0; -} - -void TableView2::SetColumnVisibility(int id, bool is_visible) { - bool changed = false; - for (std::vector<int>::iterator i = visible_columns_.begin(); - i != visible_columns_.end(); ++i) { - if (*i == id) { - if (is_visible) { - // It's already visible, bail out early. - return; - } else { - int index = static_cast<int>(i - visible_columns_.begin()); - // This could be called before the native list view has been created - // (in CreateNativeControl, called when the view is added to a - // Widget). In that case since the column is not in - // visible_columns_ it will not be added later on when it is created. - if (native_wrapper_) - native_wrapper_->RemoveColumn(index); - visible_columns_.erase(i); - changed = true; - break; - } - } - } - if (is_visible) { - DCHECK(native_wrapper_); - visible_columns_.push_back(id); - ui::TableColumn& column = all_columns_[id]; - native_wrapper_->InsertColumn(column, column_count_); - changed = true; - } - if (changed) - OnColumnsChanged(); - -} - -bool TableView2::IsColumnVisible(int id) const { - for (std::vector<int>::const_iterator i = visible_columns_.begin(); - i != visible_columns_.end(); ++i) - if (*i == id) { - return true; - } - return false; -} - -void TableView2::ResetColumnSizes() { - if (!native_wrapper_) - return; - - // See comment in TableColumn for what this does. - int width = this->width(); - gfx::Rect native_bounds = native_wrapper_->GetBounds(); - if (!native_bounds.IsEmpty()) { - if (native_bounds.width() > 0) { - // Prefer the bounds of the window over our bounds, which may be - // different. - width = native_bounds.width(); - } - } - - float percent = 0; - int fixed_width = 0; - int autosize_width = 0; - - for (std::vector<int>::const_iterator i = visible_columns_.begin(); - i != visible_columns_.end(); ++i) { - ui::TableColumn& col = all_columns_[*i]; - int col_index = static_cast<int>(i - visible_columns_.begin()); - if (col.width == -1) { - if (col.percent > 0) { - percent += col.percent; - } else { - autosize_width += col.min_visible_width; - } - } else { - fixed_width += native_wrapper_->GetColumnWidth(col_index); - } - } - - // Now do a pass to set the actual sizes of auto-sized and - // percent-sized columns. - int available_width = width - fixed_width - autosize_width; - for (std::vector<int>::const_iterator i = visible_columns_.begin(); - i != visible_columns_.end(); ++i) { - ui::TableColumn& col = all_columns_[*i]; - if (col.width == -1) { - int col_index = static_cast<int>(i - visible_columns_.begin()); - if (col.percent > 0) { - if (available_width > 0) { - int col_width = - static_cast<int>(available_width * (col.percent / percent)); - available_width -= col_width; - percent -= col.percent; - native_wrapper_->SetColumnWidth(col_index, col_width); - } - } else { - int col_width = col.min_visible_width; - // If no "percent" columns, the last column acts as one, if auto-sized. - if (percent == 0.f && available_width > 0 && - col_index == column_count_ - 1) { - col_width += available_width; - } - native_wrapper_->SetColumnWidth(col_index, col_width); - } - } - } -} - -void TableView2::Layout() { - if (native_wrapper_) { - native_wrapper_->GetView()->SetBounds(0, 0, width(), height()); - native_wrapper_->GetView()->Layout(); - } -} - -void TableView2::OnPaintFocusBorder(gfx::Canvas* canvas) { - if (NativeViewHost::kRenderNativeControlFocus) - View::OnPaintFocusBorder(canvas); -} - -size_t TableView2::GetVisibleColumnCount() { - return visible_columns_.size(); -} - -void TableView2::ViewHierarchyChanged(bool is_add, View* parent, View* child) { - if (is_add && !native_wrapper_ && GetWidget()) { - // The native wrapper's lifetime will be managed by the view hierarchy after - // we call AddChildView. - native_wrapper_ = NativeTableWrapper::CreateNativeWrapper(this); - AddChildView(native_wrapper_->GetView()); - } -} - -void TableView2::Init(const std::vector<ui::TableColumn>& columns) { - for (std::vector<ui::TableColumn>::const_iterator i = columns.begin(); - i != columns.end(); ++i) { - AddColumn(*i); - visible_columns_.push_back(i->id); - } -} - -gfx::NativeView TableView2::GetTestingHandle() { - return native_wrapper_->GetTestingHandle(); -} - -ui::TableColumn TableView2::GetVisibleColumnAt(int index) { - DCHECK(index < static_cast<int>(visible_columns_.size())); - std::map<int, ui::TableColumn>::iterator iter = - all_columns_.find(index); - DCHECK(iter != all_columns_.end()); - return iter->second; -} - -} // namespace views diff --git a/ui/views/controls/table/table_view2.h b/ui/views/controls/table/table_view2.h deleted file mode 100644 index 5ba5c1b..0000000 --- a/ui/views/controls/table/table_view2.h +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2011 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_VIEW2_H_ -#define UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW2_H_ -#pragma once - -#include <map> -#include <vector> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/base/models/table_model_observer.h" -#include "ui/gfx/canvas.h" -#include "ui/views/controls/table/native_table_wrapper.h" -#include "ui/views/controls/table/table_view.h" -#include "ui/views/view.h" - -namespace ui { -struct TableColumn; -class TableModel; -} - -// A TableView2 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. -// -// TableView2 itself has an observer that is notified when the selection -// changes. -// -// TableView2 is the current port of TableView to use a NativeControl for -// portability. -// -// TODO(jcampan): add sorting. -// TODO(jcampan): add group support. - -namespace views { - -class ListView; -class ListViewParent; -class TableView; -class TableViewObserver; -class View; - -class VIEWS_EXPORT TableView2 : public View, public ui::TableModelObserver { - public: - typedef TableSelectionIterator iterator; - - // A helper struct for GetCellColors. Set |color_is_set| to true if color is - // set. See OnCustomDraw for more details on why we need this. - struct ItemColor { - bool color_is_set; - SkColor color; - }; - - // Bitmasks of options for creating an instance of the table view. See - // comments next to the corresponding members in TableView2 for details - // (ex. SINGLE_SELECTION -> single_selection_). - enum Options { - NONE = 0, - SINGLE_SELECTION = 1 << 0, - RESIZABLE_COLUMNS = 1 << 1, - AUTOSIZE_COLUMNS = 1 << 2, - HORIZONTAL_LINES = 1 << 3, - VERTICAL_LINES = 1 << 4, - }; - - // 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). - // When autosize_columns is true, columns always fill the available width. If - // false, columns are not resized when the table is resized. An extra empty - // column at the right fills the remaining space. - // When resizable_columns is true, users can resize columns by dragging the - // separator on the column header. NOTE: Right now this is always true. The - // code to set it false is still in place to be a base for future, better - // resizing behavior (see http://b/issue?id=874646 ), but no one uses or - // tests the case where this flag is false. - // Note that setting both resizable_columns and autosize_columns to false is - // probably not a good idea, as there is no way for the user to increase a - // column's size in that case. - // |options| is a bitmask of options. See comments at Options. - TableView2(ui::TableModel* model, const std::vector<ui::TableColumn>& columns, - TableTypes table_type, int options); - virtual ~TableView2(); - - // 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 the number of rows in the table. - int GetRowCount(); - - // Returns the number of selected rows. - int SelectedRowCount(); - - // Makes all row not selected. - void ClearSelection(); - - // Makes all row not focused. - void ClearRowFocus(); - - // Returns the index of the first selected row. - int GetFirstSelectedRow(); - - // Returns the index of the first focused row. - int GetFirstFocusedRow(); - - // Selects the specified row, making sure it's visible. - void SelectRow(int model_row); - - // Sets the focus to the row at the given index. - void FocusRow(int model_row); - - // Returns true if the row at the specified index is selected. - bool IsRowSelected(int model_row); - - // Returns true if the row at the specified index has the focus. - bool IsRowFocused(int model_row); - - // Returns an iterator over the selection. The iterator proceeds from the - // 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(); - - // ui::TableModelObserver methods. - 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; - - void SetObserver(TableViewObserver* observer) { - table_view_observer_ = observer; - } - TableViewObserver* observer() const { return table_view_observer_; } - - // Replaces the set of known columns without changing the current visible - // columns. - void SetColumns(const std::vector<ui::TableColumn>& columns); - void AddColumn(const ui::TableColumn& col); - bool HasColumn(int id); - - // Sets which columns (by id) are displayed. All transient size and position - // information is lost. - void SetVisibleColumns(const std::vector<int>& columns); - void SetColumnVisibility(int id, bool is_visible); - bool IsColumnVisible(int id) const; - - ui::TableColumn GetVisibleColumnAt(int index); - size_t GetVisibleColumnCount(); - - // Resets the size of the columns based on the sizes passed to the - // constructor. Your normally needn't invoked this, it's done for you the - // first time the TableView is given a valid size. - void ResetColumnSizes(); - - bool single_selection() const { - return single_selection_; - } - - TableTypes type() const { - return table_type_; - } - - bool resizable_columns() const { - return resizable_columns_; - } - - bool autosize_columns() const { - return autosize_columns_; - } - - bool horizontal_lines() const { - return horizontal_lines_; - } - - bool vertical_lines() const { - return vertical_lines_; - } - - virtual void Layout() OVERRIDE; - - virtual void OnPaintFocusBorder(gfx::Canvas* canvas) OVERRIDE; - - // Used by tests. - virtual gfx::NativeView GetTestingHandle(); - - protected: - virtual void ViewHierarchyChanged(bool is_add, - View* parent, - View* child) OVERRIDE; - - private: - friend class ListViewParent; - friend class TableSelectionIterator; - - // Used in the constructors. - void Init(const std::vector<ui::TableColumn>& columns); - - // 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 - // subclass (in the OO sense of TableView). - struct TableViewWrapper { - explicit TableViewWrapper(TableView2* view) : table_view(view) {} - TableView2* table_view; - }; - - // Adds a new column. - void InsertColumn(const ui::TableColumn& tc, int index); - - // Update headers and internal state after columns have changed - void OnColumnsChanged(); - - ui::TableModel* model_; - TableTypes table_type_; - TableViewObserver* table_view_observer_; - - // An ordered list of id's into all_columns_ representing current visible - // columns. - std::vector<int> visible_columns_; - - // Mapping of an int id to a TableColumn representing all possible columns. - std::map<int, ui::TableColumn> all_columns_; - - // Cached value of columns_.size() - int column_count_; - - // Selection mode. - bool single_selection_; - - // Whether or not the user can resize columns. - bool resizable_columns_; - - // Whether or not columns should automatically be resized to fill the - // the available width when the list view is resized. - bool autosize_columns_; - - // Whether or not horizontal grid lines should be drawn. - bool horizontal_lines_; - - // Whether or not vertical grid lines should be drawn. - bool vertical_lines_; - - // Mappings used when sorted. - // scoped_array<int> view_to_model_; - // scoped_array<int> model_to_view_; - - // The object that actually implements the table. - NativeTableWrapper* native_wrapper_; - - DISALLOW_COPY_AND_ASSIGN(TableView2); -}; - -} // namespace views - -#endif // UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW2_H_ diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc index 01581b0..ba0ddac 100644 --- a/ui/views/controls/table/table_view_unittest.cc +++ b/ui/views/controls/table/table_view_unittest.cc @@ -21,7 +21,6 @@ #include "ui/base/models/table_model.h" #include "ui/base/models/table_model_observer.h" #include "ui/views/controls/table/table_view.h" -#include "ui/views/controls/table/table_view2.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -468,180 +467,4 @@ TEST_F(NullModelTableViewTest, DISABLED_NullModel) { #endif // OS_WIN -//////////////////////////////////////////////////////////////////////////////// -// TableView2 Tests - -class TableView2Test : public testing::Test, views::WidgetDelegate { - public: - virtual void SetUp(); - virtual void TearDown(); - - virtual views::View* GetContentsView() OVERRIDE { - return table_; - } - virtual views::Widget* GetWidget() OVERRIDE { - return table_->GetWidget(); - } - virtual const views::Widget* GetWidget() const OVERRIDE { - return table_->GetWidget(); - } - - // Returns the contents of a cell in the table. - std::string GetCellValue(int row, int column); - - protected: - // Creates the model. - TestTableModel* CreateModel(); - - virtual views::TableTypes GetTableType() { - return views::TEXT_ONLY; - } - - scoped_ptr<TestTableModel> model_; - - // The table. This is owned by the window. - views::TableView2* table_; - - private: - MessageLoopForUI message_loop_; - views::Widget* window_; -}; - -void TableView2Test::SetUp() { -#if defined(OS_WIN) - OleInitialize(NULL); -#endif - model_.reset(CreateModel()); - std::vector<ui::TableColumn> columns; - columns.resize(2); - columns[0].id = 0; - columns[1].id = 1; - table_ = new views::TableView2(model_.get(), columns, GetTableType(), - views::TableView2::NONE); - window_ = views::Widget::CreateWindowWithBounds( - this, - gfx::Rect(100, 100, 512, 512)); - window_->Show(); -} - -void TableView2Test::TearDown() { - window_->Close(); - // Temporary workaround to avoid leak of RootView::pending_paint_task_. - message_loop_.RunAllPending(); -#if defined(OS_WIN) - OleUninitialize(); -#endif -} - -TestTableModel* TableView2Test::CreateModel() { - return new TestTableModel(); -} - -std::string TableView2Test::GetCellValue(int row, int column) { -#if defined(OS_WIN) - wchar_t str[128] = {0}; - LVITEM item = {0}; - item.mask = LVIF_TEXT; - item.iItem = row; - item.iSubItem = column; - item.pszText = str; - item.cchTextMax = 128; - BOOL r = ListView_GetItem(table_->GetTestingHandle(), &item); - DCHECK(r); - return WideToUTF8(str); -#else - GtkTreeModel* gtk_model = - gtk_tree_view_get_model(GTK_TREE_VIEW(table_->GetTestingHandle())); - DCHECK(gtk_model); - GtkTreeIter row_iter; - gboolean r = gtk_tree_model_iter_nth_child(gtk_model, &row_iter, NULL, row); - DCHECK(r); - gchar* text = NULL; - gtk_tree_model_get(gtk_model, &row_iter, column, &text, -1); - DCHECK(text); - std::string value(text); - g_free(text); - return value; -#endif -} - -// Tests that the table correctly reflects changes to the model. -TEST_F(TableView2Test, ModelChangesTest) { - ASSERT_EQ(3, table_->GetRowCount()); - EXPECT_EQ("0", GetCellValue(0, 0)); - EXPECT_EQ("1", GetCellValue(1, 0)); - EXPECT_EQ("2", GetCellValue(2, 1)); - - // Test adding rows and that OnItemsAdded works. - model_->AddRow(3, 3, 3); - model_->AddRow(4, 4, 4); - table_->OnItemsAdded(3, 2); - ASSERT_EQ(5, table_->GetRowCount()); - EXPECT_EQ("3", GetCellValue(3, 0)); - EXPECT_EQ("4", GetCellValue(4, 1)); - - // Test removing rows and that OnItemsRemoved works. - model_->RemoveRow(1); - model_->RemoveRow(1); - table_->OnItemsRemoved(1, 2); - ASSERT_EQ(3, table_->GetRowCount()); - EXPECT_EQ("0", GetCellValue(0, 0)); - EXPECT_EQ("3", GetCellValue(1, 0)); - EXPECT_EQ("4", GetCellValue(2, 1)); - - // Test changing rows and that OnItemsChanged works. - model_->ChangeRow(1, 1, 1); - model_->ChangeRow(2, 2, 2); - table_->OnItemsChanged(1, 2); - EXPECT_EQ("0", GetCellValue(0, 0)); - EXPECT_EQ("1", GetCellValue(1, 0)); - EXPECT_EQ("2", GetCellValue(2, 1)); - - // Test adding and removing rows and using OnModelChanged. - model_->RemoveRow(2); - model_->AddRow(2, 5, 5); - model_->AddRow(3, 6, 6); - table_->OnModelChanged(); - ASSERT_EQ(4, table_->GetRowCount()); - EXPECT_EQ("0", GetCellValue(0, 0)); - EXPECT_EQ("1", GetCellValue(1, 0)); - EXPECT_EQ("5", GetCellValue(2, 1)); - EXPECT_EQ("6", GetCellValue(3, 1)); -} - -// Test the selection on a single-selection table. -TEST_F(TableView2Test, SingleSelectionTest) { - EXPECT_EQ(0, table_->SelectedRowCount()); - EXPECT_EQ(-1, table_->GetFirstSelectedRow()); - - table_->SelectRow(0); - EXPECT_EQ(1, table_->SelectedRowCount()); - EXPECT_EQ(0, table_->GetFirstSelectedRow()); - - table_->SelectRow(2); - EXPECT_EQ(1, table_->SelectedRowCount()); - EXPECT_EQ(2, table_->GetFirstSelectedRow()); - - table_->ClearSelection(); - EXPECT_EQ(0, table_->SelectedRowCount()); - EXPECT_EQ(-1, table_->GetFirstSelectedRow()); -} - -// Row focusing are not supported on Linux yet. -#if defined(OS_WIN) -// Test the row focus on a single-selection table. -TEST_F(TableView2Test, RowFocusTest) { - EXPECT_EQ(-1, table_->GetFirstFocusedRow()); - - table_->FocusRow(0); - EXPECT_EQ(0, table_->GetFirstFocusedRow()); - - table_->FocusRow(2); - EXPECT_EQ(2, table_->GetFirstFocusedRow()); - - table_->ClearRowFocus(); - EXPECT_EQ(-1, table_->GetFirstSelectedRow()); -} -#endif - } // namespace views diff --git a/ui/views/controls/table/table_view_views.h b/ui/views/controls/table/table_view_views.h new file mode 100644 index 0000000..4a3ae5f --- /dev/null +++ b/ui/views/controls/table/table_view_views.h @@ -0,0 +1,503 @@ +// 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_ +#pragma once + +#include <map> +#include <vector> + +#include "base/gtest_prod_util.h" +#include "base/string16.h" +#include "build/build_config.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/base/models/table_model_observer.h" +#include "ui/views/views_export.h" + +#if defined(OS_WIN) +#include <windows.h> + +// TODO(port): remove the ifdef when native_control.h is ported. +#include "ui/views/controls/native_control.h" + +typedef struct tagNMLVCUSTOMDRAW NMLVCUSTOMDRAW; +#endif // defined(OS_WIN) + +namespace gfx { +class Font; +} + +namespace ui { +struct TableColumn; +class TableModel; +} + +// 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. +// +// 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 views { + +class ListView; +class ListViewParent; +class TableView; +class TableViewObserver; + +// 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, + CHECK_BOX_AND_TEXT +}; + +// Returned from SelectionBegin/SelectionEnd +class VIEWS_EXPORT TableSelectionIterator { + public: + TableSelectionIterator(TableView* view, int view_index); + TableSelectionIterator& operator=(const TableSelectionIterator& other); + bool operator==(const TableSelectionIterator& other); + bool operator!=(const TableSelectionIterator& other); + TableSelectionIterator& operator++(); + int operator*(); + + private: + void UpdateModelIndexFromViewIndex(); + + TableView* table_view_; + 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_; +}; + +#if defined(OS_WIN) +// TODO(port): Port TableView. +class VIEWS_EXPORT TableView : public NativeControl, + public ui::TableModelObserver { + public: + typedef TableSelectionIterator iterator; + + // A helper struct for GetCellColors. Set |color_is_set| to true if color is + // set. See OnCustomDraw for more details on why we need this. + struct ItemColor { + bool color_is_set; + 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). + // When autosize_columns is true, columns always fill the available width. If + // false, columns are not resized when the table is resized. An extra empty + // column at the right fills the remaining space. + // When resizable_columns is true, users can resize columns by dragging the + // separator on the column header. NOTE: Right now this is always true. The + // code to set it false is still in place to be a base for future, better + // resizing behavior (see http://b/issue?id=874646 ), but no one uses or + // tests the case where this flag is false. + // Note that setting both resizable_columns and autosize_columns to false is + // probably not a good idea, as there is no way for the user to increase a + // column's size in that case. + TableView(ui::TableModel* model, const std::vector<ui::TableColumn>& columns, + TableTypes table_type, bool single_selection, + bool resizable_columns, bool autosize_columns); + 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_; } + + // Resorts the contents. + void SetSortDescriptors(const SortDescriptors& sort_descriptors); + + // Current sort. + const SortDescriptors& sort_descriptors() const { return sort_descriptors_; } + + // Returns the number of rows in the TableView. + int RowCount() const; + + // Returns the number of selected rows. + int SelectedRowCount(); + + // Selects the specified item, making sure it's visible. + 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 model_row, bool state); + + // Sets the focus to the item at the given index. + void SetFocusOnItem(int model_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 model_row); + + // Returns true if the item at the specified index has the focus. + bool ItemHasTheFocus(int model_row); + + // Returns an iterator over the selection. The iterator proceeds from the + // 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(); + + // ui::TableModelObserver methods. + virtual void OnModelChanged(); + virtual void OnItemsChanged(int start, int length); + virtual void OnItemsAdded(int start, int length); + virtual void OnItemsRemoved(int start, int length); + + void SetObserver(TableViewObserver* observer) { + table_view_observer_ = observer; + } + TableViewObserver* observer() const { return table_view_observer_; } + + // Replaces the set of known columns without changing the current visible + // columns. + void SetColumns(const std::vector<ui::TableColumn>& columns); + void AddColumn(const ui::TableColumn& col); + bool HasColumn(int id); + + // Sets which columns (by id) are displayed. All transient size and position + // information is lost. + void SetVisibleColumns(const std::vector<int>& columns); + void SetColumnVisibility(int id, bool is_visible); + bool IsColumnVisible(int id) const; + + // Resets the size of the columns based on the sizes passed to the + // constructor. Your normally needn't invoked this, it's done for you the + // first time the TableView is given a valid size. + void ResetColumnSizes(); + + // Sometimes we may want to size the TableView to a specific width and + // height. + virtual gfx::Size GetPreferredSize(); + void SetPreferredSize(const gfx::Size& size); + + // 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 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; + + // Sets the text to display on top of the table. This is useful if the table + // is empty and you want to inform the user why. + void SetAltText(const string16& alt_text); + + protected: + // Overriden to return the position of the first selected row. + virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE; + + // 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 + // GetCellColors is never invoked. + void SetCustomColorsEnabled(bool custom_colors_enabled); + + // Notification from the ListView that the selected state of an item has + // changed. + virtual void OnSelectedStateChanged(); + + // Notification from the ListView that the used double clicked the table. + virtual void OnDoubleClick(); + + // Notification from the ListView that the user middle clicked the table. + virtual void OnMiddleClick(); + + // Overridden from NativeControl. Notifies the observer. + virtual bool OnKeyDown(ui::KeyboardCode virtual_keycode) OVERRIDE; + + // View override. + virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; + + // 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 model_row, + int column, + ItemColor* foreground, + ItemColor* background, + LOGFONT* logfont); + + // Subclasses that want to perform some custom painting (on top of the regular + // list view painting) should return true here and implement the PostPaint + // method. + virtual bool ImplementPostPaint() { return false; } + // Subclasses can implement in this method extra-painting for cells. + virtual void PostPaint(int model_row, int column, bool selected, + const gfx::Rect& bounds, HDC device_context) { } + virtual void PostPaint() {} + + virtual HWND CreateNativeControl(HWND parent_container); + + virtual LRESULT OnNotify(int w_param, LPNMHDR l_param); + + // 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() {} + + // Returns the width of the specified column by id, or -1 if the column isn't + // visible. + int GetColumnWidth(int column_id); + + // Returns the offset from the top of the client area to the start of the + // content. + int content_offset() const { return content_offset_; } + + // Draws the alt_text_. Does nothing if there is no alt_text_. + void PaintAltText(); + + // Size (width and height) of images. + static const int kImageSize; + + 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 + // subclass (in the OO sense of TableView). + struct TableViewWrapper { + explicit TableViewWrapper(TableView* view) : table_view(view) { } + TableView* table_view; + }; + + friend class ListViewParent; + friend class TableSelectionIterator; + friend class GroupModelTableViewTest; + FRIEND_TEST_ALL_PREFIXES(GroupModelTableViewTest, ShiftSelectAcrossGroups); + FRIEND_TEST_ALL_PREFIXES(GroupModelTableViewTest, ShiftSelectSameGroup); + + 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(); + + // Selects multiple items from the current view row to the marked view row + // (implements shift-click behavior). |view_index| is the most recent row + // that the user clicked on, and so there is no guarantee that + // |view_index| > |mark_view_index| or vice-versa. Returns false if the + // selection attempt was rejected because it crossed group boundaries. + bool SelectMultiple(int view_index, int mark_view_index); + + // 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 ui::TableColumn& tc, int index); + + // Update headers and internal state after columns have changed + void OnColumnsChanged(); + + // Updates the ListView with values from the model. See UpdateListViewCache0 + // for a complete description. + // This turns off redrawing, and invokes UpdateListViewCache0 to do the + // actual updating. + void UpdateListViewCache(int start, int length, bool add); + + // Updates ListView with values from the model. + // If add is true, this adds length items starting at index start. + // If add is not true, the items are not added, the but the values in the + // range start - [start + length] are updated from the model. + void UpdateListViewCache0(int start, int length, bool add); + + // 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 view index in the table view, or -1 if the table + // is empty, or nothing is selected. + // + // WARNING: this returns coordinates in terms of the view, NOT the model. + int LastSelectedViewIndex(); + + // The TableColumn visible at position pos. + const ui::TableColumn& GetColumnAtPosition(int pos); + + // Window procedure of the list view class. We subclass the list view to + // ignore WM_ERASEBKGND, which gives smoother painting during resizing. + static LRESULT CALLBACK TableWndProc(HWND window, + UINT message, + WPARAM w_param, + LPARAM l_param); + + // Window procedure of the header class. We subclass the header of the table + // to disable resizing of columns. + static LRESULT CALLBACK TableHeaderWndProc(HWND window, UINT message, + WPARAM w_param, LPARAM l_param); + + // Updates content_offset_ from the position of the header. + void UpdateContentOffset(); + + // Reloads the groups from the model if there is one and it has groups. + void UpdateGroups(); + + // Returns the bounds of the alt text. + gfx::Rect GetAltTextBounds(); + + // Returns the font used for alt text. + gfx::Font GetAltTextFont(); + + // Overriden in order to update the column sizes, which can only be sized + // accurately when the native control is available. + virtual void VisibilityChanged(View* starting_from, bool is_visible); + + ui::TableModel* model_; + TableTypes table_type_; + TableViewObserver* table_view_observer_; + + // An ordered list of id's into |all_columns_| representing current visible + // columns. + std::vector<int> visible_columns_; + + // Mapping of an int id to a TableColumn representing all possible columns. + std::map<int, ui::TableColumn> all_columns_; + + // Cached value of columns_.size() + int column_count_; + + // Selection mode. + bool single_selection_; + + // If true, any events that would normally be propagated to the observer + // are ignored. For example, if this is true and the selection changes in + // the listview, the observer is not notified. + bool ignore_listview_change_; + + // Reflects the value passed to SetCustomColorsEnabled. + bool custom_colors_enabled_; + + // Whether or not columns should automatically be resized to fill the + // the available width when the list view is resized. + bool autosize_columns_; + + // Whether or not the user can resize columns. + bool resizable_columns_; + + // Whether the column sizes have been determined. + bool column_sizes_valid_; + + // NOTE: While this has the name View in it, it's not a view. Rather it's + // a wrapper around the List-View window. + HWND list_view_; + + // The list view's header original proc handler. It is required when + // subclassing. + WNDPROC header_original_handler_; + + // Window procedure of the listview before we subclassed it. + WNDPROC original_handler_; + + // A wrapper around 'this' used when "subclassing" the list view and header. + TableViewWrapper table_view_wrapper_; + + // A custom font we use when overriding the font type for a specific cell. + HFONT custom_cell_font_; + + // The preferred size of the table view. + gfx::Size preferred_size_; + + int content_offset_; + + // Current sort. + SortDescriptors sort_descriptors_; + + // Mappings used when sorted. + scoped_array<int> view_to_model_; + scoped_array<int> model_to_view_; + + string16 alt_text_; + + DISALLOW_COPY_AND_ASSIGN(TableView); +}; +#endif // defined(OS_WIN) + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_VIEWS_H_ diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view_win.cc index 69bba6d..bb21443 100644 --- a/ui/views/controls/table/table_view.cc +++ b/ui/views/controls/table/table_view_win.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. -#include "ui/views/controls/table/table_view.h" +#include "ui/views/controls/table/table_view_win.h" #include <commctrl.h> #include <windowsx.h> diff --git a/ui/views/controls/table/table_view_win.h b/ui/views/controls/table/table_view_win.h new file mode 100644 index 0000000..b0d4076 --- /dev/null +++ b/ui/views/controls/table/table_view_win.h @@ -0,0 +1,503 @@ +// 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_WIN_H_ +#define UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_WIN_H_ +#pragma once + +#include <map> +#include <vector> + +#include "base/gtest_prod_util.h" +#include "base/string16.h" +#include "build/build_config.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/base/models/table_model_observer.h" +#include "ui/views/views_export.h" + +#if defined(OS_WIN) +#include <windows.h> + +// TODO(port): remove the ifdef when native_control.h is ported. +#include "ui/views/controls/native_control.h" + +typedef struct tagNMLVCUSTOMDRAW NMLVCUSTOMDRAW; +#endif // defined(OS_WIN) + +namespace gfx { +class Font; +} + +namespace ui { +struct TableColumn; +class TableModel; +} + +// 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. +// +// 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 views { + +class ListView; +class ListViewParent; +class TableView; +class TableViewObserver; + +// 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, + CHECK_BOX_AND_TEXT +}; + +// Returned from SelectionBegin/SelectionEnd +class VIEWS_EXPORT TableSelectionIterator { + public: + TableSelectionIterator(TableView* view, int view_index); + TableSelectionIterator& operator=(const TableSelectionIterator& other); + bool operator==(const TableSelectionIterator& other); + bool operator!=(const TableSelectionIterator& other); + TableSelectionIterator& operator++(); + int operator*(); + + private: + void UpdateModelIndexFromViewIndex(); + + TableView* table_view_; + 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_; +}; + +#if defined(OS_WIN) +// TODO(port): Port TableView. +class VIEWS_EXPORT TableView : public NativeControl, + public ui::TableModelObserver { + public: + typedef TableSelectionIterator iterator; + + // A helper struct for GetCellColors. Set |color_is_set| to true if color is + // set. See OnCustomDraw for more details on why we need this. + struct ItemColor { + bool color_is_set; + 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). + // When autosize_columns is true, columns always fill the available width. If + // false, columns are not resized when the table is resized. An extra empty + // column at the right fills the remaining space. + // When resizable_columns is true, users can resize columns by dragging the + // separator on the column header. NOTE: Right now this is always true. The + // code to set it false is still in place to be a base for future, better + // resizing behavior (see http://b/issue?id=874646 ), but no one uses or + // tests the case where this flag is false. + // Note that setting both resizable_columns and autosize_columns to false is + // probably not a good idea, as there is no way for the user to increase a + // column's size in that case. + TableView(ui::TableModel* model, const std::vector<ui::TableColumn>& columns, + TableTypes table_type, bool single_selection, + bool resizable_columns, bool autosize_columns); + 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_; } + + // Resorts the contents. + void SetSortDescriptors(const SortDescriptors& sort_descriptors); + + // Current sort. + const SortDescriptors& sort_descriptors() const { return sort_descriptors_; } + + // Returns the number of rows in the TableView. + int RowCount() const; + + // Returns the number of selected rows. + int SelectedRowCount(); + + // Selects the specified item, making sure it's visible. + 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 model_row, bool state); + + // Sets the focus to the item at the given index. + void SetFocusOnItem(int model_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 model_row); + + // Returns true if the item at the specified index has the focus. + bool ItemHasTheFocus(int model_row); + + // Returns an iterator over the selection. The iterator proceeds from the + // 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(); + + // ui::TableModelObserver methods. + virtual void OnModelChanged(); + virtual void OnItemsChanged(int start, int length); + virtual void OnItemsAdded(int start, int length); + virtual void OnItemsRemoved(int start, int length); + + void SetObserver(TableViewObserver* observer) { + table_view_observer_ = observer; + } + TableViewObserver* observer() const { return table_view_observer_; } + + // Replaces the set of known columns without changing the current visible + // columns. + void SetColumns(const std::vector<ui::TableColumn>& columns); + void AddColumn(const ui::TableColumn& col); + bool HasColumn(int id); + + // Sets which columns (by id) are displayed. All transient size and position + // information is lost. + void SetVisibleColumns(const std::vector<int>& columns); + void SetColumnVisibility(int id, bool is_visible); + bool IsColumnVisible(int id) const; + + // Resets the size of the columns based on the sizes passed to the + // constructor. Your normally needn't invoked this, it's done for you the + // first time the TableView is given a valid size. + void ResetColumnSizes(); + + // Sometimes we may want to size the TableView to a specific width and + // height. + virtual gfx::Size GetPreferredSize(); + void SetPreferredSize(const gfx::Size& size); + + // 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 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; + + // Sets the text to display on top of the table. This is useful if the table + // is empty and you want to inform the user why. + void SetAltText(const string16& alt_text); + + protected: + // Overriden to return the position of the first selected row. + virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE; + + // 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 + // GetCellColors is never invoked. + void SetCustomColorsEnabled(bool custom_colors_enabled); + + // Notification from the ListView that the selected state of an item has + // changed. + virtual void OnSelectedStateChanged(); + + // Notification from the ListView that the used double clicked the table. + virtual void OnDoubleClick(); + + // Notification from the ListView that the user middle clicked the table. + virtual void OnMiddleClick(); + + // Overridden from NativeControl. Notifies the observer. + virtual bool OnKeyDown(ui::KeyboardCode virtual_keycode) OVERRIDE; + + // View override. + virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; + + // 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 model_row, + int column, + ItemColor* foreground, + ItemColor* background, + LOGFONT* logfont); + + // Subclasses that want to perform some custom painting (on top of the regular + // list view painting) should return true here and implement the PostPaint + // method. + virtual bool ImplementPostPaint() { return false; } + // Subclasses can implement in this method extra-painting for cells. + virtual void PostPaint(int model_row, int column, bool selected, + const gfx::Rect& bounds, HDC device_context) { } + virtual void PostPaint() {} + + virtual HWND CreateNativeControl(HWND parent_container); + + virtual LRESULT OnNotify(int w_param, LPNMHDR l_param); + + // 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() {} + + // Returns the width of the specified column by id, or -1 if the column isn't + // visible. + int GetColumnWidth(int column_id); + + // Returns the offset from the top of the client area to the start of the + // content. + int content_offset() const { return content_offset_; } + + // Draws the alt_text_. Does nothing if there is no alt_text_. + void PaintAltText(); + + // Size (width and height) of images. + static const int kImageSize; + + 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 + // subclass (in the OO sense of TableView). + struct TableViewWrapper { + explicit TableViewWrapper(TableView* view) : table_view(view) { } + TableView* table_view; + }; + + friend class ListViewParent; + friend class TableSelectionIterator; + friend class GroupModelTableViewTest; + FRIEND_TEST_ALL_PREFIXES(GroupModelTableViewTest, ShiftSelectAcrossGroups); + FRIEND_TEST_ALL_PREFIXES(GroupModelTableViewTest, ShiftSelectSameGroup); + + 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(); + + // Selects multiple items from the current view row to the marked view row + // (implements shift-click behavior). |view_index| is the most recent row + // that the user clicked on, and so there is no guarantee that + // |view_index| > |mark_view_index| or vice-versa. Returns false if the + // selection attempt was rejected because it crossed group boundaries. + bool SelectMultiple(int view_index, int mark_view_index); + + // 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 ui::TableColumn& tc, int index); + + // Update headers and internal state after columns have changed + void OnColumnsChanged(); + + // Updates the ListView with values from the model. See UpdateListViewCache0 + // for a complete description. + // This turns off redrawing, and invokes UpdateListViewCache0 to do the + // actual updating. + void UpdateListViewCache(int start, int length, bool add); + + // Updates ListView with values from the model. + // If add is true, this adds length items starting at index start. + // If add is not true, the items are not added, the but the values in the + // range start - [start + length] are updated from the model. + void UpdateListViewCache0(int start, int length, bool add); + + // 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 view index in the table view, or -1 if the table + // is empty, or nothing is selected. + // + // WARNING: this returns coordinates in terms of the view, NOT the model. + int LastSelectedViewIndex(); + + // The TableColumn visible at position pos. + const ui::TableColumn& GetColumnAtPosition(int pos); + + // Window procedure of the list view class. We subclass the list view to + // ignore WM_ERASEBKGND, which gives smoother painting during resizing. + static LRESULT CALLBACK TableWndProc(HWND window, + UINT message, + WPARAM w_param, + LPARAM l_param); + + // Window procedure of the header class. We subclass the header of the table + // to disable resizing of columns. + static LRESULT CALLBACK TableHeaderWndProc(HWND window, UINT message, + WPARAM w_param, LPARAM l_param); + + // Updates content_offset_ from the position of the header. + void UpdateContentOffset(); + + // Reloads the groups from the model if there is one and it has groups. + void UpdateGroups(); + + // Returns the bounds of the alt text. + gfx::Rect GetAltTextBounds(); + + // Returns the font used for alt text. + gfx::Font GetAltTextFont(); + + // Overriden in order to update the column sizes, which can only be sized + // accurately when the native control is available. + virtual void VisibilityChanged(View* starting_from, bool is_visible); + + ui::TableModel* model_; + TableTypes table_type_; + TableViewObserver* table_view_observer_; + + // An ordered list of id's into |all_columns_| representing current visible + // columns. + std::vector<int> visible_columns_; + + // Mapping of an int id to a TableColumn representing all possible columns. + std::map<int, ui::TableColumn> all_columns_; + + // Cached value of columns_.size() + int column_count_; + + // Selection mode. + bool single_selection_; + + // If true, any events that would normally be propagated to the observer + // are ignored. For example, if this is true and the selection changes in + // the listview, the observer is not notified. + bool ignore_listview_change_; + + // Reflects the value passed to SetCustomColorsEnabled. + bool custom_colors_enabled_; + + // Whether or not columns should automatically be resized to fill the + // the available width when the list view is resized. + bool autosize_columns_; + + // Whether or not the user can resize columns. + bool resizable_columns_; + + // Whether the column sizes have been determined. + bool column_sizes_valid_; + + // NOTE: While this has the name View in it, it's not a view. Rather it's + // a wrapper around the List-View window. + HWND list_view_; + + // The list view's header original proc handler. It is required when + // subclassing. + WNDPROC header_original_handler_; + + // Window procedure of the listview before we subclassed it. + WNDPROC original_handler_; + + // A wrapper around 'this' used when "subclassing" the list view and header. + TableViewWrapper table_view_wrapper_; + + // A custom font we use when overriding the font type for a specific cell. + HFONT custom_cell_font_; + + // The preferred size of the table view. + gfx::Size preferred_size_; + + int content_offset_; + + // Current sort. + SortDescriptors sort_descriptors_; + + // Mappings used when sorted. + scoped_array<int> view_to_model_; + scoped_array<int> model_to_view_; + + string16 alt_text_; + + DISALLOW_COPY_AND_ASSIGN(TableView); +}; +#endif // defined(OS_WIN) + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_WIN_H_ diff --git a/ui/views/examples/examples_window.cc b/ui/views/examples/examples_window.cc index a60baa6..835ae1f 100644 --- a/ui/views/examples/examples_window.cc +++ b/ui/views/examples/examples_window.cc @@ -39,7 +39,6 @@ #if !defined(USE_AURA) #include "ui/views/examples/menu_example.h" -#include "ui/views/examples/table2_example.h" #if defined(OS_WIN) #include "ui/views/examples/table_example.h" #endif @@ -128,12 +127,9 @@ class ExamplesWindowContents : public views::WidgetDelegateView { AddExample(new ScrollViewExample); AddExample(new SingleSplitViewExample); AddExample(new TabbedPaneExample); -#if !defined(USE_AURA) -#if defined(OS_WIN) +#if !defined(USE_AURA) && defined(OS_WIN) AddExample(new TableExample); #endif - AddExample(new Table2Example); -#endif AddExample(new TextExample); AddExample(new TextfieldExample); AddExample(new ThrobberExample); diff --git a/ui/views/examples/table2_example.cc b/ui/views/examples/table2_example.cc deleted file mode 100644 index 0e57272..0000000 --- a/ui/views/examples/table2_example.cc +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2011 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. - -#include "ui/views/examples/table2_example.h" - -#include "base/utf_string_conversions.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "ui/views/controls/button/checkbox.h" -#include "ui/views/controls/table/table_view2.h" -#include "ui/views/layout/grid_layout.h" - -namespace views { -namespace examples { - -Table2Example::Table2Example() : ExampleBase("Table2") { -} - -Table2Example::~Table2Example() { -} - -void Table2Example::CreateExampleView(View* container) { - column1_visible_checkbox_ = new Checkbox( - ASCIIToUTF16("Fruit column visible")); - column1_visible_checkbox_->SetChecked(true); - column1_visible_checkbox_->set_listener(this); - column2_visible_checkbox_ = new Checkbox( - ASCIIToUTF16("Color column visible")); - column2_visible_checkbox_->SetChecked(true); - column2_visible_checkbox_->set_listener(this); - column3_visible_checkbox_ = new Checkbox( - ASCIIToUTF16("Origin column visible")); - column3_visible_checkbox_->SetChecked(true); - column3_visible_checkbox_->set_listener(this); - column4_visible_checkbox_ = new Checkbox( - ASCIIToUTF16("Price column visible")); - column4_visible_checkbox_->SetChecked(true); - column4_visible_checkbox_->set_listener(this); - - GridLayout* layout = new GridLayout(container); - container->SetLayoutManager(layout); - - std::vector<ui::TableColumn> columns; - columns.push_back( - ui::TableColumn(0, ASCIIToUTF16("Fruit"), ui::TableColumn::LEFT, 100)); - columns.push_back( - ui::TableColumn(1, ASCIIToUTF16("Color"), ui::TableColumn::LEFT, 100)); - columns.push_back( - ui::TableColumn(2, ASCIIToUTF16("Origin"), ui::TableColumn::LEFT, 100)); - columns.push_back( - ui::TableColumn(3, ASCIIToUTF16("Price"), ui::TableColumn::LEFT, 100)); - const int options = (TableView2::SINGLE_SELECTION | - TableView2::RESIZABLE_COLUMNS | - TableView2::AUTOSIZE_COLUMNS | - TableView2::HORIZONTAL_LINES | - TableView2::VERTICAL_LINES); - table_ = new TableView2(this, columns, ICON_AND_TEXT, options); - table_->SetObserver(this); - icon1_.setConfig(SkBitmap::kARGB_8888_Config, 16, 16); - icon1_.allocPixels(); - SkCanvas canvas1(icon1_); - canvas1.drawColor(SK_ColorRED); - - icon2_.setConfig(SkBitmap::kARGB_8888_Config, 16, 16); - icon2_.allocPixels(); - SkCanvas canvas2(icon2_); - canvas2.drawColor(SK_ColorBLUE); - - ColumnSet* column_set = layout->AddColumnSet(0); - column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, - GridLayout::USE_PREF, 0, 0); - layout->StartRow(1 /* expand */, 0); - layout->AddView(table_); - - column_set = layout->AddColumnSet(1); - column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, - 0.5f, GridLayout::USE_PREF, 0, 0); - column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, - 0.5f, GridLayout::USE_PREF, 0, 0); - column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, - 0.5f, GridLayout::USE_PREF, 0, 0); - column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, - 0.5f, GridLayout::USE_PREF, 0, 0); - - layout->StartRow(0 /* no expand */, 1); - - layout->AddView(column1_visible_checkbox_); - layout->AddView(column2_visible_checkbox_); - layout->AddView(column3_visible_checkbox_); - layout->AddView(column4_visible_checkbox_); -} - -int Table2Example::RowCount() { - return 10; -} - -string16 Table2Example::GetText(int row, int column_id) { - const char* const cells[5][4] = { - { "Orange", "Orange", "South america", "$5" }, - { "Apple", "Green", "Canada", "$3" }, - { "Blue berries", "Blue", "Mexico", "$10.3" }, - { "Strawberries", "Red", "California", "$7" }, - { "Cantaloupe", "Orange", "South america", "$5" } - }; - return ASCIIToUTF16(cells[row % 5][column_id]); -} - -SkBitmap Table2Example::GetIcon(int row) { - return row % 2 ? icon1_ : icon2_; -} - -void Table2Example::SetObserver(ui::TableModelObserver* observer) { -} - -void Table2Example::ButtonPressed(Button* sender, const Event& event) { - int index = 0; - bool show = true; - if (sender == column1_visible_checkbox_) { - index = 0; - show = column1_visible_checkbox_->checked(); - } else if (sender == column2_visible_checkbox_) { - index = 1; - show = column2_visible_checkbox_->checked(); - } else if (sender == column3_visible_checkbox_) { - index = 2; - show = column3_visible_checkbox_->checked(); - } else if (sender == column4_visible_checkbox_) { - index = 3; - show = column4_visible_checkbox_->checked(); - } - table_->SetColumnVisibility(index, show); -} - -void Table2Example::OnSelectionChanged() { - PrintStatus("Selection changed: %d", table_->GetFirstSelectedRow()); -} - -void Table2Example::OnDoubleClick() { -} - -void Table2Example::OnMiddleClick() { -} - -void Table2Example::OnKeyDown(ui::KeyboardCode virtual_keycode) { -} - -void Table2Example::OnTableViewDelete(TableView* table_view) { -} - -void Table2Example::OnTableView2Delete(TableView2* table_view) { -} - -} // namespace examples -} // namespace views diff --git a/ui/views/examples/table2_example.h b/ui/views/examples/table2_example.h deleted file mode 100644 index 923f49a..0000000 --- a/ui/views/examples/table2_example.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2011 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_EXAMPLES_TABLE2_EXAMPLE_H_ -#define UI_VIEWS_EXAMPLES_TABLE2_EXAMPLE_H_ -#pragma once - -#include <string> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/models/table_model.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/controls/table/table_view_observer.h" -#include "ui/views/examples/example_base.h" - -namespace views { -class Checkbox; -class Event; -class TableView2; - -namespace examples { - -class Table2Example : public ExampleBase, - public ui::TableModel, - public ButtonListener, - public TableViewObserver { - public: - Table2Example(); - virtual ~Table2Example(); - - // Overridden from ExampleBase: - virtual void CreateExampleView(View* container) OVERRIDE; - - // Overridden from TableModel: - virtual int RowCount() OVERRIDE; - virtual string16 GetText(int row, int column_id) OVERRIDE; - virtual SkBitmap GetIcon(int row) OVERRIDE; - virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE; - - // Overridden from ButtonListener: - virtual void ButtonPressed(Button* sender, const Event& event) OVERRIDE; - - // Overridden from TableViewObserver: - virtual void OnSelectionChanged() OVERRIDE; - virtual void OnDoubleClick() OVERRIDE; - virtual void OnMiddleClick() OVERRIDE; - virtual void OnKeyDown(ui::KeyboardCode virtual_keycode) OVERRIDE; - virtual void OnTableViewDelete(TableView* table_view) OVERRIDE; - virtual void OnTableView2Delete(TableView2* table_view) OVERRIDE; - - private: - // The table to be tested. - TableView2* table_; - - Checkbox* column1_visible_checkbox_; - Checkbox* column2_visible_checkbox_; - Checkbox* column3_visible_checkbox_; - Checkbox* column4_visible_checkbox_; - - SkBitmap icon1_; - SkBitmap icon2_; - - DISALLOW_COPY_AND_ASSIGN(Table2Example); -}; - -} // namespace examples -} // namespace views - -#endif // UI_VIEWS_EXAMPLES_TABLE2_EXAMPLE_H_ diff --git a/ui/views/views.gyp b/ui/views/views.gyp index bab5410..8fa0304 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -205,18 +205,14 @@ 'controls/tabbed_pane/tabbed_pane.cc', 'controls/tabbed_pane/tabbed_pane.h', 'controls/tabbed_pane/tabbed_pane_listener.h', - 'controls/table/native_table_wrapper.h', - 'controls/table/native_table_gtk.cc', - 'controls/table/native_table_gtk.h', - 'controls/table/native_table_win.cc', - 'controls/table/native_table_win.h', - 'controls/table/group_table_view.cc', + 'controls/table/group_table_model.h', 'controls/table/group_table_view.h', - 'controls/table/table_view.cc', + 'controls/table/group_table_view_win.cc', + 'controls/table/group_table_view_win.h', 'controls/table/table_view.h', - 'controls/table/table_view2.cc', - 'controls/table/table_view2.h', 'controls/table/table_view_observer.h', + 'controls/table/table_view_win.cc', + 'controls/table/table_view_win.h', 'controls/textfield/gtk_views_entry.cc', 'controls/textfield/gtk_views_entry.h', 'controls/textfield/gtk_views_textview.cc', @@ -399,13 +395,9 @@ 'controls/native_control.h', 'controls/scrollbar/bitmap_scroll_bar.cc', 'controls/scrollbar/bitmap_scroll_bar.h', + 'controls/table/group_table_model.h', 'controls/table/group_table_view.cc', 'controls/table/group_table_view.h', - 'controls/table/native_table_wrapper.h', - 'controls/table/table_view.cc', - 'controls/table/table_view.h', - 'controls/table/table_view2.cc', - 'controls/table/table_view2.h', 'controls/table/table_view_observer.h', 'drag_utils_win.cc', 'widget/aero_tooltip_manager.cc', @@ -424,8 +416,7 @@ 'accessibility/native_view_accessibility_win.cc', 'controls/native_control.cc', 'controls/scrollbar/bitmap_scroll_bar.cc', - 'controls/table/group_table_view.cc', - 'controls/table/table_view.cc', + 'controls/table/group_table_model.cc', 'controls/tree/tree_view.h', 'events/event_win.cc', 'widget/aero_tooltip_manager.cc', @@ -652,8 +643,6 @@ 'examples/tabbed_pane_example.h', 'examples/table_example.cc', 'examples/table_example.h', - 'examples/table2_example.cc', - 'examples/table2_example.h', 'examples/text_example.cc', 'examples/text_example.h', 'examples/textfield_example.cc', @@ -680,8 +669,6 @@ 'sources/': [ ['exclude', 'examples/table_example.cc'], ['exclude', 'examples/table_example.h'], - ['exclude', 'examples/table2_example.cc'], - ['exclude', 'examples/table2_example.h'], ], }], ], |