modules/pmg_tk/Setting.py (75 lines of code) (raw):
#A*
#-------------------------------------------------------------------
#B* This file contains source code for the PyMOL computer program C*
#copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific. D*
#-------------------------------------------------------------------
#E* It is unlawful to modify or remove this copyright notice. F*
#-------------------------------------------------------------------
#G* Please see the accompanying LICENSE file for further information.
#H*
#-------------------------------------------------------------------
#I* Additional authors of this source file include: -* -* NOTE: Based
#on code by John E. Grayson which was in turn -* based on code written
#by Doug Hellmann. Z*
#-------------------------------------------------------------------
# this section is devoted to making sure that Tkinter variables which
# correspond to Menu-displayed settings are kept synchronized with
# PyMOL
import sys
if sys.version_info[0] == 2:
import Tkinter
from Tkinter import IntVar
else:
import tkinter as Tkinter
from tkinter import IntVar
import time
from pymol import cmd, Scratch_Storage
class PymolVar(Tkinter.Variable, object):
'''Tk variable synced with PyMOL setting'''
_items = False
def __init__(self, sinst, index, v):
self.s = sinst # pmg_tk.Setting.Setting instance
self.index = index # setting index
self.skip_w = -1 # prevent trace_w/update loops
super(PymolVar, self).__init__()
self.set(v)
self.trace_variable('w', self.trace_w)
def trace_w(self, *args):
'''Set the PyMOL setting to this var's value'''
if self.skip_w > 0:
self.skip_w -= 1
return
self.s.set(self.index, self.get())
def update(self):
'''Set this var's value to the PyMOL setting's value'''
self.skip_w += 1
if not self.skip_w:
return
vt = self.s.get_setting_tuple(self.index)[1]
if self._items:
self.set(str(vt))
for item, v in zip(self._items, vt):
item.skip_w += 1
item.set(v)
else:
self.set(vt[0])
def __getitem__(self, i):
'''For 3f settings: provide sub-variables for items'''
if not self._items:
self._items = []
N = len(self._items)
if N <= i:
v = self.s.get_setting_tuple(self.index)[1]
for j in range(N, i+1):
self._items.append(ListVarItem(j,
self.s, self.index, round(v[j], 5)))
return self._items[i]
class ListVarItem(PymolVar):
'''Tk variable for 3f setting items'''
def __init__(self, i, *args, **kwargs):
self.i = i
super(ListVarItem, self).__init__(*args, **kwargs)
def trace_w(self, *args):
if self.skip_w > 0:
self.skip_w -= 1
return
v = list(self.s.get_setting_tuple(self.index)[1])
try:
v[self.i] = float(self.get())
except ValueError:
return
self.s.set(self.index, v)
def update(self):
raise NotImplementedError
class ColorVar(PymolVar):
'''Numeric color variable'''
def set(self, v):
if isinstance(v, str) and v.strip():
v = cmd.get_color_index(v)
super(ColorVar, self).set(v)
class Setting:
'''Proxy to global or object level PyMOL settings'''
def __init__(self,app, sele='', state=0):
self.cmd = app.pymol.cmd
self.pymol = app.pymol
self.sele = sele
self.state = state
while not self.cmd.ready(): # make sure PyMOL is ready for action...
time.sleep(0.1)
self.active_dict = {}
def set(self, name, value):
self.cmd.set(name, value, self.sele, self.state, log=1, quiet=0)
def get(self, name):
return self.cmd.get(name, self.sele, self.state)
def get_setting_tuple(self, name):
r = self.cmd.get_setting_tuple(name, self.sele, self.state)
if r[0] == 0:
r = self.cmd.get_setting_tuple(name)
return r
def __getattr__(self, name):
index = self.pymol.setting.index_dict[name]
v_type, v_list = self.get_setting_tuple(name)
if v_type < 4: # bool, int, float
var = PymolVar(self, index, v_list[0])
elif v_type == 4: # 3f vector
var = PymolVar(self, index, self.get(name))
elif v_type == 5: # color
var = ColorVar(self, index, v_list[0])
else: # text
var = PymolVar(self, index, v_list[0])
setattr(self, name, var)
self.active_dict[index] = var.update
return var
def refresh(self): # get any settings changes from PyMOL and update menus
for a in self.cmd.get_setting_updates(self.sele, self.state) or ():
try:
self.active_dict[a]()
except KeyError:
pass