Merge branch 'develop' into features/JAL-653_gffalignments
[jalview.git] / src / jalview / gui / AlignFrame.java
index 1cd2ea8..cd9c533 100644 (file)
@@ -22,7 +22,6 @@ package jalview.gui;
 
 import java.awt.BorderLayout;
 import java.awt.Component;
-import java.awt.GridLayout;
 import java.awt.Rectangle;
 import java.awt.Toolkit;
 import java.awt.datatransfer.Clipboard;
@@ -56,17 +55,13 @@ import java.util.List;
 import java.util.Set;
 import java.util.Vector;
 
-import javax.swing.JButton;
 import javax.swing.JCheckBoxMenuItem;
 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.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JProgressBar;
 import javax.swing.JRadioButtonMenuItem;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
@@ -83,6 +78,7 @@ import jalview.api.AlignViewControllerGuiI;
 import jalview.api.AlignViewControllerI;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureSettingsControllerI;
 import jalview.api.SplitContainerI;
 import jalview.api.ViewStyleI;
 import jalview.api.analysis.ScoreModelI;
@@ -102,6 +98,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SeqCigar;
 import jalview.datamodel.Sequence;
@@ -111,7 +108,6 @@ import jalview.gui.ViewSelectionMenu.ViewSetProvider;
 import jalview.io.AlignmentProperties;
 import jalview.io.AnnotationFile;
 import jalview.io.BioJsHTMLOutput;
-import jalview.io.FeaturesFile;
 import jalview.io.FileLoader;
 import jalview.io.FormatAdapter;
 import jalview.io.HtmlSvgOutput;
@@ -244,6 +240,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     this(al, hiddenColumns, width, height, null);
   }
 
+
   /**
    * Create alignment frame for al with hiddenColumns, a specific width and
    * height, and specific sequenceId
@@ -293,6 +290,29 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     init();
   }
 
+  public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
+          ColumnSelection hiddenColumns, int width, int height)
+  {
+    setSize(width, height);
+
+    if (al.getDataset() == null)
+    {
+      al.setDataset(null);
+    }
+
+    viewport = new AlignViewport(al, hiddenColumns);
+
+    if (hiddenSeqs != null && hiddenSeqs.length > 0)
+    {
+      viewport.hideSequence(hiddenSeqs);
+      viewport.setHasHiddenRows(true);
+    }
+    alignPanel = new AlignmentPanel(this, viewport);
+    addAlignmentPanel(alignPanel, true);
+    init();
+  }
+
+
   /**
    * Make a new AlignFrame from existing alignmentPanels
    * 
@@ -315,6 +335,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    */
   void init()
   {
+    progressBar = new ProgressBar(this.statusPanel, this.statusBar);
+
     avc = new jalview.controller.AlignViewController(this, viewport,
             alignPanel);
     if (viewport.getAlignmentConservationAnnotation() == null)
@@ -873,9 +895,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     updateEditMenuBar();
   }
 
-  // methods for implementing IProgressIndicator
-  // need to refactor to a reusable stub class
-  Hashtable progressBars, progressBarHandlers;
+  private IProgressIndicator progressBar;
 
   /*
    * (non-Javadoc)
@@ -885,78 +905,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void setProgressBar(String message, long id)
   {
-    if (progressBars == null)
-    {
-      progressBars = new Hashtable();
-      progressBarHandlers = new Hashtable();
-    }
-
-    JPanel progressPanel;
-    Long lId = new Long(id);
-    GridLayout layout = (GridLayout) statusPanel.getLayout();
-    if (progressBars.get(lId) != null)
-    {
-      progressPanel = (JPanel) progressBars.get(new Long(id));
-      statusPanel.remove(progressPanel);
-      progressBars.remove(lId);
-      progressPanel = null;
-      if (message != null)
-      {
-        statusBar.setText(message);
-      }
-      if (progressBarHandlers.contains(lId))
-      {
-        progressBarHandlers.remove(lId);
-      }
-      layout.setRows(layout.getRows() - 1);
-    }
-    else
-    {
-      progressPanel = new JPanel(new BorderLayout(10, 5));
-
-      JProgressBar progressBar = new JProgressBar();
-      progressBar.setIndeterminate(true);
-
-      progressPanel.add(new JLabel(message), BorderLayout.WEST);
-      progressPanel.add(progressBar, BorderLayout.CENTER);
-
-      layout.setRows(layout.getRows() + 1);
-      statusPanel.add(progressPanel);
-
-      progressBars.put(lId, progressPanel);
-    }
-    // update GUI
-    // setMenusForViewport();
-    validate();
+    progressBar.setProgressBar(message, id);
   }
 
   @Override
   public void registerHandler(final long id,
           final IProgressIndicatorHandler handler)
   {
-    if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
-    {
-      throw new Error(MessageManager.getString("error.call_setprogressbar_before_registering_handler"));
-    }
-    progressBarHandlers.put(new Long(id), handler);
-    final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
-    if (handler.canCancel())
-    {
-      JButton cancel = new JButton(
-              MessageManager.getString("action.cancel"));
-      final IProgressIndicator us = this;
-      cancel.addActionListener(new ActionListener()
-      {
-
-        @Override
-        public void actionPerformed(ActionEvent e)
-        {
-          handler.cancelActivity(id);
-          us.setProgressBar(MessageManager.formatMessage("label.cancelled_params", new Object[]{((JLabel) progressPanel.getComponent(0)).getText()}), id);
-        }
-      });
-      progressPanel.add(cancel, BorderLayout.EAST);
-    }
+    progressBar.registerHandler(id, handler);
   }
 
   /**
@@ -966,18 +922,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public boolean operationInProgress()
   {
-    if (progressBars != null && progressBars.size() > 0)
-    {
-      return true;
-    }
-    return false;
+    return progressBar.operationInProgress();
   }
 
   @Override
   public void setStatus(String text)
   {
     statusBar.setText(text);
-  };
+  }
 
   /*
    * Added so Castor Mapping file can obtain Jalview Version
@@ -1170,11 +1122,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 .lastIndexOf(java.io.File.separatorChar) + 1);
       }
 
-      /*
-       * First save any linked Chimera session.
-       */
-      Desktop.instance.saveChimeraSessions(file);
-
       success = new Jalview2XML().saveAlignment(this, file, shortName);
 
       statusBar.setText(MessageManager.formatMessage(
@@ -1193,30 +1140,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         return false;
       }
 
-      String[] omitHidden = null;
-
-      if (viewport.hasHiddenColumns())
-      {
-        int reply = JOptionPane
-                .showInternalConfirmDialog(
-                        Desktop.desktop,
-                        MessageManager
-                                .getString("label.alignment_contains_hidden_columns"),
-                        MessageManager
-                                .getString("action.save_omit_hidden_columns"),
-                        JOptionPane.YES_NO_OPTION,
-                        JOptionPane.QUESTION_MESSAGE);
-
-        if (reply == JOptionPane.YES_OPTION)
-        {
-          omitHidden = viewport.getViewAsString(false);
-        }
-      }
-      FormatAdapter f = new FormatAdapter();
+      ExportData exportData = getAlignmentForExport();
+      FormatAdapter f = new FormatAdapter(viewport);
       String output = f.formatSequences(format,
-              viewport.getAlignment(), // class cast exceptions will
+              exportData.getAlignment(), // class cast exceptions will
               // occur in the distant future
-              omitHidden, f.getCacheSuffixDefault(format),
+              exportData.getOmitHidden(), exportData.getStartEndPostions(),
+              f.getCacheSuffixDefault(format),
               viewport.getColumnSelection());
 
       if (output == null)
@@ -1257,6 +1187,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     return success;
   }
 
+
   private void warningMessage(String warning, String title)
   {
     if (new jalview.util.Platform().isHeadless())
@@ -1281,9 +1212,45 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void outputText_actionPerformed(ActionEvent e)
   {
+
+    ExportData exportData = getAlignmentForExport();
+    CutAndPasteTransfer cap = new CutAndPasteTransfer();
+    cap.setForInput(null);
+
+    try
+    {
+      cap.setText(new FormatAdapter(viewport).formatSequences(
+              e.getActionCommand(),
+ exportData.getAlignment(),
+              exportData.getOmitHidden(), exportData.getStartEndPostions(),
+              viewport.getColumnSelection()));
+      Desktop.addInternalFrame(cap, MessageManager.formatMessage(
+              "label.alignment_output_command", new Object[]
+              { e.getActionCommand() }), 600, 500);
+    } catch (OutOfMemoryError oom)
+    {
+      new OOMWarning("Outputting alignment as " + e.getActionCommand(), oom);
+      cap.dispose();
+    }
+
+  }
+
+  public ExportData getAlignmentForExport()
+  {
+    AlignmentI alignmentToExport = null;
     String[] omitHidden = null;
+    int[] alignmentStartEnd = new int[2];
+    FeatureRenderer fr = new FeatureRenderer(this.alignPanel);
+    viewport.setFeatureRenderer(fr);
+    HiddenSequences hiddenSeqs = viewport.getAlignment()
+            .getHiddenSequences();
 
-    if (viewport.hasHiddenColumns())
+
+    alignmentToExport = viewport.getAlignment();
+    alignmentStartEnd = new int[]
+    { 0, alignmentToExport.getWidth() - 1 };
+
+    if (viewport.hasHiddenColumns() || hiddenSeqs.getSize() > 0)
     {
       int reply = JOptionPane
               .showInternalConfirmDialog(
@@ -1297,28 +1264,83 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
       if (reply == JOptionPane.YES_OPTION)
       {
+        // export only visible region
         omitHidden = viewport.getViewAsString(false);
+        alignmentToExport = viewport.getAlignment();
+        alignmentStartEnd = getStartEnd(alignmentStartEnd, viewport
+                .getColumnSelection().getHiddenColumns());
+        viewport.setIncludeHiddenRegion(false);
+      }
+      else
+      {
+        // export all region including visible
+        alignmentToExport = hiddenSeqs.getFullAlignment();
+        viewport.setIncludeHiddenRegion(true);
       }
     }
 
-    CutAndPasteTransfer cap = new CutAndPasteTransfer();
-    cap.setForInput(null);
+    return new ExportData(alignmentToExport, omitHidden, alignmentStartEnd);
+  }
 
-    try
+  private static int[] getStartEnd(int[] aligmentStartEnd,
+          List<int[]> hiddenCols)
+  {
+    int startPos = aligmentStartEnd[0];
+    int endPos = aligmentStartEnd[1];
+
+    int[] lowestRange = new int[2];
+    int[] higestRange = new int[2];
+
+    for (int[] hiddenCol : hiddenCols)
     {
-      Desktop.setCurrentAlignFrame(this);
-      cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
-              viewport.getAlignment(), omitHidden,
-              viewport.getColumnSelection()));
-      Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-              "label.alignment_output_command", new Object[]
-              { e.getActionCommand() }), 600, 500);
-    } catch (OutOfMemoryError oom)
+      // System.out.println("comparing : " + hiddenCol[0] + "-" + hiddenCol[1]);
+
+      lowestRange = (hiddenCol[0] <= startPos) ? hiddenCol : lowestRange;
+      higestRange = (hiddenCol[1] >= endPos) ? hiddenCol : higestRange;
+    }
+    // System.out.println("min : " + lowestRange[0] + "-" + lowestRange[1]);
+    // System.out.println("max : " + higestRange[0] + "-" + higestRange[1]);
+
+    if (lowestRange[0] == 0 && lowestRange[1] == 0)
     {
-      new OOMWarning("Outputting alignment as " + e.getActionCommand(), oom);
-      cap.dispose();
+      startPos = aligmentStartEnd[0];
+    }
+    else
+    {
+      startPos = lowestRange[1] + 1;
     }
 
+    if (higestRange[0] == 0 && higestRange[1] == 0)
+    {
+      endPos = aligmentStartEnd[1];
+    }
+    else
+    {
+      endPos = higestRange[0];
+    }
+
+    // System.out.println("Export range : " + minPos + " - " + maxPos);
+    return new int[]
+    { startPos, endPos };
+  }
+
+  public static void main(String[] args)
+  {
+    ArrayList<int[]> hiddenCols = new ArrayList<int[]>();
+    hiddenCols.add(new int[]
+    { 0, 4 });
+    hiddenCols.add(new int[]
+    { 6, 9 });
+    hiddenCols.add(new int[]
+    { 11, 12 });
+    hiddenCols.add(new int[]
+    { 33, 33 });
+    hiddenCols.add(new int[]
+    { 45, 50 });
+
+    int[] x = getStartEnd(new int[]
+    { 0, 50 }, hiddenCols);
+    // System.out.println("Export range : " + x[0] + " - " + x[1]);
   }
 
   /**
@@ -1339,8 +1361,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void bioJSMenuItem_actionPerformed(ActionEvent e)
   {
-    new BioJsHTMLOutput(alignPanel,
+    BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel,
             alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer());
+    bjs.exportJalviewAlignmentAsBioJsHtmlFile();
   }
   public void createImageMap(File file, String image)
   {
@@ -1844,7 +1867,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
 
     String output = new FormatAdapter().formatSequences("Fasta", seqs,
-            omitHidden);
+            omitHidden, null);
 
     StringSelection ss = new StringSelection(output);
 
@@ -3136,6 +3159,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public FeatureSettings featureSettings;
 
   @Override
+  public FeatureSettingsControllerI getFeatureSettingsUI()
+  {
+    return featureSettings;
+  }
+
+  @Override
   public void featureSettings_actionPerformed(ActionEvent e)
   {
     if (featureSettings != null)
@@ -4985,41 +5014,29 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    *          contents or path to retrieve file
    * @param type
    *          access mode of file (see jalview.io.AlignFile)
-   * @return true if features file was parsed corectly.
+   * @return true if features file was parsed correctly.
    */
   public boolean parseFeaturesFile(String file, String type)
   {
-    boolean featuresFile = false;
-    try
-    {
-      featuresFile = new FeaturesFile(file, type).parse(viewport
-              .getAlignment().getDataset(), alignPanel.getSeqPanel().seqCanvas
-              .getFeatureRenderer().getFeatureColours(), false,
-              jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false));
-    } catch (Exception ex)
-    {
-      ex.printStackTrace();
-    }
+    return avc.parseFeaturesFile(file, type,
+            jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false));
+    
+  }
 
-    if (featuresFile)
+  @Override
+  public void refreshFeatureUI(boolean enableIfNecessary)
+  {
+    // note - currently this is only still here rather than in the controller
+    // because of the featureSettings hard reference that is yet to be
+    // abstracted
+    if (enableIfNecessary)
     {
       viewport.setShowSequenceFeatures(true);
       showSeqFeatures.setSelected(true);
-      if (alignPanel.getSeqPanel().seqCanvas.fr != null)
-      {
-        // update the min/max ranges where necessary
-        alignPanel.getSeqPanel().seqCanvas.fr.findAllFeatures(true);
-      }
-      if (featureSettings != null)
-      {
-        featureSettings.setTableData();
-      }
-      alignPanel.paintAlignment(true);
     }
 
-    return featuresFile;
-  }
 
+  }
   @Override
   public void dragEnter(DropTargetDragEvent evt)
   {
@@ -6062,6 +6079,53 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       sf.setComplementVisible(this, show);
     }
   }
+
+  public class ExportData
+  {
+    private AlignmentI alignment;
+
+    private String[] omitHidden;
+
+    private int[] startEnd;
+
+    public ExportData(AlignmentI align, String[] ommit, int[] startEnd)
+    {
+      this.alignment = align;
+      this.omitHidden = ommit;
+      this.startEnd = startEnd;
+    }
+
+    public AlignmentI getAlignment()
+    {
+      return alignment;
+    }
+
+    public void setAlignment(AlignmentI alignment)
+    {
+      this.alignment = alignment;
+    }
+
+    public String[] getOmitHidden()
+    {
+      return omitHidden;
+    }
+
+    public void setOmitHidden(String[] omitHidden)
+    {
+      this.omitHidden = omitHidden;
+    }
+
+    public int[] getStartEndPostions()
+    {
+      return startEnd;
+    }
+
+    public void setStartEndPostions(int[] startEnd)
+    {
+      this.startEnd = startEnd;
+    }
+  }
+
 }
 
 class PrintThread extends Thread