JAL-4034 Fix #2 show an icon and a button to press to initiate search
[jalview.git] / src / jalview / gui / StructureChooser.java
index 849c278..5ea68fb 100644 (file)
 
 package jalview.gui;
 
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.concurrent.Executors;
 
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
 import javax.swing.JTable;
 import javax.swing.SwingUtilities;
 import javax.swing.table.AbstractTableModel;
@@ -48,6 +54,7 @@ import jalview.fts.core.FTSDataColumnPreferences;
 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.structurechooser.PDBStructureChooserQuerySource;
 import jalview.gui.structurechooser.StructureChooserQuerySource;
 import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource;
@@ -74,11 +81,6 @@ public class StructureChooser extends GStructureChooser
 {
   private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
 
-  /**
-   * transient combo box choice for initiating 3db fetch
-   */
-  private static final String VIEWS_QUERYING_TDB = "QUERY_3DB";
-
   private SequenceI selectedSequence;
 
   private SequenceI[] selectedSequences;
@@ -166,7 +168,8 @@ public class StructureChooser extends GStructureChooser
       canQueryTDB = true;
       if (needCanonical)
       {
-        notQueriedTDBYet = false;
+        // triggers display of the 'Query TDB' button
+        notQueriedTDBYet = true;
       }
     }
   };
@@ -182,6 +185,15 @@ public class StructureChooser extends GStructureChooser
     }
 
     chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
+    btn_queryTDB.addActionListener(new ActionListener()
+    {
+
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        promptForTDBFetch(false);
+      }
+    });
 
     Executors.defaultThreadFactory().newThread(new Runnable()
     {
@@ -230,7 +242,13 @@ public class StructureChooser extends GStructureChooser
     updateCurrentView();
   }
 
-  private void promptForTDBFetch()
+  /**
+   * raises dialog for Uniprot fetch followed by 3D beacons search
+   * 
+   * @param ignoreGui
+   *          - when true, don't ask, just fetch
+   */
+  public void promptForTDBFetch(boolean ignoreGui)
   {
     final long progressId = System.currentTimeMillis();
 
@@ -240,19 +258,46 @@ public class StructureChooser extends GStructureChooser
       @Override
       public void run()
       {
+        mainFrame.setEnabled(false);
+        cmb_filterOption.setEnabled(false);
+        progressBar.setProgressBar(
+                MessageManager.getString("status.searching_3d_beacons"),
+                progressId);
+        btn_queryTDB.setEnabled(false);
         // TODO: warn if no accessions discovered
         populateSeqsWithoutSourceDBRef();
         // redo initial discovery - this time with 3d beacons
         // Executors.
-        previousWantedFields=null;
-        
+        previousWantedFields = null;
+        lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
+        cmb_filterOption.setSelectedItem(null);
+        cachedPDBExists = false; // reset to initial
         initialStructureDiscovery();
+        if (!isStructuresDiscovered())
+        {
+          progressBar.setProgressBar(MessageManager.getString(
+                  "status.no_structures_discovered_from_3d_beacons"),
+                  progressId);
+          btn_queryTDB.setToolTipText(MessageManager.getString(
+                  "status.no_structures_discovered_from_3d_beacons"));
+          btn_queryTDB.setEnabled(false);
+          pnl_queryTDB.setVisible(false);
+        }
+        else
+        {
+          cmb_filterOption.setSelectedIndex(0); // select 'best'
+          btn_queryTDB.setVisible(false);
+          pnl_queryTDB.setVisible(false);
+          progressBar.setProgressBar(null, progressId);
+        }
+        mainFrame.setEnabled(true);
+        cmb_filterOption.setEnabled(true);
       }
     };
 
     final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
     {
-      
+
       @Override
       public void finished()
       {
@@ -260,12 +305,12 @@ public class StructureChooser extends GStructureChooser
         notQueriedTDBYet = false;
         // new thread to discover structures - via 3d beacons
         Executors.defaultThreadFactory().newThread(strucDiscovery).start();
-        
+
       }
     };
-    
+
     // fetch db refs if OK pressed
-    final Runnable discoverCanonicalDBrefs = new Runnable() 
+    final Runnable discoverCanonicalDBrefs = new Runnable()
     {
       @Override
       public void run()
@@ -283,22 +328,33 @@ public class StructureChooser extends GStructureChooser
           dbRefFetcher.addListener(afterDbRefFetch);
           // ideally this would also gracefully run with callbacks
           dbRefFetcher.fetchDBRefs(true);
-        } else {
+        }
+        else
+        {
           // call finished action directly
           afterDbRefFetch.finished();
         }
       }
 
     };
-    final Runnable revertview = new Runnable() {
-      public void run() {
-        if (lastSelected!=null) {
+    final Runnable revertview = new Runnable()
+    {
+      public void run()
+      {
+        if (lastSelected != null)
+        {
           cmb_filterOption.setSelectedItem(lastSelected);
         }
       };
     };
+    if (ignoreGui)
+    {
+      Executors.defaultThreadFactory().newThread(discoverCanonicalDBrefs)
+              .start();
+      return;
+    }
     // need cancel and no to result in the discoverPDB action - mocked is
-    // 'cancel'
+    // 'cancel' TODO: mock should be OK
     JvOptionPane.newOptionDialog(this)
             .setResponseHandler(JvOptionPane.OK_OPTION,
                     discoverCanonicalDBrefs)
@@ -308,8 +364,7 @@ public class StructureChooser extends GStructureChooser
                     MessageManager.formatMessage(
                             "label.fetch_references_for_3dbeacons",
                             seqsWithoutSourceDBRef.size()),
-                    MessageManager
-                            .getString("label.3dbeacons"),
+                    MessageManager.getString("label.3dbeacons"),
                     JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
                     null, new Object[]
                     { MessageManager.getString("action.ok"),
@@ -586,7 +641,7 @@ public class StructureChooser extends GStructureChooser
     // StructureChooser
     // works
     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
+            Cache.getProperty("LAST_DIRECTORY"));
     chooser.setFileView(new jalview.io.JalviewFileView());
     chooser.setDialogTitle(
             MessageManager.formatMessage("label.select_pdb_file_for",
@@ -599,7 +654,7 @@ public class StructureChooser extends GStructureChooser
     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
     {
       selectedPdbFileName = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
+      Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
       validateSelections();
     }
   }
@@ -654,10 +709,8 @@ public class StructureChooser extends GStructureChooser
                     "-", VIEWS_FROM_FILE, false, null));
     if (canQueryTDB && notQueriedTDBYet)
     {
-      FilterOption queryTDBOption = new FilterOption(
-              MessageManager.getString("label.search_3dbeacons"), "-",
-              VIEWS_QUERYING_TDB, false, null);
-      cmb_filterOption.addItem(queryTDBOption);
+      btn_queryTDB.setVisible(true);
+      pnl_queryTDB.setVisible(true);
     }
 
     if (cachedPDBExist)
@@ -685,13 +738,7 @@ public class StructureChooser extends GStructureChooser
   {
     FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
             .getSelectedItem());
-    
-    // first check if we need to rebuild dialog
-    if (selectedFilterOpt.getView() == VIEWS_QUERYING_TDB)
-    {
-      promptForTDBFetch();
-      return;
-    }
+
     if (lastSelected == selectedFilterOpt)
     {
       // don't need to do anything, probably
@@ -706,7 +753,7 @@ public class StructureChooser extends GStructureChooser
     String filterTitle = mainFrame.getTitle();
     mainFrame.setTitle(frameTitle);
     chk_invertFilter.setVisible(false);
-    
+
     if (selectedFilterOpt.getView() == VIEWS_FILTER)
     {
       mainFrame.setTitle(filterTitle);
@@ -791,6 +838,45 @@ public class StructureChooser extends GStructureChooser
             .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
   }
 
+  @Override
+  protected boolean showPopupFor(int selectedRow, int x, int y)
+  {
+    FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
+            .getSelectedItem());
+    String currentView = selectedFilterOpt.getView();
+
+    if (currentView == VIEWS_FILTER
+            && data instanceof ThreeDBStructureChooserQuerySource)
+    {
+
+      TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
+              .getFTSDataFor(getResultTable(), selectedRow,
+                      discoveredStructuresSet);
+      String pageUrl = row.getModelViewUrl();
+      JPopupMenu popup = new JPopupMenu("3D Beacons");
+      JMenuItem viewUrl = new JMenuItem("View model web page");
+      viewUrl.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          Desktop.showUrl(pageUrl);
+        }
+      });
+      popup.add(viewUrl);
+      SwingUtilities.invokeLater(new Runnable()
+      {
+        public void run()
+        {
+          popup.show(getResultTable(), x, y);
+        }
+      });
+      return true;
+    }
+    // event not handled by us
+    return false;
+  }
+
   /**
    * Validates inputs from the Manual PDB entry panel
    */
@@ -862,7 +948,9 @@ public class StructureChooser extends GStructureChooser
   {
     validateSelections();
   }
-  private FilterOption lastSelected=null;
+
+  private FilterOption lastSelected = null;
+
   /**
    * Handles the state change event for the 'filter' combo-box and 'invert'
    * check-box
@@ -1019,7 +1107,8 @@ public class StructureChooser extends GStructureChooser
             if (pdbIdStr.split(":").length > 1)
             {
               pdbEntry.setId(pdbIdStr.split(":")[0]);
-              pdbEntry.setChainCode(pdbIdStr.split(":")[1].toUpperCase());
+              pdbEntry.setChainCode(
+                      pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
             }
             else
             {
@@ -1246,7 +1335,7 @@ public class StructureChooser extends GStructureChooser
             // TODO move this pdb id search into the PDB specific
             // FTSSearchEngine
             // for moment, it will work fine as is because it is self-contained
-            String searchTerm = text.toLowerCase();
+            String searchTerm = text.toLowerCase(Locale.ROOT);
             searchTerm = searchTerm.split(":")[0];
             // System.out.println(">>>>> search term : " + searchTerm);
             List<FTSDataColumnI> wantedFields = new ArrayList<>();
@@ -1456,4 +1545,18 @@ public class StructureChooser extends GStructureChooser
             && mainFrame.isVisible()
             && cmb_filterOption.getSelectedItem() != null;
   }
+
+  /**
+   * 
+   * @return true if the 3D-Beacons query button will/has been displayed
+   */
+  public boolean isCanQueryTDB()
+  {
+    return canQueryTDB;
+  }
+
+  public boolean isNotQueriedTDBYet()
+  {
+    return notQueriedTDBYet;
+  }
 }