1221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// Use of this source code is governed by a BSD-style license that can be
3221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// found in the LICENSE file.
4221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
5221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/views/controls/table/table_header.h"
6221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
7221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "third_party/skia/include/core/SkColor.h"
8221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/base/cursor/cursor.h"
9221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/gfx/canvas.h"
10221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/gfx/text_utils.h"
11221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/native_theme/native_theme.h"
12221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/views/background.h"
13221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/views/controls/table/table_utils.h"
14221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/views/controls/table/table_view.h"
15221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "ui/views/native_cursor.h"
16221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
17221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromnamespace views {
18221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
19221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromnamespace {
20221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
21221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst int kVerticalPadding = 4;
22221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
23221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// The minimum width we allow a column to go down to.
24221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst int kMinColumnWidth = 10;
25221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
26221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// Distace from edge columns can be resized by.
27221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst int kResizePadding = 5;
28221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
29221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// Amount of space above/below the separator.
30221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst int kSeparatorPadding = 4;
31221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
32221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst SkColor kTextColor = SK_ColorBLACK;
33221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst SkColor kBackgroundColor1 = SkColorSetRGB(0xF9, 0xF9, 0xF9);
34221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst SkColor kBackgroundColor2 = SkColorSetRGB(0xE8, 0xE8, 0xE8);
35221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst SkColor kSeparatorColor = SkColorSetRGB(0xAA, 0xAA, 0xAA);
36221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
37221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// Size of the sort indicator (doesn't include padding).
38221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst int kSortIndicatorSize = 8;
39221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
40221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}  // namespace
41221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
42221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// static
43221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst int TableHeader::kHorizontalPadding = 7;
44221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom// static
45221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromconst int TableHeader::kSortIndicatorWidth = kSortIndicatorSize +
46221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    TableHeader::kHorizontalPadding * 2;
47221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
48221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromtypedef std::vector<TableView::VisibleColumn> Columns;
49221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
50221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromTableHeader::TableHeader(TableView* table) : table_(table) {
51392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom  set_background(Background::CreateVerticalGradientBackground(
52392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom                     kBackgroundColor1, kBackgroundColor2));
53221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
54221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
55221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromTableHeader::~TableHeader() {
56221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
57221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
58221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromvoid TableHeader::Layout() {
59221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  SetBounds(x(), y(), table_->width(), GetPreferredSize().height());
60221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
61221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
62392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid TableHeader::OnPaint(gfx::Canvas* canvas) {
63221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  // Paint the background and a separator at the bottom. The separator color
64221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  // matches that of the border around the scrollview.
65221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  OnPaintBackground(canvas);
66221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  SkColor border_color = GetNativeTheme()->GetSystemColor(
67221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      ui::NativeTheme::kColorId_UnfocusedBorderColor);
68221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  canvas->DrawLine(gfx::Point(0, height() - 1),
69221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom                   gfx::Point(width(), height() - 1), border_color);
70221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
71221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  const Columns& columns = table_->visible_columns();
72221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  const int sorted_column_id = table_->sort_descriptors().empty() ? -1 :
73221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      table_->sort_descriptors()[0].column_id;
74221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  for (size_t i = 0; i < columns.size(); ++i) {
75221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    if (columns[i].width >= 2) {
76221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      const int separator_x = GetMirroredXInView(
77221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          columns[i].x + columns[i].width - 1);
78221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      canvas->DrawLine(gfx::Point(separator_x, kSeparatorPadding),
79221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom                       gfx::Point(separator_x, height() - kSeparatorPadding),
80221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom                       kSeparatorColor);
81221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    }
82221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
83221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    const int x = columns[i].x + kHorizontalPadding;
84221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    int width = columns[i].width - kHorizontalPadding - kHorizontalPadding;
85221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    if (width <= 0)
86221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      continue;
87221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
88221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    const int title_width =
89221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        gfx::GetStringWidth(columns[i].column.title, font_list_);
90221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    const bool paint_sort_indicator =
91221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        (columns[i].column.id == sorted_column_id &&
92221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom         title_width + kSortIndicatorWidth <= width);
93221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
94221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    if (paint_sort_indicator &&
95221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        columns[i].column.alignment == ui::TableColumn::RIGHT) {
96221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      width -= kSortIndicatorWidth;
97221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    }
98221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
99221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    canvas->DrawStringRectWithFlags(
100221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        columns[i].column.title, font_list_, kTextColor,
101221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        gfx::Rect(GetMirroredXWithWidthInView(x, width), kVerticalPadding,
102221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom                  width, height() - kVerticalPadding * 2),
103221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        TableColumnAlignmentToCanvasAlignment(columns[i].column.alignment));
104221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
105221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    if (paint_sort_indicator) {
106221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      SkPaint paint;
107221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      paint.setColor(kTextColor);
108221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      paint.setStyle(SkPaint::kFill_Style);
109221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      paint.setAntiAlias(true);
110221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
111221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      int indicator_x = 0;
112221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      ui::TableColumn::Alignment alignment = columns[i].column.alignment;
113221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      if (base::i18n::IsRTL()) {
114221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        if (alignment == ui::TableColumn::LEFT)
115221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          alignment = ui::TableColumn::RIGHT;
116221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        else if (alignment == ui::TableColumn::RIGHT)
117221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          alignment = ui::TableColumn::LEFT;
118221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      }
119221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      switch (alignment) {
120ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root        case ui::TableColumn::LEFT:
121221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          indicator_x = x + title_width;
122221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          break;
123221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        case ui::TableColumn::CENTER:
124221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          indicator_x = x + width / 2;
125221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          break;
126221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        case ui::TableColumn::RIGHT:
127221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          indicator_x = x + width;
128221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom          break;
129221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      }
130221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
131221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      const int scale = base::i18n::IsRTL() ? -1 : 1;
132221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      indicator_x += (kSortIndicatorWidth - kSortIndicatorSize) / 2;
133221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      indicator_x = GetMirroredXInView(indicator_x);
134221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      int indicator_y = height() / 2 - kSortIndicatorSize / 2;
135221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      SkPath indicator_path;
136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      if (table_->sort_descriptors()[0].ascending) {
137221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        indicator_path.moveTo(
138221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom            SkIntToScalar(indicator_x),
139221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom            SkIntToScalar(indicator_y + kSortIndicatorSize));
140ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root        indicator_path.lineTo(
141221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom            SkIntToScalar(indicator_x + kSortIndicatorSize * scale),
142ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root            SkIntToScalar(indicator_y + kSortIndicatorSize));
143ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root        indicator_path.lineTo(
144221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom            SkIntToScalar(indicator_x + kSortIndicatorSize / 2 * scale),
145ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root            SkIntToScalar(indicator_y));
146ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root      } else {
147221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        indicator_path.moveTo(SkIntToScalar(indicator_x),
148221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom                              SkIntToScalar(indicator_y));
149221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        indicator_path.lineTo(
150221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom            SkIntToScalar(indicator_x + kSortIndicatorSize * scale),
151221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom            SkIntToScalar(indicator_y));
152221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        indicator_path.lineTo(
153221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom            SkIntToScalar(indicator_x + kSortIndicatorSize / 2 * scale),
154221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom            SkIntToScalar(indicator_y + kSortIndicatorSize));
155221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      }
156221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      indicator_path.close();
157221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      canvas->DrawPath(indicator_path, paint);
158221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    }
159221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  }
160221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
161221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
162221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromgfx::Size TableHeader::GetPreferredSize() const {
163221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  return gfx::Size(1, kVerticalPadding * 2 + font_list_.GetHeight());
164221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
165221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
166221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromgfx::NativeCursor TableHeader::GetCursor(const ui::MouseEvent& event) {
167221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  return GetResizeColumn(GetMirroredXInView(event.x())) != -1 ?
168221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      GetNativeColumnResizeCursor() : View::GetCursor(event);
169221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
170ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
171221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrombool TableHeader::OnMousePressed(const ui::MouseEvent& event) {
172ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root  if (event.IsOnlyLeftMouseButton()) {
173ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root    StartResize(event);
174ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root    return true;
175221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  }
176ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
177ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root  // Return false so that context menus on ancestors work.
178ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root  return false;
179ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root}
180221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
181221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrombool TableHeader::OnMouseDragged(const ui::MouseEvent& event) {
182221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  ContinueResize(event);
183221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  return true;
184221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
185221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
186221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromvoid TableHeader::OnMouseReleased(const ui::MouseEvent& event) {
187221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  const bool was_resizing = resize_details_ != NULL;
188221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  resize_details_.reset();
189221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  if (!was_resizing && event.IsOnlyLeftMouseButton())
190221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    ToggleSortOrder(event);
191221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
192221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
193221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromvoid TableHeader::OnMouseCaptureLost() {
194221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  if (is_resizing()) {
195221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    table_->SetVisibleColumnWidth(resize_details_->column_index,
196221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom                                  resize_details_->initial_width);
197221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  }
198221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  resize_details_.reset();
199221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
200221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
201221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromvoid TableHeader::OnGestureEvent(ui::GestureEvent* event) {
202221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  switch (event->type()) {
203221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    case ui::ET_GESTURE_TAP:
204221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom      if (!resize_details_.get())
205221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom        ToggleSortOrder(*event);
206      break;
207    case ui::ET_GESTURE_SCROLL_BEGIN:
208      StartResize(*event);
209      break;
210    case ui::ET_GESTURE_SCROLL_UPDATE:
211      ContinueResize(*event);
212      break;
213    case ui::ET_GESTURE_SCROLL_END:
214      resize_details_.reset();
215      break;
216    default:
217      return;
218  }
219  event->SetHandled();
220}
221
222bool TableHeader::StartResize(const ui::LocatedEvent& event) {
223  if (is_resizing())
224    return false;
225
226  const int index = GetResizeColumn(GetMirroredXInView(event.x()));
227  if (index == -1)
228    return false;
229
230  resize_details_.reset(new ColumnResizeDetails);
231  resize_details_->column_index = index;
232  resize_details_->initial_x = event.root_location().x();
233  resize_details_->initial_width = table_->visible_columns()[index].width;
234  return true;
235}
236
237void TableHeader::ContinueResize(const ui::LocatedEvent& event) {
238  if (!is_resizing())
239    return;
240
241  const int scale = base::i18n::IsRTL() ? -1 : 1;
242  const int delta = scale *
243      (event.root_location().x() - resize_details_->initial_x);
244  table_->SetVisibleColumnWidth(
245      resize_details_->column_index,
246      std::max(kMinColumnWidth, resize_details_->initial_width + delta));
247}
248
249void TableHeader::ToggleSortOrder(const ui::LocatedEvent& event) {
250  if (table_->visible_columns().empty())
251    return;
252
253  const int x = GetMirroredXInView(event.x());
254  const int index = GetClosestVisibleColumnIndex(table_, x);
255  const TableView::VisibleColumn& column(table_->visible_columns()[index]);
256  if (x >= column.x && x < column.x + column.width && event.y() >= 0 &&
257      event.y() < height())
258    table_->ToggleSortOrder(index);
259}
260
261int TableHeader::GetResizeColumn(int x) const {
262  const Columns& columns(table_->visible_columns());
263  if (columns.empty())
264    return -1;
265
266  const int index = GetClosestVisibleColumnIndex(table_, x);
267  DCHECK_NE(-1, index);
268  const TableView::VisibleColumn& column(table_->visible_columns()[index]);
269  if (index > 0 && x >= column.x - kResizePadding &&
270      x <= column.x + kResizePadding) {
271    return index - 1;
272  }
273  const int max_x = column.x + column.width;
274  return (x >= max_x - kResizePadding && x <= max_x + kResizePadding) ?
275      index : -1;
276}
277
278}  // namespace views
279