| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_UI_COCOA_TAB_MENU_BRIDGE_H_ |
| #define CHROME_BROWSER_UI_COCOA_TAB_MENU_BRIDGE_H_ |
| |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" |
| |
| @class NSMutableArray; |
| @class NSMenuItem; |
| @class TabMenuListener; |
| class TabStripModel; |
| |
| // A TabMenuBridge bidirectionally connects a list of tabs (represented by a |
| // TabStripModel) to an NSMenu, for use in the system menu bar. Specifically, |
| // the TabStripBridge appends items to the bottom of the provided NSMenu |
| // corresponding to tabs in the TabStripModel, and keeps those items |
| // synchronized with changes to the TabStripModel. Clicking one of these items |
| // activates the corresponding tab in the TabStripModel. This class assumes |
| // that: |
| // 1) It owns the bottom "dynamic" part of of the provided menu |
| // 2) The number of items not in the "dynamic" part does not change after the |
| // TabMenuBridge is constructed |
| // |
| // To use this class, construct an instance and call BuildMenu() on it. |
| class TabMenuBridge : public TabStripModelObserver { |
| public: |
| // The |menu_item| contains the actual menu this class manages. |
| TabMenuBridge(TabStripModel* model, NSMenuItem* menu_item); |
| |
| TabMenuBridge(const TabMenuBridge&) = delete; |
| TabMenuBridge& operator=(const TabMenuBridge&) = delete; |
| |
| ~TabMenuBridge() override; |
| |
| // It's legal to call this method more than once - it will clear all the |
| // existing dynamic items added by this instance before adding any new ones, |
| // so multiple calls are idempotent. |
| void BuildMenu(); |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(TabMenuBridgeTest, ClickingMenuActivatesTab); |
| |
| // These methods are used manage the dynamic menu items. |
| NSMutableArray* DynamicMenuItems(); |
| void AddDynamicItemsFromModel(); |
| |
| // This method exists to be called back into from the Cocoa part of this |
| // bridge class (TabMenuListener). |
| void OnDynamicItemChosen(NSMenuItem* item); |
| |
| // TabStripModelObserver: |
| void OnTabStripModelChanged( |
| TabStripModel* tab_strip_model, |
| const TabStripModelChange& change, |
| const TabStripSelectionChange& selection) override; |
| void TabChangedAt(content::WebContents* contents, |
| int index, |
| TabChangeType change_type) override; |
| void OnTabGroupChanged(const TabGroupChange& change) override; |
| void TabGroupedStateChanged(TabStripModel* tab_strip_model, |
| std::optional<tab_groups::TabGroupId> old_group, |
| std::optional<tab_groups::TabGroupId> new_group, |
| tabs::TabInterface* tab, |
| int index) override; |
| void OnTabStripModelDestroyed(TabStripModel* model) override; |
| |
| raw_ptr<TabStripModel> model_; |
| NSMenuItem* __weak menu_item_; |
| TabMenuListener* __strong menu_listener_; |
| |
| // When created, this class remembers how many items were present in the |
| // non-dynamic section of the menu. This offset is used to map menu items to |
| // their underlying tabs. |
| int dynamic_items_start_; |
| }; |
| |
| #endif // CHROME_BROWSER_UI_COCOA_TAB_MENU_BRIDGE_H_ |