JAL-244 Fixed idWidth labels in headless mode for non-wrap alignments
authorBen Soares <b.soares@dundee.ac.uk>
Fri, 21 Jul 2023 16:23:24 +0000 (17:23 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Fri, 21 Jul 2023 16:23:24 +0000 (17:23 +0100)
examples/argfiles/test_fab41.txt
examples/argfiles/test_fab41_nostructureviewers.txt
src/jalview/bin/Commands.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationLabels.java
src/jalview/jbgui/GAlignmentPanel.java

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
index eb8fdc0..ab52cdf 100644 (file)
@@ -11,4 +11,4 @@
 --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=output1.html
+--image=[textrenderer=text]output1.html
index d7d1ea3..838b381 100644 (file)
@@ -103,16 +103,20 @@ public class Commands
         theseArgsWereParsed &= processLinked(id);
         processGroovyScript(id);
         boolean processLinkedOkay = theseArgsWereParsed;
-        
+
         // wait around until alignFrame isn't busy
-        AlignFrame af=afMap.get(id);
-        while (af!=null && af.getViewport().isCalcInProgress())
+        AlignFrame af = afMap.get(id);
+        while (af != null && af.getViewport().isCalcInProgress())
         {
-          try {
+          try
+          {
             Thread.sleep(25);
-          } catch (Exception q) {};
+          } catch (Exception q)
+          {
+          }
+          ;
         }
-        
+
         theseArgsWereParsed &= processImages(id);
         if (processLinkedOkay)
           theseArgsWereParsed &= processOutput(id);
@@ -263,12 +267,16 @@ public class Commands
           if ("" != colour)
           {
             ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
-                    af.getViewport(), af.getViewport().getAlignment(), colour);
-            
-            if (cs==null && !"None".equals(colour))
+                    af.getViewport(), af.getViewport().getAlignment(),
+                    colour);
+
+            if (cs == null && !"None".equals(colour))
+            {
+              Console.warn(
+                      "Couldn't parse '" + colour + "' as a colourscheme.");
+            }
+            else
             {
-              Console.warn("Couldn't parse '"+colour+"' as a colourscheme.");
-            } else {
               af.changeColour(cs);
             }
             Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour);
@@ -569,15 +577,15 @@ public class Commands
                           structureFilepath, tft, paeFilepath, false,
                           ssFromStructure, false, viewerType);
 
-          if (sv==null)
+          if (sv == null)
           {
             Console.error("Failed to import and open structure view.");
             continue;
           }
           try
           {
-            long tries=1000;
-            while (sv.isBusy() && tries>0)
+            long tries = 1000;
+            while (sv.isBusy() && tries > 0)
             {
               Thread.sleep(25);
               if (sv.isBusy())
@@ -587,15 +595,18 @@ public class Commands
                         "Waiting for viewer for " + structureFilepath);
               }
             }
-            if (tries==0 && sv.isBusy())
+            if (tries == 0 && sv.isBusy())
             {
-              Console.warn("Gave up waiting for structure viewer to load. Something may have gone wrong.");
+              Console.warn(
+                      "Gave up waiting for structure viewer to load. Something may have gone wrong.");
             }
           } catch (Exception x)
           {
-            Console.warn("Exception whilst waiting for structure viewer "+structureFilepath,x);
+            Console.warn("Exception whilst waiting for structure viewer "
+                    + structureFilepath, x);
           }
-          Console.debug("Successfully opened viewer for "+structureFilepath);
+          Console.debug(
+                  "Successfully opened viewer for " + structureFilepath);
           String structureImageFilename = ArgParser.getValueFromSubValOrArg(
                   avm, av, Arg.STRUCTUREIMAGE, subVals);
           if (sv != null && structureImageFilename != null)
@@ -652,16 +663,18 @@ public class Commands
               if (sview instanceof AppJmol)
               {
                 AppJmol jmol = (AppJmol) sview;
-                try { 
-                  Console.debug("Rendering image to "+structureImageFile);
+                try
+                {
+                  Console.debug("Rendering image to " + structureImageFile);
                   jmol.makePDBImage(structureImageFile, imageType, renderer,
-                        userBis);
-                  Console.debug("Finished Rendering image to "+structureImageFile);
+                          userBis);
+                  Console.debug("Finished Rendering image to "
+                          + structureImageFile);
 
-                }
-                catch (ImageOutputException ioexc)
+                } catch (ImageOutputException ioexc)
                 {
-                  Console.warn("Unexpected error whilst exporting image to "+structureImageFile,ioexc);
+                  Console.warn("Unexpected error whilst exporting image to "
+                          + structureImageFile, ioexc);
                 }
 
               }
@@ -771,57 +784,60 @@ public class Commands
         Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false");
 
         Console.info("Writing " + file);
-        try {
-        switch (type)
+        try
         {
-
-        case "svg":
-          Console.debug("Outputting type '" + type + "' to " + fileName);
-          af.createSVG(file, renderer);
-          break;
-
-        case "png":
-          Console.debug("Outputting type '" + type + "' to " + fileName);
-          af.createPNG(file, null, userBis);
-          break;
-
-        case "html":
-          Console.debug("Outputting type '" + type + "' to " + fileName);
-          HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
-          htmlSVG.exportHTML(fileName, renderer);
-          break;
-
-        case "biojs":
-          Console.debug("Creating BioJS MSA Viwer HTML file: " + fileName);
-          try
-          {
-            BioJsHTMLOutput.refreshVersionInfo(
-                    BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
-          } catch (URISyntaxException e)
+          switch (type)
           {
-            e.printStackTrace();
+
+          case "svg":
+            Console.debug("Outputting type '" + type + "' to " + fileName);
+            af.createSVG(file, renderer);
+            break;
+
+          case "png":
+            Console.debug("Outputting type '" + type + "' to " + fileName);
+            af.createPNG(file, null, userBis);
+            break;
+
+          case "html":
+            Console.debug("Outputting type '" + type + "' to " + fileName);
+            HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
+            htmlSVG.exportHTML(fileName, renderer);
+            break;
+
+          case "biojs":
+            Console.debug(
+                    "Creating BioJS MSA Viwer HTML file: " + fileName);
+            try
+            {
+              BioJsHTMLOutput.refreshVersionInfo(
+                      BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
+            } catch (URISyntaxException e)
+            {
+              e.printStackTrace();
+            }
+            BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
+            bjs.exportHTML(fileName);
+            break;
+
+          case "eps":
+            Console.debug("Creating EPS file: " + fileName);
+            af.createEPS(file, name);
+            break;
+
+          case "imagemap":
+            Console.debug("Creating ImageMap file: " + fileName);
+            af.createImageMap(file, name);
+            break;
+
+          default:
+            Console.warn(Arg.IMAGE.argString() + " type '" + type
+                    + "' not known. Ignoring");
+            break;
           }
-          BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
-          bjs.exportHTML(fileName);
-          break;
-
-        case "eps":
-          Console.debug("Creating EPS file: " + fileName);
-          af.createEPS(file, name);
-          break;
-
-        case "imagemap":
-          Console.debug("Creating ImageMap file: " + fileName);
-          af.createImageMap(file, name);
-          break;
-
-        default:
-          Console.warn(Arg.IMAGE.argString() + " type '" + type
-                  + "' not known. Ignoring");
-          break;
-        }
-        } catch (Exception ioex) {
-          Console.warn("Unexpected error during export",ioex);
+        } catch (Exception ioex)
+        {
+          Console.warn("Unexpected error during export", ioex);
         }
       }
     }
index 2396329..8a43a4a 100644 (file)
@@ -338,18 +338,27 @@ public class AlignmentPanel extends GAlignmentPanel implements
     // Also check annotation label widths
     if (includeAnnotations && al.getAlignmentAnnotation() != null)
     {
-      fm = c.getFontMetrics(getAlabels().getFont());
-
-      for (i = 0; i < al.getAlignmentAnnotation().length; i++)
+      if (Jalview.isHeadlessMode())
+      {
+        AnnotationLabels aal = this.getAlabels();
+        int stringWidth = aal.drawLabels(null, false, idWidth, false, fm);
+        idWidth = Math.max(idWidth, stringWidth);
+      }
+      else
       {
-        AlignmentAnnotation aa = al.getAlignmentAnnotation()[i];
-        if (visibleOnly && !aa.visible)
+        fm = c.getFontMetrics(getAlabels().getFont());
+
+        for (i = 0; i < al.getAlignmentAnnotation().length; i++)
         {
-          continue;
+          AlignmentAnnotation aa = al.getAlignmentAnnotation()[i];
+          if (visibleOnly && !aa.visible)
+          {
+            continue;
+          }
+          String label = aa.label;
+          int stringWidth = fm.stringWidth(label);
+          idWidth = Math.max(idWidth, stringWidth);
         }
-        String label = aa.label;
-        int stringWidth = fm.stringWidth(label);
-        idWidth = Math.max(idWidth, stringWidth);
       }
     }
 
@@ -581,9 +590,10 @@ 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(
@@ -596,6 +606,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
             annotationSpaceFillerHolder.getWidth(), annotationHeight));
     annotationScroller.validate();
     annotationScroller.addNotify();
+    ap.validate();
   }
 
   /**
@@ -1186,6 +1197,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     }
 
     int w = getIdPanel().getWidth();
+    w = this.calculateIdWidth(-1, true, true).width;
     return (w > 0 ? w : calculateIdWidth().width);
   }
 
@@ -1211,6 +1223,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()
     {
index ffc565c..26276ae 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;
@@ -135,6 +136,8 @@ public class AnnotationLabels extends JPanel
 
   private boolean resizePanel = false;
 
+  private int annotationIdWidth = -1;
+
   /**
    * Creates a new AnnotationLabels object
    * 
@@ -1198,36 +1201,41 @@ public class AnnotationLabels extends JPanel
     {
       Graphics2D g2d = (Graphics2D) g;
       Graphics dummy = g2d.create();
-      int annotationIdWidth = drawLabels(dummy, clip, width, false);
+      int newAnnotationIdWidth = drawLabels(dummy, clip, width, false,
+              null);
       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);
+        width = Math.max(alignmentIdWidth, newAnnotationIdWidth);
       }
-      else if (annotationIdWidth > givenWidth
-              && annotationIdWidth > alignmentIdWidth)
+      else if (newAnnotationIdWidth != annotationIdWidth
+              && newAnnotationIdWidth > givenWidth
+              && newAnnotationIdWidth > alignmentIdWidth)
       {
         // otherwise if the annotation id width has become larger than the
         // current id width, increase
-        width = annotationIdWidth;
+        width = newAnnotationIdWidth;
+        annotationIdWidth = newAnnotationIdWidth;
       }
       // set the width if it's changed
       if (width != ap.av.getIdWidth())
       {
         iwa.setWidth(width);
-        ap.validateAnnotationDimensions(false);
       }
     }
-    drawLabels(g, clip, width, true);
+    drawLabels(g, clip, width, true, null);
   }
 
   /**
    * 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.
+   * 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)
@@ -1236,21 +1244,27 @@ public class AnnotationLabels extends JPanel
    *          rendered
    * @param width
    *          Width for scaling labels
+   * @param fmetrics
+   *          FontMetrics if Graphics object g is null
    */
   public int drawLabels(Graphics g, boolean clip, int width,
-          boolean actuallyDraw)
+          boolean actuallyDraw, FontMetrics fmetrics)
   {
     int actualWidth = 0;
-    if (av.getFont().getSize() < 10)
+    if (actuallyDraw && g != null)
     {
-      g.setFont(font);
-    }
-    else
-    {
-      g.setFont(av.getFont());
+      if (av.getFont().getSize() < 10)
+      {
+        g.setFont(font);
+      }
+      else
+      {
+        g.setFont(av.getFont());
+      }
     }
 
-    FontMetrics fm = g.getFontMetrics(g.getFont());
+    FontMetrics fm = fmetrics == null ? g.getFontMetrics(g.getFont())
+            : fmetrics;
     if (actuallyDraw)
     {
       g.setColor(Color.white);
@@ -1265,12 +1279,13 @@ public class AnnotationLabels extends JPanel
     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;
@@ -1334,7 +1349,7 @@ public class AnnotationLabels extends JPanel
             continue;
           }
         }
-        if (actuallyDraw)
+        if (actuallyDraw && g != null)
         {
           g.setColor(Color.black);
         }
@@ -1417,10 +1432,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)
@@ -1431,7 +1451,7 @@ public class AnnotationLabels extends JPanel
               {
                 labelWidth = fm.stringWidth(aa[gg].label) + 3;
                 x = width - labelWidth;
-                if (actuallyDraw)
+                if (actuallyDraw && g != null)
                 {
                   g.drawString(aa[gg].label, x, y - graphExtras);
 
@@ -1450,13 +1470,16 @@ public class AnnotationLabels extends JPanel
               }
             }
           }
-          g.setFont(baseFont);
+          if (actuallyDraw && g != null)
+          {
+            g.setFont(baseFont);
+          }
           fm = baseMetrics;
           fontHeight = ofontH;
         }
         else
         {
-          if (actuallyDraw)
+          if (actuallyDraw && g != null)
           {
             if (vertBar)
             {
@@ -1479,7 +1502,7 @@ public class AnnotationLabels extends JPanel
 
     if (!resizePanel && dragEvent != null && aa != null)
     {
-      if (actuallyDraw)
+      if (actuallyDraw && g != null)
       {
         g.setColor(Color.lightGray);
         g.drawString(
@@ -1492,7 +1515,7 @@ public class AnnotationLabels extends JPanel
 
     if (!av.getWrapAlignment() && ((aa == null) || (aa.length < 1)))
     {
-      if (actuallyDraw)
+      if (actuallyDraw && g != null)
       {
         g.drawString(MessageManager.getString("label.right_click"), 2, 8);
         g.drawString(MessageManager.getString("label.to_add_annotation"), 2,
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();