"""
     qtgui/displayTableObjects.py: CCP4MG Molecular Graphics Program
     Copyright (C) 2001-2008 University of York, CCLRC
     Copyright (C) 2009-2011 University of York
     Copyright (C) 2012 STFC

     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 functools,os
import shutil
from PyQt4 import QtGui,QtCore,QtSvg
from global_definitions import *
import displayTable,guiUtils
import model,model_colour,model_selection,dataobj,MolLabel,Crystal
import rebuild
import MGSimpleDialog,mgWidgets

def getVectorIcon(target):
  label_colour='#ff0000'
  line_colour='#ff0000'
  dashed=False
  arrow=''
  style='line'
  doLabel = True

  if target.style.has_key('label_mode') and 'no label' in target.style['label_mode']:
     doLabel = False

  if target.style.has_key('line_style'):
    theStyle = target.style['line_style']
    if 'dashed' in theStyle:
      dashed = True
    if 'cylinder' in theStyle:
      style = 'solid'
    elif 'cone' in theStyle:
      style = 'cone'
    elif 'no line' in theStyle:
      style = 'no line'
  if target.style.has_key('arrow_head') and target.style.has_key('line_style') and 'arrow' in target.style['line_style']:
    arrow = target.style['arrow_head']

  if target.style.has_key('line_colour'):
    import cprim
    col = cprim.RGBReps.GetColour(target.style['line_colour'])
    r = int(col[0]*255)
    g = int(col[1]*255)
    b = int(col[2]*255)
    line_colour = ('#%02x%02x%02x') % (r,g,b)

  if target.style.has_key('label_colour'):
    import cprim
    col = cprim.RGBReps.GetColour(target.style['label_colour'])
    r = int(col[0]*255)
    g = int(col[1]*255)
    b = int(col[2]*255)
    label_colour = ('#%02x%02x%02x') % (r,g,b)

  start_arrow = False
  end_arrow = False
  if arrow.lower() == "both":
     start_arrow = True
     end_arrow = True
  elif arrow.lower() == "start":
     start_arrow = True
  elif arrow.lower() == "end":
     end_arrow = True

  text = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="256"
   height="256"
   id="svg2"
   version="1.1"
   inkscape:version="0.48.1 r9760"
   sodipodi:docname="vectorsolid.svg">
  <defs
     id="defs4">
    <inkscape:perspective
       sodipodi:type="inkscape:persp3d"
       inkscape:vp_x="0 : 526.18109 : 1"
       inkscape:vp_y="0 : 1000 : 0"
       inkscape:vp_z="744.09448 : 526.18109 : 1"
       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
       id="perspective10" />
    <inkscape:perspective
       id="perspective2932"
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
       inkscape:vp_z="1 : 0.5 : 1"
       inkscape:vp_y="0 : 1000 : 0"
       inkscape:vp_x="0 : 0.5 : 1"
       sodipodi:type="inkscape:persp3d" />
    <inkscape:perspective
       id="perspective3727"
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
       inkscape:vp_z="1 : 0.5 : 1"
       inkscape:vp_y="0 : 1000 : 0"
       inkscape:vp_x="0 : 0.5 : 1"
       sodipodi:type="inkscape:persp3d" />
    <inkscape:perspective
       id="perspective3727-8"
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
       inkscape:vp_z="1 : 0.5 : 1"
       inkscape:vp_y="0 : 1000 : 0"
       inkscape:vp_x="0 : 0.5 : 1"
       sodipodi:type="inkscape:persp3d" />
    <inkscape:perspective
       id="perspective3758"
       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
       inkscape:vp_z="1 : 0.5 : 1"
       inkscape:vp_y="0 : 1000 : 0"
       inkscape:vp_x="0 : 0.5 : 1"
       sodipodi:type="inkscape:persp3d" />
  </defs>
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="2"
     inkscape:cx="59.286972"
     inkscape:cy="125.82645"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="true"
     inkscape:window-width="870"
     inkscape:window-height="761"
     inkscape:window-x="319"
     inkscape:window-y="0"
     inkscape:window-maximized="0">
    <inkscape:grid
       type="xygrid"
       id="grid2816"
       empspacing="5"
       visible="true"
       enabled="true"
       snapvisiblegridlinesonly="true" />
  </sodipodi:namedview>
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title />
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(0,-796.36217)">
  """
  if style == 'line':
    text += """
    <path
    """
    if dashed:
      text += """     style="fill:none;stroke:""" + line_colour + """;stroke-width:14;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:20,20;stroke-dashoffset:0" """
    else:
      text += """     style="fill:none;stroke:""" + line_colour + """;stroke-width:14;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;" """
    text += """
       d="m 35,962.36217 185,0"
       id="path3045"
       inkscape:connector-curvature="0" />
    """
  if doLabel:
    text += """<text
       xml:space="preserve"
       style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff0000;fill-opacity:1;stroke:#000000;font-family:Bitstream Vera Sans;stroke-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none"
       x="10"
       y="917.36218"
       id="text3815"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3817"
         x="10"
         y="917.36218"
    """
    text += """       style="font-size:72px;stroke:#000000;stroke-opacity:1;fill:""" + label_colour + """;fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none">Vector</tspan></text>"""

  if style == 'line' and start_arrow:
    text += """
      <path
    """
    text += """    style="fill:none;stroke:""" + line_colour+ """;stroke-width:14;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" """
    text += """
       d="m 30,962.36217 35,-25"
       id="path4637"
       inkscape:connector-curvature="0" />
    <path
    """
    text += """     style="fill:none;stroke:""" + line_colour+ """;stroke-width:14;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" """
    text += """
       d="m 30,962.36217 35,25"
       id="path4637-3"
       inkscape:connector-curvature="0" />
    """
  if style == 'line' and end_arrow:
    text += """
      <path
    """
    text += """     style="fill:none;stroke:""" + line_colour+ """;stroke-width:14;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" """
    text += """
       d="m 216,962.3621 -35,25"
       id="path4637-0"
       inkscape:connector-curvature="0" />
    <path
    """
    text += """     style="fill:none;stroke:""" + line_colour+ """;stroke-width:14;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" """
    text += """
       d="m 216,962.36213 -35,-25"
       id="path4637-3-1"
       inkscape:connector-curvature="0" />
    """

  if style == 'solid':
    if dashed:
      text += """
    <rect
       style="fill:"""+line_colour+""";stroke:#000000;stroke-width:6.92820311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
       id="rect4689-2"
       width="30"
       height="24.999987"
       x="50"
       y="952.36218"
       ry="0" />
    <rect
       style="fill:"""+line_colour+""";stroke:#000000;stroke-width:6.92820311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
       id="rect4689-2-3"
       width="30"
       height="24.999987"
       x="115"
       y="952.36218"
       ry="0" />
    <rect
       style="fill:"""+line_colour+""";stroke:#000000;stroke-width:6.92820311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
       id="rect4689-2-1"
       width="30"
       height="24.999987"
       x="180"
       y="952.36218"
       ry="0" />
      """
    else:
      text += """
    <rect
       style="fill:"""+line_colour+""";stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
       id="rect4689"
       width="160"
       height="25.000013"
       x="50"
       y="952.36218"
       ry="0" />
      """
    if start_arrow:
      text += """
    <path
       style="fill:"""+line_colour+""";stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
       d="m 15,962.36217 55,-25 c 0,0 15,15.28175 15,25 0,9.71825 -15,25 -15,25 z"
       id="path4691"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="ccacc" />
      """
    if end_arrow:
      text += """
    <path
       style="fill:"""+line_colour+""";stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
       d="m 245,962.36217 -55,-25 c 0,0 -15,15.2817 -15,25 0,9.7182 15,25 15,25 z"
       id="path4691-4"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="ccacc" />
      """

  if style == 'cone':
    text += """
    <path
       style="fill:"""+line_colour+""";stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
       d="m 245,962.36217 -195,-25 c 0,0 -15,15.28175 -15,25 0,9.71825 15,25 15,25 z"
       id="path4691-4"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="ccacc" />
    text += """

  text += """
  </g>
</svg>
    """
  ba = QtCore.QByteArray(text)
  svg = QtSvg.QSvgRenderer()
  svg.load(ba)
  pixmap = QtGui.QPixmap(512,512)
  pixmap.fill(QtGui.QColor(0,0,0,0))
  painter = QtGui.QPainter(pixmap)
  svg.render(painter)
  painter.end()
  icon = QtGui.QIcon(pixmap)
  return icon

def getIconFromSelectionFunction(label_command):
  useIcons = PM('advanced_options').getparams()['iconized_display_table']
  if not useIcons: return None
  icon = None
  label = label_command()
  if label in model_selection.SELECTION_ICONS:
    icon = model_selection.SELECTION_ICONS[label]
    if icon:
      if os.path.exists(os.path.join(os.environ['CCP4MG'],'qticons','disptab','selections',icon)):
         icon = os.path.join(os.environ['CCP4MG'],'qticons','disptab','selections',icon)
  return icon


#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class GAtomicDispObj(displayTable.GDispObj):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
  # Utiilty class with functionality common to atom-based
  # graphical objects (MolDisp, HBonds, SurfaceDispobj)

  molecule_props = ['atomtype','bychain','bymodel','mainside']
  residue_props = ['restype','res_sas','res_buried']
  atom_props = ['bvalue','occupancy','altloc','charge','atom_sas','atom_buried']

  def __init__(self,parent=None,table=None,name='',object_type='',mode=''):
    displayTable.GDispObj.__init__(self,parent=parent,table=table,
                            name=name,object_type=object_type)

     
#----------------------------------------------------------------------
  def getSelectionActionDef(self,name='',label='',target=None):
#----------------------------------------------------------------------

  # Returns action definitions for atom selection

    len_label = len(label)
    name = name[len_label:]
    
    if model_selection.SELECTION_LABELS.has_key(name):
      def c(): return self.isSelection(name,label)
      return dict (
      text =model_selection.SELECTION_LABELS.get(name,'ERROR'),
      group = 'select',
      checkable = 1,
      checked = c,
      slot = guiUtils.partial(self.set_atom_selection,{'name':name,'label':label})    )

    elif name == 'selection_browser':
      return dict (
      slot = guiUtils.partial(self.atom_selection_browser,label),
      text = self.tr('Selection browser..'))

    elif name == 'name_selection':
      return dict (
      slot = guiUtils.partial(self.name_atom_selection,label),
      text = self.tr('Name this selection..'))

    elif name == 'restore_selection':
      return dict (
      slot = guiUtils.partial(self.restore_atom_selection,label),
      text = self.tr('Restore selection..'))

    elif name == 'solvent':
      return dict (

        text = self.tr("Solvent"),
   )

    elif name == 'as_dispobj':
      return dict (
      slot = guiUtils.partial(self.open_as_dispobj_gui,label),
      text = self.tr('As display object..'))

    elif name[0:6] == 'sites_':
      def c(): return self.isSelection(name,label)
      ii = int( name[6:])
      return dict (
      slot = guiUtils.partial(self.set_atom_selection,{'name':name,'label':label}),
      text = target.parent._sites[ii]['description']+' ('+target.parent._sites[ii]['name']+')',
      checkable = 1,
      checked = c,
      )
    
    elif name[0:9] == 'monomers_':
      def c(): return self.isSelection(name,label)
      ii = int( name[9:])
      #print 'monomers ii',ii,target.parent.monomers
      return dict (
      slot = guiUtils.partial(self.set_atom_selection,{'name':name,'label':label}),
      text = target.parent.monomers[ii],
      checkable = 1,
      checked = c,
      )
    
    elif name[0:6] == 'chain_':
      def c(): return self.isSelection(name,label)
      ii = int( name[6:])
      #print 'chains ii',ii,target.parent.chains
      return dict (
      slot = guiUtils.partial(self.set_atom_selection,{'name':name,'label':label}),
      text = target.parent.chains[ii],
      checkable = 1,
      checked = c )
    

    return {}


  def getColourActionDef(self,name='',label='',target=None):
   #Colour menu
      len_label = len(label)
      name = name[len_label:]


      if ['complement','black','white','red','green','blue','yellow','cyan','magenta'].count(name):
        return dict (
        text = name,
        slot = guiUtils.partial(self.set_colour,name) )
      
      if name == 'browser':
        return dict (
        text = self.tr('Colour browser..'),
        slot = self.colour_browser,
        )
      
      if name == 'legend':
        def e(): return target.isLegendPossible()
        return dict (
        text = self.tr('Add colour legend'),
        slot = self.showLegend,
        enabled = e
        )
  
      elif name == 'stick_colour':
        return dict (
        text = self.tr('One colour..'),
        toolTip = self.tr('Colour of sticks in ball-and-stick'),
        slot = self.stick_colour,
        )
      
      elif name == 'stick_atom':
        return dict (
        text = self.tr('As atom'),
        toolTip = self.tr('Sticks in ball-and-stick same colour as neighbouring atoms'),
        slot = guiUtils.partial(self.stick_colour,1)
        )

      elif name == 'interface':
        return dict (
        text = self.tr('Interface to..'),
        toolTip = self.tr('Colour by area of atoms/residues buried in interface'),
        slot = guiUtils.partial(self.set_colour,'colour_interface'),
        )
 

      elif name == 'blend':
        useIcons = PM('advanced_options').getparams()['iconized_display_table']
        if useIcons:
          icon = 'blendthrough'
          icon_path = os.path.join(os.path.abspath(os.environ['CCP4MG']),'qticons','disptab','colour')
        else:
          icon = None
          icon_path = ''
           
        def c(): return int(getattr(target.model_colour,'colour_mode')==name)
        return dict (
        text = self.tr('Blend through model..'),
        group='colour_mode',
        signal = 'mouseRelease',
        slot = guiUtils.partial(self.set_colour,'colour_blend'),
        checkable = 1,
        icon_path = icon_path,
        icon = icon,
        checked = c
        )
      
      elif name == 'rules':
        def c(): return int(getattr(target.model_colour,'colour_mode')==name)
        return dict (
        text = self.tr('Edit colour scheme..'),
        group='colour_mode',
        signal = 'mouseRelease',
        slot = guiUtils.partial(self.set_colour,'colour_rules'),
        checkable = 1,
        checked = c
        )
      
      elif name == 'scheme':
        def c(): return int(getattr(target.model_colour,'colour_mode')==name)
        return dict (
        text = self.tr('Restore colour scheme..'),
        group='colour_mode',
        signal = 'mouseRelease',
        slot = guiUtils.partial(self.set_colour,'colour_scheme'),
        checkable = 1,
        checked = c
        )
      
      elif model_colour.model_colour.colour_commands.count(name):
        icon = ''
        icon_path = ''
        useIcons = PM('advanced_options').getparams()['iconized_display_table']
        if useIcons and name in model_colour.model_colour.colour_commands_icons:
          icon = model_colour.model_colour.colour_commands_icons[name]
          if icon.endswith('.svg'):
            icon = icon[:-4]
          elif icon.endswith('.png'):
            icon = icon[:-4]
          icon_path = os.path.join(os.path.abspath(os.environ['CCP4MG']),'qticons','disptab','colour')
        def c(): return int(getattr(target.model_colour,'colour_mode')==name)
        ii = model_colour.model_colour.colour_commands.index(name)
        return dict (
        text = model_colour.model_colour.colour_menu[ii],
        group='colour_mode',
        slot = guiUtils.partial(self.set_colour,name),
        icon_path = icon_path,
        icon = icon,
        checkable = 1,
        checked = c
        )
    
      elif name == 'non_C_atomtype':
        def c(): return getattr(target.model_colour,'non_C_atomtype')
        return dict (
        text = self.tr('Non carbon by atom type'),
        slot = guiUtils.partial(self.set_colour,name),
        checkable = 1,
        checked = c
        )

      else:
        return {}

#----------------------------------------------------------------------
  def getSelectionMenu(self,target,label='',ifAsDispobj=0):
#----------------------------------------------------------------------
    #print 'getSelectionMenu',self,ifAsDispobj
    menu = [label+'all',label+'allnotsolv']

    ifprot = target.parent.molecule_type.count('PROTEIN')
    ifnucl = target.parent.molecule_type.count('NUCLEIC')
    if ifprot or ifnucl:
      if ifprot:
        if ifnucl:
          submenu = [self.tr('Peptide/nucleic')]
        else:  
          submenu = [self.tr('Peptide')]
      elif ifnucl:     
        submenu=[self.tr('Nucleic acid')]
        
      if ifprot:
        for item in model_selection.PEPTIDE_ATOMTYPE_MENU: submenu.append(label+item)
      if ifnucl: 
        for item in model_selection.NUCLEIC_ATOMTYPE_MENU: submenu.append(label+item)
      menu.append(submenu)
    
    if target.parent.chains:
      if ifprot or ifnucl:
        submenu = [self.tr('.. of chains')]
      else:
         submenu = [self.tr('Chains')]
      for ii in range(len(target.parent.chains)): submenu.append(label+'chain_'+str(ii))
      menu.append(submenu)
    if target.parent.solvent_chains:
      menu.extend([label+'solvent'])

    if target.parent.saccharides:
      menu.append(label+'saccharide')

    if target.parent.monomers:
      if len(target.parent.monomers)<=20:
        submenu = [self.tr('Monomers'),label+'monomers']
        for ii in range(len(target.parent.monomers)): submenu.append(label+'monomers_'+str(ii))
        menu.append(submenu)
      else:
        menu.extend([label+'monomers'])

    if hasattr(target.parent,'sites') and target.parent._sites:
        submenu = [self.tr('Active sites'),label+'sites']
        for ii in range(len(target.parent._sites)):
             submenu.append(label+'sites_'+str(ii))
        menu.append(submenu)
      
    menu.append('sep')
    if ifAsDispobj: menu.append(label+'as_dispobj')
    
    #if len(target.parent.alt_locs)>0: menu.append('alt_locs')
    #if target.parent.nmr_models: menu.append('nmr_models')
    menu.extend([label+'restore_selection',label+'selection_browser'])
    menu.append('sep')
    menu.extend([label+'name_selection'])
    return menu

#----------------------------------------------------------------------
  def getAtomColourMenu(self,target,label=''):
#----------------------------------------------------------------------
    #print 'getAtomColourMenu'

    menu = []
    for p in self.molecule_props:
       menu.append(label+p)

    if target.parent.molecule_type.count('PROTEIN'): menu.append(label+'secstr')

    residue_props = [self.tr('Residue property')]
    for p in self.residue_props:
       if type(p) == list:
         theList = []
         theList.append(p[0])
         for p2 in p[1:]:
           if ('_pdb') in p2:
             offset = 0
             for i in range(p2.count('_pdb')):
               pnew = p2[offset:]
               pdb = pnew[pnew.find('_pdb')+4:pnew.find('_pdb')+8]
               offset = pnew.find('_pdb')+1
               if pdb[3:].upper() in target.parent.name.upper():
                 theList.append(label+p2)
           else:
             theList.append(label+p2)
         residue_props.append(theList)
       else:
         residue_props.append(label+p)

    atom_props = [self.tr('Atom property')]
    for p in self.atom_props:
       if type(p) == list:
         theList = []
         theList.append(p[0])
         for p2 in p[1:]:
           if ('_pdb') in p2:
             offset = 0
             for i in range(p2.count('_pdb')):
               pnew = p2[offset:]
               pdb = pnew[pnew.find('_pdb')+4:pnew.find('_pdb')+8]
               offset = pnew.find('_pdb')+1
               if pdb[3:].upper() in target.parent.name.upper():
                 theList.append(label+p2)
           else:
             theList.append(label+p2)
         atom_props.append(theList)
       else:
         atom_props.append(label+p)

    menu.extend([label+'blend','sep'])

    menu.extend([residue_props])
    menu.extend([atom_props])
    menu.extend([label+'interface',label+'rules','sep'])
    menu.append(label+'non_C_atomtype')
    menu.append(label+'browser')

    return menu
      

#-------------------------------------------------------------------
  def isSelection(self,name,label):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if ['','sel_'].count(label):
      mode = 'SelHandle'
    else:
      mode = 'SelHandle'+str(label[3])
    selHandle = getattr(target,mode)
    #print 'isSelection mode',self.objectName(),name,label,mode,selHandle
    if not selHandle: return 0
        
    if model_selection.PEPTIDE_ATOMTYPE_MENU.count(name) or model_selection.NUCLEIC_ATOMTYPE_MENU.count(name):
      #print 'isSelection',name,'atomtype',selHandle.selparams.get('atomtype','')
      if name == selHandle.selparams.get('atomtype',''):
        return 1
      else:
        return 0
      
    if name[0:6] == 'chain_':
      #print 'isSelection',name,selHandle
      ii = int(name[6:])
      if selHandle.getSelParams().get('chains',[]).count(target.parent.chains[ii]):
        return 1
      else:
        return 0
      
    elif name[0:6] == 'sites_':
      ii = int(name[6:])
      sites = selHandle.getSelParams().get('sites',[])
      theSel = target.parent._sites[ii]['selection']
      if set(theSel).issubset(set(sites)):
        return 1
      else:
        return 0

    elif name[0:9] == 'monomers_':
      ii = int(name[9:])
      if selHandle.getSelParams().get('monomers',[]).count(target.parent.monomers[ii]):
        return 1
      else:
        return 0

    if hasattr(target,mode):
      sele_com = getattr(target,mode).getCommand()
      #print 'isSelection',name,sele_com
      if sele_com == name:
        return 1
 
  
    return 0
    
#-------------------------------------------------------------------
  def atom_selection_browser(self,label):
#-------------------------------------------------------------------
    '''
    Open either selection browser for either first or second set of
    atoms (dependent on mode which is sel1... or sel2...)
    '''
    
    import selectionBrowser
    target = get_dispobj(name=self.objectName())
    mode = self.getSelectionMode(label)
    print "atom_selection_browser",label,mode,target,self.objectName()
    
    if not hasattr(self,'selectionBrowser'+mode):
      browser = selectionBrowser.selectionBrowser(self,target.parent.name)
      self.connect(browser,QtCore.SIGNAL('accepted()'),guiUtils.partial(self.handle_atom_selection,mode))
      browser.setSelHandle(getattr(target,'SelHandle'+mode))
      browser.openToolForCurrentSelection()
      setattr(self,'selectionBrowser'+mode,browser)
    else:
      browser  = getattr(self,'selectionBrowser'+mode)

    browser.show()
    browser.raise_()


#-------------------------------------------------------------------
  def open_as_dispobj_gui(self,label):
#-------------------------------------------------------------------
    mode = self.getSelectionMode(label)
    if not hasattr(self,'asDispobj'+mode):
      import modelUtils
      target = get_dispobj(name=self.objectName())
      gui = modelUtils.AsDispObjGui(dataobj_list = [target.parent.name],object_types =['MolDisp'],exclude=[self.objectName()])
      gui.setObjectName('asDispobj'+mode)
      gui.setWindowTitle('Selection for HBonds same as..')
      #self.connect(gui,QtCore.SIGNAL('apply'),guiUtils.partial(self.handle_as_dispobj,mode))
      self.connect(gui,QtCore.SIGNAL('apply'),self.handle_as_dispobj)
      setattr(self,'asDispobj'+mode,gui)
    else:
      gui = getattr(self,'asDispobj'+mode)
      gui.populate()
    gui.show()
    gui.raise_()

#-------------------------------------------------------------------
  def handle_as_dispobj(self,args):
#-------------------------------------------------------------------
    #print 'handle_as_dispobj',args
    if len(args)!=2: return
    mode = str(args[0].toString())[9:]
    dispobj = str(args[1].toString())
    #print 'handle_as_dispobj',mode,dispobj
    
    target = get_dispobj(name=self.objectName())
    if not target: return
    selHandle = getattr(target,'SelHandle'+mode,None)
    if selHandle:
      selHandle.setSameAs(dispobj,label='')
      target.set_do_redraw()
      
    rebuild.UpdateDisplay(target=target,controllingWidget=self)

#-------------------------------------------------------------------
  def handle_atom_selection(self,mode=''):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    DISPLAYTABLE().emit(QtCore.SIGNAL("SelectionChanged"),(target))

    # For slow drawing objects (surfaces) its probably better
    # to make object invisible when user changes selection
    if getattr(target,'hide_on_selection_update',0):
      self.set_visibility(visible=0)      

    target.set_reapply_selection()
    #for mode in ['','1','2']:
    if self.widgets.has_key('selection'+mode):
      self.updateLabel('selection'+mode)
    rebuild.UpdateDisplay(target=target,controllingWidget=self)
    #print 'done handle_atom_selection'
                         
  def getSelectionMode(self,label):
    if label[0:4] == 'sel_':
      return ''
    else:
      return label[3:4]

#-------------------------------------------------------------------
  def set_atom_selection(self,info):
#-------------------------------------------------------------------
    # Handle user picking on of the short-cut selection options
    # from the pushbutton menu
    name = info.get('name','')
    label = info.get('label','')

    mode = self.getSelectionMode(label)
    target = get_dispobj(name=self.objectName())
    #print "set_atom_selection",self,info,mode
    DISPLAYTABLE().emit(QtCore.SIGNAL("SelectionChanged"),(target))

    
    if target:
      target.set_reapply_selection()
      selHandle = getattr(target,'SelHandle'+mode,None)
      #print 'set_atom_selection selHandle',selHandle
      
      if selHandle:
        if name == 'same_as':
          selHandle.setSameAs(same_as=target.name)
        elif model_selection.PEPTIDE_ATOMTYPE_MENU.count(name) or model_selection.NUCLEIC_ATOMTYPE_MENU.count(name):
          #selHandle.setSelParams(select='',atomtype=name)
          pars = dict( select= name,
                       atomtype = name,
                   chains = selHandle.getSelParams().get('chains',[]) )
          selHandle.setSelParams(pars)
        elif name[0:6] == 'sites_':
          mon = target.parent._sites[int(name[6:])]['selection']
          sites = selHandle.getSelParams().get('sites',[])
          a = self.findChild(QtGui.QAction,label+name)
          if a:
            if a.isChecked() and (not set(mon).issubset(set(sites))):
              sites.extend(mon)
            elif (not a.isChecked()) and set(mon).issubset(set(sites)):
              for x in mon:
                 sites.remove(x)
          pars =  dict( select = 'sites',
                        sites = sites,
                        chains = selHandle.getSelParams().get('chains',[]) )
          selHandle.setSelParams(pars)
        elif name[0:9] == 'monomers_':
          mon = target.parent.monomers[int(name[9:])]
          monomers = selHandle.getSelParams().get('monomers',[])
          a = self.findChild(QtGui.QAction,label+name)
          #print 'set_atom_selection action',name,a
          if a:
            if a.isChecked() and (not monomers.count(mon)):
              monomers.append(mon)
            elif (not a.isChecked()) and monomers.count(mon):
              monomers.remove(mon)
          #print 'set_atom_selection monomers',monomers
          pars =  dict( select = 'monomers',
                        monomers = monomers,
                        chains = selHandle.getSelParams().get('chains',[]) )
          selHandle.setSelParams(pars)
        elif name[0:6] == 'chain_':
          chn = target.parent.chains[int(name[6:])]
          chains = selHandle.getSelParams().get('chains',[])
          a = self.findChild(QtGui.QAction,label+name)
          if a:
            if a.isChecked() and (not chains.count(chn)):
              chains.append(chn)
            elif (not a.isChecked()) and chains.count(chn):
              chains.remove(chn)
          #print 'set_atom_selection',chains,selHandle.selparams.get('atomtype')
          atomtype = selHandle.getSelParams().get('atomtype')
          if not atomtype: atomtype = 'peptide'
          pars =  dict (select = atomtype,
                        atomtype = atomtype,
                        chains = chains )
          selHandle.setSelParams(pars)
        else:
          pars = dict ( select=name,chains=[],monomers=[],sites = [],)
          selHandle.setSelParams(pars)

    self.handle_atom_selection(mode=mode)
    # Update a visible selection browser
    browser = getattr(self,'selectionBrowser'+mode,None)
    if browser:
      browser.updateCid()
      browser.updateTreeView()

      
#-------------------------------------------------------------------
  def name_atom_selection (self,label):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    mode = self.getSelectionMode(label)
    text = target.get_selection_label()
    win = QtGui.QDialog(self)
    layout = QtGui.QVBoxLayout(self)
    win.setLayout(layout)
    lineEdit = QtGui.QLineEdit(self)
    layout.addWidget(lineEdit)
    lineEdit.setText(text)

    buttons = QtGui.QDialogButtonBox(self)
    ok = buttons.addButton(QtGui.QDialogButtonBox.Ok)
    cancel = buttons.addButton(QtGui.QDialogButtonBox.Cancel)
    unname = buttons.addButton(self.tr("Remove name"),QtGui.QDialogButtonBox.DestructiveRole)
    layout.addWidget(buttons)

    def setCustomSelectionName():
      target.setCustomSelectionName(lineEdit.text())
      self.updateLabel('selection'+mode)

    def clearCustomSelectionName():
      target.setCustomSelectionName('')
      self.updateLabel('selection'+mode)

    ok.clicked.connect(setCustomSelectionName)
    unname.clicked.connect(clearCustomSelectionName)

    ok.clicked.connect(win.close)
    unname.clicked.connect(win.close)
    cancel.clicked.connect(win.close)
    win.show()
    return

#-------------------------------------------------------------------
  def restore_atom_selection (self,label):
#-------------------------------------------------------------------
    import selectionBrowser
    mode = self.getSelectionMode(label)
    restore_gui = getattr(self,'restore_gui'+mode,None)
    browser = getattr(self,'selectionBrowser'+mode,None)
    if restore_gui:
      restore_gui.show()
      restore_gui.raise_()
    elif browser and browser.isVisible():
      browser.show()
      browser.raise_()
      browser.openTool('general')
    else:
      target = get_dispobj(name=self.objectName())
      restore_gui = MGSimpleDialog.MGSimpleDialog(self)
      restore_gui.setWindowTitle('Save/restore selection')
      layout = QtGui.QVBoxLayout()
      namedSelection = selectionBrowser.namedSelectionGui(self,target.parent.name,save=0,close=1)
      layout.addWidget(namedSelection)
      restore_gui.setLayout(layout)
      restore_gui.show()
      
      self.connect(namedSelection,QtCore.SIGNAL('restore'),guiUtils.partial(self.restoreNamedSelection,mode))
      self.connect(namedSelection,QtCore.SIGNAL('close'),guiUtils.partial(self.closeNamedSelection,mode))
      setattr(self,'restore_gui'+mode,restore_gui)
      setattr(self,'namedSelection'+mode,namedSelection)

#---------------------------------------------------------------------------
  def closeNamedSelection(self,mode):
#---------------------------------------------------------------------------
    restore_gui = getattr(self,'restore_gui'+mode,None)
    if restore_gui:
      restore_gui.close()
      delattr(self,'restore_gui'+mode)
      delattr(self,'namedSelection'+mode)
  
#---------------------------------------------------------------------------
  def restoreNamedSelection(self,mode):
#---------------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    namedSelection = getattr(self,'namedSelection'+mode,None)
    SelHandle = getattr(target,'SelHandle'+mode,'')
    if namedSelection and SelHandle:
      set,name = namedSelection.list_widget.selectedItem()
      if name:
        SelHandle.restoreSelection(name)
        target.set_reapply_selection()
        self.updateLabel('selection'+mode)
        rebuild.UpdateDisplay(target=target,controllingWidget=self)


#-------------------------------------------------------------------
  def set_colour(self,name):
#-------------------------------------------------------------------
    '''
    Send a colour command to the target
    '''
    #print "GAtomicDispobj.set_colour",name
    import modelColourGui
    target = get_dispobj(name=self.objectName())
    if target:
      if name == 'non_C_atomtype':
        non_C_atomtype = self.findChild(QtGui.QAction,'colour_non_C_atomtype')
        if non_C_atomtype:
          target.model_colour.set_colour(non_C_atomtype=non_C_atomtype.isChecked())
      elif ['colour_blend','colour_interface','colour_rules'].count(name):
          if name == 'colour_blend':
            if not hasattr(self,"colour_blend_gui") or not self.colour_blend_gui:
              self.colour_blend_gui = modelColourGui.colourBlendGui(self,MolData=target.parent.name)
              params = target.model_colour.colparams()
              if params.has_key('colour_blend'): self.colour_blend_gui.setParams(params['colour_blend'])
              self.connect(self.colour_blend_gui,QtCore.SIGNAL('accepted()'),self.set_colour_blend)
            self.colour_blend_gui.show()
            self.colour_blend_gui.raise_()
          elif name == 'colour_interface':
            if not hasattr(self,"colour_interface_gui") or not self.colour_interface_gui:
              self.colour_interface_gui = modelColourGui.colourInterfaceGui(self,MolData=target.parent.name)
              self.colour_interface_gui.setParams(target.model_colour.colparams())
              self.connect(self.colour_interface_gui,QtCore.SIGNAL('accepted()'),self.set_colour_interface)
            self.colour_interface_gui.show()
            self.colour_interface_gui.raise_()
          elif name == 'colour_rules':
            if not hasattr(self,"colour_rules_gui") or not self.colour_rules_gui:
              self.colour_rules_gui = modelColourGui.ModelColourEditor(self,MolData=target.parent.name)
              self.connect(self.colour_rules_gui,QtCore.SIGNAL('apply'),self.set_colour_editor)
              self.connect(self.colour_rules_gui,QtCore.SIGNAL('restore_colour_scheme(PyQt_PyObject)'),self.restore_colour_scheme)
            target.model_colour.create_user_colour_definitions()
            self.colour_rules_gui.setParams(target.model_colour.colparams() )
            self.colour_rules_gui.show()
            self.colour_rules_gui.raise_()
          #gui.setAttribute(QtCore.Qt.WA_DeleteOnClose) # ??
      
      elif hasattr(target,'model_colour'):
        target.model_colour.set_colour(colour_mode=name)
        target.update_dependents('colour')
      else:
        target.set_colour(colour=name)
    self.updateLabel('colour')
    rebuild.UpdateDisplay(target=target,controllingWidget=self)

#-----------------------------------------------------------------------
  def set_colour_blend(self):
#-----------------------------------------------------------------------
    #print "set_colour_blend"
    pars = self.findChild(QtGui.QWidget,self.objectName()+'colour_blend').getParams()
    target = get_dispobj(name=self.objectName())
    target.model_colour.set_colour( colour_blend=pars, colour_mode = 'blend')

    self.updateLabel('colour')
    rebuild.UpdateDisplay(target=target,controllingWidget=self)



    
#-----------------------------------------------------------------------
  def set_colour_editor(self):
#-----------------------------------------------------------------------
    #print "set_colour_blend"
    pars = self.findChild(QtGui.QWidget,self.objectName()+'colour_editor').getParams()
    pars['colour_mode'] = 'rules'
    target = get_dispobj(name=self.objectName())
    target.model_colour.set_colour( colparams=pars, colour_mode = 'rules')

    self.updateLabel('colour')
    rebuild.UpdateDisplay(target=target,controllingWidget=self)

    
#-----------------------------------------------------------------------
  def restore_colour_scheme(self,args):
#-----------------------------------------------------------------------
    colour_scheme,set = args
    #print "GAtomicDispObj.restore_colour_scheme",colour_scheme,set
    
    target = get_dispobj(name=self.objectName())
    target.model_colour.restore_colour_scheme( label=colour_scheme,set=set)

    self.updateLabel('colour')
    rebuild.UpdateDisplay(target=target,controllingWidget=self)

    
#-----------------------------------------------------------------------
  def set_colour_interface(self):
#-----------------------------------------------------------------------
    #print "set_colour_blend"
    pars = self.findChild(QtGui.QWidget,self.objectName()+'colour_interface').getParams()
    target = get_dispobj(name=self.objectName())
    target.model_colour.set_colour( colparams=pars, colour_mode = 'interface')

    self.updateLabel('colour')
    rebuild.UpdateDisplay(target=target,controllingWidget=self)

    

#-----------------------------------------------------------------------
  def update(self):
#-----------------------------------------------------------------------
    for mode in ['','1','2']:
      if hasattr(self,'selectionBrowser'+mode):
        getattr(self,'selectionBrowser'+mode).update()

    blend_widget = self.findChild(QtGui.QWidget,self.objectName()+'colour_blend')
    if blend_widget:
      target = get_dispobj(name=self.objectName())
      blend_widget.setParams(target.model_colour.colparams() )
    # Update the base class
    displayTable.GDispObj.update(self)

#-----------------------------------------------------------------------
  def colour_interface(self):
#-----------------------------------------------------------------------
    if not hasattr(self,'interfaceGui'):
      self.interfaceGui = interfaceGui(self,MolData=self.parent().objectName())

    self.interfaceGui.show()


#-----------------------------------------------------------------------
  def showLegend(self):
#-----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    import ColourLegend
    legend = ColourLegend.ColourLegend(parent=target.parent,master=target.name)
    legend.set_text(target.model_colour.colour_legend)
    DISPLAYTABLE().addDispObj(parent_name=target.parent.name,
                              object_type='ColourLegend',name=legend.name)
    UPDATEDISPLAY()

        
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class GMapData(displayTable.GDataObj):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
  def __init__(self,parent,table=None,name='',label=''):
    displayTable.GDataObj.__init__(self,parent,table=table,name=name,label=label)
    self.iconButton.setToolTip(self.tr('Tools for map data object'))

#----------------------------------------------------------------------
  def getGuiDef(self,name='icon'):
#----------------------------------------------------------------------
    target = get_dataobj(name=self.objectName())[0]
    menudef = ['data_visible','data_centre_on','add_object','sampling_rate','data_list_data',[self.tr('Clone'),'data_clone','data_clone_dispobj'],'data_delete']
    return menudef

  def centreOn(self):
    target = get_dataobj(name=self.objectName())[0]
    map_orig_cart = target.clipper_map.GetOrigin()
    map_orig = (map_orig_cart.get_x(),map_orig_cart.get_y(),map_orig_cart.get_z())
    MAINWINDOW().glWidget.centreOn(map_orig,glide=1)
    
#----------------------------------------------------------------------
  def getActionDef(self,name,**info):
#----------------------------------------------------------------------    
    target = get_dataobj(name=self.objectName())[0]

    if hasattr(target,"is_em_map") and target.is_em_map and name == 'data_centre_on':
      return dict (
      text = self.tr("Centre on"),
      slot = self.centreOn,
      toolTip = self.tr('Centre on')
      )
    
    if name == 'add_object':
      return dict (
      text = self.tr("Add map contour display object"),
      slot = guiUtils.partial(self.add_dispobj,[target,'MapDisp']),
      toolTip = self.tr('Add a map display object')
      )

    if name == 'sampling_rate':

      return dict (
      text = self.tr("Sampling rate"),
      slot = self.samplingRateGui,
      enabled =  target.filetype == 'MTZ' or target.filetype == 'CIF',
      toolTip = self.tr('Change the map sampling rate')
      )
     
    return displayTable.GDataObj.getActionDef(self,name=name,target=target)

#-------------------------------------------------------------------
  def samplingRateGui(self):
#-------------------------------------------------------------------
    gui = self.findChild(QtGui.QDialog,'samplingrateGui')
    if gui:
      gui.show()
      gui.raise_()
      return
    
    target = get_dataobj(name=self.objectName())[0]
    dialog = MGSimpleDialog.MGSimpleDialog(self)
    dialog.setObjectName('samplingRateGui')
    dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    dialog.setWindowTitle(self.tr('Sampling rate for ')+self.objectName())
    layout = QtGui.QVBoxLayout()

    line_layout =  QtGui.QHBoxLayout()
    label = QtGui.QLabel(self.tr('Sampling rate'),self)
    widget = mgWidgets.mgSlider(QtCore.Qt.Horizontal,self)
    widget.setObjectName('sampling_rate')
    widget.setRange(0.1,3.0)
    #widget.setSingleStep(0.1)
    widget.setValue(target.rate)
    
    line_layout.addWidget(label)
    line_layout.addWidget(widget)
    layout.addLayout(line_layout)

    layout0 = QtGui.QHBoxLayout()
    layout0.addStretch()
    apply = QtGui.QPushButton(self.tr('Apply'),self)
    layout0.addWidget(apply)
    close =  QtGui.QPushButton(self.tr('Close'),self)
    layout0.addWidget(close)
    layout.addLayout(layout0)
    
    dialog.setLayout(layout)
    dialog.show()

    self.connect(apply,QtCore.SIGNAL('released()'),self.handleSamplingRate)
    self.connect(close,QtCore.SIGNAL('released()'),dialog.close)

  def handleSamplingRate(self):
    rate = self.findChild(QtGui.QWidget,'sampling_rate').value()
    target = get_dataobj(name=self.objectName())[0]
    target.set_sampling_rate(rate)
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class GMapDisp(displayTable.GDispObj):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent,table=None,name=''):
    displayTable.GDispObj.__init__(self,parent,table=table,name=name,object_type='MapDisp')
    self.iconButton.setToolTip(self.tr('Tools for map display object'))
    PM('MapDispParamsManager').add_dependent(self.resetContourScale)
    self.type_label = 'Map display object'

  def delete(self):
    PM('MapDispParamsManager').remove_dependent(self.resetContourScale)
    displayTable.GDispObj.delete(self)

#----------------------------------------------------------------------
  def getGuiDef(self,name='row',pickevent=None):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    # This is almost certainly bogus, need to check how to do this properly.
    # Broken for difference maps?
    if name == 'row':
      minimum,maximum=target.get_contour_range()
      return [          
              dict (name ='colour', mode='MENU', getIcon=target.get_colour_label, getLabel=target.get_colour_label , toolTip = self.tr('Set the map contour colour')),
              dict (name='contour', mode='VALUESLIDER', callback=self.sliderValueChanged, minimum=minimum, maximum=maximum, getValue=target.get_contour_level , toolTip = self.tr('Set the map contouring level'))
             ]
    if name == 'icon':
      surface_style = [self.tr('Surface style')]
      surface_style.extend(target.surface_style_alias)
      extent = [self.tr('Extent')]
      extent.extend(['extent_5','extent_10','extent_20','extent_gui'])
      clip = [self.tr('Clip')]
      full_alias_list =['clip_sel_none','clip_sel_point'] 
      full_alias_list = ['clip_sel_none','clip_sel_point']
      for molobj in get_dataobj (object_type='MolData') :
        menu_list,alias_list = molobj.get_selobj_menu(intermol=0)
        for iitem in  range(len(menu_list)):
          full_alias_list.append('clip_sel_MolDisp_'+alias_list[iitem])
      clip.extend(full_alias_list)
      clip_radius = [self.tr('Clip radius')]
      clip_radius.extend(['clip_radius_1','clip_radius_125','clip_radius_15','clip_radius_175','clip_radius_2','clip_radius_25','clip_radius_3','clip_radius_4','clip_radius_gui'])
      return ['visible','centre_on','flash','transparency',surface_style,'contour_details',extent,clip,clip_radius,'clone','delete']

    if name == 'colour':
      return ['colour_complement','colour_browser','colour_by_radius_greyscale','colour_by_radius_colour']

    if name == 'style' :
      import map
      return map.MapDisp.surface_style_alias

    return displayTable.GDispObj.getGuiDef(self,name=name,target=target)


#----------------------------------------------------------------------
  def resetContourScale(self,**kw):
#----------------------------------------------------------------------
    # Reset range widget if contour range style changes
    #print "GMapDisp.resetContourScale"
    target = get_dispobj(name=self.objectName())
    if not target or not hasattr(target,"get_contour_range") or not callable(target.get_contour_range): return
    minimum,maximum=target.get_contour_range()
    self.widgets['contour'].setRange(minimum,maximum)
    self.widgets['contour'].setValue(target.get_contour_level())
    
#----------------------------------------------------------------------
  def sliderValueChanged (self,value=0):
#----------------------------------------------------------------------
    #print "sliderValueChanged",value
    target = get_dispobj(name=self.objectName())
    if not target or not hasattr(target,"set_contour") or not callable(target.set_contour): return
    target.set_contour(value)

    rebuild.UpdateDisplay()
    
#-------------------------------------------------------------------
  def handleContourSlice(self):
#-------------------------------------------------------------------
    if not hasattr(self,"sliceDetails"):
      import ContourSliceDialog
      self.sliceDetails = ContourSliceDialog.ContourSliceDialog(self)
      target = get_dispobj(name=self.objectName())
      if target and hasattr(target,"map_plane") and target.map_plane is not None:
        self.sliceDetails.setParams(target.map_plane.params())
      self.connect(self.sliceDetails,QtCore.SIGNAL("apply"),self.setPlane)
      
    self.sliceDetails.show()
    self.sliceDetails.raise_()

  def setPlane(self,plane=None):
    target = get_dispobj(name=self.objectName())
    if not target or not hasattr(target,"set_params") or not callable(target.set_params): return
    params = self.sliceDetails.getParams()
    if target and params:
      # Change style to slice if not that already
      if not ['surface_style_slice','surface_style_mask'].count(getattr(target,'surface_style','')):
        target.set_params('surface_style_slice')
      target.map_plane.set_params(params)
      target.map_plane.update_plane()
      target.do_redraw = 1
      rebuild.UpdateDisplay(target=target,controllingWidget=self)
    
    
#-------------------------------------------------------------------
  def handleSurfaceStyle(self,name=''):
#-------------------------------------------------------------------
    #print 'MolDisp.handleSurfaceStyle',name
    target = get_dispobj(name=self.objectName())
    if not target or not hasattr(target,"set_params") or not callable(target.set_params): return
    target.set_params(name)
    if self.widgets.has_key('style'):
      self.widgets['style'].setText(target.get_style_label())

    rebuild.UpdateDisplay(target=target,controllingWidget=self)
        
#-------------------------------------------------------------------
  def handleExtent(self,name=''):
#-------------------------------------------------------------------
    #print 'handleExtent',name
    if  name == 'extent_gui':
      if not hasattr(self,'extent_gui'):
        self.extent_gui = QtGui.QDialog(self)
        self.extent_gui.setWindowTitle(self.tr('Map extent for ')+self.parent().objectName())
        layout = QtGui.QVBoxLayout()
	self.spin = QtGui.QDoubleSpinBox()
	self.spin.setRange(0,1000)
	buttons = QtGui.QDialogButtonBox()
	okButton = buttons.addButton(QtGui.QDialogButtonBox.Ok)
	applyButton = buttons.addButton(QtGui.QDialogButtonBox.Apply)
	cancelButton = buttons.addButton(QtGui.QDialogButtonBox.Cancel)
	self.connect(okButton,QtCore.SIGNAL("clicked(bool)"),self.handleExtentGui)
	self.connect(okButton,QtCore.SIGNAL("clicked(bool)"),self.extent_gui.hide)
	self.connect(applyButton,QtCore.SIGNAL("clicked(bool)"),self.handleExtentGui)
	self.connect(cancelButton,QtCore.SIGNAL("clicked(bool)"),self.extent_gui.hide)
	layout.addWidget(self.spin)
	layout.addWidget(buttons)
        self.extent_gui.setLayout(layout)
      target = get_dispobj(name=self.objectName())
      if target and hasattr(target,"radius") and hasattr(self,"spin"): self.spin.setValue(float(target.radius))
      self.extent_gui.show()
      self.extent_gui.raise_()
    elif name[:7]=='extent_':
      target = get_dispobj(name=self.objectName())
      target.set_selection(radius=int(name[7:]))
      self.updateLabel('extent')
      rebuild.UpdateDisplay(target=target,controllingWidget=self)


#-------------------------------------------------------------------
  def handleExtentGui(self):
#-------------------------------------------------------------------
      widget= getattr(self,'spin',None)
      if widget:
        target = get_dispobj(name=self.objectName())
        target.set_selection(radius=widget.value())
        self.updateLabel('extent')
        rebuild.UpdateDisplay(target=target,controllingWidget=self)
    
#-------------------------------------------------------------------
  def handleClipPoint(self,args):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    target.set_selection(clip_mode='POINT',clip_x=args[0],clip_y=args[1],clip_z=args[2])
    self.updateLabel('extent')
    rebuild.UpdateDisplay(target=target,controllingWidget=self)
      
#-------------------------------------------------------------------
  def handleClipSelection(self,name=''):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if name == 'clip_sel_none':
      target.set_selection(clip_mode='OFF')
      
    if name == 'clip_sel_point':
      if hasattr(target,"clip_point"):
	      x = target.clip_point[0]
	      y = target.clip_point[1]
	      z = target.clip_point[2]
      else:
	      x=y=z=0
      if not hasattr(self,'cartesianPicker'):
        self.cartesianPicker = mgWidgets.CartesianPickerDialog(self,x=x,y=y,z=z)
        self.cartesianPicker.setWindowTitle(self.tr('Clip map around point'))
      self.cartesianPicker.UnClose()
      self.connect(self.cartesianPicker,QtCore.SIGNAL("PositionChanged"),self.handleClipPoint)

    if name[:17] == 'clip_sel_MolDisp_':
      #print "We should clip to selection",name[17:]
      clip_dispobj = get_dispobj(object_type='MolDisp',name=name[17:])
      if clip_dispobj:
        target.set_selection(clip_mode='SELECTION',clip_MolDisp=name[17:])


    rebuild.UpdateDisplay(target=target,controllingWidget=self)
    self.updateLabel('extent')

#-------------------------------------------------------------------
  def handleClipRadius(self,name=''):
#-------------------------------------------------------------------
   if type(name) == str and name == 'clip_radius_gui':
      if not hasattr(self,'clip_gui'):
        self.clip_gui = QtGui.QDialog(self)
        self.clip_gui.setWindowTitle(self.tr('Clip radius for ')+self.parent().objectName())
        layout = QtGui.QVBoxLayout()
	self.clipSpin = QtGui.QDoubleSpinBox()
	buttons = QtGui.QDialogButtonBox()
	okButton = buttons.addButton(QtGui.QDialogButtonBox.Ok)
	applyButton = buttons.addButton(QtGui.QDialogButtonBox.Apply)
	cancelButton = buttons.addButton(QtGui.QDialogButtonBox.Cancel)
	self.connect(okButton,QtCore.SIGNAL("clicked(bool)"),functools.partial(self.handleClipRadius,self.clipSpin))
	self.connect(okButton,QtCore.SIGNAL("clicked(bool)"),self.clip_gui.hide)
	self.connect(applyButton,QtCore.SIGNAL("clicked(bool)"),functools.partial(self.handleClipRadius,self.clipSpin))
	self.connect(cancelButton,QtCore.SIGNAL("clicked(bool)"),self.clip_gui.hide)
	layout.addWidget(self.clipSpin)
	layout.addWidget(buttons)
        self.clip_gui.setLayout(layout)
      target = get_dispobj(name=self.objectName())
      if target and hasattr(target,"atom_clip_radius") and hasattr(self,"clipSpin"): self.clipSpin.setValue(float(target.atom_clip_radius))
      self.clip_gui.show()
      self.clip_gui.raise_()
   elif type(name) == str and name[:12]=='clip_radius_':
    ii = ['clip_radius_1','clip_radius_125','clip_radius_15','clip_radius_175','clip_radius_2','clip_radius_25','clip_radius_3','clip_radius_4'].index(name)
    val = float(['1.0','1.25','1.5','1.75','2.0','2.5','3.0','4.0'][ii])
    target = get_dispobj(name=self.objectName())
    #print name,val
    target.set_selection(atom_clip_radius=val)
    target.set_selection(point_clip_radius=val)
    #target.graphmod.obj.SetClipRadius(val)
    rebuild.UpdateDisplay(target=target,controllingWidget=self)
    self.updateLabel('extent')
   elif hasattr(name,"value"):
      target = get_dispobj(name=self.objectName())
      target.set_selection(atom_clip_radius=name.value())
      target.set_selection(point_clip_radius=name.value())
      self.updateLabel('extent')
      rebuild.UpdateDisplay(target=target,controllingWidget=self)
    

  def centreOn(self):
    target = get_dispobj(name=self.objectName())
    map_orig_cart = target.parent.clipper_map.GetOrigin()
    map_orig = (map_orig_cart.get_x(),map_orig_cart.get_y(),map_orig_cart.get_z())
    MAINWINDOW().glWidget.centreOn(map_orig,glide=1)

#-------------------------------------------------------------------      
  def getActionDef(self,name,**info):
#-------------------------------------------------------------------
     # Need to do contour slice details
     target = get_dispobj(name=self.objectName())

     if hasattr(target.parent,"is_em_map") and target.parent.is_em_map and name == 'centre_on':
       return dict (
       text = self.tr("Centre on"),
       slot = self.centreOn,
       toolTip = self.tr('Centre on')
       )
    
     if name =='contour_details':
        return dict (
        text = self.tr('Contour slice details..'),
        slot = self.handleContourSlice,
        )
     if name[0:14] =='surface_style_':
        def c(): return int(getattr(target,'surface_style','')==name)
        target = get_dispobj(name=self.objectName())
        ii = target.surface_style_alias.index(name)
        #print 'MapDisp.getActionDef',name,ii,checked
        return dict (
        checkable = 1,
        checked = c,
        group = 'surface_style',
        text = target.surface_style_menu[ii],
        slot = guiUtils.partial(self.handleSurfaceStyle,name),
        toolTip = self.tr('Set contour drawing style' ))
           
     if name[0:9] =='clip_sel_':
        def c():
          if name == 'clip_sel_none' and target.clip_mode == 'OFF':
            return 1
          elif name == 'clip_sel_point' and target.clip_mode == 'POINT':
            return 1
          elif target.clip_mode == 'SELECTION' and target.clip_MolDisp == name[17:]:
            return 1
          else:
            return 0

        if name == 'clip_sel_none':
          text = 'None'
        elif name == 'clip_sel_point':
          text = 'Point ..'
        else:
          dispobj = get_dispobj(name= name[17:])
          def t(): return dispobj.parent.name_label + ' ' + dispobj.get_selection_label()
          text = t
        return dict (
        checkable = 1,
        checked= c,
        text = text,
        slot = guiUtils.partial(self.handleClipSelection,name),
        toolTip = self.tr('Clip the map contour to an atom selection or point'))
      
     if name =='clip_radius_gui':
        return dict (
        group = 'clip_radius',
        checkable = 0,
	# checked = ?
        text = 'Select..',
        slot = guiUtils.partial(self.handleClipRadius,name),
        toolTip = self.tr('Set the clipping cutoff distance (A)'))
      
     elif name[0:12] =='clip_radius_':
        def c(): return int(getattr(target,'atom_clip_radius')== float(text))
        ii = ['clip_radius_1','clip_radius_125','clip_radius_15','clip_radius_175','clip_radius_2','clip_radius_25','clip_radius_3','clip_radius_4'].index(name)
        text = ['1.0','1.25','1.5','1.75','2.0','2.5','3.0','4.0'][ii]
        return dict (
        checkable = 1,
        checked = c,
        group = 'clip_radius',
        text = text,
        slot = guiUtils.partial(self.handleClipRadius,name) )

     if name =='extent_gui':
        return dict (
        checkable = 0,
	# checked = ?
        group = 'extent',
        text = self.tr('Select..'),
        slot = guiUtils.partial(self.handleExtent,name),
        toolTip = self.tr('Set the extent of the map contour (A)'))
      
     elif name[0:7] =='extent_':
        def c(): return int(getattr(target,'radius')== int(name[7:]))
        ii = ['extent_5','extent_10','extent_20'].index(name)
        return dict (
        checkable = 1,
        checked = c,
        group = 'extent',
        text = ['5','10','20'][ii],
        slot = guiUtils.partial(self.handleExtent,name),
        toolTip = self.tr('Set the entent of the map contour (A)'))

     if hasattr(target.parent,"is_em_map") and target.parent.is_em_map and name == 'colour_by_radius_greyscale':
        import xmapview
        def c(): return target.graphmod.obj.GetColourByRadius()==xmapview.COLOUR_BY_RADIUS_GREYSCALE
        def d():
          target.colour_by_radius=xmapview.COLOUR_BY_RADIUS_GREYSCALE
          target.graphmod.obj.SetColourByRadius(xmapview.COLOUR_BY_RADIUS_GREYSCALE)
          target.graphmod.obj.update_map_triangles()
          target.set_colour("Greyscale")
          self.updateLabel('colour')
          rebuild.UpdateDisplay()
        return dict (
        text = self.tr('Greyscale ramp'),
        toolTip = self.tr('Colour by shades of grey outwards from centre.'),
        slot = d,
        checkable = 1,
        group='map_colour',
        checked = c,
        )

     if hasattr(target.parent,"is_em_map") and target.parent.is_em_map and name == 'colour_by_radius_colour':
        import xmapview
        def c(): return target.graphmod.obj.GetColourByRadius()==xmapview.COLOUR_BY_RADIUS_COLOUR
        def d():
          target.colour_by_radius=xmapview.COLOUR_BY_RADIUS_COLOUR
          target.set_colour("Rainbow")
          target.graphmod.obj.SetColourByRadius(xmapview.COLOUR_BY_RADIUS_COLOUR)
          target.graphmod.obj.update_map_triangles()
          self.updateLabel('colour')
          rebuild.UpdateDisplay()
        return dict (
        text = self.tr('Colour ramp'),
        toolTip = self.tr('Colour by rainbow outwards from centre.'),
        slot = d,
        checkable = 1,
        group='map_colour',
        checked = c,
        )

     if name == 'colour_browser':
        import xmapview
        def c(): return target.graphmod.obj.GetColourByRadius()==xmapview.COLOUR_BY_RADIUS_NONE
        return dict (
        text = self.tr('Colour browser..'),
        toolTip = self.tr('Choose a single colour'),
        slot = self.colour_browser,
        checkable = 1,
        group='map_colour',
        checked = c,
        )


     return displayTable.GDispObj.getActionDef(self,name=name,target=target)

#----------------------------------------------------------------------
  def  set_browser_colour(self,colour=''):
#----------------------------------------------------------------------
    #print "ColourSelected set_browser_colour",colour
    if colour:
      target = get_dispobj(name=self.objectName())
      if hasattr(target.parent,"is_em_map") and target.parent.is_em_map:
        import xmapview
        target.colour_by_radius=xmapview.COLOUR_BY_RADIUS_NONE
        target.graphmod.obj.SetColourByRadius(xmapview.COLOUR_BY_RADIUS_NONE)
        target.graphmod.obj.update_map_triangles()
      target.set_colour(colour)
      print  target.graphmod.obj.GetColourByRadius()
      self.updateLabel('colour')
      rebuild.UpdateDisplay()


#----------------------------------------------------------------------
  def update(self):
#----------------------------------------------------------------------

    if hasattr(self,'sliceDetails'):
      pass

    displayTable.GDispObj.update(self)
 
#----------------------------------------------------------------------
class GMolData(displayTable.GDataObj):
#----------------------------------------------------------------------
  def __init__(self,parent,table=None,name='',label=''):
    #print "GMolData name",name,self,parent
    displayTable.GDataObj.__init__(self,parent,table=table,name=name,label=label)
    self.iconButton.setToolTip(self.tr('Tools for model data object'))

#----------------------------------------------------------------------
  def delete(self):
#----------------------------------------------------------------------
    displayTable.GDataObj.delete(self)
    MAINWINDOW().removeAnimationHandler('Animation of '+self.objectName())

    
#----------------------------------------------------------------------
  def getGuiDef(self,name='icon',**info):
#----------------------------------------------------------------------

    if name == 'icon':
      return ['data_visible', 'data_centre_on','picture_wizard', 'copy_from','add_moldisp',
       [self.tr('Add display object'),'add_surface','add_hbonds','add_contacts','add_annotation'],
       [self.tr('File save/restore'), 'save', 'save_with_screen_trans', 'rename_to_file_name', 'restore'],'data_list_data',
       [self.tr('Structure definition'),'load_warnings','list_secstr','edit_secstr','load_DSSP','edit_restypes','edit_ciffiles','edit_bonds','edit_links','list_charges','aromatic','show_2d_picture'],
       [self.tr('Transform coordinates'),'move','transformation_matrix','undo_transform'],'symmetry_mates','create_crystal_from_dataobj',
       [self.tr('Animation'),'load_animation','run_animation'],
       [self.tr('Clone'),'data_clone','data_clone_dispobj'],'data_delete']

    else:
      return displayTable.GDataObj.getGuiDef(self,name=name)

#----------------------------------------------------------------------
  def addHBondsContactsInteractively(self,target,style):
#----------------------------------------------------------------------
    hb = self.add_dispobj([target,style])
    target = get_dispobj(name=hb.objectName())
    if not target:
      return
    """
    if hasattr(target,"SelHandle1") and hasattr(target.SelHandle1,"setCommand") and callable(target.SelHandle1.setCommand):
      target.SelHandle1.setCommand("monomers")
    """
    import rebuild
    if style == "HBonds" and hasattr(target,"SelHandle2") and hasattr(target.SelHandle2,"setCommand") and callable(target.SelHandle2.setCommand):
      target.SelHandle1.setSelParams({'select':'cid','cid':''})
      target.SelHandle2.setSelParams({'select':'cid','cid':'all'})
      target.set_reapply_selection()
      hb.updateLabel('selection1')
      hb.updateLabel('selection2')
    elif style == "Contacts" and hasattr(target,"SelHandle2") and hasattr(target.SelHandle2,"setSelParams") and callable(target.SelHandle2.setSelParams):
      target.SelHandle1.setSelParams({'select':'cid','cid':''})
      target.SelHandle2.setSelParams({'select':'cid','cid':'all'})
      target.set_reapply_selection()
      hb.updateLabel('selection1')
      hb.updateLabel('selection2')
    if hb is not None and hasattr(hb,"atom_selection_browser") and callable(hb.atom_selection_browser):
      hb.atom_selection_browser("sel1")
    rebuild.UpdateDisplay()

#----------------------------------------------------------------------
  def getActionDef(self,name,**info):
#----------------------------------------------------------------------    
    target = get_dataobj(name=self.objectName())
    if not target: return
    target = target[0]
    
    
    if name == 'data_centre_on':
      return dict (
      text = self.tr("Centre on"),
      slot = self.centreOn
      )
    
    elif name == 'picture_wizard':
      return dict (
      text = self.tr("Picture wizard.."),
      slot = self.drawingStyleGui,
      toolTip = self.tr('Set the display style for the model')
      )
    
    elif name == 'copy_from':
      return dict (
      text = self.tr("Copy picture style from.."),
      slot = self.copyPictureStyle,
      toolTip = self.tr('Copy display objects from another loaded model')
      )
    
    elif name == 'add_moldisp':
      return dict (
      text = self.tr("Add model display object"),
      slot = guiUtils.partial(self.add_dispobj,[target,'MolDisp']),
      toolTip = self.tr('Add a model display object')
      )
            
    elif name == 'save':
      return dict (
      text = self.tr("Save to file"),
      slot = self.save,
      enabled = 1)
    
    elif name == 'rename_to_file_name':
      return dict (
      text = self.tr("Rename to file name"),
      slot = self.rename_to_file_name,
      enabled = 1)
    
    elif name == 'save_with_screen_trans':
      return dict (
      text = self.tr("Save with screen transformation"),
      slot = self.save_with_screen_trans,
      enabled = 1)
    
    elif name == 'restore':
      return dict (
      text = self.tr("Restore from file"),
      slot = self.restore_data,
      enabled = 0)

    elif name == 'add_surface':
      return dict (
      text = self.tr("Surface"),
      slot = guiUtils.partial(self.add_dispobj,[target,'SurfaceDispobj'] ),
      toolTip = self.tr('Add a surface display object for this model')  )
    
    elif name == 'add_hbonds':
      return dict (
      text = self.tr("HBonds"),
      slot = guiUtils.partial(self.addHBondsContactsInteractively,target,'HBonds'),
      toolTip = self.tr('Add hydrogen bond display object for this model') )
    
    elif name == 'add_contacts':
      return dict (
      text = self.tr("Contacts"),
      slot = guiUtils.partial(self.addHBondsContactsInteractively,target,'Contacts'),
      toolTip = self.tr('Add close contact display object for this model') )
    
    elif name == 'add_annotation':
      return dict (
      text = self.tr("Annotation"),
      slot = guiUtils.partial(self.add_dispobj,[target,'Annotation']),
      toolTip = self.tr('Add annotation to this model') )


    elif name == 'symmetry_mates':
      return dict (
      text = self.tr("Generate symmetry mates.."),
      slot = self.symmetryMatesGui,
      toolTip = self.tr('Show selected symmetry related copies')
      )

    elif name == 'create_crystal_from_dataobj':
      return dict (
      text = self.tr("Create crystal object"),
      slot = self.createCrystal,
      toolTip = self.tr('Generate fast symmetry')
      )

      
    elif name == 'load_animation':
      return dict (text = self.tr('Load new animation'),
                   toolTip = self.tr("Load coordinates from PDB file to create animation"),
                   slot = self.drawLoadAnimationGui,
                   enabled = 1
                   )
    
    elif name == 'run_animation':
      def e():
        aobj = getattr(target,'animation',None)
        if aobj:
          return 1
        else:
          return 0
        
      return dict (text = self.tr('Run animation'),
                   toolTip = self.tr("Run currently loaded animation"),
                   slot = self.drawAnimationGui,
                   enabled = e
                   )

    elif name == 'move':
      def c():
        if self.status==1:
          return 1
        else:
          return 0
      
      return dict (
      text = self.tr('Move ')+self.objectName(),  
      slot = self.toggleMoving,
      checkable = 1,
      checked = c,
      deleteLater = 0 )
    
    elif name == 'transformation_matrix':
      return dict (
      text = self.tr('Enter transformation'),
      toolTip = self.tr('View or change the current transformation matrix'),
      slot = self.transformationMatrixGui
      )

    elif name == 'undo_transform':
      def e(): return self.isTransformed()
      return dict (
        text = self.tr('Undo transform'),
        slot = self.undoTransformation,
        enabled = e,
        deleteLater = 0
        )
    
    elif name == 'load_warnings':
      return dict (
        text = self.tr('Show load warnings'),
        toolTip = self.tr('List any warning messages from loading the model'),
        slot = self.loadWarnings
        )
    
    elif name == 'list_secstr':
      return dict (
        text = self.tr('List secondary structure'),
        toolTip = self.tr('List all residues and their secondary structure assignment'),
        slot = self.listSecondaryStructure
        )

    elif name == 'aromatic':
      def c(): return int(target.show_aromatic_rings == 1)
      return dict (
        text = self.tr('Calculate aromatic rings.'),
        toolTip = self.tr('Determine aromaticity in conjugated rings.'),
        checkable = 1,
        checked = c,
        slot = guiUtils.partial(target.toggleAromaticity),
        )
    
    elif name == 'show_2d_picture':
      return dict (
        text = self.tr('Show 2D ligand pictures..'),
        toolTip = self.tr('Show 2-D representation of ligands, etc.'),
        slot = self.show2DList
        )
    
    elif name == 'list_charges':
      return dict (
        text = self.tr('List charges'),
        toolTip = self.tr('List charges currently assignd to model'),
        slot = self.listCharges
        )
    
    elif name == 'edit_secstr':
      return dict (
        text = self.tr('Edit secondary structure'),
        toolTip = self.tr('Override automatic secondary structure assignment'),
        slot = self.editSecondaryStructure
        )
    elif name == 'load_DSSP':
      return dict (
        text = self.tr('Load DSSP secondary str.'),
        toolTip = self.tr('Use secondary structure from DSSP output file'),
        slot = self.loadDSSP
        )
    elif name == 'edit_ciffiles':
      return dict (
        text = self.tr('Specify cif dictionaries'),
        toolTip = self.tr('Specify custom cif dictionary files to describe bonding in ligands, etc.'),
        slot = self.editCIFFiles
        )
    elif name == 'edit_restypes':
      return dict (
        text = self.tr('Edit residue type assignment'),
        toolTip = self.tr('Assign residue type'),
        slot = self.editRestypes
        )
    elif name == 'edit_bonds':
      return dict (
        text = self.tr('Edit bonds'),
        toolTip = self.tr('Add or delete bonds in structure'),
        slot = self.editBonds
        )
    elif name == 'edit_links':
      return dict (
        text = self.tr('Add inter-residue links'),
        toolTip = self.tr('Define possible inter-residue bonds'),
        slot = self.editLinks
        )
    elif name == 'custom_monomer_library':
      return dict (
        text = self.tr('Use monomer library'),
        toolTip = self.tr('Use alternative monomer library'),
        enabled = 0
        )

   # print "GMolDisp getActionDef target",target
    return displayTable.GDataObj.getActionDef(self,name,target=target)

  def createCrystal(self):
    import Crystal
    xtl = CRYSTALMANAGER().add_object()
    xtl.set_style('CONTINUOUS',force=1)
    if MAINWINDOW() and hasattr(MAINWINDOW(),"MGDisplayTable"):
      MAINWINDOW().MGDisplayTable.addDispObj(object_type='Crystal',name=xtl.name)
    target = get_dataobj(name=self.objectName())[0]
    xtl.set_source(target.name)
    target.setMasterCrystal(xtl.name)
    if MAINWINDOW() and hasattr(MAINWINDOW(),"glWidget"):
      rpos = MAINWINDOW().glWidget.rpos
      rpos = (-rpos[0],-rpos[1],-rpos[2])
      MAINWINDOW().glWidget.centreOn(rpos,glide=0)

  def isTransformed(self):
    target = get_dataobj(name=self.objectName())[0]
    ii = target.molHnd.GetIsTransformed()
    return ii

#----------------------------------------------------------------------    
  def rename_to_file_name(self):
#----------------------------------------------------------------------    
    target = get_dataobj(name=self.objectName())[0]

    name = os.path.basename(os.path.splitext(target.filename[2])[0])
    if name:
      target.renameuniquename(name,target.name)
    self.updateLabel()
    DISPLAYTABLE().update(all=1)

#----------------------------------------------------------------------    
  def save_with_screen_trans(self):
#----------------------------------------------------------------------    
    saveGui=mgWidgets.MGSaveFileDialog(self,'Save coordinates',[ [ "Coordinate file (*.pdb *.cif)", 'coordinate']])
    self.connect(saveGui,QtCore.SIGNAL('save'),self.handleSaveWithTrans)
    saveGui.exec_()
 
#----------------------------------------------------------------------    
  def save(self):
#----------------------------------------------------------------------    
    saveGui=mgWidgets.MGSaveFileDialog(self,'Save coordinates',[ [ "Coordinate file (*.pdb *.cif)", 'coordinate']])
    self.connect(saveGui,QtCore.SIGNAL('save'),self.handleSave)
    saveGui.exec_()

#----------------------------------------------------------------------    
  def handleSaveWithTrans(self,filename):
#----------------------------------------------------------------------    
    if MAINWINDOW() and hasattr(MAINWINDOW(),"glWidget"):
       import pygl_coord
       import mmdb2 as mmdb
       glWidget = MAINWINDOW().glWidget
       vtransp = glWidget.rpos
       vtrans1 = [0,0,0]
       vtrans2 = [vtransp[0],vtransp[1],vtransp[2]]
       theMat = glWidget.quat.getMatrix()
       mat = theMat.GetAsDoubleVectors()
       vrot2 = [ mat[0][0], mat[0][1],mat[0][2],
                mat[1][0], mat[1][1],mat[1][2],
                mat[2][0], mat[2][1],mat[2][2]]
       vrot1 = [ 1,0,0,
                0,1,0,
                0,0,1]
       d = data(self.objectName())
       selHnd = d.molHnd.NewSelection()
       d.molHnd.SelectAtoms(selHnd, 0,"*",mmdb.ANY_RES,"*",mmdb.ANY_RES,"*","*","*","*","*",mmdb.SKEY_OR )
       coc = pygl_coord.CartesianPtr(d.molHnd.CentreOfCoordinatesAsCartesian(selHnd))
       com = pygl_coord.CartesianPtr(d.molHnd.CentreOfMassAsCartesian(selHnd))
       d.molHnd.DeleteSelection(selHnd)
       old_transform = d.molHnd.GetTransform()
       old_filename = d.filename
       d.molHnd.SetTransform(vrot1,vtrans1,False)
       vt2c = theMat*pygl_coord.Cartesian(vtrans2)
       vtrans2 = [vt2c.get_x(),vt2c.get_y(),vt2c.get_z()] 
       d.molHnd.SetTransform(vrot2,vtrans2,False)
       selHnd = d.molHnd.NewSelection()
       d.molHnd.SelectAtoms(selHnd, 0,"*",mmdb.ANY_RES,"*",mmdb.ANY_RES,"*","*","*","*","*",mmdb.SKEY_OR )
       coc = pygl_coord.CartesianPtr(d.molHnd.CentreOfCoordinatesAsCartesian(selHnd))
       com = pygl_coord.CartesianPtr(d.molHnd.CentreOfMassAsCartesian(selHnd))
       d.molHnd.DeleteSelection(selHnd)
       rv = d.save_file(filename=filename)
       if rv:
         QtGui.QMessageBox.warning(None,'Error saving to file','Error writing file '+filename)
       d.molHnd.SetTransform(old_transform,True)
       d.setFilename(old_filename)

#----------------------------------------------------------------------    
  def handleSave(self,filename):
#----------------------------------------------------------------------    
    #print 'handleSave',filename
    rv = data(self.objectName()).save_file(filename=filename)
    if rv:
       QtGui.QMessageBox.warning(None,'Error saving to file','Error writing file '+filename)

#----------------------------------------------------------------------    
  def transformationMatrixGui(self):
#----------------------------------------------------------------------    
    target = data(self.objectName())
    if not target: return
    gui = self.findChild(QtGui.QDialog,'transformationMatrixGui')
    if gui:
      gui.show()
      gui.raise_()
    else:

      gui = mgWidgets.TransformMatrixDialog(self,title=self.objectName()+' transformation matrix')
      gui.setObjectName('transformationMatrixGui')
      self.connect(gui,QtCore.SIGNAL('transformationChanged'),self.applyTransformation)
      self.connect(gui,QtCore.SIGNAL('transformationUndone'),self.undoTransformation)
      gui.show()

    self.resetTransformationMatrixGui()

#----------------------------------------------------------------------    
  def update(self):
#----------------------------------------------------------------------    
    gui = self.findChild(QtGui.QDialog,self.objectName()+'SymmetryMates')
    #print 'GMolData.update symmates',gui
    if gui: gui.loadData()
    displayTable.GDataObj.update(self)
    
#----------------------------------------------------------------------    
  def resetTransformationMatrixGui(self):
#----------------------------------------------------------------------    
    gui = self.findChild(QtGui.QDialog,'transformationMatrixGui')
    if not gui: return
    target = data(self.objectName())
    if not target: return
  
    trmat = target.molHnd.GetTransform()
    #print 'GMolData.transformationMatrixGui',trmat

    gui.setParams(rotation= (trmat[0],trmat[1],trmat[2],
                             trmat[4],trmat[5],trmat[6],
                             trmat[8],trmat[9],trmat[10]),
                  translation = (trmat[3],trmat[7],trmat[11]))


#----------------------------------------------------------------------    
  def updateGuiAfterTransformation(self):
#----------------------------------------------------------------------    
    ''' The MolData object has been moved (eg by Superpose) and we need to
    make sure the transformationMatrixGui is updated'''
    target = data(self.objectName())
    if not target: return
    self.resetTransformationMatrixGui()
    target.update_dependents(attribute='transform')


#----------------------------------------------------------------------    
  def applyTransformation(self):
#----------------------------------------------------------------------
    target = data(self.objectName())
    if not target: return
    gui = self.findChild(QtGui.QDialog,'transformationMatrixGui')
    if not gui: return
    params = gui.getParams()
    if params.has_key('translation') and params.has_key('rotation'):
      if params.has_key('transmode') and params['transmode'] == 'relative':
        translation = params['translation']
        rotation = params['rotation']
        if MAINWINDOW() and hasattr(MAINWINDOW(),"glWidgets"):
           import pygl_coord
           quat = pygl_coord.Quat(MAINWINDOW().glWidgets[0].quat)
           mat2 = quat.getMatrix()
           mat = pygl_coord.matrix(4,4)
           mat[0][0] = rotation[0]
           mat[0][1] = rotation[1]
           mat[0][2] = rotation[2]
           mat[1][0] = rotation[3]
           mat[1][1] = rotation[4]
           mat[1][2] = rotation[5]
           mat[2][0] = rotation[6]
           mat[2][1] = rotation[7]
           mat[2][2] = rotation[8]
           mat[3][3] = 1.0
	   prod = mat2.Inverse()*mat*mat2
           rotation[0] = prod[0][0]
           rotation[1] = prod[0][1]
           rotation[2] = prod[0][2]
           rotation[3] = prod[1][0]
           rotation[4] = prod[1][1]
           rotation[5] = prod[1][2]
           rotation[6] = prod[2][0]
           rotation[7] = prod[2][1]
           rotation[8] = prod[2][2]
           transC = pygl_coord.Cartesian(translation[0],translation[1],translation[2])
           transCrot = mat2.Inverse()*transC
           translation[0] = transCrot.get_x()
           translation[1] = transCrot.get_y()
           translation[2] = transCrot.get_z()
           target.molHnd.SetTransform(rotation,translation, True)
      else:
        target.molHnd.SetTransform(params['rotation'],params['translation'], True)
      target.update_dependents(attribute='transform')

      import rebuild
      #rebuild.UpdateDisplay(data_target=target,controllingWidget=self)
      rebuild.UpdateDisplay(controllingWidget=self)

#----------------------------------------------------------------------
  def copyPictureStyle(self):
#----------------------------------------------------------------------
    if not hasattr(self,'copyPictureStyleGui'):
      import modelUtils
      self.copyPictureStyleGui = modelUtils.AsDataObjGui(self,exclude_list=[str(self.objectName())])
      self.copyPictureStyleGui.setWindowTitle('Copy picture style from '+str(self.objectName()))
      self.connect(self.copyPictureStyleGui,QtCore.SIGNAL('apply'),self.handleCopyPictureStyle)
    self.copyPictureStyleGui.show()

#----------------------------------------------------------------------
  def handleCopyPictureStyle(self,args):
#----------------------------------------------------------------------
    if len(args)!=3: return
    mode = str(args[0].toString())[9:]
    dataobj = str(args[1].toString())
    clear = int(args[2].toInt()[0])
    #print 'handleCopyPictureStyle',mode,dataobj,clear
    target = data(self.objectName())
    rv = target.copy_display(copy_from=dataobj,clear=clear)
    if rv[0]:
      if rv[1]: QtGui.QMessageBox.warning(self,self.tr('Copy picture style ')+target.name_label,rv[1])
    else:
      import rebuild
      #rebuild.UpdateDisplay(data_target=target,controllingWidget=self)
      rebuild.UpdateDisplay(controllingWidget=self)
      self.updateDispObj()

#----------------------------------------------------------------------    
  def undoTransformation(self):
#----------------------------------------------------------------------
    #print 'MolData.undoTransformation'
    target = data(self.objectName())
    if not target: return
    target.molHnd.UnSetTransform(True)
    target.update_dependents(attribute='transform')
    import rebuild
    #rebuild.UpdateDisplay(data_target=target,controllingWidget=self)
    rebuild.UpdateDisplay(controllingWidget=self)

    self.updateGuiAfterTransformation()
    
#----------------------------------------------------------------------    
  def drawingStyleGui(self):
#----------------------------------------------------------------------    

    gui = self.findChild(QtGui.QDialog,'drawingStyleGui')
    if gui:
      gui.show()
      gui.raise_()
      return

    import pictureWizardGui
    gui = pictureWizardGui.pictureWizardGui(self,moldata_name=self.objectName())
    gui.setObjectName('drawingStyleGui')

    #self.connect(apply,QtCore.SIGNAL('released()'),self.handleDrawingStyle)
    #self.connect(close,QtCore.SIGNAL('released()'),dialog.close)

#----------------------------------------------------------------------    
  def handleDrawingStyle(self):
#----------------------------------------------------------------------    
    widget = self.findChild(QtGui.QWidget,'drawingStyle')
    if not widget: return
    self.drawingStyle = widget.getStyle()

    widget = self.findChild(QtGui.QWidget,'drawingStyle_delete')
    delete = int(widget.isChecked())
    
    #print "handleDrawingStyle",self.drawingStyle,delete,self.body.children()

    if delete:
      dellist = []
      for dispobj in self.body.children():
        dellist.append(dispobj.objectName())
      self.table.deleteDispObj(dellist)

    target = get_dataobj(name=self.objectName())[0]
    target.applyDrawingStyle(drawing_style=self.drawingStyle,keep_display_objects=1-delete)
    rebuild.UpdateDisplay(target=target,controllingWidget=self)

    self.updateDispObj()


#----------------------------------------------------------------------    
  def centreOn(self):
#----------------------------------------------------------------------    
    # Centre on all visible display objects - will limit this
    # to MolDisp
    import MGApplication
    target = get_dataobj(name=self.objectName())[0]
    dispobj_list = target.get_dispobj(object_type='MolDisp')
    
    if len(dispobj_list) == 0:
      return
    elif len(dispobj_list) == 1:
      MGApplication.GetMainWindow().centreOn(molHnd = target.molHnd,
                        selHnd = dispobj_list[0].SelHandle.getSelHnd())
    else:
      # Find the visible objects
      vis_obj = []
      for obj in dispobj_list:
        if obj.visible: vis_obj.append(obj)
      # No visible objects - not sure what user is expecting here but
      # just centre on all of the objects
      if len(vis_obj) == 0: vis_obj = dispobj_list

      if len(vis_obj) == 1:
        MGApplication.GetMainWindow().centreOn(molHnd = target.molHnd,
                        selHnd = vis_obj[0].SelHandle.getSelHnd())
      else:
        import mmdb2 as mmdb
        selHnd = target.molHnd.NewSelection()
        for obj in vis_obj:
          target.molHnd.Select(selHnd,mmdb.STYPE_ATOM,obj.SelHandle.getSelHnd(),mmdb.SKEY_OR)
        
        MGApplication.GetMainWindow().centreOn(molHnd = target.molHnd,
                        selHnd = selHnd)
        target.molHnd.DeleteSelection(selHnd)


  def restore_data(self):
    pass

#-------------------------------------------------------------------
  def drawLoadAnimationGui(self):
#-------------------------------------------------------------------
    if not hasattr(self,'loadAnimationGui'):
      self.loadAnimationGui = MGSimpleDialog.MGSimpleDialog(self)
      self.loadAnimationGui.setWindowTitle(self.tr("Open Animation"))
      layout = QtGui.QVBoxLayout()

      # The following was necessary if this functionality was implemented as a plugin
      #line_layout =  QtGui.QHBoxLayout()
      #widget = QtGui.QLabel('Attach animation to currently loaded model',self)
      #line_layout.addWidget(widget)   
      #self.dataobjCombo = mgWidgets.mgDataObjCombo(object_type='MolData',parent=self)
      #line_layout.addWidget(self.dataobjCombo)
      #layout.addItem(line_layout)
       
      widget = mgWidgets.MGFileDialog(self)
      layout.addWidget(widget)
      filedialog = widget.getFileDialog()      
      filedialog.setFileMode(filedialog.ExistingFiles)
      filter_list = [self.tr("The FIRST coordinate file in series") + " (*.pdb *.cif)",
                   self.tr("Coordinate file containing multiple models") + " (*.pdb *.cif)" ]
      filedialog.setNameFilters(filter_list,all=0)

      self.loadAnimationGui.setLayout(layout)

      self.connect(filedialog, QtCore.SIGNAL('filesSelected (const QStringList&)'), functools.partial(self.loadAnimation,filedialog.selectedNameFilter))

    self.loadAnimationGui.show()

#-------------------------------------------------------------------
  def loadAnimation(self,filterCommand,selectedFiles):
#-------------------------------------------------------------------
    if len(selectedFiles)>1:
       QtGui.QMessageBox.warning(None,self.tr('Error in Open Animation'),self.tr('Please select only the FIRST coordinate file.'))
       return

    if len(selectedFiles)<1:
      return
    
    target = get_dataobj(name=self.objectName())[0]
    if hasattr(target,'animation'): target.animation.delete()

    import Animation

    params = {}
    params['filename'] = ['FULLPATH',str(selectedFiles[0]),'']
    if filterCommand() == self.tr("Coordinate file containing multiple models") + " (*.pdb *.cif)":
      params['file_format'] = 'NMR_models'
    target.animation = Animation.Animation(parent=target,params=params,load=0)
    rv = target.animation.loaddata()
    if rv:
      target.animation.delete()
    else:
      self.loadAnimationGui.hide()
      self.drawAnimationGui()

#-------------------------------------------------------------------
  def drawAnimationGui(self):
#-------------------------------------------------------------------
    if not hasattr(self,'animationGui'):
      target = get_dataobj(name=self.objectName())[0]
      self.animationGui=MGSimpleDialog.MGSimpleDialog(self)
      # Why does this not work?
      self.animationGui=MGSimpleDialog.MGSimpleDockDialog(self,defaultDockArea=QtCore.Qt.RightDockWidgetArea,tabify=False)
      self.animationGui.setWindowTitle(self.tr("Animation of "+str(self.objectName())))
      self.animationGui.setMinimumHeight(160)

      layout = QtGui.QVBoxLayout()

      # Slider control of current frame
      range = target.animation.frame_range
      line_layout = QtGui.QHBoxLayout()
      widget = QtGui.QLabel(self.tr('Animation frame ('+str(range[0]+1)+'-'+str(range[1]+1)+'):'))
      line_layout.addWidget(widget)
      widget = mgWidgets.mgSlider(QtCore.Qt.Horizontal,self)
      widget.setRange(range[0]+1,range[1]+1,integer=1)
      current =  target.animation.current_frame
      widget.setValue(current[0]+1)
      widget.setObjectName('animation_frame')
      self.connect(widget,QtCore.SIGNAL("valueChanged(int)"),self.handleAnimationFrame)
      line_layout.addWidget(widget)
      layout.addLayout(line_layout)

      # Next frame forward or backward?
      line_layout = QtGui.QHBoxLayout()
      widget = QtGui.QLabel(self.tr('Run in direction'))
      line_layout.addWidget(widget)
      layout.addLayout(line_layout)
      dir_group = QtGui.QButtonGroup(self)
      widget = QtGui.QCheckBox(self.tr('forward'),self)
      widget.setObjectName('animation_forward')
      self.connect (widget,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.handleAnimation,'forward'))
      line_layout.addWidget(widget)
      dir_group.addButton(widget)
      widget = QtGui.QCheckBox(self.tr('backward'),self)
      widget.setObjectName('animation_backward')
      self.connect (widget,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.handleAnimation,'backward'))
      line_layout.addWidget(widget)
      line_layout.addStretch()
      dir_group.addButton(widget)

      # Animation speed
      line_layout = QtGui.QHBoxLayout()
      widget = QtGui.QLabel(self.tr('Animation time interval (ms):'))
      line_layout.addWidget(widget)
      widget = mgWidgets.animationIntervalWidget(self)
      line_layout.addWidget(widget)
      layout.addLayout(line_layout)

      buttonBox = QtGui.QDialogButtonBox(self)
      buttonBox.setOrientation(QtCore.Qt.Horizontal)
      #button = buttonBox.addButton(self.tr('&Close'),QtGui.QDialogButtonBox.DestructiveRole)
      #button.setAutoDefault(0)
      #self.connect (button,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.handleAnimation,'Close'))
      button = buttonBox.addButton('',QtGui.QDialogButtonBox.ActionRole)
      button.setIcon(QtGui.QIcon(os.path.join(os.environ["CCP4MG"],'qticons','actions','movie_play.svg')))
      button.setAutoDefault(0)
      button.setObjectName('animation_run')
      self.connect (button,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.handleAnimation,'run'))
      button = buttonBox.addButton('',QtGui.QDialogButtonBox.ActionRole)
      button.setIcon(QtGui.QIcon(os.path.join(os.environ["CCP4MG"],'qticons','actions','movie_frameadvance.svg')))
      button.setAutoDefault(0)
      self.connect (button,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.handleAnimation,'next'))    
      #button = buttonBox.addButton(self.tr('&Add legend'),QtGui.QDialogButtonBox.ActionRole)
      #button.setAutoDefault(0)
      #self.connect (button,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.handleAnimation,'legend'))    
      layout.addWidget(buttonBox)
      layout.addStretch(2)
      
      self.animationGui.setLayout(layout)

    self.updateAnimationGui()

    self.animationGui.UnClose()



#-------------------------------------------------------------------
  def handleAnimationFrame(self,frame=-1):
#-------------------------------------------------------------------
    #print "MolData.handleAnimation",frame
    if frame>0:
      get_dataobj(name=self.objectName())[0].animation.set_frame(frame=int(frame)-1)
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------
  def handleAnimation(self,mode=''):
#-------------------------------------------------------------------
    #print "GMolData.handleAnimation",mode
    if mode == 'close':
      MAINWINDOW().removeAnimationHandler(self.tr('Animation of ')+self.objectName())
      #get_dataobj(name=self.objectName())[0].animation.toggle_animation(0)
      self.animationGui.close()
    elif mode == 'next':
      widget = self.animationGui.findChild(mgWidgets.mgSlider,'animation_frame')
      get_dataobj(name=self.objectName())[0].animation.next_frame()
      rebuild.UpdateDisplay()
      self.update()
      self.updateAnimationGui()
    elif ['run','stop'].count(mode):
      #get_dataobj(name=self.objectName())[0].animation.toggle_animation(mode == 'run')
      button = self.animationGui.findChild(QtGui.QPushButton,'animation_run')
      # Reset the button text and signal
      button.blockSignals(True)
      self.disconnect (button,QtCore.SIGNAL('clicked()'),self.handleAnimation)
      button.blockSignals(False)
      if mode == 'run':
        MAINWINDOW().addAnimationHandler('Animation of '+self.objectName(),self.incrementAnimation)
        #button.setText(self.tr("&Stop animation"))
        button.setIcon(QtGui.QIcon(os.path.join(os.environ["CCP4MG"],'qticons','actions','movie_pause.svg')))
        self.connect (button,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.handleAnimation,'stop'))
      else:
        MAINWINDOW().removeAnimationHandler('Animation of '+self.objectName())
        #button.setText(self.tr("&Run animation"))
        button.setIcon(QtGui.QIcon(os.path.join(os.environ["CCP4MG"],'qticons','actions','movie_play.svg')))
        self.connect (button,QtCore.SIGNAL('clicked()'),guiUtils.partial(self.handleAnimation,'run'))
    elif mode == 'forward':
      get_dataobj(name=self.objectName())[0].animation.setIncrement(1)
    elif mode == 'backward':
      get_dataobj(name=self.objectName())[0].animation.setIncrement(-1)
    elif mode == 'legend':
      target = get_dataobj(name=self.objectName())[0]
      target.animation.add_legend()
      rebuild.UpdateDisplay(target=target,controllingWidget=self)
      
      
#-------------------------------------------------------------------
  def incrementAnimation(self):
#-------------------------------------------------------------------
    # Called from Timer to increment the animation
    get_dataobj(name=self.objectName())[0].animation.next_frame()
    self.updateAnimationGui()
    import rebuild
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------
  def updateAnimationGui(self):
#-------------------------------------------------------------------
    anim_obj=getattr(get_dataobj(name=self.objectName())[0],'animation',None)
    #print 'updateAnimationGui',anim_obj,anim_obj.getFrame()
    if anim_obj:
      self.animationGui.findChild(mgWidgets.mgSlider,'animation_frame').setValue(anim_obj.getFrame())
      if anim_obj.current_frame[1]==1:
        self.animationGui.findChild(QtGui.QCheckBox,'animation_forward').setChecked(1)
      else:
        self.animationGui.findChild(QtGui.QCheckBox,'animation_backward').setChecked(1)

  
#-------------------------------------------------------------------
  def listData(self):
#-------------------------------------------------------------------
    viewer = FILEVIEWER('data_listing')
    target = get_dataobj(name=self.objectName())[0]
    window = viewer.open(target.filename[2])
    if window:
      print 'listData',window
      window.setFont(style='fixed_width')
      self.connect(window,QtCore.SIGNAL('lineClicked'),self.handleListDataClick)
      self.connect(window,QtCore.SIGNAL('lineDoubleClicked'),self.handleListDataDoubleClick)

#-------------------------------------------------------------------
  def handleListDataDoubleClick(self,line):
#-------------------------------------------------------------------
    self.handleListDataSelection(line,mode='double')
                             
#-------------------------------------------------------------------
  def handleListDataClick(self,line):
#-------------------------------------------------------------------
    self.handleListDataSelection(line,mode='single')
    

#-------------------------------------------------------------------
  def handleListDataSelection(self,line='',cid='',mode='single'):
#-------------------------------------------------------------------
    #print 'GMolData.handleListDataSelection',line,mode
 
    molobj = data(self.objectName())
    if not molobj: return
    if len(line)>6 and line[0:4] == 'ATOM' or line[0:6] == 'HETATM':
      cid = data(self.objectName()).pdbATOM2cid(line)

    if not cid: return
    
    #print 'GMolData.handleListDataSelection',cid
    ret = molobj.parse_selection(command=cid)
    if ret[0]!=0: return
    if mode == 'double':
      MAINWINDOW().centreOn(molHnd=molobj.molHnd,selHnd=ret[1])

    # label first atom in selection
    atm_ptr=molobj.interpretAtomID(mol=molobj,selHnd=ret[1])
    #print 'GMolData.handleListDataSelection',atm_ptr
    if atm_ptr:
        dispobj = molobj.findDispobjContainingAtom(atm_ptr=atm_ptr)
        if dispobj:
           rv = PICKLABEL().addLabel(atm_ptr=atm_ptr,dispobj=dispobj)
           if rv: 
            import rebuild
            rebuild.UpdateDisplay()
    molobj.molHnd.DeleteSelection(ret[1])

#-------------------------------------------------------------------
  def pickInfo(self,event):
#-------------------------------------------------------------------
    target = data(self.objectName())
    pAtom = event.getPickedAtoms()[0]
    text = self.tr('Temp factor: ')+str(pAtom.tempFactor) + \
           self.tr(' Occupancy: ')+str(pAtom.occupancy) +'\n' + \
           self.tr('Charge: ')+str(pAtom.charge)  + \
           self.tr(' Atom energy type: ')+target.get_attribute('energy_type',PAtom=pAtom)
    displayTable.GDataObj.pickInfo(self,event,text)


#-------------------------------------------------------------------
  def loadWarnings(self):
#-------------------------------------------------------------------
    target = data(self.objectName())
    if not target: return
    FILEVIEWER('data_listing').loadText(target.load_warnings,self.objectName()+self.tr(' load warnings'),)
    
#-------------------------------------------------------------------
  def listSecondaryStructure(self):
#-------------------------------------------------------------------
    target = data(self.objectName())
    if not target: return
    text = target.filename[2]+'\n'+target.molHnd.PrintSecStructure()
    window = FILEVIEWER('data_listing').loadText(text,self.objectName()+self.tr(' secondary structure'))
    window.setFont(style='fixed_width')
    
#-------------------------------------------------------------------
  def show2DList(self):
#-------------------------------------------------------------------
    target = data(self.objectName())
    if not target: return
    dw = MAINWINDOW().findChild(MGSimpleDialog.MGSimpleDockDialog,"2D Ligand pictures of "+self.objectName())
    if dw is not None and hasattr(dw,"UnClose"):
      dw.UnClose()
      return
    if hasattr(target,"molHnd") and hasattr(target.molHnd,"GetMonomerSVGs"):
      svg_list = target.molHnd.GetMonomerSVGs()
      widget = MGSimpleDialog.MGSimpleDockDialog(self,defaultDockArea=QtCore.Qt.RightDockWidgetArea,tabify=True)
      layout = QtGui.QVBoxLayout()
      listWidget = QtGui.QListWidget()
      for key,svg in svg_list.items():
        listWidget.addItem(key)
      label = QtGui.QLabel()
      layout.addWidget(listWidget)
      layout.addWidget(label)
      def drawSVG(keyin):
        for key,svg in svg_list.items():
          if keyin == key:
            svgBA = QtCore.QString(str(svg)).toUtf8()
            renderer = QtSvg.QSvgRenderer(svgBA)
            maxWidth = 300
            ratio = float(renderer.defaultSize().width())/renderer.defaultSize().height()
            if 300*ratio > maxWidth:
              image = QtGui.QImage(maxWidth,int(maxWidth/ratio),QtGui.QImage.Format_ARGB32)
            else:
              image = QtGui.QImage(int(300*ratio),300,QtGui.QImage.Format_ARGB32)
            image.fill(0)
	    painter = QtGui.QPainter()
	    painter.begin(image)
            renderer.render(painter)
            painter.end()
            label.setPixmap(QtGui.QPixmap.fromImage(image))
      listWidget.currentTextChanged.connect(drawSVG)
      listWidget.setCurrentRow(0)
        
      widget.setLayout(layout)
      dbb = QtGui.QDialogButtonBox()
      layout.addWidget(dbb)
      centreButton = dbb.addButton("Centre on",QtGui.QDialogButtonBox.ActionRole)
      enlargeButton = dbb.addButton("Large view",QtGui.QDialogButtonBox.ActionRole)
      saveButton = dbb.addButton(QtGui.QDialogButtonBox.Save)

      def enlarge(truth):
        keyin = listWidget.currentItem().text()
        for key,svg in svg_list.items():
          if keyin == key:
            svgBA = QtCore.QString(str(svg)).toUtf8()
            renderer = QtSvg.QSvgRenderer(svgBA)
            maxWidth = 800
            maxHeight = 700
            ratio = float(renderer.defaultSize().width())/renderer.defaultSize().height()
            if maxHeight*ratio > maxWidth:
              if int(maxWidth/ratio) > maxHeight:
                image = QtGui.QImage(int(maxHeight*ratio),maxHeight,QtGui.QImage.Format_ARGB32)
              else:
                image = QtGui.QImage(maxWidth,int(maxWidth/ratio),QtGui.QImage.Format_ARGB32)
            else:
              image = QtGui.QImage(int(maxHeight*ratio),maxHeight,QtGui.QImage.Format_ARGB32)
            image.fill(0)
	    painter = QtGui.QPainter()
	    painter.begin(image)
            renderer.render(painter)
            painter.end()
            bigLabel = QtGui.QLabel()
            bigLabel.setPixmap(QtGui.QPixmap.fromImage(image))
            bigWidget = QtGui.QDialog()
            bigLayout = QtGui.QVBoxLayout()
            bigWidget.setLayout(bigLayout)
            bigLayout.addWidget(bigLabel)
            bigWidget.exec_()

      def saveSVG(truth):
        keyin = listWidget.currentItem().text()
        for key,svg in svg_list.items():
          if keyin == key:
            svgBA = QtCore.QString(str(svg)).toUtf8()
            renderer = QtSvg.QSvgRenderer(svgBA)
            ratio = float(renderer.defaultSize().width())/renderer.defaultSize().height()
            lineLayout = QtGui.QHBoxLayout()
            widthWidget = QtGui.QLineEdit()
            heightWidget = QtGui.QLineEdit()
            widthWidget.setText(str(renderer.defaultSize().width()))
            heightWidget.setText(str(renderer.defaultSize().height()))
            widthLabel = QtGui.QLabel("Width: ")
            heightLabel = QtGui.QLabel("Height: ")
            lineLayout.addWidget(widthLabel)
            lineLayout.addWidget(widthWidget)
            lineLayout.addWidget(heightLabel)
            lineLayout.addWidget(heightWidget)
            def widthEdited(text):
              try:
                w = int(str(text))
                heightWidget.setText(str(int(w/ratio)))
              except:
                pass
            def heightEdited(text):
              try:
                h = int(str(text))
                widthWidget.setText(str(int(h*ratio)))
              except:
                pass
            widthWidget.textEdited.connect(widthEdited)
            heightWidget.textEdited.connect(heightEdited)
            saveDialog = QtGui.QDialog()
            saveLayout = QtGui.QVBoxLayout()
            fileDialogMain = mgWidgets.MGFileDialog(self)
            fileDialog = fileDialogMain.getFileDialog()
            fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
            fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
            fileDialog.setConfirmOverwrite(True)
            def saveSVGFile(filename):
              try:
                w = int(str(widthWidget.text()))
                h = int(str(heightWidget.text()))
                if str(filename).endswith(".svg"):
                  f = open(str(filename),"w+")
                  f.write(str(svg))
                  f.close()
                else:
                  image = QtGui.QImage(w,h,QtGui.QImage.Format_ARGB32)
                  image.fill(0)
	          painter = QtGui.QPainter()
	          painter.begin(image)
                  renderer.render(painter)
                  painter.end()
                  image.save(filename)
                saveDialog.close()
              except:
                QtGui.QMessageBox.critical(None, "Failed to write image file", "Failed to write image file. Possibly problem with width or height?", QtGui.QMessageBox.Ok )
            self.connect(fileDialog, QtCore.SIGNAL('fileSelected(const QString&)'),saveSVGFile)
            saveLayout.addLayout(lineLayout)
            saveLayout.addWidget(fileDialogMain)
            saveDialog.setLayout(saveLayout)
            saveDialog.exec_()
            break

      def centreOn(truth):
        keyin = listWidget.currentItem().text()
        MAINWINDOW().setViewParams({'centre_MolData':target.name,'centre_selection':str(keyin)})

      enlargeButton.clicked.connect(enlarge)
      centreButton.clicked.connect(centreOn)
      saveButton.clicked.connect(saveSVG)

      widget.setWindowTitle("2D Ligand pictures of "+self.objectName())
      widget.UnClose()
      widget.setObjectName("2D Ligand pictures of "+self.objectName())
    
#-------------------------------------------------------------------
  def listCharges(self):
#-------------------------------------------------------------------
    target = data(self.objectName())
    if not target: return
    text = target.filename[2]+'\n'+target.molHnd.PrintCharges()
    window = FILEVIEWER('data_listing').loadText(text,self.objectName()+self.tr(' charges'))
    window.setFont(style='fixed_width')
    
#-------------------------------------------------------------------
  def editSecondaryStructure(self):
#-------------------------------------------------------------------
    target = data(self.objectName())
    if not target: return
    gui = self.findChild(QtGui.QDialog,self.objectName()+'ModelSecStrEditor')
    if not gui:
      import modelUtils
      gui = modelUtils.ModelSecStrEditor(self,target.name)
      gui.setObjectName(self.objectName()+'ModelSecStrEditor')
    gui.show()
    gui.raise_()
    return

#-------------------------------------------------------------------
  def loadDSSP(self):
#-------------------------------------------------------------------
    gui =  self.findChild(mgWidgets.MGOpenFileDialog,self.objectName()+'loadDSSP')
    if not gui:
      gui = mgWidgets.MGOpenFileDialog(self,title=self.tr('Open DSSP file'),filters=[self.tr('DSSP secondary structure file')+' (*.dssp)'])
      gui.setObjectName(self.objectName()+'loadDSSP')
      self.connect(gui, QtCore.SIGNAL('open'), self.handleLoadDSSP)
    #print 'GMolData.loadDSSP',gui
      
    gui.show()

#-------------------------------------------------------------------
  def handleLoadDSSP(self,filename):
#-------------------------------------------------------------------
    #print 'GMolData.handleLoadDSSP',filename
    target = data(self.objectName())
    if not target: return
    target.setDSSPFile([ 'FULLPATH',filename,filename])
    import rebuild
    rebuild.UpdateDisplay()
    
#-------------------------------------------------------------------
  def editCIFFiles(self):
#-------------------------------------------------------------------
    import modelUtils
    gui = self.findChild(modelUtils.editCIFFilesGui,str(self.objectName())+'editRestype')
    if not gui:
      import modelUtils
      gui = modelUtils.editCIFFilesGui(self,str(self.objectName()))
      gui.setObjectName(self.objectName()+'editRestype')

    gui.show()

#-------------------------------------------------------------------
  def editRestypes(self):
#-------------------------------------------------------------------
    import modelUtils
    gui = self.findChild(modelUtils.editRestypesGui,str(self.objectName())+'editRestype')
    if not gui:
      import modelUtils
      gui = modelUtils.editRestypesGui(self,str(self.objectName()))
      gui.setObjectName(self.objectName()+'editRestype')

    gui.show()

#-------------------------------------------------------------------
  def editBonds(self):
#-------------------------------------------------------------------
    import modelUtils
    gui = self.findChild(modelUtils.editBondsGui,str(self.objectName())+'editBonds')
    if not gui:
      import modelUtils
      gui = modelUtils.editBondsGui(self,str(self.objectName()))
      gui.setObjectName(self.objectName()+'editBonds')

    gui.show()
    
#-------------------------------------------------------------------
  def editLinks(self):
#-------------------------------------------------------------------
    import modelUtils
    gui = self.findChild(modelUtils.editLinksGui,str(self.objectName())+'editLinks')
    if not gui:
      import modelUtils
      gui = modelUtils.editLinksGui(self,str(self.objectName()))
      gui.setObjectName(self.objectName()+'editLinks')

    gui.show()
    
#-------------------------------------------------------------------
  def symmetryMatesGui(self):
#-------------------------------------------------------------------
    target = data(self.objectName())
    if not target: return
    gui = self.findChild(QtGui.QDialog,self.objectName()+'SymmetryMates')
    if not gui:
      if not target.model_symmetry.nofCrystalSymops():
        QtGui.QMessageBox.warning(self,self.tr('Symmetry mates for ')+target.name_label,
             self.tr('There is no crystal symmetry defined in this file'))
        return
      import modelUtils
      gui = modelUtils.SymmetryMatesGui(self,target.name)
      gui.setObjectName(self.objectName()+'SymmetryMates')
      self.connect(gui,QtCore.SIGNAL('nofModelsChanged'),guiUtils.partial(self.emit,QtCore.SIGNAL('nofModelsChanged')))
    gui.UnClose()
    return

#-------------------------------------------------------------------
  def handleSymmetryMatesChanged(self):
#-------------------------------------------------------------------
    self.emit(QtCore.SIGNAL('symmetryMatesChanged'))

#-------------------------------------------------------------------
  def handleSavedSelection(self,set=''):
#-------------------------------------------------------------------
    #print 'GMolData.handleSavedSelection',set
    if set == 'generic':
      for obj in get_dataobj(object_type='MolData'):
        DISPLAYTABLE().getDataObj(obj.name).handleSavedSelection()
    else:
      self.emit(QtCore.SIGNAL('savedNamedSelection'))

    
#-------------------------------------------------------------------
class GMolDisp(GAtomicDispObj):
#-------------------------------------------------------------------

  def __init__(self,parent,table=None,name=''):
    #print "GMolDisp name",name,self,parent
    GAtomicDispObj.__init__(self,parent,table=table,name=name,object_type='MolDisp')
    self.iconButton.setToolTip(self.tr('Tools for model display object'))
    self.type_label = 'Model display object'
    
    
#----------------------------------------------------------------------
  def getGuiDef(self,name='row',pickevent=None):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target:
      #print 'Can not find GMolDisp target',self.objectName()
      return []
    if name == 'row':
      return [ dict (name='selection', mode= 'MENU', getLabel=target.get_selection_label, getIcon=target.get_selection_icon ),
              dict (name ='colour', mode='MENU', getLabel=target.get_colour_label, getIcon=target.get_colour_icon ),
              dict (name='style', mode='MENU', getLabel=target.get_style_label, getIcon=target.get_style_icon )
             ]
    if name == 'icon':
      labels = [self.tr('Atom labels')]
      labels.extend(MolLabel.LABEL_SELECTION_ALIAS)
      labels.extend(['sep','labels_details'])
      menu = ['visible','centre_on','flash','transparency',labels,['Symmetry','apply_symmetry','draw_central','apply_biomolecule'],'custom_drawing_style']
      menu.extend(['list','savelist'])
      if ['atom_sas','res_sas','atom_buried','res_buried','secstr','interface'].count(target.model_colour.colour_mode): menu.append('list_colour_data')
      menu.extend(['clone','delete'])
      #menu.extend(['clone','delete'])
      return menu
    elif name == 'colour':
      menu = self.getAtomColourMenu(target,label='colour_')
      menu.extend(['sep',[self.tr('Stick colour'),'colour_stick_atom','colour_stick_colour'],'colour_legend'])
      return menu
    elif name == 'style':
      menu = []
      menu.extend(model.MolDisp.style_commands[:model.MolDisp.style_commands.index('FATWORM')+1])
      scaleMenu = ['Worm scaled by']
      for s in model.MolDisp.style_commands[model.MolDisp.style_commands.index('FATWORM')+1:]:
        if s.startswith('VARIABLEWORM'):
          scaleMenu.append(s)
      if len(scaleMenu)>1:
        menu.append(scaleMenu)
      for s in model.MolDisp.style_commands[model.MolDisp.style_commands.index('FATWORM')+1:]:
        if not s.startswith('VARIABLEWORM'):
          menu.append(s)
      menu.append('inter_dispobj_bond')
      return menu

    elif name == 'selection':
      target = get_dispobj(name=self.objectName())
      return self.getSelectionMenu(target,label='sel_')

    elif name == 'context' and pickevent:
      pass      

    else:
      return displayTable.GDispObj.getGuiDef(self,name=name,target=target)
    
#-------------------------------------------------------------------      
  def getActionDef(self,name,**info):
#-------------------------------------------------------------------
    import model_colour
    target = get_dispobj(name=self.objectName())

    if name == 'centre_on':
        return dict (
        text = self.tr("Centre on"),
        slot = self.centreOn,
        toolTip = self.tr('Centre on this display object')
      )

    if name[0:7] =='colour_':
      return self.getColourActionDef(name,label='colour_',target=target)

           
    if name[0:4] =='sel_':
      return self.getSelectionActionDef(name,label='sel_',target=target)
      
    if name[0:6] =='label_':
        def c(): return int(target.label.label_select == name)
        ii = MolLabel.LABEL_SELECTION_ALIAS.index(name)
        return dict (
        group= 'atom_label',
        checkable = 1,
        checked = c,
        text =  MolLabel.LABEL_SELECTION_MENU[ii],
        slot = guiUtils.partial(self.handleAtomLabels,name) )

    if name == 'labels_details':
      return dict (
        text = self.tr('Details..'),
        slot =  self.atomLabelsGui,
        toolTip = self.tr('Set information to appear in atom labels'))
    
        
    # Style menu
    elif name == 'inter_dispobj_bond':
      def c(): return getattr(target,'inter_dispobj_bond')
      return dict (
        text = self.tr("Join display objects"),
        slot = guiUtils.partial(self.set_style,'join'),
        checkable = 1,
        checked = c
        )

    
    elif model.MolDisp.style_commands.count(name):
      icon = None
      icon_path = ''
      useIcons = PM('advanced_options').getparams()['iconized_display_table']
      if useIcons and name in model.MolDisp.style_commands_icons:
        icon = model.MolDisp.style_commands_icons[name]
        if icon.endswith('.svg'):
          icon = icon[:-4]
        elif icon.endswith('.png'):
          icon = icon[:-4]
        icon_path = os.path.join(os.path.abspath(os.environ['CCP4MG']),'qticons','disptab','style')
      ii = model.MolDisp.style_commands.index(name)
      def c(): return int(getattr(target,'style')==name)
      return dict (
        text = model.MolDisp.style_menu[ii],
        group='style_mode',
        slot = guiUtils.partial(self.set_style,name),
        checkable = 1,
        checked = c,
        icon_path = icon_path,
        icon = icon,
        toolTip = self.tr('Set the display object drawing style to ')+ model.MolDisp.style_menu[ii]
        )

    
    elif name =='list':
      return dict (text = self.tr('List selected atoms'),
                   slot = self.listData,
                   enabled = 1 )

    elif name =='savelist':
      return dict (text = self.tr('Save selected atoms'),
                   slot = self.saveListData,
                   enabled = 1 )
    
    elif name =='list_colour_data':
      def e(): target.model_colour.colour_data_listable()
      return dict (text = self.tr('List colour data'),
                   toolTip = self.tr('List the data currently shown by colouring'),
                   slot=guiUtils.partial(self.listData,'colour'),
                   enabled = e )
  
    else:
  
      return displayTable.GDispObj.getActionDef(self,name=name,target=target)

  
#-------------------------------------------------------------------
  def colour_scheme(self,args):
#-------------------------------------------------------------------
    #Populate a colour sub-menu with saved colour schemes
    #print "into colour_scheme",args
    target = get_dispobj(name=self.objectName())
    sub_menu,mode = args
    #print "colour_scheme sub_menu,mode",sub_menu,mode
    sub_menu.clear()
    import string
    if string.find(mode,'Dele')>=0:
      prefix = '_REMO'
    else:
      prefix = '_USER'
    colour_schemes = MODELINFO().getColourSchemeNames(target.parent.name_label)
    for group in colour_schemes:
      for scheme in group[1]:
        a = sub_menu.addAction(scheme)
        self.connect(a,QtCore.SIGNAL("triggered()"),guiUtils.partial(self.handle_colour_scheme,prefix+group[0]+'::'+scheme))
      sub_menu.addSeparator()
    #self.connect(sub_menu,QtCore.SIGNAL("triggered(QAction)"),self.handle_colour_scheme)

#-------------------------------------------------------------------
  def handle_colour_scheme(self,args):
#-------------------------------------------------------------------
    #print "handle_colour_scheme",args
    target = get_dispobj(name=self.objectName())
    target.set_colour(colour_mode=args)
    

#-------------------------------------------------------------------
  def stick_colour(self,as_atom=0):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if as_atom:
      target.model_colour.set_colour(stick_colour='ATOM')
      rebuild.UpdateDisplay()
    else:
      if not getattr(self,'stickColourGui',None):
        self.stickColourGui = mgWidgets.mgColourBrowser(selected_colour=target.get_colour())   
        self.connect(self.stickColourGui,QtCore.SIGNAL("ColourSelected"),self.set_stick_colour)
      self.stickColourGui.show()

#----------------------------------------------------------------------
  def  set_stick_colour(self,colour=''):
#----------------------------------------------------------------------
    #print "set_stick_colour",colour
    if colour:
      target = get_dispobj(name=self.objectName())
      target.model_colour.set_colour(stick_colour=colour)
      rebuild.UpdateDisplay()


#-------------------------------------------------------------------
  def set_style(self,name):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    if name == 'join':
      a = self.findChild(QtGui.QAction,'inter_dispobj_bond')
      if not a: return
      target.set_style(inter_dispobj_bond=a.isChecked())
    else:
      target.set_style(style_mode=name)
    rebuild.UpdateDisplay(target=target,controllingWidget=self)
    self.updateLabel('style')

#-------------------------------------------------------------------
  def atomLabelsGui(self,):
#-------------------------------------------------------------------
    if not hasattr(self,'atomLabels'):
      target = get_dispobj(name=self.objectName())
      import mgPreferences
      self.atomLabels = MGSimpleDialog.MGSimpleDialog(self)
      self.atomLabels.setWindowTitle(self.tr('Atom labels for')+target.parent.name)
      layout = QtGui.QGridLayout()
      widget = mgPreferences.moldispAtomLabelStyleGui(self.atomLabels,params=target.label.params())
      widget.setObjectName(self.objectName()+'atom_labels')
      layout.addWidget(widget)
      self.atomLabels.setLayout(layout)
      self.connect(widget,QtCore.SIGNAL('apply'),self.handleAtomLabelsGui)
    self.atomLabels.show()
    self.atomLabels.raise_()

#-------------------------------------------------------------------
  def initAtomLabels(self):
#-------------------------------------------------------------------
    pass

#-------------------------------------------------------------------
  def handleAtomLabels(self,name=''):
#-------------------------------------------------------------------
    # If called from the menu this has input argument corresponding to
    # the picked menu item
    #print "handleAtomLabels name",name
    target = get_dispobj(name=self.objectName())
    if MolLabel.LABEL_SELECTION_ALIAS.count(name):
      target.label.setparams(label_select=name)
      rebuild.UpdateDisplay()

    # Update the equvalent comboBox in the 'Details' dialog box
    if getattr(self,'atomLabels',''):
      widget = self.atomLabels.findChild(QtGui.QWidget,self.objectName()+'atom_labels')
      if widget: widget.setParams(label_select=name)
      
#-------------------------------------------------------------------
  def handleAtomLabelsGui(self):
#-------------------------------------------------------------------     
    target = get_dispobj(name=self.objectName())
    if getattr(self,'atomLabels',''):
      widget = self.atomLabels.findChild(QtGui.QWidget,self.objectName()+'atom_labels')
      if widget:
        pars = widget.getParams()
        #print "handleAtomLabels pars",pars
        target.label.setparams(pars)
        rebuild.UpdateDisplay(target=target,controllingWidget=self)

    #Update the QActions
    for name in MolLabel.LABEL_SELECTION_ALIAS:
      action = self.findChild(QtGui.QAction,name)
      if action: action.setChecked(target.label.label_select == name)

#-------------------------------------------------------------------
  def centreOn(self):
#-------------------------------------------------------------------
    import mmdb2 as mmdb
    target =  get_dispobj(name=self.objectName())
    if hasattr(target,"doBiomolecule") and target.doBiomolecule and hasattr(target.parent,"molHnd"):
      import pygl_coord
      tmp = pygl_coord.doublea(1)
      rtde =  tmp.frompointer(mmdb.realtype_to_double(target.parent.molHnd.Extent(target.SelHandle.getSelHnd())))
      mine,maxe = (rtde[0],rtde[1],rtde[2]),(rtde[3],rtde[4],rtde[5])
      mide = ((mine[0]+maxe[0])/2.,(mine[1]+maxe[1])/2.,(mine[2]+maxe[2])/2.)
      matrices = target.parent.molHnd.GetBiomoleculeAsMatrices(0,1);
      mide = ((mine[0]+maxe[0])/2.,(mine[1]+maxe[1])/2.,(mine[2]+maxe[2])/2.)
      total_maxe = [-1e+7,-1e+7,-1e+7]
      total_mine = [1e+7,1e+7,1e+7]
      for mat in matrices:
         midet = mat * pygl_coord.Cartesian(mide)
         if (midet.get_x()) < total_mine[0]: total_mine[0] = midet.get_x()
         if (midet.get_y()) < total_mine[1]: total_mine[1] = midet.get_y()
         if (midet.get_z()) < total_mine[2]: total_mine[2] = midet.get_z()
         if (midet.get_x()) > total_maxe[0]: total_maxe[0] = midet.get_x()
         if (midet.get_y()) > total_maxe[1]: total_maxe[1] = midet.get_y()
         if (midet.get_z()) > total_maxe[2]: total_maxe[2] = midet.get_z()
      mide = ((total_mine[0]+total_maxe[0])/2.,(total_mine[1]+total_maxe[1])/2.,(total_mine[2]+total_maxe[2])/2.)
      MAINWINDOW().centreOn(position=mide)
    else:
      MAINWINDOW().centreOn(molHnd = target.parent.molHnd,selHnd = target.SelHandle.getSelHnd())
    

#-------------------------------------------------------------------
  def update(self):
#-------------------------------------------------------------------
    #print "GMolDisp.update", hasattr(self,'atomLabels'),target.label.params()
    # Update MolDisp specific guis
    if hasattr(self,'atomLabels'):
      target = get_dispobj(name=self.objectName())
      widget = self.atomLabels.findChild(QtGui.QWidget,self.objectName()+'atom_labels')
      widget.setParams(target.label.params())

    GAtomicDispObj.update(self)


#-------------------------------------------------------------------
  def saveListData(self,mode='atoms'):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    if mode == 'atoms':
      rv = target.parent.list_data_file(target.name)
      if rv[0] == 0:
         dlfname = rv[1]
         def handler(dlfname=None,fname=None):
             if fname.endswith("cif"):
               rv2 = target.parent.list_data_file(target.name,file_format="CIF")
               dlfname2 = rv2[1]
               shutil.copy2(dlfname2,fname)
             else:
               shutil.copy2(dlfname,fname)
         filters = ["Model coordinate files (*.pdb *.mmcif *.cif)"]
         fd = mgWidgets.MGSaveFileDialog(self,filters=filters, defaultFileName=os.path.basename(rv[1]))
         fd.setWindowTitle("Save "+os.path.basename(rv[1]))
         self.connect(fd,QtCore.SIGNAL('save'),guiUtils.partialWithSignal(handler,dlfname))
         self.connect(fd,QtCore.SIGNAL('save'),fd.close)
         fd.setModal(True)
         fd.show()
        

#-------------------------------------------------------------------
  def listData(self,mode='atoms'):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    if mode == 'atoms':
      rv = target.parent.list_data_file(target.name)
    elif mode == 'colour':
      rv = target.model_colour.list_colour_data()
    #print "GMolDisp.listData",rv
    if rv[0]:
      MGGUI.WarningMessage(rv[1])
    else:
      viewer = FILEVIEWER('data_listing')
      if not viewer:
        MGGUI.WarningMessage(self.tr('ERROR opeing viewer'))
      else:
        if mode == 'atoms':
          window = viewer.open(rv[1])
        elif mode == 'colour':
          window = viewer.loadText(rv[1],title=rv[2])
          self.connect(window,QtCore.SIGNAL('wordClicked'),self.handleListDataClick)
          self.connect(window,QtCore.SIGNAL('wordDoubleClicked'),self.handleListDataDoubleClick)
        # Set fixed width font
        #print 'MolDisp.listData window',window
        if window: window.setFont(style='fixed_width')


#-------------------------------------------------------------------
  def handleListDataClick(self,word):
#-------------------------------------------------------------------
    #print 'handleListDataClick',word
    parent = DISPLAYTABLE().getDataObj(DispObj=self.objectName())
    if parent: parent.handleListDataSelection(cid=word,mode='single')
    
#-------------------------------------------------------------------
  def handleListDataDoubleClick(self,word):
#-------------------------------------------------------------------
    #print 'handleListDataDoubleClick',word
    parent = DISPLAYTABLE().getDataObj(DispObj=self.objectName())
    if parent: parent.handleListDataSelection(cid=word,mode='double')
    
#-------------------------------------------------------------------
class GContacts(GAtomicDispObj):
#-------------------------------------------------------------------

  def __init__(self,parent,table=None,name=''):
    #print "GHBonds name",name,self,parent
    GAtomicDispObj.__init__(self,parent,table=table,name=name,object_type='Contacts')
    self.iconButton.setToolTip(self.tr('Tools for Contacts display object'))
    self.type_label = 'Contacts'

#----------------------------------------------------------------------
  def getGuiDef(self,name='row'):
#----------------------------------------------------------------------
  
    target = get_dispobj(name=self.objectName())
    if name == 'row':
      return [ dict(name= 'selection1', mode='MENU', getIcon=functools.partial(getIconFromSelectionFunction,target.SelHandle1.getLabel), getLabel=target.SelHandle1.getLabel , toolTip = self.tr('Select first set of atoms')),
               dict(name='selection2', mode='MENU', getIcon=functools.partial(getIconFromSelectionFunction,target.SelHandle2.getLabel), getLabel=target.SelHandle2.getLabel ,  toolTip =  self.tr('Select second set of atoms')),
               dict(name='colour', mode='MENU', getIcon=target.get_colour_icon, getLabel=target.get_colour,  toolTip =  self.tr('Set colour of contacts'))
             ]

    if name == 'icon':
      return ['visible','flash','transparency','custom_drawing_style','list_data','export_vectors','delete']
    
    if name == 'selection1':
      menu =  self.getSelectionMenu(target,label='sel1_',ifAsDispobj=1)
      return menu

    elif name == 'selection2':
      menu =  self.getSelectionMenu(target,label='sel2_',ifAsDispobj=1)
      menu.insert(0,'sel2_same_as')
      return menu

    elif name == 'colour':
      return ['colour_complement','colour_browser']

    
    else:
      return displayTable.GDispObj.getGuiDef(self,name=name,target=target)
    
#-------------------------------------------------------------------      
  def getActionDef(self,name):
#-------------------------------------------------------------------
    
    target = get_dispobj(name=self.objectName())

    #print "getActionDef",name

    if name[0:3] == 'sel':
      rv = self.getSelectionActionDef(name,label=name[0:5],target=target)
      if rv: return rv
      
    if name[0:7] == 'colour_':
      rv = self.getColourActionDef(name,label='colour_',target=target)
      if rv: return rv

    if name == 'custom_drawing_style':
      return dict ( text = self.tr('Drawing style'),
                    toolTip = self.tr('Set contact line width and text labels'),
                    slot = self.displayStyleGui )

    if name == 'list_data':
      return dict ( text = self.tr('List contacts'),
                    toolTip = self.tr('List or write Contacts to file'),
                    slot = self.listData
                    )

    if name == 'export_vectors':
      return dict (text = self.tr('Export vectors'),
                    toolTip = self.tr('Write contacts to vector file'),
                    slot = self.exportVectorGui,
                   enabled = 1)
      
    return displayTable.GDispObj.getActionDef(self,name=name,target=target)


#-------------------------------------------------------------------
  def displayStyleGui(self):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not hasattr(self,'styleGui'):
      import mgPreferences
      dialog = MGSimpleDialog.MGSimpleDialog(self)
      layout = QtGui.QVBoxLayout()
      # getDrawingStylePM will make a custom pm if one does not exist
      pm = target.getDrawingStylePM(custom=1,auto_save=1)
      self.styleGui = mgPreferences.hbondStyleGui(dialog,pm=pm,doHbonds=False)
      layout.addWidget(self.styleGui)
      #buttons = mgPreferences.preferenceButtons(self)
      #layout.addWidget(buttons)
      dialog.setLayout(layout)
      self.connect(self.styleGui,QtCore.SIGNAL('changed'),self.handleStyleGui)

    
    self.styleGui.window().show()
    self.styleGui.window().raise_()


#-------------------------------------------------------------------
  def handleStyleGui(self):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    target.getDrawingStylePM().setparams(self.styleGui.getParams())
    target.set_do_redraw()
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------
  def exportVectorGui(self):
#-------------------------------------------------------------------
    if hasattr(self,'exportGui'):
      self.exportGui.show()
    else:
      self.exportGui = exportGui(self,'Contacts')
      self.connect(self.exportGui, QtCore.SIGNAL('save'),self.exportGui.saveFile)



#-------------------------------------------------------------------
class GHBonds(GAtomicDispObj):
#-------------------------------------------------------------------

  def __init__(self,parent,table=None,name=''):
    #print "GHBonds name",name,self,parent
    GAtomicDispObj.__init__(self,parent,table=table,name=name,object_type='HBonds')
    self.iconButton.setToolTip(self.tr('Tools for HBonds display object'))
    self.type_label = 'HBonds'

#----------------------------------------------------------------------
  def getGuiDef(self,name='row'):
#----------------------------------------------------------------------
  
    target = get_dispobj(name=self.objectName())
    if name == 'row':
      return [ dict(name= 'selection1', mode='MENU', getIcon=functools.partial(getIconFromSelectionFunction,target.SelHandle1.getLabel), getLabel=target.SelHandle1.getLabel , toolTip = self.tr('Select first set of atoms')),
               dict(name='selection2', mode='MENU', getIcon=functools.partial(getIconFromSelectionFunction,target.SelHandle2.getLabel), getLabel=target.SelHandle2.getLabel ,  toolTip = self.tr('Select second set of atoms')),
               dict(name='colour', mode='MENU', getIcon=target.get_colour_icon, getLabel=target.get_colour,  toolTip = self.tr('Set colour of HBonds'))
             ]

    if name == 'icon':
      return ['visible','flash','transparency','custom_drawing_style','list_data','export_vectors','clone','delete']
    
    if name == 'selection1':
      menu =  self.getSelectionMenu(target,label='sel1_',ifAsDispobj=1)
      return menu

    elif name == 'selection2':
      menu =  self.getSelectionMenu(target,label='sel2_',ifAsDispobj=1)
      menu.insert(0,'sel2_same_as')
      return menu

    elif name == 'colour':
      return ['colour_complement','colour_browser']

    
    else:
      return displayTable.GDispObj.getGuiDef(self,name=name,target=target)
    
#-------------------------------------------------------------------      
  def getActionDef(self,name):
#-------------------------------------------------------------------
    
    target = get_dispobj(name=self.objectName())

    #print "getActionDef",name

    if name[0:3] == 'sel':
      rv = self.getSelectionActionDef(name,label=name[0:5],target=target)
      if rv: return rv
      
    if name[0:7] == 'colour_':
      rv = self.getColourActionDef(name,label='colour_',target=target)
      if rv: return rv

    if name == 'custom_drawing_style':
      return dict ( text = self.tr('Drawing style'),
                    toolTip =  self.tr('Set HBond line width and text labels'),
                    slot = self.displayStyleGui )


    if name == 'export_vectors':
      return dict (text =  self.tr('Export vectors'),
                    toolTip =  self.tr('Write HBonds to vector file'),
                    slot = self.exportVectorGui,
                    enabled = 1)
      
    return displayTable.GDispObj.getActionDef(self,name=name,target=target)


#-------------------------------------------------------------------
  def displayStyleGui(self):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not hasattr(self,'styleGui'):
      import mgPreferences
      dialog = MGSimpleDialog.MGSimpleDialog(self)
      layout = QtGui.QVBoxLayout()
      # getDrawingStylePM will make a custom pm if one does not exist
      pm = target.getDrawingStylePM(custom=1,auto_save=1)
      self.styleGui = mgPreferences.hbondStyleGui(dialog,pm=pm,doContacts=False)
      layout.addWidget(self.styleGui)
      #buttons = mgPreferences.preferenceButtons(self)
      #layout.addWidget(buttons)
      dialog.setLayout(layout)
      self.connect(self.styleGui,QtCore.SIGNAL('changed'),self.handleStyleGui)

    
    self.styleGui.window().show()
    self.styleGui.window().raise_()

#-------------------------------------------------------------------
  def handleStyleGui(self):
#-------------------------------------------------------------------
    #print "HBonds.handleStyleGui",self.styleGui.getParams()
    target = get_dispobj(name=self.objectName())
    target.getDrawingStylePM().setparams(self.styleGui.getParams())
    target.set_do_redraw()
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------
  def exportVectorGui(self):
#-------------------------------------------------------------------
    if hasattr(self,'exportGui'):
      self.exportGui.show()
    else:
      self.exportGui = exportGui(self,'HBonds')
      self.connect(self.exportGui, QtCore.SIGNAL('save'),self.exportGui.saveFile)

  
#-------------------------------------------------------------------
class GSurfaceDispobj(GAtomicDispObj):
#-------------------------------------------------------------------

#-------------------------------------------------------------------
  def setTransparency(self,value):
#-------------------------------------------------------------------
    GAtomicDispObj.setTransparency(self,value)
    target = get_dispobj(name=self.objectName())
    if len(target.graphmod.obj.GetSurfacePrimitives())>0:
      target.graphmod.obj.forceRegenerateSurfaceArrays()
      if MAINWINDOW() and hasattr(MAINWINDOW(),"glWidget") and hasattr(MAINWINDOW().glWidget,"updateGL"):
         MAINWINDOW().glWidget.updateGL()

#-------------------------------------------------------------------
  def set_colour(self,name):
#-------------------------------------------------------------------
    '''
    Send a colour command to the target
    '''
    GAtomicDispObj.set_colour(self,name)
    target = get_dispobj(name=self.objectName())
    if len(target.graphmod.obj.GetSurfacePrimitives())>0:
      target.graphmod.obj.forceRegenerateSurfaceArrays()
      if MAINWINDOW() and hasattr(MAINWINDOW(),"glWidget") and hasattr(MAINWINDOW().glWidget,"updateGL"):
         MAINWINDOW().glWidget.updateGL()

  def __init__(self,parent,table=None,name=''):
    GAtomicDispObj.__init__(self,parent,table=table,name=name,object_type='SurfaceDispobj')
    self.iconButton.setToolTip(self.tr('Tools for surface display object'))
    self.type_label = 'Surface'

#----------------------------------------------------------------------
  def getGuiDef(self,name='row'):
#----------------------------------------------------------------------

  
    target = get_dispobj(name=self.objectName())

    if name == 'icon':
      surface_type = [self.tr('Surface type')]
      surface_type.extend(target.surface_type_alias)
      return ['visible','centre_on','flash','transparency',[self.tr('Surface style'),'surface_style_solid','surface_style_dots','surface_style_mesh'],surface_type,'apply_symmetry,','apply_biomolecule','custom_drawing_style','list_data','clone','delete']
    if name == 'row':
      return [ dict(name= 'selection1', mode='MENU', getIcon=functools.partial(getIconFromSelectionFunction,target.SelHandle1.getLabel), getLabel=target.SelHandle1.getLabel , toolTip = self.tr('Select atoms to be covered by surface')),
               dict(name='selection2', mode='MENU', getIcon=functools.partial(getIconFromSelectionFunction,target.SelHandle2.getLabel), getLabel=target.SelHandle2.getLabel ,  toolTip = self.tr('Select set of context atoms')),
               dict(name='colour', mode='MENU', getLabel=target.model_colour.getLabel, getIcon=target.model_colour.getIcon,  toolTip = self.tr('Set colour of surface'))
             ]

    if name == 'selection1':
      menu =  self.getSelectionMenu(target,label='sel1_')
      return menu

    elif name == 'selection2':
      menu =  self.getSelectionMenu(target,label='sel2_')
      menu.insert(0,'sel2_same_as')
      return menu

    elif name == 'colour':
      menu = self.getAtomColourMenu(target,label='colour_')
      menu.insert(0,'colour_electrostatic')
      menu.append('colour_legend')
      #print "menu",menu
      return menu

      
    else:
      return displayTable.GDispObj.getGuiDef(self,name=name,target=target)
    
#-------------------------------------------------------------------      
  def getActionDef(self,name):
#-------------------------------------------------------------------
    
    target = get_dispobj(name=self.objectName())

    if name == 'centre_on':
      return dict (
      text = self.tr("Centre on"),
      slot = self.centreOn
      )


    if name[0:len('apply_symmetry')] == 'apply_symmetry':
      def c(): return int(target.doSymmetry == True)
      return dict ( text = "Apply symmetry",
                    slot = guiUtils.partial(target.toggleSymmetryStatus),
                    checkable = 1,
                    checked = c
                    )

    elif name[0:len('apply_biomolecule')] == 'apply_biomolecule':
      def c(): return int(target.doBiomolecule == True)
      return dict ( text = "Show biomolecule",
                    slot = guiUtils.partial(target.toggleBiomolecule),
                    checkable = 1,
                    checked = c
                    )


    if name[0:3] == 'sel':
      rv = self.getSelectionActionDef(name,label=name[0:5],target=target)
      if rv: return rv

    if name[0:13]== 'surface_style':
      def c(): return int(target.surface_style == name[14:])
      text = name[14:]
      return dict ( text = text,
                    slot = guiUtils.partial(self.setSurfaceStyle,name[14:]),
                    group= 'surface_style',
                    checkable = 1,
                    checked = c
                    )

    
    if name[0:len("surface_type")]== 'surface_type':
      def c(): return int(target.surface_type == name[len("surface_type")+1:])
      text = name[len("surface_type")+1:]
      ii = target.surface_type_alias.index(name)
      return dict ( text = target.surface_type_menu[ii],
                    slot = guiUtils.partial(self.setSurfaceType,name[len("surface_type")+1:]),
                    group= 'surface_type',
                    checkable = 1,
                    checked = c
                    )

    
    elif name == 'colour_electrostatic':
      return dict (
        text = self.tr('Electrostatic potential'),
        slot = guiUtils.partial(self.set_colour,'electrostatic') )


    if name[0:7] == 'colour_':
      rv = self.getColourActionDef(name,label='colour_',target=target)
      if rv: return rv

    
    elif name == 'legend':
      return dict ( text = self.tr('Add colour legend'),
                    enabled = 0 )

    return displayTable.GDispObj.getActionDef(self,name=name,target=target)


  def setSurfaceStyle(self,style):
    
    target = get_dispobj(name=self.objectName())
    target.set_surface_style(surface_style=style)
    rebuild.UpdateDisplay(target=target,controllingWidget=self)

  def setSurfaceType(self,style):
    
    target = get_dispobj(name=self.objectName())
    target.set_surface_type(surface_type=style)
    self.set_visibility(visible=0)
    #rebuild.UpdateDisplay(target=target,controllingWidget=self)


#-------------------------------------------------------------------
  def centreOn(self):
#-------------------------------------------------------------------
    target =  get_dispobj(name=self.objectName())
    MAINWINDOW().centreOn(molHnd = target.parent.molHnd,
                        selHnd = target.SelHandle1.getSelHnd())
 
#-------------------------------------------------------------------
class GAnnotation(displayTable.GDispObj):
#-------------------------------------------------------------------

  def __init__(self,parent,table=None,name=''):
    self.textCentreState = 0
    #print "GMolDisp name",name,self,parent
    displayTable.GDispObj.__init__(self,parent,table=table,name=name,object_type='Annotation')
    self.type_label='Annotation'
    self.iconButton.setToolTip(self.tr('Tools for annotation display object'))

#----------------------------------------------------------------------
  def getGuiDef(self,name='row'):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if name == 'row':
      return [ dict ( name = 'text', mode = 'PUSHBUTTON', getLabel=target.get_text_label ,callback=self.editText,toolTip=self.tr('Enter text and select font and colour')),
               dict ( name = 'position', mode='PUSHBUTTON', getLabel=target.get_position_label, callback=self.editPosition , toolTip = self.tr("Set position of annotation") )
             ]
    elif name == 'icon':
      return ['visible','centre_on','flash','move','options','clone','delete']

    else:
      return []
    
#-------------------------------------------------------------------      
  def handleEditPosition(self,args):
#-------------------------------------------------------------------
    #print 'Annotation.handleEditPosition',args
    target = get_dispobj(name=self.objectName())
    if not target: return
    target.set_position(x=float(args[0]),y=float(args[1]),z=float(args[2]))
    self.updateLabel('position')
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------      
  def editPosition(self):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    pos = target.get_position()
    if not hasattr(self,'cartesianPicker'):
      self.cartesianPicker = mgWidgets.CartesianPickerDialog(self,x=pos[0],y=pos[1],z=pos[2])
      self.cartesianPicker.setWindowTitle(self.tr('Pick point in 3D coordinates'))
    self.cartesianPicker.UnClose()
    self.connect(self.cartesianPicker,QtCore.SIGNAL("PositionChanged"),self.handleEditPosition)
    
#-------------------------------------------------------------------      
  def setTextCentreState(self,state):
#-------------------------------------------------------------------      
	self.textCentreState = state
	self.handleEditText()
    
#-------------------------------------------------------------------      
  def options(self):
#-------------------------------------------------------------------      
	if not hasattr(self,"optiondGui"):
		self.optionsGui = QtGui.QWidget()
		self.optionsGui.setObjectName('annotationOptions')
		self.optionsGui.setWindowTitle(self.tr('Annotation options ')+self.objectName())
    		cb = QtGui.QCheckBox(self.tr('Centre text on coordinates'))
		target = get_dispobj(name=self.objectName())
		if target and hasattr(target,'centered'):
			self.textCentreState=target.centered
			if self.textCentreState:
				cb.setCheckState(QtCore.Qt.Checked)
			else:
				cb.setCheckState(QtCore.Qt.Unchecked)
		layout = QtGui.QVBoxLayout()
		layout.addWidget(cb)
		self.optionsGui.setLayout(layout)
		self.connect(cb,QtCore.SIGNAL("stateChanged (int)"),self.setTextCentreState)
	self.optionsGui.show()
	self.optionsGui.raise_()

  def centreOn(self):
    target = get_dispobj(name=self.objectName())
    pos = target.get_position()
    MAINWINDOW().glWidget.centreOn(pos,glide=1)

#-------------------------------------------------------------------      
  def getActionDef(self,name,**info):
#-------------------------------------------------------------------
    
    target = get_dispobj(name=self.objectName())

    
    if name == 'colour_complement':
      return dict ( text = 'complement',
                    slot= guiUtils.partial(target.set_colour,'complement') )
    
    if name == 'colour_browser':
      return dict ( text = self.tr('Colour browser'),
                    slot= self.colour_browser )

    if name == 'centre_on':
      return dict (
      text = self.tr("Centre on"),
      slot = self.centreOn)

    if name == 'options':
      return dict (
      text = self.tr("Options for ")+self.objectName(),
      slot = self.options
    )

    if name == 'move':
      def c(): return int(self.status==1)
      return dict (
      text = self.tr("Move ")+self.objectName(),
      slot = self.toggleMoving,
      checkable = 1,
      checked = c
    )


    return displayTable.GDispObj.getActionDef(self,name=name,target=target)


#-------------------------------------------------------------------
  def editText(self):
#-------------------------------------------------------------------
    
    gui = self.findChild(QtGui.QDialog,'editTextGui')
    if gui:
      gui.show()
      gui.raise_()
      return
    
    target = get_dispobj(name=self.objectName())

    dialog = QtGui.QDialog(self)
    dialog.setObjectName('editTextGui')
    dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    dialog.setWindowTitle(self.tr('Annotation text ')+self.objectName())
    layout = QtGui.QVBoxLayout()

    import TextEdit
    widget = TextEdit.TextEditWidget(self)
    widget.setObjectName('editText')
    widget.setCurrentFont(definition=FONTMANAGER().getFont('annotation'))
    widget.setText(QtCore.QString(target.text))

    layout.addWidget(widget)
    
    layout0 = QtGui.QHBoxLayout()
    layout0.addStretch()
    apply = QtGui.QPushButton(self.tr('Apply'),self)
    layout0.addWidget(apply)
    close =  QtGui.QPushButton(self.tr('Close'),self)
    layout0.addWidget(close)
    layout.addLayout(layout0)

    dialog.setLayout(layout)
    dialog.show()

    self.connect(apply,QtCore.SIGNAL('released()'),self.handleEditText)
    self.connect(close,QtCore.SIGNAL('released()'),dialog.close)

#-------------------------------------------------------------------
  def handleEditText(self):
#-------------------------------------------------------------------
    #print "handleEditText",self.textCentreState
    widget = self.findChild(QtGui.QWidget,'editText')
    target = get_dispobj(name=self.objectName())
    #print "handleEditText widget",widget
    if widget: text = str(self.findChild(QtGui.QWidget,'editText').text())
    else: text = target.text
    #print 'Annotation.handleEditText',text
    print target
    target.set_text(text)
    target.centered=self.textCentreState
    
    self.updateLabel('text')
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------
  def fontGui(self):
#-------------------------------------------------------------------
    gui = self.findChild(MGSimpleDialog.MGSimpleDialog,'fontGui')
    if gui:
      gui.show()
      gui.raise_()
      return
    
    target = get_dispobj(name=self.objectName())
    dialog = QtGui.QDialog(self)
    dialog.setWindowTitle(self.tr('Font for annotation'))
    dialog.setObjectName('fontGui')
    dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    dialog.setWindowTitle(self.tr('Font ')+self.objectName())
    layout = QtGui.QVBoxLayout()

    widget = mgWidgets.MGFontSelector('Annotation')
    widget.setObjectName('font')
    layout.addWidget(widget)
    
    layout0 = QtGui.QHBoxLayout()
    layout0.addStretch()
    apply = QtGui.QPushButton(self.tr('Apply'),self)
    layout0.addWidget(apply)
    close =  QtGui.QPushButton(self.tr('Close'),self)
    layout0.addWidget(close)
    layout.addLayout(layout0)

    dialog.setLayout(layout)
    dialog.show()

    self.connect(apply,QtCore.SIGNAL('released()'),self.handleFont)
    self.connect(close,QtCore.SIGNAL('released()'),dialog.close)

#-------------------------------------------------------------------
  def handleFont(self):
#-------------------------------------------------------------------
    widget = self.findChild(mgWidgets.MGFontSelector,'font')
    qt_font = widget.getFont()
    
    font = { 'family' : str(qt_font.family()),
             'size'  : int(qt_font.pointSize()) }
    if qt_font.italic():
      font['slant'] = 'i'
    else:
      font['slant'] = 'r'
    if qt_font.weight() == QtGui.QFont.Bold:
      font['weight'] = 'bold'
    else:
      font['weight'] = 'medium'

    #print "handleFont font",font
    get_dispobj(name=self.objectName()).set_font(font)
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class GCrystalContainer(displayTable.GDataObj):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------


  def __init__(self,parent,table=None,name='',label=''):
    displayTable.GDataObj.__init__(self,parent,table=table,name=name,label='Crystals',autoClose=1)
    self.iconButton.setToolTip(self.tr('Tools for handling crystals'))
    
#----------------------------------------------------------------------
  def getGuiDef(self,name='icon'):
#----------------------------------------------------------------------
    return ['create']

#----------------------------------------------------------------------
  def getActionDef(self,name,**info):
#----------------------------------------------------------------------
    #print "GCrystalContainer.objectName",self.objectName()
    target = get_dataobj(name=self.objectName())[0]
    if name == 'create':
      return dict (
      text = self.tr('Create crystal'),
      slot = self.addDispObj
      )
    return {}

  def addDispObj(self,name=''):
        import Crystal
        xtl = CRYSTALMANAGER().add_object()
        DISPLAYTABLE().addDispObj(parent_name='CrystalData',object_type='Crystal',name=xtl.name)

#-------------------------------------------------------------------
class GCrystal(displayTable.GDispObj):
#-------------------------------------------------------------------

  def __init__(self,parent,table=None,name=''):
    target = CRYSTALMANAGER()
    displayTable.GDispObj.__init__(self,parent,table=table,name=name,object_type='Crystal')
    self.iconButton.setToolTip(self.tr('Tools for crystal'))
    self.type_label = 'Crystal'

  def handleSymmRadius(self,name=''):
   if type(name) == str and name == 'symm_radius_gui':
      if not hasattr(self,'symm_gui'):
        self.symm_gui = QtGui.QDialog(self)
        self.symm_gui.setWindowTitle(self.tr('Symmetry search radius'))
        layout = QtGui.QVBoxLayout()
	self.symmSpin = QtGui.QDoubleSpinBox()
	self.symmSpin.setMaximum(10000)
	buttons = QtGui.QDialogButtonBox()
	okButton = buttons.addButton(QtGui.QDialogButtonBox.Ok)
	applyButton = buttons.addButton(QtGui.QDialogButtonBox.Apply)
	cancelButton = buttons.addButton(QtGui.QDialogButtonBox.Cancel)
	self.connect(okButton,QtCore.SIGNAL("clicked(bool)"),functools.partial(self.handleSymmRadius,self.symmSpin))
	self.connect(okButton,QtCore.SIGNAL("clicked(bool)"),self.symm_gui.hide)
	self.connect(applyButton,QtCore.SIGNAL("clicked(bool)"),functools.partial(self.handleSymmRadius,self.symmSpin))
	self.connect(cancelButton,QtCore.SIGNAL("clicked(bool)"),self.symm_gui.hide)
	layout.addWidget(self.symmSpin)
	layout.addWidget(buttons)
        self.symm_gui.setLayout(layout)
      target = get_dispobj(name=self.objectName())
      if target and hasattr(target,"atom_symm_radius") and hasattr(self,"symmSpin"): self.symmSpin.setValue(float(target.atom_symm_radius))
      self.symm_gui.show()
      self.symm_gui.raise_()
   elif type(name) == str and name[:12]=='symm_radius_':
    ii = ['symm_radius_25','symm_radius_50','symm_radius_75','symm_radius_100'].index(name)
    val = float(['25','50','75','100'][ii])
    target = get_dispobj(name=self.objectName())
    #print name,val
    target.set_style(radius=val)
    #target.graphmod.obj.SetSymmRadius(val)
    rebuild.UpdateDisplay(target=target,controllingWidget=self)
    self.updateLabel('style')
   elif hasattr(name,"value"):
      target = get_dispobj(name=self.objectName())
      target.set_style(radius = name.value())
      self.updateLabel('style')
      rebuild.UpdateDisplay(target=target,controllingWidget=self)
 
#----------------------------------------------------------------------
  def getGuiDef(self,name='row',pickevent=None):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if name == 'row':
      return [ dict (name='xtl_params', mode= 'MENU', label='Xtl parameters', toolTip = self.tr('Set the crystal space group and cell' )),
               dict (name = 'contents', mode = 'MENU', label='Crystal contents',toolTip=self.tr('Specify which models should have the crystal symmetry')),
               dict(name='style',mode='MENU',getIcon=target.get_style_icon,getLabel=target.get_style_label,toolTip=self.tr('Draw the crystal contents in style'))]
    elif name == 'xtl_params':
      menu = []
      for item in get_dataobj(object_type='MapData'):
        menu.append('xtl_params'+item.name)
      for item in get_dataobj(object_type='MolData'):
        if hasattr(item,'originalSymmetry'):
          menu.append('xtl_params'+item.name)
      menu.extend(['sep','xtl_params_details'])
      return menu
    elif name == 'contents':
      menu = []
      for item in get_dataobj(object_type='MolData'):
        menu.append('contents'+item.name)
      return menu
    elif name == 'style':
      menu = []
      menu.extend(Crystal.Crystal.style_alias)
      if 'CONTINUOUS' in Crystal.Crystal.style_alias:
        menu.insert(Crystal.Crystal.style_alias.index('CONTINUOUS')+1,[self.tr('within radius'),'symm_radius_25','symm_radius_50','symm_radius_75','symm_radius_100','symm_radius_gui'])
      menu.append([self.tr('Extend unit cell'),'extend_x','extend_y','extend_z'])
      menu.extend(['symm_diff_colour','cell_edges','symmetry_labels'])
      return menu

    elif name == 'icon':
      return [[self.tr('Align view on'), 'align_ab', 'align_ac','align_bc'],'delete']
      #return ['delete']
      
    return []

#----------------------------------------------------------------------
  def getActionDef(self,name,**info):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    
    if name[0:8] == 'contents':
      dataobj_list = get_dataobj(name=name[8:])
      if dataobj_list:
        def c(): return int(dataobj_list[0].masterCrystal==target.name)
        return dict (text = name[8:],
                    checkable = 1,                  
                    slot = guiUtils.partial(self.handle_gui, name),
                    checked = c )

    if name =='symm_radius_gui':
        return dict (
        group = 'symm_radius',
        checkable = 0,
        text = 'Select..',
        slot = guiUtils.partial(self.handleSymmRadius,name),
        toolTip = self.tr('Set the symmetry search radius (A)'))
      
    elif name[:len('symm_radius_')] =='symm_radius_':
        def c(): return int(getattr(target,'atom_symm_radius')== float(text))
        ii = ['symm_radius_25','symm_radius_50','symm_radius_75','symm_radius_100'].index(name)
        text = ['25','50','75','100'][ii]
        return dict (
        checkable = 1,
        checked = c,
        group = 'symm_radius',
        text = text,
        slot = guiUtils.partial(self.handleSymmRadius,name) )

    if name == 'xtl_params_details':
      return dict (text = self.tr('Details..'),
                   toolTip = self.tr('Edit space group and cell parameters'),
                   slot = guiUtils.partial(self.handle_gui, name) )
    
    if name[0:10] == 'xtl_params':
      dataobj_list = get_dataobj(name=name[10:])      
      if dataobj_list:
        def c(): return int(dataobj_list[0].name==target.source)
        return dict (text = name[10:],
                    group = 'xtl_params_group',
                    checkable = 1,                  
                    slot = guiUtils.partial(self.handle_gui, name),
                    checked = c )

    
    if Crystal.Crystal.style_alias.count(name):
      icon = ''
      icon_path = ''
      useIcons = PM('advanced_options').getparams()['iconized_display_table']
      if useIcons and name in Crystal.Crystal.style_alias_icons:
        icon = Crystal.Crystal.style_alias_icons[name]
        if icon.endswith('.svg'):
          icon = icon[:-4]
        elif icon.endswith('.png'):
          icon = icon[:-4]
        icon_path = os.path.join(os.path.abspath(os.environ['CCP4MG']),'qticons','disptab','style')
      text = Crystal.Crystal.style_menu[Crystal.Crystal.style_alias.index(name)]
      def c(): return int(name==target.style)
      return dict ( 
          text = text,
          slot = guiUtils.partial(self.handle_gui,name),
          group= 'style',
          icon_path = icon_path,
          icon = icon,
          checkable = 1,
          checked = c )

    if name[0:6] == 'extend':
      def c(): return target.unit_cell_shift[['x','y','z'].index(name[7:8])]
      return dict ( text = self.tr('Extend in '+name[7:8]),
                    checkable = 1,
                    checked = c,
                    slot = guiUtils.partial(self.handle_gui,name) )

    if name == 'symm_diff_colour':
      def c(): return target.symm_diff_colour
      return dict ( text = self.tr('Colour by symmetry'),
                    checkable = 1,
                    slot = guiUtils.partial(self.handle_gui, 'symm_diff_colour'),
                    checked = c )


    if name == 'symmetry_labels':
      def c(): return target.symmetry_labels
      return dict ( text = self.tr('Apply symm. to atom labels'),
                    checkable = 1,
                    slot = guiUtils.partial(self.handle_gui, 'symmetry_labels'),
                    checked = c )

    if name == 'cell_edges':
      def c(): return target.cell_edges
      return dict ( text = self.tr('Show cell edges'),
                    checkable = 1,
                    slot = guiUtils.partial(self.handle_gui, 'cell_edges'),
                    checked = c )

    if name[0:5] == 'align':
      return dict ( text = self.tr(name[6:8]+' face'),
                    slot = guiUtils.partial(self.handle_gui,name) )

    return displayTable.GDispObj.getActionDef(self,name=name,target=target)

    
#----------------------------------------------------------------------
  def handle_gui(self,name):
#----------------------------------------------------------------------
    widget = self.findChild(QtGui.QAction,name)
    target = get_dispobj(name=self.objectName())
    if widget and target:  
      if name == 'symm_diff_colour':
        target.set_style(symm_diff_colour= int(widget.isChecked()))
      elif name == 'cell_edges':
        target.set_style(cell_edges = int(widget.isChecked()))
      elif name == 'symmetry_labels':
        target.set_style(symmetry_labels= int(widget.isChecked()))
      elif name[0:6] == 'extend':
        apply(target.set_style,[],{ name:int(widget.isChecked()) } )      
      elif Crystal.Crystal.style_alias.count(name):
        target.set_style(style=name)
        self.updateLabel('style')        
      elif name[0:8] == 'contents':
        dataobj_list = get_dataobj(name[8:])
        if dataobj_list:
          if widget.isChecked():
            dataobj_list[0].setMasterCrystal(target.name)
          else:
            dataobj_list[0].setMasterCrystal()
      elif name == 'xtl_params_details':
        self.xtlParamsGui()
        return
      elif name[0:10] == 'xtl_params':
        dataobj_list = get_dataobj(name[10:])
        if dataobj_list:
          target.set_source(name[10:])
          target.updateContents()
        self.updateLabel('xtl_params')
      elif name[0:5] == 'align':
        target.handle_align(name[6:8])

      elif name == 'delete':
        target.delete()

    rebuild.UpdateDisplay() 

#----------------------------------------------------------------------
  def xtlParamsGui(self):
#----------------------------------------------------------------------
    #print "into xtlParamsGui exists?",hasattr(self,'xtlParams')
    if not hasattr(self,'xtlParams'):
      target = get_dispobj(name=self.objectName())
      import mgPreferences
      self.xtlParams = MGSimpleDialog.MGSimpleDialog(self)
      self.xtlParams.setWindowTitle(self.tr('Crystal parameters for')+target.name)
      self.xtlParams.setAttribute(QtCore.Qt.WA_DeleteOnClose)
      layout = QtGui.QVBoxLayout()

      line_layout =  QtGui.QHBoxLayout()
      label = QtGui.QLabel(self.tr('Space group'),self.xtlParams)
      widget =  QtGui.QLineEdit(self.xtlParams)
      widget.setObjectName('space_group')
      line_layout.addWidget(label)
      line_layout.addWidget(widget)
      layout.addLayout(line_layout)


      grid_layout = QtGui.QGridLayout()
      row = 0
      for item_list in [[['a','b','c'],5000.0],[['alpha','beta','gamma'],180.0]]:
        validator = QtGui.QDoubleValidator(0.0,item_list[1],3,self.xtlParams)
        ii = -1
        for item in item_list[0]:
          label = QtGui.QLabel(item,self.xtlParams)
          widget = QtGui.QLineEdit(self.xtlParams)
          widget.setValidator(validator)
          widget.setObjectName(item)
          ii=ii+1
          grid_layout.addWidget(label,row,ii,1,1)
          ii=ii+1
          grid_layout.addWidget(widget,row,ii,1,1)
        row = row + 1
      layout.addLayout(grid_layout)
          
      buttonBox = QtGui.QDialogButtonBox(self)
      buttonBox.setOrientation(QtCore.Qt.Horizontal)
      button = buttonBox.addButton(self.tr('&Close'),QtGui.QDialogButtonBox.DestructiveRole)
      self.connect (button,QtCore.SIGNAL('clicked()'),self.closeXtlParams)
      button = buttonBox.addButton(self.tr('&Apply'),QtGui.QDialogButtonBox.ApplyRole)
      button.setDefault(1)
      self.connect (button,QtCore.SIGNAL('clicked()'),self.applyXtlParams)
      button = buttonBox.addButton(self.tr('&Reset'),QtGui.QDialogButtonBox.ResetRole)
      self.connect (button,QtCore.SIGNAL('clicked()'),self.setXtlParams)    
      layout.addWidget(buttonBox)
      
      self.xtlParams.setLayout(layout)

    self.setXtlParams(reset=0)
    self.xtlParams.show()
    self.xtlParams.raise_()

#----------------------------------------------------------------------
  def closeXtlParams(self):
#----------------------------------------------------------------------
    self.xtlParams.close()
    del self.xtlParams
    
#----------------------------------------------------------------------
  def setXtlParams(self,reset=1):
#----------------------------------------------------------------------
    #print "setXtlParams",reset
    target = get_dispobj(name=self.objectName())
    if not target: return
    sg = ''
    if reset:
      dataobj_list = get_dataobj(target.source)
      if dataobj_list:
        source = dataobj_list[0]
        if hasattr(source,'originalSymmetry') and not source.originalSymmetry.get('status',1):
          sg = source.originalSymmetry.get('sg','')
          cell =source.originalSymmetry.get('cell','')
      
    if not sg:
      sg = getattr(target,'sg','')
      cell = getattr(target,'cell',['','','','','',''])
      
    self.xtlParams.findChild(QtGui.QWidget,'space_group').setText(QtCore.QString(sg))
    ii = -1
    for item in ['a','b','c','alpha','beta','gamma']:
      ii =ii+1
      self.xtlParams.findChild(QtGui.QWidget,item).setText(QtCore.QString(str(cell[ii])))

#----------------------------------------------------------------------
  def applyXtlParams(self):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    params = {}
    params['space_group'] = str(self.xtlParams.findChild(QtGui.QWidget,'space_group').text())
    for item in ['a','b','c','alpha','beta','gamma']:
      params[item] = float(str(self.xtlParams.findChild(QtGui.QWidget,item).text()))
      
    apply(target.set_xtl_params,[],params)

    rebuild.UpdateDisplay()

#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class GGL2dScreen(displayTable.GDataObj):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------


  def __init__(self,parent,table=None,name='',label=''):
    if not name: name = 'Legends&Images'
    if not label: label = 'Legends&Images'
    #print "initialising GGLdDScreen",name,label

    # make sure the target exists
    target = GL2DMANAGER()

    displayTable.GDataObj.__init__(self,parent,table=table,name=name,label=label,autoClose=1)
    self.iconButton.setToolTip(self.tr('Tools for handling Legends and Images'))
    
#----------------------------------------------------------------------
  def getGuiDef(self,name='icon'):
#----------------------------------------------------------------------
    if name == 'icon':
      return ['add_legend','add_image']
    else:
      return []
#----------------------------------------------------------------------
  def getActionDef(self,name,**info):
#----------------------------------------------------------------------
    #print "GCrystalContainer.objectName",self.objectName()
    target = GL2DMANAGER()
    if name == 'add_legend':
      return { 'text' : self.tr('Add legend'),
               'slot' : guiUtils.partial(MAINWINDOW().createObject,'legend') }
    if name == 'add_image':
      return { 'text' : self.tr('Add image'),
               'slot'  : MAINWINDOW().handleOpen }
    return {}

  def addDispObj(self,name=''):
    import Legend
    xl = Legend.Legend(parent=GL2DMANAGER())
    #print "xl",xl


#-------------------------------------------------------------------
class GLegend(displayTable.GDispObj):
#-------------------------------------------------------------------

  def __init__(self,parent,table=None,name=''):
    #print "initialising GLegend"
    displayTable.GDispObj.__init__(self,parent,table=table,name=name,object_type='Legend')
    self.iconButton.setToolTip(self.tr('Tools for legend display object'))
    self.type_label = 'Legend'

#----------------------------------------------------------------------
  def getGuiDef(self,name='row'):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if name == 'row':
      return [ dict ( name = 'text', mode = 'PUSHBUTTON', getLabel=target.get_text_label ,callback=self.editText, toolTip = self.tr("Enter text and select font and colour") ),
               dict ( name = 'position', mode='PUSHBUTTON', getLabel=target.get_position_label, callback=self.editPosition, toolTip = self.tr("Set position of text") )
             ]
    elif name == 'icon':
      return ['visible','centre_on','flash','move','clone','delete']

    elif name == 'colour':
      return ['colour_complement','colour_browser']
    elif name == 'context':
      return ['move']
    else:
      return displayTable.GDispObj.getGuiDef(self,name=name,target=target)
    
#-------------------------------------------------------------------      
  def getActionDef(self,name,**info):
#-------------------------------------------------------------------
    
    target = get_dispobj(name=self.objectName())
  
    if name == 'move':
      def c(): return int(self.status==1)
      return dict (
      text = "Move "+self.objectName(),
      slot = self.toggleMoving,
      checkable = 1,
      checked = c,
      deleteLater = 0
      )
    
    if name == 'colour_complement':
      return dict ( text = 'complement',
                    slot= guiUtils.partial(target.set_colour,'complement') )
    
    if name == 'colour_browser':
      return dict ( text = self.tr('Colour browser'),
                    slot= self.colour_browser )


    return displayTable.GDispObj.getActionDef(self,name=name,target=target)


#-------------------------------------------------------------------
  def editText(self):
#-------------------------------------------------------------------
    
    gui = self.findChild(QtGui.QDialog,'editTextGui')
    if gui:
      gui.show()
      gui.raise_()
      return
    
    target = get_dispobj(name=self.objectName())
    dialog = QtGui.QDialog(self)
    dialog.setObjectName('editTextGui')
    dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    dialog.setWindowTitle(self.tr('Legend text ')+self.objectName())
    layout = QtGui.QVBoxLayout()

    import TextEdit
    widget = TextEdit.TextEditWidget(self)
    widget.setObjectName('editText')
    widget.setCurrentFont(definition=FONTMANAGER().getFont('legend'),setGuiFont=True)
    widget.setText(QtCore.QString(target.get_text()))
    layout.addWidget(widget)
    
    layout0 = QtGui.QHBoxLayout()
    layout0.addStretch()
    apply = QtGui.QPushButton(self.tr('Apply'),self)
    layout0.addWidget(apply)
    close =  QtGui.QPushButton(self.tr('Close'),self)
    layout0.addWidget(close)
    layout.addLayout(layout0)

    dialog.setLayout(layout)
    dialog.show()

    self.connect(apply,QtCore.SIGNAL('released()'),self.handleEditText)
    self.connect(close,QtCore.SIGNAL('released()'),dialog.close)

#-------------------------------------------------------------------
  def handleEditText(self):
#-------------------------------------------------------------------
    widget = self.findChild(QtGui.QWidget,'editText')
    #print "handleEditText widget",widget
    text = str(self.findChild(QtGui.QWidget,'editText').text())
    #print 'handleEditText',text
    target = get_dispobj(name=self.objectName())
    target.set_text(text)
    self.updateLabel('text')
    rebuild.UpdateDisplay()


#-------------------------------------------------------------------      
  def handleEditPosition(self,args):
#-------------------------------------------------------------------
    import sys
    target = get_dispobj(name=self.objectName())
    print target
    print args
    sys.stdout.flush()
    target.set_position(x=float(args[0]),y=float(args[1]))
    self.updateLabel('position')
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------      
  def editPosition(self):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    pos = target.get_position()
    if not hasattr(self,'cartesianPicker'):
      self.cartesianPicker = mgWidgets.CartesianPickerDialog(self,x=pos[0],y=pos[1],dim=2)
      self.cartesianPicker.setWindowTitle(self.tr('Pick point in fractional screen coordinates'))
    self.cartesianPicker.UnClose()
    self.connect(self.cartesianPicker,QtCore.SIGNAL("PositionChanged"),self.handleEditPosition)

#-------------------------------------------------------------------
  def update(self):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    #Need to update text and position widgets
    widget = self.findChild(QtGui.QWidget,'editText')
    if widget:
      widget.setText(QtCore.QString(target.get_text()))
    if hasattr(self,'cartesianPicker'):
      pos = target.get_position()
      self.cartesianPicker.setParams(x=pos[0],y=pos[1])

    displayTable.GDispObj.update(self)

#-------------------------------------------------------------------
  def updateAfterMoving(self):
#-------------------------------------------------------------------
    self.updateLabel('position')
    if hasattr(self,'cartesianPicker'):
      pos =  get_dispobj(name=self.objectName()).get_position()
      self.cartesianPicker.setParams(x=pos[0],y=pos[1])

#-------------------------------------------------------------------
class GColourLegend(GLegend):
#-------------------------------------------------------------------
  def __init__(self,parent,table=None,name=''):
    #print "initialising GLegend"
    GLegend.__init__(self,parent,table=table,name=name)
    self.iconButton.setToolTip(self.tr('Tools for colour legend display object'))

      

#-------------------------------------------------------------------
class GImage(displayTable.GDispObj):
#-------------------------------------------------------------------

  #"""
  def set_visibility(self,visible=-1,redraw=1):
    import global_definitions
    target = global_definitions.get_dispobj(name=self.objectName())
    if visible<0: visible = 1 - target.get_visibility()

    icon = self.getIcon(visible=visible)
    if icon: self.iconButton.setIcon(icon)
    global_definitions.get_dispobj(name=self.objectName()).set_visibility(visibility=visible)  
    if redraw:  rebuild.UpdateDisplay()

  def getIcon(self,visible,width=32,height=32):
	import global_definitions
	target = global_definitions.get_dispobj(name=self.objectName())
	pixmap = QtGui.QPixmap(width,height)
	col = QtGui.QColor(1,1,1,0)
	pixmap.fill(col)
	painter = QtGui.QPainter()
	painter.begin(pixmap)
	if type(target.filename[2]) == unicode:
		painter.drawPixmap(0,0,QtGui.QPixmap(target.filename[2]).scaled(width,height))
	else:
		painter.drawPixmap(0,0,QtGui.QPixmap(unicode(target.filename[2],'utf-8')).scaled(width,height))
	painter.end()

	if not visible:
		image = pixmap.toImage()
		dim = False
		if image.isGrayscale(): dim = True
		for i in range(image.height()):
			for j in range(image.width()):
				pixel = image.pixel(i,j) 
				if pixel:
					if dim:
						alpha = QtGui.qAlpha(pixel)
						grey = QtGui.qGray(pixel)
						g4 = QtGui.qRgba(grey,grey,grey,alpha/2)
					else:
						alpha = QtGui.qAlpha(pixel)
						grey = QtGui.qGray(pixel)
						g4 = QtGui.qRgba(grey,grey,grey,alpha)
					image.setPixel(i,j,g4)
		pixmap = pixmap.fromImage(image)
			
	icon = QtGui.QIcon(pixmap)
	return icon
  #"""
 
  def __init__(self,parent,table=None,name=''):
    #print "initialising GImage",self,parent,name
    target = get_dispobj(name=name)
    if target.isValid:
      displayTable.GDispObj.__init__(self,parent,table=table,name=name,object_type='Image')
      self.iconButton.setToolTip(self.tr('Tools for image display object'))
    self.type_label = 'Image'
    #"""
    target = get_dispobj(name=self.objectName())
    icon = self.getIcon(visible=target.get_visibility())
    if icon: self.iconButton.setIcon(icon)
    #"""
    
#----------------------------------------------------------------------
  def editScale (self,value=0):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    target.set_scale(float(value))
    rebuild.UpdateDisplay()

#----------------------------------------------------------------------
  def getGuiDef(self,name='row'):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    if name == 'row':
      return [ dict ( name = 'scale', mode = 'VALUESLIDER', range=[0,10], getValue=target.get_scale , toolTip = self.tr("Scale image"), callback=self.editScale ),
               dict ( name = 'position', mode='PUSHBUTTON', getLabel=target.get_position_label, callback=self.editPosition, toolTip = self.tr("Set position of image") )
             ]
    elif name == 'icon':
      return ['visible','flash','move','clone','delete']
    elif name == 'context':
      return ['move']

    else:
      return displayTable.GDispObj.getGuiDef(self,name=name,target=target)


#-------------------------------------------------------------------      
  def getActionDef(self,name,**info):
#-------------------------------------------------------------------
    #
    target = get_dispobj(name=self.objectName())
    #print "GImage.getActionDef",name,'objectName',self.objectName(),target
    def c(): return int(self.status==1)
    if name == 'move':
      return dict (
      text = self.tr("Move ")+target.get_selection_label(),
      slot = self.toggleMoving,
      checkable = 1,
      checked = c,
      deleteLater = 0
      )

    if name == 'scale':
	print "scale"
    return  displayTable.GDispObj.getActionDef(self,name=name,target=target)

#-------------------------------------------------------------------      
  def handleEditPosition(self,args):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    target.set_position(x=float(args[0]),y=float(args[1]))
    self.updateLabel('position')
    rebuild.UpdateDisplay()

#-------------------------------------------------------------------      
  def editPosition(self):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    pos = target.get_position()
    if not hasattr(self,'cartesianPicker'):
      self.cartesianPicker = mgWidgets.CartesianPickerDialog(self,x=pos[0],y=pos[1],dim=2)
      self.cartesianPicker.setWindowTitle(self.tr('Pick point in fractional screen coordinates'))
    self.cartesianPicker.UnClose()
    self.connect(self.cartesianPicker,QtCore.SIGNAL("PositionChanged"),self.handleEditPosition)

    
#-------------------------------------------------------------------
  def updateAfterMoving(self):
#-------------------------------------------------------------------
    self.updateLabel('position')
    if hasattr(self,'cartesianPicker'):
      pos =  get_dispobj(name=self.objectName()).get_position()
      self.cartesianPicker.setParams(x=pos[0],y=pos[1])

#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class exportGui(QtGui.QDialog):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent=None,data_type='HBonds'):
    QtGui.QDialog.__init__(self,parent)
    self.data_type = data_type
    self.draw()
    self.show()

#-------------------------------------------------------------------
  def draw(self):
#-------------------------------------------------------------------

    self.setWindowTitle(self.tr('Export '+ self.data_type))
    layout = QtGui.QVBoxLayout()

    frame = QtGui.QFrame(self)
    frame.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Plain)
    frame_layout =  QtGui.QVBoxLayout()
    self.reloadWidget = QtGui.QCheckBox(self.tr('Read exported vector file into CCP4mg'),self)
    self.reloadWidget.setToolTip(self.tr('Create a new vector object for the ')+self.data_type)
    frame_layout.addWidget(self.reloadWidget)
    frame_layout.addWidget(QtGui.QLabel(self.tr('Comments to include in file header'),self))
    self.commentWidget = QtGui.QPlainTextEdit(self)
    self.commentWidget.setToolTip(self.tr('Add comments to file header'))
    frame_layout.addWidget(self.commentWidget)
    frame.setLayout(frame_layout)
    layout.addWidget(frame)

    file = mgWidgets.MGFileDialog(self)
    self.fileDialog = file.getFileDialog()
    self.fileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
    self.fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
    self.fileDialog.setConfirmOverwrite(False)


    self.fileDialog.setNameFilters( [ [ self.tr("Vector file")+" (*.vector)", 'vector']  ])

    self.connect(self.fileDialog, QtCore.SIGNAL('rejected()'),self.close)

    children = self.fileDialog.findChildren(QtGui.QPushButton,"")
    for child in children:
      if child.text() == self.tr("&Save"):
        self.connect(child, QtCore.SIGNAL('pressed()'),self.emitSave)
    layout.addWidget(file)

    self.setLayout(layout)
    
  def emitSave(self):
   self.emit(QtCore.SIGNAL('save'))

#-------------------------------------------------------------------
  def saveFile(self):
#-------------------------------------------------------------------
    
    target = get_dispobj(self.parent().objectName())
    if not target: return 1
    target = target[0]
    
    exfile = self.getFile()
    if not exfile: return   
    #print 'exportGui.saveFile',target,exfile
    rv = target.export_data(filename=exfile,comments=self.getComments())

    if rv[0]:
       QtGui.QMessageBox.warning(self,self.tr('Error exporting ')+self.data_type,rv[1])

    if self.getReload():
      import VectorsDispobj
      new_data = VectorsDispobj.openvectorfile(filename=exfile)
      if new_data:
        self.parent().table.addDataObj(object_type=new_data.object_type,name=new_data.name,
                   label=getattr(new_data,'name_label',''),getDispObj=1)
          
    self.close()

        
#----------------------------------------------------------------------
  def getFile(self): 
#----------------------------------------------------------------------
    exfile = self.fileDialog.selectedFiles()
    if not exfile: return ''
    exfile = str(exfile[0].toUtf8())
    if os.path.splitext(exfile)[1] != ".vector":
      exfile = exfile + ".vector"
    return exfile

#----------------------------------------------------------------------
  def getComments(self):
#----------------------------------------------------------------------
    return str(self.commentWidget.document().toPlainText())

#----------------------------------------------------------------------
  def getReload(self):
#----------------------------------------------------------------------
    return self.reloadWidget.isChecked()
  
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
class GVectorsData(displayTable.GDataObj):
#----------------------------------------------------------------------
#----------------------------------------------------------------------
#----------------------------------------------------------------------
  def __del__(self):
    if hasattr(self,"editVectorGui") and hasattr(self.editVectorGui,"endAtomPicker") and hasattr(self.editVectorGui.endAtomPicker,"dataCombo") and hasattr(self.editVectorGui.endAtomPicker.dataCombo,"disconnectGlobalSignals") and callable(self.editVectorGui.endAtomPicker.dataCombo.disconnectGlobalSignals):
       self.editVectorGui.endAtomPicker.dataCombo.disconnectGlobalSignals()
    if hasattr(self,"editVectorGui") and hasattr(self.editVectorGui,"startAtomPicker") and hasattr(self.editVectorGui.startAtomPicker,"dataCombo") and hasattr(self.editVectorGui.startAtomPicker.dataCombo,"disconnectGlobalSignals") and callable(self.editVectorGui.startAtomPicker.dataCombo.disconnectGlobalSignals):
       self.editVectorGui.startAtomPicker.dataCombo.disconnectGlobalSignals()

  def emitTheMovement(self,changed):
    self.emit(QtCore.SIGNAL('DataChanged'),changed)
  def __init__(self,parent,table=None,name='',label=''):
    #print 'GVectorsData.init',name
    displayTable.GDataObj.__init__(self,parent,table=table,name=name,label=label)
    self.iconButton.setToolTip(self.tr('Tools for vector data object'))
    self.editVectorGui = None
    self.saveGui= None
    try:
      target = get_dataobj(name=self.objectName())[0]
      self.connect(target,QtCore.SIGNAL('DataChanged'),self.emitTheMovement)
    except:
      pass
    

#----------------------------------------------------------------------
  def getGuiDef(self,name='icon'):
#----------------------------------------------------------------------
    target = get_dataobj(name=self.objectName())[0]
    alignMenu = [self.tr('Align view on')]
    centreMenu = [self.tr('Centre view on')]
    vector_list = data(self.objectName()).getVectorMenu()
    for v in vector_list:
       alignMenu.append('align_'+v)
       centreMenu.append('centre_'+v)
    
    #menudef = ['data_visible','data_centre','add_vector','add_object','data_list_data','data_save',['Clone','data_clone','data_clone_dispobj'],'data_delete']
    menudef = ['data_visible','data_centre','add_vector','add_object','data_list_data',centreMenu,alignMenu,'data_save',[self.tr('Clone'),'data_clone','data_clone_dispobj'],'data_delete']
    return menudef

#----------------------------------------------------------------------
  def centreOn(self):
#----------------------------------------------------------------------
	import pygl_coord
	import math
	total_x = 0
	total_y = 0
	total_z = 0
	vector_list = data(self.objectName()).getVectorMenu()
	numv = 0
	for i,v in zip(range(len(vector_list)),vector_list):
		vecData = data(self.objectName()).get_vector_data(i)
		if vecData and hasattr(vecData,"has_key") and vecData.has_key('start_xyz') and vecData.has_key('end_xyz'):
			start = vecData['start_xyz']
			end = vecData['end_xyz']
			x = (end[0] + start[0])*0.5
			y = (end[1] + start[1])*0.5
			z = (end[2] + start[2])*0.5
			total_x = total_x + x
			total_y = total_y + y
			total_z = total_z + z
			numv = numv + 1
	if numv>0:
		total_x = total_x/float(numv)
		total_y = total_y/float(numv)
		total_z = total_z/float(numv)
		MAINWINDOW().glWidget.centreOn([total_x,total_y,total_z])

#----------------------------------------------------------------------
  def centreVector(self,name):
#----------------------------------------------------------------------
	import pygl_coord
	import math
	vector_list = data(self.objectName()).getVectorMenu()
	for i,v in zip(range(len(vector_list)),vector_list):
		if v == name[len("centre_"):]:
			vecData = data(self.objectName()).get_vector_data(i)
			if vecData and hasattr(vecData,"has_key") and vecData.has_key('start_xyz') and vecData.has_key('end_xyz'):
				start = vecData['start_xyz']
				end = vecData['end_xyz']
				x = (end[0] + start[0])*0.5
				y = (end[1] + start[1])*0.5
				z = (end[2] + start[2])*0.5
				MAINWINDOW().glWidget.centreOn([x,y,z])
				break

#----------------------------------------------------------------------
  def align(self,name):
#----------------------------------------------------------------------
	import pygl_coord
	import math
	vector_list = data(self.objectName()).getVectorMenu()
	for i,v in zip(range(len(vector_list)),vector_list):
		if v == name[len("align_"):]:
			vecData = data(self.objectName()).get_vector_data(i)
			if vecData and hasattr(vecData,"has_key") and vecData.has_key('start_xyz') and vecData.has_key('end_xyz'):
				start = vecData['start_xyz']
				end = vecData['end_xyz']
				x = end[0] - start[0]
				y = end[1] - start[1]
				z = end[2] - start[2]
				cart = pygl_coord.Cartesian(x,y,z)
				cart.normalize()
				cartz = pygl_coord.Cartesian(0,0,1)
				angle = math.acos(pygl_coord.Cartesian.DotProduct(cart,cartz))
				if angle>0:
					cartN = pygl_coord.Cartesian.CrossProduct(cart,cartz)
					quat = pygl_coord.Quat(cartN.get_x(),cartN.get_y(),cartN.get_z(),1,angle*180./math.pi)
				else:
					quat = pygl_coord.Quat(0,0,1,0,0)
				MAINWINDOW().glWidget.setQuat(quat)
				break

#----------------------------------------------------------------------
  def getActionDef(self,name,**info):
#----------------------------------------------------------------------    
    target = get_dataobj(name=self.objectName())[0]
    
    if name[0:len("align_")] == 'align_':
      return dict (
      text = name[len("align_"):],
      slot = guiUtils.partial(self.align,name),
      toolTip = self.tr('Align graphics view on vector')
      )
    
    if name[0:len("centre_")] == 'centre_':
      return dict (
      text = name[len("centre_"):],
      slot = guiUtils.partial(self.centreVector,name),
      toolTip = self.tr('Centre graphics view on vector')
      )
    
    if name == 'data_save':
      return dict (
      text = self.tr("Save to file"),
      slot = self.save,
      toolTip = self.tr('Save the vector data to a file')
      )
    
    if name == 'edit_tags':
      return dict (
      text = self.tr("Edit tags"),
      slot = self.editTag,
      toolTip = self.tr('Create and edit tags used to group vectors')
      )
    
    if name == 'add_vector':
      return dict (
      text = self.tr("Edit vectors"),
      slot = self.editVector,
      toolTip = self.tr('Change an existing vector or create a new one')
      )
    
    if name == 'add_object':
      return dict (
      text = self.tr("Add vector display object"),
      slot = guiUtils.partial(self.add_dispobj,[target,'VectorsDispobj']),
      toolTip = self.tr('Add a vector display object')
      )

    if name == 'data_centre':
       return dict (
      text = self.tr("Centre on"),
      slot = self.centreOn,
      toolTip = self.tr('Centre display on the vectors'),
      enabled = 1
      )
     
    return displayTable.GDataObj.getActionDef(self,name=name,target=target)


#----------------------------------------------------------------------    
  def editVector(self):
#----------------------------------------------------------------------
    target = data(self.objectName())
    if not target.getDataMode():
      dialog = QtGui.QMessageBox(self)
      dialog.setWindowTitle(self.tr('Creating vectors'))
      dialog.setText(self.tr('Create vectors between pairs of atoms or pairs of points'))
      button = dialog.addButton(self.tr('Between atoms'),QtGui.QMessageBox.AcceptRole)
      button = dialog.addButton(self.tr('Between points'),QtGui.QMessageBox.AcceptRole)
      mode = dialog.exec_()
      target.setDataMode(['atoms','points'][mode])
      
    if not self.editVectorGui:
      import vectorsGui
      mode = target.getDataMode()
      if mode == 'atoms':
        self.editVectorGui = vectorsGui.editVectorDialog(self,VectorsDataName=self.objectName(),mode=['atom','atom'])
      else:
        self.editVectorGui = vectorsGui.editVectorDialog(self,VectorsDataName=self.objectName(),mode=['point','point'])
    self.editVectorGui.show()
    self.editVectorGui.raise_()


  def listData(self):
    status,text = data(self.objectName()).export_data()
    if status:
      QtGui.QMessageBox.warning(self,self.tr('Listing vector data'),self.tr('Error creating data listing'))
    window = FILEVIEWER('data_listing').loadText(text,title=self.objectName())
    window.setFont(style='fixed_width')

  def save(self):
      saveGui=mgWidgets.MGSaveFileDialog(self,self.tr('Save vectors'),[ [ self.tr("vector file")+" (*.vector)", 'vector']])
      self.connect(saveGui,QtCore.SIGNAL('save'),self.handleSave)
      saveGui.exec_()

  def handleSave(self,filename):
    #print 'handleSave',filename
    data(self.objectName()).save_file(filename)

  def Exit(self):
    #print 'GVectorData.Exit', data(self.objectName()).edited
    # Give option to save data changes on program exit
    if data(self.objectName()).edited:
      if not self.saveGui:
        self.saveGui=mgWidgets.MGSaveFileDialog(self,self.tr('Save vectors'),[ [self.tr( "vector file")+" (*.vector)", 'vector']])
      else:
        self.saveGui.hide()
      rv = self.saveGui.exec_()
      #print 'GVectorData.Exit rv',rv
      if not rv:
        filename = self.saveGui.getFilename()
        if filename:(data(self.objectName()).save_file(filename))

  """
  def centreOn(self):
    com = data(self.objectName()).centre()
    MAINWINDOW().centreOn(com)
  """
   
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class GVectorsDispobj(displayTable.GDispObj):
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------

  def __init__(self,parent,table=None,name=''):
    displayTable.GDispObj.__init__(self,parent,table=table,name=name,object_type='VectorsDispobj')
    self.iconButton.setToolTip(self.tr('Tools for vectors display object'))
    self.lineStyleGui = None
    self.selectionGui = None
    self.type_label = 'Vector display object'

#----------------------------------------------------------------------
  def getGuiDef(self,name='row',pickevent=None):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if name == 'row':
      return [ dict ( name = 'selection', mode = 'PUSHBUTTON', getLabel=target.get_selection_label ,callback=self.handleSelection,toolTip=self.tr('Select vectors to display')),
               dict ( name = 'style', mode='PUSHBUTTON', getIcon=functools.partial(getVectorIcon,target), getLabel=target.get_style_label, callback=self.handleStyle , toolTip = self.tr("Edit vector drawing style and text style") ) ]
      
    if name == 'icon':
      return ['visible','flash','transparency','clone','delete']

    return displayTable.GDispObj.getGuiDef(self,name=name,target=target)

#----------------------------------------------------------------------
  def getActionDef(self,name=''):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    return  displayTable.GDispObj.getActionDef(self,name=name,target=target)

#----------------------------------------------------------------------
  def handleSelection(self):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    nl = len(target.parent.getTagList())
    if nl < 1:
      QtGui.QMessageBox.warning(self,self.tr('Selecting vectors'),self.tr('Vectors do not have tags so no selection possible'))
      return
    if not self.selectionGui:
      import vectorsGui
      self.selectionGui = vectorsGui.VectorSelection(self,VectorsDataName=target.parent.name)
      self.connect(self.selectionGui,QtCore.SIGNAL('changed'),self.set_selection)
    else:
      self.selectionGui.load()
    self.selectionGui.setSelection(target.selection)
    self.selectionGui.show()
    self.selectionGui.raise_()
       
#----------------------------------------------------------------------
  def handleStyle(self):
#----------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not self.lineStyleGui:
      import vectorsGui
      self.lineStyleGui = vectorsGui.VectorLineStyle(self)
      self.connect(self.lineStyleGui,QtCore.SIGNAL('changed'),self.set_style)
    self.lineStyleGui.setParams(target.params())
    self.lineStyleGui.show()
    self.lineStyleGui.raise_()
    
  
#-------------------------------------------------------------------
  def set_style(self,mode='style'):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    if mode == 'style':
      target.set_style(self.lineStyleGui.getParams())
    elif mode == 'font':
      target.set_font(self.lineStyleGui.getFont())

    #rebuild.UpdateDisplay(target=target,controllingWidget=self)
    rebuild.UpdateDisplay()
    self.updateLabel('style')
    
   
#-------------------------------------------------------------------
  def set_selection(self):
#-------------------------------------------------------------------
    target = get_dispobj(name=self.objectName())
    if not target: return
    target.set_selection(self.selectionGui.getSelection())
    #rebuild.UpdateDisplay(target=target,controllingWidget=self)
    rebuild.UpdateDisplay()
    self.updateLabel('selection')
    
