JAL-2962 code tidying/documentation (non-functional) changes
[jalview.git] / src / jalview / gui / RotatableCanvas.java
index 4611533..dc33b36 100755 (executable)
@@ -1,31 +1,53 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
- * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This file is part of Jalview.
  * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.gui;
 
-import java.util.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-
-import jalview.datamodel.*;
-import jalview.math.*;
+import jalview.api.RotatableCanvasI;
+import jalview.bin.Cache;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequencePoint;
+import jalview.math.RotatableMatrix;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.RenderingHints;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.util.Vector;
+
+import javax.swing.JPanel;
+import javax.swing.ToolTipManager;
 
 /**
  * DOCUMENT ME!
@@ -34,7 +56,7 @@ import jalview.math.*;
  * @version $Revision$
  */
 public class RotatableCanvas extends JPanel implements MouseListener,
-        MouseMotionListener, KeyListener
+        MouseMotionListener, KeyListener, RotatableCanvasI
 {
   RotatableMatrix idmat = new RotatableMatrix(3, 3);
 
@@ -73,7 +95,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
   int npoint;
 
-  Vector points;
+  Vector<SequencePoint> points;
 
   float[][] orig;
 
@@ -97,7 +119,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
   float scalefactor = 1;
 
-  AlignViewport av;
+  AlignmentViewport av;
 
   AlignmentPanel ap;
 
@@ -107,7 +129,8 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
   boolean applyToAllViews = false;
 
-  // Controller controller;
+  boolean first = true;
+
   public RotatableCanvas(AlignmentPanel ap)
   {
     this.av = ap.av;
@@ -115,16 +138,23 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
     addMouseWheelListener(new MouseWheelListener()
     {
+      @Override
       public void mouseWheelMoved(MouseWheelEvent e)
       {
-        if (e.getWheelRotation() > 0)
+        double wheelRotation = e.getPreciseWheelRotation();
+        if (wheelRotation > 0)
         {
+          /*
+           * zoom in
+           */
           scale = (float) (scale * 1.1);
           repaint();
         }
-
-        else
+        else if (wheelRotation < 0)
         {
+          /*
+           * zoom out
+           */
           scale = (float) (scale * 0.9);
           repaint();
         }
@@ -139,20 +169,23 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     repaint();
   }
 
-  public void setPoints(Vector points, int npoint)
+  @Override
+  public void setPoints(Vector<SequencePoint> points, int npoint)
   {
     this.points = points;
     this.npoint = npoint;
-    ToolTipManager.sharedInstance().registerComponent(this);
-    ToolTipManager.sharedInstance().setInitialDelay(0);
-    ToolTipManager.sharedInstance().setDismissDelay(10000);
-
+    if (first)
+    {
+      ToolTipManager.sharedInstance().registerComponent(this);
+      ToolTipManager.sharedInstance().setInitialDelay(0);
+      ToolTipManager.sharedInstance().setDismissDelay(10000);
+    }
     prefsize = getPreferredSize();
     orig = new float[npoint][3];
 
     for (int i = 0; i < npoint; i++)
     {
-      SequencePoint sp = (SequencePoint) points.elementAt(i);
+      SequencePoint sp = points.elementAt(i);
 
       for (int j = 0; j < 3; j++)
       {
@@ -187,11 +220,14 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     findWidth();
 
     scale = findScale();
+    if (first)
+    {
 
-    addMouseListener(this);
-
-    addMouseMotionListener(this);
+      addMouseListener(this);
 
+      addMouseMotionListener(this);
+    }
+    first = false;
   }
 
   public void initAxes()
@@ -232,7 +268,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     {
       for (int j = 0; j < npoint; j++)
       {
-        SequencePoint sp = (SequencePoint) points.elementAt(j);
+        SequencePoint sp = points.elementAt(j);
 
         if (sp.coord[i] >= max[i])
         {
@@ -276,30 +312,30 @@ public class RotatableCanvas extends JPanel implements MouseListener,
   public float findScale()
   {
     int dim;
-    int width;
+    int w;
     int height;
 
     if (getWidth() != 0)
     {
-      width = getWidth();
+      w = getWidth();
       height = getHeight();
     }
     else
     {
-      width = prefsize.width;
+      w = prefsize.width;
       height = prefsize.height;
     }
 
-    if (width < height)
+    if (w < height)
     {
-      dim = width;
+      dim = w;
     }
     else
     {
       dim = height;
     }
 
-    return (float) ((dim * scalefactor) / (2 * maxwidth));
+    return (dim * scalefactor) / (2 * maxwidth);
   }
 
   /**
@@ -324,6 +360,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Dimension getPreferredSize()
   {
     if (prefsize != null)
@@ -341,6 +378,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Dimension getMinimumSize()
   {
     return getPreferredSize();
@@ -350,8 +388,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * DOCUMENT ME!
    * 
    * @param g
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
+  @Override
   public void paintComponent(Graphics g1)
   {
 
@@ -362,7 +401,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     if (points == null)
     {
       g.setFont(new Font("Verdana", Font.PLAIN, 18));
-      g.drawString("Calculating PCA....", 20, getHeight() / 2);
+      g.drawString(
+              MessageManager.getString("label.calculating_pca") + "....",
+              20, getHeight() / 2);
     }
     else
     {
@@ -383,7 +424,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
       drawBackground(ig, bgColour);
       drawScene(ig);
 
-      if (drawAxes == true)
+      if (drawAxes)
       {
         drawAxes(ig);
       }
@@ -396,7 +437,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * DOCUMENT ME!
    * 
    * @param g
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
   public void drawAxes(Graphics g)
   {
@@ -405,9 +446,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
     for (int i = 0; i < 3; i++)
     {
-      g.drawLine(getWidth() / 2, getHeight() / 2, (int) ((axes[i][0]
-              * scale * max[0]) + (getWidth() / 2)), (int) ((axes[i][1]
-              * scale * max[1]) + (getHeight() / 2)));
+      g.drawLine(getWidth() / 2, getHeight() / 2,
+              (int) ((axes[i][0] * scale * max[0]) + (getWidth() / 2)),
+              (int) ((axes[i][1] * scale * max[1]) + (getHeight() / 2)));
     }
   }
 
@@ -415,9 +456,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * DOCUMENT ME!
    * 
    * @param g
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param col
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
   public void drawBackground(Graphics g, Color col)
   {
@@ -429,7 +470,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * DOCUMENT ME!
    * 
    * @param g
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
   public void drawScene(Graphics g1)
   {
@@ -444,25 +485,26 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
     for (int i = 0; i < npoint; i++)
     {
-      SequencePoint sp = (SequencePoint) points.elementAt(i);
-      int x = (int) ((float) (sp.coord[0] - centre[0]) * scale) + halfwidth;
-      int y = (int) ((float) (sp.coord[1] - centre[1]) * scale)
+      SequencePoint sp = points.elementAt(i);
+      int x = (int) ((sp.coord[0] - centre[0]) * scale) + halfwidth;
+      int y = (int) ((sp.coord[1] - centre[1]) * scale)
               + halfheight;
       float z = sp.coord[1] - centre[2];
 
-      if (av.getSequenceColour(sp.sequence) == Color.black)
+      SequenceI sequence = sp.getSequence();
+      if (av.getSequenceColour(sequence) == Color.black)
       {
         g.setColor(Color.white);
       }
       else
       {
-        g.setColor(av.getSequenceColour(sp.sequence));
+        g.setColor(av.getSequenceColour(sequence));
       }
 
       if (av.getSelectionGroup() != null)
       {
-        if (av.getSelectionGroup().getSequences(null).contains(
-                ((SequencePoint) points.elementAt(i)).sequence))
+        if (av.getSelectionGroup().getSequences(null)
+                .contains(sequence))
         {
           g.setColor(Color.gray);
         }
@@ -477,8 +519,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
       if (showLabels)
       {
         g.setColor(Color.red);
-        g.drawString(((SequencePoint) points.elementAt(i)).sequence
-                .getName(), x - 3, y - 4);
+        g.drawString(sequence.getName(), x - 3, y - 4);
       }
     }
 
@@ -514,8 +555,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * DOCUMENT ME!
    * 
    * @param evt
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
+  @Override
   public void keyTyped(KeyEvent evt)
   {
   }
@@ -524,8 +566,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * DOCUMENT ME!
    * 
    * @param evt
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
+  @Override
   public void keyReleased(KeyEvent evt)
   {
   }
@@ -534,8 +577,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
    * DOCUMENT ME!
    * 
    * @param evt
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
+  @Override
   public void keyPressed(KeyEvent evt)
   {
     if (evt.getKeyCode() == KeyEvent.VK_UP)
@@ -550,8 +594,9 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     }
     else if (evt.getKeyChar() == 's')
     {
-      System.err.println("DEBUG: Rectangle selection"); // log.debug
-
+      Cache.log.warn("DEBUG: Rectangle selection");
+      // todo not yet enabled as rectx2, recty2 are always -1
+      // need to set them in mouseDragged
       if ((rectx2 != -1) && (recty2 != -1))
       {
         rectSelect(rectx1, recty1, rectx2, recty2);
@@ -561,52 +606,33 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     repaint();
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *                DOCUMENT ME!
-   */
+  @Override
   public void mouseClicked(MouseEvent evt)
   {
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *                DOCUMENT ME!
-   */
+  @Override
   public void mouseEntered(MouseEvent evt)
   {
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *                DOCUMENT ME!
-   */
+  @Override
   public void mouseExited(MouseEvent evt)
   {
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *                DOCUMENT ME!
-   */
+  @Override
   public void mouseReleased(MouseEvent evt)
   {
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *                DOCUMENT ME!
+   * If the mouse press is at (within 2 pixels of) a sequence point, toggles
+   * (adds or removes) the corresponding sequence as a member of the viewport
+   * selection group. This supports configuring a group in the alignment by
+   * clicking on points in the PCA display.
    */
+  @Override
   public void mousePressed(MouseEvent evt)
   {
     int x = evt.getX();
@@ -627,7 +653,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     rectx2 = -1;
     recty2 = -1;
 
-    SequenceI found = findPoint(x, y);
+    SequenceI found = findSequenceAtPoint(x, y);
 
     if (found != null)
     {
@@ -643,8 +669,8 @@ public class RotatableCanvas extends JPanel implements MouseListener,
         {
           aps[a].av.setSelectionGroup(new SequenceGroup());
           aps[a].av.getSelectionGroup().addOrRemove(found, true);
-          aps[a].av.getSelectionGroup().setEndRes(
-                  aps[a].av.alignment.getWidth() - 1);
+          aps[a].av.getSelectionGroup()
+                  .setEndRes(aps[a].av.getAlignment().getWidth() - 1);
         }
       }
       PaintRefresher.Refresh(this, av.getSequenceSetId());
@@ -655,30 +681,25 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     repaint();
   }
 
-  // private void fireSequenceSelectionEvent(Selection sel) {
-  // controller.handleSequenceSelectionEvent(new
-  // SequenceSelectionEvent(this,sel));
-  // }
+  /**
+   * Sets the tooltip to the name of the sequence within 2 pixels of the mouse
+   * position, or clears the tooltip if none found
+   */
+  @Override
   public void mouseMoved(MouseEvent evt)
   {
-    SequenceI found = findPoint(evt.getX(), evt.getY());
+    SequenceI found = findSequenceAtPoint(evt.getX(), evt.getY());
 
-    if (found != null)
-    {
-      this.setToolTipText(found.getName());
-    }
-    else
-    {
-      this.setToolTipText(null);
-    }
+    this.setToolTipText(found == null ? null : found.getName());
   }
 
   /**
    * DOCUMENT ME!
    * 
    * @param evt
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
+  @Override
   public void mouseDragged(MouseEvent evt)
   {
     mx = evt.getX();
@@ -694,12 +715,12 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     {
       rotmat.setIdentity();
 
-      rotmat.rotate((float) (my - omy), 'x');
-      rotmat.rotate((float) (mx - omx), 'y');
+      rotmat.rotate(my - omy, 'x');
+      rotmat.rotate(mx - omx, 'y');
 
       for (int i = 0; i < npoint; i++)
       {
-        SequencePoint sp = (SequencePoint) points.elementAt(i);
+        SequencePoint sp = points.elementAt(i);
         sp.coord[0] -= centre[0];
         sp.coord[1] -= centre[1];
         sp.coord[2] -= centre[2];
@@ -726,54 +747,50 @@ public class RotatableCanvas extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Adds any sequences whose displayed points are within the given rectangle to
+   * the viewport's current selection. Intended for key 's' after dragging to
+   * select a region of the PCA.
    * 
    * @param x1
-   *                DOCUMENT ME!
    * @param y1
-   *                DOCUMENT ME!
    * @param x2
-   *                DOCUMENT ME!
    * @param y2
-   *                DOCUMENT ME!
    */
   public void rectSelect(int x1, int y1, int x2, int y2)
   {
     for (int i = 0; i < npoint; i++)
     {
-      SequencePoint sp = (SequencePoint) points.elementAt(i);
-      int tmp1 = (int) (((sp.coord[0] - centre[0]) * scale) + ((float) getWidth() / 2.0));
-      int tmp2 = (int) (((sp.coord[1] - centre[1]) * scale) + ((float) getHeight() / 2.0));
+      SequencePoint sp = points.elementAt(i);
+      int tmp1 = (int) (((sp.coord[0] - centre[0]) * scale)
+              + (getWidth() / 2.0));
+      int tmp2 = (int) (((sp.coord[1] - centre[1]) * scale)
+              + (getHeight() / 2.0));
 
       if ((tmp1 > x1) && (tmp1 < x2) && (tmp2 > y1) && (tmp2 < y2))
       {
         if (av != null)
         {
-          if (!av.getSelectionGroup().getSequences(null).contains(
-                  sp.sequence))
+          SequenceI sequence = sp.getSequence();
+          if (!av.getSelectionGroup().getSequences(null)
+                  .contains(sequence))
           {
-            av.getSelectionGroup().addSequence(sp.sequence, true);
+            av.getSelectionGroup().addSequence(sequence, true);
           }
         }
       }
     }
-
-    // if (changedSel) {
-    // fireSequenceSelectionEvent(av.getSelection());
-    // }
   }
 
   /**
-   * DOCUMENT ME!
+   * Answers the first sequence found whose point on the display is within 2
+   * pixels of the given coordinates, or null if none is found
    * 
    * @param x
-   *                DOCUMENT ME!
    * @param y
-   *                DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
-  public SequenceI findPoint(int x, int y)
+  public SequenceI findSequenceAtPoint(int x, int y)
   {
     int halfwidth = getWidth() / 2;
     int halfheight = getHeight() / 2;
@@ -782,10 +799,10 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
     for (int i = 0; i < npoint; i++)
     {
-      SequencePoint sp = (SequencePoint) points.elementAt(i);
-      int px = (int) ((float) (sp.coord[0] - centre[0]) * scale)
+      SequencePoint sp = points.elementAt(i);
+      int px = (int) ((sp.coord[0] - centre[0]) * scale)
               + halfwidth;
-      int py = (int) ((float) (sp.coord[1] - centre[1]) * scale)
+      int py = (int) ((sp.coord[1] - centre[1]) * scale)
               + halfheight;
 
       if ((Math.abs(px - x) < 3) && (Math.abs(py - y) < 3))
@@ -796,7 +813,7 @@ public class RotatableCanvas extends JPanel implements MouseListener,
 
     if (found != -1)
     {
-      return ((SequencePoint) points.elementAt(found)).sequence;
+      return points.elementAt(found).getSequence();
     }
     else
     {
@@ -812,8 +829,23 @@ public class RotatableCanvas extends JPanel implements MouseListener,
     }
     else
     {
-      return new AlignmentPanel[]
-      { ap };
+      return new AlignmentPanel[] { ap };
     }
   }
+
+  /**
+   * 
+   * @return x,y,z positions of point s (index into points) under current
+   *         transform.
+   */
+  public double[] getPointPosition(int s)
+  {
+    double[] pts = new double[3];
+    float[] p = points.elementAt(s).coord;
+    pts[0] = p[0];
+    pts[1] = p[1];
+    pts[2] = p[2];
+    return pts;
+  }
+
 }