Index: ui/views/controls/table/table_view_views.cc |
diff --git a/ui/views/controls/table/table_view_views.cc b/ui/views/controls/table/table_view_views.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7ac75e5afe7d2beb7e8f4dfcd35882568197a0c5 |
--- /dev/null |
+++ b/ui/views/controls/table/table_view_views.cc |
@@ -0,0 +1,287 @@ |
+// Copyright (c) 2012 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 "ui/views/controls/table/table_view_views.h" |
+ |
+#include "base/i18n/rtl.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
+#include "ui/base/models/table_model.h" |
+#include "ui/gfx/canvas_skia.h" |
+#include "ui/gfx/native_theme.h" |
+#include "ui/gfx/skia_util.h" |
+#include "ui/views/border.h" |
+#include "ui/views/controls/scroll_view.h" |
+#include "ui/views/controls/table/table_view_observer.h" |
+ |
+// Padding around the text (on each side). |
+static const int kTextVerticalPadding = 3; |
+static const int kTextHorizontalPadding = 2; |
+ |
+// TODO: these should come from native theme or something. |
+static const SkColor kSelectedBackgroundColor = SkColorSetRGB(0xEE, 0xEE, 0xEE); |
+static const SkColor kTextColor = SK_ColorBLACK; |
+ |
+// Size of images. |
+static const int kImageSize = 16; |
+ |
+// Padding between the image and text. |
+static const int kImageToTextPadding = 4; |
+ |
+namespace views { |
+ |
+ |
+TableView::TableView(ui::TableModel* model, |
+ const std::vector<ui::TableColumn>& columns, |
+ TableTypes table_type, |
+ bool single_selection, |
+ bool resizable_columns, |
+ bool autosize_columns) |
+ : model_(model), |
+ table_type_(table_type), |
+ table_view_observer_(NULL), |
+ selected_row_(-1), |
+ row_height_(font_.GetHeight() + kTextVerticalPadding * 2) { |
+ // This implementation only shows a single column. |
+ DCHECK_EQ(1u, columns.size()); |
+ // CHECK_BOX_AND_TEXT is not supported. |
+ DCHECK(table_type == TEXT_ONLY || table_type == ICON_AND_TEXT); |
+ set_focusable(true); |
+ set_background(Background::CreateSolidBackground(SK_ColorWHITE)); |
+} |
+ |
+TableView::~TableView() { |
+ if (model_) |
+ model_->SetObserver(NULL); |
+} |
+ |
+void TableView::SetModel(ui::TableModel* model) { |
+ if (model == model_) |
+ return; |
+ |
+ if (model_) |
+ model_->SetObserver(NULL); |
+ model_ = model; |
+ if (RowCount()) |
+ selected_row_ = 0; |
+ if (model_) |
+ model_->SetObserver(this); |
+} |
+ |
+View* TableView::CreateParentIfNecessary() { |
+ ScrollView* scroll_view = new ScrollView; |
+ scroll_view->SetContents(this); |
+ scroll_view->set_border(Border::CreateSolidBorder( |
+ 1, gfx::NativeTheme::instance()->GetSystemColor( |
+ gfx::NativeTheme::kColorId_UnfocusedBorderColor))); |
+ return scroll_view; |
+} |
+ |
+int TableView::RowCount() const { |
+ return model_ ? model_->RowCount() : 0; |
+} |
+ |
+int TableView::SelectedRowCount() { |
+ return selected_row_ != -1 ? 1 : 0; |
+} |
+ |
+void TableView::Select(int model_row) { |
+ if (!model_) |
+ return; |
+ |
+ if (model_row == selected_row_) |
+ return; |
+ |
+ DCHECK(model_row >= 0 && model_row < RowCount()); |
+ selected_row_ = model_row; |
+ if (selected_row_ != -1) |
+ ScrollRectToVisible(GetRowBounds(selected_row_)); |
+ SchedulePaint(); |
+ if (table_view_observer_) |
+ table_view_observer_->OnSelectionChanged(); |
+} |
+ |
+int TableView::FirstSelectedRow() { |
+ return selected_row_; |
+} |
+ |
+void TableView::Layout() { |
+ // We have to override Layout like this since we're contained in a ScrollView. |
+ gfx::Size pref = GetPreferredSize(); |
+ int width = pref.width(); |
+ int height = pref.height(); |
+ if (parent()) { |
+ width = std::max(parent()->width(), width); |
+ height = std::max(parent()->height(), height); |
+ } |
+ SetBounds(x(), y(), width, height); |
+} |
+ |
+gfx::Size TableView::GetPreferredSize() { |
+ return gfx::Size(50, RowCount() * row_height_); |
+} |
+ |
+bool TableView::OnKeyPressed(const KeyEvent& event) { |
+ if (!HasFocus()) |
+ return false; |
+ |
+ switch (event.key_code()) { |
+ case ui::VKEY_UP: |
+ if (selected_row_ > 0) |
+ Select(selected_row_ - 1); |
+ else if (selected_row_ == -1 && RowCount()) |
+ Select(RowCount() - 1); |
+ return true; |
+ |
+ case ui::VKEY_DOWN: |
+ if (selected_row_ == -1) { |
+ if (RowCount()) |
+ Select(0); |
+ } else if (selected_row_ + 1 < RowCount()) { |
+ Select(selected_row_ + 1); |
+ } |
+ return true; |
+ |
+ default: |
+ break; |
+ } |
+ return false; |
+} |
+ |
+bool TableView::OnMousePressed(const MouseEvent& event) { |
+ RequestFocus(); |
+ int row = event.y() / row_height_; |
+ if (row >= 0 && row < RowCount()) { |
+ Select(row); |
+ if (table_view_observer_ && event.flags() & ui::EF_IS_DOUBLE_CLICK) |
+ table_view_observer_->OnDoubleClick(); |
+ } |
+ return true; |
+} |
+ |
+void TableView::OnModelChanged() { |
+ if (RowCount()) |
+ selected_row_ = 0; |
+ else |
+ selected_row_ = -1; |
+ NumRowsChanged(); |
+} |
+ |
+void TableView::OnItemsChanged(int start, int length) { |
+ SchedulePaint(); |
+} |
+ |
+void TableView::OnItemsAdded(int start, int length) { |
+ if (selected_row_ >= start) |
+ selected_row_ += length; |
+ NumRowsChanged(); |
+} |
+ |
+void TableView::OnItemsRemoved(int start, int length) { |
+ bool notify_selection_changed = false; |
+ if (selected_row_ >= (start + length)) { |
+ selected_row_ -= length; |
+ if (selected_row_ == 0 && RowCount() == 0) { |
+ selected_row_ = -1; |
+ notify_selection_changed = true; |
+ } |
+ } else if (selected_row_ >= start) { |
+ selected_row_ = start; |
+ if (selected_row_ == RowCount()) |
+ selected_row_--; |
+ notify_selection_changed = true; |
+ } |
+ if (table_view_observer_ && notify_selection_changed) |
+ table_view_observer_->OnSelectionChanged(); |
+} |
+ |
+gfx::Point TableView::GetKeyboardContextMenuLocation() { |
+ int first_selected = FirstSelectedRow(); |
+ gfx::Rect vis_bounds(GetVisibleBounds()); |
+ int y = vis_bounds.height() / 2; |
+ if (first_selected != -1) { |
+ gfx::Rect cell_bounds(GetRowBounds(first_selected)); |
+ if (cell_bounds.bottom() >= vis_bounds.y() && |
+ cell_bounds.bottom() < vis_bounds.bottom()) { |
+ y = cell_bounds.bottom(); |
+ } |
+ } |
+ gfx::Point screen_loc(0, y); |
+ if (base::i18n::IsRTL()) |
+ screen_loc.set_x(width()); |
+ ConvertPointToScreen(this, &screen_loc); |
+ return screen_loc; |
+} |
+ |
+void TableView::OnPaint(gfx::Canvas* canvas) { |
+ // Don't invoke View::OnPaint so that we can render our own focus border. |
+ OnPaintBackground(canvas); |
+ |
+ if (!RowCount()) |
+ return; |
+ |
+ int min_y, max_y; |
+ { |
+ SkRect sk_clip_rect; |
+ if (canvas->GetSkCanvas()->getClipBounds(&sk_clip_rect)) { |
+ gfx::Rect clip_rect = gfx::SkRectToRect(sk_clip_rect); |
+ min_y = clip_rect.y(); |
+ max_y = clip_rect.bottom(); |
+ } else { |
+ gfx::Rect vis_bounds = GetVisibleBounds(); |
+ min_y = vis_bounds.y(); |
+ max_y = vis_bounds.bottom(); |
+ } |
+ } |
+ |
+ int min_row = std::min(RowCount() - 1, std::max(0, min_y / row_height_)); |
+ int max_row = max_y / row_height_; |
+ if (max_y % row_height_ != 0) |
+ max_row++; |
+ max_row = std::min(max_row, RowCount()); |
+ for (int i = min_row; i < max_row; ++i) { |
+ gfx::Rect row_bounds(GetRowBounds(i)); |
+ if (i == selected_row_) { |
+ canvas->FillRect(kSelectedBackgroundColor, row_bounds); |
+ if (HasFocus()) |
+ canvas->DrawFocusRect(row_bounds); |
+ } |
+ int text_x = kTextHorizontalPadding; |
+ if (table_type_ == ICON_AND_TEXT) { |
+ SkBitmap image = model_->GetIcon(i); |
+ if (!image.isNull()) { |
+ canvas->DrawBitmapInt( |
+ image, 0, 0, image.width(), image.height(), |
+ text_x, row_bounds.y() + (row_bounds.height() - kImageSize) / 2, |
+ kImageSize, kImageSize, true); |
+ } |
+ text_x += kImageSize + kImageToTextPadding; |
+ } |
+ canvas->DrawStringInt(model_->GetText(i, 0), font_, kTextColor, |
+ text_x, |
+ row_bounds.y() + kTextVerticalPadding, |
+ row_bounds.width() - text_x, |
+ row_bounds.height() - kTextVerticalPadding * 2); |
+ } |
+} |
+ |
+void TableView::OnFocus() { |
+ if (selected_row_ != -1) |
+ SchedulePaintInRect(GetRowBounds(selected_row_)); |
+} |
+ |
+void TableView::OnBlur() { |
+ if (selected_row_ != -1) |
+ SchedulePaintInRect(GetRowBounds(selected_row_)); |
+} |
+ |
+void TableView::NumRowsChanged() { |
+ PreferredSizeChanged(); |
+ SchedulePaint(); |
+} |
+ |
+gfx::Rect TableView::GetRowBounds(int row) { |
+ return gfx::Rect(0, row * row_height_, width(), row_height_); |
+} |
+ |
+} // namespace views |