chromium/components/remote_cocoa/app_shim/mojo_menu_model.mm

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/remote_cocoa/app_shim/mojo_menu_model.h"

#include "ui/base/models/image_model.h"

namespace remote_cocoa {

MojoMenuModel::MojoMenuModel(std::vector<mojom::MenuItemPtr> menu_items,
                             mojom::MenuHost* menu_host)
    : menu_items_(std::move(menu_items)), menu_host_(menu_host) {
  submenus_.resize(menu_items_.size());
}

MojoMenuModel::~MojoMenuModel() = default;

base::WeakPtr<ui::MenuModel> MojoMenuModel::AsWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

size_t MojoMenuModel::GetItemCount() const {
  return menu_items_.size();
}

ui::MenuModel::ItemType MojoMenuModel::GetTypeAt(size_t index) const {
  switch (menu_items_[index]->which()) {
    case mojom::MenuItem::Tag::kSeparator:
      return TYPE_SEPARATOR;
    case mojom::MenuItem::Tag::kRegular:
      return TYPE_COMMAND;
    case mojom::MenuItem::Tag::kSubmenu:
      return TYPE_SUBMENU;
  }
  NOTREACHED_IN_MIGRATION();
}

ui::MenuSeparatorType MojoMenuModel::GetSeparatorTypeAt(size_t index) const {
  // Not used by MenuControllerCocoa.
  return ui::NORMAL_SEPARATOR;
}

int MojoMenuModel::GetCommandIdAt(size_t index) const {
  return GetCommonFieldsAt(index)->command_id;
}

std::u16string MojoMenuModel::GetLabelAt(size_t index) const {
  return GetCommonFieldsAt(index)->label;
}

bool MojoMenuModel::IsItemDynamicAt(size_t index) const {
  // For now we don't support dynamic menu items. This doesn't matter since only
  // dynamic items in submenus would be meaningful anyway (as a MojoMenuModel is
  // never displayed more than once, so the top-level menu can't be shown
  // multiple times).
  return false;
}

bool MojoMenuModel::MayHaveMnemonicsAt(size_t index) const {
  return GetCommonFieldsAt(index)->may_have_mnemonics;
}

bool MojoMenuModel::GetAcceleratorAt(size_t index,
                                     ui::Accelerator* accelerator) const {
  // On macOS context menus never have accelerators. Since this class is only
  // used for context menus, this always returns false.
  return false;
}

bool MojoMenuModel::IsItemCheckedAt(size_t index) const {
  return GetCommonFieldsAt(index)->is_checked;
}

int MojoMenuModel::GetGroupIdAt(size_t index) const {
  // Not used by MenuControllerCocoa.
  return -1;
}

ui::ImageModel MojoMenuModel::GetIconAt(size_t index) const {
  if (const auto& icon = GetCommonFieldsAt(index)->icon; !icon.isNull()) {
    return ui::ImageModel::FromImageSkia(icon);
  }
  return {};
}

ui::ButtonMenuItemModel* MojoMenuModel::GetButtonMenuItemAt(
    size_t index) const {
  // Not used by MenuControllerCocoa.
  return nullptr;
}

bool MojoMenuModel::IsEnabledAt(size_t index) const {
  return GetCommonFieldsAt(index)->is_enabled;
}

bool MojoMenuModel::IsVisibleAt(size_t index) const {
  return GetCommonFieldsAt(index)->is_visible;
}

bool MojoMenuModel::IsAlertedAt(size_t index) const {
  return GetCommonFieldsAt(index)->is_alerted;
}

bool MojoMenuModel::IsNewFeatureAt(size_t index) const {
  return GetCommonFieldsAt(index)->is_new_feature;
}

MojoMenuModel* MojoMenuModel::GetSubmenuModelAt(size_t index) const {
  if (!menu_items_[index]->is_submenu()) {
    return nullptr;
  }
  std::unique_ptr<MojoMenuModel>& submenu = submenus_[index];
  if (!submenu) {
    submenu = std::make_unique<MojoMenuModel>(
        std::move(menu_items_[index]->get_submenu()->children), menu_host_);
  }
  return submenu.get();
}

void MojoMenuModel::ActivatedAt(size_t index) {
  ActivatedAt(index, /*event_flags=*/0);
}

void MojoMenuModel::ActivatedAt(size_t index, int event_flags) {
  menu_host_->CommandActivated(GetCommonFieldsAt(index)->command_id,
                               event_flags);
}

mojom::MenuItemCommonFields* MojoMenuModel::GetCommonFieldsAt(
    size_t index) const {
  switch (menu_items_[index]->which()) {
    case mojom::MenuItem::Tag::kSeparator:
      return menu_items_[index]->get_separator().get();
    case mojom::MenuItem::Tag::kRegular:
      return menu_items_[index]->get_regular().get();
    case mojom::MenuItem::Tag::kSubmenu:
      return menu_items_[index]->get_submenu()->common.get();
  }
  NOTREACHED_IN_MIGRATION();
}

}  // namespace remote_cocoa