# Orca
#
# Copyright 2010 Informal Informatica LTDA.
# Author: Jose Vilmar <vilmar@informal.com.br>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA  02110-1301 USA.

"""Custom script for Eclipse."""
__id__        = "$Id$"
__version__   = "$Revision$"
__date__      = "$Date$"
__copyright__ = "Copyright (c) 2010 Informal Informatica LTDA."
__license__   = "LGPL"


import orca.debug as debug
import orca.focus_manager as focus_manager
import orca.scripts.toolkits.gtk as gtk
from orca.ax_text import AXText
from orca.ax_utilities import AXUtilities

########################################################################
#                                                                      #
# The Eclipse script class.                                            #
#                                                                      #
########################################################################
class Script(gtk.Script):

    def __init__(self, app):
        """Creates a new script for the given application."""
        super().__init__(app)
        self.movementKeys = ["Up", "Down", "Left", "Right", "Page_Up",
                   "Page_Down", "Home", "End"]

    def _presentTextAtNewCaretPosition(self, event, otherObj=None):
        """Updates braille and outputs speech for the event.source or the
        otherObj. Overridden here so that we can give more feedback to user.
        """

        # Let the default script's normal behavior do its thing
        #
        super()._presentTextAtNewCaretPosition(event, otherObj)

        # check if the obj was spoken in the default script
        lastKey, mods = self.utilities.lastKeyAndModifiers()
        if lastKey in self.movementKeys:
            # already spoken in default script
            return

        obj = otherObj or event.source
        if AXUtilities.is_single_line(obj):
            return

        # if Tab key is pressed and there is text selected, we must announce
        # the text selected because probably we are in a parameter list
        # and we are jumping between the parameters with the tab key. 
        hasSelection = False
        if lastKey in ["Tab", "ISO_Left_Tab"]:
            text, startOffset, endOffset = AXText.get_selected_text(obj)
            hasSelection = endOffset > 0

        if hasSelection:
            self.sayPhrase(obj, startOffset, endOffset)
        else:
            self.sayLine(obj)

        self._saveLastTextPosition(obj)

    def onFocus(self, event):
        """Callback for focus: accessibility events."""

        # NOTE: This event type is deprecated and Orca should no longer use it.
        # This callback remains just to handle bugs in applications and toolkits.
        if AXUtilities.is_panel(event.source):
            focus_manager.getManager().set_locus_of_focus(event, event.source)
            return

        if AXUtilities.is_text(event.source) \
           and self.utilities.lastInputEventWasUnmodifiedArrow() \
           and self.utilities.inMenu():
            msg = "ECLIPSE: Ignoring event. In menu."
            debug.printMessage(debug.LEVEL_INFO, msg, True)
            return

        super().onFocus(event)

    def onTextInserted(self, event):
        """Called whenever text is inserted into an object. Overridden here
        so that we can avoid speaking text when caret moves after new text
        is inserted.

        Arguments:
        - event: the Event
        """

        if self.utilities.isTextArea(event.source):
            if event.detail1 == 0 and event.detail2 == AXText.get_character_count(event.source):
                # seems to be generated by a reformat (ctrl+shift+f)
                # or by commenting some block (ctrl+/).
                # if not discarded, orca will speak all the text of the file.
                return
            # Let the default script's normal behavior do its thing
            super().onTextInserted(event)
            self._saveLastTextPosition(event.source)

    def onTextDeleted(self, event):
        """Called whenever text is deleted from an object.  Overridden here
        so that we can avoid speaking text when caret moves after new text
        is deleted.

        Arguments:
        - event: the Event
        """

        # Let the default script's normal behavior do its thing
        #
        super().onTextDeleted(event)
        self._saveLastTextPosition(event.source)

    def _saveLastTextPosition(self, obj):
        if self.utilities.isTextArea(obj):
            self._saveLastCursorPosition(obj, AXText.get_caret_offset(obj))

    def onSelectionChanged(self, event):
        """Callback for object:selection-changed accessibility events."""

        # Sometimes Eclipse fires an object:selection-changed event for non-focused
        # containers. We don't want to present those. The exception is the MenuBar.
        if not (AXUtilities.is_focused(event.source) or AXUtilities.is_menu_bar(event.source)):
            return

        super().onSelectionChanged(event)

