private int labelWidthWest; // label left width in pixels if shown
- private int wrappedSpaceAboveAlignment; // gap between widths
+ int wrappedSpaceAboveAlignment; // gap between widths
- private int wrappedRepeatHeightPx; // height in pixels of wrapped width
+ int wrappedRepeatHeightPx; // height in pixels of wrapped width
private int wrappedVisibleWidths; // number of wrapped widths displayed
calculateWrappedGeometry(canvasWidth, canvasHeight);
/*
- * draw one width at a time (excluding any scales or annotation shown),
+ * draw one width at a time (excluding any scales shown),
* until we have run out of either alignment or vertical space available
*/
int ypos = wrappedSpaceAboveAlignment;
* (av.getScaleAboveWrapped() ? 2 : 1);
/*
- * height in pixels of the wrapped widths
+ * compute height in pixels of the wrapped widths
+ * - start with space above plus sequences
*/
wrappedRepeatHeightPx = wrappedSpaceAboveAlignment;
- // add sequences
wrappedRepeatHeightPx += av.getAlignment().getHeight()
* charHeight;
- // add annotations panel height if shown
- wrappedRepeatHeightPx += getAnnotationHeight();
+
+ /*
+ * add annotations panel height if shown
+ * also gap between sequences and annotations
+ */
+ if (av.isShowAnnotation())
+ {
+ wrappedRepeatHeightPx += getAnnotationHeight();
+ wrappedRepeatHeightPx += SEQS_ANNOTATION_GAP; // 3px
+ }
/*
* number of visible widths (the last one may be part height),
* @param endColumn
* @param canvasHeight
*/
- protected void drawWrappedWidth(Graphics g, int ypos, int startColumn,
- int endColumn, int canvasHeight)
+ protected void drawWrappedWidth(Graphics g, final int ypos,
+ final int startColumn, final int endColumn,
+ final int canvasHeight)
{
ViewportRanges ranges = av.getRanges();
int viewportWidth = ranges.getViewportWidth();
if (av.isShowAnnotation())
{
- g.translate(0, cHeight + ypos + SEQS_ANNOTATION_GAP);
+ final int yShift = cHeight + ypos + SEQS_ANNOTATION_GAP;
+ g.translate(0, yShift);
if (annotations == null)
{
annotations = new AnnotationPanel(av);
annotations.renderer.drawComponent(annotations, av, g, -1,
startColumn, endx + 1);
- g.translate(0, -cHeight - ypos - SEQS_ANNOTATION_GAP);
+ g.translate(0, -yShift);
}
g.setClip(clip);
g.translate(-xOffset, 0);
int alignmentHeight = av.getAlignment().getHeight();
if (av.getWrapAlignment())
{
- int hgap = charHeight;
- if (av.getScaleAboveWrapped())
- {
- hgap += charHeight;
- }
+ seqCanvas.calculateWrappedGeometry(seqCanvas.getWidth(),
+ seqCanvas.getHeight());
+ // int gapHeight = charHeight;
+ // if (av.getScaleAboveWrapped())
+ // {
+ // gapHeight += charHeight;
+ // }
+ //
+ // final int alignmentHeightPixels = gapHeight
+ // + alignmentHeight * charHeight;
+ // int cHeight = alignmentHeightPixels;
+ // if (av.isShowAnnotation())
+ // {
+ // cHeight += (seqCanvas.getAnnotationHeight() +
+ // SeqCanvas.SEQS_ANNOTATION_GAP);
+ // }
- final int alignmentHeightPixels = alignmentHeight * charHeight + hgap;
- final int annotationHeight = seqCanvas.getAnnotationHeight();
- final int cHeight = alignmentHeightPixels + annotationHeight
- + SeqCanvas.SEQS_ANNOTATION_GAP;
+ /*
+ * yPos modulo repeating width height
+ */
+ int yOffsetPx = y % seqCanvas.wrappedRepeatHeightPx;
- int yOffsetPx = y % cHeight; // yPos below repeating width(s)
- if (yOffsetPx >= alignmentHeightPixels
- + SeqCanvas.SEQS_ANNOTATION_GAP)
+ /*
+ * height of sequences plus space / scale above,
+ * plus gap between sequences and annotations
+ */
+ int alignmentHeightPixels = seqCanvas.wrappedSpaceAboveAlignment
+ + alignmentHeight * charHeight
+ + SeqCanvas.SEQS_ANNOTATION_GAP;
+ if (yOffsetPx >= alignmentHeightPixels)
{
/*
- * mouse is over annotations; find annotation index, also
+ * mouse is over annotations; find annotation index, also set
* last sequence above (for backwards compatible behaviour)
*/
AlignmentAnnotation[] anns = av.getAlignment()
.getAlignmentAnnotation();
- int rowOffsetPx = yOffsetPx - alignmentHeightPixels
- - SeqCanvas.SEQS_ANNOTATION_GAP;
+ int rowOffsetPx = yOffsetPx - alignmentHeightPixels;
annIndex = AnnotationPanel.getRowIndex(rowOffsetPx, anns);
seqIndex = alignmentHeight - 1;
}
/*
* mouse is over sequence (or the space above sequences)
*/
- yOffsetPx -= hgap;
+ yOffsetPx -= seqCanvas.wrappedSpaceAboveAlignment;
if (yOffsetPx >= 0)
{
seqIndex = Math.min(yOffsetPx / charHeight, alignmentHeight - 1);
int startRes = av.getRanges().getStartRes();
if (av.getWrapAlignment())
{
-
int hgap = av.getCharHeight();
if (av.getScaleAboveWrapped())
{
// allow for wrapped view scrolled right (possible from Overview)
int startOffset = startRes % cwidth;
res = wrappedBlock * cwidth + startOffset
- + +Math.min(cwidth - 1, x / av.getCharWidth());
+ + Math.min(cwidth - 1, x / av.getCharWidth());
}
else
{
{
lastMousePosition = null;
setToolTipText(null);
+ lastTooltip = null;
ap.alignFrame.statusBar.setText("");
return;
}
@Override
public Point getToolTipLocation(MouseEvent event)
{
- int x = event.getX(), w = getWidth();
- int wdth = (w - x < 200) ? -(w / 2) : 5; // switch sides when tooltip is too
- // close to edge
+ if (tooltipText == null || tooltipText.length() <= 6)
+ {
+ lastp = null;
+ return null;
+ }
+
+ int x = event.getX();
+ int w = getWidth();
+ // switch sides when tooltip is too close to edge
+ int wdth = (w - x < 200) ? -(w / 2) : 5;
Point p = lastp;
if (!event.isShiftDown() || p == null)
{
- p = (tooltipText != null && tooltipText.length() > 6)
- ? new Point(event.getX() + wdth, event.getY() - 20)
- : null;
+ p = new Point(event.getX() + wdth, event.getY() - 20);
+ lastp = p;
}
/*
- * TODO: try to modify position region is not obcured by tooltip
+ * TODO: try to set position so region is not obscured by tooltip
*/
- return lastp = p;
+ return p;
}
String lastTooltip;
import java.awt.Font;
import java.awt.FontMetrics;
-import junit.extensions.PA;
-
import org.testng.annotations.Test;
+import junit.extensions.PA;
+
public class SeqCanvasTest
{
/**
assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
/*
- * reduce canvas height by 1 pixel - should not be enough height
- * to draw 3 widths
+ * reduce canvas height by 1 pixel
+ * - should not be enough height to draw 3 widths
*/
canvasHeight -= 1;
testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
canvasWidth += 8;
wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
canvasHeight);
- assertEquals(wrappedWidth, 27);
+ assertEquals(wrappedWidth, 27); // 8px not enough
canvasWidth += 1;
wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
canvasHeight);
- assertEquals(wrappedWidth, 28);
+ assertEquals(wrappedWidth, 28); // 9px is enough
/*
* now West but not East scale - lose 39 pixels or 4 columns
canvasWidth += 2;
wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
canvasHeight);
- assertEquals(wrappedWidth, 24);
+ assertEquals(wrappedWidth, 24); // 2px not enough
canvasWidth += 1;
wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
canvasHeight);
- assertEquals(wrappedWidth, 25);
+ assertEquals(wrappedWidth, 25); // 3px is enough
/*
* turn off scales left and right, make width exactly 157 columns
2 * charHeight);
int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
- + annotationHeight);
+ + SeqCanvas.SEQS_ANNOTATION_GAP + annotationHeight);
assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
/*
- * repeat height is 17 * (2 + 15) = 289 + annotationHeight = 507
- * make canvas height 2 * 289 + 3 * charHeight so just enough to
- * draw 2 widths and the first sequence of a third
+ * repeat height is 17 * (2 + 15) = 289 + 3 + annotationHeight = 510
+ * make canvas height 2 of these plus 3 charHeights
+ * so just enough to draw 2 widths, gap + scale + the first sequence of a third
*/
- canvasHeight = charHeight * (17 * 2 + 3) + 2 * annotationHeight;
+ canvasHeight = charHeight * (17 * 2 + 3)
+ + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP);
testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
* reduce height to enough for 2 widths and not quite a third
* i.e. two repeating heights + spacer + sequence - 1 pixel
*/
- canvasHeight = charHeight * (16 * 2 + 2) + 2 * annotationHeight - 1;
+ canvasHeight = charHeight * (16 * 2 + 2)
+ + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP) - 1;
testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
}
@Test(groups = "Functional")
- public void testFindMousePosition_wrapped()
+ public void testFindMousePosition_wrapped_annotations()
{
Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "true");
Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
/*
* cursor below sequences, in 3-pixel gap above annotations
+ * method reports index of nearest sequence above
*/
y += 1;
evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
/*
* cursor still in the gap above annotations, now at the bottom of it
- * method reports index of nearest sequence above
*/
y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
assertEquals(pos.seqIndex, 0);
assertEquals(pos.annotationIndex, -1);
}
+ @Test(groups = "Functional")
+ public void testFindMousePosition_wrapped_noAnnotations()
+ {
+ Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false");
+ Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
+ AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
+ "examples/uniref50.fa", DataSourceType.FILE);
+ AlignViewportI av = alignFrame.getViewport();
+ av.setScaleAboveWrapped(false);
+ av.setScaleLeftWrapped(false);
+ av.setScaleRightWrapped(false);
+ alignFrame.alignPanel.paintAlignment(false, false);
+
+ final int charHeight = av.getCharHeight();
+ final int charWidth = av.getCharWidth();
+ final int alignmentHeight = av.getAlignment().getHeight();
+
+ // sanity checks:
+ assertTrue(charHeight > 0);
+ assertTrue(charWidth > 0);
+ assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
+
+ SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
+ int x = 0;
+ int y = 0;
+
+ /*
+ * mouse at top left of wrapped panel; there is a gap of charHeight
+ * above the alignment
+ */
+ MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
+ 0, 0, 0, false, 0);
+ MousePos pos = testee.findMousePosition(evt);
+ assertEquals(pos.column, 0);
+ assertEquals(pos.seqIndex, -1); // above sequences
+ assertEquals(pos.annotationIndex, -1);
+
+ /*
+ * cursor over top of first sequence
+ */
+ y = charHeight;
+ evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+ false, 0);
+ pos = testee.findMousePosition(evt);
+ assertEquals(pos.seqIndex, 0);
+ assertEquals(pos.annotationIndex, -1);
+
+ /*
+ * cursor at bottom of last sequence
+ */
+ y = charHeight * (1 + alignmentHeight) - 1;
+ evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+ false, 0);
+ pos = testee.findMousePosition(evt);
+ assertEquals(pos.seqIndex, alignmentHeight - 1);
+ assertEquals(pos.annotationIndex, -1);
+
+ /*
+ * cursor below sequences, at top of charHeight gap between widths
+ */
+ y += 1;
+ evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+ false, 0);
+ pos = testee.findMousePosition(evt);
+ assertEquals(pos.seqIndex, -1);
+ assertEquals(pos.annotationIndex, -1);
+
+ /*
+ * cursor below sequences, at top of charHeight gap between widths
+ */
+ y += charHeight - 1;
+ evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+ false, 0);
+ pos = testee.findMousePosition(evt);
+ assertEquals(pos.seqIndex, -1);
+ assertEquals(pos.annotationIndex, -1);
+
+ /*
+ * cursor at the top of the first sequence, second width
+ */
+ y += 1;
+ evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+ false, 0);
+ pos = testee.findMousePosition(evt);
+ assertEquals(pos.seqIndex, 0);
+ assertEquals(pos.annotationIndex, -1);
+ }
@BeforeClass(alwaysRun = true)
public static void setUpBeforeClass() throws Exception
{