OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "views/controls/table/table_view.h" | 5 #include "views/controls/table/table_view.h" |
6 | 6 |
| 7 #include <commctrl.h> |
7 #include <windowsx.h> | 8 #include <windowsx.h> |
8 #include <atlbase.h> | |
9 #include <atlapp.h> | |
10 #include <atlmisc.h> | |
11 | 9 |
12 #include <algorithm> | 10 #include <algorithm> |
13 | 11 |
14 #include "app/gfx/canvas.h" | 12 #include "app/gfx/canvas.h" |
15 #include "app/gfx/favicon_size.h" | 13 #include "app/gfx/favicon_size.h" |
16 #include "app/gfx/icon_util.h" | 14 #include "app/gfx/icon_util.h" |
17 #include "app/l10n_util_win.h" | 15 #include "app/l10n_util_win.h" |
18 #include "app/resource_bundle.h" | 16 #include "app/resource_bundle.h" |
19 #include "app/table_model.h" | 17 #include "app/table_model.h" |
20 #include "base/string_util.h" | 18 #include "base/string_util.h" |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 | 225 |
228 TableView::iterator TableView::SelectionEnd() { | 226 TableView::iterator TableView::SelectionEnd() { |
229 return TableView::iterator(this, -1); | 227 return TableView::iterator(this, -1); |
230 } | 228 } |
231 | 229 |
232 void TableView::OnItemsChanged(int start, int length) { | 230 void TableView::OnItemsChanged(int start, int length) { |
233 if (!list_view_) | 231 if (!list_view_) |
234 return; | 232 return; |
235 | 233 |
236 if (length == -1) { | 234 if (length == -1) { |
237 DCHECK(start >= 0); | 235 DCHECK_GE(start, 0); |
238 length = model_->RowCount() - start; | 236 length = model_->RowCount() - start; |
239 } | 237 } |
240 int row_count = RowCount(); | 238 int row_count = RowCount(); |
241 DCHECK(start >= 0 && length > 0 && start + length <= row_count); | 239 DCHECK(start >= 0 && length > 0 && start + length <= row_count); |
242 SendMessage(list_view_, WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0); | 240 SendMessage(list_view_, WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0); |
243 if (table_type_ == ICON_AND_TEXT) { | 241 if (table_type_ == ICON_AND_TEXT) { |
244 // The redraw event does not include the icon in the clip rect, preventing | 242 // The redraw event does not include the icon in the clip rect, preventing |
245 // our icon from being repainted. So far the only way I could find around | 243 // our icon from being repainted. So far the only way I could find around |
246 // this is to change the image for the item. Even if the image does not | 244 // this is to change the image for the item. Even if the image does not |
247 // exist, it causes the clip rect to include the icon's bounds so we can | 245 // exist, it causes the clip rect to include the icon's bounds so we can |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 // | 349 // |
352 // When the model is set to NULL all the rows are removed. We don't notify | 350 // When the model is set to NULL all the rows are removed. We don't notify |
353 // the delegate in this case as setting the model to NULL is usually done as | 351 // the delegate in this case as setting the model to NULL is usually done as |
354 // the last step before being deleted and callers shouldn't have to deal with | 352 // the last step before being deleted and callers shouldn't have to deal with |
355 // getting a selection change when the model is being reset. | 353 // getting a selection change when the model is being reset. |
356 if (model_ && table_view_observer_ && had_selection && RowCount() == 0) | 354 if (model_ && table_view_observer_ && had_selection && RowCount() == 0) |
357 table_view_observer_->OnSelectionChanged(); | 355 table_view_observer_->OnSelectionChanged(); |
358 } | 356 } |
359 | 357 |
360 void TableView::AddColumn(const TableColumn& col) { | 358 void TableView::AddColumn(const TableColumn& col) { |
361 DCHECK(all_columns_.count(col.id) == 0); | 359 DCHECK_EQ(0, all_columns_.count(col.id)); |
362 all_columns_[col.id] = col; | 360 all_columns_[col.id] = col; |
363 } | 361 } |
364 | 362 |
365 void TableView::SetColumns(const std::vector<TableColumn>& columns) { | 363 void TableView::SetColumns(const std::vector<TableColumn>& columns) { |
366 // Remove the currently visible columns. | 364 // Remove the currently visible columns. |
367 while (!visible_columns_.empty()) | 365 while (!visible_columns_.empty()) |
368 SetColumnVisibility(visible_columns_.front(), false); | 366 SetColumnVisibility(visible_columns_.front(), false); |
369 | 367 |
370 all_columns_.clear(); | 368 all_columns_.clear(); |
371 for (std::vector<TableColumn>::const_iterator i = columns.begin(); | 369 for (std::vector<TableColumn>::const_iterator i = columns.begin(); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 // list-view twice in a row. | 531 // list-view twice in a row. |
534 // 2. Right clicking on the icon would show the scrollbar menu. | 532 // 2. Right clicking on the icon would show the scrollbar menu. |
535 // | 533 // |
536 // As a work around this uses the position of the cursor and ignores | 534 // As a work around this uses the position of the cursor and ignores |
537 // the position supplied in the l_param. | 535 // the position supplied in the l_param. |
538 if (table_view->UILayoutIsRightToLeft() && | 536 if (table_view->UILayoutIsRightToLeft() && |
539 (GET_X_LPARAM(l_param) != -1 || GET_Y_LPARAM(l_param) != -1)) { | 537 (GET_X_LPARAM(l_param) != -1 || GET_Y_LPARAM(l_param) != -1)) { |
540 POINT screen_point; | 538 POINT screen_point; |
541 GetCursorPos(&screen_point); | 539 GetCursorPos(&screen_point); |
542 POINT table_point = screen_point; | 540 POINT table_point = screen_point; |
543 WTL::CRect client_rect; | 541 RECT client_rect; |
544 if (ScreenToClient(window, &table_point) && | 542 if (ScreenToClient(window, &table_point) && |
545 GetClientRect(window, &client_rect) && | 543 GetClientRect(window, &client_rect) && |
546 client_rect.PtInRect(table_point)) { | 544 PtInRect(&client_rect, table_point)) { |
547 // The point is over the client area of the table, handle it ourself. | 545 // The point is over the client area of the table, handle it ourself. |
548 // But first select the row if it isn't already selected. | 546 // But first select the row if it isn't already selected. |
549 LVHITTESTINFO hit_info = {0}; | 547 LVHITTESTINFO hit_info = {0}; |
550 hit_info.pt.x = table_point.x; | 548 hit_info.pt.x = table_point.x; |
551 hit_info.pt.y = table_point.y; | 549 hit_info.pt.y = table_point.y; |
552 int view_index = ListView_HitTest(window, &hit_info); | 550 int view_index = ListView_HitTest(window, &hit_info); |
553 if (view_index != -1) { | 551 if (view_index != -1) { |
554 int model_index = table_view->view_to_model(view_index); | 552 int model_index = table_view->view_to_model(view_index); |
555 if (!table_view->IsItemSelected(model_index)) | 553 if (!table_view->IsItemSelected(model_index)) |
556 table_view->Select(model_index); | 554 table_view->Select(model_index); |
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 // We get notifications for empty items, just ignore them. | 1194 // We get notifications for empty items, just ignore them. |
1197 if (view_index >= model_->RowCount()) | 1195 if (view_index >= model_->RowCount()) |
1198 return CDRF_DODEFAULT; | 1196 return CDRF_DODEFAULT; |
1199 int model_index = view_to_model(view_index); | 1197 int model_index = view_to_model(view_index); |
1200 LRESULT r = CDRF_DODEFAULT; | 1198 LRESULT r = CDRF_DODEFAULT; |
1201 // First let's take care of painting the right icon. | 1199 // First let's take care of painting the right icon. |
1202 if (table_type_ == ICON_AND_TEXT) { | 1200 if (table_type_ == ICON_AND_TEXT) { |
1203 SkBitmap image = model_->GetIcon(model_index); | 1201 SkBitmap image = model_->GetIcon(model_index); |
1204 if (!image.isNull()) { | 1202 if (!image.isNull()) { |
1205 // Get the rect that holds the icon. | 1203 // Get the rect that holds the icon. |
1206 WTL::CRect icon_rect, client_rect; | 1204 RECT icon_rect, client_rect; |
1207 if (ListView_GetItemRect(list_view_, view_index, &icon_rect, | 1205 if (ListView_GetItemRect(list_view_, view_index, &icon_rect, |
1208 LVIR_ICON) && | 1206 LVIR_ICON) && |
1209 GetClientRect(list_view_, &client_rect)) { | 1207 GetClientRect(list_view_, &client_rect)) { |
1210 WTL::CRect intersection; | 1208 RECT intersection; |
1211 // Client rect includes the header but we need to make sure we don't | 1209 // Client rect includes the header but we need to make sure we don't |
1212 // paint into it. | 1210 // paint into it. |
1213 client_rect.top += content_offset_; | 1211 client_rect.top += content_offset_; |
1214 // Make sure the region need to paint is visible. | 1212 // Make sure the region need to paint is visible. |
1215 if (intersection.IntersectRect(&icon_rect, &client_rect)) { | 1213 if (IntersectRect(&intersection, &icon_rect, &client_rect)) { |
1216 gfx::Canvas canvas(icon_rect.Width(), icon_rect.Height(), false); | 1214 gfx::Canvas canvas(icon_rect.right - icon_rect.left, |
| 1215 icon_rect.bottom - icon_rect.top, false); |
1217 | 1216 |
1218 // It seems the state in nmcd.uItemState is not correct. | 1217 // It seems the state in nmcd.uItemState is not correct. |
1219 // We'll retrieve it explicitly. | 1218 // We'll retrieve it explicitly. |
1220 int selected = ListView_GetItemState( | 1219 int selected = ListView_GetItemState( |
1221 list_view_, view_index, LVIS_SELECTED | LVIS_DROPHILITED); | 1220 list_view_, view_index, LVIS_SELECTED | LVIS_DROPHILITED); |
1222 bool drop_highlight = ((selected & LVIS_DROPHILITED) != 0); | 1221 bool drop_highlight = ((selected & LVIS_DROPHILITED) != 0); |
1223 int bg_color_index; | 1222 int bg_color_index; |
1224 if (!IsEnabled()) | 1223 if (!IsEnabled()) |
1225 bg_color_index = COLOR_3DFACE; | 1224 bg_color_index = COLOR_3DFACE; |
1226 else if (drop_highlight) | 1225 else if (drop_highlight) |
(...skipping 25 matching lines...) Expand all Loading... |
1252 canvas.getTopPlatformDevice().drawToHDC(draw_info->nmcd.hdc, | 1251 canvas.getTopPlatformDevice().drawToHDC(draw_info->nmcd.hdc, |
1253 intersection.left, | 1252 intersection.left, |
1254 intersection.top, | 1253 intersection.top, |
1255 &to_draw); | 1254 &to_draw); |
1256 r = CDRF_SKIPDEFAULT; | 1255 r = CDRF_SKIPDEFAULT; |
1257 } | 1256 } |
1258 } | 1257 } |
1259 } | 1258 } |
1260 } | 1259 } |
1261 if (ImplementPostPaint()) { | 1260 if (ImplementPostPaint()) { |
1262 WTL::CRect cell_rect; | 1261 RECT cell_rect; |
1263 if (ListView_GetItemRect(list_view_, view_index, &cell_rect, | 1262 if (ListView_GetItemRect(list_view_, view_index, &cell_rect, |
1264 LVIR_BOUNDS)) { | 1263 LVIR_BOUNDS)) { |
1265 PostPaint(model_index, 0, false, gfx::Rect(cell_rect), | 1264 PostPaint(model_index, 0, false, gfx::Rect(cell_rect), |
1266 draw_info->nmcd.hdc); | 1265 draw_info->nmcd.hdc); |
1267 r = CDRF_SKIPDEFAULT; | 1266 r = CDRF_SKIPDEFAULT; |
1268 } | 1267 } |
1269 } | 1268 } |
1270 return r; | 1269 return r; |
1271 } | 1270 } |
1272 default: | 1271 default: |
1273 return CDRF_DODEFAULT; | 1272 return CDRF_DODEFAULT; |
1274 } | 1273 } |
1275 } | 1274 } |
1276 | 1275 |
1277 void TableView::UpdateListViewCache(int start, int length, bool add) { | 1276 void TableView::UpdateListViewCache(int start, int length, bool add) { |
1278 ignore_listview_change_ = true; | 1277 ignore_listview_change_ = true; |
1279 UpdateListViewCache0(start, length, add); | 1278 UpdateListViewCache0(start, length, add); |
1280 ignore_listview_change_ = false; | 1279 ignore_listview_change_ = false; |
1281 } | 1280 } |
1282 | 1281 |
1283 void TableView::ResetColumnSizes() { | 1282 void TableView::ResetColumnSizes() { |
1284 if (!list_view_) | 1283 if (!list_view_) |
1285 return; | 1284 return; |
1286 | 1285 |
1287 // See comment in TableColumn for what this does. | 1286 // See comment in TableColumn for what this does. |
1288 int width = this->width(); | 1287 int width = this->width(); |
1289 WTL::CRect native_bounds; | 1288 RECT native_bounds; |
1290 if (GetClientRect(GetNativeControlHWND(), &native_bounds) && | 1289 if (GetClientRect(GetNativeControlHWND(), &native_bounds)) { |
1291 native_bounds.Width() > 0) { | 1290 int window_width = native_bounds.right - native_bounds.left; |
1292 // Prefer the bounds of the window over our bounds, which may be different. | 1291 if (window_width > 0) { |
1293 width = native_bounds.Width(); | 1292 // Prefer the bounds of the window over our bounds, which may be |
| 1293 // different. |
| 1294 width = window_width; |
| 1295 } |
1294 } | 1296 } |
1295 | 1297 |
1296 float percent = 0; | 1298 float percent = 0; |
1297 int fixed_width = 0; | 1299 int fixed_width = 0; |
1298 int autosize_width = 0; | 1300 int autosize_width = 0; |
1299 | 1301 |
1300 for (std::vector<int>::const_iterator i = visible_columns_.begin(); | 1302 for (std::vector<int>::const_iterator i = visible_columns_.begin(); |
1301 i != visible_columns_.end(); ++i) { | 1303 i != visible_columns_.end(); ++i) { |
1302 TableColumn& col = all_columns_[*i]; | 1304 TableColumn& col = all_columns_[*i]; |
1303 int col_index = static_cast<int>(i - visible_columns_.begin()); | 1305 int col_index = static_cast<int>(i - visible_columns_.begin()); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1462 table_view_observer_->OnKeyDown(virtual_keycode); | 1464 table_view_observer_->OnKeyDown(virtual_keycode); |
1463 } | 1465 } |
1464 } | 1466 } |
1465 | 1467 |
1466 void TableView::OnCheckedStateChanged(int model_row, bool is_checked) { | 1468 void TableView::OnCheckedStateChanged(int model_row, bool is_checked) { |
1467 if (!ignore_listview_change_) | 1469 if (!ignore_listview_change_) |
1468 model_->SetChecked(model_row, is_checked); | 1470 model_->SetChecked(model_row, is_checked); |
1469 } | 1471 } |
1470 | 1472 |
1471 int TableView::PreviousSelectedViewIndex(int view_index) { | 1473 int TableView::PreviousSelectedViewIndex(int view_index) { |
1472 DCHECK(view_index >= 0); | 1474 DCHECK_GE(view_index, 0); |
1473 if (!list_view_ || view_index <= 0) | 1475 if (!list_view_ || view_index <= 0) |
1474 return -1; | 1476 return -1; |
1475 | 1477 |
1476 int row_count = RowCount(); | 1478 int row_count = RowCount(); |
1477 if (row_count == 0) | 1479 if (row_count == 0) |
1478 return -1; // Empty table, nothing can be selected. | 1480 return -1; // Empty table, nothing can be selected. |
1479 | 1481 |
1480 // For some reason | 1482 // For some reason |
1481 // ListView_GetNextItem(list_view_,item, LVNI_SELECTED | LVNI_ABOVE) | 1483 // ListView_GetNextItem(list_view_,item, LVNI_SELECTED | LVNI_ABOVE) |
1482 // fails on Vista (always returns -1), so we iterate through the indices. | 1484 // fails on Vista (always returns -1), so we iterate through the indices. |
(...skipping 12 matching lines...) Expand all Loading... |
1495 if (!list_view_) | 1497 if (!list_view_) |
1496 return; | 1498 return; |
1497 | 1499 |
1498 HWND header = ListView_GetHeader(list_view_); | 1500 HWND header = ListView_GetHeader(list_view_); |
1499 if (!header) | 1501 if (!header) |
1500 return; | 1502 return; |
1501 | 1503 |
1502 POINT origin = {0, 0}; | 1504 POINT origin = {0, 0}; |
1503 MapWindowPoints(header, list_view_, &origin, 1); | 1505 MapWindowPoints(header, list_view_, &origin, 1); |
1504 | 1506 |
1505 WTL::CRect header_bounds; | 1507 RECT header_bounds; |
1506 GetWindowRect(header, &header_bounds); | 1508 GetWindowRect(header, &header_bounds); |
1507 | 1509 |
1508 content_offset_ = origin.y + header_bounds.Height(); | 1510 content_offset_ = origin.y + header_bounds.bottom - header_bounds.top; |
1509 } | 1511 } |
1510 | 1512 |
1511 // | 1513 // |
1512 // TableSelectionIterator | 1514 // TableSelectionIterator |
1513 // | 1515 // |
1514 TableSelectionIterator::TableSelectionIterator(TableView* view, | 1516 TableSelectionIterator::TableSelectionIterator(TableView* view, |
1515 int view_index) | 1517 int view_index) |
1516 : table_view_(view), | 1518 : table_view_(view), |
1517 view_index_(view_index) { | 1519 view_index_(view_index) { |
1518 UpdateModelIndexFromViewIndex(); | 1520 UpdateModelIndexFromViewIndex(); |
(...skipping 25 matching lines...) Expand all Loading... |
1544 } | 1546 } |
1545 | 1547 |
1546 void TableSelectionIterator::UpdateModelIndexFromViewIndex() { | 1548 void TableSelectionIterator::UpdateModelIndexFromViewIndex() { |
1547 if (view_index_ == -1) | 1549 if (view_index_ == -1) |
1548 model_index_ = -1; | 1550 model_index_ = -1; |
1549 else | 1551 else |
1550 model_index_ = table_view_->view_to_model(view_index_); | 1552 model_index_ = table_view_->view_to_model(view_index_); |
1551 } | 1553 } |
1552 | 1554 |
1553 } // namespace views | 1555 } // namespace views |
OLD | NEW |