def body(self, guiParent): # Ensure that the first row and column in popup expand guiParent.grid_rowconfigure(1, weight=1) guiParent.grid_columnconfigure(0, weight=1, minsize=200) frame = Frame(guiParent) # Body widgets can be put in this frame frame.grid(row=1, column=0, sticky='nsew') frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1, minsize=200) self.dangleFrame = DangleFrame(frame, self, project=self.project) self.dangleFrame.grid(row=0, column=0, sticky='nsew') # Dictionary to store popups opened by this application - e.g. need to close upon quit self.popups = {} # Default font self.font = 'Helvetica 10' # Closing the window from the desktop environment calls the proper quit self.protocol('WM_DELETE_WINDOW', self.quit) self.mainMenu = Menu(self) self.projectMenu = self.makeProjectMenu() self.viewMenu = self.viewFileMenu() self.otherMenu = self.makeAppearanceMenu() # Put the main menu self.config(menu=self.mainMenu) self.initProject()
class Separator(Frame): refresh = 0 def __init__(self, parent, orient = Tkinter.HORIZONTAL, relief='solid', color='black', bgColor = 'grey', *args, **kw): if (orient == Tkinter.HORIZONTAL): size = kw.get('height', 1) else: size = kw.get('width', 1) if relief =='solid': kw['relief'] = 'flat' else: kw['relief'] = relief kw['borderwidth'] = (size-1)/2 apply(Frame.__init__, (self, parent) + args, kw) self.config(bg=color) self.relief = relief if self.relief in ('solid','flat'): color2 = bgColor else: color2 = color self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.innerFrame = Frame(self, borderwidth=0, bg=color2) self.innerFrame.grid(sticky = Tkinter.NSEW) self.innerFrame.grid_columnconfigure(0, weight=1) self.innerFrame.grid_rowconfigure(0, weight=1) # color is a tuple def setColor(self, color, bgColor='grey'): if type(color) is type(()) : (r,g,b) = color color = hexRepr(r,g,b) if type(bgColor) is type(()) : (r,g,b) = bgColor bgColor = hexRepr(r,g,b) self.config(bg = color) if self.relief in ('solid','flat'): self.innerFrame.config(bg = bgColor) else: self.innerFrame.config(bg = color)
def body(self, guiFrame): guiFrame.grid_columnconfigure(0, weight=1) row = 0 frame = Frame(guiFrame, grid=(row, 0), sticky='ew') frame.grid_columnconfigure(6, weight=1) label = Label(frame, text='MolSystem:', grid=(0, 0)) tipText = 'Selects which molecular system to select a structure for' self.molSystemPulldown = PulldownList(frame, callback=self.setMolSystem, grid=(0, 1), tipText=tipText) label = Label(frame, text=' Ensemble:', grid=(0, 2)) tipText = 'Selects which structure ensemble to display, for the specified molecular system' self.structurePulldown = PulldownList(frame, callback=self.setStructure, grid=(0, 3), tipText=tipText) label = Label(frame, text=' Model:', grid=(0, 4)) tipText = 'Selects which conformational model of the selected structure/ensemble to display' self.modelPulldown = PulldownList(frame, callback=self.setModel, grid=(0, 5), tipText=tipText) label = Label(frame, text='Peak List:', grid=(0, 7), sticky='e') tipText = 'When using the "Show Peak" option, sets which peak list is used to display atom connectivities' self.peakListPulldown = PulldownList(frame, callback=self.setPeakList, grid=(0, 8), sticky='e', tipText=tipText) label = Label(frame, text=' Dist Method:', grid=(0, 9), sticky='e') tipText = 'Where the distances between sets of atoms are displayed, sets whether to use the NOE equivalent (sum r^-6 intensities) or minimum distance' self.distMethodPulldown = PulldownList(frame, callback=self.setDistMethod, texts=distanceMethods.keys(), grid=(0, 10), sticky='e', tipText=tipText) row += 1 guiFrame.grid_rowconfigure(row, weight=1) analysisProject = self.analysisProject getOption = lambda key, defaultValue: getPrintOption( analysisProject, key, defaultValue) setOption = lambda key, value: setPrintOption(analysisProject, key, value) self.structFrame = ViewStructureFrame(guiFrame, project=self.project, radiiScale=0.0, bondWidth=1, atomCallback=self.selectAtom, getPrintOption=getOption, setPrintOption=setOption, grid=(row, 0)) row += 1 frame = Frame(guiFrame) frame.grid(row=row, column=0, sticky='ew') frame.grid_columnconfigure(2, weight=1) tipTexts = [ 'Remove all highlights and connections from the structure display', 'For an ensemble, calculate the per-atom coordinate root mean square deviations and adjust atom size and colours accordingly', 'Display the selected structural parameters on the structure, adjusting atom labels, size and colours accordingly' ] texts = [ 'Reset', 'RMSDs', 'Display Params:', ] commands = [ self.clearConnections, self.displayAtomRmsds, self.displayStrucParams, ] self.paramButtons = ButtonList(frame, texts=texts, commands=commands, grid=(0, 0), tipTexts=tipTexts) tipText = 'Selects which structural parameters, from those calculated, to display on the structure' self.strucParamPulldown = PulldownList(frame, grid=(0, 1), tipText=tipText) tipTexts = [ 'In the stated peak list, display peak assignment connectivities between the highlighted atoms (left click to select atoms in the display)', ] texts = ['Show Peaks'] commands = [ self.showPeaks, ] self.bottomButtons = UtilityButtonList(frame, texts=texts, commands=commands, helpUrl=self.help_url, grid=(0, 3), tipTexts=tipTexts) self.updateMolSystems() self.updatePeakLists() self.administerNotifiers(self.registerNotify)
class ViewRamachandranPopup(BasePopup): """ **Display Protein Backbone Phi & Psi Angles** This graphical display allow the user to display phi and psi protein backbone dihedral angles on a Ramachandran plot that indicates the likelihood (database abundance) of those angles. This can be used as a form of structure quality control to detect residues in a calculated three dimensional structure that are distorted away from regular protein-like conformations. Although a few atypical angles may truly occur in a given protein structure the presence of many unusual angles and abnormal distributions of angles over a structure ensemble with many models may indicate a poor quality structure. With this popup window the user selects a molecular system and then a structure ensemble that relates to that system. Th e user can choose to display dihedral angle information for all models (conformations) in the structure ensemble or just one model, by changing the "Model" pulldown menu. The user can control which residues are considered by selecting either a particular type of residue via "Ccp Code" or a specific residue in the sequence. Other options control how the phi & psi angle information is presented on screen. The "Labels" options control which angle spots on the Ramachandran chart have residue sequence number and type displayed; by default only the "disallowed" angles in unusual (white) regions of the plot are labelled. The "Spot Size" dictates how large the angle markers are and the "Colours" is a colour scheme to differentiate the different models from within the selected ensemble. The [Previous Residue] and [Next Residue] buttons allow the user to quickly scan though all of the residues in the structure, to check for unusual/disallowed backbone angles or unlikely distributions of within the ensemble. In the Ramachandran matrix plot the wite areas represent phi & psi angle combinations that are very unusual and thus usually indicative of a poor structure at that point. The grey and red areas represent the more common, and thus more expected, angle combinations. The more red the colour of a square the greater the likelihood of the phi & psi angles. It should be noted that when displaying angle points for only a single residue or residue type, the Ramachandran chart in the background is at residue-specific version, i.e. it shows angle likelihoods for only that one kind of residue. This is particularly important for Pro and Gly residues that have notably different distributions (and hence angle expectations) to other residues. """ def __init__(self, parent, *args, **kw): self.molSystem = None self.structure = None self.model = None self.waiting = False self.colorScheme = None self.ccpCode = None # Which Rama background to use self.residue = None self.labelMode = LABEL_MODES[1] BasePopup.__init__(self, parent=parent, title='Chart : Ramachandran Plot', **kw) def open(self): BasePopup.open(self) self.updateAfter() def body(self, guiFrame): self.geometry('700x700') self.update_idletasks() guiFrame.grid_columnconfigure(0, weight=1) row = 0 frame = Frame(guiFrame, relief='raised', bd=1, grid=(row,0), sticky='ew') frame.grid_columnconfigure(8, weight=1) label = Label(frame, text='MolSystem:', grid=(0,0)) tipText = 'Selects which molecular system to display data for; from which a structure is selected' self.molSystemPulldown = PulldownList(frame, callback=self.setMolSystem, grid=(0,1), tipText=tipText) label = Label(frame, text=' Structure:', grid=(0,2)) tipText = 'Selects which structure ensemble to display phi/psi backbone angle data for' self.structurePulldown = PulldownList(frame, callback=self.setStructure, grid=(0,3), tipText=tipText) label = Label(frame, text=' Model:', grid=(0,4)) tipText = 'Selects which conformational model(s), from the structure ensemble, to display data for' self.modelPulldown = PulldownList(frame, callback=self.setModel, grid=(0,5), tipText=tipText) label = Label(frame, text=' Labels:', grid=(0,6)) tipText = 'Sets which phi/psi points carry residue labels, e.g. according to whether values are "disallowed" (very uncommon)' self.labelPulldown = PulldownList(frame, texts=LABEL_MODES, index=1, callback=self.updateLabels, grid=(0,7), sticky='e', tipText=tipText) utilButtons = UtilityButtonList(frame, helpUrl=self.help_url, grid=(0,9)) label = Label(frame, text='Ccp Code:', grid=(1,0)) tipText = 'Allows the phi/psi points to be restricted to only those from a particular residue type' self.ccpCodePulldown = PulldownList(frame, callback=self.setCcpCode, grid=(1,1), tipText=tipText) label = Label(frame, text=' Residue:', grid=(1,2)) tipText = 'Allows the display of phi/psi points from only a single residue' self.residuePulldown = PulldownList(frame, callback=self.setResidue, grid=(1,3), tipText=tipText) label = Label(frame, text=' Spot Size:', grid=(1,4)) sizes = [1,2,3,4,5,6,7,8,9,10] texts = [str(s) for s in sizes] tipText = 'Sets how large to display the circles that indicate the phi/psi points' self.spotSizePulldown = PulldownList(frame, texts=texts, objects=sizes, callback=self.updateAfter, index=1, grid=(1,5), tipText=tipText) label = Label(frame, text=' Colours:', grid=(1,6)) tipText = 'Selects which colour scheme to use to distinguish phi/psi points from different conformational models' self.schemePulldown = PulldownList(frame, callback=self.selectColorScheme, grid=(1,7), tipText=tipText) row +=1 tipText = 'The percentage of residues found in the different regions of the Ramachandran plot, according to PROCHECK cetegories' self.regionLabel = Label(guiFrame, text=REGION_TEXT % (0.0,0.0,0.0), grid=(row, 0), tipText=tipText) row +=1 self.colorRow = row self.colorFrame = Frame(guiFrame, sticky='ew') self.colorFrame.grid_columnconfigure(0, weight=1) self.colorLabels = [] tipText = 'The colors of the ensembles in the plot' label = Label(self.colorFrame, text='Colors: ', grid=(0,0), sticky='w', tipText=tipText) row +=1 guiFrame.grid_rowconfigure(row, weight=1) self.plot = ViewRamachandranFrame(guiFrame, relief='sunken', bgColor=self.cget('bg')) self.plot.grid(row=row, column=0, sticky='nsew') row +=1 tipTexts = ['Show phi/spi spots for the previous residue in the sequence; when there is no current residue, starts fron the first in sequence there is data for', 'Show phi/spi spots for the next residue in the sequence; when there is no current residue, starts fron the first in sequence there is data for'] texts = ['Previous Residue','Next Residue'] commands = [self.prevResidue,self.nextResidue] self.bottomButtons = ButtonList(guiFrame, commands=commands, texts=texts, grid=(row,0), tipTexts=tipTexts) self.updateColorSchemes() self.updateMolSystems() self.updateAfter() self.administerNotifiers(self.registerNotify) def administerNotifiers(self, notifyFunc): for func in ('__init__', 'delete',): notifyFunc(self.updateStructuresAfter, 'ccp.molecule.MolStructure.StructureEnsemble', func) for func in ('__init__', 'delete','setColors'): notifyFunc(self.updateColorSchemes, 'ccpnmr.AnalysisProfile.ColorScheme', func) def stepResidue(self, step=1): structure = self.structure if structure: if structure == 'All': structure = self.getStructures()[0] if not self.residue: chain = structure.sortedCoordChains()[0] residue = chain.sortedResidues()[1] else: residue = self.residue chain = self.residue.chain residues = chain.sortedResidues()[1:] index = residues.index(residue) index = (index+step) % len(residues) residue = residues[index] self.residue = residue self.updateResidues() self.updateAfter() def prevResidue(self): self.stepResidue(-1) def nextResidue(self): self.stepResidue(1) def setResidue(self,residue): if residue is not self.residue: if residue: self.ccpCode = None self.ccpCodePulldown.setIndex(0) self.residue = residue self.updateAfter() def setCcpCode(self, ccpCode): if ccpCode != self.ccpCode: if ccpCode: self.residue = None self.residuePulldown.setIndex(0) self.ccpCode = ccpCode self.updateAfter() def updateLabels(self, selection): if selection is not self.labelMode: self.labelMode = selection self.updateAfter() def updateStructuresAfter(self, structure): if structure.molSystem is self.molSystem: self.updateStructures() def selectColorScheme(self, scheme): if scheme is not self.colorScheme: self.colorScheme = scheme if self.structure: self.updateAfter() def updateColorSchemes(self, scheme=None): schemes = getHueSortedColorSchemes(self.analysisProfile) names = [s.name for s in schemes] colors = [list(s.colors) for s in schemes] index = 0 scheme = self.colorScheme if schemes: if scheme not in schemes: scheme = self.analysisProfile.findFirstColorScheme(name=DEFAULT_SCHEME) if not scheme: scheme = schemes[0] index = schemes.index(scheme) else: scheme = None if scheme is not self.colorScheme: self.colorScheme = scheme if self.structure: self.updateAfter() self.schemePulldown.setup(names, schemes, index, colors=colors) def updateResidues(self): resNames = ['<All>',] ccpNames = ['<All>',] ccpCodes = [None,] residues = [None,] resCats = [None,] indexR = 0 indexC = 0 structure = self.structure if structure: if structure == 'All': structure = self.getStructures()[0] models = structure.sortedModels() models.append(None) ccpCodes0 = set() for chain in structure.sortedCoordChains(): chainCode = chain.code for residue in chain.sortedResidues()[1:]: sysResidue = residue.residue seqCode = residue.seqCode ccpCode = sysResidue.ccpCode ccpCodes0.add(ccpCode) resName = '%d %s' % (seqCode, ccpCode) n = 10*int(seqCode/10) resCat = '%s %d-%d' % (chainCode,n,n+10) resNames.append(resName) residues.append(residue) resCats.append(resCat) ccpCodes0 = list(ccpCodes0) ccpCodes0.sort() ccpCodes += ccpCodes0 ccpNames += ccpCodes0 doUpdate = False if self.residue not in residues: if self.residue and len(residues) > 1: chain = residues[1].chain self.residue = chain.findFirstResidue(residue=self.residue.residue) else: self.residue = None doUpdate = True indexR = residues.index(self.residue) if self.ccpCode not in ccpCodes: self.ccpCode = None doUpdate = True indexC = ccpCodes.index(self.ccpCode) self.residuePulldown.setup(resNames, residues, indexR, categories=resCats) self.ccpCodePulldown.setup(ccpNames, ccpCodes, indexC) if doUpdate: self.updateAfter() def updateModels(self, model=None): structure = self.structure # looks like model is always None # possibly need to worry about below otherwise if structure = 'All' if model and (model.structureEnsemble is not structure): return self.updateResidues() models = [] names = [] index = 0 model = self.model if structure: if structure != 'All': models = self.structure.sortedModels() models.append(None) if models: if model not in models: model = models[0] names = ['%d' % m.serial for m in models[:-1]] names.append('<All>') index = models.index(model) else: model = None self.modelPulldown.setup(names, models, index) if self.model is not model: self.model = model self.updateAfter() def setModel(self, model): if model is not self.model: self.model = model self.updateAfter() def setStructure(self, structure): if structure is not self.structure: self.structure = structure self.model = None self.updateModels() self.updateAfter() def getStructures(self, molSystem=None): molSystem = molSystem or self.molSystem structures = [] if molSystem: for structure in molSystem.sortedStructureEnsembles(): for chain in structure.coordChains: for residue in chain.residues: if residue.residue.molResidue.molType == 'protein': structures.append(structure) break else: continue break return structures def updateStructures(self, structure=None): if structure and (structure.molSystem is not self.molSystem): return names = [] index = 0 structures = self.getStructures() if structures: names = [str(x.ensembleId) for x in structures] names.append('<All>') structures.append('All') if self.structure in structures: structure = self.structure else: structure = structures[0] index = structures.index(structure) else: structure = None self.structurePulldown.setup(names, structures, index) if structure is not self.structure: self.structure = structure self.model = None self.updateModels() def setMolSystem(self, molSystem): if molSystem is not self.molSystem: self.molSystem = molSystem self.structure = None self.model = None self.updateStructures() def getMolSystems(self): molSystems = [] if self.project: for molSystem in self.project.sortedMolSystems(): if self.getStructures(molSystem): molSystems.append(molSystem) return molSystems def updateMolSystems(self, *object): names = [] index = 0 molSystems = self.getMolSystems() if molSystems: if self.molSystem in molSystems: molSystem = self.molSystem else: molSystem = molSystems[0] names = [x.code for x in molSystems] index = molSystems.index(molSystem) else: molSystem = None self.molSystemPulldown.setup(names, molSystems, index) if molSystem is not self.molSystem: self.molSystem = molSystem self.structure = None self.model = None self.updateStructures() def updateAfter(self, object=None): if self.waiting: return self.waiting = True self.after_idle(self.update) def destroy(self): self.administerNotifiers(self.unregisterNotify) BasePopup.destroy(self) def update(self): self.plot.setAminoAcid(self.ccpCode) self.updatePhiPsi() self.waiting = False def updatePhiPsi(self): # labels='outliers', '' if not self.structure: return model = self.model ccpCode = self.ccpCode residueSel = self.residue labelMode = self.labelMode getValue = self.plot.getIntensityValue ccpCode = self.ccpCode if self.residue: ccpCode = self.residue.residue.ccpCode self.plot.setAminoAcid(ccpCode) phiPsiAccept = [] plotObjects = [] resLabels = [] colors = [] if self.colorScheme: scheme = list(self.colorScheme.colors) else: scheme = ['#800000','#008000','#000080'] nCols = len(scheme) nCore = 0 nAllowed = 0 nDisallowed = 0 colorFrame = self.colorFrame colorLabels = self.colorLabels structure = self.structure if structure == 'All': structures = self.getStructures() nstructures = len(structures) ncolorLabels = len(colorLabels) n = nstructures - ncolorLabels if n > 0: for i in range(n): label = Label(colorFrame, grid=(0,i+ncolorLabels+1)) colorLabels.append(label) for i, structure0 in enumerate(structures): text = 'Structure %d' % structure0.ensembleId label = colorLabels[i] label.set(text) color = scheme[i % nCols] label.config(bg=color) if color == '#000000': label.config(fg='#FFFFFF') else: label.config(fg='#000000') colorFrame.grid(row=self.colorRow, column=0) else: structures = [structure] colorFrame.grid_forget() for structure0 in structures: if model: models = [model,] else: models = list(structure0.models) nModels = len(models) for chain in structure0.coordChains: for residue in chain.residues: sysResidue = residue.residue sysCode = getResidueCode(sysResidue) resLabel = '%d%s' % (sysResidue.seqCode,sysCode) if sysResidue.molResidue.molType != 'protein': continue if residue and residueSel and (residue.residue is not residueSel.residue): continue if ccpCode and (sysCode != ccpCode): continue for model0 in models: phi, psi = getResiduePhiPsi(residue, model=model0) if None in (phi,psi): continue value = getValue(phi,psi) if nModels == 1: resLabels.append(resLabel) else: resLabels.append( '%s:%d' % (resLabel, model0.serial) ) doLabel = False if value < 6.564e-5: if labelMode == LABEL_MODES[1]: doLabel = True nDisallowed += 1 elif value < 0.000821: nAllowed += 1 else: nCore += 1 if labelMode == LABEL_MODES[0]: doLabel = False elif labelMode == LABEL_MODES[2]: doLabel = True if structure == 'All': ind = structures.index(structure0) else: ind = model0.serial - 1 colors.append(scheme[ind % nCols]) plotObjects.append((residue, model0)) phiPsiAccept.append((phi,psi,doLabel)) spotSize = self.spotSizePulldown.getObject() nRes = 0.01*float(nDisallowed+nAllowed+nCore) if nRes: self.regionLabel.set(REGION_TEXT % (nCore/nRes,nAllowed/nRes,nDisallowed/nRes)) else: self.regionLabel.set(REGION_TEXT % (0.0, 0.0, 0.0)) self.plot.cirRadius = spotSize self.plot.updateObjects(phiPsiAccept, plotObjects, resLabels, colors)
def body(self, guiFrame): self.geometry('700x700') self.update_idletasks() guiFrame.grid_columnconfigure(0, weight=1) row = 0 frame = Frame(guiFrame, relief='raised', bd=1, grid=(row,0), sticky='ew') frame.grid_columnconfigure(8, weight=1) label = Label(frame, text='MolSystem:', grid=(0,0)) tipText = 'Selects which molecular system to display data for; from which a structure is selected' self.molSystemPulldown = PulldownList(frame, callback=self.setMolSystem, grid=(0,1), tipText=tipText) label = Label(frame, text=' Structure:', grid=(0,2)) tipText = 'Selects which structure ensemble to display phi/psi backbone angle data for' self.structurePulldown = PulldownList(frame, callback=self.setStructure, grid=(0,3), tipText=tipText) label = Label(frame, text=' Model:', grid=(0,4)) tipText = 'Selects which conformational model(s), from the structure ensemble, to display data for' self.modelPulldown = PulldownList(frame, callback=self.setModel, grid=(0,5), tipText=tipText) label = Label(frame, text=' Labels:', grid=(0,6)) tipText = 'Sets which phi/psi points carry residue labels, e.g. according to whether values are "disallowed" (very uncommon)' self.labelPulldown = PulldownList(frame, texts=LABEL_MODES, index=1, callback=self.updateLabels, grid=(0,7), sticky='e', tipText=tipText) utilButtons = UtilityButtonList(frame, helpUrl=self.help_url, grid=(0,9)) label = Label(frame, text='Ccp Code:', grid=(1,0)) tipText = 'Allows the phi/psi points to be restricted to only those from a particular residue type' self.ccpCodePulldown = PulldownList(frame, callback=self.setCcpCode, grid=(1,1), tipText=tipText) label = Label(frame, text=' Residue:', grid=(1,2)) tipText = 'Allows the display of phi/psi points from only a single residue' self.residuePulldown = PulldownList(frame, callback=self.setResidue, grid=(1,3), tipText=tipText) label = Label(frame, text=' Spot Size:', grid=(1,4)) sizes = [1,2,3,4,5,6,7,8,9,10] texts = [str(s) for s in sizes] tipText = 'Sets how large to display the circles that indicate the phi/psi points' self.spotSizePulldown = PulldownList(frame, texts=texts, objects=sizes, callback=self.updateAfter, index=1, grid=(1,5), tipText=tipText) label = Label(frame, text=' Colours:', grid=(1,6)) tipText = 'Selects which colour scheme to use to distinguish phi/psi points from different conformational models' self.schemePulldown = PulldownList(frame, callback=self.selectColorScheme, grid=(1,7), tipText=tipText) row +=1 tipText = 'The percentage of residues found in the different regions of the Ramachandran plot, according to PROCHECK cetegories' self.regionLabel = Label(guiFrame, text=REGION_TEXT % (0.0,0.0,0.0), grid=(row, 0), tipText=tipText) row +=1 self.colorRow = row self.colorFrame = Frame(guiFrame, sticky='ew') self.colorFrame.grid_columnconfigure(0, weight=1) self.colorLabels = [] tipText = 'The colors of the ensembles in the plot' label = Label(self.colorFrame, text='Colors: ', grid=(0,0), sticky='w', tipText=tipText) row +=1 guiFrame.grid_rowconfigure(row, weight=1) self.plot = ViewRamachandranFrame(guiFrame, relief='sunken', bgColor=self.cget('bg')) self.plot.grid(row=row, column=0, sticky='nsew') row +=1 tipTexts = ['Show phi/spi spots for the previous residue in the sequence; when there is no current residue, starts fron the first in sequence there is data for', 'Show phi/spi spots for the next residue in the sequence; when there is no current residue, starts fron the first in sequence there is data for'] texts = ['Previous Residue','Next Residue'] commands = [self.prevResidue,self.nextResidue] self.bottomButtons = ButtonList(guiFrame, commands=commands, texts=texts, grid=(row,0), tipTexts=tipTexts) self.updateColorSchemes() self.updateMolSystems() self.updateAfter() self.administerNotifiers(self.registerNotify)
def createLink(self, role, clazz): title_label = Label(self.parent_frame) class_label = ToggleLabel(self.parent_frame, text=role.clazz.name, callback=self.gridWidgets, isArrowClosed=True) class_label.label.config(anchor=Tkinter.W) name_label = Label(self.parent_frame, text=role.name, anchor=Tkinter.W, bg=name_bg) value_label = Label(self.parent_frame) type_label = Label(self.parent_frame, text=clazz.name, anchor=Tkinter.W) card_label = Label(self.parent_frame, text=self.getCardinality(role), anchor=Tkinter.W) note_label = Label(self.parent_frame, text=self.getNote(role), anchor=Tkinter.W) link_frame = Frame(self.parent_frame) link_frame.grid_rowconfigure(0, weight=1) link_frame.grid_columnconfigure(table_col, weight=1) # table must be created first table = ObjectTable(link_frame, clazz, initialRows=3) texts = ['Goto'] commands = [lambda: self.gotoObject(table, clazz)] if (role.hierarchy == child_hierarchy): texts.extend(['Create', 'Delete']) commands.extend([ lambda: self.createChild(clazz), lambda: self.deleteChild(table) ]) elif (not role.isDerived and (not self.editMode or (role.changeability == changeable and (role.locard != role.hicard)))): if (role.hicard == 1): texts.extend(['Set', 'Unset']) commands.extend([ lambda: self.setLink(role, clazz), lambda: self.unsetLink(role) ]) else: texts.extend(['Add', 'Remove']) commands.extend([ lambda: self.addLink(role, clazz), lambda: self.removeLink(table, role) ]) buttons = ButtonList(link_frame, texts=texts, commands=commands, direction=Tkinter.VERTICAL) self.widget_dict[(role, clazz)] = (title_label, class_label, name_label, value_label, type_label, card_label, note_label, link_frame, buttons, table) table.callback = lambda obj, row, col: self.setButtonState( table, role, clazz, buttons)
def body(self, guiFrame): self.geometry('700x700') guiFrame.expandGrid(0,0) options = ['Peak Lists & Settings','Peak Intensity Comparison'] tabbedFrame = TabbedFrame(guiFrame, options=options, callback=self.changeTab) tabbedFrame.grid(row=0, column=0, sticky='nsew') self.tabbedFrame = tabbedFrame frameA, frameB = tabbedFrame.frames row = 0 frameA.grid_columnconfigure(1, weight=1) frameA.grid_columnconfigure(3, weight=1) frameA.grid_columnconfigure(5, weight=1) frameA.grid_rowconfigure(5, weight=1) tipText = 'Number of reference peaks (no saturation)' self.peaksALabel = Label(frameA, text='Number of Ref Peaks: ', tipText=tipText) self.peaksALabel.grid(row=1,column=0,columnspan=2,sticky='w') tipText = 'Number of NOE saturation peaks' self.peaksBLabel = Label(frameA, text='Number of Sat Peaks: ', tipText=tipText) self.peaksBLabel.grid(row=1,column=2,columnspan=2,sticky='w') tipText = 'Number of peaks in assigned list' self.peaksCLabel = Label(frameA, text='Number of Assign Peaks: ', tipText=tipText) self.peaksCLabel.grid(row=1,column=4,columnspan=2,sticky='w') tipText = 'Selects which peak list is considered the NOE intensity reference (no saturation)' specALabel = Label(frameA, text='Ref Peak List: ') specALabel.grid(row=0,column=0,sticky='w') self.specAPulldown = PulldownList(frameA, callback=self.setRefPeakList, tipText=tipText) self.specAPulldown.grid(row=0,column=1,sticky='w') tipText = 'Selects which peak list is considered as NOE saturated.' specBLabel = Label(frameA, text='Sat Peak List: ') specBLabel.grid(row=0,column=2,sticky='w') self.specBPulldown = PulldownList(frameA, callback=self.setSatPeakList, tipText=tipText) self.specBPulldown.grid(row=0,column=3,sticky='w') tipText = 'Selects a peak list with assignments to use as a positional reference' specCLabel = Label(frameA, text='Assignment Peak List: ') specCLabel.grid(row=0,column=4,sticky='w') self.specCPulldown = PulldownList(frameA, callback=self.setAssignPeakList, tipText=tipText) self.specCPulldown.grid(row=0,column=5,sticky='w') frame0a = Frame(frameA) frame0a.grid(row=2,column=0,columnspan=6,sticky='nsew') frame0a.grid_columnconfigure(9, weight=1) tipText = '1H ppm tolerance for matching assigned peaks to reference & NOE saturation peaks' tolHLabel = Label(frame0a, text='Tolerances: 1H') tolHLabel.grid(row=0,column=0,sticky='w') self.tolHEntry = FloatEntry(frame0a,text='0.02', width=6, tipText=tipText) self.tolHEntry .grid(row=0,column=1,sticky='w') tipText = '15N ppm tolerance for matching assigned peaks to reference & NOE saturation peaks' tolNLabel = Label(frame0a, text=' 15N') tolNLabel .grid(row=0,column=2,sticky='w') self.tolNEntry = FloatEntry(frame0a,text='0.1', width=6, tipText=tipText) self.tolNEntry .grid(row=0,column=3,sticky='w') tipText = 'Whether to peak new peaks in reference & NOE saturated lists (at assignment locations)' label = Label(frame0a, text=' Pick new peaks?', grid=(0,4)) self.pickPeaksSelect = CheckButton(frame0a, tipText=tipText, grid=(0,5), selected=True) tipText = 'Whether to assign peaks in the peaks in the reference & NOE saturation lists, if not already assigned' label = Label(frame0a, text=' Assign peaks?') label.grid(row=0,column=6,sticky='w') self.assignSelect = CheckButton(frame0a, tipText=tipText) self.assignSelect.set(1) self.assignSelect.grid(row=0,column=7,sticky='w') tipText = 'Whether to consider peak height or volume in the heteronuclear NOE calculation' intensLabel = Label(frame0a, text=' Intensity Type:') intensLabel .grid(row=0,column=8,sticky='w') self.intensPulldown = PulldownList(frame0a, texts=['height','volume'], callback=self.setIntensityType, tipText=tipText) self.intensPulldown.grid(row=0,column=9,sticky='w') divider = LabelDivider(frameA, text='Peaks', grid=(3,0), gridSpan=(1,6)) tipTexts = ['Show the selected intensity reference peaks in the below table', 'Show the selected NOE saturation peaks in the below table', 'Show the selected assigned peak list in the below table', 'Show the displayed peaks in a separate peak table, where assignments etc. may be adjusted'] texts = ['Show Ref Peaks','Show Sat Peaks', 'Show Assign Peaks', 'Separate Peak Table'] commands = [self.viewRefPeakList, self.viewSatPeakList, self.viewAssignPeakList, self.viewSeparatePeakTable] self.viewPeaksButtons = ButtonList(frameA, expands=True, tipTexts=tipTexts, texts=texts, commands=commands) self.viewPeaksButtons.grid(row=4,column=0,columnspan=6,sticky='nsew') self.peakTable = PeakTableFrame(frameA, self.guiParent, grid=(5,0), gridSpan=(1,6)) self.peakTable.bottomButtons1.grid_forget() self.peakTable.bottomButtons2.grid_forget() #self.peakTable.topFrame.grid_forget() self.peakTable.topFrame.grid(row=2, column=0, sticky='ew') # Next tab frameB.expandGrid(0,0) tipTexts = ['Row number', 'Assignment annotation for NOE saturation peak', 'Assignment annotation for reference peak (no saturation)', '1H chemical shift of NOE saturation peak', '1H chemical shift of reference peak', '15N chemical shift of NOE saturation peak', '15N chemical shift of reference peak', 'The separation between compared peaks: square root of the sum of ppm differences squared', 'The intensity if the NOE saturation peak', 'The intensity of the reference peak (no saturation)', 'Ratio of peak intensities: saturated over reference', 'Residue(s) for reference peak'] colHeadings = ['#','Sat Peak','Ref Peak','1H shift A', '1H shift B','15N shift A','15N shift B', 'Closeness\nScore','Intensity A','Intensity B', 'Intensity\nRatio','Residue'] self.scrolledMatrix = ScrolledMatrix(frameB, multiSelect=True, headingList=colHeadings, callback=self.selectCell, tipTexts=tipTexts, grid=(0,0), deleteFunc=self.removePair) tipTexts = ['Force a manual update of the table; pair-up NOE saturation and reference peaks according to assigned peak positions', 'Remove the selected rows of peak pairs', 'Show peaks corresponding to the selected row in a table', 'Save the Heteronuclear NOE values in the CCPN project as a data list'] texts = ['Refresh Table','Remove Pairs', 'Show Peak Pair','Create Hetero NOE List'] commands = [self.matchPeaks,self.removePair, self.showPeakPair,self.makeNoeList] self.pairButtons = ButtonList(frameB, tipTexts=tipTexts, grid=(1,0), texts=texts, commands=commands) bottomButtons = UtilityButtonList(tabbedFrame.sideFrame, helpUrl=self.help_url) bottomButtons.grid(row=0, column=0, sticky='e') self.updatePulldowns() self.updateAfter() self.administerNotifiers(self.registerNotify)
class PopupTemplate(BasePopup): def __init__(self, parent, project=None, *args, **kw): self.project = project self.parent = parent self.objects = self.getObjects() self.object = None BasePopup.__init__(self, parent=parent, title='Popup Template', **kw) self.updateObjects() def body(self, mainFrame): mainFrame.grid_columnconfigure(1, weight=1, minsize=100) mainFrame.config(borderwidth=5, relief='solid') row = 0 label = Label(mainFrame, text="Frame (with sub-widgets):") label.grid(row=row, column=0, sticky=Tkinter.E) frame = Frame(mainFrame, relief='raised', border=2, background='#8080D0') # Frame expands East-West frame.grid(row=row, column=1, sticky=Tkinter.EW) # Last column expands => Widgets pusted to the West frame.grid_columnconfigure(3, weight=1) # Label is within the sub frame label = Label(frame, text='label ') label.grid(row=0, column=0, sticky=Tkinter.W) entry = Entry(frame, text='Entry', returnCallback=self.showWarning) entry.grid(row=0, column=1, sticky=Tkinter.W) self.check = CheckButton(frame, text='Checkbutton', selected=True, callback=self.updateObjects) self.check.grid(row=0, column=2, sticky=Tkinter.W) # stick a button to the East wall button = Button(frame, text='Button', command=self.pressButton) button.grid(row=0, column=3, sticky=Tkinter.E) row += 1 label = Label(mainFrame, text="Text:") label.grid(row=row, column=0, sticky=Tkinter.E) self.textWindow = Text(mainFrame, text='Initial Text\n', width=60, height=5) self.textWindow.grid(row=row, column=1, sticky=Tkinter.NSEW) row += 1 label = Label(mainFrame, text="CheckButtons:") label.grid(row=row, column=0, sticky=Tkinter.E) entries = ['Alpha','Beta','Gamma','Delta'] selected = entries[2:] self.checkButtons = CheckButtons(mainFrame, entries, selected=selected,select_callback=self.changedCheckButtons) self.checkButtons.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="PartitionedSelector:") label.grid(row=row, column=0, sticky=Tkinter.E) labels = ['Bool','Int','Float','String'] objects = [type(0),type(1),type(1.0),type('a')] selected = [type('a')] self.partitionedSelector= PartitionedSelector(mainFrame, labels=labels, objects=objects, colors = ['red','yellow','green','#000080'], callback=self.toggleSelector,selected=selected) self.partitionedSelector.grid(row=row, column=1, sticky=Tkinter.EW) row += 1 label = Label(mainFrame, text="PulldownMenu") label.grid(row=row, column=0, sticky=Tkinter.E) entries = ['Frodo','Pipin','Merry','Sam','Bill','Gandalf','Strider','Gimli','Legolas'] self.pulldownMenu = PulldownMenu(mainFrame, callback=self.selectPulldown, entries=entries, selected_index=2, do_initial_callback=False) self.pulldownMenu.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="RadioButtons in a\nScrolledFrame.frame:") label.grid(row=row, column=0, sticky=Tkinter.EW) frame = ScrolledFrame(mainFrame, yscroll = False, doExtraConfig = True, width=100) frame.grid(row=row, column=1, sticky=Tkinter.EW) frame.grid_columnconfigure(0, weight=1) self.radioButtons = RadioButtons(frame.frame, entries=entries, select_callback=self.checkRadioButtons, selected_index=1, relief='groove') self.radioButtons.grid(row=0, column=0, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="LabelFrame with\nToggleLabels inside:") label.grid(row=row, column=0, sticky=Tkinter.E) labelFrame = LabelFrame(mainFrame, text='Frame Title') labelFrame.grid(row=row, column=1, sticky=Tkinter.NSEW) labelFrame.grid_rowconfigure(0, weight=1) labelFrame.grid_columnconfigure(3, weight=1) self.toggleLabel1 = ToggleLabel(labelFrame, text='ScrolledMatrix', callback=self.toggleFrame1) self.toggleLabel1.grid(row=0, column=0, sticky=Tkinter.W) self.toggleLabel1.arrowOn() self.toggleLabel2 = ToggleLabel(labelFrame, text='ScrolledGraph', callback=self.toggleFrame2) self.toggleLabel2.grid(row=0, column=1, sticky=Tkinter.W) self.toggleLabel3 = ToggleLabel(labelFrame, text='ScrolledCanvas', callback=self.toggleFrame3) self.toggleLabel3.grid(row=0, column=2, sticky=Tkinter.W) row += 1 mainFrame.grid_rowconfigure(row, weight=1) label = Label(mainFrame, text="changing/shrinking frames:") label.grid(row=row, column=0, sticky=Tkinter.E) self.toggleRow = row self.toggleFrame = Frame(mainFrame) self.toggleFrame.grid(row=row, column=1, sticky=Tkinter.NSEW) self.toggleFrame.grid_rowconfigure(0, weight=1) self.toggleFrame.grid_columnconfigure(0, weight=1) # option 1 self.intEntry = IntEntry(self, returnCallback = self.setNumber, width=8) self.multiWidget = MultiWidget(self, Entry, options=None, values=None, callback=self.setKeywords, minRows=3, maxRows=5) editWidgets = [None, None, self.intEntry, self.multiWidget] editGetCallbacks = [None, None, self.getNumber, self.getKeywords] editSetCallbacks = [None, None, self.setNumber, self.setKeywords] headingList = ['Name','Color','Number','Keywords'] self.scrolledMatrix = ScrolledMatrix(self.toggleFrame, headingList=headingList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, callback=self.selectObject, multiSelect=False) self.scrolledMatrix.grid(row=0, column=0, sticky=Tkinter.NSEW) # option 2 self.scrolledGraph = ScrolledGraph(self.toggleFrame, width=400, height=300, symbolSize=5, symbols=['square','circle'], dataColors=['#000080','#800000'], lineWidths=[0,1] ) self.scrolledGraph.setZoom(1.3) dataSet1 = [[0,0],[1,1],[2,4],[3,9],[4,16],[5,25]] dataSet2 = [[0,0],[1,3],[2,6],[3,9],[4,12],[5,15]] self.scrolledGraph.update(dataSets=[dataSet1,dataSet2], xLabel = 'X axis label', yLabel = 'Y axis label', title = 'Main Title') self.scrolledGraph.draw() # option 3 self.scrolledCanvas = ScrolledCanvas(self.toggleFrame,relief = 'groove', borderwidth = 2, resizeCallback=None) canvas = self.scrolledCanvas.canvas font = 'Helvetica 10' box = canvas.create_rectangle(10,10,150,200, outline='grey', fill='grey90') line = canvas.create_line(0,0,200,200,fill='#800000', width=2) text = canvas.create_text(120,50, text='Text', font=font, fill='black') circle = canvas.create_oval(30,30,50,50,outline='#008000',fill='#404040',width=3) row += 1 label = Label(mainFrame, text="FloatEntry:") label.grid(row=row, column=0, sticky=Tkinter.E) self.floatEntry = FloatEntry(mainFrame, text=3.14159265, returnCallback=self.floatEntryReturn) self.floatEntry.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="Scale:") label.grid(row=row, column=0, sticky=Tkinter.E) self.scale = Scale(mainFrame, from_=10, to=90, value=50, orient=Tkinter.HORIZONTAL) self.scale.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="Value Ramp:") label.grid(row=row, column=0, sticky=Tkinter.E) self.valueRamp = ValueRamp(mainFrame, self.valueRampCallback, speed = 1.5, delay = 50) self.valueRamp.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="ButtonList:") label.grid(row=row, column=0, sticky=Tkinter.E) texts = ['Select File','Close','Quit'] commands = [self.selectFile, self.close, self.quit] bottomButtons = ButtonList(mainFrame, texts=texts, commands=commands, expands=True) bottomButtons.grid(row=row, column=1, sticky=Tkinter.EW) self.protocol('WM_DELETE_WINDOW', self.quit) def floatEntryReturn(self, event): value = self.floatEntry.get() self.textWindow.setText('%s\n' % value) def selectObject(self, object, row, col): self.object = object def getKeywords(self, object): if object : values = object.keywords self.multiWidget.set(values) def setKeywords(self, event): values = self.multiWidget.get() self.object.keywords = values self.updateObjects() def getNumber(self, object): if object : self.intEntry.set(object.quantity) def setNumber(self, event): value = self.intEntry.get() self.object.quantity = value self.updateObjects() def toggleFrame1(self, isHidden): if isHidden: self.scrolledMatrix.grid_forget() self.toggleFrame.grid_forget() else: self.scrolledGraph.grid_forget() self.scrolledCanvas.grid_forget() self.scrolledMatrix.grid(row=0, column=0, sticky=Tkinter.NSEW) self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW) self.toggleLabel2.arrowOff() self.toggleLabel3.arrowOff() def toggleFrame2(self, isHidden): if isHidden: self.scrolledGraph.grid_forget() self.toggleFrame.grid_forget() else: self.scrolledMatrix.grid_forget() self.scrolledCanvas.grid_forget() self.scrolledGraph.grid(row=0, column=0, sticky=Tkinter.NSEW) self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW) self.toggleLabel1.arrowOff() self.toggleLabel3.arrowOff() def toggleFrame3(self, isHidden): if isHidden: self.scrolledCanvas.grid_forget() self.toggleFrame.grid_forget() else: self.scrolledMatrix.grid_forget() self.scrolledGraph.grid_forget() self.scrolledCanvas.grid(row=0, column=0, sticky=Tkinter.NSEW) self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW) self.toggleLabel1.arrowOff() self.toggleLabel2.arrowOff() def valueRampCallback(self, value): self.textWindow.setText('%s\n' % value) def checkRadioButtons(self, value): self.textWindow.setText('%s\n' % value) def selectPulldown(self, index, name): self.textWindow.setText('%d, %s\n' % (index, name)) def toggleSelector(self, value): self.textWindow.setText('%s\n' % value) def changedCheckButtons(self, values): self.textWindow.setText(','.join(values) + '\n') def getObjects(self): objects = [] objects.append( Fruit('Lemon', '#FFFF00',1,keywords=['Bitter','Tangy'] ) ) objects.append( Fruit('Orange', '#FF8000',4 ) ) objects.append( Fruit('Banana', '#FFF000',5 ) ) objects.append( Fruit('Pinapple','#FFD000',9 ) ) objects.append( Fruit('Kiwi', '#008000',12) ) objects.append( Fruit('Lime', '#00FF00',2 ) ) objects.append( Fruit('Apple', '#800000',5,keywords=['Crunchy'] ) ) objects.append( Fruit('Pear', '#408000',6 ) ) objects.append( Fruit('Peach', '#FFE0C0',2,keywords=['Sweet','Furry'] ) ) objects.append( Fruit('Plumb', '#800080',7 ) ) return objects def updateObjects(self, event=None): textMatrix = [] objectList = [] colorMatrix = [] for object in self.objects: datum = [] datum.append( object.name ) datum.append( None ) datum.append( object.quantity ) datum.append( ','.join(object.keywords) ) colors = [None, object.color, None, None] textMatrix.append(datum) objectList.append(object) colorMatrix.append(colors) if self.check.get(): self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList) else: self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList, colorMatrix=colorMatrix) def selectFile(self): fileSelectPopup = FileSelectPopup(self, title = 'Choose file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = fileSelectPopup.getFile() self.textWindow.setText('File Selected: %s\n' % fileName) def showWarning(self, eventObject): self.textWindow.setText('Text Entry Return Pressed\n') showWarning('Warning Title','Warning Message') return def pressButton(self): self.textWindow.setText('Button Pressed\n') if showYesNo('Title','Prompt: Clear text window?'): self.textWindow.clear() return def quit(self): BasePopup.destroy(self)
def body(self, guiFrame): self.geometry('600x600') guiFrame.expandGrid(0, 0) tipTexts = [ 'A table of all the NMR measurement lists in the project, including shift lists, T1 lists, J-coupling lists etc.', 'A table listing all of the individual measurements within an NMR measurement list' ] options = ['Measurement Lists', 'Measurements Table'] tabbedFrame = TabbedFrame(guiFrame, options=options, grid=(0, 0), tipTexts=tipTexts) self.tabbedFrame = tabbedFrame frameA, frameB = tabbedFrame.frames # Measurement Lists frameA.expandGrid(1, 0) self.detailsEntry = Entry(self, text='', returnCallback=self.setDetails, width=12) self.nameEntry = Entry(self, text='', returnCallback=self.setName, width=12) row = 0 frame0 = Frame(frameA, grid=(row, 0), gridSpan=(1, 2)) frame0.grid_columnconfigure(2, weight=1) label = Label(frame0, text='Experiment:', grid=(0, 0), sticky='e') tipText = 'Selects an experiment, if required, to restrict the measurement list table display; showing only lists which were derived using the experiment' self.experimentPulldown = PulldownList(frame0, callback=self.setExperiment, grid=(0, 1), tipText=tipText) row += 1 tipTexts = [ 'The serial number of measurement list', 'The type of measurement list, e.g. shift list, T1 list, J coupling list', 'A short identifying name for the list, for graphical displays', 'The number of measurements contained within the list', 'The unit of measurement used for the values in the list', 'The names of the experiments which were used to derive the measurements', 'A user-specified textual comment for the measurement list' ] justifyList = [ 'center', 'center', 'center', 'center', 'center', 'left' ] #colHeadings = ['List Type','Name','Size','Unit','Experiments','Other Info','Details'] colHeadings = [ '#', 'List Type', 'Name', 'Size', 'Unit', 'Experiments', 'Details' ] editWidgets = [ None, None, self.nameEntry, None, None, None, None, self.detailsEntry ] editGetCallbacks = [ None, None, self.getName, None, None, None, None, self.getDetails ] editSetCallbacks = [ None, None, self.setName, None, None, None, None, self.setDetails ] self.listsMatrix = ScrolledMatrix( frameA, grid=(row, 0), gridSpan=(1, 2), justifyList=justifyList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, headingList=colHeadings, callback=self.selectListCell, deleteFunc=self.deleteMeasurementList, tipTexts=tipTexts) row += 1 tipTexts = [ 'Show a table of the individual measurements within the selected measurement list', 'Make a new, blank chemical shift list within the project', 'Make a synthetic chemical shift list using random coil values, adjusting protein backbone values for sequence where approprate', 'Delete the selected measurement list' ] texts = [ 'Show Measurements', 'New Shift List', 'Make Random Coil Shift List', 'Delete' ] commands = [ self.showMeasurements, self.addShiftList, self.makeRandomCoilShiftList, self.deleteMeasurementList ] self.listButtons = ButtonList(frameA, texts=texts, commands=commands, grid=(row, 0), gridSpan=(1, 2), tipTexts=tipTexts) # Measurements self.measurementDetailsEntry = Entry( self, text='', returnCallback=self.setMeasurementDetails, width=12) self.measurementMeritEntry = FloatEntry( self, returnCallback=self.setMeasurementMerit, width=6) row = 0 frame0 = Frame(frameB, grid=(row, 0)) frame0.grid_columnconfigure(2, weight=1) label = Label(frame0, text='Measurement List:', grid=(0, 0), sticky='e') tipText = 'Selects the measurement list to display measurements for' self.listPulldown = PulldownList(frame0, callback=self.setMeasurementList, grid=(0, 1), tipText=tipText) row += 1 frameB.expandGrid(row, 0) tipTexts = [ 'The serial number of the measurement within its containing list', 'The number or assignment of the NMR resonance(s) to which the measurement applies', 'The numeric value of the NMR measurement on the specified resonance(s), and the unit of measurement', 'The standard deviation error in the measured value', 'The molecular chain, if any, to which the measurement relates by virtue of atom assigned resonances', 'The isotope type(s) of the measures resonance(s)', 'A figure-of-merit value for the measurement indicating its quality or reliability', 'The number of peaks in the CCPN project used to take the measurement', 'A user-defined textual comment for the measurement' ] justifyList = [ 'center', 'center', 'center', 'center', 'center', 'center', 'center', 'center', 'center', 'left' ] colHeadings = [ '#', 'Resonance', 'Value', 'SD', 'Chain', 'Isotope', 'Fig of\nMerit', 'Peaks', 'Details' ] editWidgets = [ None, None, None, None, None, None, self.measurementMeritEntry, None, self.measurementDetailsEntry ] editGetCallbacks = [ None, None, None, None, None, None, self.getMeasurementMerit, self.showPeaks, self.getMeasurementDetails ] editSetCallbacks = [ None, None, None, None, None, None, self.setMeasurementMerit, None, self.setMeasurementDetails ] self.measurementsMatrix = ScrolledMatrix( frameB, grid=(row, 0), multiSelect=True, tipTexts=tipTexts, justifyList=justifyList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, headingList=colHeadings, callback=self.selectMeasurementCell) row += 1 tipTexts = [ 'Show a table containing peaks that were used to derive the selected measurements', 'For some measurement lists (currently only shift lists) manually trigger a recalculation of values', 'Show a table containing the resonances that relate to the selected measurements', 'Delete the selected measurement records; cannot be done for chemical shift values still ties to peaks via assignment' ] texts = ['Show Peaks', 'Recalculate', 'Show Resonances', 'Delete'] commands = [ self.showPeaks, self.recalculateMeasurements, self.showResonances, self.deleteMeasurements ] self.measurementButtons = ButtonList(frameB, texts=texts, grid=(row, 0), commands=commands, tipTexts=tipTexts) # Main Frame self.bottomButtons = UtilityButtonList(tabbedFrame.sideFrame, helpUrl=self.help_url, grid=(0, 0), gridSpan=(1, 2), sticky='e') self.updateMeasurementListAfter() self.updateMeasurementsAfter() self.administerNotifiers(self.registerNotify)
def body(self, guiFrame): self.geometry('700x600') guiFrame.expandGrid(0, 0) tipTexts = [ 'A table of all of the reference isotope scheme definitions available to the project', 'A list of the residue isotopomers that comprise the selected isotope labelling scheme', 'A three-dimensional representation of residues and their isotopomer labelling' ] options = ['Reference Schemes', 'Isotopomers', 'Isotopomer Structure'] tabbedFrame = TabbedFrame(guiFrame, options=options, grid=(0, 0), tipTexts=tipTexts) self.tabbedFrame = tabbedFrame frameA, frameB, frameC = tabbedFrame.frames # # Schemes # frameA.expandGrid(0, 0) tipTexts = [ 'A short textual code that identifies the reference isotope scheme in graphical displays', 'The full name for the isotope scheme', 'A detailed description of the isotope scheme including user comments', 'The name of the CCPN data repository in which the isotope scheme is saved; "refData" is in the CCPn installation' ] headingList = ['Code', 'Name', 'Description', 'Save Location'] self.schemeNameEntry = Entry(self, text='', returnCallback=self.setSchemeName, width=20) self.schemeDetailsEntry = Entry(self, text='', returnCallback=self.setSchemeDetails, width=20) editWidgets = [ None, self.schemeNameEntry, self.schemeDetailsEntry, None ] editGetCallbacks = [ None, self.getSchemeName, self.getSchemeDetails, None ] editSetCallbacks = [ None, self.setSchemeName, self.setSchemeDetails, None ] self.schemeMatrix = ScrolledMatrix(frameA, headingList=headingList, callback=self.selectScheme, editWidgets=editWidgets, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, multiSelect=False, grid=(0, 0), tipTexts=tipTexts) self.schemeMatrix.doEditMarkExtraRules = self.schemeEditRules tipTexts = [ 'Make a new reference isotope scheme definition based on a copy of the scheme currently selected', 'Delete the selected isotope scheme', 'Make a new, blank isotope scheme' ] texts = ['Copy', 'Delete', 'New'] commands = [self.copyScheme, self.removeScheme, self.makeNewScheme] self.schemeButtons = ButtonList(frameA, texts=texts, commands=commands, grid=(1, 0), tipTexts=tipTexts) # # Isotopomers # frameB.expandGrid(3, 0) row = 0 frame = Frame(frameB, grid=(row, 0)) frame.expandGrid(0, 2) tipText = 'Selects which of the available isotope schemes to view/edit' label = Label(frame, text='Reference Scheme:', grid=(0, 0)) self.schemePulldown = PulldownList(frame, callback=self.setLabellingScheme, grid=(0, 1), tipText=tipText) row += 1 div = LabelDivider(frameB, text='Isotopomers', grid=(row, 0)) row += 1 frame = Frame(frameB, grid=(row, 0)) frame.expandGrid(1, 2) self.isotopomerFrame = frame self.abundanceWidget = MultiWidget(self, FloatEntry, relief='raised', borderwidth=2, callback=self.setDefaultAbundances, useImages=False) tipText = 'Opens a panel that allows you to set the basis/default abundances for C, H & N isotopes; used as the starting point for new isotopomer definitions' self.abundanceButton = Button(frame, text='Set Default\nAbundances', borderwidth=1, command=self.enterDefaultAbundances, grid=(0, 0), tipText=tipText) tipText = 'Sets the basis/default abundances for C, H & N isotopes to their natural abundance proportions' button = Button(frame, text='Set Natural\nAbundance Default', borderwidth=1, command=self.resetDefaultAbundance, grid=(0, 1), sticky='ew', tipText=tipText) label = Label(frame, text='Molecule Type:', grid=(0, 2), sticky='e') entries = standardResidueCcpCodes.keys() entries.sort() entries.reverse() tipText = 'Selects which type of bio-polymer to define residue isotopomer labelling for' self.molTypePulldown = PulldownList(frame, callback=self.setMolType, texts=entries, grid=(0, 3), tipText=tipText) row += 1 tipTexts = [ 'The CCPN code that identifies the kind of residue the isotopomer relates to', 'The number of the particular isotopomer (isotope pattern) within its residue type', 'The fraction of the total residues, of its kind, that the isotopomer make up' ] headingList = ['Ccp Code', 'Variant', 'Weight'] self.isotopomerWeightEntry = FloatEntry( self, text='', returnCallback=self.setIsotopomerWeight, width=6) editWidgets = [None, None, self.isotopomerWeightEntry] editGetCallbacks = [None, None, self.getIsotopomerWeight] editSetCallbacks = [None, None, self.setIsotopomerWeight] self.isotopomerMatrix = ScrolledMatrix( frameB, tipTexts=tipTexts, headingList=headingList, callback=self.selectIsotopomer, editWidgets=editWidgets, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, multiSelect=True, grid=(row, 0)) self.isotopomerMatrix.doEditMarkExtraRules = self.isotopomerEditRules row += 1 frame = Frame(frameB, grid=(row, 0), sticky='ew') frame.expandGrid(0, 0) tipTexts = [ 'Delete the selected residue isotopomers from the current isotope scheme', 'Make a new residue isotopomer definition by copying the details of the last selected isotopomer', 'Add a complete set of isotopomers to the isotope scheme, one for each residue type, based on the states default isotope abundances', 'For all residue isotopomers in the scheme, set the labelling of one kind of atom (the user is prompted) to its default isotopic incorporation ', 'Add a new residue isotopomer definition that uses the default isotopic incorporation' ] texts = [ 'Delete\nSelected', 'Copy\nSelected', 'Add Default\nAbundance Set', 'Set Atom Type\nTo Default', 'Add\nNew:' ] commands = [ self.removeIsotopomers, self.duplicateResidues, self.addDefaultIsotopomers, self.setAtomTypeDefault, self.addNewIsotopomer ] self.isotopomerButtons = ButtonList(frame, texts=texts, commands=commands, grid=(0, 0), tipTexts=tipTexts) tipText = 'Selects which kind of residue isotopomer may be added to the current isotope scheme' self.ccpCodePulldown = PulldownList(frame, callback=None, grid=(0, 1), sticky='e', tipText=tipText) row += 1 div = LabelDivider(frameB, text='Atom Labels', grid=(row, 0)) row += 1 frame = Frame(frameB, grid=(row, 0)) frame.expandGrid(1, 3) label = Label(frame, text='Chemical Element:', grid=(0, 0)) tipText = 'Selects which kind of atoms to select from the selected residue isotopomer; to display isotopic incorporation in the below table' self.elementPulldown = PulldownList(frame, callback=self.changeChemElement, grid=(0, 1), tipText=tipText) self.updateChemElements() label = Label(frame, text='Water Exchangeable Atoms:', grid=(0, 2)) tipText = 'Sets whether to show atoms considered as being "water exchangeable"; their isotopic labelling will rapidly equilibrate with aqueous solvent' self.exchangeCheck = CheckButton(frame, callback=self.updateAtomLabelsAfter, grid=(0, 3), selected=False, tipText=tipText) row += 1 # Tip texts set on update headingList = [ 'Atom\nName', 'Weighting\n13C' 'Weighting\n12C', '%12C', '%13C' ] self.atomLabelTupleWeightEntry = FloatEntry( self, text='', width=6, returnCallback=self.setAtomLabelWeight) self.atomsMatrix = ScrolledMatrix(frameB, headingList=headingList, callback=self.selectAtomLabel, multiSelect=True, grid=(row, 0)) self.atomsMatrix.doEditMarkExtraRules = self.atomsEditRules row += 1 tipTexts = [ 'For the selected atom sites, in the current isotopomer, set their isotopic incorporation to the default values', 'Spread the isotopic incorporation values from the last selected atom site to all selected atoms sites' ] texts = ['Reset Selected to Default Abundance', 'Propagate Abundances'] commands = [self.setAtomLabelsDefault, self.propagateAbundances] self.atomButtons = ButtonList(frameB, texts=texts, commands=commands, grid=(row, 0), tipTexts=tipTexts) # # View Frame # frameC.expandGrid(1, 0) row = 0 frame = Frame(frameC, grid=(row, 0), sticky='ew') frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Residue Type:', grid=(0, 0)) tipText = 'Selects which kind of residue, within the current isotope scheme, to show isotopomer structures for' self.viewCcpCodePulldown = PulldownList( frame, callback=self.selectViewCcpcode, grid=(0, 1), tipText=tipText) label = Label(frame, text='Isotopomer:', grid=(0, 2)) tipText = 'Selects which kind of isotopomer (labelling pattern) to display, from the selected residue type.' self.viewIsotopomerPulldown = PulldownList( frame, callback=self.selectViewIsotopomer, grid=(0, 3), tipText=tipText) row += 1 self.viewIsotopomerFrame = ViewIsotopomerFrame(frameC, None, grid=(row, 0)) # # Main # tipTexts = [ 'Save all changes to the reference isotope scheme to disk; the saves ALL changes to the CCPN installation for all projects to use', ] texts = ['Save Schemes'] commands = [self.saveSchemes] self.bottomButtons = UtilityButtonList(tabbedFrame.sideFrame, texts=texts, commands=commands, helpUrl=self.help_url, grid=(0, 0), sticky='e', tipTexts=tipTexts) self.updateChemElements() self.updateCcpCodes() self.updateSchemes() self.administerNotifiers(self.registerNotify)
def __init__(self, parent, getOption=None, setOption=None, text='Print Options', haveTicks=False, doOutlineBox=True, *args, **kw): self.getOption = getOption self.setOption = setOption self.haveTicks = haveTicks self.doOutlineBox = doOutlineBox LabelFrame.__init__(self, parent=parent, text=text, *args, **kw) self.file_select_popup = None self.getOptionValues() try: size_index = self.paper_types.index(self.paper_type) except: size_index = 0 try: other_unit_index = self.paper_units.index(self.other_unit) except: other_unit_index = 0 try: orientation_index = self.paper_orientations.index(self.orientation) except: orientation_index = 0 try: style_index = self.style_choices.index(self.output_style) except: style_index = 0 try: format_index = self.format_choices.index(self.output_format) except: format_index = 0 if haveTicks: try: tick_location_index = self.tick_locations.index( self.tick_location) except: tick_location_index = 0 self.grid_columnconfigure(2, weight=1) row = 0 label = Label(self, text='File:') label.grid(row=row, column=0, sticky='e') self.file_entry = Entry(self, width=40, text=self.file_name) self.file_entry.grid(row=row, column=1, columnspan=2, sticky='ew') button = Button(self, text='Choose File', command=self.findFile) button.grid(row=row, column=3, rowspan=2, sticky='nsew') row += 1 label = Label(self, text='Title:') label.grid(row=row, column=0, sticky='e') self.title_entry = Entry(self, width=40, text=self.title) self.title_entry.grid(row=row, column=1, columnspan=2, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Paper size:') label.grid(row=0, column=0, sticky='e') entries = [] for t in paper_types: if t == Output.other_paper_type: entry = t else: (w, h, u) = paper_sizes[t] entry = t + ' (%2.1f %s x %2.1f %s)' % (w, u, h, u) entries.append(entry) self.size_menu = PulldownList(frame, callback=self.changedSize, texts=entries, index=size_index) self.size_menu.grid(row=0, column=1, sticky='w') self.other_frame = Frame(frame) self.other_frame.grid_columnconfigure(0, weight=1) self.other_entry = FloatEntry(self.other_frame, text=self.other_size, isArray=True) self.other_entry.grid(row=0, column=0, sticky='ew') self.other_unit_menu = PulldownList(self.other_frame, texts=paper_units, index=other_unit_index) self.other_unit_menu.grid(row=0, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(5, weight=1) label = Label(frame, text='Orientation:') label.grid(row=0, column=0, sticky='e') self.orientation_menu = PulldownList(frame, texts=paper_orientations, index=orientation_index) self.orientation_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Style:') label.grid(row=0, column=2, sticky='e') self.style_menu = PulldownList(frame, texts=style_choices, index=style_index) self.style_menu.grid(row=0, column=3, sticky='w') label = Label(frame, text=' Format:') label.grid(row=0, column=4, sticky='e') self.format_menu = PulldownList(frame, callback=self.changedFormat, texts=format_choices, index=format_index) self.format_menu.grid(row=0, column=5, sticky='w') if haveTicks: row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Location:') label.grid(row=0, column=0, sticky='e') self.tick_menu = PulldownList(frame, texts=tick_locations, index=tick_location_index) self.tick_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Tick Placement:') label.grid(row=0, column=2, sticky='e') self.tick_buttons = CheckButtons(frame, entries=tick_placements, selected=self.tick_placement) self.tick_buttons.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Include:') label.grid(row=0, column=0, sticky='e') self.border_buttons = CheckButtons(frame, entries=border_decorations, selected=self.border_decoration) self.border_buttons.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Scaling:') label.grid(row=0, column=2, sticky='e') self.scaling_scale = Scale(frame, orient=Tkinter.HORIZONTAL, value=self.scaling) self.scaling_scale.grid(row=0, column=3, sticky='ew')
class PrintFrame(LabelFrame): def __init__(self, parent, getOption=None, setOption=None, text='Print Options', haveTicks=False, doOutlineBox=True, *args, **kw): self.getOption = getOption self.setOption = setOption self.haveTicks = haveTicks self.doOutlineBox = doOutlineBox LabelFrame.__init__(self, parent=parent, text=text, *args, **kw) self.file_select_popup = None self.getOptionValues() try: size_index = self.paper_types.index(self.paper_type) except: size_index = 0 try: other_unit_index = self.paper_units.index(self.other_unit) except: other_unit_index = 0 try: orientation_index = self.paper_orientations.index(self.orientation) except: orientation_index = 0 try: style_index = self.style_choices.index(self.output_style) except: style_index = 0 try: format_index = self.format_choices.index(self.output_format) except: format_index = 0 if haveTicks: try: tick_location_index = self.tick_locations.index( self.tick_location) except: tick_location_index = 0 self.grid_columnconfigure(2, weight=1) row = 0 label = Label(self, text='File:') label.grid(row=row, column=0, sticky='e') self.file_entry = Entry(self, width=40, text=self.file_name) self.file_entry.grid(row=row, column=1, columnspan=2, sticky='ew') button = Button(self, text='Choose File', command=self.findFile) button.grid(row=row, column=3, rowspan=2, sticky='nsew') row += 1 label = Label(self, text='Title:') label.grid(row=row, column=0, sticky='e') self.title_entry = Entry(self, width=40, text=self.title) self.title_entry.grid(row=row, column=1, columnspan=2, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Paper size:') label.grid(row=0, column=0, sticky='e') entries = [] for t in paper_types: if t == Output.other_paper_type: entry = t else: (w, h, u) = paper_sizes[t] entry = t + ' (%2.1f %s x %2.1f %s)' % (w, u, h, u) entries.append(entry) self.size_menu = PulldownList(frame, callback=self.changedSize, texts=entries, index=size_index) self.size_menu.grid(row=0, column=1, sticky='w') self.other_frame = Frame(frame) self.other_frame.grid_columnconfigure(0, weight=1) self.other_entry = FloatEntry(self.other_frame, text=self.other_size, isArray=True) self.other_entry.grid(row=0, column=0, sticky='ew') self.other_unit_menu = PulldownList(self.other_frame, texts=paper_units, index=other_unit_index) self.other_unit_menu.grid(row=0, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(5, weight=1) label = Label(frame, text='Orientation:') label.grid(row=0, column=0, sticky='e') self.orientation_menu = PulldownList(frame, texts=paper_orientations, index=orientation_index) self.orientation_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Style:') label.grid(row=0, column=2, sticky='e') self.style_menu = PulldownList(frame, texts=style_choices, index=style_index) self.style_menu.grid(row=0, column=3, sticky='w') label = Label(frame, text=' Format:') label.grid(row=0, column=4, sticky='e') self.format_menu = PulldownList(frame, callback=self.changedFormat, texts=format_choices, index=format_index) self.format_menu.grid(row=0, column=5, sticky='w') if haveTicks: row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Location:') label.grid(row=0, column=0, sticky='e') self.tick_menu = PulldownList(frame, texts=tick_locations, index=tick_location_index) self.tick_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Tick Placement:') label.grid(row=0, column=2, sticky='e') self.tick_buttons = CheckButtons(frame, entries=tick_placements, selected=self.tick_placement) self.tick_buttons.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Include:') label.grid(row=0, column=0, sticky='e') self.border_buttons = CheckButtons(frame, entries=border_decorations, selected=self.border_decoration) self.border_buttons.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Scaling:') label.grid(row=0, column=2, sticky='e') self.scaling_scale = Scale(frame, orient=Tkinter.HORIZONTAL, value=self.scaling) self.scaling_scale.grid(row=0, column=3, sticky='ew') def destroy(self): self.setOptionValues() if self.file_select_popup: self.file_select_popup.destroy() Frame.destroy(self) def getOptionValues(self): getOption = self.getOption if getOption: file_name = getOption('FileName', defaultValue='') title = getOption('Title', defaultValue='') paper_type = getOption('PaperSize', defaultValue=paper_types[0]) paper_type = paper_type_dict.get(paper_type, paper_types[0]) other_height = getOption('OtherHeight', defaultValue=10) other_width = getOption('OtherWidth', defaultValue=10) other_size = [other_height, other_width] other_unit = getOption('OtherUnit', defaultValue=paper_units[0]) orientation = getOption('Orientation', defaultValue=paper_orientations[0]) in_color = getOption('InColor', defaultValue=True) if in_color: output_style = style_choices[0] else: output_style = style_choices[1] format_option = getOption('OutputFormat', defaultValue=format_options[0]) output_format = format_choices[format_options.index(format_option)] if self.haveTicks: tick_outside = getOption('TickOutside', defaultValue=tick_locations[0]) if tick_outside: tick_location = tick_locations.index(PrintTicks.Outside) else: tick_location = tick_locations.index(PrintTicks.Inside) tick_placement = getTickPlacement1( getOption('TickPlacement', defaultValue='nsew')) dateTime = getOption('ShowsDateTime', defaultValue=True) fileName = getOption('ShowsFileName', defaultValue=True) border_decoration = [] if dateTime: border_decoration.append(border_decorations[0]) if fileName: border_decoration.append(border_decorations[1]) scaling = getOption('Scaling', defaultValue=0.9) scaling = int(round(100.0 * scaling)) else: file_name = '' title = '' paper_type = paper_types[0] other_unit = paper_units[0] other_size = '' orientation = paper_orientations[0] output_style = style_choices[0] output_format = format_choices[0] if self.haveTicks: tick_location = tick_locations[0] tick_placement = tick_placements border_decoration = border_decorations scaling = 90 if not self.haveTicks: tick_location = None tick_placement = None self.file_name = file_name self.title = title self.paper_type = paper_type self.other_unit = other_unit self.other_size = other_size self.orientation = orientation self.output_style = output_style self.output_format = output_format self.tick_location = tick_location self.tick_placement = tick_placement self.border_decoration = border_decoration self.scaling = scaling def setOptionValues(self): self.file_name = file_name = self.file_entry.get() self.title = title = self.title_entry.get() n = self.size_menu.getSelectedIndex() self.paper_type = paper_type = paper_types[n] if paper_type == Output.other_paper_type: other_size = self.other_entry.get() other_unit = self.other_unit_menu.getText() else: other_size = None other_unit = None self.other_size = other_size self.other_unit = other_unit self.paper_orientation = paper_orientation = self.orientation_menu.getText( ) self.output_style = output_style = self.style_menu.getText() self.output_format = output_format = self.format_menu.getText() if self.haveTicks: tick_location = self.tick_menu.getText() tick_placement = self.tick_buttons.getSelected() else: tick_location = tick_placement = None self.tick_location = tick_location self.tick_placement = tick_placement self.border_decoration = border_decoration = self.border_buttons.getSelected( ) scaling = self.scaling_scale.get() self.scaling = scaling = int(round(scaling)) setOption = self.setOption if setOption: setOption('FileName', value=file_name) setOption('Title', value=title) if paper_type == Output.other_paper_type: setOption('OtherHeight', value=other_size[0]) setOption('OtherWidth', value=other_size[1]) setOption('OtherUnit', value=other_unit) else: paper_type = paper_type_inverse_dict[paper_type] setOption('PaperSize', value=paper_type) setOption('Orientation', value=paper_orientation) in_color = (output_style == style_choices[0]) setOption('InColor', value=in_color) output_format = format_options[format_choices.index(output_format)] setOption('OutputFormat', value=output_format) if self.haveTicks: tick_outside = (tick_location == PrintTicks.Outside) setOption('TickOutside', value=tick_outside) tick_placement = getTickPlacement2(tick_placement) setOption('TickPlacement', value=tick_placement) dateTime = (border_decorations[0] in border_decoration) fileName = (border_decorations[1] in border_decoration) setOption('ShowsDateTime', value=dateTime) setOption('ShowsFileName', value=fileName) setOption('Scaling', value=0.01 * scaling) def findFile(self): if self.file_select_popup: self.file_select_popup.open() else: file_types = [ FileType('All', ['*']), FileType('PostScript', ['*.ps', '*.eps']), FileType('PDF', ['*.pdf', '*.ai']) ] self.file_select_popup = FileSelectPopup(self, file_types=file_types) file = self.file_select_popup.getFile() if file: self.file_entry.set(file) def changedSize(self, entry): if entry == Output.other_paper_type: self.other_frame.grid(row=0, column=2, columnspan=2, sticky='w') else: self.other_frame.grid_forget() def changedFormat(self, entry): file_suffix = file_suffixes.get(entry) if not file_suffix: return file_name = self.file_entry.get() if not file_name: return for suffix in format_suffixes: if file_name.endswith(suffix): if suffix != file_suffix: n = len(suffix) file_name = file_name[:-n] + file_suffix self.file_entry.set(file_name) break else: file_name = file_name + file_suffix self.file_entry.set(file_name) # width and height are of plot, in pixels def getOutputHandler(self, width, height, fonts=None): if not fonts: fonts = [] else: fonts = list(fonts) for n in range(len(fonts)): if fonts[n] == 'Times': fonts[n] = 'Times-Roman' self.setOptionValues() if not self.file_name: showError('No file', 'No file specified', parent=self) return None if os.path.exists(self.file_name): if not showYesNo('File exists', 'File "%s" exists, overwrite?' % self.file_name, parent=self): return None if (self.paper_type == Output.other_paper_type): paper_size = self.other_size + [self.other_unit] else: paper_size = paper_sizes[self.paper_type] output_scaling = self.scaling / 100.0 font = 'Times-Roman' border_text = {} for decoration in self.border_decoration: if (decoration == 'Time & date'): location = 'se' text = time.ctime(time.time()) elif (decoration == 'File name'): location = 'sw' text = self.file_name else: continue # should not be here border_text[location] = (text, font, 12) if (self.title): location = 'n' border_text[location] = (self.title, font, 18) if font not in fonts: fonts.append(font) outputHandler = PrintHandler.getOutputHandler( self.file_name, width, height, output_scaling=output_scaling, paper_size=paper_size, paper_orientation=self.paper_orientation, output_style=self.output_style, output_format=self.output_format, border_text=border_text, fonts=fonts, do_outline_box=self.doOutlineBox) return outputHandler def getAspectRatio(self): self.setOptionValues() if self.paper_type == Output.other_paper_type: paper_size = self.other_size else: paper_size = paper_sizes[self.paper_type] r = paper_size[1] / paper_size[0] if self.paper_orientation == 'Landscape': r = 1.0 / r return r
def __init__(self, parent, getOption = None, setOption = None, haveTicks = False, doOutlineBox = True, *args, **kw): self.getOption = getOption self.setOption = setOption self.haveTicks = haveTicks self.doOutlineBox = doOutlineBox Frame.__init__(self, parent=parent, *args, **kw) self.file_select_popup = None self.getOptionValues() try: size_index = paper_types.index(self.paper_type) except: size_index = 0 try: other_unit_index = paper_units.index(self.other_unit) except: other_unit_index = 0 try: orientation_index = paper_orientations.index(self.paper_orientation) except: orientation_index = 0 try: style_index = style_choices.index(self.output_style) except: style_index = 0 try: format_index = format_choices.index(self.output_format) except: format_index = 0 if haveTicks: try: tick_location_index = tick_locations.index(self.tick_location) except: tick_location_index = 0 self.grid_columnconfigure(1, weight=1) row = 0 button = Button(self, text='File:', command=self.findFile, tipText='Select location to save print file') button.grid(row=row, column=0, sticky='e') self.file_entry = Entry(self, width=40, text=self.file_name, tipText='Location where file is saved on disk') self.file_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='Title:') label.grid(row=row, column=0, sticky='e') self.title_entry = Entry(self, width=40, text=self.title, tipText='Title of the printout, displayed at top') self.title_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='X axis label:') label.grid(row=row, column=0, sticky='e') self.x_axis_entry = Entry(self, width=40, text=self.x_axis_label, tipText='X axis label for the printout') self.x_axis_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='Y axis label:') label.grid(row=row, column=0, sticky='e') self.y_axis_entry = Entry(self, width=40, text=self.y_axis_label, tipText='Y axis label for the printout') self.y_axis_entry.grid(row=row, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=2, sticky='ew') frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Paper size:') label.grid(row=0, column=0, sticky='e') entries = [] for t in paper_types: if t == Output.other_paper_type: entry = t else: (w, h, u) = paper_sizes[t] entry = t + ' (%2.1f %s x %2.1f %s)' % (w, u, h, u) entries.append(entry) self.size_menu = PulldownList(frame, callback=self.changedSize, texts=entries, index=size_index, tipText='The paper size for the printout') self.size_menu.grid(row=0, column=1, sticky='w') self.other_frame = Frame(frame) self.other_frame.grid_columnconfigure(0, weight=1) self.other_entry = FloatEntry(self.other_frame, text=self.other_size, isArray=True, tipText='The size of the Other paper in both dimensions; this requires two values, space or comma separated') self.other_entry.grid(row=0, column=0, sticky='ew') self.other_unit_menu= PulldownList(self.other_frame, texts=paper_units, index=other_unit_index, tipText='The unit for the Other paper size') self.other_unit_menu.grid(row=0, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(5, weight=1) label = Label(frame, text='Orientation:') label.grid(row=0, column=0, sticky='e') self.orientation_menu = PulldownList(frame, texts=paper_orientations, index=orientation_index, tipText='Whether the paper should be set in Portrait or Landscape mode') self.orientation_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Style:') label.grid(row=0, column=2, sticky='e') self.style_menu = PulldownList(frame, texts=style_choices, index=style_index, tipText='Whether the printout should be in colour or black and white') self.style_menu.grid(row=0, column=3, sticky='w') label = Label(frame, text=' Format:') label.grid(row=0, column=4, sticky='e') self.format_menu = PulldownList(frame, callback=self.changedFormat, texts=format_choices, index=format_index, tipText='Whether to save as PS, EPS or PDF') self.format_menu.grid(row=0, column=5, sticky='w') if haveTicks: row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Location:') label.grid(row=0, column=0, sticky='e') self.tick_menu = PulldownList(frame, texts=tick_locations, index=tick_location_index, tipText='Whether the tick marks appear on the inside or outside of the frame') self.tick_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Tick Placement:') label.grid(row=0, column=2, sticky='e') if self.tick_placement is None: selected = None else: selected = [(x in self.tick_placement) for x in tick_placements] self.tick_buttons = CheckButtons(frame, entries=tick_placements, selected=selected, tipTexts=('Whether the tick marks appear on the top and/or bottom and/or left and/or right',)) self.tick_buttons.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Font:') label.grid(row=0, column=0, sticky='e') self.tick_font_list = FontList(frame, mode='Print', selected=self.tick_font, extraTexts=[PrintTicks.no_tick_text], tipText='The font used for the tick mark labels') self.tick_font_list.grid(row=0, column=1, sticky='w') label = Label(frame, text='Tick Spacing:') label.grid(row=0, column=2, sticky='e') # TBD: put preferred choice in data model self.spacing_menu = PulldownList(frame, texts=spacing_choices, index=0, callback=self.changedSpacing, tipText='Whether the program should automatically calculate the major/minor tick spacings and how many decimal places are used for the ticks, or whether the these are specified manually') self.spacing_menu.grid(row=0, column=3, sticky='w') ff = self.spacing_frame = Frame(frame) ff.grid_columnconfigure(1, weight=1) ff.grid_columnconfigure(2, weight=1) label = Label(ff, text='Tick Spacing') label.grid(row=0, column=0, sticky='w') label = Label(ff, text='Major') label.grid(row=0, column=1, sticky='ew') label = Label(ff, text='Minor') label.grid(row=0, column=2, sticky='ew') label = Label(ff, text='Decimals') label.grid(row=0, column=3, sticky='ew') label = Label(ff, text='X:') label.grid(row=1, column=0, sticky='w') self.x_major_entry = FloatEntry(ff, tipText='The spacing in display units of the major tick marks in the X dimension') self.x_major_entry.grid(row=1, column=1, sticky='ew') self.x_minor_entry = FloatEntry(ff, tipText='The spacing in display units of the minor tick marks in the X dimension (not printed if left blank)') self.x_minor_entry.grid(row=1, column=2, sticky='ew') self.x_decimal_entry = IntEntry(ff, tipText='The number of decimal places for the tick numbers in the X dimension') self.x_decimal_entry.grid(row=1, column=3, sticky='ew') label = Label(ff, text='Y:') label.grid(row=2, column=0, sticky='w') self.y_major_entry = FloatEntry(ff, tipText='The spacing in display units of the major tick marks in the Y dimension') self.y_major_entry.grid(row=2, column=1, sticky='ew') self.y_minor_entry = FloatEntry(ff, tipText='The spacing in display units of the minor tick marks in the Y dimension (not printed if left blank)') self.y_minor_entry.grid(row=2, column=2, sticky='ew') self.y_decimal_entry = IntEntry(ff, tipText='The number of decimal places for the tick numbers in the Y dimension') self.y_decimal_entry.grid(row=2, column=3, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) label = Label(frame, text='Tick Length:') label.grid(row=0, column=0, sticky='e') # TBD: put preferred choice in data model self.tick_length_menu = PulldownList(frame, texts=tick_length_choices, index=0, callback=self.changedLength, tipText='Whether the program should automatically calculate the major/minor tick lengths, or whether the these are specified manually') self.tick_length_menu.grid(row=0, column=1, sticky='w') ff = self.length_frame = Frame(frame) ff.grid_columnconfigure(1, weight=1) label = Label(ff, text=' Major length:') label.grid(row=0, column=0, sticky='w') self.length_major_entry = FloatEntry(ff, tipText='The length in points of the major tick marks') self.length_major_entry.grid(row=0, column=1, sticky='w') label = Label(ff, text='Minor length:') label.grid(row=0, column=2, sticky='w') self.length_minor_entry = FloatEntry(ff, tipText='The length in points of the minor tick marks') self.length_minor_entry.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Scaling:') label.grid(row=0, column=0, sticky='e') # TBD: put preferred choice in data model self.scaling_menu = PulldownList(frame, texts=scaling_choices, index=0, callback=self.changedScaling, tipText='Whether the plot should be scaled as a percentage of the maximum size that would fit on the paper, or instead should be specified by the number of cms or inches per unit') self.scaling_menu.grid(row=0, column=1, sticky='ew') self.scaling_scale = Scale(frame, orient=Tkinter.HORIZONTAL, value=self.scaling, tipText='The percentage of the maximum size that would fit on the paper that the plot is scaled by') self.scaling_scale.grid(row=0, column=2, columnspan=3, sticky='ew') self.x_scaling_label = Label(frame, text='X:') self.x_scaling_entry = FloatEntry(frame, tipText='The scaling that should be used in the X dimension as cms or inches per unit') self.y_scaling_label = Label(frame, text='Y:') self.y_scaling_entry = FloatEntry(frame, tipText='The scaling that should be used in the Y dimension as cms or inches per unit') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='w') frame.grid_columnconfigure(2, weight=1) label = Label(frame, text='Include:') label.grid(row=0, column=0, sticky='e') tipTexts = ('Whether the time and date should be included in the printout', 'Whether the file name should be included in the printout') if self.border_decoration is None: selected = None else: selected = [(x in self.border_decoration) for x in border_decorations] self.border_buttons = CheckButtons(frame, entries=border_decorations, selected=selected, tipTexts=tipTexts) self.border_buttons.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Using Font:') label.grid(row=0, column=2, sticky='e') self.border_font_list = FontList(frame, mode='Print', selected=self.border_font, tipText='The font used for the border texts') self.border_font_list.grid(row=0, column=3, sticky='w') row += 1 label = Label(self, text='Line width:') label.grid(row=row, column=0, sticky='w') self.linewidth_entry = FloatEntry(self, width=10, text=self.linewidth, tipText='Line width for drawing') self.linewidth_entry.grid(row=row, column=1, sticky='w')
class PrintFrame(Frame): def __init__(self, parent, getOption = None, setOption = None, haveTicks = False, doOutlineBox = True, *args, **kw): self.getOption = getOption self.setOption = setOption self.haveTicks = haveTicks self.doOutlineBox = doOutlineBox Frame.__init__(self, parent=parent, *args, **kw) self.file_select_popup = None self.getOptionValues() try: size_index = paper_types.index(self.paper_type) except: size_index = 0 try: other_unit_index = paper_units.index(self.other_unit) except: other_unit_index = 0 try: orientation_index = paper_orientations.index(self.paper_orientation) except: orientation_index = 0 try: style_index = style_choices.index(self.output_style) except: style_index = 0 try: format_index = format_choices.index(self.output_format) except: format_index = 0 if haveTicks: try: tick_location_index = tick_locations.index(self.tick_location) except: tick_location_index = 0 self.grid_columnconfigure(1, weight=1) row = 0 button = Button(self, text='File:', command=self.findFile, tipText='Select location to save print file') button.grid(row=row, column=0, sticky='e') self.file_entry = Entry(self, width=40, text=self.file_name, tipText='Location where file is saved on disk') self.file_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='Title:') label.grid(row=row, column=0, sticky='e') self.title_entry = Entry(self, width=40, text=self.title, tipText='Title of the printout, displayed at top') self.title_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='X axis label:') label.grid(row=row, column=0, sticky='e') self.x_axis_entry = Entry(self, width=40, text=self.x_axis_label, tipText='X axis label for the printout') self.x_axis_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='Y axis label:') label.grid(row=row, column=0, sticky='e') self.y_axis_entry = Entry(self, width=40, text=self.y_axis_label, tipText='Y axis label for the printout') self.y_axis_entry.grid(row=row, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=2, sticky='ew') frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Paper size:') label.grid(row=0, column=0, sticky='e') entries = [] for t in paper_types: if t == Output.other_paper_type: entry = t else: (w, h, u) = paper_sizes[t] entry = t + ' (%2.1f %s x %2.1f %s)' % (w, u, h, u) entries.append(entry) self.size_menu = PulldownList(frame, callback=self.changedSize, texts=entries, index=size_index, tipText='The paper size for the printout') self.size_menu.grid(row=0, column=1, sticky='w') self.other_frame = Frame(frame) self.other_frame.grid_columnconfigure(0, weight=1) self.other_entry = FloatEntry(self.other_frame, text=self.other_size, isArray=True, tipText='The size of the Other paper in both dimensions; this requires two values, space or comma separated') self.other_entry.grid(row=0, column=0, sticky='ew') self.other_unit_menu= PulldownList(self.other_frame, texts=paper_units, index=other_unit_index, tipText='The unit for the Other paper size') self.other_unit_menu.grid(row=0, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(5, weight=1) label = Label(frame, text='Orientation:') label.grid(row=0, column=0, sticky='e') self.orientation_menu = PulldownList(frame, texts=paper_orientations, index=orientation_index, tipText='Whether the paper should be set in Portrait or Landscape mode') self.orientation_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Style:') label.grid(row=0, column=2, sticky='e') self.style_menu = PulldownList(frame, texts=style_choices, index=style_index, tipText='Whether the printout should be in colour or black and white') self.style_menu.grid(row=0, column=3, sticky='w') label = Label(frame, text=' Format:') label.grid(row=0, column=4, sticky='e') self.format_menu = PulldownList(frame, callback=self.changedFormat, texts=format_choices, index=format_index, tipText='Whether to save as PS, EPS or PDF') self.format_menu.grid(row=0, column=5, sticky='w') if haveTicks: row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Location:') label.grid(row=0, column=0, sticky='e') self.tick_menu = PulldownList(frame, texts=tick_locations, index=tick_location_index, tipText='Whether the tick marks appear on the inside or outside of the frame') self.tick_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Tick Placement:') label.grid(row=0, column=2, sticky='e') if self.tick_placement is None: selected = None else: selected = [(x in self.tick_placement) for x in tick_placements] self.tick_buttons = CheckButtons(frame, entries=tick_placements, selected=selected, tipTexts=('Whether the tick marks appear on the top and/or bottom and/or left and/or right',)) self.tick_buttons.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Font:') label.grid(row=0, column=0, sticky='e') self.tick_font_list = FontList(frame, mode='Print', selected=self.tick_font, extraTexts=[PrintTicks.no_tick_text], tipText='The font used for the tick mark labels') self.tick_font_list.grid(row=0, column=1, sticky='w') label = Label(frame, text='Tick Spacing:') label.grid(row=0, column=2, sticky='e') # TBD: put preferred choice in data model self.spacing_menu = PulldownList(frame, texts=spacing_choices, index=0, callback=self.changedSpacing, tipText='Whether the program should automatically calculate the major/minor tick spacings and how many decimal places are used for the ticks, or whether the these are specified manually') self.spacing_menu.grid(row=0, column=3, sticky='w') ff = self.spacing_frame = Frame(frame) ff.grid_columnconfigure(1, weight=1) ff.grid_columnconfigure(2, weight=1) label = Label(ff, text='Tick Spacing') label.grid(row=0, column=0, sticky='w') label = Label(ff, text='Major') label.grid(row=0, column=1, sticky='ew') label = Label(ff, text='Minor') label.grid(row=0, column=2, sticky='ew') label = Label(ff, text='Decimals') label.grid(row=0, column=3, sticky='ew') label = Label(ff, text='X:') label.grid(row=1, column=0, sticky='w') self.x_major_entry = FloatEntry(ff, tipText='The spacing in display units of the major tick marks in the X dimension') self.x_major_entry.grid(row=1, column=1, sticky='ew') self.x_minor_entry = FloatEntry(ff, tipText='The spacing in display units of the minor tick marks in the X dimension (not printed if left blank)') self.x_minor_entry.grid(row=1, column=2, sticky='ew') self.x_decimal_entry = IntEntry(ff, tipText='The number of decimal places for the tick numbers in the X dimension') self.x_decimal_entry.grid(row=1, column=3, sticky='ew') label = Label(ff, text='Y:') label.grid(row=2, column=0, sticky='w') self.y_major_entry = FloatEntry(ff, tipText='The spacing in display units of the major tick marks in the Y dimension') self.y_major_entry.grid(row=2, column=1, sticky='ew') self.y_minor_entry = FloatEntry(ff, tipText='The spacing in display units of the minor tick marks in the Y dimension (not printed if left blank)') self.y_minor_entry.grid(row=2, column=2, sticky='ew') self.y_decimal_entry = IntEntry(ff, tipText='The number of decimal places for the tick numbers in the Y dimension') self.y_decimal_entry.grid(row=2, column=3, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) label = Label(frame, text='Tick Length:') label.grid(row=0, column=0, sticky='e') # TBD: put preferred choice in data model self.tick_length_menu = PulldownList(frame, texts=tick_length_choices, index=0, callback=self.changedLength, tipText='Whether the program should automatically calculate the major/minor tick lengths, or whether the these are specified manually') self.tick_length_menu.grid(row=0, column=1, sticky='w') ff = self.length_frame = Frame(frame) ff.grid_columnconfigure(1, weight=1) label = Label(ff, text=' Major length:') label.grid(row=0, column=0, sticky='w') self.length_major_entry = FloatEntry(ff, tipText='The length in points of the major tick marks') self.length_major_entry.grid(row=0, column=1, sticky='w') label = Label(ff, text='Minor length:') label.grid(row=0, column=2, sticky='w') self.length_minor_entry = FloatEntry(ff, tipText='The length in points of the minor tick marks') self.length_minor_entry.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Scaling:') label.grid(row=0, column=0, sticky='e') # TBD: put preferred choice in data model self.scaling_menu = PulldownList(frame, texts=scaling_choices, index=0, callback=self.changedScaling, tipText='Whether the plot should be scaled as a percentage of the maximum size that would fit on the paper, or instead should be specified by the number of cms or inches per unit') self.scaling_menu.grid(row=0, column=1, sticky='ew') self.scaling_scale = Scale(frame, orient=Tkinter.HORIZONTAL, value=self.scaling, tipText='The percentage of the maximum size that would fit on the paper that the plot is scaled by') self.scaling_scale.grid(row=0, column=2, columnspan=3, sticky='ew') self.x_scaling_label = Label(frame, text='X:') self.x_scaling_entry = FloatEntry(frame, tipText='The scaling that should be used in the X dimension as cms or inches per unit') self.y_scaling_label = Label(frame, text='Y:') self.y_scaling_entry = FloatEntry(frame, tipText='The scaling that should be used in the Y dimension as cms or inches per unit') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='w') frame.grid_columnconfigure(2, weight=1) label = Label(frame, text='Include:') label.grid(row=0, column=0, sticky='e') tipTexts = ('Whether the time and date should be included in the printout', 'Whether the file name should be included in the printout') if self.border_decoration is None: selected = None else: selected = [(x in self.border_decoration) for x in border_decorations] self.border_buttons = CheckButtons(frame, entries=border_decorations, selected=selected, tipTexts=tipTexts) self.border_buttons.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Using Font:') label.grid(row=0, column=2, sticky='e') self.border_font_list = FontList(frame, mode='Print', selected=self.border_font, tipText='The font used for the border texts') self.border_font_list.grid(row=0, column=3, sticky='w') row += 1 label = Label(self, text='Line width:') label.grid(row=row, column=0, sticky='w') self.linewidth_entry = FloatEntry(self, width=10, text=self.linewidth, tipText='Line width for drawing') self.linewidth_entry.grid(row=row, column=1, sticky='w') def destroy(self): self.setOptionValues() if self.file_select_popup: self.file_select_popup.destroy() Frame.destroy(self) def getOptionValues(self): getOption = self.getOption if getOption: file_name = getOption('FileName', defaultValue='') title = getOption('Title', defaultValue='') x_axis_label = getOption('XAxisLabel', defaultValue='') y_axis_label = getOption('YAxisLabel', defaultValue='') paper_type = getOption('PaperSize', defaultValue=paper_types[0]) paper_type = paper_type_dict.get(paper_type, paper_types[0]) other_height = getOption('OtherHeight', defaultValue=10) other_width = getOption('OtherWidth', defaultValue=10) other_size = [other_height, other_width] other_unit = getOption('OtherUnit', defaultValue=paper_units[0]) paper_orientation = getOption('Orientation', defaultValue=paper_orientations[0]) in_color = getOption('InColor', defaultValue=True) if in_color: output_style = style_choices[0] else: output_style = style_choices[1] format_option = getOption('OutputFormat', defaultValue=format_options[0]) output_format = format_choices[format_options.index(format_option)] if self.haveTicks: tick_outside = getOption('TickOutside', defaultValue=tick_locations[0]) if tick_outside: tick_location = tick_locations.index(PrintTicks.Outside) else: tick_location = tick_locations.index(PrintTicks.Inside) tick_placement = getTickPlacement1(getOption('TickPlacement', defaultValue='nsew')) dateTime = getOption('ShowsDateTime', defaultValue=True) fileName = getOption('ShowsFileName', defaultValue=True) border_font = getOption('BorderFont', defaultValue='Helvetica 10') border_decoration = [] if dateTime: border_decoration.append(border_decorations[0]) if fileName: border_decoration.append(border_decorations[1]) if self.haveTicks: spacing_choice = getOption('SpacingChoice', defaultValue=spacing_choices[0]) x_major = getOption('XMajor', defaultValue=1.0) x_minor = getOption('XMinor', defaultValue=1.0) x_decimal = getOption('XDecimal', defaultValue=3) y_major = getOption('YMajor', defaultValue=1.0) y_minor = getOption('YMinor', defaultValue=1.0) y_decimal = getOption('YDecimal', defaultValue=3) tick_length_choice = getOption('TickLengthChoice', defaultValue=tick_length_choices[0]) tick_major = getOption('TickMajor', defaultValue=10) tick_minor = getOption('TickMinor', defaultValue=5) scaling_choice = getOption('ScalingChoice', defaultValue=scaling_choices[0]) scaling = getOption('Scaling', defaultValue=0.7) scaling = int(round(100.0 * scaling)) x_scaling = getOption('XScaling', defaultValue=1.0) y_scaling = getOption('YScaling', defaultValue=1.0) if self.haveTicks: tick_font = getOption('TickFont', defaultValue='Helvetica 10') linewidth = getOption('LineWidth', defaultValue=Output.default_linewidth) else: file_name = '' title = '' x_axis_label = '' y_axis_label = '' paper_type = paper_types[0] other_unit = paper_units[0] other_size = '' paper_orientation = paper_orientations[0] output_style = style_choices[0] output_format = format_choices[0] if self.haveTicks: tick_location = tick_locations[0] tick_placement = tick_placements border_decoration = border_decorations border_font = 'Helvetica 10' if self.haveTicks: spacing_choice = spacing_choices[0] x_major = 1.0 x_minor = 1.0 x_decimal = 3 y_major = 1.0 y_minor = 1.0 y_decimal = 3 tick_length_choice = tick_length_choices[0] tick_major = 10 tick_minor = 5 scaling_choice = scaling_choices[0] scaling = 70 x_scaling = 1.0 y_scaling = 1.0 if self.haveTicks: tick_font = 'Helvetica 10' linewidth = Output.default_linewidth if not self.haveTicks: tick_location = None tick_placement = None spacing_choice = spacing_choices[0] x_major = 1.0 x_minor = 1.0 x_decimal = 3 y_major = 1.0 y_minor = 1.0 y_decimal = 3 tick_font = 'Helvetica 10' tick_length_choice = tick_length_choices[0] tick_major = 10 tick_minor = 5 self.file_name = file_name self.title = title self.x_axis_label = x_axis_label self.y_axis_label = y_axis_label self.paper_type = paper_type self.other_unit = other_unit self.other_size = other_size self.paper_orientation = paper_orientation self.output_style = output_style self.output_format = output_format self.tick_location = tick_location self.tick_placement = tick_placement self.border_decoration = border_decoration self.border_font = border_font self.spacing_choice = spacing_choice self.x_major = x_major self.x_minor = x_minor self.x_decimal = x_decimal self.y_major = y_major self.y_minor = y_minor self.y_decimal = y_decimal self.scaling_choice = scaling_choices[0] self.scaling = scaling self.x_scaling = x_scaling self.y_scaling = y_scaling self.tick_font = tick_font self.linewidth = linewidth self.tick_length_choice = tick_length_choice self.tick_major = tick_major self.tick_minor = tick_minor def setOptionValues(self): if not hasattr(self, 'file_entry'): # it looks like on destroy can have function called but file_entry deleted already return self.file_name = file_name = self.file_entry.get() self.title = title = self.title_entry.get() self.x_axis_label = x_axis_label = self.x_axis_entry.get() self.y_axis_label = y_axis_label = self.y_axis_entry.get() n = self.size_menu.getSelectedIndex() self.paper_type = paper_type = paper_types[n] if paper_type == Output.other_paper_type: other_size = self.other_entry.get() other_unit = self.other_unit_menu.getText() else: other_size = None other_unit = None self.other_size = other_size self.other_unit = other_unit self.paper_orientation = paper_orientation = self.orientation_menu.getText() self.output_style = output_style = self.style_menu.getText() self.output_format = output_format = self.format_menu.getText() if self.haveTicks: tick_location = self.tick_menu.getText() tick_placement = self.tick_buttons.getSelected() else: tick_location = tick_placement = None self.tick_location = tick_location self.tick_placement = tick_placement self.border_decoration = border_decoration = self.border_buttons.getSelected() self.border_font = border_font = self.border_font_list.getText() if self.haveTicks: self.spacing_choice = spacing_choice = self.spacing_menu.getText() if spacing_choice != spacing_choices[0]: self.x_major = self.x_major_entry.get() self.x_minor = self.x_minor_entry.get() self.x_decimal = self.x_decimal_entry.get() self.y_major = self.y_major_entry.get() self.y_minor = self.y_minor_entry.get() self.y_decimal = self.y_decimal_entry.get() self.tick_length_choice = tick_length_choice = self.tick_length_menu.getText() if tick_length_choice != tick_length_choices[0]: self.tick_major = self.length_major_entry.get() self.tick_minor = self.length_minor_entry.get() self.scaling_choice = scaling_choice = self.scaling_menu.getText() if self.scaling_choice == scaling_choices[0]: scaling = self.scaling_scale.get() self.scaling = int(round(scaling)) else: self.x_scaling = self.x_scaling_entry.get() self.y_scaling = self.y_scaling_entry.get() if self.haveTicks: self.tick_font = self.tick_font_list.getText() self.linewidth = self.linewidth_entry.get() setOption = self.setOption if setOption: setOption('FileName', value=file_name) setOption('Title', value=title) setOption('XAxisLabel', value=x_axis_label) setOption('YAxisLabel', value=y_axis_label) if paper_type == Output.other_paper_type: setOption('OtherHeight', value=other_size[0]) setOption('OtherWidth', value=other_size[1]) setOption('OtherUnit', value=other_unit) else: paper_type = paper_type_inverse_dict[paper_type] setOption('PaperSize', value=paper_type) setOption('Orientation', value=paper_orientation) in_color = (output_style == style_choices[0]) setOption('InColor', value=in_color) output_format = format_options[format_choices.index(output_format)] setOption('OutputFormat', value=output_format) if self.haveTicks: tick_outside = (tick_location == PrintTicks.Outside) setOption('TickOutside', value=tick_outside) tick_placement = getTickPlacement2(tick_placement) setOption('TickPlacement', value=tick_placement) dateTime = (border_decorations[0] in border_decoration) fileName = (border_decorations[1] in border_decoration) setOption('ShowsDateTime', value=dateTime) setOption('ShowsFileName', value=fileName) setOption('BorderFont', value=border_font) if self.haveTicks: setOption('SpacingChoice', value=spacing_choice) if spacing_choice != spacing_choices[0]: setOption('XMajor', self.x_major) setOption('XMinor', self.x_minor) setOption('XDecimal', self.x_decimal) setOption('YMajor', self.y_major) setOption('YMinor', self.y_minor) setOption('YDecimal', self.y_decimal) setOption('TickLengthChoice', value=tick_length_choice) if tick_length_choice != tick_length_choices[0]: setOption('TickMajor', self.tick_major) setOption('TickMinor', self.tick_minor) setOption('ScalingChoice', value=scaling_choice) if scaling_choice == scaling_choices[0]: setOption('Scaling', value=0.01*self.scaling) else: setOption('XScaling', value=self.x_scaling) setOption('YScaling', value=self.y_scaling) if self.haveTicks: setOption('TickFont', self.tick_font) setOption('LineWidth', self.linewidth) def findFile(self): if self.file_select_popup: self.file_select_popup.open() else: file_types = [ FileType('All', ['*']), FileType('PostScript', ['*.ps', '*.eps']), FileType('PDF', ['*.pdf', '*.ai']) ] self.file_select_popup = FileSelectPopup(self, file_types=file_types) file = self.file_select_popup.getFile() if file: self.file_entry.set(file) def changedSize(self, entry): if entry == Output.other_paper_type: self.other_frame.grid(row=0, column=2, columnspan=2, sticky='w') else: self.other_frame.grid_forget() def changedFormat(self, entry): file_suffix = file_suffixes.get(entry) if not file_suffix: return file_name = self.file_entry.get() if not file_name: return for suffix in format_suffixes: if file_name.endswith(suffix): if suffix != file_suffix: n = len(suffix) file_name = file_name[:-n] + file_suffix self.file_entry.set(file_name) break else: file_name = file_name + file_suffix self.file_entry.set(file_name) def changedScaling(self, choice): if choice == scaling_choices[0]: self.scaling_scale.grid(row=0, column=2, columnspan=3, sticky='ew') self.x_scaling_label.grid_forget() self.x_scaling_entry.grid_forget() self.y_scaling_label.grid_forget() self.y_scaling_entry.grid_forget() else: self.scaling_scale.grid_forget() self.x_scaling_label.grid(row=0, column=2, sticky='w') self.x_scaling_entry.grid(row=0, column=3, columnspan=2, sticky='ew') self.y_scaling_label.grid(row=1, column=2, sticky='w') self.y_scaling_entry.grid(row=1, column=3, columnspan=2, sticky='ew') self.setOptionValues() def changedSpacing(self, choice): if choice == spacing_choices[0]: self.spacing_frame.grid_forget() else: self.spacing_frame.grid(row=1, column=1, columnspan=3, sticky='ew') self.setOptionValues() def changedLength(self, choice): if choice == tick_length_choices[0]: self.length_frame.grid_forget() else: self.length_frame.grid(row=1, column=0, columnspan=4, sticky='ew') self.setOptionValues() # width and height are of plot, in pixels def getOutputHandler(self, pixel_width, pixel_height, unit_width=1.0, unit_height=1.0, fonts=None): if not fonts: fonts = [] else: fonts = list(fonts) for n in range(len(fonts)): if fonts[n] == 'Times': fonts[n] = 'Times-Roman' self.setOptionValues() if not self.file_name: showError('No file', 'No file specified', parent=self) return None x_scaling = y_scaling = 1.0 if self.scaling_choice != scaling_choices[0]: try: x_scaling = float(self.x_scaling) except: showError('Bad X Scaling', 'Specified X Scaling must be floating point', parent=self) return None try: y_scaling = float(self.y_scaling) except: showError('Bad Y Scaling', 'Specified Y Scaling must be floating point', parent=self) return None if os.path.exists(self.file_name): if not showYesNo('File exists', 'File "%s" exists, overwrite?' % self.file_name, parent=self): return None if self.paper_type == Output.other_paper_type: paper_size = self.other_size + [ self.other_unit ] else: paper_size = paper_sizes[self.paper_type] output_scaling = self.scaling / 100.0 border_font = self.border_font (font, size) = border_font.split() size = int(size) border_text = {} for decoration in self.border_decoration: if decoration == 'Time and Date': location = 'se' text = time.ctime(time.time()) elif decoration == 'File Name': location = 'sw' text = self.file_name else: continue # should not be here border_text[location] = (text, font, size) if self.title: location = 'n' border_text[location] = (self.title, font, size+6) if font not in fonts: fonts.append(font) if self.haveTicks and self.tick_location == PrintTicks.Outside: axis_label_offset = 2 else: axis_label_offset = 0 outputHandler = PrintHandler.getOutputHandler(self.file_name, pixel_width, pixel_height, unit_width, unit_height, scaling_choice=self.scaling_choice, output_scaling=output_scaling, w_scaling=x_scaling, h_scaling=y_scaling, paper_size=paper_size, paper_orientation=self.paper_orientation, output_style=self.output_style, output_format=self.output_format, border_text=border_text, x_axis_label=self.x_axis_label, y_axis_label=self.y_axis_label, axis_label_font=font, axis_label_size=size, axis_label_offset=axis_label_offset, fonts=fonts, linewidth=self.linewidth, do_outline_box=self.doOutlineBox) return outputHandler def getAspectRatio(self): self.setOptionValues() if self.paper_type == Output.other_paper_type: paper_size = self.other_size else: paper_size = paper_sizes[self.paper_type] r = paper_size[1] / paper_size[0] if self.paper_orientation == 'Landscape': r = 1.0 / r return r
def body(self): frame = self.frame self.resultsResidueNumber = 1 frame.expandGrid(5, 0) resultTopFrame = LabelFrame(frame, text='Which results to show') resultTopFrame.grid(row=0, column=0, sticky='ew') self.resultsResidueNumber = 3 texts = [' < '] commands = [self.resultsPrevResidue] self.resultsPreviousButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.resultsPreviousButton.grid(row=0, column=1, sticky='nsew') tipText = 'The Number of the residue in the sequence to display results for' self.resultsResidueNumberEntry = IntEntry( resultTopFrame, grid=(0, 2), width=7, text=3, returnCallback=self.resultsUpdateAfterEntry, tipText=tipText) #self.resultsResidueNumberEntry.bind('<Leave>', self.resultsUpdateAfterEntry, '+') texts = [' > '] commands = [self.resultsNextResidue] self.resultsNextButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.resultsNextButton.grid(row=0, column=3, sticky='nsew') selectCcpCodes = ['residue'] + AMINO_ACIDS self.resultsSelectedCcpCode = 'residue' tipText = 'Instead of going through the sequence residue by residue, jump directly to next amino acid of a specific type.' resultsSelectCcpCodeLabel = Label( resultTopFrame, text='Directly jump to previous/next:', grid=(0, 4)) self.resultsSelectCcpCodePulldown = PulldownList( resultTopFrame, callback=self.resultsChangeSelectedCcpCode, texts=selectCcpCodes, index=selectCcpCodes.index(self.resultsSelectedCcpCode), grid=(0, 5), tipText=tipText) self.selectedSolution = 1 runLabel = Label(resultTopFrame, text='run:') runLabel.grid(row=0, column=6) texts = [' < '] commands = [self.resultsPrevSolution] self.resultsPreviousSolutionButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.resultsPreviousSolutionButton.grid(row=0, column=7, sticky='nsew') tipText = 'If you ran the algorithm more than once, you can select the solution given by the different runs.' self.resultsSolutionNumberEntry = IntEntry( resultTopFrame, grid=(0, 8), width=7, text=1, returnCallback=self.solutionUpdateAfterEntry, tipText=tipText) #self.resultsSolutionNumberEntry.bind('<Leave>', self.solutionUpdateAfterEntry, '+') texts = [' > '] commands = [self.resultsNextSolution] self.resultsNextSolutionButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.resultsNextSolutionButton.grid(row=0, column=9, sticky='nsew') self.energyLabel = Label(resultTopFrame, text='energy:') self.energyLabel.grid(row=0, column=10) texts = ['template for puzzling'] commands = [self.adoptSolution] self.adoptButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.adoptButton.grid(row=0, column=11, sticky='nsew') # LabelFrame(frame, text='Spin Systems') resultsSecondFrame = Frame(frame) resultsSecondFrame.grid(row=2, column=0, sticky='nsew') resultsSecondFrame.grid_columnconfigure(0, weight=1) resultsSecondFrame.grid_columnconfigure(1, weight=1) resultsSecondFrame.grid_columnconfigure(2, weight=1) resultsSecondFrame.grid_columnconfigure(3, weight=1) resultsSecondFrame.grid_columnconfigure(4, weight=1) headingList = ['#', '%'] tipTexts = [ 'Spinsystem number {} indicates serial of the spinsystem. If the spinsystem was already assigned to a residue, the residue number is shown aswell', 'percentage of the solutions that connected this spinsystem to this residue' ] editWidgets = [None, None, None] self.displayResultsTables = [] self.residueLabels = [] for i in range(5): label = Label(resultsSecondFrame, text='residue') label.grid(row=0, column=i) #editGetCallbacks = [createCallbackFunction(i)]*3 displayResultsTable = ScrolledMatrix( resultsSecondFrame, headingList=headingList, multiSelect=False, tipTexts=tipTexts, callback=self.selectSpinSystemForTable, passSelfToCallback=True) displayResultsTable.grid(row=2, column=i, sticky='nsew') displayResultsTable.sortDown = False self.residueLabels.append(label) self.displayResultsTables.append(displayResultsTable) # LabelFrame(frame, text='Sequence Fragment') resultsFirstFrame = Frame(resultsSecondFrame) resultsFirstFrame.grid(row=1, column=0, sticky='ew', columnspan=5) resultsFirstFrame.grid_rowconfigure(0, weight=1) resultsFirstFrame.grid_rowconfigure(1, weight=1) resultsFirstFrame.grid_columnconfigure(0, weight=1) texts = [ ' res 1 ', ' links ', ' res 2 ', ' links ', ' res 3 ', ' links ', ' res 4 ', ' links ', ' res 5 ' ] commands = [ lambda: self.selectRelativeResidue(1, True), lambda: self.selectLink(1, True), lambda: self.selectRelativeResidue(2, True), lambda: self.selectLink(2, True), lambda: self.selectRelativeResidue(3, True), lambda: self.selectLink(3, True), lambda: self.selectRelativeResidue(4, True), lambda: self.selectLink(4, True), lambda: self.selectRelativeResidue(5, True) ] self.sequenceButtons = ButtonList(resultsFirstFrame, commands=commands, texts=texts) self.sequenceButtons.grid(row=0, column=0, sticky='nsew') for n, button in enumerate(self.sequenceButtons.buttons): if n % 2: button.grid(column=n, sticky='ns') self.sequenceButtons.grid_columnconfigure(n, weight=0) else: self.sequenceButtons.grid_columnconfigure(n, uniform=2) spacer = Spacer(resultsFirstFrame) spacer.grid(row=1, column=0, sticky='nsew') texts = [ ' res 1 ', ' links ', ' res 2 ', ' links ', ' res 3 ', ' links ', ' res 4 ', ' links ', ' res 5 ' ] commands = commands = [ lambda: self.selectRelativeResidue(1, False), lambda: self.selectLink(1, False), lambda: self.selectRelativeResidue(2, False), lambda: self.selectLink(2, False), lambda: self.selectRelativeResidue(3, False), lambda: self.selectLink(3, False), lambda: self.selectRelativeResidue(4, False), lambda: self.selectLink(4, False), lambda: self.selectRelativeResidue(5, False) ] self.sequenceButtonsB = ButtonList(resultsFirstFrame, commands=commands, texts=texts) self.sequenceButtonsB.grid(row=2, column=0, sticky='nsew') for n, button in enumerate(self.sequenceButtonsB.buttons): if n % 2: button.grid(column=n, sticky='ns') self.sequenceButtonsB.grid_columnconfigure(n, weight=0) else: self.sequenceButtonsB.grid_columnconfigure(n, uniform=2) frame.grid_rowconfigure(3, weight=2) resultsThirdFrame = Frame(frame) resultsThirdFrame.grid(row=3, column=0, sticky='nsew') resultsThirdFrame.grid_rowconfigure(0, weight=1) resultsThirdFrame.grid_columnconfigure(0, weight=1) tabbedFrameB = TabbedFrame(resultsThirdFrame, options=['Peaks', 'Spin System'], callback=self.toggleTab, grid=(0, 0)) #self.tabbedFrameB = tabbedFrame PeakFrame, SpinSystemFrame = tabbedFrameB.frames SpinSystemFrame.grid_rowconfigure(0, weight=1) PeakFrame.grid_rowconfigure(1, weight=1) SpinSystemFrame.grid_columnconfigure(0, weight=1) PeakFrame.grid_columnconfigure(0, weight=1) headingList = [ 'residue', 'assigned to in project', 'user defined sequence', 'selected annealing result', '%' ] tipTexts = [None, None, None, None, None] editWidgets = [None, None, None, None, None] editGetCallbacks = [None, None, None, None, None] editSetCallbacks = [None, None, None, None, None] self.spinSysTable = ScrolledMatrix(SpinSystemFrame, headingList=headingList, editWidgets=editWidgets, multiSelect=False, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks, tipTexts=tipTexts) self.spinSysTable.grid(row=0, column=0, sticky='nsew') buttonFrameinPeakFrame = Frame(PeakFrame) buttonFrameinPeakFrame.grid(sticky='ew') self.findButton = Button( buttonFrameinPeakFrame, text=' Go to Peak ', borderwidth=1, padx=2, pady=1, command=self.findPeak, tipText='Locate the currently selected peak in the specified window' ) self.findButton.grid(row=0, column=0, sticky='e') label = Label(buttonFrameinPeakFrame, text='in window:') label.grid(row=0, column=1, sticky='w') self.windowPulldown = PulldownList( buttonFrameinPeakFrame, callback=self.selectWindowPane, tipText='Choose the spectrum window for locating peaks or strips') self.windowPulldown.grid(row=0, column=2, sticky='w') self.assignSelectedPeaksButton = Button( buttonFrameinPeakFrame, text='Assign Resonances to Peak(s)', borderwidth=1, padx=2, pady=1, command=self.assignSelectedPeaks, tipText= 'Assign resonances to peak dimensions, this of course only works when the peak is found in the spectrum.' ) self.assignSelectedPeaksButton.grid(row=0, column=3, sticky='ew') self.assignSelectedSpinSystemsToResiduesButton = Button( buttonFrameinPeakFrame, text='Assign Spinsystems to Residues', borderwidth=1, padx=2, pady=1, command=self.assignSelectedSpinSystemsToResidues, tipText='Assign spinsystems to residues') self.assignSelectedSpinSystemsToResiduesButton.grid(row=0, column=4, sticky='ew') headingList = [ '#', 'spectrum', 'Dim1', 'Dim2', 'Dim3', 'c.s. dim1', 'c.s. dim2', 'c.s. dim3', 'colabelling' ] tipTexts = [ 'Peak number, only present when the peak was actually found in the spectrum.', 'Name of the spectrum', 'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type', 'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type', 'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type', 'Chemical Shift', 'Chemical Shift', 'Chemical Shift', 'Colabbeling fraction over all nuclei that are on the magnetization transfer pathway during the experiment that gave rise to the peak, including visited nuclei that were not measured in any of the peak dimensions' ] #editWidgets = [None, None, None, None, None, None, None, None, None] editGetCallbacks = [ None, None, None, None, None, None, None, None, None ] #editGetCallbacks = [self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak] editSetCallbacks = [ None, None, None, None, None, None, None, None, None ] self.displayPeakTable = ScrolledMatrix(PeakFrame, headingList=headingList, multiSelect=True, tipTexts=tipTexts) #editWidgets=editWidgets, multiSelect=True, # editGetCallbacks=editGetCallbacks, # editSetCallbacks=editSetCallbacks, # tipTexts=tipTexts) self.displayPeakTable.grid(row=1, column=0, sticky='nsew') self.windowPane = None self.updateWindows()
def body(self, mainFrame): mainFrame.grid_columnconfigure(1, weight=1, minsize=100) mainFrame.config(borderwidth=5, relief='solid') row = 0 label = Label(mainFrame, text="Frame (with sub-widgets):") label.grid(row=row, column=0, sticky=Tkinter.E) frame = Frame(mainFrame, relief='raised', border=2, background='#8080D0') # Frame expands East-West frame.grid(row=row, column=1, sticky=Tkinter.EW) # Last column expands => Widgets pusted to the West frame.grid_columnconfigure(3, weight=1) # Label is within the sub frame label = Label(frame, text='label ') label.grid(row=0, column=0, sticky=Tkinter.W) entry = Entry(frame, text='Entry', returnCallback=self.showWarning) entry.grid(row=0, column=1, sticky=Tkinter.W) self.check = CheckButton(frame, text='Checkbutton', selected=True, callback=self.updateObjects) self.check.grid(row=0, column=2, sticky=Tkinter.W) # stick a button to the East wall button = Button(frame, text='Button', command=self.pressButton) button.grid(row=0, column=3, sticky=Tkinter.E) row += 1 label = Label(mainFrame, text="Text:") label.grid(row=row, column=0, sticky=Tkinter.E) self.textWindow = Text(mainFrame, text='Initial Text\n', width=60, height=5) self.textWindow.grid(row=row, column=1, sticky=Tkinter.NSEW) row += 1 label = Label(mainFrame, text="CheckButtons:") label.grid(row=row, column=0, sticky=Tkinter.E) entries = ['Alpha','Beta','Gamma','Delta'] selected = entries[2:] self.checkButtons = CheckButtons(mainFrame, entries, selected=selected,select_callback=self.changedCheckButtons) self.checkButtons.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="PartitionedSelector:") label.grid(row=row, column=0, sticky=Tkinter.E) labels = ['Bool','Int','Float','String'] objects = [type(0),type(1),type(1.0),type('a')] selected = [type('a')] self.partitionedSelector= PartitionedSelector(mainFrame, labels=labels, objects=objects, colors = ['red','yellow','green','#000080'], callback=self.toggleSelector,selected=selected) self.partitionedSelector.grid(row=row, column=1, sticky=Tkinter.EW) row += 1 label = Label(mainFrame, text="PulldownMenu") label.grid(row=row, column=0, sticky=Tkinter.E) entries = ['Frodo','Pipin','Merry','Sam','Bill','Gandalf','Strider','Gimli','Legolas'] self.pulldownMenu = PulldownMenu(mainFrame, callback=self.selectPulldown, entries=entries, selected_index=2, do_initial_callback=False) self.pulldownMenu.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="RadioButtons in a\nScrolledFrame.frame:") label.grid(row=row, column=0, sticky=Tkinter.EW) frame = ScrolledFrame(mainFrame, yscroll = False, doExtraConfig = True, width=100) frame.grid(row=row, column=1, sticky=Tkinter.EW) frame.grid_columnconfigure(0, weight=1) self.radioButtons = RadioButtons(frame.frame, entries=entries, select_callback=self.checkRadioButtons, selected_index=1, relief='groove') self.radioButtons.grid(row=0, column=0, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="LabelFrame with\nToggleLabels inside:") label.grid(row=row, column=0, sticky=Tkinter.E) labelFrame = LabelFrame(mainFrame, text='Frame Title') labelFrame.grid(row=row, column=1, sticky=Tkinter.NSEW) labelFrame.grid_rowconfigure(0, weight=1) labelFrame.grid_columnconfigure(3, weight=1) self.toggleLabel1 = ToggleLabel(labelFrame, text='ScrolledMatrix', callback=self.toggleFrame1) self.toggleLabel1.grid(row=0, column=0, sticky=Tkinter.W) self.toggleLabel1.arrowOn() self.toggleLabel2 = ToggleLabel(labelFrame, text='ScrolledGraph', callback=self.toggleFrame2) self.toggleLabel2.grid(row=0, column=1, sticky=Tkinter.W) self.toggleLabel3 = ToggleLabel(labelFrame, text='ScrolledCanvas', callback=self.toggleFrame3) self.toggleLabel3.grid(row=0, column=2, sticky=Tkinter.W) row += 1 mainFrame.grid_rowconfigure(row, weight=1) label = Label(mainFrame, text="changing/shrinking frames:") label.grid(row=row, column=0, sticky=Tkinter.E) self.toggleRow = row self.toggleFrame = Frame(mainFrame) self.toggleFrame.grid(row=row, column=1, sticky=Tkinter.NSEW) self.toggleFrame.grid_rowconfigure(0, weight=1) self.toggleFrame.grid_columnconfigure(0, weight=1) # option 1 self.intEntry = IntEntry(self, returnCallback = self.setNumber, width=8) self.multiWidget = MultiWidget(self, Entry, options=None, values=None, callback=self.setKeywords, minRows=3, maxRows=5) editWidgets = [None, None, self.intEntry, self.multiWidget] editGetCallbacks = [None, None, self.getNumber, self.getKeywords] editSetCallbacks = [None, None, self.setNumber, self.setKeywords] headingList = ['Name','Color','Number','Keywords'] self.scrolledMatrix = ScrolledMatrix(self.toggleFrame, headingList=headingList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, callback=self.selectObject, multiSelect=False) self.scrolledMatrix.grid(row=0, column=0, sticky=Tkinter.NSEW) # option 2 self.scrolledGraph = ScrolledGraph(self.toggleFrame, width=400, height=300, symbolSize=5, symbols=['square','circle'], dataColors=['#000080','#800000'], lineWidths=[0,1] ) self.scrolledGraph.setZoom(1.3) dataSet1 = [[0,0],[1,1],[2,4],[3,9],[4,16],[5,25]] dataSet2 = [[0,0],[1,3],[2,6],[3,9],[4,12],[5,15]] self.scrolledGraph.update(dataSets=[dataSet1,dataSet2], xLabel = 'X axis label', yLabel = 'Y axis label', title = 'Main Title') self.scrolledGraph.draw() # option 3 self.scrolledCanvas = ScrolledCanvas(self.toggleFrame,relief = 'groove', borderwidth = 2, resizeCallback=None) canvas = self.scrolledCanvas.canvas font = 'Helvetica 10' box = canvas.create_rectangle(10,10,150,200, outline='grey', fill='grey90') line = canvas.create_line(0,0,200,200,fill='#800000', width=2) text = canvas.create_text(120,50, text='Text', font=font, fill='black') circle = canvas.create_oval(30,30,50,50,outline='#008000',fill='#404040',width=3) row += 1 label = Label(mainFrame, text="FloatEntry:") label.grid(row=row, column=0, sticky=Tkinter.E) self.floatEntry = FloatEntry(mainFrame, text=3.14159265, returnCallback=self.floatEntryReturn) self.floatEntry.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="Scale:") label.grid(row=row, column=0, sticky=Tkinter.E) self.scale = Scale(mainFrame, from_=10, to=90, value=50, orient=Tkinter.HORIZONTAL) self.scale.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="Value Ramp:") label.grid(row=row, column=0, sticky=Tkinter.E) self.valueRamp = ValueRamp(mainFrame, self.valueRampCallback, speed = 1.5, delay = 50) self.valueRamp.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="ButtonList:") label.grid(row=row, column=0, sticky=Tkinter.E) texts = ['Select File','Close','Quit'] commands = [self.selectFile, self.close, self.quit] bottomButtons = ButtonList(mainFrame, texts=texts, commands=commands, expands=True) bottomButtons.grid(row=row, column=1, sticky=Tkinter.EW) self.protocol('WM_DELETE_WINDOW', self.quit)
def body(self, guiFrame): guiFrame.grid_columnconfigure(0, weight=1) row = 0 frame = Frame(guiFrame) frame.grid(row=row, column=0, sticky='nsew') frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Shift List:') label.grid(row=0, column=0, sticky='w') self.shiftListPulldown = PulldownMenu(frame, callback=self.setShiftList) self.shiftListPulldown.grid(row=0, column=1, sticky='w') label = Label(frame, text='Sequential Link Type:') label.grid(row=0, column=2, sticky='w') entries = ['-1', '-1,+1', '+1'] self.linkPulldown = PulldownMenu(frame, callback=self.setLink, entries=entries, do_initial_callback=False, selected_index=entries.index( self.link)) self.linkPulldown.grid(row=0, column=3, sticky='w') row += 1 frame = LabelFrame(guiFrame, text='Link Atoms:') frame.grid(row=row, column=0, sticky='nsew') frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(0, weight=1) labels = ['C', 'CA', 'CB', 'CG', 'CD', 'H', 'HA', 'HB', 'HG', 'HD'] selected = ['CA', 'CB'] self.atomSelector = PartitionedSelector(frame, objects=labels, labels=labels, selected=selected, toggledBg='#808080', callback=self.changeAtoms, maxRowObjects=10) self.atomSelector.grid(row=0, column=0, sticky='ew') row += 1 guiFrame.grid_rowconfigure(row, weight=1) frame = LabelFrame(guiFrame, text='Predicted Residue Assignments') frame.grid(row=row, column=0, sticky='nsew') frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(0, weight=1) headingList = [ '#', 'Predicted\nResidue', 'Prob.', 'Links', 'CA', 'CA -1', 'CB', 'CB -1' ] self.spinSystemMatrix = ScrolledMatrix(frame, headingList=headingList, callback=self.selectSpinSystem, multiSelect=1) self.spinSystemMatrix.grid(row=0, column=0, sticky='nsew') row += 1 texts = ['Link Selected', 'Link All', 'Commit Assignment'] commands = [ self.linkSelectedSpinSystems, self.linkAllSpinSystems, self.commitAssignments ] buttonList = UtilityButtonList(guiFrame, texts=texts, commands=commands, helpUrl=self.help_url) buttonList.grid(row=row, column=0, sticky='ew') self.buttons = buttonList.buttons for func in ('__init__', 'delete'): for clazz in ('ccp.nmr.Nmr.ShiftList', ): self.registerNotify(self.updateShiftLists, clazz, func) for func in ('__init__', 'delete', 'setNmrChains', 'setResidue', 'setResonances', 'addResonance', 'removeResonance'): self.registerNotify(self.updateSpinSystemsAfter, 'ccp.nmr.Nmr.ResonanceGroup', func) self.updateShiftLists()
def __init__(self, parent, *args, **kw): apply(Frame.__init__, (self, parent) + args, kw) self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(1, weight=0) self.grid_rowconfigure(2, weight=0) self.grid_rowconfigure(3, weight=0) self.canvas = Canvas(self, relief='sunken', borderwidth=2, width=150) self.canvas.grid(row=0, column=1, columnspan=1, sticky=Tkinter.NSEW, pady=2, padx=2) frame = Frame(self) frame.grid_columnconfigure(1, weight=1) self.boxSize = 100 self.numPixels = 10 self.pixelWidth = round(self.boxSize / self.numPixels) self.colorBox = Canvas(frame, relief='sunken', borderwidth=2, width=self.boxSize + 2, height=self.boxSize + 2) self.colorBox.bind('<Button-1>', self.pickInColorBox) self.colorBox.bind('<Button-2>', self.pickInColorBox) self.colorBox.bind('<Button-3>', self.pickInColorBox) self.colorBox.grid(row=0, column=2, rowspan=3, sticky=Tkinter.NSEW, padx=4, pady=4) self.pixel = [] self.colors = [] self.setupColorBox() self.scale = Tkinter.Scale(frame, orient=Tkinter.VERTICAL, length=self.boxSize, from_=0, to=99, label='', showvalue=0, command=self.refreshColorBox) self.scale.grid(row=0, column=3, rowspan=3, sticky=Tkinter.NS, padx=4, pady=4) frame.grid(row=1, column=0, columnspan=2, sticky=Tkinter.NSEW) labels = ('Red', 'Green', 'Blue') self.labeled_scale = 3 * [None] for n in range(3): label = Label(frame, text=labels[n] + ':', anchor=Tkinter.W) label.grid(row=n, column=0, sticky=Tkinter.EW) self.labeled_scale[n] = LabeledScale( frame, values=range(101), label_format='%3d', set_callback=self.scaleCallback) self.labeled_scale[n].grid(row=n, column=1, sticky=Tkinter.EW)
def body(self, guiFrame): self.geometry('550x600') guiFrame.grid_columnconfigure(0, weight=1) row = 0 frame = Frame(guiFrame, grid=(row, 0)) frame.expandGrid(0, 4) label = Label(frame, text='Peak List:', grid=(0, 0)) tipText = 'For spectra with (mostly) one peak per residue, selects which peak list to initialise; by adding anonymous resonance and spin system numbers' self.peakListPulldown = PulldownList(frame, self.changePeakList, grid=(0, 1), tipText=tipText) label = Label(frame, text='15N tolerance (ppm):', grid=(0, 2)) tipText = 'The upper limit in the difference between 15N ppm positions for two peaks to be considered as a potential amide' self.tolEntry = FloatEntry(frame, text=0.02, width=8, grid=(0, 3), sticky='ew', tipText=tipText) frame2 = Frame(frame, grid=(1, 0), gridSpan=(1, 4), sticky='ew') frame2.grid_columnconfigure(5, weight=1) label = Label(frame2, text='Follow Amides:', grid=(0, 0)) tipText = 'Sets whether to follow the H-N locations of potential amide peaks when clicking in rows of the table' self.followSelect = CheckButton(frame2, callback=None, grid=(0, 1), selected=True, tipText=tipText) self.windowLabel = Label(frame2, text='Window:', grid=(0, 2)) tipText = 'Selects the spectrum window in which to show positions of potential amide peaks' self.windowPulldown = PulldownList(frame2, self.selectWindowPane, grid=(0, 3), tipText=tipText) label = Label(frame2, text='Mark Amides:', grid=(0, 4)) tipText = 'Whether to put a multi-dimensional cross mark though the H-N positions of the selected peak pair' self.markSelect = CheckButton(frame2, callback=None, grid=(0, 5), selected=True, tipText=tipText) utilButtons = UtilityButtonList(guiFrame, grid=(row, 1), sticky='ne', helpUrl=self.help_url) row += 1 tipTexts = [ 'For the stated peak list, considering confirmed amide side chain peaks, add spin system and resonance numbers to all peaks', ] commands = [ self.initialisePeakList, ] texts = [ 'Initialise Peak List!', ] self.initButtons = ButtonList(guiFrame, commands=commands, grid=(row, 0), texts=texts, gridSpan=(1, 2), tipTexts=tipTexts) self.initButtons.buttons[0].config(bg='#B0FFB0') row += 1 div = LabelDivider(guiFrame, text='Amide Side Chain Peaks', gridSpan=(1, 2), grid=(row, 0)) row += 1 guiFrame.grid_rowconfigure(row, weight=1) frame = Frame(guiFrame, gridSpan=(1, 2), grid=(row, 0)) frame.expandGrid(0, 0) editSetCallbacks = [None] * 8 editGetCallbacks = [None] * 8 editWidgets = [None] * 8 editGetCallbacks[1] = self.toggleConfirm #self.userCodeEntry = Entry(self,text='', returnCallback=self.setResidueCode, width=6) tipTexts = [ 'Number of the peak pair for the table', 'Whether the peak pair is confirmed as being from an amide side chain; a common nitrogen by different hydrogens', 'The difference in 15N ppm position between the two peaks of the pair', 'The assignment annotation of the first peak in the pair', 'The assignment annotation of the second peak in the pair', 'The average 15N position of the peaks in the pair', 'The 1H chemical shift of the first peak in the pair', 'The 1H chemical shift of the second peak in the pair' ] headingList = [ '#', 'Confirmed?', u'15N\n\u0394ppm', 'Peak 1', 'Peak 2', 'Shift N', 'Shift H1', 'Shift H2' ] self.amidePairMatrix = ScrolledMatrix( frame, headingList=headingList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, callback=self.selectAmidePair, multiSelect=True, grid=(0, 0), tipTexts=tipTexts) tipTexts = [ 'Confirm the selected peak pairs as being amide side chain peaks; a common nitrogen by different hydrogens', 'remove any conformation for the selected peak pairs being amide side chain peaks', 'Manually force an update the table of potential pairs of amide side chain peaks' ] commands = [ self.confirmAmidePairs, self.unconfirmAmidePairs, self.predictAmidePairs ] texts = ['Confirm\nSelected', 'Unconfirm\nSelected', 'Update\nTable'] self.amideButtons = ButtonList(frame, texts=texts, commands=commands, grid=(1, 0), tipTexts=tipTexts) self.updatePeakLists() self.administerNotifiers(self.registerNotify)
class MultiWidget(Frame): def __init__(self, parent, widgetClass, options=None, values=None, callback=None, minRows=3, maxRows=None, useImages=True, *args, **kw): Frame.__init__(self, parent, **kw) if not values: values = [] if not options: options = [] # Widget types currently: Entries, Pulldown, Checkbutton if useImages: gfxDir = path.join(getTopDirectory(), 'python', 'memops', 'gui', 'graphics') self.crossImage = Tkinter.PhotoImage( file=path.join(gfxDir, 'cross.gif')) self.tickImage = Tkinter.PhotoImage( file=path.join(gfxDir, 'tick.gif')) self.plusImage = Tkinter.PhotoImage( file=path.join(gfxDir, 'plus.gif')) self.minusImage = Tkinter.PhotoImage( file=path.join(gfxDir, 'minus.gif')) else: self.crossImage = None self.tickImage = None self.plusImage = None self.minusImage = None module = widgetClass.__module__ self.widgetType = module.split('.')[-1] self.widgetClass = widgetClass self.callback = callback self.numRows = 0 self.values = values self.options = options self.minRows = minRows self.maxRows = maxRows self.widgets = [] self.labels = [] self.grid_columnconfigure(1, weight=1) self.topFrame = Frame(self) self.topFrame.grid(row=0, column=0, columnspan=4, sticky=Tkinter.NSEW) self.topFrame.grid_columnconfigure(1, weight=1) self.topFrame.grid_rowconfigure(0, weight=1) self.addButton = None self.removeButton = None self.commitButton = None self.cancelButton = None self.set(self.values, self.options) self.updateButtons() self.bind('<KeyPress-Return>', self.commit) self.bind('<KeyPress-Escape>', self.cancel) def get(self): values = [] if self.widgetType == 'PulldownMenu': for i in range(self.numRows): value = self.widgets[i].getSelected() if value is not None: values.append(value) elif self.widgetType == 'PulldownList': for i in range(self.numRows): value = self.widgets[i].getObject() if value is not None: values.append(value) else: for i in range(self.numRows): value = self.widgets[i].get() if (value is not None) and (value != ''): values.append(value) return values def set(self, values=None, options=None): if values is not None: self.values = values if options is not None: self.options = options N = max(len(self.values), self.minRows) if self.maxRows is not None: N = min(N, self.maxRows) #N = max( min(len(self.values), self.maxRows), self.minRows) #N = len(self.values) if self.numRows < N: for i in range(self.numRows, N): self.addRow() elif self.numRows > N: for i in range(N, self.numRows): self.removeRow(doClear=1) for i in range(self.numRows): if i < len(self.values): value = self.values[i] else: value = None if i < len(self.options): option = self.options[i] else: option = None self.updateWidget(i, value, option) def setOptions(self, options): self.set(self.values, options) def setValues(self, values): self.set(values, self.options) def updateWidget(self, row, value, option): if self.labels: font = self.labels[0].cget('font') else: font = None widget = self.widgets[row] if self.widgetType in ('Entry', 'IntEntry', 'FloatEntry'): widget.set(value) label = self.labels[row] label.set(option or '') if font: label.config(font=font) elif self.widgetType == 'PulldownMenu': index = -1 if value in self.options: index = self.options.index(value or self.options[0]) widget.setup(self.options, index) elif self.widgetType == 'PulldownList': index = 0 if value in self.options: index = self.options.index(value or self.options[0]) widget.setup(self.options, self.options, index) elif self.widgetType == 'CheckButton': widget.set(value) label = self.labels[row] label.set(option or '') if font: label.config(font=font) else: raise 'Widget type %s not supported in MultiWidget' % self.widgetType def updateButtons(self): row = 1 col = 0 if self.widgetType != 'CheckButton': if (self.maxRows is None) or (self.numRows < self.maxRows): if not self.addButton: if self.plusImage: self.addButton = Button(self, image=self.plusImage, command=self.addRow, borderwidth=1) else: self.addButton = Button(self, text='+', command=self.addRow, borderwidth=1, bg=blueColor) self.addButton.grid(row=row, column=col, sticky=Tkinter.EW) col += 1 elif self.addButton: self.addButton.grid_forget() if self.numRows > self.minRows: if not self.removeButton: if self.minusImage: self.removeButton = Button(self, image=self.minusImage, command=self.removeRow, borderwidth=1) else: self.removeButton = Button(self, text='-', command=self.removeRow, borderwidth=1, bg=blueColor) self.removeButton.grid(row=row, column=col, sticky=Tkinter.EW) col += 1 elif self.removeButton: self.removeButton.grid_forget() if self.callback: if not self.commitButton: if self.tickImage: self.commitButton = Button(self, image=self.tickImage, command=self.commit, borderwidth=1) else: self.commitButton = Button(self, text='OK', command=self.commit, borderwidth=1, bg=blueColor) self.commitButton.grid(row=row, column=col, sticky=Tkinter.EW) self.grid_columnconfigure(col, weight=1) col += 1 if not self.cancelButton: if self.crossImage: self.cancelButton = Button(self, image=self.crossImage, command=self.cancel, borderwidth=1) else: self.cancelButton = Button(self, text='Cancel', command=self.cancel, borderwidth=1, bg=blueColor) self.cancelButton.grid(row=row, column=col, sticky=Tkinter.EW) self.grid_columnconfigure(col, weight=1) def addWidget(self, row, value=None): if self.widgetType in ('Entry', 'IntEntry', 'FloatEntry'): option = '' if row < len(self.options): option = self.options[row] label = Label(self.topFrame, text=option or '', anchor='w') label.grid(row=row, column=0, sticky=Tkinter.E) self.labels.append(label) widget = self.widgetClass(self.topFrame, text=value, width=12) widget.grid(row=row, column=1, sticky=Tkinter.EW) widget.bind('<KeyPress-Return>', self.commit) widget.bind('<KeyPress-Escape>', self.cancel) elif self.widgetType == 'PulldownList': index = -1 if value in self.options: index = self.options.index(value or self.options[0]) widget = self.widgetClass(self.topFrame) widget.setup(self.options, self.options, index) widget.grid(row=row, column=0, columnspan=2, sticky=Tkinter.W) elif self.widgetType == 'PulldownMenu': index = -1 if value in self.options: index = self.options.index(value or self.options[0]) widget = self.widgetClass(self.topFrame) widget.setup(self.options, index) widget.grid(row=row, column=0, columnspan=2, sticky=Tkinter.W) elif self.widgetType == 'CheckButton': widget = self.widgetClass(self.topFrame) widget.set(value) widget.grid(row=row, column=0, sticky=Tkinter.W) option = '' if row < len(self.options): option = self.options[row] label = Label(self.topFrame, text=option or '', anchor='w') label.grid(row=row, column=1, sticky=Tkinter.W) self.labels.append(label) else: raise 'Widget type %s not supported in MultiWidget' % self.widgetType return widget def commit(self, event=None): values = self.get() if self.callback: self.callback(values) def cancel(self, event=None): if self.callback: self.callback(None) def addRow(self): if (self.maxRows is None) or (self.numRows < self.maxRows): row = self.numRows self.numRows += 1 if self.numRows > len(self.widgets): widget = self.addWidget(row) self.widgets.append(widget) else: widget = self.widgets[row] if self.widgetType in ('Entry', 'IntEntry', 'FloatEntry'): label = self.labels[row] label.grid(row=row, column=0, sticky=Tkinter.E) widget.grid(row=row, column=1, sticky=Tkinter.EW) elif self.widgetType == 'CheckButton': widget.grid(row=row, column=0, sticky=Tkinter.W) label = self.labels[row] label.grid(row=row, column=1, sticky=Tkinter.W) else: widget.grid(row=row, column=0, columnspan=2, sticky=Tkinter.W) if row == 0: self.topFrame.grid(row=0, column=0, columnspan=4, sticky=Tkinter.NSEW) self.updateButtons() def removeRow(self, doClear=0): if self.numRows > self.minRows: self.numRows -= 1 row = self.numRows widget = self.widgets[row] widget.grid_forget() if self.widgetType == 'CheckButton': label = self.labels[row] label.grid_forget() elif self.widgetType in ('Entry', 'IntEntry', 'FloatEntry'): label = self.labels[row] label.grid_forget() if doClear: self.updateWidget(row, None, '') if self.numRows == 0: self.topFrame.grid_forget() self.updateButtons()
def setEntries(self, entries, docKeys=None, tipTexts=None): if entries == self.entries: return nentries = len(entries) if not docKeys: docKeys = [None] * nentries if not tipTexts: tipTexts = [None] * nentries if self.entries: for b in self.buttons: b.destroy() self.entries = entries self.buttons = nentries * [None] self.frames = nentries * [None] for n, entry in enumerate(entries): frame = Frame(self, borderwidth=self.borderwidth) entryText = entry m = self.min_text_width - len(entryText) if m > 0: entryText = entryText + m * ' ' bgColor = self.cget('bg') callback = lambda entry=entry, callback=self.selectCallback: callback( entry) button = RadioButton(frame, bg=bgColor, text=entryText, callback=callback, highlightbackground=bgColor, highlightcolor=bgColor, activebackground='#D0B0A0', activeforeground='white', variable=self.var, font=self.font, value=n, docKey=docKeys[n], tipText=tipTexts[n]) if self.selectcolor: button.config(selectcolor=self.selectcolor) if self.direction == Tkinter.HORIZONTAL: frame.grid(row=0, pady=0, column=n, sticky=Tkinter.NSEW, padx=self.padding) self.grid_columnconfigure(n, weight=1) else: frame.grid(row=n, padx=0, sticky=Tkinter.NSEW, pady=self.padding) self.grid_rowconfigure(n, weight=1) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) button.grid(sticky='nw') self.buttons[n] = button self.frames[n] = frame self.setOptions()
class ScrolledFrame(Frame): def __init__(self, parent, xscroll=True, yscroll=True, width=500, height=500, doExtraConfig=True, tipText=None, *args, **kw): Frame.__init__(self, parent, *args, **kw) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) self.doExtraConfig = doExtraConfig self.xscroll = xscroll self.yscroll = yscroll self.canvas = Tkinter.Canvas(self, borderwidth=0, bg=self.cget('bg'), highlightthickness=0, width=25, height=25) self.canvas.grid(row=0, column=0, sticky=Tkinter.NSEW) if (xscroll): self.xscrollbar = Tkinter.Scrollbar(self, orient=Tkinter.HORIZONTAL, borderwidth=1) self.xscrollbar.config(command=self.canvas.xview) self.canvas.config(xscrollcommand=self.xscrollbar.set) if (yscroll): self.yscrollbar = Tkinter.Scrollbar(self, orient=Tkinter.VERTICAL, borderwidth=1) self.yscrollbar.config(command=self.canvas.yview) self.canvas.config(yscrollcommand=self.yscrollbar.set) # reset the view (always do this if you don't use scrollbars) self.canvas.xview('moveto', 0) self.canvas.yview('moveto', 0) # create the frame self.frame = Frame(self.canvas, tipText=tipText) self.frame.grid(row=0, column=0, sticky=Tkinter.NSEW) self.frame.grid_rowconfigure(0, weight=1) self.frame.grid_columnconfigure(0, weight=1) self.waiting = 0 # track changes to its size self.bind('<Configure>', self.configureCanvasAfter) # track changes to its contents self.frame.bind('<Configure>', self.configureFrame) # place the frame inside the canvas (this also # runs the __configure method) self.canvas.create_window(0, 0, window=self.frame, anchor='nw') #self.frameWidth = self.frame.winfo_reqwidth() #self.frameHeight = self.frame.winfo_reqheight() self.frameWidth = 0 self.frameHeight = 0 def configureFrame(self, event): # frame contents have changed size, but make no change to displayed canvas size if (event.width != self.frameWidth) or (event.height != self.frameHeight): # the size of the frame with widgets in the 'background' self.frameWidth = event.width self.frameHeight = event.height # the scrolled region is always the entire frame self.canvas.config(scrollregion="0 0 %s %s" % (self.frameWidth, self.frameHeight)) self.configureCanvasAfter() def configureCanvasAfter(self, event=None): if self.waiting: return else: self.waiting = 1 self.after_idle(lambda: self.configureCanvas(event)) def configureCanvas(self, event=None): d = 2 * int(self.cget('borderwidth')) if (event): # the canvas visible display size updates with the rezize event unless the axis is not scrolled canvasWidth = event.width - d canvasHeight = event.height - d else: # if no resize event the canvas size is unaltered canvasWidth = int(self.winfo_width()) - d canvasHeight = int(self.winfo_height()) - d if self.xscroll: if (self.frameWidth > 1): if (self.frameWidth > canvasWidth): self.xscrollbar.grid(row=1, column=0, sticky=Tkinter.EW) else: self.xscrollbar.grid_forget() else: self.xscrollbar.grid(row=1, column=0, sticky=Tkinter.EW) else: # display full width canvasWidth = self.frameWidth if self.yscroll: if (self.frameHeight > 1): if (self.frameHeight > canvasHeight): self.yscrollbar.grid(row=0, column=1, sticky=Tkinter.NS) else: self.yscrollbar.grid_forget() else: self.yscrollbar.grid(row=0, column=1, sticky=Tkinter.NS) else: # display full height canvasHeight = self.frameHeight if (self.doExtraConfig): # sometimes below seems to be needed and sometimes not # seems to depend on what else is there in widget besides scrolled frame # can sometimes wildly iterate if below is done self.canvas.config(width=canvasWidth, height=canvasHeight) self.waiting = 0
def setEntries(self, entries): if (entries == self.entries): return if (self.entries): for b in self.buttons: b.destroy() self.entries = entries self.buttons = len(entries) * [0] self.frames = len(entries) * [0] for n in range(len(entries)): frame = Frame(self, borderwidth=self.borderwidth) entry = entries[n] entryText = entry m = self.min_text_width - len(entryText) if m > 0: entryText = entryText + m * ' ' bgColor = self.cget('bg') button = Tkinter.Radiobutton(frame, bg=bgColor, text=entryText, highlightbackground=bgColor, highlightcolor=bgColor, variable=self.var, font=self.font, value=n) command = lambda entry=entry, callback=self.selectCallback: callback( entry) button.config(command=command) if (self.selectcolor): button.config(selectcolor=self.selectcolor) if (self.direction == Tkinter.HORIZONTAL): frame.grid(row=0, pady=0, column=n, sticky=Tkinter.NSEW, padx=self.padding) self.grid_columnconfigure(n, weight=1) else: frame.grid(row=n, padx=0, sticky=Tkinter.NSEW, pady=self.padding) self.grid_rowconfigure(n, weight=1) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) button.grid(sticky='nw') self.buttons[n] = button self.frames[n] = frame self.setOptions()