summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-01 01:06:12 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-01 01:06:12 +0000
commit0b2fa2b16961888c0936290b58435937de938b42 (patch)
treecfbd5b88232a447517c5cc1fa8eab810dc6f0a49 /views
parent78cc12bfd89dbabb585fc658b508ff90de3ff473 (diff)
downloadchromium_src-0b2fa2b16961888c0936290b58435937de938b42.zip
chromium_src-0b2fa2b16961888c0936290b58435937de938b42.tar.gz
chromium_src-0b2fa2b16961888c0936290b58435937de938b42.tar.bz2
Porting the table view to Linux toolkit views.
It is the initial implementation, it is still missing: - row focusing - resizable columns - autosize columns BUG=None TEST=Run the unit-tests, play with the TableView2 tab in the view examples. Review URL: http://codereview.chromium.org/434066 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33400 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/controls/table/native_table_gtk.cc318
-rw-r--r--views/controls/table/native_table_gtk.h84
-rw-r--r--views/controls/table/native_table_win.cc16
-rw-r--r--views/controls/table/native_table_win.h16
-rw-r--r--views/controls/table/native_table_wrapper.h16
-rw-r--r--views/controls/table/table_view_unittest.cc38
-rw-r--r--views/examples/examples_main.cc5
-rw-r--r--views/examples/table2_example.h1
-rw-r--r--views/view.cc2
-rw-r--r--views/views.gyp2
10 files changed, 465 insertions, 33 deletions
diff --git a/views/controls/table/native_table_gtk.cc b/views/controls/table/native_table_gtk.cc
new file mode 100644
index 0000000..ebacb22
--- /dev/null
+++ b/views/controls/table/native_table_gtk.cc
@@ -0,0 +1,318 @@
+// Copyright (c) 2009 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 "views/controls/table/native_table_gtk.h"
+
+#include "app/gfx/gtk_util.h"
+#include "base/string_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "views/controls/table/table_view2.h"
+#include "views/controls/table/table_view_observer.h"
+#include "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.
+ Focus();
+}
+
+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 TableColumn& column, int index) {
+ NOTIMPLEMENTED();
+}
+
+void NativeTableGtk::RemoveColumn(int index) {
+ NOTIMPLEMENTED();
+}
+
+int NativeTableGtk::GetColumnWidth(int column_index) const {
+ NOTIMPLEMENTED();
+ return -1;
+}
+
+void NativeTableGtk::SetColumnWidth(int column_index, int width) {
+ NOTIMPLEMENTED();
+}
+
+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());
+ // 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 horizontal separator lines only.
+ gtk_tree_view_set_grid_lines(tree_view_, GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
+
+ 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());
+}
+
+void NativeTableGtk::InsertTextColumn(const TableColumn& column, int index) {
+ GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(tree_view_, -1,
+ WideToUTF8(column.title).c_str(),
+ renderer, "text", index, NULL);
+}
+
+void NativeTableGtk::InsertIconAndTextColumn(const 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(index == 0) << "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, WideToUTF8(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 =
+ WideToUTF8(table_->model()->GetText(row_index,
+ table_->GetVisibleColumnAt(i).id));
+ gtk_list_store_set(gtk_model_, iter, gtk_column_index, text.c_str(), -1);
+ }
+}
+
+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/views/controls/table/native_table_gtk.h b/views/controls/table/native_table_gtk.h
new file mode 100644
index 0000000..aa18f50
--- /dev/null
+++ b/views/controls/table/native_table_gtk.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2009 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 VIEWS_CONTROLS_TABLE_NATIVE_TABLE_GTK_H_
+#define VIEWS_CONTROLS_TABLE_NATIVE_TABLE_GTK_H_
+
+#include "app/table_model.h"
+#include "views/controls/native_control_gtk.h"
+#include "views/controls/table/native_table_wrapper.h"
+
+namespace views {
+
+class TableView2;
+
+// A View that hosts a native GTK table.
+// 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;
+ virtual View* GetView();
+ virtual void SetFocus();
+ virtual gfx::NativeView GetTestingHandle() const;
+ virtual void InsertColumn(const 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;
+
+ protected:
+ // NativeControlGtk implementation:
+ virtual void CreateNativeControl();
+
+ private:
+ void InsertTextColumn(const TableColumn& column, int index);
+ void InsertIconAndTextColumn(const 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);
+
+ // 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 // VIEWS_CONTROLS_TABLE_NATIVE_TABLE_GTK_H_
diff --git a/views/controls/table/native_table_win.cc b/views/controls/table/native_table_win.cc
index a7564d6..2bf96f3 100644
--- a/views/controls/table/native_table_win.cc
+++ b/views/controls/table/native_table_win.cc
@@ -51,7 +51,7 @@ NativeTableWin::~NativeTableWin() {
////////////////////////////////////////////////////////////////////////////////
// NativeTableWin, NativeTableWrapper implementation:
-int NativeTableWin::GetRowCount() {
+int NativeTableWin::GetRowCount() const {
if (!native_view())
return 0;
return ListView_GetItemCount(native_view());
@@ -109,7 +109,7 @@ gfx::NativeView NativeTableWin::GetTestingHandle() const {
return native_view();
}
-int NativeTableWin::GetColumnWidth(int column_index) {
+int NativeTableWin::GetColumnWidth(int column_index) const {
if (!native_view())
return 0;
return ListView_GetColumnWidth(native_view(), column_index);
@@ -121,19 +121,19 @@ void NativeTableWin::SetColumnWidth(int column_index, int width) {
ListView_SetColumnWidth(native_view(), column_index, width);
}
-int NativeTableWin::GetSelectedRowCount() {
+int NativeTableWin::GetSelectedRowCount() const {
if (!native_view())
return 0;
return ListView_GetSelectedCount(native_view());
}
-int NativeTableWin::GetFirstSelectedRow() {
+int NativeTableWin::GetFirstSelectedRow() const {
if (!native_view())
return -1;
return ListView_GetNextItem(native_view(), -1, LVNI_ALL | LVIS_SELECTED);
}
-int NativeTableWin::GetFirstFocusedRow() {
+int NativeTableWin::GetFirstFocusedRow() const {
if (!native_view())
return -1;
return ListView_GetNextItem(native_view(), -1, LVNI_ALL | LVIS_FOCUSED);
@@ -168,14 +168,14 @@ void NativeTableWin::SetFocusState(int model_row, bool state) {
state ? LVIS_FOCUSED : 0, LVIS_FOCUSED)
}
-bool NativeTableWin::IsRowSelected(int model_row) {
+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) {
+bool NativeTableWin::IsRowFocused(int model_row) const {
if (!native_view())
return false;
return ListView_GetItemState(native_view(), model_row, LVIS_FOCUSED) ==
@@ -231,7 +231,7 @@ void NativeTableWin::OnRowsRemoved(int start, int length) {
}
}
-gfx::Rect NativeTableWin::GetBounds() {
+gfx::Rect NativeTableWin::GetBounds() const {
RECT native_bounds;
if (!native_view() || GetClientRect(native_view(), &native_bounds))
return gfx::Rect();
diff --git a/views/controls/table/native_table_win.h b/views/controls/table/native_table_win.h
index 6b6c8ef..2725bb2 100644
--- a/views/controls/table/native_table_win.h
+++ b/views/controls/table/native_table_win.h
@@ -24,27 +24,27 @@ class NativeTableWin : public NativeControlWin, public NativeTableWrapper {
virtual ~NativeTableWin();
// NativeTableWrapper implementation:
- virtual int GetRowCount();
+ virtual int GetRowCount() const;
virtual View* GetView();
virtual void SetFocus();
virtual gfx::NativeView GetTestingHandle() const;
virtual void InsertColumn(const TableColumn& column, int index);
virtual void RemoveColumn(int index);
- virtual int GetColumnWidth(int column_index);
+ virtual int GetColumnWidth(int column_index) const;
virtual void SetColumnWidth(int column_index, int width);
- virtual int GetSelectedRowCount();
- virtual int GetFirstSelectedRow();
- virtual int GetFirstFocusedRow();
+ 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);
- virtual bool IsRowFocused(int model_row);
+ 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();
+ virtual gfx::Rect GetBounds() const;
// Overridden from View:
virtual gfx::Size GetPreferredSize();
diff --git a/views/controls/table/native_table_wrapper.h b/views/controls/table/native_table_wrapper.h
index 5f635e5..a4a6cbf 100644
--- a/views/controls/table/native_table_wrapper.h
+++ b/views/controls/table/native_table_wrapper.h
@@ -17,18 +17,18 @@ class View;
class NativeTableWrapper {
public:
// Returns the number of rows in the table.
- virtual int GetRowCount() = 0;
+ virtual int GetRowCount() const = 0;
// Inserts/removes a column at the specified index.
virtual void InsertColumn(const TableColumn& column, int index) = 0;
virtual void RemoveColumn(int index) = 0;
// Returns the number of rows that are selected.
- virtual int GetSelectedRowCount() = 0;
+ virtual int GetSelectedRowCount() const = 0;
// Returns the first row that is selected/focused in terms of the model.
- virtual int GetFirstSelectedRow() = 0;
- virtual int GetFirstFocusedRow() = 0;
+ virtual int GetFirstSelectedRow() const = 0;
+ virtual int GetFirstFocusedRow() const = 0;
// Unselect all rows.
virtual void ClearSelection() = 0;
@@ -40,10 +40,10 @@ class NativeTableWrapper {
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) = 0;
+ 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) = 0;
+ virtual bool IsRowFocused(int model_row) const = 0;
// Retrieves the views::View that hosts the native control.
virtual View* GetView() = 0;
@@ -55,7 +55,7 @@ class NativeTableWrapper {
virtual gfx::NativeView GetTestingHandle() const = 0;
// Gets/sets the columns width.
- virtual int GetColumnWidth(int column_index) = 0;
+ 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
@@ -65,7 +65,7 @@ class NativeTableWrapper {
virtual void OnRowsRemoved(int start, int length) = 0;
// Returns the bounds of the native table.
- virtual gfx::Rect GetBounds() = 0;
+ virtual gfx::Rect GetBounds() const = 0;
// Creates an appropriate NativeButtonWrapper for the platform.
static NativeTableWrapper* CreateNativeWrapper(TableView2* table);
diff --git a/views/controls/table/table_view_unittest.cc b/views/controls/table/table_view_unittest.cc
index 7ced10c..761ae02 100644
--- a/views/controls/table/table_view_unittest.cc
+++ b/views/controls/table/table_view_unittest.cc
@@ -12,7 +12,11 @@
#include "views/controls/table/table_view.h"
#include "views/controls/table/table_view2.h"
#include "views/window/window_delegate.h"
+#if defined(OS_WIN)
#include "views/window/window_win.h"
+#else
+#include "views/window/window_gtk.h"
+#endif
using views::TableView;
@@ -59,7 +63,7 @@ class TestTableModel : public TableModel {
TableModelObserver* observer_;
// The data.
- std::vector<std::vector<int>> rows_;
+ std::vector<std::vector<int> > rows_;
DISALLOW_COPY_AND_ASSIGN(TestTableModel);
};
@@ -120,6 +124,8 @@ void TestTableModel::SetChecked(int row, bool is_checked) {
check_notifications_.push_back(check_notification);
}
+#if defined(OS_WIN)
+
// TableViewTest ---------------------------------------------------------------
class TableViewTest : public testing::Test, views::WindowDelegate {
@@ -402,6 +408,8 @@ TEST_F(NullModelTableViewTest, NullModel) {
// to a NULL model we'll crash.
}
+#endif // OS_WIN
+
////////////////////////////////////////////////////////////////////////////////
// TableView2 Tests
@@ -436,7 +444,9 @@ class TableView2Test : public testing::Test, views::WindowDelegate {
};
void TableView2Test::SetUp() {
+#if defined(OS_WIN)
OleInitialize(NULL);
+#endif
model_.reset(CreateModel());
std::vector<TableColumn> columns;
columns.resize(2);
@@ -454,7 +464,9 @@ 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() {
@@ -474,13 +486,24 @@ std::wstring TableView2Test::GetCellValue(int row, int column) {
DCHECK(r);
return std::wstring(str);
#else
- NOTIMPLEMENTED();
+ 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::wstring str(UTF8ToWide(text));
+ g_free(text);
+ return str;
#endif
}
// Tests that the table correctly reflects changes to the model.
TEST_F(TableView2Test, ModelChangesTest) {
- EXPECT_EQ(3, table_->GetRowCount());
+ ASSERT_EQ(3, table_->GetRowCount());
EXPECT_EQ(L"0", GetCellValue(0, 0));
EXPECT_EQ(L"1", GetCellValue(1, 0));
EXPECT_EQ(L"2", GetCellValue(2, 1));
@@ -489,7 +512,7 @@ TEST_F(TableView2Test, ModelChangesTest) {
model_->AddRow(3, 3, 3);
model_->AddRow(4, 4, 4);
table_->OnItemsAdded(3, 2);
- EXPECT_EQ(5, table_->GetRowCount());
+ ASSERT_EQ(5, table_->GetRowCount());
EXPECT_EQ(L"3", GetCellValue(3, 0));
EXPECT_EQ(L"4", GetCellValue(4, 1));
@@ -497,7 +520,7 @@ TEST_F(TableView2Test, ModelChangesTest) {
model_->RemoveRow(1);
model_->RemoveRow(1);
table_->OnItemsRemoved(1, 2);
- EXPECT_EQ(3, table_->GetRowCount());
+ ASSERT_EQ(3, table_->GetRowCount());
EXPECT_EQ(L"0", GetCellValue(0, 0));
EXPECT_EQ(L"3", GetCellValue(1, 0));
EXPECT_EQ(L"4", GetCellValue(2, 1));
@@ -515,7 +538,7 @@ TEST_F(TableView2Test, ModelChangesTest) {
model_->AddRow(2, 5, 5);
model_->AddRow(3, 6, 6);
table_->OnModelChanged();
- EXPECT_EQ(4, table_->GetRowCount());
+ ASSERT_EQ(4, table_->GetRowCount());
EXPECT_EQ(L"0", GetCellValue(0, 0));
EXPECT_EQ(L"1", GetCellValue(1, 0));
EXPECT_EQ(L"5", GetCellValue(2, 1));
@@ -540,6 +563,8 @@ TEST_F(TableView2Test, SingleSelectionTest) {
EXPECT_EQ(-1, table_->GetFirstSelectedRow());
}
+// Row focusing and checkbox cell 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());
@@ -588,3 +613,4 @@ TEST_F(CheckTableView2Test, TestCheckTable) {
EXPECT_EQ(0, model_->check_notifications_[2].row);
EXPECT_FALSE(model_->check_notifications_[2].state);
}
+#endif
diff --git a/views/examples/examples_main.cc b/views/examples/examples_main.cc
index badef5c..5aa3279 100644
--- a/views/examples/examples_main.cc
+++ b/views/examples/examples_main.cc
@@ -20,8 +20,8 @@
#if defined(OS_WIN)
// TableView and TableView2 are not yet ported to Linux.
#include "views/examples/table_example.h"
-#include "views/examples/table2_example.h"
#endif
+#include "views/examples/table2_example.h"
#include "views/examples/textfield_example.h"
#include "views/examples/widget_example.h"
#include "views/focus/accelerator_handler.h"
@@ -110,15 +110,14 @@ void ExamplesMain::Run() {
scroll_view_example.GetExampleView());
#if defined(OS_WIN)
- // TableView and TableView2 are not yet ported to Linux.
examples::TableExample table_example(this);
tabbed_pane->AddTab(table_example.GetExampleTitle(),
table_example.GetExampleView());
+#endif
examples::Table2Example table2_example(this);
tabbed_pane->AddTab(table2_example.GetExampleTitle(),
table2_example.GetExampleView());
-#endif
examples::WidgetExample widget_example(this);
tabbed_pane->AddTab(widget_example.GetExampleTitle(),
diff --git a/views/examples/table2_example.h b/views/examples/table2_example.h
index fc8f900..475faf6 100644
--- a/views/examples/table2_example.h
+++ b/views/examples/table2_example.h
@@ -11,6 +11,7 @@
#include "base/string_util.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "views/controls/button/checkbox.h"
+#include "views/controls/table/table_view_observer.h"
#include "views/controls/table/table_view2.h"
#include "views/examples/example_base.h"
diff --git a/views/view.cc b/views/view.cc
index f4869ec..a8de837 100644
--- a/views/view.cc
+++ b/views/view.cc
@@ -518,6 +518,8 @@ void View::AddChildView(View* v) {
}
void View::AddChildView(int index, View* v) {
+ CHECK(v != this) << "You cannot add a view as its own child";
+
// Remove the view from its current parent if any.
if (v->GetParent())
v->GetParent()->RemoveChildView(v);
diff --git a/views/views.gyp b/views/views.gyp
index 93f551d..5184423 100644
--- a/views/views.gyp
+++ b/views/views.gyp
@@ -183,6 +183,8 @@
'controls/tabbed_pane/native_tabbed_pane_win.h',
'controls/tabbed_pane/native_tabbed_pane_wrapper.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',