JAL-2089 Merge branch releases/Release_2_10_Branch to master
[jalview.git] / src / jalview / gui / ScalePanel.java
index 8a3138d..3842b99 100755 (executable)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
+ * Copyright (C) 2015 The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
@@ -23,7 +23,10 @@ package jalview.gui;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.ScaleRenderer;
+import jalview.renderer.ScaleRenderer.ScaleMark;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 
 import java.awt.Color;
 import java.awt.FontMetrics;
@@ -35,26 +38,23 @@ import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.swing.JMenuItem;
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
+import javax.swing.SwingUtilities;
 import javax.swing.ToolTipManager;
 
 /**
- * DOCUMENT ME!
- * 
- * @author $author$
- * @version $Revision$
+ * The panel containing the sequence ruler (when not in wrapped mode), and
+ * supports a range of mouse operations to select, hide or reveal columns.
  */
 public class ScalePanel extends JPanel implements MouseMotionListener,
         MouseListener
 {
   protected int offy = 4;
 
-  /** DOCUMENT ME!! */
   public int width;
 
   protected AlignViewport av;
@@ -63,13 +63,26 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
 
   boolean stretchingGroup = false;
 
-  int min; // used by mouseDragged to see if user
+  /*
+   * min, max hold the extent of a mouse drag action
+   */
+  int min;
 
-  int max; // used by mouseDragged to see if user
+  int max;
 
   boolean mouseDragging = false;
 
-  // wants to delete columns
+  /*
+   * holds a hidden column range when the mouse is over an adjacent column
+   */
+  int[] reveal;
+
+  /**
+   * Constructor
+   * 
+   * @param av
+   * @param ap
+   */
   public ScalePanel(AlignViewport av, AlignmentPanel ap)
   {
     this.av = av;
@@ -108,10 +121,19 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
     min = res;
     max = res;
 
-    if (evt.isPopupTrigger())
+    if (evt.isPopupTrigger()) // Mac: mousePressed
     {
       rightMouseButtonPressed(evt, res);
     }
+    else if (SwingUtilities.isRightMouseButton(evt) && !Platform.isAMac())
+    {
+      /*
+       * defer right-mouse click handling to mouse up on Windows
+       * (where isPopupTrigger() will answer true)
+       * but accept Cmd-click on Mac which passes isRightMouseButton
+       */
+      return;
+    }
     else
     {
       leftMouseButtonPressed(evt, res);
@@ -210,7 +232,12 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
    */
   protected void leftMouseButtonPressed(MouseEvent evt, final int res)
   {
-    if (!evt.isControlDown() && !evt.isShiftDown())
+    /*
+     * Ctrl-click/Cmd-click adds to the selection
+     * Shift-click extends the selection
+     */
+    // TODO Problem: right-click on Windows not reported until mouseReleased?!?
+    if (!Platform.isControlDown(evt) && !evt.isShiftDown())
     {
       av.getColumnSelection().clear();
     }
@@ -269,8 +296,14 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
 
     if (!stretchingGroup)
     {
-      ap.paintAlignment(false);
-
+      if (evt.isPopupTrigger()) // Windows: mouseReleased
+      {
+        rightMouseButtonPressed(evt, res);
+      }
+      else
+      {
+        ap.paintAlignment(false);
+      }
       return;
     }
 
@@ -394,6 +427,8 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
   @Override
   public void mouseMoved(MouseEvent evt)
   {
+    this.setToolTipText(null);
+    reveal = null;
     if (!av.hasHiddenColumns())
     {
       return;
@@ -403,7 +438,6 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
 
     res = av.getColumnSelection().adjustForHiddenColumns(res);
 
-    reveal = null;
     if (av.getColumnSelection().getHiddenColumns() != null)
     {
       for (int[] region : av.getColumnSelection().getHiddenColumns())
@@ -416,17 +450,11 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
                   .getString("label.reveal_hidden_columns"));
           break;
         }
-        else
-        {
-          this.setToolTipText(null);
-        }
       }
     }
     repaint();
   }
 
-  int[] reveal;
-
   /**
    * DOCUMENT ME!
    * 
@@ -461,7 +489,6 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
     ColumnSelection cs = av.getColumnSelection();
     int avCharWidth = av.getCharWidth(), avCharHeight = av.getCharHeight();
 
-    int s;
     if (cs != null)
     {
       gg.setColor(new Color(220, 0, 0));
@@ -494,7 +521,8 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
     int widthx = 1 + endx - startx;
 
     FontMetrics fm = gg.getFontMetrics(av.getFont());
-    int y = avCharHeight, yOf = fm.getDescent();
+    int y = avCharHeight;
+    int yOf = fm.getDescent();
     y -= yOf;
     if (av.hasHiddenColumns())
     {
@@ -519,20 +547,21 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
               -1 + res * avCharWidth - avCharHeight / 4,
               -1 + res * avCharWidth + avCharHeight / 4,
               -1 + res * avCharWidth }, new int[] { y, y, y + 2 * yOf }, 3);
-
         }
       }
     }
     // Draw the scale numbers
     gg.setColor(Color.black);
 
-    List<Object[]> marks = calculateMarks(startx, endx);
     int maxX = 0;
-    for (Object[] mark : marks)
+    List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, startx,
+            endx);
+
+    for (ScaleMark mark : marks)
     {
-      boolean major = Boolean.valueOf((Boolean) mark[0]);
-      int mpos = ((Integer) mark[1]).intValue(); // (i - startx - 1)
-      String mstring = (String) mark[2];
+      boolean major = mark.major;
+      int mpos = mark.column; // (i - startx - 1)
+      String mstring = mark.text;
       if (mstring != null)
       {
         if (mpos * avCharWidth > maxX)
@@ -552,100 +581,6 @@ public class ScalePanel extends JPanel implements MouseMotionListener,
                 (mpos * avCharWidth) + (avCharWidth / 2), y + (yOf * 2));
       }
     }
-    if (av.hasHiddenColumns())
-    {
-      if (reveal != null && reveal[0] > startx && reveal[0] < endx)
-      {
-        gg.drawString(MessageManager.getString("label.reveal_columns"),
-                reveal[0] * avCharWidth, 0);
-      }
-    }
-
   }
 
-  /**
-   * calculate positions markers on the alignment ruler
-   * 
-   * @return List { Object { .. } } Boolean: true/false for major/minor mark,
-   *         Integer: marker position in alignment column coords, String: null
-   *         or a String to be rendered at the position.
-   */
-  public List<Object[]> calculateMarks(int startx, int endx)
-  {
-    new ArrayList<Object[]>();
-
-    int scalestartx = (startx / 10) * 10;
-
-    SequenceI refSeq = av.getAlignment().getSeqrep();
-    int refSp = 0, refEp = -1, refStart = 0, refEnd = -1, refStartI = 0, refEndI = -1;
-    if (refSeq != null)
-    {
-      // find bounds and set origin appopriately
-      // locate first visible position for this sequence
-      int[] refbounds = av.getColumnSelection()
-              .locateVisibleBoundsOfSequence(refSeq);
-
-      refSp = refbounds[0];
-      refEp = refbounds[1];
-      refStart = refbounds[2];
-      refEnd = refbounds[3];
-      refStartI = refbounds[4];
-      refEndI = refbounds[5];
-      scalestartx = refSp + ((scalestartx - refSp) / 10) * 10;
-    }
-
-
-    if (refSeq == null && scalestartx % 10 == 0)
-    {
-      scalestartx += 5;
-    }
-    List<Object[]> marks = new ArrayList<Object[]>();
-    String string;
-    int maxX = 0, refN, iadj;
-    // todo: add a 'reference origin column' to set column number relative to
-    for (int i = scalestartx; i < endx; i += 5)
-    {
-      Object[] amark = new Object[3];
-      if (((i - refSp) % 10) == 0)
-      {
-        if (refSeq == null)
-        {
-          iadj = av.getColumnSelection().adjustForHiddenColumns(i - 1) + 1;
-          string = String.valueOf(iadj);
-        }
-        else
-        {
-          iadj = av.getColumnSelection().adjustForHiddenColumns(i - 1);
-          refN = refSeq.findPosition(iadj);
-          // TODO show bounds if position is a gap
-          // - ie L--R -> "1L|2R" for
-          // marker
-          if (iadj < refStartI)
-          {
-            string = String.valueOf(iadj - refStartI);
-          }
-          else if (iadj > refEndI)
-          {
-            string = "+" + String.valueOf(iadj - refEndI);
-          }
-          else
-          {
-            string = String.valueOf(refN) + refSeq.getCharAt(iadj);
-          }
-        }
-        amark[0] = Boolean.TRUE;
-        amark[1] = Integer.valueOf(i - startx - 1);
-        amark[2] = string;
-
-      }
-      else
-      {
-        amark[0] = Boolean.FALSE;
-        amark[1] = Integer.valueOf(i - startx - 1);
-        amark[2] = null;
-      }
-      marks.add(amark);
-    }
-    return marks;
-  }
 }