for (int i = 0; i < sequences.size(); i++)
{
- if (getSequenceAt(i).getLength() > maxLength)
- {
- maxLength = getSequenceAt(i).getLength();
- }
+ maxLength = Math.max(maxLength, getSequenceAt(i).getLength());
}
-
return maxLength;
}
- /*
- @Override
- public int getWidth()
- {
- final Wrapper temp = new Wrapper();
-
- forEachSequence(new Consumer<SequenceI>()
- {
- @Override
- public void accept(SequenceI s)
- {
- if (s.getLength() > temp.inner)
- {
- temp.inner = s.getLength();
- }
- }
- }, 0, sequences.size() - 1);
-
- return temp.inner;
- }
-
- public static class Wrapper
- {
- public int inner;
- }*/
/**
* DOCUMENT ME!
MouseListener, MouseWheelListener, MouseMotionListener,
ActionListener, AdjustmentListener, Scrollable, ViewportListenerI
{
+ enum DragMode
+ {
+ Select, Resize, Undefined
+ };
+
String HELIX = MessageManager.getString("label.helix");
String SHEET = MessageManager.getString("label.sheet");
// Used For mouse Dragging and resizing graphs
int graphStretch = -1;
- int graphStretchY = -1;
+ int mouseDragLastX = -1;
- int min; // used by mouseDragged to see if user
+ int mouseDragLastY = -1;
- int max; // used by mouseDragged to see if user
+ DragMode dragMode = DragMode.Undefined;
boolean mouseDragging = false;
}
/**
- * DOCUMENT ME!
+ * Action on right mouse pressed on Mac is to show a pop-up menu for the
+ * annotation. Action on left mouse pressed is to find which annotation is
+ * pressed and mark the start of a column selection or graph resize operation.
*
* @param evt
- * DOCUMENT ME!
*/
@Override
public void mousePressed(MouseEvent evt)
{
return;
}
+ mouseDragLastX = evt.getX();
+ mouseDragLastY = evt.getY();
+ /*
+ * add visible annotation heights until we reach the y
+ * position, to find which annotation it is in
+ */
int height = 0;
activeRow = -1;
}
else if (aa[i].graph > 0)
{
- // Stretch Graph
+ /*
+ * we have clicked on a resizable graph annotation
+ */
graphStretch = i;
- graphStretchY = y;
}
-
break;
}
}
}
/**
- * DOCUMENT ME!
+ * Action on mouse up is to clear mouse drag data and call mouseReleased on
+ * ScalePanel, to deal with defining the selection group (if any) defined by
+ * the mouse drag
*
* @param evt
- * DOCUMENT ME!
*/
@Override
public void mouseReleased(MouseEvent evt)
{
graphStretch = -1;
- graphStretchY = -1;
+ mouseDragLastX = -1;
+ mouseDragLastY = -1;
mouseDragging = false;
+ dragMode = DragMode.Undefined;
ap.getScalePanel().mouseReleased(evt);
/*
@Override
public void mouseDragged(MouseEvent evt)
{
- if (graphStretch > -1)
+ /*
+ * todo: if dragMode is Undefined:
+ * - set to Select if dx > dy
+ * - set to Resize if dy > dx
+ * - do nothing if dx == dy
+ */
+ final int x = evt.getX();
+ final int y = evt.getY();
+ if (dragMode == DragMode.Undefined)
{
- av.getAlignment()
- .getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
- - evt.getY();
- if (av.getAlignment()
- .getAlignmentAnnotation()[graphStretch].graphHeight < 0)
+ int dx = Math.abs(x - mouseDragLastX);
+ int dy = Math.abs(y - mouseDragLastY);
+ if (graphStretch == -1 || dx > dy)
+ {
+ /*
+ * mostly horizontal drag, or not a graph annotation
+ */
+ dragMode = DragMode.Select;
+ }
+ else if (dy > dx)
{
- av.getAlignment()
- .getAlignmentAnnotation()[graphStretch].graphHeight = 0;
+ /*
+ * mostly vertical drag
+ */
+ dragMode = DragMode.Resize;
}
- graphStretchY = evt.getY();
- adjustPanelHeight();
- ap.paintAlignment(false, false);
}
- else
+
+ if (dragMode == DragMode.Undefined)
+ {
+ /*
+ * drag is diagonal - defer deciding whether to
+ * treat as up/down or left/right
+ */
+ return;
+ }
+
+ try
+ {
+ if (dragMode == DragMode.Resize)
+ {
+ /*
+ * resize graph annotation if mouse was dragged up or down
+ */
+ int deltaY = mouseDragLastY - evt.getY();
+ if (deltaY != 0)
+ {
+ AlignmentAnnotation graphAnnotation = av.getAlignment()
+ .getAlignmentAnnotation()[graphStretch];
+ int newHeight = Math.max(0, graphAnnotation.graphHeight + deltaY);
+ graphAnnotation.graphHeight = newHeight;
+ adjustPanelHeight();
+ ap.paintAlignment(false, false);
+ }
+ }
+ else
+ {
+ /*
+ * for mouse drag left or right, delegate to
+ * ScalePanel to adjust the column selection
+ */
+ ap.getScalePanel().mouseDragged(evt);
+ }
+ } finally
{
- ap.getScalePanel().mouseDragged(evt);
+ mouseDragLastX = x;
+ mouseDragLastY = y;
}
}
import jalview.util.MessageManager;
import jalview.util.Platform;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import java.awt.BorderLayout;
import java.awt.event.MouseEvent;
{
if (scrollThread != null)
{
- scrollThread.running = false;
+ scrollThread.stopScrolling();
}
}
{
if (scrollThread != null)
{
- scrollThread.running = false;
+ scrollThread.stopScrolling();
}
mouseDragging = false;
this.idCanvas = idCanvas;
}
- // this class allows scrolling off the bottom of the visible alignment
+ /**
+ * Performs scrolling of the visible alignment up or down, adding newly
+ * visible sequences to the current selection
+ */
class ScrollThread extends Thread
{
- boolean running = false;
+ private boolean running = false;
- boolean up = true;
+ private boolean up;
+ /**
+ * Constructor for a thread that scrolls either up or down
+ *
+ * @param up
+ */
public ScrollThread(boolean up)
{
this.up = up;
+ setName("IdPanel$ScrollThread$" + String.valueOf(up));
start();
}
+ /**
+ * Sets a flag to stop the scrolling
+ */
public void stopScrolling()
{
running = false;
}
+ /**
+ * Scrolls the alignment either up or down, one row at a time, adding newly
+ * visible sequences to the current selection. Speed is limited to a maximum
+ * of ten rows per second. The thread exits when the end of the alignment is
+ * reached or a flag is set to stop it.
+ */
@Override
public void run()
{
while (running)
{
- if (av.getRanges().scrollUp(up))
+ ViewportRanges ranges = IdPanel.this.av.getRanges();
+ if (ranges.scrollUp(up))
{
- // scroll was ok, so add new sequence to selection
- int seq = av.getRanges().getStartSeq();
-
- if (!up)
- {
- seq = av.getRanges().getEndSeq();
- }
-
- if (seq < lastid)
- {
- selectSeqs(lastid - 1, seq);
- }
- else if (seq > lastid)
- {
- selectSeqs(lastid + 1, seq);
- }
-
- lastid = seq;
+ int toSeq = up ? ranges.getStartSeq() : ranges.getEndSeq();
+ int fromSeq = toSeq < lastid ? lastid - 1 : lastid + 1;
+ IdPanel.this.selectSeqs(fromSeq, toSeq);
+
+ lastid = toSeq;
}
else
{
+ /*
+ * scroll did nothing - reached limit of visible alignment
+ */
running = false;
}
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
+import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
}
/**
- * DOCUMENT ME!
+ * Action on mouseUp is to set the limit of the current selection group (if
+ * there is one) and broadcast the selection
*
* @param evt
- * DOCUMENT ME!
*/
@Override
public void mouseReleased(MouseEvent evt)
{
mouseDragging = false;
+ ap.getSeqPanel().stopScrolling();
+ // todo res calculation should be a method on AlignViewport
int res = (evt.getX() / av.getCharWidth())
+ av.getRanges().getStartRes();
-
if (av.hasHiddenColumns())
{
res = av.getAlignment().getHiddenColumns()
.visibleToAbsoluteColumn(res);
}
-
- if (res >= av.getAlignment().getWidth())
- {
- res = av.getAlignment().getWidth() - 1;
- }
+ res = Math.min(res, av.getAlignment().getWidth() - 1);
if (!stretchingGroup)
{
{
if (mouseDragging)
{
- ap.getSeqPanel().scrollCanvas(null);
+ ap.getSeqPanel().stopScrolling();
}
}
+ /**
+ * Action on leaving the panel bounds with mouse drag in progress is to start
+ * scrolling the alignment in the direction of the mouse. To restrict
+ * scrolling to left-right (not up-down), the y-value of the mouse position is
+ * replaced with zero.
+ */
@Override
public void mouseExited(MouseEvent evt)
{
if (mouseDragging)
{
- ap.getSeqPanel().scrollCanvas(evt);
+ ap.getSeqPanel().startScrolling(new Point(evt.getX(), 0));
}
}
import jalview.util.MessageManager;
import jalview.util.Platform;
import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
import java.awt.BorderLayout;
import java.awt.Color;
return;
}
- if (!editingSeqs)
+ if (editingSeqs)
+ {
+ endEditing();
+ }
+ else
{
doMouseReleasedDefineMode(evt, didDrag);
- return;
}
-
- endEditing();
}
/**
}
mouseDragging = true;
- if ((scrollThread != null) && (scrollThread.isRunning()))
+ if (scrollThread != null)
{
- scrollThread.setEvent(evt);
+ scrollThread.setMousePosition(evt.getPoint());
}
}
}
/**
- * DOCUMENT ME!
+ * On reentering the panel, stops any scrolling that was started on dragging
+ * out of the panel
*
* @param e
- * DOCUMENT ME!
*/
@Override
public void mouseEntered(MouseEvent e)
{
oldSeq = 0;
}
-
- if ((scrollThread != null) && (scrollThread.isRunning()))
- {
- scrollThread.stopScrolling();
- scrollThread = null;
- }
+ stopScrolling();
}
/**
- * DOCUMENT ME!
+ * On leaving the panel, if the mouse is being dragged, starts a thread to
+ * scroll it until the mouse is released (in unwrapped mode only)
*
* @param e
- * DOCUMENT ME!
*/
@Override
public void mouseExited(MouseEvent e)
{
- if (av.getWrapAlignment())
- {
- return;
- }
-
- if (mouseDragging && scrollThread == null)
+ if (!av.getWrapAlignment() && mouseDragging && scrollThread == null)
{
scrollThread = new ScrollThread();
}
return;
}
- if (res >= av.getAlignment().getWidth())
- {
- res = av.getAlignment().getWidth() - 1;
- }
+ res = Math.min(res, av.getAlignment().getWidth()-1);
if (stretchGroup.getEndRes() == res)
{
mouseDragging = true;
- if ((scrollThread != null) && (scrollThread.isRunning()))
+ if (scrollThread != null)
{
- scrollThread.setEvent(evt);
+ scrollThread.setMousePosition(evt.getPoint());
}
}
- void scrollCanvas(MouseEvent evt)
+ /**
+ * Stops the scroll thread if it is running
+ */
+ void stopScrolling()
{
- if (evt == null)
+ if (scrollThread != null)
{
- if ((scrollThread != null) && (scrollThread.isRunning()))
- {
- scrollThread.stopScrolling();
- scrollThread = null;
- }
- mouseDragging = false;
+ scrollThread.stopScrolling();
+ scrollThread = null;
}
- else
- {
- if (scrollThread == null)
- {
- scrollThread = new ScrollThread();
- }
+ mouseDragging = false;
+ }
- mouseDragging = true;
- scrollThread.setEvent(evt);
+ /**
+ * Starts a thread to scroll the alignment, towards a given mouse position
+ * outside the panel bounds
+ *
+ * @param mousePos
+ */
+ void startScrolling(Point mousePos)
+ {
+ if (scrollThread == null)
+ {
+ scrollThread = new ScrollThread();
}
+ mouseDragging = true;
+ scrollThread.setMousePosition(mousePos);
}
- // this class allows scrolling off the bottom of the visible alignment
+ /**
+ * Performs scrolling of the visible alignment left, right, up or down
+ */
class ScrollThread extends Thread
{
- MouseEvent evt;
+ private Point mousePos;
private volatile boolean threadRunning = true;
+ /**
+ * Constructor
+ */
public ScrollThread()
{
+ setName("SeqPanel$ScrollThread");
start();
}
- public void setEvent(MouseEvent e)
+ /**
+ * Sets the position of the mouse that determines the direction of the
+ * scroll to perform
+ *
+ * @param p
+ */
+ public void setMousePosition(Point p)
{
- evt = e;
+ mousePos = p;
}
+ /**
+ * Sets a flag that will cause the thread to exit
+ */
public void stopScrolling()
{
threadRunning = false;
}
- public boolean isRunning()
- {
- return threadRunning;
- }
-
+ /**
+ * Scrolls the alignment left or right, and/or up or down, depending on the
+ * last notified mouse position, until the limit of the alignment is
+ * reached, or a flag is set to stop the scroll
+ */
@Override
public void run()
{
- while (threadRunning)
+ while (threadRunning && mouseDragging)
{
- if (evt != null)
+ if (mousePos != null)
{
- if (mouseDragging && (evt.getY() < 0)
- && (av.getRanges().getStartSeq() > 0))
+ boolean scrolled = false;
+ ViewportRanges ranges = SeqPanel.this.av.getRanges();
+
+ /*
+ * scroll up or down
+ */
+ if (mousePos.y < 0)
{
- av.getRanges().scrollUp(true);
+ // mouse is above this panel - try scroll up
+ scrolled = ranges.scrollUp(true);
}
-
- if (mouseDragging && (evt.getY() >= getHeight()) && (av
- .getAlignment().getHeight() > av.getRanges().getEndSeq()))
+ else if (mousePos.y >= getHeight())
{
- av.getRanges().scrollUp(false);
+ // mouse is below this panel - try scroll down
+ scrolled = ranges.scrollUp(false);
}
- if (mouseDragging && (evt.getX() < 0))
+ /*
+ * scroll left or right
+ */
+ if (mousePos.x < 0)
{
- av.getRanges().scrollRight(false);
+ scrolled |= ranges.scrollRight(false);
}
- else if (mouseDragging && (evt.getX() >= getWidth()))
+ else if (mousePos.x >= getWidth())
{
- av.getRanges().scrollRight(true);
+ scrolled |= ranges.scrollRight(true);
+ }
+ if (!scrolled)
+ {
+ /*
+ * we have reached the limit of the visible alignment - quit
+ */
+ threadRunning = false;
+ SeqPanel.this.ap.repaint();
}
}