X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FAnnotationPanel.java;h=a88aa4a4ee30b6e5ea5920c84140c92bd5af46dc;hb=797df64fa2a0a30773d0f48f5494d4155e5a8be3;hp=c3984f29cf4c3757a8e2e44a7c020a0ea3c356dc;hpb=77ee0174127cb2fd3d817b010b5a36278dd37c45;p=jalview.git
diff --git a/src/jalview/gui/AnnotationPanel.java b/src/jalview/gui/AnnotationPanel.java
index c3984f2..a88aa4a 100755
--- a/src/jalview/gui/AnnotationPanel.java
+++ b/src/jalview/gui/AnnotationPanel.java
@@ -1,20 +1,19 @@
/*
- * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
- * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
+ * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This file is part of Jalview.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Jalview. If not, see .
*/
package jalview.gui;
@@ -27,7 +26,10 @@ import java.util.Hashtable;
import javax.swing.*;
+import com.stevesoft.pat.Regex;
+
import jalview.analysis.AAFrequency;
+import jalview.analysis.StructureFrequency;
import jalview.datamodel.*;
import jalview.schemes.ColourSchemeI;
@@ -44,6 +46,11 @@ public class AnnotationPanel extends JPanel implements MouseListener,
final String SHEET = "Sheet";
+ /**
+ * For RNA secondary structure "stems" aka helices
+ */
+ final String STEM = "RNA Helix";
+
final String LABEL = "Label";
final String REMOVE = "Remove Annotation";
@@ -54,6 +61,8 @@ public class AnnotationPanel extends JPanel implements MouseListener,
final Color SHEET_COLOUR = Color.green.darker().darker();
+ final Color STEM_COLOUR = Color.blue.darker();
+
/** DOCUMENT ME!! */
AlignViewport av;
@@ -86,11 +95,16 @@ public class AnnotationPanel extends JPanel implements MouseListener,
boolean MAC = false;
+ // for editing cursor
+ int cursorX = 0;
+
+ int cursorY = 0;
+
/**
* Creates a new AnnotationPanel object.
*
* @param ap
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public AnnotationPanel(AlignmentPanel ap)
{
@@ -118,7 +132,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void adjustmentValueChanged(AdjustmentEvent evt)
{
@@ -126,10 +140,32 @@ public class AnnotationPanel extends JPanel implements MouseListener,
}
/**
- * DOCUMENT ME!
+ * Calculates the height of the annotation displayed in the annotation panel.
+ * Callers should normally call the ap.adjustAnnotationHeight method to ensure
+ * all annotation associated components are updated correctly.
+ *
*/
public int adjustPanelHeight()
{
+ int height = calcPanelHeight();
+ this.setPreferredSize(new Dimension(1, height));
+ if (ap != null)
+ {
+ // revalidate only when the alignment panel is fully constructed
+ ap.validate();
+ }
+
+ return height;
+ }
+
+ /**
+ * calculate the height for visible annotation, revalidating bounds where
+ * necessary ABSTRACT GUI METHOD
+ *
+ * @return total height of annotation
+ */
+ public int calcPanelHeight()
+ {
// setHeight of panels
AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
int height = 0;
@@ -138,6 +174,11 @@ public class AnnotationPanel extends JPanel implements MouseListener,
{
for (int i = 0; i < aa.length; i++)
{
+ if (aa[i] == null)
+ {
+ System.err.println("Null annotation row: ignoring.");
+ continue;
+ }
if (!aa[i].visible)
{
continue;
@@ -168,13 +209,11 @@ public class AnnotationPanel extends JPanel implements MouseListener,
height += aa[i].height;
}
}
- else
+ if (height == 0)
{
+ // set minimum
height = 20;
}
-
- this.setPreferredSize(new Dimension(1, height));
-
return height;
}
@@ -182,11 +221,15 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void actionPerformed(ActionEvent evt)
{
AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
+ if (aa == null)
+ {
+ return;
+ }
Annotation[] anot = aa[activeRow].annotations;
if (anot.length < av.getColumnSelection().getMax())
@@ -230,9 +273,9 @@ public class AnnotationPanel extends JPanel implements MouseListener,
if (anot[index] == null)
{
anot[index] = new Annotation(label, "", ' ', 0); // TODO: verify that
- // null exceptions
- // aren't raised
- // elsewhere.
+ // null exceptions
+ // aren't raised
+ // elsewhere.
}
else
{
@@ -276,6 +319,13 @@ public class AnnotationPanel extends JPanel implements MouseListener,
symbol = "\u03B2";
}
+ // Added by LML to color stems
+ else if (evt.getActionCommand().equals(STEM))
+ {
+ type = 'S';
+ symbol = "\u03C3";
+ }
+
if (!aa[activeRow].hasIcons)
{
aa[activeRow].hasIcons = true;
@@ -330,14 +380,15 @@ public class AnnotationPanel extends JPanel implements MouseListener,
continue;
String tlabel = null;
if (anot[index] != null)
- {
+ { // LML added stem code
if (label2.equals(HELIX) || label2.equals(SHEET)
- || label2.equals(LABEL))
+ || label2.equals(STEM) || label2.equals(LABEL))
{
tlabel = anot[index].description;
- if (tlabel == null)
+ if (tlabel == null || tlabel.length() < 1)
{
- if (label2.equals(HELIX) || label2.equals(SHEET))
+ if (label2.equals(HELIX) || label2.equals(SHEET)
+ || label2.equals(STEM))
{
tlabel = "" + anot[index].secondaryStructure;
}
@@ -364,7 +415,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void mousePressed(MouseEvent evt)
{
@@ -410,12 +461,25 @@ public class AnnotationPanel extends JPanel implements MouseListener,
}
JPopupMenu pop = new JPopupMenu("Structure type");
- JMenuItem item = new JMenuItem(HELIX);
- item.addActionListener(this);
- pop.add(item);
- item = new JMenuItem(SHEET);
- item.addActionListener(this);
- pop.add(item);
+ JMenuItem item;
+ /*
+ * Just display the needed structure options
+ */
+ if (av.alignment.isNucleotide() == true)
+ {
+ item = new JMenuItem(STEM);
+ item.addActionListener(this);
+ pop.add(item);
+ }
+ else
+ {
+ item = new JMenuItem(HELIX);
+ item.addActionListener(this);
+ pop.add(item);
+ item = new JMenuItem(SHEET);
+ item.addActionListener(this);
+ pop.add(item);
+ }
item = new JMenuItem(LABEL);
item.addActionListener(this);
pop.add(item);
@@ -443,7 +507,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void mouseReleased(MouseEvent evt)
{
@@ -457,7 +521,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void mouseEntered(MouseEvent evt)
{
@@ -468,7 +532,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void mouseExited(MouseEvent evt)
{
@@ -479,7 +543,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void mouseDragged(MouseEvent evt)
{
@@ -505,7 +569,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void mouseMoved(MouseEvent evt)
{
@@ -548,7 +612,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
res = av.getColumnSelection().adjustForHiddenColumns(res);
}
- if (aa[row].annotations != null && row > -1
+ if (row > -1 && aa[row].annotations != null
&& res < (int) aa[row].annotations.length)
{
if (aa[row].graphGroup > -1)
@@ -570,10 +634,16 @@ public class AnnotationPanel extends JPanel implements MouseListener,
}
}
else if (aa[row].annotations[res] != null
- && aa[row].annotations[res].description != null)
+ && aa[row].annotations[res].description != null
+ && aa[row].annotations[res].description.length() > 0)
{
this.setToolTipText(aa[row].annotations[res].description);
}
+ else
+ {
+ // clear the tooltip.
+ this.setToolTipText(null);
+ }
if (aa[row].annotations[res] != null)
{
@@ -598,17 +668,49 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param evt
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void mouseClicked(MouseEvent evt)
{
+ if (activeRow != -1)
+ {
+ AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
+ AlignmentAnnotation anot = aa[activeRow];
+
+ if (anot.description.equals("secondary structure"))
+ {
+ // System.out.println(anot.description+" "+anot.getRNAStruc());
+ }
+ }
+ }
+
+ // TODO mouseClicked-content and drawCursor are quite experimental!
+ public void drawCursor(Graphics graphics, SequenceI seq, int res, int x1,
+ int y1)
+ {
+ int pady = av.charHeight / 5;
+ int charOffset = 0;
+ graphics.setColor(Color.black);
+ graphics.fillRect(x1, y1, av.charWidth, av.charHeight);
+
+ if (av.validCharWidth)
+ {
+ graphics.setColor(Color.white);
+
+ char s = seq.getCharAt(res);
+
+ charOffset = (av.charWidth - fm.charWidth(s)) / 2;
+ graphics.drawString(String.valueOf(s), charOffset + x1,
+ (y1 + av.charHeight) - pady);
+ }
+
}
/**
* DOCUMENT ME!
*
* @param g
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void paintComponent(Graphics g)
{
@@ -655,7 +757,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* non-Thread safe repaint
*
* @param horizontal
- * repaint with horizontal shift in alignment
+ * repaint with horizontal shift in alignment
*/
public void fastPaint(int horizontal)
{
@@ -699,11 +801,11 @@ public class AnnotationPanel extends JPanel implements MouseListener,
* DOCUMENT ME!
*
* @param g
- * DOCUMENT ME!
+ * DOCUMENT ME!
* @param startRes
- * DOCUMENT ME!
+ * DOCUMENT ME!
* @param endRes
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void drawComponent(Graphics g, int startRes, int endRes)
{
@@ -771,8 +873,15 @@ public class AnnotationPanel extends JPanel implements MouseListener,
int iconOffset = 0;
boolean validRes = false;
boolean validEnd = false;
+ boolean labelAllCols = false;
+ boolean centreColLabels, centreColLabelsDef = av
+ .getCentreColumnLabels();
+ boolean scaleColLabel = false;
boolean[] graphGroupDrawn = new boolean[aa.length];
-
+ int charOffset = 0; // offset for a label
+ float fmWidth, fmScaling = 1f; // scaling for a label to fit it into a
+ // column.
+ Font ofont = g.getFont();
// \u03B2 \u03B1
for (int i = 0; i < aa.length; i++)
{
@@ -782,10 +891,11 @@ public class AnnotationPanel extends JPanel implements MouseListener,
{
continue;
}
-
+ centreColLabels = row.centreColLabels || centreColLabelsDef;
+ labelAllCols = row.showAllColLabels;
+ scaleColLabel = row.scaleColLabel;
lastSS = ' ';
lastSSX = 0;
-
if (row.graph > 0)
{
if (row.graphGroup > -1 && graphGroupDrawn[row.graphGroup])
@@ -848,7 +958,9 @@ public class AnnotationPanel extends JPanel implements MouseListener,
continue;
}
- x = 0;
+ // first pass sets up state for drawing continuation from left-hand column
+ // of startRes
+ x = (startRes == 0) ? 0 : -1;
while (x < endRes - startRes)
{
if (av.hasHiddenColumns)
@@ -874,139 +986,144 @@ public class AnnotationPanel extends JPanel implements MouseListener,
{
validRes = true;
}
-
- if (activeRow == i)
+ if (x > -1)
{
- g.setColor(Color.red);
-
- if (av.getColumnSelection() != null)
+ if (activeRow == i)
{
- for (int n = 0; n < av.getColumnSelection().size(); n++)
- {
- int v = av.getColumnSelection().columnAt(n);
+ g.setColor(Color.red);
- if (v == column)
+ if (av.getColumnSelection() != null)
+ {
+ for (int n = 0; n < av.getColumnSelection().size(); n++)
{
- g
- .fillRect(x * av.charWidth, y, av.charWidth,
- av.charHeight);
+ int v = av.getColumnSelection().columnAt(n);
+
+ if (v == column)
+ {
+ g.fillRect(x * av.charWidth, y, av.charWidth,
+ av.charHeight);
+ }
}
}
}
- }
- if (av.validCharWidth && validRes
- && row.annotations[column].displayCharacter != null
- && (row.annotations[column].displayCharacter.length() > 0))
- {
+ if (av.validCharWidth
+ && validRes
+ && row.annotations[column].displayCharacter != null
+ && (row.annotations[column].displayCharacter.length() > 0))
+ {
- int charOffset = (av.getCentreColumnLabels()) ? ((av.charWidth - fm
- .charsWidth(row.annotations[column].displayCharacter
- .toCharArray(), 0,
- row.annotations[column].displayCharacter.length())) / 2)
- : (av.charWidth - fm
- .charWidth(row.annotations[column].displayCharacter
- .charAt(0))) / 2;
+ if (centreColLabels || scaleColLabel)
+ {
+ fmWidth = (float) fm.charsWidth(
+ row.annotations[column].displayCharacter
+ .toCharArray(), 0,
+ row.annotations[column].displayCharacter.length());
- if (row.annotations[column].colour == null)
- g.setColor(Color.black);
- else
- g.setColor(row.annotations[column].colour);
+ if (scaleColLabel)
+ {
+ // justify the label and scale to fit in column
+ if (fmWidth > av.charWidth)
+ {
+ // scale only if the current font isn't already small enough
+ fmScaling = av.charWidth;
+ fmScaling /= fmWidth;
+ g.setFont(ofont.deriveFont(AffineTransform
+ .getScaleInstance(fmScaling, 1.0)));
+ // and update the label's width to reflect the scaling.
+ fmWidth = av.charWidth;
+ }
+ }
+ }
+ else
+ {
+ fmWidth = (float) fm
+ .charWidth(row.annotations[column].displayCharacter
+ .charAt(0));
+ }
+ charOffset = (int) ((av.charWidth - fmWidth) / 2f);
- if (column == 0 || row.graph > 0)
- {
- g.drawString(row.annotations[column].displayCharacter,
- (x * av.charWidth) + charOffset, y + iconOffset);
- }
- else if (row.annotations[column - 1] == null
- || (!row.annotations[column].displayCharacter
- .equals(row.annotations[column - 1].displayCharacter) || (row.annotations[column].displayCharacter
- .length() < 2 && row.annotations[column].secondaryStructure == ' ')))
- {
- g.drawString(row.annotations[column].displayCharacter, x
- * av.charWidth + charOffset, y + iconOffset);
+ if (row.annotations[column].colour == null)
+ g.setColor(Color.black);
+ else
+ g.setColor(row.annotations[column].colour);
+
+ if (column == 0 || row.graph > 0)
+ {
+ g.drawString(row.annotations[column].displayCharacter,
+ (x * av.charWidth) + charOffset, y + iconOffset);
+ }
+ else if (row.annotations[column - 1] == null
+ || (labelAllCols
+ || !row.annotations[column].displayCharacter
+ .equals(row.annotations[column - 1].displayCharacter) || (row.annotations[column].displayCharacter
+ .length() < 2 && row.annotations[column].secondaryStructure == ' ')))
+ {
+ g.drawString(row.annotations[column].displayCharacter, x
+ * av.charWidth + charOffset, y + iconOffset);
+ }
+ g.setFont(ofont);
}
}
-
if (row.hasIcons)
{
- if (!validRes
- || (row.annotations[column].secondaryStructure != lastSS))
+ char ss = validRes ? row.annotations[column].secondaryStructure
+ : ' ';
+ if (ss == 'S')
{
- switch (lastSS)
+ // distinguish between forward/backward base-pairing
+ if (row.annotations[column].displayCharacter.indexOf(')') > -1)
{
- case 'H':
- g.setColor(HELIX_COLOUR);
- if (MAC)
+ ss = 's';
+ }
+ }
+ if (!validRes || (ss != lastSS))
+ {
+ if (x > -1)
+ {
+ switch (lastSS)
{
- // Off by 1 offset when drawing rects and ovals
- // to offscreen image on the MAC
- g.fillRoundRect(lastSSX, y + 4 + iconOffset,
- (x * av.charWidth) - lastSSX, 7, 8, 8);
+ case 'H':
+ drawHelixAnnot(g, row, lastSSX, x, y, iconOffset, startRes,
+ column, validRes, validEnd);
break;
- }
-
- int sCol = (lastSSX / av.charWidth) + startRes;
- int x1 = lastSSX;
- int x2 = (x * av.charWidth);
- if (sCol == 0
- || row.annotations[sCol - 1] == null
- || row.annotations[sCol - 1].secondaryStructure != 'H')
- {
- g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90,
- 180);
- x1 += av.charWidth / 2;
- }
-
- if (!validRes || row.annotations[column] == null
- || row.annotations[column].secondaryStructure != 'H')
- {
- g.fillArc((x * av.charWidth) - av.charWidth, y + 4
- + iconOffset, av.charWidth, 8, 270, 180);
- x2 -= av.charWidth / 2;
- }
-
- g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);
- break;
-
- case 'E':
- g.setColor(SHEET_COLOUR);
- g.fillRect(lastSSX, y + 4 + iconOffset, (x * av.charWidth)
- - lastSSX - 4, 7);
- g.fillPolygon(new int[]
- { (x * av.charWidth) - 4, (x * av.charWidth) - 4,
- (x * av.charWidth) }, new int[]
- { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
- 3);
+ case 'E':
+ drawSheetAnnot(g, row, lastSSX, x, y, iconOffset, startRes,
+ column, validRes, validEnd);
+ break;
- break;
+ case 'S': // Stem case for RNA secondary structure
+ case 's': // and opposite direction
+ drawStemAnnot(g, row, lastSSX, x, y, iconOffset, startRes,
+ column, validRes, validEnd);
+ break;
- default:
- g.setColor(Color.gray);
- g.fillRect(lastSSX, y + 6 + iconOffset, (x * av.charWidth)
- - lastSSX, 2);
+ default:
+ g.setColor(Color.gray);
+ g.fillRect(lastSSX, y + 6 + iconOffset, (x * av.charWidth)
+ - lastSSX, 2);
- break;
+ break;
+ }
}
-
if (validRes)
{
- lastSS = row.annotations[column].secondaryStructure;
+ lastSS = ss;
}
else
{
lastSS = ' ';
}
-
- lastSSX = (x * av.charWidth);
+ if (x > -1)
+ {
+ lastSSX = (x * av.charWidth);
+ }
}
}
-
column++;
x++;
}
-
if (column >= row.annotations.length)
{
column = row.annotations.length - 1;
@@ -1024,66 +1141,22 @@ public class AnnotationPanel extends JPanel implements MouseListener,
switch (lastSS)
{
case 'H':
- g.setColor(HELIX_COLOUR);
- if (MAC)
- {
- // Off by 1 offset when drawing rects and ovals
- // to offscreen image on the MAC
- g.fillRoundRect(lastSSX, y + 4 + iconOffset, (x * av.charWidth)
- - lastSSX, 7, 8, 8);
- break;
- }
-
- int sCol = (lastSSX / av.charWidth) + startRes;
- int x1 = lastSSX;
- int x2 = (x * av.charWidth);
-
- if (sCol == 0 || row.annotations[sCol - 1] == null
- || row.annotations[sCol - 1].secondaryStructure != 'H')
- {
- g
- .fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8,
- 90, 180);
- x1 += av.charWidth / 2;
- }
-
- if (row.annotations[column] == null
- || row.annotations[column].secondaryStructure != 'H')
- {
- g.fillArc((x * av.charWidth) - av.charWidth,
- y + 4 + iconOffset, av.charWidth, 8, 270, 180);
- x2 -= av.charWidth / 2;
- }
-
- g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);
-
+ drawHelixAnnot(g, row, lastSSX, x, y, iconOffset, startRes,
+ column, validRes, validEnd);
break;
case 'E':
- g.setColor(SHEET_COLOUR);
-
- if (!validEnd || row.annotations[endRes] == null
- || row.annotations[endRes].secondaryStructure != 'E')
- {
- g.fillRect(lastSSX, y + 4 + iconOffset, (x * av.charWidth)
- - lastSSX - 4, 7);
- g.fillPolygon(new int[]
- { (x * av.charWidth) - 4, (x * av.charWidth) - 4,
- (x * av.charWidth) }, new int[]
- { y + iconOffset, y + 14 + iconOffset, y + 7 + iconOffset }, 3);
- }
- else
- {
- g.fillRect(lastSSX, y + 4 + iconOffset, (x + 1) * av.charWidth
- - lastSSX, 7);
- }
+ drawSheetAnnot(g, row, lastSSX, x, y, iconOffset, startRes,
+ column, validRes, validEnd);
+ break;
+ case 's':
+ case 'S': // Stem case for RNA secondary structure
+ drawStemAnnot(g, row, lastSSX, x, y, iconOffset, startRes,
+ column, validRes, validEnd);
break;
-
default:
- g.setColor(Color.gray);
- g.fillRect(lastSSX, y + 6 + iconOffset, (x * av.charWidth)
- - lastSSX, 2);
-
+ drawGlyphLine(g, row, lastSSX, x, y, iconOffset, startRes,
+ column, validRes, validEnd);
break;
}
}
@@ -1153,6 +1226,157 @@ public class AnnotationPanel extends JPanel implements MouseListener,
}
}
+ private void drawStemAnnot(Graphics g, AlignmentAnnotation row,
+ int lastSSX, int x, int y, int iconOffset, int startRes,
+ int column, boolean validRes, boolean validEnd)
+ {
+ g.setColor(STEM_COLOUR);
+ int sCol = (lastSSX / av.charWidth) + startRes;
+ int x1 = lastSSX;
+ int x2 = (x * av.charWidth);
+ Regex closeparen = new Regex("(\\))");
+
+ String dc = column == 0 ? ""
+ : row.annotations[column - 1].displayCharacter;
+
+ boolean diffupstream = sCol == 0 || row.annotations[sCol - 1] == null
+ || !dc.equals(row.annotations[sCol - 1].displayCharacter);
+ boolean diffdownstream = !validRes || !validEnd
+ || row.annotations[column] == null
+ || !dc.equals(row.annotations[column].displayCharacter);
+ // System.out.println("Column "+column+" diff up: "+diffupstream+" down:"+diffdownstream);
+ // If a closing base pair half of the stem, display a backward arrow
+ if (column > 0 && closeparen.search(dc))
+ {
+ if (diffupstream)
+ // if (validRes && column>1 && row.annotations[column-2]!=null &&
+ // dc.equals(row.annotations[column-2].displayCharacter))
+ {
+ g.fillPolygon(new int[]
+ { lastSSX + 5, lastSSX + 5, lastSSX }, new int[]
+ { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
+ x1 += 5;
+ }
+ if (diffdownstream)
+ {
+ x2 -= 1;
+ }
+ }
+ else
+ {
+ // display a forward arrow
+ if (diffdownstream)
+ {
+ g.fillPolygon(new int[]
+ { x2 - 5, x2 - 5, x2 }, new int[]
+ { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
+ x2 -= 5;
+ }
+ if (diffupstream)
+ {
+ x1 += 1;
+ }
+ }
+ // draw arrow body
+ g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 7);
+ }
+
+ private void drawGlyphLine(Graphics g, AlignmentAnnotation row,
+ int lastSSX, int x, int y, int iconOffset, int startRes,
+ int column, boolean validRes, boolean validEnd)
+ {
+ g.setColor(Color.gray);
+ g
+ .fillRect(lastSSX, y + 6 + iconOffset, (x * av.charWidth)
+ - lastSSX, 2);
+ }
+
+ private void drawSheetAnnot(Graphics g, AlignmentAnnotation row,
+ int lastSSX, int x, int y, int iconOffset, int startRes,
+ int column, boolean validRes, boolean validEnd)
+ {
+ g.setColor(SHEET_COLOUR);
+
+ if (!validEnd || !validRes || row.annotations[column] == null
+ || row.annotations[column].secondaryStructure != 'E')
+ {
+ g.fillRect(lastSSX, y + 4 + iconOffset, (x * av.charWidth) - lastSSX
+ - 4, 7);
+ g.fillPolygon(
+ new int[]
+ { (x * av.charWidth) - 4, (x * av.charWidth) - 4,
+ (x * av.charWidth) }, new int[]
+ { y + iconOffset, y + 14 + iconOffset, y + 7 + iconOffset },
+ 3);
+ }
+ else
+ {
+ g.fillRect(lastSSX, y + 4 + iconOffset, (x + 1) * av.charWidth
+ - lastSSX, 7);
+ }
+
+ }
+
+ private void drawHelixAnnot(Graphics g, AlignmentAnnotation row,
+ int lastSSX, int x, int y, int iconOffset, int startRes,
+ int column, boolean validRes, boolean validEnd)
+ {
+ g.setColor(HELIX_COLOUR);
+
+ int sCol = (lastSSX / av.charWidth) + startRes;
+ int x1 = lastSSX;
+ int x2 = (x * av.charWidth);
+
+ if (MAC)
+ {
+ int ofs = av.charWidth / 2;
+ // Off by 1 offset when drawing rects and ovals
+ // to offscreen image on the MAC
+ g.fillRoundRect(lastSSX, y + 4 + iconOffset, x2 - x1, 8, 8, 8);
+ if (sCol == 0 || row.annotations[sCol - 1] == null
+ || row.annotations[sCol - 1].secondaryStructure != 'H')
+ {
+ }
+ else
+ {
+ // g.setColor(Color.orange);
+ g.fillRoundRect(lastSSX, y + 4 + iconOffset, x2 - x1 - ofs + 1, 8,
+ 0, 0);
+ }
+ if (!validRes || row.annotations[column] == null
+ || row.annotations[column].secondaryStructure != 'H')
+ {
+
+ }
+ else
+ {
+ // g.setColor(Color.magenta);
+ g.fillRoundRect(lastSSX + ofs, y + 4 + iconOffset, x2 - x1 - ofs
+ + 1, 8, 0, 0);
+
+ }
+
+ return;
+ }
+
+ if (sCol == 0 || row.annotations[sCol - 1] == null
+ || row.annotations[sCol - 1].secondaryStructure != 'H')
+ {
+ g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90, 180);
+ x1 += av.charWidth / 2;
+ }
+
+ if (!validRes || row.annotations[column] == null
+ || row.annotations[column].secondaryStructure != 'H')
+ {
+ g.fillArc((x * av.charWidth) - av.charWidth, y + 4 + iconOffset,
+ av.charWidth, 8, 270, 180);
+ x2 -= av.charWidth / 2;
+ }
+
+ g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);
+ }
+
public void drawLineGraph(Graphics g, AlignmentAnnotation aa, int sRes,
int eRes, int y, float min, float max, int graphHeight)
{
@@ -1246,7 +1470,7 @@ public class AnnotationPanel extends JPanel implements MouseListener,
int eRes, float min, float max, int y)
{
ColourSchemeI profcolour = av.getGlobalColourScheme();
- if (profcolour==null)
+ if (profcolour == null)
{
profcolour = new jalview.schemes.ZappoColourScheme();
}
@@ -1272,7 +1496,21 @@ public class AnnotationPanel extends JPanel implements MouseListener,
int column;
int aaMax = aa.annotations.length - 1;
-
+ boolean renderHistogram = true, renderProfile = true;
+ if (aa.autoCalculated && aa.label.startsWith("Consensus"))
+ {
+ // TODO: generalise this to have render styles for consensus/profile data
+ if (aa.groupRef != null)
+ {
+ renderHistogram = aa.groupRef.isShowConsensusHistogram();
+ renderProfile = aa.groupRef.isShowSequenceLogo();
+ }
+ else
+ {
+ renderHistogram = av.isShowConsensusHistogram();
+ renderProfile = av.isShowSequenceLogo();
+ }
+ }
while (x < eRes - sRes)
{
column = sRes + x;
@@ -1291,7 +1529,6 @@ public class AnnotationPanel extends JPanel implements MouseListener,
x++;
continue;
}
-
if (aa.annotations[column].colour == null)
g.setColor(Color.black);
else
@@ -1300,49 +1537,91 @@ public class AnnotationPanel extends JPanel implements MouseListener,
y1 = y
- (int) (((aa.annotations[column].value - min) / (range)) * aa.graphHeight);
- if (y1 - y2 > 0)
+ if (renderHistogram)
{
- g.fillRect(x * av.charWidth, y2, av.charWidth, y1 - y2);
- }
- else
- {
- g.fillRect(x * av.charWidth, y1, av.charWidth, y2 - y1);
+ if (y1 - y2 > 0)
+ {
+ g.fillRect(x * av.charWidth, y2, av.charWidth, y1 - y2);
+ }
+ else
+ {
+ g.fillRect(x * av.charWidth, y1, av.charWidth, y2 - y1);
+ }
}
// draw profile if available
- if (aa.annotations[column].value!=0)
+ if (renderProfile && aa.annotations[column].value != 0)
{
- int profl[] = getProfileFor(aa,column);
- int ht = y1,htn=y2-y1;//aa.graphHeight;
+
+ int profl[] = getProfileFor(aa, column);
+ // just try to draw the logo if profl is not null
+ if (profl != null)
+ {
+
+ int ht = y1, htn = y2 - y1;// aa.graphHeight;
float wdth;
- double ht2=0;
- char[] dc = new char[1];
+ double ht2 = 0;
+ char[] dc;
+
+ /**
+ * profl.length == 51 indicates that the profile of a secondary
+ * structure conservation row was accesed.
+ * Therefore dc gets length 2, to have space for a basepair instead of
+ * just a single nucleotide
+ */
+ if (profl.length == 51)
+ {
+ dc = new char[2];
+ }
+ else
+ {
+ dc = new char[1];
+ }
+
LineMetrics lm;
- for (int c=1;profl!=null && c2)
+ wdth = av.charWidth;
+ wdth /= (float) fm.charsWidth(dc, 0, dc.length);
+
+ if (c > 2)
{
- ht+=(int)ht2;
+ ht += (int) ht2;
}
{
- //if (aa.annotations[column].value==0) {
- // g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(wdth, (ht2=(aa.graphHeight*0.1/av.charHeight)))));
- // ht = y2-(int)ht2;
- //} else {
- g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(wdth, (ht2=(htn*((double)profl[c++])/100.0))/av.charHeight)));
- lm = g.getFontMetrics().getLineMetrics(dc,0,1, g);
- //htn -=ht2;
- //}
- g.setColor(profcolour.findColour(dc[0])); // (av.globalColourScheme!=null) ? );// try to get a colourscheme for the group(aa.groupRef.cs==null) ? av.textColour2 : cs.findColour(dc));
- g.drawChars(dc,0,1,x*av.charWidth, (int) (ht+lm.getHeight()));
+ // if (aa.annotations[column].value==0) {
+ // g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(wdth,
+ // (ht2=(aa.graphHeight*0.1/av.charHeight)))));
+ // ht = y2-(int)ht2;
+ // } else {
+ g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(
+ wdth, (ht2 = (htn * ((double) profl[c++]) / 100.0))
+ / av.charHeight)));
+ lm = g.getFontMetrics().getLineMetrics(dc, 0, 1, g);
+ // htn -=ht2;
+ // }
+ g.setColor(profcolour.findColour(dc[0])); // (av.globalColourScheme!=null)
+ // ? );// try to get a
+ // colourscheme for the
+ // group(aa.groupRef.cs==null)
+ // ? av.textColour2 :
+ // cs.findColour(dc));
+ // System.out.println(dc[0]);
+
+ g.drawChars(dc, 0, dc.length, x * av.charWidth,
+ (int) (ht + lm.getHeight()));
+
// ht+=g.getFontMetrics().getAscent()-g.getFontMetrics().getDescent();
}
}
g.setFont(ofont);
+ }
}
x++;
}
@@ -1362,13 +1641,46 @@ public class AnnotationPanel extends JPanel implements MouseListener,
private int[] getProfileFor(AlignmentAnnotation aa, int column)
{
- if (aa.groupRef!=null && aa.groupRef.consensusData!=null) {
- return AAFrequency.extractProfile(aa.groupRef.consensusData[column],aa.groupRef.getIgnoreGapsConsensus());
+ if (aa.autoCalculated && aa.label.startsWith("Consensus"))
+ {
+ if (aa.groupRef != null && aa.groupRef.consensusData != null
+ && aa.groupRef.isShowSequenceLogo())
+ {
+ return AAFrequency.extractProfile(
+ aa.groupRef.consensusData[column], aa.groupRef
+ .getIgnoreGapsConsensus());
+ }
+ // TODO extend annotation row to enable dynamic and static profile data to
+ // be stored
+ if (aa.groupRef == null && aa.sequenceRef == null
+ && av.isShowSequenceLogo())
+ {
+ return AAFrequency.extractProfile(av.hconsensus[column], av
+ .getIgnoreGapsConsensus());
+ }
}
- // TODO extend annotation row to enable dynamic and static profile data to be stored
- if (aa.autoCalculated && aa.groupRef==null && aa.sequenceRef==null && aa.label.equals("Consensus"))
+ else
{
- return AAFrequency.extractProfile(av.hconsensus[column],av.getIgnoreGapsConsensus());
+ if (aa.autoCalculated && aa.label.startsWith("StrucConsensus"))
+ {
+ if (aa.groupRef != null && aa.groupRef.consensusData != null
+ && aa.groupRef.isShowSequenceLogo())
+ {
+ //TODO check what happens for group selections
+ return StructureFrequency.extractProfile(
+ aa.groupRef.consensusData[column], aa.groupRef
+ .getIgnoreGapsConsensus());
+ }
+ // TODO extend annotation row to enable dynamic and static profile data
+ // to
+ // be stored
+ if (aa.groupRef == null && aa.sequenceRef == null
+ && av.isShowSequenceLogo())
+ {
+ return StructureFrequency.extractProfile(av.hStrucConsensus[column],
+ av.getIgnoreGapsConsensus());
+ }
+ }
}
return null;
}