import jalview.analysis.AnnotationSorter;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
+import jalview.api.SequenceRenderer;
import jalview.bin.Cache;
import jalview.bin.Jalview;
import jalview.datamodel.AlignmentI;
import java.awt.event.AdjustmentListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
+import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.io.PrintWriter;
import java.util.List;
-import javax.swing.SwingUtilities;
+import javax.swing.JScrollBar;
/**
- * DOCUMENT ME!
+ * The main panel of an AlignFrame, containing holders for the IdPanel,
+ * SeqPanel, AnnotationLabels (a JPanel), and AnnotationPanel.
+ *
+ * Additional holders contain an IdPanelWidthAdjuster space above the idPanel,
+ * AnnotationScroller (JScrollPane for AnnotationPanel), and vertical and
+ * horizontal scrollbars.
+ *
+ *
*
* @author $author$
* @version $Revision: 1.161 $
*/
public AlignmentPanel(AlignFrame af, final AlignViewport av)
{
-// setBackground(Color.white); // BH 2019
+ setBackground(Color.white); // BH 2019
+ setOpaque(true);
alignFrame = af;
this.av = av;
setSeqPanel(new SeqPanel(av, this));
annotationScroller.setViewportView(getAnnotationPanel());
annotationSpaceFillerHolder.add(getAlabels(), BorderLayout.CENTER);
-
+ if (!av.isShowAnnotation())
+ {
+ annotationScroller.setVisible(false);
+ annotationSpaceFillerHolder.setVisible(false);
+ }
scalePanelHolder.add(getScalePanel(), BorderLayout.CENTER);
seqPanelHolder.add(getSeqPanel(), BorderLayout.CENTER);
hscroll.addAdjustmentListener(this);
vscroll.addAdjustmentListener(this);
+
addComponentListener(new ComponentAdapter()
{
@Override
public void componentResized(ComponentEvent evt)
{
+ System.out.println("AlignmentPanel resized " + evt);
// reset the viewport ranges when the alignment panel is resized
// in particular, this initialises the end residue value when Jalview
// is initialised
/ av.getCharHeight();
ranges.setViewportWidth(widthInRes);
+ ViewportRanges.sTest += "AP.resize chht=" + av.getCharHeight()
+ + "canvHt=" + getSeqPanel().seqCanvas.getHeight() + " "
+ + heightInSeq + "\n";
ranges.setViewportHeight(heightInSeq);
}
}
}
@Override
+ public void setBounds(int x, int y, int width, int height)
+ {
+ System.out.println("?AlignmentPanel.setBounds " + this.getX() + " "
+ + this.getY() + " " + this.getWidth() + " " + getHeight() + " "
+ + x + " " + y + " " + width + " " + height);
+ // BH 2020.03.23 when the Desktop changes its progress bar it re-lays out
+ // all
+ // its
+ // children, for unclear reasons. Maybe because they could be tiled?
+ if (x == this.getX() && y == this.getY() && width == this.getWidth()
+ && height == this.getHeight())
+ {
+ return;
+ }
+ System.out.println("!AlignmentPanel.setBounds " + this.getX() + " "
+ + this.getY() + " " + this.getWidth() + " " + getHeight() + " "
+ + x + " " + y + " " + width + " " + height);
+ super.setBounds(x, y, width, height);
+ }
+
+ // @Override
+ // public void reshape(int x, int y, int width, int height)
+ // {
+ // // BH 2020.03.23 when the Desktop changes its progress bar it relays out
+ // all its
+ // // children, for unclear reasons. Maybe because they could be tiled?
+ // if (x == this.getX() && y == this.getY() && width == this.getWidth()
+ // && height == this.getHeight())
+ // {
+ // return;
+ // }
+ //
+ // System.out.println("AlignmentPanel.reshape " + this.getX() + " "
+ // + this.getY() + " " + this.getWidth() + " " + getHeight() + " "
+ // + x
+ // + " " + y + " " + width + " " + height);
+ // super.reshape(x, y, width, height);
+ // }
+
+ @Override
public AlignViewportI getAlignViewport()
{
return av;
*/
protected void validateAnnotationDimensions(boolean adjustPanelHeight)
{
+ // 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,
+ // 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);
Dimension e = idPanel.getSize();
alabels.setSize(new Dimension(e.width, annotationHeight));
+
annotationSpaceFillerHolder.setPreferredSize(new Dimension(
annotationSpaceFillerHolder.getWidth(), annotationHeight));
annotationScroller.validate();
*/
public void updateLayout()
{
- fontChanged();
+ fontChanged(); // fires repaint
setAnnotationVisible(av.isShowAnnotation());
boolean wrap = av.getWrapAlignment();
ViewportRanges ranges = av.getRanges();
* visible column to scroll to
* @param y
* visible row to scroll to
+ *
+ * @return true if scrollbars will fire property changes
*
*/
- public void setScrollValues(int xpos, int ypos)
+ public boolean setScrollValues(int xpos, int ypos)
{
int x = xpos;
int y = ypos;
if (av == null || av.getAlignment() == null)
{
- return;
+ return false;
}
if (av.getWrapAlignment())
{
- setScrollingForWrappedPanel(x);
+ return setScrollingForWrappedPanel(x);
}
- else
+ 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)
{
- int width = av.getAlignment().getVisibleWidth();
- int height = av.getAlignment().getHeight();
+ hextent = width;
+ }
- hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
- vextent = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight();
+ if (vextent > height)
+ {
+ vextent = height;
+ }
- if (hextent > width)
- {
- hextent = width;
- }
+ if ((hextent + x) > width)
+ {
+ x = width - hextent;
+ }
- if (vextent > height)
- {
- vextent = height;
- }
+ if ((vextent + y) > height)
+ {
+ y = height - vextent;
+ }
- if ((hextent + x) > width)
- {
- x = width - hextent;
- }
+ if (y < 0)
+ {
+ y = 0;
+ }
- if ((vextent + y) > height)
- {
- y = height - vextent;
- }
+ if (x < 0)
+ {
+ x = 0;
+ }
- if (y < 0)
- {
- y = 0;
- }
+ // update the scroll values and return true if they changed
- if (x < 0)
- {
- x = 0;
- }
+ return (setIfChanged(hscroll, x, hextent, 0, width)
+ + setIfChanged(vscroll, y, vextent, 0, height) != 0);
+
+ }
- // update the scroll values
- hscroll.setValues(x, hextent, 0, width);
- vscroll.setValues(y, vextent, 0, height);
+ /**
+ * Update a horizontal or vertical scrollbar and indicate if it is actually changed
+ * (and so will be firing an AdjustmentChangedEvent)
+ * @param sb
+ * @param val
+ * @param extent
+ * @param min
+ * @praam max
+ * @return 1 if JScrollBar is changed; 0 if not
+ */
+ private int setIfChanged(JScrollBar sb, int val, int extent, int min,
+ int max)
+ {
+ if (sb.getValue() == val && sb.getModel().getExtent() == extent
+ && sb.getMinimum() == min && sb.getMaximum() == max)
+ {
+ return 0;
}
+ sb.setValues(val, extent, min, max);
+ return 1;
}
/**
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
{
return;
}
+
+ ViewportRanges.sTest += "AP.adjvalChanged chht=" + av.getCharHeight()
+ + "canvHt=" + getSeqPanel().seqCanvas.getHeight() + " newHt="
+ + height + "\n";
+
ranges.setViewportStartAndHeight(y, height);
}
repaint();
// 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()
+ Jalview.execRunnable(new Runnable()
{
@Override
public void run()
av.isShowAutocalculatedAbove());
sorter.sort(getAlignment().getAlignmentAnnotation(),
av.getSortAnnotationsBy());
- // BH 2019.04.18 this should not be necessary, but
- // there is something wrong with the fast painting
- // in that there is a -1 shift that should not be there.
- // It is being covered in Java by the Consensus and Conservation
- // threads forcing a full repaint after pasting.
- seqPanel.seqCanvas.clearFastPaint();
repaint();
if (updateStructures)
}
if (updateOverview)
{
-
if (overviewPanel != null)
{
overviewPanel.updateOverviewImage();
}
}
+ @Override
+ public void invalidate()
+ {
+ System.out.println("AlignmentPanel invalidate");
+ super.invalidate();
+ }
+
+ @Override
+ public void validate()
+ {
+ System.out.println("AlignmentPanel validate");
+ super.validate();
+ }
+
/**
* DOCUMENT ME!
*
@Override
public void paintComponent(Graphics g)
{
+
+ System.out.println("AlignmentPanel paintComponent");
+
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());
+ if (!setScrollValues(ranges.getStartRes(), ranges.getStartSeq()))
+ {
+ // super.paintComponent(g);
+ }
super.paintComponent(g);
}
* @param topLeftColumn
* the column position at top left (0..)
*/
- private void setScrollingForWrappedPanel(int topLeftColumn)
+ private boolean setScrollingForWrappedPanel(int topLeftColumn)
{
ViewportRanges ranges = av.getRanges();
int scrollPosition = ranges.getWrappedScrollPosition(topLeftColumn);
* so we add extent (1) to the maxScroll value
*/
vscroll.setUnitIncrement(1);
- vscroll.setValues(scrollPosition, 1, 0, maxScroll + 1);
+ return (setIfChanged(vscroll, scrollPosition, 1, 0,
+ maxScroll + 1) != 0);
}
/**
public int printWrappedAlignment(int pageWidth, int pageHeight, int pageNumber,
Graphics g) throws PrinterException
{
+
int annotationHeight = 0;
if (av.isShowAnnotation())
{
int totalHeight = cHeight * (maxwidth / resWidth + 1);
+ g = g.create();
+
g.setColor(Color.white);
g.fillRect(0, 0, pageWidth, pageHeight);
g.setFont(av.getFont());
*/
g.translate(0, -pageNumber * pageHeight);
- g.setClip(0, pageNumber * pageHeight, pageWidth, pageHeight);
+ // BH 2020.03.19 avoiding g.setClip
+ g.clipRect(0, pageNumber * pageHeight, pageWidth, pageHeight);
/*
* draw sequence ids and annotation labels (if shown)
getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(g, pageWidth - idWidth,
totalHeight, 0);
+ g.dispose();
if ((pageNumber * pageHeight) < totalHeight)
{
return Printable.PAGE_EXISTS;
public int getVisibleIdWidth(boolean onscreen)
{
// see if rendering offscreen - check preferences and calc width accordingly
- if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
+ if (!onscreen && Cache.getDefault(Preferences.FIGURE_AUTOIDWIDTH, false))
{
return calculateIdWidth(-1).width + 4;
}
Integer idwidth = null;
if (onscreen || (idwidth = Cache
- .getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
+ .getIntegerProperty(Preferences.FIGURE_FIXEDIDWIDTH)) == null)
{
int w = getIdPanel().getWidth();
return (w > 0 ? w : calculateIdWidth().width + 4);
{
int seqPanelWidth = getSeqPanel().seqCanvas.getWidth();
- if (System.getProperty("java.awt.headless") != null
- && System.getProperty("java.awt.headless").equals("true"))
+ if (Jalview.isHeadlessMode())
{
seqPanelWidth = alignFrame.getWidth() - getVisibleIdWidth()
- vscroll.getPreferredSize().width
return calculationDialog;
}
+ @Override
+ public SequenceRenderer getSequenceRenderer()
+ {
+ return seqPanel.seqCanvas.getSequenceRenderer();
+ }
+
+ 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;
+ }
+
+ @Override
+ public void overviewDone(BufferedImage miniMe)
+ {
+ overviewPanel.canvas.finalizeDraw(miniMe);
+ }
+
+
+ private boolean holdRepaint = false;
+
+ public boolean getHoldRepaint()
+ {
+ return holdRepaint;
+ }
+
+ public void setHoldRepaint(boolean b)
+ {
+ if (holdRepaint == b)
+ {
+ return;
+ }
+ holdRepaint = b;
+ if (!b)
+ {
+ repaint();
+ }
+ }
+
+ @Override
+ public void repaint()
+ {
+ if (holdRepaint)
+ {
+ // System.out.println("AP repaint holding");
+ // Platform.stackTrace();
+ return;
+ }
+ super.repaint();
+ }
+
}