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

Unified Diff: views/controls/table/native_table_win.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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « views/controls/table/native_table_win.h ('k') | views/controls/table/native_table_wrapper.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: views/controls/table/native_table_win.cc
diff --git a/views/controls/table/native_table_win.cc b/views/controls/table/native_table_win.cc
deleted file mode 100644
index 23b1780d695ef1eba83bcd6b33c23249d1c2ad62..0000000000000000000000000000000000000000
--- a/views/controls/table/native_table_win.cc
+++ /dev/null
@@ -1,914 +0,0 @@
-// Copyright (c) 2011 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_win.h"
-
-#include <commctrl.h>
-#include <windowsx.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/win/scoped_gdi_object.h"
-#include "skia/ext/skia_utils_win.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/base/models/table_model.h"
-#include "ui/base/win/hwnd_util.h"
-#include "ui/gfx/canvas_skia.h"
-#include "ui/gfx/favicon_size.h"
-#include "ui/gfx/icon_util.h"
-#include "ui/views/widget/widget.h"
-#include "views/controls/table/table_view2.h"
-#include "views/controls/table/table_view_observer.h"
-
-namespace views {
-
-// Added to column width to prevent truncation.
-const int kListViewTextPadding = 15;
-// Additional column width necessary if column has icons.
-const int kListViewIconWidthAndPadding = 18;
-
-// static
-const int NativeTableWin::kImageSize = 18;
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeTableWin, public:
-
-NativeTableWin::NativeTableWin(TableView2* table)
- : ignore_listview_change_(false),
- table_(table),
- content_offset_(0),
- header_original_handler_(NULL),
- original_handler_(NULL) {
- // Associates the actual HWND 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);
-}
-
-NativeTableWin::~NativeTableWin() {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeTableWin, NativeTableWrapper implementation:
-
-int NativeTableWin::GetRowCount() const {
- if (!native_view())
- return 0;
- return ListView_GetItemCount(native_view());
-}
-
-void NativeTableWin::InsertColumn(const ui::TableColumn& tc, int index) {
- if (!native_view())
- return;
-
- LVCOLUMN column = { 0 };
- column.mask = LVCF_TEXT|LVCF_FMT;
- column.pszText = const_cast<LPWSTR>(tc.title.c_str());
- switch (tc.alignment) {
- case ui::TableColumn::LEFT:
- column.fmt = LVCFMT_LEFT;
- break;
- case ui::TableColumn::RIGHT:
- column.fmt = LVCFMT_RIGHT;
- break;
- case ui::TableColumn::CENTER:
- column.fmt = LVCFMT_CENTER;
- break;
- default:
- NOTREACHED();
- }
- if (tc.width != -1) {
- column.mask |= LVCF_WIDTH;
- column.cx = tc.width;
- }
- column.mask |= LVCF_SUBITEM;
- // Sub-items are 1s indexed.
- column.iSubItem = index + 1;
- SendMessage(native_view(), LVM_INSERTCOLUMN, index,
- reinterpret_cast<LPARAM>(&column));
-}
-
-void NativeTableWin::RemoveColumn(int index) {
- if (!native_view())
- return;
- SendMessage(native_view(), LVM_DELETECOLUMN, index, 0);
- if (table_->model()->RowCount() > 0)
- OnRowsChanged(0, table_->model()->RowCount() - 1);
-}
-
-View* NativeTableWin::GetView() {
- return this;
-}
-
-void NativeTableWin::SetFocus() {
- // Focus the associated HWND.
- OnFocus();
-}
-
-gfx::NativeView NativeTableWin::GetTestingHandle() const {
- return native_view();
-}
-
-int NativeTableWin::GetColumnWidth(int column_index) const {
- if (!native_view())
- return 0;
- return ListView_GetColumnWidth(native_view(), column_index);
-}
-
-void NativeTableWin::SetColumnWidth(int column_index, int width) {
- if (!native_view())
- return;
- ListView_SetColumnWidth(native_view(), column_index, width);
-}
-
-int NativeTableWin::GetSelectedRowCount() const {
- if (!native_view())
- return 0;
- return ListView_GetSelectedCount(native_view());
-}
-
-int NativeTableWin::GetFirstSelectedRow() const {
- if (!native_view())
- return -1;
- return ListView_GetNextItem(native_view(), -1, LVNI_ALL | LVIS_SELECTED);
-}
-
-int NativeTableWin::GetFirstFocusedRow() const {
- if (!native_view())
- return -1;
- return ListView_GetNextItem(native_view(), -1, LVNI_ALL | LVIS_FOCUSED);
-}
-
-void NativeTableWin::ClearSelection() {
- if (native_view())
- ListView_SetItemState(native_view(), -1, 0, LVIS_SELECTED);
-}
-
-void NativeTableWin::ClearRowFocus() {
- if (native_view())
- ListView_SetItemState(native_view(), -1, 0, LVIS_FOCUSED);
-}
-
-void NativeTableWin::SetSelectedState(int model_row, bool state) {
- if (!native_view())
- return;
-
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0);
- ListView_SetItemState(native_view(), model_row,
- state ? LVIS_SELECTED : 0, LVIS_SELECTED);
- // Make the selected row visible.
- ListView_EnsureVisible(native_view(), model_row, FALSE);
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0);
-}
-
-void NativeTableWin::SetFocusState(int model_row, bool state) {
- if (!native_view())
- return;
- ListView_SetItemState(native_view(), model_row,
- state ? LVIS_FOCUSED : 0, LVIS_FOCUSED)
-}
-
-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) const {
- if (!native_view())
- return false;
- return ListView_GetItemState(native_view(), model_row, LVIS_FOCUSED) ==
- LVIS_FOCUSED;
-}
-
-void NativeTableWin::OnRowsChanged(int start, int length) {
- if (!native_view())
- return;
-
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0);
- UpdateListViewCache(start, length, false);
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0);
-}
-
-void NativeTableWin::OnRowsAdded(int start, int length) {
- if (!native_view())
- return;
-
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0);
- UpdateListViewCache(start, length, true);
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0);
-}
-
-void NativeTableWin::OnRowsRemoved(int start, int length) {
- if (!native_view())
- return;
-
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0);
-
- bool had_selection = (GetSelectedRowCount() > 0);
- int old_row_count = GetRowCount();
- if (start == 0 && length == GetRowCount()) {
- // Everything was removed.
- ListView_DeleteAllItems(native_view());
- } else {
- for (int i = 0; i < length; ++i)
- ListView_DeleteItem(native_view(), start);
- }
-
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0);
-
- // If the row count goes to zero and we had a selection LVN_ITEMCHANGED isn't
- // invoked, so we handle it here.
- //
- // When the model is set to NULL all the rows are removed. We don't notify
- // the delegate in this case as setting the model to NULL is usually done as
- // the last step before being deleted and callers shouldn't have to deal with
- // getting a selection change when the model is being reset.
- if (table_->model() && table_->observer() && had_selection &&
- GetRowCount() == 0) {
- table_->observer()->OnSelectionChanged();
- }
-}
-
-gfx::Rect NativeTableWin::GetBounds() const {
- RECT native_bounds;
- if (!native_view() || GetClientRect(native_view(), &native_bounds))
- return gfx::Rect();
- return gfx::Rect(native_bounds);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeTableWin, View overrides:
-
-gfx::Size NativeTableWin::GetPreferredSize() {
- SIZE sz = {0};
- SendMessage(native_view(), BCM_GETIDEALSIZE, 0,
- reinterpret_cast<LPARAM>(&sz));
-
- return gfx::Size(sz.cx, sz.cy);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeTableWin, NativeControlWin overrides:
-
-bool NativeTableWin::ProcessMessage(UINT message, WPARAM w_param,
- LPARAM l_param, LRESULT* result) {
- if (message == WM_NOTIFY) {
- LPNMHDR hdr = reinterpret_cast<LPNMHDR>(l_param);
- switch (hdr->code) {
- case NM_CUSTOMDRAW: {
- // Draw notification. dwDragState indicates the current stage of
- // drawing.
- *result = OnCustomDraw(reinterpret_cast<NMLVCUSTOMDRAW*>(hdr));
- return true;
- }
-
- case LVN_ITEMCHANGED: {
- // Notification that the state of an item has changed. The state
- // includes such things as whether the item is selected.
- NMLISTVIEW* state_change = reinterpret_cast<NMLISTVIEW*>(hdr);
- if ((state_change->uChanged & LVIF_STATE) != 0) {
- if ((state_change->uOldState & LVIS_SELECTED) !=
- (state_change->uNewState & LVIS_SELECTED)) {
- // Selected state of the item changed.
- OnSelectedStateChanged();
- }
- }
- break;
- }
-
- case HDN_BEGINTRACKW:
- case HDN_BEGINTRACKA:
- // Prevent clicks so columns cannot be resized.
- if (!table_->resizable_columns())
- return true;
- break;
-
- case NM_DBLCLK:
- OnDoubleClick();
- break;
-
- case LVN_COLUMNCLICK: {
- const ui::TableColumn& column = table_->GetVisibleColumnAt(
- reinterpret_cast<NMLISTVIEW*>(hdr)->iSubItem);
- break;
- }
-
- case LVN_MARQUEEBEGIN: // We don't want the marquee selection.
- return true;
-
- case LVN_GETINFOTIP: {
- // This is called when the user hovers items in column zero.
- // * If the text in this column is not fully visible, the dwFlags
- // field will be set to 0, and pszText will contain the full text.
- // If you return without making any changes, this text will be
- // displayed in a "labeltip" - a bubble that's overlaid (at the
- // correct alignment!) on the item. If you return with a different
- // pszText, it will be displayed as a tooltip if nonempty.
- // * Otherwise, dwFlags will be LVGIT_UNFOLDED and pszText will be
- // empty. On return, if pszText is nonempty, it will be displayed
- // as a labeltip if dwFlags has been changed to 0 (even if it bears
- // no resemblance to the item text), or as a tooltip otherwise.
- //
- // Once the tooltip for an item has been obtained, this will not be
- // called again until the user hovers a different item. If after that
- // the original item is hovered a second time, this will be called.
- //
- // When the user hovers items in other columns, they will be "unfolded"
- // (displayed as labeltips) when necessary, but this function will
- // never be called.
- //
- // Changing the LVS_EX_INFOTIP extended style to LVS_EX_LABELTIP will
- // cause all of the above to be true except that this function will not
- // be called when dwFlags would be LVGIT_UNFOLDED. Removing it entirely
- // will disable all of the above behavior.
- NMLVGETINFOTIP* info_tip = reinterpret_cast<NMLVGETINFOTIP*>(hdr);
- string16 tooltip = table_->model()->GetTooltip(info_tip->iItem);
- CHECK_GE(info_tip->cchTextMax, 2);
- if (tooltip.length() >= static_cast<size_t>(info_tip->cchTextMax)) {
- // Elide the tooltip if necessary.
- tooltip.erase(info_tip->cchTextMax - 2); // Ellipsis + '\0'
- const wchar_t kEllipsis = L'\x2026';
- tooltip += kEllipsis;
- }
- if (!tooltip.empty())
- wcscpy_s(info_tip->pszText, tooltip.length() + 1, tooltip.c_str());
- return true;
- }
-
- default:
- break;
- }
- }
-
- return NativeControlWin::ProcessMessage(message, w_param, l_param, result);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeTableWin, protected:
-
-void NativeTableWin::CreateNativeControl() {
- int style = WS_CHILD | LVS_REPORT | LVS_SHOWSELALWAYS;
- if (table_->single_selection())
- style |= LVS_SINGLESEL;
- // If there's only one column and the title string is empty, don't show a
- // header.
- if (table_->GetVisibleColumnCount() == 1U) {
- if (table_->GetVisibleColumnAt(1).title.empty())
- style |= LVS_NOCOLUMNHEADER;
- }
- HWND hwnd = ::CreateWindowEx(WS_EX_CLIENTEDGE | GetAdditionalRTLStyle(),
- WC_LISTVIEW,
- L"",
- style,
- 0, 0, width(), height(),
- table_->GetWidget()->GetNativeView(),
- NULL, NULL, NULL);
- ui::CheckWindowCreated(hwnd);
-
- // Reduce overdraw/flicker artifacts by double buffering. Support tooltips
- // and display elided items completely on hover (see comments in OnNotify()
- // under LVN_GETINFOTIP). Make the selection extend across the row.
- ListView_SetExtendedListViewStyle(hwnd,
- LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT);
- l10n_util::AdjustUIFontForWindow(hwnd);
-
- NativeControlCreated(hwnd);
- // native_view() is now valid.
-
- // Add the columns.
- for (size_t i = 0; i < table_->GetVisibleColumnCount(); ++i)
- InsertColumn(table_->GetVisibleColumnAt(i), i);
-
- if (table_->model())
- UpdateListViewCache(0, table_->model()->RowCount(), true);
-
- if (table_->type() == ICON_AND_TEXT) {
- HIMAGELIST image_list =
- ImageList_Create(kImageSize, kImageSize, ILC_COLOR32, 2, 2);
- // We create 2 phony images because we are going to switch images at every
- // refresh in order to force a refresh of the icon area (somehow the clip
- // rect does not include the icon).
- gfx::CanvasSkia canvas(kImageSize, kImageSize, false);
- // Make the background completely transparent.
- canvas.sk_canvas()->drawColor(SK_ColorBLACK, SkXfermode::kClear_Mode);
- {
- base::win::ScopedHICON empty_icon(
- IconUtil::CreateHICONFromSkBitmap(canvas.ExtractBitmap()));
- ImageList_AddIcon(image_list, empty_icon);
- ImageList_AddIcon(image_list, empty_icon);
- }
- ListView_SetImageList(native_view(), image_list, LVSIL_SMALL);
- }
-
- if (!table_->resizable_columns()) {
- // To disable the resizing of columns we'll filter the events happening on
- // the header. We also need to intercept the HDM_LAYOUT to size the header
- // for the Chrome headers.
- HWND header = ListView_GetHeader(native_view());
- DCHECK(header);
- SetWindowLongPtr(header, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
- header_original_handler_ =
- ui::SetWindowProc(header, &NativeTableWin::TableHeaderWndProc);
- }
-
- SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
- original_handler_ =
- ui::SetWindowProc(hwnd, &NativeTableWin::TableWndProc);
-
- // Bug 964884: detach the IME attached to this window.
- // We should attach IMEs only when we need to input CJK strings.
- ::ImmAssociateContextEx(hwnd, NULL, 0);
-
- UpdateContentOffset();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeTableWin, private:
-
-void NativeTableWin::Select(int model_row) {
- if (!native_view())
- return;
-
- DCHECK(model_row >= 0 && model_row < table_->model()->RowCount());
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(FALSE), 0);
- ignore_listview_change_ = true;
-
- // Unselect everything.
- ClearSelection();
-
- // Select the specified item.
- SetSelectedState(model_row, true);
- SetFocusState(model_row, true);
-
- // Make it visible.
- ListView_EnsureVisible(native_view(), model_row, FALSE);
- ignore_listview_change_ = false;
- SendMessage(native_view(), WM_SETREDRAW, static_cast<WPARAM>(TRUE), 0);
- if (table_->observer())
- table_->observer()->OnSelectionChanged();
-}
-
-void NativeTableWin::OnSelectedStateChanged() {
- if (!ignore_listview_change_ && table_->observer())
- table_->observer()->OnSelectionChanged();
-}
-
-void NativeTableWin::OnDoubleClick() {
- if (!ignore_listview_change_ && table_->observer())
- table_->observer()->OnDoubleClick();
-}
-
-void NativeTableWin::OnMiddleClick() {
- if (!ignore_listview_change_ && table_->observer())
- table_->observer()->OnMiddleClick();
-}
-
-bool NativeTableWin::OnKeyDown(ui::KeyboardCode virtual_keycode) {
- if (!ignore_listview_change_ && table_->observer())
- table_->observer()->OnKeyDown(virtual_keycode);
- return false; // Let the key event be processed as ususal.
-}
-
-LRESULT NativeTableWin::OnCustomDraw(NMLVCUSTOMDRAW* draw_info) {
- switch (draw_info->nmcd.dwDrawStage) {
- case CDDS_PREPAINT: {
- return CDRF_NOTIFYITEMDRAW;
- }
- case CDDS_ITEMPREPAINT: {
- // The list-view is about to paint an item, tell it we want to
- // notified when it paints every subitem.
- LRESULT r = CDRF_NOTIFYSUBITEMDRAW;
- if (table_->type() == ICON_AND_TEXT)
- r |= CDRF_NOTIFYPOSTPAINT;
- return r;
- }
- case CDDS_ITEMPREPAINT | CDDS_SUBITEM: {
- // TODO(jcampan): implement custom colors and fonts.
- return CDRF_DODEFAULT;
- }
- case CDDS_ITEMPOSTPAINT: {
- DCHECK(table_->type() == ICON_AND_TEXT);
- int view_index = static_cast<int>(draw_info->nmcd.dwItemSpec);
- // We get notifications for empty items, just ignore them.
- if (view_index >= table_->model()->RowCount())
- return CDRF_DODEFAULT;
- LRESULT r = CDRF_DODEFAULT;
- // First let's take care of painting the right icon.
- if (table_->type() == ICON_AND_TEXT) {
- SkBitmap image = table_->model()->GetIcon(view_index);
- if (!image.isNull()) {
- // Get the rect that holds the icon.
- RECT icon_rect, client_rect;
- if (ListView_GetItemRect(native_view(), view_index, &icon_rect,
- LVIR_ICON) &&
- GetClientRect(native_view(), &client_rect)) {
- RECT intersection;
- // Client rect includes the header but we need to make sure we don't
- // paint into it.
- client_rect.top += content_offset_;
- // Make sure the region need to paint is visible.
- if (IntersectRect(&intersection, &icon_rect, &client_rect)) {
- gfx::CanvasSkia canvas(icon_rect.right - icon_rect.left,
- icon_rect.bottom - icon_rect.top, false);
-
- // It seems the state in nmcd.uItemState is not correct.
- // We'll retrieve it explicitly.
- int selected = ListView_GetItemState(
- native_view(), view_index, LVIS_SELECTED | LVIS_DROPHILITED);
- bool drop_highlight = ((selected & LVIS_DROPHILITED) != 0);
- int bg_color_index;
- if (!IsEnabled())
- bg_color_index = COLOR_3DFACE;
- else if (drop_highlight)
- bg_color_index = COLOR_HIGHLIGHT;
- else if (selected)
- bg_color_index = HasFocus() ? COLOR_HIGHLIGHT : COLOR_3DFACE;
- else
- bg_color_index = COLOR_WINDOW;
- // NOTE: This may be invoked without the ListView filling in the
- // background (or rather windows paints background, then invokes
- // this twice). As such, we always fill in the background.
- canvas.sk_canvas()->drawColor(
- skia::COLORREFToSkColor(GetSysColor(bg_color_index)),
- SkXfermode::kSrc_Mode);
- // + 1 for padding (we declared the image as 18x18 in the list-
- // view when they are 16x16 so we get an extra pixel of padding).
- canvas.DrawBitmapInt(image, 0, 0,
- image.width(), image.height(),
- 1, 1,
- gfx::kFaviconSize, gfx::kFaviconSize, true);
-
- // Only paint the visible region of the icon.
- RECT to_draw = { intersection.left - icon_rect.left,
- intersection.top - icon_rect.top,
- 0, 0 };
- to_draw.right = to_draw.left +
- (intersection.right - intersection.left);
- to_draw.bottom = to_draw.top +
- (intersection.bottom - intersection.top);
- skia::DrawToNativeContext(canvas.sk_canvas(), draw_info->nmcd.hdc,
- intersection.left, intersection.top,
- &to_draw);
- r = CDRF_SKIPDEFAULT;
- }
- }
- }
- }
- return r;
- }
- default:
- return CDRF_DODEFAULT;
- }
-}
-
-void NativeTableWin::UpdateListViewCache(int start, int length, bool add) {
- LVITEM item = {0};
- int start_column = 0;
- int max_row = start + length;
- if (add) {
- item.mask |= LVIF_PARAM;
- for (int i = start; i < max_row; ++i) {
- item.iItem = i;
- item.lParam = i;
- ignore_listview_change_ = true;
- ListView_InsertItem(native_view(), &item);
- ignore_listview_change_ = false;
- }
- }
-
- memset(&item, 0, sizeof(LVITEM));
- item.stateMask = 0;
- item.mask = LVIF_TEXT;
- if (table_->type() == ICON_AND_TEXT)
- item.mask |= LVIF_IMAGE;
-
- for (size_t j = start_column; j < table_->GetVisibleColumnCount(); ++j) {
- ui::TableColumn col = table_->GetVisibleColumnAt(j);
- int max_text_width = ListView_GetStringWidth(native_view(),
- col.title.c_str());
- for (int i = start; i < max_row; ++i) {
- item.iItem = i;
- item.iSubItem = j;
- string16 text = table_->model()->GetText(i, col.id);
- item.pszText = const_cast<LPWSTR>(text.c_str());
- item.iImage = 0;
- ListView_SetItem(native_view(), &item);
-
- // Compute width in px, using current font.
- int string_width = ListView_GetStringWidth(native_view(), item.pszText);
- // The width of an icon belongs to the first column.
- if (j == 0 && table_->type() == ICON_AND_TEXT)
- string_width += kListViewIconWidthAndPadding;
- max_text_width = std::max(string_width, max_text_width);
- }
-
- // ListView_GetStringWidth must be padded or else truncation will occur
- // (MSDN). 15px matches the Win32/LVSCW_AUTOSIZE_USEHEADER behavior.
- max_text_width += kListViewTextPadding;
-
- // Protect against partial update.
- if (max_text_width > col.min_visible_width ||
- (start == 0 && length == table_->model()->RowCount())) {
- col.min_visible_width = max_text_width;
- }
- }
-}
-
-void NativeTableWin::UpdateContentOffset() {
- content_offset_ = 0;
-
- if (!native_view())
- return;
-
- HWND header = ListView_GetHeader(native_view());
- if (!header)
- return;
-
- POINT origin = {0, 0};
- MapWindowPoints(header, native_view(), &origin, 1);
-
- RECT header_bounds;
- GetWindowRect(header, &header_bounds);
-
- content_offset_ = origin.y + header_bounds.bottom - header_bounds.top;
-}
-
-static int GetViewIndexFromMouseEvent(HWND window, LPARAM l_param) {
- int x = GET_X_LPARAM(l_param);
- int y = GET_Y_LPARAM(l_param);
- LVHITTESTINFO hit_info = {0};
- hit_info.pt.x = x;
- hit_info.pt.y = y;
- return ListView_HitTest(window, &hit_info);
-}
-
-// static
-LRESULT CALLBACK NativeTableWin::TableWndProc(HWND window,
- UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- NativeTableWin* native_table_win = reinterpret_cast<NativeTableWin*>(
- GetWindowLongPtr(window, GWLP_USERDATA));
- TableView2* table = native_table_win->table_;
-
- // Is the mouse down on the table?
- static bool in_mouse_down = false;
- // Should we select on mouse up?
- static bool select_on_mouse_up = false;
-
- // If the mouse is down, this is the location of the mouse down message.
- static int mouse_down_x, mouse_down_y;
-
- switch (message) {
- case WM_CONTEXTMENU: {
- // This addresses two problems seen with context menus in right to left
- // locales:
- // 1. The mouse coordinates in the l_param were occasionally wrong in
- // weird ways. This is most often seen when right clicking on the
- // list-view twice in a row.
- // 2. Right clicking on the icon would show the scrollbar menu.
- //
- // As a work around this uses the position of the cursor and ignores
- // the position supplied in the l_param.
- if (base::i18n::IsRTL() &&
- (GET_X_LPARAM(l_param) != -1 || GET_Y_LPARAM(l_param) != -1)) {
- POINT screen_point;
- GetCursorPos(&screen_point);
- POINT table_point = screen_point;
- RECT client_rect;
- if (ScreenToClient(window, &table_point) &&
- GetClientRect(window, &client_rect) &&
- PtInRect(&client_rect, table_point)) {
- // The point is over the client area of the table, handle it ourself.
- // But first select the row if it isn't already selected.
- LVHITTESTINFO hit_info = {0};
- hit_info.pt.x = table_point.x;
- hit_info.pt.y = table_point.y;
- int view_index = ListView_HitTest(window, &hit_info);
- // TODO(jcampan): fix code below
- // if (view_index != -1 && table->IsItemSelected(view_index))
- // table->Select(view_index);
- // table->OnContextMenu(screen_point);
- return 0; // So that default processing doesn't occur.
- }
- }
- // else case: default handling is fine, so break and let the default
- // handler service the request (which will likely calls us back with
- // OnContextMenu).
- break;
- }
-
- case WM_CANCELMODE: {
- if (in_mouse_down) {
- in_mouse_down = false;
- return 0;
- }
- break;
- }
-
- case WM_ERASEBKGND:
- // We make WM_ERASEBKGND do nothing (returning 1 indicates we handled
- // the request). We do this so that the table view doesn't flicker during
- // resizing.
- return 1;
-
- case WM_KEYDOWN: {
- if (!table->single_selection() && w_param == 'A' &&
- GetKeyState(VK_CONTROL) < 0 && table->model()->RowCount() > 0) {
- // Select everything.
- ListView_SetItemState(window, -1, LVIS_SELECTED, LVIS_SELECTED);
- // And make the first row focused.
- ListView_SetItemState(window, 0, LVIS_FOCUSED, LVIS_FOCUSED);
- return 0;
- } else if (w_param == VK_DELETE && table->observer()) {
- table->observer()->OnTableView2Delete(table);
- return 0;
- }
- // else case: fall through to default processing.
- break;
- }
-
- case WM_LBUTTONDBLCLK: {
- if (w_param == MK_LBUTTON)
- native_table_win->OnDoubleClick();
- return 0;
- }
-
- case WM_MBUTTONDOWN: {
- if (w_param == MK_MBUTTON) {
- int view_index = GetViewIndexFromMouseEvent(window, l_param);
- if (view_index != -1) {
- // Clear all and select the row that was middle clicked.
- native_table_win->Select(view_index);
- native_table_win->OnMiddleClick();
- }
- }
- return 0;
- }
-
- case WM_LBUTTONUP: {
- if (in_mouse_down) {
- in_mouse_down = false;
- ReleaseCapture();
- ::SetFocus(window);
- if (select_on_mouse_up) {
- int view_index = GetViewIndexFromMouseEvent(window, l_param);
- if (view_index != -1)
- native_table_win->Select(view_index);
- }
- return 0;
- }
- break;
- }
-
- case WM_LBUTTONDOWN: {
- // ListView treats clicking on an area outside the text of a column as
- // drag to select. This is confusing when the selection is shown across
- // the whole row. For this reason we override the default handling for
- // mouse down/move/up and treat the whole row as draggable. That is, no
- // matter where you click in the row we'll attempt to start dragging.
- //
- // Only do custom mouse handling if no other mouse buttons are down.
- if ((w_param | (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) ==
- (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) {
- if (in_mouse_down)
- return 0;
-
- int view_index = GetViewIndexFromMouseEvent(window, l_param);
- if (view_index != -1) {
- native_table_win->ignore_listview_change_ = true;
- in_mouse_down = true;
- select_on_mouse_up = false;
- mouse_down_x = GET_X_LPARAM(l_param);
- mouse_down_y = GET_Y_LPARAM(l_param);
- bool select = true;
- if (w_param & MK_CONTROL) {
- select = false;
- if (!native_table_win->IsRowSelected(view_index)) {
- if (table->single_selection()) {
- // Single selection mode and the row isn't selected, select
- // only it.
- native_table_win->Select(view_index);
- } else {
- // Not single selection, add this row to the selection.
- native_table_win->SetSelectedState(view_index, true);
- }
- } else {
- // Remove this row from the selection.
- native_table_win->SetSelectedState(view_index, false);
- }
- ListView_SetSelectionMark(window, view_index);
- } else if (!table->single_selection() && w_param & MK_SHIFT) {
- int mark_view_index = ListView_GetSelectionMark(window);
- if (mark_view_index != -1) {
- // Unselect everything.
- ListView_SetItemState(window, -1, 0, LVIS_SELECTED);
- select = false;
-
- // Select from mark to mouse down location.
- for (int i = std::min(view_index, mark_view_index),
- max_i = std::max(view_index, mark_view_index); i <= max_i;
- ++i) {
- native_table_win->SetSelectedState(i, true);
- }
- }
- }
- // Make the row the user clicked on the focused row.
- ListView_SetItemState(window, view_index, LVIS_FOCUSED,
- LVIS_FOCUSED);
- if (select) {
- if (!native_table_win->IsRowSelected(view_index)) {
- // Clear all.
- ListView_SetItemState(window, -1, 0, LVIS_SELECTED);
- // And select the row the user clicked on.
- native_table_win->SetSelectedState(view_index, true);
- } else {
- // The item is already selected, don't clear the state right away
- // in case the user drags. Instead wait for mouse up, then only
- // select the row the user clicked on.
- select_on_mouse_up = true;
- }
- ListView_SetSelectionMark(window, view_index);
- }
- native_table_win->ignore_listview_change_ = false;
- table->observer()->OnSelectionChanged();
- SetCapture(window);
- return 0;
- }
- // else case, continue on to default handler
- }
- break;
- }
-
- case WM_MOUSEMOVE: {
- if (in_mouse_down) {
- int x = GET_X_LPARAM(l_param);
- int y = GET_Y_LPARAM(l_param);
- if (View::ExceededDragThreshold(x - mouse_down_x, y - mouse_down_y)) {
- // We're about to start drag and drop, which results in no mouse up.
- // Release capture and reset state.
- ReleaseCapture();
- in_mouse_down = false;
-
- NMLISTVIEW details;
- memset(&details, 0, sizeof(details));
- details.hdr.code = LVN_BEGINDRAG;
- SendMessage(::GetParent(window), WM_NOTIFY, 0,
- reinterpret_cast<LPARAM>(&details));
- }
- return 0;
- }
- break;
- }
-
- default:
- break;
- }
-
- DCHECK(native_table_win->original_handler_);
- return CallWindowProc(native_table_win->original_handler_, window, message,
- w_param, l_param);
-}
-
-LRESULT CALLBACK NativeTableWin::TableHeaderWndProc(HWND window, UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- NativeTableWin* native_table_win = reinterpret_cast<NativeTableWin*>(
- GetWindowLongPtr(window, GWLP_USERDATA));
-
- switch (message) {
- case WM_SETCURSOR:
- if (!native_table_win->table_->resizable_columns())
- // Prevents the cursor from changing to the resize cursor.
- return TRUE;
- break;
- // TODO(jcampan): we should also block single click messages on the
- // separator as right now columns can still be resized.
- case WM_LBUTTONDBLCLK:
- if (!native_table_win->table_->resizable_columns())
- // Prevents the double-click on the column separator from auto-resizing
- // the column.
- return TRUE;
- break;
- default:
- break;
- }
- DCHECK(native_table_win->header_original_handler_);
- return CallWindowProc(native_table_win->header_original_handler_,
- window, message, w_param, l_param);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeTableWrapper, public:
-
-// static
-NativeTableWrapper* NativeTableWrapper::CreateNativeWrapper(TableView2* table) {
- return new NativeTableWin(table);
-}
-
-} // namespace views
« no previous file with comments | « views/controls/table/native_table_win.h ('k') | views/controls/table/native_table_wrapper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698