* @author $author$
* @version $Revision: 1.130 $
*/
-public class SeqPanel extends JPanel implements MouseListener,
- MouseMotionListener, MouseWheelListener, SequenceListener,
- SelectionListener
+public class SeqPanel extends JPanel
+ implements MouseListener, MouseMotionListener, MouseWheelListener,
+ SequenceListener, SelectionListener
{
/** DOCUMENT ME!! */
+ hgap + seqCanvas.getAnnotationHeight();
int y = evt.getY();
- y -= hgap;
- x = Math.max(0, x - seqCanvas.labelWidthWest);
+ y = Math.max(0, y - hgap);
+ x = Math.max(0, x - seqCanvas.getLabelWidthWest());
int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
if (cwidth < 1)
wrappedBlock += startRes / cwidth;
// allow for wrapped view scrolled right (possible from Overview)
int startOffset = startRes % cwidth;
- res = wrappedBlock * cwidth
- + Math.min(cwidth - 1, startOffset + x / av.getCharWidth());
+ res = wrappedBlock * cwidth + startOffset
+ + +Math.min(cwidth - 1, x / av.getCharWidth());
}
else
{
if (av.hasHiddenColumns())
{
res = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(res);
+ .visibleToAbsoluteColumn(res);
}
return res;
y -= hgap;
- seq = Math.min((y % cHeight) / av.getCharHeight(), av.getAlignment()
- .getHeight() - 1);
+ seq = Math.min((y % cHeight) / av.getCharHeight(),
+ av.getAlignment().getHeight() - 1);
}
else
{
- seq = Math.min((y / av.getCharHeight())
- + av.getRanges().getStartSeq(),
- av
- .getAlignment().getHeight() - 1);
+ seq = Math.min(
+ (y / av.getCharHeight()) + av.getRanges().getStartSeq(),
+ av.getAlignment().getHeight() - 1);
}
return seq;
if (editCommand != null && editCommand.getSize() > 0)
{
ap.alignFrame.addHistoryItem(editCommand);
- av.firePropertyChange("alignment", null, av.getAlignment()
- .getSequences());
+ av.firePropertyChange("alignment", null,
+ av.getAlignment().getSequences());
}
} finally
{
void setCursorRow()
{
seqCanvas.cursorY = getKeyboardNo1() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void setCursorColumn()
{
seqCanvas.cursorX = getKeyboardNo1() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void setCursorRowAndColumn()
{
seqCanvas.cursorX = getKeyboardNo1() - 1;
seqCanvas.cursorY = getKeyboardNo2() - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
}
SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
seqCanvas.cursorX = sequence.findIndex(getKeyboardNo1()) - 1;
- scrollToVisible();
+ scrollToVisible(true);
}
void moveCursor(int dx, int dy)
HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- if (av.hasHiddenColumns()
- && !hidden.isVisible(seqCanvas.cursorX))
+ if (av.hasHiddenColumns() && !hidden.isVisible(seqCanvas.cursorX))
{
int original = seqCanvas.cursorX - dx;
int maxWidth = av.getAlignment().getWidth();
- while (!hidden.isVisible(seqCanvas.cursorX)
- && seqCanvas.cursorX < maxWidth && seqCanvas.cursorX > 0)
+ if (!hidden.isVisible(seqCanvas.cursorX))
{
- seqCanvas.cursorX += dx;
+ int visx = hidden.absoluteToVisibleColumn(seqCanvas.cursorX - dx);
+ int[] region = hidden.getRegionWithEdgeAtRes(visx);
+
+ if (region != null) // just in case
+ {
+ if (dx == 1)
+ {
+ // moving right
+ seqCanvas.cursorX = region[1] + 1;
+ }
+ else if (dx == -1)
+ {
+ // moving left
+ seqCanvas.cursorX = region[0] - 1;
+ }
+ }
+ seqCanvas.cursorX = (seqCanvas.cursorX < 0) ? 0 : seqCanvas.cursorX;
}
if (seqCanvas.cursorX >= maxWidth
}
}
- scrollToVisible();
+ scrollToVisible(false);
}
- void scrollToVisible()
+ /**
+ * Scroll to make the cursor visible in the viewport.
+ *
+ * @param jump
+ * just jump to the location rather than scrolling
+ */
+ void scrollToVisible(boolean jump)
{
if (seqCanvas.cursorX < 0)
{
}
endEditing();
- if (av.getWrapAlignment())
+
+ boolean repaintNeeded = true;
+ if (jump)
{
- av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
+ // only need to repaint if the viewport did not move, as otherwise it will
+ // get a repaint
+ repaintNeeded = !av.getRanges().setViewportLocation(seqCanvas.cursorX,
+ seqCanvas.cursorY);
}
else
{
- av.getRanges().scrollToVisible(seqCanvas.cursorX, seqCanvas.cursorY);
+ if (av.getWrapAlignment())
+ {
+ // scrollToWrappedVisible expects x-value to have hidden cols subtracted
+ int x = av.getAlignment().getHiddenColumns()
+ .absoluteToVisibleColumn(seqCanvas.cursorX);
+ av.getRanges().scrollToWrappedVisible(x);
+ }
+ else
+ {
+ av.getRanges().scrollToVisible(seqCanvas.cursorX,
+ seqCanvas.cursorY);
+ }
}
- setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
+
+ if (av.getAlignment().getHiddenColumns().isVisible(seqCanvas.cursorX))
+ {
+ setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
seqCanvas.cursorX, seqCanvas.cursorY);
+ }
- seqCanvas.repaint();
+ if (repaintNeeded)
+ {
+ seqCanvas.repaint();
+ }
}
+
void setSelectionAreaAtCursor(boolean topLeft)
{
SequenceI sequence = av.getAlignment().getSequenceAt(seqCanvas.cursorY);
av.setSelectionGroup(sg);
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
}
/**
- * DOCUMENT ME!
+ * Action on mouse movement is to update the status bar to show the current
+ * sequence position, and (if features are shown) to show any features at the
+ * position in a tooltip. Does nothing if the mouse move does not change
+ * residue position.
*
* @param evt
- * DOCUMENT ME!
*/
@Override
public void mouseMoved(MouseEvent evt)
}
final int column = findColumn(evt);
- int seq = findSeq(evt);
+ final int seq = findSeq(evt);
+
if (column < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
{
lastMouseSeq = -1;
Point p = lastp;
if (!event.isShiftDown() || p == null)
{
- p = (tooltipText != null && tooltipText.length() > 6) ? new Point(
- event.getX() + wdth, event.getY() - 20) : null;
+ p = (tooltipText != null && tooltipText.length() > 6)
+ ? new Point(event.getX() + wdth, event.getY() - 20)
+ : null;
}
/*
* TODO: try to modify position region is not obcured by tooltip
/**
* set when the current UI interaction has resulted in a change that requires
- * overview shading to be recalculated. this could be changed to something
- * more expressive that indicates what actually has changed, so selective
- * redraws can be applied
+ * shading in overviews and structures to be recalculated. this could be
+ * changed to a something more expressive that indicates what actually has
+ * changed, so selective redraws can be applied (ie. only structures, only
+ * overview, etc)
*/
- private boolean needOverviewUpdate = false; // TODO: refactor to avcontroller
+ private boolean updateOverviewAndStructs = false; // TODO: refactor to avcontroller
/**
* set if av.getSelectionGroup() refers to a group that is defined on the
}
else
{
- residue = "X".equalsIgnoreCase(displayChar) ? "X" : ("*"
- .equals(displayChar) ? "STOP"
- : ResidueProperties.aa2Triplet.get(displayChar));
+ residue = "X".equalsIgnoreCase(displayChar) ? "X"
+ : ("*".equals(displayChar) ? "STOP"
+ : ResidueProperties.aa2Triplet.get(displayChar));
}
text.append(" ").append(nucleotide ? "Nucleotide" : "Residue")
.append(": ").append(residue == null ? displayChar : residue);
int oldWidth = av.getCharWidth();
// Which is bigger, left-right or up-down?
- if (Math.abs(evt.getY() - lastMousePress.getY()) > Math.abs(evt
- .getX() - lastMousePress.getX()))
+ if (Math.abs(evt.getY() - lastMousePress.getY()) > Math
+ .abs(evt.getX() - lastMousePress.getX()))
{
/*
* on drag up or down, decrement or increment font size
}
if (newWidth > 0)
{
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
if (copyChanges)
{
/*
}
mouseDragging = true;
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
scrollThread.setEvent(evt);
}
}
if (editCommand == null)
{
- editCommand = new EditCommand(MessageManager.formatMessage(
- "label.edit_params", new String[] { label }));
+ editCommand = new EditCommand(MessageManager
+ .formatMessage("label.edit_params", new String[]
+ { label }));
}
}
ap.alignFrame.statusBar.setText(message.toString());
// Are we editing within a selection group?
- if (groupEditing
- || (sg != null && sg.getSequences(av.getHiddenRepSequences())
- .contains(seq)))
+ if (groupEditing || (sg != null
+ && sg.getSequences(av.getHiddenRepSequences()).contains(seq)))
{
fixedColumns = true;
{
fixedColumns = true;
int y1 = av.getAlignment().getHiddenColumns()
- .getHiddenBoundaryLeft(startres);
+ .getNextHiddenBoundary(true, startres);
int y2 = av.getAlignment().getHiddenColumns()
- .getHiddenBoundaryRight(startres);
+ .getNextHiddenBoundary(false, startres);
if ((insertGap && startres > y1 && lastres < y1)
|| (!insertGap && startres < y2 && lastres > y2))
// Find the next gap before the end
// of the visible region boundary
boolean blank = false;
- for (fixedRight = fixedRight; fixedRight > lastres; fixedRight--)
+ for (; fixedRight > lastres; fixedRight--)
{
blank = true;
if (sg.getSize() == av.getAlignment().getHeight())
{
if ((av.hasHiddenColumns() && startres < av.getAlignment()
- .getHiddenColumns().getHiddenBoundaryRight(startres)))
+ .getHiddenColumns()
+ .getNextHiddenBoundary(false, startres)))
{
endEditing();
return;
}
else
{
- appendEdit(Action.INSERT_GAP, groupSeqs, startres, startres
- - lastres);
+ appendEdit(Action.INSERT_GAP, groupSeqs, startres,
+ startres - lastres);
}
}
else
}
else
{
- appendEdit(Action.DELETE_GAP, groupSeqs, startres, lastres
- - startres);
+ appendEdit(Action.DELETE_GAP, groupSeqs, startres,
+ lastres - startres);
}
}
oldSeq = 0;
}
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
- scrollThread.running = false;
+ scrollThread.stopScrolling();
scrollThread = null;
}
}
return;
}
- if (mouseDragging)
+ if (mouseDragging && scrollThread == null)
{
scrollThread = new ScrollThread();
}
public void mouseWheelMoved(MouseWheelEvent e)
{
e.consume();
- if (e.getWheelRotation() > 0)
+ double wheelRotation = e.getPreciseWheelRotation();
+ if (wheelRotation > 0)
{
if (e.isShiftDown())
{
av.getRanges().scrollRight(true);
}
- else if (!av.getWrapAlignment())
+ else
{
av.getRanges().scrollUp(false);
}
}
- else
+ else if (wheelRotation < 0)
{
if (e.isShiftDown())
{
av.getRanges().scrollRight(false);
}
- else if (!av.getWrapAlignment())
+ else
{
av.getRanges().scrollUp(true);
}
}
- // TODO Update tooltip for new position.
+
+ /*
+ * update status bar and tooltip for new position
+ * (need to synthesize a mouse movement to refresh tooltip)
+ */
+ mouseMoved(e);
+ ToolTipManager.sharedInstance().mouseMoved(e);
}
/**
final int res = findColumn(evt);
final int seq = findSeq(evt);
oldSeq = seq;
- needOverviewUpdate = false;
+ updateOverviewAndStructs = false;
startWrapBlock = wrappedBlock;
if (av.getWrapAlignment() && seq > av.getAlignment().getHeight())
{
- JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
- .getString("label.cannot_edit_annotations_in_wrapped_view"),
+ JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+ MessageManager.getString(
+ "label.cannot_edit_annotations_in_wrapped_view"),
MessageManager.getString("label.wrapped_view_no_edit"),
JvOptionPane.WARNING_MESSAGE);
return;
if (stretchGroup == null)
{
- // Only if left mouse button do we want to change group sizes
+ createStretchGroup(res, sequence);
+ }
+
+ if (stretchGroup != null)
+ {
+ stretchGroup.addPropertyChangeListener(seqCanvas);
+ }
- // define a new group here
- SequenceGroup sg = new SequenceGroup();
- sg.setStartRes(res);
- sg.setEndRes(res);
- sg.addSequence(sequence, false);
- av.setSelectionGroup(sg);
- stretchGroup = sg;
+ seqCanvas.repaint();
+ }
- if (av.getConservationSelected())
- {
- SliderPanel.setConservationSlider(ap, av.getResidueShading(),
- ap.getViewName());
- }
+ private void createStretchGroup(int res, SequenceI sequence)
+ {
+ // Only if left mouse button do we want to change group sizes
+ // define a new group here
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(res);
+ sg.setEndRes(res);
+ sg.addSequence(sequence, false);
+ av.setSelectionGroup(sg);
+ stretchGroup = sg;
- if (av.getAbovePIDThreshold())
- {
- SliderPanel.setPIDSliderSource(ap, av.getResidueShading(),
- ap.getViewName());
- }
- // TODO: stretchGroup will always be not null. Is this a merge error ?
- if ((stretchGroup != null) && (stretchGroup.getEndRes() == res))
- {
- // Edit end res position of selected group
- changeEndRes = true;
- }
- else if ((stretchGroup != null)
- && (stretchGroup.getStartRes() == res))
- {
- // Edit end res position of selected group
- changeStartRes = true;
- }
- stretchGroup.getWidth();
+ if (av.getConservationSelected())
+ {
+ SliderPanel.setConservationSlider(ap, av.getResidueShading(),
+ ap.getViewName());
}
- seqCanvas.repaint();
+ if (av.getAbovePIDThreshold())
+ {
+ SliderPanel.setPIDSliderSource(ap, av.getResidueShading(),
+ ap.getViewName());
+ }
+ // TODO: stretchGroup will always be not null. Is this a merge error ?
+ // or is there a threading issue here?
+ if ((stretchGroup != null) && (stretchGroup.getEndRes() == res))
+ {
+ // Edit end res position of selected group
+ changeEndRes = true;
+ }
+ else if ((stretchGroup != null) && (stretchGroup.getStartRes() == res))
+ {
+ // Edit end res position of selected group
+ changeStartRes = true;
+ }
+ stretchGroup.getWidth();
+
}
/**
{
return;
}
+
+ stretchGroup.removePropertyChangeListener(seqCanvas);
+
// always do this - annotation has own state
// but defer colourscheme update until hidden sequences are passed in
boolean vischange = stretchGroup.recalcConservation(true);
- needOverviewUpdate |= vischange && av.isSelectionDefinedGroup()
+ updateOverviewAndStructs |= vischange && av.isSelectionDefinedGroup()
&& afterDrag;
if (stretchGroup.cs != null)
{
stretchGroup.cs.alignmentChanged(stretchGroup,
av.getHiddenRepSequences());
- ResidueShaderI groupColourScheme = stretchGroup.getGroupColourScheme();
+ ResidueShaderI groupColourScheme = stretchGroup
+ .getGroupColourScheme();
String name = stretchGroup.getName();
if (stretchGroup.cs.conservationApplied())
{
}
}
PaintRefresher.Refresh(this, av.getSequenceSetId());
- ap.paintAlignment(needOverviewUpdate);
- needOverviewUpdate = false;
+ // TODO: structure colours only need updating if stretchGroup used to or now
+ // does contain sequences with structure views
+ ap.paintAlignment(updateOverviewAndStructs, updateOverviewAndStructs);
+ updateOverviewAndStructs = false;
changeEndRes = false;
changeStartRes = false;
stretchGroup = null;
if (res > (stretchGroup.getStartRes() - 1))
{
stretchGroup.setEndRes(res);
- needOverviewUpdate |= av.isSelectionDefinedGroup();
+ updateOverviewAndStructs |= av.isSelectionDefinedGroup();
}
}
else if (changeStartRes)
if (res < (stretchGroup.getEndRes() + 1))
{
stretchGroup.setStartRes(res);
- needOverviewUpdate |= av.isSelectionDefinedGroup();
+ updateOverviewAndStructs |= av.isSelectionDefinedGroup();
}
}
if (stretchGroup.getSequences(null).contains(nextSeq))
{
stretchGroup.deleteSequence(seq, false);
- needOverviewUpdate |= av.isSelectionDefinedGroup();
+ updateOverviewAndStructs |= av.isSelectionDefinedGroup();
}
else
{
}
stretchGroup.addSequence(nextSeq, false);
- needOverviewUpdate |= av.isSelectionDefinedGroup();
+ updateOverviewAndStructs |= av.isSelectionDefinedGroup();
}
}
mouseDragging = true;
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
scrollThread.setEvent(evt);
}
-
- seqCanvas.repaint();
}
void scrollCanvas(MouseEvent evt)
{
if (evt == null)
{
- if (scrollThread != null)
+ if ((scrollThread != null) && (scrollThread.isRunning()))
{
- scrollThread.running = false;
+ scrollThread.stopScrolling();
scrollThread = null;
}
mouseDragging = false;
{
MouseEvent evt;
- boolean running = false;
+ private volatile boolean threadRunning = true;
public ScrollThread()
{
public void stopScrolling()
{
- running = false;
+ threadRunning = false;
+ }
+
+ public boolean isRunning()
+ {
+ return threadRunning;
}
@Override
public void run()
{
- running = true;
-
- while (running)
+ while (threadRunning)
{
if (evt != null)
{
if (mouseDragging && (evt.getY() < 0)
&& (av.getRanges().getStartSeq() > 0))
{
- running = av.getRanges().scrollUp(true);
+ av.getRanges().scrollUp(true);
}
- if (mouseDragging && (evt.getY() >= getHeight())
- && (av.getAlignment().getHeight() > av.getRanges()
- .getEndSeq()))
+ if (mouseDragging && (evt.getY() >= getHeight()) && (av
+ .getAlignment().getHeight() > av.getRanges().getEndSeq()))
{
- running = av.getRanges().scrollUp(false);
+ av.getRanges().scrollUp(false);
}
if (mouseDragging && (evt.getX() < 0))
{
- running = av.getRanges().scrollRight(false);
+ av.getRanges().scrollRight(false);
}
else if (mouseDragging && (evt.getX() >= getWidth()))
{
- running = av.getRanges().scrollRight(true);
+ av.getRanges().scrollRight(true);
}
}
// handles selection messages...
// TODO: extend config options to allow user to control if selections may be
// shared between viewports.
- boolean iSentTheSelection = (av == source || (source instanceof AlignViewport && ((AlignmentViewport) source)
- .getSequenceSetId().equals(av.getSequenceSetId())));
+ boolean iSentTheSelection = (av == source
+ || (source instanceof AlignViewport
+ && ((AlignmentViewport) source).getSequenceSetId()
+ .equals(av.getSequenceSetId())));
if (iSentTheSelection)
{
repaint = true;
}
- if (copycolsel
- && av.hasHiddenColumns()
+ if (copycolsel && av.hasHiddenColumns()
&& (av.getAlignment().getHiddenColumns() == null))
{
System.err.println("Bad things");