"""
     python/ui/services.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.
"""
from global_definitions import *


class TempObjs:

  objinsts = []
  
  def __init__(self):
    self.objinsts.append(self)
    import graphicsmodel
    self.graphmod = graphicsmodel.graphicsmodel( )
    BUILD().append(self.graphmod)


  def delete(self):
    if  self.objinsts.count(self): self.objinsts.remove(self)
    BUILD().deletemod(self.graphmod)
    self.graphmod = ''


class MakeVector(TempObjs):

#-----------------------------------------------------------------------
  def __init__(self,display_style='',first_atom=''):
#-----------------------------------------------------------------------
    TempObjs.__init__(self)
    self.first_atom = first_atom
    self.display_style = display_style
    self.do_redraw = 1
    self.colour = 'red'

#------------------------------------------------------------------
  def delete(self,**keywords):
#------------------------------------------------------------------
    TempObjs.delete(self)

#------------------------------------------------------------------
  def draw (self ):
#------------------------------------------------------------------
    #print "MakeVector draw"
    if not self.do_redraw or not self.visible : return

    self.graphmod.obj.clear_prims()
    import cprim,pygl_coord
    col = MGCOLOUR().RGB(self.colour)
    colv = pygl_coord.DoubleVector.IntVector(col)
    #cprim.DrawSimpleConnection(self.graphmod.obj, \
    #           ,something_ere,  colv)
    self.graphmod.obj.rebuild()
    self.do_redraw = 0



#---------------------------------------------------------------------
#---------------------------------------------------------------------
#---------------------------------------------------------------------
class ParamsManager:
#---------------------------------------------------------------------
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# class to manage the parameters for algorithms such as hydrogen bond 
# calculation

  insts = []

#---------------------------------------------------------------------
  def __init__(self,name='',title='Parameters',
               gui=[],default={},definition={},
               help='',update={},apply_mode='',
               picture_definition=0,project='',
               copy_from='',c_access=0,custom_gui=None,apply_action=None,plugin=None,onCreate=None):
#---------------------------------------------------------------------
    #print "ParamsManager.init name",name
    self.title = title
    self.name = name
    self.gui = gui
    self.custom_gui = custom_gui
    self.apply_mode = apply_mode
    self.apply_action = apply_action
    self.plugin = plugin
    self.picture_definition = picture_definition
    # Specify project for which this parameter set should be saved
    self.project = project
    # Set the current params and the default params (which will be saved
    # to use with 'reset' option
    self.params = {}
    self.params.update(default)
    self.defaults = {}
    self.defaults.update(default)
    self.definition = {}
    for key in definition.keys():
      #print "ParamsManager.init key",key
      self.definition[key] = {}
      self.definition[key].update(definition[key])
    self.help=help
    self.update_defn = update
    self.insts.append(self)
    self.dependents = []
    self.c_access = c_access
    self.onCreate = onCreate

    # Initialise from another PM (probably a 'global' when this is a
    # local - object specific instance) 
    if copy_from:
      self.copy(copy_from=copy_from)

    # Look in the shadow class for parameters saved between sessions
    saved_params = PM_MANAGER().get(name)
    #print "ParamsManager.init saved_params",self,saved_params
    if saved_params:
      # Update the restored parameters according to self.update_defn
      # This is to handle changes with program version
      if self.update_defn:
        for key in  self.update_defn:
          if saved_params.has_key(key):
            if  self.update_defn[key].has_key(saved_params[key]):
              saved_params[key] = self.update_defn[key][saved_params[key]]
      for key in self.params.keys():
        if saved_params.has_key(key):
          self.params[key]= saved_params[key]

    # Create the C object and load
    self.CParamsManager = None
    if self.c_access: self.createCParamsManager()

      

#---------------------------------------------------------------------
  def createCParamsManager(self):
#---------------------------------------------------------------------
      import paramsmanager
      self.CParamsManager = paramsmanager.CParamsManager()
      #print "CParamsManager",self.name,self.CParamsManager
      for  key in self.params.keys():
        if self.definition.has_key(key):
          type = self.definition[key].get('type',int)
          if type == int or type == bool:
            self.CParamsManager.SetInt(key,self.params.get(key,0))
          elif  type == float:
            self.CParamsManager.SetFloat(key,self.params.get(key,1.0))

   
#---------------------------------------------------------------------
  def delete(self):
#---------------------------------------------------------------------
    if self.insts.count(self):
      self.insts.remove(self)
    if hasattr(self,'CParamsManager'): del self.CParamsManager

#--------------------------------------------------------------------
  def add_dependent(self,dependent):
#--------------------------------------------------------------------
    #print "ParamsManager add_dependent",dependent
    if not self.dependents.count(dependent):
      self.dependents.append(dependent)

#--------------------------------------------------------------------
  def remove_dependent(self,dependent,delete=0):
#--------------------------------------------------------------------
    if self.dependents.count(dependent):
      self.dependents.remove(dependent)
    #print "ParamsManager remove_dependent",delete,len(self.dependents)
    if delete and len(self.dependents)==0:
      self.delete()
    
#--------------------------------------------------------------------
  def getCustomGui(self):
#--------------------------------------------------------------------
    if hasattr(self,'custom_gui'):
      return self.custom_gui
    else:
      return None
    
#--------------------------------------------------------------------
  def getGuiDef(self):
#--------------------------------------------------------------------
    return self.gui

#--------------------------------------------------------------------
  def getParamDef(self,name):
#--------------------------------------------------------------------
    if self.definition.has_key(name):
      return self.definition[name]
    else:
      return {}

#--------------------------------------------------------------------
  def getTitle(self):
#--------------------------------------------------------------------
    return self.title

#--------------------------------------------------------------------
  def getDefaults(self):
#--------------------------------------------------------------------
    defs = {}
    defs.update(self.defaults)
    return defs
  

#-------------------------------------------------------------------
  def getparams(self):
#-------------------------------------------------------------------
    params = {}
    params.update(self.params)
    return params
  
#-------------------------------------------------------------------
  def setparams(self,new_params = {}, do_rebuild=1, **keywords):
#-------------------------------------------------------------------
    #print "setparams",exit,keywords
    #print "dependents",self.dependents
      
    new_params.update(keywords)
    updated = self.interpret_parameters(current_params=self.params,
                                 new_params = new_params )
    #print "setparams updated",self.name,updated,self.dependents
    # If something updated then stick new value in
    # self.params and inform all dependent objects
    #print "updated",updated
    if(updated):
      self.params.update(updated)
      if self.c_access:
        if not self.CParamsManager: self.createCParamsManager()
        for key,value in updated.items():
          type = self.definition[key].get('type',int)
          if type == int or type == bool:
            self.CParamsManager.SetInt(key,value)
          elif type == float:
            self.CParamsManager.SetFloat(key,value)
      for dep in self.dependents: dep(ParamsManager=self.name,updated=updated)

    if do_rebuild:
      import rebuild
      rebuild.UpdateDisplay()
    
#--------------------------------------------------------------------
  def interpret_parameters(self,current_params={},new_params={}):
#--------------------------------------------------------------------
    import utils
    updated = {}
    #print "current_params",current_params
    #print "new_params",new_params
    
    for item in new_params.keys():
      if current_params.has_key(item):
        if self.definition and self.definition.has_key(item):
          # Beware definition[item][0] is usually int or float
          # but if it is 'bool' should be converted to an int
          #print "interpret_parameters item",item,new_params[item]
          type = self.definition[item].get('type','')
          if ['bool',int].count(type):
            new_params[item] = utils.safeInt(new_params[item], current_params[item])
          elif [float,'float','real'].count(type):
            new_params[item] = utils.safeFloat(new_params[item], current_params[item])
        if new_params[item] != current_params[item]:
            updated[item] = new_params[item]
      else:
        updated[item] = new_params[item]
    #print "interpret_parameters updated",updated
    return updated

#--------------------------------------------------------------------
  def update(self,command):
#--------------------------------------------------------------------
    import pygl_coord
    n_int = 0
    n_float = 0
    n_str = 0
    #print "update self.params",self.params
    for par in self.gui:
      item = self.definition[par]
      type = self.definition[par].get('type',int)
      if type == int:
        n_int = n_int + 1
      elif type == float:
        n_float = n_float + 1
      elif type == str:
        n_str = n_str + 1
      elif type == 'bool':
        n_int = n_int + 1
    #print "n_int,n_float",n_int,n_float
    ipars = pygl_coord.inta(n_int)
    fpars = pygl_coord.doublea(n_float)
    i_int = 0
    i_float = 0
    i_str = 0
    for par in self.gui:
      item = self.definition[par]
      type = self.definition[par].get('type',int)
      if type == int:
        ipars[i_int] = int(self.params[par])
        i_int = i_int + 1
      elif type == float:
        fpars[i_float] = float(self.params[par])
        i_float = i_float +1
      elif type == str:
        pass
      elif type == 'bool':
        ipars[i_int] = int(self.params[par])
        i_int = i_int + 1
        #
        #
    #print "ParamsManager update n_float  n_int",n_float,n_int
    if n_float and n_int:
      command(n_float,fpars,n_int,ipars)
    elif n_float:
      command(n_float,fpars)
    elif n_int:
      command(n_int,ipars)

#------------------------------------------------------------------
  def get(self,key = ''):
#------------------------------------------------------------------
    if not key:
      pars = {}
      pars.update(self.params)
      return pars
    elif self.params.has_key(key):
      return self.params[key]
    else:
      return ''

#-------------------------------------------------------------------
  def copy(self,copy_from=None):
#-------------------------------------------------------------------
    import types
    if isinstance(copy_from,types.StringType): copy_from=PM(copy_from)
    if not copy_from: return 1
    for key in  self.params.keys():
      if copy_from.params.has_key(key):
        self.params[key] = copy_from.params[key]

#-------------------------------------------------------------------
  def update_data_status(self,params={}):
#-------------------------------------------------------------------
    #print "ParamsManager updata_data_status",self.name,params
    import utils
    diffs = utils.dict_diffs(self.params,params)[1]
    #print "update_data_status",self.name,diffs
    if diffs:
      self.params.update(diffs)
      #print "update_data_status diffs",diffs
      for key,value in diffs.items():
        if self.definition.has_key(key):
          type = self.definition[key].get('type',int)
          if self.c_access:
            if not self.CParamsManager: self.createCParamsManager()
            if type == int or type == bool:
              self.CParamsManager.SetInt(key,value)
            elif type == float:
              self.CParamsManager.SetFloat(key,value)
            else:
              del diffs[key]
      for dep in self.dependents: dep(ParamsManager=self.name,updated=diffs)
      return 1
    else:
      return 0
      
      
#--------------------------------------------------------------------
  def compare_objects(self,initial_status=None,final_status=None):
#--------------------------------------------------------------------
    changed_initial = {}
    changed_final = {}
    for item,defn in self.definition.items():
      if initial_status.has_key(item) and final_status.has_key(item) and \
                   initial_status[item]!=final_status[item]:
        changed_initial[item] = initial_status[item]
        changed_final[item] = final_status[item]

    return [changed_initial,changed_final]
  

#-------------------------------------------------------------------
  def movie_interpolation(self,initial_status=None,final_status=None, \
                          fraction=0.0,step='',**keywords):
#-------------------------------------------------------------------
    updated = {}
    for item in initial_status.keys():
      new_value = ((1-fraction)*float(initial_status[item])) + \
                             (fraction * float(final_status[item]))
      if self.definition[item].get('type') == int:
        updated[item] = int(new_value+0.499999)
        if self.c_access: self.CParamsManager.SetInt(item,int(new_value))
      elif self.definition[item].get('type') == float:
        updated[item] =  new_value
        if self.c_access: self.CParamsManager.SetFloat(item,new_value)
      
      self.params.update(updated)
    #print "ParamsManager movie_interpolation changed",self,updated
    for dep in self.dependents: dep(ParamsManager=self.name,updated=updated)

#-------------------------------------------------------------------
  def save_picture_definition(self,pretty_print,style='method',all=1):
#-------------------------------------------------------------------
    #if not self.picture_definition: return ""
    import utils
    stream = ''
    if style == 'method':
      b_end = ')'
      stream = stream + 'ParamsManager( '
    else:
      b_end='}'
      stream = stream + self.name + ' = '+ '{ '

    stream=stream+utils.picture_defn_item('name',self.name,pretty_print,style=style)

    nout = 0
    for key,value in self.params.items():
      if all or ( self.defaults.has_key(key) and value != self.defaults[key]):
        nout = nout + 1
        stream=stream+utils.picture_defn_item(key,value,pretty_print,style=style)
    stream = stream[0:-1]+ '          '+b_end+'\n\n'

    if nout > 0:
      return stream
    else:
      return ""

#-------------------------------------------------------------------
  def restore_picture_definition(self,params={}):
#-------------------------------------------------------------------
    # Method probably redundant - update_data_status used in prefrences
    #print "restore_picture_definition",self.name,self,params
    for key,value in params.items():
      # Make sure it is relevant item
      if self.defaults.has_key(key):
        self.params[key]=params[key]
    #if not params.has_key('picture_definition'): self.picture_definition=0

        
#--------------------------------------------------------------------
#--------------------------------------------------------------------
#--------------------------------------------------------------------
#--------------------------------------------------------------------

class ParamsManagerManager:
  #There should be one instance of this class which manages
  # saving and restoring the params from all instances of ParamsManager
  insts = None

  def __init__(self):
    ParamsManagerManager.insts = self
    self.restored_data = {}
    
#--------------------------------------------------------------------
  def save(self,picture_definition=-1,project=''):
#--------------------------------------------------------------------
    # Return dictionary containing data from all PMs
    #print "PMManager save",
    #for item in ParamsManager.insts: print item.name,

    data = {}
    data.update(self.restored_data)
    for obj in ParamsManager.insts:
      if obj.project == project:
        if picture_definition<0 or picture_definition == obj.picture_definition:
          data[obj.name] = obj.getparams()

    for obj in ColourSchemeManager.insts:
      if obj.project == project:
        data[obj.name]= obj.getparams()
        #print "saving",obj.name,self.data[obj.name]

    #print "ParamsManagerManager.save",data.keys(),data.get('Surface_electro',{})
    return data
      
#---------------------------------------------------------------------
  def restore(self,data={},initialise=0):
#---------------------------------------------------------------------
    if initialise: self.restored_data={}
    self.restored_data.update(data)

    # is there existing ColourSchemeManager?
    for cs in ColourSchemeManager.insts:
      if self.restored_data.has_key(cs.name):
        #print "ParamsManagerManager.restore ColourSchemeManager exists",cs.name
        cs.setparams(self.restored_data[cs.name])
    
    for mode in ColourSchemeManager.colour_pref_alias:
      if self.restored_data.has_key(mode):        
        #print "PMManager creating ColourSchemeManager",mode
        scheme_obj = ColourSchemeManager(name=mode)
        scheme_obj.setparams(self.restored_data[mode])
        
    # Update any existing ParamsManagers
    for pm in ParamsManager.insts:
      if self.restored_data.has_key(pm.name):
        #print 'updating',pm.name,self.data[pm.name]
        pm.update_data_status(self.restored_data[pm.name])
    
#--------------------------------------------------------------------
  def get(self,name):
#--------------------------------------------------------------------
    if self.restored_data.has_key(name):
      return self.restored_data[name]
    else:
      return None

#--------------------------------------------------------------------
  def difference(self,other={}):
#--------------------------------------------------------------------
    import utils
    diffs = {}
    for item in self.restored_data.keys():
      if other.has_key(item):
        dd = utils.dict_diffs(self.restored_data[item],other[item])[1]
        #print "PMManager difference",item,dd
        if dd: diffs[item] = dd
    return diffs

#--------------------------------------------------------------------
  def add(self,source={}):
#--------------------------------------------------------------------
    for item in source.keys():
      if self.restored_data.has_key(item):
        for it in source[item].keys():
           self.restored_data[item][it] = source[item][it]

#--------------------------------------------------------------------
  def update_data_status(self,data={},exclude_list=[]):
#--------------------------------------------------------------------
    update_gui = []
    #print "ParamsManagerManager.update_data_status data",data
    for pm in ParamsManager.insts:
      if (not exclude_list.count(pm.name)):
        if data.has_key(pm.name):
          rv = pm.update_data_status(data[pm.name])
          if rv: update_gui.append(['update_PM',pm.name])
        else:
          # Its deleted?
          #print "history.update_data_status delete_PM",pm.name
          PM(pm.name).delete()
          update_gui.append(['delete_PM',pm.name])

    for pm in ColourSchemeManager.insts:
      if data.has_key(pm.name):
        rv = pm.update_data_status(data[pm.name])
        if rv: update_gui.append(['update_PM',pm.name])

    #print "ParamsManagerManager.update_data_status update_gui",update_gui
    return update_gui

#---------------------------------------------------------------------
#---------------------------------------------------------------------
#---------------------------------------------------------------------
class ParamsManagerShadow:
#---------------------------------------------------------------------
#---------------------------------------------------------------------
#---------------------------------------------------------------------
  # This class is for restoring pre2.0 status files
  insts = None

#---------------------------------------------------------------------
  def __init__(self):
#---------------------------------------------------------------------
    ParamsManagerShadow.insts = self

#---------------------------------------------------------------------
  def restore(self):
#---------------------------------------------------------------------
    ParamsManagerShadow.insts = self
    PM_MANAGER().restore(data=self.data)
  
#--------------------------------------------------------------------
  def difference(self,other={}):
#--------------------------------------------------------------------
    import utils
    diffs = {}
    for item in self.data.keys():
      if other.has_key(item):
        dd = utils.dict_diffs(self.data[item],other[item])[1]
        #print "ParamsManagerShadow difference",item,dd
        if dd: diffs[item] = dd
    return diffs


#-----------------------------------------------------------------
def getCColourSchemes():
#-----------------------------------------------------------------
  # Need to have RGBreps initialised!  This is done of initialising
  # the colour class
  if not ColourSchemeManager.CColourSchemes:
    import mgapp
    c = MGCOLOUR()
    ColourSchemeManager.CColourSchemes = mgapp.CColourSchemes()    
  return ColourSchemeManager.CColourSchemes



#-----------------------------------------------------------------
def colourschememanager(name=''):
#-----------------------------------------------------------------

  for obj in ColourSchemeManager.insts:
    if obj.name == name:
      return obj
  if  ColourSchemeManager.colour_pref_alias.count(name):
    return ColourSchemeManager(name=name)
  else:
    return None



#-----------------------------------------------------------------
def colourschemesgui(item='',colour_pref='',**keys):
#-----------------------------------------------------------------
    if item and ColourSchemeManager.colour_pref_menu.count(item):
      obj = colourschememanager(ColourSchemeManager.colour_pref_alias[ColourSchemeManager.colour_pref_menu.index(item)])
    else:
      return
    if obj: obj.draw_gui()



#-----------------------------------------------------------------
#-----------------------------------------------------------------
#-----------------------------------------------------------------
class ColourSchemeManager:
#-----------------------------------------------------------------
#-----------------------------------------------------------------
#-----------------------------------------------------------------
  
  import cprim
  import atom_util
  CColourSchemes = None
  insts = []
  colour_pref_menu = ['Atom type','Residue type','Secondary structure',
               'Temperature factor','Occupancy','Charge',
               'Atom solvent access','Residue solvent access',
               'Atom buried area','Residue buried area']
  colour_pref_alias = ['atomtype','restype','secstr','bvalue','occupancy',
                 'charge','atom_sas','res_sas','atom_contact','res_contact']
  colour_pref_definitions = {
    'atomtype': {'type':'str','style':'lineedit'},
    'restype': {'type':'str','style':'lineedit'},
    'secstr': {'type':'str','style':'label','extensible':0},
    'bvalue': {'type':'float','max':9999,'min':-9999,'step':5,'style':'spinbox'},
    'occupancy': {'type':'float','max':1.0,'min':0.0,'step':0.05,'style':'spinbox'},
    'charge':  {'type':'float','max':5.0,'min':-5.0,'step':0.2,'style':'spinbox'},
    'atom_sas': {'type':'float','max':100.0,'min':0.0,'step':5.0,'style':'spinbox'},
    'atom_contact': {'type':'float','max':100.0,'min':0.0,'step':5.0,'style':'spinbox'},
    'res_sas':  {'type':'float','max':400.0,'min':0.0,'step':5.0,'style':'spinbox'},
    'res_contact': {'type':'float','max':400.0,'min':0.0,'step':5.0,'style':'spinbox'} }
  interpolation_alias = ['NO','RGB','HSV']
  interpolation_codes = [cprim.NOCOLOURREP,cprim.RGBCOLOURREP,cprim.HSVCOLOURREP]
  direction_alias = ['clockwise','anti-clockwise']
  direction_codes = [atom_util.COLOUR_WHEEL_CLOCK,atom_util.COLOUR_WHEEL_ANTICLOCK]
  
#----------------------------------------------------------------
  def __init__(self,name='',title='',mode='float',interpolate='HSV',
                  direction='clockwise',
                  ranges=[],colours=[],definitions={},project=''):
#----------------------------------------------------------------
    import mgapp

    #print "ColourSchemeManager.__init__",name
    getCColourSchemes()


    self.interpolate_mode = interpolate
    self.colour_wheel_direction = direction
    self.name = name
    self.definitions = {}
    self.definitions.update(definitions)
    if title: 
      self.title = title
    elif self.colour_pref_alias.count(name):
      self.title = self.colour_pref_menu[self.colour_pref_alias.index(name)]
    else:
      self.title = name
    self.project=project
    ranges0 = []
    for item in ranges: ranges0.append(item)
    colours0 = []
    for item in colours: colours0.append(item)
    self.defaults = { 'ranges' : ranges0,
                      'colours': colours0 }
  
    self.dependents = []   


    scheme_obj = ColourSchemeManager.CColourSchemes.GetScheme(str(name))
    #print "ColourSchemeManager",name,scheme_obj,colours0
    if scheme_obj:
      self.ColourScheme = scheme_obj
      self.mode = scheme_obj.GetMode()
      #Convert from old modes
      if self.mode == 'real':
        self.mode='float'
      elif self.mode == 'string':
        self.mode='str'
      if not self.defaults['ranges']:
        rv = self.GetColourScheme()
        #print 'ColourSchemeManger.init defaults',rv
        self.defaults['colours'] = rv[2]
        if self.name == 'secstr':
          import model
          rng = []
          for item in rv[1]:
            rng.append(model.convertSecstrCode(item))
          self.defaults['ranges'] = rng
        else:
          self.defaults['ranges'] = rv[1]
    else:
      self.ColourScheme = mgapp.CColourScheme()
      self.mode = mode
      self.SetColourScheme(limit=ranges0,colour=colours0,
                      interpolate_mode=self.interpolate_mode,
                      colour_wheel_direction=self.colour_wheel_direction)


    self.insts.append(self)

    # Look in the shadow class for parameters saved between sessions
    saved_params = PM_MANAGER().get(name)
    #print "saved_params",saved_params
    if saved_params:
      self.setparams(saved_params)

#----------------------------------------------------------------
  def __del__(self):
#----------------------------------------------------------------
    if self.insts.count(self): self.insts.remove(self)
    
#----------------------------------------------------------------
  def CColourScheme(self):
#----------------------------------------------------------------
    return self.ColourScheme


#--------------------------------------------------------------------
  def getTitle(self):
#--------------------------------------------------------------------
    return self.title

#--------------------------------------------------------------------
  def getParamDef(self,param,default={}):
#--------------------------------------------------------------------
    # get GUI properties for the 'param' parameter (currently only
    # expect param to be 'ranges'
    if self.definitions.has_key(param):
      return self.definitions[param]
    if param == 'ranges' and ColourSchemeManager.colour_pref_definitions.has_key(self.name):
      return ColourSchemeManager.colour_pref_definitions.get(self.name)
    else:
      return default

#--------------------------------------------------------------------
  def getDefaults(self):
#--------------------------------------------------------------------
    defs = {}
    defs.update(self.defaults)
    return defs
  
#----------------------------------------------------------------------
  def apply(self):
#----------------------------------------------------------------------
    # Mark any molecule display object which is coloured by this mode
    # for recolouring
    import dataobj
    for obj in get_dispobj(object_type=['MolDisp','SurfaceDispobj']):
      #print "ColourSchemeManager.apply",obj,obj.model_colour.colour_mode
      if obj.model_colour.colour_mode == self.name:
        obj.model_colour.do_recolour = 2
      elif self.name=='atom_contact':
        if obj.model_colour.colour_mode == 'atom_buried': obj.model_colour.do_recolour = 2
      elif self.name=='res_contact':
        if obj.model_colour.colour_mode== 'res_buried': obj.model_colour.do_recolour = 2
      elif self.name == 'atomtype' and obj.model_colour.non_C_atomtype:
        obj.model_colour.do_recolour = 2


    # Send signal to dependent objects
    # ( self.dependents is just a list of commands )
    for dep in self.dependents:
      if DEVELOPER():
        dep(ColourSchemeManager=self.name)
      else:
        try:
          dep(ColourSchemeManager=self.name)
        except:
          print 'Error updating colours'

#----------------------------------------------------------------------
  def setparams(self,params={},**kw):
#----------------------------------------------------------------------
    #print "ColourSchemeManager.setparams",self.mode,params
    params.update(kw)

    # v1.1 update restype colouring to take account of remediated pdb
    if self.name =='restype' and params.has_key('ranges')and params.has_key('colours') and params['ranges'].count('DA') == 0:
      params['ranges'].extend(['DA','DT','DG','DC'])
      params['colours'].extend(["red", "yellow", "green", "blue"])

    for item in ['interpolate_mode','colour_wheel_direction']:
      if params.has_key(item):
        setattr(self,item,params[item])

    #print 'calling SetInterpolationMode',self.interpolate_mode,self.colour_wheel_direction
    interp = self.interpolation_codes[self.interpolation_alias.index(self.interpolate_mode)]
    if self.direction_alias.count(self.colour_wheel_direction):
      dirn = self.direction_codes[self.direction_alias.index(self.colour_wheel_direction)]
    else:
      dirn = self.direction_codes[0]
    #print 'calling SetInterpolationMode',interp,dirn
    self.ColourScheme.SetInterpolationMode(interp,dirn)

    if params.has_key('colours') and params.has_key('ranges'):
      if self.mode == 'float':
        self.ColourScheme.SetSchemeFloat(params['ranges'],params['colours'])
      elif self.mode == 'int':
        import types
        if self.name == 'secstr' and len(params['ranges']) and (not isinstance(params['ranges'][0],types.IntType)):
          import model
          ranges = []
          for item in params['ranges']: ranges.append( model.convertSecstrCode( item))
          #print 'ColourSchemeManager.setparams',ranges,params['colours']
          self.ColourScheme.SetSchemeInt(ranges,params['colours'])
        else:
          self.ColourScheme.SetSchemeInt(params['ranges'],params['colours'])

      elif self.mode == 'str':
         self.ColourScheme.SetSchemeString(params['ranges'],params['colours'])

    self.apply()
    
#----------------------------------------------------------------------
  def getparams(self):
#----------------------------------------------------------------------
    if self.mode == 'float':
      rngs = self.ColourScheme.GetSchemeFloat()
    elif  self.mode == 'int':
      rngs =  self.ColourScheme.GetSchemeInt()
    else:
      rngs =  self.ColourScheme.GetSchemeString()
    ranges = []
    if self.name == 'secstr':
      import model
      for item in rngs: ranges.append( model.convertSecstrCode(item))
    else:
      for item in rngs: ranges.append(item)
    cols = self.ColourScheme.GetSchemeColours()
    colours = []
    for item in cols: colours.append(item)
    pars = {}
    pars['ranges']=ranges
    pars['colours']=colours
    for item in ['interpolate_mode','colour_wheel_direction']:
      pars[item]=getattr(self,item)
    #print "ColourSchemeManager.getparams",pars
    return pars


#------------------------------------------------------------------------
  def SetColourScheme(self,limit=[],colour=[], \
          interpolate_mode='RGB',colour_wheel_direction='clockwise'):
#------------------------------------------------------------------------
    #print "SetColourScheme",self.name,self.interpolate_mode

    if self.mode == 'float':
      self.ColourScheme.SetSchemeFloat(limit,colour)
    elif self.mode == 'int':
      self.ColourScheme.SetSchemeInt(limit, colour )      
    else:
      self.ColourScheme.SetSchemeString(limit,colour)

    if self.interpolation_alias.count(self.interpolate_mode):
      interp = self.interpolation_codes[self.interpolation_alias.index(self.interpolate_mode)]
      if self.direction_alias.count(self.colour_wheel_direction):
        dirn = self.direction_codes[self.direction_alias.index(self.colour_wheel_direction)]
      else:
        dirn = self.direction_codes[0]
      #print 'calling SetInterpolationMode',interp,dirn
      self.ColourScheme.SetInterpolationMode(interp,dirn)

    self.interpolate_mode=interpolate_mode
    self.colour_wheel_direction=colour_wheel_direction
      
#----------------------------------------------------------------------
  def GetColourScheme(self):
#----------------------------------------------------------------------    
    tcolour = self.ColourScheme.GetSchemeColours()
    colour = []
    for item in tcolour: colour.append(item)
    nrange = len(colour)
    if self.mode == 'float':
      tdefn = self.ColourScheme.GetSchemeFloat()
    elif self.mode == 'int':
      tdefn = self.ColourScheme.GetSchemeInt()
    else:
     tdefn = self.ColourScheme.GetSchemeString()
    defn = []
    for item in tdefn:defn.append(item)
    #print "GetColourScheme",colour,defn
    return [nrange,defn,colour]

#--------------------------------------------------------------------
  def add_dependent(self,dependent):
#--------------------------------------------------------------------
    self.dependents.append(dependent)

#--------------------------------------------------------------------
  def remove_dependent(self,dependent):
#--------------------------------------------------------------------
    if self.dependents.count(dependent):
      try:
        self.dependents.remove(dependent)
      except:
        pass

#--------------------------------------------------------------------
  def compare_objects(self,initial_status=None,final_status=None):
#--------------------------------------------------------------------
    changed_initial = {}
    changed_final = {}

    if self.mode == 'float' and \
        len( initial_status['ranges'])==len(final_status['ranges']):
      if initial_status['ranges']!=final_status['ranges']:
        changed_initial['ranges'] = initial_status['ranges']
        changed_final['ranges'] = final_status['ranges']
    
    return [changed_initial,changed_final]
  
#-------------------------------------------------------------------
  def save_picture_definition(self,pretty_print,style='method',all=1):
#-------------------------------------------------------------------
    import utils
    pars = self.getparams()
    #print "ColourScheme pars",pars
    stream = ''
    if style == 'method':
      b_end = ')'
      stream = stream + 'ColourSchemeManager('
    else:
      b_end='}'
      stream = stream + self.name + ' = '+ '{'

    stream=stream+utils.picture_defn_item('name',self.name,pretty_print,style=style)

    for key,value in pars.items():
      stream=stream+utils.picture_defn_item(key,value,pretty_print,style=style)
    stream = stream[0:-1]+ '          '+b_end+'\n\n'

    return stream


#-------------------------------------------------------------------
  def restore_picture_definition(self,params={}):
#-------------------------------------------------------------------
    pars = self.getparams()
    pars.update(params)
    self.setparams(pars)
    

#-------------------------------------------------------------------
  def movie_interpolation(self,initial_status=None,final_status=None, \
                          fraction=0.0,step='',**keywords):
#-------------------------------------------------------------------
    for item in initial_status.keys():
      ranges = []
      for ii in range(0,len(initial_status[item])):
        ranges.append(((1-fraction)*initial_status[item][ii]) + \
                             (fraction * final_status[item][ii]) )

      colours = self.ColourScheme.GetSchemeColours()
      self.ColourScheme.SetSchemeFloat(ranges,colours)

    for dep in self.dependents: dep(ColourSchemeManager=self.name)
    
#-------------------------------------------------------------------
  def update_data_status(self,params={}):
#-------------------------------------------------------------------
    #print "ColourScheme updata_data_status",self.name,params
    cur_params = self.getparams()
    import utils
    diffs = utils.dict_diffs(cur_params,params)[1]
    #print "ColourScheme.update_data_status",self.name,diffs
    if diffs:
      # Beware setparams expects colours/ranges as a pair
      if diffs.has_key('colours') and not diffs.has_key('ranges'):
        diffs['ranges'] = cur_params['ranges']
      elif diffs.has_key('rangess') and not diffs.has_key('colourss'):
        diffs['colours'] = cur_params['colours']
      self.setparams(diffs)
      self.apply()
      return 1
    else:
      return 0
 

