JAL-819 menu options to reinstate missing auto-calculated annotation
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 22 Nov 2019 15:14:13 +0000 (15:14 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 22 Nov 2019 15:14:13 +0000 (15:14 +0000)
src/jalview/api/AlignViewportI.java
src/jalview/datamodel/AlignmentAnnotation.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AnnotationLabels.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/viewmodel/AlignmentViewport.java

index 785dd14..707d03d 100644 (file)
@@ -528,4 +528,29 @@ public interface AlignViewportI extends ViewStyleI
    *          - a group defined on sequences in the alignment held by the view
    */
   void addSequenceGroup(SequenceGroup sequenceGroup);
+
+  /**
+   * Creates an empty Conservation annotation and adds it to the alignment
+   */
+  void initConservation();
+
+  /**
+   * Creates an empty Quality annotation and adds it to the alignment
+   */
+  void initQuality();
+
+  /**
+   * Creates an empty Consensus annotation and adds it to the alignment
+   */
+  void initConsensus();
+
+  /**
+   * Creates an empty Occupancy annotation and adds it to the alignment
+   */
+  void initOccupancy();
+
+  /**
+   * Creates an empty RNA Structure annotation and adds it to the alignment
+   */
+  void initRNAStructure();
 }
index 2ee4503..a898746 100755 (executable)
@@ -1647,20 +1647,27 @@ public class AlignmentAnnotation
     }
   }
 
+  /**
+   * Answers a (possibly empty) iterable list of those annotations in the supplied
+   * list whose reference sequence, calcId or label matches the supplied
+   * parameters. Null parameter values are ignored.
+   * 
+   * @param list
+   * @param seq
+   * @param calcId
+   * @param label
+   * @return
+   */
   public static Iterable<AlignmentAnnotation> findAnnotations(
           Iterable<AlignmentAnnotation> list, SequenceI seq, String calcId,
           String label)
   {
-
-    ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
+    List<AlignmentAnnotation> aa = new ArrayList<>();
     for (AlignmentAnnotation ann : list)
     {
-      if ((calcId == null || (ann.getCalcId() != null
-              && ann.getCalcId().equals(calcId)))
-              && (seq == null || (ann.sequenceRef != null
-                      && ann.sequenceRef == seq))
-              && (label == null
-                      || (ann.label != null && ann.label.equals(label))))
+      if ((calcId == null || calcId.equals(ann.getCalcId()))
+              && (seq == null || seq == ann.sequenceRef)
+              && (label == null || label.equals(ann.label)))
       {
         aa.add(ann);
       }
@@ -1693,6 +1700,14 @@ public class AlignmentAnnotation
     return false;
   }
 
+  /**
+   * Returns a (possibly empty) iterable set of annotations in the given list
+   * whose calcId matches the given value (which may not be null)
+   * 
+   * @param list
+   * @param calcId
+   * @return
+   */
   public static Iterable<AlignmentAnnotation> findAnnotation(
           List<AlignmentAnnotation> list, String calcId)
   {
index fcb6572..a44df97 100644 (file)
@@ -893,6 +893,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     scaleLeft.setVisible(av.getWrapAlignment());
     scaleRight.setVisible(av.getWrapAlignment());
     annotationPanelMenuItem.setState(av.isShowAnnotation());
+
     /*
      * Show/hide annotations only enabled if annotation panel is shown
      */
@@ -908,6 +909,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
     showSequenceLogo.setSelected(av.isShowSequenceLogo());
     normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
+    buildAutoAnnotationMenu(av);
 
     ColourMenuHelper.setColourSelected(colourMenu,
             av.getGlobalColourScheme());
@@ -928,6 +930,168 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   /**
+   * Adds menu items for the Autocalculated Annotation sub-menu
+   * 
+   * @param av 
+   */
+  void buildAutoAnnotationMenu(AlignViewport av)
+  {
+    autoAnnMenu.removeAll();
+    autoAnnMenu.add(showAutoFirst);
+    autoAnnMenu.add(showAutoLast);
+    autoAnnMenu.addSeparator();
+    autoAnnMenu.add(applyAutoAnnotationSettings);
+    autoAnnMenu.add(showConsensusHistogram);
+    autoAnnMenu.add(showSequenceLogo);
+    autoAnnMenu.add(normaliseSequenceLogo);
+    autoAnnMenu.addSeparator();
+
+    /*
+     * add options to reinstate any deleted auto-calculated annotations
+     */
+    boolean hasConservation = false;
+    boolean hasQuality = false;
+    boolean hasConsensus = false;
+    boolean hasOccupancy = false;
+    boolean hasRnaStruct = false;
+    AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
+    if (anns == null)
+    {
+      return;
+    }
+    for (int i = 0; i < anns.length; i++)
+    {
+      if (anns[i].autoCalculated)
+      {
+        // TODO JAL-3485 should let these strings be constants instead
+        if ("Conservation".equals(anns[i].label))
+        {
+          hasConservation = true;
+        }
+        else if ("Quality".equals(anns[i].label))
+        {
+          hasQuality = true;
+        }
+        else if ("Consensus".equals(anns[i].label))
+        {
+          hasConsensus = true;
+        }
+        else if ("Occupancy".equals(anns[i].label))
+        {
+          hasOccupancy = true;
+        }
+        else if ("StrucConsensus".equals(anns[i].label))
+        {
+          hasRnaStruct = true;
+        }
+      }
+    }
+    boolean added = false;
+
+    /*
+     * a shareable action to refresh stuff; NB action listeners
+     * get run in reverse order to that in which they are added!
+     */
+    ActionListener refresher = new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        alignPanel.adjustAnnotationHeight();
+        av.alignmentChanged(alignPanel);
+        buildAutoAnnotationMenu(av);
+      }
+    };
+
+    if (!av.isNucleotide())
+    {
+      if (!hasConservation)
+      {
+        JMenuItem mi = new JMenuItem("Conservation");
+        mi.addActionListener(refresher);
+        mi.addActionListener(new ActionListener()
+        {
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            av.initConservation();
+          }
+        });
+        autoAnnMenu.add(mi);
+        added = true;
+      }
+      if (!hasQuality)
+      {
+        JMenuItem mi = new JMenuItem("Quality");
+        mi.addActionListener(refresher);
+        mi.addActionListener(new ActionListener()
+        {
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            av.initQuality();
+          }
+        });
+        autoAnnMenu.add(mi);
+        added = true;
+      }
+    }
+    if (!hasConsensus)
+    {
+      JMenuItem mi = new JMenuItem("Consensus");
+      mi.addActionListener(refresher);
+      mi.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.initConsensus();
+        }
+      });
+      autoAnnMenu.add(mi);
+      added = true;
+    }
+    if (!hasOccupancy)
+    {
+      JMenuItem mi = new JMenuItem("Occupancy");
+      mi.addActionListener(refresher);
+      mi.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.initOccupancy();
+        }
+      });
+      autoAnnMenu.add(mi);
+      added = true;
+    }
+    if (!hasRnaStruct && av.isNucleotide()
+            && av.getAlignment().hasRNAStructure())
+    {
+      JMenuItem mi = new JMenuItem("Structure Consensus");
+      mi.addActionListener(refresher);
+      mi.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.initRNAStructure();
+        }
+      });
+      autoAnnMenu.add(mi);
+      added = true;
+    }
+
+    if (added)
+    {
+      autoAnnMenu.addSeparator();
+    }
+    autoAnnMenu.add(showGroupConservation);
+    autoAnnMenu.add(showGroupConsensus);
+  }
+
+  /**
    * Set the enabled state of the 'Run Groovy' option in the Calculate menu
    * 
    * @param b
index 6da6cc3..af76d26 100755 (executable)
@@ -278,7 +278,7 @@ public class AnnotationLabels extends JPanel
     {
       aa[selectedRow].scaleColLabel = !aa[selectedRow].scaleColLabel;
     }
-
+    ap.alignFrame.setMenusForViewport();
     ap.refresh(fullRepaint);
 
   }
index 075b490..63bc050 100755 (executable)
@@ -207,6 +207,12 @@ public class GAlignFrame extends JInternalFrame
 
   private SplitContainerI splitFrame;
 
+  protected JMenu autoAnnMenu;
+
+  protected JRadioButtonMenuItem showAutoFirst;
+
+  protected JRadioButtonMenuItem showAutoLast;
+
   public GAlignFrame()
   {
     try
@@ -875,9 +881,9 @@ public class GAlignFrame extends JInternalFrame
     });
 
     ButtonGroup buttonGroup = new ButtonGroup();
-    final JRadioButtonMenuItem showAutoFirst = new JRadioButtonMenuItem(
+    showAutoFirst = new JRadioButtonMenuItem(
             MessageManager.getString("label.show_first"));
-    final JRadioButtonMenuItem showAutoLast = new JRadioButtonMenuItem(
+    showAutoLast = new JRadioButtonMenuItem(
             MessageManager.getString("label.show_last"));
     buttonGroup.add(showAutoFirst);
     buttonGroup.add(showAutoLast);
@@ -1709,7 +1715,7 @@ public class GAlignFrame extends JInternalFrame
     selectHighlighted.addActionListener(al);
     JMenu tooltipSettingsMenu = new JMenu(
             MessageManager.getString("label.sequence_id_tooltip"));
-    JMenu autoAnnMenu = new JMenu(
+    autoAnnMenu = new JMenu(
             MessageManager.getString("label.autocalculated_annotation"));
 
     JMenu exportImageMenu = new JMenu(
@@ -1805,17 +1811,7 @@ public class GAlignFrame extends JInternalFrame
     annotationsMenu.add(sortAnnBySequence);
     annotationsMenu.add(sortAnnByLabel);
     annotationsMenu.addSeparator();
-    autoAnnMenu.add(showAutoFirst);
-    autoAnnMenu.add(showAutoLast);
-    autoAnnMenu.addSeparator();
-    autoAnnMenu.add(applyAutoAnnotationSettings);
-    autoAnnMenu.add(showConsensusHistogram);
-    autoAnnMenu.add(showSequenceLogo);
-    autoAnnMenu.add(normaliseSequenceLogo);
-    autoAnnMenu.addSeparator();
-    autoAnnMenu.add(showGroupConservation);
-    autoAnnMenu.add(showGroupConsensus);
-    annotationsMenu.add(autoAnnMenu);
+    annotationsMenu.add(autoAnnMenu); // autoAnnMenu is populated later
 
     sort.add(sortIDMenuItem);
     sort.add(sortLengthMenuItem);
index 8dcd1b3..9de0b94 100644 (file)
@@ -1931,18 +1931,31 @@ public abstract class AlignmentViewport
     {
       if (!alignment.isNucleotide())
       {
-        initConservation();
-        initQuality();
+        if (showConservation && conservation == null)
+        {
+          initConservation();
+        }
+        if (showQuality && quality == null)
+        {
+          initQuality();
+        }
       }
       else
       {
-        initRNAStructure();
+        if (showConsensus && alignment.hasRNAStructure()
+                && strucConsensus == null)
+        {
+          initRNAStructure();
+        }
+      }
+      if (showConsensus)
+      {
+        initConsensus();
+      }
+      if (showOccupancy)
+      {
+        initOccupancy();
       }
-      consensus = new AlignmentAnnotation("Consensus",
-              MessageManager.getString("label.consensus_descr"),
-              new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
-      initConsensus(consensus);
-      initGapCounts();
 
       initComplementConsensus();
     }
@@ -1988,84 +2001,76 @@ public abstract class AlignmentViewport
     return false;
   }
 
+  @Override
+  public void initConsensus()
+  {
+    consensus = new AlignmentAnnotation("Consensus",
+            MessageManager.getString("label.consensus_descr"),
+            new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+    initConsensus(consensus);
+  }
+
   private void initConsensus(AlignmentAnnotation aa)
   {
-    aa.hasText = true;
-    aa.autoCalculated = true;
+    consensus = new AlignmentAnnotation("Consensus",
+            MessageManager.getString("label.consensus_descr"),
+            new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+    consensus.hasText = true;
+    consensus.autoCalculated = true;
 
     if (showConsensus)
     {
-      alignment.addAnnotation(aa);
+      alignment.addAnnotation(consensus);
     }
   }
 
-  // these should be extracted from the view model - style and settings for
-  // derived annotation
-  private void initGapCounts()
+  @Override
+  public void initOccupancy()
   {
-    if (showOccupancy)
-    {
-      gapcounts = new AlignmentAnnotation("Occupancy",
-              MessageManager.getString("label.occupancy_descr"),
-              new Annotation[1], 0f, alignment.getHeight(),
-              AlignmentAnnotation.BAR_GRAPH);
-      gapcounts.hasText = true;
-      gapcounts.autoCalculated = true;
-      gapcounts.scaleColLabel = true;
-      gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
+    gapcounts = new AlignmentAnnotation("Occupancy",
+            MessageManager.getString("label.occupancy_descr"),
+            new Annotation[1], 0f, alignment.getHeight(),
+            AlignmentAnnotation.BAR_GRAPH);
+    gapcounts.hasText = true;
+    gapcounts.autoCalculated = true;
+    gapcounts.scaleColLabel = true;
+    gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
 
-      alignment.addAnnotation(gapcounts);
-    }
+    alignment.addAnnotation(gapcounts);
   }
 
-  private void initConservation()
+  @Override
+  public void initConservation()
   {
-    if (showConservation)
-    {
-      if (conservation == null)
-      {
-        conservation = new AlignmentAnnotation("Conservation",
-                MessageManager.formatMessage("label.conservation_descr",
-                        getConsPercGaps()),
-                new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
-        conservation.hasText = true;
-        conservation.autoCalculated = true;
-        alignment.addAnnotation(conservation);
-      }
-    }
+    conservation = new AlignmentAnnotation("Conservation",
+            MessageManager.formatMessage("label.conservation_descr",
+                    getConsPercGaps()),
+            new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
+    conservation.hasText = true;
+    conservation.autoCalculated = true;
+    alignment.addAnnotation(conservation);
   }
 
-  private void initQuality()
+  @Override
+  public void initQuality()
   {
-    if (showQuality)
-    {
-      if (quality == null)
-      {
-        quality = new AlignmentAnnotation("Quality",
-                MessageManager.getString("label.quality_descr"),
-                new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
-        quality.hasText = true;
-        quality.autoCalculated = true;
-        alignment.addAnnotation(quality);
-      }
-    }
+    quality = new AlignmentAnnotation("Quality",
+            MessageManager.getString("label.quality_descr"),
+            new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
+    quality.hasText = true;
+    quality.autoCalculated = true;
+    alignment.addAnnotation(quality);
   }
 
-  private void initRNAStructure()
+  @Override
+  public void initRNAStructure()
   {
-    if (alignment.hasRNAStructure() && strucConsensus == null)
-    {
-      strucConsensus = new AlignmentAnnotation("StrucConsensus",
-              MessageManager.getString("label.strucconsensus_descr"),
-              new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
-      strucConsensus.hasText = true;
-      strucConsensus.autoCalculated = true;
-
-      if (showConsensus)
-      {
-        alignment.addAnnotation(strucConsensus);
-      }
-    }
+    strucConsensus = new AlignmentAnnotation("StrucConsensus",
+            MessageManager.getString("label.strucconsensus_descr"),
+            new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+    strucConsensus.hasText = true;
+    strucConsensus.autoCalculated = true;
+    alignment.addAnnotation(strucConsensus);
   }
 
   /*