X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FSeqCanvas.java;h=d110e659c29f6eb7a97729de1217d20c0d13ecc2;hb=afe4b88500a5d61bc8d312909cfdde2b7cdd53df;hp=7ecedf4647772df2f3934e7584b7f419f2813a18;hpb=6f0b432ac19ed1d0d5e01a834586dc81b8a6a72d;p=jalview.git
diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java
index 7ecedf4..d110e65 100755
--- a/src/jalview/gui/SeqCanvas.java
+++ b/src/jalview/gui/SeqCanvas.java
@@ -20,27 +20,14 @@
*/
package jalview.gui;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.SearchResultsI;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.datamodel.VisibleContigsIterator;
-import jalview.renderer.ScaleRenderer;
-import jalview.renderer.ScaleRenderer.ScaleMark;
-import jalview.util.Comparison;
-import jalview.viewmodel.ViewportListenerI;
-import jalview.viewmodel.ViewportRanges;
-
-import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
+import java.awt.Rectangle;
import java.awt.RenderingHints;
-import java.awt.Shape;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.util.Iterator;
@@ -48,14 +35,34 @@ import java.util.List;
import javax.swing.JPanel;
+import jalview.api.SequenceRenderer;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.SearchResultsI;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.VisibleContigsIterator;
+import jalview.renderer.ScaleRenderer;
+import jalview.renderer.ScaleRenderer.ScaleMark;
+import jalview.util.Comparison;
+import jalview.viewmodel.ViewportListenerI;
+import jalview.viewmodel.ViewportRanges;
+
/**
* The Swing component on which the alignment sequences, and annotations (if
* shown), are drawn. This includes scales above, left and right (if shown) in
* Wrapped mode, but not the scale above in Unwrapped mode.
*
*/
+@SuppressWarnings("serial")
public class SeqCanvas extends JPanel implements ViewportListenerI
{
+ /**
+ * vertical gap in pixels between sequences and annotations when in wrapped
+ * mode
+ */
+ static final int SEQS_ANNOTATION_GAP = 3;
+
private static final String ZEROS = "0000000000";
final FeatureRenderer fr;
@@ -70,7 +77,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
private final SequenceRenderer seqRdr;
- private boolean fastPaint = false;
+ boolean fastPaint = false;
private boolean fastpainting = false;
@@ -83,14 +90,14 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
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
// Don't do this! Graphics handles are supposed to be transient
- //private Graphics2D gg;
+ // private Graphics2D gg;
/**
* Creates a new SeqCanvas object.
@@ -101,7 +108,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
{
this.av = ap.av;
fr = new FeatureRenderer(ap);
- seqRdr = new SequenceRenderer(av);
+ seqRdr = new jalview.gui.SequenceRenderer(av);
setLayout(new BorderLayout());
PaintRefresher.Register(this, av.getSequenceSetId());
setBackground(Color.white);
@@ -151,7 +158,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
for (ScaleMark mark : marks)
{
int mpos = mark.column; // (i - startx - 1)
-// System.out.println("n " + mpos + " " + ypos);
if (mpos < 0)
{
continue;
@@ -198,9 +204,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
int yPos = ypos + charHeight;
int startX = startx;
int endX = endx;
-
- //System.out.println("v " + startx + " " + endx + " " + ypos);
-
if (av.hasHiddenColumns())
{
@@ -245,7 +248,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
// fillRect origin is top left of rectangle
g.fillRect(0, y - charHeight, left ? labelWidthWest : labelWidthEast,
charHeight + 1);
-
+
if (value != -1)
{
/*
@@ -259,11 +262,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
int xOffset = labelSpace - labelLength;
g.setColor(Color.black);
g.drawString(valueAsString, xOffset, y);
-
- //System.out.println("v " + valueAsString + " " + xOffset + " " + y);
-
}
}
+
}
/**
@@ -277,6 +278,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
*
scrolling by trackpad, middle mouse button, or other device
* by moving the box in the Overview window
* programmatically to make a highlighted position visible
+ * pasting a block of sequences
*
*
* @param horizontal
@@ -286,18 +288,21 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
*/
public void fastPaint(int horizontal, int vertical)
{
- if (fastpainting || img == null)
+
+ // effectively:
+ // if (horizontal != 0 && vertical != 0)
+ // throw new InvalidArgumentException();
+ if (fastpainting || img == null)
{
return;
}
fastpainting = true;
fastPaint = true;
-
try
{
int charHeight = av.getCharHeight();
int charWidth = av.getCharWidth();
-
+
ViewportRanges ranges = av.getRanges();
int startRes = ranges.getStartRes();
int endRes = ranges.getEndRes();
@@ -305,11 +310,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
int endSeq = ranges.getEndSeq();
int transX = 0;
int transY = 0;
-
- Graphics gg = img.getGraphics();
- gg.copyArea(horizontal * charWidth, vertical * charHeight,
- img.getWidth(), img.getHeight(), -horizontal * charWidth,
- -vertical * charHeight);
if (horizontal > 0) // scrollbar pulled right, image to the left
{
@@ -323,7 +323,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
if (vertical > 0) // scroll down
{
- startSeq = endSeq - vertical;
+ startSeq = endSeq - vertical + 1;
if (startSeq < ranges.getStartSeq())
{ // ie scrolling too fast, more than a page at a time
@@ -331,12 +331,12 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
else
{
- transY = img.getHeight() - ((vertical + 1) * charHeight);
+ transY = img.getHeight() - (vertical * charHeight);
}
}
- else if (vertical < 0)
+ else if (vertical < 0) // scroll up
{
- endSeq = startSeq - vertical;
+ endSeq = startSeq - vertical - 1;
if (endSeq > ranges.getEndSeq())
{
@@ -344,14 +344,28 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
}
+ // jalview.bin.Console.errPrintln(">>> FastPaint to " + transX + " " +
+ // transY + " "
+ // + horizontal + " " + vertical + " " + startRes + " " + endRes
+ // + " " + startSeq + " " + endSeq);
+
+ Graphics gg = img.getGraphics();
+ gg.copyArea(horizontal * charWidth, vertical * charHeight,
+ img.getWidth(), img.getHeight(), -horizontal * charWidth,
+ -vertical * charHeight);
+
+ /** @j2sNative xxi = this.img */
+
gg.translate(transX, transY);
- drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
+ drawPanel(seqRdr, gg, startRes, endRes, startSeq, endSeq, 0);
gg.translate(-transX, -transY);
gg.dispose();
-
+
// Call repaint on alignment panel so that repaints from other alignment
// panel components can be aggregated. Otherwise performance of the
// overview window and others may be adversely affected.
+ // jalview.bin.Console.outPrintln("SeqCanvas fastPaint() repaint()
+ // request...");
av.getAlignPanel().repaint();
} finally
{
@@ -362,46 +376,74 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
@Override
public void paintComponent(Graphics g)
{
- super.paintComponent(g);
int charHeight = av.getCharHeight();
int charWidth = av.getCharWidth();
- ViewportRanges ranges = av.getRanges();
-
int width = getWidth();
int height = getHeight();
width -= (width % charWidth);
height -= (height % charHeight);
- // selectImage is the selection group outline image
- BufferedImage selectImage = drawSelectionGroup(ranges.getStartRes(),
- ranges.getEndRes(), ranges.getStartSeq(), ranges.getEndSeq());
+ // BH 2019 can't possibly fastPaint if either width or height is 0
- if ((img != null) && (fastPaint
- || (getVisibleRect().width != g.getClipBounds().width)
- || (getVisibleRect().height != g.getClipBounds().height)))
+ if (width == 0 || height == 0)
{
- BufferedImage lcimg = buildLocalImage(selectImage);
- g.drawImage(lcimg, 0, 0, this);
+ return;
+ }
+
+ ViewportRanges ranges = av.getRanges();
+ int startRes = ranges.getStartRes();
+ int startSeq = ranges.getStartSeq();
+ int endRes = ranges.getEndRes();
+ int endSeq = ranges.getEndSeq();
+
+ // [JAL-3226] problem that JavaScript (or Java) may consolidate multiple
+ // repaint() requests in unpredictable ways. In this case, the issue was
+ // that in response to a CTRL-C/CTRL-V paste request, in Java a fast
+ // repaint request preceded two full requests, thus resulting
+ // in a full request for paint. In constrast, in JavaScript, the three
+ // requests were bundled together into one, so the fastPaint flag was
+ // still present for the second and third request.
+ //
+ // This resulted in incomplete painting.
+ //
+ // The solution was to set seqCanvas.fastPaint and idCanvas.fastPaint false
+ // in PaintRefresher when the target to be painted is one of those two
+ // components.
+ //
+ // BH 2019.04.22
+ //
+ // An initial idea; can be removed once we determine this issue is closed:
+ // if (av.isFastPaintDisabled())
+ // {
+ // fastPaint = false;
+ // }
+
+ Rectangle vis, clip;
+ if (img != null
+ && (fastPaint
+ || (vis = getVisibleRect()).width != (clip = g
+ .getClipBounds()).width
+ || vis.height != clip.height))
+ {
+ g.drawImage(img, 0, 0, this);
+ drawSelectionGroup((Graphics2D) g, startRes, endRes, startSeq,
+ endSeq);
fastPaint = false;
}
- else if ((width > 0) && (height > 0))
+ else
{
- // img is a cached version of the last view we drew, if any
- // if we have no img or the size has changed, make a new one
+ // img is a cached version of the last view we drew.
+ // If we have no img or the size has changed, make a new one.
+ //
if (img == null || width != img.getWidth()
|| height != img.getHeight())
{
- img = setupImage();
- if (img == null)
- {
- return;
- }
+ img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
}
-
Graphics2D gg = (Graphics2D) img.getGraphics();
gg.setFont(av.getFont());
@@ -416,30 +458,26 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
if (av.getWrapAlignment())
{
- drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes());
+ drawWrappedPanel(seqRdr, gg, getWidth(), getHeight(),
+ ranges.getStartRes());
}
else
{
- drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
- ranges.getStartSeq(), ranges.getEndSeq(), 0);
+ drawPanel(seqRdr, gg, startRes, endRes, startSeq, endSeq, 0);
}
-
-
- gg.dispose();
- // lcimg is a local *copy* of img which we'll draw selectImage on top of
- BufferedImage lcimg = buildLocalImage(selectImage);
- g.drawImage(lcimg, 0, 0, this);
+ drawSelectionGroup(gg, startRes, endRes, startSeq, endSeq);
+ g.drawImage(img, 0, 0, this);
+ gg.dispose();
}
if (av.cursorMode)
{
- drawCursor(g, ranges.getStartRes(), ranges.getEndRes(),
- ranges.getStartSeq(), ranges.getEndSeq());
+ drawCursor(g, startRes, endRes, startSeq, endSeq);
}
}
-
+
/**
* Draw an alignment panel for printing
*
@@ -457,16 +495,10 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
public void drawPanelForPrinting(Graphics g1, int startRes, int endRes,
int startSeq, int endSeq)
{
- drawPanel(g1, startRes, endRes, startSeq, endSeq, 0);
+ SequenceRenderer localSeqR = new jalview.gui.SequenceRenderer(av);
+ drawPanel(localSeqR, g1, startRes, endRes, startSeq, endSeq, 0);
- BufferedImage selectImage = drawSelectionGroup(startRes, endRes,
- startSeq, endSeq);
- if (selectImage != null)
- {
- ((Graphics2D) g1).setComposite(AlphaComposite
- .getInstance(AlphaComposite.SRC_OVER));
- g1.drawImage(selectImage, 0, 0, this);
- }
+ drawSelectionGroup((Graphics2D) g1, startRes, endRes, startSeq, endSeq);
}
/**
@@ -484,102 +516,15 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
public void drawWrappedPanelForPrinting(Graphics g, int canvasWidth,
int canvasHeight, int startRes)
{
- SequenceGroup group = av.getSelectionGroup();
-
- drawWrappedPanel(g, canvasWidth, canvasHeight, startRes);
+ SequenceRenderer localSeqR = new jalview.gui.SequenceRenderer(av);
+ drawWrappedPanel(localSeqR, g, canvasWidth, canvasHeight, startRes);
+ SequenceGroup group = av.getSelectionGroup();
if (group != null)
{
- BufferedImage selectImage = null;
- try
- {
- selectImage = new BufferedImage(canvasWidth, canvasHeight,
- BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
- } catch (OutOfMemoryError er)
- {
- System.gc();
- System.err.println("Print image OutOfMemory Error.\n" + er);
- new OOMWarning("Creating wrapped alignment image for printing", er);
- }
- if (selectImage != null)
- {
- Graphics2D g2 = selectImage.createGraphics();
- setupSelectionGroup(g2, selectImage);
- drawWrappedSelection(g2, group, canvasWidth, canvasHeight,
- startRes);
-
- g2.setComposite(
- AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
- g.drawImage(selectImage, 0, 0, this);
- g2.dispose();
- }
- }
- }
-
- /*
- * Make a local image by combining the cached image img
- * with any selection
- */
- private BufferedImage buildLocalImage(BufferedImage selectImage)
- {
- // clone the cached image
- BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
- img.getType());
-
- // BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
- // img.getType());
- Graphics2D g2d = lcimg.createGraphics();
- g2d.drawImage(img, 0, 0, null);
-
- // overlay selection group on lcimg
- if (selectImage != null)
- {
- g2d.setComposite(
- AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
- g2d.drawImage(selectImage, 0, 0, this);
+ drawWrappedSelection((Graphics2D) g, group, canvasWidth, canvasHeight,
+ startRes);
}
-
- g2d.dispose();
-
- return lcimg;
- }
-
- /*
- * Set up a buffered image of the correct height and size for the sequence canvas
- */
- private BufferedImage setupImage()
- {
- BufferedImage lcimg = null;
-
- int charWidth = av.getCharWidth();
- int charHeight = av.getCharHeight();
-
- int width = getWidth();
- int height = getHeight();
-
- width -= (width % charWidth);
- height -= (height % charHeight);
-
- if ((width < 1) || (height < 1))
- {
- return null;
- }
-
- try
- {
- lcimg = new BufferedImage(width, height,
- BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
- } catch (OutOfMemoryError er)
- {
- System.gc();
- System.err.println(
- "Group image OutOfMemory Redraw Error.\n" + er);
- new OOMWarning("Creating alignment image for display", er);
-
- return null;
- }
-
- return lcimg;
}
/**
@@ -598,7 +543,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
FontMetrics fm = getFontMetrics(av.getFont());
int labelWidth = 0;
-
+
if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
{
labelWidth = getLabelWidth(fm);
@@ -611,6 +556,20 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
}
+ public int getMinimumWrappedCanvasWidth()
+ {
+ int charWidth = av.getCharWidth();
+ FontMetrics fm = getFontMetrics(av.getFont());
+ int labelWidth = 0;
+ if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
+ {
+ labelWidth = getLabelWidth(fm);
+ }
+ labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0;
+ labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0;
+ return labelWidthEast + labelWidthWest + charWidth;
+ }
+
/**
* Returns a pixel width sufficient to show the largest sequence coordinate
* (end position) in the alignment, calculated as the FontMetrics width of
@@ -655,8 +614,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* @param startColumn
* the first column (0...) of the alignment to draw
*/
- public void drawWrappedPanel(Graphics g, int canvasWidth,
- int canvasHeight, final int startColumn)
+ public void drawWrappedPanel(SequenceRenderer seqRdr, Graphics g,
+ int canvasWidth, int canvasHeight, final int startColumn)
{
int wrappedWidthInResidues = calculateWrappedGeometry(canvasWidth,
canvasHeight);
@@ -672,7 +631,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
calculateWrappedGeometry(canvasWidth, canvasHeight);
/*
- * draw one width at a time (including 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;
@@ -682,9 +641,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
int currentWidth = 0;
while ((currentWidth < wrappedVisibleWidths) && (start < maxWidth))
{
- int endColumn = Math
- .min(maxWidth, start + wrappedWidthInResidues - 1);
- drawWrappedWidth(g, ypos, start, endColumn, canvasHeight);
+ int endColumn = Math.min(maxWidth,
+ start + wrappedWidthInResidues - 1);
+ drawWrappedWidth(seqRdr, g, ypos, start, endColumn, canvasHeight);
ypos += wrappedRepeatHeightPx;
start += wrappedWidthInResidues;
currentWidth++;
@@ -719,14 +678,21 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* (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.getRanges().getViewportHeight()
- * charHeight;
- // add annotations panel height if shown
- wrappedRepeatHeightPx += getAnnotationHeight();
+ wrappedRepeatHeightPx += av.getAlignment().getHeight() * charHeight;
+
+ /*
+ * 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),
@@ -744,7 +710,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* compute width in residues; this also sets East and West label widths
*/
int wrappedWidthInResidues = getWrappedCanvasWidth(canvasWidth);
-
+ av.setWrappedWidth(wrappedWidthInResidues); // update model accordingly
/*
* limit visibleWidths to not exceed width of alignment
*/
@@ -770,8 +736,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* @param endColumn
* @param canvasHeight
*/
- protected void drawWrappedWidth(Graphics g, int ypos, int startColumn,
- int endColumn, int canvasHeight)
+ protected void drawWrappedWidth(SequenceRenderer seqRdr, Graphics g,
+ final int ypos, final int startColumn, final int endColumn,
+ final int canvasHeight)
{
ViewportRanges ranges = av.getRanges();
int viewportWidth = ranges.getViewportWidth();
@@ -786,22 +753,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
int charWidth = av.getCharWidth();
int xOffset = labelWidthWest
+ ((startColumn - ranges.getStartRes()) % viewportWidth)
- * charWidth;
- g.translate(xOffset, 0);
+ * charWidth;
- // When printing we have an extra clipped region,
- // the Printable page which we need to account for here
- Shape clip = g.getClip();
-
- if (clip == null)
- {
- g.setClip(0, 0, viewportWidth * charWidth, canvasHeight);
- }
- else
- {
- g.setClip(0, (int) clip.getBounds().getY(),
- viewportWidth * charWidth, (int) clip.getBounds().getHeight());
- }
+ g.translate(xOffset, 0);
/*
* white fill the region to be drawn (so incremental fast paint doesn't
@@ -811,14 +765,15 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
g.fillRect(0, ypos, (endx - startColumn + 1) * charWidth,
wrappedRepeatHeightPx);
- drawPanel(g, startColumn, endx, 0, av.getAlignment().getHeight() - 1,
- ypos);
+ drawPanel(seqRdr, g, startColumn, endx, 0,
+ av.getAlignment().getHeight() - 1, ypos);
int cHeight = av.getAlignment().getHeight() * av.getCharHeight();
if (av.isShowAnnotation())
{
- g.translate(0, cHeight + ypos + 3);
+ final int yShift = cHeight + ypos + SEQS_ANNOTATION_GAP;
+ g.translate(0, yShift);
if (annotations == null)
{
annotations = new AnnotationPanel(av);
@@ -826,9 +781,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
annotations.renderer.drawComponent(annotations, av, g, -1,
startColumn, endx + 1);
- g.translate(0, -cHeight - ypos - 3);
+ g.translate(0, -yShift);
}
- g.setClip(clip);
g.translate(-xOffset, 0);
}
@@ -844,6 +798,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
int charWidth = av.getCharWidth();
g.setFont(av.getFont());
+
g.setColor(Color.black);
int ypos = wrappedSpaceAboveAlignment;
@@ -865,8 +820,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
if (av.getScaleRightWrapped())
{
int x = labelWidthWest + viewportWidth * charWidth;
-
- //System.out.println("shifting " + x);
+
g.translate(x, 0);
drawVerticalScale(g, startCol, endColumn, ypos, false);
g.translate(-x, 0);
@@ -878,8 +832,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
*/
g.translate(labelWidthWest, 0);
g.setColor(Color.white);
- g.fillRect(0, ypos - wrappedSpaceAboveAlignment, viewportWidth
- * charWidth + labelWidthWest, wrappedSpaceAboveAlignment);
+ g.fillRect(0, ypos - wrappedSpaceAboveAlignment,
+ viewportWidth * charWidth + labelWidthWest,
+ wrappedSpaceAboveAlignment);
g.setColor(Color.black);
g.translate(-labelWidthWest, 0);
@@ -950,40 +905,26 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* Draw a selection group over a wrapped alignment
*/
private void drawWrappedSelection(Graphics2D g, SequenceGroup group,
- int canvasWidth,
- int canvasHeight, int startRes)
+ int canvasWidth, int canvasHeight, int startRes)
{
- int charHeight = av.getCharHeight();
- int charWidth = av.getCharWidth();
-
- // height gap above each panel
- int hgap = charHeight;
- if (av.getScaleAboveWrapped())
- {
- hgap += charHeight;
- }
+ // chop the wrapped alignment extent up into panel-sized blocks and treat
+ // each block as if it were a block from an unwrapped alignment
+ g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_ROUND, 3f, new float[]
+ { 5f, 3f }, 0f));
+ g.setColor(Color.RED);
+ int charWidth = av.getCharWidth();
int cWidth = (canvasWidth - labelWidthEast - labelWidthWest)
/ charWidth;
- int cHeight = av.getAlignment().getHeight() * charHeight;
-
int startx = startRes;
- int endx;
- int ypos = hgap; // vertical offset
- int maxwidth = av.getAlignment().getWidth();
-
- if (av.hasHiddenColumns())
- {
- maxwidth = av.getAlignment().getHiddenColumns()
- .absoluteToVisibleColumn(maxwidth);
- }
+ int maxwidth = av.getAlignment().getVisibleWidth();
+ int ypos = wrappedSpaceAboveAlignment;
- // chop the wrapped alignment extent up into panel-sized blocks and treat
- // each block as if it were a block from an unwrapped alignment
while ((ypos <= canvasHeight) && (startx < maxwidth))
{
// set end value to be start + width, or maxwidth, whichever is smaller
- endx = startx + cWidth - 1;
+ int endx = startx + cWidth - 1;
if (endx > maxwidth)
{
@@ -991,21 +932,23 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
g.translate(labelWidthWest, 0);
-
drawUnwrappedSelection(g, group, startx, endx, 0,
- av.getAlignment().getHeight() - 1,
- ypos);
-
+ av.getAlignment().getHeight() - 1, ypos);
g.translate(-labelWidthWest, 0);
- // update vertical offset
- ypos += cHeight + getAnnotationHeight() + hgap;
+ ypos += wrappedRepeatHeightPx;
- // update horizontal offset
startx += cWidth;
}
+ g.setStroke(new BasicStroke());
}
+ /**
+ * Answers zero if annotations are not shown, otherwise recalculates and
+ * answers the total height of all annotation rows in pixels
+ *
+ * @return
+ */
int getAnnotationHeight()
{
if (!av.isShowAnnotation())
@@ -1027,6 +970,10 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* between the markers is drawn separately, followed by the hidden column
* marker.
*
+ * @param localSeqR
+ * - sequence renderer implementation - when null, uses the one used
+ * for rendering interactive GUI
+ *
* @param g1
* the graphics context, positioned at the first residue to be drawn
* @param startRes
@@ -1040,15 +987,20 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* @param yOffset
* vertical offset at which to draw (for wrapped alignments)
*/
- public void drawPanel(Graphics g1, final int startRes, final int endRes,
- final int startSeq, final int endSeq, final int yOffset)
+ public void drawPanel(SequenceRenderer localSeqR, Graphics g1,
+ final int startRes, final int endRes, final int startSeq,
+ final int endSeq, final int yOffset)
{
int charHeight = av.getCharHeight();
int charWidth = av.getCharWidth();
+ if (localSeqR == null)
+ {
+ localSeqR = seqRdr;
+ }
if (!av.hasHiddenColumns())
{
- draw(g1, startRes, endRes, startSeq, endSeq, yOffset);
+ draw(localSeqR, g1, startRes, endRes, startSeq, endSeq, yOffset);
}
else
{
@@ -1072,7 +1024,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
*/
g1.translate(screenY * charWidth, 0);
- draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
+ draw(localSeqR, g1, blockStart, blockEnd, startSeq, endSeq,
+ yOffset);
/*
* draw the downline of the hidden column marker (ScalePanel draws the
@@ -1098,6 +1051,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
/**
* Draws a region of the visible alignment
*
+ * @param seqRdr
+ *
* @param g1
* @param startRes
* offset of the first column in the visible region (0..)
@@ -1110,8 +1065,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* @param yOffset
* vertical offset at which to draw (for wrapped alignments)
*/
- private void draw(Graphics g, int startRes, int endRes, int startSeq,
- int endSeq, int offset)
+ private void draw(SequenceRenderer seqRdr, Graphics g, int startRes,
+ int endRes, int startSeq, int endSeq, int offset)
{
int charHeight = av.getCharHeight();
int charWidth = av.getCharWidth();
@@ -1170,14 +1125,21 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
+ /**
+ * Draws the outlines of any groups defined on the alignment (excluding the
+ * current selection group, if any)
+ *
+ * @param g1
+ * @param startRes
+ * @param endRes
+ * @param startSeq
+ * @param endSeq
+ * @param offset
+ */
void drawGroupsBoundaries(Graphics g1, int startRes, int endRes,
int startSeq, int endSeq, int offset)
{
Graphics2D g = (Graphics2D) g1;
- //
- // ///////////////////////////////////
- // Now outline any areas if necessary
- // ///////////////////////////////////
SequenceGroup group = null;
int groupIndex = -1;
@@ -1190,8 +1152,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
if (group != null)
{
- g.setStroke(new BasicStroke());
-
do
{
g.setColor(group.getOutlineColour());
@@ -1199,49 +1159,37 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
endSeq, offset);
groupIndex++;
-
- g.setStroke(new BasicStroke());
-
if (groupIndex >= av.getAlignment().getGroups().size())
{
break;
}
-
group = av.getAlignment().getGroups().get(groupIndex);
-
} while (groupIndex < av.getAlignment().getGroups().size());
-
}
-
}
-
- /*
- * Draw the selection group as a separate image and overlay
+ /**
+ * Draws the outline of the current selection group (if any)
+ *
+ * @param g
+ * @param startRes
+ * @param endRes
+ * @param startSeq
+ * @param endSeq
*/
- private BufferedImage drawSelectionGroup(int startRes, int endRes,
+ private void drawSelectionGroup(Graphics2D g, int startRes, int endRes,
int startSeq, int endSeq)
{
- // get a new image of the correct size
- BufferedImage selectionImage = setupImage();
-
- if (selectionImage == null)
- {
- return null;
- }
-
SequenceGroup group = av.getSelectionGroup();
if (group == null)
{
- // nothing to draw
- return null;
+ return;
}
- // set up drawing colour
- Graphics2D g = (Graphics2D) selectionImage.getGraphics();
-
- setupSelectionGroup(g, selectionImage);
-
+ g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_ROUND, 3f, new float[]
+ { 5f, 3f }, 0f));
+ g.setColor(Color.RED);
if (!av.getWrapAlignment())
{
drawUnwrappedSelection(g, group, startRes, endRes, startSeq, endSeq,
@@ -1252,9 +1200,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
drawWrappedSelection(g, group, getWidth(), getHeight(),
av.getRanges().getStartRes());
}
-
- g.dispose();
- return selectionImage;
+ g.setStroke(new BasicStroke());
}
/**
@@ -1272,8 +1218,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* the cursor drawn on it, if any
*/
private void drawCursor(Graphics g, int startRes, int endRes,
- int startSeq,
- int endSeq)
+ int startSeq, int endSeq)
{
// convert the cursorY into a position on the visible alignment
int cursor_ypos = cursorY;
@@ -1344,40 +1289,29 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
}
-
- /*
- * Set up graphics for selection group
- */
- private void setupSelectionGroup(Graphics2D g,
- BufferedImage selectionImage)
- {
- // set background to transparent
- g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
- g.fillRect(0, 0, selectionImage.getWidth(), selectionImage.getHeight());
-
- // set up foreground to draw red dashed line
- g.setComposite(AlphaComposite.Src);
- g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
- BasicStroke.JOIN_ROUND, 3f, new float[]
- { 5f, 3f }, 0f));
- g.setColor(Color.RED);
- }
-
- /*
+ /**
* Draw a selection group over an unwrapped alignment
- * @param g graphics object to draw with
- * @param group selection group
- * @param startRes start residue of area to draw
- * @param endRes end residue of area to draw
- * @param startSeq start sequence of area to draw
- * @param endSeq end sequence of area to draw
- * @param offset vertical offset (used when called from wrapped alignment code)
+ *
+ * @param g
+ * graphics object to draw with
+ * @param group
+ * selection group
+ * @param startRes
+ * start residue of area to draw
+ * @param endRes
+ * end residue of area to draw
+ * @param startSeq
+ * start sequence of area to draw
+ * @param endSeq
+ * end sequence of area to draw
+ * @param offset
+ * vertical offset (used when called from wrapped alignment code)
*/
private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
int startRes, int endRes, int startSeq, int endSeq, int offset)
{
int charWidth = av.getCharWidth();
-
+
if (!av.hasHiddenColumns())
{
drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq,
@@ -1400,8 +1334,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
blockStart = region[0];
g.translate(screenY * charWidth, 0);
- drawPartialGroupOutline(g, group,
- blockStart, blockEnd, startSeq, endSeq, offset);
+ drawPartialGroupOutline(g, group, blockStart, blockEnd, startSeq,
+ endSeq, offset);
g.translate(-screenY * charWidth, 0);
screenY += blockEnd - blockStart + 1;
@@ -1409,8 +1343,16 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
}
- /*
- * Draw the selection group as a separate image and overlay
+ /**
+ * Draws part of a selection group outline
+ *
+ * @param g
+ * @param group
+ * @param startRes
+ * @param endRes
+ * @param startSeq
+ * @param endSeq
+ * @param verticalOffset
*/
private void drawPartialGroupOutline(Graphics2D g, SequenceGroup group,
int startRes, int endRes, int startSeq, int endSeq,
@@ -1465,7 +1407,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
else if (inGroup)
{
- drawVerticals(g, sx, xwidth, visWidth, oldY, sy);
+ drawVerticals(g, sx, xwidth, visWidth, oldY, bottom);
drawHorizontals(g, sx, xwidth, visWidth, top, bottom);
// reset top and bottom
@@ -1477,7 +1419,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
if (inGroup)
{
sy = verticalOffset + ((i - startSeq) * charHeight);
- drawVerticals(g, sx, xwidth, visWidth, oldY, sy);
+ drawVerticals(g, sx, xwidth, visWidth, oldY,
+ bottom == -1 ? sy : bottom);
drawHorizontals(g, sx, xwidth, visWidth, top, bottom);
}
}
@@ -1552,17 +1495,17 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
// group
if (sx >= 0 && sx < visWidth)
{
- g.drawLine(sx, oldY, sx, sy);
+ g.drawLine(sx, oldY, sx, sy - 1);
}
// if end position is visible, draw vertical line to right of
// group
if (sx + xwidth < visWidth)
{
- g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
+ g.drawLine(sx + xwidth, oldY, sx + xwidth, sy - 1);
}
}
-
+
/**
* Highlights search results in the visible region by rendering as white text
* on a black background. Any previous highlighting is removed. Answers true
@@ -1578,7 +1521,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
return highlightSearchResults(results, false);
}
-
+
/**
* Highlights search results in the visible region by rendering as white text
* on a black background. Any previous highlighting is removed. Answers true
@@ -1736,13 +1679,14 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
{
firstCol = alignment.getHiddenColumns()
.absoluteToVisibleColumn(firstCol);
- lastCol = alignment.getHiddenColumns().absoluteToVisibleColumn(lastCol);
+ lastCol = alignment.getHiddenColumns()
+ .absoluteToVisibleColumn(lastCol);
}
int transX = (firstCol - ranges.getStartRes()) * av.getCharWidth();
int transY = (firstSeq - ranges.getStartSeq()) * av.getCharHeight();
Graphics gg = img.getGraphics();
gg.translate(transX, transY);
- drawPanel(gg, firstCol, lastCol, firstSeq, lastSeq, 0);
+ drawPanel(seqRdr, gg, firstCol, lastCol, firstSeq, lastSeq, 0);
gg.translate(-transX, -transY);
gg.dispose();
}
@@ -1754,7 +1698,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
public void propertyChange(PropertyChangeEvent evt)
{
String eventName = evt.getPropertyName();
-
+ // jalview.bin.Console.errPrintln(">>SeqCanvas propertyChange " +
+ // eventName);
if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED))
{
fastPaint = true;
@@ -1764,6 +1709,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT))
{
fastPaint = false;
+ // jalview.bin.Console.errPrintln("!!!! fastPaint false from
+ // MOVE_VIEWPORT");
repaint();
return;
}
@@ -1785,7 +1732,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
ViewportRanges vpRanges = av.getRanges();
- int range = vpRanges.getEndRes() - vpRanges.getStartRes();
+ int range = vpRanges.getEndRes() - vpRanges.getStartRes() + 1;
if (scrollX > range)
{
scrollX = range;
@@ -1795,37 +1742,37 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
scrollX = -range;
}
}
- // Both scrolling and resizing change viewport ranges: scrolling changes
- // both start and end points, but resize only changes end values.
- // Here we only want to fastpaint on a scroll, with resize using a normal
- // paint, so scroll events are identified as changes to the horizontal or
- // vertical start value.
- if (eventName.equals(ViewportRanges.STARTRES))
+ // Both scrolling and resizing change viewport ranges: scrolling changes
+ // both start and end points, but resize only changes end values.
+ // Here we only want to fastpaint on a scroll, with resize using a normal
+ // paint, so scroll events are identified as changes to the horizontal or
+ // vertical start value.
+ if (eventName.equals(ViewportRanges.STARTRES))
+ {
+ if (av.getWrapAlignment())
{
- if (av.getWrapAlignment())
- {
- fastPaintWrapped(scrollX);
- }
- else
- {
- fastPaint(scrollX, 0);
- }
+ fastPaintWrapped(scrollX);
}
- else if (eventName.equals(ViewportRanges.STARTSEQ))
+ else
{
- // scroll
- fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+ fastPaint(scrollX, 0);
}
- else if (eventName.equals(ViewportRanges.STARTRESANDSEQ))
+ }
+ else if (eventName.equals(ViewportRanges.STARTSEQ))
+ {
+ // scroll
+ fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+ }
+ else if (eventName.equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ if (av.getWrapAlignment())
{
- if (av.getWrapAlignment())
- {
- fastPaintWrapped(scrollX);
- }
- else
- {
- fastPaint(scrollX, 0);
- }
+ fastPaintWrapped(scrollX);
+ }
+ else
+ {
+ fastPaint(scrollX, 0);
+ }
}
else if (eventName.equals(ViewportRanges.STARTSEQ))
{
@@ -1854,10 +1801,10 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
{
ViewportRanges ranges = av.getRanges();
- if (Math.abs(scrollX) > ranges.getViewportWidth())
+ if (Math.abs(scrollX) >= ranges.getViewportWidth())
{
/*
- * shift of more than one view width is
+ * shift of one view width or more is
* overcomplicated to handle in this method
*/
fastPaint = false;
@@ -1875,9 +1822,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
try
{
-
+
Graphics gg = img.getGraphics();
-
+
calculateWrappedGeometry(getWidth(), getHeight());
/*
@@ -1893,8 +1840,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
if (scrollX < 0)
{
int startRes = ranges.getStartRes();
- drawWrappedWidth(gg, wrappedSpaceAboveAlignment, startRes, startRes
- - scrollX - 1, getHeight());
+ drawWrappedWidth(seqRdr, gg, wrappedSpaceAboveAlignment, startRes,
+ startRes - scrollX - 1, getHeight());
}
else
{
@@ -1907,7 +1854,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
drawWrappedDecorators(gg, ranges.getStartRes());
gg.dispose();
-
+
repaint();
} finally
{
@@ -1932,7 +1879,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
Graphics gg = img.getGraphics();
-
+
ViewportRanges ranges = av.getRanges();
int viewportWidth = ranges.getViewportWidth();
int charWidth = av.getCharWidth();
@@ -1943,7 +1890,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
*/
int visibleWidths = wrappedVisibleWidths;
int canvasHeight = getHeight();
- boolean lastWidthPartHeight = (wrappedVisibleWidths * wrappedRepeatHeightPx) > canvasHeight;
+ boolean lastWidthPartHeight = (wrappedVisibleWidths
+ * wrappedRepeatHeightPx) > canvasHeight;
if (lastWidthPartHeight)
{
@@ -1959,16 +1907,15 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
/*
* white fill first to erase annotations
*/
-
-
+
gg.translate(xOffset, 0);
gg.setColor(Color.white);
- gg.fillRect(labelWidthWest, ypos,
- (endRes - startRes + 1) * charWidth, wrappedRepeatHeightPx);
+ gg.fillRect(labelWidthWest, ypos, (endRes - startRes + 1) * charWidth,
+ wrappedRepeatHeightPx);
gg.translate(-xOffset, 0);
- drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
-
+ drawWrappedWidth(seqRdr, gg, ypos, startRes, endRes, canvasHeight);
+
}
/*
@@ -2000,7 +1947,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
if (startRes < ranges.getVisibleAlignmentWidth())
{
- drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+ drawWrappedWidth(seqRdr, gg, ypos, startRes, endRes, canvasHeight);
}
/*
@@ -2013,7 +1960,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
gg.fillRect(0, canvasHeight - heightBelow, getWidth(), heightBelow);
}
gg.dispose();
- }
+ }
/**
* Shifts the visible alignment by the specified number of columns - left if
@@ -2062,10 +2009,17 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
while (y >= 0)
{
+ /*
+ * shift 'widthToCopy' residues by 'positions' places to the right
+ */
gg.copyArea(copyFromLeftStart, y, widthToCopy, heightToCopy,
positions * charWidth, 0);
if (y > 0)
{
+ /*
+ * copy 'positions' residue from the row above (right hand end)
+ * to this row's left hand end
+ */
gg.copyArea(copyFromRightStart, y - wrappedRepeatHeightPx,
positions * charWidth, heightToCopy, -widthToCopy,
wrappedRepeatHeightPx);
@@ -2094,8 +2048,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
if (y + wrappedRepeatHeightPx < canvasHeight - wrappedRepeatHeightPx
&& (xpos + viewportWidth <= xMax))
{
- gg.copyArea(labelWidthWest, y + wrappedRepeatHeightPx, -positions
- * charWidth, heightToCopy, widthToCopy,
+ gg.copyArea(labelWidthWest, y + wrappedRepeatHeightPx,
+ -positions * charWidth, heightToCopy, widthToCopy,
-wrappedRepeatHeightPx);
}
y += wrappedRepeatHeightPx;
@@ -2105,7 +2059,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
gg.dispose();
}
-
/**
* Redraws any positions in the search results in the visible region of a
* wrapped alignment. Any highlights are drawn depending on the search results
@@ -2139,8 +2092,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
int firstVisibleColumn = ranges.getStartRes();
- int lastVisibleColumn = ranges.getStartRes() + repeats
- * ranges.getViewportWidth() - 1;
+ int lastVisibleColumn = ranges.getStartRes()
+ + repeats * ranges.getViewportWidth() - 1;
AlignmentI alignment = av.getAlignment();
if (av.hasHiddenColumns())
@@ -2153,7 +2106,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
int gapHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
-
Graphics gg = img.getGraphics();
for (int seqNo = ranges.getStartSeq(); seqNo <= ranges
@@ -2197,8 +2149,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
* transX: offset from left edge of canvas to residue position
*/
int transX = labelWidthWest
- + ((displayColumn - ranges.getStartRes()) % wrappedWidth)
- * av.getCharWidth();
+ + ((displayColumn - ranges.getStartRes())
+ % wrappedWidth) * av.getCharWidth();
/*
* transY: offset from top edge of canvas to residue position
@@ -2216,8 +2168,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
{
matchFound = true;
gg.translate(transX, transY);
- drawPanel(gg, displayColumn, displayColumn, seqNo, seqNo,
- yOffset);
+ drawPanel(seqRdr, gg, displayColumn, displayColumn, seqNo,
+ seqNo, yOffset);
gg.translate(-transX, -transY);
}
}
@@ -2225,7 +2177,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
}
}
}
-
+
gg.dispose();
return matchFound;
@@ -2240,4 +2192,5 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
{
return labelWidthWest;
}
+
}