import jalview.util.Comparison;
import jalview.util.ImageMaker;
import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
import jalview.viewmodel.ViewportListenerI;
import jalview.viewmodel.ViewportRanges;
*/
public AlignmentPanel(AlignFrame af, final AlignViewport av)
{
+ setName("AligmentPanel");
// setBackground(Color.white); // BH 2019
alignFrame = af;
this.av = av;
ranges.setViewportWidth(widthInRes);
ranges.setViewportHeight(heightInSeq);
}
+ repaint();
}
});
@Override
public void propertyChange(PropertyChangeEvent evt)
{
- if (evt.getPropertyName().equals("alignment"))
- {
+ switch (evt.getPropertyName()) {
+ case AlignmentViewport.PROPERTY_SEQUENCE:
+ updateScrollBarsFromRanges();
+ if (annotationPanel != null)
+ annotationPanel.paintImmediately(0, 0, getWidth(), getHeight());
+ break;
+ case AlignmentViewport.PROPERTY_ALIGNMENT:
+ updateScrollBarsFromRanges();
PaintRefresher.Refresh(ap, av.getSequenceSetId(), true, true);
alignmentChanged();
+ break;
}
}
};
int oldWidth = av.getIdWidth();
// calculate sensible default width when no preference is available
- Dimension r = null;
+ Dimension d = null;
if (av.getIdWidth() < 0)
{
- int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
- int idWidth = Math.min(afwidth - 200, 2 * afwidth / 3);
- int maxwidth = Math.max(IdwidthAdjuster.MIN_ID_WIDTH, idWidth);
- r = calculateIdWidth(maxwidth);
- av.setIdWidth(r.width);
+ int maxWidth = getMaxWidth();
+ d = calculateIdWidth(maxWidth);
+ av.setIdWidth(d.width);
}
else
{
- r = new Dimension();
- r.width = av.getIdWidth();
- r.height = 0;
+ d = new Dimension();
+ d.width = av.getIdWidth();
+ d.height = 0;
}
/*
* fudge: if desired width has changed, update layout
* (see also paintComponent - updates layout on a repaint)
*/
- if (r.width != oldWidth)
+ if (d.width != oldWidth)
{
- idPanelHolder.setPreferredSize(r);
+ idPanelHolder.setPreferredSize(d);
validate();
}
- return r;
+ return d;
+ }
+
+ public int getMaxWidth()
+ {
+ int afwidth = (alignFrame != null ? alignFrame.getWidth() : 300);
+ int idWidth = Math.min(afwidth - 200, 2 * afwidth / 3);
+ return Math.max(IdwidthAdjuster.MIN_ID_WIDTH, idWidth);
}
/**
* @return Dimension giving the maximum width of the alignment label panel
* that should be used.
*/
- protected Dimension calculateIdWidth(int maxwidth)
+ public Dimension calculateIdWidth(int maxwidth)
{
- Container c = new Container();
+ Container c = this;// new Container();
FontMetrics fm = c.getFontMetrics(
new Font(av.font.getName(), Font.ITALIC, av.font.getSize()));
int i = 0;
int idWidth = 0;
+ boolean withSuffix = av.getShowJVSuffix();
while ((i < al.getHeight()) && (al.getSequenceAt(i) != null))
{
SequenceI s = al.getSequenceAt(i);
- String id = s.getDisplayId(av.getShowJVSuffix());
+ String id = s.getDisplayId(withSuffix);
int stringWidth = fm.stringWidth(id);
idWidth = Math.max(idWidth, stringWidth);
i++;
{
// BH 2018.04.18 comment: addNotify() is not appropriate here. We
// are not changing ancestors, and keyboard action listeners do
- // not need to be reset. addNotify() is a very expensive operation,
+ // not need to be reset, and most importantly, we can't be sure we are actually
+ // connected to resources.
+
+ // addNotify() is a very expensive operation,
// requiring a full re-layout of all parents and children.
+
// Note in JComponent:
+
// This method is called by the toolkit internally and should
// not be called directly by programs.
+
// I note that addNotify() is called in several areas of Jalview.
int annotationHeight = getAnnotationPanel().adjustPanelHeight();
annotationHeight = getAnnotationPanel()
.adjustForAlignFrame(adjustPanelHeight, annotationHeight);
+ // BH no!!
hscroll.addNotify();
annotationScroller.setPreferredSize(
new Dimension(annotationScroller.getWidth(), annotationHeight));
Dimension e = idPanel.getSize();
alabels.setSize(new Dimension(e.width, annotationHeight));
+
annotationSpaceFillerHolder.setPreferredSize(new Dimension(
annotationSpaceFillerHolder.getWidth(), annotationHeight));
annotationScroller.validate();
/**
* update alignment layout for viewport settings
- *
- * @param wrap
- * DOCUMENT ME!
*/
public void updateLayout()
{
+ ViewportRanges ranges = av.getRanges();
fontChanged();
setAnnotationVisible(av.isShowAnnotation());
boolean wrap = av.getWrapAlignment();
- ViewportRanges ranges = av.getRanges();
ranges.setStartSeq(0);
scalePanelHolder.setVisible(!wrap);
hscroll.setVisible(!wrap);
{
annotationScroller.setVisible(true);
annotationSpaceFillerHolder.setVisible(true);
+ }
+
+ idSpaceFillerPanel1.setVisible(!wrap);
+
+ /*
+ * defer dimension calculations if panel not yet added to a Window
+ * BH 2020.06.09
+ */
+ if (getTopLevelAncestor() == null)
+ {
+ repaint();
+ return;
+ }
+
+ if (!wrap && av.isShowAnnotation())
+ {
validateAnnotationDimensions(false);
}
}
}
- idSpaceFillerPanel1.setVisible(!wrap);
+ // System.out.println("ap dim = " + getSize());
+ // these values will go negative if getSize() returns (0,0):
+ // System.out.println("seqpan dim = " + getSeqPanel().getSize());
+ // System.out.println("seqcan dim = " + getSeqPanel().seqCanvas.getSize());
repaint();
}
* visible row to scroll to
*
*/
- public void setScrollValues(int xpos, int ypos)
+ public void setScrollValues(int x, int y)
{
- int x = xpos;
- int y = ypos;
if (av == null || av.getAlignment() == null)
{
int width = av.getAlignment().getVisibleWidth();
int height = av.getAlignment().getHeight();
- hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
- vextent = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight();
-
- if (hextent > width)
- {
- hextent = width;
- }
-
- if (vextent > height)
- {
- vextent = height;
- }
-
- if ((hextent + x) > width)
- {
- x = width - hextent;
- }
-
- if ((vextent + y) > height)
- {
- y = height - vextent;
- }
-
- if (y < 0)
- {
- y = 0;
- }
-
- if (x < 0)
- {
- x = 0;
- }
-
- // update the scroll values
- hscroll.setValues(x, hextent, 0, width);
- vscroll.setValues(y, vextent, 0, height);
+
+ hextent = Math.min(getSeqPanel().seqCanvas.getWidth() / av.getCharWidth(), width);
+ vextent = Math.min(getSeqPanel().seqCanvas.getHeight() / av.getCharHeight(), height);
+
+ x = Math.max(0, Math.min(x, width - hextent));
+ y = Math.max(0, Math.min(y, height - vextent));
+
+ updateRanges(x, y);
+ updateScrollBars(x, y, width, height);
}
}
+ private void updateScrollBars(int x, int y, int width, int height)
+ {
+ hscroll.setValues(x, hextent, 0, width);
+ vscroll.setValues(y, vextent, 0, height);
+ }
/**
* Respond to adjustment event when horizontal or vertical scrollbar is
* changed
return;
}
- ViewportRanges ranges = av.getRanges();
if (evt.getSource() == hscroll)
{
+ if (!updateRanges(hscroll.getValue(), Integer.MIN_VALUE))
+ return;
+ }
+ else if (evt.getSource() == vscroll)
+ {
+ if (!updateRanges(Integer.MIN_VALUE, vscroll.getValue()))
+ return;
+ }
+ repaint();
+ }
+
+ private boolean updateRanges(int x, int y)
+ {
+ ViewportRanges ranges = av.getRanges();
+ boolean isChanged = false;
+ if (x != Integer.MIN_VALUE)
+ {
int oldX = ranges.getStartRes();
int oldwidth = ranges.getViewportWidth();
- int x = hscroll.getValue();
int width = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
// 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 (width > 0 && (x != oldX || width != oldwidth))
{
- return;
+ ranges.setViewportStartAndWidth(x, width);
+ isChanged = true;
}
- ranges.setViewportStartAndWidth(x, width);
}
- else if (evt.getSource() == vscroll)
+ if (y != Integer.MIN_VALUE)
{
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))
+ if (height > 0 && (y != oldY || height != oldheight))
{
- return;
+ ranges.setViewportStartAndHeight(y, height);
+ isChanged = true;
}
- ranges.setViewportStartAndHeight(y, height);
}
- repaint();
+ return isChanged;
}
/**
av.isShowAutocalculatedAbove());
sorter.sort(getAlignment().getAlignmentAnnotation(),
av.getSortAnnotationsBy());
- repaint();
if (updateStructures)
{
if (updateOverview)
{
+ alignFrame.repaint();
if (overviewPanel != null)
{
overviewPanel.updateOverviewImage();
}
+ } else {
+ invalidate(); // needed so that the id width adjuster works correctly
+ repaint();
}
}
@Override
public void paintComponent(Graphics g)
{
+ // BH OUCH!
invalidate(); // needed so that the id width adjuster works correctly
Dimension d = getIdPanel().getIdCanvas().getPreferredSize();
* though I still think this call should be elsewhere.
*/
ViewportRanges ranges = av.getRanges();
- setScrollValues(ranges.getStartRes(), ranges.getStartSeq());
+ // setScrollValues(ranges.getStartRes(), ranges.getStartSeq());
super.paintComponent(g);
}
public int printWrappedAlignment(int pageWidth, int pageHeight,
int pageNumber, Graphics g) throws PrinterException
{
- getSeqPanel().seqCanvas.calculateWrappedGeometry(getWidth(),
- getHeight());
+ getSeqPanel().seqCanvas.calculateWrappedGeometry();
int annotationHeight = 0;
if (av.isShowAnnotation())
{
} catch (Exception ex)
{
}
+
if (b)
{
setAlignFrameView();
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);
+ updateScrollBarsFromRanges();
// now update any complementary alignment (its viewport ranges object
// is different so does not get automatically updated)
}
}
+ void updateScrollBarsFromRanges()
+ {
+ ViewportRanges ranges = av.getRanges();
+ setScrollValues(ranges.getStartRes(), ranges.getStartSeq());
+ }
/**
* Set the reference to the PCA/Tree chooser dialog for this panel. This
* reference should be nulled when the dialog is closed.
return calculationDialog;
}
+ /**
+ * From appletgui, for JalviewJS JavaScript interface
+ *
+ * preliminary - untested
+ *
+ * @param ostart
+ * @param end
+ * @param seqIndex
+ * @param scrollToNearest
+ * @param redrawOverview
+ * @return
+ */
+ public boolean scrollTo(int ostart, int end, int seqIndex,
+ boolean scrollToNearest, boolean redrawOverview)
+ {
+ int startv, endv, starts, ends;// , width;
+
+ int start = -1;
+ if (av.hasHiddenColumns())
+ {
+ AlignmentI al = av.getAlignment();
+ start = al.getHiddenColumns().absoluteToVisibleColumn(ostart);
+ end = al.getHiddenColumns().absoluteToVisibleColumn(end);
+ if (start == end)
+ {
+ if (!scrollToNearest && !al.getHiddenColumns().isVisible(ostart))
+ {
+ // don't scroll - position isn't visible
+ return false;
+ }
+ }
+ }
+ else
+ {
+ start = ostart;
+ }
+
+ ViewportRanges ranges = av.getRanges();
+ if (!av.getWrapAlignment())
+ {
+ /*
+ * int spos=av.getStartRes(),sqpos=av.getStartSeq(); if ((startv =
+ * av.getStartRes()) >= start) { spos=start-1; // seqIn //
+ * setScrollValues(start - 1, seqIndex); } else if ((endv =
+ * av.getEndRes()) <= end) { // setScrollValues(spos=startv + 1 + end -
+ * endv, seqIndex); spos=startv + 1 + end - endv; } else if ((starts =
+ * av.getStartSeq()) > seqIndex) { setScrollValues(av.getStartRes(),
+ * seqIndex); } else if ((ends = av.getEndSeq()) <= seqIndex) {
+ * setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1); }
+ */
+
+ // below is scrolling logic up to Jalview 2.8.2
+ // if ((av.getStartRes() > end)
+ // || (av.getEndRes() < start)
+ // || ((av.getStartSeq() > seqIndex) || (av.getEndSeq() < seqIndex)))
+ // {
+ // if (start > av.getAlignment().getWidth() - hextent)
+ // {
+ // start = av.getAlignment().getWidth() - hextent;
+ // if (start < 0)
+ // {
+ // start = 0;
+ // }
+ //
+ // }
+ // if (seqIndex > av.getAlignment().getHeight() - vextent)
+ // {
+ // seqIndex = av.getAlignment().getHeight() - vextent;
+ // if (seqIndex < 0)
+ // {
+ // seqIndex = 0;
+ // }
+ // }
+ // setScrollValues(start, seqIndex);
+ // }
+ // logic copied from jalview.gui.AlignmentPanel:
+ if ((startv = ranges.getStartRes()) >= start)
+ {
+ /*
+ * Scroll left to make start of search results visible
+ */
+ setScrollValues(start - 1, seqIndex);
+ }
+ else if ((endv = ranges.getEndRes()) <= end)
+ {
+ /*
+ * Scroll right to make end of search results visible
+ */
+ setScrollValues(startv + 1 + 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)
+ {
+ /*
+ * 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
+ */
+ }
+ else
+ {
+ ranges.scrollToWrappedVisible(start);
+ }
+
+ paintAlignment(redrawOverview, false);
+ return true;
+ }
+
+ private boolean holdRepaint = false;
+
+ /**
+ * Called by IdCanvas and SeqPanel to defer painting until after JVP loading.
+ *
+ * @return true if holding
+ */
+ public boolean getHoldRepaint()
+ {
+ return holdRepaint;
+ }
+
+ /**
+ * Called by Jalview2xml while loading
+ *
+ * @param tf
+ */
+ public void setHoldRepaint(boolean tf)
+ {
+ if (holdRepaint == tf)
+ {
+ return;
+ }
+ holdRepaint = tf;
+ if (!tf)
+ {
+ repaint();
+ }
+ }
+
+ @Override
+ public void repaint()
+ {
+ if (holdRepaint)
+ {
+ // System.out.println("AP repaint holding");
+ // Platform.stackTrace();
+ return;
+ }
+ super.repaint();
+ }
+
+ public void selectAllSequences()
+ {
+ selectSequences(av.getAlignment().getSequences());
+ }
+
+ public void deselectAllSequences()
+ {
+ if (av.cursorMode)
+ {
+ getSeqPanel().keyboardNo1 = null;
+ getSeqPanel().keyboardNo2 = null;
+ }
+ av.setSelectionGroup(null);
+ av.getColumnSelection().clear();
+ av.setSearchResults(null);
+ getIdPanel().getIdCanvas().searchResults = null;
+ av.sendSelection();
+ // JAL-2034 - should delegate to
+ // alignPanel to decide if overview needs
+ // updating.
+ paintAlignment(false, false);
+ PaintRefresher.Refresh(this, av.getSequenceSetId());
+ }
+
+ public void selectSequences(List<SequenceI> seqs)
+ {
+ SequenceGroup sg = new SequenceGroup(seqs);
+ sg.setEndRes(av.getAlignment().getWidth() - 1);
+ av.setSelectionGroup(sg);
+ av.isSelectionGroupChanged(true);
+ av.sendSelection();
+ // JAL-2034 - should delegate to
+ // alignPanel to decide if overview needs
+ // updating.
+ paintAlignment(false, false);
+ PaintRefresher.Refresh(this, av.getSequenceSetId());
+ }
+
}