JAL-1953 start on making everything interface based
[jalview.git] / src / jalview / gui / AlignFrame.java
index 7ad362f..184ffeb 100644 (file)
@@ -53,6 +53,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.PDBEntry;
@@ -60,6 +61,11 @@ import jalview.datamodel.SeqCigar;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.ext.archaeopteryx.AptxInit;
+import jalview.ext.forester.io.SupportedTreeFileFilter;
+import jalview.ext.forester.io.TreeParser;
+import jalview.ext.treeviewer.ExternalTreeFrame;
+import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
 import jalview.gui.ColourMenuHelper.ColourChangeListener;
 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
 import jalview.io.AlignmentProperties;
@@ -86,6 +92,7 @@ import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemes;
 import jalview.schemes.ResidueColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
+import jalview.util.DBRefUtils;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.ViewportRanges;
@@ -98,6 +105,8 @@ import jalview.ws.seqfetcher.DbSourceProxy;
 
 import java.awt.BorderLayout;
 import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
 import java.awt.Rectangle;
 import java.awt.Toolkit;
 import java.awt.datatransfer.Clipboard;
@@ -123,6 +132,7 @@ import java.awt.print.PrinterJob;
 import java.beans.PropertyChangeEvent;
 import java.io.File;
 import java.io.FileWriter;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URL;
 import java.util.ArrayList;
@@ -131,17 +141,26 @@ import java.util.Deque;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.StringTokenizer;
 import java.util.Vector;
 
 import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JComboBox;
 import javax.swing.JEditorPane;
 import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
 import javax.swing.JLayeredPane;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
+import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
 
+import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
+import org.forester.archaeopteryx.webservices.WebservicesManager;
+
 /**
  * DOCUMENT ME!
  * 
@@ -163,8 +182,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
   AlignViewport viewport;
 
-  ViewportRanges vpRanges;
-
   public AlignViewControllerI avc;
 
   List<AlignmentPanel> alignPanels = new ArrayList<>();
@@ -336,7 +353,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       progressBar = new ProgressBar(this.statusPanel, this.statusBar);
     }
 
-    vpRanges = viewport.getRanges();
     avc = new jalview.controller.AlignViewController(this, viewport,
             alignPanel);
     if (viewport.getAlignmentConservationAnnotation() == null)
@@ -654,9 +670,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                   { (viewport.cursorMode ? "on" : "off") }));
           if (viewport.cursorMode)
           {
-            alignPanel.getSeqPanel().seqCanvas.cursorX = vpRanges
+            ViewportRanges ranges = viewport.getRanges();
+            alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
                     .getStartRes();
-            alignPanel.getSeqPanel().seqCanvas.cursorY = vpRanges
+            alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
                     .getStartSeq();
           }
           alignPanel.getSeqPanel().seqCanvas.repaint();
@@ -689,10 +706,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           break;
         }
         case KeyEvent.VK_PAGE_UP:
-          vpRanges.pageUp();
+          viewport.getRanges().pageUp();
           break;
         case KeyEvent.VK_PAGE_DOWN:
-          vpRanges.pageDown();
+          viewport.getRanges().pageDown();
           break;
         }
       }
@@ -2147,7 +2164,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       {
 
         // propagate alignment changed.
-        vpRanges.setEndSeq(alignment.getHeight());
+        viewport.getRanges().setEndSeq(alignment.getHeight());
         if (annotationAdded)
         {
           // Duplicate sequence annotation in all views.
@@ -2548,7 +2565,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       {
         trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
                 column, viewport.getAlignment());
-        vpRanges.setStartRes(0);
+        viewport.getRanges().setStartRes(0);
       }
       else
       {
@@ -2613,13 +2630,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // This is to maintain viewport position on first residue
     // of first sequence
     SequenceI seq = viewport.getAlignment().getSequenceAt(0);
-    int startRes = seq.findPosition(vpRanges.getStartRes());
+    ViewportRanges ranges = viewport.getRanges();
+    int startRes = seq.findPosition(ranges.getStartRes());
     // ShiftList shifts;
     // viewport.getAlignment().removeGaps(shifts=new ShiftList());
     // edit.alColumnChanges=shifts.getInverse();
     // if (viewport.hasHiddenColumns)
     // viewport.getColumnSelection().compensateForEdits(shifts);
-    vpRanges.setStartRes(seq.findIndex(startRes) - 1);
+    ranges.setStartRes(seq.findIndex(startRes) - 1);
     viewport.firePropertyChange("alignment", null,
             viewport.getAlignment().getSequences());
 
@@ -2652,12 +2670,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // This is to maintain viewport position on first residue
     // of first sequence
     SequenceI seq = viewport.getAlignment().getSequenceAt(0);
-    int startRes = seq.findPosition(vpRanges.getStartRes());
+    int startRes = seq.findPosition(viewport.getRanges().getStartRes());
 
     addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
             viewport.getAlignment()));
 
-    vpRanges.setStartRes(seq.findIndex(startRes) - 1);
+    viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
 
     viewport.firePropertyChange("alignment", null,
             viewport.getAlignment().getSequences());
@@ -2713,8 +2731,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     /*
      * Create a new AlignmentPanel (with its own, new Viewport)
      */
-    AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel,
-            true);
+    AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel);
     if (!copyAnnotation)
     {
       /*
@@ -3554,7 +3571,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     viewport.followSelection = listenToViewSelections.isSelected();
   }
 
-
   /**
    * Constructs a tree panel and adds it to the desktop
    * 
@@ -3578,7 +3594,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       SequenceGroup sg = viewport.getSelectionGroup();
 
       /* Decide if the selection is a column region */
-      for (SequenceI _s : sg.getSequences())
+      for (SequenceI _s : sg.getSequences()) // port this to Archaeopteryx?
       {
         if (_s.getLength() < sg.getEndRes())
         {
@@ -3732,6 +3748,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
+
   /**
    * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
    * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
@@ -3747,15 +3764,21 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     List<Component> comps = PaintRefresher.components
             .get(viewport.getSequenceSetId());
     List<TreePanel> treePanels = new ArrayList<>();
+
+    Map<ExternalTreeFrame, ExternalTreeViewerBindingI> aptxFrames = AptxInit
+            .getAllAptxFrames();
+
     for (Component comp : comps)
     {
+      // old treepanels
       if (comp instanceof TreePanel)
       {
         treePanels.add((TreePanel) comp);
       }
+
     }
 
-    if (treePanels.size() < 1)
+    if (treePanels.isEmpty() && aptxFrames.isEmpty())
     {
       sortByTreeMenu.setVisible(false);
       return;
@@ -3763,6 +3786,42 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     sortByTreeMenu.setVisible(true);
 
+    for (Entry<ExternalTreeFrame, ExternalTreeViewerBindingI> aptxFrameWithBinding : aptxFrames
+            .entrySet())
+    {
+      ExternalTreeFrame aptxFrame = aptxFrameWithBinding.getKey();
+      ExternalTreeViewerBindingI binding = aptxFrameWithBinding.getValue();
+
+      // future support for multiple tabs
+      // for (org.forester.archaeopteryx.TreePanel aptxTree : aptxFrame
+      // .getMainPanel().getTreePanels())
+      {
+        final JMenuItem item = new JMenuItem(
+                aptxFrame.getTree().getTreeName());
+
+          item.addActionListener(new ActionListener()
+          {
+
+            @Override
+            public void actionPerformed(ActionEvent e)
+            {
+            binding.sortByTree_actionPerformed();
+            addHistoryItem(binding.sortAlignmentIn(alignPanel));
+            }
+
+          });
+        sortByTreeMenu.add(item);
+      }
+
+
+
+      }
+       
+
+           
+
+
+    // old treepanels
     for (final TreePanel tp : treePanels)
     {
       final JMenuItem item = new JMenuItem(tp.getTitle());
@@ -3880,14 +3939,81 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
   {
+    chooseTreeFile();
+  }
+
+  @Override
+  protected void loadTreeUrlItem_actionPerformed(ActionEvent e)
+  {
+    chooseTreeUrl();
+  }
+
+  @Override
+  protected void loadTreeBaseStudy_actionPerformed(ActionEvent e)
+  {
+    chooseTreeDb(0, null);
+
+  }
+
+  @Override
+  protected void loadTreeBase_actionPerformed(ActionEvent e)
+  {
+    chooseTreeDb(1, null);
+
+  }
+  @Override
+  protected void loadTreePfam_actionPerformed(ActionEvent e)
+  {
+
+    // only DBRefs of first sequence are checked for matching DB for now,
+    // iterating through them all seems excessive
+    SequenceI seq = viewport.getAlignment().getSequenceAt(0);
+    String dbId = null;
+    for (DBRefEntry pfamRef : DBRefUtils
+            .searchRefsForSource(seq.getDBRefs(), "pfam"))
+    {
+      if (pfamRef.getAccessionId().startsWith("PF"))
+      {
+        dbId = pfamRef.getAccessionId().replaceAll("[A-Za-z]", "");
+      }
+
+    }
+    chooseTreeDb(2, dbId);
+
+  }
+  @Override
+  protected void loadTreeFam_actionPerformed(ActionEvent e)
+  {
+    chooseTreeDb(3, null);
+
+  }
+
+  @Override
+  protected void loadTreeOfLife_actionPerformed(ActionEvent e)
+  {
+    chooseTreeDb(4, null);
+
+  }
+
+
+
+
+
+  public void chooseTreeFile()
+  {
     // Pick the tree file
     JalviewFileChooser chooser = new JalviewFileChooser(
             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(
-            MessageManager.getString("label.select_newick_like_tree_file"));
+            MessageManager.getString("label.select_tree_file")); // modify
     chooser.setToolTipText(
-            MessageManager.getString("label.load_tree_file"));
+            MessageManager.getString("label.load_tree_for_sequence_set"));
+    for (SupportedTreeFileFilter treeFormat : SupportedTreeFileFilter
+            .values())
+    {
+      chooser.setFileFilter(treeFormat.getTreeFilter());
+    }
 
     int value = chooser.showOpenDialog(null);
 
@@ -3895,27 +4021,101 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       String filePath = chooser.getSelectedFile().getPath();
       Cache.setProperty("LAST_DIRECTORY", filePath);
-      NewickFile fin = null;
-      try
+      
+      
+      TreeParser treeParser = new TreeParser(filePath);
+      treeParser.loadTree(viewport);
+
+    }
+  }
+
+  /**
+   * Break up and move to TreeParser?
+   */
+  public void chooseTreeUrl()
+  {
+
+    JLabel label = new JLabel(
+            MessageManager.getString("label.tree_url_example"));
+    // add "example" button
+    final JComboBox<String> history = new JComboBox<>();
+
+    JPanel panel = new JPanel(new GridLayout(2, 1));
+    panel.add(label);
+    panel.add(history);
+    history.setPreferredSize(new Dimension(400, 20));
+    history.setEditable(true);
+    history.addItem("http://www.");
+
+    String historyItems = jalview.bin.Cache.getProperty("RECENT_URL");
+
+    StringTokenizer st;
+
+    if (historyItems != null)
       {
-        fin = new NewickFile(filePath, DataSourceType.FILE);
-        viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
-      } catch (Exception ex)
+      st = new StringTokenizer(historyItems, "\t");
+
+      while (st.hasMoreTokens())
       {
-        JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
-                MessageManager.getString("label.problem_reading_tree_file"),
-                JvOptionPane.WARNING_MESSAGE);
-        ex.printStackTrace();
+        history.addItem(st.nextToken());
+      }
       }
-      if (fin != null && fin.hasWarningMessage())
+
+    int reply = JvOptionPane.showInternalConfirmDialog(this, panel,
+            MessageManager.getString("label.load_tree_url"),
+            JvOptionPane.OK_CANCEL_OPTION);
+
+    if (reply == JvOptionPane.OK_OPTION)
+    {
+
+      String urlString = history.getSelectedItem().toString();
+      URL treeUrl;
+
+      try
       {
-        JvOptionPane.showMessageDialog(Desktop.desktop,
-                fin.getWarningMessage(),
-                MessageManager
-                        .getString("label.possible_problem_with_tree_file"),
-                JvOptionPane.WARNING_MESSAGE);
+        FileFormatI format = null;
+
+        format = new IdentifyFile().identify(urlString, DataSourceType.URL);
+        // add actual use for the format identification (jalview .jar files)
+        treeUrl = new URL(urlString);
+        AptxInit.createInstancesFromUrl(treeUrl, viewport);
+
+      } catch (IOException | RuntimeException e)
+      {
+        JvOptionPane.showMessageDialog(this, MessageManager.formatMessage(
+                "exception.failed_to_read_data_from_source", new String[]
+                { urlString }),
+                MessageManager.getString("label.url_not_found"),
+                JvOptionPane.ERROR_MESSAGE);
+        e.printStackTrace();
       }
     }
+    else
+    {
+
+    }
+  }
+
+  /**
+   * Disgustingly hardcoded atm.
+   * 
+   * @param databaseIndex
+   */
+  public void chooseTreeDb(int databaseIndex, String defaultIdentifier)
+  {
+    final WebservicesManager webservices_manager = WebservicesManager
+            .getInstance();
+    final PhylogeniesWebserviceClient client = webservices_manager
+            .getAvailablePhylogeniesWebserviceClient(databaseIndex);
+    String identifier = JvOptionPane
+            .showInternalInputDialog(Desktop.desktop,
+                    client.getInstructions() + "\n(Reference: "
+                            + client.getReference() + ")",
+                    client.getDescription(), JvOptionPane.QUESTION_MESSAGE,
+                    null, null, defaultIdentifier)
+            .toString();
+
+    AptxInit.createInstancesFromDb(client, identifier, viewport);
   }
 
   public TreePanel showNewickTree(NewickFile nf, String treeTitle)
@@ -3981,6 +4181,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
   private boolean buildingMenu = false;
 
+  public void BuildTreeDbMenu()
+  {
+
+  }
   /**
    * Generates menu items and listener event actions for web service clients
    * 
@@ -4156,7 +4360,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         }
         buildingMenu = false;
       }
-    }).start();
+    }, "BuildWebServiceThread").start();
 
   }
 
@@ -4264,7 +4468,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
           final String source)
   {
-    new Thread(CrossRefAction.showProductsFor(sel, _odna, source, this))
+    new Thread(CrossRefAction.showProductsFor(sel, _odna, source, this),
+            "CrossReferencesThread")
             .start();
   }
 
@@ -4543,7 +4748,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             ex.printStackTrace();
           }
         }
-      }).start();
+      }, "DropFileThread").start();
     }
   }
 
@@ -4914,7 +5119,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             });
             dbRefFetcher.fetchDBRefs(false);
           }
-        }).start();
+        }, "BuildFetchDBMenuThread").start();
 
       }