X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fappletgui%2FAnnotationPanel.java;h=7d1333bff4796e55ac3e36a8b2eaeb684f3d587f;hb=a45774ee31d9f35d4eff46d54d7deab719afb092;hp=13db9158c5959ccb37cb52e1b625a5b09ed5ae0b;hpb=506d60f0e188723ddc91c26824b41ac7034df3fe;p=jalview.git diff --git a/src/jalview/appletgui/AnnotationPanel.java b/src/jalview/appletgui/AnnotationPanel.java index 13db915..7d1333b 100755 --- a/src/jalview/appletgui/AnnotationPanel.java +++ b/src/jalview/appletgui/AnnotationPanel.java @@ -1,20 +1,19 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4) - * Copyright (C) 2008 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, 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.appletgui; @@ -22,8 +21,12 @@ import java.util.*; import java.awt.*; import java.awt.event.*; +import java.awt.font.LineMetrics; +import java.awt.geom.AffineTransform; +import jalview.analysis.AAFrequency; import jalview.datamodel.*; +import jalview.schemes.ColourSchemeI; public class AnnotationPanel extends Panel implements AdjustmentListener, ActionListener, MouseListener, MouseMotionListener @@ -60,6 +63,13 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, boolean fastPaint = false; + // Used For mouse Dragging and resizing graphs + int graphStretch = -1; + + int graphStretchY = -1; + + boolean mouseDragging = false; + public static int GRAPH_HEIGHT = 40; boolean MAC = false; @@ -70,7 +80,8 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, this.ap = ap; av = ap.av; setLayout(null); - adjustPanelHeight(); + int height = adjustPanelHeight(); + ap.apvscroll.setValues(0, getSize().height, 0, height); addMouseMotionListener(this); @@ -86,18 +97,21 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, public void adjustmentValueChanged(AdjustmentEvent evt) { - ap.alabels.setScrollOffset(-evt.getValue()); } /** * 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()) @@ -246,7 +260,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, return; } - int height = 0; + int height = -scrollOffset; activeRow = -1; for (int i = 0; i < aa.length; i++) @@ -262,6 +276,12 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, { activeRow = i; } + else if (aa[i].graph > 0) + { + // Stretch Graph + graphStretch = i; + graphStretchY = evt.getY(); + } break; } @@ -307,6 +327,14 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, public void mouseReleased(MouseEvent evt) { + graphStretch = -1; + graphStretchY = -1; + mouseDragging = false; + if (needValidating) + { + ap.validate(); + needValidating = false; + } ap.scalePanel.mouseReleased(evt); } @@ -314,9 +342,27 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, { } + boolean needValidating = false; + public void mouseDragged(MouseEvent evt) { - ap.scalePanel.mouseDragged(evt); + if (graphStretch > -1) + { + av.alignment.getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY + - evt.getY(); + if (av.alignment.getAlignmentAnnotation()[graphStretch].graphHeight < 0) + { + av.alignment.getAlignmentAnnotation()[graphStretch].graphHeight = 0; + } + graphStretchY = evt.getY(); + calcPanelHeight(); + needValidating = true; + ap.paintAlignment(true); + } + else + { + ap.scalePanel.mouseDragged(evt); + } } public void mouseMoved(MouseEvent evt) @@ -328,7 +374,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, } int row = -1; - int height = 0; + int height = -scrollOffset; for (int i = 0; i < aa.length; i++) { @@ -375,6 +421,26 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, public int adjustPanelHeight() { + return adjustPanelHeight(true); + } + + public int adjustPanelHeight(boolean repaint) + { + int height = calcPanelHeight(); + this.setSize(new Dimension(getSize().width, height)); + if (repaint) + { + repaint(); + } + 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; @@ -413,15 +479,11 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, height += aa[i].height; } } - else + if (height == 0) { height = 20; } - this.setSize(getSize().width, height); - - repaint(); - return height; } @@ -463,13 +525,16 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, public void paint(Graphics g) { - - imgWidth = getSize().width; + Dimension d = getSize(); + imgWidth = d.width; // (av.endRes - av.startRes + 1) * av.charWidth; - - if (image == null || imgWidth != image.getWidth(this)) + if (imgWidth<1 || d.height<1) { - image = createImage(imgWidth, ap.annotationPanel.getSize().height); + return; + } + if (image == null || imgWidth != image.getWidth(this) || d.height != image.getHeight(this)) + { + image = createImage(imgWidth, d.height); gg = image.getGraphics(); gg.setFont(av.getFont()); fm = gg.getFontMetrics(); @@ -527,15 +592,16 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, * 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) { - g.setFont(av.getFont()); + Font ofont = av.getFont(); + g.setFont(ofont); g.setColor(Color.white); g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height); @@ -560,7 +626,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, } AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation(); - + g.translate(0, -scrollOffset); int x = 0; int y = 0; int column = 0; @@ -569,8 +635,14 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, int iconOffset = av.charHeight / 2; 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. // \u03B2 \u03B1 for (int i = 0; i < aa.length; i++) { @@ -580,7 +652,9 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, { continue; } - + centreColLabels = row.centreColLabels || centreColLabelsDef; + labelAllCols = row.showAllColLabels; + scaleColLabel = row.scaleColLabel; lastSS = ' '; lastSSX = 0; @@ -596,13 +670,15 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, if (row.hasText) { + iconOffset = av.charHeight - fm.getDescent(); y -= av.charHeight; } } - - if (row.hasText) + // TODO: else is the logic used in application, applet had no 'else' + else if (row.hasText) { - iconOffset = av.charHeight / 2; + iconOffset = av.charHeight - fm.getDescent(); + } else { @@ -648,9 +724,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, if (v == column) { - g - .fillRect(x * av.charWidth, y, av.charWidth, - av.charHeight); + g.fillRect(x * av.charWidth, y, av.charWidth, av.charHeight); } } } @@ -661,13 +735,36 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, && (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 (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; + // not 1.1 // g.setFont(new + // Font(ofont,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 (row.annotations[column].colour == null) g.setColor(Color.black); @@ -677,16 +774,19 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, if (column == 0 || row.graph > 0) { g.drawString(row.annotations[column].displayCharacter, - (x * av.charWidth) + charOffset, y + iconOffset + 3); + (x * av.charWidth) + charOffset, y + iconOffset + 3); // + + // 3? } else if (row.annotations[column - 1] == null - || (!row.annotations[column].displayCharacter - .equals(row.annotations[column - 1].displayCharacter) || (row.annotations[column].displayCharacter + || (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 + 3); + (x * av.charWidth) + charOffset, y + iconOffset + 3); // +3? } + g.setFont(ofont); } if (row.hasIcons) @@ -720,7 +820,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, x1 += av.charWidth / 2; } - if (row.annotations[column] == null + if (!validRes || row.annotations[column] == null || row.annotations[column].secondaryStructure != 'H') { g.fillArc((x * av.charWidth) - av.charWidth, y + 4 @@ -802,9 +902,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, 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); + g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90, 180); x1 += av.charWidth / 2; } @@ -852,7 +950,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, } } - if (row.graph > 0) + if (row.graph > 0 && row.graphHeight > 0) { if (row.graph == AlignmentAnnotation.LINE_GRAPH) { @@ -915,6 +1013,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, y += aa[i].height; } } + g.translate(0, +scrollOffset); } public void drawLineGraph(Graphics g, AlignmentAnnotation aa, int sRes, @@ -966,7 +1065,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, } if (aa.annotations[column] == null) // || coaa.annotations[column - 1] == - // null) + // null) { x++; continue; @@ -1006,11 +1105,16 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, public void drawBarGraph(Graphics g, AlignmentAnnotation aa, int sRes, int eRes, float min, float max, int y) { + ColourSchemeI profcolour = av.getGlobalColourScheme(); + if (profcolour == null) + { + profcolour = new jalview.schemes.ZappoColourScheme(); + } if (sRes > aa.annotations.length) { return; } - + Font ofont = g.getFont(); eRes = Math.min(eRes, aa.annotations.length); int x = 0, y1 = y, y2 = y; @@ -1028,6 +1132,20 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, int column; int aaMax = aa.annotations.length - 1; + boolean renderHistogram = true, renderProfile = false; + 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) { @@ -1056,13 +1174,47 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, 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); + 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); + } } - else + // draw profile if available + if (aa.annotations[column].value != 0 && renderProfile) { - g.fillRect(x * av.charWidth, y1, av.charWidth, y2 - y1); + int profl[] = getProfileFor(aa, column); + int ht = y1, htn = y2 - y1;// aa.graphHeight; + float wdth; + double ht2 = 0; + char[] dc = new char[1]; + LineMetrics lm; + for (int c = 1; profl != null && c < profl[0];) + { + dc[0] = (char) profl[c++]; + wdth = av.charWidth; + wdth /= (float) fm.charsWidth(dc, 0, 1); + + if (c > 2) + { + ht += (int) ht2; + } + { // not java 1.1 compatible: Bug # 0060064 + g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance( + wdth, (ht2 = (htn * ((double) profl[c++]) / 100.0)) + / av.charHeight))); + lm = g.getFontMetrics().getLineMetrics(dc, 0, 1, g); + g.setColor(profcolour.findColour(dc[0])); + g.drawChars(dc, 0, 1, x * av.charWidth, + (int) (ht + lm.getHeight())); + } + } + g.setFont(ofont); } x++; @@ -1076,6 +1228,27 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, } } + private int[] getProfileFor(AlignmentAnnotation aa, int column) + { + // 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()); + } + // } + return null; + } + // used by overview window public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y, int sRes, int eRes) @@ -1103,4 +1276,12 @@ public class AnnotationPanel extends Panel implements AdjustmentListener, x += av.charWidth; } } + + int scrollOffset = 0; + + public void setScrollOffset(int value) + { + scrollOffset = value; + repaint(); + } }