"""
     python/ui/VectorsDispobj.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     Copyright (C) 2009-2010 University of York

     This library is free software: you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public License
     version 3, modified in accordance with the provisions of the 
     license to address the requirements of UK law.
 
     You should have received a copy of the modified GNU Lesser General 
     Public License along with this library.  If not, copies may be 
     downloaded from http://www.ccp4.ac.uk/ccp4license.php
 
     This program 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.
"""
import sys
from PyQt4 import QtCore

import dataobj
from global_definitions import *
from graphicsmodel import graphicsmodel
import cprim,mgapp,mmut
 
def GetLoopString(Loop, arg,row):
  res = Loop.GetString(arg,row)
  if type(res) == int:
    return ("",res)
  else:
    return res

#-----------------------------------------------------------------------
def openvectorfile(filename=''):
#-----------------------------------------------------------------------
  m = VectorsData (filename=filename)
  # LoadData may return the parameters for the display_object(s)
  # defined in the file
  #print 'openvectorfile',filename,m.filename
  if m.filename: rv = m.loaddata(m.filename[2])
  #print 'openvectorfile.loaddata',m,rv
  if rv[0]:
    MGGUI().WarningMessage(rv[1])
    m.delete()
    return None
  elif len(rv)>2:
    if rv[2]:
      for pars in rv[2]:
        s =  VectorsDispobj(parent=m.name,params=pars,visible=1)
        #print 'openvectorfile s',s
    else:
      s = VectorsDispobj(parent=m.name,visible=1)
  return m
        
#------------------------------------------------------------------------
#------------------------------------------------------------------------
#------------------------------------------------------------------------
class Vectorsgraphicsmodel(graphicsmodel):
   def __init__(self):
     graphicsmodel.__init__(self)
     self.MGVectors = None
     self.line = None

   def GetAtomsInVolume(self,contained_volume):
     pass

   def GetClickedLinesAndPoints(self,xyzbox,near,far,symmetry=1):
     import cprim
     #print "GetClickedLinesAndPoints",self.MGVectors
     if not self.MGVectors or not  self.MGVectors.connected:
       self.line = [-1,-1,10000.0,-1]
       return 
     line = cprim.FindLine(self.obj,self.MGVectors.connected, \
                           xyzbox,symmetry)
     self.line = [ line.first,line.second, line.dist, line.symm ]
     #print "Vectorsgraphicsmodel GetClickedLinesAndPoints",self.line
     
   def ClickedPrimitiveCoords(self):
     line = self.line
     if line[0] < 0 and line[1] >= 0:
       conn = self.MGVectors.GetCoordinate(line[1],2)
     elif line[0] >= 0 and line[1] < 0 :
       conn = self.MGVectors.GetCoordinate(line[0],1)
     else:
       return
     if conn:
        xyz = conn
        return [xyz.get_x(),xyz.get_y(),xyz.get_z()]

   def ClickedLineCoords(self):
     if self.line[0] < 0 or self.line[1] < 0: return
     coord = []
     for ll in range(0,2):
       conn = self.MGVectors.GetCoordinate(line[ll],ll+1)
       if conn:
         xyz = conn
         coord.append([xyz.get_x(),xyz.get_y(),xyz.get_z()])
     if len(coord)>1: return coord

   def AddLineLabel(self):
     self.AddLabel()

   def AddLabel(self,text_label=""):
     import mmut
     mode = self.MGVectors.DataMode()
     if [mmut.CONN_ATOM_ATOM,mmut.CONN_ATOM_POINT,mmut.CONN_ATOM_DISP].count(mode):
       if self.line[0] >= 0:
         at =self.MGVectors.GetAtom(self.line[0],1)
         if at: PICKLABEL().draw_atom_label( atm_ptr=at)
     if [mmut.CONN_ATOM_ATOM,mmut.CONN_POINT_ATOM].count(mode):
       if self.line[1] >= 0:
         at =self.MGVectors.GetAtom(self.line[1],2)
         if at: PICKLABEL().draw_atom_label( atm_ptr= at)
       
   def GetPrimitiveLabel(self,user_defined=0):
     import atom_util
     # return an identifier for the picked line
     return [str(self.line[0]),str(self.line[1])]
        
   def GetAtomLabel(self,atomPtr,user_defined=1):
     
    text_label =  self.ui.parent.molHnd.AtomLabel_atom1(atomPtr)
    return text_label


#=================================================================
#=================================================================
#=================================================================
#=================================================================

class VectorsData(dataobj.DataObj,QtCore.QObject):
  class_dependents = {}
  edit_atom = { 'start_atom':['',''],
                'end_atom' : ['',''] }

  initialise_vector = { 'end_d_xyz' : [1.0,1.0,1.0],
                        'start_xyz' : [0.0,0.0,0.0],
                        'end_xyz' : [1.0,1.0,1.0],
                        'start_atom' : '',
                        'end_atom' : '',
                        'start_mol' : None,
                        'end_mol' : None,
                        'tag' : -1,
                        'label' : '' }
 
#------------------------------------------------------------------
  def __init__(self,name='',filename=[],dataparams={},restore_from_version=0,**kw):
#------------------------------------------------------------------
    QtCore.QObject.__init__(self)
    if not filename and dataparams.has_key('filename'):
      filename=dataparams['filename']
    if not name and not filename : name = 'Vectors'
    #print 'VectorsData.init filename',filename
    dataobj.DataObj.__init__(self,'VectorsData',name=name,
         module='VectorsDispobj',filename=filename,dataparams=dataparams)
    self.update_dependents('create')
    self.MolData_id = []
    self.MolData = []
    self.MGVectors = ''
    self.taglist = []
    self.tagannote= []
    self.edited=0
    self.export_selection = '1'
    self.transform_mode = 1
    self.transform_vector = -1

    # transform mode determines if interactive translation
    # (mediateed by atom_picking class) is applied to
    # whole vector (1) start (2) or end (3) of vector

#----------------------------------------------------------------
  def getDataMode(self):
#----------------------------------------------------------------
    if not self.MGVectors:
      return ''
    else:
      mode = self.MGVectors.DataMode()
      if mode == mmut.CONN_ATOM_ATOM:
        return 'atoms'
      else:
        return 'points'
      
#----------------------------------------------------------------
  def setDataMode(self,mode):
#----------------------------------------------------------------
    if mode == 'atoms':
      self.MGVectors = mgapp.MGVectors(mmut.CONN_ATOM_ATOM,0,1)
    else:
      self.MGVectors = mgapp.MGVectors(mmut.CONN_POINT_POINT,0,1)
    #print 'setDataMode MGVectors',mode,self.MGVectors

#----------------------------------------------------------------
  def GetNofVectors(self):
#----------------------------------------------------------------
    return self.MGVectors.GetNofConnections()

#----------------------------------------------------------------
  def getVectorMenu(self,first=0,last=-1):
#----------------------------------------------------------------
    vector_list = []
    if not self.MGVectors: return []
    mode = self.MGVectors.DataMode()
    nV = self.MGVectors.GetNofConnections()
    if not nV: return []
    if last<0 or last>nV: last = nV
    for iV in range(first,last):
      if [mmut.CONN_ATOM_ATOM,mmut.CONN_ATOM_DISP,mmut.CONN_ATOM_POINT].count(mode):
        label = self.MGVectors.GetAtomID(iV,1) + '  '
      elif [mmut.CONN_POINT_POINT].count(mode):
        conn = self.MGVectors.GetCoordinate(iV,1)
        if conn:
          xyz = conn
          label = '%.1f  %.1f  %.1f  '%(xyz.get_x(),xyz.get_y(),xyz.get_z())
        else:
          label = '                     '
      if [mmut.CONN_ATOM_ATOM].count(mode):
        label = label+self.MGVectors.GetAtomID(iV,2) + '  '
      else:
        conn = self.MGVectors.GetCoordinate(iV,2)
        if conn:
          xyz = conn
          label = label + '%.1f  %.1f  %.1f  '%(xyz.get_x(),xyz.get_y(),xyz.get_z())
        else:
          label = label +  '                     '
      if self.taglist:
        iT = self.MGVectors.GetTag(iV)
        if iT>=0 and iT<len(self.taglist):            
          tag=(self.taglist[iT]+'      ')[0:6] + ' '
        else:
          tag = '       '
      else:
        tag = ''
      
      label = tag + label + self.MGVectors.GetLabel(iV)
      vector_list.append(label)
    #print 'getVectorMenu',vector_list

    return vector_list
                           
#----------------------------------------------------------------
  def getTagList(self):
#----------------------------------------------------------------
    ll = ['UNTAGGED']
    ll.extend(self.taglist)
    return ll
  
#----------------------------------------------------------------
  def delete ( self,**keywords):
#-----------------------------------------------------------------
    if self.edited: self.save_file(block=20)
    # Delete this object
    dataobj.DataObj.delete(self)
    del self
    
#------------------------------------------------------------------
  def save_file(self,vector_file='',export_selection=0,**keywords):
#------------------------------------------------------------------
      # User has given file name
      status,text = self.export_data(export_selection=export_selection)
      if not status:
        import utils
        utils.saveFile(vector_file,text=text,warning=1)
        self.filename =  utils.get_project(vector_file)
        self.edited = 0
    
#--------------------------------------------------------------------
  def loaddata(self,filename='',**keywords):
#--------------------------------------------------------------------
    import utils,pygl_coord
    import mmdb2 as mmdb
    import string
    if not filename: filename = self.filename[2]
    if not filename: return [1,'No vector file specified']
    CIF =  mmdb.Data()
    RC = CIF.ReadMMCIFData ( filename )
    #print 'VectorsDataobj.loaddata',filename,RC
    if RC:
      err = mmdb.GetErrorDescription(RC)
      print "Error reading vectors CIF",RC,err
      return [1,"Error reading file: "+err]

    # Read if any model files are required to be loaded   
    needs_file = []
    RC_ptr = pygl_coord.inta(1)
    Loop = CIF.GetLoop ( "_model" );
    if Loop:
      import os
      maxV =  Loop.GetLoopLength()
      row = 0
      while row < maxV:
        id = ''
        filename = ''
        id,RC_ptr = GetLoopString(Loop, "id",row)
        filename,RC_ptr =  GetLoopString(Loop, "filename",row)
        found_file = 0
        for mod in get_dataobj(object_type='MolData'):
          #print "mod",mod,mod.filename
          if (mod.filename[2] == filename or \
              utils.fileRoot(filename) ==  utils.fileRoot(mod.filename[2])) \
              and not self.MolData.count(mod):
            self.MolData.append(mod)
            self.MolData_id.append(id)
            found_file = 1
            break
        if not found_file: needs_file.append(filename)
        row = row + 1
      #print "VectorsData.loaddata filename",filename,self.MolData,needs_file
      del Loop

    Loop =  CIF.GetLoop ( "_tags" );
    if Loop:
      row = 0
      maxR =  Loop.GetLoopLength()
      while row < maxR:
        id,RC_ptr =  GetLoopString(Loop, "name",row)
        if not  RC_ptr:
          annote,RC_ptr = GetLoopString(Loop, "annotation",row)
          if not  RC_ptr:
            self.taglist.append(id)
            if annote:
              self.tagannote.append(annote)
            else:
              self.tagannote.append(' ')
        row = row+1 
    del Loop
    #print "taglist",self.taglist
    #print "tagannote",self.tagannote

    
    display_objects = []
    Loop =  CIF.GetLoop ( "_display_objects" );
    if Loop:
      row = 0
      maxR =  Loop.GetLoopLength()
      while row < maxR:
        pars = {}
        pars['selection'] = []
        for item in self.taglist: pars['selection'].append(item)
        data = {}
        data.update(VectorsDispobj.style_initialisation)
        font = {}
        sele,RC_ptr =  GetLoopString(Loop, "selection",row)
        if sele:
          pars['selection'] = string.split(string.strip(sele))
          for item0 in pars['selection']:
            item = string.strip(item0)
            if not item == 'all' and not self.taglist.count(item):
              #print "_display_objects appending",item 
              self.taglist.append(item)
              self.tagannote.append(item)
        if not pars['selection']:  pars['selection']='all'

        for item in [
          ['line_style','line_style_menu','line_style_alias'],
          ['label_mode','label_mode_menu','label_mode_alias'],
          ['cone_mode','cone_mode_menu','cone_mode_alias'],
          ['arrow_head','arrow_head_menu','arrow_head_alias'],
          ['dash_end','dash_end_menu','dash_end_alias']
          ]:
          inp,RC_ptr =  GetLoopString(Loop, item[0],row)
          if getattr(VectorsDispobj,item[1]).count(inp):
            ii = getattr(VectorsDispobj,item[1]).index(inp)
            data[item[0]] = getattr(VectorsDispobj,item[2])[ii]
        # load colour - test OK
        for item in ['line_colour','label_colour']:
          inp,RC_ptr =  GetLoopString(Loop, item,row)
          if MGCOLOUR().index(inp)>= 0: data[item] = inp

        # just load numerical
        for item in ['cylinder_radius','cone_radius',
           'cone_fraction','dash_length']:
          dat,RC_ptr =  GetLoopString(Loop, item,row)
          data[item] =  utils.safeFloat(dat,data[item])

        data['line_width'] =  utils.safeInt( GetLoopString(Loop,'line_width' ,row)[0],data['line_width'])

        font = {}
        for item in ['family','weight','size','slant','underline']:
          font[item],RC_ptr =  GetLoopString(Loop, "font_"+item,row)
        # As of Sep08 isValidFont just return true
        #if not FONTMANAGER().isValidFont(inp): font = FONTMANAGER().getFont('annotation')
        font = FONTMANAGER().getFont('annotation')


        pars['style'] = {}
        for item in ['line_style','line_colour','line_width',
             'cylinder_radius','arrow_head','cone_mode','cone_radius',
             'cone_fraction','dash_length','dash_end','label_mode','label_colour']:
          pars['style'][item]=data[item] 
        pars['font']= {}
        for item in ['family','weight','size','slant','underline']:
          pars['font'][item]=font.get(item)          
        display_objects.append(pars)
        row = row+1 
    del Loop

    
    Loop = CIF.GetLoop ( "_vector" );
    if not Loop: return [1,'No vectors defined in file']

    maxV =  Loop.GetLoopLength()
    #print 'Reading',maxV,'vectors from file',filename
    
    row = 0
    failed_interpretAtomID = 0
    xyz1 = pygl_coord.doublea(3)
    xyz2 = pygl_coord.doublea(3)
    while row < maxV:
      tagno = -1
      start_atom = ''
      start_xyz = []
      end_atom = ''
      end_xyz = []
      end_d_xyz = []
      label = ''

      # Get the vector tag
      tag,RC_ptr =  GetLoopString(Loop, "tag",row)
      if  RC_ptr or not tag:
        tagno = -1
      else:
        if not self.taglist.count(tag):
          self.taglist.append(tag)
          self.tagannote.append(tag)
        tagno = self.taglist.index(tag)

      # Get atoms - or if there are none the point or displacement
      start_atom,RC_ptr = GetLoopString(Loop, "start_atom",row)
      if  not RC_ptr:
        start_mol,RC_ptr =  GetLoopString(Loop, "start_model_id",row)
      else:
        rv,start_xyz = self.get_cif_xyz(Loop,row,'start_')
      end_atom,RC_ptr = GetLoopString(Loop, "end_atom",row)
      if  not RC_ptr:
        end_mol,RC_ptr= GetLoopString(Loop, "end_model_id",row)
      else:
        rv,end_xyz = self.get_cif_xyz(Loop,row,'end_')
        if rv: rv1,end_xyz =  self.get_cif_xyz(Loop,row,'end_d_')

      label,RC_ptr = GetLoopString(Loop, "label",row)
      if not label: label = ' '
      #print 'start',start_atom,start_xyz,'end',end_atom, \
       #  end_xyz,end_d_xyz,'label',label

      # On the first row sort out if we have appropriate molecule loaded 
      if row==0:
        #print "row0",start_atom,end_atom
        if (start_atom or end_atom) and ((not self.MolData) or needs_file ):
          # There is a named molecule file so report to user
          if needs_file:
            return [1, 'Can not draw vectors from file '+\
                'because the molecule file '+needs_file[0]+' is not loaded']
          else:
            return [1,'Can not draw vectors from file '+\
               'because no molecule file is not specified']
 
        # Do we need to instantiate MGVectors - sort
        # out the data_mode and tagged
        if start_atom:
          if end_atom:
            data_mode = mmut.CONN_ATOM_ATOM
          elif end_xyz:
            data_mode = mmut.CONN_ATOM_POINT
          elif end_d_xyz:
            data_mode = mmut.CONN_ATOM_DISP
        elif start_xyz:
          if end_xyz:
            data_mode = mmut.CONN_POINT_POINT
          elif end_d_xyz:
            data_mode = mmut.CONN_POINT_DISP
          elif end_atom:
           data_mode = mmut.CONN_POINT_ATOM
        else:
          return [1,'Vector data does not have reasonable start and end atom or point']
        tagged = 1
        if self.MGVectors: del self.MGVectors
        self.MGVectors = mgapp.MGVectors(data_mode,0,tagged)

      #print 'vectors.loaddata data_mode',data_mode

      # Add the new vector to MGVectors object
      if data_mode == mmut.CONN_ATOM_ATOM:
        pAtom1 = self.interpretAtomID(start_atom,mol=start_mol)
        pAtom2 = self.interpretAtomID(end_atom,mol=end_mol)
        #print "vectors.loaddata pAtom1,pAtom2",pAtom1,pAtom2,'*',label,'*',tagno
        if pAtom1 and pAtom2:
          self.MGVectors.AddConnection(pAtom1,pAtom2,label,tagno)
        else:
          failed_interpretAtomID= failed_interpretAtomID+1
      elif data_mode == mmut.CONN_POINT_POINT or data_mode == mmut.CONN_POINT_DISP:
        for i in range(0,3): xyz1[i]=float(start_xyz[i])
        for i in range(0,3): xyz2[i]=float(end_xyz[i])
        self.MGVectors.AddConnection( xyz1,xyz2,label,tagno)
      elif data_mode == mmut.CONN_ATOM_POINT or data_mode == mmut.CONN_ATOM_DISP:
        pAtom1 = self.interpretAtomID(start_atom,mol=start_mol)
        if pAtom1:
          for i in range(0,3): xyz2[i]=float(end_xyz[i])
          self.MGVectors.AddConnection( pAtom1,xyz2,label,tagno)
        else:
          failed_interpretAtomID= failed_interpretAtomID+1
      elif data_mode == mmut.CONN_POINT_ATOM:
        pAtom2 = self.interpretAtomID(end_atom,mol=end_mol)
        if pAtom2:
          for i in range(0,3): xyz1[i]=float(start_xyz[i])
          #print "AddConnection",pAtom2,xyz1,label,tagno
          self.MGVectors.AddConnection(pAtom2,xyz1,label,tagno)
        else:
          failed_interpretAtomID= failed_interpretAtomID+1
      
      row=row + 1

    #print 'vectors.loaddata row',row
    
    # Set edited false - file and internal data currently in sync
    self.edited = 0
    
    # Add dependency on MolData
    self.make_dependencies()
    
    #print "failed_interpretAtomID",failed_interpretAtomID
    return [0,'',display_objects]


#-----------------------------------------------------------------------
  def make_dependencies(self,mol=''):
#-----------------------------------------------------------------------
    if mol:
      self.add_dependency(mol,['delete','transform','reconfigure','edit'], \
        [self.handle_dependency,self.handle_dependency, \
         self.handle_dependency,self.handle_dependency])
    else:
      for mol in self.MolData:
        self.add_dependency(mol,['delete','transform','reconfigure','edit'], \
        [self.handle_dependency,self.handle_dependency, \
         self.handle_dependency,self.handle_dependency])

#-------------------------------------------------------------
  def handle_dependency(self,master='',attribute='',**keywords):
#-------------------------------------------------------------
    moldata_names = []
    for item in  self.MolData: moldata_names.append(item.name)
    if attribute == 'delete' and moldata_names.count(master):
      self.delete()
    else:
      self.MGVectors.UpdateCoordinates()
      for obj in self.objinsts:
        obj.do_redraw = 1
#-------------------------------------------------------------------
  def interpretAtomID(self,atomid,mol=''):
#-------------------------------------------------------------------
    if mol and self.MolData_id.count(mol):
      ii =  self.MolData_id.index(mol)
    else:
      ii = 0
    return  self.MolData[ii].interpretAtomID(self.MolData[ii],atomid)
 
#-----------------------------------------------------------------
  def export_data(self,filename='',export_selection=0,comments=[]):
#-----------------------------------------------------------------
    import time
    
    nV=self.MGVectors.GetNofConnections()
    mode = self.MGVectors.DataMode()

    # Create the vectors loop first to find out, at the same time,
    # which MolData are referenced
    
    text='loop_\n'
    if self.taglist: text=text+'_vector.tag\n'
    if [mmut.CONN_ATOM_ATOM,mmut.CONN_ATOM_POINT,mmut.CONN_ATOM_DISP].count(mode):
       text=text+'''_vector.start_model_id
_vector.start_atom\n'''
    else:
       text=text+'''_vector.start_x
_vector.start_y
_vector.start_z\n'''
       
    if [mmut.CONN_ATOM_ATOM,mmut.CONN_POINT_ATOM].count(mode):
      text=text+'''_vector.end_model_id
_vector.end_atom\n'''
    elif [ mmut.CONN_POINT_POINT,mmut.CONN_ATOM_POINT].count(mode):
       text=text+'''_vector.end_x
_vector.end_y
_vector.end_z\n'''
    else:
       text=text+'''_vector.end_d_x
_vector.end_d_y
_vector.end_d_z\n'''

    text=text+'_vector.label\n'

    for iV in range(0,nV):
      vector = self.get_vector_data(iV)
      if not vector: break
      if self.taglist:
        if vector['tag']>=0 and vector['tag']<len(self.taglist) and \
                                      self.taglist[vector['tag']]:
          text=text+'"'+self.taglist[vector['tag']]+'" '
        else:
          text=text+'. '
      if [mmut.CONN_ATOM_ATOM,mmut.CONN_ATOM_POINT,mmut.CONN_ATOM_DISP].count(mode):
        if vector['start_mol']:
          model_id = vector['start_mol'].name
          atomid = vector['start_atom']
        else:
          model_id = '.'
          atomid = '.'
        text=text+'"'+model_id+'"  "'+atomid+'" '
      else:
        text=text+str(vector['start_xyz'][0])+' '+str(vector['start_xyz'][1]) \
            +' '+str(vector['start_xyz'][2])+' '
       
      if [mmut.CONN_ATOM_ATOM,mmut.CONN_POINT_ATOM].count(mode):
        if vector['end_mol']:
          model_id = vector['end_mol'].name
          atomid = vector['end_atom']
        else:
          model_id = '.'
          atomid ='.'
        text=text+'"'+model_id+'"  "'+atomid+'"  '
      elif [ mmut.CONN_POINT_POINT,mmut.CONN_ATOM_POINT].count(mode):
        text=text+str(vector['end_xyz'][0])+' '+str(vector['end_xyz'][1])+' '+\
               str(vector['end_xyz'][2])+' '
      else:
        text=text+str(vector['end_d_xyz'][0])+' '+str(vector['end_d_xyz'][1])\
            +' '+str(vector['end_d_xyz'][2])+' '

      text=text+'"'+vector['label']+'" \n'

    #print "text",text


    # Create header
    head = '#Definition of vectors for display with CCP4mg\n'+ \
           '#Created on '+time.asctime(time.localtime(time.time()))+"\n"

    head = head+'\ndata_VECTORS\n'
    
    for item in comments:
      head = head+"# "+item+"\n"
    head = head+"\n\n"
    
    if self.MolData:
      head = head+'''loop_
_model.id
_model.filename\n'''
      for item in self.MolData:
        head = head+'"'+item.name+'"  "'+item.filename[2]+'"\n'
      head = head+"\n\n"

    if self.taglist:
      head=head+'''loop_
_tags.name
_tags.annotation\n'''
      for i in range(0,len(self.taglist)):
         if self.taglist[i]:
           head=head+'"'+self.taglist[i]+'"  "'+self.tagannote[i]+'"\n'
      head = head+"\n\n"

    if export_selection and len(self.objinsts)>0:
      head=head+'loop_\n'
      if self.taglist: head = head + "_display_objects.selection\n"
      head = head + '''_display_objects.line_style
_display_objects.line_colour
_display_objects.line_width
_display_objects.cylinder_radius
_display_objects.arrow_head
_display_objects.cone_mode
_display_objects.cone_radius
_display_objects.cone_fraction
_display_objects.dash_length
_display_objects.dash_end
_display_objects.label_mode
_display_objects.label_colour
_display_objects.font_family
_display_objects.font_size
_display_objects.font_weight
_display_objects.font_slant
_display_objects.font_underline\n'''
      for obj in self.objinsts:
        if self.taglist:
          selected_tags = ''
          if obj.selection == 'all':
            selected_tags ='all'
          else:
            for item in obj.selection:
              selected_tags =selected_tags + item + ' '
          head = head+'"'+ selected_tags +'" '
        head = head+ '"' + \
               obj.style['line_style']+'" "' + \
               str(obj.style['line_colour'])+'" "'+ \
               str(obj.style['line_width'])+ '" "'+ \
               str(obj.style['cylinder_radius'])+ '" "'+ \
               obj.style['arrow_head'] + '" "'+ \
               obj.style['cone_mode'] + '" "'+ \
               str(obj.style['cone_radius'])+ '" "'+ \
               str(obj.style['cone_fraction'])+ '" "'+ \
               str(obj.style['dash_length'])+ '" "'+ \
               obj.style['dash_end'] + '" "'+ \
               label_mode+'" "'+str(obj.style['label_colour'])+\
               '" "'+obj.font['family']+'" "'+str(obj.font['size'])+\
               '" "'+obj.font['weight']+'" "'+obj.font['slant']+'" "'+obj.font['underline']+'"\n'
               
      head = head+"\n\n"

    #print "head",head
    return [0,head+text]
    
#-----------------------------------------------------------------
  def get_cif_xyz(self,loop='',row=0,prepend=''):
#-----------------------------------------------------------------
    import utils
    x = ''
    y = ''
    z = ''
    xx,RC_ptr = GetLoopString(loop, prepend+'x',row)
    if RC_ptr: return [1,[]]
    yy,RC_ptr = GetLoopString(loop, prepend+'y',row)
    if RC_ptr: return [1,[]]
    zz,RC_ptr = GetLoopString(loop, prepend+'z',row)
    if RC_ptr: return [1,[]]
    return [0,[utils.safeFloat(xx),utils.safeFloat(yy),utils.safeFloat(zz)]]
 

#-----------------------------------------------------------------
  def add_object(self,params={},**keywords):
#-----------------------------------------------------------------
     dobj = VectorsDispobj(self.name,visible=1,params=params)
     return dobj


#-----------------------------------------------------------------
  def get_tag(self,index):
#-----------------------------------------------------------------
    if index>=0 and index< len(self.taglist):
      
      return (str(self.taglist[index]),str(self.tagannote[index]))
    else:
      return ('','')

#-----------------------------------------------------------------
  def edit_tag(self,index,name='',annotation='',**keywords):
#------------------------------------------------------------------
    import utils
    update = 0
    oldtag = ''
    if index<0:
      self.taglist.append(name)
      self.tagannote.append(annotation)
      return
    elif index<len(self.taglist):
      if name!= self.taglist[index]: oldtag = self.taglist[index]
      self.taglist[index] = name
      self.tagannote[index] = annotation
    else:
      return

    # tag name changed - may need to opdate display object selections
    if oldtag:
      for obj in self.objinsts:
        if obj.selection.count(oldtag):
          ii = obj.selection.index(oldtag)
          obj.selection.pop(ii)
          obj.selection.insert(ii,self.taglist[index])
          update = 1


    # Update the display and any open edit_vector gui
    if update:
      for obj in self.objinsts: obj.do_redraw=1

#------------------------------------------------------------------
  def delete_tag(self,index):
#------------------------------------------------------------------
    if index<0 or index> len(self.taglist): return
    update = 0
    oldtag = self.taglist[index]
    self.taglist.pop(index)
    self.tagannote.pop(index)
    
    nV=self.MGVectors.GetNofConnections()
    for iV in range(nV):
      tag = self.MGVectors.GetTag(iV)
      if tag == index:
        self.MGVectors.SetTag(iV,-1)
        update = 1
      if tag > index:
        self.MGVectors.SetTag(iV,index-1)
        update = 1

    # Test if we have removed any tags which are currently in
    # the self.selection list
    for obj in self.objinsts:
      if obj.selection != 'all' and obj.selection.count(oldtag):
        obj.selection.remove(oldtag)
        update = 1
        
    if update:
      for obj in self.objinsts: obj.do_redraw=1

#------------------------------------------------------------------
  def get_vector_data(self,iV):
#------------------------------------------------------------------
    import mmut
    vector = {}
    vector.update(VectorsData.initialise_vector)   

    if iV >=0:
      # modes are defined in mmut_connectivity.h
      mode = self.MGVectors.DataMode()
      #print "define_edit_vector mode",mode

      # Get data for this vector
      vector['label'] = self.MGVectors.GetLabel(iV)
      vector['tag'] = self.MGVectors.GetTag(iV)
      #print "get_vector_data", vector['tag']
      if [mmut.CONN_POINT_ATOM].count(mode):
        vector['start_atom'] = None
        end_atom = self.MGVectors.GetAtom(iV,1)
        if end_atom:
          theAddr= mmut.GetMMANManagerAddress(end_atom)
          for m in get_dataobj(object_type='MolData'):
            if m.molHnd.GetAddress() == theAddr:
              vector['end_mol'] = m
              break
          vector['end_atom'] = self.MGVectors.GetAtomID(iV,1)
      else:
        start_atom = self.MGVectors.GetAtom(iV,1)
        #print 'VectorData.get_vector_data start_atom',start_atom
        if start_atom :
           theAddr= mmut.GetMMANManagerAddress(start_atom)
           for m in get_dataobj(object_type='MolData'):
             if m.molHnd.GetAddress() == theAddr:
               vector['start_mol'] = m
               break
           vector['start_atom'] = self.MGVectors.GetAtomID(iV,1)
        end_atom = self.MGVectors.GetAtom(iV,2)
        if end_atom :
          theAddr= mmut.GetMMANManagerAddress(end_atom)
          for m in get_dataobj(object_type='MolData'):
            if m.molHnd.GetAddress() == theAddr:
              vector['end_mol'] = m
              break
          vector['end_atom'] = self.MGVectors.GetAtomID(iV,2)

      #print "get_vector_data",vector['start_atom'],vector['end_atom']
      conn = self.MGVectors.GetCoordinate(iV,1)
      if conn:
        xyz = conn
        vector['start_xyz'] = [xyz.get_x(),xyz.get_y(),xyz.get_z()]
      conn = self.MGVectors.GetCoordinate(iV,2)
      if conn:
        xyz = conn
        vector['end_xyz'] = [xyz.get_x(),xyz.get_y(),xyz.get_z()]
      conn = self.MGVectors.GetCoordinate(iV,3)
      if conn:
        xyz = conn
        vector['end_d_xyz'] = [xyz.get_x(),xyz.get_y(),xyz.get_z()]

    #print "VectorData.get_vector_data",vector['start_atom'],vector['end_atom'],vector
    return vector

#-----------------------------------------------------------------------
  def set_vector_data ( self,iV=-1, vector = {},data_mode=-1 ):
#-----------------------------------------------------------------------
    import types,string
    import pygl_coord
    xyz1 = pygl_coord.doublea(3)
    xyz2 = pygl_coord.doublea(3)

    if data_mode<0: data_mode=self.MGVectors.DataMode()

    # Ensure that the tag is either -1 (==untagged) or an index to
    # the taglist
    if not vector.has_key('tag') or not vector['tag']: vector['tag'] = -1
    tag = vector['tag']
    if isinstance(tag,types.StringType):
      tag = string.strip(tag)
      if len(tag)>0:
        if self.taglist.count(tag):
          vector['tag'] = self.taglist.index(tag)
        else:
          self.taglist.append(tag)
          self.tagannote.append('')
          vector['tag'] = len(self.taglist)-1

      

    if vector['start_atom'] and isinstance(vector['start_atom'],types.StringType):
      pAtom = start_md.interpretAtomID(start_md,vector['start_atom'])

    #print "set_vector_data vector",data_mode,mmut.CONN_ATOM_ATOM,vector
    if data_mode == mmut.CONN_ATOM_ATOM:
     if vector['start_atom'] and vector['end_atom']:
       if ( iV < 0):
         self.MGVectors.AddConnection( \
           vector['start_atom'],vector['end_atom'],vector['label'],vector['tag'])
       else:
         self.MGVectors.InsertConnection(True,iV,\
           vector['start_atom'],vector['end_atom'],vector['label'],vector['tag'])
     else:
       return -1
    elif [mmut.CONN_POINT_POINT,mmut.CONN_POINT_DISP].count(data_mode):
      for i in range(0,3): xyz1[i]=float(vector['start_xyz'][i])
      for i in range(0,3): xyz2[i]=float(vector['end_xyz'][i])
      if (iV < 0 ):
        self.MGVectors.AddConnection( \
          xyz1,xyz2,vector['label'],vector['tag'])
      else:
        self.MGVectors.InsertConnection(True,iV, \
          xyz1,xyz2,vector['label'],vector['tag'])
    elif [mmut.CONN_ATOM_POINT,mmut.CONN_ATOM_DISP].count(data_mode):
      if vector['start_atom']:
        for i in range(0,3):xyz2[i]=float(vector['end_xyz'][i])
        if ( iV < 0 ):
          self.MGVectors.AddConnection( \
            vector['start_atom'],xyz2,vector['label'],vector['tag'])
        else:
          self.MGVectors.InsertConnection(True,iV, \
            vector['start_atom'],xyz2,vector['label'],vector['tag'])
      else:
        return -1
    elif data_mode == mmut.CONN_POINT_ATOM:
      if vector['end_atom']:
        for i in range(0,3): xyz1[i]=float(vector['start_xyz'][i])
        if (iV < 0):
          self.MGVectors.AddConnection( \
            vector['end_atom'],xyz1,vector['label'],vector['tag'])
        else:
          self.MGVectors.InsertConnection(True,iV, \
            vector['end_atom'],xyz1,vector['label'],vector['tag'])
      else:
        return -1

    # Set flag that data changed c.f. file 
    self.edited = 1

    for item in ['start_mol','end_mol']:
      if vector.get(item,None) and not self.MolData.count(vector[item]):
        self.MolData.append(vector[item])
        self.make_dependencies(vector[item])

    self.edited = self.edited + 1
    self.set_do_redraw()

    if iV>=0:
      return iV
    else:
      # Have created a vector - return it's id
      return self.MGVectors.GetNofConnections()-1

#---------------------------------------------------------------
  def set_do_redraw(self):
#---------------------------------------------------------------
    for obj in self.objinsts:
      obj.do_redraw = 1

  def setTransformVector(self,iV):
    self.transform_vector = iV

  def getTransformMode(self):
    return self.transform_mode

  def setTransformMode(self,mode):
    self.transform_mode = mode
    
#---------------------------------------------------------------
  def transform(self,glwidget):
#---------------------------------------------------------------
    '''
    Method invoked from atom_picking class handling movement
    of objects on the screen
    '''
    #print 'VectorsData.transform',self.transform_mode,self.transform_vector
    if self.transform_mode<=0 or self.transform_vector<0:return
    import utils

    dx,dy,dz = glwidget.worldTranslate()
    vector = self.get_vector_data(self.transform_vector)
    
    if [1,2].count(self.transform_mode):
          start_xyz = \
                [ utils.round(dx+vector['start_xyz'][0]),
                  utils.round(dy+vector['start_xyz'][1]),
                  utils.round(dz+vector['start_xyz'][2]) ]
          vector['start_xyz'] = start_xyz
    if [1,3].count(self.transform_mode):
          end_xyz = \
                [ utils.round(dx+vector['end_xyz'][0]),
                  utils.round(dy+vector['end_xyz'][1]),
                  utils.round(dz+vector['end_xyz'][2]) ]
          vector['end_xyz'] = end_xyz
    #print "transform calling set_vector_data",vector
    self.set_vector_data ( iV=self.transform_vector,vector = vector)
    self.emit(QtCore.SIGNAL('DataChanged'),(vector['start_xyz'],vector['end_xyz']))

    self.set_do_redraw()
     
    
#-------------------------------------------------------------
  def delete_vector (self, iV ):
#-------------------------------------------------------------
    # Delete the iV 'th vector
    if iV<0 or iV>= self.MGVectors.GetNofConnections(): return
    # Delete from MGVectors
    self.MGVectors.DeleteConnection(iV)
    self.edited = 1
    # Force redraw of all display objects
    for obj in self.objinsts:
      obj.do_redraw = 1

    '''
    # Remove this vector from the last picked list?
    last_picked = []
    for item in VectorsDispobj.last_picked_edge:
      if item[2]>iV:
        last_picked.append([item[0],item[1],item[2]-1])
      elif item[2] < iV:
        last_picked.append(item)
    VectorsDispobj.last_picked_edge=last_picked
    '''
        
#----------------------------------------------------------------
  def centre( self,**keywords):
#----------------------------------------------------------------
    if not self.MGVectors or not self.MGVectors.GetNofConnections(): return []
    import pygl_coord
    # This does not work because Extent returns p_realtype and doublea wants p_double
    extentptr = self.MGVectors.Extent()
    print 'VectorsDispobj.centre',extentptr
    print 'VectorsDispobj.centre',extentptr[0]
    tmp = pygl_coord.doublea(6)
    extent = tmp.frompointer(extentptr)
    com = []
    com.append(( extent[0] + extent[3] ) / 2.0)
    com.append(( extent[1] + extent[4] ) / 2.0)
    com.append(( extent[2] + extent[5] ) / 2.0)
    #print 'VectorDataobj.centre',com
    return com

#-------------------------------------------------------------------------
  def clone(self,**keywords):
#-------------------------------------------------------------------------
    import os
    if not os.path.exists(self.filename[2]) \
          or not os.path.isfile(self.filename[2]):
      MGGUI().WarningMessage('File no longer exists '+self.filename[2])
      return None
    
    m = VectorsData(filename=self.filename,dataparams=self.dataparams())
    rv = m.loaddata()
    if rv[0]==1:
      MGGUI().WarningMessage("ERROR loading data from file "+self.filename[2])
      m.delete()
      return None
    return m


#=============================================================== 
#=============================================================== 
#=============================================================== 
class VectorsDispobj(dataobj.DispObj):
#=============================================================== 
#=============================================================== 
#=============================================================== 

  class_dependents = {}
  edit_make_vector = None
  edge_popup = {
    'edit':['VectorsDispobj','VectorsDispobj.define_vector_popup_menu'] }
  last_picked_edge = []
  last_picked_vertex = []
  line_width = 2
  line_style_menu = ['no line','solid','dashed','arrow','dashed arrow','cylinder','cylinder arrow','dashed cylinder','dashed cylinder arrow','cone']
  line_style_alias = [cprim.NOLINE,cprim.LINE, cprim.DASHLINE, cprim.ARROW,cprim.DASHARROW, cprim.CYLINDER, cprim.CYLINDERARROW, cprim.DASHCYLINDER, cprim.DASHCYLINDERARROW, cprim.CONE]
  arrow_head_menu = ['start','end','both']
  arrow_head_alias = [mgapp.ARROW_HEAD_START,mgapp.ARROW_HEAD_END,mgapp.ARROW_HEAD_BOTH]
  dash_end_menu = ['dash','gap']
  dash_end_alias = [0,1]
  
  cone_mode_menu = ['fixed','fraction']
  cone_mode_alias = [ mgapp.CONE_RADIUS_FIXED,mgapp.CONE_RADIUS_FRACTION ]
  label_mode_menu = ['no label','label centre','label start','label end']
  label_mode_alias = [cprim.NOTLABELLED, cprim.LABELLEDCENTRE,
                      cprim.LABELLEDSTART,cprim.LABELLEDEND]
  
  style_initialisation = {
    'line_style' : 'dashed',
    'line_colour' : 'complement',
    'line_width' : 1,
    'cylinder_radius' : 0.2,
    'arrow_head' : 'end',
    'cone_mode' : 'fixed',
    'cone_radius' : 0.4,
    'cone_fraction' : 0.3,
    'dash_length' : 0.5,
    'dash_end' : 'gap',
    'label_mode' : 'label start',
    'label_colour' : 'complement' }
  style_initialisation_order = ['line_style','line_colour','line_width',
    'cylinder_radius','arrow_head','cone_mode','cone_radius','cone_fraction',
    'dash_length','dash_end','label_mode','label_colour']

#---------------------------------------------------------------------
  def __init__(self,parent='',visible=1,name='',
               selection='all',colour='',style='', 
               params={},display_table_visible=1,restore_from_version=0,**keywords):
#--------------------------------------------------------------------- 
    import types

    #print 'VectorDispObj.init',selection,colour,style,'params',params
    self.selection=selection
    self.style = {}
    self.style.update(VectorsDispobj.style_initialisation)
    self.font = {}
    self.font.update(FONTMANAGER().getFont('annotation'))
    self.scaling_mode = mgapp.NO_SCALING
    self.scale = 1.0
    
    if params.has_key('selection'):
      selection = params['selection']
      del params['selection']
      
    if params.has_key('line_parameters'):
      self.style.update(params['line_parameters'])
      del params['line_parameters']
    if params.has_key('label_parameters'):
      self.style.update(params['label_parameters'])
      del params['label_parameters']
    # Handle pre-2.0 status with 'colour' and 'style' dicts in params
    for item in ['colour','style']:
      if params.has_key(item):
        if isinstance(params[item],types.ListType):
          # Deal with old data structure
          if item == 'colour':
            order = ['line_style','line_colour','line_width',
              'cylinder_radius','arrow_head','cone_mode','cone_radius','cone_fraction',
              'dash_length','dash_end']
          elif item == 'style':
            order = ['label_mode','label_colour']
          else:
            params[item] = []
          for n in range (0,len(params[item])):
              self.style[order[n]] = params[item][n]            
        else:
          try:
            self.style.update(params[item])
            del params[item]
          except:
            print "Error restoring vector ",item
    # This should deal with 2.0 style data
    self.style.update(params)
    self.validate_style()
            
    
    dataobj.DispObj.__init__(self,'VectorsDispobj',name,parent= parent,
          visible=visible,params=params,display_table_visible=display_table_visible )

    # Put in self.label_graphmod object since it may include text which must
    # be drawn in unthreaded mode

    self.label_graphmod = Vectorsgraphicsmodel()
    self.label_graphmod.MGVectors = self.parent.MGVectors
    BUILD().append(self.label_graphmod)
    self.label_graphmod.obj.SetAlpha(self.opacity)
    
    self.set_selection(selection)
   # update params based on input params

    self.style_label = self.style['line_colour']+' '+self.style['line_style']
    self.set_visibility(visibility=self.visible)

    self.update_dependents('create')
    self.do_redraw = 1

#--------------------------------------------------------------------
  def validate_style(self):
#--------------------------------------------------------------------
    # ensure imported data is in correct format for v2.0
    if VectorsDispobj.label_mode_alias.count(self.style['label_mode']):
      self.style['label_mode'] = VectorsDispobj.label_mode_menu[VectorsDispobj.label_mode_alias.index(self.style['label_mode'])]

    if VectorsDispobj.line_style_alias.count(self.style['line_style']):
      self.style['line_style'] = VectorsDispobj.line_style_menu[VectorsDispobj.line_style_alias.index(self.style['line_style'])]

    if VectorsDispobj.arrow_head_alias.count(self.style['arrow_head']):
      self.style['arrow_head'] = VectorsDispobj.arrow_head_menu[VectorsDispobj.arrow_head_alias.index(self.style['arrow_head'])]
      
    if VectorsDispobj.cone_mode_alias.count(self.style['cone_mode']):
      self.style['cone_mode'] = VectorsDispobj.cone_mode_menu[VectorsDispobj.cone_mode_alias.index(self.style['cone_mode'])]
      
    if VectorsDispobj.dash_end_alias.count(self.style['dash_end']):
      self.style['dash_end'] = VectorsDispobj.dash_end_menu[VectorsDispobj.dash_end_alias.index(self.style['dash_end'])]

    for item in ['cylinder_radius','cone_radius','cone_fraction','dash_length']:
      self.style[item] = float(self.style[item])

#--------------------------------------------------------------------
  def canBeTransparent(self):
#--------------------------------------------------------------------
    return 1
      
#--------------------------------------------------------------------
  def set_selection(self,selection='all',**keywords):
#--------------------------------------------------------------------
    #print 'VectorsDispObj.set_selection',selection
    if selection != self.selection:  self.do_redraw = 1
    self.selection = selection
    
    if not self.selection:
      self.selection_label = 'None'
    elif self.selection == 'all':
      self.selection_label = 'All'
    else:
      self.selection_label = ''
      for item in self.selection:
        if item == 'UNTAGGED' or self.parent.taglist.count(item):
          self.selection_label =  self.selection_label + item + ' '
        else:
          self.selection.remove(item)
    #print 'VectorsDispobj.set_selection',self.selection,self.selection_label

#---------------------------------------------------------------------
  def set_style(self,params):
#---------------------------------------------------------------------
    for key,value in params.items():
      if self.style.has_key(key):
        if self.style[key] != value:
          self.style[key] = value
          self.do_redraw = 1
    #print 'VectorDispObj.set_style',self.style
    self.style_label = self.style['line_colour']+' '+self.style['line_style']


    
#-------------------------------------------------------------------
  def scale_vectors(self,scale={},scaling_mode='',**keywords):
#-------------------------------------------------------------------

    if scaling_mode:
      if scaling_mode != self.scaling_mode:
        self.scaling_mode=scaling_mode
        self.do_redraw = 1
    if scale:
      self.scale = scale
      self.do_redraw = 1
      

#------------------------------------------------------------------
  def params(self,all=1):
#------------------------------------------------------------------
    pars = dataobj.DispObj.params(self,all=all)
    pars.update(self.style)
    for item in ['font']:
      fonts = getattr(self,item)
      fonts_new = {}
      for k,v in fonts.items():
        if hasattr(v,"toUtf8") and callable(v.toUtf8):
          v =  str(v.toUtf8())
        fonts_new[k] = v
      pars[item]=fonts_new
    if all or self.scaling_mode != mgapp.NO_SCALING:
      for item in ['scale','scaling_mode']:
        pars[item]=getattr(self,item)
    pars['selection'] = self.selection
    return pars

#------------------------------------------------------------------
  def update_data_status(self,shadowdisp):
#------------------------------------------------------------------
    import utils
    rv = 0
    diffs = utils.dict_diffs(self.params(),shadowdisp.params)[1]
    if diffs: rv = 1
    for key in diffs.keys():
      if key == 'font':
        self.set_font(font = shadowdisp.params['font'])
      elif key == 'scale':
        self.scale_vectors(scale = shadowdisp.params['scale'])
      elif key == 'scaling_mode':
        self.scale_vectors(scaling_mode= shadowdisp.params['scaling_mode'])
        
    rv = max(rv,dataobj.DispObj.update_data_status0(self,shadowdisp))
    if rv:
      return [[self.name,'DispObj','update']]
    else:
      return []

#-----------------------------------------------------------------
  def set_font(self,params={}):
#-----------------------------------------------------------------
    #print 'VectorDispobj.set_font',params
    self.font.update(params)
    self.do_redraw = 1
    
#------------------------------------------------------------------
  def unthreadedDraw (self ):
#------------------------------------------------------------------
    #print "VectorsDispobj draw ", self.do_redraw, self.visible, self.selection
    if not self.do_redraw or not self.visible or not self.parent.MGVectors:
      if self.do_update_opacity:
         self.label_graphmod.obj.SetAlpha(self.opacity)
         self.do_rebuildGL.append('label_graphmod')
         self.do_update_opacity = 0
         return 1
      else:
         return 0

    import cprim,utils
    import pygl_coord 
    col = MGCOLOUR().RGB(self.style['line_colour'])
    colv = pygl_coord.DoubleVector(col)
    #print "draw colv",colv
    
    # If the vector data is tagged then apply selection in Draw
    selTags = []
    scaleFactors = []
    if self.selection == 'all':
      apply_sel = 0
    else:
      apply_sel = 1
      if self.selection:
        for item in self.selection:
          if self.parent.taglist.count(item):
            selTags.append(self.parent.taglist.index(item))
          elif item == 'UNTAGGED':
            selTags.append(-1)
    selTagsv = pygl_coord.IntVector(selTags)
    #print 'VectorsDispobj.draw',self.parent.taglist,self.selection,selTags
            
    if self.scaling_mode == mgapp.SCALE_ALL:
      if not self.scale.has_key('UNTAGGED'):self.scale['UNTAGGED']=1.0
      scaleFactors.append(self.scale['UNTAGGED'])
    elif  self.scaling_mode == mgapp.SCALE_BY_TAGS:
      for item in self.parent.taglist:
        if not self.scale.has_key(item):self.scale[item]=1.0
        scaleFactors.append(self.scale[item])       
    scaleFactorsv =  pygl_coord.DoubleVector(scaleFactors)    
    #print "scaleFactors", self.scaling_mode,scaleFactors
      
    self.label_graphmod.MGVectors = self.parent.MGVectors
    if not FONTMANAGER().isValidFont(self.font):
      self.font = FONTMANAGER().getFont('annotation')
    #print 'VectorsDispobj.draw font',self.font
    self.parent.MGVectors.SetFont(str(self.font['family']),str(self.font['weight']),
         str(self.font['slant']),str(self.font['size']))
    
    if VectorsDispobj.label_mode_menu.count(self.style['label_mode']):
      label_mode = VectorsDispobj.label_mode_alias[VectorsDispobj.label_mode_menu.index(self.style['label_mode'])]
    else:
      label_mode = self.style['label_mode']

    if VectorsDispobj.line_style_menu.count(self.style['line_style']):
      line_style = VectorsDispobj.line_style_alias[VectorsDispobj.line_style_menu.index(self.style['line_style'])]
    else:
      line_style = self.style['line_style']
    if VectorsDispobj.arrow_head_menu.count(self.style['arrow_head']):
      arrow_head = VectorsDispobj.arrow_head_alias[VectorsDispobj.arrow_head_menu.index(self.style['arrow_head'])]
    else:
      arrow_head = self.style['arrow_head']
    if VectorsDispobj.cone_mode_menu.count(self.style['cone_mode']):
      cone_mode = VectorsDispobj.cone_mode_alias[VectorsDispobj.cone_mode_menu.index(self.style['cone_mode'])]
    else:
      cone_mode = self.style['cone_mode']
    if VectorsDispobj.dash_end_menu.count(self.style['dash_end']):
      dash_end = VectorsDispobj.dash_end_alias[VectorsDispobj.dash_end_menu.index(self.style['dash_end'])]
    else:
      dash_end = utils.safeInt(self.style['dash_end'],0)
 
    self.parent.MGVectors.SetLabel(label_mode,self.style['label_colour'])
    self.parent.MGVectors.SetVectorStyle(line_style)
    self.parent.MGVectors.SetLineWidth(self.style['line_width'])
    self.parent.MGVectors.SetCylinderRadius(self.style['cylinder_radius'])
    self.parent.MGVectors.SetArrowHead(arrow_head)
    self.parent.MGVectors.SetConeRadius(cone_mode,
              self.style['cone_radius'], self.style['cone_fraction'])
    self.parent.MGVectors.SetDashLength(self.style['dash_length'])
    self.parent.MGVectors.SetDashEnd(dash_end)
    self.parent.MGVectors.SetVectorColour(colv)

    #print 'to Draw',self.label_graphmod,self.graphmod.obj,selTagsv,apply_sel,scaleFactorsv,self.scaling_mode
    self.parent.MGVectors.Draw(self.label_graphmod.obj,selTagsv,bool(apply_sel),scaleFactorsv,self.scaling_mode)
    #print self.style['line_style']

    self.label_graphmod.obj.SetAnchored(False)
    self.label_graphmod.obj.SetUseVBO(False)
    self.label_graphmod.obj.SetUseVertexArrays(False)
    if not "cylinder" in self.style['line_style'] and not "cone" in self.style['line_style']:
      mainwin = MAINWINDOW()
      rpm = PM('render_quality')
      useVBOopt = rpm.get('use_vbo')
      if useVBOopt and hasattr(mainwin,"glWidget") and hasattr(mainwin.glWidget,"format") and callable(mainwin.glWidget.format):
         if hasattr(mainwin.glWidget.format(),"directRendering") and callable(mainwin.glWidget.format().directRendering):
            useVA = True
            if sys.platform == "win32" and not sys.argv.count('-quit'):
              import opengl
              gl_renderer = opengl.glGetString(opengl.GL_RENDERER)
              useVAopt = rpm.get('force_use_va')
              if not useVAopt:
                if "Intel" in gl_renderer:
                  print "Disabling use of VA on Windows with Intel GMA because of probable CCP4MG bug"
                  useVA = False
            if mainwin.glWidget.format().directRendering()==True:
               if useVA:
                 self.label_graphmod.obj.SetAnchored(True)
                 self.label_graphmod.obj.SetUseVBO(True)
                 self.label_graphmod.obj.SetUseVertexArrays(True)
    
    #self.label_graphmod.rebuild()
    #print 'VectorsDispobj.draw font',self.font
    self.label_graphmod.obj.SetTextFont( str(self.font['family']), str(self.font['weight']), \
                                     str(self.font['slant']),int(self.font['size']),int(self.font['underline']))
    self.label_graphmod.obj.rebuild()
    self.label_graphmod.obj.SetAlpha(self.opacity)
    self.do_rebuildGL.append('label_graphmod')
    
    self.do_redraw = 0
    return 1

#---------------------------------------------------------------------------
  def movie_interpolation(self,initial_status=None,final_status=None, \
                          fraction=0.0,step=''):
#---------------------------------------------------------------------------
    #print "Vectors movie_interpolation"
    if initial_status and final_status:
      import utils
      diffs = utils.dict_diffs(initial_status.params,final_status.params)[1]
      for item in diffs.keys():
        if item == 'scale':
          ini_scale = initial_status.params['scale']
          fin_scale = final_status.params['scale']
          self.scale = {}
          for item in ini_scale.keys():
            if fin_scale.has_key(item):
              self.scale[item] = ((1-fraction)*ini_scale[item])+(fraction*fin_scale[item])
            else:
              self.scale[item] = ini_scale[item]
          self.do_redraw = 1
        elif item == 'style':
          ini_col = initial_status.params['style']
          fin_col = final_status.params['style']
          self.set_style( 
                    line_width=((1-fraction)*ini_col['line_width'])+
                            (fraction*fin_col['line_width']), 
                    cylinder_radius=((1-fraction)*ini_col['cylinder_radius'])+
                            (fraction*fin_col['cylinder_radius']),
                    cone_radius=((1-fraction)*ini_col['cone_radius'])+
                            (fraction*fin_col['cone_radius']),
                    cone_fraction=((1-fraction)*ini_col['cone_fraction'])+
                            (fraction*fin_col['cone_fraction']), 
                    dash_length=((1-fraction)*ini_col['dash_length'])+
                            (fraction*fin_col['dash_length']))
       
      dataobj.DispObj.movie_interpolation(self,initial_status=initial_status,
          final_status=final_status,fraction= fraction,step=step)    


#====================================================================
#====================================================================
#====================================================================
#====================================================================

      
