From 8f11fde42942229be12283a3b82ac2405dbbdd8f Mon Sep 17 00:00:00 2001 From: kiramt Date: Wed, 16 Aug 2017 08:13:04 +0100 Subject: [PATCH] JAL-2665 Draw selection group - works on scroll but not when static --- src/jalview/gui/SeqCanvas.java | 268 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 245 insertions(+), 23 deletions(-) diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index edb41e6..a289dba 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -30,6 +30,7 @@ import jalview.renderer.ScaleRenderer.ScaleMark; import jalview.viewmodel.ViewportListenerI; import jalview.viewmodel.ViewportRanges; +import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; @@ -356,16 +357,74 @@ public class SeqCanvas extends JComponent implements ViewportListenerI // img and call later. super.paintComponent(g); + BufferedImage selectImage = drawSelectionGroup(); + if (lcimg != null && (fastPaint || (getVisibleRect().width != g.getClipBounds().width) || (getVisibleRect().height != g .getClipBounds().height))) { + Graphics2D g2 = (Graphics2D) lcimg.getGraphics(); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); + // g.drawImage(lcimg, 0, 0, this); + + // overlay selection group on lcimg + if (selectImage != null) + { + g2.setComposite( + AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); + g2.drawImage(selectImage, 0, 0, this); + } g.drawImage(lcimg, 0, 0, this); + fastPaint = false; return; } + lcimg = setupImage(lcimg); + // img = lcimg; + if (lcimg == null) + { + return; + } + + if (av.antiAlias) + { + gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + } + + gg.setColor(Color.white); + gg.fillRect(0, 0, imgWidth, imgHeight); + + ViewportRanges ranges = av.getRanges(); + if (av.getWrapAlignment()) + { + drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes()); + } + else + { + drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(), + ranges.getStartSeq(), ranges.getEndSeq(), 0); + } + + Graphics2D g2 = (Graphics2D) lcimg.getGraphics(); + // g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); + // g.drawImage(lcimg, 0, 0, this); // scrolling only works with g not g2??? + + // overlay selection group on lcimg + if (selectImage != null) + { + g2.setComposite( + AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); + g2.drawImage(selectImage, 0, 0, this); + } + g.drawImage(lcimg, 0, 0, this); + // g.drawImage(selectImage, 0, 0, this); + } + + private BufferedImage setupImage(BufferedImage lcimg) + { // this draws the whole of the alignment imgWidth = getWidth(); imgHeight = getHeight(); @@ -375,7 +434,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI if ((imgWidth < 1) || (imgHeight < 1)) { - return; + return null; } if (lcimg == null || imgWidth != lcimg.getWidth() @@ -384,7 +443,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI try { lcimg = img = new BufferedImage(imgWidth, imgHeight, - BufferedImage.TYPE_INT_RGB); + BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works gg = (Graphics2D) img.getGraphics(); gg.setFont(av.getFont()); } catch (OutOfMemoryError er) @@ -393,32 +452,42 @@ public class SeqCanvas extends JComponent implements ViewportListenerI System.err.println("SeqCanvas OutOfMemory Redraw Error.\n" + er); new OOMWarning("Creating alignment image for display", er); - return; + return null; } } + return lcimg; + } - if (av.antiAlias) - { - gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - } + private BufferedImage setupSelectionImage() + { + BufferedImage lcimg = null; - gg.setColor(Color.white); - gg.fillRect(0, 0, imgWidth, imgHeight); + int width = getWidth(); + int height = getHeight(); - ViewportRanges ranges = av.getRanges(); - if (av.getWrapAlignment()) + width -= (width % charWidth); + height -= (height % charHeight); + + if ((width < 1) || (height < 1)) { - drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes()); + return null; } - else + + try { - drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(), - ranges.getStartSeq(), ranges.getEndSeq(), 0); - } + lcimg = new BufferedImage(imgWidth, imgHeight, + BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works + } catch (OutOfMemoryError er) + { + System.gc(); + System.err.println( + "Selection Group image OutOfMemory Redraw Error.\n" + er); + new OOMWarning("Creating alignment image for display", er); - g.drawImage(lcimg, 0, 0, this); + return null; + } + return lcimg; } /** @@ -794,7 +863,9 @@ public class SeqCanvas extends JComponent implements ViewportListenerI // /////////////////////////////////// // Now outline any areas if necessary // /////////////////////////////////// - SequenceGroup group = av.getSelectionGroup(); + // SequenceGroup group = av.getSelectionGroup(); + + SequenceGroup group = null; int sx = -1; int sy = -1; @@ -802,7 +873,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI int groupIndex = -1; int visWidth = (endRes - startRes + 1) * charWidth; - if ((group == null) && (av.getAlignment().getGroups().size() > 0)) + // if ((group == null) && (av.getAlignment().getGroups().size() > 0)) + if (av.getAlignment().getGroups().size() > 0) { group = av.getAlignment().getGroups().get(0); groupIndex = 0; @@ -854,7 +926,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI oldY = sy; inGroup = true; - if (group == av.getSelectionGroup()) + /*if (group == av.getSelectionGroup()) { g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f }, @@ -862,10 +934,10 @@ public class SeqCanvas extends JComponent implements ViewportListenerI g.setColor(Color.RED); } else - { + {*/ g.setStroke(new BasicStroke()); g.setColor(group.getOutlineColour()); - } + // } } } else @@ -981,6 +1053,156 @@ public class SeqCanvas extends JComponent implements ViewportListenerI } + /* + * Draw the selection group as a separate image and overlay + */ + private BufferedImage drawSelectionGroup() + { + // get a new image of the correct size + BufferedImage selectionImage = setupSelectionImage(); + + if (selectionImage == null) + { + return null; + } + + SequenceGroup group = av.getSelectionGroup(); + if (group == null) + { + // nothing to draw + return null; + } + + // set up drawing colour + Graphics2D g = (Graphics2D) selectionImage.getGraphics(); + // set background to transparent + g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f)); + g.fillRect(0, 0, selectionImage.getWidth(), selectionImage.getHeight()); + + 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); + + int visWidth = av.getRanges().getViewportWidth() * charWidth; + + int startRes = av.getRanges().getStartRes(); + + // set x start and end positions of group + int startx = (group.getStartRes() - startRes) * charWidth; + int endx = (group.getEndRes() - startRes + 1) * charWidth; + + int oldY = -1; + int i = 0; + boolean inGroup = false; + int top = -1; + int bottom = -1; + + // get sequences to determine y positions of group + int startSeq = av.getRanges().getStartSeq(); + for (i = startSeq; i <= av.getRanges().getEndSeq(); ++i) + { + int sy = (i - startSeq) * charHeight; + + if (group.getSequences(null) + .contains(av.getAlignment().getSequenceAt(i))) + { + if ((bottom == -1) && !group.getSequences(null) + .contains(av.getAlignment().getSequenceAt(i + 1))) + { + bottom = sy + charHeight; + } + + if (!inGroup) + { + if (((top == -1) && (i == 0)) || !group.getSequences(null) + .contains(av.getAlignment().getSequenceAt(i - 1))) + { + top = sy; + } + + oldY = sy; + inGroup = true; + } + } + else + { + if (inGroup) + { + // if start position is visible, draw vertical line to left of + // group + if (startx >= 0 && startx < visWidth * charWidth) + { + g.drawLine(startx, oldY, startx, sy); + } + + // if end position is visible, draw vertical line to right of + // group + if (endx <= visWidth * charWidth) + { + g.drawLine(endx, oldY, endx, sy); + } + + if (endx > visWidth * charWidth) + { + endx = visWidth * charWidth; + } + + // draw horizontal line at top of group + if (top != -1) + { + g.drawLine(startx, top, endx, top); + top = -1; + } + + // draw horizontal line at bottom of group + if (bottom != -1) + { + g.drawLine(startx, bottom, endx, bottom); + bottom = -1; + } + + inGroup = false; + } + } + } + if (inGroup) + { + int sy = (i - startSeq) * charHeight; + if (startx >= 0 && startx < visWidth) + { + g.drawLine(startx, oldY, startx, sy); + } + + if (endx < visWidth) + { + g.drawLine(endx, oldY, endx, sy); + } + + if (endx > visWidth) + { + endx = visWidth; + } + + if (top != -1) + { + g.drawLine(startx, top, endx, top); + top = -1; + } + + if (bottom != -1) + { + g.drawLine(startx, bottom - 1, endx, bottom - 1); + bottom = -1; + } + + inGroup = false; + } + + return selectionImage; + } + /** * DOCUMENT ME! * -- 1.7.10.2