| // Copyright 2012 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "ui/views/examples/tree_view_example.h" | |
| #include <utility> | |
| #include "base/strings/utf_string_conversions.h" | |
| #include "ui/base/l10n/l10n_util.h" | |
| #include "ui/base/mojom/menu_source_type.mojom-forward.h" | |
| #include "ui/views/controls/button/label_button.h" | |
| #include "ui/views/controls/menu/menu_model_adapter.h" | |
| #include "ui/views/controls/menu/menu_runner.h" | |
| #include "ui/views/controls/scroll_view.h" | |
| #include "ui/views/controls/tree/tree_view.h" | |
| #include "ui/views/controls/tree/tree_view_drawing_provider.h" | |
| #include "ui/views/examples/grit/views_examples_resources.h" | |
| #include "ui/views/layout/flex_layout.h" | |
| #include "ui/views/layout/flex_layout_types.h" | |
| #include "ui/views/view_class_properties.h" | |
| using l10n_util::GetStringUTF16; | |
| using l10n_util::GetStringUTF8; | |
| namespace { | |
| class ExampleTreeViewDrawingProvider : public views::TreeViewDrawingProvider { | |
| public: | |
| ExampleTreeViewDrawingProvider() = default; | |
| ~ExampleTreeViewDrawingProvider() override = default; | |
| std::u16string GetAuxiliaryTextForNode(views::TreeView* tree_view, | |
| ui::TreeModelNode* node) override { | |
| if (tree_view->GetSelectedNode() == node) { | |
| return GetStringUTF16(IDS_TREE_VIEW_SELECTED_LABEL); | |
| } | |
| return views::TreeViewDrawingProvider::GetAuxiliaryTextForNode(tree_view, | |
| node); | |
| } | |
| bool ShouldDrawIconForNode(views::TreeView* tree_view, | |
| ui::TreeModelNode* node) override { | |
| return tree_view->GetSelectedNode() != node; | |
| } | |
| }; | |
| } // namespace | |
| namespace views::examples { | |
| TreeViewExample::TreeViewExample() | |
| : ExampleBase(GetStringUTF8(IDS_TREE_VIEW_SELECT_LABEL).c_str()), | |
| model_(std::make_unique<ui::TreeModelNode>( | |
| GetStringUTF16(IDS_TREE_VIEW_ROOT_NODE_LABEL))) {} | |
| TreeViewExample::~TreeViewExample() { | |
| if (tree_view_) { | |
| tree_view_->SetModel(nullptr); | |
| tree_view_->set_context_menu_controller(nullptr); | |
| tree_view_->SetController(nullptr); | |
| } | |
| } | |
| void TreeViewExample::CreateExampleView(View* container) { | |
| // Add some sample data. | |
| ui::TreeModelNode* colors_node = | |
| model_.GetRoot()->Add(std::make_unique<ui::TreeModelNode>( | |
| GetStringUTF16(IDS_TREE_VIEW_COLOR_NODE_LABEL)), | |
| 0); | |
| colors_node->Add(std::make_unique<ui::TreeModelNode>( | |
| GetStringUTF16(IDS_TREE_VIEW_COLOR_RED_LABEL)), | |
| 0); | |
| colors_node->Add(std::make_unique<ui::TreeModelNode>( | |
| GetStringUTF16(IDS_TREE_VIEW_COLOR_GREEN_LABEL)), | |
| 1); | |
| colors_node->Add(std::make_unique<ui::TreeModelNode>( | |
| GetStringUTF16(IDS_TREE_VIEW_COLOR_BLUE_LABEL)), | |
| 2); | |
| ui::TreeModelNode* sheep_node = | |
| model_.GetRoot()->Add(std::make_unique<ui::TreeModelNode>( | |
| GetStringUTF16(IDS_TREE_VIEW_SHEEP_NODE_LABEL)), | |
| 0); | |
| sheep_node->Add(std::make_unique<ui::TreeModelNode>( | |
| GetStringUTF16(IDS_TREE_VIEW_SHEEP1_LABEL)), | |
| 0); | |
| sheep_node->Add(std::make_unique<ui::TreeModelNode>( | |
| GetStringUTF16(IDS_TREE_VIEW_SHEEP2_LABEL)), | |
| 1); | |
| auto tree_view = std::make_unique<TreeView>(); | |
| tree_view->set_context_menu_controller(this); | |
| tree_view->SetRootShown(false); | |
| tree_view->SetModel(&model_); | |
| tree_view->SetController(this); | |
| tree_view->SetDrawingProvider( | |
| std::make_unique<ExampleTreeViewDrawingProvider>()); | |
| auto add = std::make_unique<LabelButton>( | |
| base::BindRepeating(&TreeViewExample::AddNewNode, base::Unretained(this)), | |
| GetStringUTF16(IDS_TREE_VIEW_ADD_BUTTON_LABEL)); | |
| add->SetRequestFocusOnPress(true); | |
| auto remove = std::make_unique<LabelButton>( | |
| base::BindRepeating(&TreeViewExample::RemoveSelectedNode, | |
| base::Unretained(this)), | |
| GetStringUTF16(IDS_TREE_VIEW_REMOVE_BUTTON_LABEL)); | |
| remove->SetRequestFocusOnPress(true); | |
| auto change_title = std::make_unique<LabelButton>( | |
| base::BindRepeating(&TreeViewExample::SetSelectedNodeTitle, | |
| base::Unretained(this)), | |
| GetStringUTF16(IDS_TREE_VIEW_CHANGE_TITLE_LABEL)); | |
| change_title->SetRequestFocusOnPress(true); | |
| container->SetLayoutManager(std::make_unique<views::FlexLayout>()) | |
| ->SetOrientation(LayoutOrientation::kVertical); | |
| auto full_flex = FlexSpecification(MinimumFlexSizeRule::kScaleToZero, | |
| MaximumFlexSizeRule::kUnbounded) | |
| .WithWeight(4); | |
| tree_view_ = tree_view.get(); | |
| container | |
| ->AddChildView(TreeView::CreateScrollViewWithTree(std::move(tree_view))) | |
| ->SetProperty(views::kFlexBehaviorKey, full_flex); | |
| // Add control buttons horizontally. | |
| auto* button_panel = container->AddChildView(std::make_unique<View>()); | |
| button_panel->SetProperty(views::kFlexBehaviorKey, | |
| FlexSpecification(MinimumFlexSizeRule::kScaleToZero, | |
| MaximumFlexSizeRule::kUnbounded) | |
| .WithWeight(1)); | |
| button_panel->SetLayoutManager(std::make_unique<FlexLayout>()) | |
| ->SetOrientation(LayoutOrientation::kHorizontal); | |
| add_ = button_panel->AddChildView(std::move(add)); | |
| remove_ = button_panel->AddChildView(std::move(remove)); | |
| change_title_ = button_panel->AddChildView(std::move(change_title)); | |
| for (View* view : button_panel->children()) { | |
| view->SetProperty(views::kFlexBehaviorKey, full_flex); | |
| } | |
| } | |
| void TreeViewExample::AddNewNode() { | |
| ui::TreeModelNode* selected_node = tree_view_->GetSelectedNode(); | |
| if (!selected_node) { | |
| selected_node = model_.GetRoot(); | |
| } | |
| ui::TreeModelNode* new_node = model_.Add( | |
| selected_node, | |
| std::make_unique<ui::TreeModelNode>(selected_node->GetTitle())); | |
| tree_view_->SetSelectedNode(new_node); | |
| } | |
| void TreeViewExample::RemoveSelectedNode() { | |
| ui::TreeModelNode* selected_node = tree_view_->GetSelectedNode(); | |
| CHECK(selected_node, base::NotFatalUntil::M163); | |
| CHECK_NE(model_.GetRoot(), selected_node, base::NotFatalUntil::M163); | |
| model_.Remove(selected_node->parent(), selected_node); | |
| } | |
| void TreeViewExample::SetSelectedNodeTitle() { | |
| ui::TreeModelNode* selected_node = tree_view_->GetSelectedNode(); | |
| CHECK(selected_node, base::NotFatalUntil::M163); | |
| model_.SetTitle( | |
| selected_node, | |
| selected_node->GetTitle() + GetStringUTF16(IDS_TREE_VIEW_NEW_NODE_LABEL)); | |
| } | |
| bool TreeViewExample::IsCommandIdEnabled(int command_id) { | |
| return command_id != ID_REMOVE || | |
| tree_view_->GetSelectedNode() != model_.GetRoot(); | |
| } | |
| void TreeViewExample::OnTreeViewSelectionChanged(TreeView* tree_view) { | |
| ui::TreeModelNode* node = tree_view_->GetSelectedNode(); | |
| if (node) { | |
| change_title_->SetEnabled(true); | |
| remove_->SetEnabled(node != model_.GetRoot()); | |
| } else { | |
| change_title_->SetEnabled(false); | |
| remove_->SetEnabled(false); | |
| } | |
| } | |
| bool TreeViewExample::CanEdit(TreeView* tree_view, ui::TreeModelNode* node) { | |
| return true; | |
| } | |
| void TreeViewExample::ShowContextMenuForViewImpl( | |
| View* source, | |
| const gfx::Point& point, | |
| ui::mojom::MenuSourceType source_type) { | |
| context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this); | |
| context_menu_model_->AddItem(ID_EDIT, | |
| GetStringUTF16(IDS_TREE_VIEW_EDIT_BUTTON_LABEL)); | |
| context_menu_model_->AddItem( | |
| ID_REMOVE, GetStringUTF16(IDS_TREE_VIEW_REMOVE_BUTTON_LABEL)); | |
| context_menu_model_->AddItem(ID_ADD, | |
| GetStringUTF16(IDS_TREE_VIEW_ADD_BUTTON_LABEL)); | |
| context_menu_runner_ = | |
| std::make_unique<MenuRunner>(context_menu_model_.get(), 0); | |
| context_menu_runner_->RunMenuAt(source->GetWidget(), nullptr, | |
| gfx::Rect(point, gfx::Size()), | |
| MenuAnchorPosition::kTopLeft, source_type); | |
| } | |
| bool TreeViewExample::IsCommandIdChecked(int command_id) const { | |
| return false; | |
| } | |
| bool TreeViewExample::IsCommandIdEnabled(int command_id) const { | |
| return const_cast<TreeViewExample*>(this)->IsCommandIdEnabled(command_id); | |
| } | |
| void TreeViewExample::ExecuteCommand(int command_id, int event_flags) { | |
| ui::TreeModelNode* selected_node = tree_view_->GetSelectedNode(); | |
| switch (command_id) { | |
| case ID_EDIT: | |
| tree_view_->StartEditing(selected_node); | |
| break; | |
| case ID_REMOVE: | |
| model_.Remove(selected_node->parent(), selected_node); | |
| break; | |
| case ID_ADD: | |
| AddNewNode(); | |
| break; | |
| default: | |
| NOTREACHED(); | |
| } | |
| } | |
| } // namespace views::examples |