#-------------------------------------------------------------------------
#
#  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:   05/20/2005
#
#-------------------------------------------------------------------------

""" Defines the key binding editor for use with the KeyBinding class. This is a
    specialized editor used to associate a particular key with a control (i.e.,
    the key binding editor).
"""

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

import wx

from traits.api \
    import Event, false

# FIXME: ToolkitEditorFactory is a proxy class defined here just for backward
# compatibility. The class has been moved to the
# traitsui.editors.key_binding_editor file.
from traitsui.editors.key_binding_editor \
    import KeyBindingEditor as ToolkitEditorFactory

from pyface.wx.dialog \
    import confirmation

from editor \
    import Editor

from key_event_to_name \
    import key_event_to_name

#-------------------------------------------------------------------------
#  'KeyBindingEditor' class:
#-------------------------------------------------------------------------


class KeyBindingEditor(Editor):
    """ An editor for modifying bindings of keys to controls.
    """

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

    # Does the editor's control have focus currently?
    has_focus = false

    # Keyboard event
    key = Event

    # Clear field event
    clear = Event

    #-------------------------------------------------------------------------
    #  Finishes initializing the editor by creating the underlying toolkit
    #  widget:
    #-------------------------------------------------------------------------

    def init(self, parent):
        """ Finishes initializing the editor by creating the underlying toolkit
            widget.
        """
        self.control = KeyBindingCtrl(self, parent, size=wx.Size(160, 19))

    #-------------------------------------------------------------------------
    #  Handles the user entering input data in the edit control:
    #-------------------------------------------------------------------------

    def update_object(self, event):
        """ Handles the user entering input data in the edit control.
        """
        try:
            self.value = value = key_event_to_name(event)
            self._binding.text = value
        except:
            pass

    #-------------------------------------------------------------------------
    #  Updates the editor when the object trait changes external to the editor:
    #-------------------------------------------------------------------------

    def update_editor(self):
        """ Updates the editor when the object trait changes externally to the
            editor.
        """
        self.control.Refresh()

    #-------------------------------------------------------------------------
    #  Updates the current focus setting of the control:
    #-------------------------------------------------------------------------

    def update_focus(self, has_focus):
        """ Updates the current focus setting of the control.
        """
        if has_focus:
            self._binding.border_size = 1
            self.object.owner.focus_owner = self._binding

    #-------------------------------------------------------------------------
    #  Handles a keyboard event:
    #-------------------------------------------------------------------------

    def _key_changed(self, event):
        """ Handles a keyboard event.
        """
        binding = self.object
        key_name = key_event_to_name(event)
        cur_binding = binding.owner.key_binding_for(binding, key_name)
        if cur_binding is not None:
            if confirmation(None,
                            "'%s' has already been assigned to '%s'.\n"
                            "Do you wish to continue?" % (
                                key_name, cur_binding.description),
                            'Duplicate Key Definition') == 5104:
                return

        self.value = key_name

    #-------------------------------------------------------------------------
    #  Handles a clear field event:
    #-------------------------------------------------------------------------

    def _clear_changed(self):
        """ Handles a clear field event.
        """
        self.value = ''

#-------------------------------------------------------------------------
#  'KeyBindingCtrl' class:
#-------------------------------------------------------------------------


class KeyBindingCtrl(wx.Window):
    """ wxPython control for editing key bindings.
    """

    #-------------------------------------------------------------------------
    #  Initialize the object:
    #-------------------------------------------------------------------------

    def __init__(self, editor, parent, wid=-1, pos=wx.DefaultPosition,
                 size=wx.DefaultSize):

        super(KeyBindingCtrl, self).__init__(parent, wid, pos, size,
                                             style=wx.CLIP_CHILDREN |
                                             wx.WANTS_CHARS)
        # Save the reference to the controlling editor object:
        self.editor = editor

        # Indicate we don't have the focus right now:
        editor.has_focus = False

        # Set up the 'erase background' event handler:
        wx.EVT_ERASE_BACKGROUND(self, self._on_erase_background)

        # Set up the 'paint' event handler:
        wx.EVT_PAINT(self, self._paint)

        # Set up the focus change handlers:
        wx.EVT_SET_FOCUS(self, self._get_focus)
        wx.EVT_KILL_FOCUS(self, self._lose_focus)

        # Set up mouse event handlers:
        wx.EVT_LEFT_DOWN(self, self._set_focus)
        wx.EVT_LEFT_DCLICK(self, self._clear_contents)

        # Handle key events:
        wx.EVT_CHAR(self, self._on_char)

    #-------------------------------------------------------------------------
    #  Handle keyboard keys being pressed:
    #-------------------------------------------------------------------------

    def _on_char(self, event):
        """ Handle keyboard keys being pressed.
        """
        self.editor.key = event

    #-------------------------------------------------------------------------
    #  Erase background event handler:
    #-------------------------------------------------------------------------

    def _on_erase_background(self, event):
        pass

    #-------------------------------------------------------------------------
    #  Do a GUI toolkit specific screen update:
    #-------------------------------------------------------------------------

    def _paint(self, event):
        """ Updates the screen.
        """
        wdc = wx.PaintDC(self)
        dx, dy = self.GetSizeTuple()
        if self.editor.has_focus:
            wdc.SetPen(wx.Pen(wx.RED, 2))
            wdc.DrawRectangle(1, 1, dx - 1, dy - 1)
        else:
            wdc.SetPen(wx.Pen(wx.BLACK))
            wdc.DrawRectangle(0, 0, dx, dy)

        wdc.SetFont(self.GetFont())
        wdc.DrawText(self.editor.str_value, 5, 3)

    #-------------------------------------------------------------------------
    #  Sets the keyboard focus to this window:
    #-------------------------------------------------------------------------

    def _set_focus(self, event):
        """ Sets the keyboard focus to this window.
        """
        self.SetFocus()

    #-------------------------------------------------------------------------
    #  Handles getting/losing the focus:
    #-------------------------------------------------------------------------

    def _get_focus(self, event):
        """ Handles getting the focus.
        """
        self.editor.has_focus = True
        self.Refresh()

    def _lose_focus(self, event):
        """ Handles losing the focus.
        """
        self.editor.has_focus = False
        self.Refresh()

    #-------------------------------------------------------------------------
    #  Handles the user double clicking the control to clear its contents:
    #-------------------------------------------------------------------------

    def _clear_contents(self, event):
        """ Handles the user double clicking the control to clear its contents.
        """
        self.editor.clear = True

### EOF #######################################################################
