#-------------------------------------------------------------------------
#
#  Copyright (c) 2005, Enthought, Inc.
#  All rights reserved.
#
#  This software is provided without warranty under the terms of the BSD
#  license included in enthought/LICENSE.txt and may be redistributed only
#  under the conditions described in the aforementioned license.  The license
#  is also available online at http://www.enthought.com/licenses/BSD.txt
#
#  Thanks for using Enthought open source!
#
#  Author: David C. Morrill
#  Date:   12/14/2005
#
#-------------------------------------------------------------------------

""" Defines the DockableViewElement class, which allows Traits UIs and
    Traits UI elements to be docked in external PyFace DockWindow windows.
"""

#-------------------------------------------------------------------------
#  Imports:
#-------------------------------------------------------------------------

from __future__ import absolute_import

from traits.api import HasPrivateTraits, Instance, Bool

from .ui import UI

from .group import Group

from .view import View

from .view_element import ViewSubElement

from pyface.dock.idockable import IDockable

#-------------------------------------------------------------------------
#  'DockableViewElement' class:
#-------------------------------------------------------------------------


class DockableViewElement(HasPrivateTraits, IDockable):
    """ Allows Traits UIs and Traits UI elements to be docked in external
        PyFace DockWindow windows.
    """

    #-------------------------------------------------------------------------
    #  Trait definitions:
    #-------------------------------------------------------------------------

    # The Traits UI that can be docked with an external DockWindow
    ui = Instance(UI)

    # The (optional) element of the Traits UI that can be docked
    element = Instance(ViewSubElement)

    # Should the DockControl be closed on redocking?
    should_close = Bool(False)

#-- IDockable interface --------------------------------------------------

    #-------------------------------------------------------------------------
    #  Should the current DockControl be closed before creating the new one:
    #-------------------------------------------------------------------------

    def dockable_should_close(self):
        """ Should the current DockControl be closed before creating the new
            one?
        """
        element = self.element
        if element is None:
            element = self.ui.view.content

        if not isinstance(element, Group):
            element = Group().set(content=[element])

        group = Group().set(content=[element])
        self._view = View().set(**self.ui.view.get()).set(content=group,
                                                          title='')

        # FIXME: The following private traits are being set here to facilitate
        # rebuilding the ui (which will require the context and the handler).
        # When a current dock control is closed (close_dock_control method), the
        # contents of self.ui have been disposed of and self.ui is now None.
        # Now if a new UI needs to be created by calling dockable_get_control
        # (e.g., when doing an 'undock' action on a dock window), we need to
        # pass on the context and handler to the UI. Therefore, we are setting
        # these private traits here so dockable_get_control can access them.
        # In future, we need to investigate if there is a better way to do
        # this.

        self._context = self.ui.context.copy()
        # Make copy since context will be emptied when calling
        # self.ui.dispose()
        self._handler = self.ui.handler

        return (self.should_close or (self.element is None))

    #-------------------------------------------------------------------------
    #  Gets a control that can be docked into a DockWindow:
    #-------------------------------------------------------------------------

    def dockable_get_control(self, parent):
        """ Gets a control that can be docked into a DockWindow.
        """
        # Create the new UI:
        ui = self._view.ui(self._context, parent=parent,
                           kind='subpanel',
                           handler=self._handler)

        # Discard the reference to the view created previously:
        self._view = None

        # If the old UI was closed, then switch to using the new one:
        if self.element is None:
            self.ui = ui
        else:
            self._ui = ui

        return ui.control

    #-------------------------------------------------------------------------
    #  Allows the object to override the default DockControl settings:
    #-------------------------------------------------------------------------

    def dockable_init_dockcontrol(self, dock_control):
        """ Allows the object to override the default DockControl settings.
        """
        dockable = self
        if self.element is not None:
            dockable = DockableViewElement(ui=self._ui,
                                           element=self.element,
                                           should_close=True)
            self._ui = None

        dock_control.set(dockable=dockable,
                         on_close=dockable.close_dock_control)

    #-------------------------------------------------------------------------
    #  Handles the closing of a DockControl containing a Traits UI:
    #-------------------------------------------------------------------------

    def close_dock_control(self, dock_control, abort):
        """ Handles the closing of a DockControl containing a Traits UI.
        """
        ui = self.ui

        # Ask the traits UI handler if it is OK to close the window:
        if (not abort) and (not ui.handler.close(ui.info, True)):
            # If not, tell the DockWindow not to close it:
            return False

        # Otherwise, clean up and close the traits UI:
        ui.dispose(abort=abort)

        # Break our linkage to the UI and ViewElement object:
        self.ui = self.element = None

        # And tell the DockWindow to remove the DockControl:
        return True
