Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: ui/views/controls/table/table_view_unittest.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/controls/table/table_view.h"
6
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/views/controls/table/table_grouper.h"
11 #include "ui/views/controls/table/table_header.h"
12 #include "ui/views/controls/table/table_view_observer.h"
13
14 // Put the tests in the views namespace to make it easier to declare them as
15 // friend classes.
16 namespace views {
17
18 class TableViewTestHelper {
19 public:
20 explicit TableViewTestHelper(TableView* table) : table_(table) {}
21
22 std::string GetPaintRegion(const gfx::Rect& bounds) {
23 TableView::PaintRegion region(table_->GetPaintRegion(bounds));
24 return "rows=" + base::IntToString(region.min_row) + " " +
25 base::IntToString(region.max_row) + " cols=" +
26 base::IntToString(region.min_column) + " " +
27 base::IntToString(region.max_column);
28 }
29
30 size_t visible_col_count() {
31 return table_->visible_columns().size();
32 }
33
34 TableHeader* header() { return table_->header_; }
35
36 private:
37 TableView* table_;
38
39 DISALLOW_COPY_AND_ASSIGN(TableViewTestHelper);
40 };
41
42 namespace {
43
44 // TestTableModel2 -------------------------------------------------------------
45
46 // Trivial TableModel implementation that is backed by a vector of vectors.
47 // Provides methods for adding/removing/changing the contents that notify the
48 // observer appropriately.
49 //
50 // Initial contents are:
51 // 0, 1
52 // 1, 1
53 // 2, 2
54 // 3, 0
55 class TestTableModel2 : public ui::TableModel {
56 public:
57 TestTableModel2();
58
59 // Adds a new row at index |row| with values |c1_value| and |c2_value|.
60 void AddRow(int row, int c1_value, int c2_value);
61
62 // Removes the row at index |row|.
63 void RemoveRow(int row);
64
65 // Changes the values of the row at |row|.
66 void ChangeRow(int row, int c1_value, int c2_value);
67
68 // ui::TableModel:
69 virtual int RowCount() override;
70 virtual base::string16 GetText(int row, int column_id) override;
71 virtual void SetObserver(ui::TableModelObserver* observer) override;
72 virtual int CompareValues(int row1, int row2, int column_id) override;
73
74 private:
75 ui::TableModelObserver* observer_;
76
77 // The data.
78 std::vector<std::vector<int> > rows_;
79
80 DISALLOW_COPY_AND_ASSIGN(TestTableModel2);
81 };
82
83 TestTableModel2::TestTableModel2() : observer_(NULL) {
84 AddRow(0, 0, 1);
85 AddRow(1, 1, 1);
86 AddRow(2, 2, 2);
87 AddRow(3, 3, 0);
88 }
89
90 void TestTableModel2::AddRow(int row, int c1_value, int c2_value) {
91 DCHECK(row >= 0 && row <= static_cast<int>(rows_.size()));
92 std::vector<int> new_row;
93 new_row.push_back(c1_value);
94 new_row.push_back(c2_value);
95 rows_.insert(rows_.begin() + row, new_row);
96 if (observer_)
97 observer_->OnItemsAdded(row, 1);
98 }
99 void TestTableModel2::RemoveRow(int row) {
100 DCHECK(row >= 0 && row <= static_cast<int>(rows_.size()));
101 rows_.erase(rows_.begin() + row);
102 if (observer_)
103 observer_->OnItemsRemoved(row, 1);
104 }
105
106 void TestTableModel2::ChangeRow(int row, int c1_value, int c2_value) {
107 DCHECK(row >= 0 && row < static_cast<int>(rows_.size()));
108 rows_[row][0] = c1_value;
109 rows_[row][1] = c2_value;
110 if (observer_)
111 observer_->OnItemsChanged(row, 1);
112 }
113
114 int TestTableModel2::RowCount() {
115 return static_cast<int>(rows_.size());
116 }
117
118 base::string16 TestTableModel2::GetText(int row, int column_id) {
119 return base::IntToString16(rows_[row][column_id]);
120 }
121
122 void TestTableModel2::SetObserver(ui::TableModelObserver* observer) {
123 observer_ = observer;
124 }
125
126 int TestTableModel2::CompareValues(int row1, int row2, int column_id) {
127 return rows_[row1][column_id] - rows_[row2][column_id];
128 }
129
130 // Returns the view to model mapping as a string.
131 std::string GetViewToModelAsString(TableView* table) {
132 std::string result;
133 for (int i = 0; i < table->RowCount(); ++i) {
134 if (i != 0)
135 result += " ";
136 result += base::IntToString(table->ViewToModel(i));
137 }
138 return result;
139 }
140
141 // Returns the model to view mapping as a string.
142 std::string GetModelToViewAsString(TableView* table) {
143 std::string result;
144 for (int i = 0; i < table->RowCount(); ++i) {
145 if (i != 0)
146 result += " ";
147 result += base::IntToString(table->ModelToView(i));
148 }
149 return result;
150 }
151
152 class TestTableView : public TableView {
153 public:
154 TestTableView(ui::TableModel* model,
155 const std::vector<ui::TableColumn>& columns)
156 : TableView(model, columns, TEXT_ONLY, false) {
157 }
158
159 // View overrides:
160 virtual bool HasFocus() const override {
161 // Overriden so key processing works.
162 return true;
163 }
164
165 private:
166 DISALLOW_COPY_AND_ASSIGN(TestTableView);
167 };
168
169 } // namespace
170
171 class TableViewTest : public testing::Test {
172 public:
173 TableViewTest() : table_(NULL) {}
174
175 virtual void SetUp() override {
176 model_.reset(new TestTableModel2);
177 std::vector<ui::TableColumn> columns(2);
178 columns[0].title = base::ASCIIToUTF16("Title Column 0");
179 columns[0].sortable = true;
180 columns[1].title = base::ASCIIToUTF16("Title Column 1");
181 columns[1].id = 1;
182 columns[1].sortable = true;
183 table_ = new TestTableView(model_.get(), columns);
184 parent_.reset(table_->CreateParentIfNecessary());
185 parent_->SetBounds(0, 0, 10000, 10000);
186 parent_->Layout();
187 helper_.reset(new TableViewTestHelper(table_));
188 }
189
190 void ClickOnRow(int row, int flags) {
191 const int y = row * table_->row_height();
192 const ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(0, y),
193 gfx::Point(0, y),
194 ui::EF_LEFT_MOUSE_BUTTON | flags,
195 ui::EF_LEFT_MOUSE_BUTTON);
196 table_->OnMousePressed(pressed);
197 }
198
199 void TapOnRow(int row) {
200 const int y = row * table_->row_height();
201 const ui::GestureEventDetails event_details(ui::ET_GESTURE_TAP);
202 ui::GestureEvent tap(0, y, 0, base::TimeDelta(), event_details);
203 table_->OnGestureEvent(&tap);
204 }
205
206 // Returns the state of the selection model as a string. The format is:
207 // 'active=X anchor=X selection=X X X...'.
208 std::string SelectionStateAsString() const {
209 const ui::ListSelectionModel& model(table_->selection_model());
210 std::string result = "active=" + base::IntToString(model.active()) +
211 " anchor=" + base::IntToString(model.anchor()) +
212 " selection=";
213 const ui::ListSelectionModel::SelectedIndices& selection(
214 model.selected_indices());
215 for (size_t i = 0; i < selection.size(); ++i) {
216 if (i != 0)
217 result += " ";
218 result += base::IntToString(selection[i]);
219 }
220 return result;
221 }
222
223 void PressKey(ui::KeyboardCode code) {
224 ui::KeyEvent event(ui::ET_KEY_PRESSED, code, ui::EF_NONE);
225 table_->OnKeyPressed(event);
226 }
227
228 protected:
229 scoped_ptr<TestTableModel2> model_;
230
231 // Owned by |parent_|.
232 TableView* table_;
233
234 scoped_ptr<TableViewTestHelper> helper_;
235
236 private:
237 scoped_ptr<View> parent_;
238
239 DISALLOW_COPY_AND_ASSIGN(TableViewTest);
240 };
241
242 // Verifies GetPaintRegion.
243 TEST_F(TableViewTest, GetPaintRegion) {
244 // Two columns should be visible.
245 EXPECT_EQ(2u, helper_->visible_col_count());
246
247 EXPECT_EQ("rows=0 4 cols=0 2", helper_->GetPaintRegion(table_->bounds()));
248 EXPECT_EQ("rows=0 4 cols=0 1",
249 helper_->GetPaintRegion(gfx::Rect(0, 0, 1, table_->height())));
250 }
251
252 // Verifies SetColumnVisibility().
253 TEST_F(TableViewTest, ColumnVisibility) {
254 // Two columns should be visible.
255 EXPECT_EQ(2u, helper_->visible_col_count());
256
257 // Should do nothing (column already visible).
258 table_->SetColumnVisibility(0, true);
259 EXPECT_EQ(2u, helper_->visible_col_count());
260
261 // Hide the first column.
262 table_->SetColumnVisibility(0, false);
263 ASSERT_EQ(1u, helper_->visible_col_count());
264 EXPECT_EQ(1, table_->visible_columns()[0].column.id);
265 EXPECT_EQ("rows=0 4 cols=0 1", helper_->GetPaintRegion(table_->bounds()));
266
267 // Hide the second column.
268 table_->SetColumnVisibility(1, false);
269 EXPECT_EQ(0u, helper_->visible_col_count());
270
271 // Show the second column.
272 table_->SetColumnVisibility(1, true);
273 ASSERT_EQ(1u, helper_->visible_col_count());
274 EXPECT_EQ(1, table_->visible_columns()[0].column.id);
275 EXPECT_EQ("rows=0 4 cols=0 1", helper_->GetPaintRegion(table_->bounds()));
276
277 // Show the first column.
278 table_->SetColumnVisibility(0, true);
279 ASSERT_EQ(2u, helper_->visible_col_count());
280 EXPECT_EQ(1, table_->visible_columns()[0].column.id);
281 EXPECT_EQ(0, table_->visible_columns()[1].column.id);
282 EXPECT_EQ("rows=0 4 cols=0 2", helper_->GetPaintRegion(table_->bounds()));
283 }
284
285 // Verifies resizing a column works.
286 TEST_F(TableViewTest, Resize) {
287 const int x = table_->visible_columns()[0].width;
288 EXPECT_NE(0, x);
289 // Drag the mouse 1 pixel to the left.
290 const ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(x, 0),
291 gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON,
292 ui::EF_LEFT_MOUSE_BUTTON);
293 helper_->header()->OnMousePressed(pressed);
294 const ui::MouseEvent dragged(ui::ET_MOUSE_DRAGGED, gfx::Point(x - 1, 0),
295 gfx::Point(x - 1, 0), ui::EF_LEFT_MOUSE_BUTTON,
296 0);
297 helper_->header()->OnMouseDragged(dragged);
298
299 // This should shrink the first column and pull the second column in.
300 EXPECT_EQ(x - 1, table_->visible_columns()[0].width);
301 EXPECT_EQ(x - 1, table_->visible_columns()[1].x);
302 }
303
304 // Verifies resizing a column works with a gesture.
305 TEST_F(TableViewTest, ResizeViaGesture) {
306 const int x = table_->visible_columns()[0].width;
307 EXPECT_NE(0, x);
308 // Drag the mouse 1 pixel to the left.
309 ui::GestureEvent scroll_begin(
310 x,
311 0,
312 0,
313 base::TimeDelta(),
314 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
315 helper_->header()->OnGestureEvent(&scroll_begin);
316 ui::GestureEvent scroll_update(
317 x - 1,
318 0,
319 0,
320 base::TimeDelta(),
321 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE));
322 helper_->header()->OnGestureEvent(&scroll_update);
323
324 // This should shrink the first column and pull the second column in.
325 EXPECT_EQ(x - 1, table_->visible_columns()[0].width);
326 EXPECT_EQ(x - 1, table_->visible_columns()[1].x);
327 }
328
329 // Assertions for table sorting.
330 TEST_F(TableViewTest, Sort) {
331 // Toggle the sort order of the first column, shouldn't change anything.
332 table_->ToggleSortOrder(0);
333 ASSERT_EQ(1u, table_->sort_descriptors().size());
334 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
335 EXPECT_TRUE(table_->sort_descriptors()[0].ascending);
336 EXPECT_EQ("0 1 2 3", GetViewToModelAsString(table_));
337 EXPECT_EQ("0 1 2 3", GetModelToViewAsString(table_));
338
339 // Invert the sort (first column descending).
340 table_->ToggleSortOrder(0);
341 ASSERT_EQ(1u, table_->sort_descriptors().size());
342 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
343 EXPECT_FALSE(table_->sort_descriptors()[0].ascending);
344 EXPECT_EQ("3 2 1 0", GetViewToModelAsString(table_));
345 EXPECT_EQ("3 2 1 0", GetModelToViewAsString(table_));
346
347 // Change cell 0x3 to -1, meaning we have 0, 1, 2, -1 (in the first column).
348 model_->ChangeRow(3, -1, 0);
349 ASSERT_EQ(1u, table_->sort_descriptors().size());
350 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
351 EXPECT_FALSE(table_->sort_descriptors()[0].ascending);
352 EXPECT_EQ("2 1 0 3", GetViewToModelAsString(table_));
353 EXPECT_EQ("2 1 0 3", GetModelToViewAsString(table_));
354
355 // Invert sort again (first column ascending).
356 table_->ToggleSortOrder(0);
357 ASSERT_EQ(1u, table_->sort_descriptors().size());
358 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
359 EXPECT_TRUE(table_->sort_descriptors()[0].ascending);
360 EXPECT_EQ("3 0 1 2", GetViewToModelAsString(table_));
361 EXPECT_EQ("1 2 3 0", GetModelToViewAsString(table_));
362
363 // Add a row so that model has 0, 3, 1, 2, -1.
364 model_->AddRow(1, 3, 4);
365 ASSERT_EQ(1u, table_->sort_descriptors().size());
366 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
367 EXPECT_TRUE(table_->sort_descriptors()[0].ascending);
368 EXPECT_EQ("4 0 2 3 1", GetViewToModelAsString(table_));
369 EXPECT_EQ("1 4 2 3 0", GetModelToViewAsString(table_));
370
371 // Delete the first row, ending up with 3, 1, 2, -1.
372 model_->RemoveRow(0);
373 ASSERT_EQ(1u, table_->sort_descriptors().size());
374 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
375 EXPECT_TRUE(table_->sort_descriptors()[0].ascending);
376 EXPECT_EQ("3 1 2 0", GetViewToModelAsString(table_));
377 EXPECT_EQ("3 1 2 0", GetModelToViewAsString(table_));
378 }
379
380 // Verfies clicking on the header sorts.
381 TEST_F(TableViewTest, SortOnMouse) {
382 EXPECT_TRUE(table_->sort_descriptors().empty());
383
384 const int x = table_->visible_columns()[0].width / 2;
385 EXPECT_NE(0, x);
386 // Press and release the mouse.
387 const ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(x, 0),
388 gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON,
389 ui::EF_LEFT_MOUSE_BUTTON);
390 // The header must return true, else it won't normally get the release.
391 EXPECT_TRUE(helper_->header()->OnMousePressed(pressed));
392 const ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(x, 0),
393 gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON,
394 ui::EF_LEFT_MOUSE_BUTTON);
395 helper_->header()->OnMouseReleased(release);
396
397 ASSERT_EQ(1u, table_->sort_descriptors().size());
398 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
399 EXPECT_TRUE(table_->sort_descriptors()[0].ascending);
400 }
401
402 namespace {
403
404 class TableGrouperImpl : public TableGrouper {
405 public:
406 TableGrouperImpl() {}
407
408 void SetRanges(const std::vector<int>& ranges) {
409 ranges_ = ranges;
410 }
411
412 // TableGrouper overrides:
413 virtual void GetGroupRange(int model_index, GroupRange* range) override {
414 int offset = 0;
415 size_t range_index = 0;
416 for (; range_index < ranges_.size() && offset < model_index; ++range_index)
417 offset += ranges_[range_index];
418
419 if (offset == model_index) {
420 range->start = model_index;
421 range->length = ranges_[range_index];
422 } else {
423 range->start = offset - ranges_[range_index - 1];
424 range->length = ranges_[range_index - 1];
425 }
426 }
427
428 private:
429 std::vector<int> ranges_;
430
431 DISALLOW_COPY_AND_ASSIGN(TableGrouperImpl);
432 };
433
434 } // namespace
435
436 // Assertions around grouping.
437 TEST_F(TableViewTest, Grouping) {
438 // Configure the grouper so that there are two groups:
439 // A 0
440 // 1
441 // B 2
442 // 3
443 TableGrouperImpl grouper;
444 std::vector<int> ranges;
445 ranges.push_back(2);
446 ranges.push_back(2);
447 grouper.SetRanges(ranges);
448 table_->SetGrouper(&grouper);
449
450 // Toggle the sort order of the first column, shouldn't change anything.
451 table_->ToggleSortOrder(0);
452 ASSERT_EQ(1u, table_->sort_descriptors().size());
453 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
454 EXPECT_TRUE(table_->sort_descriptors()[0].ascending);
455 EXPECT_EQ("0 1 2 3", GetViewToModelAsString(table_));
456 EXPECT_EQ("0 1 2 3", GetModelToViewAsString(table_));
457
458 // Sort descending, resulting:
459 // B 2
460 // 3
461 // A 0
462 // 1
463 table_->ToggleSortOrder(0);
464 ASSERT_EQ(1u, table_->sort_descriptors().size());
465 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
466 EXPECT_FALSE(table_->sort_descriptors()[0].ascending);
467 EXPECT_EQ("2 3 0 1", GetViewToModelAsString(table_));
468 EXPECT_EQ("2 3 0 1", GetModelToViewAsString(table_));
469
470 // Change the entry in the 4th row to -1. The model now becomes:
471 // A 0
472 // 1
473 // B 2
474 // -1
475 // Since the first entry in the range didn't change the sort isn't impacted.
476 model_->ChangeRow(3, -1, 0);
477 ASSERT_EQ(1u, table_->sort_descriptors().size());
478 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
479 EXPECT_FALSE(table_->sort_descriptors()[0].ascending);
480 EXPECT_EQ("2 3 0 1", GetViewToModelAsString(table_));
481 EXPECT_EQ("2 3 0 1", GetModelToViewAsString(table_));
482
483 // Change the entry in the 3rd row to -1. The model now becomes:
484 // A 0
485 // 1
486 // B -1
487 // -1
488 model_->ChangeRow(2, -1, 0);
489 ASSERT_EQ(1u, table_->sort_descriptors().size());
490 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
491 EXPECT_FALSE(table_->sort_descriptors()[0].ascending);
492 EXPECT_EQ("0 1 2 3", GetViewToModelAsString(table_));
493 EXPECT_EQ("0 1 2 3", GetModelToViewAsString(table_));
494
495 // Toggle to ascending sort.
496 table_->ToggleSortOrder(0);
497 ASSERT_EQ(1u, table_->sort_descriptors().size());
498 EXPECT_EQ(0, table_->sort_descriptors()[0].column_id);
499 EXPECT_TRUE(table_->sort_descriptors()[0].ascending);
500 EXPECT_EQ("2 3 0 1", GetViewToModelAsString(table_));
501 EXPECT_EQ("2 3 0 1", GetModelToViewAsString(table_));
502 }
503
504 namespace {
505
506 class TableViewObserverImpl : public TableViewObserver {
507 public:
508 TableViewObserverImpl() : selection_changed_count_(0) {}
509
510 int GetChangedCountAndClear() {
511 const int count = selection_changed_count_;
512 selection_changed_count_ = 0;
513 return count;
514 }
515
516 // TableViewObserver overrides:
517 virtual void OnSelectionChanged() override {
518 selection_changed_count_++;
519 }
520
521 private:
522 int selection_changed_count_;
523
524 DISALLOW_COPY_AND_ASSIGN(TableViewObserverImpl);
525 };
526
527 } // namespace
528
529 // Assertions around changing the selection.
530 TEST_F(TableViewTest, Selection) {
531 TableViewObserverImpl observer;
532 table_->SetObserver(&observer);
533
534 // Initially no selection.
535 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
536
537 // Select the last row.
538 table_->Select(3);
539 EXPECT_EQ(1, observer.GetChangedCountAndClear());
540 EXPECT_EQ("active=3 anchor=3 selection=3", SelectionStateAsString());
541
542 // Change sort, shouldn't notify of change (toggle twice so that order
543 // actually changes).
544 table_->ToggleSortOrder(0);
545 table_->ToggleSortOrder(0);
546 EXPECT_EQ(0, observer.GetChangedCountAndClear());
547 EXPECT_EQ("active=3 anchor=3 selection=3", SelectionStateAsString());
548
549 // Remove the selected row, this should notify of a change and update the
550 // selection.
551 model_->RemoveRow(3);
552 EXPECT_EQ(1, observer.GetChangedCountAndClear());
553 EXPECT_EQ("active=2 anchor=2 selection=2", SelectionStateAsString());
554
555 // Insert a row, since the selection in terms of the original model hasn't
556 // changed the observer is not notified.
557 model_->AddRow(0, 1, 2);
558 EXPECT_EQ(0, observer.GetChangedCountAndClear());
559 EXPECT_EQ("active=3 anchor=3 selection=3", SelectionStateAsString());
560
561 table_->SetObserver(NULL);
562 }
563
564 // Verifies selection works by way of a gesture.
565 TEST_F(TableViewTest, SelectOnTap) {
566 // Initially no selection.
567 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
568
569 TableViewObserverImpl observer;
570 table_->SetObserver(&observer);
571
572 // Click on the first row, should select it.
573 TapOnRow(0);
574 EXPECT_EQ(1, observer.GetChangedCountAndClear());
575 EXPECT_EQ("active=0 anchor=0 selection=0", SelectionStateAsString());
576
577 table_->SetObserver(NULL);
578 }
579
580 // Verifies up/down correctly navigates through groups.
581 TEST_F(TableViewTest, KeyUpDown) {
582 // Configure the grouper so that there are three groups:
583 // A 0
584 // 1
585 // B 5
586 // C 2
587 // 3
588 model_->AddRow(2, 5, 0);
589 TableGrouperImpl grouper;
590 std::vector<int> ranges;
591 ranges.push_back(2);
592 ranges.push_back(1);
593 ranges.push_back(2);
594 grouper.SetRanges(ranges);
595 table_->SetGrouper(&grouper);
596
597 TableViewObserverImpl observer;
598 table_->SetObserver(&observer);
599
600 // Initially no selection.
601 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
602
603 PressKey(ui::VKEY_DOWN);
604 EXPECT_EQ(1, observer.GetChangedCountAndClear());
605 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
606
607 PressKey(ui::VKEY_DOWN);
608 EXPECT_EQ(1, observer.GetChangedCountAndClear());
609 EXPECT_EQ("active=1 anchor=1 selection=0 1", SelectionStateAsString());
610
611 PressKey(ui::VKEY_DOWN);
612 EXPECT_EQ(1, observer.GetChangedCountAndClear());
613 EXPECT_EQ("active=2 anchor=2 selection=2", SelectionStateAsString());
614
615 PressKey(ui::VKEY_DOWN);
616 EXPECT_EQ(1, observer.GetChangedCountAndClear());
617 EXPECT_EQ("active=3 anchor=3 selection=3 4", SelectionStateAsString());
618
619 PressKey(ui::VKEY_DOWN);
620 EXPECT_EQ(1, observer.GetChangedCountAndClear());
621 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
622
623 PressKey(ui::VKEY_DOWN);
624 EXPECT_EQ(0, observer.GetChangedCountAndClear());
625 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
626
627 PressKey(ui::VKEY_UP);
628 EXPECT_EQ(1, observer.GetChangedCountAndClear());
629 EXPECT_EQ("active=3 anchor=3 selection=3 4", SelectionStateAsString());
630
631 PressKey(ui::VKEY_UP);
632 EXPECT_EQ(1, observer.GetChangedCountAndClear());
633 EXPECT_EQ("active=2 anchor=2 selection=2", SelectionStateAsString());
634
635 PressKey(ui::VKEY_UP);
636 EXPECT_EQ(1, observer.GetChangedCountAndClear());
637 EXPECT_EQ("active=1 anchor=1 selection=0 1", SelectionStateAsString());
638
639 PressKey(ui::VKEY_UP);
640 EXPECT_EQ(1, observer.GetChangedCountAndClear());
641 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
642
643 PressKey(ui::VKEY_UP);
644 EXPECT_EQ(0, observer.GetChangedCountAndClear());
645 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
646
647 // Sort the table descending by column 1, view now looks like:
648 // B 5 model: 2
649 // C 2 3
650 // 3 4
651 // A 0 0
652 // 1 1
653 table_->ToggleSortOrder(0);
654 table_->ToggleSortOrder(0);
655
656 EXPECT_EQ("2 3 4 0 1", GetViewToModelAsString(table_));
657
658 table_->Select(-1);
659 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
660
661 observer.GetChangedCountAndClear();
662 // Up with nothing selected selects the first row.
663 PressKey(ui::VKEY_UP);
664 EXPECT_EQ(1, observer.GetChangedCountAndClear());
665 EXPECT_EQ("active=2 anchor=2 selection=2", SelectionStateAsString());
666
667 PressKey(ui::VKEY_DOWN);
668 EXPECT_EQ(1, observer.GetChangedCountAndClear());
669 EXPECT_EQ("active=3 anchor=3 selection=3 4", SelectionStateAsString());
670
671 PressKey(ui::VKEY_DOWN);
672 EXPECT_EQ(1, observer.GetChangedCountAndClear());
673 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
674
675 PressKey(ui::VKEY_DOWN);
676 EXPECT_EQ(1, observer.GetChangedCountAndClear());
677 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
678
679 PressKey(ui::VKEY_DOWN);
680 EXPECT_EQ(1, observer.GetChangedCountAndClear());
681 EXPECT_EQ("active=1 anchor=1 selection=0 1", SelectionStateAsString());
682
683 PressKey(ui::VKEY_DOWN);
684 EXPECT_EQ(0, observer.GetChangedCountAndClear());
685 EXPECT_EQ("active=1 anchor=1 selection=0 1", SelectionStateAsString());
686
687 PressKey(ui::VKEY_UP);
688 EXPECT_EQ(1, observer.GetChangedCountAndClear());
689 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
690
691 PressKey(ui::VKEY_UP);
692 EXPECT_EQ(1, observer.GetChangedCountAndClear());
693 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
694
695 PressKey(ui::VKEY_UP);
696 EXPECT_EQ(1, observer.GetChangedCountAndClear());
697 EXPECT_EQ("active=3 anchor=3 selection=3 4", SelectionStateAsString());
698
699 PressKey(ui::VKEY_UP);
700 EXPECT_EQ(1, observer.GetChangedCountAndClear());
701 EXPECT_EQ("active=2 anchor=2 selection=2", SelectionStateAsString());
702
703 PressKey(ui::VKEY_UP);
704 EXPECT_EQ(0, observer.GetChangedCountAndClear());
705 EXPECT_EQ("active=2 anchor=2 selection=2", SelectionStateAsString());
706
707 table_->SetObserver(NULL);
708 }
709
710 // Verifies home/end do the right thing.
711 TEST_F(TableViewTest, HomeEnd) {
712 // Configure the grouper so that there are three groups:
713 // A 0
714 // 1
715 // B 5
716 // C 2
717 // 3
718 model_->AddRow(2, 5, 0);
719 TableGrouperImpl grouper;
720 std::vector<int> ranges;
721 ranges.push_back(2);
722 ranges.push_back(1);
723 ranges.push_back(2);
724 grouper.SetRanges(ranges);
725 table_->SetGrouper(&grouper);
726
727 TableViewObserverImpl observer;
728 table_->SetObserver(&observer);
729
730 // Initially no selection.
731 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
732
733 PressKey(ui::VKEY_HOME);
734 EXPECT_EQ(1, observer.GetChangedCountAndClear());
735 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
736
737 PressKey(ui::VKEY_END);
738 EXPECT_EQ(1, observer.GetChangedCountAndClear());
739 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
740
741 table_->SetObserver(NULL);
742 }
743
744 // Verifies multiple selection gestures work (control-click, shift-click ...).
745 TEST_F(TableViewTest, Multiselection) {
746 // Configure the grouper so that there are three groups:
747 // A 0
748 // 1
749 // B 5
750 // C 2
751 // 3
752 model_->AddRow(2, 5, 0);
753 TableGrouperImpl grouper;
754 std::vector<int> ranges;
755 ranges.push_back(2);
756 ranges.push_back(1);
757 ranges.push_back(2);
758 grouper.SetRanges(ranges);
759 table_->SetGrouper(&grouper);
760
761 // Initially no selection.
762 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
763
764 TableViewObserverImpl observer;
765 table_->SetObserver(&observer);
766
767 // Click on the first row, should select it and the second row.
768 ClickOnRow(0, 0);
769 EXPECT_EQ(1, observer.GetChangedCountAndClear());
770 EXPECT_EQ("active=0 anchor=0 selection=0 1", SelectionStateAsString());
771
772 // Click on the last row, should select it and the row before it.
773 ClickOnRow(4, 0);
774 EXPECT_EQ(1, observer.GetChangedCountAndClear());
775 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
776
777 // Shift click on the third row, should extend selection to it.
778 ClickOnRow(2, ui::EF_SHIFT_DOWN);
779 EXPECT_EQ(1, observer.GetChangedCountAndClear());
780 EXPECT_EQ("active=2 anchor=4 selection=2 3 4", SelectionStateAsString());
781
782 // Control click on third row, should toggle it.
783 ClickOnRow(2, ui::EF_CONTROL_DOWN);
784 EXPECT_EQ(1, observer.GetChangedCountAndClear());
785 EXPECT_EQ("active=2 anchor=2 selection=3 4", SelectionStateAsString());
786
787 // Control-shift click on second row, should extend selection to it.
788 ClickOnRow(1, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
789 EXPECT_EQ(1, observer.GetChangedCountAndClear());
790 EXPECT_EQ("active=1 anchor=2 selection=0 1 2 3 4", SelectionStateAsString());
791
792 // Click on last row again.
793 ClickOnRow(4, 0);
794 EXPECT_EQ(1, observer.GetChangedCountAndClear());
795 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
796
797 table_->SetObserver(NULL);
798 }
799
800 // Verifies multiple selection gestures work when sorted.
801 TEST_F(TableViewTest, MultiselectionWithSort) {
802 // Configure the grouper so that there are three groups:
803 // A 0
804 // 1
805 // B 5
806 // C 2
807 // 3
808 model_->AddRow(2, 5, 0);
809 TableGrouperImpl grouper;
810 std::vector<int> ranges;
811 ranges.push_back(2);
812 ranges.push_back(1);
813 ranges.push_back(2);
814 grouper.SetRanges(ranges);
815 table_->SetGrouper(&grouper);
816
817 // Sort the table descending by column 1, view now looks like:
818 // B 5 model: 2
819 // C 2 3
820 // 3 4
821 // A 0 0
822 // 1 1
823 table_->ToggleSortOrder(0);
824 table_->ToggleSortOrder(0);
825
826 // Initially no selection.
827 EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString());
828
829 TableViewObserverImpl observer;
830 table_->SetObserver(&observer);
831
832 // Click on the third row, should select it and the second row.
833 ClickOnRow(2, 0);
834 EXPECT_EQ(1, observer.GetChangedCountAndClear());
835 EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString());
836
837 // Extend selection to first row.
838 ClickOnRow(0, ui::EF_SHIFT_DOWN);
839 EXPECT_EQ(1, observer.GetChangedCountAndClear());
840 EXPECT_EQ("active=2 anchor=4 selection=2 3 4", SelectionStateAsString());
841
842 table_->SetObserver(NULL);
843 }
844
845 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/table/table_view_row_background_painter.h ('k') | ui/views/controls/table/test_table_model.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698