Tooltips for features, links for features added
[jalview.git] / src / jalview / appletgui / AlignFrame.java
index 189a36d..77154e0 100755 (executable)
@@ -172,18 +172,26 @@ public class AlignFrame extends Frame implements ActionListener,
       StringTokenizer st;\r
       SequenceFeature sf;\r
       FeatureRenderer fr = alignPanel.seqPanel.seqCanvas.getFeatureRenderer();\r
-      int lineNo = 0;\r
-      String featureGroup = null;\r
+      String featureGroup = null, groupLink = null;\r
+      Hashtable typeLink = new Hashtable();\r
+\r
       while ( (line = in.readLine()) != null)\r
       {\r
-        lineNo++;\r
         st = new StringTokenizer(line, "\t");\r
-        if (st.countTokens() == 2)\r
+        if(!st.hasMoreTokens())\r
+          continue;\r
+\r
+        if (st.countTokens() < 4)\r
         {\r
           type = st.nextToken();\r
           if(type.equalsIgnoreCase("startgroup"))\r
           {\r
             featureGroup = st.nextToken();\r
+            if (st.hasMoreElements())\r
+            {\r
+              groupLink = st.nextToken();\r
+              fr.addFeatureLink(featureGroup, groupLink);\r
+            }\r
           }\r
           else if(type.equalsIgnoreCase("endgroup"))\r
           {\r
@@ -191,11 +199,19 @@ public class AlignFrame extends Frame implements ActionListener,
             //but at present theres no way of showing more than 1 group\r
             st.nextToken();\r
             featureGroup = null;\r
+            groupLink = null;\r
           }\r
           else\r
           {\r
             UserColourScheme ucs = new UserColourScheme(st.nextToken());\r
             fr.setColour(type, ucs.findColour("A"));\r
+            if (st.hasMoreElements())\r
+            {\r
+                String link = st.nextToken();\r
+                typeLink.put(type, link);\r
+                fr.addFeatureLink(type, link);\r
+            }\r
+\r
           }\r
           continue;\r
         }\r
@@ -203,6 +219,7 @@ public class AlignFrame extends Frame implements ActionListener,
         while (st.hasMoreElements())\r
         {\r
           desc = st.nextToken();\r
+\r
           token = st.nextToken();\r
           if (!token.equals("ID_NOT_SPECIFIED"))\r
           {\r
@@ -229,9 +246,21 @@ public class AlignFrame extends Frame implements ActionListener,
             fr.setColour(type, ucs.findColour("A"));\r
           }\r
 \r
-          sf = new SequenceFeature(type, desc, "", start, end, featureGroup);\r
-\r
+          sf = new SequenceFeature(type, desc, start, end, 0f, featureGroup);\r
           seq.addSequenceFeature(sf);\r
+\r
+          if(groupLink!=null)\r
+          {\r
+            sf.addLink(groupLink);\r
+            sf.description += "%LINK%";\r
+          }\r
+          if(typeLink.containsKey(type))\r
+          {\r
+            sf.addLink(typeLink.get(type).toString());\r
+            sf.description += "%LINK%";\r
+          }\r
+\r
+          parseDescriptionHTML(sf);\r
         }\r
       }\r
 \r
@@ -248,8 +277,42 @@ public class AlignFrame extends Frame implements ActionListener,
     }\r
   }\r
 \r
+  void parseDescriptionHTML(SequenceFeature sf)\r
+  {\r
+    StringBuffer sb = new StringBuffer();\r
+    StringTokenizer st = new StringTokenizer(sf.getDescription(), "<");\r
+    String token,  link;\r
+    while(st.hasMoreElements())\r
+    {\r
+      token = st.nextToken("<>");\r
+      if(token.equalsIgnoreCase("html") || token.startsWith("/"))\r
+        continue;\r
+\r
+      if(token.startsWith("a href="))\r
+      {\r
+        link = token.substring(token.indexOf("\"")+1, token.length()-1);\r
+        String label = st.nextToken("<>");\r
+        sf.addLink(label+"|"+link);\r
+        sb.append(label+"%LINK%");\r
+      }\r
+      else if(token.equalsIgnoreCase("br"))\r
+        sb.append("\n");\r
+      else\r
+        sb.append(token);\r
+    }\r
+\r
+    sf.description = sb.toString();\r
+  }\r
+\r
   public void keyPressed(KeyEvent evt)\r
   {\r
+    if (viewport.cursorMode\r
+        && evt.getKeyCode() >= KeyEvent.VK_0\r
+        && evt.getKeyCode() <= KeyEvent.VK_9)\r
+    {\r
+      alignPanel.seqPanel.numberPressed(evt.getKeyChar());\r
+    }\r
+\r
     switch (evt.getKeyCode())\r
     {\r
       case 27: // escape key\r
@@ -262,6 +325,10 @@ public class AlignFrame extends Frame implements ActionListener,
         }\r
         break;\r
       case KeyEvent.VK_C:\r
+        if (viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.setCursorColumn();\r
+        }\r
         if (evt.isControlDown() || evt.isMetaDown())\r
         {\r
           copy_actionPerformed();\r
@@ -280,21 +347,108 @@ public class AlignFrame extends Frame implements ActionListener,
         }\r
         break;\r
       case KeyEvent.VK_DOWN:\r
-        moveSelectedSequences(false);\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.moveCursor(0,1);\r
+        }\r
+        else\r
+          moveSelectedSequences(false);\r
         break;\r
+\r
       case KeyEvent.VK_UP:\r
-        moveSelectedSequences(true);\r
+        if (viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.moveCursor(0,-1);\r
+        }\r
+        else\r
+          moveSelectedSequences(true);\r
+        break;\r
+\r
+      case KeyEvent.VK_LEFT:\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.moveCursor(-1,0);\r
+        }\r
+        break;\r
+\r
+      case KeyEvent.VK_RIGHT:\r
+        if (viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.moveCursor(1,0);\r
+        }\r
+        break;\r
+      case KeyEvent.VK_SPACE:\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown());\r
+        }\r
+        break;\r
+\r
+      case KeyEvent.VK_DELETE:\r
+      case KeyEvent.VK_BACK_SPACE:\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown());\r
+        }\r
+       else\r
+        {\r
+          cut_actionPerformed();\r
+          alignPanel.seqPanel.seqCanvas.repaint();\r
+        }\r
+        break;\r
+\r
+      case KeyEvent.VK_S:\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.setCursorRow();\r
+        }\r
+        break;\r
+      case KeyEvent.VK_P:\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.setCursorPosition();\r
+        }\r
+        break;\r
+\r
+      case KeyEvent.VK_ENTER:\r
+      case KeyEvent.VK_COMMA:\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.setCursorRowAndColumn();\r
+        }\r
         break;\r
+\r
+      case KeyEvent.VK_Q:\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.setSelectionAreaAtCursor(true);\r
+        }\r
+        break;\r
+      case KeyEvent.VK_M:\r
+        if(viewport.cursorMode)\r
+        {\r
+          alignPanel.seqPanel.setSelectionAreaAtCursor(false);\r
+        }\r
+        break;\r
+\r
+     case KeyEvent.VK_F2:\r
+       viewport.cursorMode = ! viewport.cursorMode;\r
+       statusBar.setText("Keyboard editing mode is "+\r
+           (viewport.cursorMode ? "on" : "off"));\r
+       if(viewport.cursorMode)\r
+       {\r
+         alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;\r
+         alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;\r
+       }\r
+       alignPanel.seqPanel.seqCanvas.repaint();\r
+       break;\r
+\r
       case KeyEvent.VK_F:\r
         if (evt.isControlDown())\r
         {\r
           findMenuItem_actionPerformed();\r
         }\r
         break;\r
-      case KeyEvent.VK_BACK_SPACE:\r
-      case KeyEvent.VK_DELETE:\r
-        cut_actionPerformed();\r
-        break;\r
     }\r
   }\r
   public void keyReleased(KeyEvent evt)\r
@@ -335,6 +489,8 @@ public void itemStateChanged(ItemEvent evt)
             abovePIDThreshold_actionPerformed();\r
           else if(evt.getSource()==applyToAllGroups)\r
             applyToAllGroups_actionPerformed();\r
+      else if(evt.getSource()==autoCalculate)\r
+          viewport.autocalculateConsensus = autoCalculate.getState();\r
   }\r
  public void actionPerformed(ActionEvent evt)\r
  {\r
@@ -829,6 +985,11 @@ public void itemStateChanged(ItemEvent evt)
 \r
   public void deselectAllSequenceMenuItem_actionPerformed()\r
   {\r
+    if(viewport.cursorMode)\r
+    {\r
+      alignPanel.seqPanel.keyboardNo1=null;\r
+      alignPanel.seqPanel.keyboardNo2=null;\r
+    }\r
     viewport.setSelectionGroup(null);\r
     viewport.getColumnSelection().clear();\r
     viewport.setSelectionGroup(null);\r
@@ -1003,8 +1164,13 @@ public void itemStateChanged(ItemEvent evt)
 \r
   public void alignmentChanged()\r
   {\r
-    viewport.updateConsensus();\r
-    viewport.updateConservation ();\r
+    viewport.alignment.padGaps();\r
+    if(viewport.autocalculateConsensus)\r
+    {\r
+      viewport.updateConsensus();\r
+      viewport.updateConservation();\r
+    }\r
+\r
     resetAllColourSchemes();\r
     if(alignPanel.overviewPanel!=null)\r
       alignPanel.overviewPanel.updateOverviewImage();\r
@@ -1749,6 +1915,8 @@ public void itemStateChanged(ItemEvent evt)
     protected CheckboxMenuItem scaleRight = new CheckboxMenuItem();\r
     MenuItem modifyPID = new MenuItem();\r
     MenuItem modifyConservation = new MenuItem();\r
+    protected CheckboxMenuItem autoCalculate\r
+        = new CheckboxMenuItem("Autocalculate Consensus", true);\r
     protected Menu sortByTreeMenu = new Menu();\r
     Menu sort = new Menu();\r
     Menu calculate = new Menu();\r
@@ -1926,6 +2094,7 @@ public void itemStateChanged(ItemEvent evt)
         sortByTreeMenu.setLabel("By Tree Order");\r
         sort.setLabel("Sort");\r
         calculate.setLabel("Calculate Tree");\r
+        autoCalculate.addItemListener(this);\r
         inputText.setLabel("Input from textbox");\r
         inputText.addActionListener(this);\r
 \r
@@ -2021,6 +2190,7 @@ public void itemStateChanged(ItemEvent evt)
         calculateMenu.addSeparator();\r
         calculateMenu.add(pairwiseAlignmentMenuItem);\r
         calculateMenu.add(PCAMenuItem);\r
+        calculateMenu.add(autoCalculate);\r
         this.add(statusBar, BorderLayout.SOUTH);\r
         pasteMenu.add(pasteNew);\r
         pasteMenu.add(pasteThis);\r