//! 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::*;
use objc2_foundation::*;

use crate::*;

/// [Apple's documentation](https://developer.apple.com/documentation/appkit/nspopoverappearance?language=objc)
// NS_ENUM
#[deprecated]
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NSPopoverAppearance(pub NSInteger);
impl NSPopoverAppearance {
    /// The popover will use the default, light content appearance.
    #[doc(alias = "NSPopoverAppearanceMinimal")]
    #[deprecated]
    pub const Minimal: Self = Self(0);
    /// The popover will draw with a HUD appearance.
    #[doc(alias = "NSPopoverAppearanceHUD")]
    #[deprecated]
    pub const HUD: Self = Self(1);
}

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

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

/// [Apple's documentation](https://developer.apple.com/documentation/appkit/nspopoverbehavior?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NSPopoverBehavior(pub NSInteger);
impl NSPopoverBehavior {
    #[doc(alias = "NSPopoverBehaviorApplicationDefined")]
    pub const ApplicationDefined: Self = Self(0);
    #[doc(alias = "NSPopoverBehaviorTransient")]
    pub const Transient: Self = Self(1);
    #[doc(alias = "NSPopoverBehaviorSemitransient")]
    pub const Semitransient: Self = Self(2);
}

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

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

extern_class!(
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nspopover?language=objc)
    #[unsafe(super(NSResponder, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "NSResponder")]
    pub struct NSPopover;
);

#[cfg(all(feature = "NSAccessibilityProtocols", feature = "NSResponder"))]
extern_conformance!(
    unsafe impl NSAccessibility for NSPopover {}
);

#[cfg(all(feature = "NSAccessibilityProtocols", feature = "NSResponder"))]
extern_conformance!(
    unsafe impl NSAccessibilityElementProtocol for NSPopover {}
);

#[cfg(all(feature = "NSAppearance", feature = "NSResponder"))]
extern_conformance!(
    unsafe impl NSAppearanceCustomization for NSPopover {}
);

#[cfg(feature = "NSResponder")]
extern_conformance!(
    unsafe impl NSCoding for NSPopover {}
);

#[cfg(feature = "NSResponder")]
extern_conformance!(
    unsafe impl NSObjectProtocol for NSPopover {}
);

#[cfg(feature = "NSResponder")]
impl NSPopover {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

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

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

        /// 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 NSPopoverDelegate>>);

        #[cfg(feature = "NSAppearance")]
        /// The appearance of the popover. The popover's contentView will inherit this appearance. The default effective appearance is the NSAppearanceNameVibrantLight appearance.
        /// If nil is set, nil will be returned, and the effective appearance will return to the default.
        /// To prevent conflicts with the previous appearance property, this is only available for apps that target 10.10 and higher.
        #[unsafe(method(appearance))]
        #[unsafe(method_family = none)]
        pub fn appearance(&self) -> Option<Retained<NSAppearance>>;

        #[cfg(feature = "NSAppearance")]
        /// Setter for [`appearance`][Self::appearance].
        #[unsafe(method(setAppearance:))]
        #[unsafe(method_family = none)]
        pub fn setAppearance(&self, appearance: Option<&NSAppearance>);

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

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

        /// Setter for [`behavior`][Self::behavior].
        #[unsafe(method(setBehavior:))]
        #[unsafe(method_family = none)]
        pub fn setBehavior(&self, behavior: NSPopoverBehavior);

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

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

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

        #[cfg(feature = "NSViewController")]
        /// Setter for [`contentViewController`][Self::contentViewController].
        #[unsafe(method(setContentViewController:))]
        #[unsafe(method_family = none)]
        pub fn setContentViewController(&self, content_view_controller: Option<&NSViewController>);

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

        /// Setter for [`contentSize`][Self::contentSize].
        #[unsafe(method(setContentSize:))]
        #[unsafe(method_family = none)]
        pub fn setContentSize(&self, content_size: NSSize);

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

        /// Returns
        /// `YES`if the window is detached to an implicitly created detached window,
        /// `NO`otherwise. This method does not apply when the popover is detached to a window returned with
        /// `-detachableWindowForPopover:.`
        #[unsafe(method(isDetached))]
        #[unsafe(method_family = none)]
        pub fn isDetached(&self) -> bool;

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

        /// Setter for [`positioningRect`][Self::positioningRect].
        #[unsafe(method(setPositioningRect:))]
        #[unsafe(method_family = none)]
        pub fn setPositioningRect(&self, positioning_rect: NSRect);

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

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

        #[cfg(feature = "NSView")]
        /// Shows the popover anchored to the specified view.
        ///
        /// The popover will animate onscreen and eventually animate offscreen when it is closed (unless the property `animates` is set to `NO`).
        ///
        /// - Parameters:
        /// - positioningRect: The rectangle within `positioningView` relative to which the popover should be positioned. Normally set to the bounds of `positioningView`. May be an empty rectangle, which will default to the bounds of `positioningView`.
        /// - positioningView: The view relative to which the popover should be positioned. Causes the method to raise `NSInvalidArgumentException` if `nil`.
        /// - preferredEdge: The edge of `positioningView` the popover should prefer to be anchored to (respects to the `-isFlipped` state of `positioningView`). The current (but not guaranteed) behavior is that AppKit will place the anchor towards the `preferredEdge` of the `positioningRect` unless such a placement would cause the popover not to fit on the screen of `positioningView`. If the anchor cannot be placed towards the `preferredEdge`, AppKit will (in the current implementation) attempt to place the anchor on the opposite side of the `positioningRect`. If that cannot be done, AppKit will attempt to place the anchor on a remaining side of the popover, and failing that will center the popover on the screen, causing it to (at least temporarily) lose its anchor.
        ///
        /// - Note: This method will throw a `NSInvalidArgumentException` if view is `nil` or if `view` is not in a window, or if the popover’s behavior is `NSPopoverBehaviorSemitransient` and the popover’s `positioningView` is in a popover or child window. It will throw a `NSInternalInconsistencyException` if the popover’s  content view controller (or the view controller’s view) is `nil`. If the popover is already being shown, this method will update to be associated with the new `view` and `positioningRect` passed.
        ///
        /// - Note: If the positioning view isn’t visible (its window isn’t visible, or the positioning rect is outside of its visible rect), this method does nothing.
        #[unsafe(method(showRelativeToRect:ofView:preferredEdge:))]
        #[unsafe(method_family = none)]
        pub fn showRelativeToRect_ofView_preferredEdge(
            &self,
            positioning_rect: NSRect,
            positioning_view: &NSView,
            preferred_edge: NSRectEdge,
        );

        #[cfg(feature = "NSToolbarItem")]
        /// Shows the popover positioned relative to
        /// `toolbarItem`. When the item is in the overflow menu, the popover will be presented from another appropriate affordance in the window. See the comments in
        /// `-showRelativeToRect:ofView:preferredEdge:`for the popover behavior.
        ///
        /// This method will throw an
        /// `NSInvalidArgumentException`if it cannot locate the toolbar item. This could happen because the item is not in a toolbar, or because the toolbar is not in a window.
        #[unsafe(method(showRelativeToToolbarItem:))]
        #[unsafe(method_family = none)]
        pub fn showRelativeToToolbarItem(&self, toolbar_item: &NSToolbarItem);

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

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

/// Methods declared on superclass `NSObject`.
#[cfg(feature = "NSResponder")]
impl NSPopover {
    extern_methods!(
        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new(mtm: MainThreadMarker) -> Retained<Self>;
    );
}

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

/// [Apple's documentation](https://developer.apple.com/documentation/appkit/nspopoverclosereasonvalue?language=objc)
// NS_TYPED_ENUM
pub type NSPopoverCloseReasonValue = NSString;

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

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

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

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

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

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

extern_protocol!(
    /// [Apple's documentation](https://developer.apple.com/documentation/appkit/nspopoverdelegate?language=objc)
    pub unsafe trait NSPopoverDelegate: NSObjectProtocol + MainThreadOnly {
        #[cfg(feature = "NSResponder")]
        /// The popover invokes this method on its delegate whenever it is about to close to give the delegate a chance to veto the close.
        /// If the delegate does not implement this method,
        /// `-popoverShouldClose:`will also be invoked on the popover to allow the popover to veto the close.
        ///
        /// Returns: Return YES if the popover should close, NO otherwise.
        #[optional]
        #[unsafe(method(popoverShouldClose:))]
        #[unsafe(method_family = none)]
        fn popoverShouldClose(&self, popover: &NSPopover) -> bool;

        #[cfg(feature = "NSResponder")]
        /// Return
        /// `YES`to allow the popover to detach from its positioning view. Return
        /// `NO`if it should not. If this method is not implemented, the default behavior is
        /// `NO.`If this method returns YES, and
        /// `-detachableWindowForPopover:`is not implemented or returns nil, a detachable window will be created with the popover’s
        /// `contentViewController.`This implicit detached window will have the same appearance as the popover. If the
        /// `contentViewController`has a title, it will be bound to and displayed as the title of the detached window. Upon being released in a detached state, the popover will call
        /// `-popoverDidDetach:`on the delegate. Once the detached popover is closed, PopoverShould/Will/DidClose delegate calls and notifications will be sent with the reason
        /// `NSPopoverCloseReasonStandard.`
        /// Parameter `popover`: The popover that may be detached
        ///
        /// Returns: YES if the popover should detach, whether to a custom window or the implicitly detached window. NO if not.
        #[optional]
        #[unsafe(method(popoverShouldDetach:))]
        #[unsafe(method_family = none)]
        fn popoverShouldDetach(&self, popover: &NSPopover) -> bool;

        #[cfg(feature = "NSResponder")]
        /// This is called when the popover has been released in an implicitly detached state, i.e. not when detached to a custom window returned from
        /// `-detachableWindowForPopover:.`
        /// Parameter `popover`: The popover that detached from its anchor view and is not closing.
        #[optional]
        #[unsafe(method(popoverDidDetach:))]
        #[unsafe(method_family = none)]
        fn popoverDidDetach(&self, popover: &NSPopover);

        #[cfg(all(feature = "NSResponder", feature = "NSWindow"))]
        /// Return a custom window to which the popover should be detached. This should be used when the content of the detached window is wanted to be different from the content of the popover. If the same content should be used in the detached window, only
        /// `-popoverShouldDetach:`needs to be implemented.
        /// If implementing this method, you should not remove the popover's content view as part of your implementation of this method. The popover and the detachable window may be shown at the same time and therefore cannot share a content view (or a content view controller).  If the popover and the detachable window should have the same content, you should define the content in a separate nib file and use a view controller to instantiate separate copies of the content for the popover and the detachable window.  The popover will animate to appear as though it morphs into the detachable window (unless the animates property is set to NO.  The exact animation used is not guaranteed).  Subclasses of NSPopover may also implement this method, in which case the subclass method will be invoked only if the delegate does not implement the method.
        /// Not implementing this method, and just returning YES to
        /// `-popoverShouldDetach:`is recommended over providing a custom window.
        /// If
        /// `-popoverShouldDetach:`is not overridden or returns NO, this method will not be called and the popover will not be detachable.
        ///
        /// Parameter `popover`: The popover that is being detached
        ///
        /// Returns: The custom window to detach to.
        #[optional]
        #[unsafe(method(detachableWindowForPopover:))]
        #[unsafe(method_family = none)]
        fn detachableWindowForPopover(&self, popover: &NSPopover) -> Option<Retained<NSWindow>>;

        /// Invoked on the delegate when the NSPopoverWillShowNotification notification is sent.  This method will also be invoked on the popover.
        #[optional]
        #[unsafe(method(popoverWillShow:))]
        #[unsafe(method_family = none)]
        fn popoverWillShow(&self, notification: &NSNotification);

        /// Invoked on the delegate when the NSPopoverDidShowNotification notification is sent.  This method will also be invoked on the popover.
        #[optional]
        #[unsafe(method(popoverDidShow:))]
        #[unsafe(method_family = none)]
        fn popoverDidShow(&self, notification: &NSNotification);

        /// Invoked on the delegate when the NSPopoverWillCloseNotification notification is sent.  This method will also be invoked on the popover.
        #[optional]
        #[unsafe(method(popoverWillClose:))]
        #[unsafe(method_family = none)]
        fn popoverWillClose(&self, notification: &NSNotification);

        /// Invoked on the delegate when the NSPopoverDidCloseNotification notification is sent.  This method will also be invoked on the popover.
        #[optional]
        #[unsafe(method(popoverDidClose:))]
        #[unsafe(method_family = none)]
        fn popoverDidClose(&self, notification: &NSNotification);
    }
);
