X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FAlignmentPanel.java;h=92b9a5065cd1b64168b5eb2ffa4a4b0a40023d33;hb=16d109024847af92482237e43f99b82fd997451a;hp=631638fb133107dcf16fcacc801eb42a5c214967;hpb=5edb685cf52a607834a82c10cb4dd9c139e31dde;p=jalview.git diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index 631638f..92b9a50 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -25,16 +25,20 @@ import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; import jalview.bin.Cache; import jalview.datamodel.AlignmentI; +import jalview.datamodel.HiddenColumns; import jalview.datamodel.SearchResultsI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.io.HTMLOutput; import jalview.jbgui.GAlignmentPanel; import jalview.math.AlignmentDimension; import jalview.schemes.ResidueProperties; import jalview.structure.StructureSelectionManager; +import jalview.util.Comparison; import jalview.util.MessageManager; -import jalview.util.Platform; +import jalview.viewmodel.ViewportListenerI; +import jalview.viewmodel.ViewportRanges; import java.awt.BorderLayout; import java.awt.Color; @@ -43,9 +47,11 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; -import java.awt.Insets; +import java.awt.Graphics2D; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; @@ -65,7 +71,7 @@ import javax.swing.SwingUtilities; * @version $Revision: 1.161 $ */ public class AlignmentPanel extends GAlignmentPanel implements - AdjustmentListener, Printable, AlignmentViewPanel + AdjustmentListener, Printable, AlignmentViewPanel, ViewportListenerI { public AlignViewport av; @@ -88,21 +94,20 @@ public class AlignmentPanel extends GAlignmentPanel implements private AnnotationLabels alabels; - // this value is set false when selection area being dragged - boolean fastPaint = true; - private int hextent = 0; private int vextent = 0; /* * Flag set while scrolling to follow complementary cDNA/protein scroll. When - * true, suppresses invoking the same method recursively. + * false, suppresses invoking the same method recursively. */ - private boolean dontScrollComplement; + private boolean scrollComplementaryPanel = true; private PropertyChangeListener propertyChangeListener; + private CalculationChooser calculationDialog; + /** * Creates a new AlignmentPanel object. * @@ -136,6 +141,35 @@ public class AlignmentPanel extends GAlignmentPanel implements hscroll.addAdjustmentListener(this); vscroll.addAdjustmentListener(this); + addComponentListener(new ComponentAdapter() + { + @Override + public void componentResized(ComponentEvent evt) + { + // reset the viewport ranges when the alignment panel is resized + // in particular, this initialises the end residue value when Jalview + // is initialised + ViewportRanges ranges = av.getRanges(); + if (av.getWrapAlignment()) + { + int widthInRes = getSeqPanel().seqCanvas.getWrappedCanvasWidth( + getSeqPanel().seqCanvas.getWidth()); + ranges.setViewportWidth(widthInRes); + } + else + { + int widthInRes = getSeqPanel().seqCanvas.getWidth() + / av.getCharWidth(); + int heightInSeq = getSeqPanel().seqCanvas.getHeight() + / av.getCharHeight(); + + ranges.setViewportWidth(widthInRes); + ranges.setViewportHeight(heightInSeq); + } + } + + }); + final AlignmentPanel ap = this; propertyChangeListener = new PropertyChangeListener() { @@ -150,6 +184,8 @@ public class AlignmentPanel extends GAlignmentPanel implements } }; av.addPropertyChangeListener(propertyChangeListener); + + av.getRanges().addPropertyChangeListener(this); fontChanged(); adjustAnnotationHeight(); updateLayout(); @@ -165,9 +201,15 @@ public class AlignmentPanel extends GAlignmentPanel implements { av.alignmentChanged(this); + if (getCalculationDialog() != null) + { + getCalculationDialog().validateCalcTypes(); + } + alignFrame.updateEditMenuBar(); - paintAlignment(true); + // no idea if we need to update structure + paintAlignment(true, true); } @@ -180,11 +222,12 @@ public class AlignmentPanel extends GAlignmentPanel implements // to prevent drawing old image FontMetrics fm = getFontMetrics(av.getFont()); - scalePanelHolder.setPreferredSize(new Dimension(10, av.getCharHeight() - + fm.getDescent())); - idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av - .getCharHeight() + fm.getDescent())); - + scalePanelHolder.setPreferredSize( + new Dimension(10, av.getCharHeight() + fm.getDescent())); + idSpaceFillerPanel1.setPreferredSize( + new Dimension(10, av.getCharHeight() + fm.getDescent())); + idwidthAdjuster.invalidate(); + scalePanelHolder.invalidate(); getIdPanel().getIdCanvas().gg = null; getSeqPanel().seqCanvas.img = null; getAnnotationPanel().adjustPanelHeight(); @@ -195,15 +238,6 @@ public class AlignmentPanel extends GAlignmentPanel implements getIdPanel().getIdCanvas().setPreferredSize(d); hscrollFillerPanel.setPreferredSize(d); - if (overviewPanel != null) - { - overviewPanel.setBoxPosition(); - } - if (this.alignFrame.getSplitViewContainer() != null) - { - ((SplitFrame) this.alignFrame.getSplitViewContainer()).adjustLayout(); - } - repaint(); } @@ -247,8 +281,8 @@ public class AlignmentPanel extends GAlignmentPanel implements { Container c = new Container(); - FontMetrics fm = c.getFontMetrics(new Font(av.font.getName(), - Font.ITALIC, av.font.getSize())); + FontMetrics fm = c.getFontMetrics( + new Font(av.font.getName(), Font.ITALIC, av.font.getSize())); AlignmentI al = av.getAlignment(); int i = 0; @@ -289,29 +323,21 @@ public class AlignmentPanel extends GAlignmentPanel implements } } - return new Dimension(maxwidth < 0 ? idWidth : Math.min(maxwidth, - idWidth), 12); + return new Dimension( + maxwidth < 0 ? idWidth : Math.min(maxwidth, idWidth), 12); } /** - * Highlight the given results on the alignment. + * Highlight the given results on the alignment * */ public void highlightSearchResults(SearchResultsI results) { - scrollToPosition(results); - getSeqPanel().seqCanvas.highlightSearchResults(results); - } + boolean scrolled = scrollToPosition(results, 0, false); - /** - * Scroll the view to show the position of the highlighted region in results - * (if any) and redraw the overview - * - * @param results - */ - public boolean scrollToPosition(SearchResultsI results) - { - return scrollToPosition(results, 0, true, false); + boolean noFastPaint = scrolled && av.getWrapAlignment(); + + getSeqPanel().seqCanvas.highlightSearchResults(results, noFastPaint); } /** @@ -319,157 +345,137 @@ public class AlignmentPanel extends GAlignmentPanel implements * (if any) * * @param searchResults - * @param redrawOverview * @return */ - public boolean scrollToPosition(SearchResultsI searchResults, - boolean redrawOverview) + public boolean scrollToPosition(SearchResultsI searchResults) { - return scrollToPosition(searchResults, 0, redrawOverview, false); + return scrollToPosition(searchResults, 0, false); } /** - * Scroll the view to show the position of the highlighted region in results - * (if any) + * Scrolls the view (if necessary) to show the position of the first + * highlighted region in results (if any). Answers true if the view was + * scrolled, or false if no matched region was found, or it is already + * visible. * * @param results * @param verticalOffset * if greater than zero, allows scrolling to a position below the * first displayed sequence - * @param redrawOverview - * - when set, the overview will be recalculated (takes longer) * @param centre * if true, try to centre the search results horizontally in the view - * @return false if results were not found + * @return */ - public boolean scrollToPosition(SearchResultsI results, - int verticalOffset, boolean redrawOverview, boolean centre) + protected boolean scrollToPosition(SearchResultsI results, + int verticalOffset, boolean centre) { int startv, endv, starts, ends; - // TODO: properly locate search results in view when large numbers of hidden - // columns exist before highlighted region - // do we need to scroll the panel? - // TODO: tons of nullpointerexceptions raised here. - if (results != null && results.getSize() > 0 && av != null - && av.getAlignment() != null) - { - int seqIndex = av.getAlignment().findIndex(results); - if (seqIndex == -1) - { - return false; - } - SequenceI seq = av.getAlignment().getSequenceAt(seqIndex); + ViewportRanges ranges = av.getRanges(); - int[] r = results.getResults(seq, 0, av.getAlignment().getWidth()); - if (r == null) - { - return false; - } - int start = r[0]; - int end = r[1]; - // DEBUG - // System.err.println(this.av.viewName + " Seq : " + seqIndex - // + " Scroll to " + start + "," + end); + if (results == null || results.isEmpty() || av == null + || av.getAlignment() == null) + { + return false; + } + int seqIndex = av.getAlignment().findIndex(results); + if (seqIndex == -1) + { + return false; + } + SequenceI seq = av.getAlignment().getSequenceAt(seqIndex); - /* - * To centre results, scroll to positions half the visible width - * left/right of the start/end positions - */ - if (centre) - { - int offset = (av.getEndRes() - av.getStartRes() + 1) / 2 - 1; - start = Math.max(start - offset, 0); - end = end + offset - 1; - } - if (start < 0) - { - return false; - } - if (end == seq.getEnd()) - { - return false; - } - if (av.hasHiddenColumns()) + int[] r = results.getResults(seq, 0, av.getAlignment().getWidth()); + if (r == null) + { + return false; + } + int start = r[0]; + int end = r[1]; + + /* + * To centre results, scroll to positions half the visible width + * left/right of the start/end positions + */ + if (centre) + { + int offset = (ranges.getEndRes() - ranges.getStartRes() + 1) / 2 - 1; + start = Math.max(start - offset, 0); + end = end + offset - 1; + } + if (start < 0) + { + return false; + } + if (end == seq.getEnd()) + { + return false; + } + + if (av.hasHiddenColumns()) + { + HiddenColumns hidden = av.getAlignment().getHiddenColumns(); + start = hidden.absoluteToVisibleColumn(start); + end = hidden.absoluteToVisibleColumn(end); + if (start == end) { - start = av.getColumnSelection().findColumnPosition(start); - end = av.getColumnSelection().findColumnPosition(end); - if (start == end) + if (!hidden.isVisible(r[0])) { - if (!av.getColumnSelection().isVisible(r[0])) - { - // don't scroll - position isn't visible - return false; - } + // don't scroll - position isn't visible + return false; } } + } - /* - * allow for offset of target sequence (actually scroll to one above it) - */ - seqIndex = Math.max(0, seqIndex - verticalOffset); + /* + * allow for offset of target sequence (actually scroll to one above it) + */ + seqIndex = Math.max(0, seqIndex - verticalOffset); + boolean scrollNeeded = true; - // System.out.println("start=" + start + ", end=" + end + ", startv=" - // + av.getStartRes() + ", endv=" + av.getEndRes() + ", starts=" - // + av.getStartSeq() + ", ends=" + av.getEndSeq()); - if (!av.getWrapAlignment()) + if (!av.getWrapAlignment()) + { + if ((startv = ranges.getStartRes()) >= start) { - if ((startv = av.getStartRes()) >= start) - { - /* - * Scroll left to make start of search results visible - */ - // setScrollValues(start - 1, seqIndex); // plus one residue - setScrollValues(start, seqIndex); - } - else if ((endv = av.getEndRes()) <= end) - { - /* - * Scroll right to make end of search results visible - */ - // setScrollValues(startv + 1 + end - endv, seqIndex); // plus one - setScrollValues(startv + end - endv, seqIndex); - } - else if ((starts = av.getStartSeq()) > seqIndex) - { - /* - * Scroll up to make start of search results visible - */ - setScrollValues(av.getStartRes(), seqIndex); - } - else if ((ends = av.getEndSeq()) <= seqIndex) - { - /* - * Scroll down to make end of search results visible - */ - setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1); - } /* - * Else results are already visible - no need to scroll + * Scroll left to make start of search results visible */ + setScrollValues(start, seqIndex); } - else + else if ((endv = ranges.getEndRes()) <= end) + { + /* + * Scroll right to make end of search results visible + */ + setScrollValues(startv + end - endv, seqIndex); + } + else if ((starts = ranges.getStartSeq()) > seqIndex) + { + /* + * Scroll up to make start of search results visible + */ + setScrollValues(ranges.getStartRes(), seqIndex); + } + else if ((ends = ranges.getEndSeq()) <= seqIndex) { - scrollToWrappedVisible(start); + /* + * Scroll down to make end of search results visible + */ + setScrollValues(ranges.getStartRes(), starts + seqIndex - ends + + 1); } + /* + * Else results are already visible - no need to scroll + */ + scrollNeeded = false; } - if (redrawOverview && overviewPanel != null) + else { - overviewPanel.setBoxPosition(); + scrollNeeded = ranges.scrollToWrappedVisible(start); } - paintAlignment(redrawOverview); - return true; - } - void scrollToWrappedVisible(int res) - { - int cwidth = getSeqPanel().seqCanvas - .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth()); - if (res < av.getStartRes() || res >= (av.getStartRes() + cwidth)) - { - vscroll.setValue((res / cwidth)); - av.setStartRes(vscroll.getValue() * cwidth); - } + paintAlignment(false, false); + return scrollNeeded; } /** @@ -524,7 +530,9 @@ public class AlignmentPanel extends GAlignmentPanel implements } validateAnnotationDimensions(true); addNotify(); - paintAlignment(true); + // TODO: many places call this method and also paintAlignment with various + // different settings. this means multiple redraws are triggered... + paintAlignment(true, av.needToUpdateStructureViews()); } /** @@ -534,42 +542,12 @@ public class AlignmentPanel extends GAlignmentPanel implements protected void validateAnnotationDimensions(boolean adjustPanelHeight) { int annotationHeight = getAnnotationPanel().adjustPanelHeight(); + annotationHeight = getAnnotationPanel() + .adjustForAlignFrame(adjustPanelHeight, annotationHeight); - if (adjustPanelHeight) - { - int rowHeight = av.getCharHeight(); - int alignmentHeight = rowHeight * av.getAlignment().getHeight(); - - /* - * Estimate available height in the AlignFrame for alignment + - * annotations. Deduct an estimate for title bar, menu bar, scale panel, - * hscroll, status bar (as these are not laid out we can't inspect their - * actual heights). Insets gives frame borders. - */ - int stuff = Platform.isAMac() ? 80 : 100; - Insets insets = alignFrame.getInsets(); - int availableHeight = alignFrame.getHeight() - stuff - insets.top - - insets.bottom; - - /* - * If not enough vertical space, maximize annotation height while keeping - * at least two rows of alignment visible - */ - if (annotationHeight + alignmentHeight > availableHeight) - { - annotationHeight = Math.min(annotationHeight, availableHeight - 2 - * rowHeight); - } - } - else - { - // maintain same window layout whilst updating sliders - annotationHeight = annotationScroller.getSize().height; - } hscroll.addNotify(); - - annotationScroller.setPreferredSize(new Dimension(annotationScroller - .getWidth(), annotationHeight)); + annotationScroller.setPreferredSize( + new Dimension(annotationScroller.getWidth(), annotationHeight)); Dimension e = idPanel.getSize(); alabels.setSize(new Dimension(e.width, annotationHeight)); @@ -591,7 +569,8 @@ public class AlignmentPanel extends GAlignmentPanel implements fontChanged(); setAnnotationVisible(av.isShowAnnotation()); boolean wrap = av.getWrapAlignment(); - av.setStartSeq(0); + ViewportRanges ranges = av.getRanges(); + ranges.setStartSeq(0); scalePanelHolder.setVisible(!wrap); hscroll.setVisible(!wrap); idwidthAdjuster.setVisible(!wrap); @@ -605,76 +584,32 @@ public class AlignmentPanel extends GAlignmentPanel implements { annotationScroller.setVisible(true); annotationSpaceFillerHolder.setVisible(true); + validateAnnotationDimensions(false); } - idSpaceFillerPanel1.setVisible(!wrap); - - repaint(); - } - - // return value is true if the scroll is valid - public boolean scrollUp(boolean up) - { - if (up) - { - if (vscroll.getValue() < 1) + int canvasWidth = getSeqPanel().seqCanvas.getWidth(); + if (canvasWidth > 0) + { // may not yet be laid out + if (wrap) { - return false; + int widthInRes = getSeqPanel().seqCanvas + .getWrappedCanvasWidth(canvasWidth); + ranges.setViewportWidth(widthInRes); } - - fastPaint = false; - vscroll.setValue(vscroll.getValue() - 1); - } - else - { - if ((vextent + vscroll.getValue()) >= av.getAlignment().getHeight()) - { - return false; - } - - fastPaint = false; - vscroll.setValue(vscroll.getValue() + 1); - } - - fastPaint = true; - - return true; - } - - /** - * DOCUMENT ME! - * - * @param right - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public boolean scrollRight(boolean right) - { - if (!right) - { - if (hscroll.getValue() < 1) + else { - return false; - } + int widthInRes = (canvasWidth / av.getCharWidth()); + int heightInSeq = (getSeqPanel().seqCanvas.getHeight() + / av.getCharHeight()); - fastPaint = false; - hscroll.setValue(hscroll.getValue() - 1); - } - else - { - if ((hextent + hscroll.getValue()) >= av.getAlignment().getWidth()) - { - return false; + ranges.setViewportWidth(widthInRes); + ranges.setViewportHeight(heightInSeq); } - - fastPaint = false; - hscroll.setValue(hscroll.getValue() + 1); } - fastPaint = true; + idSpaceFillerPanel1.setVisible(!wrap); - return true; + repaint(); } /** @@ -686,183 +621,188 @@ public class AlignmentPanel extends GAlignmentPanel implements * visible row to scroll to * */ - public void setScrollValues(int x, int y) + public void setScrollValues(int xpos, int ypos) { + int x = xpos; + int y = ypos; + if (av == null || av.getAlignment() == null) { return; } - int width = av.getAlignment().getWidth(); - int height = av.getAlignment().getHeight(); - if (av.hasHiddenColumns()) + if (av.getWrapAlignment()) { - // reset the width to exclude hidden columns - width = av.getColumnSelection().findColumnPosition(width); + setScrollingForWrappedPanel(x); } - - hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth(); - vextent = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight(); - - if (hextent > width) + else { - hextent = width; - } + int width = av.getAlignment().getVisibleWidth(); + int height = av.getAlignment().getHeight(); - if (vextent > height) - { - vextent = height; - } + hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth(); + vextent = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight(); - if ((hextent + x) > width) - { - x = width - hextent; - } + if (hextent > width) + { + hextent = width; + } - if ((vextent + y) > height) - { - y = height - vextent; - } + if (vextent > height) + { + vextent = height; + } - if (y < 0) - { - y = 0; - } + if ((hextent + x) > width) + { + x = width - hextent; + } - if (x < 0) - { - x = 0; - } + if ((vextent + y) > height) + { + y = height - vextent; + } - // update endRes after x has (possibly) been adjusted - av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av - .getCharWidth())) - 1); + if (y < 0) + { + y = 0; + } - /* - * each scroll adjustment triggers adjustmentValueChanged, which resets the - * 'do not scroll complement' flag; ensure it is the same for both - * operations - */ - boolean flag = isDontScrollComplement(); - hscroll.setValues(x, hextent, 0, width); - setDontScrollComplement(flag); - vscroll.setValues(y, vextent, 0, height); + if (x < 0) + { + x = 0; + } + + // update the scroll values + hscroll.setValues(x, hextent, 0, width); + vscroll.setValues(y, vextent, 0, height); + } } /** - * DOCUMENT ME! + * Respond to adjustment event when horizontal or vertical scrollbar is + * changed * * @param evt - * DOCUMENT ME! + * adjustment event encoding whether hscroll or vscroll changed */ @Override public void adjustmentValueChanged(AdjustmentEvent evt) { - int oldX = av.getStartRes(); - int oldY = av.getStartSeq(); - - if (evt.getSource() == hscroll) + if (av.getWrapAlignment()) { - int x = hscroll.getValue(); - av.setStartRes(x); - av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av - .getCharWidth())) - 1); + adjustScrollingWrapped(evt); + return; } - if (evt.getSource() == vscroll) + ViewportRanges ranges = av.getRanges(); + + if (evt.getSource() == hscroll) { - int offy = vscroll.getValue(); + int oldX = ranges.getStartRes(); + int oldwidth = ranges.getViewportWidth(); + int x = hscroll.getValue(); + int width = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth(); - if (av.getWrapAlignment()) + // if we're scrolling to the position we're already at, stop + // this prevents infinite recursion of events when the scroll/viewport + // ranges values are the same + if ((x == oldX) && (width == oldwidth)) { - if (offy > -1) - { - int rowSize = getSeqPanel().seqCanvas - .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth()); - av.setStartRes(offy * rowSize); - av.setEndRes((offy + 1) * rowSize); - } - else - { - // This is only called if file loaded is a jar file that - // was wrapped when saved and user has wrap alignment true - // as preference setting - SwingUtilities.invokeLater(new Runnable() - { - @Override - public void run() - { - setScrollValues(av.getStartRes(), av.getStartSeq()); - } - }); - } + return; } - else + ranges.setViewportStartAndWidth(x, width); + } + else if (evt.getSource() == vscroll) + { + int oldY = ranges.getStartSeq(); + int oldheight = ranges.getViewportHeight(); + int y = vscroll.getValue(); + int height = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight(); + + // if we're scrolling to the position we're already at, stop + // this prevents infinite recursion of events when the scroll/viewport + // ranges values are the same + if ((y == oldY) && (height == oldheight)) { - av.setStartSeq(offy); - av.setEndSeq(offy - + (getSeqPanel().seqCanvas.getHeight() / av.getCharHeight()) - - 1); + return; } + ranges.setViewportStartAndHeight(y, height); } + repaint(); + } - if (overviewPanel != null) + /** + * Responds to a scroll change by setting the start position of the viewport. + * Does + * + * @param evt + */ + protected void adjustScrollingWrapped(AdjustmentEvent evt) + { + if (evt.getSource() == hscroll) { - overviewPanel.setBoxPosition(); + return; // no horizontal scroll when wrapped } + final ViewportRanges ranges = av.getRanges(); - int scrollX = av.getStartRes() - oldX; - int scrollY = av.getStartSeq() - oldY; - - if (av.getWrapAlignment() || !fastPaint) - { - repaint(); - } - else + if (evt.getSource() == vscroll) { - // Make sure we're not trying to draw a panel - // larger than the visible window - if (scrollX > av.getEndRes() - av.getStartRes()) - { - scrollX = av.getEndRes() - av.getStartRes(); - } - else if (scrollX < av.getStartRes() - av.getEndRes()) + int newY = vscroll.getValue(); + + /* + * if we're scrolling to the position we're already at, stop + * this prevents infinite recursion of events when the scroll/viewport + * ranges values are the same + */ + int oldX = ranges.getStartRes(); + int oldY = ranges.getWrappedScrollPosition(oldX); + if (oldY == newY) { - scrollX = av.getStartRes() - av.getEndRes(); + return; } - - if (scrollX != 0 || scrollY != 0) + if (newY > -1) { - getIdPanel().getIdCanvas().fastPaint(scrollY); - getSeqPanel().seqCanvas.fastPaint(scrollX, scrollY); - getScalePanel().repaint(); - - if (av.isShowAnnotation() && scrollX != 0) - { - getAnnotationPanel().fastPaint(scrollX); - } + /* + * limit page up/down to one width's worth of positions + */ + int rowSize = ranges.getViewportWidth(); + int newX = newY > oldY ? oldX + rowSize : oldX - rowSize; + ranges.setViewportStartAndWidth(Math.max(0, newX), rowSize); } } - /* - * If there is one, scroll the (Protein/cDNA) complementary alignment to - * match, unless we are ourselves doing that. - */ - if (isDontScrollComplement()) - { - setDontScrollComplement(false); - } else { - av.scrollComplementaryAlignment(); + // This is only called if file loaded is a jar file that + // was wrapped when saved and user has wrap alignment true + // as preference setting + SwingUtilities.invokeLater(new Runnable() + { + @Override + public void run() + { + // When updating scrolling to use ViewportChange events, this code + // could not be validated and it is not clear if it is now being + // called. Log warning here in case it is called and unforeseen + // problems occur + Cache.log.warn( + "Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences"); + + // scroll to start of panel + ranges.setStartRes(0); + ranges.setStartSeq(0); + } + }); } + repaint(); } - /** - * Repaint the alignment including the annotations and overview panels (if - * shown). + /* (non-Javadoc) + * @see jalview.api.AlignmentViewPanel#paintAlignment(boolean) */ @Override - public void paintAlignment(boolean updateOverview) + public void paintAlignment(boolean updateOverview, + boolean updateStructures) { final AnnotationSorter sorter = new AnnotationSorter(getAlignment(), av.isShowAutocalculatedAbove()); @@ -870,10 +810,12 @@ public class AlignmentPanel extends GAlignmentPanel implements av.getSortAnnotationsBy()); repaint(); - if (updateOverview) + if (updateStructures) { - // TODO: determine if this paintAlignment changed structure colours av.getStructureSelectionManager().sequenceColoursChanged(this); + } + if (updateOverview) + { if (overviewPanel != null) { @@ -891,45 +833,41 @@ public class AlignmentPanel extends GAlignmentPanel implements @Override public void paintComponent(Graphics g) { - invalidate(); + invalidate(); // needed so that the id width adjuster works correctly Dimension d = getIdPanel().getIdCanvas().getPreferredSize(); idPanelHolder.setPreferredSize(d); hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12)); - validate(); + + validate(); // needed so that the id width adjuster works correctly /* - * set scroll bar positions; first suppress this being 'followed' in any - * complementary split pane + * set scroll bar positions - tried to remove but necessary for split panel to resize correctly + * though I still think this call should be elsewhere. */ - setDontScrollComplement(true); - - if (av.getWrapAlignment()) - { - int maxwidth = av.getAlignment().getWidth(); + ViewportRanges ranges = av.getRanges(); + setScrollValues(ranges.getStartRes(), ranges.getStartSeq()); + } - if (av.hasHiddenColumns()) - { - maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1; - } + /** + * Set vertical scroll bar position, and number of increments, for wrapped + * panel + * + * @param topLeftColumn + * the column position at top left (0..) + */ + private void setScrollingForWrappedPanel(int topLeftColumn) + { + ViewportRanges ranges = av.getRanges(); + int scrollPosition = ranges.getWrappedScrollPosition(topLeftColumn); + int maxScroll = ranges.getWrappedMaxScroll(topLeftColumn); - int canvasWidth = getSeqPanel().seqCanvas - .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth()); - if (canvasWidth > 0) - { - int max = maxwidth - / getSeqPanel().seqCanvas - .getWrappedCanvasWidth(getSeqPanel().seqCanvas - .getWidth()) + 1; - vscroll.setMaximum(max); - vscroll.setUnitIncrement(1); - vscroll.setVisibleAmount(1); - } - } - else - { - setScrollValues(av.getStartRes(), av.getStartSeq()); - } + /* + * a scrollbar's value can be set to at most (maximum-extent) + * so we add extent (1) to the maxScroll value + */ + vscroll.setUnitIncrement(1); + vscroll.setValues(scrollPosition, 1, 0, maxScroll + 1); } /** @@ -967,30 +905,16 @@ public class AlignmentPanel extends GAlignmentPanel implements } /** - * DOCUMENT ME! - * - * @param pg - * DOCUMENT ME! - * @param pwidth - * DOCUMENT ME! - * @param pheight - * DOCUMENT ME! - * @param pi - * DOCUMENT ME! - * - * @return DOCUMENT ME! - * - * @throws PrinterException - * DOCUMENT ME! - */ - /** * Draws the alignment image, including sequence ids, sequences, and * annotation labels and annotations if shown, on either one or two Graphics - * context. + * contexts. * * @param pageWidth + * in pixels * @param pageHeight - * @param pi + * in pixels + * @param pageIndex + * (0, 1, ...) * @param idGraphics * the graphics context for sequence ids and annotation labels * @param alignmentGraphics @@ -999,7 +923,7 @@ public class AlignmentPanel extends GAlignmentPanel implements * @return * @throws PrinterException */ - public int printUnwrapped(int pageWidth, int pageHeight, int pi, + public int printUnwrapped(int pageWidth, int pageHeight, int pageIndex, Graphics idGraphics, Graphics alignmentGraphics) throws PrinterException { @@ -1009,11 +933,12 @@ public class AlignmentPanel extends GAlignmentPanel implements * Get the horizontal offset to where we draw the sequences. * This is idWidth if using a single Graphics context, else zero. */ - final int alignmentGraphicsOffset = idGraphics != alignmentGraphics ? 0 : idWidth; + final int alignmentGraphicsOffset = idGraphics != alignmentGraphics ? 0 + : idWidth; FontMetrics fm = getFontMetrics(av.getFont()); - int charHeight = av.getCharHeight(); - int scaleHeight = charHeight + fm.getDescent(); + final int charHeight = av.getCharHeight(); + final int scaleHeight = charHeight + fm.getDescent(); idGraphics.setColor(Color.white); idGraphics.fillRect(0, 0, pageWidth, pageHeight); @@ -1022,32 +947,22 @@ public class AlignmentPanel extends GAlignmentPanel implements /* * How many sequences and residues can we fit on a printable page? */ - int totalRes = (pageWidth - idWidth) / av.getCharWidth(); + final int totalRes = (pageWidth - idWidth) / av.getCharWidth(); - int totalSeq = (pageHeight - scaleHeight) / charHeight - 1; + final int totalSeq = (pageHeight - scaleHeight) / charHeight - 1; - int alignmentWidth = av.getAlignment().getWidth(); + final int alignmentWidth = av.getAlignment().getVisibleWidth(); int pagesWide = (alignmentWidth / totalRes) + 1; - final int startRes = (pi % pagesWide) * totalRes; - int endRes = (startRes + totalRes) - 1; - - if (endRes > (alignmentWidth - 1)) - { - endRes = alignmentWidth - 1; - } - - final int startSeq = (pi / pagesWide) * totalSeq; - int endSeq = startSeq + totalSeq; + final int startRes = (pageIndex % pagesWide) * totalRes; + final int endRes = Math.min(startRes + totalRes - 1, + alignmentWidth - 1); - int alignmentHeight = av.getAlignment().getHeight(); - if (endSeq > alignmentHeight) - { - endSeq = alignmentHeight; - } + final int startSeq = (pageIndex / pagesWide) * totalSeq; + final int alignmentHeight = av.getAlignment().getHeight(); + final int endSeq = Math.min(startSeq + totalSeq, alignmentHeight); - int pagesHigh = ((alignmentHeight / totalSeq) + 1) - * pageHeight; + int pagesHigh = ((alignmentHeight / totalSeq) + 1) * pageHeight; if (av.isShowAnnotation()) { @@ -1056,12 +971,11 @@ public class AlignmentPanel extends GAlignmentPanel implements pagesHigh /= pageHeight; - if (pi >= (pagesWide * pagesHigh)) + if (pageIndex >= (pagesWide * pagesHigh)) { return Printable.NO_SUCH_PAGE; } - final int alignmentDrawnHeight = (endSeq - startSeq) * charHeight - + 3; + final int alignmentDrawnHeight = (endSeq - startSeq) * charHeight + 3; /* * draw the Scale at horizontal offset, then reset to top left (0, 0) @@ -1076,49 +990,12 @@ public class AlignmentPanel extends GAlignmentPanel implements * then reset to top left (0, 0) */ idGraphics.translate(0, scaleHeight); - idGraphics.setFont(getIdPanel().getIdCanvas().getIdfont()); - Color currentColor = null; - Color currentTextColor = null; - - SequenceI seq; - for (int i = startSeq; i < endSeq; i++) - { - seq = av.getAlignment().getSequenceAt(i); - if ((av.getSelectionGroup() != null) - && av.getSelectionGroup().getSequences(null).contains(seq)) - { - /* - * gray out ids of sequences in selection group (if any) - */ - currentColor = Color.gray; - currentTextColor = Color.black; - } - else - { - currentColor = av.getSequenceColour(seq); - currentTextColor = Color.black; - } + IdCanvas idCanvas = getIdPanel().getIdCanvas(); + List selection = av.getSelectionGroup() == null ? null + : av.getSelectionGroup().getSequences(null); + idCanvas.drawIds((Graphics2D) idGraphics, av, startSeq, endSeq - 1, + selection); - idGraphics.setColor(currentColor); - idGraphics.fillRect(0, (i - startSeq) * charHeight, idWidth, - charHeight); - - idGraphics.setColor(currentTextColor); - - int xPos = 0; - String displayId = seq.getDisplayId(av.getShowJVSuffix()); - if (av.isRightAlignIds()) - { - fm = idGraphics.getFontMetrics(); - xPos = idWidth - - fm.stringWidth(displayId) - - 4; - } - - idGraphics.drawString(displayId, xPos, - (((i - startSeq) * charHeight) + charHeight) - - (charHeight / 5)); - } idGraphics.setFont(av.getFont()); idGraphics.translate(0, -scaleHeight); @@ -1127,8 +1004,8 @@ public class AlignmentPanel extends GAlignmentPanel implements * single graphics context), then reset to (0, scale height) */ alignmentGraphics.translate(alignmentGraphicsOffset, scaleHeight); - getSeqPanel().seqCanvas.drawPanel(alignmentGraphics, startRes, endRes, - startSeq, endSeq, 0); + getSeqPanel().seqCanvas.drawPanelForPrinting(alignmentGraphics, startRes, + endRes, startSeq, endSeq - 1); alignmentGraphics.translate(-alignmentGraphicsOffset, 0); if (av.isShowAnnotation() && (endSeq == alignmentHeight)) @@ -1148,7 +1025,8 @@ public class AlignmentPanel extends GAlignmentPanel implements * draw the annotations starting at * (idOffset, alignmentHeight) from (0, scaleHeight) */ - alignmentGraphics.translate(alignmentGraphicsOffset, alignmentDrawnHeight); + alignmentGraphics.translate(alignmentGraphicsOffset, + alignmentDrawnHeight); getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av, alignmentGraphics, -1, startRes, endRes + 1); } @@ -1157,31 +1035,27 @@ public class AlignmentPanel extends GAlignmentPanel implements } /** - * DOCUMENT ME! + * Prints one page of an alignment in wrapped mode. Returns + * Printable.PAGE_EXISTS (0) if a page was drawn, or Printable.NO_SUCH_PAGE if + * no page could be drawn (page number out of range). * - * @param pg - * DOCUMENT ME! - * @param pwidth - * DOCUMENT ME! - * @param pheight - * DOCUMENT ME! - * @param pi - * DOCUMENT ME! + * @param pageWidth + * @param pageHeight + * @param pageNumber + * (0, 1, ...) + * @param g * - * @return DOCUMENT ME! + * @return * * @throws PrinterException - * DOCUMENT ME! */ - public int printWrappedAlignment(int pwidth, int pheight, int pi, - Graphics pg) throws PrinterException + public int printWrappedAlignment(int pageWidth, int pageHeight, int pageNumber, + Graphics g) throws PrinterException { int annotationHeight = 0; - AnnotationLabels labels = null; if (av.isShowAnnotation()) { annotationHeight = getAnnotationPanel().adjustPanelHeight(); - labels = new AnnotationLabels(av); } int hgap = av.getCharHeight(); @@ -1195,74 +1069,42 @@ public class AlignmentPanel extends GAlignmentPanel implements int idWidth = getVisibleIdWidth(false); - int maxwidth = av.getAlignment().getWidth(); - if (av.hasHiddenColumns()) - { - maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1; - } + int maxwidth = av.getAlignment().getVisibleWidth(); - int resWidth = getSeqPanel().seqCanvas.getWrappedCanvasWidth(pwidth - - idWidth); + int resWidth = getSeqPanel().seqCanvas + .getWrappedCanvasWidth(pageWidth - idWidth); int totalHeight = cHeight * (maxwidth / resWidth + 1); - pg.setColor(Color.white); - pg.fillRect(0, 0, pwidth, pheight); - pg.setFont(av.getFont()); - - // ////////////// - // Draw the ids - pg.setColor(Color.black); - - pg.translate(0, -pi * pheight); - - pg.setClip(0, pi * pheight, pwidth, pheight); + g.setColor(Color.white); + g.fillRect(0, 0, pageWidth, pageHeight); + g.setFont(av.getFont()); + g.setColor(Color.black); - int ypos = hgap; + /* + * method: print the whole wrapped alignment, but with a clip region that + * is restricted to the requested page; this supports selective print of + * single pages or ranges, (at the cost of some repeated processing in + * the 'normal' case, when all pages are printed) + */ + g.translate(0, -pageNumber * pageHeight); - do - { - for (int i = 0; i < av.getAlignment().getHeight(); i++) - { - pg.setFont(getIdPanel().getIdCanvas().getIdfont()); - SequenceI s = av.getAlignment().getSequenceAt(i); - String string = s.getDisplayId(av.getShowJVSuffix()); - int xPos = 0; - if (av.isRightAlignIds()) - { - FontMetrics fm = pg.getFontMetrics(); - xPos = idWidth - fm.stringWidth(string) - 4; - } - pg.drawString(string, xPos, - ((i * av.getCharHeight()) + ypos + av.getCharHeight()) - - (av.getCharHeight() / 5)); - } - if (labels != null) - { - pg.translate(-3, - ypos + (av.getAlignment().getHeight() * av.getCharHeight())); - - pg.setFont(av.getFont()); - labels.drawComponent(pg, idWidth); - pg.translate( - +3, - -ypos - - (av.getAlignment().getHeight() * av - .getCharHeight())); - } + g.setClip(0, pageNumber * pageHeight, pageWidth, pageHeight); - ypos += cHeight; - } while (ypos < totalHeight); + /* + * draw sequence ids and annotation labels (if shown) + */ + IdCanvas idCanvas = getIdPanel().getIdCanvas(); + idCanvas.drawIdsWrapped((Graphics2D) g, av, 0, totalHeight); - pg.translate(idWidth, 0); + g.translate(idWidth, 0); - getSeqPanel().seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, + getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(g, pageWidth - idWidth, totalHeight, 0); - if ((pi * pheight) < totalHeight) + if ((pageNumber * pageHeight) < totalHeight) { return Printable.PAGE_EXISTS; - } else { @@ -1298,8 +1140,8 @@ public class AlignmentPanel extends GAlignmentPanel implements return calculateIdWidth(-1).width + 4; } Integer idwidth = null; - if (onscreen - || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null) + if (onscreen || (idwidth = Cache + .getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null) { int w = getIdPanel().getWidth(); return (w > 0 ? w : calculateIdWidth().width + 4); @@ -1311,15 +1153,15 @@ public class AlignmentPanel extends GAlignmentPanel implements { int boarderBottomOffset = 5; long pSessionId = System.currentTimeMillis(); - headless = (System.getProperty("java.awt.headless") != null && System - .getProperty("java.awt.headless").equals("true")); + headless = (System.getProperty("java.awt.headless") != null + && System.getProperty("java.awt.headless").equals("true")); if (alignFrame != null && !headless) { if (file != null) { - alignFrame.setProgressBar(MessageManager.formatMessage( - "status.saving_file", new Object[] { type.getLabel() }), - pSessionId); + alignFrame.setProgressBar(MessageManager + .formatMessage("status.saving_file", new Object[] + { type.getLabel() }), pSessionId); } } try @@ -1346,9 +1188,9 @@ public class AlignmentPanel extends GAlignmentPanel implements } im = new jalview.util.ImageMaker(this, type, imageAction, - aDimension.getWidth(), aDimension.getHeight() - + boarderBottomOffset, file, imageTitle, - alignFrame, pSessionId, headless); + aDimension.getWidth(), + aDimension.getHeight() + boarderBottomOffset, file, + imageTitle, alignFrame, pSessionId, headless); Graphics graphics = im.getGraphics(); if (av.getWrapAlignment()) { @@ -1364,8 +1206,8 @@ public class AlignmentPanel extends GAlignmentPanel implements { if (graphics != null) { - printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), - 0, graphics, graphics); + printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0, + graphics, graphics); im.writeImage(); } } @@ -1389,11 +1231,7 @@ public class AlignmentPanel extends GAlignmentPanel implements public AlignmentDimension getAlignmentDimension() { - int maxwidth = av.getAlignment().getWidth(); - if (av.hasHiddenColumns()) - { - maxwidth = av.getColumnSelection().findColumnPosition(maxwidth); - } + int maxwidth = av.getAlignment().getVisibleWidth(); int height = ((av.getAlignment().getHeight() + 1) * av.getCharHeight()) + getScalePanel().getHeight(); @@ -1409,9 +1247,8 @@ public class AlignmentPanel extends GAlignmentPanel implements // this duplicates the calculation in getWrappedHeight but adjusts for // offscreen idWith width = alignFrame.getWidth() - vscroll.getPreferredSize().width - - alignFrame.getInsets().left - - alignFrame.getInsets().right - getVisibleIdWidth() - + getVisibleIdWidth(false); + - alignFrame.getInsets().left - alignFrame.getInsets().right + - getVisibleIdWidth() + getVisibleIdWidth(false); } else { @@ -1462,33 +1299,32 @@ public class AlignmentPanel extends GAlignmentPanel implements { try { - int s, sSize = av.getAlignment().getHeight(), res, alwidth = av - .getAlignment().getWidth(), g, gSize, f, fSize, sy; + int sSize = av.getAlignment().getHeight(); + int alwidth = av.getAlignment().getWidth(); PrintWriter out = new PrintWriter(new FileWriter(imgMapFile)); - out.println(jalview.io.HTMLOutput.getImageMapHTML()); + out.println(HTMLOutput.getImageMapHTML()); out.println("" + ""); - for (s = 0; s < sSize; s++) + for (int s = 0; s < sSize; s++) { - sy = s * av.getCharHeight() + scaleHeight; + int sy = s * av.getCharHeight() + scaleHeight; SequenceI seq = av.getAlignment().getSequenceAt(s); - SequenceFeature[] features = seq.getSequenceFeatures(); SequenceGroup[] groups = av.getAlignment().findAllGroups(seq); - for (res = 0; res < alwidth; res++) + for (int column = 0; column < alwidth; column++) { - StringBuilder text = new StringBuilder(); + StringBuilder text = new StringBuilder(512); String triplet = null; if (av.getAlignment().isNucleotide()) { triplet = ResidueProperties.nucleotideName.get(seq - .getCharAt(res) + ""); + .getCharAt(column) + ""); } else { - triplet = ResidueProperties.aa2Triplet.get(seq.getCharAt(res) + triplet = ResidueProperties.aa2Triplet.get(seq.getCharAt(column) + ""); } @@ -1497,84 +1333,73 @@ public class AlignmentPanel extends GAlignmentPanel implements continue; } - int alIndex = seq.findPosition(res); - gSize = groups.length; - for (g = 0; g < gSize; g++) + int seqPos = seq.findPosition(column); + int gSize = groups.length; + for (int g = 0; g < gSize; g++) { if (text.length() < 1) { text.append(" res) + if (groups[g].getStartRes() < column + && groups[g].getEndRes() > column) { text.append("
").append(groups[g].getName()) .append(""); } } - if (features != null) + if (text.length() < 1) { - if (text.length() < 1) - { - text.append(" features = seq.findFeatures(column, column); + for (SequenceFeature sf : features) { - - if ((features[f].getBegin() <= seq.findPosition(res)) - && (features[f].getEnd() >= seq.findPosition(res))) + if (sf.isContactFeature()) { - if (features[f].isContactFeature()) - { - if (features[f].getBegin() == seq.findPosition(res) - || features[f].getEnd() == seq - .findPosition(res)) - { - text.append("
").append(features[f].getType()) - .append(" ").append(features[f].getBegin()) - .append(":").append(features[f].getEnd()); - } - } - else + text.append("
").append(sf.getType()).append(" ") + .append(sf.getBegin()).append(":") + .append(sf.getEnd()); + } + else + { + text.append("
"); + text.append(sf.getType()); + String description = sf.getDescription(); + if (description != null + && !sf.getType().equals(description)) { - text.append("
"); - text.append(features[f].getType()); - if (features[f].getDescription() != null - && !features[f].getType().equals( - features[f].getDescription())) - { - text.append(" ").append(features[f].getDescription()); - } - - if (features[f].getValue("status") != null) - { - text.append(" (").append(features[f].getValue("status")) - .append(")"); - } + description = description.replace("\"", """); + text.append(" ").append(description); } } - + String status = sf.getStatus(); + if (status != null && !"".equals(status)) + { + text.append(" (").append(status).append(")"); + } + } + if (text.length() > 1) + { + text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">"); + out.println(text.toString()); } - } - if (text.length() > 1) - { - text.append("')\"; onMouseOut=\"toolTip()\"; href=\"#\">"); - out.println(text.toString()); } } } @@ -1622,7 +1447,8 @@ public class AlignmentPanel extends GAlignmentPanel implements int maxwidth = av.getAlignment().getWidth(); if (av.hasHiddenColumns()) { - maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1; + maxwidth = av.getAlignment().getHiddenColumns() + .absoluteToVisibleColumn(maxwidth) - 1; } int height = ((maxwidth / chunkWidth) + 1) * cHeight; @@ -1640,19 +1466,22 @@ public class AlignmentPanel extends GAlignmentPanel implements PaintRefresher.RemoveComponent(getIdPanel().getIdCanvas()); PaintRefresher.RemoveComponent(this); + closeChildFrames(); + /* * try to ensure references are nulled */ if (annotationPanel != null) { annotationPanel.dispose(); + annotationPanel = null; } if (av != null) { av.removePropertyChangeListener(propertyChangeListener); - jalview.structure.StructureSelectionManager ssm = av - .getStructureSelectionManager(); + propertyChangeListener = null; + StructureSelectionManager ssm = av.getStructureSelectionManager(); ssm.removeStructureViewerListener(getSeqPanel(), null); ssm.removeSelectionListener(getSeqPanel()); ssm.removeCommandListener(av); @@ -1671,6 +1500,23 @@ public class AlignmentPanel extends GAlignmentPanel implements } /** + * Close any open dialogs that would be orphaned when this one is closed + */ + protected void closeChildFrames() + { + if (overviewPanel != null) + { + overviewPanel.dispose(); + overviewPanel = null; + } + if (calculationDialog != null) + { + calculationDialog.closeFrame(); + calculationDialog = null; + } + } + + /** * hides or shows dynamic annotation rows based on groups and av state flags */ public void updateAnnotation() @@ -1700,7 +1546,7 @@ public class AlignmentPanel extends GAlignmentPanel implements @Override public String getViewName() { - return av.viewName; + return av.getViewName(); } /** @@ -1829,52 +1675,93 @@ public class AlignmentPanel extends GAlignmentPanel implements * @param verticalOffset * the number of visible sequences to show above the mapped region */ - public void scrollToCentre(SearchResultsI sr, int verticalOffset) + protected void scrollToCentre(SearchResultsI sr, int verticalOffset) { - /* - * To avoid jumpy vertical scrolling (if some sequences are gapped or not - * mapped), we can make the scroll-to location a sequence above the one - * actually mapped. - */ - SequenceI mappedTo = sr.getResults().get(0).getSequence(); - List seqs = av.getAlignment().getSequences(); + scrollToPosition(sr, verticalOffset, true); + } - /* - * This is like AlignmentI.findIndex(seq) but here we are matching the - * dataset sequence not the aligned sequence - */ - boolean matched = false; - for (SequenceI seq : seqs) + /** + * Set a flag to say do not scroll any (cDNA/protein) complement. + * + * @param b + */ + protected void setToScrollComplementPanel(boolean b) + { + this.scrollComplementaryPanel = b; + } + + /** + * Get whether to scroll complement panel + * + * @return true if cDNA/protein complement panels should be scrolled + */ + protected boolean isSetToScrollComplementPanel() + { + return this.scrollComplementaryPanel; + } + + /** + * Redraw sensibly. + * + * @adjustHeight if true, try to recalculate panel height for visible + * annotations + */ + protected void refresh(boolean adjustHeight) + { + validateAnnotationDimensions(adjustHeight); + addNotify(); + if (adjustHeight) { - if (mappedTo == seq.getDatasetSequence()) - { - matched = true; - break; - } + // sort, repaint, update overview + paintAlignment(true, false); } - if (!matched) + else { - return; // failsafe, shouldn't happen + // lightweight repaint + repaint(); } + } - /* - * Scroll to position but centring the target residue. - */ - scrollToPosition(sr, verticalOffset, true, true); + @Override + /** + * Property change event fired when a change is made to the viewport ranges + * object associated with this alignment panel's viewport + */ + public void propertyChange(PropertyChangeEvent evt) + { + // update this panel's scroll values based on the new viewport ranges values + ViewportRanges ranges = av.getRanges(); + int x = ranges.getStartRes(); + int y = ranges.getStartSeq(); + setScrollValues(x, y); + + // now update any complementary alignment (its viewport ranges object + // is different so does not get automatically updated) + if (isSetToScrollComplementPanel()) + { + setToScrollComplementPanel(false); + av.scrollComplementaryAlignment(); + setToScrollComplementPanel(true); + } } /** - * Set a flag to say do not scroll any (cDNA/protein) complement. + * Set the reference to the PCA/Tree chooser dialog for this panel. This + * reference should be nulled when the dialog is closed. * - * @param b + * @param calculationChooser */ - protected void setDontScrollComplement(boolean b) + public void setCalculationDialog(CalculationChooser calculationChooser) { - this.dontScrollComplement = b; + calculationDialog = calculationChooser; } - protected boolean isDontScrollComplement() + /** + * Returns the reference to the PCA/Tree chooser dialog for this panel (null + * if none is open) + */ + public CalculationChooser getCalculationDialog() { - return this.dontScrollComplement; + return calculationDialog; } }