def body(self, guiParent): self.geometry('900x750') # Ensure that the first row and column in popup expand guiParent.expandGrid(0,0) self.eciFrame = EntryCompletionFrame(guiParent, basePopup=self, grid=(0,0)) # Add help, close buttons #buttonList = UtilityButtonList(self.eciFrame.tabbedFrame.sideFrame, # grid=(0,0), sticky='e') # 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.ccpNmrMenu = self.makeCcpNmrMenu() self.otherMenu = self.makeOtherMenu() # Put the main menu self.config(menu=self.mainMenu) self.initProject()
def body(self, guiParent): # Ensure that the first row and column in popup expand guiParent.grid_rowconfigure(0, weight=1) guiParent.grid_columnconfigure(0, weight=1, minsize=200) frame = Frame(guiParent) # Body widgets can be put in this frame frame.grid() buttons = createDismissHelpButtonList(frame, dismiss_text='Quit', dismiss_cmd=self.quit, help_url=self.help_url, expands=1) buttons.grid(row=0, column=0, sticky=Tkinter.NSEW) self.helpButton = buttons.buttons[-1] self.helpButtonCommand = self.helpButton.buttonCommand # the command with no project # 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.otherMenu = self.makeOtherMenu() # Put the main menu self.config(menu=self.mainMenu) self.initProject()
def __init__(self, parent, resizeCallback = None, width=600, height=600, *args, **kw): self.bbox = None self.busy = 0 self.initialX = None self.initialY = None self.resizeCallback = resizeCallback apply(Frame.__init__, (self, parent) + args, kw) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) self.menu = Menu(self, tearoff=0, include_event=True) self.configMenu() self.canvas = Canvas(self, relief='flat', borderwidth=0, width=width, height=height) self.canvas.configure(xscrollincrement=2, yscrollincrement=2) self.canvas.grid(row = 0, column = 0, sticky = Tkinter.NSEW ) self.horizScrollbar = Tkinter.Scrollbar(self, bg=self.cget('bg'), command=self.canvas.xview, orient=Tkinter.HORIZONTAL, borderwidth=1) self.vertScrollbar = Tkinter.Scrollbar(self, bg=self.cget('bg'), command=self.canvas.yview, orient=Tkinter.VERTICAL, borderwidth=1) self.canvas.configure(xscrollcommand=self.horizScrollbar.set,yscrollcommand=self.vertScrollbar.set) self.canvas.bind('<Configure>', self.resizeAfter) self.canvas.bind('<Button-1>', self.mouseButton1) self.canvas.bind('<Button-2>', self.mouseButton2) self.canvas.bind('<Button-3>', self.mouseButton3) self.canvas.bind('<ButtonRelease-1>', self.mouseButtonRelease1) self.canvas.bind('<ButtonRelease-2>', self.mouseButtonRelease2) self.canvas.bind('<B2-Motion>', self.mouseScroll) self.canvas.bind('<B3-Motion>', self.doNothing) self.canvas.bind('<Motion>', self.mouseEnter) self.canvas.bind('<Enter>', self.mouseEnter)
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()
def __init__(self, parent, setFunc, sizes=(8,10,12,14), doBold=1, doItalic=1, doBoldItalic=0, *args, **kw): Menu.__init__(self, parent, *args, **kw) subMenus = {} for fontName in fontNames: subMenus[fontName] = Menu(self, tearoff=0) for s in sizes: spec = '%s %d' % (fontName,s) subMenus[fontName].add_command(label='%dpt' % s, font=spec, command=lambda s=spec: setFunc(s) ) if doBold: for s in sizes: spec = '%s %d bold' % (fontName,s) subMenus[fontName].add_command(label='%dpt bold' % s, font=spec, command=lambda s=spec: setFunc(s) ) if doItalic: for s in sizes: spec = '%s %d italic' % (fontName,s) subMenus[fontName].add_command(label='%dpt italic' % s, font=spec, command=lambda s=spec: setFunc(s) ) if doBoldItalic: for s in sizes: spec = '%s %d bold italic' % (fontName,s) subMenus[fontName].add_command(label='%dpt bold italic' % s, font=spec, command=lambda s=spec: setFunc(s) ) self.add_cascade(label=fontName, shortcut=fontName[0], menu=subMenus[fontName])
def body(self, guiParent): self.geometry('600x350') # Ensure that the first row and column in popup expand guiParent.expandGrid(0, 0) self.importFrame = DataFileImportFrame(guiParent, basePopup=self, grid=(0, 0)) # Dictionary to store popups opened by this application - e.g. need to close upon quit self.popups = {} # Default font self.font = DEFAULT_FONT # 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.mainMenu.add_command(label='Formats', shortcut='F', command=self.importFrame.showFormats) self.mainMenu.add_command( label='Help', shortcut='H', command=self.importFrame.showMainInstructions) # Put the main menu self.config(menu=self.mainMenu) self.setMenuState()
def viewFileMenu(self): # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call menu.add_command(label='Prediction Graph', shortcut='G', command=self.viewGraph, tipText='Show a graphical view of the poredicted backbone dihedral angles') self.mainMenu.add_cascade(label='View', shortcut='V', menu=menu) menu.options = ['Prediction Graph'] return menu
def makeOtherMenu(self): # The fonts menu is a pre-created widget fontsMenu = FontMenu(self.mainMenu, self.setFont, sizes=(8,10,12), doItalic=0, doBoldItalic=0, tearoff=0) # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Only Fonts option so far menu.add_cascade(label='Fonts', shortcut='F', menu=fontsMenu) self.mainMenu.add_cascade(label='Options', shortcut='O', menu=menu) menu.options = ['Fonts',] return menu
def __init__(self, parent, callback=None, texts=None, objects=None, categories=None, colors=None, index=0, prefix='', indent='', initCallback=False, forceCallback=False, numbering=False, arrowLine='#602000', arrowFill='#B05848', labelColor='#501000', menuBg='#F0F0FF', sticky='w', docKey=None, tipText=None, categoriesLast=True, *args, **kw): Frame.__init__(self, parent, sticky=sticky, docKey=docKey, tipText=tipText, createToolTip=True, *args, **kw) self.callback = callback self.texts = texts or [] self.objects = objects or [] self.categories = categories or [] self.colors = colors or [] self.prefix = prefix self.indent = indent self.initCallback = initCallback self.numbering = numbering self.arrowLine = arrowLine self.arrowFill = arrowFill self.labelColor = labelColor self.active = True self.categoriesLast = categoriesLast # Current selection self.index = None self.object = NullText self.rows = [] self.bg = self.cget('bg') self.label = Label(self, foreground=labelColor) self.canvas = Canvas(self, width=12, height=12, background=self.bg) self.menu = Menu(self.canvas, tearoff=False, bg=menuBg, relief='solid', borderwidth=1, activeborderwidth=1) self.menu.images = [] # Photoimage has to remain referenced self.setup(self.texts, self.objects, index, self.colors, self.categories) self.label.bind( "<Button-1>", self._labelClick) self.menu.bind( "<Leave>", self._leave) self.canvas.bind("<Button-1>", self._canvasClick) self.canvas.bind("<Configure>", self._resizeCallback) self.grid_columnconfigure(0, weight=1) self.label.grid(row=0, column=0, sticky='w') self.canvas.grid(row=0, column=1, sticky='w', padx=2)
def makeRepositoryMenu(self): self.repMenu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call self.repMenu.add_command(label='Manager', shortcut='M', command=self.tmpCall) self.repMenu.add_command(label='Connect', shortcut='C', command=self.openRepository) # doesn't really work to have a disconnect; we do not have a list # of repositories and so would it refer to? Better to do this from # within the RepositoryFrame self.repMenu.add_command(label='Disconnect', shortcut='D', command=self.tmpCall) # again, this is functionality that would make sense but which it is hard to put # in the top level menu because it is not obvious which repository it refers # to self.repMenu.add_command(label='Import Project', shortcut='I', command=self.tmpCall) self.repMenu.add_command(label='Export Project', shortcut='E', command=self.tmpCall) # FIXME JMCI # the quit option needs to be tied to a dialogue box that asks whether # the current connection state should be saved. This will have to be # secured and so means that the GUI should have a login itself (beyond # the logins for the various resources). self.repMenu.add_command(label='Quit', shortcut='Q', command=self.quit) self.mainMenu.add_cascade(label='Repository', shortcut='R', menu=self.repMenu) self.repMenu.options = [ 'Connect', 'Disconnect', 'Import Project', 'Export Project', 'Quit' ] return self.repMenu
def makeProjectMenu(self): # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call menu.add_command(label='New', shortcut='N', command=self.newProject, tipText='Make a new, blank CCPN project. Closes any existing project') menu.add_command(label='Open', shortcut='O', command=self.openProject, tipText='Open a new CCPN project from disk, closing any existing project') menu.add_command(label='Close', shortcut='C', command=self.closeProject, tipText='Close the current CCPN project') menu.add_command(label='Save', shortcut='S', command=self.saveProject, tipText='Save the current CCPN prjoject at its pre-specified location') menu.add_command(label='Save As', shortcut='A', command=self.saveAsProject, tipText='Save the current CCPN project at a new location') menu.add_command(label='Backup', shortcut='B', command=self.backupProject, tipText='Manage options for automatic CCPN project backup') menu.add_command(label='Quit', shortcut='Q', command=self.quit, tipText='Exit from the DANGLE program') menu.add_command(label='Version', shortcut='V', command=self.showVersion) self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu) menu.options = ['New','Open','Close','Save','Save As','Backup','Quit','Version'] return menu
class CingGui(BasePopup): def __init__(self, parent, options, *args, **kw): # Fill in below variable once run generates some results self.haveResults = None # store the options self.options = options BasePopup.__init__(self, parent=parent, title='CING Setup', **kw) # self.setGeometry(850, 750, 50, 50) self.project = None # self.tk_strictMotif( True) self.updateGui() # end def __init__ def body(self, guiFrame): row = 0 col = 0 # frame = Frame( guiFrame ) # frame.grid(row=row, column=col, sticky='news') self.menuBar = Menu(guiFrame) self.menuBar.grid(row=row, column=col, sticky='ew') #---------------------------------------------------------------------------------- # Project frame #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(row, weight=1) # frame = LabelFrame(guiFrame, text='Project', font=medFont) row = +1 col = 0 frame = LabelFrame(guiFrame, text='Project', **labelFrameAttributes) print '>', frame.keys() frame.grid(row=row, column=col, sticky='nsew') frame.grid_columnconfigure(2, weight=1) # frame.grid_rowconfigure(0, weight=1) srow = 0 self.projectOptions = [ 'old', 'new from PDB', 'new from CCPN', 'new from CYANA' ] self.projOptionsSelect = RadioButtons(frame, selected_index=0, entries=self.projectOptions, direction='vertical', select_callback=self.updateGui) self.projOptionsSelect.grid(row=srow, column=0, rowspan=len(self.projectOptions), columnspan=2, sticky='w') if self.options.name: text = self.options.name else: text = '' # end if self.projEntry = Entry(frame, bd=1, text=text, returnCallback=self.updateGui) self.projEntry.grid(row=srow, column=2, columnspan=2, sticky='ew') # self.projEntry.bind('<Key>', self.updateGui) self.projEntry.bind('<Leave>', self.updateGui) projButton = Button(frame, bd=1, command=self.chooseOldProjectFile, text='browse') projButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.pdbEntry = Entry(frame, bd=1, text='') self.pdbEntry.grid(row=srow, column=2, sticky='ew') self.pdbEntry.bind('<Leave>', self.updateGui) pdbButton = Button(frame, bd=1, command=self.choosePdbFile, text='browse') pdbButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.ccpnEntry = Entry(frame, bd=1, text='') self.ccpnEntry.grid(row=srow, column=2, sticky='ew') self.ccpnEntry.bind('<Leave>', self.updateGui) ccpnButton = Button(frame, bd=1, command=self.chooseCcpnFile, text='browse') ccpnButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.cyanaEntry = Entry(frame, bd=1, text='') self.cyanaEntry.grid(row=srow, column=2, sticky='ew') self.cyanaEntry.bind('<Leave>', self.updateGui) cyanaButton = Button(frame, bd=1, command=self.chooseCyanaFile, text='browse') cyanaButton.grid(row=srow, column=3, sticky='ew') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 label = Label(frame, text='Project name:') label.grid(row=srow, column=0, sticky='nw') self.nameEntry = Entry(frame, bd=1, text='') self.nameEntry.grid(row=srow, column=2, sticky='w') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 self.openProjectButton = Button(frame, command=self.openProject, text='Open Project', **actionButtonAttributes) self.openProjectButton.grid(row=srow, column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # status #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(1, weight=0) srow = 0 frame = LabelFrame(guiFrame, text='Status', **labelFrameAttributes) frame.grid(row=srow, column=1, sticky='wnes') self.projectStatus = Text(frame, height=11, width=70, borderwidth=0, relief='flat') self.projectStatus.grid(row=0, column=0, sticky='wen') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 self.closeProjectButton = Button(frame, command=self.closeProject, text='Close Project', **actionButtonAttributes) self.closeProjectButton.grid(row=srow, column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # Validate frame #---------------------------------------------------------------------------------- row += 1 col = 0 frame = LabelFrame(guiFrame, text='Validate', **labelFrameAttributes) # frame = LabelFrame(guiFrame, text='Validate', font=medFont) frame.grid(row=row, column=col, sticky='nsew') # frame.grid_columnconfigure(2, weight=1) frame.grid_rowconfigure(0, weight=1) srow = 0 # label = Label(frame, text='validation') # label.grid(row=srow,column=0,sticky='nw') # # self.selectDoValidation = CheckButton(frame) # self.selectDoValidation.grid(row=srow, column=1,sticky='nw' ) # self.selectDoValidation.set(True) # # srow += 1 # label = Label(frame, text='') # label.grid(row=srow,column=0,sticky='nw') # # srow += 1 label = Label(frame, text='checks') label.grid(row=srow, column=0, sticky='nw') self.selectCheckAssign = CheckButton(frame) self.selectCheckAssign.grid(row=srow, column=1, sticky='nw') self.selectCheckAssign.set(True) label = Label(frame, text='assignments and shifts') label.grid(row=srow, column=2, sticky='nw') # srow += 1 # self.selectCheckQueen = CheckButton(frame) # self.selectCheckQueen.grid(row=srow, column=4,sticky='nw' ) # self.selectCheckQueen.set(False) # label = Label(frame, text='QUEEN') # label.grid(row=srow,column=5,sticky='nw') # # queenButton = Button(frame, bd=1,command=None, text='setup') # queenButton.grid(row=srow,column=6,sticky='ew') srow += 1 self.selectCheckResraint = CheckButton(frame) self.selectCheckResraint.grid(row=srow, column=1, sticky='nw') self.selectCheckResraint.set(True) label = Label(frame, text='restraints') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectCheckStructure = CheckButton(frame) self.selectCheckStructure.grid(row=srow, column=1, sticky='nw') self.selectCheckStructure.set(True) label = Label(frame, text='structural') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectMakeHtml = CheckButton(frame) self.selectMakeHtml.grid(row=srow, column=1, sticky='nw') self.selectMakeHtml.set(True) label = Label(frame, text='generate HTML') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectCheckScript = CheckButton(frame) self.selectCheckScript.grid(row=srow, column=1, sticky='nw') self.selectCheckScript.set(False) label = Label(frame, text='user script') label.grid(row=srow, column=0, sticky='nw') self.validScriptEntry = Entry(frame, bd=1, text='') self.validScriptEntry.grid(row=srow, column=2, columnspan=3, sticky='ew') scriptButton = Button(frame, bd=1, command=self.chooseValidScript, text='browse') scriptButton.grid(row=srow, column=5, sticky='ew') srow += 1 label = Label(frame, text='ranges') label.grid(row=srow, column=0, sticky='nw') self.rangesEntry = Entry(frame, text='') self.rangesEntry.grid(row=srow, column=2, columnspan=3, sticky='ew') # self.validScriptEntry = Entry(frame, bd=1, text='') # self.validScriptEntry.grid(row=srow,column=3,sticky='ew') # # scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') # scriptButton.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Run Validation', 'View Results', 'Setup QUEEN'] commands = [self.runCing, None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands, expands=True) buttonBar.grid(row=srow, column=0, columnspan=6, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.runButton = buttonBar.buttons[0] self.viewResultButton = buttonBar.buttons[1] self.queenButton = buttonBar.buttons[2] #---------------------------------------------------------------------------------- # Miscellaneous frame #---------------------------------------------------------------------------------- row += 0 col = 1 # frame = LabelFrame(guiFrame, text='Miscellaneous', font=medFont) frame = LabelFrame(guiFrame, text='Miscellaneous', **labelFrameAttributes) frame.grid(row=row, column=col, sticky='news') frame.grid_columnconfigure(2, weight=1) frame.grid_columnconfigure(4, weight=1, minsize=30) frame.grid_rowconfigure(0, weight=1) # Exports srow = 0 label = Label(frame, text='export to') label.grid(row=srow, column=0, sticky='nw') self.selectExportXeasy = CheckButton(frame) self.selectExportXeasy.grid(row=srow, column=1, sticky='nw') self.selectExportXeasy.set(True) label = Label(frame, text='Xeasy, Sparky, TALOS, ...') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportCcpn = CheckButton(frame) self.selectExportCcpn.grid(row=srow, column=1, sticky='nw') self.selectExportCcpn.set(True) label = Label(frame, text='CCPN') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportQueen = CheckButton(frame) self.selectExportQueen.grid(row=srow, column=1, sticky='nw') self.selectExportQueen.set(True) label = Label(frame, text='QUEEN') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportRefine = CheckButton(frame) self.selectExportRefine.grid(row=srow, column=1, sticky='nw') self.selectExportRefine.set(True) label = Label(frame, text='refine') label.grid(row=srow, column=2, sticky='nw') srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') # User script srow += 1 label = Label(frame, text='user script') label.grid(row=srow, column=0, sticky='nw') self.selectMiscScript = CheckButton(frame) self.selectMiscScript.grid(row=srow, column=1, sticky='nw') self.selectMiscScript.set(False) self.miscScriptEntry = Entry(frame, bd=1, text='') self.miscScriptEntry.grid(row=srow, column=3, sticky='ew') script2Button = Button(frame, bd=1, command=self.chooseMiscScript, text='browse') script2Button.grid(row=srow, column=4, sticky='ew') srow += 1 texts = ['Export', 'Run Script'] commands = [None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands, expands=True) buttonBar.grid(row=srow, column=0, columnspan=5, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.exportButton = buttonBar.buttons[0] self.scriptButton = buttonBar.buttons[1] #---------------------------------------------------------------------------------- # Textarea #---------------------------------------------------------------------------------- row += 1 guiFrame.grid_rowconfigure(row, weight=1) self.outputTextBox = ScrolledText(guiFrame) self.outputTextBox.grid(row=row, column=0, columnspan=2, sticky='nsew') self.redirectConsole() #---------------------------------------------------------------------------------- # Buttons #---------------------------------------------------------------------------------- row += 1 col = 0 texts = ['Quit', 'Help'] commands = [self.close, None] self.buttonBar = ButtonList(guiFrame, texts=texts, commands=commands, expands=True) self.buttonBar.grid(row=row, column=col, columnspan=2, sticky='ew') # self.openProjectButton = self.buttonBar.buttons[0] # self.closeProjectButton = self.buttonBar.buttons[1] # self.runButton = self.buttonBar.buttons[0] # self.viewResultButton = self.buttonBar.buttons[1] for button in self.buttonBar.buttons: button.config(**actionButtonAttributes) # end for # end def body def getGuiOptions(self): projectName = self.projEntry.get() index = self.projOptionsSelect.getIndex() if index > 0: makeNewProject = True projectImport = None if index > 1: i = index - 2 format = ['PDB', 'CCPN', 'CYANA'][i] file = [self.pdbEntry, self.ccpnEntry, self.cyanaEntry][i].get() if not file: showWarning('Failure', 'No %s file selected' % format) return # end if projectImport = (format, file) # end if else: # Chould also check that any old project file exists makeNewProject = False projectImport = None # end if doValidation = self.selectDoValidation.get() checks = [] if doValidation: if self.selectCheckAssign.get(): checks.append('assignments') # end if if self.selectCheckResraint.get(): checks.append('restraints') # end if if self.selectCheckStructure.get(): checks.append('structural') # end if if self.selectMakeHtml.get(): checks.append('HTML') # end if if self.selectCheckScript.get(): script = self.validScriptEntry.get() if script: checks.append(('script', script)) # end if # end if if self.selectCheckQueen.get(): checks.append('queen') # end if # end if exports = [] if self.selectExportXeasy.get(): exports.append('Xeasy') # end if if self.selectExportCcpn.get(): exports.append('CCPN') # end if if self.selectExportQueen.get(): exports.append('QUEEN') # end if if self.selectExportRefine.get(): exports.append('refine') # end if miscScript = None if self.selectMiscScript.get(): script = self.miscScriptEntry.get() if script: miscScript = script # end if # end if return projectName, makeNewProject, projectImport, doValidation, checks, exports, miscScript # end def getGuiOptions def runCing(self): options = self.getGuiOptions() if options: projectName, makeNewProject, projectImport, doValidation, checks, exports, miscScript = options print 'Project name:', projectName print 'Make new project?', makeNewProject print 'Import source:', projectImport print 'Do vailidation?', doValidation print 'Validation checks:', ','.join(checks) print 'Export to:', ','.join(exports) print 'User script:', miscScript # end if # end def runCing # else there was already an error message def chooseOldProjectFile(self): fileTypes = [FileType('CING', ['project.xml']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types=fileTypes, title='Select CING project file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() # dirName = popup.getDirectory() if len(fileName) > 0: # Put text into entry,name widgets dummy, name = cing.Project.rootPath(fileName) self.projEntry.configure(state='normal') self.projEntry.set(fileName) self.nameEntry.configure(state='normal') self.nameEntry.set(name) self.nameEntry.configure(state='disabled') # choose the correct radiobutton self.projOptionsSelect.setIndex(0) self.updateGui() # end if #nd if popup.destroy() # end def chooseOldProjectFile def choosePdbFile(self): fileTypes = [FileType('PDB', ['*.pdb']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types=fileTypes, title='PDB file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() if len(fileName) > 0: # Put text into entry widget self.pdbEntry.configure(state='normal') self.pdbEntry.set(fileName) # Put text into name widget _dir, name, dummy = nTpath(fileName) self.nameEntry.configure(state='normal') self.nameEntry.set(name) # choose the correct radiobutton self.projOptionsSelect.setIndex(1) self.updateGui() #end if popup.destroy() # end def choosePdbFile def chooseCcpnFile(self): fileTypes = [FileType('XML', ['*.xml']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types=fileTypes, title='CCPN project XML file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() if len(fileName) > 0: self.pdbEntry.configure(state='normal') self.pdbEntry.set(fileName) self.projOptionsSelect.setIndex(1) _dir, name, dummy = nTpath(fileName) self.nameEntry.set(name) #end if self.ccpnEntry.set(fileName) self.projOptionsSelect.setIndex(2) popup.destroy() # end def chooseCcpnFile def chooseCyanaFile(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types=fileTypes, title='CYANA fproject file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() self.cyanaEntry.set(fileName) self.projOptionsSelect.setIndex(3) popup.destroy() # end def chooseCyanaFile def chooseValidScript(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types=fileTypes, title='Script file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() self.validScriptEntry.set(fileName) popup.destroy() # end def chooseValidScript def chooseMiscScript(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types=fileTypes, title='Script file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() self.miscScriptEntry.set(fileName) popup.destroy() # end def chooseMiscScript def openProject(self): projOption = self.projOptionsSelect.get() if projOption == self.projectOptions[0]: self.openOldProject() elif projOption == self.projectOptions[1]: self.initPdb() # end if if self.project: self.project.gui = self # end if self.updateGui() #end def def openOldProject(self): fName = self.projEntry.get() if not os.path.exists(fName): nTerror('Error: file "%s" does not exist\n', fName) #end if if self.project: self.closeProject() # end if self.project = cing.Project.open(name=fName, status='old', verbose=False) #end def def initPdb(self): fName = self.pdbEntry.get() if not os.path.exists(fName): nTerror('Error: file "%s" does not exist\n', fName) #end if self.project = cing.Project.open(self.nameEntry.get(), status='new') self.project.initPDB(pdbFile=fName, convention='PDB') #end def def closeProject(self): if self.project: self.project.close() # end if self.project = None self.updateGui() #end def def updateGui(self, event=None): projOption = self.projOptionsSelect.get() buttons = self.buttonBar.buttons # Disable entries for e in [ self.projEntry, self.pdbEntry, self.ccpnEntry, self.cyanaEntry, self.nameEntry ]: e.configure(state='disabled') #end for if projOption == self.projectOptions[0]: # Enable entries self.projEntry.configure(state='normal') if (len(self.projEntry.get()) > 0): self.openProjectButton.enable() self.runButton.enable() else: self.openProjectButton.disable() self.runButton.disable() #end if elif projOption == self.projectOptions[1]: # Enable entries self.pdbEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.pdbEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if elif projOption == self.projectOptions[2]: # Enable entries self.ccpnEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.ccpnEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if elif projOption == self.projectOptions[3]: # Enable entries self.cyanaEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.cyanaEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if self.projectStatus.clear() if not self.project: self.projectStatus.setText('No open project') self.closeProjectButton.setText('Close Project') self.closeProjectButton.disable() else: self.projectStatus.setText(self.project.format()) self.closeProjectButton.enable() self.closeProjectButton.setText( sprintf('Close Project "%s"', self.project.name)) #end if #end def def redirectConsole(self): #pipe = TextPipe(self.inputTextBox.text_area) #sys.stdin = pipe pipe = TextPipe(self.outputTextBox.text_area) sys.stdout = pipe nTmessage.stream = pipe # end def redirectConsole # sys.stderr = pipe def resetConsole(self): #sys.stdin = stdin nTmessage.stream = stdout sys.stdout = stdout sys.stderr = stderr # end def resetConsole def open(self): self.redirectConsole() BasePopup.open(self) # end def open def close(self): geometry = self.getGeometry() self.resetConsole() BasePopup.close(self) print 'close:', geometry sys.exit(0) # remove later # end def close def destroy(self): geometry = self.getGeometry() self.resetConsole() BasePopup.destroy(self) print 'destroy:', geometry sys.exit(0) # remove later
def body(self, guiFrame): row = 0 col =0 # frame = Frame( guiFrame ) # frame.grid(row=row, column=col, sticky='news') self.menuBar = Menu( guiFrame) self.menuBar.grid( row=row, column=col, sticky='ew') #---------------------------------------------------------------------------------- # Project frame #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(row, weight=1) # frame = LabelFrame(guiFrame, text='Project', font=medFont) row = +1 col =0 frame = LabelFrame(guiFrame, text='Project', **labelFrameAttributes ) print '>', frame.keys() frame.grid(row=row, column=col, sticky='nsew' ) frame.grid_columnconfigure(2, weight=1) # frame.grid_rowconfigure(0, weight=1) srow = 0 self.projectOptions = ['old','new from PDB','new from CCPN','new from CYANA'] self.projOptionsSelect = RadioButtons(frame, selected_index=0, entries=self.projectOptions, direction='vertical', select_callback=self.updateGui ) self.projOptionsSelect.grid(row=srow,column=0,rowspan=len(self.projectOptions),columnspan=2, sticky='w') if self.options.name: text = self.options.name else: text='' # end if self.projEntry = Entry(frame, bd=1, text=text, returnCallback=self.updateGui) self.projEntry.grid(row=srow,column=2,columnspan=2,sticky='ew') # self.projEntry.bind('<Key>', self.updateGui) self.projEntry.bind('<Leave>', self.updateGui) projButton = Button(frame, bd=1,command=self.chooseOldProjectFile, text='browse') projButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.pdbEntry = Entry(frame, bd=1, text='') self.pdbEntry.grid(row=srow,column=2,sticky='ew') self.pdbEntry.bind('<Leave>', self.updateGui) pdbButton = Button(frame, bd=1,command=self.choosePdbFile, text='browse') pdbButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.ccpnEntry = Entry(frame, bd=1, text='') self.ccpnEntry.grid(row=srow,column=2,sticky='ew') self.ccpnEntry.bind('<Leave>', self.updateGui) ccpnButton = Button(frame, bd=1,command=self.chooseCcpnFile, text='browse') ccpnButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.cyanaEntry = Entry(frame, bd=1, text='') self.cyanaEntry.grid(row=srow,column=2,sticky='ew') self.cyanaEntry.bind('<Leave>', self.updateGui) cyanaButton = Button(frame, bd=1,command=self.chooseCyanaFile, text='browse') cyanaButton.grid(row=srow,column=3,sticky='ew') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 label = Label(frame, text='Project name:') label.grid(row=srow,column=0,sticky='nw') self.nameEntry = Entry(frame, bd=1, text='') self.nameEntry.grid(row=srow,column=2,sticky='w') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 self.openProjectButton = Button(frame, command=self.openProject, text='Open Project', **actionButtonAttributes ) self.openProjectButton.grid(row=srow,column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # status #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(1, weight=0) srow = 0 frame = LabelFrame(guiFrame, text='Status', **labelFrameAttributes) frame.grid( row=srow, column=1, sticky='wnes') self.projectStatus = Text(frame, height=11, width=70, borderwidth=0, relief='flat') self.projectStatus.grid(row=0, column=0, sticky='wen') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 self.closeProjectButton = Button(frame, command=self.closeProject, text='Close Project', **actionButtonAttributes) self.closeProjectButton.grid(row=srow,column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # Validate frame #---------------------------------------------------------------------------------- row +=1 col=0 frame = LabelFrame(guiFrame, text='Validate', **labelFrameAttributes) # frame = LabelFrame(guiFrame, text='Validate', font=medFont) frame.grid(row=row, column=col, sticky='nsew') # frame.grid_columnconfigure(2, weight=1) frame.grid_rowconfigure(0, weight=1) srow = 0 # label = Label(frame, text='validation') # label.grid(row=srow,column=0,sticky='nw') # # self.selectDoValidation = CheckButton(frame) # self.selectDoValidation.grid(row=srow, column=1,sticky='nw' ) # self.selectDoValidation.set(True) # # srow += 1 # label = Label(frame, text='') # label.grid(row=srow,column=0,sticky='nw') # # srow += 1 label = Label(frame, text='checks') label.grid(row=srow,column=0,sticky='nw') self.selectCheckAssign = CheckButton(frame) self.selectCheckAssign.grid(row=srow, column=1,sticky='nw' ) self.selectCheckAssign.set(True) label = Label(frame, text='assignments and shifts') label.grid(row=srow,column=2,sticky='nw') # srow += 1 # self.selectCheckQueen = CheckButton(frame) # self.selectCheckQueen.grid(row=srow, column=4,sticky='nw' ) # self.selectCheckQueen.set(False) # label = Label(frame, text='QUEEN') # label.grid(row=srow,column=5,sticky='nw') # # queenButton = Button(frame, bd=1,command=None, text='setup') # queenButton.grid(row=srow,column=6,sticky='ew') srow += 1 self.selectCheckResraint = CheckButton(frame) self.selectCheckResraint.grid(row=srow, column=1,sticky='nw' ) self.selectCheckResraint.set(True) label = Label(frame, text='restraints') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectCheckStructure = CheckButton(frame) self.selectCheckStructure.grid(row=srow, column=1,sticky='nw' ) self.selectCheckStructure.set(True) label = Label(frame, text='structural') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectMakeHtml = CheckButton(frame) self.selectMakeHtml.grid(row=srow, column=1,sticky='nw' ) self.selectMakeHtml.set(True) label = Label(frame, text='generate HTML') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectCheckScript = CheckButton(frame) self.selectCheckScript.grid(row=srow, column=1,sticky='nw' ) self.selectCheckScript.set(False) label = Label(frame, text='user script') label.grid(row=srow,column=0,sticky='nw') self.validScriptEntry = Entry(frame, bd=1, text='') self.validScriptEntry.grid(row=srow,column=2,columnspan=3, sticky='ew') scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') scriptButton.grid(row=srow,column=5,sticky='ew') srow += 1 label = Label(frame, text='ranges') label.grid(row=srow,column=0,sticky='nw') self.rangesEntry = Entry( frame, text='' ) self.rangesEntry.grid( row=srow, column=2, columnspan=3, sticky='ew') # self.validScriptEntry = Entry(frame, bd=1, text='') # self.validScriptEntry.grid(row=srow,column=3,sticky='ew') # # scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') # scriptButton.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Run Validation','View Results','Setup QUEEN'] commands = [self.runCing, None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands,expands=True) buttonBar.grid(row=srow, column=0, columnspan=6, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.runButton = buttonBar.buttons[0] self.viewResultButton = buttonBar.buttons[1] self.queenButton = buttonBar.buttons[2] #---------------------------------------------------------------------------------- # Miscellaneous frame #---------------------------------------------------------------------------------- row +=0 col=1 # frame = LabelFrame(guiFrame, text='Miscellaneous', font=medFont) frame = LabelFrame(guiFrame, text='Miscellaneous', **labelFrameAttributes) frame.grid(row=row, column=col, sticky='news') frame.grid_columnconfigure(2, weight=1) frame.grid_columnconfigure(4, weight=1,minsize=30) frame.grid_rowconfigure(0, weight=1) # Exports srow = 0 label = Label(frame, text='export to') label.grid(row=srow,column=0,sticky='nw') self.selectExportXeasy = CheckButton(frame) self.selectExportXeasy.grid(row=srow, column=1,sticky='nw' ) self.selectExportXeasy.set(True) label = Label(frame, text='Xeasy, Sparky, TALOS, ...') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportCcpn = CheckButton(frame) self.selectExportCcpn.grid(row=srow, column=1,sticky='nw' ) self.selectExportCcpn.set(True) label = Label(frame, text='CCPN') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportQueen = CheckButton(frame) self.selectExportQueen.grid(row=srow, column=1,sticky='nw' ) self.selectExportQueen.set(True) label = Label(frame, text='QUEEN') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportRefine = CheckButton(frame) self.selectExportRefine.grid(row=srow, column=1,sticky='nw' ) self.selectExportRefine.set(True) label = Label(frame, text='refine') label.grid(row=srow,column=2,sticky='nw') srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') # User script srow += 1 label = Label(frame, text='user script') label.grid(row=srow,column=0,sticky='nw') self.selectMiscScript = CheckButton(frame) self.selectMiscScript.grid(row=srow, column=1,sticky='nw' ) self.selectMiscScript.set(False) self.miscScriptEntry = Entry(frame, bd=1, text='') self.miscScriptEntry.grid(row=srow,column=3,sticky='ew') script2Button = Button(frame, bd=1,command=self.chooseMiscScript, text='browse') script2Button.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Export','Run Script'] commands = [None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands,expands=True) buttonBar.grid(row=srow, column=0, columnspan=5, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.exportButton = buttonBar.buttons[0] self.scriptButton = buttonBar.buttons[1] #---------------------------------------------------------------------------------- # Textarea #---------------------------------------------------------------------------------- row +=1 guiFrame.grid_rowconfigure(row, weight=1) self.outputTextBox = ScrolledText(guiFrame) self.outputTextBox.grid(row=row, column=0, columnspan=2, sticky='nsew') self.redirectConsole() #---------------------------------------------------------------------------------- # Buttons #---------------------------------------------------------------------------------- row +=1 col=0 texts = ['Quit', 'Help'] commands = [self.close, None] self.buttonBar = ButtonList(guiFrame, texts=texts, commands=commands,expands=True) self.buttonBar.grid(row=row, column=col, columnspan=2, sticky='ew') # self.openProjectButton = self.buttonBar.buttons[0] # self.closeProjectButton = self.buttonBar.buttons[1] # self.runButton = self.buttonBar.buttons[0] # self.viewResultButton = self.buttonBar.buttons[1] for button in self.buttonBar.buttons: button.config(**actionButtonAttributes)
class CingGui(BasePopup): def __init__(self, parent, options, *args, **kw): # Fill in below variable once run generates some results self.haveResults = None # store the options self.options = options BasePopup.__init__(self, parent=parent, title='CING Setup', **kw) # self.setGeometry(850, 750, 50, 50) self.project = None # self.tk_strictMotif( True) self.updateGui() # end def __init__ def body(self, guiFrame): row = 0 col =0 # frame = Frame( guiFrame ) # frame.grid(row=row, column=col, sticky='news') self.menuBar = Menu( guiFrame) self.menuBar.grid( row=row, column=col, sticky='ew') #---------------------------------------------------------------------------------- # Project frame #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(row, weight=1) # frame = LabelFrame(guiFrame, text='Project', font=medFont) row = +1 col =0 frame = LabelFrame(guiFrame, text='Project', **labelFrameAttributes ) print '>', frame.keys() frame.grid(row=row, column=col, sticky='nsew' ) frame.grid_columnconfigure(2, weight=1) # frame.grid_rowconfigure(0, weight=1) srow = 0 self.projectOptions = ['old','new from PDB','new from CCPN','new from CYANA'] self.projOptionsSelect = RadioButtons(frame, selected_index=0, entries=self.projectOptions, direction='vertical', select_callback=self.updateGui ) self.projOptionsSelect.grid(row=srow,column=0,rowspan=len(self.projectOptions),columnspan=2, sticky='w') if self.options.name: text = self.options.name else: text='' # end if self.projEntry = Entry(frame, bd=1, text=text, returnCallback=self.updateGui) self.projEntry.grid(row=srow,column=2,columnspan=2,sticky='ew') # self.projEntry.bind('<Key>', self.updateGui) self.projEntry.bind('<Leave>', self.updateGui) projButton = Button(frame, bd=1,command=self.chooseOldProjectFile, text='browse') projButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.pdbEntry = Entry(frame, bd=1, text='') self.pdbEntry.grid(row=srow,column=2,sticky='ew') self.pdbEntry.bind('<Leave>', self.updateGui) pdbButton = Button(frame, bd=1,command=self.choosePdbFile, text='browse') pdbButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.ccpnEntry = Entry(frame, bd=1, text='') self.ccpnEntry.grid(row=srow,column=2,sticky='ew') self.ccpnEntry.bind('<Leave>', self.updateGui) ccpnButton = Button(frame, bd=1,command=self.chooseCcpnFile, text='browse') ccpnButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.cyanaEntry = Entry(frame, bd=1, text='') self.cyanaEntry.grid(row=srow,column=2,sticky='ew') self.cyanaEntry.bind('<Leave>', self.updateGui) cyanaButton = Button(frame, bd=1,command=self.chooseCyanaFile, text='browse') cyanaButton.grid(row=srow,column=3,sticky='ew') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 label = Label(frame, text='Project name:') label.grid(row=srow,column=0,sticky='nw') self.nameEntry = Entry(frame, bd=1, text='') self.nameEntry.grid(row=srow,column=2,sticky='w') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 self.openProjectButton = Button(frame, command=self.openProject, text='Open Project', **actionButtonAttributes ) self.openProjectButton.grid(row=srow,column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # status #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(1, weight=0) srow = 0 frame = LabelFrame(guiFrame, text='Status', **labelFrameAttributes) frame.grid( row=srow, column=1, sticky='wnes') self.projectStatus = Text(frame, height=11, width=70, borderwidth=0, relief='flat') self.projectStatus.grid(row=0, column=0, sticky='wen') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 self.closeProjectButton = Button(frame, command=self.closeProject, text='Close Project', **actionButtonAttributes) self.closeProjectButton.grid(row=srow,column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # Validate frame #---------------------------------------------------------------------------------- row +=1 col=0 frame = LabelFrame(guiFrame, text='Validate', **labelFrameAttributes) # frame = LabelFrame(guiFrame, text='Validate', font=medFont) frame.grid(row=row, column=col, sticky='nsew') # frame.grid_columnconfigure(2, weight=1) frame.grid_rowconfigure(0, weight=1) srow = 0 # label = Label(frame, text='validation') # label.grid(row=srow,column=0,sticky='nw') # # self.selectDoValidation = CheckButton(frame) # self.selectDoValidation.grid(row=srow, column=1,sticky='nw' ) # self.selectDoValidation.set(True) # # srow += 1 # label = Label(frame, text='') # label.grid(row=srow,column=0,sticky='nw') # # srow += 1 label = Label(frame, text='checks') label.grid(row=srow,column=0,sticky='nw') self.selectCheckAssign = CheckButton(frame) self.selectCheckAssign.grid(row=srow, column=1,sticky='nw' ) self.selectCheckAssign.set(True) label = Label(frame, text='assignments and shifts') label.grid(row=srow,column=2,sticky='nw') # srow += 1 # self.selectCheckQueen = CheckButton(frame) # self.selectCheckQueen.grid(row=srow, column=4,sticky='nw' ) # self.selectCheckQueen.set(False) # label = Label(frame, text='QUEEN') # label.grid(row=srow,column=5,sticky='nw') # # queenButton = Button(frame, bd=1,command=None, text='setup') # queenButton.grid(row=srow,column=6,sticky='ew') srow += 1 self.selectCheckResraint = CheckButton(frame) self.selectCheckResraint.grid(row=srow, column=1,sticky='nw' ) self.selectCheckResraint.set(True) label = Label(frame, text='restraints') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectCheckStructure = CheckButton(frame) self.selectCheckStructure.grid(row=srow, column=1,sticky='nw' ) self.selectCheckStructure.set(True) label = Label(frame, text='structural') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectMakeHtml = CheckButton(frame) self.selectMakeHtml.grid(row=srow, column=1,sticky='nw' ) self.selectMakeHtml.set(True) label = Label(frame, text='generate HTML') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectCheckScript = CheckButton(frame) self.selectCheckScript.grid(row=srow, column=1,sticky='nw' ) self.selectCheckScript.set(False) label = Label(frame, text='user script') label.grid(row=srow,column=0,sticky='nw') self.validScriptEntry = Entry(frame, bd=1, text='') self.validScriptEntry.grid(row=srow,column=2,columnspan=3, sticky='ew') scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') scriptButton.grid(row=srow,column=5,sticky='ew') srow += 1 label = Label(frame, text='ranges') label.grid(row=srow,column=0,sticky='nw') self.rangesEntry = Entry( frame, text='' ) self.rangesEntry.grid( row=srow, column=2, columnspan=3, sticky='ew') # self.validScriptEntry = Entry(frame, bd=1, text='') # self.validScriptEntry.grid(row=srow,column=3,sticky='ew') # # scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') # scriptButton.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Run Validation','View Results','Setup QUEEN'] commands = [self.runCing, None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands,expands=True) buttonBar.grid(row=srow, column=0, columnspan=6, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.runButton = buttonBar.buttons[0] self.viewResultButton = buttonBar.buttons[1] self.queenButton = buttonBar.buttons[2] #---------------------------------------------------------------------------------- # Miscellaneous frame #---------------------------------------------------------------------------------- row +=0 col=1 # frame = LabelFrame(guiFrame, text='Miscellaneous', font=medFont) frame = LabelFrame(guiFrame, text='Miscellaneous', **labelFrameAttributes) frame.grid(row=row, column=col, sticky='news') frame.grid_columnconfigure(2, weight=1) frame.grid_columnconfigure(4, weight=1,minsize=30) frame.grid_rowconfigure(0, weight=1) # Exports srow = 0 label = Label(frame, text='export to') label.grid(row=srow,column=0,sticky='nw') self.selectExportXeasy = CheckButton(frame) self.selectExportXeasy.grid(row=srow, column=1,sticky='nw' ) self.selectExportXeasy.set(True) label = Label(frame, text='Xeasy, Sparky, TALOS, ...') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportCcpn = CheckButton(frame) self.selectExportCcpn.grid(row=srow, column=1,sticky='nw' ) self.selectExportCcpn.set(True) label = Label(frame, text='CCPN') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportQueen = CheckButton(frame) self.selectExportQueen.grid(row=srow, column=1,sticky='nw' ) self.selectExportQueen.set(True) label = Label(frame, text='QUEEN') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportRefine = CheckButton(frame) self.selectExportRefine.grid(row=srow, column=1,sticky='nw' ) self.selectExportRefine.set(True) label = Label(frame, text='refine') label.grid(row=srow,column=2,sticky='nw') srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') # User script srow += 1 label = Label(frame, text='user script') label.grid(row=srow,column=0,sticky='nw') self.selectMiscScript = CheckButton(frame) self.selectMiscScript.grid(row=srow, column=1,sticky='nw' ) self.selectMiscScript.set(False) self.miscScriptEntry = Entry(frame, bd=1, text='') self.miscScriptEntry.grid(row=srow,column=3,sticky='ew') script2Button = Button(frame, bd=1,command=self.chooseMiscScript, text='browse') script2Button.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Export','Run Script'] commands = [None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands,expands=True) buttonBar.grid(row=srow, column=0, columnspan=5, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.exportButton = buttonBar.buttons[0] self.scriptButton = buttonBar.buttons[1] #---------------------------------------------------------------------------------- # Textarea #---------------------------------------------------------------------------------- row +=1 guiFrame.grid_rowconfigure(row, weight=1) self.outputTextBox = ScrolledText(guiFrame) self.outputTextBox.grid(row=row, column=0, columnspan=2, sticky='nsew') self.redirectConsole() #---------------------------------------------------------------------------------- # Buttons #---------------------------------------------------------------------------------- row +=1 col=0 texts = ['Quit', 'Help'] commands = [self.close, None] self.buttonBar = ButtonList(guiFrame, texts=texts, commands=commands,expands=True) self.buttonBar.grid(row=row, column=col, columnspan=2, sticky='ew') # self.openProjectButton = self.buttonBar.buttons[0] # self.closeProjectButton = self.buttonBar.buttons[1] # self.runButton = self.buttonBar.buttons[0] # self.viewResultButton = self.buttonBar.buttons[1] for button in self.buttonBar.buttons: button.config(**actionButtonAttributes) # end for # end def body def getGuiOptions(self): projectName = self.projEntry.get() index = self.projOptionsSelect.getIndex() if index > 0: makeNewProject = True projectImport = None if index > 1: i = index-2 format = ['PDB','CCPN','CYANA'][i] file = [self.pdbEntry, self.ccpnEntry, self.cyanaEntry][i].get() if not file: showWarning('Failure','No %s file selected' % format) return # end if projectImport = (format, file) # end if else: # Chould also check that any old project file exists makeNewProject = False projectImport = None # end if doValidation = self.selectDoValidation.get() checks = [] if doValidation: if self.selectCheckAssign.get(): checks.append('assignments') # end if if self.selectCheckResraint.get(): checks.append('restraints') # end if if self.selectCheckStructure.get(): checks.append('structural') # end if if self.selectMakeHtml.get(): checks.append('HTML') # end if if self.selectCheckScript.get(): script = self.validScriptEntry.get() if script: checks.append( ('script',script) ) # end if # end if if self.selectCheckQueen.get(): checks.append('queen') # end if # end if exports = [] if self.selectExportXeasy.get(): exports.append('Xeasy') # end if if self.selectExportCcpn.get(): exports.append('CCPN') # end if if self.selectExportQueen.get(): exports.append('QUEEN') # end if if self.selectExportRefine.get(): exports.append('refine') # end if miscScript = None if self.selectMiscScript.get(): script = self.miscScriptEntry.get() if script: miscScript = script # end if # end if return projectName, makeNewProject, projectImport, doValidation, checks, exports, miscScript # end def getGuiOptions def runCing(self): options = self.getGuiOptions() if options: projectName, makeNewProject, projectImport, doValidation, checks, exports, miscScript = options print 'Project name:', projectName print 'Make new project?', makeNewProject print 'Import source:', projectImport print 'Do vailidation?', doValidation print 'Validation checks:', ','.join(checks) print 'Export to:', ','.join(exports) print 'User script:', miscScript # end if # end def runCing # else there was already an error message def chooseOldProjectFile(self): fileTypes = [ FileType('CING', ['project.xml']), FileType('All', ['*']) ] popup = FileSelectPopup(self, file_types = fileTypes, title = 'Select CING project file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() # dirName = popup.getDirectory() if len(fileName) > 0: # Put text into entry,name widgets dummy,name = cing.Project.rootPath(fileName) self.projEntry.configure(state='normal') self.projEntry.set(fileName) self.nameEntry.configure(state='normal') self.nameEntry.set(name) self.nameEntry.configure(state='disabled') # choose the correct radiobutton self.projOptionsSelect.setIndex(0) self.updateGui() # end if #nd if popup.destroy() # end def chooseOldProjectFile def choosePdbFile(self): fileTypes = [ FileType('PDB', ['*.pdb']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types = fileTypes, title = 'PDB file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() if len(fileName)>0: # Put text into entry widget self.pdbEntry.configure(state='normal') self.pdbEntry.set(fileName) # Put text into name widget _dir,name,dummy = nTpath( fileName ) self.nameEntry.configure(state='normal') self.nameEntry.set(name) # choose the correct radiobutton self.projOptionsSelect.setIndex(1) self.updateGui() #end if popup.destroy() # end def choosePdbFile def chooseCcpnFile(self): fileTypes = [ FileType('XML', ['*.xml']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types = fileTypes, title = 'CCPN project XML file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() if len(fileName)>0: self.pdbEntry.configure(state='normal') self.pdbEntry.set(fileName) self.projOptionsSelect.setIndex(1) _dir,name,dummy = nTpath( fileName ) self.nameEntry.set(name) #end if self.ccpnEntry.set(fileName) self.projOptionsSelect.setIndex(2) popup.destroy() # end def chooseCcpnFile def chooseCyanaFile(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types = fileTypes, title = 'CYANA fproject file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() self.cyanaEntry.set(fileName) self.projOptionsSelect.setIndex(3) popup.destroy() # end def chooseCyanaFile def chooseValidScript(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types = fileTypes, title = 'Script file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() self.validScriptEntry.set(fileName) popup.destroy() # end def chooseValidScript def chooseMiscScript(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types = fileTypes, title = 'Script file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() self.miscScriptEntry.set(fileName) popup.destroy() # end def chooseMiscScript def openProject(self ): projOption = self.projOptionsSelect.get() if projOption == self.projectOptions[0]: self.openOldProject() elif projOption == self.projectOptions[1]: self.initPdb() # end if if self.project: self.project.gui = self # end if self.updateGui() #end def def openOldProject(self ): fName = self.projEntry.get() if not os.path.exists( fName ): nTerror('Error: file "%s" does not exist\n', fName) #end if if self.project: self.closeProject() # end if self.project = cing.Project.open( name=fName, status='old', verbose=False ) #end def def initPdb(self ): fName = self.pdbEntry.get() if not os.path.exists( fName ): nTerror('Error: file "%s" does not exist\n', fName) #end if self.project = cing.Project.open( self.nameEntry.get(), status='new' ) self.project.initPDB( pdbFile=fName, convention = 'PDB' ) #end def def closeProject(self): if self.project: self.project.close() # end if self.project = None self.updateGui() #end def def updateGui(self, event=None): projOption = self.projOptionsSelect.get() buttons = self.buttonBar.buttons # Disable entries for e in [self.projEntry, self.pdbEntry, self.ccpnEntry, self.cyanaEntry, self.nameEntry]: e.configure(state='disabled') #end for if projOption == self.projectOptions[0]: # Enable entries self.projEntry.configure(state='normal') if (len(self.projEntry.get()) > 0): self.openProjectButton.enable() self.runButton.enable() else: self.openProjectButton.disable() self.runButton.disable() #end if elif projOption == self.projectOptions[1]: # Enable entries self.pdbEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.pdbEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if elif projOption == self.projectOptions[2]: # Enable entries self.ccpnEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.ccpnEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if elif projOption == self.projectOptions[3]: # Enable entries self.cyanaEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.cyanaEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if self.projectStatus.clear() if not self.project: self.projectStatus.setText('No open project') self.closeProjectButton.setText('Close Project') self.closeProjectButton.disable() else: self.projectStatus.setText(self.project.format()) self.closeProjectButton.enable() self.closeProjectButton.setText(sprintf('Close Project "%s"', self.project.name)) #end if #end def def redirectConsole(self): #pipe = TextPipe(self.inputTextBox.text_area) #sys.stdin = pipe pipe = TextPipe(self.outputTextBox.text_area) sys.stdout = pipe nTmessage.stream = pipe # end def redirectConsole # sys.stderr = pipe def resetConsole(self): #sys.stdin = stdin nTmessage.stream = stdout sys.stdout = stdout sys.stderr = stderr # end def resetConsole def open(self): self.redirectConsole() BasePopup.open(self) # end def open def close(self): geometry = self.getGeometry() self.resetConsole() BasePopup.close(self) print 'close:',geometry sys.exit(0) # remove later # end def close def destroy(self): geometry = self.getGeometry() self.resetConsole() BasePopup.destroy(self) print 'destroy:',geometry sys.exit(0) # remove later
def makeCcpNmrMenu(self): try: from ccpnmr.analysis.AnalysisPopup import AnalysisPopup haveAnalysis = True except ImportError: haveAnalysis = False try: from ccpnmr.format.gui.FormatConverter import FormatConverter from ccpnmr.format.gui.DataShifter import DataShifter haveFormatConv = True except ImportError: haveFormatConv = False menu = Menu(self.mainMenu, tearoff=0) if haveAnalysis: menu.add_command(label='Analysis', shortcut='A', command=self.ccpNmrAnalysis) else: menu.add_command(label='Analysis ** NOT INSTALLED **', shortcut='A', command=None) if haveFormatConv: menu.add_command(label='Format Converter', shortcut='F', command=self.ccpNmrFormatConverter) menu.add_command(label='Data Shifter', shortcut='D', command=self.ccpNmrDataShifter) else: menu.add_command(label='Format Converter ** NOT INSTALLED **', shortcut='F', command=None) menu.add_command(label='Data Shifter ** NOT INSTALLED **', shortcut='D', command=None) self.mainMenu.add_cascade(label='CcpNmr', shortcut='C', menu=menu) menu.options = ['Analysis', 'Format Converter', 'Data Shifter'] return menu
class EntryCompletionGui(BasePopup): ''' The standalone version of CcpNmr Entry Completion Interface (ECI). With it, you can complete all the necessary information required for PDB and BMRB data depositions by adding an "Entry" object to your CCPN project. An "Entry" object contains all the information that you wish to deposit with your submission. You can also select chemical shift lists, peak lists, structural restraints, ensembles, etc. and all at the click of a button. In addition, you can add all the meta data that is required for submissions to the PDB and BMRB. This can be done securely on your desktop computer over the duration of your NMR project. ''' help_url = 'http://www.ccpn.ac.uk' def __init__(self, root): self.root = root self.font = DEFAULT_FONT # Application object needed to store application-specific data with project self.application = Application(name=PROGRAM_NAME) self.versionInfo = VERSION # Application popup is a superclass of memops.editor.BasePoup BasePopup.__init__(self, parent=root, title=PROGRAM_NAME, location='+100+100', class_=self.application.name) #self.setTitle(PROGRAM_NAME) def body(self, guiParent): self.geometry('900x750') # Ensure that the first row and column in popup expand guiParent.expandGrid(0,0) self.eciFrame = EntryCompletionFrame(guiParent, basePopup=self, grid=(0,0)) # Add help, close buttons #buttonList = UtilityButtonList(self.eciFrame.tabbedFrame.sideFrame, # grid=(0,0), sticky='e') # 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.ccpNmrMenu = self.makeCcpNmrMenu() self.otherMenu = self.makeOtherMenu() # Put the main menu self.config(menu=self.mainMenu) self.initProject() def makeProjectMenu(self): importsMenu = Menu(self.mainMenu, tearoff=False) importsMenu.add_command(label='Fasta Sequence',command=self.importFastaSeq) importsMenu.add_command(label='NMR-STAR 2.1.1', command=self.importNmrStar211) importsMenu.add_command(label='NMR-STAR 3.1', command=self.importNmrStar31) importsMenu.add_command(label='PDB 3.20',command=self.importPdb) importsMenu.add_command(label='PDB Coords',command=self.importPdbCoords) #importsMenu.add_command(label='CNS Distance Restraints',command=self.importCnsDistance) exportsMenu = Menu(self.mainMenu, tearoff=False) exportsMenu.add_command(label='NMR-STAR 3.1', command=self.eciFrame.exportNmrStar31) exportsMenu.add_command(label='PDB Coords',command=self.eciFrame.exportPdb) #exportsMenu.add_command(label='CNS Distance Restraints',command=self.eciFrame.exportCnsDistance) # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call menu.add_command(label='New', shortcut='N', command=self.newProject) menu.add_command(label='Open', shortcut='O', command=self.openProject) menu.add_command(label='Close', shortcut='C', command=self.closeProject) menu.add_command(label='Save', shortcut='S', command=self.saveProject) menu.add_command(label='Save As', shortcut='A', command=self.saveAsProject) menu.add_cascade(label='Import', shortcut='I', menu=importsMenu) menu.add_cascade(label='Export', shortcut='E', menu=exportsMenu) menu.add_command(label='Quit', shortcut='Q', command=self.quit) menu.add_command(label='Version', shortcut='V', command=self.showVersion) self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu) menu.options = ['New','Open','Close','Save','Save As','Import','Export','Quit','Version'] return menu def makeOtherMenu(self): # The fonts menu is a pre-created widget fontsMenu = FontMenu(self.mainMenu, self.setFont, sizes=(8,10,12), doItalic=0, doBoldItalic=0, tearoff=0) # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Only Fonts option so far menu.add_cascade(label='Fonts', shortcut='F', menu=fontsMenu) self.mainMenu.add_cascade(label='Options', shortcut='O', menu=menu) menu.options = ['Fonts',] return menu def makeCcpNmrMenu(self): try: from ccpnmr.analysis.AnalysisPopup import AnalysisPopup haveAnalysis = True except ImportError: haveAnalysis = False try: from ccpnmr.format.gui.FormatConverter import FormatConverter from ccpnmr.format.gui.DataShifter import DataShifter haveFormatConv = True except ImportError: haveFormatConv = False menu = Menu(self.mainMenu, tearoff=0) if haveAnalysis: menu.add_command(label='Analysis', shortcut='A', command=self.ccpNmrAnalysis) else: menu.add_command(label='Analysis ** NOT INSTALLED **', shortcut='A', command=None) if haveFormatConv: menu.add_command(label='Format Converter', shortcut='F', command=self.ccpNmrFormatConverter) menu.add_command(label='Data Shifter', shortcut='D', command=self.ccpNmrDataShifter) else: menu.add_command(label='Format Converter ** NOT INSTALLED **', shortcut='F', command=None) menu.add_command(label='Data Shifter ** NOT INSTALLED **', shortcut='D', command=None) self.mainMenu.add_cascade(label='CcpNmr', shortcut='C', menu=menu) menu.options = ['Analysis','Format Converter','Data Shifter'] return menu def ccpNmrAnalysis(self, cacheSize=64): from ccpnmr.analysis.AnalysisPopup import AnalysisPopup analysis = AnalysisPopup(self, cache_size=cacheSize, glDirect=None) analysis.update_idletasks() # fast if self.project: analysis.initProject(self.project) def ccpNmrFormatConverter(self): from ccpnmr.format.gui.FormatConverter import FormatConverter fc = FormatConverter(self,threading=False,project=self.project) fc.open() if self.project: fc.initProject(self.project) def ccpNmrDataShifter(self): from ccpnmr.format.gui.DataShifter import DataShifter ds = DataShifter(self) ds.open() def newProject(self): if self.project: # Project already present if not self.closeProject(): # If we don't close the current project do nothing return name = askString(title='Project name', prompt='Enter project name:',parent=self) if name: # Make the API Project object project = Implementation.MemopsRoot(name=name) nmrProject = project.newNmrProject(name=name) self.initProject(project) def openProject(self): if self.project: if not self.closeProject(): return self.openPopup('open_project', OpenProjectPopup, callback=self.initProject) def openPopup(self, popup_name, clazz, oldStyle=False, *args, **kw): popup = self.popups.get(popup_name) if (popup): popup.open() else: if self.project: analysisProfile = self.analysisProfile else: analysisProfile = None if analysisProfile: transient = analysisProfile.transientDialogs else: transient = True name = popup_name if (oldStyle): popup = self.popups[popup_name] = clazz(self, transient=transient, *args, **kw) else: popup = self.popups[popup_name] = clazz(self, project=self.project, popup_name=name, transient=transient, *args, **kw) # above automatically opens popup return popup def closeProject(self, queryClose = True, querySave = True): if queryClose: if not showYesNo('Close project', 'Close current project?', parent=self): return False if querySave: if not self.checkSaving(): return False self.destroyPopups() self.initProject() return True def saveProject(self): self.saveFile() def saveAsProject(self): self.askSaveFile() def importNmrStar211(self): if not self.project: showWarning('Failure','Please create a new CCPN project.', parent=self) return fileTypes = [ FileType('STAR', ['*.str']), FileType('All', ['*'])] fileSelectPopup = FileSelectPopup(self, file_types=fileTypes, title='Import NMR-STAR 2.1.1 file', dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False,) fileName = fileSelectPopup.getFile() if not os.path.exists(fileName): showWarning('Failure','No such file.', parent=self) return if fileName: nmrStarObj = NmrStarFormat(self.project, self, verbose=True) nmrStarObj.readProject(fileName, minimalPrompts=True, version='2.1.1') self.eciFrame.updateAll() return nmrStarObj def importNmrStar31(self): if not self.project: showWarning('Failure','Please create a new CCPN project.', parent=self) return fileTypes = [ FileType('STAR', ['*.str']), FileType('All', ['*'])] fileSelectPopup = FileSelectPopup(self, file_types=fileTypes, title='Import NMR-STAR 3.1 file', dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False,) fileName = fileSelectPopup.getFile() if not os.path.exists(fileName): showWarning('Failure','No such file.', parent=self) return if fileName: nmrStarObj = NmrStarFormat(self.project, self, verbose=True) nmrStarObj.readProject(fileName, minimalPrompts=True, version='3.1') self.eciFrame.updateAll() return nmrStarObj def importPdb(self): if not self.project: showWarning('Failure','Please create a new CCPN project.', parent=self) return fileTypes = [ FileType('PDB', ['*.pdb']), FileType('PDB Entry', ['*.ent']), FileType('All', ['*']) ] fileSelectPopup = FileSelectPopup(self, file_types=fileTypes, title='Import PDB 3.20 file', dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False,) fileName = fileSelectPopup.getFile() if not os.path.exists(fileName): showWarning('Failure','No such file.', parent=self) return if fileName: name = os.path.split(fileName)[1] if '.' in name: name = name.split('.')[0] pdbObj = ReadPdb(fileName, self.project, 'PDB_'+ name, self) self.eciFrame.updateAll() return pdbObj def importCnsDistance(self): if not self.project: showWarning('Failure','Please create a new CCPN project.', parent=self) return fileTypes = [ FileType('CNS', ['*.tbl']), FileType('All', ['*']) ] fileSelectPopup = FileSelectPopup(self, file_types=fileTypes, title='Import CNS distance restraints file', dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False,) fileName = fileSelectPopup.getFile() if not os.path.exists(fileName): showWarning('Failure','No such file.', parent=self) return if fileName: name = os.path.split(fileName)[1] if '.' in name: name = name.split('.')[0] cnsObj = CnsFormat(self.project, self, verbose=True) cnsObj.readDistanceConstraints(fileName, minimalPrompts=True) self.eciFrame.updateAll() return cnsObj def importFastaSeq(self): if not self.project: showWarning('Failure','Please create a new CCPN project.', parent=self) return fileTypes = [ FileType('Fasta', ['*.fsa']), FileType('All', ['*']) ] fileSelectPopup = FileSelectPopup(self, file_types=fileTypes, title='Import Fasta sequence file', dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False,) fileName = fileSelectPopup.getFile() if not os.path.exists(fileName): showWarning('Failure','No such file.', parent=self) return if fileName: name = os.path.split(fileName)[1] if '.' in name: name = name.split('.')[0] fastaObj = FastaFormat(self.project, self, verbose=True) fastaObj.readSequence(fileName, minimalPrompts=True) self.eciFrame.updateAll() return fastaObj def importPdbCoords(self): if not self.project: showWarning('Failure','Please create a new CCPN project.', parent=self) return fileTypes = [ FileType('PDB', ['*.pdb']), FileType('PDB Entry', ['*.ent']), FileType('All', ['*']) ] fileSelectPopup = FileSelectPopup(self, file_types=fileTypes, title='Import PDB coordinates file', dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False,) fileName = fileSelectPopup.getFile() if not os.path.exists(fileName): showWarning('Failure','No such file.', parent=self) return if fileName: name = os.path.split(fileName)[1] if '.' in name: name = name.split('.')[0] pdbObj = PseudoPdbFormat(self.project, self, verbose=True) pdbObj.readCoordinates(fileName, minimalPrompts=True) self.eciFrame.updateAll() return pdbObj def showVersion(self): showInfo('Version', 'Version ' + self.versionInfo, parent=self) def changeFont(self, analysisProfile): if analysisProfile is self.analysisProfile: if self.font != analysisProfile.font: self.font = analysisProfile.font or DEFAULT_FONT self.setFont() def selectFont(self, font): # Only called from main menu option if self.project: self.analysisProfile.font = font def setFont(self, font=None, popup=None): if font is None: font = self.font or DEFAULT_FONT else: self.font = font if not popup: popup = self childList = popup.children.values() classes = [Tkinter.Button, Tkinter.Label, Tkinter.Menu, Tkinter.Entry, Tkinter.Checkbutton, Tkinter.Radiobutton] for child in childList: for clazz in classes: if isinstance(child, clazz): if hasattr(child, 'font'): if not child.font: child.config( font=font) else: child.config( font=font ) break if isinstance(child, Tkinter.Frame): child.font = font elif isinstance(child, ScrolledMatrix): child.setFont(font) if hasattr(child, 'children'): childList.extend( child.children.values() ) def initProject(self, project=None): self.project = project if project: self.initTopObjects(self.project) self.project.application = self.application self.setFont() webBrowser = ProjectWebBrowser(self.top, popup=self, project=project) self.setupSoftware() self.eciFrame.updateAll(project) self.setMenuState() def setupSoftware(self): project = self.project methodStore = project.currentMethodStore or \ project.findFirstMethodStore() or \ project.newMethodStore(name=project.name) software = methodStore.findFirstSoftware(name=PROGRAM_NAME, version=VERSION) if not software: software = methodStore.newSoftware(name=PROGRAM_NAME, version=VERSION) software.vendorName = 'PDBe & CCPN' #software.vendorAddress = '' software.vendorWebAddress = 'http://www.ebi.ac.uk/pdbe/' software.details = 'The PDBe & CCPN Entry Completion Interface' software.tasks = ['data deposition'] def setMenuState(self): if self.project: state = Tkinter.NORMAL else: state = Tkinter.DISABLED # Disable bits of the project menu if there's no project for option in ('Close','Save','Save As',): i = self.projectMenu.options.index(option) self.projectMenu.entryconfig(i, state=state) # Disable other menus if there's no project for menu in [self.otherMenu,]: # Include more menus in this list for i in range(len(menu.options)): menu.entryconfig(i, state=state) def askSaveFile(self): popup = self.openPopup('save_project', SaveProjectPopup) popup.refresh() def modalAskSaveFile(self): popup = SaveProjectPopup(self, project=self.project, dismiss_text='Cancel Quit', modal=True) did_save = popup.did_save popup.destroy() return did_save def quitSaveProject(self): if (self.project.activeRepositories): return self.saveFile() else: return self.modalAskSaveFile() def destroyPopups(self): for key in self.popups.keys(): popup = self.popups[key] popup.destroy() self.popups = {} def copyModifiedStorages(self): modifiedStorages = [storage for storage in self.project.storages if storage.isModified] if (self.project.isModified): modifiedStorages.append(self.project) for storage in modifiedStorages: self.copyStorage(storage) def saveFile(self): if not self.project: return False try: saveProject(self.project, createFallback=True) print 'successfully saved project' return True except IOError, e: showError('Saving file', str(e), parent=self) return False
class DangleGui(BasePopup): """ **A Bayesian inferential prediction method for protein backbone dihedral angles** DANGLE (Dihedral ANgles from Global Likelihood Estimates) predicts protein backbone Phi and Psi angles and secondary structure assignments solely from amino acid sequence information, experimental chemical shifts and a database of known protein structures and their associated shifts. This approach uses Bayesian inferential logic to analyse the likelihood of conformations throughout Ramachandran space, paying explicit attention to the population distributions expected for different amino acid residue types. Simple filtering procedures can identify the most "predictable" residues, yielding 92% of all Phi and Psi predictions accurate to within +/-30 degrees. In contrast to previous approaches, more than 80% of Phi or Psi predictions for glycine and pre-proline are reliable. Furthermore, DANGLE provides meaningful upper and lower bounds for the predictions which are shown to represent the precision of the prediction. Over 90% of the experimental dihedral angles in the set of test proteins are within the boundary ranges suggested by DANGLE. At a lower resolution level, the program correctly assigns each residue to one of three secondary structure states (H, E or C) in 85% of cases. DANGLE also provides an indication of the degeneracy in the relationship between shift measurements and conformation at each site. For more documentation see the `DANGLE web site`_ at SourceForge. .. _`DANGLE web site`: http://dangle.sourceforge.net/ **Reference** *Ming-Sin Cheung, Mahon L. Maguire, Tim J. Stevens, and R. William Broadhurst. "DANGLE: A Bayesian inferential method for predicting protein backbone dihedral angles and secondary structure." Journal of Magnetic Resonance Volume 202, Issue 2, February 2010, Pages 223-233* """ def __init__(self, root, programName=PROGRAM_NAME, **kw): self.parent = root self.programName = programName # Application object needed to store application-specific data with project self.application = Application(name=PROGRAM_NAME) self.versionInfo = 'Version ' + VERSION self.graphPopup = None self.analysisProfile = None # Application popup is a superclass of memops.editor.BasePoup BasePopup.__init__(self, parent=root, title=PROGRAM_NAME, location='+100+100', class_=self.application.name, **kw) 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() def makeProjectMenu(self): # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call menu.add_command(label='New', shortcut='N', command=self.newProject, tipText='Make a new, blank CCPN project. Closes any existing project') menu.add_command(label='Open', shortcut='O', command=self.openProject, tipText='Open a new CCPN project from disk, closing any existing project') menu.add_command(label='Close', shortcut='C', command=self.closeProject, tipText='Close the current CCPN project') menu.add_command(label='Save', shortcut='S', command=self.saveProject, tipText='Save the current CCPN prjoject at its pre-specified location') menu.add_command(label='Save As', shortcut='A', command=self.saveAsProject, tipText='Save the current CCPN project at a new location') menu.add_command(label='Backup', shortcut='B', command=self.backupProject, tipText='Manage options for automatic CCPN project backup') menu.add_command(label='Quit', shortcut='Q', command=self.quit, tipText='Exit from the DANGLE program') menu.add_command(label='Version', shortcut='V', command=self.showVersion) self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu) menu.options = ['New','Open','Close','Save','Save As','Backup','Quit','Version'] return menu def viewFileMenu(self): # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call menu.add_command(label='Prediction Graph', shortcut='G', command=self.viewGraph, tipText='Show a graphical view of the poredicted backbone dihedral angles') self.mainMenu.add_cascade(label='View', shortcut='V', menu=menu) menu.options = ['Prediction Graph'] return menu def makeAppearanceMenu(self): # The fonts menu is a pre-created widget fontsMenu = FontMenu(self.mainMenu, self.setFont, sizes=(8,10,12), doItalic=0, doBoldItalic=0, tearoff=0) # Plot color schemes colorMenu = Menu(self.mainMenu, tearoff=0) colorMenu.add_radiobutton(label='Red', command=self.colorSchemeRed,) colorMenu.add_radiobutton(label='Rainbow', command=self.colorSchemeRainbow,) #colorMenu.add_radiobutton(label='Black', shortcut='B', command=self.colorSchemeBlack) #colorMenu.add_radiobutton(label='White', shortcut='W', command=self.colorSchemeWhite) # Submenu of the main menu menu = Menu(self.mainMenu, tearoff=0) # Only Fonts option so far menu.add_cascade(label='Plot Colour Scheme',shortcut='C', menu=colorMenu) menu.add_cascade(label='Fonts', shortcut='F', menu=fontsMenu) self.mainMenu.add_cascade(label='Appearance', shortcut='A', menu=menu) menu.options = ['Plot Colour Scheme','Fonts'] return menu def colorSchemeRed(self): self.dangleFrame.colorScheme = 'red' def colorSchemeRainbow(self): self.dangleFrame.colorScheme = 'rainbow' def colorSchemeBlack(self): self.dangleFrame.colorScheme = 'black' def colorSchemeWhite(self): self.dangleFrame.colorScheme = 'white' def viewGraph(self): phiData, psiData = self.dangleFrame.getPhiPsiPredictions() if self.graphPopup: self.graphPopup.open() else: self.graphPopup = DangleGraphPopup(self) dangleChain = self.dangleFrame.dangleChain good = [] med = [] bad = [] if dangleChain: resNum = 0 # In case no residues for dResidue in dangleChain.dangleResidues: resNum = dResidue.residue.seqCode nIslands = dResidue.numIslands if nIslands < 2: good.append((resNum, nIslands)) elif nIslands < 4: med.append((resNum, nIslands)) else: bad.append((resNum, nIslands)) good.append((resNum, 0)) # To bias the graph islandData = [good, med, bad] self.graphPopup.update(phiData,psiData,islandData) def newProject(self): if self.project: # Project already present if not self.closeProject(): # If we don't close the current project do nothing return name = askString(title='Project name', prompt='Enter project name:',parent=self) if name: # Make the API Project object project = Implementation.MemopsRoot(name=name) nmrProject = project.newNmrProject(name = project.name) self.initProject(project) def openProject(self): if self.project: if not self.closeProject(): return self.openPopup('open_project', OpenProjectPopup, callback=self.initProject) def openPopup(self, popup_name, clazz, *args, **kw): popup = self.popups.get(popup_name) if popup: popup.open() else: if self.analysisProfile: transient = self.analysisProfile.transientWindows else: transient = True # Below automatically opens popup popup = self.popups[popup_name] = clazz(self, project=self.project, transient=transient, *args, **kw) return popup def closeProject(self, queryClose=True, querySave=True): if queryClose: if (not showYesNo('Close project', 'Close current project?')): return False if querySave: if (not self.checkSaving()): return False self.destroyPopups() self.initProject() return True def saveProject(self): #if (self.project.isStored): self.saveFile() #else: # self.askSaveFile() def saveAsProject(self): self.askSaveFile() def backupProject(self): pass #self.openPopup('backup_project', BackupProjectPopup) def showVersion(self): showInfo('Version', self.versionInfo, parent=self) def setFont(self, fontName=None, popup=None): if fontName is None: if self.analysisProfile: # Get font specification saved as project application data self.font = self.analysisProfile.font else: self.font = fontName if self.analysisProfile: # Set font specification as project application data self.analysisProfile.font = fontName if not popup: popup = self childList = popup.children.values() classes = [Tkinter.Button, Tkinter.Label, Tkinter.Menu, Tkinter.Entry, Tkinter.Checkbutton, Tkinter.Radiobutton] for child in childList: for clazz in classes: if isinstance(child, clazz): if hasattr(child, 'font'): if not child.font: child.config( font=self.font) else: child.config( font=self.font ) break if hasattr(child, 'children'): childList.extend( child.children.values() ) def initProject(self, project=None): if project: self.project = project else: project = self.project self.setTitle(self.programName) if project: self.project.application = self.application self.setFont() self.dangleFrame.updateProject(project) self.setupSoftware() if not project.currentAnalysisProfile: analysisProfiles = project.sortedAnalysisProfiles() if analysisProfiles: project.currentAnalysisProfile = analysisProfiles[0] else: project.newAnalysisProfile(name=project.name) self.analysisProfile = project.currentAnalysisProfile self.setMenuState() def setupSoftware(self): project = self.project methodStore = project.currentMethodStore or \ project.findFirstMethodStore() or \ project.newMethodStore(name=project.name) software = methodStore.findFirstSoftware(name=PROGRAM_NAME, version=VERSION) if not software: software = methodStore.newSoftware(name=PROGRAM_NAME, version=VERSION) #software.vendorName = 'Nicole Cheung' #software.vendorAddress = '' #software.vendorWebAddress = 'http:' #software.details = '' def setMenuState(self): if self.project: state = Tkinter.NORMAL else: state = Tkinter.DISABLED # Disable bits of the project menu if there's no project for option in ('Save','Save As','Backup','Close'): i = self.projectMenu.options.index(option) self.projectMenu.entryconfig(i, state=state) # Disable bits of the project menu if not stand-alone if hasattr(self.parent, 'project'): for option in ('New','Open','Close'): i = self.projectMenu.options.index(option) self.projectMenu.entryconfig(i, state=Tkinter.DISABLED) # Disable other manus and view menu if there's no project for menu in [self.otherMenu,self.viewMenu]: # Include more menus in this list for i in range(len(menu.options)): menu.entryconfig(i, state=state) def askSaveFile(self): popup = self.openPopup('save_project', SaveProjectPopup) def modalAskSaveFile(self): popup = SaveProjectPopup(self, project=self.project, dismiss_text='Cancel Quit', modal=True) did_save = popup.did_save popup.destroy() return did_save def quitSaveProject(self): if self.project.activeRepositories: return self.saveFile() else: return self.modalAskSaveFile() def destroyPopups(self): for key in self.popups.keys(): popup = self.popups[key] popup.destroy() self.popups = {} def saveFile(self): if (not self.project): return False try: self.project.saveModified() print 'Successfully saved project' return True except IOError, e: showError('Saving file', str(e)) return False
def body(self, guiFrame): row = 0 col = 0 # frame = Frame( guiFrame ) # frame.grid(row=row, column=col, sticky='news') self.menuBar = Menu(guiFrame) self.menuBar.grid(row=row, column=col, sticky='ew') #---------------------------------------------------------------------------------- # Project frame #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(row, weight=1) # frame = LabelFrame(guiFrame, text='Project', font=medFont) row = +1 col = 0 frame = LabelFrame(guiFrame, text='Project', **labelFrameAttributes) print '>', frame.keys() frame.grid(row=row, column=col, sticky='nsew') frame.grid_columnconfigure(2, weight=1) # frame.grid_rowconfigure(0, weight=1) srow = 0 self.projectOptions = [ 'old', 'new from PDB', 'new from CCPN', 'new from CYANA' ] self.projOptionsSelect = RadioButtons(frame, selected_index=0, entries=self.projectOptions, direction='vertical', select_callback=self.updateGui) self.projOptionsSelect.grid(row=srow, column=0, rowspan=len(self.projectOptions), columnspan=2, sticky='w') if self.options.name: text = self.options.name else: text = '' # end if self.projEntry = Entry(frame, bd=1, text=text, returnCallback=self.updateGui) self.projEntry.grid(row=srow, column=2, columnspan=2, sticky='ew') # self.projEntry.bind('<Key>', self.updateGui) self.projEntry.bind('<Leave>', self.updateGui) projButton = Button(frame, bd=1, command=self.chooseOldProjectFile, text='browse') projButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.pdbEntry = Entry(frame, bd=1, text='') self.pdbEntry.grid(row=srow, column=2, sticky='ew') self.pdbEntry.bind('<Leave>', self.updateGui) pdbButton = Button(frame, bd=1, command=self.choosePdbFile, text='browse') pdbButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.ccpnEntry = Entry(frame, bd=1, text='') self.ccpnEntry.grid(row=srow, column=2, sticky='ew') self.ccpnEntry.bind('<Leave>', self.updateGui) ccpnButton = Button(frame, bd=1, command=self.chooseCcpnFile, text='browse') ccpnButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.cyanaEntry = Entry(frame, bd=1, text='') self.cyanaEntry.grid(row=srow, column=2, sticky='ew') self.cyanaEntry.bind('<Leave>', self.updateGui) cyanaButton = Button(frame, bd=1, command=self.chooseCyanaFile, text='browse') cyanaButton.grid(row=srow, column=3, sticky='ew') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 label = Label(frame, text='Project name:') label.grid(row=srow, column=0, sticky='nw') self.nameEntry = Entry(frame, bd=1, text='') self.nameEntry.grid(row=srow, column=2, sticky='w') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 self.openProjectButton = Button(frame, command=self.openProject, text='Open Project', **actionButtonAttributes) self.openProjectButton.grid(row=srow, column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # status #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(1, weight=0) srow = 0 frame = LabelFrame(guiFrame, text='Status', **labelFrameAttributes) frame.grid(row=srow, column=1, sticky='wnes') self.projectStatus = Text(frame, height=11, width=70, borderwidth=0, relief='flat') self.projectStatus.grid(row=0, column=0, sticky='wen') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 self.closeProjectButton = Button(frame, command=self.closeProject, text='Close Project', **actionButtonAttributes) self.closeProjectButton.grid(row=srow, column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # Validate frame #---------------------------------------------------------------------------------- row += 1 col = 0 frame = LabelFrame(guiFrame, text='Validate', **labelFrameAttributes) # frame = LabelFrame(guiFrame, text='Validate', font=medFont) frame.grid(row=row, column=col, sticky='nsew') # frame.grid_columnconfigure(2, weight=1) frame.grid_rowconfigure(0, weight=1) srow = 0 # label = Label(frame, text='validation') # label.grid(row=srow,column=0,sticky='nw') # # self.selectDoValidation = CheckButton(frame) # self.selectDoValidation.grid(row=srow, column=1,sticky='nw' ) # self.selectDoValidation.set(True) # # srow += 1 # label = Label(frame, text='') # label.grid(row=srow,column=0,sticky='nw') # # srow += 1 label = Label(frame, text='checks') label.grid(row=srow, column=0, sticky='nw') self.selectCheckAssign = CheckButton(frame) self.selectCheckAssign.grid(row=srow, column=1, sticky='nw') self.selectCheckAssign.set(True) label = Label(frame, text='assignments and shifts') label.grid(row=srow, column=2, sticky='nw') # srow += 1 # self.selectCheckQueen = CheckButton(frame) # self.selectCheckQueen.grid(row=srow, column=4,sticky='nw' ) # self.selectCheckQueen.set(False) # label = Label(frame, text='QUEEN') # label.grid(row=srow,column=5,sticky='nw') # # queenButton = Button(frame, bd=1,command=None, text='setup') # queenButton.grid(row=srow,column=6,sticky='ew') srow += 1 self.selectCheckResraint = CheckButton(frame) self.selectCheckResraint.grid(row=srow, column=1, sticky='nw') self.selectCheckResraint.set(True) label = Label(frame, text='restraints') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectCheckStructure = CheckButton(frame) self.selectCheckStructure.grid(row=srow, column=1, sticky='nw') self.selectCheckStructure.set(True) label = Label(frame, text='structural') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectMakeHtml = CheckButton(frame) self.selectMakeHtml.grid(row=srow, column=1, sticky='nw') self.selectMakeHtml.set(True) label = Label(frame, text='generate HTML') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectCheckScript = CheckButton(frame) self.selectCheckScript.grid(row=srow, column=1, sticky='nw') self.selectCheckScript.set(False) label = Label(frame, text='user script') label.grid(row=srow, column=0, sticky='nw') self.validScriptEntry = Entry(frame, bd=1, text='') self.validScriptEntry.grid(row=srow, column=2, columnspan=3, sticky='ew') scriptButton = Button(frame, bd=1, command=self.chooseValidScript, text='browse') scriptButton.grid(row=srow, column=5, sticky='ew') srow += 1 label = Label(frame, text='ranges') label.grid(row=srow, column=0, sticky='nw') self.rangesEntry = Entry(frame, text='') self.rangesEntry.grid(row=srow, column=2, columnspan=3, sticky='ew') # self.validScriptEntry = Entry(frame, bd=1, text='') # self.validScriptEntry.grid(row=srow,column=3,sticky='ew') # # scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') # scriptButton.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Run Validation', 'View Results', 'Setup QUEEN'] commands = [self.runCing, None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands, expands=True) buttonBar.grid(row=srow, column=0, columnspan=6, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.runButton = buttonBar.buttons[0] self.viewResultButton = buttonBar.buttons[1] self.queenButton = buttonBar.buttons[2] #---------------------------------------------------------------------------------- # Miscellaneous frame #---------------------------------------------------------------------------------- row += 0 col = 1 # frame = LabelFrame(guiFrame, text='Miscellaneous', font=medFont) frame = LabelFrame(guiFrame, text='Miscellaneous', **labelFrameAttributes) frame.grid(row=row, column=col, sticky='news') frame.grid_columnconfigure(2, weight=1) frame.grid_columnconfigure(4, weight=1, minsize=30) frame.grid_rowconfigure(0, weight=1) # Exports srow = 0 label = Label(frame, text='export to') label.grid(row=srow, column=0, sticky='nw') self.selectExportXeasy = CheckButton(frame) self.selectExportXeasy.grid(row=srow, column=1, sticky='nw') self.selectExportXeasy.set(True) label = Label(frame, text='Xeasy, Sparky, TALOS, ...') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportCcpn = CheckButton(frame) self.selectExportCcpn.grid(row=srow, column=1, sticky='nw') self.selectExportCcpn.set(True) label = Label(frame, text='CCPN') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportQueen = CheckButton(frame) self.selectExportQueen.grid(row=srow, column=1, sticky='nw') self.selectExportQueen.set(True) label = Label(frame, text='QUEEN') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportRefine = CheckButton(frame) self.selectExportRefine.grid(row=srow, column=1, sticky='nw') self.selectExportRefine.set(True) label = Label(frame, text='refine') label.grid(row=srow, column=2, sticky='nw') srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') # User script srow += 1 label = Label(frame, text='user script') label.grid(row=srow, column=0, sticky='nw') self.selectMiscScript = CheckButton(frame) self.selectMiscScript.grid(row=srow, column=1, sticky='nw') self.selectMiscScript.set(False) self.miscScriptEntry = Entry(frame, bd=1, text='') self.miscScriptEntry.grid(row=srow, column=3, sticky='ew') script2Button = Button(frame, bd=1, command=self.chooseMiscScript, text='browse') script2Button.grid(row=srow, column=4, sticky='ew') srow += 1 texts = ['Export', 'Run Script'] commands = [None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands, expands=True) buttonBar.grid(row=srow, column=0, columnspan=5, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.exportButton = buttonBar.buttons[0] self.scriptButton = buttonBar.buttons[1] #---------------------------------------------------------------------------------- # Textarea #---------------------------------------------------------------------------------- row += 1 guiFrame.grid_rowconfigure(row, weight=1) self.outputTextBox = ScrolledText(guiFrame) self.outputTextBox.grid(row=row, column=0, columnspan=2, sticky='nsew') self.redirectConsole() #---------------------------------------------------------------------------------- # Buttons #---------------------------------------------------------------------------------- row += 1 col = 0 texts = ['Quit', 'Help'] commands = [self.close, None] self.buttonBar = ButtonList(guiFrame, texts=texts, commands=commands, expands=True) self.buttonBar.grid(row=row, column=col, columnspan=2, sticky='ew') # self.openProjectButton = self.buttonBar.buttons[0] # self.closeProjectButton = self.buttonBar.buttons[1] # self.runButton = self.buttonBar.buttons[0] # self.viewResultButton = self.buttonBar.buttons[1] for button in self.buttonBar.buttons: button.config(**actionButtonAttributes)
class PulldownMenu(Frame): # if using indentation then should use list as stack only # in other words only delete or insert at end # entries entries must have attribute text_attr or if this is # None then assume that entries entries themselves provide name def __init__(self, parent, callback=None, entries=None, text_attr=None, colors=None, outline='#602000', fill='#B05848', label_color='#501000', selected_index=-1, indent='', extra='', sticky='w', do_initial_callback=True, force_callback=False, *args, **kw): if (entries is None): entries = [] Frame.__init__(self, parent, sticky=sticky, *args, **kw) self.text_attr = text_attr #indentation and extra string for popup information self.indent = indent self.extra = extra self.callback = callback self.do_initial_callback = do_initial_callback self.force_callback = force_callback frame = Frame(self) #frame = parent self.frame = frame self.bg = frame.cget('bg') self.outline = outline self.fill = fill self.label_color = label_color self.menu = Menu(parent, tearoff=0, borderwidth=1, activeborderwidth=1) self.menu.images = [] self.label = Label(self, foreground=label_color) self.first_pass = True #self.entries = entries self.entries = [] self.colors = [] self.setup(entries, selected_index, colors=colors) s = 10 self.canvas = Canvas(self, width=s, height=s, background=self.bg) self.label.bind("<Button-1>", self.labelPopup) # below does not work for some reason #self.bind("<Button-1>", self.labelPopup) # below does not work any more since can have submenus and # no way to reach those with below since involves leaving menu #self.menu.bind("<Leave>", self.popdown) self.menu.bind("<Leave>", self.leave) self.menu.bind("<Button-1>", self.buttonPress) self.poppedUpSubmenu = False self.canvas.bind("<Button-1>", self.canvasPopup) self.canvas.bind("<Configure>", self.resizeCallback) self.label.grid(row=0, column=0, sticky=Tkinter.W) self.canvas.grid(row=0, column=1, sticky=Tkinter.E, padx=2) def leave(self, event): if (not self.poppedUpSubmenu): x = event.x y = event.y x1 = self.menu.winfo_width() y1 = self.menu.winfo_height() if (x < 0) or (y < 0) or (x >= x1) or (y >= y1): self.popdown() def buttonPress(self, event): if (event.widget != self.menu): return for n in range(len(self.entries) - 1, -1, -1): if event.y >= self.menu.yposition(n): break else: return item = self.entries[n] if (isinstance(item, {}.__class__) and item['kind'] == 'cascade'): self.poppedUpSubmenu = True else: self.poppedUpSubmenu = False def resizeCallback(self, *event): w = self.canvas.winfo_width() / 2 h = self.canvas.winfo_height() / 2 self.canvas.delete('all') self.canvas.create_polygon(1, 1, w, 2 * h - 1, 2 * w - 1, 1, fill=self.fill, outline=self.outline) def getEntry(self, entry_index, entries=None): if not entries: entries = self.entries if type(entry_index) == types.TupleType: e = entry_index[0] if len(entry_index) > 1: items = entries[e]['submenu'] entry = self.getEntry(entry_index[1:], items) else: entry = entries[e]['label'] elif (entry_index >= 0): entry = entries[entry_index] else: entry = None return entry def getEntryText(self, entry_index, entries=None): if not entries: entries = self.entries if type(entry_index) in (types.TupleType, types.ListType): e = entry_index[0] if len(entry_index) > 1: items = entries[e]['submenu'] text = self.getEntryText(entry_index[1:], items) else: text = entries[e]['label'] elif (entry_index != -1): #print 'getEntryText', entry_index, entries entry = entries[entry_index] if (self.text_attr): text = getattr(entry, self.text_attr) else: text = entry else: text = '' # TBD: for now text returned should not be unicode text = str(text) # below did not work for one person (Chinese characters??) but above did ###text = text.encode('utf-8') return text def setup(self, entries, selected_index, first_pass=True, colors=None): #print 'setup', entries, selected_index if first_pass is not None: self.first_pass = first_pass self.clearMenuItems() if (entries): e = list(entries) else: e = [No_entries_label] self.entries = e self.colors = colors or [None] * len(e) if type(selected_index) in (types.TupleType, types.ListType): if (not selected_index or selected_index[0] >= len(entries)): selected_index = -1 else: if (selected_index >= len(entries)): selected_index = -1 if (selected_index == -1): selected_index = 0 self.selected_index = -1 # changed in setSelectedIndex() self.setMenuItems() self.setSelectedIndex(selected_index) def substituteCascadeCallbacks(self, item, selected_index): if (item['kind'] == 'cascade'): n = 0 for subitem in item['submenu']: self.substituteCascadeCallbacks(subitem, selected_index + [n]) n = n + 1 else: callback = item.get('command') if (callback): label = item['label'] item['command'] = lambda: self.cascadeCallback( callback, label, tuple(selected_index)) def cascadeCallback(self, callback, label, selected_index): self.selected_index = selected_index self.setLabel(selected_index) callback(selected_index, label) def setMenuItems(self): self.menu.images = [] for n in range(len(self.entries)): columnbreak = 0 if n and n % 20 == 0: columnbreak = 1 item = self.entries[n] color = None if n < len(self.colors): color = self.colors[n] if isinstance(item, {}.__class__): if (item['kind'] == 'cascade'): self.substituteCascadeCallbacks(item, [n]) else: t = (self.indent * n) + self.extra + str(self.getEntryText(n)) command = lambda n=n: self.setSelectedIndex(n) if color: image = self.makeColorTile(color) item = { 'kind': 'command', 'accelerator': t, 'command': command, 'image': image, 'columnbreak': columnbreak } else: item = { 'kind': 'command', 'label': t, 'command': command, 'columnbreak': columnbreak } self.menu.addMenuItem(item) def clearMenuItems(self): if self.entries: self.menu.delete(0, len(self.entries)) # below assumes entry_index is integer not tuple def insert(self, entry_index, entry, make_selected=False, color=None): if (self.haveNoEntries()): if (entry_index != 0): return elif ((entry_index < 0) or (entry_index >= len(self.entries))): return self.clearMenuItems() self.checkForNone() self.entries.insert(entry_index, entry) self.colors.insert(entry_index, color) self.setMenuItems() if (make_selected or (self.selected_index == -1)): self.setSelectedIndex(entry_index, force_callback=True) else: self.setSelectedIndex(self.selected_index) # below assumes entry is integer not tuple def append(self, entry, make_selected=False, color=None): self.clearMenuItems() self.checkForNone() self.entries.append(entry) self.colors.append(color) self.setMenuItems() if (make_selected or (self.selected_index == -1)): self.setSelectedIndex(len(self.entries) - 1, force_callback=True) else: self.setSelectedIndex(self.selected_index) def checkForNone(self): if (self.haveNoEntries()): self.entries = [] self.colors = [] self.menu.delete(0) def haveNoEntries(self): if (len(self.entries) == 1 and self.entries[0] == No_entries_label): return True else: return False def baseIndex(self, ind): if type(ind) == types.TupleType: ind = ind[0] return ind # below assumes entry_index is integer not tuple def delete(self, entry_index, n=1): if (self.haveNoEntries()): return if ((entry_index < 0) or (entry_index >= len(self.entries))): return self.clearMenuItems() n1 = entry_index n2 = n1 + n m = self.baseIndex(self.selected_index) del self.entries[n1:n2] del self.colors[n1:n2] if (not self.entries): self.entries = [No_entries_label] self.colors = [None] self.setMenuItems() if ((m >= n1) and (m < n2)): if (n1 == 0): selected_index = 0 else: selected_index = n1 - 1 self.setSelectedIndex(selected_index, force_callback=True) def replace(self, entries, selected_index=-1, colors=None): self.menu.delete(0, len(self.entries)) self.setup(entries, selected_index, first_pass=False, colors=colors) def popdown(self, *event): self.menu.unpost() def setLabel(self, selected_index): text = self.getEntryText(selected_index) if (not text): text = self.extra # arbitrary self.label.set(text=text) def labelPopup(self, event): self.poppedUpSubmenu = False s = self.baseIndex(self.selected_index) x = event.x_root - event.x + 2 y = event.y_root - event.y - \ max(0, s) * (self.label.winfo_height() + 1) self.menu.post(x, y) def canvasPopup(self, event): s = self.baseIndex(self.selected_index) x = event.x_root - event.x - self.label.winfo_width() + 2 y = event.y_root - event.y - \ max(0, s) * (self.label.winfo_height() + 1) + \ self.canvas.winfo_height() - self.label.winfo_height() self.menu.post(x, y) def getSelectedIndex(self): return self.selected_index def setSelectedIndex(self, selected_index, force_callback=False): if (force_callback or self.force_callback or \ (selected_index != self.selected_index)): #print 'setSelectedIndex', self.entries, selected_index, self.selected_index, self.first_pass self.selected_index = selected_index self.setLabel(selected_index) if (self.callback): if (self.haveNoEntries()): if (not self.first_pass): self.callback(-1, None) elif (selected_index != -1): if (not self.first_pass or self.do_initial_callback): self.callback(selected_index, self.entries[selected_index]) self.first_pass = False def get(self): return self.getSelected() def getSelected(self): ind = self.getSelectedIndex() if (ind == -1): return None else: return self.getEntry(ind) def set(self, selected): self.setSelected(selected) def findEntryIndex(self, entry, entries=None): #print 'findEntryIndex1', entry, entries if (entries): noEntries = True else: noEntries = False entries = self.entries try: ind = entries.index(entry) return ind except: pass #print 'findEntryIndex2', entry, entries for n in range(len(entries)): e = entries[n] #print 'findEntryIndex3', entry, e if e == entry: if noEntries: return [n] else: return n elif type(e) == types.DictType: if (len(entries) > 1): try: ind = self.findEntryIndex(entry, e['submenu']) return [n] + ind except: pass else: if (entry == e['label']): return [n] raise 'unknown entry "%s"' % entry # selects first item found in entries which matches def setSelected(self, selected): #print 'setSelected1', selected, type(selected), self.entries try: selected_index = self.findEntryIndex(selected) except: #selected_index = -1 return #print 'setSelected2', selected_index self.setSelectedIndex(selected_index) def makeColorTile(self, color): image = Tkinter.PhotoImage() self.menu.images.append(image) if type(color) == type([]): colors = [scaleColor(self.menu, c, 1.0) for c in color] else: colors = [ scaleColor(self.menu, color, 1.0), ] cols = max(8, len(colors)) for x in range(cols): i = x % len(colors) c = colors[i] for y in range(16): image.put('{%s %s}' % (c, c), to=(2 * x, y)) return image
def makeProjectMenu(self): # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) menu.add_command(label='Save', shortcut='S', command=self.saveProject) menu.add_command(label='Save As', shortcut='A', command=self.saveAsProject) menu.add_command(label='Quit', shortcut='Q', command=self.quit) menu.add_command(label='Version', shortcut='V', command=self.showVersion) self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu) menu.options = ['Save', 'Save As', 'Quit', 'Version'] return menu
class ScrolledCanvas(Frame): def __init__(self, parent, resizeCallback=None, width=600, height=600, *args, **kw): self.bbox = None self.busy = 0 self.initialX = None self.initialY = None self.resizeCallback = resizeCallback apply(Frame.__init__, (self, parent) + args, kw) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) self.menu = Menu(self, tearoff=0, include_event=True) self.configMenu() self.canvas = Canvas(self, relief='flat', borderwidth=0, width=width, height=height) self.canvas.configure(xscrollincrement=2, yscrollincrement=2) self.canvas.grid(row=0, column=0, sticky=Tkinter.NSEW) self.horizScrollbar = Tkinter.Scrollbar(self, bg=self.cget('bg'), command=self.canvas.xview, orient=Tkinter.HORIZONTAL, borderwidth=1) self.vertScrollbar = Tkinter.Scrollbar(self, bg=self.cget('bg'), command=self.canvas.yview, orient=Tkinter.VERTICAL, borderwidth=1) self.canvas.configure(xscrollcommand=self.horizScrollbar.set, yscrollcommand=self.vertScrollbar.set) self.canvas.bind('<Configure>', self.resizeAfter) self.canvas.bind('<Button-1>', self.mouseButton1) self.canvas.bind('<Button-2>', self.mouseButton2) self.canvas.bind('<Button-3>', self.mouseButton3) self.canvas.bind('<ButtonRelease-1>', self.mouseButtonRelease1) self.canvas.bind('<ButtonRelease-2>', self.mouseButtonRelease2) self.canvas.bind('<B2-Motion>', self.mouseScroll) self.canvas.bind('<B3-Motion>', self.doNothing) self.canvas.bind('<Motion>', self.mouseEnter) self.canvas.bind('<Enter>', self.mouseEnter) def doNothing(self, event): pass def mouseEnter(self, event): if self.menu.winfo_ismapped(): self.removeMenu() def refresh(self): self.bbox = self.canvas.bbox('all') bbox = self.bbox if not bbox: self.busy = 0 return cWidth = int(self.canvas.cget('width')) cHeight = int(self.canvas.cget('height')) if cHeight > bbox[3] - bbox[1]: self.vertScrollbar.grid_forget() else: self.vertScrollbar.grid(row=0, column=1, sticky=Tkinter.NS) if cWidth > bbox[2] - bbox[0]: self.horizScrollbar.grid_forget() else: self.horizScrollbar.grid(row=1, column=0, sticky=Tkinter.EW) x1 = bbox[0] y1 = bbox[1] x2 = max(bbox[0] + cWidth, bbox[2]) y2 = max(bbox[1] + cHeight, bbox[3]) self.canvas.configure(scrollregion=(x1, y1, x2, y2)) self.update_idletasks() self.busy = 0 def printCanvas(self, *event): fileTypes = [FileType('PostScript', ['*.ps']), FileType('All', ['*'])] fileSelectPopup = FileSelectPopup(self, file_types=fileTypes, title='Print canvas to file', dismiss_text='Cancel', selected_file_must_exist=False) fileName = fileSelectPopup.getFile() self.bbox = bbox = self.canvas.bbox('all') w = bbox[2] - bbox[0] h = bbox[3] - bbox[1] self.canvas.postscript(colormode='color', file=fileName, x=bbox[0], y=bbox[1], width=w + 2, pagewidth='21.c', height=h + 2) def configMenu(self): items = [ { 'kind': 'command', 'label': 'Print to file', 'command': self.printCanvas }, ] self.menu.setMenuItems(items) def removeMenu(self, *event): self.menu.unpost() def mouseButton3(self, event): self.menu.popupMenu(event) def mouseButton1(self, event): self.removeMenu() if not self.initialX: self.initialX = event.x self.initialY = event.y def mouseButton2(self, event): self.removeMenu() if not self.initialX: self.initialX = event.x self.initialY = event.y self.initialPX = self.horizScrollbar.get()[0] self.initialPY = self.vertScrollbar.get()[0] def mouseButtonRelease1(self, event): self.initialX = None self.initialY = None def mouseButtonRelease2(self, event): self.initialX = None self.initialY = None self.initialPX = None self.initialPY = None def mouseScroll(self, event): self.menu.unpost() bbox = self.bbox if not bbox: return bW = float(bbox[2] - bbox[0]) bH = float(bbox[3] - bbox[1]) cWidth = int(self.canvas.cget('width')) cHeight = int(self.canvas.cget('height')) if cWidth < bW: dx = self.initialX - event.x prop = self.initialPX + (dx / bW) self.canvas.xview('moveto', prop) if cHeight < bH: dy = self.initialY - event.y prop = self.initialPY + (dy / bH) self.canvas.yview('moveto', prop) def resizeAfter(self, event): if self.busy: return else: self.busy = 1 self.removeMenu() self.after_idle(lambda: self.resize(event)) def resize(self, event): if self.resizeCallback: self.after_idle( lambda: self.resizeCallback(event.width, event.height)) self.canvas.configure(width=event.width, height=event.height) self.after_idle(self.refresh)
class LinkChart(Frame): def __init__(self, parent, scrollX=True, scrollY=True, *args, **kw): self.parent = parent self.scrollX = scrollX self.scrollY = scrollY self.prototypes = [] self.nodes = [] self.node = None # Selected self.links = [] self.link = None # Selected self.objDict = {} # Map canvas to nodes, links self.cornerDict = {} self.editWidget = None self.mouseOver = None self.inMotion = None self.inMotion2 = None self.inMotion3 = None self.dragRegion = None self._resizeBusy = False self.selectedNodes = [] self.selectedLinks = [] self.highlightNodes = [] self.highlightLinks = [] kw['relief'] = 'flat' kw['borderwidth'] = 0 Frame.__init__(self, parent, *args, **kw) self.canvas = canvas = Canvas(self, relief='flat', borderwidth=0) self.canvas.configure(xscrollincrement=2, yscrollincrement=2, bg=self.cget('bg')) self.canvas.grid(row=0, column=0, sticky='nsew') if scrollX: self.horizScrollbar = Tkinter.Scrollbar(self, bg=self.cget('bg'), command=self.canvas.xview, orient=Tkinter.HORIZONTAL, borderwidth=1) self.canvas.configure(xscrollcommand=self.horizScrollbar.set) if scrollY: self.vertScrollbar = Tkinter.Scrollbar(self, bg=self.cget('bg'), command=self.canvas.yview, orient=Tkinter.VERTICAL, borderwidth=1) self.canvas.configure(yscrollcommand=self.vertScrollbar.set) canvas.bind('<Button-1>', self._mouseSingleClick) if not isWindowsOS(): canvas.bind('<Button-4>', self.scrollUp) canvas.bind('<Button-5>', self.scrollDown) else: canvas.bind('<MouseWheel>', self._windowsOsScroll) canvas.bind('<Double-1>', self._mouseDoubleClick) canvas.bind('<B1-Motion>', self._mouseDrag) canvas.bind('<ButtonRelease-1>', self._mouseRelease) canvas.bind('<Motion>', self._mouseEnter) canvas.bind('<Enter>', self._mouseEnter) canvas.bind('<Leave>', self._mouseLeave) canvas.bind('<KeyPress-Up>', self._moveUp) canvas.bind('<KeyPress-Down>', self._moveDown) canvas.bind('<KeyPress-Right>', self._moveRight) canvas.bind('<KeyPress-Left>', self._moveLeft) canvas.bind('<KeyPress-Delete>', self.deleteSelected) self.bind('<Configure>', self._resizeAfter) self.menu = Menu(self, tearoff=False) alignItems = [{ 'kind': 'command', 'label': 'Y axis', 'command': self._alignHorizontal }, { 'kind': 'command', 'label': 'X axis', 'command': self._alignVertical }] distributeItems = [{ 'kind': 'command', 'label': 'Horizontal', 'command': self._distributeHorizontal }, { 'kind': 'command', 'label': 'Verical', 'command': self._distributeVertical }] menuItems = [ { 'kind': 'cascade', 'label': 'Align', 'submenu': alignItems }, #0 { 'kind': 'cascade', 'label': 'Distribute', 'submenu': distributeItems }, #1 { 'kind': 'command', 'label': 'Link Selected', 'command': self.linkSelected }, #2 { 'kind': 'command', 'label': 'Reset Links', 'command': self._resetLinks }, #3 { 'kind': 'separator' }, { 'kind': 'command', 'label': 'Delete Links', #5 'command': self.deleteLinks }, { 'kind': 'command', 'label': 'Delete Items', #6 'command': self.deleteNodes }, { 'kind': 'separator' }, { 'kind': 'command', 'label': 'Save PostScript File', 'command': self.printCanvas }, ] self.menuItems = menuItems self.menu.setMenuItems(menuItems) canvas.bind('<ButtonPress-3>', self._popupMenu) self._drawAfter() def _resizeAfter(self, event): if self._resizeBusy: return self._resizeBusy = True self._popdownMenu(event) self.after_idle(lambda: self._refreshScrollbars(event)) def _refreshScrollbars(self, event): bbox = self.canvas.bbox('all') if not bbox: self._resizeBusy = False return cWidth = event.width cHeight = event.height vertScrollbar = self.vertScrollbar horizScrollbar = self.horizScrollbar xSpace = bbox[2] + bbox[0] # Symmetric space ySpace = bbox[3] + bbox[1] horizHeight = int(horizScrollbar.winfo_height()) vertWidth = int(vertScrollbar.winfo_width()) if cHeight < ySpace + horizHeight: vertScrollbar.grid(row=0, column=1, sticky='ns') cWidth -= vertWidth else: vertScrollbar.grid_forget() if cWidth < xSpace + vertWidth: horizScrollbar.grid(row=1, column=0, sticky='ew') cHeight -= horizHeight else: horizScrollbar.grid_forget() x1 = 0 y1 = 0 x2 = max(cWidth, xSpace) y2 = max(cHeight, ySpace) self.canvas.configure(width=cWidth, height=cHeight) self.canvas.configure(scrollregion=(x1, y1, x2, y2)) self.update_idletasks() self._resizeBusy = False def _popupMenu(self, event): self._finishEdit() self._configMenu() self.menu.popupMenu(event) def _popdownMenu(self, event): self._finishEdit() self.menu.unpost() def _configMenu(self): if self.selectedLinks: self.menu.entryconfig(5, state=ACTIVE) self.menu.entryconfig(3, state=ACTIVE) else: self.menu.entryconfig(5, state=INACTIVE) self.menu.entryconfig(3, state=INACTIVE) if self.selectedNodes: self.menu.entryconfig(2, state=ACTIVE) self.menu.entryconfig(6, state=ACTIVE) else: self.menu.entryconfig(2, state=INACTIVE) self.menu.entryconfig(6, state=INACTIVE) if self.selectedNodes or self.selectedLinks: self.menu.entryconfig(0, state=ACTIVE) self.menu.entryconfig(1, state=ACTIVE) else: self.menu.entryconfig(0, state=INACTIVE) self.menu.entryconfig(1, state=INACTIVE) def _resetLinks(self): for link in self.selectedLinks: link.resetCoords() def _alignSelected(self, vertical=False, horizontal=False): obj = self.node or self.link if not obj: return x0, y0 = obj.coords objs = self.selectedNodes + self.selectedLinks n = len(objs) if n < 2: return if horizontal: for obj in objs: obj.move(obj.coords[0], y0) if vertical: for obj in objs: obj.move(x0, obj.coords[1]) def _distributeSelected(self, vertical=False, horizontal=False): xCoords = [] yCoords = [] objs = self.selectedNodes + self.selectedLinks n = len(objs) if n < 3: return for obj in objs: x, y = obj.coords xCoords.append((x, obj)) yCoords.append((y, obj)) if horizontal: xCoords.sort() xA = xCoords[0][0] dx = (xCoords[-1][0] - xA) / float(n - 1) for i, (x0, obj) in enumerate(xCoords): y = obj.coords[1] x = xA + (i * dx) obj.move(x, y) if vertical: yCoords.sort() yA = yCoords[0][0] dy = (yCoords[-1][0] - yA) / float(n - 1) for i, (y0, obj) in enumerate(yCoords): x = obj.coords[0] y = yA + (i * dy) obj.move(x, y) def _alignHorizontal(self): self._alignSelected(horizontal=True) def _alignVertical(self): self._alignSelected(vertical=True) def _distributeHorizontal(self): self._distributeSelected(horizontal=True) def _distributeVertical(self): self._distributeSelected(vertical=True) def linkSelected(self): nodes = self.selectedNodes n = len(nodes) if n > 1: for i in range(n - 1): nodeA = nodes[i] for j in range(i + 1, n): nodeB = nodes[j] for link in nodeA.links: if nodeB in link.nodes: #print link, link.nodes, nodeA, nodeB break else: link = Link(self, nodeA, nodeB, text='*') #print link def deleteNodes(self): if self.selectedNodes: msg = 'Really delete %d selected nodes?' % len(self.selectedNodes) if showOkCancel('Confirm', msg, parent=self): for node in self.selectedNodes[:]: node.delete() self.selectedNodes = [] self.node = None def deleteLinks(self): if self.selectedLinks: msg = 'Really delete %d selected links?' % len(self.selectedLinks) if showOkCancel('Confirm', msg, parent=self): for link in self.selectedLinks[:]: link.delete() self.selectedLinks = [] self.link = None def deleteSelected(self, event=None): objs = self.selectedLinks + self.selectedNodes if objs: n1 = len(self.selectedNodes) n2 = len(self.selectedLinks) msg = 'Really delete %d selected objects?\n' % (n1 + n2) msg += '(%d nodes, %d links)' % (n1, n2) if showOkCancel('Confirm', msg, parent=self): for obj in objs: obj.delete() self.selectedLinks = [] self.link = None self.selectedNodes = [] self.node = None def printCanvas(self, *event): from memops.gui.FileSelect import FileType from memops.gui.FileSelectPopup import FileSelectPopup fileTypes = [FileType('PostScript', ['*.ps']), FileType('All', ['*'])] fileSelectPopup = FileSelectPopup(self, file_types=fileTypes, title='Print canvas to file', dismiss_text='Cancel', selected_file_must_exist=False) fileName = fileSelectPopup.getFile() self.postscript(colormode='color', file=fileName) def _clearSelection(self): for node in self.selectedNodes: node.isSelected = False for link in self.selectedLinks: link.isSelected = False self.selectedNodes = [] self.selectedLinks = [] self.link = None self.node = None def _clearHighlights(self): for node in self.highlightNodes: node.highlight = False for link in self.highlightLinks: link.highlight = False self.mouseOver = None self.highlightNodes = [] self.highlightLinks = [] def _mouseSingleClick(self, event): self._mouseClick(event) def _mouseDoubleClick(self, event): self._mouseClick(event, True) def _mouseClick(self, event, edit=False): #self.menu.popdownMenu(event) self._finishEdit() canvas = event.widget canvas.focus_force() x = canvas.canvasx(event.x) y = canvas.canvasy(event.y) items = canvas.find('overlapping', x - 1, y - 1, x + 1, y + 1) #item = self.find('closest',x,y)[0] if not items: self._clearSelection() self._clearHighlights() self.draw() return objs = [ self.objDict.get(item) for item in items if self.objDict.get(item) ] for obj in objs: if isinstance(obj, Node): if not (event.state & 4 or event.state & 1): self._clearSelection() obj.isSelected = True self.node = obj if obj not in self.selectedNodes: self.selectedNodes.append(obj) break else: self.node = None for obj in objs: if isinstance(obj, Link): if not (event.state & 4 or event.state & 1): self._clearSelection() obj.isSelected = True self.link = obj if obj not in self.selectedLinks: self.selectedLinks.append(obj) break else: self.link = None self._drawAfter() if not obj: return if edit and obj.editWidget: obj.edit() self.editWidget = obj.editWidget def _clearDragRegion(self, canvas): if self.dragRegion: canvas.delete(self.dragRegion[0]) self.dragRegion = None def _mouseEnter(self, event): self.menu.popdownMenu(event) canvas = event.widget canvas.focus_force() x = canvas.canvasx(event.x) y = canvas.canvasy(event.y) items = canvas.find('overlapping', x - 1, y - 1, x + 1, y + 1) #item = self.find('closest',x,y)[0] if not items: self._clearHighlights() self.draw() return obj = self.objDict.get(items[0]) self._clearHighlights() if obj is None: self.draw() return if obj is self.mouseOver: if self.inMotion2: for item in items: if self.cornerDict.has_key(item): self.inMotion2 = None break return objs = [ self.objDict.get(item) for item in items if self.objDict.get(item) ] for obj in objs: if isinstance(obj, Node): self.highlightNodes = [ obj, ] break else: for obj in objs: if isinstance(obj, Link): self.highlightLinks = [ obj, ] obj.highlight = True self.mouseOver = obj self.draw() def _mouseLeave(self, event): #self._mouseRelease(event) #self._finishEdit() self._clearHighlights() self.draw() def _mouseDrag(self, event): self.menu.popdownMenu(event) canvas = event.widget canvas.focus_force() x = canvas.canvasx(event.x) y = canvas.canvasy(event.y) #width = int(canvas.winfo_width()) #height = int (canvas.winfo_height()) # #if not (0 < x < width) or not (0 < y < height): # self._mouseRelease(event) # return inMotion = self.inMotion objs = self.selectedNodes + self.selectedLinks if objs: items = canvas.find('overlapping', x - 1, y - 1, x + 1, y + 1) if not inMotion: for item in items: if self.inMotion2 or self.cornerDict.has_key(item): obj = self.node x1, y1 = obj.coords # offsets dx = abs(x - x1) dy = abs(y - y1) size = max(dx, dy) + 1 obj.width = size obj.draw() self.inMotion2 = True return if inMotion: offsets = inMotion # Get offsets else: offsets = [] for obj in objs: x1, y1 = obj.coords # offsets dx = x - x1 # Offset relative to centre dy = y - y1 if isinstance(obj, Node) and obj.isPrototype: obj = obj.copy() offsets.append((dx, dy, obj)) self.inMotion = offsets # Store click offset and Node #print event, event.widget._root() for dx, dy, obj in offsets: x2 = x - dx y2 = y - dy obj.move(x2, y2) x0, y0 = event.x_root, event.y_root under = self.winfo_containing(x0, y0) if isinstance(under, Canvas): under = under.parent if isinstance(under, LinkChart) and (under is not self): for dx, dy, obj in offsets: if not isinstance(obj, Node): continue original = obj.original if original and original.isPrototype: xT = x0 - under.winfo_rootx() - dx yT = y0 - under.winfo_rooty() - dy if original.spawn: original.spawn.move(xT, yT) else: original.spawn = original.copy(under, coords=(xT, yT)) else: for dx, dy, obj in offsets: if not isinstance(obj, Node): continue original = obj.original if original and original.spawn: original.spawn.delete() original.spawn = None else: if self.inMotion3: x0, y0, = self.inMotion3 else: #self._mouseRelease(event) x0 = x y0 = y self.inMotion3 = (x, y) if self.dragRegion: item = self.dragRegion[0] canvas.coords(item, x0, y0, x, y) else: item = canvas.create_rectangle(x0, y0, x, y, outline='#008000', fill='#00E000', stipple='gray25') self.dragRegion = (item, x0, y0, x, y) def _mouseRelease(self, event): canvas = event.widget if self.dragRegion: item, x1, y1, x2, y2 = self.dragRegion xCoords = [x1, x2] yCoords = [y1, y2] xCoords.sort() yCoords.sort() x1, x2 = xCoords y1, y2 = yCoords self.node = None self.selectedNodes = [] for node in self.nodes: x0, y0 = node.coords if (x1 < x0 < x2) and (y1 < y0 < y2): self.selectedNodes.append(node) node.isSelected = True self.node = node else: node.isSelected = False self.link = None self.selectedLinks = [] for link in self.links: x0, y0 = link.coords if (x1 < x0 < x2) and (y1 < y0 < y2): self.selectedLinks.append(link) link.isSelected = True self.link = link else: link.isSelected = False self._clearDragRegion(canvas) self.draw() if self.inMotion: for dx, dy, obj in self.inMotion: if isinstance( obj, Node) and obj.original and obj.original.isPrototype: if obj.original.spawn: obj.original.spawn.original = None obj.original.spawn = None obj.delete() self.inMotion = None self.inMotion2 = None self.inMotion3 = None def _finishEdit(self): if self.editWidget: self.focus_force() self.editWidget.commit() self.editWidget.hide() self.editWidget = None def _moveUp(self, event): self._moveSelected(event, 0, -1) def _moveDown(self, event): self._moveSelected(event, 0, 1) def _moveRight(self, event): self._moveSelected(event, 1, 0) def _moveLeft(self, event): self._moveSelected(event, -1, 0) def _moveSelected(self, event, dx, dy): if not (event.state & 4 or event.state & 1): dx *= MOVE_STEP dy *= MOVE_STEP for node in self.selectedNodes: x0, y0 = node.coords node.move(x0 + dx, y0 + dy) for link in self.selectedLinks: x0, y0 = link.coords link.move(x0 + dx, y0 + dy) def scrollUp(self, event=None): pass def scrollDown(self, event): pass def _windowsOsScroll(self, event=None): delta = event.delta if delta > 0: self.scrollUp(event) elif delta < 0: self.scrollDown(event) def _drawAfter(self): self.after_idle(self.draw) def draw(self): for link in self.links: link.draw() for node in self.nodes: node.draw()
def __init__(self, parent, scrollX=True, scrollY=True, *args, **kw): self.parent = parent self.scrollX = scrollX self.scrollY = scrollY self.prototypes = [] self.nodes = [] self.node = None # Selected self.links = [] self.link = None # Selected self.objDict = {} # Map canvas to nodes, links self.cornerDict = {} self.editWidget = None self.mouseOver = None self.inMotion = None self.inMotion2 = None self.inMotion3 = None self.dragRegion = None self._resizeBusy = False self.selectedNodes = [] self.selectedLinks = [] self.highlightNodes = [] self.highlightLinks = [] kw['relief'] = 'flat' kw['borderwidth'] = 0 Frame.__init__(self, parent, *args, **kw) self.canvas = canvas = Canvas(self, relief='flat', borderwidth=0) self.canvas.configure(xscrollincrement=2, yscrollincrement=2, bg=self.cget('bg')) self.canvas.grid(row=0, column=0, sticky='nsew') if scrollX: self.horizScrollbar = Tkinter.Scrollbar(self, bg=self.cget('bg'), command=self.canvas.xview, orient=Tkinter.HORIZONTAL, borderwidth=1) self.canvas.configure(xscrollcommand=self.horizScrollbar.set) if scrollY: self.vertScrollbar = Tkinter.Scrollbar(self, bg=self.cget('bg'), command=self.canvas.yview, orient=Tkinter.VERTICAL, borderwidth=1) self.canvas.configure(yscrollcommand=self.vertScrollbar.set) canvas.bind('<Button-1>', self._mouseSingleClick) if not isWindowsOS(): canvas.bind('<Button-4>', self.scrollUp) canvas.bind('<Button-5>', self.scrollDown) else: canvas.bind('<MouseWheel>', self._windowsOsScroll) canvas.bind('<Double-1>', self._mouseDoubleClick) canvas.bind('<B1-Motion>', self._mouseDrag) canvas.bind('<ButtonRelease-1>', self._mouseRelease) canvas.bind('<Motion>', self._mouseEnter) canvas.bind('<Enter>', self._mouseEnter) canvas.bind('<Leave>', self._mouseLeave) canvas.bind('<KeyPress-Up>', self._moveUp) canvas.bind('<KeyPress-Down>', self._moveDown) canvas.bind('<KeyPress-Right>', self._moveRight) canvas.bind('<KeyPress-Left>', self._moveLeft) canvas.bind('<KeyPress-Delete>', self.deleteSelected) self.bind('<Configure>', self._resizeAfter) self.menu = Menu(self, tearoff=False) alignItems = [{ 'kind': 'command', 'label': 'Y axis', 'command': self._alignHorizontal }, { 'kind': 'command', 'label': 'X axis', 'command': self._alignVertical }] distributeItems = [{ 'kind': 'command', 'label': 'Horizontal', 'command': self._distributeHorizontal }, { 'kind': 'command', 'label': 'Verical', 'command': self._distributeVertical }] menuItems = [ { 'kind': 'cascade', 'label': 'Align', 'submenu': alignItems }, #0 { 'kind': 'cascade', 'label': 'Distribute', 'submenu': distributeItems }, #1 { 'kind': 'command', 'label': 'Link Selected', 'command': self.linkSelected }, #2 { 'kind': 'command', 'label': 'Reset Links', 'command': self._resetLinks }, #3 { 'kind': 'separator' }, { 'kind': 'command', 'label': 'Delete Links', #5 'command': self.deleteLinks }, { 'kind': 'command', 'label': 'Delete Items', #6 'command': self.deleteNodes }, { 'kind': 'separator' }, { 'kind': 'command', 'label': 'Save PostScript File', 'command': self.printCanvas }, ] self.menuItems = menuItems self.menu.setMenuItems(menuItems) canvas.bind('<ButtonPress-3>', self._popupMenu) self._drawAfter()
def setProjectMenu(self): ProjectMenu = 'Project' # Imports submenu importsMenu = Menu(self.menubar, tearoff=False) importsMenu.add_command(label='Via Format Converter', shortcut='F', command=self.runFormatConverter) importsMenu.add_command(label='NMR-STAR 2.1.1', command=self.importNmrStar211) importsMenu.add_command(label='NMR-STAR 3.1', shortcut='N', command=self.importNmrStar31) importsMenu.add_command(label='PDB 3.20', shortcut='P', command=self.importPdb) importsMenu.add_command(label='Coordinates (PDB-style)', shortcut='C', command=self.importCoordinates) # Preferences submenu fontsMenu = FontMenu(self.menubar, self.selectFont, sizes=(8, 10, 12), doItalic=False, doBoldItalic=False, tearoff=0) prefsMenu = Menu(self.menubar, tearoff=False) prefsMenu.add_cascade( label='Fonts', shortcut='F', image=self.iconFont, compound='left', menu=fontsMenu, tipText='Select font to use in the graphical interface') prefsMenu.add_command(label='Colour Schemes', image=self.iconTable, compound='left', shortcut='C', tipText='Edit and create colour schemes', command=self.editColorSchemes) prefsMenu.add_command( label='Residue Codes', image=self.iconTable, compound='left', shortcut='R', tipText= 'User-specified codes that override the standard residue names', command=self.editResidueCodes) prefsMenu.add_command(label='User Options', image=self.iconTable, compound='left', shortcut='U', tipText='General options for Analysis behaviour', command=self.editProfiles) # menu = Menu(self.menubar, tearoff=0) menu.add_command( label='New', shortcut='N', image=self.iconNewWindow, compound='left', command=self.newProject, tipText='Create a new, blank CCPN project (closes any open project)' ) menu.add_command( label='Open Project', shortcut='O', image=self.iconOpen, compound='left', command=self.openProject, tipText= 'Open a new CCPN project by selecting a project directory on disk') menu.add_command( label='Open Spectra', shortcut='p', image=self.iconOpenFile, compound='left', command=self.openSpectrum, tipText= 'Open spectrum data fom disk, creating a default CCPN project if needed' ) menu.add_command(label='Save', shortcut='S', image=self.iconSave, compound='left', command=self.saveProject, tipText='Save the current CCPN project on disk') menu.add_command( label='Save As', shortcut='A', image=self.iconSaveAs, compound='left', command=self.saveAsProject, tipText= 'Save the current CCPN project under a different name (project directory)' ) menu.add_cascade(label='Import', shortcut='I', image=self.iconImport, compound='left', menu=importsMenu) menu.add_command(label='Close', shortcut='C', image=self.iconClose, compound='left', command=self.closeProject, tipText='Close the current CCPN project') menu.add_command( label='Quit', shortcut='Q', image=self.iconQuit, compound='left', command=self.quit, tipText='Quit Extend-NMR, closing any open CCPN project') menu.add_separator() menu.add_cascade(label='Preferences', shortcut='P', image=self.iconPrefs, compound='left', menu=prefsMenu) menu.add_command( label='Validate', shortcut='V', image=self.iconTool, compound='left', command=self.validateProject, tipText= 'Check the current CCPN project for data model consistency errors') menu.add_command( label='Backup', shortcut='B', image=self.iconTool, compound='left', command=self.backupProject, tipText='Setup options for automated backup of CCPN project data') menu.add_command( label='Archive', shortcut='r', image=self.iconTool, compound='left', command=self.archiveProject, tipText= 'Save the current CCPN project in an archived form, e.g. tar gzipped' ) self.menubar.add_cascade(label=ProjectMenu, shortcut='j', menu=menu) self.menus[ProjectMenu] = menu self.menu_items[ProjectMenu] = [ 'New', 'Open Project', 'Open Spectra', 'Save', 'Save As', 'Import', 'Close', 'Quit', 'Preferences', 'Validate', 'Backup', 'Archive', ] # Menus that area ctive in absence of a project #for ii in (0,1,2,7,13,15): for ii in ( 0, 1, 2, 7, ): self.fixedActiveMenus[(ProjectMenu, ii)] = True
def makeAppearanceMenu(self): # The fonts menu is a pre-created widget fontsMenu = FontMenu(self.mainMenu, self.setFont, sizes=(8,10,12), doItalic=0, doBoldItalic=0, tearoff=0) # Plot color schemes colorMenu = Menu(self.mainMenu, tearoff=0) colorMenu.add_radiobutton(label='Red', command=self.colorSchemeRed,) colorMenu.add_radiobutton(label='Rainbow', command=self.colorSchemeRainbow,) #colorMenu.add_radiobutton(label='Black', shortcut='B', command=self.colorSchemeBlack) #colorMenu.add_radiobutton(label='White', shortcut='W', command=self.colorSchemeWhite) # Submenu of the main menu menu = Menu(self.mainMenu, tearoff=0) # Only Fonts option so far menu.add_cascade(label='Plot Colour Scheme',shortcut='C', menu=colorMenu) menu.add_cascade(label='Fonts', shortcut='F', menu=fontsMenu) self.mainMenu.add_cascade(label='Appearance', shortcut='A', menu=menu) menu.options = ['Plot Colour Scheme','Fonts'] return menu
def makeProjectMenu(self): # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call menu.add_command(label='New', shortcut='N', command=self.newProject) menu.add_command(label='Open', shortcut='O', command=self.openProject) menu.add_command(label='Close', shortcut='C', command=self.closeProject) menu.add_command(label='Save', shortcut='S', command=self.saveProject) menu.add_command(label='Save As', shortcut='A', command=self.saveAsProject) menu.add_command(label='Quit', shortcut='Q', command=self.quit) menu.add_command(label='Version', shortcut='V', command=self.showVersion) self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu) menu.options = [ 'New', 'Open', 'Close', 'Save', 'Save As', 'Quit', 'Version' ] return menu
class ApplicationPopup(BasePopup): help_url = 'http://www.ccpn.ac.uk' def __init__(self, root, programName='Ccpn Workflow Management System'): self.programName = programName self.font = DEFAULT_FONT # Application object needed to store application-specific data with project self.application = Application(name=PROGRAM_NAME) self.versionInfo = 'Version ' + VERSION self.ariaProjectFile = None self.username = None # what do these do?? self.updateFuncs = [] self.projButtons = [] # may need these in the end self.ariaPaths = [] self.isdPaths = [] # FIXME JMCI # hard code this for now. this should be initialised from file # read during GUI login and then extended using the menu options # should set a placeholder. In fact, this placeholder will also have # a default user (guest) so that there is always a structure to # extend should the user wish to start from scratch and not log in self.repList = RepositoryList() self.currentTask = None # going to stick in shortcuts to frames for quick access self.frameShortcuts = {} # Application popup is a superclass of memops.editor.BasePoup BasePopup.__init__(self, parent=root, title=PROGRAM_NAME, location='+100+100', class_=self.application.name) self.setTitle(PROGRAM_NAME) def body(self, guiParent): self.geometry('700x600') # Ensure that the first row and column in popup expand guiParent.grid_rowconfigure(0, weight=1) guiParent.grid_columnconfigure(0, weight=1, minsize=200) frame = Frame(guiParent) # Body widgets can be put in this frame frame.grid() # this is going to set up the options on the tabs. Really we need # stronger bookeeping between the options and the frames. it # might make sense to define a master dictionary with option_name # => index. We can use this dictionary to build up the software # options and can also use it to define any refreshes etc (although # these would be better done through notifiers) softwareOpts = [ 'Repository', 'Project', 'Process', 'Client Tasks', 'Server Tasks', 'Data Exchange', 'Workflow', 'Protocols', 'User' ] # FIXME JMCI # we should have a tidier tabbed frame. ned to discuss rules with # tjs but it would seem to make sense to have the tabs stretch # across the entire top of the frame. Check the existing options # first, though self.tabbedFrame = TabbedFrame(guiParent, options=softwareOpts, toggleOff=False, selected=0) self.tabbedFrame.grid(row=0, column=0, sticky='nsew') frames = self.tabbedFrame.frames # Logos ccpnDir = getTopDirectory() imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images') imageFile = os.path.join(imageDir, 'CcpnLogo.gif') self.ccpnLogo = Tkinter.PhotoImage(file=imageFile) # 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) # jmci we are going to have to change these drastically self.mainMenu = Menu(self) self.userMenu = self.makeUserMenu() self.repositoryMenu = self.makeRepositoryMenu() self.otherMenu = self.makeOtherMenu() # Put the top level menu self.config(menu=self.mainMenu) self.initRepository(frames[0]) self.initProjectFrame(frames[1]) self.initWms(frames[2]) self.initTasks(frames[3]) self.initDataExch(frames[5]) self.initWorkflow(frames[6]) self.initProtocol(frames[7]) self.initUserFrame(frames[8]) self.initProject() if not self.project: for button in self.projButtons: button.disable() # the main client side daemon. This is going to run in the background # and control the task processing self.taskDaemon = TaskManager(self) self.taskDaemon.active = False self.taskDaemon.start() ## THE TABBED FRAMES ## def initRepository(self, frame): frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(1, weight=1) repositoryFrame = RepositoryFrame(frame, basePopup=self) repositoryFrame.grid(row=1, column=0, sticky='nsew') self.updateFuncs.append(repositoryFrame.updateAll) def initProjectFrame(self, frame): frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(1, weight=1) self.projectFrame = ProjectFrame(frame, basePopup=self) self.projectFrame.grid(row=1, column=0, sticky='nsew') self.updateFuncs.append(self.projectFrame.updateAll) def initWms(self, frame): frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(1, weight=1) extendNmrFrame = ExtendNmrFrame(frame, basePopup=self) extendNmrFrame.grid(row=1, column=0, sticky='nsew') self.updateFuncs.append(extendNmrFrame.updateAll) def initTasks(self, frame): frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(1, weight=1) tasksFrame = TasksFrame(frame, self) tasksFrame.grid(row=1, column=0, sticky='nsew') self.updateFuncs.append(tasksFrame.updateAll) def initDataExch(self, frame): row = 0 frame.config(bg='#E6E6E6') frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(1, weight=1) dataExchFrame = DataExchFrame(frame, basePopup=self) dataExchFrame.grid(row=1, column=0, sticky='nsew') self.updateFuncs.append(dataExchFrame.updateAll) def initWorkflow(self, frame): row = 0 frame.config(bg='#FFFFFF') frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(1, weight=1) workflowFrame = WorkflowFrame(frame, basePopup=self) workflowFrame.grid(row=1, column=0, sticky='nsew') self.updateFuncs.append(workflowFrame.updateAll) def initProtocol(self, frame): row = 0 frame.config(bg='#FFFFFF') frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(1, weight=1) protocolFrame = ProtocolFrame(frame, basePopup=self) protocolFrame.grid(row=1, column=0, sticky='nsew') self.updateFuncs.append(protocolFrame.updateAll) def initUserFrame(self, frame): frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(1, weight=1) row = 0 frame.config(bg='#FFFFFF') userFrame = UserFrame(frame, basePopup=self) userFrame.grid(row=1, column=0, sticky='nsew') self.updateFuncs.append(userFrame.updateAll) ## The Menu ## def makeUserMenu(self): menu = Menu(self.mainMenu, tearoff=0) menu.add_command(label='Log In', shortcut='I', command=self.openLoginPopup) menu.add_command(label='Log Out', shortcut='O', command=self.logout) menu.add_command(label='Save Profile', shortcut='S', command=self.tmpCall) menu.add_command(label='View Profile', shortcut='V', command=self.tmpCall) menu.add_command(label='Create Profile', shortcut='C', command=self.tmpCall) menu.add_command(label='Edit Profile', shortcut='E', command=self.tmpCall) self.mainMenu.add_cascade(label='User', shortcut='U', menu=menu) menu.options = [ 'Log In', 'Log Out', 'Save Profile', 'View Profile', 'Create Profile', 'Edit Profile' ] return menu def makeRepositoryMenu(self): self.repMenu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call self.repMenu.add_command(label='Manager', shortcut='M', command=self.tmpCall) self.repMenu.add_command(label='Connect', shortcut='C', command=self.openRepository) # doesn't really work to have a disconnect; we do not have a list # of repositories and so would it refer to? Better to do this from # within the RepositoryFrame self.repMenu.add_command(label='Disconnect', shortcut='D', command=self.tmpCall) # again, this is functionality that would make sense but which it is hard to put # in the top level menu because it is not obvious which repository it refers # to self.repMenu.add_command(label='Import Project', shortcut='I', command=self.tmpCall) self.repMenu.add_command(label='Export Project', shortcut='E', command=self.tmpCall) # FIXME JMCI # the quit option needs to be tied to a dialogue box that asks whether # the current connection state should be saved. This will have to be # secured and so means that the GUI should have a login itself (beyond # the logins for the various resources). self.repMenu.add_command(label='Quit', shortcut='Q', command=self.quit) self.mainMenu.add_cascade(label='Repository', shortcut='R', menu=self.repMenu) self.repMenu.options = [ 'Connect', 'Disconnect', 'Import Project', 'Export Project', 'Quit' ] return self.repMenu def makeProjectMenu(self): # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call menu.add_command(label='New', shortcut='N', command=self.newProject) menu.add_command(label='Open', shortcut='O', command=self.openProject) menu.add_command(label='Close', shortcut='C', command=self.closeProject) menu.add_command(label='Save', shortcut='S', command=self.saveProject) menu.add_command(label='Save As', shortcut='A', command=self.saveAsProject) menu.add_command(label='Quit', shortcut='Q', command=self.quit) menu.add_command(label='Version', shortcut='V', command=self.showVersion) self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu) menu.options = [ 'New', 'Open', 'Close', 'Save', 'Save As', 'Quit', 'Version' ] return menu def makeOtherMenu(self): # The fonts menu is a pre-created widget fontsMenu = FontMenu(self.mainMenu, self.setFont, sizes=(8, 10, 12), doItalic=0, doBoldItalic=0, tearoff=0) # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Only Fonts option so far menu.add_cascade(label='Fonts', shortcut='F', menu=fontsMenu) self.mainMenu.add_cascade(label='Options', shortcut='O', menu=menu) menu.options = [ 'Fonts', ] return menu def makeCcpNmrMenu(self): try: from ccpnmr.analysis.AnalysisPopup import AnalysisPopup haveAnalysis = True except ImportError: haveAnalysis = False try: from ccpnmr.format.gui.FormatConverter import FormatConverter from ccpnmr.format.gui.DataShifter import DataShifter haveFormatConv = True except ImportError: haveFormatConv = False menu = Menu(self.mainMenu, tearoff=0) if haveAnalysis: menu.add_command(label='Analysis', shortcut='A', command=self.ccpNmrAnalysis) else: menu.add_command(label='Analysis ** NOT INSTALLED **', shortcut='A', command=None) if haveFormatConv: menu.add_command(label='Format Converter', shortcut='F', command=self.ccpNmrFormatConverter) menu.add_command(label='Data Shifter', shortcut='D', command=self.ccpNmrDataShifter) else: menu.add_command(label='Format Converter ** NOT INSTALLED **', shortcut='F', command=None) menu.add_command(label='Data Shifter ** NOT INSTALLED **', shortcut='D', command=None) self.mainMenu.add_cascade(label='CcpNmr', shortcut='C', menu=menu) menu.options = ['Analysis', 'Format Converter', 'Data Shifter'] return menu def ccpNmrAnalysis(self, cacheSize=64): from ccpnmr.analysis.AnalysisPopup import AnalysisPopup analysis = AnalysisPopup(self, cache_size=cacheSize, glDirect=None) analysis.update_idletasks() # fast if self.project: analysis.initProject(self.project) def ccpNmrFormatConverter(self): from ccpnmr.format.gui.FormatConverter import FormatConverter fc = FormatConverter(self, threading=False, project=self.project) fc.open() if self.project: fc.initProject(self.project) def ccpNmrDataShifter(self): from ccpnmr.format.gui.DataShifter import DataShifter ds = DataShifter(self) ds.open() def newProject(self): if self.project: # Project already present if not self.closeProject(): # If we don't close the current project do nothing return name = askString(title='Project name', prompt='Enter project name:', parent=self) if name: # Make the API Project object project = Implementation.MemopsRoot(name=name) nmrProject = project.newNmrProject(name=name) self.initProject(project) # placeholder method until we write code def tmpCall(self): return def openProject(self): if self.project: if not self.closeProject(): return self.openPopup('open_project', OpenProjectPopup, callback=self.initProject) def openLoginPopup(self): # at the moment we do this through methods in the popup. It # would be much more sensible to do this through some # sort of callback. login_popup = LoginPopup(self) # really we want to imoblise the rest. how to do? def setRepository(self, rep): self.repList.currentRepository = rep if self.frameShortcuts.has_key('Repository'): self.frameShortcuts['Repository'].drawFrame() if self.frameShortcuts.has_key('Tasks'): self.frameShortcuts['Tasks'].drawFrame() #for ff in self.tabbedFrame.frames[0].children.values(): # ff.draw() #for ff in self.tabbedFrame.frames[3].children.values(): # ff.draw() for ff in self.tabbedFrame.frames[8].children.values(): ff.draw() def openRepository(self): rep_popup = RepositoryPropertiesPopup(self) def closeRepository(self): pass def logout(self): self.setUsername(None) self.repList = RepositoryList() print 'in logout ', self.repList print '#########################' print self.tabbedFrame.frames[0].__dict__ print '#########################' if self.frameShortcuts.has_key('Repository'): self.frameShortcuts['Repository'].drawFrame() #for ff in self.tabbedFrame.frames[0].children.values(): # ff.draw() for ff in self.tabbedFrame.frames[8].children.values(): ff.draw() def openPopup(self, popup_name, clazz, oldStyle=False, *args, **kw): popup = self.popups.get(popup_name) if (popup): popup.open() else: if self.project: analysisProfile = self.analysisProfile else: analysisProfile = None if analysisProfile: transient = analysisProfile.transientDialogs else: transient = True name = popup_name if (oldStyle): popup = self.popups[popup_name] = clazz(self, transient=transient, *args, **kw) else: popup = self.popups[popup_name] = clazz(self, project=self.project, popup_name=name, transient=transient, *args, **kw) # above automatically opens popup return popup def closeProject(self, queryClose=True, querySave=True): if queryClose: if not showYesNo( 'Close project', 'Close current project?', parent=self): return False if querySave: if not self.checkSaving(): return False self.destroyPopups() self.initProject() return True def saveProject(self): self.saveFile() # NBNB Rasmus 22/8/08 changed to fit AnalysisPopup (and removed 'isStored' bug) #if (self.project.isStored): # self.saveFile() #else: # self.askSaveFile() def saveAsProject(self): self.askSaveFile() def showVersion(self): showInfo('Version', self.versionInfo, parent=self) def changeFont(self, analysisProfile): if analysisProfile is self.analysisProfile: if self.font != analysisProfile.font: self.font = analysisProfile.font or DEFAULT_FONT self.setFont() def selectFont(self, font): # Only called from main menu option if self.project: self.analysisProfile.font = font def setFont(self, font=None, popup=None): if font is None: font = self.font or DEFAULT_FONT else: self.font = font if not popup: popup = self childList = popup.children.values() classes = [ Tkinter.Button, Tkinter.Label, Tkinter.Menu, Tkinter.Entry, Tkinter.Checkbutton, Tkinter.Radiobutton ] for child in childList: for clazz in classes: if isinstance(child, clazz): if hasattr(child, 'font'): if not child.font: child.config(font=font) else: child.config(font=font) break if isinstance(child, Tkinter.Frame): child.font = font elif isinstance(child, ScrolledMatrix): child.setFont(font) if hasattr(child, 'children'): childList.extend(child.children.values()) def initProject(self, project=None): self.project = project if project: self.initTopObjects(self.project) self.project.application = self.application self.setFont() webBrowser = ProjectWebBrowser(self.top, popup=self, project=project) #self.helpButton.config(command = lambda url=self.help_url: webBrowser.open(url) ) for i, func in enumerate(self.updateFuncs): func(project) for button in self.projButtons: button.enable() self.setupSoftware() else: for button in self.projButtons: button.disable() self.setMenuState() def setUsername(self, name): self.username = name print 'set username ', self.username # jmci FIXME # need to look into this carefully and analyse the possible # states def setMenuState(self): if self.project: state = Tkinter.NORMAL else: state = Tkinter.DISABLED # Disable bits of the project menu if there's no project #for option in ('Save','Save As','Close'): # i = self.projectMenu.options.index(option) # self.projectMenu.entryconfig(i, state=state) # Disable other manus if there's no project #for menu in [self.otherMenu,]: # Include more menus in this list # for i in range(len(menu.options)): # menu.entryconfig(i, state=state) def setupSoftware(self): project = self.project methodStore = project.currentMethodStore or \ project.findFirstMethodStore() or \ project.newMethodStore(name=project.name) software = methodStore.findFirstSoftware(name=PROGRAM_NAME, version=VERSION) if not software: software = methodStore.newSoftware(name=PROGRAM_NAME, version=VERSION) #software.vendorName = 'PDBe & CCPN' #software.vendorAddress = '' #software.vendorWebAddress = 'http:' #software.details = '' def askSaveFile(self): popup = self.openPopup('save_project', SaveProjectPopup) popup.refresh() def modalAskSaveFile(self): popup = SaveProjectPopup(self, project=self.project, dismiss_text='Cancel Quit', modal=True) did_save = popup.did_save popup.destroy() return did_save def quitSaveProject(self): if (self.project.activeRepositories): return self.saveFile() else: return self.modalAskSaveFile() def destroyPopups(self): for key in self.popups.keys(): popup = self.popups[key] popup.destroy() self.popups = {} ## WMS methods # should maybe merge this with setUsername # this will read a config file that stores user setups. How this # is done TBD so hack for now and just return def readConfig(self, userName): # this should return the full RepositoryList structure. In reality this # will parse from file. set it by hand from here for now for speed repList = RepositoryList(userName) rep1 = repList.newRepository('remote', 'localhost:8080/HalxService', 'ccpn', 'remote') repList.currentRepository = rep1 # should these be directory objects? repList.current_export_dir = '/home/jionides/work/CCPN/test_JMCI_data' repList.current_import_dir = '/home/jionides/work/CCPN/test_EXP_data' self.repList = repList print 'in readconfig ' self.setRepository(rep1) # really should be done through notifiers if self.frameShortcuts.has_key('Repository'): self.frameShortcuts['Repository'].drawFrame() if self.frameShortcuts.has_key('Tasks'): self.frameShortcuts['Tasks'].drawFrame() if self.frameShortcuts.has_key('DataExch'): self.frameShortcuts['DataExch'].drawFrame() for ff in self.tabbedFrame.frames[8].children.values(): ff.draw() # want to update the top menu. The idea should be to add a bar item # and then to list all the repositories underneath. Clicking on a given # repository will set the home repository as current. That seems to # be a good sensible way of simplifying the interface in a expected # way. We could, alternatively, use tabs. opts = {} self.repMenu.add('separator', **opts) for rep in repList.repositories: item = { 'command': lambda rep=rep: self.setRepository(rep), 'label': rep.name } self.repMenu.add('comman', **item) self.repMenu.config() ## end WMS methods def copyModifiedStorages(self): modifiedStorages = [ storage for storage in self.project.storages if storage.isModified ] if (self.project.isModified): modifiedStorages.append(self.project) for storage in modifiedStorages: self.copyStorage(storage) def saveFile(self): if not self.project: return False try: saveProject(self.project, createFallback=True) print 'successfully saved project' return True except IOError, e: showError('Saving file', str(e), parent=self) return False
def makeProjectMenu(self): importsMenu = Menu(self.mainMenu, tearoff=False) importsMenu.add_command(label='Fasta Sequence',command=self.importFastaSeq) importsMenu.add_command(label='NMR-STAR 2.1.1', command=self.importNmrStar211) importsMenu.add_command(label='NMR-STAR 3.1', command=self.importNmrStar31) importsMenu.add_command(label='PDB 3.20',command=self.importPdb) importsMenu.add_command(label='PDB Coords',command=self.importPdbCoords) #importsMenu.add_command(label='CNS Distance Restraints',command=self.importCnsDistance) exportsMenu = Menu(self.mainMenu, tearoff=False) exportsMenu.add_command(label='NMR-STAR 3.1', command=self.eciFrame.exportNmrStar31) exportsMenu.add_command(label='PDB Coords',command=self.eciFrame.exportPdb) #exportsMenu.add_command(label='CNS Distance Restraints',command=self.eciFrame.exportCnsDistance) # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) # Add various options to the menu and state the functions they call menu.add_command(label='New', shortcut='N', command=self.newProject) menu.add_command(label='Open', shortcut='O', command=self.openProject) menu.add_command(label='Close', shortcut='C', command=self.closeProject) menu.add_command(label='Save', shortcut='S', command=self.saveProject) menu.add_command(label='Save As', shortcut='A', command=self.saveAsProject) menu.add_cascade(label='Import', shortcut='I', menu=importsMenu) menu.add_cascade(label='Export', shortcut='E', menu=exportsMenu) menu.add_command(label='Quit', shortcut='Q', command=self.quit) menu.add_command(label='Version', shortcut='V', command=self.showVersion) self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu) menu.options = ['New','Open','Close','Save','Save As','Import','Export','Quit','Version'] return menu
class DataFileImportGui(BasePopup): # TODO CHANGE help_url = 'http://www.ebi.ac.uk/pdbe' def __init__(self, root): self.root = root self.font = DEFAULT_FONT # Application object needed to store application-specific data with project self.application = Application(name=PROGRAM_NAME) self.versionInfo = VERSION ccpnProjectName = askString( "CCPN project name", 'Please give a name to this import session:') self.fcWrapper = FormatConverterWrapper( ccpnProjectName=ccpnProjectName, guiRoot=self) self.project = self.fcWrapper.formatConversion.ccpnProject # Application popup is a superclass of memops.editor.BasePoup BasePopup.__init__(self, parent=root, title=PROGRAM_NAME, location='+100+100', class_=self.application.name) self.setTitle(PROGRAM_NAME) def body(self, guiParent): self.geometry('600x350') # Ensure that the first row and column in popup expand guiParent.expandGrid(0, 0) self.importFrame = DataFileImportFrame(guiParent, basePopup=self, grid=(0, 0)) # Dictionary to store popups opened by this application - e.g. need to close upon quit self.popups = {} # Default font self.font = DEFAULT_FONT # 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.mainMenu.add_command(label='Formats', shortcut='F', command=self.importFrame.showFormats) self.mainMenu.add_command( label='Help', shortcut='H', command=self.importFrame.showMainInstructions) # Put the main menu self.config(menu=self.mainMenu) self.setMenuState() def makeProjectMenu(self): # Submenu of the min menu menu = Menu(self.mainMenu, tearoff=0) menu.add_command(label='Save', shortcut='S', command=self.saveProject) menu.add_command(label='Save As', shortcut='A', command=self.saveAsProject) menu.add_command(label='Quit', shortcut='Q', command=self.quit) menu.add_command(label='Version', shortcut='V', command=self.showVersion) self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu) menu.options = ['Save', 'Save As', 'Quit', 'Version'] return menu def saveProject(self): self.saveFile() def saveAsProject(self): self.askSaveFile() def showVersion(self): showInfo('Version', 'Version ' + self.versionInfo, parent=self) def setMenuState(self): state = Tkinter.NORMAL for option in ('Save', 'Save As', 'Quit', 'Version'): i = self.projectMenu.options.index(option) self.projectMenu.entryconfig(i, state=state) def askSaveFile(self): popup = self.openPopup('save_project', SaveProjectPopup) popup.refresh() def modalAskSaveFile(self): popup = SaveProjectPopup(self, project=self.project, dismiss_text='Cancel Quit', modal=True) did_save = popup.did_save popup.destroy() return did_save def quitSaveProject(self): if (self.project.activeRepositories): return self.saveFile() else: return self.modalAskSaveFile() """ def destroyPopups(self): for key in self.popups.keys(): popup = self.popups[key] popup.destroy() self.popups = {} """ def saveFile(self): if not self.project: return False try: saveProject(self.project, createFallback=True) print 'successfully saved project' return True except IOError, e: showError('Saving file', str(e), parent=self) return False
def body(self, guiParent): self.geometry('700x600') # Ensure that the first row and column in popup expand guiParent.grid_rowconfigure(0, weight=1) guiParent.grid_columnconfigure(0, weight=1, minsize=200) frame = Frame(guiParent) # Body widgets can be put in this frame frame.grid() # this is going to set up the options on the tabs. Really we need # stronger bookeeping between the options and the frames. it # might make sense to define a master dictionary with option_name # => index. We can use this dictionary to build up the software # options and can also use it to define any refreshes etc (although # these would be better done through notifiers) softwareOpts = [ 'Repository', 'Project', 'Process', 'Client Tasks', 'Server Tasks', 'Data Exchange', 'Workflow', 'Protocols', 'User' ] # FIXME JMCI # we should have a tidier tabbed frame. ned to discuss rules with # tjs but it would seem to make sense to have the tabs stretch # across the entire top of the frame. Check the existing options # first, though self.tabbedFrame = TabbedFrame(guiParent, options=softwareOpts, toggleOff=False, selected=0) self.tabbedFrame.grid(row=0, column=0, sticky='nsew') frames = self.tabbedFrame.frames # Logos ccpnDir = getTopDirectory() imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images') imageFile = os.path.join(imageDir, 'CcpnLogo.gif') self.ccpnLogo = Tkinter.PhotoImage(file=imageFile) # 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) # jmci we are going to have to change these drastically self.mainMenu = Menu(self) self.userMenu = self.makeUserMenu() self.repositoryMenu = self.makeRepositoryMenu() self.otherMenu = self.makeOtherMenu() # Put the top level menu self.config(menu=self.mainMenu) self.initRepository(frames[0]) self.initProjectFrame(frames[1]) self.initWms(frames[2]) self.initTasks(frames[3]) self.initDataExch(frames[5]) self.initWorkflow(frames[6]) self.initProtocol(frames[7]) self.initUserFrame(frames[8]) self.initProject() if not self.project: for button in self.projButtons: button.disable() # the main client side daemon. This is going to run in the background # and control the task processing self.taskDaemon = TaskManager(self) self.taskDaemon.active = False self.taskDaemon.start()
def __init__(self, parent, callback=None, entries=None, text_attr=None, colors=None, outline='#602000', fill='#B05848', label_color='#501000', selected_index=-1, indent='', extra='', sticky='w', do_initial_callback=True, force_callback=False, *args, **kw): if (entries is None): entries = [] Frame.__init__(self, parent, sticky=sticky, *args, **kw) self.text_attr = text_attr #indentation and extra string for popup information self.indent = indent self.extra = extra self.callback = callback self.do_initial_callback = do_initial_callback self.force_callback = force_callback frame = Frame(self) #frame = parent self.frame = frame self.bg = frame.cget('bg') self.outline = outline self.fill = fill self.label_color = label_color self.menu = Menu(parent, tearoff=0, borderwidth=1, activeborderwidth=1) self.menu.images = [] self.label = Label(self, foreground=label_color) self.first_pass = True #self.entries = entries self.entries = [] self.colors = [] self.setup(entries, selected_index, colors=colors) s = 10 self.canvas = Canvas(self, width=s, height=s, background=self.bg) self.label.bind("<Button-1>", self.labelPopup) # below does not work for some reason #self.bind("<Button-1>", self.labelPopup) # below does not work any more since can have submenus and # no way to reach those with below since involves leaving menu #self.menu.bind("<Leave>", self.popdown) self.menu.bind("<Leave>", self.leave) self.menu.bind("<Button-1>", self.buttonPress) self.poppedUpSubmenu = False self.canvas.bind("<Button-1>", self.canvasPopup) self.canvas.bind("<Configure>", self.resizeCallback) self.label.grid(row=0, column=0, sticky=Tkinter.W) self.canvas.grid(row=0, column=1, sticky=Tkinter.E, padx=2)
def makeUserMenu(self): menu = Menu(self.mainMenu, tearoff=0) menu.add_command(label='Log In', shortcut='I', command=self.openLoginPopup) menu.add_command(label='Log Out', shortcut='O', command=self.logout) menu.add_command(label='Save Profile', shortcut='S', command=self.tmpCall) menu.add_command(label='View Profile', shortcut='V', command=self.tmpCall) menu.add_command(label='Create Profile', shortcut='C', command=self.tmpCall) menu.add_command(label='Edit Profile', shortcut='E', command=self.tmpCall) self.mainMenu.add_cascade(label='User', shortcut='U', menu=menu) menu.options = [ 'Log In', 'Log Out', 'Save Profile', 'View Profile', 'Create Profile', 'Edit Profile' ] return menu