Example #1
0
    def body(self, guiParent):

        self.menus = {}
        self.menu_items = {}

        self.fixedActiveMenus = {}

        self.popups = {}

        self.callbacksDict = {}

        self.selected_objects = []

        self.menubar = menubar = Menu(guiParent)

        self.font = DEFAULT_FONT

        self.setProjectMenu()
        #

        menu = Menu(self.menubar, tearoff=0)
        menu.bind('<Button>', self.printAnalysisCommandLineInfo)
        self.menubar.add_cascade(label='CcpNmr Analysis',
                                 shortcut='C',
                                 menu=menu)
        self.menubar.add_command(label='FormatConverter',
                                 shortcut='F',
                                 command=self.runFormatConverter)

        self.menubar = menu
        self.initProject()
        self.setPeaksMenu()
        self.setMoleculeMenu()
        self.setAssignMenu()
        self.setResonanceMenu()
        self.setDataMenu()
        self.setStructureMenu()
        self.setChartMenu()
        self.setMacroMenu()
        self.setOtherMenu()
        self.setMenuState()  # need to do it again because of OtherMenu state

        # Help Submenu

        helpMenu = Menu(self.menubar, tearoff=0)
        helpMenu.add_command(label='Version',
                             shortcut='V',
                             command=self.showVersion)
        helpMenu.add_command(label='About',
                             shortcut='A',
                             command=self.showAbout)
        helpMenu.add_command(label='Help', shortcut='H', command=self.showHelp)

        menu.add_separator()
        menu.add_command(label='CCPN Updates',
                         shortcut='U',
                         image=self.iconRefresh,
                         compound='left',
                         command=self.updateAnalysis,
                         tipText='Get any new patches and updates to CcpNmr')
        menu.add_cascade(label='CCPN Help',
                         shortcut='H',
                         image=self.iconHelp,
                         compound='left',
                         menu=helpMenu)

        self.config(menu=menubar)

        # 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()

        softwareOpts = [
            'Extend-NMR', 'ARIA 2', 'Auremol', 'CING', ' ECI ', 'HADDOCK',
            ' ISD ', 'PRODECOMP'
        ]

        self.tabbedFrame = TabbedFrame(guiParent,
                                       options=softwareOpts,
                                       toggleOff=False,
                                       selected=0,
                                       callback=self.toggleTab)
        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, 'Fp6Logo.gif')
        self.fp6Logo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CingLogo.gif')
        self.cingLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AriaLogo.gif')
        self.ariaLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'IsdLogo.gif')
        self.isdLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'HaddockLogo.gif')
        self.haddockLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AuremolLogo.gif')
        self.auremolLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CcpnLogo.gif')
        self.ccpnLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'ProdecompLogo.gif')
        self.prodecompLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MddLogo.gif')
        self.mddLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'BrukerLogo.gif')
        self.brukerLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MsdLogo.gif')
        self.msdLogo = Tkinter.PhotoImage(file=imageFile)

        self.initExtendNmr(frames[0])

        self.initAria(frames[1])

        self.initAuremol(frames[2])

        self.initCing(frames[3])

        self.initEci(frames[4])

        self.initHaddock(frames[5])

        self.initIsd(frames[6])

        self.initProdecomp(frames[7])

        self.initProject(self.project)

        if not self.project:
            for button in self.projButtons:
                button.disable()

        self.geometry('680x670')
Example #2
0
    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
Example #3
0
class PulldownList(Frame):

  # if using indentation then should use list as stack only
  # in other words only delete or insert at end
  
  # There is a 1:1 correspondance between the ordered lists of texts and 
  # list of objects

  # categories is the category name for each text/object
  # objects with the same category will go under a submenu
  # of that name

  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)

  # 
  # Retrieval
  #

  def get(self):
  
    return (self.getText(),self.getObject())

  def getSelected(self):

    return self.get()

  def getObject(self):
  
    return self._fetch(self.index, self.objects)  

  def getText(self):
   
    return self._fetch(self.index, self.texts)

  def getSelectedIndex(self):

    return self.index


  #
  # Setting selected 
  #

  def set(self, item, doCallback=False):
    # Works with an object or a text

    index = None
    
    if item in self.texts:
      index = list(self.texts).index(item)

    elif item in self.objects:
      index = list(self.objects).index(item)

    if index is not None:
      self.setIndex(index, doCallback=doCallback)

  def setSelected(self, item, doCallback=False):
    
    self.set(item, doCallback=doCallback)

  def setIndex(self, index, doCallback=False):

    self.index = index

    if self.objects:
      obj = self.objects[index]
      
      if obj is not self.object:
        self.object = obj
        
        if (doCallback or self.initCallback) and self.texts and self.callback:
          self.callback(obj)

    self._updateLabel()

  #
  # Bulk configuration
  #

  def clear(self):
  
    self.setup([], [], 0)

  def setup(self, texts, objects, index, colors=None, categories=None):
          
    self.texts = texts
    nTexts = len(texts)

    if not objects:
      objects = texts

    while len(objects) < nTexts:
      objects.append(None)

    self.objects = objects

    if colors is None:
      self.colors = [None] * nTexts
    else:
      while len(colors) < nTexts:
        colors.append(None)  
      self.colors = colors
      
    if categories is None:
      self.categories = [None] * nTexts  

    else:
      while len(categories) < nTexts:
        categories.append(None)
      self.categories = categories  

    self._setMenuItems()
    
    self.setIndex(index or 0)
        
  #
  # In-place/minor configuration
  #        
        
  def insert(self, index, text, object=None, color=None,
             category=None, select=False):
   
    index = max(0, min(len(self.texts),index))
   
    self.texts.insert(index, text)
    self.objects.insert(index, object)
    self.colors.insert(index, color)
    self.categories.insert(index, category)
   
    self._setMenuItems()
      
    if select:  
      self.setIndex(index)

  def append(self, text, object=None, color=None, category=None, select=False):

    self.insert(len(self.texts), text, object=None,
                color=None, category=None, select=False)
   
  def delete(self, index, howMany=1):

    if index < 0:
      return
    elif index >= len(self.texts):
      return  

    end = min(index+howMany,len(self.texts))

    self._clearMenu()

    del self.texts[index:end]
    del self.objects[index:end]
    del self.colors[index:end]
    del self.categories[index:end]

    self._setMenuItems()

    index = min(len(self.texts)-1,self.index)

    self.setIndex(index)
    
  def disable(self):
   
    self.label.config(foreground='#808080')
    self.active = False
    self._resizeCallback()

  def enable(self):
  
    self.label.config(foreground=self.labelColor)
    self.active = True
    self._resizeCallback()

  #
  # Internal methods
  #

  def _leave(self, event):

    # look for widget under event, if it is a Menu do not popdown
    # this often seems to throw exceptions deep in Tk so use try/except
    try:
      widget = self.menu.winfo_containing(event.x_root, event.y_root)
      if not isinstance(widget, Menu):
        self._popdown()
    except:
      """ The problem with the below approach is that when moving to a submenu
      the menu produces a leaving event which can easily be outside that menu,
      which causes an unintended popdown.
"""
      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 _resizeCallback(self, *event):

    if self.active:
      fill = self.arrowFill
      outline = self.arrowLine
    else:
      fill = '#808080'
      outline = '#404040'
      

    c = self.canvas
    w = c.winfo_width() -1
    h = c.winfo_height() -1
    c.delete('all')
    c.create_rectangle(0,0,10,2,
                       fill=fill, outline=outline)
    c.create_polygon(0, 4, 0, 6, 5, 11, 10, 6, 10, 4, 
                     fill=fill, outline=outline)


  def _fetch(self, index, array):

    if index is None:
      return None 

    if index < 0:
      index += len(array)
    
    if index < 0:
      return None

    elif index >= len(array):
      return None
    
    else:
      return array[index]  
 

  def _setMenuItems(self):
    self._clearMenu()
    self.menu.images = [] # Clear photoimages
    
        
    if not self.texts and not self.menu.entrycget(1, 'label'):
    
      item =  {'kind': 'command',
               'label': NullText,
               'command': None }
      self.menu.addMenuItem(item)
      self.rows = [0]
      
      return
    
    topList = []
    categoryDict = {}
    catLast = self.categoriesLast
    catList = []
    
    for i in range(len(self.texts)):
      text     = self.texts[i]
      color    = self.colors[i]
      category = self.categories[i]        

      if type(category) is SET_TYPE:
        for altCat in category:
          if altCat is None:
            topList.append((i, text, color, None))
          
          else:
            if categoryDict.get(altCat) is None:
              categoryDict[altCat] = []
              if catLast:
                catList.append((None, altCat, None, altCat))
              else:
                topList.append((None, altCat, None, altCat))
 
            categoryDict[altCat].append((i, text, color))
      
      elif category:
        if categoryDict.get(category) is None:
          categoryDict[category] = []
          if catLast:
            catList.append((None, category, None, category))
          else:
            topList.append((None, category, None, category))
        
        categoryDict[category].append((i, text, color))
   
      else:
        topList.append((i, text, color, None))
   
    if catLast:
      catList.sort()
      topList += catList
   
    divider = False
   
    row = 0
    for index, text, color, cat in topList:
      columnbreak = 0
      if row and row % 36 == 0:
        columnbreak = 1
            
      
      if cat:
        string = (self.indent * row) + self.prefix + text
        items = []
        
        rowB = 0
        for index2, text2, color2 in categoryDict.get(cat, []):
          columnbreakB = 0
          if rowB and rowB % 36 == 0:
            columnbreakB = 1
          
          if self.numbering:
            number = '%d%. ' % (index2+1)
          else:
            number = ''
            
          string2 = number + self.prefix + text2
          command = lambda n=index2: self.setIndex(n, True)
          if color2:
            image = self._makeColorTile(color2)
            item2 = {'kind': 'command', 'accelerator': string2,
                     'command': command, 'image': image,
                     'columnbreak': columnbreakB}
          else:
            item2 = {'kind': 'command', 'label': string2,
                     'command': command, 'columnbreak': columnbreakB}
          
          items.append(item2)
          self.rows.append(row)
          rowB += 1
        
        if catLast and not divider:
          divider = True
          self.menu.add_separator()
        
        item = {'kind':'cascade', 'label':string, 
                'submenu':items, 'columnbreak':columnbreak}
        
      else:

        if self.numbering:
          number = '%d%. ' % (index+1)
        else:
          number = ''
   
        string = (self.indent * row) + number + self.prefix + text
        command = lambda n=index: self.setIndex(n, True)

        if color:
          image = self._makeColorTile(color)
          item = {'kind': 'command', 'accelerator': string, 'command': command,
                  'image': image, 'columnbreak': columnbreak}
        else:
          item = {'kind': 'command', 'label': string,
                  'command': command, 'columnbreak': columnbreak}
      
      self.menu.addMenuItem(item)
      self.rows.append(row)
       
      row += 1

  def _clearMenu(self):

    self.menu.delete(0, 'end')
    self.index = 0
    self.rows = []

  def _popdown(self, *event):

    self.menu.unpost()

  def _labelClick(self, event):

    if not self.active:
      return

    s = self.rows[self.index]
    #x = event.x_root - event.x + 2 + self.label.winfo_width()
    x = event.x_root - 2
    y = event.y_root - event.y - max(0, s) * (self.label.winfo_height() + 1)
    self.menu.post(x, y)

  def _canvasClick(self, event):

    if not self.active:
      return

    s = self.rows[self.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 _updateLabel(self):

    if self.texts:
      text = self.texts[self.index] or NullText
    else:
      text = NullText

    self.label.set(text=text)
    

  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