'''
Handle several problems with gedit, including mainly the spellcheck dialogue and the document statistics dialogue

@author: Andy Shi / Cristobal Palmer
@organization: UNC Chapel Hill
@owner: Regents of the University of California
@copyright: Copyright (c) 2007, Andy Shi / Cristobal Palmer
@license: BSD

All rights reserved. This program and the accompanying materials are made 
available under the terms of the BSD License which is available at
U{http://www.opensource.org/licenses/bsd-license.php}
'''
# import useful modules for Perks
import Perk, Task, AEConstants
from POR import POR
from i18n import bind, _

# metadata describing this Perk
__uie__ = dict(kind='perk', tier='gedit', all_tiers=False)

# to support translation of strings in this Perk, uncomment the following line
# and provide the proper domain and path to your translation file
# _ = bind(domain, locale_dir)

class SC(Perk.Perk):
  '''
  This class exists to register tasks that handle the check spelling dialog and
  document statistics dialog. It also defines a hotkey, caps-m, that reads the
  current misspelled word. This only works in the context of the check spelling
  dialogue.
  '''
  def init(self):
    self.registerTask(HandleGeditViewChange('view change'))
    self.registerTask(HandleMisspelledWordByHotkey('misspelled word by hotkey'))
    self.registerTask(HandleDocumentStatistics('document statistics'))
    self.registerTask(HandleContextInformation('context info', tier=True))
    self.registerTask(HandleButtonPress('button press', tier=True))
    self.registerTask(HandleCharacterInsert('character insert'))
    self.registerTask(ReadPerkName('read perk name'))
    kbd = self.getInputDevice('Keyboard')
    self.addInputModifiers(kbd, kbd.AEK_CAPS_LOCK)
    self.registerCommand(kbd, 'read perk name', False,
                         [kbd.AEK_CAPS_LOCK, kbd.AEK_A])
    self.registerCommand(kbd, 'misspelled word by hotkey', False,
                         [kbd.AEK_CAPS_LOCK, kbd.AEK_M])
                         
  def getDescription(self):
    return _('Applies to gedit by default.')

class ReadPerkName(Task.InputTask):
  '''
  Example Task that announces the name of this Perk.
  '''
  def execute(self, **kwargs):
    self.stopNow()
    self.sayInfo(text='SC handling an input gesture')

class HandleGeditViewChange(Task.ViewTask):
  '''
  This class monitors for whether the check spelling dialogue is up. If it
  comes up, it reads the misspelled word. 
  '''
  def executeGained(self, por, **kwargs):
    por = self.getRootAcc()
    #for check spelling dialog
    checkLabel = self.getAccFromPath(por, 0,0,1)
    checkButton = self.getAccFromPath(por, 0,0,0,1)
    checkTextField = self.getAccFromPath(por, 0,0,0,0)
    misspelled_word_por = self.getAccFromPath(por, 0,0,2)
    misspelled_word_text = self.getAccName(misspelled_word_por)
    if self.hasAccRole('label', checkLabel):
      if self.hasAccRole('push button', checkButton): 
        if self.hasAccRole('text', checkTextField):
          self.inhibitMayStop()
          self.sayItem(text='misspelled word')
          for i in misspelled_word_text:
            self.sayItem(text=i)
          #block further output that was clobbering the misspelled word
          self.blockNTasks(1,Task.SelectorTask)
          return False

class HandleContextInformation(Task.CaretTask):
  '''
  Retrieving the context information (the current line in which the misspelled word
  is detected) by monitoring the caret movement event.
  Read and spell the misspelled word.
  Note: the hightlighted word is the misspelled word
  '''
  def executeMoved(self, por, text, text_offset, **kwargs):
    if self.hasAccRole('text', por):
      if self.hasAccState('multi line'):
        if self.getAccTextSelectionCount() > 0:
          self.inhibitMayStop()
          self.sayInfo(text=_('context information'))
          self.sayItem(text=text)
          selections = self.getAccTextSelection()
          if len(selections) > 0:
            selected = selections[0]
            self.inhibitMayStop()
            #read the highlighted word (the misspelled word)
            self.sayInfo(text=_('misspelled word'))
            self.sayItem(text=selected)
            for each in selected:
              self.inhibitMayStop()
              #spell the hightlighted word
              self.sayItem(text=each)

class HandleDocumentStatistics(Task.FocusTask):
  '''
  Read the text in the DocumentStatistics dialog
  Note: the information is read from left to right
        for example:  Line 124 20 where 124 and 20 are from the document and selection
        columns, respectively.
  '''
  def executeGained(self, por, **kwargs):
    por = self.getRootAcc()
    # check if Document Statistics dialog is open
    lblOne = self.getAccFromPath(por, 0,0,0)
    lblTwo = self.getAccFromPath(por, 0,0,1,1,2)
    lblThree = self.getAccFromPath(por, 0,0,1,1,3)
    ItemList = []
    #line
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,2))
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,1))
    ItemList.append(self.getAccFromPath(por, 0,0,1,2,1))
    #word
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,3))
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,4))
    ItemList.append(self.getAccFromPath(por, 0,0,1,2,2))
    #character with spaces
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,6))
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,5))
    ItemList.append(self.getAccFromPath(por, 0,0,1,2,3))
    #character without spaces
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,8))
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,7))
    ItemList.append(self.getAccFromPath(por, 0,0,1,2,4))
    #bytes
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,10))
    ItemList.append(self.getAccFromPath(por, 0,0,1,1,9))
    ItemList.append(self.getAccFromPath(por, 0,0,1,2,5))
    txtThree = self.getItemText(lblThree)
    if self.hasAccRole('label', lblOne):
      if self.hasAccRole('label', lblTwo):
        if self.hasAccRole('label', lblThree):
          for i in ItemList:
            self.inhibitMayStop()
            self.sayItem(i)
          self.blockNTasks(1, Task.SelectorTask)
          return False

class HandleCharacterInsert(Task.CaretTask):
  '''
  Read characters typed in text fields if we get them one at a time.
  '''
  def executeInserted(self, por, text, text_offset, **kwargs):
    if len(text) == 1:
      self.inhibitMayStop()
      self.sayItem(text=text)


class HandleButtonPress(Task.CaretTask):
  '''
  monitor the caret change when Check Word button is pressed
  '''
  def executeDeleted(self, por, text, text_offset, **kwargs):
    por = self.getRootAcc()
    #for check spelling dialog
    checkLabel = self.getAccFromPath(por, 0,0,1)
    checkButton = self.getAccFromPath(por, 0,0,0,1)
    checkTextField = self.getAccFromPath(por, 0,0,0,0)
    check_word = self.getAccFromPath(por, 0,0,0,1)
    table = self.getAccFromPath(por, 0,1,3,0)
    if self.hasAccRole('label', checkLabel):
      if self.hasAccRole('push button', checkButton): 
        if self.hasAccRole('text', checkTextField):
          if self.hasAccState('focused', check_word):
            if self.hasAccState('enabled', table):
              self.inhibitMayStop()
              self.sayInfo(text='spelled wrong')           

class HandleMisspelledWordByHotkey(Task.InputTask):
  '''
  Retrieve the misspelled word when the check spelling dialog is first opened.
  Note: because the first misspelled word is not highlighted, getAccSelection() cannot
        be used to retrieve the misspelled word. The only way to get to the misspelled
        word is by accessing the misspelled word label to explicitly extract its contents.
  '''
  def execute(self, **kwargs):
    por = self.getRootAcc()
    #por to the misspelled word
    misspelled_word_por = self.getAccFromPath(por, 0,0,2)
    misspelled_word_text = self.getAccName(misspelled_word_por)
    self.inhibitMayStop()
    self.sayInfo(text='misspelled word')
    for i in misspelled_word_text:
      self.sayItem(text=i)

