Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 const auto& gesture = static_cast<const ui::GestureEvent&>(event); | |
| 75 return gesture.details().tap_count() == 2; | |
|
tapted
2016/06/13 07:03:47
I think we can skip the `auto` and do
return
Elly Fong-Jones
2016/06/14 17:21:27
Done.
| |
| 76 } else { | |
|
tapted
2016/06/13 07:03:48
nit: "no else after return" - last item at https:/
Elly Fong-Jones
2016/06/14 17:21:27
Done.
| |
| 77 return event.flags() & ui::EF_IS_DOUBLE_CLICK; | |
| 78 } | |
| 79 } | |
| 80 | |
| 71 } // namespace | 81 } // namespace |
| 72 | 82 |
| 73 TreeView::TreeView() | 83 TreeView::TreeView() |
| 74 : model_(NULL), | 84 : model_(NULL), |
| 75 selected_node_(NULL), | 85 selected_node_(NULL), |
| 76 editing_(false), | 86 editing_(false), |
| 77 editor_(NULL), | 87 editor_(NULL), |
| 78 focus_manager_(NULL), | 88 focus_manager_(NULL), |
| 79 auto_expand_children_(false), | 89 auto_expand_children_(false), |
| 80 editable_(true), | 90 editable_(true), |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 | 395 |
| 386 void TreeView::ShowContextMenu(const gfx::Point& p, | 396 void TreeView::ShowContextMenu(const gfx::Point& p, |
| 387 ui::MenuSourceType source_type) { | 397 ui::MenuSourceType source_type) { |
| 388 if (!model_) | 398 if (!model_) |
| 389 return; | 399 return; |
| 390 if (source_type == ui::MENU_SOURCE_MOUSE) { | 400 if (source_type == ui::MENU_SOURCE_MOUSE) { |
| 391 // Only invoke View's implementation (which notifies the | 401 // Only invoke View's implementation (which notifies the |
| 392 // ContextMenuController) if over a node. | 402 // ContextMenuController) if over a node. |
| 393 gfx::Point local_point(p); | 403 gfx::Point local_point(p); |
| 394 ConvertPointFromScreen(this, &local_point); | 404 ConvertPointFromScreen(this, &local_point); |
| 395 int row = (local_point.y() - kVerticalInset) / row_height_; | 405 if (!NodeAtPoint(local_point)) |
|
tapted
2016/06/13 07:03:47
I think it would improve NodeAtPoint if it require
Elly Fong-Jones
2016/06/14 17:21:27
Done.
| |
| 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; | 406 return; |
| 403 } | 407 } |
| 404 View::ShowContextMenu(p, source_type); | 408 View::ShowContextMenu(p, source_type); |
| 405 } | 409 } |
| 406 | 410 |
| 407 void TreeView::GetAccessibleState(ui::AXViewState* state) { | 411 void TreeView::GetAccessibleState(ui::AXViewState* state) { |
| 408 state->role = ui::AX_ROLE_TREE; | 412 state->role = ui::AX_ROLE_TREE; |
| 409 state->AddStateFlag(ui::AX_STATE_READ_ONLY); | 413 state->AddStateFlag(ui::AX_STATE_READ_ONLY); |
| 410 if (!selected_node_) | 414 if (!selected_node_) |
| 411 return; | 415 return; |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 633 GetInputMethod()->DetachTextInputClient(GetPrefixSelector()); | 637 GetInputMethod()->DetachTextInputClient(GetPrefixSelector()); |
| 634 SchedulePaintForNode(selected_node_); | 638 SchedulePaintForNode(selected_node_); |
| 635 if (selector_) | 639 if (selector_) |
| 636 selector_->OnViewBlur(); | 640 selector_->OnViewBlur(); |
| 637 } | 641 } |
| 638 | 642 |
| 639 bool TreeView::OnClickOrTap(const ui::LocatedEvent& event) { | 643 bool TreeView::OnClickOrTap(const ui::LocatedEvent& event) { |
| 640 CommitEdit(); | 644 CommitEdit(); |
| 641 RequestFocus(); | 645 RequestFocus(); |
| 642 | 646 |
| 643 int row = (event.y() - kVerticalInset) / row_height_; | 647 int depth; |
| 644 int depth = 0; | 648 InternalNode* node = NodeAtPoint(event.location(), &depth); |
| 645 InternalNode* node = GetNodeByRow(row, &depth); | 649 if (!node) |
| 646 if (node) { | 650 return true; |
| 647 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth)); | 651 |
| 648 if (bounds.Contains(event.location())) { | 652 bool hits_arrow = HitsNodeArrow(node, depth, event.location()); |
| 649 int relative_x = event.x() - bounds.x(); | 653 if (!hits_arrow) |
| 650 if (base::i18n::IsRTL()) | 654 SetSelectedNode(node->model_node()); |
| 651 relative_x = bounds.width() - relative_x; | 655 |
| 652 if (relative_x < kArrowRegionSize && | 656 if (hits_arrow || EventIsDoubleTapOrClick(event)) { |
| 653 model_->GetChildCount(node->model_node())) { | 657 if (node->is_expanded()) |
| 654 if (node->is_expanded()) | 658 Collapse(node->model_node()); |
| 655 Collapse(node->model_node()); | 659 else |
| 656 else | 660 Expand(node->model_node()); |
| 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 } | 661 } |
| 677 return true; | 662 return true; |
| 678 } | 663 } |
| 679 | 664 |
| 680 void TreeView::LoadChildren(InternalNode* node) { | 665 void TreeView::LoadChildren(InternalNode* node) { |
| 681 DCHECK_EQ(0, node->child_count()); | 666 DCHECK_EQ(0, node->child_count()); |
| 682 DCHECK(!node->loaded_children()); | 667 DCHECK(!node->loaded_children()); |
| 683 node->set_loaded_children(true); | 668 node->set_loaded_children(true); |
| 684 for (int i = 0, child_count = model_->GetChildCount(node->model_node()); | 669 for (int i = 0, child_count = model_->GetChildCount(node->model_node()); |
| 685 i < child_count; ++i) { | 670 i < child_count; ++i) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 735 -(empty_editor_size_.height() - font_list_.GetHeight()) / 2); | 720 -(empty_editor_size_.height() - font_list_.GetHeight()) / 2); |
| 736 // Give a little extra space for editing. | 721 // Give a little extra space for editing. |
| 737 row_bounds.set_width(row_bounds.width() + 50); | 722 row_bounds.set_width(row_bounds.width() + 50); |
| 738 editor_->SetBoundsRect(row_bounds); | 723 editor_->SetBoundsRect(row_bounds); |
| 739 editor_->Layout(); | 724 editor_->Layout(); |
| 740 } | 725 } |
| 741 | 726 |
| 742 void TreeView::SchedulePaintForNode(InternalNode* node) { | 727 void TreeView::SchedulePaintForNode(InternalNode* node) { |
| 743 if (!node) | 728 if (!node) |
| 744 return; // Explicitly allow NULL to be passed in. | 729 return; // Explicitly allow NULL to be passed in. |
| 745 SchedulePaintInRect(GetBoundsForNode(node)); | 730 SchedulePaintInRect(GetBackgroundBoundsForNode(node)); |
| 746 } | 731 } |
| 747 | 732 |
| 748 void TreeView::PaintRows(gfx::Canvas* canvas, | 733 void TreeView::PaintRows(gfx::Canvas* canvas, |
| 749 int min_row, | 734 int min_row, |
| 750 int max_row, | 735 int max_row, |
| 751 InternalNode* node, | 736 InternalNode* node, |
| 752 int depth, | 737 int depth, |
| 753 int* row) { | 738 int* row) { |
| 754 if (*row >= max_row) | 739 if (*row >= max_row) |
| 755 return; | 740 return; |
| 756 | 741 |
| 757 if (*row >= min_row && *row < max_row) | 742 if (*row >= min_row && *row < max_row) |
| 758 PaintRow(canvas, node, *row, depth); | 743 PaintRow(canvas, node, *row, depth); |
| 759 (*row)++; | 744 (*row)++; |
| 760 if (!node->is_expanded()) | 745 if (!node->is_expanded()) |
| 761 return; | 746 return; |
| 762 depth++; | 747 depth++; |
| 763 for (int i = 0; i < node->child_count() && *row < max_row; ++i) | 748 for (int i = 0; i < node->child_count() && *row < max_row; ++i) |
| 764 PaintRows(canvas, min_row, max_row, node->GetChild(i), depth, row); | 749 PaintRows(canvas, min_row, max_row, node->GetChild(i), depth, row); |
| 765 } | 750 } |
| 766 | 751 |
| 767 void TreeView::PaintRow(gfx::Canvas* canvas, | 752 void TreeView::PaintRow(gfx::Canvas* canvas, |
| 768 InternalNode* node, | 753 InternalNode* node, |
| 769 int row, | 754 int row, |
| 770 int depth) { | 755 int depth) { |
| 771 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth)); | 756 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, depth)); |
| 757 const SkColor selected_row_bg_color = GetNativeTheme()->GetSystemColor( | |
| 758 text_background_color_id(HasFocus() || editing_)); | |
| 759 | |
| 760 // Paint the row background. | |
| 761 if (PlatformStyle::kTreeViewSelectsEntireRow && selected_node_ == node) | |
| 762 canvas->FillRect(GetBackgroundBoundsForNode(node), selected_row_bg_color); | |
| 772 | 763 |
| 773 if (model_->GetChildCount(node->model_node())) | 764 if (model_->GetChildCount(node->model_node())) |
| 774 PaintExpandControl(canvas, bounds, node->is_expanded()); | 765 PaintExpandControl(canvas, bounds, node->is_expanded()); |
|
tapted
2016/06/13 07:03:47
We probably need to convert this to a vector icon
Elly Fong-Jones
2016/06/14 17:21:27
Acknowledged.
| |
| 775 | 766 |
| 776 // Paint the icon. | 767 // Paint the icon. |
| 777 gfx::ImageSkia icon; | 768 gfx::ImageSkia icon; |
| 778 int icon_index = model_->GetIconIndex(node->model_node()); | 769 int icon_index = model_->GetIconIndex(node->model_node()); |
| 779 if (icon_index != -1) | 770 if (icon_index != -1) |
| 780 icon = icons_[icon_index]; | 771 icon = icons_[icon_index]; |
| 781 else if (node == selected_node_) | 772 else if (node == selected_node_) |
| 782 icon = open_icon_; | 773 icon = open_icon_; |
| 783 else | 774 else |
| 784 icon = closed_icon_; | 775 icon = closed_icon_; |
| 785 int icon_x = kArrowRegionSize + kImagePadding + | 776 int icon_x = kArrowRegionSize + kImagePadding + |
| 786 (open_icon_.width() - icon.width()) / 2; | 777 (open_icon_.width() - icon.width()) / 2; |
| 787 if (base::i18n::IsRTL()) | 778 if (base::i18n::IsRTL()) |
| 788 icon_x = bounds.right() - icon_x - open_icon_.width(); | 779 icon_x = bounds.right() - icon_x - open_icon_.width(); |
| 789 else | 780 else |
| 790 icon_x += bounds.x(); | 781 icon_x += bounds.x(); |
| 791 canvas->DrawImageInt( | 782 canvas->DrawImageInt( |
| 792 icon, icon_x, | 783 icon, icon_x, |
| 793 bounds.y() + (bounds.height() - icon.height()) / 2); | 784 bounds.y() + (bounds.height() - icon.height()) / 2); |
| 794 | 785 |
| 795 if (!editing_ || node != selected_node_) { | 786 // 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(), | 787 // separate editing control, so it does not need to be painted here. |
| 797 bounds.width() - text_offset_, bounds.height()); | 788 if (editing_ && selected_node_ == node) |
| 798 if (base::i18n::IsRTL()) | 789 return; |
| 799 text_bounds.set_x(bounds.x()); | 790 |
| 800 if (node == selected_node_) { | 791 gfx::Rect text_bounds(bounds.x() + text_offset_, bounds.y(), |
| 801 const SkColor bg_color = GetNativeTheme()->GetSystemColor( | 792 bounds.width() - text_offset_, bounds.height()); |
| 802 text_background_color_id(HasFocus())); | 793 if (base::i18n::IsRTL()) |
| 803 canvas->FillRect(text_bounds, bg_color); | 794 text_bounds.set_x(bounds.x()); |
| 804 if (HasFocus()) | 795 |
| 805 canvas->DrawFocusRect(text_bounds); | 796 // Paint the background on the selected row. |
| 806 } | 797 if (!PlatformStyle::kTreeViewSelectsEntireRow && node == selected_node_) { |
| 807 const ui::NativeTheme::ColorId color_id = | 798 canvas->FillRect(text_bounds, selected_row_bg_color); |
| 808 text_color_id(HasFocus(), node == selected_node_); | 799 if (HasFocus()) |
| 809 const gfx::Rect internal_bounds( | 800 canvas->DrawFocusRect(text_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 } | 801 } |
| 802 | |
| 803 // Paint the text. | |
| 804 const ui::NativeTheme::ColorId color_id = | |
| 805 text_color_id(HasFocus(), node == selected_node_); | |
| 806 const gfx::Rect internal_bounds( | |
| 807 text_bounds.x() + kTextHorizontalPadding, | |
| 808 text_bounds.y() + kTextVerticalPadding, | |
| 809 text_bounds.width() - kTextHorizontalPadding * 2, | |
| 810 text_bounds.height() - kTextVerticalPadding * 2); | |
| 811 canvas->DrawStringRect(node->model_node()->GetTitle(), font_list_, | |
| 812 GetNativeTheme()->GetSystemColor(color_id), | |
| 813 internal_bounds); | |
| 818 } | 814 } |
| 819 | 815 |
| 820 void TreeView::PaintExpandControl(gfx::Canvas* canvas, | 816 void TreeView::PaintExpandControl(gfx::Canvas* canvas, |
| 821 const gfx::Rect& node_bounds, | 817 const gfx::Rect& node_bounds, |
| 822 bool expanded) { | 818 bool expanded) { |
| 823 int center_x; | 819 int center_x; |
| 824 if (base::i18n::IsRTL()) { | 820 if (base::i18n::IsRTL()) { |
| 825 center_x = node_bounds.right() - kArrowRegionSize + | 821 center_x = node_bounds.right() - kArrowRegionSize + |
| 826 (kArrowRegionSize - 4) / 2; | 822 (kArrowRegionSize - 4) / 2; |
| 827 } else { | 823 } else { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 858 return NULL; | 854 return NULL; |
| 859 if (!parent_internal_node->loaded_children()) { | 855 if (!parent_internal_node->loaded_children()) { |
| 860 if (create_type == DONT_CREATE_IF_NOT_LOADED) | 856 if (create_type == DONT_CREATE_IF_NOT_LOADED) |
| 861 return NULL; | 857 return NULL; |
| 862 LoadChildren(parent_internal_node); | 858 LoadChildren(parent_internal_node); |
| 863 } | 859 } |
| 864 return parent_internal_node->GetChild( | 860 return parent_internal_node->GetChild( |
| 865 model_->GetIndexOf(parent_internal_node->model_node(), model_node)); | 861 model_->GetIndexOf(parent_internal_node->model_node(), model_node)); |
| 866 } | 862 } |
| 867 | 863 |
| 864 gfx::Rect TreeView::GetBackgroundBoundsForNode(InternalNode* node) { | |
| 865 gfx::Rect row_bounds(GetBoundsForNode(node)); | |
| 866 if (PlatformStyle::kTreeViewSelectsEntireRow) { | |
| 867 row_bounds.set_x(bounds().x()); | |
| 868 row_bounds.set_width(bounds().width()); | |
| 869 } | |
| 870 return row_bounds; | |
| 871 } | |
| 872 | |
| 868 gfx::Rect TreeView::GetBoundsForNode(InternalNode* node) { | 873 gfx::Rect TreeView::GetBoundsForNode(InternalNode* node) { |
|
tapted
2016/06/13 07:03:47
perhaps we should rename these to GetTextBoundsFor
Elly Fong-Jones
2016/06/14 17:21:27
Done.
| |
| 869 int row, depth; | 874 int row, depth; |
| 870 row = GetRowForInternalNode(node, &depth); | 875 row = GetRowForInternalNode(node, &depth); |
| 871 return GetBoundsForNodeImpl(node, row, depth); | 876 return GetBoundsForNodeImpl(node, row, depth); |
| 872 } | 877 } |
| 873 | 878 |
| 874 gfx::Rect TreeView::GetBoundsForNodeImpl(InternalNode* node, | 879 gfx::Rect TreeView::GetBoundsForNodeImpl(InternalNode* node, |
| 875 int row, | 880 int row, |
| 876 int depth) { | 881 int depth) { |
| 877 gfx::Rect rect(depth * kIndent + kHorizontalInset, | 882 gfx::Rect rect(depth * kIndent + kHorizontalInset, |
| 878 row * row_height_ + kVerticalInset, | 883 row * row_height_ + kVerticalInset, |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 } | 1009 } |
| 1005 return return_value; | 1010 return return_value; |
| 1006 } | 1011 } |
| 1007 | 1012 |
| 1008 PrefixSelector* TreeView::GetPrefixSelector() { | 1013 PrefixSelector* TreeView::GetPrefixSelector() { |
| 1009 if (!selector_) | 1014 if (!selector_) |
| 1010 selector_.reset(new PrefixSelector(this)); | 1015 selector_.reset(new PrefixSelector(this)); |
| 1011 return selector_.get(); | 1016 return selector_.get(); |
| 1012 } | 1017 } |
| 1013 | 1018 |
| 1019 TreeView::InternalNode* TreeView::NodeAtPoint(const gfx::Point& point, | |
| 1020 int* depth) { | |
| 1021 int row = (point.y() - kVerticalInset) / row_height_; | |
| 1022 int local_depth = 0; | |
| 1023 InternalNode* node = GetNodeByRow(row, &local_depth); | |
| 1024 if (!node) | |
| 1025 return nullptr; | |
| 1026 | |
| 1027 // If the entire row gets a selected background, clicking anywhere in the row | |
| 1028 // serves to hit this node. | |
| 1029 if (PlatformStyle::kTreeViewSelectsEntireRow) { | |
| 1030 if (depth) | |
| 1031 *depth = local_depth; | |
| 1032 return node; | |
| 1033 } | |
| 1034 gfx::Rect bounds(GetBoundsForNodeImpl(node, row, local_depth)); | |
| 1035 if (bounds.Contains(point)) { | |
| 1036 if (depth) | |
| 1037 *depth = local_depth; | |
| 1038 return node; | |
| 1039 } | |
| 1040 return nullptr; | |
| 1041 } | |
| 1042 | |
| 1043 bool TreeView::HitsNodeArrow(InternalNode* node, | |
| 1044 int depth, | |
| 1045 const gfx::Point& point) { | |
| 1046 if (!model_->GetChildCount(node->model_node())) | |
| 1047 return false; | |
|
tapted
2016/06/13 07:03:48
nit: blank line after
Elly Fong-Jones
2016/06/14 17:21:27
Done.
| |
| 1048 gfx::Rect bounds(GetBackgroundBoundsForNode(node)); | |
| 1049 int arrow_dx = depth * kIndent + kHorizontalInset; | |
| 1050 gfx::Rect arrow_bounds(bounds.x() + arrow_dx, bounds.y(), kArrowRegionSize, | |
|
tapted
2016/06/13 07:03:48
I don't think we can use bounds.x() here -- GetBac
Elly Fong-Jones
2016/06/14 17:21:27
Done.
| |
| 1051 bounds.height()); | |
| 1052 if (base::i18n::IsRTL()) | |
| 1053 arrow_bounds.set_x(bounds.width() - arrow_dx - kArrowRegionSize); | |
| 1054 return arrow_bounds.Contains(point); | |
| 1055 } | |
| 1056 | |
| 1014 // InternalNode ---------------------------------------------------------------- | 1057 // InternalNode ---------------------------------------------------------------- |
| 1015 | 1058 |
| 1016 TreeView::InternalNode::InternalNode() | 1059 TreeView::InternalNode::InternalNode() |
| 1017 : model_node_(NULL), | 1060 : model_node_(NULL), |
| 1018 loaded_children_(false), | 1061 loaded_children_(false), |
| 1019 is_expanded_(false), | 1062 is_expanded_(false), |
| 1020 text_width_(0) { | 1063 text_width_(0) { |
| 1021 } | 1064 } |
| 1022 | 1065 |
| 1023 TreeView::InternalNode::~InternalNode() { | 1066 TreeView::InternalNode::~InternalNode() { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1044 if (!is_expanded_) | 1087 if (!is_expanded_) |
| 1045 return max_width; | 1088 return max_width; |
| 1046 for (int i = 0; i < child_count(); ++i) { | 1089 for (int i = 0; i < child_count(); ++i) { |
| 1047 max_width = std::max(max_width, | 1090 max_width = std::max(max_width, |
| 1048 GetChild(i)->GetMaxWidth(indent, depth + 1)); | 1091 GetChild(i)->GetMaxWidth(indent, depth + 1)); |
| 1049 } | 1092 } |
| 1050 return max_width; | 1093 return max_width; |
| 1051 } | 1094 } |
| 1052 | 1095 |
| 1053 } // namespace views | 1096 } // namespace views |
| OLD | NEW |