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

     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 GUI
from dataobj import Dependency
import mmut
import pygl_coord

#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
class CInterSel(Dependency):
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------

  operator_menu = ['OR: add to current selection', \
                   'EXCLude: exclude from selection (=and not)', \
                          'AND - atom must be in both selections']
  operator_alias = ['or','excl','and']

  ifskeleton = 1
  skeleton_selection = 'ALL'

#----------------------------------------------------------------------
  def __init__(self,moldisp=None,CSelection=None):
#----------------------------------------------------------------------
    self.moldisp = moldisp
    self.CSelection = CSelection
    self.skeleton=None
    self.saved_style_mode = None
    self.gui_user_sel = ''
    self.user_sel_range = []
    self.operator = 'or'
    self.not_operator = 0
    self.object_type = ''
    self.interface_mode = 'advanced'
    self.gui_user_sel_stack = []
    
    self.name = 'CInterSel'
    Dependency.__init__(self)
    
    self.set_skeleton()

#----------------------------------------------------------------------
  def delete(self):
#----------------------------------------------------------------------    
    #print "Deleting CInterSel",self,self.CSelection
    if self.skeleton:
      self.handle_skeleton(mode=-1)
      self.skeleton = None
    ATOMPICKING().popup_request( \
       mode='vertex',feature='user_sel',delete=1)
    GUI.GUI.insts.DeleteGUIWindow ( 'mol_userselect'+self.moldisp.name)
    if self.saved_style_mode and self.CSelection.style == 'FATBONDS':
      # Beware the CSelection object may have been zapped
      try:
        self.CSelection.set_style(style_mode=self.saved_style_mode)
      except:
        pass
    try:
      self.CSelection.CInterSel=None
      if hasattr(self.CSelection,'selection_params'):
        self.CSelection.selection_params['interactive_sele_gui']='off'
    except:
      pass
    Dependency.delete(self)
    
#--------------------------------------------------------------------
  def name_string(self):
#--------------------------------------------------------------------
    return  'model.'+self.CSelection.name_string()+'.CInterSel'


#----------------------------------------------------------------------
  def user_sel_popup (self,**keywords):
#------------------------------------------------------------------------
    # Define a portion of the pop-up menu to appear when
    # the user picks an atom
    molobj,dispobj,atomptr = ATOMPICKING().get_last_picked(\
       'atom')
    #print "molobj,dispobj",molobj.name,dispobj.name
    if molobj != self.CSelection.parent: return ['','','']
    range_menu = ['Start residue range','Start atom range','Start chain range']
    range_alias = ['start_residue','start_atom','start_chain']
    if self.user_sel_range:
      range_menu.insert(0,'End range from '+self.user_sel_range[1])
      range_alias.insert(0,'end')
    if ['excl'].count(self.operator):
      exclude = '1'
    else:
      exclude = '0'
    params = [
           ['RETURN',self.name_string()+'.handle_user_sel_popup'], 
            ['PARAM','selected_atom',
            ['TYPE','text'],
            ['INITIAL','%atomid%']],
           ['PARAM','exclude',
             ['TYPE','_logical'],
             ['INITIAL',exclude],
             ['LABEL','Exclude next selection']],
           ['PARAM','add_user_sel',
             ['TYPEDEF','menu',['atom','side chain','main chain','residue','SSE','chain','all'],
                             ['atom','side','main','residue','SSE','chain','all']],
             ['INITIAL',''],
             ['LABEL','Select this..']],
           ['PARAM','add_user_range',
             ['TYPEDEF','menu',range_menu,range_alias],
             ['INITIAL',''],
             ['LABEL','Atom/res/chain range..']],
           ['PARAM','add_user_neighb',
             ['TYPEDEF','menu',['atom','residue','chain'],
                             ['atom','residue','chain']],
             ['INITIAL',''],
             ['LABEL',"Neighbhood of this.."]],
           ['PARAM','undo',
             ['TYPE','_logical'],
             ['LABEL','Undo last']],
           ['PARAM','skeleton_selection' ,
             ['LABEL','Skeleton atoms'],
             ['TYPEDEF','menu',['no skeleton','all atoms','trace and monomers'], \
                           ['OFF','ALL','CALIGAND']],
             ['INITIAL',self.skeleton_selection]]
        ]

    display = [ ['lab','Select'],
                ['cb','exclude'],
                ['pr','add_user_sel'],
                ['pr','add_user_neighb'],
                ['pr','add_user_range']]
    
    if self.gui_user_sel_stack: display.append(['com','undo'])
    display.append(['pr','skeleton_selection'])
    return ['',params,display]


#-----------------------------------------------------------------------
  def handle_user_sel_popup( self,add_user_sel='',selected_atom='', \
              add_user_neighb='', add_user_range='', exclude='', undo='', \
                            skeleton_selection='', **keywords ):
#-----------------------------------------------------------------------
    #print "handle_user_sel_popup",undo,add_user_sel
    if exclude:
      if exclude == '1':
        self.operator = 'excl'
      else:
        self.operator = 'or'
      GUI.GUI.insts.UpdateGUIWindow ( 'mol_userselect'+self.moldisp.name, \
      [['PARAM','operator',
       ['UPDATE',self.operator]]])

    if not selected_atom:
      from atom_util import inta
      molobj,dispobj,atomptr = ATOMPICKING().get_last_picked('atom')
      mask = inta(9)
      py_mask = [0,1,1,1,1,1,1,1,0]
      for i in range(0,9): mask[i]=py_mask[i]
      selected_atom = molobj.molHnd.AtomLabel_mask(atomptr,mask)
      del mask
      
    if add_user_sel:
      
      if add_user_sel == 'all':
        # reset to all or nothing
        if self.operator == 'excl':
          sel = ''
        elif self.operator == 'or':
          sel = 'all'
        self.append_sel(sel=sel,mode='reset')
        return 0
      
      elif add_user_sel == 'atom':
        sel = selected_atom
      elif ['side','main'].count(add_user_sel):
        import mmdb2 as mmdb
        import string
        sel = self.CSelection.parent.convertAtomID ( inp = 'atom', \
                      out = 'residue', atomID = selected_atom)
        if add_user_sel == 'side':
          cmd = sel+' and not main'
        else:
          cmd = sel+' and main'
        rv=self.CSelection.parent.parse_selection(command=cmd)
        if not rv[0]:
          selAtoms = mmdb.newPPCAtom()
          selindexp = pygl_coord.intp()
          #natoms = self.CSelection.parent.molHnd.GetSelIndex(rv[1],selAtoms)
          selAtoms = mmut.GetAtomSelIndex(self.CSelection.parent.molHnd,rv[1],selindexp)
          natoms = selindexp.value()
          for n in range(0,natoms):
            pcat = mmdb.getPCAtom(selAtoms,n)
            sel = sel+string.strip(pcat.GetAtomName())+','
          sel = sel[0:-1]
          self.CSelection.parent.molHnd.DeleteSelection(rv[1])
          #mmdb.delPPCAtom(selAtoms)
        
      elif add_user_sel == 'SSE':
        molobj,dispobj,atomptr = \
          ATOMPICKING().get_last_picked('atom')
        mask = inta(7)
        for i in range(0,7): mask[i] = 1
        import string
        sub = string.strip(molobj.molHnd.ListSecStructure(mask,atomptr))
        if sub:
          sel = string.split(sub)[1]
        else:
          return
      else:
        sel = self.CSelection.parent.convertAtomID ( inp = 'atom', \
                      out = add_user_sel, atomID = selected_atom)
      #print "handle_user_sel_popup",sel
      self.append_sel(sel)
      return 0
    
    elif add_user_neighb:
      if add_user_neighb == 'atom':
        sel = selected_atom
      else:
        sel = self.CSelection.parent.convertAtomID ( inp = 'atom', \
                      out = add_user_neighb, atomID = selected_atom)
      self.CSelection.define_neighb(selparams={'neighb_sel': sel } , \
        gui_offset='mol_userselect'+self.moldisp.name,return_method=self.name_string()+'.handle')
      
    elif add_user_range:
      if add_user_range[0:5] == 'start':
        import string
        start,mode = string.split(add_user_range,'_')
        sel = self.CSelection.parent.convertAtomID ( inp = 'atom', \
             out = mode , atomID = selected_atom)
        self.user_sel_range = [mode,sel]
        #print "add_user_range",self.user_sel_range
      elif  add_user_range == 'end' and self.user_sel_range:
        sel = self.CSelection.parent.convertAtomID ( inp = 'atom', \
             out =self.user_sel_range[0] , atomID = selected_atom)
    
        self.append_sel('range '+ self.user_sel_range[1]+' '+ \
                        sel+ ' ' + self.user_sel_range[0] )
        self.user_sel_range = ''

    elif undo:
      self.append_sel(mode='undo')
      
    elif skeleton_selection:
      if skeleton_selection == 'OFF':
        if  self.ifskeleton:
          self.ifskeleton = 0
          self.handle_skeleton(mode=-1)
      else:
        if not self.ifskeleton:
          self.ifskeleton = 1
          CInterSel.skeleton_selection = skeleton_selection
          self.handle_skeleton(mode=1)
        elif skeleton_selection != self.skeleton_selection:
          CInterSel.skeleton_selection = skeleton_selection
          self.handle_skeleton(mode=0)



#--------------------------------------------------------------------
  def handle_selection ( self,widget='',exit='',**keywords ):
#--------------------------------------------------------------------
    if exit == 'dismiss' or \
       (widget == 'ranges' and ['add','delete'].count(exit)): return
    retval = self.moldisp.interpret_selection (kw=keywords,widget=widget)
    if retval[0] or not retval[3]: return
    status,separams,sel,alias = retval
    rv,command = self.CSelection.parent.list_to_command(sel)
    self.append_sel(sel=command)
    
#---------------------------------------------------------------------
  def append_sel ( self, sel='',operator = '',not_operator='',mode='append',user_alias='' ):
#---------------------------------------------------------------------
    import string
    import re
    import utils

    #print "append_sel",sel,mode

    # self.gui_user_sel = Selection string that appears in GUI - include
    #                     line breaks and html style < > etc
    # sel0              = corrected selection string
    #print "append_sel",sel,operator,mode
    #print "gui_user_sel",self.gui_user_sel

    # Put current selection on stack
    self.gui_user_sel_stack.append(self.gui_user_sel)

    if mode == 'append':
      # sel is a selection to be appended to existing com string
      if not sel: return
      if sel: sel = string.strip(sel)
    
      if not_operator != '':
        notop = not_operator
      else:
        notop = self.not_operator
      if notop and not re.match(r'^not',sel):
        sel = 'not '+sel
        
      # convert < and > to standard &lt &gt (eg from Property menu)
      sel = re.sub('&','&amp;',sel)
      sel = re.sub('<','&lt;',sel)
      sel = re.sub('>','&gt;',sel)
      if not self.gui_user_sel:
        self.gui_user_sel = str(sel)
      elif operator:
        string.strip(self.gui_user_sel)
        self.gui_user_sel = re.sub('<br>$','',self.gui_user_sel)
        self.gui_user_sel = self.gui_user_sel+' <br> '+str(operator)+' '+str(sel)
      else:
        self.gui_user_sel = self.gui_user_sel+' <br> '+self.operator+' '+str(sel)
        
    elif mode == 'undo':
      if len(self.gui_user_sel_stack)<2: return [1]
      self.gui_user_sel = self.gui_user_sel_stack.pop()
      self.gui_user_sel = self.gui_user_sel_stack.pop()
      
    elif ['update'].count(mode):
      # Called from MolDisp.set_selection when user has picked the
      # display table selection menu
      self.gui_user_sel = string.strip(sel)
    
    elif ['reset'].count(mode):
      # User has editted command in text window
      # - could be very wrong
      self.gui_user_sel = re.sub('<br>','',sel)
      self.gui_user_sel = re.sub('&','&amp;',self.gui_user_sel)
      self.gui_user_sel = re.sub('<','&lt;',self.gui_user_sel)
      self.gui_user_sel = re.sub('>','&gt;',self.gui_user_sel)
      self.gui_user_sel = re.sub(' or ',' <br> or ',self.gui_user_sel)
      self.gui_user_sel = re.sub(' and ',' <br> and ',self.gui_user_sel)
      self.gui_user_sel = re.sub(' excl ',' <br> excl ',self.gui_user_sel)
      
    # Update the MolDisp selection params 
    # (not necessary if this call is MolDisp updating CInterSel!)
    if mode != 'update':
      sel0 = re.sub('<br>','',self.gui_user_sel)
      sel0 = re.sub('&amp','&',sel0)
      sel0 = re.sub('&lt;','<',sel0)
      sel0 = re.sub('&gt;','>',sel0)

      if not sel0:
        self.gui_user_sel = ''
        self.CSelection.set_selection(select='cid',cid='',user_sel=1)
        self.CSelection.update_selection('','No selection')
      else:
        rv = self.CSelection.parent.parse_selection(command=sel0,test=1)
        #print "rv",rv
        if rv[0] != 0 :
          self.gui_user_sel = self.gui_user_sel_stack.pop()
          GUI.GUI.insts.WarningMessage('Can not interpret selection command')
          return [1]     
        # Sort out the alias
        if user_alias:
          user_alias = utils.oneWord(user_alias,tcl_safe=1)
        else:
          user_alias = utils.oneWord(sel0,tcl_safe=1)
        if len(user_alias) > 20: user_alias = user_alias[0:20]
        
        self.CSelection.set_selection(select='cid',cid=sel0,user_sel=1)
        if len(rv)>2:
          self.CSelection.update_selection(rv[2],user_alias)
        else:
          self.CSelection.update_selection('',user_alias)

    #print "updating gui gui_user_sel",self.gui_user_sel
    GUI.GUI.insts.UpdateGUIWindow ( 'mol_userselect'+self.moldisp.name, [
          ['OBJECT','user_sel',
          ['CONFIGURE', ['text', utils.tclSafe(self.gui_user_sel) ]]]])

    
#--------------------------------------------------------------------
  def handle_skeleton(self,mode=0):
#--------------------------------------------------------------------
    if mode>0:
      # Create a 'skeleton' MolDisp object
      style = {}
      style['style_mode'] = 'THINBONDS'
      sel = {}
      sel['select']='all'
      if self.skeleton_selection == 'CALIGAND':
        sel['select']="catrace"
        if self.CSelection.parent.monomers:
          sel['monomers']= []
          for mon in self.CSelection.parent.monomers:
            sel['monomers'].append(mon)
      import model
      self.skeleton = model.MolDisp (self.CSelection.parent.name, \
               selparams = sel, styleparams=style, \
               master_application=self,display_table_visible=0)
    elif mode < 0:
      if self.skeleton: self.skeleton.delete()
      self.skeleton = None
    else:
      if not self.skeleton: return
      # Update the skeleton display selection
      if self.skeleton_selection == 'CALIGAND':  
        self.skeleton.set_selection(select="catrace",monomers='all')
      else:
        self.skeleton.set_selection(select="all")

#--------------------------------------------------------------------
  def set_skeleton(self):
#--------------------------------------------------------------------
      if self.ifskeleton:
        if self.skeleton:
          #There is already a skeleton - force it visible
          self.skeleton.set_visibility(visibility='1')
          self.set_fatbonds()
          return
        else:
          self.handle_skeleton(mode=1)
          self.set_fatbonds()
          # Do not return - allow the current selection to be applied
      else:
        if self.skeleton: self.skeleton.set_visibility(visibility='0')
        self.set_fatbonds(0)
        return

#-----------------------------------------------------------------------
  def set_fatbonds(self,mode=1):
#-----------------------------------------------------------------------
    # Force the current object style to FATBONDS if it is currently
    # BONDS or THINBONDS
    if  self.CSelection.object_type != 'MolDisp': return
    if mode:
      if self.CSelection.style_mode == 'BONDS' or \
              self.CSelection.style_mode == 'THINBONDS':
        self.saved_style_mode = self.CSelection.style_mode
        self.CSelection.set_style(style_mode='FATBONDS')
    else:
      if self.saved_style_mode:
        self.CSelection.set_style(style_mode=self.saved_style_mode)
        self.saved_style_mode = None

#------------------------------------------------------------------
  def define_userselect (self,interface_mode='',user_sel='',
                         user_alias='',user_old_alias=''):
#------------------------------------------------------------------
    import utils
    import re
 
    if interface_mode: self.interface_mode =interface_mode
    
    if user_sel or user_alias:
      self.set_user_selection(user_sel=user_sel, \
                          user_alias=user_alias, \
                          user_old_alias=user_alias)

    if utils.oneWord(user_sel) == user_alias:
      user_alias = ''
    if user_sel:
      self.gui_user_sel = re.sub('<','&lt;',user_sel)
      self.gui_user_sel = re.sub('>','&gt;',self.gui_user_sel)
      self.gui_user_sel = re.sub('&','&amp;',self.gui_user_sel)
      self.gui_user_sel = re.sub(' or ',' <br> or ',self.gui_user_sel)
      self.gui_user_sel = re.sub(' and ',' <br> and ',self.gui_user_sel)
      self.gui_user_sel = re.sub(' excl ',' <br> excl ',self.gui_user_sel)
    else:
      self.gui_user_sel = ''

    save_mode_menu = ['this model','all models']
    save_mode_menu.extend(MODELINFO().list_loaded())
    save_mode_alias = ['this','generic']
    save_mode_alias.extend(MODELINFO().list_loaded())

    if self.interface_mode == 'advanced':    
      desc = [
      ['TITLE','Atom Selection for '+self.CSelection.parent.name_label],
      ['ICON',' Selection'],
      ['HELP','selection#interactive'],
      ['RETURN_METHOD','set_user_selection',
       ['RETURN_LIST','save','select','user_alias',
        ['user_sel::text',['ALIAS','user_sel']]]],
      ['PARAM','select',
         ['TYPEDEF','postmenu',[''],[''],'15'],
         ['RETURN_METHOD','handle',
           ['RETURN_LIST',
            ['user_sel::text',['ALIAS','user_sel']]]],
         ['INITIAL','selection..'] ],
      ['PARAM','save',
         ['TYPEDEF','varbutton','1','0'],
         ['RETURN_METHOD','handle_save',
           ['RETURN_LIST','save','user_alias','save_mode',
           ['user_sel::text',['ALIAS','user_sel']]]],
         ['LABEL','Save'] ],
    #  ['PARAM','overwrite',
    #     ['TYPE','_logical'],
    #     ['INITIAL','1']],
      ['PARAM','save_mode',
         ['TYPEDEF','menu',save_mode_menu,save_mode_alias],
         ['INITIAL','this']],
      ['PARAM','user_alias',
         ['TYPE','_text30'],
         ['INITIAL',utils.tclSafe(user_alias)]],
      ['PARAM','operator',
       ['TYPEDEF','menu',self.operator_menu,self.operator_alias],
       ['INITIAL',self.operator],
       ['RETURN_METHOD','set_user_selection',
         ['RETURN_LIST','operator']]],
      ['PARAM','not_operator',
       ['TYPE','_logical'],
       ['INITIAL',self.not_operator],
       ['RETURN_METHOD','set_user_selection',
         ['RETURN_LIST','not_operator']]],
      ['PARAM','ifskeleton',
         ['TYPE','_logical'],
         ['INITIAL',self.ifskeleton],
         ['RETURN_METHOD','set_user_selection',
           ['RETURN_LIST','ifskeleton','user_alias','user_old_alias',
            ['user_sel::text',['ALIAS','user_sel']]]]],
      ['PARAM','skeleton_selection',
         ['TYPEDEF','menu',['all atoms','trace and monomers'], \
                               ['ALL','CALIGAND']],
         ['INITIAL',self.skeleton_selection],
         ['RETURN_METHOD','set_user_selection',
           ['RETURN_LIST','skeleton_selection']]],
      ['OBJECT','user_sel',
          ['TYPE','TextEditor'],
          ['CONFIGURE', ['text',utils.tclSafe(self.gui_user_sel)]]],
      ['DISPLAY','WINDOW',
          ['LINE',
            ['MESSAGE','Show the unselected atoms in the model so they can be picked'],
            ['WIDGET','ifskeleton'],
            ['LABEL','Show'],
            ['MESSAGE','Show CA trace or all atoms'],
            ['WIDGET','skeleton_selection'],
            ['LABEL','molecule skeleton for interactive selection']],
          ['LINE',
            ['LABEL','Combine next selection by'],
            ['MESSAGE','Use operator to merge next entered selection'],
            ['WIDGET','operator'],
            ['WIDGET','not_operator'],
            ['LABEL','NOT the next selection']],
           ['LINE',
            ['LABEL','Select from menu','-italic'],
            ['MESSAGE','Choose selection command from the menu'],
            ['WIDGET','select'],
            ['LABEL','OR right-click on atom for pop-up menu OR edit text window below','-italic']],
          ['DRAW','user_sel'],
       # Beware not using default 'dismiss' button since want all
       # parameter 'select' returned so set_selection knows that
       # it is this window which is closing down
          ['LINE',
            ['MESSAGE','Save selection command for this model or for general use'],
            ['LABEL','Save for'],
            ['WIDGET','save_mode'],
            ['MESSAGE','Enter a one word identifier for the selection command'],
            ['LABEL','as named selection:'],
            ['WIDGET','user_alias'],
            ['MESSAGE','Save selection command now'],
            ['WIDGET','save']],
    #      ['LINE',
    #        ['WIDGET','overwrite'],
    #        ['LABEL','Overwrite any any selection with same name']],
         ['BUTTONS',['ok',['LABEL','Apply'],
                          ['MESSAGE','Apply selection now']],
                      ['undo',['LABEL','Undo last']],
                      ['clear',['LABEL','Clear selection']],
                      ['dismiss',['CLOSE']]]
          ]
       ]

      GUI.GUI.insts.CreateGUIWindow ( 'mol_userselect'+self.moldisp.name,self , desc)
    elif self.interface_mode == 'simple':
      GUI.GUI.insts.DeleteGUIWindow ( 'mol_userselect'+self.moldisp.name)
      
    # And append options to the atom pick menu
    ATOMPICKING().popup_request( \
              mode='vertex',feature='user_sel', \
              module='model',
              method=self.name_string()+'.user_sel_popup')


#----------------------------------------------------------------------
  def handle ( self, post_menu='',window='',parent='',
                      _neighb='',_ranges='',
                      _property='',_cid='',widget='', exit='', **keywords):
#----------------------------------------------------------------------
    if exit == 'dismiss': return
    if post_menu == 'select':
      import model
      guidef,menu = model.define_selection_menu( moldata=self.moldisp.parent,
        not_required=['not_select','interactive_sele_gui','remove_user','save_current'])
      guidef.insert(0,['WINDOW_ID',window])
      guidef.insert(1,['PARENT',parent])
      guidef.insert(2,['RETURN_METHOD','handle',
                        ['RETURN_WIDGET']] )
      display = [['DISPLAY','PULLDOWN', menu ]]
      guidef.extend(display)
      #print "intersel handle guidef",guidef

      GUI.GUI.insts.CreateGUIWindow('mol_selection',self,guidef)
    else:
      if _neighb=='1':
        self.CSelection.define_neighb(gui_offset='mol_userselect'+self.moldisp.name,\
         return_method=self.name_string()+'.handle_selection' )
      elif _ranges=='1':
        self.CSelection.define_ranges(gui_offset='mol_userselect'+self.moldisp.name,\
         return_method=self.name_string()+'.handle_selection')
      elif _property=='1':
        self.CSelection.define_property(gui_offset='mol_userselect'+self.moldisp.name, \
         return_method=self.name_string()+'.handle_selection')
  
      else:
        retval = self.moldisp.interpret_selection(selparams={},kw=keywords,widget=widget)
        
        if retval[0] or not retval[3]: return
        status,selparams,sel,alias = retval
        rv,command = self.CSelection.parent.list_to_command(sel)
        self.append_sel(sel=command)

#-----------------------------------------------------------------------
  def set_user_selection ( self,user_alias='', user_sel='', 
                           ifskeleton='',skeleton_selection='',
               operator='',not_operator='',
               exit='',widget='',**keywords):
#-----------------------------------------------------------------------
    import re
    import utils

    # Deal with the display handling tools
    if operator:
      self.operator = operator
      return

    if not_operator:
      self.not_operator = int(not_operator)
      return

    if skeleton_selection:
      CInterSel.skeleton_selection = skeleton_selection
      self.handle_skeleton(mode=0)
      return
    
    if ifskeleton and int(ifskeleton) != self.ifskeleton:
      self.ifskeleton = int(ifskeleton)
      self.set_skeleton()
      return
    
    if exit == 'dismiss':
      self.delete()
      del self
      return

    elif exit == 'clear':
      self.append_sel(sel='',mode='reset')
      return
      
    elif exit == 'undo':
      self.append_sel(mode='undo')
      return
    
    elif exit == 'ok' or user_sel:
      #print "user_sel",user_sel
      self.append_sel(sel=user_sel,mode='reset')
      return 

#---------------------------------------------------------------------------
  def handle_save(self,save='',save_mode='this', \
                  user_alias='',user_sel='',**keywords):
#---------------------------------------------------------------------------
    import re
    if not user_alias:
      GUI.GUI.insts.WarningMessage('Please enter a short name for the selection before saving',parent = 'mol_userselect'+self.moldisp.name)
      return
    if not user_sel:
      GUI.GUI.insts.WarningMessage('Please enter a selection before saving',parent = 'mol_userselect'+self.moldisp.name)
      return
  
    user_sel = re.sub ('<br>',' ',user_sel)             
    rv = self.CSelection.parent.parse_selection(command=user_sel,test=1)
      #print "parse_selection rv",rv
    if rv[0] != 0:
      GUI.GUI.insts.WarningMessage('Selection is not interpretable',parent = 'mol_userselect'+self.moldisp.name)
      return
    elif rv[1] == 0 or len(rv)<3:
      alias = user_alias
      sel = ""
    else:
      alias = user_alias
      sel = rv[2]

    #print "handle_save alias",alias,'sel',sel
    if (sel):
      self.moldisp.save_current_selection (overwrite='1', \
           save_mode=save_mode,alias=user_alias,selection=sel)
           
      
    self.moldisp.update_selection(sel,alias)
