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

Side by Side Diff: ui/views/controls/tree/tree_view.cc

Issue 2050813002: MacViews: support backgrounds for selected rows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: placate msvc Created 4 years, 3 months 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
« no previous file with comments | « ui/views/controls/tree/tree_view.h ('k') | ui/views/style/platform_style.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ui/views/controls/tree/tree_view.h" 5 #include "ui/views/controls/tree/tree_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/i18n/rtl.h" 9 #include "base/i18n/rtl.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
11 #include "ui/accessibility/ax_view_state.h" 11 #include "ui/accessibility/ax_view_state.h"
12 #include "ui/base/ime/input_method.h" 12 #include "ui/base/ime/input_method.h"
13 #include "ui/base/resource/resource_bundle.h" 13 #include "ui/base/resource/resource_bundle.h"
14 #include "ui/events/event.h" 14 #include "ui/events/event.h"
15 #include "ui/events/keycodes/keyboard_codes.h" 15 #include "ui/events/keycodes/keyboard_codes.h"
16 #include "ui/gfx/canvas.h" 16 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/geometry/rect.h" 17 #include "ui/gfx/geometry/rect.h"
18 #include "ui/gfx/geometry/rect_conversions.h" 18 #include "ui/gfx/geometry/rect_conversions.h"
19 #include "ui/gfx/image/image.h" 19 #include "ui/gfx/image/image.h"
20 #include "ui/gfx/skia_util.h" 20 #include "ui/gfx/skia_util.h"
21 #include "ui/native_theme/native_theme.h" 21 #include "ui/native_theme/native_theme.h"
22 #include "ui/resources/grit/ui_resources.h" 22 #include "ui/resources/grit/ui_resources.h"
23 #include "ui/views/controls/prefix_selector.h" 23 #include "ui/views/controls/prefix_selector.h"
24 #include "ui/views/controls/scroll_view.h" 24 #include "ui/views/controls/scroll_view.h"
25 #include "ui/views/controls/textfield/textfield.h" 25 #include "ui/views/controls/textfield/textfield.h"
26 #include "ui/views/controls/tree/tree_view_controller.h" 26 #include "ui/views/controls/tree/tree_view_controller.h"
27 #include "ui/views/resources/grit/views_resources.h" 27 #include "ui/views/resources/grit/views_resources.h"
28 #include "ui/views/style/platform_style.h"
28 29
29 using ui::TreeModel; 30 using ui::TreeModel;
30 using ui::TreeModelNode; 31 using ui::TreeModelNode;
31 32
32 namespace views { 33 namespace views {
33 34
34 // Insets around the view. 35 // Insets around the view.
35 static const int kHorizontalInset = 2; 36 static const int kHorizontalInset = 2;
36 static const int kVerticalInset = 2; 37 static const int kVerticalInset = 2;
37 // Padding before/after the image. 38 // Padding before/after the image.
(...skipping 23 matching lines...) Expand all
61 // and |is_selected| is true if the item is selected. 62 // and |is_selected| is true if the item is selected.
62 ui::NativeTheme::ColorId text_color_id(bool has_focus, bool is_selected) { 63 ui::NativeTheme::ColorId text_color_id(bool has_focus, bool is_selected) {
63 if (is_selected) { 64 if (is_selected) {
64 if (has_focus) 65 if (has_focus)
65 return ui::NativeTheme::kColorId_TreeSelectedText; 66 return ui::NativeTheme::kColorId_TreeSelectedText;
66 return ui::NativeTheme::kColorId_TreeSelectedTextUnfocused; 67 return ui::NativeTheme::kColorId_TreeSelectedTextUnfocused;
67 } 68 }
68 return ui::NativeTheme::kColorId_TreeText; 69 return ui::NativeTheme::kColorId_TreeText;
69 } 70 }
70 71
72 bool EventIsDoubleTapOrClick(const ui::LocatedEvent& event) {
73 if (event.type() == ui::ET_GESTURE_TAP)
74 return event.AsGestureEvent()->details().tap_count() == 2;
75 return !!(event.flags() & ui::EF_IS_DOUBLE_CLICK);
76 }
77
71 } // namespace 78 } // namespace
72 79
73 TreeView::TreeView() 80 TreeView::TreeView()
74 : model_(NULL), 81 : model_(NULL),
75 selected_node_(NULL), 82 selected_node_(NULL),
76 editing_(false), 83 editing_(false),
77 editor_(NULL), 84 editor_(NULL),
78 focus_manager_(NULL), 85 focus_manager_(NULL),
79 auto_expand_children_(false), 86 auto_expand_children_(false),
80 editable_(true), 87 editable_(true),
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 SchedulePaintForNode(selected_node_); 243 SchedulePaintForNode(selected_node_);
237 selected_node_ = node; 244 selected_node_ = node;
238 if (selected_node_ == &root_ && !root_shown_) 245 if (selected_node_ == &root_ && !root_shown_)
239 selected_node_ = NULL; 246 selected_node_ = NULL;
240 if (selected_node_ && selected_node_ != &root_) 247 if (selected_node_ && selected_node_ != &root_)
241 Expand(model_->GetParent(selected_node_->model_node())); 248 Expand(model_->GetParent(selected_node_->model_node()));
242 SchedulePaintForNode(selected_node_); 249 SchedulePaintForNode(selected_node_);
243 } 250 }
244 251
245 if (selected_node_) 252 if (selected_node_)
246 ScrollRectToVisible(GetBoundsForNode(selected_node_)); 253 ScrollRectToVisible(GetForegroundBoundsForNode(selected_node_));
247 254
248 // Notify controller if the old selection was empty to handle the case of 255 // Notify controller if the old selection was empty to handle the case of
249 // remove explicitly resetting selected_node_ before invoking this. 256 // remove explicitly resetting selected_node_ before invoking this.
250 if (controller_ && (changed || was_empty_selection)) 257 if (controller_ && (changed || was_empty_selection))
251 controller_->OnTreeViewSelectionChanged(this); 258 controller_->OnTreeViewSelectionChanged(this);
252 259
253 if (changed) { 260 if (changed) {
254 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); 261 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
255 NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); 262 NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true);
256 } 263 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 392
386 void TreeView::ShowContextMenu(const gfx::Point& p, 393 void TreeView::ShowContextMenu(const gfx::Point& p,
387 ui::MenuSourceType source_type) { 394 ui::MenuSourceType source_type) {
388 if (!model_) 395 if (!model_)
389 return; 396 return;
390 if (source_type == ui::MENU_SOURCE_MOUSE) { 397 if (source_type == ui::MENU_SOURCE_MOUSE) {
391 // Only invoke View's implementation (which notifies the 398 // Only invoke View's implementation (which notifies the
392 // ContextMenuController) if over a node. 399 // ContextMenuController) if over a node.
393 gfx::Point local_point(p); 400 gfx::Point local_point(p);
394 ConvertPointFromScreen(this, &local_point); 401 ConvertPointFromScreen(this, &local_point);
395 int row = (local_point.y() - kVerticalInset) / row_height_; 402 if (!GetNodeAtPoint(local_point))
396 int depth = 0;
397 InternalNode* node = GetNodeByRow(row, &depth);
398 if (!node)
399 return;
400 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth));
401 if (!bounds.Contains(local_point))
402 return; 403 return;
403 } 404 }
404 View::ShowContextMenu(p, source_type); 405 View::ShowContextMenu(p, source_type);
405 } 406 }
406 407
407 void TreeView::GetAccessibleState(ui::AXViewState* state) { 408 void TreeView::GetAccessibleState(ui::AXViewState* state) {
408 state->role = ui::AX_ROLE_TREE; 409 state->role = ui::AX_ROLE_TREE;
409 state->AddStateFlag(ui::AX_STATE_READ_ONLY); 410 state->AddStateFlag(ui::AX_STATE_READ_ONLY);
410 if (!selected_node_) 411 if (!selected_node_)
411 return; 412 return;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 SetSelectedNode(GetNodeForRow(row)); 530 SetSelectedNode(GetNodeForRow(row));
530 } 531 }
531 532
532 base::string16 TreeView::GetTextForRow(int row) { 533 base::string16 TreeView::GetTextForRow(int row) {
533 return GetNodeForRow(row)->GetTitle(); 534 return GetNodeForRow(row)->GetTitle();
534 } 535 }
535 536
536 gfx::Point TreeView::GetKeyboardContextMenuLocation() { 537 gfx::Point TreeView::GetKeyboardContextMenuLocation() {
537 int y = height() / 2; 538 int y = height() / 2;
538 if (selected_node_) { 539 if (selected_node_) {
539 gfx::Rect node_bounds(GetBoundsForNode(selected_node_)); 540 gfx::Rect node_bounds(GetForegroundBoundsForNode(selected_node_));
540 gfx::Rect vis_bounds(GetVisibleBounds()); 541 gfx::Rect vis_bounds(GetVisibleBounds());
541 if (node_bounds.y() >= vis_bounds.y() && 542 if (node_bounds.y() >= vis_bounds.y() &&
542 node_bounds.y() < vis_bounds.bottom()) { 543 node_bounds.y() < vis_bounds.bottom()) {
543 y = node_bounds.y(); 544 y = node_bounds.y();
544 } 545 }
545 } 546 }
546 gfx::Point screen_loc(0, y); 547 gfx::Point screen_loc(0, y);
547 if (base::i18n::IsRTL()) 548 if (base::i18n::IsRTL())
548 screen_loc.set_x(width()); 549 screen_loc.set_x(width());
549 ConvertPointToScreen(this, &screen_loc); 550 ConvertPointToScreen(this, &screen_loc);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 GetInputMethod()->DetachTextInputClient(GetPrefixSelector()); 637 GetInputMethod()->DetachTextInputClient(GetPrefixSelector());
637 SchedulePaintForNode(selected_node_); 638 SchedulePaintForNode(selected_node_);
638 if (selector_) 639 if (selector_)
639 selector_->OnViewBlur(); 640 selector_->OnViewBlur();
640 } 641 }
641 642
642 bool TreeView::OnClickOrTap(const ui::LocatedEvent& event) { 643 bool TreeView::OnClickOrTap(const ui::LocatedEvent& event) {
643 CommitEdit(); 644 CommitEdit();
644 RequestFocus(); 645 RequestFocus();
645 646
646 int row = (event.y() - kVerticalInset) / row_height_; 647 InternalNode* node = GetNodeAtPoint(event.location());
647 int depth = 0; 648 if (!node)
648 InternalNode* node = GetNodeByRow(row, &depth); 649 return true;
649 if (node) { 650
650 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth)); 651 bool hits_arrow = IsPointInExpandControl(node, event.location());
651 if (bounds.Contains(event.location())) { 652 if (!hits_arrow)
652 int relative_x = event.x() - bounds.x(); 653 SetSelectedNode(node->model_node());
653 if (base::i18n::IsRTL()) 654
654 relative_x = bounds.width() - relative_x; 655 if (hits_arrow || EventIsDoubleTapOrClick(event)) {
655 if (relative_x < kArrowRegionSize && 656 if (node->is_expanded())
656 model_->GetChildCount(node->model_node())) { 657 Collapse(node->model_node());
657 if (node->is_expanded()) 658 else
658 Collapse(node->model_node()); 659 Expand(node->model_node());
659 else
660 Expand(node->model_node());
661 } else if (relative_x > kArrowRegionSize) {
662 SetSelectedNode(node->model_node());
663 bool should_toggle = false;
664 if (event.type() == ui::ET_GESTURE_TAP) {
665 const ui::GestureEvent& gesture =
666 static_cast<const ui::GestureEvent&>(event);
667 should_toggle = gesture.details().tap_count() == 2;
668 } else {
669 should_toggle = (event.flags() & ui::EF_IS_DOUBLE_CLICK) != 0;
670 }
671 if (should_toggle) {
672 if (node->is_expanded())
673 Collapse(node->model_node());
674 else
675 Expand(node->model_node());
676 }
677 }
678 }
679 } 660 }
680 return true; 661 return true;
681 } 662 }
682 663
683 void TreeView::LoadChildren(InternalNode* node) { 664 void TreeView::LoadChildren(InternalNode* node) {
684 DCHECK_EQ(0, node->child_count()); 665 DCHECK_EQ(0, node->child_count());
685 DCHECK(!node->loaded_children()); 666 DCHECK(!node->loaded_children());
686 node->set_loaded_children(true); 667 node->set_loaded_children(true);
687 for (int i = 0, child_count = model_->GetChildCount(node->model_node()); 668 for (int i = 0, child_count = model_->GetChildCount(node->model_node());
688 i < child_count; ++i) { 669 i < child_count; ++i) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 kTextHorizontalPadding * 2, 702 kTextHorizontalPadding * 2,
722 row_height_ * GetRowCount() + kVerticalInset * 2); 703 row_height_ * GetRowCount() + kVerticalInset * 2);
723 } 704 }
724 705
725 void TreeView::LayoutEditor() { 706 void TreeView::LayoutEditor() {
726 if (!editing_) 707 if (!editing_)
727 return; 708 return;
728 709
729 DCHECK(selected_node_); 710 DCHECK(selected_node_);
730 // Position the editor so that its text aligns with the text we drew. 711 // Position the editor so that its text aligns with the text we drew.
731 gfx::Rect row_bounds = GetBoundsForNode(selected_node_); 712 gfx::Rect row_bounds = GetForegroundBoundsForNode(selected_node_);
732 row_bounds.set_x( 713 row_bounds.set_x(
733 GetMirroredXWithWidthInView(row_bounds.x(), row_bounds.width())); 714 GetMirroredXWithWidthInView(row_bounds.x(), row_bounds.width()));
734 row_bounds.set_x(row_bounds.x() + text_offset_); 715 row_bounds.set_x(row_bounds.x() + text_offset_);
735 row_bounds.set_width(row_bounds.width() - text_offset_); 716 row_bounds.set_width(row_bounds.width() - text_offset_);
736 row_bounds.Inset(kTextHorizontalPadding, kTextVerticalPadding); 717 row_bounds.Inset(kTextHorizontalPadding, kTextVerticalPadding);
737 row_bounds.Inset(-empty_editor_size_.width() / 2, 718 row_bounds.Inset(-empty_editor_size_.width() / 2,
738 -(empty_editor_size_.height() - font_list_.GetHeight()) / 2); 719 -(empty_editor_size_.height() - font_list_.GetHeight()) / 2);
739 // Give a little extra space for editing. 720 // Give a little extra space for editing.
740 row_bounds.set_width(row_bounds.width() + 50); 721 row_bounds.set_width(row_bounds.width() + 50);
741 editor_->SetBoundsRect(row_bounds); 722 editor_->SetBoundsRect(row_bounds);
742 editor_->Layout(); 723 editor_->Layout();
743 } 724 }
744 725
745 void TreeView::SchedulePaintForNode(InternalNode* node) { 726 void TreeView::SchedulePaintForNode(InternalNode* node) {
746 if (!node) 727 if (!node)
747 return; // Explicitly allow NULL to be passed in. 728 return; // Explicitly allow NULL to be passed in.
748 SchedulePaintInRect(GetBoundsForNode(node)); 729 SchedulePaintInRect(GetBackgroundBoundsForNode(node));
749 } 730 }
750 731
751 void TreeView::PaintRows(gfx::Canvas* canvas, 732 void TreeView::PaintRows(gfx::Canvas* canvas,
752 int min_row, 733 int min_row,
753 int max_row, 734 int max_row,
754 InternalNode* node, 735 InternalNode* node,
755 int depth, 736 int depth,
756 int* row) { 737 int* row) {
757 if (*row >= max_row) 738 if (*row >= max_row)
758 return; 739 return;
759 740
760 if (*row >= min_row && *row < max_row) 741 if (*row >= min_row && *row < max_row)
761 PaintRow(canvas, node, *row, depth); 742 PaintRow(canvas, node, *row, depth);
762 (*row)++; 743 (*row)++;
763 if (!node->is_expanded()) 744 if (!node->is_expanded())
764 return; 745 return;
765 depth++; 746 depth++;
766 for (int i = 0; i < node->child_count() && *row < max_row; ++i) 747 for (int i = 0; i < node->child_count() && *row < max_row; ++i)
767 PaintRows(canvas, min_row, max_row, node->GetChild(i), depth, row); 748 PaintRows(canvas, min_row, max_row, node->GetChild(i), depth, row);
768 } 749 }
769 750
770 void TreeView::PaintRow(gfx::Canvas* canvas, 751 void TreeView::PaintRow(gfx::Canvas* canvas,
771 InternalNode* node, 752 InternalNode* node,
772 int row, 753 int row,
773 int depth) { 754 int depth) {
774 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth)); 755 gfx::Rect bounds(GetForegroundBoundsForNodeImpl(node, row, depth));
756 const SkColor selected_row_bg_color = GetNativeTheme()->GetSystemColor(
757 text_background_color_id(HasFocus() || editing_));
758
759 // Paint the row background.
760 if (PlatformStyle::kTreeViewSelectionPaintsEntireRow &&
761 selected_node_ == node) {
762 canvas->FillRect(GetBackgroundBoundsForNode(node), selected_row_bg_color);
763 }
775 764
776 if (model_->GetChildCount(node->model_node())) 765 if (model_->GetChildCount(node->model_node()))
777 PaintExpandControl(canvas, bounds, node->is_expanded()); 766 PaintExpandControl(canvas, bounds, node->is_expanded());
778 767
779 // Paint the icon. 768 // Paint the icon.
780 gfx::ImageSkia icon; 769 gfx::ImageSkia icon;
781 int icon_index = model_->GetIconIndex(node->model_node()); 770 int icon_index = model_->GetIconIndex(node->model_node());
782 if (icon_index != -1) 771 if (icon_index != -1)
783 icon = icons_[icon_index]; 772 icon = icons_[icon_index];
784 else if (node == selected_node_) 773 else if (node == selected_node_)
785 icon = open_icon_; 774 icon = open_icon_;
786 else 775 else
787 icon = closed_icon_; 776 icon = closed_icon_;
788 int icon_x = kArrowRegionSize + kImagePadding + 777 int icon_x = kArrowRegionSize + kImagePadding +
789 (open_icon_.width() - icon.width()) / 2; 778 (open_icon_.width() - icon.width()) / 2;
790 if (base::i18n::IsRTL()) 779 if (base::i18n::IsRTL())
791 icon_x = bounds.right() - icon_x - open_icon_.width(); 780 icon_x = bounds.right() - icon_x - open_icon_.width();
792 else 781 else
793 icon_x += bounds.x(); 782 icon_x += bounds.x();
794 canvas->DrawImageInt( 783 canvas->DrawImageInt(
795 icon, icon_x, 784 icon, icon_x,
796 bounds.y() + (bounds.height() - icon.height()) / 2); 785 bounds.y() + (bounds.height() - icon.height()) / 2);
797 786
798 if (!editing_ || node != selected_node_) { 787 // Paint the text background and text. In edit mode, the selected node is a
799 gfx::Rect text_bounds(bounds.x() + text_offset_, bounds.y(), 788 // separate editing control, so it does not need to be painted here.
800 bounds.width() - text_offset_, bounds.height()); 789 if (editing_ && selected_node_ == node)
801 if (base::i18n::IsRTL()) 790 return;
802 text_bounds.set_x(bounds.x()); 791
803 if (node == selected_node_) { 792 gfx::Rect text_bounds(GetTextBoundsForNode(node));
804 const SkColor bg_color = GetNativeTheme()->GetSystemColor( 793 if (base::i18n::IsRTL())
805 text_background_color_id(HasFocus())); 794 text_bounds.set_x(bounds.x());
806 canvas->FillRect(text_bounds, bg_color); 795
807 if (HasFocus()) 796 // Paint the background on the selected row.
808 canvas->DrawFocusRect(text_bounds); 797 if (!PlatformStyle::kTreeViewSelectionPaintsEntireRow &&
809 } 798 node == selected_node_) {
810 const ui::NativeTheme::ColorId color_id = 799 canvas->FillRect(text_bounds, selected_row_bg_color);
811 text_color_id(HasFocus(), node == selected_node_); 800 if (HasFocus())
812 const gfx::Rect internal_bounds( 801 canvas->DrawFocusRect(text_bounds);
813 text_bounds.x() + kTextHorizontalPadding,
814 text_bounds.y() + kTextVerticalPadding,
815 text_bounds.width() - kTextHorizontalPadding * 2,
816 text_bounds.height() - kTextVerticalPadding * 2);
817 canvas->DrawStringRect(node->model_node()->GetTitle(), font_list_,
818 GetNativeTheme()->GetSystemColor(color_id),
819 internal_bounds);
820 } 802 }
803
804 // Paint the text.
805 const ui::NativeTheme::ColorId color_id =
806 text_color_id(HasFocus(), node == selected_node_);
807 const gfx::Rect internal_bounds(
808 text_bounds.x() + kTextHorizontalPadding,
809 text_bounds.y() + kTextVerticalPadding,
810 text_bounds.width() - kTextHorizontalPadding * 2,
811 text_bounds.height() - kTextVerticalPadding * 2);
812 canvas->DrawStringRect(node->model_node()->GetTitle(), font_list_,
813 GetNativeTheme()->GetSystemColor(color_id),
814 internal_bounds);
821 } 815 }
822 816
823 void TreeView::PaintExpandControl(gfx::Canvas* canvas, 817 void TreeView::PaintExpandControl(gfx::Canvas* canvas,
824 const gfx::Rect& node_bounds, 818 const gfx::Rect& node_bounds,
825 bool expanded) { 819 bool expanded) {
826 int center_x; 820 int center_x;
827 if (base::i18n::IsRTL()) { 821 if (base::i18n::IsRTL()) {
828 center_x = node_bounds.right() - kArrowRegionSize + 822 center_x = node_bounds.right() - kArrowRegionSize +
829 (kArrowRegionSize - 4) / 2; 823 (kArrowRegionSize - 4) / 2;
830 } else { 824 } else {
(...skipping 30 matching lines...) Expand all
861 return NULL; 855 return NULL;
862 if (!parent_internal_node->loaded_children()) { 856 if (!parent_internal_node->loaded_children()) {
863 if (create_type == DONT_CREATE_IF_NOT_LOADED) 857 if (create_type == DONT_CREATE_IF_NOT_LOADED)
864 return NULL; 858 return NULL;
865 LoadChildren(parent_internal_node); 859 LoadChildren(parent_internal_node);
866 } 860 }
867 return parent_internal_node->GetChild( 861 return parent_internal_node->GetChild(
868 model_->GetIndexOf(parent_internal_node->model_node(), model_node)); 862 model_->GetIndexOf(parent_internal_node->model_node(), model_node));
869 } 863 }
870 864
871 gfx::Rect TreeView::GetBoundsForNode(InternalNode* node) { 865 gfx::Rect TreeView::GetBackgroundBoundsForNode(InternalNode* node) {
866 if (!PlatformStyle::kTreeViewSelectionPaintsEntireRow)
867 return GetForegroundBoundsForNode(node);
868
869 int row, ignored_depth;
870 row = GetRowForInternalNode(node, &ignored_depth);
871 return gfx::Rect(bounds().x(), row * row_height_ + kVerticalInset,
872 bounds().width(), row_height_);
873 }
874
875 gfx::Rect TreeView::GetForegroundBoundsForNode(InternalNode* node) {
872 int row, depth; 876 int row, depth;
873 row = GetRowForInternalNode(node, &depth); 877 row = GetRowForInternalNode(node, &depth);
874 return GetBoundsForNodeImpl(node, row, depth); 878 return GetForegroundBoundsForNodeImpl(node, row, depth);
875 } 879 }
876 880
877 gfx::Rect TreeView::GetBoundsForNodeImpl(InternalNode* node, 881 gfx::Rect TreeView::GetTextBoundsForNode(InternalNode* node) {
878 int row, 882 gfx::Rect bounds(GetForegroundBoundsForNode(node));
879 int depth) { 883 bounds.Inset(text_offset_, 0, 0, 0);
884 return bounds;
885 }
886
887 gfx::Rect TreeView::GetForegroundBoundsForNodeImpl(InternalNode* node,
888 int row,
889 int depth) {
880 gfx::Rect rect(depth * kIndent + kHorizontalInset, 890 gfx::Rect rect(depth * kIndent + kHorizontalInset,
881 row * row_height_ + kVerticalInset, 891 row * row_height_ + kVerticalInset,
882 text_offset_ + node->text_width() + 892 text_offset_ + node->text_width() +
883 kTextHorizontalPadding * 2, 893 kTextHorizontalPadding * 2,
884 row_height_); 894 row_height_);
885 rect.set_x(GetMirroredXWithWidthInView(rect.x(), rect.width())); 895 rect.set_x(GetMirroredXWithWidthInView(rect.x(), rect.width()));
886 return rect; 896 return rect;
887 } 897 }
888 898
889 int TreeView::GetRowForInternalNode(InternalNode* node, int* depth) { 899 int TreeView::GetRowForInternalNode(InternalNode* node, int* depth) {
890 DCHECK(!node->parent() || IsExpanded(node->parent()->model_node())); 900 DCHECK(!node->parent() || IsExpanded(node->parent()->model_node()));
891 *depth = -1; 901 *depth = -1;
892 int row = -1; 902 int row = -1;
893 InternalNode* tmp_node = node; 903 InternalNode* tmp_node = node;
894 while (tmp_node->parent()) { 904 while (tmp_node->parent()) {
895 int index_in_parent = tmp_node->parent()->GetIndexOf(tmp_node); 905 int index_in_parent = tmp_node->parent()->GetIndexOf(tmp_node);
896 (*depth)++; 906 (*depth)++;
897 row++; // For node. 907 row++; // For node.
898 for (int i = 0; i < index_in_parent; ++i) 908 for (int i = 0; i < index_in_parent; ++i)
899 row += tmp_node->parent()->GetChild(i)->NumExpandedNodes(); 909 row += tmp_node->parent()->GetChild(i)->NumExpandedNodes();
900 tmp_node = tmp_node->parent(); 910 tmp_node = tmp_node->parent();
901 } 911 }
902 if (root_shown_) { 912 if (root_shown_) {
903 (*depth)++; 913 (*depth)++;
904 row++; 914 row++;
905 } 915 }
906 return row; 916 return row;
907 } 917 }
908 918
919 TreeView::InternalNode* TreeView::GetNodeAtPoint(const gfx::Point& point) {
920 int row = (point.y() - kVerticalInset) / row_height_;
921 int depth = -1;
922 InternalNode* node = GetNodeByRow(row, &depth);
923 if (!node)
924 return nullptr;
925
926 // If the entire row gets a selected background, clicking anywhere in the row
927 // serves to hit this node.
928 if (PlatformStyle::kTreeViewSelectionPaintsEntireRow)
929 return node;
930 gfx::Rect bounds(GetForegroundBoundsForNodeImpl(node, row, depth));
931 return bounds.Contains(point) ? node : nullptr;
932 }
933
909 TreeView::InternalNode* TreeView::GetNodeByRow(int row, int* depth) { 934 TreeView::InternalNode* TreeView::GetNodeByRow(int row, int* depth) {
910 int current_row = root_row(); 935 int current_row = root_row();
911 *depth = 0; 936 *depth = 0;
912 return GetNodeByRowImpl(&root_, row, root_depth(), &current_row, depth); 937 return GetNodeByRowImpl(&root_, row, root_depth(), &current_row, depth);
913 } 938 }
914 939
915 TreeView::InternalNode* TreeView::GetNodeByRowImpl(InternalNode* node, 940 TreeView::InternalNode* TreeView::GetNodeByRowImpl(InternalNode* node,
916 int target_row, 941 int target_row,
917 int current_depth, 942 int current_depth,
918 int* current_row, 943 int* current_row,
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 } 1032 }
1008 return return_value; 1033 return return_value;
1009 } 1034 }
1010 1035
1011 PrefixSelector* TreeView::GetPrefixSelector() { 1036 PrefixSelector* TreeView::GetPrefixSelector() {
1012 if (!selector_) 1037 if (!selector_)
1013 selector_.reset(new PrefixSelector(this)); 1038 selector_.reset(new PrefixSelector(this));
1014 return selector_.get(); 1039 return selector_.get();
1015 } 1040 }
1016 1041
1042 bool TreeView::IsPointInExpandControl(InternalNode* node,
1043 const gfx::Point& point) {
1044 if (!model_->GetChildCount(node->model_node()))
1045 return false;
1046
1047 int depth = -1;
1048 int row = GetRowForInternalNode(node, &depth);
1049
1050 int arrow_dx = depth * kIndent + kHorizontalInset;
1051 gfx::Rect arrow_bounds(bounds().x() + arrow_dx,
1052 row * row_height_ + kVerticalInset, kArrowRegionSize,
1053 row_height_);
1054 if (base::i18n::IsRTL())
1055 arrow_bounds.set_x(bounds().width() - arrow_dx - kArrowRegionSize);
1056 return arrow_bounds.Contains(point);
1057 }
1058
1017 // InternalNode ---------------------------------------------------------------- 1059 // InternalNode ----------------------------------------------------------------
1018 1060
1019 TreeView::InternalNode::InternalNode() 1061 TreeView::InternalNode::InternalNode()
1020 : model_node_(NULL), 1062 : model_node_(NULL),
1021 loaded_children_(false), 1063 loaded_children_(false),
1022 is_expanded_(false), 1064 is_expanded_(false),
1023 text_width_(0) { 1065 text_width_(0) {
1024 } 1066 }
1025 1067
1026 TreeView::InternalNode::~InternalNode() { 1068 TreeView::InternalNode::~InternalNode() {
(...skipping 20 matching lines...) Expand all
1047 if (!is_expanded_) 1089 if (!is_expanded_)
1048 return max_width; 1090 return max_width;
1049 for (int i = 0; i < child_count(); ++i) { 1091 for (int i = 0; i < child_count(); ++i) {
1050 max_width = std::max(max_width, 1092 max_width = std::max(max_width,
1051 GetChild(i)->GetMaxWidth(indent, depth + 1)); 1093 GetChild(i)->GetMaxWidth(indent, depth + 1));
1052 } 1094 }
1053 return max_width; 1095 return max_width;
1054 } 1096 }
1055 1097
1056 } // namespace views 1098 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/tree/tree_view.h ('k') | ui/views/style/platform_style.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698