blob: acfafca94e475351c2d61ea6b277373603c28a50 [file] [log] [blame]
// Copyright 2020 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.
#ifndef ASH_CLIPBOARD_CLIPBOARD_HISTORY_MENU_MODEL_ADAPTER_H_
#define ASH_CLIPBOARD_CLIPBOARD_HISTORY_MENU_MODEL_ADAPTER_H_
#include <memory>
#include "ash/ash_export.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
namespace gfx {
class Rect;
} // namespace gfx
namespace views {
class MenuItemView;
class MenuRunner;
} // namespace views
namespace ash {
namespace ClipboardHistoryUtil {
enum class Action;
} // namespace ClipboardHistoryUtil
class ClipboardHistory;
class ClipboardHistoryItem;
class ClipboardHistoryItemView;
class ClipboardHistoryResourceManager;
// Used to show the clipboard history menu, which holds the last few things
// copied.
class ASH_EXPORT ClipboardHistoryMenuModelAdapter : views::MenuModelAdapter {
public:
static std::unique_ptr<ClipboardHistoryMenuModelAdapter> Create(
ui::SimpleMenuModel::Delegate* delegate,
base::RepeatingClosure menu_closed_callback,
const ClipboardHistory* clipboard_history,
const ClipboardHistoryResourceManager* resource_manager);
ClipboardHistoryMenuModelAdapter(const ClipboardHistoryMenuModelAdapter&) =
delete;
ClipboardHistoryMenuModelAdapter& operator=(
const ClipboardHistoryMenuModelAdapter&) = delete;
~ClipboardHistoryMenuModelAdapter() override;
// Shows the menu anchored at `anchor_rect`, `source_type` indicates how the
// menu is triggered.
void Run(const gfx::Rect& anchor_rect,
ui::MenuSourceType source_type);
// Returns if the menu is currently running.
bool IsRunning() const;
// Hides and cancels the menu.
void Cancel();
// Returns the command of the currently selected menu item. If no menu item is
// currently selected, returns |base::nullopt|.
base::Optional<int> GetSelectedMenuItemCommand() const;
// Returns the item mapped by `command_id` in `item_snapshots_`.
const ClipboardHistoryItem& GetItemFromCommandId(int command_id) const;
// Returns the count of menu items.
int GetMenuItemsCount() const;
// Selects the menu item specified by `command_id`.
void SelectMenuItemWithCommandId(int command_id);
// Selects the menu item hovered by mouse.
void SelectMenuItemHoveredByMouse();
// Removes the menu item specified by `command_id`.
void RemoveMenuItemWithCommandId(int command_id);
// Advances the pseudo focus (backward if `reverse` is true).
void AdvancePseudoFocus(bool reverse);
// Returns the action to take on the menu item specified by `command_id`.
ClipboardHistoryUtil::Action GetActionForCommandId(int command_id) const;
// Returns menu bounds in screen coordinates.
gfx::Rect GetMenuBoundsInScreenForTest() const;
const views::MenuItemView* GetMenuItemViewAtForTest(int index) const;
views::MenuItemView* GetMenuItemViewAtForTest(int index);
void set_item_removal_callback_for_test(base::RepeatingClosure new_callback) {
item_removal_callback_for_test_ = std::move(new_callback);
}
private:
class ScopedA11yIgnore;
ClipboardHistoryMenuModelAdapter(
std::unique_ptr<ui::SimpleMenuModel> model,
base::RepeatingClosure menu_closed_callback,
const ClipboardHistory* clipboard_history,
const ClipboardHistoryResourceManager* resource_manager);
// Advances the pseduo focus from the selected history item view (backward if
// `reverse` is true).
void AdvancePseudoFocusFromSelectedItem(bool reverse);
// Returns the command id of the menu item to be selected after the
// menu item specified by `command_id` is deleted.
int CalculateSelectedCommandIdAfterDeletion(int command_id) const;
// Removes the item view specified by `command_id` from the root menu.
void RemoveItemView(int command_id);
// views::MenuModelAdapter:
views::MenuItemView* AppendMenuItem(views::MenuItemView* menu,
ui::MenuModel* model,
int index) override;
void OnMenuClosed(views::MenuItemView* menu) override;
// The model which holds the contents of the menu.
std::unique_ptr<ui::SimpleMenuModel> const model_;
// The root MenuItemView which contains all child MenuItemViews. Owned by
// |menu_runner_|.
views::MenuItemView* root_view_ = nullptr;
// Responsible for showing |root_view_|.
std::unique_ptr<views::MenuRunner> menu_runner_;
// The timestamp taken when the menu is opened. Used in metrics.
base::TimeTicks menu_open_time_;
// The mapping between the command ids and items that are copied from
// `clipboard_history_` when the menu is created. It is used to solve the
// possible inconsistency between the menu model data and the clipboard
// history data. For example, a new item is added to `clipboard_history_`
// while the menu is showing.
// It updates synchronously when a item is removed.
std::map<int, ClipboardHistoryItem> item_snapshots_;
// Stores mappings between command ids and history item view pointers.
// It updates synchronously when a item is removed.
std::map<int, ClipboardHistoryItemView*> item_views_by_command_id_;
const ClipboardHistory* const clipboard_history_;
// Resource manager used to fetch image models. Owned by
// ClipboardHistoryController.
const ClipboardHistoryResourceManager* const resource_manager_;
// Indicates the number of item deletion operations in progress. Note that
// a `ClipboardHistoryItemView` instance is deleted asynchronously.
int item_deletion_in_progress_count_ = 0;
std::unique_ptr<ScopedA11yIgnore> scoped_ignore_;
// Indicates whether `Run()` has been called before.
bool run_before_ = false;
// Called when an item view is removed from the root menu.
base::RepeatingClosure item_removal_callback_for_test_;
base::WeakPtrFactory<ClipboardHistoryMenuModelAdapter> weak_ptr_factory_{
this};
};
} // namespace ash
#endif // ASH_CLIPBOARD_CLIPBOARD_HISTORY_MENU_MODEL_ADAPTER_H_