// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/app_menu/notification_menu_controller.h"
#include "ash/app_menu/app_menu_model_adapter.h"
#include "ash/app_menu/notification_menu_view.h"
#include "ash/public/cpp/app_menu_constants.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/submenu_view.h"
namespace ash {
NotificationMenuController::NotificationMenuController(
const std::string& app_id,
views::MenuItemView* root_menu,
AppMenuModelAdapter* app_menu_model_adapter)
: app_id_(app_id),
root_menu_(root_menu),
app_menu_model_adapter_(app_menu_model_adapter) {
DCHECK(app_menu_model_adapter_);
message_center_observation_.Observe(message_center::MessageCenter::Get());
InitializeNotificationMenuView();
}
NotificationMenuController::~NotificationMenuController() = default;
void NotificationMenuController::OnNotificationAdded(
const std::string& notification_id) {
message_center::Notification* notification =
message_center::MessageCenter::Get()->FindVisibleNotificationById(
notification_id);
DCHECK(notification);
if (notification->notifier_id().id != app_id_)
return;
if (!notification_menu_view_) {
InitializeNotificationMenuView();
return;
}
notification_menu_view_->AddNotificationItemView(*notification);
}
void NotificationMenuController::OnNotificationUpdated(
const std::string& notification_id) {
if (!notification_menu_view_)
return;
message_center::Notification* notification =
message_center::MessageCenter::Get()->FindVisibleNotificationById(
notification_id);
DCHECK(notification);
if (notification->notifier_id().id != app_id_)
return;
notification_menu_view_->UpdateNotificationItemView(*notification);
}
void NotificationMenuController::OnNotificationRemoved(
const std::string& notification_id,
bool by_user) {
if (!notification_menu_view_)
return;
// Remove the view from the container.
notification_menu_view_->OnNotificationRemoved(notification_id);
if (!notification_menu_view_->IsEmpty())
return;
// There are no more notifications to show, so remove |item_| from
// |root_menu_|, and remove the entry from the model.
root_menu_->RemoveMenuItem(notification_menu_view_->parent());
app_menu_model_adapter_->model()->RemoveItemAt(
app_menu_model_adapter_->model()
->GetIndexOfCommandId(NOTIFICATION_CONTAINER)
.value());
notification_menu_view_ = nullptr;
// Notify the root MenuItemView so it knows to resize and re-calculate the
// menu bounds.
root_menu_->ChildrenChanged();
}
ui::Layer* NotificationMenuController::GetSlideOutLayer() {
return notification_menu_view_ ? notification_menu_view_->GetSlideOutLayer()
: nullptr;
}
void NotificationMenuController::OnSlideChanged(bool in_progress) {}
void NotificationMenuController::OnSlideOut() {
// Results in |this| being deleted if there are no more notifications to show.
// Only the displayed NotificationItemView can call OnSlideOut.
message_center::MessageCenter::Get()->RemoveNotification(
notification_menu_view_->GetDisplayedNotificationID(), true);
}
void NotificationMenuController::ActivateNotificationAndClose(
const std::string& notification_id) {
message_center::MessageCenter::Get()->ClickOnNotification(notification_id);
// Results in |this| being deleted.
app_menu_model_adapter_->Cancel();
}
void NotificationMenuController::OnOverflowAddedOrRemoved() {
// Make the root MenuItemView recalculate the menu bounds.
root_menu_->ChildrenChanged();
}
void NotificationMenuController::InitializeNotificationMenuView() {
DCHECK(!notification_menu_view_);
// Initialize the container only if there are notifications to show.
if (message_center::MessageCenter::Get()
->FindNotificationsByAppId(app_id_)
.empty()) {
return;
}
app_menu_model_adapter_->model()->AddItem(NOTIFICATION_CONTAINER,
std::u16string());
// Add the container MenuItemView to |root_menu_|.
views::MenuItemView* container =
root_menu_->AppendMenuItem(NOTIFICATION_CONTAINER);
notification_menu_view_ = new NotificationMenuView(this, this, app_id_);
container->AddChildView(notification_menu_view_.get());
for (message_center::Notification* notification :
message_center::MessageCenter::Get()->FindNotificationsByAppId(
app_id_)) {
notification_menu_view_->AddNotificationItemView(*notification);
}
// Notify the root MenuItemView so it knows to resize and re-calculate the
// menu bounds.
root_menu_->ChildrenChanged();
}
} // namespace ash