Merge branch 'develop' into features/JAL-4134_use_annotation_row_for_colours_and_groups
[jalview.git] / src / jalview / gui / StructureChooser.java
index 5cd339b..6fce984 100644 (file)
@@ -28,10 +28,11 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.concurrent.Callable;
+import java.util.Map;
 import java.util.concurrent.Executors;
 
 import javax.swing.JCheckBox;
@@ -45,11 +46,16 @@ import javax.swing.table.AbstractTableModel;
 
 import com.stevesoft.pat.Regex;
 
+import jalview.analysis.AlignmentUtils;
+import jalview.api.AlignmentViewPanel;
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
 import jalview.bin.Console;
 import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JmolParser;
 import jalview.fts.api.FTSData;
@@ -60,6 +66,7 @@ import jalview.fts.core.FTSRestRequest;
 import jalview.fts.core.FTSRestResponse;
 import jalview.fts.service.pdb.PDBFTSRestClient;
 import jalview.fts.service.threedbeacons.TDB_FTSData;
+import jalview.gui.StructureViewer.ViewerType;
 import jalview.gui.structurechooser.PDBStructureChooserQuerySource;
 import jalview.gui.structurechooser.StructureChooserQuerySource;
 import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource;
@@ -342,7 +349,7 @@ public class StructureChooser extends GStructureChooser
     };
 
     // fetch db refs if OK pressed
-    final Callable discoverCanonicalDBrefs = () -> {
+    final Runnable discoverCanonicalDBrefs = () -> {
       btn_queryTDB.setEnabled(false);
       populateSeqsWithoutSourceDBRef();
 
@@ -364,14 +371,12 @@ public class StructureChooser extends GStructureChooser
         // call finished action directly
         afterDbRefFetch.finished();
       }
-      return null;
     };
-    final Callable revertview = () -> {
+    final Runnable revertview = () -> {
       if (lastSelected != null)
       {
         cmb_filterOption.setSelectedItem(lastSelected);
       }
-      return null;
     };
     int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
             THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
@@ -736,16 +741,18 @@ public class StructureChooser extends GStructureChooser
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
       String fileName = chooser.getSelectedFile().getPath();
-      try {
+      try
+      {
         PAEContactMatrix.validateContactMatrixFile(fileName);
       } catch (Exception thr)
       {
         JvOptionPane.showInternalMessageDialog(this, MessageManager
                 .formatMessage("label.couldnt_load_file", new Object[]
-                { fileName})+"<br>"+thr.getLocalizedMessage(),
+                { fileName }) + "<br>" + thr.getLocalizedMessage(),
                 MessageManager.getString("label.error_loading_file"),
                 JvOptionPane.WARNING_MESSAGE);
-        Console.error("Couldn't import "+fileName+" as a PAE matrix",thr);
+        Console.error("Couldn't import " + fileName + " as a PAE matrix",
+                thr);
         return;
       }
       localPdbPaeMatrixFileName = fileName;
@@ -1205,8 +1212,9 @@ public class StructureChooser extends GStructureChooser
     btn_newView.setEnabled(false);
     btn_cancel.setEnabled(false);
     actionsPanel.setEnabled(false);
-    
-    final String progress=MessageManager.getString("label.working_ellipsis");
+
+    final String progress = MessageManager
+            .getString("label.working_ellipsis");
     setProgressBar(progress, progress.hashCode());
     Runnable viewStruc = new Runnable()
     {
@@ -1304,7 +1312,8 @@ public class StructureChooser extends GStructureChooser
           String pdbFilename = selectedPdbFileName;
 
           StructureChooser.openStructureFileForSequence(ssm, sc, ap,
-                  selectedSequence, true, pdbFilename, tft, paeFilename);
+                  selectedSequence, true, pdbFilename, tft, paeFilename,
+                  true);
         }
         SwingUtilities.invokeLater(new Runnable()
         {
@@ -1364,6 +1373,15 @@ public class StructureChooser extends GStructureChooser
           StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
           final AlignmentPanel alignPanel, SequenceI[] sequences)
   {
+    return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
+            sequences, null);
+  }
+
+  private StructureViewer launchStructureViewer(
+          StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
+          final AlignmentPanel alignPanel, SequenceI[] sequences,
+          ViewerType viewerType)
+  {
     long progressId = sequences.hashCode();
     setProgressBar(MessageManager
             .getString("status.launching_3d_structure_viewer"), progressId);
@@ -1428,7 +1446,8 @@ public class StructureChooser extends GStructureChooser
               MessageManager.getString(
                       "status.fetching_3d_structures_for_selected_entries"),
               progressId);
-      theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel);
+      theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
+              viewerType);
     }
     else
     {
@@ -1436,7 +1455,8 @@ public class StructureChooser extends GStructureChooser
               "status.fetching_3d_structures_for",
               pdbEntriesToView[0].getId()), progressId);
       // Can we pass a pre-computeMappinged pdbFile?
-      theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel);
+      theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
+              viewerType);
     }
     setProgressBar(null, progressId);
     // remember the last viewer we used...
@@ -1677,20 +1697,21 @@ public class StructureChooser extends GStructureChooser
   @Override
   public void setProgressBar(String message, long id)
   {
-    if (!Platform.isHeadless())
+    if (!Platform.isHeadless() && progressBar != null)
       progressBar.setProgressBar(message, id);
   }
 
   @Override
   public void registerHandler(long id, IProgressIndicatorHandler handler)
   {
-    progressBar.registerHandler(id, handler);
+    if (progressBar != null)
+      progressBar.registerHandler(id, handler);
   }
 
   @Override
   public boolean operationInProgress()
   {
-    return progressBar.operationInProgress();
+    return progressBar == null ? false : progressBar.operationInProgress();
   }
 
   public JalviewStructureDisplayI getOpenedStructureViewer()
@@ -1737,26 +1758,73 @@ public class StructureChooser extends GStructureChooser
   public static void openStructureFileForSequence(
           StructureSelectionManager ssm, StructureChooser sc,
           AlignmentPanel ap, SequenceI seq, boolean prompt,
-          String sFilename, TFType tft, String paeFilename)
+          String sFilename, TFType tft, String paeFilename,
+          boolean doXferSettings)
+  {
+    openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
+            paeFilename, false, true, doXferSettings, null);
+  }
+
+  public static StructureViewer openStructureFileForSequence(
+          StructureSelectionManager ssm, StructureChooser sc,
+          AlignmentPanel ap, SequenceI seq, boolean prompt,
+          String sFilename, TFType tft, String paeFilename,
+          boolean forceHeadless, boolean showRefAnnotations,
+          boolean doXferSettings, ViewerType viewerType)
   {
-    boolean headless = false;
+    StructureViewer sv = null;
+    boolean headless = forceHeadless;
     if (sc == null)
     {
-      headless = true;
+      // headless = true;
+      prompt = false;
       sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false);
     }
     if (ssm == null)
+    {
       ssm = ap.getStructureSelectionManager();
+    }
 
     PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
             sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
-            tft, paeFilename);
+            tft, paeFilename, doXferSettings);
+
+    // if headless, "false" in the sc constructor above will avoid GUI behaviour
+    // in sc.launchStructureViewer()
+    if (!headless && !(viewerType == null))
+    {
+      sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
+              new SequenceI[]
+              { seq }, viewerType);
+    }
 
-    StructureViewer sViewer = sc.launchStructureViewer(ssm,
-            new PDBEntry[]
-            { fileEntry }, ap, new SequenceI[] { seq });
+    sc.mainFrame.dispose();
+
+    if (showRefAnnotations)
+      showReferenceAnnotationsForSequence(ap.alignFrame, seq);
+
+    return sv;
+  }
+
+  public static void showReferenceAnnotationsForSequence(AlignFrame af,
+          SequenceI sequence)
+  {
+    AlignViewport av = af.getCurrentView();
+    AlignmentI al = av.getAlignment();
+
+    List<SequenceI> forSequences = new ArrayList<>();
+    forSequences.add(sequence);
+    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
+    AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
+            candidates, al);
+    final SequenceGroup selectionGroup = av.getSelectionGroup();
+    AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
+    for (AlignmentViewPanel ap : af.getAlignPanels())
+    {
+      // required to readjust the height and position of the PAE
+      // annotation
+      ap.adjustAnnotationHeight();
+    }
 
-    if (headless)
-      sc.mainFrame.dispose();
   }
 }