blob: c4d27452a98d6bbd8038e17fa2f50896b865a07b [file] [log] [blame]
// Copyright 2017 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/system_tray_view.h"
#include "ash/shell.h"
#include "ash/system/tray/system_tray_item.h"
#include "base/metrics/histogram_macros.h"
#include "ui/views/layout/box_layout.h"
namespace ash {
namespace {
class BottomAlignedBoxLayout : public views::BoxLayout {
public:
explicit BottomAlignedBoxLayout() : BoxLayout(BoxLayout::kVertical) {
SetDefaultFlex(1);
}
~BottomAlignedBoxLayout() override = default;
private:
void Layout(views::View* host) override {
if (host->height() >= host->GetPreferredSize().height()) {
BoxLayout::Layout(host);
return;
}
int consumed_height = 0;
for (int i = host->child_count() - 1;
i >= 0 && consumed_height < host->height(); --i) {
views::View* child = host->child_at(i);
if (!child->visible())
continue;
gfx::Size size = child->GetPreferredSize();
child->SetBounds(0, host->height() - consumed_height - size.height(),
host->width(), size.height());
consumed_height += size.height();
}
}
DISALLOW_COPY_AND_ASSIGN(BottomAlignedBoxLayout);
};
} // anonymous namespace
SystemTrayView::SystemTrayView(SystemTrayType system_tray_type,
const std::vector<ash::SystemTrayItem*>& items)
: items_(items), system_tray_type_(system_tray_type) {
SetLayoutManager(std::make_unique<BottomAlignedBoxLayout>());
}
SystemTrayView::~SystemTrayView() {
DestroyItemViews();
}
bool SystemTrayView::CreateItemViews(LoginStatus login_status) {
tray_item_view_map_.clear();
// If a system modal dialog is present, create the same tray as
// in locked state.
if (Shell::IsSystemModalWindowOpen() &&
login_status != LoginStatus::NOT_LOGGED_IN) {
login_status = LoginStatus::LOCKED;
}
views::View* focus_view = nullptr;
for (ash::SystemTrayItem* const it : items_) {
views::View* item_view = nullptr;
switch (system_tray_type_) {
case SYSTEM_TRAY_TYPE_DEFAULT:
item_view = it->CreateDefaultView(login_status);
if (it->restore_focus())
focus_view = item_view;
break;
case SYSTEM_TRAY_TYPE_DETAILED:
item_view = it->CreateDetailedView(login_status);
break;
}
if (item_view) {
AddChildView(item_view);
tray_item_view_map_[it->uma_type()] = item_view;
}
}
if (focus_view) {
focus_view->RequestFocus();
return true;
}
return false;
}
void SystemTrayView::DestroyItemViews() {
for (ash::SystemTrayItem* const it : items_) {
switch (system_tray_type_) {
case SYSTEM_TRAY_TYPE_DEFAULT:
it->OnDefaultViewDestroyed();
break;
case SYSTEM_TRAY_TYPE_DETAILED:
it->OnDetailedViewDestroyed();
break;
}
}
}
void SystemTrayView::RecordVisibleRowMetrics() {
if (system_tray_type_ != SYSTEM_TRAY_TYPE_DEFAULT)
return;
for (const std::pair<SystemTrayItem::UmaType, views::View*>& pair :
tray_item_view_map_) {
if (pair.second->visible() &&
pair.first != SystemTrayItem::UMA_NOT_RECORDED) {
UMA_HISTOGRAM_ENUMERATION("Ash.SystemMenu.DefaultView.VisibleRows",
pair.first, SystemTrayItem::UMA_COUNT);
}
}
}
} // namespace ash