#!/home/revaz/local/bin/python

# version 5.2

import getopt
import string
from numarray import *
from Tkinter import *   
from tkMessageBox import askokcancel
from tkFileDialog import asksaveasfilename
import os
import glob
import time

import pNbody
from pNbody.palette import *

try:
  from optik import OptionParser
except ImportError:
  from optparse import OptionParser


####################################################################################
def parse_options():
####################################################################################

  usage = "usage: %prog [options] file"
  parser = OptionParser(usage=usage)


  parser.add_option("-f", "--fullscreen",
                    action="store_true", 
		    dest="fullscreen", 
		    default=0,
                    help="fullscreen mode")

  parser.add_option("--stereo",
                    action="store_true", 
		    dest="stereo", 
		    default=0,
                    help="stereo mode")
		      
  parser.add_option("-a", "--auto",
                    action="store_true", 
		    dest="auto", 
		    default=0,
                    help="automatically run the movie")

  parser.add_option("--nopalette",
                    action="store_true", 
		    dest="nopalette", 
		    default=0,
                    help="do not display the palette")

  parser.add_option("--nocontroll",
                    action="store_true", 
		    dest="nocontroll", 
		    default=0,
                    help="do not display the controll pannel")

  parser.add_option("--notime",
                    action="store_true", 
		    dest="notime", 
		    default=0,
                    help="do not display the time")

  parser.add_option("-p",
  		    action="store", 
  		    dest="palette",
  		    type="string",
		    default = None,		    
  		    help="palette name",       
  		    metavar=" PALETTE NAME")

  parser.add_option("-z",
  		    action="store", 
  		    dest="zoom",
  		    type="string",
		    default = 1,		    
  		    help="zoom factor",       
  		    metavar=" INT")

  parser.add_option("-s",
  		    action="store", 
  		    dest="speed",
  		    type="int",
		    default = 1,		    
  		    help="speed",       
  		    metavar=" INT")

  parser.add_option("-i",
                    action="store_true", 
		    dest="info", 
		    default=0,
                    help="read the whole film before displaying it (get info)")

  parser.add_option("--delay",
  		    action="store", 
  		    dest="delay",
  		    type="float",
		    default = 0.,		    
  		    help="delay before starting in auto mode",       
  		    metavar=" FLOAT")

  parser.add_option("--presentation",
                    action="store_true", 
		    dest="presentation", 
		    default=0,
                    help="choose parameters for presentation")

  parser.add_option("--loop",
                    action="store_true", 
		    dest="loop", 
		    default=0,
                    help="loop on")

		    
  parser.add_option("-b","--background",
  		    action="store", 
  		    dest="background",
  		    type="string",
		    default = 'black',		    
  		    help="palette name",       
  		    metavar=" COLOR")	    

  (options, args) = parser.parse_args()

    
  palette    = options.palette
  zoom       = options.zoom
  speed      = options.speed
  info       = options.info
  fullscreen = options.fullscreen
  stereo     = options.stereo
  auto       = options.auto
  nopalette  = options.nopalette
  nocontroll = options.nocontroll
  notime     = options.notime
  delay      = options.delay
  background = options.background
  loop       = options.loop
  
  if stereo:
    fullscreen = 1
    nopalette = 1  
    nocontroll = 1
    notime = 1
    pass

  if options.presentation:
    fullscreen = 1
    nopalette = 1
    nocontroll = 1
    notime = 1


  if len(args) == 0:
    print "you must specify a filename"
    sys.exit(0)
  
  return args[0],palette,zoom,speed,info,fullscreen,stereo,auto,nopalette,nocontroll,notime,delay,background,loop



####################################################################################
#
# Main Class
#
####################################################################################

from Tkinter import *
import os
from tkFileDialog   import askopenfilename


class App:
  
  def __init__(self,master,fname_init,palette_init,zoom_init,speed_init,info_init,fullscreen,stereo,auto,nopalette,nocontroll,notime,delay,background,loop):
  
    # global variables
    
  
    self.master = master
    #self.screenwidth  = master.winfo_screenwidth() -int(0.1*master.winfo_screenwidth())
    #self.screenheight = master.winfo_screenheight()-int(0.1*master.winfo_screenheight())
    self.screenwidth  = master.winfo_screenwidth()
    self.screenheight = master.winfo_screenheight()
    
    self.npic = 0
    self.stopfl = 0
    self.fnopen = 0
    self.stepfl=0
    self.strtime = StringVar()  
    self.current_fname = fname_init
    self.subfname=os.path.basename(self.current_fname)
    
    # look at the availables colormap tables
    self.tables = glob.glob(os.path.join(PALETTEDIR,'*'))
    # create a pallette object
    self.palette = Palette()
    
    
    # parameters
    
    self.speed = speed_init
    self.zoom = float(zoom_init)
    self.info = info_init

    self.fullscreen = fullscreen
    self.stereo = stereo
    self.auto = auto
    self.nopalette = nopalette 
    self.nocontroll = nocontroll
    self.notime = notime
    self.delay = delay
    self.background = background
    self.loop = loop
    
    self.stepsize = 1
    
    # init sequence
    
    if self.current_fname!="":
      self.film_init()
    else:
      self.default_init()
   
          
      
    ###############
    # control panel
    ###############  
      
    # frame  
      
    frame = Frame(master)
    frame.grid(column=0,row=0,sticky=N+S+E+W)
    self.frame = frame

    if fullscreen and auto:
      self.draw_win_control(0)
    else:
      self.draw_win_control(1)


    if palette_init != None:
    
      if os.path.isfile(palette_init):
        palette_name = palette_init
      else:
        palette_name = os.path.join(PALETTEDIR,palette_init)
      
      self.palette.change(palette_name)
    
    
    self.stopfl = 0
    
    
    # if needed, open the film window and
    # display the first image
    
    if self.current_fname !="":
      self.displayfilm()

    if self.auto:
      self.run()


  ###########################
  def draw_win_control(self,mode):
  ###########################

    self.frame_controll = Frame(self.frame)  
    if not self.nocontroll:
      self.frame_controll.grid(column=0,row=0,sticky=E+N+S+W)	
    
    # run button
    self.runBut = Button(self.frame_controll,text="RUN",fg="black",command=self.run)
    self.runBut.grid(column=0,row=1,sticky=E+N+S+W)
    
    # stop button
    self.stopBut = Button(self.frame_controll,text="STOP",fg="black",command=self.stop)
    self.stopBut.grid(column=0,row=2,sticky=E+N+S+W)
    
    # step button
    self.stepBut = Button(self.frame_controll,text="STEP",fg="black",command=self.step)
    self.stepBut.grid(column=1,row=1,sticky=E+N+S+W)
    
    # reset button
    self.resetBut = Button(self.frame_controll,text="RESET",fg="black",command=self.reset)
    self.resetBut.grid(column=2,row=1,sticky=E+N+S+W)   
    
    # back button
    self.backBut = Button(self.frame_controll,text="BACK",fg="black",command=self.back)
    self.backBut.grid(column=1,row=2,sticky=E+N+S+W) 
    

    # quit button
    self.quitBut = Button(self.frame_controll,text="QUIT",fg="black",command=self.quit)
    self.quitBut.grid(column=2,row=2,sticky=E+N+S+W)       
    
    # zoom button
    self.resetBut = Button(self.frame_controll,text="ZOOM",fg="black",command=lambda zoom=self.makezoom:zoom(1.25))
    self.resetBut.grid(column=0,row=3,sticky=E+N+S+W)  
    
    # unzoom button
    self.resetBut = Button(self.frame_controll,text="UNZOOM",fg="black",command=lambda zoom=self.makezoom:zoom(0.8))
    self.resetBut.grid(column=1,row=3,sticky=E+N+S+W)     
     
    # reset zoom button
    self.resetzoomBut = Button(self.frame_controll,text="RESET ZOOM",fg="black",command=self.reset_zoom)
    self.resetzoomBut.grid(column=2,row=3,sticky=E+N+S+W)      

    # label for the file entry
    self.filenameLab = Label(self.frame_controll,text="filename :")
    self.filenameLab.grid(column=0,row=0,sticky=E+N+S+W)

    if self.info:   
      # labels for the starting time
      self.starttimeLab = Label(self.frame_controll,text="start. time :")
      self.starttimeLab.grid(column=5,row=1,sticky=E+N+S+W)  
    
      # entry for the starting time
      self.starttimeEnt = Entry(self.frame_controll,width=5)
      self.starttimeEnt.grid(column=6,row=1,sticky=E+N+S+W)
      self.starttimeEnt.insert(INSERT,self.starttime)
      self.starttimeEnt.bind("<Return>",self.changestarttime)
    
      # labels for the stoping time
      self.stoptimeLab = Label(self.frame_controll,text="stop. time :")
      self.stoptimeLab.grid(column=5,row=2,sticky=E+N+S+W)  
    
      # entry for the stopping time
      self.stoptimeEnt = Entry(self.frame_controll,width=5)
      self.stoptimeEnt.grid(column=6,row=2,sticky=E+N+S+W)
      self.stoptimeEnt.insert(INSERT,self.stoptime)
      self.stoptimeEnt.bind("<Return>",self.changestoptime)
    
       # labels for the starting pic
      self.startpicLab = Label(self.frame_controll,text="start. pic :")
      self.startpicLab.grid(column=7,row=1,sticky=E+N+S+W)  
    
      # entry for the starting pic
      self.startpicEnt = Entry(self.frame_controll,width=5)
      self.startpicEnt.grid(column=8,row=1,sticky=E+N+S+W)
      self.startpicEnt.insert(INSERT,`self.startpic`)
      self.startpicEnt.bind("<Return>",self.changestartpic)
    
      # labels for the stoping pic
      self.stoppicLab = Label(self.frame_controll,text="stop. pic :")
      self.stoppicLab.grid(column=7,row=2,sticky=E+N+S+W)  
    
      # entry for the stopping pic
      self.stoppicEnt = Entry(self.frame_controll,width=5)
      self.stoppicEnt.grid(column=8,row=2,sticky=E+N+S+W)
      self.stoppicEnt.insert(INSERT,self.stoppic)
      self.stoppicEnt.bind("<Return>",self.changestoppic)
    
      # labels for the step size
      self.stepsizeLab = Label(self.frame_controll,text="step size :")
      self.stepsizeLab.grid(column=7,row=3,sticky=E+N+S+W)  
    
      # entry for the step size
      self.stepsizeEnt = Entry(self.frame_controll,width=3)
      self.stepsizeEnt.grid(column=8,row=3,sticky=E+N+S+W)
      self.stepsizeEnt.insert(INSERT,self.stepsize)

    
    # entry for the filename
    self.fname = Entry(self.frame_controll)
    self.fname.grid(column=1,row=0,columnspan=10,sticky=E+N+S+W)
    self.fname.insert(INSERT,self.current_fname)
    self.fname.bind("<Return>",self.fnameentry)
         
    # frame for the palette
    if not self.nocontroll and not self.nopalette:
      self.paletteFrame = Frame(self.frame_controll,height=48,width=512)
      self.paletteFrame.grid(column=0,row=5,columnspan=10) 
      self.palette.addFrame(self.paletteFrame)
      self.paletteFrame.bind('<ButtonRelease>',self.redisplay)
    
    # menus
        
    self.menubar = Menu(self.master)
    
    self.filemenu = Menu(self.menubar,tearoff=0)
    self.filemenu.add_command(label="open",command=self.open)
    self.filemenu.add_command(label="reload",command=self.reload)
    self.filemenu.add_command(label="save image",command=self.save)
    self.filemenu.add_separator()
    self.filemenu.add_command(label="quit",command=self.quit)
    
    self.colormapmenu = Menu(self.menubar,tearoff=0)
   
    
    for table in self.tables:
      self.colormapmenu.add_command(label=os.path.basename(table),
                                    command=lambda table=table,colormap=self.colormap:colormap(table)) 
				    
     
            
    self.speedmenu = Menu(self.menubar,tearoff=0)
    self.speedmenu.add_command(label="speed   1",command=lambda speed=self.set_speed:speed(  1))
    self.speedmenu.add_command(label="speed  50",command=lambda speed=self.set_speed:speed( 50))
    self.speedmenu.add_command(label="speed 100",command=lambda speed=self.set_speed:speed(100))
    
    self.zoommenu = Menu(self.menubar,tearoff=0)
    self.zoommenu.add_command(label="x 1.25",command=lambda zoom=self.makezoom:zoom(1.25))
    self.zoommenu.add_command(label="x 2.00",command=lambda zoom=self.makezoom:zoom(2.))
    self.zoommenu.add_command(label="x 0.80",command=lambda zoom=self.makezoom:zoom(0.8))
    self.zoommenu.add_command(label="x 0.50",command=lambda zoom=self.makezoom:zoom(0.5))
    
    self.menubar.add_cascade(label="File",menu=self.filemenu)
    self.menubar.add_cascade(label="Colormap",menu=self.colormapmenu)
    self.menubar.add_cascade(label="Speed",menu=self.speedmenu)
    self.menubar.add_cascade(label="Zoom",menu=self.zoommenu)
       
    if not self.fullscreen and not self.nocontroll:   
      self.master.config(menu=self.menubar)
      
    # bind key  
    self.master.bind('<KeyPress>',self.onKeyPress)  
    
    if self.nocontroll:
      self.master.bind('<Button-1>',lambda event:self.step())
      self.master.bind('<Button-2>',lambda event:self.reset())
      self.master.bind('<Button-3>',lambda event:self.back())
   
      self.master.bind('<Double-Button-1>',lambda event:self.run())
      self.master.bind('<Double-Button-2>',lambda event:self.quit())
      self.master.bind('<Double-Button-3>',lambda event:self.stop())
    
    
    
     
  ##########################
  def onKeyPress(self,event):
  ##########################
        
      
    if event.char == 'r':		# run
      self.run()
      		
    if event.char == 's':		# stop
      self.stop()
    
    if event.char == 'n':		# step
      self.step()
    
    if event.char == 'b':		# back  
      self.back()
                  
    if event.char ==  u'\u000D':	# reset (enter) 
      self.reset()
          
    if event.char == 'q':		# quit
      self.quit()
  
    if event.char == u'\u001B':		# quit (escape)
      self.quit()
      
#    if event.char == 'f':		# fullscreen
#      self.master.overrideredirect(1)     
        
  ###########################  
  def colormap_slider(self,event):
  ########################### 
    self.colormap(self.paletteSc.get())
    
  ###########################
  def default_init(self):
  ###########################     
  
      self.starttime = '0.'
      self.stoptime = '0.'
      self.startpic = 0
      self.stoppic = 0
      
     

  ###########################
  def film_init(self):
  ###########################    
    
    # parameters
  
    npic = 0
    
    self.openfilm()
    if self.fnopen == 1:

      # first, read the header and find numByte
      
      self.header = self.film.read(256)
      
      if len(self.header) == 256:
  
	self.film.seek(240)
	
	str1 = self.film.read(8)
	str2 = self.film.read(8)
	         
        if (str1 !="        " and str2 !="        "):
          self.naxis1_init = string.atoi(str1)
          self.naxis2_init = string.atoi(str2)
        else:
          self.naxis1_init = 256
          self.naxis2_init = 192
	  	
        self.numByte = self.naxis1_init
	self.numLine = self.naxis2_init
	
        if self.stereo:
	  self.naxis1_init =  self.naxis1_init/2  
 
        self.naxis1 = self.naxis1_init*self.zoom
        self.naxis2 = self.naxis2_init*self.zoom
        self.shape = (self.naxis1_init,self.naxis2_init)
        self.zshape = (self.naxis1,self.naxis2)
	 
       	if self.numByte < 256:
          self.headerlength = 256
	else:
	  self.headerlength = self.numByte
	  
	self.film.seek(0) # go to the top of the file  
        
	self.readpic()

        # reading next label
        self.time = self.film.read(self.headerlength)
	self.starttime = self.time[:8]
        if len(self.time) == self.headerlength:

          # reading next data
          self.data = self.film.read(self.numByte*self.numLine)
          if len(self.data) == self.numByte*self.numLine:

            # converting time
            self.time = self.time[:8]
            npic = npic + 1
 
 	    # split data if stereo mode 					      
	    if self.stereo:							      
	      mat = reshape(fromstring(self.data,'b'),(self.numLine,self.numByte))    
	      smat1 = mat[0:self.naxis1_init,0:self.naxis2_init] 
	      smat2 = mat[0:self.naxis1_init,self.naxis2_init:]
	      data1 = smat1.tostring()  
	      data2 = smat2.tostring()  
	      self.image = (Image.fromstring("P",self.shape,data1),Image.fromstring("P",self.shape,data2))	        			 
	    else:
    	      self.image = Image.fromstring("P",self.shape,self.data)



 
 
            ok = 1
	    
	    if self.info:
 
	      while ok:
 
	        ok = 0
	        # reading next label
	        ctime = self.film.read(self.headerlength)
	        if len(ctime) == self.headerlength:

	         # reading next data
	         self.data = self.film.read(self.numByte*self.numLine)
	         if len(self.data) == self.numByte*self.numLine:
	           ok = 1
	           npic = npic + 1
	           self.stoptime = ctime[:8]
		   
	
	
      # go to the top of the file and miss the header	
		
      self.film.seek(0)	
	
      # read the first image	
      self.readpic()
	
		
      # parameters
      if self.info:
	npcitot = npic
	self.npic = 1
	self.startpic = 1
	self.stoppic = npic
	self.ntotime = (string.atof(self.stoptime)-string.atof(self.starttime))/(npic-1)
	if self.ntotime == 0:
	  self.timeton = 1.  
	else:
	  self.timeton = 1. / self.ntotime
	self.firsttime = string.atof(self.starttime)

	self.npicmax = self.stoppic 
	self.npicmin = self.startpic 


 
  ###########################
  def open(self):
  ###########################   
  
     name = askopenfilename()
     if name!="":
       self.current_fname = name
  
       self.fname.delete(0,len(self.fname.get())+1)
       self.fname.insert(INSERT,self.current_fname)
       self.reload()
      
  ###########################
  def reload(self):
  ###########################    
  
    self.film_init()

    if self.info:
  
      # erasing old values
      self.starttimeEnt.delete(0,len(self.starttimeEnt.get())+1)
      self.stoptimeEnt.delete(0,len(self.stoptimeEnt.get())+1)
      self.startpicEnt.delete(0,len(self.startpicEnt.get())+1)
      self.stoppicEnt.delete(0,len(self.stoppicEnt.get())+1)

      # inserting new values
      self.startpicEnt.insert(INSERT,`self.startpic`)
      self.stoppicEnt.insert(INSERT,`self.stoppic`)
      self.starttimeEnt.insert(INSERT,self.starttime)
      self.stoptimeEnt.insert(INSERT,self.stoptime)
    
 
    # displaying first image
    self.subfname=os.path.basename(self.current_fname)
 
    self.set_size()
    self.film_window.title(self.subfname)
  
        
  ###########################
  def readpic(self):
  ###########################  
  
    # reading next label
    self.time = self.film.read(self.headerlength)
    if len(self.time) == self.headerlength:
      
      # reading next data
      self.data = self.film.read(self.numByte*self.numLine)
      if len(self.data) == self.numByte*self.numLine:
 
    	# converting time
    	self.time = self.time[:8]
    	self.npic = self.npic + 1

 	# split data if stereo mode					          
	if self.stereo: 						          
	  mat = reshape(fromstring(self.data,'b'),(self.numLine,self.numByte))    
	  smat1 = mat[0:self.naxis1_init,0:self.naxis2_init] 
	  smat2 = mat[0:self.naxis1_init,self.naxis2_init:]					          
	  data1 = smat1.tostring()  
	  data2 = smat2.tostring()  
	  self.image = (Image.fromstring("P",self.shape,data1),Image.fromstring("P",self.shape,data2)) 				          
	else:
    	  self.image = Image.fromstring("P",self.shape,self.data)
	
	return(1)
	
    else:
      return(0)      
	
 

  ###########################
  def draw_win_film(self):
  ###########################
 
     try :
       self.film_window
       
     except AttributeError :
     
     
       if not self.fullscreen and not self.nocontroll:
     
         self.film_window = Toplevel()
         self.film_window.title(self.subfname)  

       else:
     
         self.film_window = Frame(self.frame,height=48,width=512)
         self.film_window.grid(column=0,row=6,columnspan=10,sticky=W+E+N+S) 
         self.film_window.bind('<ButtonRelease>',self.redisplay)

         
       # frame					  
       self.frame_film = Frame(self.film_window)  
       self.frame_film.grid(column=0,row=0,sticky=W+E+N+S)

       # label for the time
       if not self.notime:
         self.timeLab = Label(self.frame_film,textvariable=self.strtime)
         self.timeLab.grid(column=0,row=0,sticky=W+E+N+S)
 
       # canvas for the film
       if self.stereo:
	 self.canvas = Canvas(self.frame_film,height=self.screenheight,width=self.screenwidth,background=self.background,highlightbackground=self.background)	
       else:
         self.canvas = Canvas(self.frame_film,height=self.naxis2,width=self.naxis1,background=self.background)
       
       
       self.canvas.grid(column=0,row=1,sticky=W+E+N+S)

       # frame for the palette
       if self.nocontroll and not self.nopalette:
         self.paletteFilmFrame = Frame(self.frame_film,height=48,width=512)
         self.paletteFilmFrame.grid(column=0,row=2) 
         self.palette.addFrame(self.paletteFilmFrame)
         self.paletteFilmFrame.bind('<ButtonRelease>',self.redisplay)	    
       
       # bind events
       self.film_window.bind("<Destroy>",self.destroy_film)

       # bind key  
       self.film_window.bind('<KeyPress>',self.onKeyPress)  
    
  ########################### 
  def destroy_film(self,event):
  ########################### 
  
    try:
      del self.film_window
    except AttributeError :
      return  

  ########################### 
  def reset_zoom(self):
  ###########################
       
    try:
      self.film_window.destroy
      self.zoom = 1.
      self.naxis1 =self.naxis1_init
      self.naxis2 =self.naxis2_init
      self.zshape = (self.naxis1,self.naxis2)
 
      if self.stereo:
        self.canvas.config(height=self.screenheight,width=self.screenwidth)	
      else:
        self.canvas.config(height=self.naxis2,width=self.naxis1)
      
    except AttributeError :
      pass  
      
    self.displayfilm()        

  ########################### 
  def set_size(self):
  ###########################
       
    try:
      self.film_window.destroy
      self.naxis1 =self.naxis1_init*self.zoom
      self.naxis2 =self.naxis2_init*self.zoom
      self.zshape = (self.naxis1,self.naxis2)

      if self.stereo:
        self.canvas.config(height=self.screenheight,width=self.screenwidth)	
      else:
        self.canvas.config(height=self.naxis2,width=self.naxis1)
	       
    except AttributeError :
      pass  
      
    self.displayfilm()        
    

  
  ########################### 
  def makezoom(self,z):
  ###########################   
   
    self.film_window.destroy
    self.zoom = self.zoom*z
    self.naxis1 =int(self.naxis1*z)
    self.naxis2 =int(self.naxis2*z)
    self.zshape = (self.naxis1,self.naxis2)

    if self.stereo:
      self.canvas.config(height=self.screenheight,width=self.screenwidth)     
    else:
      self.canvas.config(height=self.naxis2,width=self.naxis1)
	    
    self.displayfilm()
    
  ########################### 
  def colormap(self,name):
  ###########################    
   
    self.palette.change(name)
    
    if self.stopfl == 0:
      self.palette.draw()
      
    self.displayfilm()   
      
  ########################### 
  def set_speed(self,sp):
  ###########################    
   
    self.speed = sp   


  ########################### 
  def errorbox(self,txterror):
  ###########################    
  
    self.error = Toplevel()  
    
    frame = Frame(self.error) 
    frame.pack()
     
    text0 = Label(frame,text="ERROR !",fg="red")
    text0.pack()
    
    text = Label(frame,text=txterror,fg="red")
    text.pack()
    
    ok = Button(frame,text="OK",fg="black",command=self.error.destroy)
    ok.pack()

    self.error.mainloop() 
    
  ########################### 
  def fnameentry(self,event):
  ###########################  
  
    self.current_fname = self.fname.get()
    self.reload()    


  ###########################
  def openfilm(self):
  ###########################
          
    # check if the file is already open
    
    self.fnopen = 0
    
    
    # check if it exists
    if os.path.exists(self.current_fname):
    
      try :
        self.film.close()
      except :
        None
    
      self.film = open(self.current_fname, 'r')
      self.fnopen = 1
    else:
      self.film = None
      self.errorbox("'"+self.current_fname+"'"+"  does not exist")
 

    
     
  ###########################  
  def changestartpic(self,event):  
  ########################### 
    
    self.startpic = string.atoi(self.startpicEnt.get())
    if self.startpic > self.npicmax:
      self.startpic = self.npicmax
      self.startpicEnt.delete(0,len(self.startpicEnt.get())+1)
      self.startpicEnt.insert(INSERT,`self.startpic`) 
    elif self.startpic < self.npicmin:
      self.startpic = self.npicmin
      self.startpicEnt.delete(0,len(self.startpicEnt.get())+1)
      self.startpicEnt.insert(INSERT,`self.startpic`)       
      
    self.starttimeEnt.delete(0,len(self.starttimeEnt.get())+1)
    self.starttimeEnt.insert(INSERT,self.firsttime + self.ntotime*(self.startpic-1)) 
    
  ###########################  
  def changestoppic(self,event):  
  ########################### 
    
    self.stoppic = string.atoi(self.stoppicEnt.get())
    if self.stoppic > self.npicmax:
      self.stoppic = self.npicmax
      self.stoppicEnt.delete(0,len(self.stoppicEnt.get())+1)
      self.stoppicEnt.insert(INSERT,`self.stoppic`)       
    elif self.stoppic < self.npicmin:
      self.stoppic = self.npicmin
      self.stoppicEnt.delete(0,len(self.stoppicEnt.get())+1)
      self.stoppicEnt.insert(INSERT,`self.stoppic`)   
          
    self.stoptimeEnt.delete(0,len(self.stoptimeEnt.get())+1)
    self.stoptimeEnt.insert(INSERT,self.firsttime + self.ntotime*(self.stoppic-1))  
    
  ###########################  
  def changestarttime(self,event):  
  ########################### 
    
    starttime = string.atof(self.starttimeEnt.get())
    self.startpic=int(self.timeton*(starttime-self.firsttime))+1    
    self.startpicEnt.delete(0,len(self.startpicEnt.get())+1)
    self.startpicEnt.insert(INSERT,`self.startpic`)
    self.changestartpic(None)
      
    
    
  ###########################  
  def changestoptime(self,event):  
  ########################### 
    
    stoptime = string.atof(self.stoptimeEnt.get())
    self.stoppic=int(self.timeton*(stoptime-self.firsttime))+1    
    self.stoppicEnt.delete(0,len(self.stoppicEnt.get())+1)
    self.stoppicEnt.insert(INSERT,`self.stoppic`)
    self.changestoppic(None)
    

  ###########################  
  def run(self):  
  ###########################

  
    # parameters
    
    if self.info:
    
      self.stepsize = string.atoi(self.stepsizeEnt.get())
      self.startpic = string.atoi(self.startpicEnt.get())
      self.stoppic = string.atoi(self.stoppicEnt.get())

    else:
    
      self.stepsize = 1
      self.startpic = 1
      self.stoppic  = 1e20  

	
    # if the film is correctely open
    if self.fnopen == 1:
          
      # if the stop button has not been pressed
      if self.stopfl == 0:
 
#        if self.npic < self.stoppic:
 
          if self.stepsize > 1:
	    self.film.read((self.stepsize-1)*(self.numByte*(self.numLine)+self.headerlength))
            self.npic = self.npic + self.stepsize-1
	  	    
	  if self.readpic():
 	    
            # displaying data
	    self.displayfilm()
	    
	    # wait before begining
	    if self.delay!=0:
	      if self.auto:
	        self.master.update()
                time.sleep(self.delay)
                self.delay = 0.
 
            if self.stepfl==0:

	      self.master.after(self.speed,self.run)
            else:
              self.stepfl = 0
            
          else:					# go through only if -i is enabled
    	    if self.loop:
	      self.reset()
	      self.run()


	
	
      # if the stop button has been pressed  

      else:
	self.stopfl = 0		 	
      

  ###########################  
  def step(self):  
  ###########################
  
    self.stepfl = 1
    self.run()
    
  ########################### 
  def back(self):
  ###########################  
    
    self.stepfl = 1
    if self.fnopen == 1: 
      current_byte = self.film.tell()
      new_byte = current_byte-self.stepsize*2*(self.numByte*(self.numLine)+self.headerlength)
      if new_byte < 0:
	self.film.seek(0)
	self.npic=0
      else:
        self.film.seek(new_byte)
        self.npic=self.npic-2*self.stepsize
	
      self.stepfl = 1
      self.run()
      
  ###########################  
  def displayfilm(self):  
  ###########################
  
    # parameters
    import os
    
    # open the win film if not already done
    self.draw_win_film()
    
    if self.stereo:

      # zoom
      if self.zoom != 1:
        zimage1 = self.image[0].transform(self.zshape,Image.AFFINE,(1./self.zoom,0.,0.,0.,1./self.zoom,0.),Image.BICUBIC) # no change if NEAREST is used
        zimage2 = self.image[1].transform(self.zshape,Image.AFFINE,(1./self.zoom,0.,0.,0.,1./self.zoom,0.),Image.BICUBIC) # no change if NEAREST is used
      else:
        zimage1 = self.image[0]
	zimage2 = self.image[1]

      # include the palette
      zimage1.putpalette(self.palette.palette)
      zimage2.putpalette(self.palette.palette)
      # making the photo
      self.photo1 = ImageTk.PhotoImage(zimage1) 
      self.photo2 = ImageTk.PhotoImage(zimage2) 
      
      # displaying the photo
      x1 = (self.screenwidth - 2*zimage1.size[0] )/4
      x2 = x1 + self.screenwidth/2
      y1 = y2 = (self.screenheight  - zimage1.size[1])/2
      
      self.canvas.create_image(x1,y1,anchor=NW,image=self.photo1) 
      self.canvas.create_image(x2,y2,anchor=NW,image=self.photo2) 
    
    else:      

      # zoom																	        				     
      if self.zoom != 1:															        				     
        zimage = self.image.transform(self.zshape,Image.AFFINE,(1./self.zoom,0.,0.,0.,1./self.zoom,0.),Image.BICUBIC) # no change if NEAREST is used    				     
      else:																	        				     
        zimage = self.image															        				     

      # include the palette															        				     
      zimage.putpalette(self.palette.palette)													        				     
      # making the photo															        				     
      self.photo = ImageTk.PhotoImage(zimage) 													        				     
      # displaying the photo															        				     
      self.canvas.create_image(0.,0.,anchor=NW,image=self.photo) 										        				     
    
    # new value for the label
    if not self.notime:
      self.strtime.set(self.time[:8]+' ('+`self.npic`+' )')


  ########################### 
  def redisplay(self,event):
  ###########################  
  
    self.displayfilm()
      
      
  ########################### 
  def stop(self):
  ###########################
  
    self.film_window.destroy
    self.stopfl = 1  
    
  ########################### 
  def reset(self):
  ###########################
  
    if self.fnopen == 1:

      self.film.seek(0)
      self.npic = 0

      while self.npic != self.startpic :
        self.readpic()
     
      # displaying data
      self.displayfilm()
    
	    
  ###########################	    
  def quit(self):
  ###########################
     #ans = askokcancel('Verify exit', "Really quit?")
     #if ans: sys.exit() 
     sys.exit()	    

  ########################### 
  def save(self):
  ###########################    
    
    savename = asksaveasfilename()
    if savename != "":
      
      if savename[len(savename)-5:] == ".fits":
        shape = [self.naxis2,self.naxis1]
        data = fromstring(self.data,'b')
        data.shape = shape
        WriteFits(data,savename, None)
      else:
        self.image.save(savename)	    

        
#
# Save a numeric array to a FITS image file
#
# The FITS image dimensions are taken from the array dimensions.
# The data is saved in the numeric format of the array, or as 32-bit
# floats if a non-FITS data type is passed.
#
# A list of extra header records can be passed in extraHeader. The
# SIMPLE, BITPIX, NAXIS* and END records in this list are ignored.
# Header records are padded to 80 characters where necessary.
#

def WriteFits(data, filename, extraHeader = None) :
    type = data.typecode()
    if type == UnsignedInt8 : bitpix = 8
    elif type == Int16 : bitpix = 16
    elif type == Int32 : bitpix = 32
    else :
        data = data.astype(Float32)
        bitpix = -32
    shape = list(data.shape)
    shape.reverse()
    naxis = len(shape)
    header = [ 'SIMPLE  = T', 'BITPIX  = %d' % bitpix, 'NAXIS   = %d' % naxis ]
    for i in range(naxis) :
        keyword = 'NAXIS%d' % (i + 1)
        keyword = string.ljust(keyword, 8)
        header.append('%s= %d' % (keyword, shape[i]))
    if extraHeader != None :
        for rec in extraHeader :
            try :
                key = string.split(rec)[0]
            except IndexError :
                pass
            else :
                if key != 'SIMPLE' and \
                   key != 'BITPIX' and \
                   key[:5] != 'NAXIS' and \
                   key != 'END' :
                    header.append(rec)
    header.append('END')
    header = map(lambda x: string.ljust(x,80)[:80], header)
    header = string.join(header,'')
    numBlock = (len(header) + 2880 - 1) / 2880
    header = string.ljust(string.join(header,''), numBlock*2880)
    file = open(filename, 'w')
    file.write(header)
    if LittleEndian : data = data.byteswapped()
    data = data.tostring()
    file.write(data)
    numBlock = (len(data) + 2880 - 1) / 2880
    padding = ' ' * (numBlock*2880 - len(data))
    file.write(padding)
       
####################################################################################  
#
#  MAIN
#
####################################################################################  
 
 
import Image
import ImageDraw
import ImageFont
import ImagePalette
import ImageTk 
 

# parse options
fname_init,palette_init,zoom_init,speed_init,info_init,fullscreen,stereo,auto,nopalette,nocontroll,notime,delay,background,loop = parse_options()

if not(os.path.exists(fname_init)):
  if fname_init !="":
    print fname_init+" does not exist."
    sys.exit(0)


######################  
# create main window
######################  
        
root = Tk()
root.title("gmov")
root.configure(bg=background)


screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()

if fullscreen:
  root.overrideredirect(1)
  root.geometry(str(root.winfo_screenwidth())+"x"+str(root.winfo_screenheight()))
  #  root.focus_set()
  #  root.focus_force()
  #  root.focus_displayof()
  #  root.focusmodel()
  #  root.grab_set_global()
  
  
app = App(root,fname_init,palette_init,zoom_init,speed_init,info_init,fullscreen,stereo,auto,nopalette,nocontroll,notime,delay,background,loop)

root.mainloop()   

