JAL-974 create mixture of sequence features marking disordered regions and sequence...
[jalview.git] / src / jalview / ws / jws2 / SequenceAnnotationWSClient.java
index e3f3674..d72681d 100644 (file)
@@ -7,28 +7,37 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.List;
 
+import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
 
 import compbio.metadata.Argument;
 
 import jalview.api.AlignCalcWorkerI;
+import jalview.bin.Cache;
 import jalview.datamodel.AlignmentView;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.gui.JalviewDialog;
 import jalview.gui.JvSwingUtils;
+import jalview.ws.jws2.dm.AAConsSettings;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.params.WsParamSetI;
 
 /**
- * @author jimp
+ * @author jprocter 
  * 
  */
-public class SequenceAnnotationWSClient extends Jws2Client
+public class SequenceAnnotationWSClient extends Jws2Client 
 {
 
+  public static final String AAConsCalcId = "jabaws2.AACons";
+
   /**
    * initialise a client so its attachWSMenuEntry method can be called.
    */
@@ -41,20 +50,24 @@ public class SequenceAnnotationWSClient extends Jws2Client
           AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
   {
     super(alignFrame, preset, null);
+    initSequenceAnnotationWSClient(sh, alignFrame, preset, editParams);
+  }
+
+  public void initSequenceAnnotationWSClient(final Jws2Instance sh,
+          AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
+  {
     if (alignFrame.getViewport().getAlignment().isNucleotide())
     {
-      JOptionPane
-              .showMessageDialog(
-                      Desktop.desktop,
-                      sh.serviceType+" can only be used\nfor amino acid alignments.",
-                      "Wrong type of sequences!",
-                      JOptionPane.WARNING_MESSAGE);
+      JOptionPane.showMessageDialog(Desktop.desktop, sh.serviceType
+              + " can only be used\nfor amino acid alignments.",
+              "Wrong type of sequences!", JOptionPane.WARNING_MESSAGE);
       return;
 
     }
     if (sh.action.toLowerCase().contains("conservation"))
     {
-      // Build an AACons style client - take alignment, return annotation for columns
+      // Build an AACons style client - take alignment, return annotation for
+      // columns
 
       List<AlignCalcWorkerI> clnts = alignFrame.getViewport()
               .getCalcManager()
@@ -65,11 +78,15 @@ public class SequenceAnnotationWSClient extends Jws2Client
         {
           return;
         }
+        AAConsClient worker;
         alignFrame
                 .getViewport()
                 .getCalcManager()
                 .registerWorker(
-                        new AAConsClient(sh, alignFrame, preset, paramset));
+                        worker = new AAConsClient(sh, alignFrame,
+                                this.preset, paramset));
+        alignFrame.getViewport().getCalcManager().startWorker(worker);
+
       }
       else
       {
@@ -81,17 +98,20 @@ public class SequenceAnnotationWSClient extends Jws2Client
         }
 
         if (!processParams(sh, editParams, true))
+        {
           return;
+        }
         // reinstate worker if it was blacklisted (might have happened due to
         // invalid parameters)
         alignFrame.getViewport().getCalcManager().workerMayRun(worker);
-        worker.updateParameters(preset, paramset);
+        worker.updateParameters(this.preset, paramset);
 
       }
     }
     if (sh.action.toLowerCase().contains("disorder"))
     {
-      // build IUPred style client. take sequences, returns annotation per sequence.
+      // build IUPred style client. take sequences, returns annotation per
+      // sequence.
       if (!processParams(sh, editParams))
       {
         return;
@@ -106,6 +126,14 @@ public class SequenceAnnotationWSClient extends Jws2Client
 
   }
 
+  public SequenceAnnotationWSClient(AAConsSettings fave,
+          AlignFrame alignFrame, boolean b)
+  {
+    super(alignFrame, fave.getPreset(), fave.getJobArgset());
+    initSequenceAnnotationWSClient(fave.getService(), alignFrame,
+            fave.getPreset(), b);
+  }
+
   /*
    * (non-Javadoc)
    * 
@@ -115,9 +143,16 @@ public class SequenceAnnotationWSClient extends Jws2Client
   public void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
           final AlignFrame alignFrame)
   {
+    if (service.serviceType.equals(compbio.ws.client.Services.AAConWS
+            .toString()))
+    {
+      registerAAConsWSInstance(wsmenu, service, alignFrame);
+      return;
+    }
     boolean hasparams = service.hasParameters();
     // Assume name ends in WS
-    String calcName = service.serviceType.substring(0,service.serviceType.length()-2);
+    String calcName = service.serviceType.substring(0,
+            service.serviceType.length() - 2);
 
     JMenuItem aacons = new JMenuItem(calcName + " Defaults");
     aacons.addActionListener(new ActionListener()
@@ -174,4 +209,238 @@ public class SequenceAnnotationWSClient extends Jws2Client
 
     }
   }
+
+  private final String AAconsToggle = "AACons Calculations",
+          AAconsToggleTooltip = "When checked, AACons calculations are updated automatically.",
+          AAeditSettings = "Change AACons Settings...",
+          AAeditSettingsTooltip = "Modify settings for AACons calculations.";
+
+  // private final enableAAConsCalculation(final AlignFrame alignFrame, )
+  private void registerAAConsWSInstance(final JMenu wsmenu,
+          final Jws2Instance service, final AlignFrame alignFrame)
+  {
+    // register this in the AACons settings set
+    JCheckBoxMenuItem _aaConsEnabled = null;
+    for (int i = 0; i < wsmenu.getItemCount(); i++)
+    {
+      JMenuItem item = wsmenu.getItem(i);
+      if (item instanceof JCheckBoxMenuItem
+              && item.getText().equals(AAconsToggle))
+      {
+        _aaConsEnabled = (JCheckBoxMenuItem) item;
+      }
+    }
+    // is there an aaCons worker already present - if so, set it to use the
+    // given service handle
+    {
+      List<AlignCalcWorkerI> aaconsClient = alignFrame.getViewport()
+              .getCalcManager()
+              .getRegisteredWorkersOfClass(AAConsClient.class);
+      if (aaconsClient != null && aaconsClient.size() > 0)
+      {
+        AAConsClient worker = (AAConsClient) aaconsClient.get(0);
+        if (!worker.service.hosturl.equals(service.hosturl))
+        {
+         // javax.swing.SwingUtilities.invokeLater(new Runnable()
+          {
+         //   @Override
+         //   public void run()
+            {
+              removeCurrentAAConsWorkerFor(alignFrame);
+              buildCurrentAAConsWorkerFor(alignFrame, service);
+            }
+          }//);
+        }
+      }
+    }
+
+    // is there a service already registered ? there shouldn't be if we are
+    // being called correctly
+    if (_aaConsEnabled == null)
+    {
+      final JCheckBoxMenuItem aaConsEnabled = new JCheckBoxMenuItem(
+              AAconsToggle);
+      wsmenu.addMenuListener(new MenuListener()
+      {
+
+        @Override
+        public void menuSelected(MenuEvent arg0)
+        {
+          wsmenu.setEnabled(!alignFrame.getViewport().getAlignment()
+                  .isNucleotide());
+          List<AlignCalcWorkerI> aaconsClient = alignFrame.getViewport()
+                  .getCalcManager()
+                  .getRegisteredWorkersOfClass(AAConsClient.class);
+          if (aaconsClient != null && aaconsClient.size() > 0)
+          {
+            aaConsEnabled.setSelected(true);
+          }
+          else
+          {
+            aaConsEnabled.setSelected(false);
+          }
+        }
+
+        @Override
+        public void menuDeselected(MenuEvent arg0)
+        {
+          // TODO Auto-generated method stub
+
+        }
+
+        @Override
+        public void menuCanceled(MenuEvent arg0)
+        {
+          // TODO Auto-generated method stub
+
+        }
+      });
+      aaConsEnabled.setToolTipText("<html><p>"
+              + JvSwingUtils.wrapTooltip(AAconsToggleTooltip + "</p>")
+              + "</html>");
+      aaConsEnabled.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent arg0)
+        {
+          // aaConsEnabled.setSelected(!aaConsEnabled.isSelected());
+          List<AlignCalcWorkerI> aaconsClient = alignFrame.getViewport()
+                  .getCalcManager()
+                  .getRegisteredWorkersOfClass(AAConsClient.class);
+          if (aaconsClient != null && aaconsClient.size() > 0)
+          {
+            removeCurrentAAConsWorkerFor(alignFrame);
+          }
+          else
+          {
+            buildCurrentAAConsWorkerFor(alignFrame);
+
+          }
+        }
+
+      });
+      wsmenu.add(aaConsEnabled);
+      JMenuItem modifyParams = new JMenuItem(AAeditSettings);
+      modifyParams.setToolTipText("<html><p>"
+              + JvSwingUtils.wrapTooltip(AAeditSettingsTooltip + "</p>")
+              + "</html>");
+      modifyParams.addActionListener(new ActionListener()
+      {
+
+        @Override
+        public void actionPerformed(ActionEvent arg0)
+        {
+          showAAConsAnnotationSettingsFor(alignFrame);
+        }
+      });
+      wsmenu.add(modifyParams);
+
+    }
+  }
+
+  private static void showAAConsAnnotationSettingsFor(AlignFrame alignFrame)
+  {
+    /*
+     * preferred settings Whether AACons is automatically recalculated Which
+     * AACons server to use What parameters to use
+     */
+    // could actually do a class search for this too
+    AAConsSettings fave = (AAConsSettings) alignFrame.getViewport()
+            .getCalcIdSettingsFor(AAConsCalcId);
+    if (fave == null)
+    {
+      fave = createDefaultAAConsSettings();
+    }
+    new SequenceAnnotationWSClient(fave, alignFrame, true);
+
+  }
+
+  private static void buildCurrentAAConsWorkerFor(AlignFrame alignFrame)
+  {
+    buildCurrentAAConsWorkerFor(alignFrame, null);
+  }
+
+  private static void buildCurrentAAConsWorkerFor(AlignFrame alignFrame,
+          Jws2Instance service)
+  {
+    /*
+     * preferred settings Whether AACons is automatically recalculated Which
+     * AACons server to use What parameters to use
+     */
+    AAConsSettings fave = (AAConsSettings) alignFrame.getViewport()
+            .getCalcIdSettingsFor(AAConsCalcId);
+    if (fave == null)
+    {
+      fave = createDefaultAAConsSettings(service);
+    }
+    else
+    {
+      if (service != null
+              && !fave.getService().hosturl.equals(service.hosturl))
+      {
+        Cache.log.debug("Changing AACons service to " + service.hosturl
+                + " from " + fave.getService().hosturl);
+        fave.setService(service);
+      }
+    }
+    new SequenceAnnotationWSClient(fave, alignFrame, false);
+  }
+
+  private static AAConsSettings createDefaultAAConsSettings()
+  {
+    return createDefaultAAConsSettings(null);
+  }
+
+  private static AAConsSettings createDefaultAAConsSettings(
+          Jws2Instance service)
+  {
+    if (service != null)
+    {
+      if (!service.serviceType.toString().equals(
+              compbio.ws.client.Services.AAConWS.toString()))
+      {
+        Cache.log
+                .warn("Ignoring invalid preferred service for AACons calculations (service type was "
+                        + service.serviceType + ")");
+        service = null;
+      }
+      else
+      {
+        // check service is actually in the list of currently avaialable
+        // services
+        if (!Jws2Discoverer.getDiscoverer().getServices().contains(service))
+        {
+          // it isn't ..
+          service = null;
+        }
+      }
+    }
+    if (service == null)
+    {
+      // get the default service for AACons
+      service = Jws2Discoverer.getDiscoverer().getPreferredServiceFor(null,
+              compbio.ws.client.Services.AAConWS.toString());
+      /*
+       * for (Jws2Instance sv : Jws2Discoverer.getDiscoverer().getServices()) {
+       * if (sv.serviceType.toString().equals(
+       * compbio.ws.client.Services.AAConWS.toString())) { service = sv; break;
+       * } }
+       */
+    }
+    if (service == null)
+    {
+      // TODO raise dialog box explaining error, and/or open the JABA
+      // preferences menu.
+      throw new Error("No AACons service found.");
+    }
+    return new AAConsSettings(true, service, null, null);
+  }
+
+  private static void removeCurrentAAConsWorkerFor(AlignFrame alignFrame)
+  {
+    alignFrame.getViewport().getCalcManager()
+            .removeRegisteredWorkersOfClass(AAConsClient.class);
+    // AAConsClient.removeAAConsAnnotation(alignFrame.alignPanel);
+
+  }
 }