JAL-244 Changes to Annotation labels width now adjusts the overall idWidth if larger...
authorBen Soares <b.soares@dundee.ac.uk>
Wed, 19 Jul 2023 23:34:55 +0000 (00:34 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Wed, 19 Jul 2023 23:34:55 +0000 (00:34 +0100)
src/jalview/gui/AlignViewport.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/IdwidthAdjuster.java

index 5613f16..ef9e575 100644 (file)
@@ -45,7 +45,6 @@ import jalview.bin.Console;
 import jalview.commands.CommandI;
 import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.Alignment;
-import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.ContactMatrixI;
index 3dfb510..db193f1 100644 (file)
@@ -269,10 +269,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     Dimension r = null;
     if (av.getIdWidth() < 0)
     {
-      int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
-      int idWidth = Math.min(afwidth - 200, 2 * afwidth / 3);
-      int maxwidth = Math.max(IdwidthAdjuster.MIN_ID_WIDTH, idWidth);
-      r = calculateIdWidth(maxwidth);
+      r = calculateDefaultAlignmentIdWidth();
       av.setIdWidth(r.width);
     }
     else
@@ -294,6 +291,14 @@ public class AlignmentPanel extends GAlignmentPanel implements
     return r;
   }
 
+  public Dimension calculateDefaultAlignmentIdWidth()
+  {
+    int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
+    int idWidth = Math.min(afwidth - 200, 2 * afwidth / 3);
+    int maxwidth = Math.max(IdwidthAdjuster.MIN_ID_WIDTH, idWidth);
+    return calculateIdWidth(-1);
+  }
+
   /**
    * Calculate the width of the alignment labels based on the displayed names
    * and any bounds on label width set in preferences.
@@ -1175,7 +1180,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
     return (w > 0 ? w : calculateIdWidth().width);
   }
 
-  void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer) throws ImageOutputException
+  void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer)
+          throws ImageOutputException
   {
     makeAlignmentImage(type, file, renderer,
             BitmapImageSizing.nullBitmapImageSizing());
@@ -1266,7 +1272,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
   }
 
-  public void makePNGImageMap(File imgMapFile, String imageName) throws ImageOutputException
+  public void makePNGImageMap(File imgMapFile, String imageName)
+          throws ImageOutputException
   {
     // /////ONLY WORKS WITH NON WRAPPED ALIGNMENTS
     // ////////////////////////////////////////////
@@ -1391,7 +1398,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
       } catch (Exception ex)
       {
-        throw new ImageOutputException("couldn't write ImageMap due to unexpected error",ex);
+        throw new ImageOutputException(
+                "couldn't write ImageMap due to unexpected error", ex);
       }
     } // /////////END OF IMAGE MAP
 
index 6b82a37..d459217 100755 (executable)
@@ -50,6 +50,8 @@ import javax.swing.ToolTipManager;
 
 import jalview.analysis.AlignSeq;
 import jalview.analysis.AlignmentUtils;
+import jalview.bin.Cache;
+import jalview.bin.Jalview;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
@@ -113,6 +115,8 @@ public class AnnotationLabels extends JPanel
   private static final String COPYCONS_SEQ = MessageManager
           .getString("label.copy_consensus_sequence");
 
+  private static final String ADJUST_ANNOTATION_LABELS_WIDTH_PREF = "ADJUST_ANNOTATION_LABELS_WIDTH";
+
   private final boolean debugRedraw = false;
 
   private AlignmentPanel ap;
@@ -138,7 +142,6 @@ public class AnnotationLabels extends JPanel
    */
   public AnnotationLabels(AlignmentPanel ap)
   {
-
     this.ap = ap;
     av = ap.av;
     ToolTipManager.sharedInstance().registerComponent(this);
@@ -418,65 +421,74 @@ public class AnnotationLabels extends JPanel
         pop.add(consclipbrd);
       }
 
-      addColourOrFilterByOptions(ap,aa[selectedRow],pop);
-      
+      addColourOrFilterByOptions(ap, aa[selectedRow], pop);
+
       if (aa[selectedRow].graph == AlignmentAnnotation.CONTACT_MAP)
       {
-        addContactMatrixOptions(ap,aa[selectedRow],pop);
-          // Set/adjust threshold for grouping ?
-          // colour alignment by this [type]
-          // select/hide columns by this row
-          
-        }
+        addContactMatrixOptions(ap, aa[selectedRow], pop);
+        // Set/adjust threshold for grouping ?
+        // colour alignment by this [type]
+        // select/hide columns by this row
+
       }
-    
+    }
+
     pop.show(this, evt.getX(), evt.getY());
   }
 
   static void addColourOrFilterByOptions(final AlignmentPanel ap,
-          final AlignmentAnnotation alignmentAnnotation, final JPopupMenu pop)
+          final AlignmentAnnotation alignmentAnnotation,
+          final JPopupMenu pop)
   {
     JMenuItem item;
-    item = new JMenuItem(MessageManager.getString("label.colour_by_annotation"));
+    item = new JMenuItem(
+            MessageManager.getString("label.colour_by_annotation"));
     item.addActionListener(new ActionListener()
     {
-      
+
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        AnnotationColourChooser.displayFor(ap.av, ap,alignmentAnnotation,false);
+        AnnotationColourChooser.displayFor(ap.av, ap, alignmentAnnotation,
+                false);
       };
     });
     pop.add(item);
-    if (alignmentAnnotation.sequenceRef!=null)
+    if (alignmentAnnotation.sequenceRef != null)
     {
-      item = new JMenuItem(MessageManager.getString("label.colour_by_annotation")+" ("+MessageManager.getString("label.per_seq")+")");
+      item = new JMenuItem(
+              MessageManager.getString("label.colour_by_annotation") + " ("
+                      + MessageManager.getString("label.per_seq") + ")");
       item.addActionListener(new ActionListener()
       {
         @Override
         public void actionPerformed(ActionEvent e)
         {
-          AnnotationColourChooser.displayFor(ap.av, ap,alignmentAnnotation,true);
+          AnnotationColourChooser.displayFor(ap.av, ap, alignmentAnnotation,
+                  true);
         };
       });
       pop.add(item);
     }
-    item = new JMenuItem(MessageManager.getString("action.select_by_annotation"));
+    item = new JMenuItem(
+            MessageManager.getString("action.select_by_annotation"));
     item.addActionListener(new ActionListener()
     {
-      
+
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        AnnotationColumnChooser.displayFor(ap.av,ap,alignmentAnnotation);
+        AnnotationColumnChooser.displayFor(ap.av, ap, alignmentAnnotation);
       };
     });
     pop.add(item);
   }
+
   static void addContactMatrixOptions(final AlignmentPanel ap,
-          final AlignmentAnnotation alignmentAnnotation, final JPopupMenu pop)
+          final AlignmentAnnotation alignmentAnnotation,
+          final JPopupMenu pop)
   {
-    
+
     final ContactMatrixI cm = ap.av.getContactMatrix(alignmentAnnotation);
     JMenuItem item;
     if (cm != null)
@@ -485,10 +497,13 @@ public class AnnotationLabels extends JPanel
 
       if (cm.hasGroups())
       {
-        JCheckBoxMenuItem chitem = new JCheckBoxMenuItem(MessageManager.getString("action.show_groups_on_matrix"));
-        chitem.setToolTipText(MessageManager.getString("action.show_groups_on_matrix_tooltip"));
-        boolean showGroups = alignmentAnnotation.isShowGroupsForContactMatrix();
-        final AlignmentAnnotation sel_row=alignmentAnnotation;
+        JCheckBoxMenuItem chitem = new JCheckBoxMenuItem(
+                MessageManager.getString("action.show_groups_on_matrix"));
+        chitem.setToolTipText(MessageManager
+                .getString("action.show_groups_on_matrix_tooltip"));
+        boolean showGroups = alignmentAnnotation
+                .isShowGroupsForContactMatrix();
+        final AlignmentAnnotation sel_row = alignmentAnnotation;
         chitem.setState(showGroups);
         chitem.addActionListener(new ActionListener()
         {
@@ -498,15 +513,17 @@ public class AnnotationLabels extends JPanel
           {
             sel_row.setShowGroupsForContactMatrix(chitem.getState());
             ap.getAnnotationPanel()
-            .paint(ap.getAnnotationPanel().getGraphics());
+                    .paint(ap.getAnnotationPanel().getGraphics());
           }
         });
         pop.add(chitem);
       }
       if (cm.hasTree())
       {
-        item = new JMenuItem(MessageManager.getString("action.show_tree_for_matrix"));
-        item.setToolTipText(MessageManager.getString("action.show_tree_for_matrix_tooltip"));
+        item = new JMenuItem(
+                MessageManager.getString("action.show_tree_for_matrix"));
+        item.setToolTipText(MessageManager
+                .getString("action.show_tree_for_matrix_tooltip"));
         item.addActionListener(new ActionListener()
         {
 
@@ -522,8 +539,10 @@ public class AnnotationLabels extends JPanel
       }
       else
       {
-        item = new JMenuItem(MessageManager.getString("action.cluster_matrix"));
-        item.setToolTipText(MessageManager.getString("action.cluster_matrix_tooltip"));
+        item = new JMenuItem(
+                MessageManager.getString("action.cluster_matrix"));
+        item.setToolTipText(
+                MessageManager.getString("action.cluster_matrix_tooltip"));
         item.addActionListener(new ActionListener()
         {
           @Override
@@ -535,7 +554,11 @@ public class AnnotationLabels extends JPanel
               public void run()
               {
                 final long progBar;
-                ap.alignFrame.setProgressBar(MessageManager.formatMessage("action.clustering_matrix_for",cm.getAnnotDescr(),5f), progBar = System.currentTimeMillis());
+                ap.alignFrame.setProgressBar(
+                        MessageManager.formatMessage(
+                                "action.clustering_matrix_for",
+                                cm.getAnnotDescr(), 5f),
+                        progBar = System.currentTimeMillis());
                 cm.setGroupSet(GroupSet.makeGroups(cm, 5f, true));
                 ap.alignFrame.showContactMapTree(alignmentAnnotation, cm);
                 ap.alignFrame.setProgressBar(null, progBar);
@@ -1166,8 +1189,58 @@ public class AnnotationLabels extends JPanel
    * @param width
    *          Width for scaling labels
    */
-  public void drawComponent(Graphics g, boolean clip, int width)
+  public void drawComponent(Graphics g, boolean clip, int givenWidth)
+  {
+    int width = givenWidth;
+    IdwidthAdjuster iwa = ap.idwidthAdjuster;
+    if ((Cache.getDefault(ADJUST_ANNOTATION_LABELS_WIDTH_PREF, true)
+            || Jalview.isHeadlessMode()) && !iwa.manuallyAdjusted())
+    {
+      Graphics2D g2d = (Graphics2D) g;
+      Graphics dummy = g2d.create();
+      int annotationIdWidth = drawLabels(dummy, clip, width, false);
+      Dimension d = ap.calculateDefaultAlignmentIdWidth();
+      int alignmentIdWidth = d.width;
+      if (!iwa.manuallyAdjusted())
+      {
+        // If no manual adjustment to ID column with has been made then adjust
+        // width match widest of alignment or annotation id widths
+        width = Math.max(alignmentIdWidth, annotationIdWidth);
+      }
+      else if (annotationIdWidth > givenWidth
+              && annotationIdWidth > alignmentIdWidth)
+      {
+        // otherwise if the annotation id width has become larger than the
+        // current id width, increase
+        width = annotationIdWidth;
+      }
+      // set the width if it's changed
+      if (width != ap.av.getIdWidth())
+      {
+        iwa.setWidth(width);
+        ap.validateAnnotationDimensions(false);
+      }
+    }
+    drawLabels(g, clip, width, true);
+  }
+
+  /**
+   * Render the full set of annotation Labels for the alignment at the given
+   * cursor. If actuallyDraw is false then no actual drawing will occur, but the
+   * widest label width will be returned.
+   * 
+   * @param g
+   *          Graphics2D instance (needed for font scaling)
+   * @param clip
+   *          - true indicates that only current visible area needs to be
+   *          rendered
+   * @param width
+   *          Width for scaling labels
+   */
+  public int drawLabels(Graphics g, boolean clip, int width,
+          boolean actuallyDraw)
   {
+    int actualWidth = 0;
     if (av.getFont().getSize() < 10)
     {
       g.setFont(font);
@@ -1178,11 +1251,17 @@ public class AnnotationLabels extends JPanel
     }
 
     FontMetrics fm = g.getFontMetrics(g.getFont());
-    g.setColor(Color.white);
-    g.fillRect(0, 0, getWidth(), getHeight());
+    if (actuallyDraw)
+    {
+      g.setColor(Color.white);
+      g.fillRect(0, 0, getWidth(), getHeight());
+    }
 
-    g.translate(0, getScrollOffset());
-    g.setColor(Color.black);
+    if (actuallyDraw)
+    {
+      g.translate(0, getScrollOffset());
+      g.setColor(Color.black);
+    }
     SequenceI lastSeqRef = null;
     String lastLabel = null;
     AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
@@ -1255,8 +1334,10 @@ public class AnnotationLabels extends JPanel
             continue;
           }
         }
-        g.setColor(Color.black);
-
+        if (actuallyDraw)
+        {
+          g.setColor(Color.black);
+        }
         offset = -aa[i].height / 2;
 
         if (aa[i].hasText)
@@ -1301,7 +1382,9 @@ public class AnnotationLabels extends JPanel
             vertBar = true;
           }
         }
-        x = width - fm.stringWidth(label) - 3;
+
+        int labelWidth = fm.stringWidth(label) + 3;
+        x = width - labelWidth;
 
         if (aa[i].graphGroup > -1)
         {
@@ -1346,19 +1429,23 @@ public class AnnotationLabels extends JPanel
             {
               if (aa[gg].graphGroup == aa[i].graphGroup)
               {
-                x = width - fm.stringWidth(aa[gg].label) - 3;
-                g.drawString(aa[gg].label, x, y - graphExtras);
-
-                if (aa[gg]._linecolour != null)
+                labelWidth = fm.stringWidth(aa[gg].label) + 3;
+                x = width - labelWidth;
+                if (actuallyDraw)
                 {
+                  g.drawString(aa[gg].label, x, y - graphExtras);
 
-                  g.setColor(aa[gg]._linecolour);
-                  g.drawLine(x, y - graphExtras + 3,
-                          x + fm.stringWidth(aa[gg].label),
-                          y - graphExtras + 3);
-                }
+                  if (aa[gg]._linecolour != null)
+                  {
+
+                    g.setColor(aa[gg]._linecolour);
+                    g.drawLine(x, y - graphExtras + 3,
+                            x + fm.stringWidth(aa[gg].label),
+                            y - graphExtras + 3);
+                  }
 
-                g.setColor(Color.black);
+                  g.setColor(Color.black);
+                }
                 graphExtras += fontHeight + 8;
               }
             }
@@ -1369,35 +1456,51 @@ public class AnnotationLabels extends JPanel
         }
         else
         {
-          if (vertBar)
+          if (actuallyDraw)
           {
-            g.drawLine(width - 3, y + offset - fontHeight, width - 3,
-                    (int) (y - 1.5 * aa[i].height - offset - fontHeight));
-            // g.drawLine(20, y + offset, x - 20, y + offset);
+            if (vertBar)
+            {
+              g.drawLine(width - 3, y + offset - fontHeight, width - 3,
+                      (int) (y - 1.5 * aa[i].height - offset - fontHeight));
+              // g.drawLine(20, y + offset, x - 20, y + offset);
 
+            }
+            g.drawString(label, x, y + offset);
           }
-          g.drawString(label, x, y + offset);
         }
         lastSeqRef = aa[i].sequenceRef;
+
+        if (labelWidth > actualWidth)
+        {
+          actualWidth = labelWidth;
+        }
       }
     }
 
     if (!resizePanel && dragEvent != null && aa != null)
     {
-      g.setColor(Color.lightGray);
-      g.drawString(
-              (aa[selectedRow].sequenceRef == null ? ""
-                      : aa[selectedRow].sequenceRef.getName())
-                      + aa[selectedRow].label,
-              dragEvent.getX(), dragEvent.getY() - getScrollOffset());
+      if (actuallyDraw)
+      {
+        g.setColor(Color.lightGray);
+        g.drawString(
+                (aa[selectedRow].sequenceRef == null ? ""
+                        : aa[selectedRow].sequenceRef.getName())
+                        + aa[selectedRow].label,
+                dragEvent.getX(), dragEvent.getY() - getScrollOffset());
+      }
     }
 
     if (!av.getWrapAlignment() && ((aa == null) || (aa.length < 1)))
     {
-      g.drawString(MessageManager.getString("label.right_click"), 2, 8);
-      g.drawString(MessageManager.getString("label.to_add_annotation"), 2,
-              18);
+      if (actuallyDraw)
+      {
+        g.drawString(MessageManager.getString("label.right_click"), 2, 8);
+        g.drawString(MessageManager.getString("label.to_add_annotation"), 2,
+                18);
+      }
     }
+
+    return actualWidth;
   }
 
   public int getScrollOffset()
index 4ba0699..eef5bfb 100755 (executable)
@@ -20,8 +20,6 @@
  */
 package jalview.gui;
 
-import jalview.api.AlignViewportI;
-
 import java.awt.Color;
 import java.awt.Cursor;
 import java.awt.Graphics;
@@ -31,6 +29,8 @@ import java.awt.event.MouseMotionListener;
 
 import javax.swing.JPanel;
 
+import jalview.api.AlignViewportI;
+
 /**
  * DOCUMENT ME!
  * 
@@ -46,6 +46,8 @@ public class IdwidthAdjuster extends JPanel
 
   AlignmentPanel ap;
 
+  private boolean manuallyAdjusted = false;
+
   /**
    * Creates a new IdwidthAdjuster object.
    * 
@@ -146,7 +148,26 @@ public class IdwidthAdjuster extends JPanel
       return;
     }
     viewport.setIdWidth(newWidth);
+    ap.validateAnnotationDimensions(false);
     ap.paintAlignment(true, false);
+
+    manuallyAdjusted = true;
+  }
+
+  public void setWidth(int newWidth)
+  {
+    if (newWidth < MIN_ID_WIDTH)
+    {
+      return;
+    }
+    final AlignViewportI viewport = ap.getAlignViewport();
+    viewport.setIdWidth(newWidth);
+    ap.paintAlignment(true, false);
+  }
+
+  public boolean manuallyAdjusted()
+  {
+    return manuallyAdjusted;
   }
 
   @Override