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

Side by Side Diff: views/controls/table/group_table_view.cc

Issue 8655001: views: Move table and tree directories to ui/views/controls/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: exclude native_widget_win_unittest too Created 9 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « views/controls/table/group_table_view.h ('k') | views/controls/table/native_table_gtk.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "views/controls/table/group_table_view.h"
6
7 #include "base/bind.h"
8 #include "base/compiler_specific.h"
9 #include "base/message_loop.h"
10 #include "ui/gfx/canvas.h"
11
12 namespace views {
13
14 const COLORREF kSeparatorLineColor = RGB(208, 208, 208);
15 const int kSeparatorLineThickness = 1;
16
17 const char GroupTableView::kViewClassName[] = "views/GroupTableView";
18
19 GroupTableView::GroupTableView(GroupTableModel* model,
20 const std::vector<ui::TableColumn>& columns,
21 TableTypes table_type,
22 bool single_selection,
23 bool resizable_columns,
24 bool autosize_columns,
25 bool draw_group_separators)
26 : TableView(model, columns, table_type, false, resizable_columns,
27 autosize_columns),
28 model_(model),
29 draw_group_separators_(draw_group_separators),
30 ALLOW_THIS_IN_INITIALIZER_LIST(sync_selection_factory_(this)) {
31 }
32
33 GroupTableView::~GroupTableView() {
34 }
35
36 void GroupTableView::SyncSelection() {
37 int index = 0;
38 int row_count = model_->RowCount();
39 GroupRange group_range;
40 while (index < row_count) {
41 model_->GetGroupRangeForItem(index, &group_range);
42 if (group_range.length == 1) {
43 // No synching required for single items.
44 index++;
45 } else {
46 // We need to select the group if at least one item is selected.
47 bool should_select = false;
48 for (int i = group_range.start;
49 i < group_range.start + group_range.length; ++i) {
50 if (IsItemSelected(i)) {
51 should_select = true;
52 break;
53 }
54 }
55 if (should_select) {
56 for (int i = group_range.start;
57 i < group_range.start + group_range.length; ++i) {
58 SetSelectedState(i, true);
59 }
60 }
61 index += group_range.length;
62 }
63 }
64 }
65
66 bool GroupTableView::OnKeyDown(ui::KeyboardCode virtual_keycode) {
67 // In a list view, multiple items can be selected but only one item has the
68 // focus. This creates a problem when the arrow keys are used for navigating
69 // between items in the list view. An example will make this more clear:
70 //
71 // Suppose we have 5 items in the list view, and three of these items are
72 // part of one group:
73 //
74 // Index0: ItemA (No Group)
75 // Index1: ItemB (GroupX)
76 // Index2: ItemC (GroupX)
77 // Index3: ItemD (GroupX)
78 // Index4: ItemE (No Group)
79 //
80 // When GroupX is selected (say, by clicking on ItemD with the mouse),
81 // GroupTableView::SyncSelection() will make sure ItemB, ItemC and ItemD are
82 // selected. Also, the item with the focus will be ItemD (simply because
83 // this is the item the user happened to click on). If then the UP arrow is
84 // pressed once, the focus will be switched to ItemC and not to ItemA and the
85 // end result is that we are stuck in GroupX even though the intention was to
86 // switch to ItemA.
87 //
88 // For that exact reason, we need to set the focus appropriately when we
89 // detect that one of the arrow keys is pressed. Thus, when it comes time
90 // for the list view control to actually switch the focus, the right item
91 // will be selected.
92 if ((virtual_keycode != ui::VKEY_UP) &&
93 (virtual_keycode != ui::VKEY_DOWN)) {
94 return TableView::OnKeyDown(virtual_keycode);
95 }
96
97 // We start by finding the index of the item with the focus. If no item
98 // currently has the focus, then this routine doesn't do anything.
99 int focused_index;
100 int row_count = model_->RowCount();
101 for (focused_index = 0; focused_index < row_count; focused_index++) {
102 if (ItemHasTheFocus(focused_index)) {
103 break;
104 }
105 }
106
107 if (focused_index == row_count)
108 return false;
109
110 DCHECK_LT(focused_index, row_count);
111
112 // Nothing to do if the item which has the focus is not part of a group.
113 GroupRange group_range;
114 model_->GetGroupRangeForItem(focused_index, &group_range);
115 if (group_range.length == 1)
116 return false;
117
118 // If the user pressed the UP key, then the focus should be set to the
119 // topmost element in the group. If the user pressed the DOWN key, the focus
120 // should be set to the bottommost element.
121 if (virtual_keycode == ui::VKEY_UP) {
122 SetFocusOnItem(group_range.start);
123 } else {
124 DCHECK_EQ(virtual_keycode, ui::VKEY_DOWN);
125 SetFocusOnItem(group_range.start + group_range.length - 1);
126 }
127
128 return false;
129 }
130
131 void GroupTableView::PrepareForSort() {
132 GroupRange range;
133 int row_count = RowCount();
134 model_index_to_range_start_map_.clear();
135 for (int model_row = 0; model_row < row_count;) {
136 model_->GetGroupRangeForItem(model_row, &range);
137 for (int range_counter = 0; range_counter < range.length; range_counter++)
138 model_index_to_range_start_map_[range_counter + model_row] = model_row;
139 model_row += range.length;
140 }
141 }
142
143 int GroupTableView::CompareRows(int model_row1, int model_row2) {
144 int range1 = model_index_to_range_start_map_[model_row1];
145 int range2 = model_index_to_range_start_map_[model_row2];
146 if (range1 == range2) {
147 // The two rows are in the same group, sort so that items in the same group
148 // always appear in the same order.
149 return model_row1 - model_row2;
150 }
151 // Sort by the first entry of each of the groups.
152 return TableView::CompareRows(range1, range2);
153 }
154
155 void GroupTableView::OnSelectedStateChanged() {
156 // The goal is to make sure all items for a same group are in a consistent
157 // state in term of selection. When a user clicks an item, several selection
158 // messages are sent, possibly including unselecting all currently selected
159 // items. For that reason, we post a task to be performed later, after all
160 // selection messages have been processed. In the meantime we just ignore all
161 // selection notifications.
162 if (!sync_selection_factory_.HasWeakPtrs()) {
163 MessageLoop::current()->PostTask(
164 FROM_HERE,
165 base::Bind(&GroupTableView::SyncSelection,
166 sync_selection_factory_.GetWeakPtr()));
167 }
168 TableView::OnSelectedStateChanged();
169 }
170
171 // Draws the line separator betweens the groups.
172 void GroupTableView::PostPaint(int model_row, int column, bool selected,
173 const gfx::Rect& bounds, HDC hdc) {
174 if (!draw_group_separators_)
175 return;
176
177 GroupRange group_range;
178 model_->GetGroupRangeForItem(model_row, &group_range);
179
180 // We always paint a vertical line at the end of the last cell.
181 HPEN hPen = CreatePen(PS_SOLID, kSeparatorLineThickness, kSeparatorLineColor);
182 HPEN hPenOld = (HPEN) SelectObject(hdc, hPen);
183 int x = bounds.right() - kSeparatorLineThickness;
184 MoveToEx(hdc, x, bounds.y(), NULL);
185 LineTo(hdc, x, bounds.bottom());
186
187 // We paint a separator line after the last item of a group.
188 if (model_row == (group_range.start + group_range.length - 1)) {
189 int y = bounds.bottom() - kSeparatorLineThickness;
190 MoveToEx(hdc, 0, y, NULL);
191 LineTo(hdc, bounds.width(), y);
192 }
193 SelectObject(hdc, hPenOld);
194 DeleteObject(hPen);
195 }
196
197 std::string GroupTableView::GetClassName() const {
198 return kViewClassName;
199 }
200
201 } // namespace views
OLDNEW
« no previous file with comments | « views/controls/table/group_table_view.h ('k') | views/controls/table/native_table_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698