summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-10 23:21:15 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-10 23:21:15 +0000
commit7ea8d057c10b5ebf3fb28a1caa8af3ffc83e3cd6 (patch)
tree8a02fa5e51ea30b0089ce422447d7d52aea2ba85 /ui
parenteaa406bbd5e2c92c307f1895befc00bb9c3386f4 (diff)
downloadchromium_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')
-rw-r--r--ui/views/controls/table/group_table_model.h28
-rw-r--r--ui/views/controls/table/group_table_view.h82
-rw-r--r--ui/views/controls/table/group_table_view_views.h76
-rw-r--r--ui/views/controls/table/group_table_view_win.cc (renamed from ui/views/controls/table/group_table_view.cc)5
-rw-r--r--ui/views/controls/table/group_table_view_win.h76
-rw-r--r--ui/views/controls/table/native_table_gtk.cc371
-rw-r--r--ui/views/controls/table/native_table_gtk.h91
-rw-r--r--ui/views/controls/table/native_table_win.cc913
-rw-r--r--ui/views/controls/table/native_table_win.h127
-rw-r--r--ui/views/controls/table/native_table_wrapper.h85
-rw-r--r--ui/views/controls/table/table_view.h496
-rw-r--r--ui/views/controls/table/table_view2.cc334
-rw-r--r--ui/views/controls/table/table_view2.h268
-rw-r--r--ui/views/controls/table/table_view_unittest.cc177
-rw-r--r--ui/views/controls/table/table_view_views.h503
-rw-r--r--ui/views/controls/table/table_view_win.cc (renamed from ui/views/controls/table/table_view.cc)4
-rw-r--r--ui/views/controls/table/table_view_win.h503
-rw-r--r--ui/views/examples/examples_window.cc6
-rw-r--r--ui/views/examples/table2_example.cc154
-rw-r--r--ui/views/examples/table2_example.h72
-rw-r--r--ui/views/views.gyp27
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'],
],
}],
],