//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;
#[cfg(feature = "objc2-core-foundation")]
use objc2_core_foundation::*;
use objc2_foundation::*;

use crate::*;

/// When set as a value on `NSMenu.presentationStyle`, determines how
/// the given menu is presented.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenupresentationstyle?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NSMenuPresentationStyle(pub NSInteger);
impl NSMenuPresentationStyle {
    /// The default presentation style. Typically means the menu will
    /// be presented as either a popup or pulldown menu, based on the
    /// context.
    #[doc(alias = "NSMenuPresentationStyleRegular")]
    pub const Regular: Self = Self(0);
    /// The menu marked as palette is to be displayed in place of the
    /// menu item presenting it, with its items aligned horizontally.
    #[doc(alias = "NSMenuPresentationStylePalette")]
    pub const Palette: Self = Self(1);
}

unsafe impl Encode for NSMenuPresentationStyle {
    const ENCODING: Encoding = NSInteger::ENCODING;
}

unsafe impl RefEncode for NSMenuPresentationStyle {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// When set as a value on `NSMenu.selectionMode`, determines how the
/// menu manages selection states of the menu items that belong to
/// the same selection group.
///
/// This does not apply to menu items that have distinct
/// target/action values.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenuselectionmode?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NSMenuSelectionMode(pub NSInteger);
impl NSMenuSelectionMode {
    /// The menu will determine the appropriate selection mode based
    /// on the context and its contents.
    #[doc(alias = "NSMenuSelectionModeAutomatic")]
    pub const Automatic: Self = Self(0);
    /// The user will be allowed to select at most one menu item in
    /// the same selection group at a time. A change in selection
    /// will deselect any previously selected item.
    #[doc(alias = "NSMenuSelectionModeSelectOne")]
    pub const SelectOne: Self = Self(1);
    /// The user can select multiple items in the menu. A change in
    /// selection will not automatically deselect any previously
    /// selected item in the same selection group.
    #[doc(alias = "NSMenuSelectionModeSelectAny")]
    pub const SelectAny: Self = Self(2);
}

unsafe impl Encode for NSMenuSelectionMode {
    const ENCODING: Encoding = NSInteger::ENCODING;
}

unsafe impl RefEncode for NSMenuSelectionMode {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenu?language=objc)
    #[unsafe(super(NSObject))]
    #[thread_kind = MainThreadOnly]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct NSMenu;
);

#[cfg(feature = "NSAccessibilityProtocols")]
extern_conformance!(
    unsafe impl NSAccessibility for NSMenu {}
);

#[cfg(feature = "NSAccessibilityProtocols")]
extern_conformance!(
    unsafe impl NSAccessibilityElementProtocol for NSMenu {}
);

#[cfg(feature = "NSAppearance")]
extern_conformance!(
    unsafe impl NSAppearanceCustomization for NSMenu {}
);

extern_conformance!(
    unsafe impl NSCoding for NSMenu {}
);

extern_conformance!(
    unsafe impl NSCopying for NSMenu {}
);

unsafe impl CopyingHelper for NSMenu {
    type Result = Self;
}

extern_conformance!(
    unsafe impl NSObjectProtocol for NSMenu {}
);

#[cfg(feature = "NSUserInterfaceItemIdentification")]
extern_conformance!(
    unsafe impl NSUserInterfaceItemIdentification for NSMenu {}
);

impl NSMenu {
    extern_methods!(
        #[unsafe(method(initWithTitle:))]
        #[unsafe(method_family = init)]
        pub fn initWithTitle(this: Allocated<Self>, title: &NSString) -> Retained<Self>;

        /// # Safety
        ///
        /// `coder` possibly has further requirements.
        #[unsafe(method(initWithCoder:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithCoder(this: Allocated<Self>, coder: &NSCoder) -> Retained<Self>;

        #[unsafe(method(title))]
        #[unsafe(method_family = none)]
        pub fn title(&self) -> Retained<NSString>;

        /// Setter for [`title`][Self::title].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setTitle:))]
        #[unsafe(method_family = none)]
        pub fn setTitle(&self, title: &NSString);

        #[cfg(all(feature = "NSEvent", feature = "NSResponder", feature = "NSView"))]
        #[unsafe(method(popUpContextMenu:withEvent:forView:))]
        #[unsafe(method_family = none)]
        pub fn popUpContextMenu_withEvent_forView(menu: &NSMenu, event: &NSEvent, view: &NSView);

        #[cfg(all(
            feature = "NSEvent",
            feature = "NSFont",
            feature = "NSResponder",
            feature = "NSView"
        ))]
        #[unsafe(method(popUpContextMenu:withEvent:forView:withFont:))]
        #[unsafe(method_family = none)]
        pub fn popUpContextMenu_withEvent_forView_withFont(
            menu: &NSMenu,
            event: &NSEvent,
            view: &NSView,
            font: Option<&NSFont>,
        );

        #[cfg(all(feature = "NSMenuItem", feature = "NSResponder", feature = "NSView"))]
        #[unsafe(method(popUpMenuPositioningItem:atLocation:inView:))]
        #[unsafe(method_family = none)]
        pub fn popUpMenuPositioningItem_atLocation_inView(
            &self,
            item: Option<&NSMenuItem>,
            location: NSPoint,
            view: Option<&NSView>,
        ) -> bool;

        #[unsafe(method(setMenuBarVisible:))]
        #[unsafe(method_family = none)]
        pub fn setMenuBarVisible(visible: bool, mtm: MainThreadMarker);

        #[unsafe(method(menuBarVisible))]
        #[unsafe(method_family = none)]
        pub fn menuBarVisible(mtm: MainThreadMarker) -> bool;

        /// # Safety
        ///
        /// This is not retained internally, you must ensure the object is still alive.
        #[unsafe(method(supermenu))]
        #[unsafe(method_family = none)]
        pub unsafe fn supermenu(&self) -> Option<Retained<NSMenu>>;

        /// Setter for [`supermenu`][Self::supermenu].
        ///
        /// # Safety
        ///
        /// This is unretained, you must ensure the object is kept alive while in use.
        #[unsafe(method(setSupermenu:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSupermenu(&self, supermenu: Option<&NSMenu>);

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(insertItem:atIndex:))]
        #[unsafe(method_family = none)]
        pub fn insertItem_atIndex(&self, new_item: &NSMenuItem, index: NSInteger);

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(addItem:))]
        #[unsafe(method_family = none)]
        pub fn addItem(&self, new_item: &NSMenuItem);

        #[cfg(feature = "NSMenuItem")]
        /// # Safety
        ///
        /// `selector` must be a valid selector.
        #[unsafe(method(insertItemWithTitle:action:keyEquivalent:atIndex:))]
        #[unsafe(method_family = none)]
        pub unsafe fn insertItemWithTitle_action_keyEquivalent_atIndex(
            &self,
            string: &NSString,
            selector: Option<Sel>,
            char_code: &NSString,
            index: NSInteger,
        ) -> Retained<NSMenuItem>;

        #[cfg(feature = "NSMenuItem")]
        /// # Safety
        ///
        /// `selector` must be a valid selector.
        #[unsafe(method(addItemWithTitle:action:keyEquivalent:))]
        #[unsafe(method_family = none)]
        pub unsafe fn addItemWithTitle_action_keyEquivalent(
            &self,
            string: &NSString,
            selector: Option<Sel>,
            char_code: &NSString,
        ) -> Retained<NSMenuItem>;

        #[unsafe(method(removeItemAtIndex:))]
        #[unsafe(method_family = none)]
        pub fn removeItemAtIndex(&self, index: NSInteger);

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(removeItem:))]
        #[unsafe(method_family = none)]
        pub fn removeItem(&self, item: &NSMenuItem);

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(setSubmenu:forItem:))]
        #[unsafe(method_family = none)]
        pub fn setSubmenu_forItem(&self, menu: Option<&NSMenu>, item: &NSMenuItem);

        #[unsafe(method(removeAllItems))]
        #[unsafe(method_family = none)]
        pub fn removeAllItems(&self);

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(itemArray))]
        #[unsafe(method_family = none)]
        pub fn itemArray(&self) -> Retained<NSArray<NSMenuItem>>;

        #[cfg(feature = "NSMenuItem")]
        /// Setter for [`itemArray`][Self::itemArray].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setItemArray:))]
        #[unsafe(method_family = none)]
        pub fn setItemArray(&self, item_array: &NSArray<NSMenuItem>);

        #[unsafe(method(numberOfItems))]
        #[unsafe(method_family = none)]
        pub fn numberOfItems(&self) -> NSInteger;

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(itemAtIndex:))]
        #[unsafe(method_family = none)]
        pub fn itemAtIndex(&self, index: NSInteger) -> Option<Retained<NSMenuItem>>;

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(indexOfItem:))]
        #[unsafe(method_family = none)]
        pub fn indexOfItem(&self, item: &NSMenuItem) -> NSInteger;

        #[unsafe(method(indexOfItemWithTitle:))]
        #[unsafe(method_family = none)]
        pub fn indexOfItemWithTitle(&self, title: &NSString) -> NSInteger;

        #[unsafe(method(indexOfItemWithTag:))]
        #[unsafe(method_family = none)]
        pub fn indexOfItemWithTag(&self, tag: NSInteger) -> NSInteger;

        /// # Safety
        ///
        /// `object` should be of the correct type.
        #[unsafe(method(indexOfItemWithRepresentedObject:))]
        #[unsafe(method_family = none)]
        pub unsafe fn indexOfItemWithRepresentedObject(
            &self,
            object: Option<&AnyObject>,
        ) -> NSInteger;

        #[unsafe(method(indexOfItemWithSubmenu:))]
        #[unsafe(method_family = none)]
        pub fn indexOfItemWithSubmenu(&self, submenu: Option<&NSMenu>) -> NSInteger;

        /// # Safety
        ///
        /// - `target` should be of the correct type.
        /// - `action_selector` must be a valid selector.
        #[unsafe(method(indexOfItemWithTarget:andAction:))]
        #[unsafe(method_family = none)]
        pub unsafe fn indexOfItemWithTarget_andAction(
            &self,
            target: Option<&AnyObject>,
            action_selector: Option<Sel>,
        ) -> NSInteger;

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(itemWithTitle:))]
        #[unsafe(method_family = none)]
        pub fn itemWithTitle(&self, title: &NSString) -> Option<Retained<NSMenuItem>>;

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(itemWithTag:))]
        #[unsafe(method_family = none)]
        pub fn itemWithTag(&self, tag: NSInteger) -> Option<Retained<NSMenuItem>>;

        #[unsafe(method(autoenablesItems))]
        #[unsafe(method_family = none)]
        pub fn autoenablesItems(&self) -> bool;

        /// Setter for [`autoenablesItems`][Self::autoenablesItems].
        #[unsafe(method(setAutoenablesItems:))]
        #[unsafe(method_family = none)]
        pub fn setAutoenablesItems(&self, autoenables_items: bool);

        #[unsafe(method(update))]
        #[unsafe(method_family = none)]
        pub fn update(&self);

        #[cfg(feature = "NSEvent")]
        #[unsafe(method(performKeyEquivalent:))]
        #[unsafe(method_family = none)]
        pub fn performKeyEquivalent(&self, event: &NSEvent) -> bool;

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(itemChanged:))]
        #[unsafe(method_family = none)]
        pub fn itemChanged(&self, item: &NSMenuItem);

        #[unsafe(method(performActionForItemAtIndex:))]
        #[unsafe(method_family = none)]
        pub fn performActionForItemAtIndex(&self, index: NSInteger);

        #[unsafe(method(delegate))]
        #[unsafe(method_family = none)]
        pub fn delegate(&self) -> Option<Retained<ProtocolObject<dyn NSMenuDelegate>>>;

        /// Setter for [`delegate`][Self::delegate].
        ///
        /// This is a [weak property][objc2::topics::weak_property].
        #[unsafe(method(setDelegate:))]
        #[unsafe(method_family = none)]
        pub fn setDelegate(&self, delegate: Option<&ProtocolObject<dyn NSMenuDelegate>>);

        #[cfg(feature = "objc2-core-foundation")]
        #[unsafe(method(menuBarHeight))]
        #[unsafe(method_family = none)]
        pub fn menuBarHeight(&self) -> CGFloat;

        #[unsafe(method(cancelTracking))]
        #[unsafe(method_family = none)]
        pub fn cancelTracking(&self);

        #[unsafe(method(cancelTrackingWithoutAnimation))]
        #[unsafe(method_family = none)]
        pub fn cancelTrackingWithoutAnimation(&self);

        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(highlightedItem))]
        #[unsafe(method_family = none)]
        pub fn highlightedItem(&self) -> Option<Retained<NSMenuItem>>;

        #[cfg(feature = "objc2-core-foundation")]
        #[unsafe(method(minimumWidth))]
        #[unsafe(method_family = none)]
        pub fn minimumWidth(&self) -> CGFloat;

        #[cfg(feature = "objc2-core-foundation")]
        /// Setter for [`minimumWidth`][Self::minimumWidth].
        #[unsafe(method(setMinimumWidth:))]
        #[unsafe(method_family = none)]
        pub fn setMinimumWidth(&self, minimum_width: CGFloat);

        #[unsafe(method(size))]
        #[unsafe(method_family = none)]
        pub fn size(&self) -> NSSize;

        #[cfg(feature = "NSFont")]
        #[unsafe(method(font))]
        #[unsafe(method_family = none)]
        pub fn font(&self) -> Option<Retained<NSFont>>;

        #[cfg(feature = "NSFont")]
        /// Setter for [`font`][Self::font].
        ///
        /// # Safety
        ///
        /// `font` might not allow `None`.
        #[unsafe(method(setFont:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setFont(&self, font: Option<&NSFont>);

        #[unsafe(method(allowsContextMenuPlugIns))]
        #[unsafe(method_family = none)]
        pub fn allowsContextMenuPlugIns(&self) -> bool;

        /// Setter for [`allowsContextMenuPlugIns`][Self::allowsContextMenuPlugIns].
        #[unsafe(method(setAllowsContextMenuPlugIns:))]
        #[unsafe(method_family = none)]
        pub fn setAllowsContextMenuPlugIns(&self, allows_context_menu_plug_ins: bool);

        #[unsafe(method(automaticallyInsertsWritingToolsItems))]
        #[unsafe(method_family = none)]
        pub fn automaticallyInsertsWritingToolsItems(&self) -> bool;

        /// Setter for [`automaticallyInsertsWritingToolsItems`][Self::automaticallyInsertsWritingToolsItems].
        #[unsafe(method(setAutomaticallyInsertsWritingToolsItems:))]
        #[unsafe(method_family = none)]
        pub fn setAutomaticallyInsertsWritingToolsItems(
            &self,
            automatically_inserts_writing_tools_items: bool,
        );

        #[unsafe(method(showsStateColumn))]
        #[unsafe(method_family = none)]
        pub fn showsStateColumn(&self) -> bool;

        /// Setter for [`showsStateColumn`][Self::showsStateColumn].
        #[unsafe(method(setShowsStateColumn:))]
        #[unsafe(method_family = none)]
        pub fn setShowsStateColumn(&self, shows_state_column: bool);

        #[cfg(feature = "NSUserInterfaceLayout")]
        #[unsafe(method(userInterfaceLayoutDirection))]
        #[unsafe(method_family = none)]
        pub fn userInterfaceLayoutDirection(&self) -> NSUserInterfaceLayoutDirection;

        #[cfg(feature = "NSUserInterfaceLayout")]
        /// Setter for [`userInterfaceLayoutDirection`][Self::userInterfaceLayoutDirection].
        #[unsafe(method(setUserInterfaceLayoutDirection:))]
        #[unsafe(method_family = none)]
        pub fn setUserInterfaceLayoutDirection(
            &self,
            user_interface_layout_direction: NSUserInterfaceLayoutDirection,
        );
    );
}

/// Methods declared on superclass `NSObject`.
impl NSMenu {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new(mtm: MainThreadMarker) -> Retained<Self>;
    );
}

/// NSPaletteMenus.
impl NSMenu {
    extern_methods!(
        #[cfg(all(feature = "NSColor", feature = "block2"))]
        /// Creates a palette menu displaying user-selectable color
        /// tags using the provided array of colors and optional titles.
        ///
        /// Note that the palette menu is configured for display as an inline menu; you must set it as the submenu of another menu item, contained in a standard menu.
        /// The palette menu cannot be used to invoke the `popUpMenuPositioningItem` method, or attached directly to a popup button or toolbar item.
        ///
        ///
        /// Returns: An autoconfigured palette menu.
        #[unsafe(method(paletteMenuWithColors:titles:selectionHandler:))]
        #[unsafe(method_family = none)]
        pub fn paletteMenuWithColors_titles_selectionHandler(
            colors: &NSArray<NSColor>,
            item_titles: &NSArray<NSString>,
            on_selection_change: Option<&block2::DynBlock<dyn Fn(NonNull<NSMenu>)>>,
            mtm: MainThreadMarker,
        ) -> Retained<Self>;

        #[cfg(all(feature = "NSColor", feature = "NSImage", feature = "block2"))]
        /// Creates a palette menu displaying user-selectable color tags
        /// using the provided template image, tinted using the specified
        /// array of colors.
        ///
        /// Optionally allows observing changes to the selection state in
        /// the compact menu. The block is invoked after the selection
        /// has been updated. Currently selected items can be retrieved
        /// from the `selectedItems` property.
        ///
        /// Note that the palette menu is configured for display as an inline menu; you must set it as the submenu of another menu item, contained in a standard menu.
        /// The palette menu cannot be used to invoke the `popUpMenuPositioningItem` method, or attached directly to a popup button or toolbar item.
        ///
        ///
        /// Returns: An autoconfigured palette menu.
        #[unsafe(method(paletteMenuWithColors:titles:templateImage:selectionHandler:))]
        #[unsafe(method_family = none)]
        pub fn paletteMenuWithColors_titles_templateImage_selectionHandler(
            colors: &NSArray<NSColor>,
            item_titles: &NSArray<NSString>,
            image: &NSImage,
            on_selection_change: Option<&block2::DynBlock<dyn Fn(NonNull<NSMenu>)>>,
            mtm: MainThreadMarker,
        ) -> Retained<Self>;

        /// The presentation style of the menu.
        ///
        ///
        /// Note: This property is not respected if the menu is the main
        /// menu of the app.
        #[unsafe(method(presentationStyle))]
        #[unsafe(method_family = none)]
        pub fn presentationStyle(&self) -> NSMenuPresentationStyle;

        /// Setter for [`presentationStyle`][Self::presentationStyle].
        #[unsafe(method(setPresentationStyle:))]
        #[unsafe(method_family = none)]
        pub fn setPresentationStyle(&self, presentation_style: NSMenuPresentationStyle);

        /// The selection mode of the menu.
        ///
        /// Note the selection mode only has effect on menu items that
        /// belong to the same selection group. A selection group consists
        /// of the items with the same target/action.
        #[unsafe(method(selectionMode))]
        #[unsafe(method_family = none)]
        pub fn selectionMode(&self) -> NSMenuSelectionMode;

        /// Setter for [`selectionMode`][Self::selectionMode].
        #[unsafe(method(setSelectionMode:))]
        #[unsafe(method_family = none)]
        pub fn setSelectionMode(&self, selection_mode: NSMenuSelectionMode);

        #[cfg(feature = "NSMenuItem")]
        /// The menu items that are selected.
        ///
        /// An item is selected when its state is `NSControl.StateValue.on`.
        ///
        ///
        /// Note: This property is settable. Setting `selectedItems` will
        /// select any items that are contained in the provided array, and
        /// deselect any previously selected items that are not in the array.
        #[unsafe(method(selectedItems))]
        #[unsafe(method_family = none)]
        pub fn selectedItems(&self) -> Retained<NSArray<NSMenuItem>>;

        #[cfg(feature = "NSMenuItem")]
        /// Setter for [`selectedItems`][Self::selectedItems].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setSelectedItems:))]
        #[unsafe(method_family = none)]
        pub fn setSelectedItems(&self, selected_items: &NSArray<NSMenuItem>);
    );
}

/// NSSubmenuAction.
impl NSMenu {
    extern_methods!(
        /// # Safety
        ///
        /// `sender` should be of the correct type.
        #[unsafe(method(submenuAction:))]
        #[unsafe(method_family = none)]
        pub unsafe fn submenuAction(&self, sender: Option<&AnyObject>);
    );
}

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenuitemvalidation?language=objc)
    pub unsafe trait NSMenuItemValidation: NSObjectProtocol + MainThreadOnly {
        #[cfg(feature = "NSMenuItem")]
        #[unsafe(method(validateMenuItem:))]
        #[unsafe(method_family = none)]
        fn validateMenuItem(&self, menu_item: &NSMenuItem) -> bool;
    }
);

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenudelegate?language=objc)
    pub unsafe trait NSMenuDelegate: NSObjectProtocol + MainThreadOnly {
        #[optional]
        #[unsafe(method(menuNeedsUpdate:))]
        #[unsafe(method_family = none)]
        fn menuNeedsUpdate(&self, menu: &NSMenu);

        #[optional]
        #[unsafe(method(numberOfItemsInMenu:))]
        #[unsafe(method_family = none)]
        fn numberOfItemsInMenu(&self, menu: &NSMenu) -> NSInteger;

        #[cfg(feature = "NSMenuItem")]
        #[optional]
        #[unsafe(method(menu:updateItem:atIndex:shouldCancel:))]
        #[unsafe(method_family = none)]
        fn menu_updateItem_atIndex_shouldCancel(
            &self,
            menu: &NSMenu,
            item: &NSMenuItem,
            index: NSInteger,
            should_cancel: bool,
        ) -> bool;

        #[optional]
        #[unsafe(method(menuWillOpen:))]
        #[unsafe(method_family = none)]
        fn menuWillOpen(&self, menu: &NSMenu);

        #[optional]
        #[unsafe(method(menuDidClose:))]
        #[unsafe(method_family = none)]
        fn menuDidClose(&self, menu: &NSMenu);

        #[cfg(feature = "NSMenuItem")]
        #[optional]
        #[unsafe(method(menu:willHighlightItem:))]
        #[unsafe(method_family = none)]
        fn menu_willHighlightItem(&self, menu: &NSMenu, item: Option<&NSMenuItem>);

        #[cfg(feature = "NSScreen")]
        #[optional]
        #[unsafe(method(confinementRectForMenu:onScreen:))]
        #[unsafe(method_family = none)]
        fn confinementRectForMenu_onScreen(
            &self,
            menu: &NSMenu,
            screen: Option<&NSScreen>,
        ) -> NSRect;
    }
);

/// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenuproperties?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NSMenuProperties(pub NSUInteger);
bitflags::bitflags! {
    impl NSMenuProperties: NSUInteger {
        #[doc(alias = "NSMenuPropertyItemTitle")]
        const ItemTitle = 1<<0;
        #[doc(alias = "NSMenuPropertyItemAttributedTitle")]
        const ItemAttributedTitle = 1<<1;
        #[doc(alias = "NSMenuPropertyItemKeyEquivalent")]
        const ItemKeyEquivalent = 1<<2;
        #[doc(alias = "NSMenuPropertyItemImage")]
        const ItemImage = 1<<3;
        #[doc(alias = "NSMenuPropertyItemEnabled")]
        const ItemEnabled = 1<<4;
        #[doc(alias = "NSMenuPropertyItemAccessibilityDescription")]
        const ItemAccessibilityDescription = 1<<5;
    }
}

unsafe impl Encode for NSMenuProperties {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for NSMenuProperties {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// NSMenuPropertiesToUpdate.
impl NSMenu {
    extern_methods!(
        #[unsafe(method(propertiesToUpdate))]
        #[unsafe(method_family = none)]
        pub fn propertiesToUpdate(&self) -> NSMenuProperties;
    );
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenuwillsendactionnotification?language=objc)
    pub static NSMenuWillSendActionNotification: &'static NSNotificationName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenudidsendactionnotification?language=objc)
    pub static NSMenuDidSendActionNotification: &'static NSNotificationName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenudidadditemnotification?language=objc)
    pub static NSMenuDidAddItemNotification: &'static NSNotificationName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenudidremoveitemnotification?language=objc)
    pub static NSMenuDidRemoveItemNotification: &'static NSNotificationName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenudidchangeitemnotification?language=objc)
    pub static NSMenuDidChangeItemNotification: &'static NSNotificationName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenudidbegintrackingnotification?language=objc)
    pub static NSMenuDidBeginTrackingNotification: &'static NSNotificationName;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nsmenudidendtrackingnotification?language=objc)
    pub static NSMenuDidEndTrackingNotification: &'static NSNotificationName;
}

/// NSDeprecated.
impl NSMenu {
    extern_methods!(
        /// # Safety
        ///
        /// - `menu_rep` should be of the correct type.
        /// - `menu_rep` might not allow `None`.
        #[deprecated]
        #[unsafe(method(setMenuRepresentation:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMenuRepresentation(&self, menu_rep: Option<&AnyObject>);

        #[deprecated]
        #[unsafe(method(menuRepresentation))]
        #[unsafe(method_family = none)]
        pub fn menuRepresentation(&self) -> Option<Retained<AnyObject>>;

        /// # Safety
        ///
        /// - `menu_rep` should be of the correct type.
        /// - `menu_rep` might not allow `None`.
        #[deprecated]
        #[unsafe(method(setContextMenuRepresentation:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setContextMenuRepresentation(&self, menu_rep: Option<&AnyObject>);

        #[deprecated]
        #[unsafe(method(contextMenuRepresentation))]
        #[unsafe(method_family = none)]
        pub fn contextMenuRepresentation(&self) -> Option<Retained<AnyObject>>;

        /// # Safety
        ///
        /// - `menu_rep` should be of the correct type.
        /// - `menu_rep` might not allow `None`.
        #[deprecated]
        #[unsafe(method(setTearOffMenuRepresentation:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setTearOffMenuRepresentation(&self, menu_rep: Option<&AnyObject>);

        #[deprecated]
        #[unsafe(method(tearOffMenuRepresentation))]
        #[unsafe(method_family = none)]
        pub fn tearOffMenuRepresentation(&self) -> Option<Retained<AnyObject>>;

        #[deprecated]
        #[unsafe(method(menuZone))]
        #[unsafe(method_family = none)]
        pub fn menuZone(mtm: MainThreadMarker) -> *mut NSZone;

        /// # Safety
        ///
        /// `zone` must be a valid pointer.
        #[deprecated]
        #[unsafe(method(setMenuZone:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setMenuZone(zone: *mut NSZone, mtm: MainThreadMarker);

        #[deprecated]
        #[unsafe(method(attachedMenu))]
        #[unsafe(method_family = none)]
        pub fn attachedMenu(&self) -> Option<Retained<NSMenu>>;

        #[deprecated]
        #[unsafe(method(isAttached))]
        #[unsafe(method_family = none)]
        pub fn isAttached(&self) -> bool;

        #[deprecated]
        #[unsafe(method(sizeToFit))]
        #[unsafe(method_family = none)]
        pub fn sizeToFit(&self);

        /// # Safety
        ///
        /// `submenu` might not allow `None`.
        #[deprecated]
        #[unsafe(method(locationForSubmenu:))]
        #[unsafe(method_family = none)]
        pub unsafe fn locationForSubmenu(&self, submenu: Option<&NSMenu>) -> NSPoint;

        #[deprecated]
        #[unsafe(method(menuChangedMessagesEnabled))]
        #[unsafe(method_family = none)]
        pub fn menuChangedMessagesEnabled(&self) -> bool;

        /// Setter for [`menuChangedMessagesEnabled`][Self::menuChangedMessagesEnabled].
        #[deprecated]
        #[unsafe(method(setMenuChangedMessagesEnabled:))]
        #[unsafe(method_family = none)]
        pub fn setMenuChangedMessagesEnabled(&self, menu_changed_messages_enabled: bool);

        #[cfg(feature = "NSEvent")]
        #[deprecated]
        #[unsafe(method(helpRequested:))]
        #[unsafe(method_family = none)]
        pub fn helpRequested(&self, event_ptr: &NSEvent);

        #[deprecated]
        #[unsafe(method(isTornOff))]
        #[unsafe(method_family = none)]
        pub fn isTornOff(&self) -> bool;
    );
}
