#
# This file is part of GNU Enterprise.
#
# GNU Enterprise is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2, or (at your option) any later version.
#
# GNU Enterprise 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with program; see the file COPYING. If not,
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
# Copyright 2002-2007 Free Software Foundation
#
# FILE:
# TextBox.py
#
# DESCRIPTION:
#
# NOTES:
#


import curses, string

import sio
from constants import *
from Control import Control

class TextArea(Control):
  """
    An example textbox control.  Allows the user to enter text.  Only
    basic editing though
  """
  def __init__(self, Parent, TextboxName, Y, X, W, H, DefaultValue="", Password=0,
         **properties):
    Control.__init__(self, Parent, TextboxName, **properties)
    self.PARENT = Parent
    self.CLASS = "TEXTBOX"
    self.PASSWORD = Password
    self.X = X
    self.Y = Y
    self.W = W
    self.H = H
    self.TEXT = DefaultValue
    self.CANGETFOCUS = 1
    self.FOCUS = 0
    self.DEPTH = 0  # our position in the text: 0..N
    self.MAXLENGTH = -1   # if -1, text length is unlimited

    self.SetMethod("SYSPAINT", self.Paint)
    self.SetMethod("SYSGOTFOCUS", self.GotFocus)
    self.SetMethod("SYSLOSTFOCUS", self.LostFocus)
    self.SetMethod("SYSRUN", self.Run)
    self.SetMethod("VERIFY", self.BogusVerify)
    self.SetMethod("LOSTFOCUS", None)
    self.SetMethod("GOTFOCUS", None)
    self.last_act = 1  # 1 = forward, 0 = backward
    self.laststart = 0
    self.EDITABLE = 1

    self.SetColor('TEXTBOX', 'TEXTBOX_FOCUS')

  def Run(self, v1, v2, v3):
    Container = self.PARENT.Screen()
    if self.EDITABLE:
      try:
        curses.curs_set(1)
      except:
        pass
    if v1 :
      Depth = self.DEPTH
      offset = (v3 - self.X)
      textlen = len(self.TEXT)
      if Depth < self.W:
        Depth = offset
      else:
        Depth = Depth -  (self.W- offset)
      if Depth < 0:
        Depth = 0
      elif Depth > textlen:
        Depth = textlen
      self.DEPTH = Depth
      self.Paint(0,0,0)
    while 1:
      ch = Container.GetChar()
      if self.PARENT.BreakOrder(ch) :
        try:
          curses.curs_set(0)
        except:
          pass
        return

      ch = self.PARENT.KeystrokeHook(ch)
      if ch != None:

        Depth = self.DEPTH
        Text = self.TEXT
        global BACKWARDS
        if ch in (Container.TokDownArrow, Container.TokNextField, Container.TokActivate, Container.TokUpArrow):
          BACKWARDS = 0
          if ch == Container.TokUpArrow:
            BACKWARDS = 1
          if self.ExecMethod( "VERIFY", self.TEXT, None, None) :
            try:
              curses.curs_set(0)
            except:
              pass
            return
        elif ch == Container.TokLeftArrow:
          Depth = Depth - 1
          self.last_act = 0
          if Depth < 0:
            Depth = 0
        elif ch == Container.TokHomeKey:
          Depth = 0
        elif ch == Container.TokEndKey:
          Depth = len(Text)
        elif ch == Container.TokRightArrow:
          Depth = Depth + 1
          self.last_act = 1
          if Depth > len(Text):
            Depth = len(Text)
        elif ch == Container.TokBackspace:
          Depth = Depth - 1
          if Depth < 0:
            Depth = 0
          Text = Text[0:Depth] + Text[Depth+1:len(Text)]
        else:
          if ch <= 256 and self.EDITABLE:
            if Depth == len(Text):    # at end
              Text = Text + chr(ch)
            elif Depth == 0:    # at the beginning
              if len(Text) == 0:
                Text = chr(ch)
              else:
                Text = chr(ch) + Text
            else:         # insert text
              Text = Text[:Depth] + chr(ch) + Text[Depth:]
            Depth = Depth + 1
            self.last_act = 1
        self.DEPTH = Depth
        self.TEXT = Text
        self.Paint(None, None, None)

  def BogusVerify(self, TheControl, TheText, v3):
    return 1

  def Paint(self, v1, v2, v3):
    Container = self.PARENT.Screen()
    TextLen = len(self.TEXT)

    if self.PASSWORD:
      Text = "*" * TextLen
    else:
      Text = self.TEXT

    W = self.W
    Depth = self.DEPTH
    Visuals = ''
    self.LoLight()

    i = 0
    for line in lineWrap(Text, W):
      TextLen = len(line)
      if TextLen <= W or Depth < W:
        Visuals = line + ((W - TextLen) * "_")
        if len(Visuals) > W:
          Visuals = Visuals[:W-1] + ">"
        Container.PrintAt(self.Y+i, self.X, Visuals, self.FOCUS and self.FOCUSCOLOR or self.COLOR)
        Container.GotoYX(self.Y+i, self.X+ Depth)
      else:
        if Depth >= W:
          Visuals = "<" + Text[Depth - (W - 1):] + (((W - 1) - TextLen) * "_")
          if len(Visuals) > W:
            Visuals = Visuals[:W]
          Container.PrintAt(self.Y+i, self.X, Visuals, self.FOCUS and self.FOCUSCOLOR or self.COLOR)
          Container.GotoYX(self.Y+i, self.X+  W)
      i += 1

      for j in range(self.H - i):
        Container.PrintAt(self.Y + i + j, self.X, "_" * W, self.FOCUS and self.FOCUSCOLOR or self.COLOR)


  def SetCursor(self, location):
    self.DEPTH = location
    Container = self.PARENT.Screen()
    curses.curs_set(1)
    Container.GotoYX(self.Y, self.X+ self.DEPTH)
    self.Paint(None, None, None)

  def LostFocus(self, v1, v2, v3):
    curses.curs_set(0)
    self.SetColor('TEXTBOX')
    Container = self.PARENT.Screen()
    if self.PARENT.VISIBLE:
      self.Paint(0,0,0)

  def GotFocus(self, v1, v2, v3):
    self.SetColor('TEXTBOX_FOCUS')
    Container = self.PARENT.Screen()
    self.Paint(None, None, None)
    Container.GotoYX(self.Y, self.X+ self.DEPTH)

  def SetValue(self, newText, repaint=1):
    self.TEXT = newText
    if self.PARENT.VISIBLE:
      self.Paint(0,0,0)

  def GetValue(self):
    return self.TEXT


# very simple lineWrap
def lineWrap(message,maxWidth):
  text = []

  for strings in string.split(message,"\n"):
    while len(strings) > maxWidth:
      index = 0
      for sep in [' ',',',':']:
        ind = string.rfind(strings,sep,0,maxWidth-1)+1
        if ind > index: index = ind

      if index > maxWidth:
        index = maxWidth-1

      text.append(strings[:index])
      strings = strings[index:]

    text.append(strings)

  return text


