blob: 317d01fa0ad3daadf661a65a6422dab5f1097730 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/tray/tri_view.h"
#include "ash/system/tray/size_range_layout.h"
#include "base/logging.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/border.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/layout_manager.h"
namespace ash {
namespace {
// Converts TriView::Orientation values to views::BoxLayout::Orientation values.
views::BoxLayout::Orientation GetOrientation(TriView::Orientation orientation) {
switch (orientation) {
case TriView::Orientation::HORIZONTAL:
return views::BoxLayout::kHorizontal;
case TriView::Orientation::VERTICAL:
return views::BoxLayout::kVertical;
}
// Required for some compilers.
NOTREACHED();
return views::BoxLayout::kHorizontal;
}
// A View that will perform a layout if a child view's preferred size changes.
class RelayoutView : public views::View {
public:
RelayoutView() = default;
// views::View:
void ChildPreferredSizeChanged(View* child) override { Layout(); }
private:
DISALLOW_COPY_AND_ASSIGN(RelayoutView);
};
} // namespace
TriView::TriView() : TriView(0) {}
TriView::TriView(int padding_between_containers)
: TriView(Orientation::HORIZONTAL, padding_between_containers) {}
TriView::TriView(Orientation orientation) : TriView(orientation, 0) {}
TriView::TriView(Orientation orientation, int padding_between_containers) {
AddChildView(new RelayoutView);
AddChildView(new RelayoutView);
AddChildView(new RelayoutView);
start_container_layout_manager_ =
GetContainer(Container::START)
->SetLayoutManager(std::make_unique<SizeRangeLayout>());
center_container_layout_manager_ =
GetContainer(Container::CENTER)
->SetLayoutManager(std::make_unique<SizeRangeLayout>());
end_container_layout_manager_ =
GetContainer(Container::END)
->SetLayoutManager(std::make_unique<SizeRangeLayout>());
auto layout = std::make_unique<views::BoxLayout>(
GetOrientation(orientation), gfx::Insets(), padding_between_containers);
layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kStart);
box_layout_ = SetLayoutManager(std::move(layout));
enable_hierarchy_changed_dcheck_ = true;
}
TriView::~TriView() {
enable_hierarchy_changed_dcheck_ = false;
}
void TriView::SetMinHeight(int height) {
gfx::Size min_size;
min_size = GetMinSize(TriView::Container::START);
min_size.set_height(height);
SetMinSize(TriView::Container::START, min_size);
min_size = GetMinSize(TriView::Container::CENTER);
min_size.set_height(height);
SetMinSize(TriView::Container::CENTER, min_size);
min_size = GetMinSize(TriView::Container::END);
min_size.set_height(height);
SetMinSize(TriView::Container::END, min_size);
}
void TriView::SetMinSize(Container container, const gfx::Size& size) {
GetLayoutManager(container)->SetMinSize(size);
}
gfx::Size TriView::GetMinSize(Container container) {
return GetLayoutManager(container)->min_size();
}
void TriView::SetMaxSize(Container container, const gfx::Size& size) {
GetLayoutManager(container)->SetMaxSize(size);
}
void TriView::AddView(Container container, views::View* view) {
GetContainer(container)->AddChildView(view);
}
void TriView::RemoveAllChildren(Container container, bool delete_children) {
GetContainer(container)->RemoveAllChildViews(delete_children);
}
void TriView::SetInsets(const gfx::Insets& insets) {
box_layout_->set_inside_border_insets(insets);
}
void TriView::SetContainerBorder(Container container,
std::unique_ptr<views::Border> border) {
GetContainer(container)->SetBorder(std::move(border));
}
void TriView::SetContainerVisible(Container container, bool visible) {
if (GetContainer(container)->visible() == visible)
return;
GetContainer(container)->SetVisible(visible);
Layout();
}
void TriView::SetFlexForContainer(Container container, int flex) {
box_layout_->SetFlexForView(GetContainer(container), flex);
}
void TriView::SetContainerLayout(
Container container,
std::unique_ptr<views::LayoutManager> layout_manager) {
GetLayoutManager(container)->SetLayoutManager(std::move(layout_manager));
}
void TriView::ViewHierarchyChanged(
const views::ViewHierarchyChangedDetails& details) {
views::View::ViewHierarchyChanged(details);
if (!enable_hierarchy_changed_dcheck_)
return;
if (details.parent == this) {
if (details.is_add) {
DCHECK(false)
<< "Child views should not be added directly. They should be added "
"using TriView::AddView().";
} else {
DCHECK(false) << "Container views should not be removed.";
}
}
}
const char* TriView::GetClassName() const {
return "TriView";
}
views::View* TriView::GetContainer(Container container) {
return children()[static_cast<size_t>(container)];
}
SizeRangeLayout* TriView::GetLayoutManager(Container container) {
switch (container) {
case Container::START:
return start_container_layout_manager_;
case Container::CENTER:
return center_container_layout_manager_;
case Container::END:
return end_container_layout_manager_;
}
// Required for some compilers.
NOTREACHED();
return nullptr;
}
} // namespace ash