#
# 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:
# FileSelectPad.py
#
# DESCRIPTION:
#
# NOTES:
#


import os
import string
import curses

from constants import *
from Control import Control
from ScrollBar import ScrollBar

class FileSelectPad(Control):
  """
  """
  __prefix_width__ = 6
  __threshhold__   = 250

  def __init__(self, Root, Y, X,H, W, **properties):
    Control.__init__(self, Root, '', properties)
    self.Y = Y
    self.ROWS = H
    self.X = X
    self.H = H
    self.W = W
    self.PARENT = Root
    self.X = self.X
    self.Y = self.Y
    self._W = self.W
    self._H = self.H
    self.MYROOT = Root
    self.NAME = 'fileselectpad'
    self.SetMethod("SYSRUN",self.Run)
    self.SetMethod("GOTFOCUS",self.GotFocus)
    self.SetMethod("LOSTFOCUS",self.LostFocus)
#    self.SetMethod("SYSPAINT",self.Paint)
    self.SetMethod("PAINT",self.Paint)
    self.CANGETFOCUS = 1
    self.COLWIDTH = 25
    self.COLDISP = W / self.COLWIDTH
    self.pad = None
    self.hilit = 1
    self.xoffset = -1
    self.yoffset = 0
    self.SetColor(1)
    self.LoLight()
    self.dirlist = []
    self.sb = None
    self.changed = 1
    self.__first = 1

  def Run(self,v1,v2,v3):
    rows = self.ROWS
    if v1 :
      self.__SetHilit(v2,v3)
      if self.sb != None:
         self.sb.Set(self.hilit / rows)
      if self.dirlist[self.hilit-1][:1] != 'D':
        active = self.GetMethod("ACTIVE")
        if active != None and self.Verify(None,None,None):
          apply(active,(self,self.dirlist[self.hilit-1][self.__prefix_width__:],None))
      action = self.GetMethod("ACTION")
      if action != None and self.Verify(None,None,None):
        if self.path[-1:] != '/':
          self.path += '/'
        apply(action,(self,self.path + self.dirlist[self.hilit-1][self.__prefix_width__:],None))
      self.Paint(0,0,0)
    Container = self.SCREEN
    while 1:
      self.__DrawItem(self.hilit,1)
      if self.active != 1:
        return 0
      ch = Container.GetChar()
      if self.PARENT.BreakOrder(ch) :
        return 
      if ch in (Container.TokNextField,):
        return
      elif ch == Container.TokActivate:
        action = self.GetMethod("ACTION")
        if action != None and self.Verify(None,None,None):
          if self.path[-1:] != '/':
            self.path += '/'
          apply(action,(self,self.path + self.dirlist[self.hilit-1][self.__prefix_width__:], None))
      elif ch == Container.TokDownArrow:
        self.hilit += 1
        if self.Verify(None,None,None) and self.sb != None:
          col = (self.hilit) / self.ROWS
          self.sb.Set(col-1)
      elif ch == Container.TokUpArrow:
        self.hilit -= 1
        if self.Verify(None,None,None) and self.sb != None:
          col = (self.hilit) / self.ROWS
          self.sb.Set(col-1)
      elif ch == Container.TokLeftArrow:
        self.hilit -= rows
        if self.Verify(None,None,None) and self.sb != None:
          self.sb.Dec(None,None,None)
      elif ch == Container.TokRightArrow:
        self.hilit += rows
        if self.Verify(None,None,None) and self.sb != None:
          self.sb.Inc(None,None,None)
      if self.hilit > len(self.dirlist):
        self.hilit = len(self.dirlist)
      elif self.hilit <= 0:
        self.hilit = 1
      active = self.GetMethod("ACTIVE")
      if active != None and self.Verify(None,None,None):
        apply(active,(self,self.dirlist[self.hilit-1][self.__prefix_width__:],None))
      self.Paint(0,0,0)

  def GotFocus(self,v1,v2,v3):
    self.X = self.X
    self.Y = self.Y
    self._W = self.W
    self._H = self.H
    self.FOCUS = 1
    self.Paint(None,None,None)
    return 1

  def LostFocus(self,v1,v2,v3):
    self.FOCUS = 0
    self.Paint(None,None,None)
    return 1

  def Display(self, path):
    if self.pad != None:
      self.pad.erase()
      self.hilit = 1
#      self.Paint(0,0,0)
    if os.access(path, os.R_OK | os.X_OK) and os.path.isdir(path):
      self.path = path
      self.dirlist = os.listdir(path)
      self.__SortAndMarkDirList()
      count = len(self.dirlist)
      rows = self.H
      colwidth = self.COLWIDTH
      if (count) * colwidth > self.__area():
        rows -= 1
        setupSB = 1
      else:
        setupSB = 0
      self.ROWS = rows
      cols = ((count / rows) * colwidth)
      self.pad = curses.newpad(rows+1,cols+((self.COLDISP+1) * (colwidth)))
      self.__initScrollBar( setupSB, (count / rows) )
      if curses.has_colors():
        self.pad.bkgdset(' ',curses.color_pair(1))
      self.pad.erase()
      self.fillpad(1)
      self.Paint(None,None,None)
      self.SCREEN.Refresh()
      self.__first = 0

  def __initScrollBar(self, activate, cols):
    if activate :
      if self.sb != None:
        self.sb.Init(cols)
      else:
        self.sb = ScrollBar(self.PARENT,'filesb',self.H+3,2, self.W)
        self.PARENT.AddControl(self.sb)
        self._cols = cols
        self.sb.Init(cols)
        self.PARENT.Refresh(None,None,None)
        self.sb.SetMethod("CHANGED", self.SetCol)
    elif self.sb != None:
      self.PARENT.DelControl(self.sb)
      self.sb.__del__()
      self.PARENT.Refresh(None,None,None)
      self.sb = None

  def SetCol(self,newCol,MaxCol,arg3):
    self.__DrawItem(self.hilit,1)
    rows = self.ROWS
    if newCol <= self._cols and newCol >= 0:
      self.hilit = (rows * (newCol)) + self.yoffset + 1
      if self.hilit < 0:
        self.hilit = 0
      elif self.hilit > len(self.dirlist):
        self.hilit = len(self.dirlist)
      if self.dirlist[self.hilit-1][:1] != 'D':
        active = self.GetMethod("ACTIVE")
        if active != None and self.Verify(None,None,None):
          apply(active,(self,self.dirlist[self.hilit-1][self.__prefix_width__:],None))
      self.Paint(None, None,None)
      self.PARENT.Screen().Refresh()

  def __SortAndMarkDirList(self):
    path = self.path
    if path[-1:] != '/':
      path = self.path + '/'
    dirSort = [ [ not os.path.isdir(path + x), x ] for x in self.dirlist ]
    dirSort.sort
    dirs  = []
    files = []
    for i in dirSort:
      if i[0]==0:
        i[1] = string.ljust('D',self.__prefix_width__) + i[1]
        dirs.append(i[1])
      else:
        i[1] = string.ljust('',self.__prefix_width__)+i[1]
        files.append(i[1])
    dirs.sort()
    files.sort()
    dirs.extend(files)
    self.dirlist = dirs
    for i in range(0,len(self.dirlist)):
      if os.path.islink(path + self.dirlist[i][self.__prefix_width__:]):
        inter = self.dirlist[i][:1] + 'l' + self.dirlist[i][2:]
        self.dirlist[i] = inter
      mod = os.R_OK
      if  os.access( path + self.dirlist[i][self.__prefix_width__:], mod ):
        self.dirlist[i] = self.dirlist[i][:2] + 'r' + self.dirlist[i][3:]
      else:
        self.dirlist[i] = self.dirlist[i][:2] + '-' + self.dirlist[i][3:]
      mod = os.W_OK
      if  os.access( path + self.dirlist[i][self.__prefix_width__:], mod ):
        self.dirlist[i] = self.dirlist[i][:3] + 'w' + self.dirlist[i][4:]
      else:
        self.dirlist[i] = self.dirlist[i][:3] + '-' + self.dirlist[i][4:]
      mod |= os.X_OK
      if  os.access( path + self.dirlist[i][self.__prefix_width__:], mod ):
        self.dirlist[i] = self.dirlist[i][:4] + 'x' + self.dirlist[i][5:]
      else:
        self.dirlist[i] = self.dirlist[i][:4] + '-' + self.dirlist[i][5:]
  def __area(self):
    return self.H* self.W

  def Paint(self,arg1,arg2,arg3):
    if self.pad != None and self.__first == 0:
      self.__DrawItem(self.hilit,3)
      rows = self.ROWS
      colwidth = self.COLWIDTH
      self.yoffset = (self.hilit-1) % rows
      newXoffset = ((self.hilit-1) / rows ) * colwidth
      self.xoffset = newXoffset
      self.pad.refresh(0, self.xoffset,self.Y,self.X,
        self.Y + self._H,self.X + self._W)
    
  def fillpad(self, showProgress = 0):
    rows = self.ROWS
    xoffset = 0
    yoffset = 0
    step = 0
    pb = None
    if showProgress :
      pb = self.PROGRESS
    if pb != None and len(self.dirlist) > self.__threshhold__:
      pb.DeActivate(1)
      pb.Init(len(self.dirlist))
      step = 1
    for i in range(1,len(self.dirlist)+1):
      color = 1
      if step :
        pb.Step()
      if i == self.hilit and self.FOCUS:
        color = 3
      elif self.dirlist[i-1][2] != 'r':
        color = 4
      self.__DrawItem(i,color)
      if i % rows == 0:
        xoffset += self.COLWIDTH
        yoffset = 0
      else:
        yoffset += 1
    if step :
      pb.Init(1)
      pb.DeActivate(0)
    self.changed = 1

  def __DrawItem(self,id,col):
    if self.pad != None and len(self.dirlist)>0:
      rows = self.ROWS
      hilitCol = ((id-1) / rows) * self.COLWIDTH
      hilitRow = (id-1) % rows
      mods = 0
      self.pad.addstr(hilitRow,hilitCol,'')
      String = str(self.dirlist[id-1][:self.COLWIDTH-2])
      if String[2]!='r' and col == 1:
        col = 4
      if curses.has_colors():
        mods = curses.color_pair(col)
      for j in range(0,len(String)):
        if ord(String[j]) == tiHLINE:
          self.pad.addch(curses.ACS_HLINE, mods)
        elif ord(String[j]) == tiVLINE:
          self.pad.addch(curses.ACS_VLINE, mods)
        elif ord(String[j]) == tiBOX:
          self.pad.addch(curses.ACS_BOARD, mods)
        else:
          self.pad.addstr(str(String[j]), mods)
  def __SetHilit(self, YPOS, XPOS):
    self.__DrawItem(self.hilit,1)
    colNo = (self.xoffset + (XPOS-self.X)) / self.COLWIDTH
    self.hilit = ( colNo * self.ROWS) + (YPOS-self.Y) + 1
    if self.hilit < 1:
      self.hilit = 1
    if self.hilit > len(self.dirlist):
      self.hilit = len(self.dirlist)
    self.__DrawItem(self.hilit,3)

  def Verify(self, arg1, arg2, arg3):
    return self.hilit > 0 and self.hilit <= len(self.dirlist)


