blob: 040daff9f625d5b100ce909e4788fb9833dc9b0c [file] [log] [blame]
// 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<NodeType>(
GetStringUTF16(IDS_TREE_VIEW_ROOT_NODE_LABEL),
1)) {}
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.
NodeType* colors_node = model_.GetRoot()->Add(
std::make_unique<NodeType>(GetStringUTF16(IDS_TREE_VIEW_COLOR_NODE_LABEL),
1),
0);
colors_node->Add(std::make_unique<NodeType>(
GetStringUTF16(IDS_TREE_VIEW_COLOR_RED_LABEL), 1),
0);
colors_node->Add(std::make_unique<NodeType>(
GetStringUTF16(IDS_TREE_VIEW_COLOR_GREEN_LABEL), 1),
1);
colors_node->Add(std::make_unique<NodeType>(
GetStringUTF16(IDS_TREE_VIEW_COLOR_BLUE_LABEL), 1),
2);
NodeType* sheep_node = model_.GetRoot()->Add(
std::make_unique<NodeType>(GetStringUTF16(IDS_TREE_VIEW_SHEEP_NODE_LABEL),
1),
0);
sheep_node->Add(
std::make_unique<NodeType>(GetStringUTF16(IDS_TREE_VIEW_SHEEP1_LABEL), 1),
0);
sheep_node->Add(
std::make_unique<NodeType>(GetStringUTF16(IDS_TREE_VIEW_SHEEP2_LABEL), 1),
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(1);
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->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() {
NodeType* selected_node =
static_cast<NodeType*>(tree_view_->GetSelectedNode());
if (!selected_node) {
selected_node = model_.GetRoot();
}
NodeType* new_node = model_.Add(
selected_node, std::make_unique<NodeType>(selected_node->GetTitle(), 1));
tree_view_->SetSelectedNode(new_node);
}
void TreeViewExample::RemoveSelectedNode() {
auto* selected_node = static_cast<NodeType*>(tree_view_->GetSelectedNode());
DCHECK(selected_node);
DCHECK_NE(model_.GetRoot(), selected_node);
model_.Remove(selected_node->parent(), selected_node);
}
void TreeViewExample::SetSelectedNodeTitle() {
auto* selected_node = static_cast<NodeType*>(tree_view_->GetSelectedNode());
DCHECK(selected_node);
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) {
NodeType* selected_node =
static_cast<NodeType*>(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