#------------------------------------------------------------------------------
#
#  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:   10/21/2004
#
#------------------------------------------------------------------------------

""" Defines the a text entry field (actually a combo-box) with a drop-down list
    of values previously entered into the control.
"""

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

import wx

from traits.api \
    import HasPrivateTraits, Instance, Str, List, Int, Bool

from pyface.timer.api \
    import do_later

from constants \
    import OKColor, ErrorColor

#-------------------------------------------------------------------------------
#  'HistoryControl' class:
#-------------------------------------------------------------------------------

class HistoryControl ( HasPrivateTraits ):

    # The UI control:
    control = Instance( wx.Window )

    # The current value of the control:
    value = Str

    # Should 'value' be updated on every keystroke?
    auto_set = Bool( False )

    # The current history of the control:
    history = List( Str )

    # The maximum number of history entries allowed:
    entries = Int( 10 )

    # Is the current value valid?
    error = Bool( False )

    #-- Public Methods ---------------------------------------------------------

    def create_control ( self, parent ):
        """ Creates the control.
        """
        self.control = control = wx.ComboBox( parent, -1, self.value,
                                          wx.Point( 0, 0 ), wx.Size( -1, -1 ),
                                          self.history, style = wx.CB_DROPDOWN )
        wx.EVT_COMBOBOX( parent, control.GetId(), self._update_value )
        wx.EVT_KILL_FOCUS( control, self._kill_focus )
        wx.EVT_TEXT_ENTER( parent, control.GetId(),
                           self._update_text_value )
        if self.auto_set:
            wx.EVT_TEXT( parent, control.GetId(), self._update_value_only )

        return control

    def dispose ( self ):
        """ Disposes of the control at the end of its life cycle.
        """
        control, self.control = self.control, None
        parent = control.GetParent()
        wx.EVT_COMBOBOX(   parent, control.GetId(), None )
        wx.EVT_TEXT_ENTER( parent, control.GetId(), None )
        wx.EVT_KILL_FOCUS( control, None )

    def set_value ( self, value ):
        """ Sets the specified value and adds it to the history.
        """
        self._update( value )

    #-- Traits Event Handlers --------------------------------------------------

    def _value_changed ( self, value ):
        """ Handles the 'value' trait being changed.
        """
        if not self._no_update:
            control = self.control
            if control is not None:
                control.SetValue( value )
                self._restore = False

    def _history_changed ( self ):
        """ Handles the 'history' being changed.
        """
        if not self._no_update:
            if self._first_time is None:
                self._first_time = False
                if (self.value == '') and (len( self.history ) > 0):
                    self.value = self.history[0]

            self._load_history( select = False )

    def _error_changed ( self, error ):
        """ Handles the 'error' trait being changed.
        """
        if error:
            self.control.SetBackgroundColour( ErrorColor )
        else:
            self.control.SetBackgroundColour( OKColor )

        self.control.Refresh()

    #-- Wx Event Handlers ------------------------------------------------------

    def _update_value ( self, event ):
        """ Handles the user selecting something from the drop-down list of the
            combobox.
        """
        self._update( event.GetString() )

    def _update_value_only ( self, event ):
        """ Handles the user typing into the text field in 'auto_set' mode.
        """
        self._no_update = True
        self.value      = event.GetString()
        self._no_update = False

    def _update_text_value ( self, event, select = True ):
        """ Handles the user typing something into the text field of the
            combobox.
        """
        if not self._no_update:
            self._update( self.control.GetValue(), select )

    def _kill_focus ( self, event ):
        """ Handles the combobox losing focus.
        """
        self._update_text_value( event, False )
        event.Skip()

    #-- Private Methods --------------------------------------------------------

    def _update ( self, value, select = True ):
        """ Updates the value and history list based on a specified value.
        """
        self._no_update = True

        if value.strip() != '':
            history = self.history
            if (len( history ) == 0) or (value != history[0]):
                if value in history:
                    history.remove( value )
                history.insert( 0, value )
                del history[ self.entries: ]
                self._load_history( value, select )

        self.value = value

        self._no_update = False

    def _load_history ( self, restore = None, select = True ):
        """ Loads the current history list into the control.
        """
        control = self.control
        control.Freeze()

        if restore is None:
            restore = control.GetValue()

        control.Clear()
        for value in self.history:
            control.Append( value )

        self._restore = True
        do_later( self._thaw_value, restore, select )

    def _thaw_value ( self, restore, select ):
        """ Restores the value of the combobox control.
        """
        control = self.control
        if control is not None:
           if self._restore:
               control.SetValue( restore )

               if select:
                   control.SetMark( 0, len( restore ) )

           control.Thaw()

