Merge branch 'releases/Release_2_10_4_Branch' into develop
[jalview.git] / src / jalview / gui / AnnotationLabels.java
index 45350fd..6f8b225 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import jalview.analysis.AlignSeq;
 import jalview.analysis.AlignmentUtils;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
@@ -30,16 +31,17 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.io.FileFormat;
 import jalview.io.FormatAdapter;
+import jalview.util.Comparison;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 
 import java.awt.Color;
+import java.awt.Cursor;
 import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.MediaTracker;
 import java.awt.RenderingHints;
 import java.awt.Toolkit;
 import java.awt.datatransfer.StringSelection;
@@ -50,8 +52,10 @@ import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.regex.Pattern;
 
 import javax.swing.JCheckBoxMenuItem;
@@ -62,63 +66,74 @@ import javax.swing.SwingUtilities;
 import javax.swing.ToolTipManager;
 
 /**
- * DOCUMENT ME!
- * 
- * @author $author$
- * @version $Revision$
+ * The panel that holds the labels for alignment annotations, providing
+ * tooltips, context menus, drag to reorder rows, and drag to adjust panel
+ * height
  */
 public class AnnotationLabels extends JPanel
         implements MouseListener, MouseMotionListener, ActionListener
 {
+  /**
+   * width in pixels within which height adjuster arrows are shown and active
+   */
+  private static final int HEIGHT_ADJUSTER_WIDTH = 50;
+
+  /**
+   * height in pixels for allowing height adjuster to be active
+   */
+  private static int HEIGHT_ADJUSTER_HEIGHT = 10;
+
   private static final Pattern LEFT_ANGLE_BRACKET_PATTERN = Pattern
           .compile("<");
 
-  String TOGGLE_LABELSCALE = MessageManager
+  private static final Font font = new Font("Arial", Font.PLAIN, 11);
+
+  private static final String TOGGLE_LABELSCALE = MessageManager
           .getString("label.scale_label_to_column");
 
-  String ADDNEW = MessageManager.getString("label.add_new_row");
+  private static final String ADDNEW = MessageManager
+          .getString("label.add_new_row");
 
-  String EDITNAME = MessageManager
+  private static final String EDITNAME = MessageManager
           .getString("label.edit_label_description");
 
-  String HIDE = MessageManager.getString("label.hide_row");
+  private static final String HIDE = MessageManager
+          .getString("label.hide_row");
 
-  String DELETE = MessageManager.getString("label.delete_row");
+  private static final String DELETE = MessageManager
+          .getString("label.delete_row");
 
-  String SHOWALL = MessageManager.getString("label.show_all_hidden_rows");
+  private static final String SHOWALL = MessageManager
+          .getString("label.show_all_hidden_rows");
 
-  String OUTPUT_TEXT = MessageManager.getString("label.export_annotation");
+  private static final String OUTPUT_TEXT = MessageManager
+          .getString("label.export_annotation");
 
-  String COPYCONS_SEQ = MessageManager
+  private static final String COPYCONS_SEQ = MessageManager
           .getString("label.copy_consensus_sequence");
 
-  boolean resizePanel = false;
-
-  Image image;
+  private final boolean debugRedraw = false;
 
-  AlignmentPanel ap;
+  private AlignmentPanel ap;
 
   AlignViewport av;
 
-  boolean resizing = false;
-
-  MouseEvent dragEvent;
+  private MouseEvent dragEvent;
 
-  int oldY;
+  private int oldY;
 
-  int selectedRow;
+  private int selectedRow;
 
   private int scrollOffset = 0;
 
-  Font font = new Font("Arial", Font.PLAIN, 11);
-
   private boolean hasHiddenRows;
 
+  private boolean resizePanel = false;
+
   /**
-   * Creates a new AnnotationLabels object.
+   * Creates a new AnnotationLabels object
    * 
    * @param ap
-   *          DOCUMENT ME!
    */
   public AnnotationLabels(AlignmentPanel ap)
   {
@@ -126,30 +141,6 @@ public class AnnotationLabels extends JPanel
     av = ap.av;
     ToolTipManager.sharedInstance().registerComponent(this);
 
-    java.net.URL url = getClass().getResource("/images/idwidth.gif");
-    Image temp = null;
-
-    if (url != null)
-    {
-      temp = java.awt.Toolkit.getDefaultToolkit().createImage(url);
-    }
-
-    try
-    {
-      MediaTracker mt = new MediaTracker(this);
-      mt.addImage(temp, 0);
-      mt.waitForID(0);
-    } catch (Exception ex)
-    {
-    }
-
-    BufferedImage bi = new BufferedImage(temp.getHeight(this),
-            temp.getWidth(this), BufferedImage.TYPE_INT_RGB);
-    Graphics2D g = (Graphics2D) bi.getGraphics();
-    g.rotate(Math.toRadians(90));
-    g.drawImage(temp, 0, -bi.getWidth(this), this);
-    image = bi;
-
     addMouseListener(this);
     addMouseMotionListener(this);
     addMouseWheelListener(ap.getAnnotationPanel());
@@ -266,9 +257,7 @@ public class AnnotationLabels extends JPanel
     }
     else if (evt.getActionCommand().equals(OUTPUT_TEXT))
     {
-      new AnnotationExporter().exportAnnotations(ap,
-              new AlignmentAnnotation[]
-              { aa[selectedRow] });
+      new AnnotationExporter(ap).exportAnnotation(aa[selectedRow]);
     }
     else if (evt.getActionCommand().equals(COPYCONS_SEQ))
     {
@@ -607,10 +596,9 @@ public class AnnotationLabels extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * Reorders annotation rows after a drag of a label
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseReleased(MouseEvent evt)
@@ -625,6 +613,9 @@ public class AnnotationLabels extends JPanel
     getSelectedRow(evt.getY() - getScrollOffset());
     int end = selectedRow;
 
+    /*
+     * if dragging to resize instead, start == end
+     */
     if (start != end)
     {
       // Swap these annotations
@@ -648,31 +639,13 @@ public class AnnotationLabels extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void mouseEntered(MouseEvent evt)
-  {
-    if (evt.getY() < 10)
-    {
-      resizePanel = true;
-      repaint();
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *          DOCUMENT ME!
+   * Removes the height adjuster image on leaving the panel, unless currently
+   * dragging it
    */
   @Override
   public void mouseExited(MouseEvent evt)
   {
-    if (dragEvent == null)
+    if (resizePanel && dragEvent == null)
     {
       resizePanel = false;
       repaint();
@@ -680,10 +653,11 @@ public class AnnotationLabels extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * A mouse drag may be either an adjustment of the panel height (if flag
+   * resizePanel is set on), or a reordering of the annotation rows. The former
+   * is dealt with by this method, the latter in mouseReleased.
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseDragged(MouseEvent evt)
@@ -717,15 +691,14 @@ public class AnnotationLabels extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * Updates the tooltip as the mouse moves over the labels
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseMoved(MouseEvent evt)
   {
-    resizePanel = evt.getY() < 10;
+    showOrHideAdjuster(evt);
 
     getSelectedRow(evt.getY() - getScrollOffset());
 
@@ -801,6 +774,26 @@ public class AnnotationLabels extends JPanel
     }
   }
 
+  /**
+   * Shows the height adjuster image if the mouse moves into the top left
+   * region, or hides it if the mouse leaves the regio
+   * 
+   * @param evt
+   */
+  protected void showOrHideAdjuster(MouseEvent evt)
+  {
+    boolean was = resizePanel;
+    resizePanel = evt.getY() < HEIGHT_ADJUSTER_HEIGHT && evt.getX() < HEIGHT_ADJUSTER_WIDTH;
+
+    if (resizePanel != was)
+    {
+      setCursor(Cursor.getPredefinedCursor(
+              resizePanel ? Cursor.S_RESIZE_CURSOR
+                      : Cursor.DEFAULT_CURSOR));
+      repaint();
+    }
+  }
+
   @Override
   public void mouseClicked(MouseEvent evt)
   {
@@ -820,11 +813,9 @@ public class AnnotationLabels extends JPanel
             // process modifiers
             SequenceGroup sg = ap.av.getSelectionGroup();
             if (sg == null || sg == aa[selectedRow].groupRef
-                    || !(jalview.util.Platform.isControlDown(evt)
-                            || evt.isShiftDown()))
+                    || !(Platform.isControlDown(evt) || evt.isShiftDown()))
             {
-              if (jalview.util.Platform.isControlDown(evt)
-                      || evt.isShiftDown())
+              if (Platform.isControlDown(evt) || evt.isShiftDown())
               {
                 // clone a new selection group from the associated group
                 ap.av.setSelectionGroup(
@@ -883,8 +874,7 @@ public class AnnotationLabels extends JPanel
               // we make a copy rather than edit the current selection if no
               // modifiers pressed
               // see Enhancement JAL-1557
-              if (!(jalview.util.Platform.isControlDown(evt)
-                      || evt.isShiftDown()))
+              if (!(Platform.isControlDown(evt) || evt.isShiftDown()))
               {
                 sg = new SequenceGroup(sg);
                 sg.clear();
@@ -892,7 +882,7 @@ public class AnnotationLabels extends JPanel
               }
               else
               {
-                if (jalview.util.Platform.isControlDown(evt))
+                if (Platform.isControlDown(evt))
                 {
                   sg.addOrRemove(aa[selectedRow].sequenceRef, true);
                 }
@@ -937,16 +927,17 @@ public class AnnotationLabels extends JPanel
     if (dseqs[0] == null)
     {
       dseqs[0] = new Sequence(sq);
-      dseqs[0].setSequence(jalview.analysis.AlignSeq.extractGaps(
-              jalview.util.Comparison.GapChars, sq.getSequenceAsString()));
+      dseqs[0].setSequence(AlignSeq.extractGaps(Comparison.GapChars,
+              sq.getSequenceAsString()));
 
       sq.setDatasetSequence(dseqs[0]);
     }
     Alignment ds = new Alignment(dseqs);
     if (av.hasHiddenColumns())
     {
-      omitHidden = av.getAlignment().getHiddenColumns()
-              .getVisibleSequenceStrings(0, sq.getLength(), seqs);
+      Iterator<int[]> it = av.getAlignment().getHiddenColumns()
+              .getVisContigsIterator(0, sq.getLength(), false);
+      omitHidden = new String[] { sq.getSequenceStringFromIterator(it) };
     }
 
     int[] alignmentStartEnd = new int[] { 0, ds.getWidth() - 1 };
@@ -1020,8 +1011,6 @@ public class AnnotationLabels extends JPanel
     drawComponent(g, false, width);
   }
 
-  private final boolean debugRedraw = false;
-
   /**
    * Draw the full set of annotation Labels for the alignment at the given
    * cursor
@@ -1204,11 +1193,7 @@ public class AnnotationLabels extends JPanel
       }
     }
 
-    if (resizePanel)
-    {
-      g.drawImage(image, 2, 0 - getScrollOffset(), this);
-    }
-    else if (dragEvent != null && aa != null)
+    if (!resizePanel && dragEvent != null && aa != null)
     {
       g.setColor(Color.lightGray);
       g.drawString(aa[selectedRow].label, dragEvent.getX(),
@@ -1227,4 +1212,9 @@ public class AnnotationLabels extends JPanel
   {
     return scrollOffset;
   }
+
+  @Override
+  public void mouseEntered(MouseEvent e)
+  {
+  }
 }