# Source code for enaml.widgets.toolkit_dialog

    #------------------------------------------------------------------------------
    # Copyright (c) 2013-2025, Nucleic Development Team.
    #
    # Distributed under the terms of the Modified BSD License.
    #
    # The full license is in the file LICENSE, distributed with this software.
    #------------------------------------------------------------------------------
    from atom.api import Bool, Str, Typed, ForwardTyped, Event, Callable

    from enaml.application import deferred_call
    from enaml.core.declarative import d_, observe

    from .toolkit_object import ToolkitObject, ProxyToolkitObject

    class ProxyToolkitDialog(ProxyToolkitObject):
        """ The abstract definition of a proxy ToolkitDialog object.

        """
        #: A reference to the ToolkitDialog declaration.
        declaration = ForwardTyped(lambda: ToolkitDialog)

        def set_title(self, title):
            raise NotImplementedError

        def show(self):
            raise NotImplementedError

        def open(self):
            raise NotImplementedError

        def exec_(self):
            raise NotImplementedError

        def accept(self):
            raise NotImplementedError

        def reject(self):
            raise NotImplementedError

    class ToolkitDialog(ToolkitObject):
        """ A base class for defining toolkit dialogs.

        A toolkit dialog is a dialog where the content is defined by the
        toolkit rather than the user. Customary examples would be a file
        dialog or a color selection dialog, where the implementation can
        often be a native operating system dialog.

        """
        #: The title of the dialog window.
        title = d_(Str())

        #: An optional callback which will be invoked when the dialog is
        #: closed. This is a convenience to make it easier to handle a
        #: dialog opened in non-blocking mode. The callback must accept
        #: a single argument, which will be the dialog instance.
        callback = d_(Callable())

        #: Whether to destroy the dialog widget on close. The default is
        #: True since dialogs are typically used in a transitory fashion.
        destroy_on_close = d_(Bool(True))

        #: An event fired if the dialog is accepted. It has no payload.
        accepted = d_(Event(), writable=False)

        #: An event fired when the dialog is rejected. It has no payload.
        rejected = d_(Event(), writable=False)

        #: An event fired when the dialog is finished. The payload is the
        #: boolean result of the dialog.
        finished = d_(Event(bool), writable=False)

        #: Whether or not the dialog was accepted by the user. It will be
        #: updated when the dialog is closed. This value is output only.
        result = Bool(False)

        #: A reference to the ProxyToolkitDialog object.
        proxy = Typed(ProxyToolkitDialog)

        def show(self):
            """ Open the dialog as a non modal dialog.

            """
            if not self.is_initialized:
                self.initialize()
            if not self.proxy_is_active:
                self.activate_proxy()
            self._prepare()
            self.proxy.show()

        def open(self):
            """ Open the dialog as a window modal dialog.

            """
            if not self.is_initialized:
                self.initialize()
            if not self.proxy_is_active:
                self.activate_proxy()
            self._prepare()
            self.proxy.open()

        def exec_(self):
            """ Open the dialog as an application modal dialog.

            Returns
            -------
            result : bool
                Whether or not the dialog was accepted.

            """
            if not self.is_initialized:
                self.initialize()
            if not self.proxy_is_active:
                self.activate_proxy()
            self._prepare()
            self.proxy.exec_()
            return self.result

        def accept(self):
            """ Accept the current state and close the dialog.

            """
            if self.proxy_is_active:
                self.proxy.accept()

        def reject(self):
            """ Reject the current state and close the dialog.

            """
            if self.proxy_is_active:
                self.proxy.reject()

        #--------------------------------------------------------------------------
        # Observers
        #--------------------------------------------------------------------------
        @observe('title')
        def _update_proxy(self, change):
            """ An observer which updates the proxy when the data changes.

            """
            # The superclass implementation is sufficient.
            super(ToolkitDialog, self)._update_proxy(change)

        #--------------------------------------------------------------------------
        # Utility Methods
        #--------------------------------------------------------------------------
        def _proxy_finished(self, result):
            """ Called by the proxy object when the dialog is finished.

            Parameters
            ----------
            result : bool
                Wether or not the dialog was accepted.

            """
            self.result = result
            self.finished(result)
            if result:
                self.accepted()
            else:
                self.rejected()
            if self.callback:
                self.callback(self)
            if self.destroy_on_close:
                deferred_call(self.destroy)

        def _prepare(self):
            """ Prepare the dialog to be shown.

            This method can be reimplemented by subclasses.

            """
            self.result = False