1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/system/tray/tri_view.h"
6
7 #include "ash/system/tray/size_range_layout.h"
8 #include "base/check.h"
9 #include "base/notreached.h"
10 #include "ui/gfx/geometry/insets.h"
11 #include "ui/views/border.h"
12 #include "ui/views/layout/box_layout.h"
13 #include "ui/views/layout/fill_layout.h"
14 #include "ui/views/layout/layout_manager.h"
15
16 namespace ash {
17 namespace {
18
19 // Converts TriView::Orientation values to views::BoxLayout::Orientation values.
GetOrientation(TriView::Orientation orientation)20 views::BoxLayout::Orientation GetOrientation(TriView::Orientation orientation) {
21 switch (orientation) {
22 case TriView::Orientation::HORIZONTAL:
23 return views::BoxLayout::Orientation::kHorizontal;
24 case TriView::Orientation::VERTICAL:
25 return views::BoxLayout::Orientation::kVertical;
26 }
27 // Required for some compilers.
28 NOTREACHED();
29 return views::BoxLayout::Orientation::kHorizontal;
30 }
31
32 // A View that will perform a layout if a child view's preferred size changes.
33 class RelayoutView : public views::View {
34 public:
35 RelayoutView() = default;
36
37 // views::View:
ChildPreferredSizeChanged(View * child)38 void ChildPreferredSizeChanged(View* child) override { Layout(); }
39
40 private:
41 DISALLOW_COPY_AND_ASSIGN(RelayoutView);
42 };
43
44 } // namespace
45
TriView()46 TriView::TriView() : TriView(0) {}
47
TriView(int padding_between_containers)48 TriView::TriView(int padding_between_containers)
49 : TriView(Orientation::HORIZONTAL, padding_between_containers) {}
50
TriView(Orientation orientation)51 TriView::TriView(Orientation orientation) : TriView(orientation, 0) {}
52
TriView(Orientation orientation,int padding_between_containers)53 TriView::TriView(Orientation orientation, int padding_between_containers) {
54 AddChildView(new RelayoutView);
55 AddChildView(new RelayoutView);
56 AddChildView(new RelayoutView);
57
58 start_container_layout_manager_ =
59 GetContainer(Container::START)
60 ->SetLayoutManager(std::make_unique<SizeRangeLayout>());
61 center_container_layout_manager_ =
62 GetContainer(Container::CENTER)
63 ->SetLayoutManager(std::make_unique<SizeRangeLayout>());
64 end_container_layout_manager_ =
65 GetContainer(Container::END)
66 ->SetLayoutManager(std::make_unique<SizeRangeLayout>());
67
68 auto layout = std::make_unique<views::BoxLayout>(
69 GetOrientation(orientation), gfx::Insets(), padding_between_containers);
70 layout->set_cross_axis_alignment(
71 views::BoxLayout::CrossAxisAlignment::kStart);
72 box_layout_ = SetLayoutManager(std::move(layout));
73
74 enable_hierarchy_changed_dcheck_ = true;
75 }
76
~TriView()77 TriView::~TriView() {
78 enable_hierarchy_changed_dcheck_ = false;
79 }
80
SetMinHeight(int height)81 void TriView::SetMinHeight(int height) {
82 gfx::Size min_size;
83
84 min_size = GetMinSize(TriView::Container::START);
85 min_size.set_height(height);
86 SetMinSize(TriView::Container::START, min_size);
87
88 min_size = GetMinSize(TriView::Container::CENTER);
89 min_size.set_height(height);
90 SetMinSize(TriView::Container::CENTER, min_size);
91
92 min_size = GetMinSize(TriView::Container::END);
93 min_size.set_height(height);
94 SetMinSize(TriView::Container::END, min_size);
95 }
96
SetMinSize(Container container,const gfx::Size & size)97 void TriView::SetMinSize(Container container, const gfx::Size& size) {
98 GetLayoutManager(container)->SetMinSize(size);
99 }
100
GetMinSize(Container container)101 gfx::Size TriView::GetMinSize(Container container) {
102 return GetLayoutManager(container)->min_size();
103 }
104
SetMaxSize(Container container,const gfx::Size & size)105 void TriView::SetMaxSize(Container container, const gfx::Size& size) {
106 GetLayoutManager(container)->SetMaxSize(size);
107 }
108
AddView(Container container,views::View * view)109 void TriView::AddView(Container container, views::View* view) {
110 GetContainer(container)->AddChildView(view);
111 }
112
RemoveAllChildren(Container container,bool delete_children)113 void TriView::RemoveAllChildren(Container container, bool delete_children) {
114 GetContainer(container)->RemoveAllChildViews(delete_children);
115 }
116
SetInsets(const gfx::Insets & insets)117 void TriView::SetInsets(const gfx::Insets& insets) {
118 box_layout_->set_inside_border_insets(insets);
119 }
120
SetContainerBorder(Container container,std::unique_ptr<views::Border> border)121 void TriView::SetContainerBorder(Container container,
122 std::unique_ptr<views::Border> border) {
123 GetContainer(container)->SetBorder(std::move(border));
124 }
125
SetContainerVisible(Container container,bool visible)126 void TriView::SetContainerVisible(Container container, bool visible) {
127 if (GetContainer(container)->GetVisible() == visible)
128 return;
129 GetContainer(container)->SetVisible(visible);
130 Layout();
131 }
132
SetFlexForContainer(Container container,int flex)133 void TriView::SetFlexForContainer(Container container, int flex) {
134 box_layout_->SetFlexForView(GetContainer(container), flex);
135 }
136
SetContainerLayout(Container container,std::unique_ptr<views::LayoutManager> layout_manager)137 void TriView::SetContainerLayout(
138 Container container,
139 std::unique_ptr<views::LayoutManager> layout_manager) {
140 GetLayoutManager(container)->SetLayoutManager(std::move(layout_manager));
141 }
142
ViewHierarchyChanged(const views::ViewHierarchyChangedDetails & details)143 void TriView::ViewHierarchyChanged(
144 const views::ViewHierarchyChangedDetails& details) {
145 views::View::ViewHierarchyChanged(details);
146 if (!enable_hierarchy_changed_dcheck_)
147 return;
148
149 if (details.parent == this) {
150 if (details.is_add) {
151 DCHECK(false)
152 << "Child views should not be added directly. They should be added "
153 "using TriView::AddView().";
154 } else {
155 DCHECK(false) << "Container views should not be removed.";
156 }
157 }
158 }
159
GetClassName() const160 const char* TriView::GetClassName() const {
161 return "TriView";
162 }
163
GetContainer(Container container)164 views::View* TriView::GetContainer(Container container) {
165 return children()[static_cast<size_t>(container)];
166 }
167
GetLayoutManager(Container container)168 SizeRangeLayout* TriView::GetLayoutManager(Container container) {
169 switch (container) {
170 case Container::START:
171 return start_container_layout_manager_;
172 case Container::CENTER:
173 return center_container_layout_manager_;
174 case Container::END:
175 return end_container_layout_manager_;
176 }
177 // Required for some compilers.
178 NOTREACHED();
179 return nullptr;
180 }
181
182 } // namespace ash
183