#------------------------------------------------------------------------------
#
#  Copyright (c) 2008, 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:   10/21/2004
#
#------------------------------------------------------------------------------
""" Defines the list editor factory for the traits user interface toolkits..
"""

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

from __future__ import absolute_import

from traits.api import (
    HasTraits,
    BaseTraitHandler,
    Range,
    Str,
    Any,
    Int,
    Instance,
    Property,
    Bool,
    Callable,
    Enum,
    PrototypedFrom)

# CIRCULAR IMPORT FIXME: Importing from the source rather than traits.ui.api
# to avoid circular imports, as this EditorFactory will be part of
# traits.ui.api as well.
from ..view import View

from ..item import Item

from ..ui_traits import style_trait, AView

from ..editor_factory import EditorFactory

from ..toolkit import toolkit_object

# Currently, this traits is used only for the wx backend.
from ..helper import DockStyle

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

# Trait whose value is a BaseTraitHandler object
handler_trait = Instance(BaseTraitHandler)

# The visible number of rows displayed
rows_trait = Range(1, 50, 5,
                   desc='the number of list rows to display')

# The visible number of columns displayed
columns_trait = Range(1, 10, 1,
                      desc='the number of list columns to display')

editor_trait = Instance(EditorFactory)

#-------------------------------------------------------------------------
#  'ToolkitEditorFactory' class:
#-------------------------------------------------------------------------


class ToolkitEditorFactory(EditorFactory):
    """ Editor factory for list editors.
    """

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

    # The editor to use for each list item:
    editor = editor_trait

    # Can the list be reorganized, or have items added and deleted.
    mutable = Bool(True)

    # The style of editor to use for each item:
    style = style_trait

    # The trait handler for each list item:
    trait_handler = handler_trait

    # The number of list rows to display:
    rows = rows_trait

    # The number of list columns to create:
    columns = columns_trait

    # Use a notebook for a custom view?
    use_notebook = Bool(False)

    # Show a right-click context menu for the notebook tabs?  (Qt only)
    show_notebook_menu = Bool(False)

    #-- Notebook Specific Traits ---------------------------------------------

    # Are notebook items deletable?
    deletable = Bool(False)

    # The extended name of the trait on each page object which should be used
    # to determine whether or not an individual page should be deletable.
    deletable_trait = Str()

    # FIXME: Currently, this trait is used only in the wx backend.
    # The DockWindow graphical theme
    dock_theme = Any

    # FIXME: Currently, this trait is used only in the wx backend.
    # Dock page style to use for each DockControl:
    dock_style = DockStyle

    # Export class for each item in a notebook:
    export = Str

    # Name of the view to use in notebook mode:
    view = AView

    # The type of UI to construct ('panel', 'subpanel', etc)
    ui_kind = Enum('subpanel', 'panel')

    # A factory function that can be used to define that actual object to be
    # edited (i.e. view_object = factory( object )):
    factory = Callable

    # Extended name to use for each notebook page. It can be either the actual
    # name or the name of an attribute on the object in the form:
    # '.name[.name...]'
    page_name = Str

    # Name of the [object.]trait[.trait...] to synchronize notebook page
    # selection with:
    selected = Str

    #-------------------------------------------------------------------------
    #  Traits view definition:
    #-------------------------------------------------------------------------

    traits_view = View([['use_notebook{Use a notebook in a custom view}',
                         '|[Style]'],
                        [Item('page_name',
                              enabled_when='object.use_notebook'),
                         Item('view',
                              enabled_when='object.use_notebook'),
                         '|[Notebook options]'],
                        [Item('rows',
                              enabled_when='not object.use_notebook'),
                         '|[Number of list rows to display]<>']])

    #-------------------------------------------------------------------------
    #  'Editor' factory methods:
    #-------------------------------------------------------------------------

    def _get_custom_editor_class(self):
        if self.use_notebook:
            return toolkit_object('list_editor:NotebookEditor')
        return toolkit_object('list_editor:CustomEditor')

#-------------------------------------------------------------------------
#  'ListItemProxy' class:
#   This class is used to update the list editors when the object changes
#   external to the editor.
#-------------------------------------------------------------------------


class ListItemProxy(HasTraits):

    # The list proxy:
    list = Property

    # The item proxies index into the original list:
    index = Int

    # Delegate all other traits to the original object:
    _ = PrototypedFrom('_zzz_object')

    # Define all of the private internal use values (the funny names are an
    # attempt to avoid name collisions with delegated trait names):
    _zzz_inited = Any
    _zzz_object = Any
    _zzz_name = Any

    def __init__(self, object, name, index, trait, value):
        super(ListItemProxy, self).__init__()

        self._zzz_inited = False
        self._zzz_object = object
        self._zzz_name = name
        self.index = index

        if trait is not None:
            self.add_trait('value', trait)
            self.value = value

        self._zzz_inited = (self.index < len(self.list))

    def _get_list(self):
        return getattr(self._zzz_object, self._zzz_name)

    def _value_changed(self, old_value, new_value):
        if self._zzz_inited:
            self.list[self.index] = new_value


# Define the ListEditor class
ListEditor = ToolkitEditorFactory

### EOF ---------------------------------------------------------------------
