import javax.swing.ToolTipManager;
import jalview.api.AlignViewportI;
+import jalview.bin.Cache;
import jalview.bin.Console;
import jalview.commands.EditCommand;
import jalview.commands.EditCommand.Action;
MousePos o = (MousePos) obj;
boolean b = (column == o.column && seqIndex == o.seqIndex
&& annotationIndex == o.annotationIndex);
- // System.out.println(obj + (b ? "= " : "!= ") + this);
+ // jalview.bin.Console.outPrintln(obj + (b ? "= " : "!= ") + this);
return b;
}
}
}
+ /**
+ * Rotation threshold for up/down trackpad/wheelmouse movement to register for
+ * an alignment in wrapped format. Up/down scrolling here results in a large
+ * jump so a larger threshold is appropriate, and reduces unintended up/down
+ * jumps when panning left/right. Should be at least 0.1 and less than 1.0
+ * since some platforms only send a value of 1.0.
+ */
+ private static double wrappedVerticalScrollRotationThreshold;
+
+ /**
+ * Property name if user needs to change rotation threshold
+ */
+ private static String WRAPPEDVERTICALSCROLLROTATIONTHRESHOLDPC = "WRAPPEDVERTICALSCROLLROTATIONTHRESHOLDPC";
+
+ /**
+ * Time threshold since last left/right trackpad/wheelmouse scroll for up/down
+ * trackpad/wheelmouse movement to register for an alignment in wrapped
+ * format. This reduces unintended up/down jumps when panning left/right. In
+ * ms.
+ */
+ private static int wrappedVerticalScrollChangeTimeThreshold;
+
+ /**
+ * Property name if user needs to change rotation threshold
+ */
+ private static String WRAPPEDVERTICALSCROLLCHANGETIMETHRESHOLD = "WRAPPEDVERTICALSCROLLCHANGETIMETHRESHOLD ";
+
+ static
+ {
+ wrappedVerticalScrollRotationThreshold = Cache.getDefault(
+ WRAPPEDVERTICALSCROLLROTATIONTHRESHOLDPC, 50) / 100.0;
+ wrappedVerticalScrollChangeTimeThreshold = Cache
+ .getDefault(WRAPPEDVERTICALSCROLLCHANGETIMETHRESHOLD, 200);
+ }
+
private static final int MAX_TOOLTIP_LENGTH = 300;
public SeqCanvas seqCanvas;
}
/**
+ * @param evt
+ * @return absolute column in alignment nearest to the mouse pointer
+ */
+ int findAlignmentColumn(MouseEvent evt)
+ {
+ return findNearestColumn(evt, true);
+ }
+
+ /**
* Returns the aligned sequence position (base 0) at the mouse position, or
* the closest visible one
* <p>
*/
int findColumn(MouseEvent evt)
{
+ return findNearestColumn(evt, false);
+ }
+
+ /**
+ * @param nearestColumn
+ * when false returns negative values for out of bound positions - -1
+ * for scale left/right, <-1 if far to right
+ * @return nearest absolute column to mouse pointer
+ */
+ private int findNearestColumn(MouseEvent evt, boolean nearestColumn)
+ {
int res = 0;
int x = evt.getX();
if (x < 0)
{
// mouse is over left scale
- return -1;
+ if (!nearestColumn)
+ {
+ return -1;
+ }
+ else
+ {
+ x = 0;
+ }
}
int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
}
if (x >= cwidth * charWidth)
{
- // mouse is over right scale
- return -1;
+ if (!nearestColumn)
+ {
+ // mouse is over right scale
+ return -1;
+ }
+ else
+ {
+ x = cwidth * charWidth - 1;
+ }
}
wrappedBlock = y / cHeight;
* rather than right-hand gutter
*/
x = Math.min(x, seqCanvas.getX() + seqCanvas.getWidth());
+ if (nearestColumn)
+ {
+ x = Math.max(x, 0);
+ }
+
res = (x / charWidth) + startRes;
res = Math.min(res, av.getRanges().getEndRes());
+
}
if (av.hasHiddenColumns())
if (lastMessage == null || !lastMessage.equals(tmp))
{
- // System.err.println("mouseOver Sequence: "+tmp);
+ // jalview.bin.Console.errPrintln("mouseOver Sequence: "+tmp);
ssm.mouseOverSequence(sequence, index, pos, av);
}
lastMessage = tmp;
@Override
public void updateColours(SequenceI seq, int index)
{
- System.out.println("update the seqPanel colours");
+ jalview.bin.Console.outPrintln("update the seqPanel colours");
// repaint();
}
AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
String tooltip = AnnotationPanel.buildToolTip(anns[rowIndex], column,
- anns, 0, av);
+ anns, 0, av, ap);
if (tooltip == null ? tooltip != lastTooltip
: !tooltip.equals(lastTooltip))
{
}
}
+ /**
+ * recorded time of last left/right mousewheel/trackpad scroll in wrapped mode
+ */
+ private long lastLeftRightWrappedScrollTime = 0;
+
+ /**
+ * Responds to a mouse wheel movement by scrolling the alignment
+ * <ul>
+ * <li>left or right, if the shift key is down, else up or down</li>
+ * <li>right (or down) if the reported mouse movement is positive</li>
+ * <li>left (or up) if the reported mouse movement is negative</li>
+ * </ul>
+ * Note that this method may also be fired by scrolling with a gesture on a
+ * trackpad.
+ */
@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
e.consume();
- double wheelRotation = e.getPreciseWheelRotation();
+ double preciseWheelRotation = e.getPreciseWheelRotation();
+ int wheelRotation = e.getWheelRotation();
+ if (wheelRotation == 0 && Math.abs(preciseWheelRotation) > 0.1)
+ {
+ // this is one of -1, 0 ,+1 for <0, ==0, >0
+ wheelRotation = (int) Math.signum(preciseWheelRotation);
+ }
+
+ /*
+ * scroll more for large (fast) mouse movements
+ */
+ int size = Math.abs(wheelRotation);
+
if (wheelRotation > 0)
{
if (e.isShiftDown())
{
- av.getRanges().scrollRight(true);
-
+ /*
+ * scroll right
+ * stop trying to scroll right when limit is reached (saves
+ * expensive calls to Alignment.getWidth())
+ */
+ if (!ap.isScrolledFullyRight())
+ {
+ av.getRanges().scrollRight(true, size);
+ }
+ this.lastLeftRightWrappedScrollTime = System.currentTimeMillis();
}
else
{
- av.getRanges().scrollUp(false);
+ /*
+ * scroll down
+ */
+ // apply a more definite threshold for up and down scrolling in wrap
+ // format (either not a wrapped alignment, or BOTH time since last
+ // left/right scroll is above threshold AND trackpad/mousewheel movement
+ // is above threshold)
+ if (!ap.getAlignViewport().getWrapAlignment() || (Math.abs(
+ preciseWheelRotation) > wrappedVerticalScrollRotationThreshold
+ && System.currentTimeMillis()
+ - lastLeftRightWrappedScrollTime > wrappedVerticalScrollChangeTimeThreshold))
+ {
+ while (size-- > 0)
+ {
+ if (!av.getRanges().scrollUp(false))
+ {
+ break;
+ }
+ }
+ }
}
}
else if (wheelRotation < 0)
{
if (e.isShiftDown())
{
- av.getRanges().scrollRight(false);
+ /*
+ * scroll left if not already at start
+ */
+ if (av.getRanges().getStartRes() > 0)
+ {
+ av.getRanges().scrollRight(false, size);
+ }
+ this.lastLeftRightWrappedScrollTime = System.currentTimeMillis();
}
else
{
- av.getRanges().scrollUp(true);
+ /*
+ * scroll up
+ */
+ // apply a more definite threshold for up and down scrolling in wrap
+ // format (either not a wrapped alignment, or BOTH time since last
+ // left/right scroll is above threshold AND trackpad/mousewheel movement
+ // is above threshold)
+ if (!ap.getAlignViewport().getWrapAlignment() || (Math.abs(
+ preciseWheelRotation) > wrappedVerticalScrollRotationThreshold
+ && System.currentTimeMillis()
+ - lastLeftRightWrappedScrollTime > wrappedVerticalScrollChangeTimeThreshold))
+ {
+ while (size-- > 0)
+ {
+ if (!av.getRanges().scrollUp(true))
+ {
+ break;
+ }
+ }
+ }
}
}
if (copycolsel && av.hasHiddenColumns()
&& (av.getAlignment().getHiddenColumns() == null))
{
- System.err.println("Bad things");
+ jalview.bin.Console.errPrintln("Bad things");
}
if (repaint) // always true!
{
* if hidden column selection has changed
*/
ap.paintAlignment(hiddenChanged, hiddenChanged);
+ // propagate any selection changes
+ PaintRefresher.Refresh(ap, av.getSequenceSetId());
return true;
}