Merge branch 'feature/JAL-244_Automatically_adjust_left_margin_to_avoid_cropping_anno...
authorBen Soares <b.soares@dundee.ac.uk>
Fri, 18 Aug 2023 13:34:52 +0000 (14:34 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Fri, 18 Aug 2023 13:34:52 +0000 (14:34 +0100)
17 files changed:
examples/argfiles/test_fab41.txt
examples/argfiles/test_fab41_nostructureviewers.txt [new file with mode: 0644]
src/jalview/bin/Commands.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/IdCanvas.java
src/jalview/gui/IdwidthAdjuster.java
src/jalview/gui/SeqCanvas.java
src/jalview/gui/StructureChooser.java
src/jalview/gui/StructureViewer.java
src/jalview/jbgui/GAlignmentPanel.java
src/jalview/viewmodel/styles/ViewStyle.java
test/files/annotation_label_width/sample.a2m [new file with mode: 0644]
test/files/annotation_label_width/test_fab41_nostructureviewers.txt [new file with mode: 0644]
test/jalview/gui/AnnotationLabelsTest2.java [new file with mode: 0644]

index e6f7627..b7f0d45 100644 (file)
@@ -10,4 +10,4 @@
 --paematrix=[label=pAE R4-M5]./examples/test_fab41.result/test_fab41_unrelaxed_rank_4_model_5_scores.json
 --structure=./examples/test_fab41.result/test_fab41_unrelaxed_rank_5_model_1.pdb
 --paematrix=[label=pAE R5-M1]./examples/test_fab41.result/test_fab41_unrelaxed_rank_5_model_1_scores.json
---image=output1.html
+--image=[textrenderer=text]output1.html
diff --git a/examples/argfiles/test_fab41_nostructureviewers.txt b/examples/argfiles/test_fab41_nostructureviewers.txt
new file mode 100644 (file)
index 0000000..ab52cdf
--- /dev/null
@@ -0,0 +1,14 @@
+--open=./examples/test_fab41.result/sample.a2m
+--colour=gecos:flower
+--gui
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb
+--paematrix=[label=pAE R1-M3]./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3_scores.json
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_2_model_4.pdb
+--paematrix=[label=pAE R2-M4]./examples/test_fab41.result/test_fab41_unrelaxed_rank_2_model_4_scores.json
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_3_model_2.pdb
+--paematrix=[label=pAE R3-M2]./examples/test_fab41.result/test_fab41_unrelaxed_rank_3_model_2_scores.json
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_4_model_5.pdb
+--paematrix=[label=pAE R4-M5]./examples/test_fab41.result/test_fab41_unrelaxed_rank_4_model_5_scores.json
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_5_model_1.pdb
+--paematrix=[label=pAE R5-M1]./examples/test_fab41.result/test_fab41_unrelaxed_rank_5_model_1_scores.json
+--image=[textrenderer=text]output1.html
index 17a1af2..63247a7 100644 (file)
@@ -6,7 +6,6 @@ import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -166,13 +165,9 @@ public class Commands
     if (avm == null)
       return true;
 
-    /*
-     * // script to execute after all loading is completed one way or another String
-     * groovyscript = m.get(Arg.GROOVY) == null ? null :
-     * m.get(Arg.GROOVY).getValue(); String file = m.get(Arg.OPEN) == null ? null :
-     * m.get(Arg.OPEN).getValue(); String data = null; FileFormatI format = null;
-     * DataSourceType protocol = null;
-     */
+    // set wrap scope here so it can be applied after structures are opened
+    boolean wrap = false;
+
     if (avm.containsArg(Arg.APPEND) || avm.containsArg(Arg.OPEN))
     {
       commandArgsProvided = true;
@@ -256,11 +251,6 @@ public class Commands
           af = fileLoader.LoadFileWaitTillLoaded(openFile, protocol,
                   format);
 
-          // wrap alignment?
-          boolean wrap = ArgParser.getFromSubValArgOrPref(avm, Arg.WRAP, sv,
-                  null, "WRAP_ALIGNMENT", false);
-          af.getCurrentView().setWrapAlignment(wrap);
-
           // colour alignment?
           String colour = ArgParser.getFromSubValArgOrPref(avm, av,
                   Arg.COLOUR, sv, null, "DEFAULT_COLOUR_PROT", "");
@@ -365,6 +355,12 @@ public class Commands
                     false, false);
           }
 
+          // wrap alignment? do this last for formatting reasons
+          wrap = ArgParser.getFromSubValArgOrPref(avm, Arg.WRAP, sv, null,
+                  "WRAP_ALIGNMENT", false);
+          // af.setWrapFormat(wrap) is applied after structures are opened for
+          // annotation reasons
+
           // store the AlignFrame for this id
           afMap.put(id, af);
 
@@ -556,20 +552,7 @@ public class Commands
           String sViewer = ArgParser.getFromSubValArgOrPref(avm,
                   Arg.STRUCTUREVIEWER, Position.AFTER, av, subVals, null,
                   null, "jmol");
-          ViewerType viewerType = null;
-          if (!"none".equals(sViewer))
-          {
-            for (ViewerType v : EnumSet.allOf(ViewerType.class))
-            {
-              String name = v.name().toLowerCase(Locale.ROOT)
-                      .replaceAll(" ", "");
-              if (sViewer.equals(name))
-              {
-                viewerType = v;
-                break;
-              }
-            }
-          }
+          ViewerType viewerType = ViewerType.getFromString(sViewer);
 
           // TODO use ssFromStructure
           StructureViewer sv = StructureChooser
@@ -689,6 +672,15 @@ public class Commands
       }
     }
 
+    if (wrap)
+    {
+      AlignFrame af = afMap.get(id);
+      if (af != null)
+      {
+        af.setWrapFormat(wrap, true);
+      }
+    }
+
     /*
     boolean doShading = avm.getBoolean(Arg.TEMPFAC_SHADING);
     if (doShading)
index eb98d98..217175e 100644 (file)
@@ -3183,11 +3183,20 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void wrapMenuItem_actionPerformed(ActionEvent e)
   {
-    scaleAbove.setVisible(wrapMenuItem.isSelected());
-    scaleLeft.setVisible(wrapMenuItem.isSelected());
-    scaleRight.setVisible(wrapMenuItem.isSelected());
-    viewport.setWrapAlignment(wrapMenuItem.isSelected());
+    setWrapFormat(wrapMenuItem.isSelected(), false);
+  }
+
+  public void setWrapFormat(boolean b, boolean setMenuItem)
+  {
+    scaleAbove.setVisible(b);
+    scaleLeft.setVisible(b);
+    scaleRight.setVisible(b);
+    viewport.setWrapAlignment(b);
     alignPanel.updateLayout();
+    if (setMenuItem)
+    {
+      wrapMenuItem.setSelected(b);
+    }
   }
 
   @Override
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 3de02bc..ee71483 100644 (file)
@@ -50,6 +50,7 @@ import jalview.api.AlignmentViewPanel;
 import jalview.bin.Cache;
 import jalview.bin.Console;
 import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SearchResultsI;
@@ -269,10 +270,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 +292,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, false, false);
+  }
+
   /**
    * Calculate the width of the alignment labels based on the displayed names
    * and any bounds on label width set in preferences.
@@ -305,6 +311,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
    */
   protected Dimension calculateIdWidth(int maxwidth)
   {
+    return calculateIdWidth(maxwidth, true, false);
+  }
+
+  public Dimension calculateIdWidth(int maxwidth,
+          boolean includeAnnotations, boolean visibleOnly)
+  {
     Container c = new Container();
 
     FontMetrics fm = c.getFontMetrics(
@@ -324,18 +336,29 @@ public class AlignmentPanel extends GAlignmentPanel implements
     }
 
     // Also check annotation label widths
-    i = 0;
-
-    if (al.getAlignmentAnnotation() != null)
+    if (includeAnnotations && al.getAlignmentAnnotation() != null)
     {
-      fm = c.getFontMetrics(getAlabels().getFont());
-
-      while (i < al.getAlignmentAnnotation().length)
+      if (Jalview.isHeadlessMode())
       {
-        String label = al.getAlignmentAnnotation()[i].label;
-        int stringWidth = fm.stringWidth(label);
+        AnnotationLabels aal = this.getAlabels();
+        int stringWidth = aal.drawLabels(null, false, idWidth, false, fm);
         idWidth = Math.max(idWidth, stringWidth);
-        i++;
+      }
+      else
+      {
+        fm = c.getFontMetrics(getAlabels().getFont());
+
+        for (i = 0; i < al.getAlignmentAnnotation().length; i++)
+        {
+          AlignmentAnnotation aa = al.getAlignmentAnnotation()[i];
+          if (visibleOnly && !aa.visible)
+          {
+            continue;
+          }
+          String label = aa.label;
+          int stringWidth = fm.stringWidth(label);
+          idWidth = Math.max(idWidth, stringWidth);
+        }
       }
     }
 
@@ -567,21 +590,29 @@ public class AlignmentPanel extends GAlignmentPanel implements
     // not be called directly by programs.
     // I note that addNotify() is called in several areas of Jalview.
 
-    int annotationHeight = getAnnotationPanel().adjustPanelHeight();
-    annotationHeight = getAnnotationPanel()
-            .adjustForAlignFrame(adjustPanelHeight, annotationHeight);
+    AnnotationPanel ap = getAnnotationPanel();
+    int annotationHeight = ap.adjustPanelHeight();
+    annotationHeight = ap.adjustForAlignFrame(adjustPanelHeight,
+            annotationHeight);
 
     hscroll.addNotify();
-    annotationScroller.setPreferredSize(
-            new Dimension(annotationScroller.getWidth(), annotationHeight));
-
     Dimension e = idPanel.getSize();
-    alabels.setSize(new Dimension(e.width, annotationHeight));
+    int idWidth = e.width;
+    boolean manuallyAdjusted = this.getIdPanel().getIdCanvas()
+            .manuallyAdjusted();
+    annotationScroller.setPreferredSize(new Dimension(
+            manuallyAdjusted ? idWidth : annotationScroller.getWidth(),
+            annotationHeight));
+
+    alabels.setPreferredSize(new Dimension(idWidth, annotationHeight));
 
     annotationSpaceFillerHolder.setPreferredSize(new Dimension(
-            annotationSpaceFillerHolder.getWidth(), annotationHeight));
+            manuallyAdjusted ? idWidth
+                    : annotationSpaceFillerHolder.getWidth(),
+            annotationHeight));
     annotationScroller.validate();
     annotationScroller.addNotify();
+    ap.validate();
   }
 
   /**
@@ -597,9 +628,10 @@ public class AlignmentPanel extends GAlignmentPanel implements
     boolean wrap = av.getWrapAlignment();
     ViewportRanges ranges = av.getRanges();
     ranges.setStartSeq(0);
-    scalePanelHolder.setVisible(!wrap);
+    // scalePanelHolder.setVisible(!wrap);
     hscroll.setVisible(!wrap);
-    idwidthAdjuster.setVisible(!wrap);
+    // Allow idPanel width adjustment in wrap mode
+    idwidthAdjuster.setVisible(true);
 
     if (wrap)
     {
@@ -633,7 +665,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
       }
     }
 
-    idSpaceFillerPanel1.setVisible(!wrap);
+    // idSpaceFillerPanel1.setVisible(!wrap);
 
     repaint();
   }
@@ -854,10 +886,27 @@ public class AlignmentPanel extends GAlignmentPanel implements
   public void paintComponent(Graphics g)
   {
     invalidate(); // needed so that the id width adjuster works correctly
-
     Dimension d = getIdPanel().getIdCanvas().getPreferredSize();
-    idPanelHolder.setPreferredSize(d);
-    hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
+    int idWidth = d.width;
+
+    // check wrapped alignment as at least 1 residue width
+    if (av.getWrapAlignment())
+    {
+      SeqCanvas sc = this.getSeqPanel().seqCanvas;
+      if (sc != null && sc.getWidth() < sc.getMinimumWrappedCanvasWidth())
+      {
+        // need to make some adjustments
+        idWidth -= (sc.getMinimumWrappedCanvasWidth() - sc.getWidth());
+        av.setIdWidth(idWidth);
+        av.getAlignPanel().getIdPanel().getIdCanvas()
+                .setManuallyAdjusted(true);
+
+        validateAnnotationDimensions(false);
+      }
+    }
+
+    idPanelHolder.setPreferredSize(new Dimension(idWidth, d.height));
+    hscrollFillerPanel.setPreferredSize(new Dimension(idWidth, 12));
 
     validate(); // needed so that the id width adjuster works correctly
 
@@ -1172,10 +1221,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
     }
 
     int w = getIdPanel().getWidth();
+    w = this.calculateIdWidth(-1, true, true).width;
     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());
@@ -1196,6 +1247,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     final int borderBottomOffset = 5;
 
     AlignmentDimension aDimension = getAlignmentDimension();
+
     // todo use a lambda function in place of callback here?
     ImageWriterI writer = new ImageWriterI()
     {
@@ -1266,7 +1318,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 +1444,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
 
@@ -1407,8 +1461,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
   {
     int seqPanelWidth = getSeqPanel().seqCanvas.getWidth();
 
-    if (System.getProperty("java.awt.headless") != null
-            && System.getProperty("java.awt.headless").equals("true"))
+    if (Jalview.isHeadlessMode())
     {
       seqPanelWidth = alignFrame.getWidth() - getVisibleIdWidth()
               - vscroll.getPreferredSize().width
index d26ba89..20e1b1b 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import java.awt.Canvas;
 import java.awt.Color;
 import java.awt.Cursor;
 import java.awt.Dimension;
@@ -50,6 +51,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;
@@ -85,7 +88,7 @@ public class AnnotationLabels extends JPanel
   /**
    * height in pixels for allowing height adjuster to be active
    */
-  private static int HEIGHT_ADJUSTER_HEIGHT = 10;
+  public static int HEIGHT_ADJUSTER_HEIGHT = 10;
 
   private static final Font font = new Font("Arial", Font.PLAIN, 11);
 
@@ -113,6 +116,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;
@@ -131,6 +136,10 @@ public class AnnotationLabels extends JPanel
 
   private boolean resizePanel = false;
 
+  private int annotationIdWidth = -1;
+
+  public static final String RESIZE_MARGINS_MARK_PREF = "RESIZE_MARGINS_MARK";
+
   /**
    * Creates a new AnnotationLabels object
    * 
@@ -138,7 +147,6 @@ public class AnnotationLabels extends JPanel
    */
   public AnnotationLabels(AlignmentPanel ap)
   {
-
     this.ap = ap;
     av = ap.av;
     ToolTipManager.sharedInstance().registerComponent(this);
@@ -418,65 +426,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 +502,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()
         {
@@ -507,8 +527,10 @@ public class AnnotationLabels extends JPanel
       }
       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()
         {
 
@@ -524,8 +546,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
@@ -537,7 +561,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, true));
                 cm.randomlyReColourGroups();
                 cm.transferGroupColorsTo(alignmentAnnotation);
@@ -1141,7 +1169,6 @@ public class AnnotationLabels extends JPanel
     }
 
     drawComponent(g2, true, width);
-
   }
 
   /**
@@ -1171,32 +1198,146 @@ 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)
   {
-    if (av.getFont().getSize() < 10)
+    int width = givenWidth;
+    IdwidthAdjuster iwa = null;
+    if (ap != null)
     {
-      g.setFont(font);
+      iwa = ap.idwidthAdjuster;
+      if ((Cache.getDefault(ADJUST_ANNOTATION_LABELS_WIDTH_PREF, true)
+              || Jalview.isHeadlessMode()))
+      {
+        Graphics2D g2d = (Graphics2D) g;
+        Graphics dummy = g2d.create();
+        int newAnnotationIdWidth = drawLabels(dummy, clip, width, false,
+                null);
+        dummy.dispose();
+        Dimension d = ap.calculateDefaultAlignmentIdWidth();
+        int alignmentIdWidth = d.width;
+        if (iwa != null && !iwa.manuallyAdjusted())
+        {
+          // If no manual adjustment to ID column with has been made then adjust
+          // width match widest of alignment or annotation id widths
+          boolean allowShrink = Cache.getDefault("ALLOW_SHRINK_ID_WIDTH",
+                  false);
+          width = Math.max(alignmentIdWidth, newAnnotationIdWidth);
+          if (clip && width < givenWidth && !allowShrink)
+          {
+            width = givenWidth;
+          }
+        }
+        else if (newAnnotationIdWidth != annotationIdWidth
+                && newAnnotationIdWidth > givenWidth
+                && newAnnotationIdWidth > alignmentIdWidth)
+        {
+          // otherwise if the annotation id width has become larger than the
+          // current id width, increase
+          width = newAnnotationIdWidth;
+          annotationIdWidth = newAnnotationIdWidth;
+        }
+        // set the width if it's changed
+        if (width != ap.av.getIdWidth())
+        {
+          iwa.setWidth(width);
+        }
+      }
     }
     else
     {
-      g.setFont(av.getFont());
+      int newAnnotationIdWidth = drawLabels(g, clip, width, false, null);
+      width = Math.max(newAnnotationIdWidth, givenWidth);
+    }
+    drawLabels(g, clip, width, true, null);
+  }
+
+  /**
+   * Render the full set of annotation Labels for the alignment at the given
+   * cursor. If actuallyDraw is false or g is null then no actual drawing will
+   * occur, but the widest label width will be returned. If g is null then
+   * fmetrics must be supplied.
+   * 
+   * Returns the width of the annotation labels.
+   * 
+   * @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
+   * @param fmetrics
+   *          FontMetrics if Graphics object g is null
+   */
+  public int drawLabels(Graphics g0, boolean clip, int width,
+          boolean actuallyDraw, FontMetrics fmetrics)
+  {
+    if (clip)
+    {
+      clip = Cache.getDefault("MOVE_SEQUENCE_ID_WITH_VISIBLE_ANNOTATIONS",
+              true);
+    }
+    Graphics g = null;
+    // create a dummy Graphics object if not drawing and one is supplied
+    if (g0 != null)
+    {
+      if (!actuallyDraw)
+      {
+        Graphics2D g2d = (Graphics2D) g0;
+        g = g2d.create();
+      }
+      else
+      {
+        g = g0;
+      }
     }
+    int actualWidth = 0;
+    if (g != null)
+    {
+      if (av.getFont().getSize() < 10)
+      {
+        g.setFont(font);
+      }
+      else
+      {
+        g.setFont(av.getFont());
+      }
+    }
+
+    FontMetrics fm = fmetrics == null ? g.getFontMetrics(g.getFont())
+            : fmetrics;
+    if (actuallyDraw)
+    {
+      g.setColor(Color.white);
+      g.fillRect(0, 0, getWidth(), getHeight());
+
+      if (!Cache.getDefault(RESIZE_MARGINS_MARK_PREF, false)
+              && !av.getWrapAlignment())
+      {
+        g.setColor(Color.LIGHT_GRAY);
+        g.drawLine(0, HEIGHT_ADJUSTER_HEIGHT / 4, HEIGHT_ADJUSTER_WIDTH / 4,
+                HEIGHT_ADJUSTER_HEIGHT / 4);
+        g.drawLine(0, 3 * HEIGHT_ADJUSTER_HEIGHT / 4,
+                HEIGHT_ADJUSTER_WIDTH / 4, 3 * HEIGHT_ADJUSTER_HEIGHT / 4);
 
-    FontMetrics fm = g.getFontMetrics(g.getFont());
-    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();
-    int fontHeight = g.getFont().getSize();
+    int fontHeight = g != null ? g.getFont().getSize()
+            : fm.getFont().getSize();
     int y = 0;
     int x = 0;
     int graphExtras = 0;
     int offset = 0;
-    Font baseFont = g.getFont();
+    Font baseFont = g != null ? g.getFont() : fm.getFont();
     FontMetrics baseMetrics = fm;
     int ofontH = fontHeight;
     int sOffset = 0;
@@ -1260,8 +1401,10 @@ public class AnnotationLabels extends JPanel
             continue;
           }
         }
-        g.setColor(Color.black);
-
+        if (actuallyDraw && g != null)
+        {
+          g.setColor(Color.black);
+        }
         offset = -aa[i].height / 2;
 
         if (aa[i].hasText)
@@ -1306,7 +1449,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)
         {
@@ -1339,10 +1484,15 @@ public class AnnotationLabels extends JPanel
               s = ((float) fontHeight) / (float) ofontH;
               Font f = baseFont
                       .deriveFont(AffineTransform.getScaleInstance(s, s));
-              g.setFont(f);
-              fm = g.getFontMetrics();
-              graphExtras = (aa[i].height - (groupSize * (fontHeight + 8)))
-                      / 2;
+              Canvas c = new Canvas();
+              fm = c.getFontMetrics(f);
+              if (actuallyDraw && g != null)
+              {
+                g.setFont(f);
+                // fm = g.getFontMetrics();
+                graphExtras = (aa[i].height
+                        - (groupSize * (fontHeight + 8))) / 2;
+              }
             }
           }
           if (visible)
@@ -1351,58 +1501,81 @@ 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 != null)
                 {
+                  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;
               }
             }
           }
-          g.setFont(baseFont);
+          if (actuallyDraw && g != null)
+          {
+            g.setFont(baseFont);
+          }
           fm = baseMetrics;
           fontHeight = ofontH;
         }
         else
         {
-          if (vertBar)
+          if (actuallyDraw && g != null)
           {
-            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 != null)
+      {
+        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 != null)
+      {
+        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 c94dee0..eb0715a 100755 (executable)
@@ -22,6 +22,7 @@ package jalview.gui;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
@@ -382,6 +383,12 @@ public class IdCanvas extends JPanel implements ViewportListenerI
   void drawIdsWrapped(Graphics2D g, AlignViewport alignViewport,
           int startSeq, int pageHeight)
   {
+    drawIdsWrapped(g, alignViewport, startSeq, pageHeight, -1);
+  }
+
+  void drawIdsWrapped(Graphics2D g, AlignViewport alignViewport,
+          int startSeq, int pageHeight, int idWidth)
+  {
     int alignmentWidth = alignViewport.getAlignment().getWidth();
     final int alheight = alignViewport.getAlignment().getHeight();
 
@@ -428,8 +435,23 @@ public class IdCanvas extends JPanel implements ViewportListenerI
 
       if (labels != null && alignViewport.isShowAnnotation())
       {
+        int getWidth = getWidth();
+        int thisIdWidth = getWidth;
         g.translate(0, ypos + (alheight * charHeight));
-        labels.drawComponent(g, getWidth());
+        if (!manuallyAdjusted())
+        {
+          int getAnnotationsIdWidth = labels.drawLabels(g, false, -1, false,
+                  null);
+          thisIdWidth = idWidth < 0 ? getAnnotationsIdWidth : idWidth;
+          if (thisIdWidth > getWidth)
+          {
+            this.setPreferredSize(
+                    new Dimension(thisIdWidth, this.getHeight()));
+            this.repaint();
+            alignViewport.setIdWidth(thisIdWidth);
+          }
+        }
+        labels.drawComponent(g, false, thisIdWidth);
         g.translate(0, -ypos - (alheight * charHeight));
       }
 
@@ -585,4 +607,16 @@ public class IdCanvas extends JPanel implements ViewportListenerI
       repaint();
     }
   }
+
+  private boolean manuallyAdjusted = false;
+
+  public boolean manuallyAdjusted()
+  {
+    return manuallyAdjusted;
+  }
+
+  public void setManuallyAdjusted(boolean b)
+  {
+    manuallyAdjusted = b;
+  }
 }
index 4ba0699..4596e1f 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,9 @@ import java.awt.event.MouseMotionListener;
 
 import javax.swing.JPanel;
 
+import jalview.api.AlignViewportI;
+import jalview.bin.Cache;
+
 /**
  * DOCUMENT ME!
  * 
@@ -136,6 +137,18 @@ public class IdwidthAdjuster extends JPanel
       return;
     }
 
+    /*
+     * don't allow residue width to be < 1 in wrapped format
+     */
+    if (viewport.getWrapAlignment())
+    {
+      SeqCanvas sc = ap.getSeqPanel().seqCanvas;
+      if (sc != null && sc.getWrappedCanvasWidth(sc.getWidth() - dif) < 1)
+      {
+        return;
+      }
+    }
+
     oldX = evt.getX();
 
     /*
@@ -146,9 +159,29 @@ public class IdwidthAdjuster extends JPanel
       return;
     }
     viewport.setIdWidth(newWidth);
+    ap.validateAnnotationDimensions(false);
+    ap.paintAlignment(true, false);
+
+    ap.getIdPanel().getIdCanvas().setManuallyAdjusted(true);
+  }
+
+  public void setWidth(int newWidth)
+  {
+    if (newWidth < MIN_ID_WIDTH
+            || ap.getIdPanel().getIdCanvas().manuallyAdjusted())
+    {
+      return;
+    }
+    final AlignViewportI viewport = ap.getAlignViewport();
+    viewport.setIdWidth(newWidth);
     ap.paintAlignment(true, false);
   }
 
+  public boolean manuallyAdjusted()
+  {
+    return ap.getIdPanel().getIdCanvas().manuallyAdjusted();
+  }
+
   @Override
   public void mouseMoved(MouseEvent evt)
   {
@@ -167,8 +200,21 @@ public class IdwidthAdjuster extends JPanel
   @Override
   public void paintComponent(Graphics g)
   {
+    int width = getWidth();
+    int height = getHeight();
     g.setColor(Color.white);
-    g.fillRect(0, 0, getWidth(), getHeight());
+    g.fillRect(0, 0, width, height);
+
+    if (!Cache.getDefault(AnnotationLabels.RESIZE_MARGINS_MARK_PREF, false))
+    // && !ap.getAlignViewport().getWrapAlignment()) // now allowing adjustment
+    // in wrap mode
+    {
+      int spacer = Math.max(2, AnnotationLabels.HEIGHT_ADJUSTER_HEIGHT / 4);
+      g.setColor(Color.LIGHT_GRAY);
+      g.drawLine(width - 3 * spacer, 0, width - 3 * spacer, height / 2);
+      g.drawLine(width - spacer, 0, width - spacer, height / 2);
+    }
+
     setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
   }
 }
index 4f82557..0faedb0 100755 (executable)
@@ -550,6 +550,20 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
     return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
   }
 
+  public int getMinimumWrappedCanvasWidth()
+  {
+    int charWidth = av.getCharWidth();
+    FontMetrics fm = getFontMetrics(av.getFont());
+    int labelWidth = 0;
+    if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
+    {
+      labelWidth = getLabelWidth(fm);
+    }
+    labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0;
+    labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0;
+    return labelWidthEast + labelWidthWest + charWidth;
+  }
+
   /**
    * Returns a pixel width sufficient to show the largest sequence coordinate
    * (end position) in the alignment, calculated as the FontMetrics width of
index 6221f31..d00b1c2 100644 (file)
@@ -71,7 +71,6 @@ import jalview.gui.structurechooser.PDBStructureChooserQuerySource;
 import jalview.gui.structurechooser.StructureChooserQuerySource;
 import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource;
 import jalview.io.DataSourceType;
-import jalview.io.FileFormatException;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
 import jalview.jbgui.FilterOption;
@@ -85,7 +84,6 @@ import jalview.util.StringUtils;
 import jalview.ws.DBRefFetcher;
 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
-import jalview.ws.dbsources.EBIAlfaFold;
 import jalview.ws.seqfetcher.DbSourceProxy;
 import jalview.ws.sifts.SiftsSettings;
 
@@ -1801,7 +1799,9 @@ public class StructureChooser extends GStructureChooser
     sc.mainFrame.dispose();
 
     if (showRefAnnotations)
+    {
       showReferenceAnnotationsForSequence(ap.alignFrame, seq);
+    }
 
     return sv;
   }
index 6cef665..ad3fc6a 100644 (file)
 package jalview.gui;
 
 import java.util.ArrayList;
+import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -66,7 +68,27 @@ public class StructureViewer
 
   public enum ViewerType
   {
-    JMOL, CHIMERA, CHIMERAX, PYMOL
+    JMOL, CHIMERA, CHIMERAX, PYMOL;
+
+    public static ViewerType getFromString(String viewerString)
+    {
+      ViewerType viewerType = null;
+      if (!"none".equals(viewerString))
+      {
+        for (ViewerType v : EnumSet.allOf(ViewerType.class))
+        {
+          String name = v.name().toLowerCase(Locale.ROOT).replaceAll(" ",
+                  "");
+          if (viewerString.equals(name))
+          {
+            viewerType = v;
+            break;
+          }
+        }
+      }
+      return viewerType;
+    }
+
   };
 
   /**
index 6594e2d..2f0c75e 100755 (executable)
@@ -76,7 +76,7 @@ public class GAlignmentPanel extends JPanel
 
   protected JPanel scalePanelHolder = newJPanel();
 
-  protected JPanel idPanelHolder = newJPanel();
+  public JPanel idPanelHolder = newJPanel();
 
   protected JPanel idSpaceFillerPanel1 = newJPanel();
 
index 91f2f0c..715645a 100644 (file)
  */
 package jalview.viewmodel.styles;
 
-import jalview.api.ViewStyleI;
-
 import java.awt.Color;
 
+import jalview.api.ViewStyleI;
+
 /**
  * A container for holding alignment view properties. View properties are
  * data-independent, which means they can be safely copied between views
diff --git a/test/files/annotation_label_width/sample.a2m b/test/files/annotation_label_width/sample.a2m
new file mode 100644 (file)
index 0000000..0ca6801
--- /dev/null
@@ -0,0 +1,80 @@
+>101
+P.I...A..Q..I.....H.....I........L.......E........G.......R.......S....D.......E.......Q.....K....E.
+T..LI....RE...V.S.E...A...I......S.......R...S.......L........D....A.....P......L...................
+..........T......S.......V.......R......V...I....I.......T......E.....M........A....K.........G.....
+.H..........F..........G........I..........G........G......E........L....A...SK
+>UPI
+P.Hye.V..S..V.....T.....M........P.......T........G.......Wl......N....T.......V.......R.....K....Q.
+G..MI....DA...V.T.R...A...L......L.......E...A.......I........A....T.....P......F...................
+..........D......Essrfr..V.......R......C...L....I.......P......E.....I........P....D.........G.....
+.N..........W..........G........S..........G........Gya....L........P....L...S-
+>SRR
+P.H...V..A..V.....K.....L........Y.......P........G.......R.......T....E.......Q.......Q.....K....E.
+Q..LA....RA...I.A.D...D...V......M.......R...I.......L........G....S.....S......E...................
+..........A......S.......V.......S......V...S....I.......E......E.....V........D....A.........A.....
+.D..........W..........A........EkvyrplivegG........G......T........L....Y...KK
+>SRR
+P.H...V..I..V.....K.....L........W.......P........G.......R.......S....E.......P.......Q.....K....Q.
+K..LV....ES...V.T.K...A...V......T.......T...S.......L........G....Y.....S......D...................
+..........E......A.......V.......S......V...S....L.......Q......E.....V........P....S.........D.....
+.Q..........WtekvyrpdilG........T..........A........G......R........L....Y...KK
+>MGY
+P.I...V..R..I.....T.....M........F.......E........G.......R.......T....K.......E.......Q.....K....Q.
+E..LA....RV...I.T.E...A...V......V.......N...I.......A........K....T.....T......P...................
+..........D......A.......T.......E......VkdqI....L.......Q......K.....VllvrslrlP....PppasrrqvsG.....
+.A..........W..........S........A..........D........G......K........P....T...SE
+>446
+P.H...V..I..V.....K.....L........W.......P........G.......K.......S....E.......R.......E.....E....T.
+Q..LA....EA...I.T.K...S...V......T.......E...T.......L........N....F.....G......P...................
+..........E......S.......V.......S......V...A....F.......E......E.....I........P....A.........K.....
+.D..........W..........AskvyhadiI..........Gne......G......K........L....Y...KK
+>SRR
+P.L...V..R..I.....T.....Y........P.......R........Ga......L.......S....P.......E.......H.....K....T.
+R..IA....RA...L.T.E...I...V......L.......D...Vevdaa..T........D....A.....G......R...................
+..........M......V.......T.......V......V...H....F.......N......E.....A........A....P.........D.....
+.D..........W..........A........V..........G........G......Eirs.....T....A...AE
+>SRR
+P.L...V..R..I.....T.....Y........P.......R........Ga......L.......S....P.......D.......H.....K....R.
+R..IA....RE...L.T.E...I...V......L.......D...Vevdaa..T........D....A.....G......R...................
+..........M......V.......T.......V......I...H....F.......N......E.....A........A....A.........D.....
+.D..........W..........A........V..........G........G......Eirs.....T....A...AE
+>SRR
+P.R...Y..R..Vip...T.....V........P.......E........G.......Qy......S....N.......E.......S.....R....K.
+A..LV....KD...V.T.E...A...V......V.......R...A.......D........G....G.....K......Y...................
+..........E......Dvapr...V.......W......V...F....P.......T......E.....I........P....D.........G.....
+.Q..........W..........G........S..........R........Gvi....R........P....L...PE
+>SRR
+P.R...Y..R..Iip...T.....V........P.......E........G.......Qy......S....N.......E.......S.....R....K.
+A..LV....KD...V.T.E...A...V......V.......R...A.......D........G....G.....K......Y...................
+..........E......Dvapr...V.......W......V...F....P.......T......E.....I........P....D.........G.....
+.Q..........W..........G........S..........R........Gvi....R........P....L...PE
+>SRR
+P.V...I..E..M.....F.....V........P.......E........G.......La......D....A.......E.......A.....K....R.
+A..LH....DR...V.S.R...Q...V......L.......E...V.......E........G....AtydesP......L...................
+..........A......Qsi.....T.......W......M...L....I.......Q......E.....V........L....E.........C.....
+.G..........W..........S........V..........G........S......K........Avw..A...SE
+>SRR
+P.I...I..E..M.....H.....V........Q.......E........Gv......L.......D....E.......E.......T.....K....R.
+T..LH....ER...V.G.R...Q...V......L.......E...I.......E........G....Any...D......E...................
+..........N......D.......Varllt..F......M...F....I.......R......E.....H........P....E.........G.....
+.G..........F..........S........I..........G........G......E........M....It..SE
+>SRR
+P.Lyr.V..D..V.....T.....V........P.......E........Gsmihg..Q.......G....Pwal....S.......R.....R....R.
+A..IV....RE...V.T.E...I...V......L.......E...A.......E........G....S.....D......P...................
+..........Slgeaw.R.......V.......W......V...V....L.......R......E.....V........G....D.........A.....
+.F..........W..........G........A..........A........G......E........L....-...--
+>SRR
+P.Lyr.V..Q..I.....T.....V........P.......E........Gsmlhg..Q.......G....Pwai....E.......R.....R....R.
+E..LV....RA...V.S.K...A...V......L.......D...A.......E........G....Teyn..P......A...................
+..........Saw....R.......V.......W......V...L....M.......S......E.....I........S....E.........T.....
+.H..........W..........G........A..........A........G......E........-....-...--
+>SRR
+P.L...V..E..M.....S.....F........P.......V........Gv......L.......T....L.......D.......Q.....K....A.
+A..MI....KS...V.T.D...V...V......R.......G...A.......M........K....L.....P......P...................
+..........Dpar...K.......L.......F......V...E....I.......F......E.....T........P....G.........G.....
+.G..........F..........G........Vtakvvvvp..G........Gky....R........P....A...P-
+>SRR
+P.L...V..E..I.....D.....L........L.......E........A.......W.......A....P.......D.......Q.....I....D.
+A..IA....DA...I.H.E...A...M......V.......E...T.......L........G....V.....P......Eraagrdsatkqhfysrfaa
+llaeratvqsA......D.......L.......T......A...V....L.......V......E.....N........S....R.........D.....
+.D..........W..........S........F..........Gm.......G......Q........-....-...--
diff --git a/test/files/annotation_label_width/test_fab41_nostructureviewers.txt b/test/files/annotation_label_width/test_fab41_nostructureviewers.txt
new file mode 100644 (file)
index 0000000..b40c4e2
--- /dev/null
@@ -0,0 +1,15 @@
+--nonews
+--nosplash
+--open=./test/files/annotation_label_width/sample.a2m
+--colour=gecos:flower
+--gui
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb
+--paematrix=./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3_scores.json
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_2_model_4.pdb
+--paematrix=./examples/test_fab41.result/test_fab41_unrelaxed_rank_2_model_4_scores.json
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_3_model_2.pdb
+--paematrix=./examples/test_fab41.result/test_fab41_unrelaxed_rank_3_model_2_scores.json
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_4_model_5.pdb
+--paematrix=./examples/test_fab41.result/test_fab41_unrelaxed_rank_4_model_5_scores.json
+--structure=[structureviewer=none]./examples/test_fab41.result/test_fab41_unrelaxed_rank_5_model_1.pdb
+--paematrix=./examples/test_fab41.result/test_fab41_unrelaxed_rank_5_model_1_scores.json
diff --git a/test/jalview/gui/AnnotationLabelsTest2.java b/test/jalview/gui/AnnotationLabelsTest2.java
new file mode 100644 (file)
index 0000000..ad97e8b
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import jalview.bin.Cache;
+import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.structure.StructureImportSettings.TFType;
+
+public class AnnotationLabelsTest2
+{
+  @BeforeClass(alwaysRun = true)
+  public static void setUpBeforeClass() throws Exception
+  {
+    if (Desktop.instance != null)
+      Desktop.instance.closeAll_actionPerformed(null);
+
+    setUpJvOptionPane();
+    /*
+     * use read-only test properties file
+     */
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+    Jalview.main(new String[] { "--nonews", "--nosplash", });
+  }
+
+  @AfterMethod(alwaysRun = true)
+  public void tearDown()
+  {
+    if (Desktop.instance != null)
+      Desktop.instance.closeAll_actionPerformed(null);
+  }
+
+  /**
+   * configure (read-only) properties for test to ensure Consensus is computed
+   * for colour Above PID testing
+   */
+  @BeforeMethod(alwaysRun = true)
+  public void setUp()
+  {
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+    Cache.applicationProperties.setProperty("SHOW_IDENTITY",
+            Boolean.TRUE.toString());
+
+  }
+
+  public static void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
+  @Test(
+    groups =
+    { "Functional", "testTask1" },
+    dataProvider = "openFilesWithIdWidthChanges")
+  public void testIdWidthChanges(String alignmentFilename, boolean wrap,
+          int idWidth1min, int idWidth1max, int manualWidth,
+          String structureFilename, String paeFilename,
+          boolean secondaryStructureView, TFType temperatureFactorType,
+          ViewerType viewerType, int idWidth2min, int idWidth2max)
+  {
+    AlignFrame af = new FileLoader()
+            .LoadFileWaitTillLoaded(alignmentFilename, DataSourceType.FILE);
+    try
+    {
+      Thread.sleep(200); // to allow alignment annotations to open
+    } catch (InterruptedException e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    AlignViewport av = af.getCurrentView();
+
+    int idWidth = 0;
+
+    idWidth = av.getIdWidth();
+    assertTrue(idWidth > idWidth1min,
+            "idWidth (" + idWidth + ") is not greater than " + idWidth1min);
+    assertTrue(idWidth < idWidth1max,
+            "idWidth (" + idWidth + ") is not narrower than" + idWidth1max);
+
+    // set wrap
+    if (wrap)
+    {
+      af.setWrapFormat(true, false);
+      idWidth = av.getIdWidth();
+      assertTrue(idWidth > idWidth1min, "After wrap idWidth (" + idWidth
+              + ") is not greater than " + idWidth1min);
+      assertTrue(idWidth < idWidth1max, "After wrap idWidth (" + idWidth
+              + ") is not narrower than" + idWidth1max);
+    }
+
+    AlignmentI al = av.getAlignment();
+    SequenceI s = al.getSequenceAt(0);
+    AlignmentPanel ap = af.alignPanel;
+
+    File structureFile = new File(structureFilename);
+    File paeFile = new File(paeFilename);
+
+    StructureViewer sv = StructureChooser.openStructureFileForSequence(null,
+            null, ap, s, false, structureFile.getAbsolutePath(),
+            temperatureFactorType, paeFile.getAbsolutePath(), true,
+            secondaryStructureView, false, viewerType);
+    // give time for annotations to open
+    try
+    {
+      Thread.sleep(200); // to allow alignment annotations to open
+    } catch (InterruptedException e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+
+    // idWidth = ap.getIdPanel().getWidth();
+    idWidth = av.getIdWidth();
+    assertTrue(idWidth > idWidth2min,
+            "idWidth (" + idWidth + ") is not greater than " + idWidth2min);
+    assertTrue(idWidth < idWidth2max,
+            "idWidth (" + idWidth + ") is not narrower than" + idWidth2max);
+  }
+
+  @Test(
+    groups =
+    { "Functional", "testTask1" },
+    dataProvider = "openFilesWithIdWidthChanges")
+  public void testIdWidthNoChanges(String alignmentFilename, boolean wrap,
+          int idWidth1min, int idWidth1max, int manualWidth,
+          String structureFilename, String paeFilename,
+          boolean secondaryStructureView, TFType temperatureFactorType,
+          ViewerType viewerType, int idWidth2min, int idWidth2max)
+  {
+    AlignFrame af = new FileLoader()
+            .LoadFileWaitTillLoaded(alignmentFilename, DataSourceType.FILE);
+    try
+    {
+      Thread.sleep(200); // to allow alignment annotations to open
+    } catch (InterruptedException e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    AlignViewport av = af.getCurrentView();
+
+    int idWidth = 0;
+
+    idWidth = av.getIdWidth();
+    assertTrue(idWidth > idWidth1min,
+            "idWidth (" + idWidth + ") is not greater than " + idWidth1min);
+    assertTrue(idWidth < idWidth1max,
+            "idWidth (" + idWidth + ") is not narrower than" + idWidth1max);
+
+    AlignmentI al = av.getAlignment();
+    SequenceI s = al.getSequenceAt(0);
+    AlignmentPanel ap = af.alignPanel;
+
+    // set width manually
+    av.setIdWidth(manualWidth);
+    ap.validateAnnotationDimensions(false);
+    ap.paintAlignment(true, false);
+    ap.getIdPanel().getIdCanvas().setManuallyAdjusted(true);
+
+    idWidth = av.getIdWidth();
+    assertEquals(idWidth, manualWidth,
+            "idWidth is not set to the manually set width " + manualWidth);
+
+    File structureFile = new File(structureFilename);
+    File paeFile = new File(paeFilename);
+
+    StructureViewer sv = StructureChooser.openStructureFileForSequence(null,
+            null, ap, s, false, structureFile.getAbsolutePath(),
+            temperatureFactorType, paeFile.getAbsolutePath(), false,
+            secondaryStructureView, false, viewerType);
+
+    idWidth = ap.getIdPanel().getWidth();// av.getIdWidth();
+    idWidth = av.getIdWidth();
+    assertEquals(idWidth, manualWidth,
+            "idWidth is not set to the manually set width " + manualWidth
+                    + " after adding structure annotations");
+    assertFalse(idWidth > idWidth2min,
+            "idWidth (" + idWidth + ") is greater than " + idWidth2min);
+  }
+
+  @DataProvider(name = "openFilesWithIdWidthChanges")
+  public Object[][] openFilesWithIdWidthChanges()
+  {
+    /*
+      String alignmentFilename,
+      boolean wrap,
+      int idWidth1min,
+      int idWidth1max,
+      int manualWidth, // ignored by testIdWidthChanges()
+      String structureFilename,
+      String paeFilename,
+      boolean secondaryStructureView,
+      TFType temperatureFactorType,
+      ViewerType viewerType,
+      int idWidth2min,
+      int idWidth2max,
+     */
+    return new Object[][] {
+        //
+        /*
+         */
+        { "./test/files/annotation_label_width/sample.a2m", false, 50, 70,
+            100,
+            "./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb",
+            "./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3_scores.json",
+            true, TFType.PLDDT, null, 115, 130 },
+        { "./test/files/annotation_label_width/sample.a2m", true, 50, 70,
+            100,
+            "./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3.pdb",
+            "./examples/test_fab41.result/test_fab41_unrelaxed_rank_1_model_3_scores.json",
+            true, TFType.PLDDT, null, 115, 130 },
+        /*
+         */
+    };
+  }
+
+}