Merge branch 'develop' into bug/JAL-2510amendFeatures
[jalview.git] / src / jalview / renderer / OverviewRenderer.java
diff --git a/src/jalview/renderer/OverviewRenderer.java b/src/jalview/renderer/OverviewRenderer.java
new file mode 100644 (file)
index 0000000..9291ca6
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * 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.
+ *  
+ * 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 <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import jalview.api.AlignmentColsCollectionI;
+import jalview.api.AlignmentRowsCollectionI;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.renderer.seqfeatures.FeatureRenderer;
+import jalview.viewmodel.OverviewDimensions;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+public class OverviewRenderer
+{
+  private FeatureColourFinder finder;
+
+  private jalview.api.SequenceRenderer sr;
+
+  // image to render on
+  private BufferedImage miniMe;
+
+  // raw number of pixels to allocate to each column
+  private float pixelsPerCol;
+
+  // raw number of pixels to allocate to each row
+  private float pixelsPerSeq;
+
+  public OverviewRenderer(jalview.api.SequenceRenderer seqRenderer,
+          FeatureRenderer fr, OverviewDimensions od)
+  // FeatureColourFinder colfinder, OverviewDimensions od)
+  {
+    sr = seqRenderer;
+    finder = new FeatureColourFinder(fr); // colfinder;
+
+    pixelsPerCol = od.getPixelsPerCol();
+    pixelsPerSeq = od.getPixelsPerSeq();
+    miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
+            BufferedImage.TYPE_INT_RGB);
+  }
+
+  /**
+   * Draw alignment rows and columns onto an image
+   * 
+   * @param rit
+   *          Iterator over rows to be drawn
+   * @param cit
+   *          Iterator over columns to be drawn
+   * @return image containing the drawing
+   */
+  public BufferedImage draw(AlignmentRowsCollectionI rows,
+          AlignmentColsCollectionI cols)
+  {
+    int rgbcolor = Color.white.getRGB();
+    int seqIndex = 0;
+    int pixelRow = 0;
+    for (int alignmentRow : rows)
+    {
+      // get details of this alignment row
+      boolean hidden = rows.isHidden(alignmentRow);
+      SequenceI seq = rows.getSequence(alignmentRow);
+
+      // calculate where this row extends to in pixels
+      int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
+              miniMe.getHeight() - 1);
+
+      int colIndex = 0;
+      int pixelCol = 0;
+      for (int alignmentCol : cols)
+      {
+        // calculate where this column extends to in pixels
+        int endCol = Math.min(
+                Math.round((colIndex + 1) * pixelsPerCol) - 1,
+                miniMe.getWidth() - 1);
+
+        // don't do expensive colour determination if we're not going to use it
+        // NB this is important to avoid performance issues in the overview
+        // panel
+        if (pixelCol <= endCol)
+        {
+          // determine the colour based on the sequence and column position
+          rgbcolor = getColumnColourFromSequence(seq,
+                  hidden || cols.isHidden(alignmentCol), alignmentCol,
+                  finder);
+
+          // fill in the appropriate number of pixels
+          for (int row = pixelRow; row <= endRow; ++row)
+          {
+            for (int col = pixelCol; col <= endCol; ++col)
+            {
+              miniMe.setRGB(col, row, rgbcolor);
+            }
+          }
+
+          pixelCol = endCol + 1;
+        }
+        colIndex++;
+      }
+      pixelRow = endRow + 1;
+      seqIndex++;
+    }
+    return miniMe;
+  }
+
+  /*
+   * Find the colour of a sequence at a specified column position
+   */
+  private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq,
+          boolean isHidden, int lastcol, FeatureColourFinder fcfinder)
+  {
+    Color color = Color.white;
+
+    if ((seq != null) && (seq.getLength() > lastcol))
+    {
+      color = sr.getResidueColour(seq, lastcol, fcfinder);
+    }
+
+    if (isHidden)
+    {
+      color = color.darker().darker();
+    }
+
+    return color.getRGB();
+  }
+
+  /**
+   * Draw the alignment annotation in the overview panel
+   * 
+   * @param g
+   *          the graphics object to draw on
+   * @param anno
+   *          alignment annotation information
+   * @param charWidth
+   *          alignment character width value
+   * @param y
+   *          y-position for the annotation graph
+   * @param cols
+   *          the collection of columns used in the overview panel
+   */
+  public void drawGraph(Graphics g, AlignmentAnnotation anno, int charWidth,
+          int y, AlignmentColsCollectionI cols)
+  {
+    Annotation[] annotations = anno.annotations;
+    g.setColor(Color.white);
+    g.fillRect(0, 0, miniMe.getWidth(), y);
+
+    int height;
+    int colIndex = 0;
+    int pixelCol = 0;
+    for (int alignmentCol : cols)
+    {
+      if (alignmentCol >= annotations.length)
+      {
+        break; // no more annotations to draw here
+      }
+      else
+      {
+        int endCol = Math.min(
+                Math.round((colIndex + 1) * pixelsPerCol) - 1,
+                miniMe.getWidth() - 1);
+
+        if (annotations[alignmentCol] != null)
+        {
+          if (annotations[alignmentCol].colour == null)
+          {
+            g.setColor(Color.black);
+          }
+          else
+          {
+            g.setColor(annotations[alignmentCol].colour);
+          }
+
+          height = (int) ((annotations[alignmentCol].value / anno.graphMax) * y);
+          if (height > y)
+          {
+            height = y;
+          }
+
+          g.fillRect(pixelCol, y - height, endCol - pixelCol + 1, height);
+        }
+        pixelCol = endCol + 1;
+        colIndex++;
+      }
+    }
+  }
+}