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

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: GetForegroundBoundsForNode :( Created 4 years, 6 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
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 (!NodeAtPoint(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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 SetSelectedNode(GetNodeForRow(row)); 527 SetSelectedNode(GetNodeForRow(row));
527 } 528 }
528 529
529 base::string16 TreeView::GetTextForRow(int row) { 530 base::string16 TreeView::GetTextForRow(int row) {
530 return GetNodeForRow(row)->GetTitle(); 531 return GetNodeForRow(row)->GetTitle();
531 } 532 }
532 533
533 gfx::Point TreeView::GetKeyboardContextMenuLocation() { 534 gfx::Point TreeView::GetKeyboardContextMenuLocation() {
534 int y = height() / 2; 535 int y = height() / 2;
535 if (selected_node_) { 536 if (selected_node_) {
536 gfx::Rect node_bounds(GetBoundsForNode(selected_node_)); 537 gfx::Rect node_bounds(GetForegroundBoundsForNode(selected_node_));
537 gfx::Rect vis_bounds(GetVisibleBounds()); 538 gfx::Rect vis_bounds(GetVisibleBounds());
538 if (node_bounds.y() >= vis_bounds.y() && 539 if (node_bounds.y() >= vis_bounds.y() &&
539 node_bounds.y() < vis_bounds.bottom()) { 540 node_bounds.y() < vis_bounds.bottom()) {
540 y = node_bounds.y(); 541 y = node_bounds.y();
541 } 542 }
542 } 543 }
543 gfx::Point screen_loc(0, y); 544 gfx::Point screen_loc(0, y);
544 if (base::i18n::IsRTL()) 545 if (base::i18n::IsRTL())
545 screen_loc.set_x(width()); 546 screen_loc.set_x(width());
546 ConvertPointToScreen(this, &screen_loc); 547 ConvertPointToScreen(this, &screen_loc);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 GetInputMethod()->DetachTextInputClient(GetPrefixSelector()); 634 GetInputMethod()->DetachTextInputClient(GetPrefixSelector());
634 SchedulePaintForNode(selected_node_); 635 SchedulePaintForNode(selected_node_);
635 if (selector_) 636 if (selector_)
636 selector_->OnViewBlur(); 637 selector_->OnViewBlur();
637 } 638 }
638 639
639 bool TreeView::OnClickOrTap(const ui::LocatedEvent& event) { 640 bool TreeView::OnClickOrTap(const ui::LocatedEvent& event) {
640 CommitEdit(); 641 CommitEdit();
641 RequestFocus(); 642 RequestFocus();
642 643
643 int row = (event.y() - kVerticalInset) / row_height_; 644 InternalNode* node = NodeAtPoint(event.location());
644 int depth = 0; 645 if (!node)
645 InternalNode* node = GetNodeByRow(row, &depth); 646 return true;
646 if (node) { 647
647 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth)); 648 bool hits_arrow = HitsNodeArrow(node, event.location());
648 if (bounds.Contains(event.location())) { 649 if (!hits_arrow)
649 int relative_x = event.x() - bounds.x(); 650 SetSelectedNode(node->model_node());
650 if (base::i18n::IsRTL()) 651
651 relative_x = bounds.width() - relative_x; 652 if (hits_arrow || EventIsDoubleTapOrClick(event)) {
652 if (relative_x < kArrowRegionSize && 653 if (node->is_expanded())
653 model_->GetChildCount(node->model_node())) { 654 Collapse(node->model_node());
654 if (node->is_expanded()) 655 else
655 Collapse(node->model_node()); 656 Expand(node->model_node());
656 else
657 Expand(node->model_node());
658 } else if (relative_x > kArrowRegionSize) {
659 SetSelectedNode(node->model_node());
660 bool should_toggle = false;
661 if (event.type() == ui::ET_GESTURE_TAP) {
662 const ui::GestureEvent& gesture =
663 static_cast<const ui::GestureEvent&>(event);
664 should_toggle = gesture.details().tap_count() == 2;
665 } else {
666 should_toggle = (event.flags() & ui::EF_IS_DOUBLE_CLICK) != 0;
667 }
668 if (should_toggle) {
669 if (node->is_expanded())
670 Collapse(node->model_node());
671 else
672 Expand(node->model_node());
673 }
674 }
675 }
676 } 657 }
677 return true; 658 return true;
678 } 659 }
679 660
680 void TreeView::LoadChildren(InternalNode* node) { 661 void TreeView::LoadChildren(InternalNode* node) {
681 DCHECK_EQ(0, node->child_count()); 662 DCHECK_EQ(0, node->child_count());
682 DCHECK(!node->loaded_children()); 663 DCHECK(!node->loaded_children());
683 node->set_loaded_children(true); 664 node->set_loaded_children(true);
684 for (int i = 0, child_count = model_->GetChildCount(node->model_node()); 665 for (int i = 0, child_count = model_->GetChildCount(node->model_node());
685 i < child_count; ++i) { 666 i < child_count; ++i) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 kTextHorizontalPadding * 2, 699 kTextHorizontalPadding * 2,
719 row_height_ * GetRowCount() + kVerticalInset * 2); 700 row_height_ * GetRowCount() + kVerticalInset * 2);
720 } 701 }
721 702
722 void TreeView::LayoutEditor() { 703 void TreeView::LayoutEditor() {
723 if (!editing_) 704 if (!editing_)
724 return; 705 return;
725 706
726 DCHECK(selected_node_); 707 DCHECK(selected_node_);
727 // Position the editor so that its text aligns with the text we drew. 708 // Position the editor so that its text aligns with the text we drew.
728 gfx::Rect row_bounds = GetBoundsForNode(selected_node_); 709 gfx::Rect row_bounds = GetForegroundBoundsForNode(selected_node_);
729 row_bounds.set_x( 710 row_bounds.set_x(
730 GetMirroredXWithWidthInView(row_bounds.x(), row_bounds.width())); 711 GetMirroredXWithWidthInView(row_bounds.x(), row_bounds.width()));
731 row_bounds.set_x(row_bounds.x() + text_offset_); 712 row_bounds.set_x(row_bounds.x() + text_offset_);
732 row_bounds.set_width(row_bounds.width() - text_offset_); 713 row_bounds.set_width(row_bounds.width() - text_offset_);
733 row_bounds.Inset(kTextHorizontalPadding, kTextVerticalPadding); 714 row_bounds.Inset(kTextHorizontalPadding, kTextVerticalPadding);
734 row_bounds.Inset(-empty_editor_size_.width() / 2, 715 row_bounds.Inset(-empty_editor_size_.width() / 2,
735 -(empty_editor_size_.height() - font_list_.GetHeight()) / 2); 716 -(empty_editor_size_.height() - font_list_.GetHeight()) / 2);
736 // Give a little extra space for editing. 717 // Give a little extra space for editing.
737 row_bounds.set_width(row_bounds.width() + 50); 718 row_bounds.set_width(row_bounds.width() + 50);
738 editor_->SetBoundsRect(row_bounds); 719 editor_->SetBoundsRect(row_bounds);
739 editor_->Layout(); 720 editor_->Layout();
740 } 721 }
741 722
742 void TreeView::SchedulePaintForNode(InternalNode* node) { 723 void TreeView::SchedulePaintForNode(InternalNode* node) {
743 if (!node) 724 if (!node)
744 return; // Explicitly allow NULL to be passed in. 725 return; // Explicitly allow NULL to be passed in.
745 SchedulePaintInRect(GetBoundsForNode(node)); 726 SchedulePaintInRect(GetBackgroundBoundsForNode(node));
746 } 727 }
747 728
748 void TreeView::PaintRows(gfx::Canvas* canvas, 729 void TreeView::PaintRows(gfx::Canvas* canvas,
749 int min_row, 730 int min_row,
750 int max_row, 731 int max_row,
751 InternalNode* node, 732 InternalNode* node,
752 int depth, 733 int depth,
753 int* row) { 734 int* row) {
754 if (*row >= max_row) 735 if (*row >= max_row)
755 return; 736 return;
756 737
757 if (*row >= min_row && *row < max_row) 738 if (*row >= min_row && *row < max_row)
758 PaintRow(canvas, node, *row, depth); 739 PaintRow(canvas, node, *row, depth);
759 (*row)++; 740 (*row)++;
760 if (!node->is_expanded()) 741 if (!node->is_expanded())
761 return; 742 return;
762 depth++; 743 depth++;
763 for (int i = 0; i < node->child_count() && *row < max_row; ++i) 744 for (int i = 0; i < node->child_count() && *row < max_row; ++i)
764 PaintRows(canvas, min_row, max_row, node->GetChild(i), depth, row); 745 PaintRows(canvas, min_row, max_row, node->GetChild(i), depth, row);
765 } 746 }
766 747
767 void TreeView::PaintRow(gfx::Canvas* canvas, 748 void TreeView::PaintRow(gfx::Canvas* canvas,
768 InternalNode* node, 749 InternalNode* node,
769 int row, 750 int row,
770 int depth) { 751 int depth) {
771 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth)); 752 gfx::Rect bounds(GetForegroundBoundsForNodeImpl(node, row, depth));
753 const SkColor selected_row_bg_color = GetNativeTheme()->GetSystemColor(
754 text_background_color_id(HasFocus() || editing_));
755
756 // Paint the row background.
757 if (PlatformStyle::kTreeViewSelectsEntireRow && selected_node_ == node)
758 canvas->FillRect(GetBackgroundBoundsForNode(node), selected_row_bg_color);
772 759
773 if (model_->GetChildCount(node->model_node())) 760 if (model_->GetChildCount(node->model_node()))
774 PaintExpandControl(canvas, bounds, node->is_expanded()); 761 PaintExpandControl(canvas, bounds, node->is_expanded());
775 762
776 // Paint the icon. 763 // Paint the icon.
777 gfx::ImageSkia icon; 764 gfx::ImageSkia icon;
778 int icon_index = model_->GetIconIndex(node->model_node()); 765 int icon_index = model_->GetIconIndex(node->model_node());
779 if (icon_index != -1) 766 if (icon_index != -1)
780 icon = icons_[icon_index]; 767 icon = icons_[icon_index];
781 else if (node == selected_node_) 768 else if (node == selected_node_)
782 icon = open_icon_; 769 icon = open_icon_;
783 else 770 else
784 icon = closed_icon_; 771 icon = closed_icon_;
785 int icon_x = kArrowRegionSize + kImagePadding + 772 int icon_x = kArrowRegionSize + kImagePadding +
786 (open_icon_.width() - icon.width()) / 2; 773 (open_icon_.width() - icon.width()) / 2;
787 if (base::i18n::IsRTL()) 774 if (base::i18n::IsRTL())
788 icon_x = bounds.right() - icon_x - open_icon_.width(); 775 icon_x = bounds.right() - icon_x - open_icon_.width();
789 else 776 else
790 icon_x += bounds.x(); 777 icon_x += bounds.x();
791 canvas->DrawImageInt( 778 canvas->DrawImageInt(
792 icon, icon_x, 779 icon, icon_x,
793 bounds.y() + (bounds.height() - icon.height()) / 2); 780 bounds.y() + (bounds.height() - icon.height()) / 2);
794 781
795 if (!editing_ || node != selected_node_) { 782 // Paint the text background and text. In edit mode, the selected node is a
796 gfx::Rect text_bounds(bounds.x() + text_offset_, bounds.y(), 783 // separate editing control, so it does not need to be painted here.
797 bounds.width() - text_offset_, bounds.height()); 784 if (editing_ && selected_node_ == node)
798 if (base::i18n::IsRTL()) 785 return;
799 text_bounds.set_x(bounds.x()); 786
800 if (node == selected_node_) { 787 gfx::Rect text_bounds(GetTextBoundsForNode(node));
801 const SkColor bg_color = GetNativeTheme()->GetSystemColor( 788 if (base::i18n::IsRTL())
802 text_background_color_id(HasFocus())); 789 text_bounds.set_x(bounds.x());
803 canvas->FillRect(text_bounds, bg_color); 790
804 if (HasFocus()) 791 // Paint the background on the selected row.
805 canvas->DrawFocusRect(text_bounds); 792 if (!PlatformStyle::kTreeViewSelectsEntireRow && node == selected_node_) {
806 } 793 canvas->FillRect(text_bounds, selected_row_bg_color);
807 const ui::NativeTheme::ColorId color_id = 794 if (HasFocus())
808 text_color_id(HasFocus(), node == selected_node_); 795 canvas->DrawFocusRect(text_bounds);
809 const gfx::Rect internal_bounds(
810 text_bounds.x() + kTextHorizontalPadding,
811 text_bounds.y() + kTextVerticalPadding,
812 text_bounds.width() - kTextHorizontalPadding * 2,
813 text_bounds.height() - kTextVerticalPadding * 2);
814 canvas->DrawStringRect(node->model_node()->GetTitle(), font_list_,
815 GetNativeTheme()->GetSystemColor(color_id),
816 internal_bounds);
817 } 796 }
797
798 // Paint the text.
799 const ui::NativeTheme::ColorId color_id =
800 text_color_id(HasFocus(), node == selected_node_);
801 const gfx::Rect internal_bounds(
802 text_bounds.x() + kTextHorizontalPadding,
803 text_bounds.y() + kTextVerticalPadding,
804 text_bounds.width() - kTextHorizontalPadding * 2,
805 text_bounds.height() - kTextVerticalPadding * 2);
806 canvas->DrawStringRect(node->model_node()->GetTitle(), font_list_,
807 GetNativeTheme()->GetSystemColor(color_id),
808 internal_bounds);
818 } 809 }
819 810
820 void TreeView::PaintExpandControl(gfx::Canvas* canvas, 811 void TreeView::PaintExpandControl(gfx::Canvas* canvas,
821 const gfx::Rect& node_bounds, 812 const gfx::Rect& node_bounds,
822 bool expanded) { 813 bool expanded) {
823 int center_x; 814 int center_x;
824 if (base::i18n::IsRTL()) { 815 if (base::i18n::IsRTL()) {
825 center_x = node_bounds.right() - kArrowRegionSize + 816 center_x = node_bounds.right() - kArrowRegionSize +
826 (kArrowRegionSize - 4) / 2; 817 (kArrowRegionSize - 4) / 2;
827 } else { 818 } else {
(...skipping 30 matching lines...) Expand all
858 return NULL; 849 return NULL;
859 if (!parent_internal_node->loaded_children()) { 850 if (!parent_internal_node->loaded_children()) {
860 if (create_type == DONT_CREATE_IF_NOT_LOADED) 851 if (create_type == DONT_CREATE_IF_NOT_LOADED)
861 return NULL; 852 return NULL;
862 LoadChildren(parent_internal_node); 853 LoadChildren(parent_internal_node);
863 } 854 }
864 return parent_internal_node->GetChild( 855 return parent_internal_node->GetChild(
865 model_->GetIndexOf(parent_internal_node->model_node(), model_node)); 856 model_->GetIndexOf(parent_internal_node->model_node(), model_node));
866 } 857 }
867 858
868 gfx::Rect TreeView::GetBoundsForNode(InternalNode* node) { 859 gfx::Rect TreeView::GetBackgroundBoundsForNode(InternalNode* node) {
860 if (!PlatformStyle::kTreeViewSelectsEntireRow)
861 return GetForegroundBoundsForNode(node);
862
863 int row, ignored_depth;
864 row = GetRowForInternalNode(node, &ignored_depth);
865 return gfx::Rect(bounds().x(), row * row_height_ + kVerticalInset,
866 bounds().width(), row_height_);
867 }
868
869 gfx::Rect TreeView::GetForegroundBoundsForNode(InternalNode* node) {
869 int row, depth; 870 int row, depth;
870 row = GetRowForInternalNode(node, &depth); 871 row = GetRowForInternalNode(node, &depth);
871 return GetBoundsForNodeImpl(node, row, depth); 872 return GetForegroundBoundsForNodeImpl(node, row, depth);
872 } 873 }
873 874
874 gfx::Rect TreeView::GetBoundsForNodeImpl(InternalNode* node, 875 gfx::Rect TreeView::GetTextBoundsForNode(InternalNode* node) {
875 int row, 876 gfx::Rect bounds(GetForegroundBoundsForNode(node));
876 int depth) { 877 bounds.Inset(text_offset_, 0, 0, 0);
878 return bounds;
879 }
880
881 gfx::Rect TreeView::GetForegroundBoundsForNodeImpl(InternalNode* node,
882 int row,
883 int depth) {
877 gfx::Rect rect(depth * kIndent + kHorizontalInset, 884 gfx::Rect rect(depth * kIndent + kHorizontalInset,
878 row * row_height_ + kVerticalInset, 885 row * row_height_ + kVerticalInset,
879 text_offset_ + node->text_width() + 886 text_offset_ + node->text_width() +
880 kTextHorizontalPadding * 2, 887 kTextHorizontalPadding * 2,
881 row_height_); 888 row_height_);
882 rect.set_x(GetMirroredXWithWidthInView(rect.x(), rect.width())); 889 rect.set_x(GetMirroredXWithWidthInView(rect.x(), rect.width()));
883 return rect; 890 return rect;
884 } 891 }
885 892
886 int TreeView::GetRowForInternalNode(InternalNode* node, int* depth) { 893 int TreeView::GetRowForInternalNode(InternalNode* node, int* depth) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 } 1011 }
1005 return return_value; 1012 return return_value;
1006 } 1013 }
1007 1014
1008 PrefixSelector* TreeView::GetPrefixSelector() { 1015 PrefixSelector* TreeView::GetPrefixSelector() {
1009 if (!selector_) 1016 if (!selector_)
1010 selector_.reset(new PrefixSelector(this)); 1017 selector_.reset(new PrefixSelector(this));
1011 return selector_.get(); 1018 return selector_.get();
1012 } 1019 }
1013 1020
1021 TreeView::InternalNode* TreeView::NodeAtPoint(const gfx::Point& point) {
1022 int row = (point.y() - kVerticalInset) / row_height_;
1023 int depth = -1;
1024 InternalNode* node = GetNodeByRow(row, &depth);
1025 if (!node)
1026 return nullptr;
1027
1028 // If the entire row gets a selected background, clicking anywhere in the row
1029 // serves to hit this node.
1030 if (PlatformStyle::kTreeViewSelectsEntireRow)
1031 return node;
1032 gfx::Rect bounds(GetForegroundBoundsForNodeImpl(node, row, depth));
1033 return bounds.Contains(point) ? node : nullptr;
1034 }
1035
1036 bool TreeView::HitsNodeArrow(InternalNode* node, const gfx::Point& point) {
1037 if (!model_->GetChildCount(node->model_node()))
1038 return false;
1039
1040 int depth = -1;
1041 int row = GetRowForInternalNode(node, &depth);
sky 2016/06/16 17:34:39 Can this use GetForegroundBoundsForNode? It would
Elly Fong-Jones 2016/06/23 19:47:13 I don't think so. This function needs to use row a
1042
1043 int arrow_dx = depth * kIndent + kHorizontalInset;
1044 gfx::Rect arrow_bounds(bounds().x() + arrow_dx,
1045 row * row_height_ + kVerticalInset, kArrowRegionSize,
1046 row_height_);
1047 if (base::i18n::IsRTL())
1048 arrow_bounds.set_x(bounds().width() - arrow_dx - kArrowRegionSize);
1049 return arrow_bounds.Contains(point);
1050 }
1051
1014 // InternalNode ---------------------------------------------------------------- 1052 // InternalNode ----------------------------------------------------------------
1015 1053
1016 TreeView::InternalNode::InternalNode() 1054 TreeView::InternalNode::InternalNode()
1017 : model_node_(NULL), 1055 : model_node_(NULL),
1018 loaded_children_(false), 1056 loaded_children_(false),
1019 is_expanded_(false), 1057 is_expanded_(false),
1020 text_width_(0) { 1058 text_width_(0) {
1021 } 1059 }
1022 1060
1023 TreeView::InternalNode::~InternalNode() { 1061 TreeView::InternalNode::~InternalNode() {
(...skipping 20 matching lines...) Expand all
1044 if (!is_expanded_) 1082 if (!is_expanded_)
1045 return max_width; 1083 return max_width;
1046 for (int i = 0; i < child_count(); ++i) { 1084 for (int i = 0; i < child_count(); ++i) {
1047 max_width = std::max(max_width, 1085 max_width = std::max(max_width,
1048 GetChild(i)->GetMaxWidth(indent, depth + 1)); 1086 GetChild(i)->GetMaxWidth(indent, depth + 1));
1049 } 1087 }
1050 return max_width; 1088 return max_width;
1051 } 1089 }
1052 1090
1053 } // namespace views 1091 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698