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;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
+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;
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;
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);
*/
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();
}
if (!stretchingGroup)
{
- ap.paintAlignment(false);
-
+ if (evt.isPopupTrigger()) // Windows: mouseReleased
+ {
+ rightMouseButtonPressed(evt, res);
+ }
+ else
+ {
+ ap.paintAlignment(false);
+ }
return;
}
@Override
public void mouseMoved(MouseEvent evt)
{
+ this.setToolTipText(null);
+ reveal = null;
if (!av.hasHiddenColumns())
{
return;
res = av.getColumnSelection().adjustForHiddenColumns(res);
- reveal = null;
if (av.getColumnSelection().getHiddenColumns() != null)
{
for (int[] region : av.getColumnSelection().getHiddenColumns())
.getString("label.reveal_hidden_columns"));
break;
}
- else
- {
- this.setToolTipText(null);
- }
}
}
repaint();
}
- int[] reveal;
-
/**
* DOCUMENT ME!
*
ColumnSelection cs = av.getColumnSelection();
int avCharWidth = av.getCharWidth(), avCharHeight = av.getCharHeight();
- int s;
if (cs != null)
{
gg.setColor(new Color(220, 0, 0));
}
}
}
- // Draw the scale numbers
- gg.setColor(Color.black);
- int scalestartx = (startx / 10) * 10;
int widthx = 1 + endx - startx;
FontMetrics fm = gg.getFontMetrics(av.getFont());
- int y = avCharHeight - fm.getDescent();
-
- if ((scalestartx % 10) == 0)
- {
- scalestartx += 5;
- }
-
- String string;
- boolean isrgap = false;
- char rc;
- int maxX = 0, refN, iadj;
- SequenceI refSeq = av.getAlignment().getSeqrep();
- int refSp = -1, refEp = -1;
- if (refSeq != null)
- {
- refSp = refSeq.findIndex(refSeq.getStart()) - 1;
- refEp = refSeq.findIndex(refSeq.getEnd()) - 1;
- }
- // todo: add a 'reference origin column' to set column number relative to
- for (int i = scalestartx; i < endx; i += 5)
- {
- if ((i % 10) == 0)
- {
- iadj = av.getColumnSelection().adjustForHiddenColumns(i) - 1;
- if (refSeq == null)
- {
- string = String.valueOf(iadj + 1);
- }
- else
- {
- refN = refSeq.findPosition(iadj);
- // TODO show bounds if position is a gap
- // - ie L--R -> "1L|2R" for
- // marker
- if (iadj < refSp)
- {
- string = String.valueOf(iadj - refSp);
- }
- else if (iadj > refEp)
- {
- string = "+" + String.valueOf(iadj - refEp);
- }
- else
- {
- string = String.valueOf(refN) + refSeq.getCharAt(iadj);
- }
- }
- if ((i - startx - 1) * avCharWidth > maxX)
- {
- gg.drawString(string, (i - startx - 1) * avCharWidth, y);
- maxX = (i - startx + 1) * avCharWidth + fm.stringWidth(string);
- }
-
- gg.drawLine(((i - startx - 1) * avCharWidth) + (avCharWidth / 2),
- y + 2,
- ((i - startx - 1) * avCharWidth) + (avCharWidth / 2), y
- + (fm.getDescent() * 2));
- }
- else
- {
- gg.drawLine(((i - startx - 1) * avCharWidth) + (avCharWidth / 2), y
- + fm.getDescent(), ((i - startx - 1) * avCharWidth)
- + (avCharWidth / 2), y + (fm.getDescent() * 2));
- }
- }
-
+ int y = avCharHeight;
+ int yOf = fm.getDescent();
+ y -= yOf;
if (av.hasHiddenColumns())
{
+ // draw any hidden column markers
gg.setColor(Color.blue);
int res;
if (av.getShowHiddenMarkers()
continue;
}
- gg.fillPolygon(new int[] { res * avCharWidth - avCharHeight / 4,
- res * avCharWidth + avCharHeight / 4, res * avCharWidth },
- new int[] { y - avCharHeight / 2, y - avCharHeight / 2,
- y + 8 }, 3);
-
+ gg.fillPolygon(new int[] {
+ -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);
+
+ int maxX = 0;
+ List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, startx,
+ endx);
- if (reveal != null && reveal[0] > startx && reveal[0] < endx)
+ for (ScaleMark mark : marks)
+ {
+ boolean major = mark.major;
+ int mpos = mark.column; // (i - startx - 1)
+ String mstring = mark.text;
+ if (mstring != null)
{
- gg.drawString(MessageManager.getString("label.reveal_columns"),
- reveal[0] * avCharWidth, 0);
+ if (mpos * avCharWidth > maxX)
+ {
+ gg.drawString(mstring, mpos * avCharWidth, y);
+ maxX = (mpos + 2) * avCharWidth + fm.stringWidth(mstring);
+ }
+ }
+ if (major)
+ {
+ gg.drawLine((mpos * avCharWidth) + (avCharWidth / 2), y + 2,
+ (mpos * avCharWidth) + (avCharWidth / 2), y + (yOf * 2));
+ }
+ else
+ {
+ gg.drawLine((mpos * avCharWidth) + (avCharWidth / 2), y + yOf,
+ (mpos * avCharWidth) + (avCharWidth / 2), y + (yOf * 2));
}
}
-
}
+
}