diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-01 01:06:12 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-01 01:06:12 +0000 |
commit | 0b2fa2b16961888c0936290b58435937de938b42 (patch) | |
tree | cfbd5b88232a447517c5cc1fa8eab810dc6f0a49 /views | |
parent | 78cc12bfd89dbabb585fc658b508ff90de3ff473 (diff) | |
download | chromium_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.cc | 318 | ||||
-rw-r--r-- | views/controls/table/native_table_gtk.h | 84 | ||||
-rw-r--r-- | views/controls/table/native_table_win.cc | 16 | ||||
-rw-r--r-- | views/controls/table/native_table_win.h | 16 | ||||
-rw-r--r-- | views/controls/table/native_table_wrapper.h | 16 | ||||
-rw-r--r-- | views/controls/table/table_view_unittest.cc | 38 | ||||
-rw-r--r-- | views/examples/examples_main.cc | 5 | ||||
-rw-r--r-- | views/examples/table2_example.h | 1 | ||||
-rw-r--r-- | views/view.cc | 2 | ||||
-rw-r--r-- | views/views.gyp | 2 |
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', |