JAL-3369 JAL-3253-applet adds embedded dim checking for overview frame
authorhansonr <hansonr@STO24954W.ad.stolaf.edu>
Mon, 29 Jul 2019 20:24:46 +0000 (15:24 -0500)
committerhansonr <hansonr@STO24954W.ad.stolaf.edu>
Mon, 29 Jul 2019 20:24:46 +0000 (15:24 -0500)
14 files changed:
src/jalview/api/AlignmentViewPanel.java
src/jalview/appletgui/AlignmentPanel.java
src/jalview/appletgui/OverviewCanvas.java
src/jalview/appletgui/OverviewPanel.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/Desktop.java
src/jalview/gui/OverviewCanvas.java
src/jalview/gui/OverviewPanel.java
src/jalview/renderer/OverviewRenderer.java
src/jalview/viewmodel/OverviewDimensions.java
src/jalview/viewmodel/OverviewDimensionsHideHidden.java
src/jalview/viewmodel/OverviewDimensionsShowHidden.java
test/jalview/renderer/OverviewRendererTest.java

index ad7800c..9593a5b 100644 (file)
@@ -23,6 +23,8 @@ package jalview.api;
 import jalview.datamodel.AlignmentI;
 import jalview.structure.StructureSelectionManager;
 
+import java.awt.image.BufferedImage;
+
 /**
  * abstract interface implemented by alignment panels holding an alignment view
  * 
@@ -65,4 +67,7 @@ public interface AlignmentViewPanel extends OOMHandlerI
   String getViewName();
 
   SequenceRenderer getSequenceRenderer();
+
+  void overviewDone(BufferedImage miniMe);
+
 }
index 58569cd..df8fe87 100644 (file)
@@ -43,6 +43,7 @@ import java.awt.event.AdjustmentEvent;
 import java.awt.event.AdjustmentListener;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
+import java.awt.image.BufferedImage;
 import java.beans.PropertyChangeEvent;
 import java.util.List;
 
@@ -178,6 +179,7 @@ public class AlignmentPanel extends Panel
     return av;
   }
 
+  @Override
   public SequenceRenderer getSequenceRenderer()
   {
     return seqPanel.seqCanvas.sr;
@@ -1158,4 +1160,10 @@ public class AlignmentPanel extends Panel
 
   }
 
+  @Override
+  public void overviewDone(BufferedImage miniMe)
+  {
+    overviewPanel.canvas.finalizeDraw(miniMe);
+  }
+
 }
index 07f5919..5ea9c04 100644 (file)
@@ -30,7 +30,9 @@ import java.awt.Dimension;
 import java.awt.Frame;
 import java.awt.Graphics;
 import java.awt.Image;
+import java.awt.image.BufferedImage;
 
+@SuppressWarnings("serial")
 public class OverviewCanvas extends Component
 {
   // This is set true if the alignment view changes whilst
@@ -49,13 +51,23 @@ public class OverviewCanvas extends Component
 
   private AlignViewport av;
 
+  private boolean showSequenceFeatures;
+
+  private boolean showAnnotation;
+
+  private jalview.api.FeatureRenderer featureRenderer;
+
   private jalview.renderer.seqfeatures.FeatureRenderer fr;
 
   private Frame nullFrame;
 
-  public OverviewCanvas(OverviewDimensions overviewDims,
+  private OverviewPanel panel;
+
+  public OverviewCanvas(OverviewPanel panel,
+          OverviewDimensions overviewDims,
           AlignViewport alignvp)
   {
+    this.panel = panel;
     od = overviewDims;
     av = alignvp;
 
@@ -101,46 +113,24 @@ public class OverviewCanvas extends Component
   }
 
   public void draw(boolean showSequenceFeatures, boolean showAnnotation,
-          FeatureRenderer transferRenderer)
+          jalview.api.FeatureRenderer featureRenderer)
   {
-    miniMe = null;
+    this.showSequenceFeatures = showSequenceFeatures;
+    this.showAnnotation = showAnnotation;
+    this.featureRenderer = featureRenderer;
 
     if (showSequenceFeatures)
     {
-      fr.transferSettings(transferRenderer);
+      fr.transferSettings(featureRenderer);
     }
 
     setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
 
-    or = new OverviewRenderer(fr, od, av.getAlignment(),
+    or = new OverviewRenderer(panel.ap, fr, od, av.getAlignment(),
             av.getResidueShading(), new OverviewResColourFinder());
-    miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
     offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
-
-    miniMe = or.draw(od.getRows(av.getAlignment()),
+    or.draw(od.getRows(av.getAlignment()),
             od.getColumns(av.getAlignment()));
-
-    Graphics mg = miniMe.getGraphics();
-
-    // checks for conservation annotation to make sure overview works for DNA
-    // too
-    if (showAnnotation)
-    {
-      mg.translate(0, od.getSequencesHeight());
-      or.drawGraph(mg, av.getAlignmentConservationAnnotation(),
-              od.getGraphHeight(), od.getColumns(av.getAlignment()));
-      mg.translate(0, -od.getSequencesHeight());
-    }
-
-    if (restart)
-    {
-      restart = false;
-      draw(showSequenceFeatures, showAnnotation, transferRenderer);
-    }
-    else
-    {
-      updaterunning = false;
-    }
   }
 
   @Override
@@ -152,13 +142,14 @@ public class OverviewCanvas extends Component
   @Override
   public void paint(Graphics g)
   {
-    Graphics og = offscreen.getGraphics();
     if (miniMe != null)
     {
+      Graphics og = offscreen.getGraphics();
       og.drawImage(miniMe, 0, 0, this);
       og.setColor(Color.red);
       od.drawBox(og);
       g.drawImage(offscreen, 0, 0, this);
+      og.dispose();
     }
   }
 
@@ -170,4 +161,29 @@ public class OverviewCanvas extends Component
     od = null;
   }
 
+  public void finalizeDraw(BufferedImage miniMe)
+  {
+    Graphics mg = miniMe.getGraphics();
+
+    // checks for conservation annotation to make sure overview works for DNA
+    // too
+    if (showAnnotation)
+    {
+      mg.translate(0, od.getSequencesHeight());
+      or.drawGraph(mg, av.getAlignmentConservationAnnotation(),
+              od.getGraphHeight(), od.getColumns(av.getAlignment()));
+      mg.translate(0, -od.getSequencesHeight());
+    }
+
+    if (restart)
+    {
+      restart = false;
+      draw(showSequenceFeatures, showAnnotation, featureRenderer);
+    }
+    else
+    {
+      updaterunning = false;
+    }
+  }
+
 }
index 4e69399..ef684f7 100755 (executable)
@@ -46,16 +46,17 @@ import java.beans.PropertyChangeEvent;
 
 import javax.swing.SwingUtilities;
 
+@SuppressWarnings("serial")
 public class OverviewPanel extends Panel implements Runnable,
         MouseMotionListener, MouseListener, ViewportListenerI
 {
-  private OverviewDimensions od;
+  OverviewDimensions od;
 
-  private OverviewCanvas oviewCanvas;
+  OverviewCanvas canvas;
 
   private AlignViewport av;
 
-  private AlignmentPanel ap;
+  AlignmentPanel ap;
 
   private boolean showHidden = true;
 
@@ -73,9 +74,9 @@ public class OverviewPanel extends Panel implements Runnable,
             (av.isShowAnnotation()
                     && av.getSequenceConsensusHash() != null));
 
-    oviewCanvas = new OverviewCanvas(od, av);
+    canvas = new OverviewCanvas(this, od, av);
     setLayout(new BorderLayout());
-    add(oviewCanvas, BorderLayout.CENTER);
+    add(canvas, BorderLayout.CENTER);
 
     setSize(new Dimension(od.getWidth(), od.getHeight()));
 
@@ -220,7 +221,7 @@ public class OverviewPanel extends Panel implements Runnable,
    */
   public void updateOverviewImage()
   {
-    if (oviewCanvas == null)
+    if (canvas == null)
     {
       /*
        * panel has been disposed
@@ -239,7 +240,7 @@ public class OverviewPanel extends Panel implements Runnable,
     {
       if (updateRunning)
       {
-        oviewCanvas.restartDraw();
+        canvas.restartDraw();
         return;
       }
 
@@ -254,7 +255,7 @@ public class OverviewPanel extends Panel implements Runnable,
   @Override
   public void run()
   {
-    oviewCanvas.draw(av.isShowSequenceFeatures(),
+    canvas.draw(av.isShowSequenceFeatures(),
             (av.isShowAnnotation()
                     && av.getAlignmentConservationAnnotation() != null),
             ap.seqPanel.seqCanvas.getFeatureRenderer());
@@ -321,7 +322,7 @@ public class OverviewPanel extends Panel implements Runnable,
               (av.isShowAnnotation()
                       && av.getAlignmentConservationAnnotation() != null));
     }
-    oviewCanvas.resetOviewDims(od);
+    canvas.resetOviewDims(od);
     updateOverviewImage();
   }
 
@@ -339,11 +340,11 @@ public class OverviewPanel extends Panel implements Runnable,
     } finally
     {
       av = null;
-      if (oviewCanvas != null)
+      if (canvas != null)
       {
-        oviewCanvas.dispose();
+        canvas.dispose();
       }
-      oviewCanvas = null;
+      canvas = null;
       ap = null;
       od = null;
     }
index 01aa9b0..4fa8408 100644 (file)
@@ -3385,12 +3385,38 @@ public class AlignFrame extends GAlignFrame
     }
 
     JInternalFrame frame = new JInternalFrame();
-    final OverviewPanel overview = new OverviewPanel(alignPanel);
+
+    // BH 2019.07.26 we allow for an embedded
+    // undecorated overview with defined size
+    frame.setName(Jalview.getAppID("overview"));
+    //
+    Dimension dim = (Dimension) Platform.getEmbeddedAttribute(frame,
+            Platform.EMBEDDED_DIM);
+    if (dim != null && dim.width == 0)
+    {
+      dim = null; // hidden, not embedded
+    }
+
+    OverviewPanel overview = new OverviewPanel(alignPanel, dim);
+
     frame.setContentPane(overview);
+    if (dim == null)
+    {
+      dim = new Dimension();
+      // was frame.getSize(), but that is 0,0 at this point;
+    }
+    else
+    {
+      // we are imbedding, and so we have an undecorated frame
+      // and we can set the the frame dimensions accordingly.
+    }
+    // allowing for unresizable option using, style="resize:none"
+    boolean resizable = (Platform.getEmbeddedAttribute(frame,
+            "resize") != "none");
     Desktop.addInternalFrame(frame, MessageManager
             .formatMessage("label.overview_params", new Object[]
-            { this.getTitle() }), true, frame.getWidth(), frame.getHeight(),
-            true, true, "overview");
+            { this.getTitle() }), true, dim.width, dim.height, resizable,
+            true);
     frame.pack();
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
     frame.addInternalFrameListener(
index 5fa8fdf..d305183 100644 (file)
@@ -1840,4 +1840,10 @@ public class AlignmentPanel extends GAlignmentPanel implements
     return true;
   }
 
+  @Override
+  public void overviewDone(BufferedImage miniMe)
+  {
+    overviewPanel.canvas.finalizeDraw(miniMe);
+  }
+
 }
index 957fb96..9fbfb83 100644 (file)
@@ -864,7 +864,7 @@ public class Desktop extends GDesktop
           final JInternalFrame frame, String title, int w, int h,
           boolean resizable)
   {
-    addInternalFrame(frame, title, true, w, h, resizable, false, null);
+    addInternalFrame(frame, title, true, w, h, resizable, false);
   }
 
   /**
@@ -887,38 +887,8 @@ public class Desktop extends GDesktop
    *          Do not set the default minimum size for frame
    */
   public static synchronized void addInternalFrame(
-          JInternalFrame frame, String title, boolean makeVisible, int w,
-          int h, boolean resizable, boolean ignoreMinSize)
-  {
-    addInternalFrame(frame, title, makeVisible, w, h, resizable,
-            ignoreMinSize, null);
-  }
-
-  /**
-   * Add an internal frame to the Jalview desktop
-   * 
-   * @param frame
-   *          Frame to show
-   * @param title
-   *          Visible Title
-   * @param makeVisible
-   *          When true, display frame immediately, otherwise, caller must call
-   *          setVisible themselves.
-   * @param w
-   *          width
-   * @param h
-   *          height
-   * @param resizable
-   *          Allow resize
-   * @param ignoreMinSize
-   *          Do not set the default minimum size for frame
-   * @param name
-   *          for HTML div embedding
-   */
-  public static synchronized void addInternalFrame(
           final JInternalFrame frame, String title, boolean makeVisible,
-          int w, int h, boolean resizable, boolean ignoreMinSize,
-          String name)
+          int w, int h, boolean resizable, boolean ignoreMinSize)
   {
 
 
@@ -927,13 +897,8 @@ public class Desktop extends GDesktop
     // TODO: consider fixing method to update entries in the window submenu with
     // the current window title
 
-    if (name != null)
-    {
-      frame.setName(Jalview.getAppID(name));
-    }
-
     frame.setTitle(title);
-    if (frame.getWidth() < 1 || frame.getHeight() < 1)
+    if (w > 0 && (frame.getWidth() < 1 || frame.getHeight() < 1))
     {
       frame.setSize(w, h);
     }
index ca27a9c..aafac38 100644 (file)
@@ -22,6 +22,7 @@ package jalview.gui;
 
 import jalview.api.AlignViewportI;
 import jalview.bin.Cache;
+import jalview.datamodel.AlignmentI;
 import jalview.renderer.OverviewRenderer;
 import jalview.renderer.OverviewResColourFinder;
 import jalview.viewmodel.OverviewDimensions;
@@ -33,6 +34,7 @@ import java.awt.image.BufferedImage;
 
 import javax.swing.JPanel;
 
+@SuppressWarnings("serial")
 public class OverviewCanvas extends JPanel
 {
   private static final Color TRANS_GREY = new Color(100, 100, 100, 25);
@@ -43,9 +45,7 @@ public class OverviewCanvas extends JPanel
 
   private volatile boolean updaterunning = false;
 
-  private boolean dispose = false;
-
-  private BufferedImage miniMe;
+  private boolean disposed = false;
 
   private BufferedImage lastMiniMe = null;
 
@@ -65,9 +65,19 @@ public class OverviewCanvas extends JPanel
 
   private ProgressPanel progressPanel;
 
-  public OverviewCanvas(OverviewDimensions overviewDims,
+  private boolean showSequenceFeatures;
+
+  private boolean showAnnotation;
+
+  private jalview.api.FeatureRenderer featureRenderer;
+
+  private OverviewPanel panel;
+
+  public OverviewCanvas(OverviewPanel panel,
+          OverviewDimensions overviewDims,
           AlignViewportI alignvp, ProgressPanel pp)
   {
+    this.panel = panel;
     od = overviewDims;
     av = alignvp;
     progressPanel = pp;
@@ -84,6 +94,7 @@ public class OverviewCanvas extends JPanel
     cf = new OverviewResColourFinder(useLegacy, gapCol, hiddenCol);
 
     setSize(od.getWidth(), od.getHeight());
+    setPreferredSize(getSize()); // BH 2019.07.29 added
   }
 
   /**
@@ -107,11 +118,7 @@ public class OverviewCanvas extends JPanel
     {
       if (updaterunning)
       {
-        restart = true;
-        if (or != null)
-        {
-          or.setRedraw(true);
-        }
+        setRestart("restartDraw");
       }
       else
       {
@@ -121,6 +128,16 @@ public class OverviewCanvas extends JPanel
     }
   }
 
+  private void setRestart(String why)
+  {
+    // System.out.println("OC restart true " + why);
+    restart = true;
+    if (or != null)
+    {
+      or.setRedraw(true);
+    }
+  }
+
   /**
    * Draw the overview sequences
    * 
@@ -128,31 +145,40 @@ public class OverviewCanvas extends JPanel
    *          true if sequence features are to be shown
    * @param showAnnotation
    *          true if the annotation is to be shown
-   * @param transferRenderer
+   * @param featureRenderer
    *          the renderer to transfer feature colouring from
    */
   public void draw(boolean showSequenceFeatures, boolean showAnnotation,
-          FeatureRenderer transferRenderer)
+          jalview.api.FeatureRenderer featureRenderer)
   {
-    miniMe = null;
+    this.showSequenceFeatures = showSequenceFeatures;
+    this.showAnnotation = showAnnotation;
+    this.featureRenderer = featureRenderer;
+
+    // System.out.println("OC draw " + ++ndraw + " showseqf="
+    // + showSequenceFeatures + " showAnno=" + showAnnotation);
 
     if (showSequenceFeatures)
     {
-      fr.transferSettings(transferRenderer);
+      fr.transferSettings(featureRenderer);
     }
 
     setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
 
-    or = new OverviewRenderer(fr, od, av.getAlignment(),
-            av.getResidueShading(), cf);
-
-    or.addPropertyChangeListener(progressPanel);
-
-    miniMe = or.draw(od.getRows(av.getAlignment()),
-            od.getColumns(av.getAlignment()));
+    AlignmentI al = av.getAlignment();
+    or = new OverviewRenderer(panel.ap, fr, od, al,
+            av.getResidueShading(), cf,
+            progressPanel != null);
+    if (progressPanel != null)
+    {
+      or.addPropertyChangeListener(progressPanel);
+    }
+    or.draw(od.getRows(al), od.getColumns(al));
+  }
 
+  void finalizeDraw(BufferedImage miniMe)
+  {
     Graphics mg = miniMe.getGraphics();
-
     if (showAnnotation)
     {
       mg.translate(0, od.getSequencesHeight());
@@ -160,113 +186,125 @@ public class OverviewCanvas extends JPanel
               od.getGraphHeight(), od.getColumns(av.getAlignment()));
       mg.translate(0, -od.getSequencesHeight());
     }
-
-    or.removePropertyChangeListener(progressPanel);
+    mg.dispose(); // BH 2019
+    if (progressPanel != null)
+    {
+      or.removePropertyChangeListener(progressPanel);
+    }
     or = null;
     if (restart)
     {
       restart = false;
-      if (!dispose)
+      if (!disposed)
       {
-        draw(showSequenceFeatures, showAnnotation, transferRenderer);
+        draw(showSequenceFeatures, showAnnotation, featureRenderer);
       }
     }
     else
     {
       updaterunning = false;
       lastMiniMe = miniMe;
+      repaint();
     }
-  }
 
+  }
   @Override
   public void paintComponent(Graphics g)
   {
-    //super.paintComponent(g);
 
+    int w = getWidth();
+    int h = getHeight();
+    if (w == 0 || od.getBoxWidth() <= 0)
+    {
+      // BH 2019.07.27 removes two unnecessary paints, since boxwidth can be -1
+      // or 0 during early-stage painting
+      return;
+    }
+
+    boolean drawMe = (lastMiniMe != null);
     if (restart)
     {
-      if (lastMiniMe == null)
+      if (drawMe)
       {
-        g.setColor(Color.white);
-        g.fillRect(0, 0, getWidth(), getHeight());
+        g.drawImage(lastMiniMe, 0, 0, w, h, this);
       }
       else
       {
-        g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
+        g.setColor(Color.white);
+        g.fillRect(0, 0, w, h);
       }
       g.setColor(TRANS_GREY);
-      g.fillRect(0, 0, getWidth(), getHeight());
+      g.fillRect(0, 0, w, h);
+      drawMe = false;
     }
-    else if (lastMiniMe != null)
+    else if (drawMe)
     {
       // is this a resize?
-      if ((getWidth() > 0) && (getHeight() > 0)
-              && ((getWidth() != od.getWidth())
-                      || (getHeight() != od.getHeight())))
+      if (w != od.getWidth() ||  h != od.getHeight()) {
+      // if there is annotation, scale the alignment and annotation
+      // separately
+      if (od.getGraphHeight() <= 0 && od.getSequencesHeight() <= 0)
       {
-        // if there is annotation, scale the alignment and annotation
-        // separately
-        if (od.getGraphHeight() > 0 
-                       && od.getSequencesHeight() > 0  // BH 2019
-                       )
-        {
-          BufferedImage topImage = lastMiniMe.getSubimage(0, 0,
-                  od.getWidth(), od.getSequencesHeight());
-          BufferedImage bottomImage = lastMiniMe.getSubimage(0,
-                  od.getSequencesHeight(), od.getWidth(),
-                  od.getGraphHeight());
-
-          // must be done at this point as we rely on using old width/height
-          // above, and new width/height below
-          od.setWidth(getWidth());
-          od.setHeight(getHeight());
-
-          // stick the images back together so lastMiniMe is consistent in the
-          // event of a repaint - BUT probably not thread safe
-          lastMiniMe = new BufferedImage(od.getWidth(), od.getHeight(),
-                  BufferedImage.TYPE_INT_RGB);
-          Graphics lg = lastMiniMe.getGraphics();
-          lg.drawImage(topImage, 0, 0, od.getWidth(),
-                  od.getSequencesHeight(), null);
-          lg.drawImage(bottomImage, 0, od.getSequencesHeight(),
-                  od.getWidth(), od.getGraphHeight(), this);
-          lg.dispose();
-        }
-        else
-        {
-          od.setWidth(getWidth());
-          od.setHeight(getHeight());
-        }
-
-        // make sure the box is in the right place
-        od.setBoxPosition(av.getAlignment().getHiddenSequences(),
-                av.getAlignment().getHiddenColumns());
+        od.setWidth(w);
+        od.setHeight(h);
+        return;
+      }
+        // System.out.println("OC new subimages");
+      BufferedImage topImage = lastMiniMe.getSubimage(0, 0, od.getWidth(),
+              od.getSequencesHeight());
+      BufferedImage bottomImage = lastMiniMe.getSubimage(0,
+              od.getSequencesHeight(), od.getWidth(), od.getGraphHeight());
+
+      // must be done at this point as we rely on using old width/height
+      // above, and new width/height below
+      od.setWidth(w);
+      od.setHeight(h);
+
+      // stick the images back together so lastMiniMe is consistent in the
+      // event of a repaint - BUT probably not thread safe
+      // System.out.println("OC new lastminime " + w + " " + h);
+      lastMiniMe = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+      Graphics lg = lastMiniMe.getGraphics();
+      lg.drawImage(topImage, 0, 0, w, od.getSequencesHeight(), null);
+      lg.drawImage(bottomImage, 0, od.getSequencesHeight(), w,
+              od.getGraphHeight(), this);
+      lg.dispose();
+      // BH 2019: removed -- this is now taken care of using vpbox in
+      // OverviewDimension
+      // // make sure the box is in the right place
+      // od.setBoxPosition(av.getAlignment().getHiddenSequences(),
+      // av.getAlignment().getHiddenColumns());
       }
-      // fall back to normal behaviour
-      g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
     }
-    else
+
+    if (drawMe)
     {
-      g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
+      g.drawImage(lastMiniMe, 0, 0, w, h, this);
     }
-    
     // draw the box
     g.setColor(Color.red);
+    // System.out.println("OC paintComponent nd=" + ndraw + " nr=" + nrepaint
+    // + " np=" + ++npaint);
     od.drawBox(g);
   }
 
+  private int ndraw, npaint, nrepaint;
+
+  // @Override
+  // public void repaint()
+  // {
+  // System.out.println("OC repaint " + (++nrepaint));
+  // super.repaint();
+  // }
 
   public void dispose()
   {
-    dispose = true;
+    disposed = true;
     od = null;
     synchronized (this)
     {
-      restart = true;
-      if (or != null)
-      {
-        or.setRedraw(true);
-      }
+      setRestart("dispose");
     }
   }
+
 }
index a5aaf7c..8f24185 100755 (executable)
@@ -20,6 +20,8 @@
  */
 package jalview.gui;
 
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
 import jalview.bin.Cache;
 import jalview.renderer.OverviewRenderer;
 import jalview.util.MessageManager;
@@ -61,11 +63,11 @@ public class OverviewPanel extends JPanel
 {
   protected OverviewDimensions od;
 
-  private OverviewCanvas oviewCanvas;
+  OverviewCanvas canvas;
 
-  protected AlignViewport av;
+  protected AlignViewportI av;
 
-  private AlignmentPanel ap;
+  AlignmentViewPanel ap;
 
   protected JCheckBoxMenuItem displayToggle;
 
@@ -75,70 +77,79 @@ public class OverviewPanel extends JPanel
 
   protected ProgressPanel progressPanel;
 
+  private Dimension dim;
+
+  private boolean showProgress = !Platform.isJS(); // Jalview.getInstance().getShowStatus()
+
   /**
    * Creates a new OverviewPanel object.
    * 
    * @param alPanel
    *          The alignment panel which is shown in the overview panel
    */
-  public OverviewPanel(AlignmentPanel alPanel)
+  public OverviewPanel(AlignmentViewPanel alPanel, Dimension dim)
   {
-    this.av = alPanel.av;
+    this.av = alPanel.getAlignViewport();
     this.ap = alPanel;
+    this.dim = dim;
 
     showHidden = Cache.getDefault(Preferences.SHOW_OV_HIDDEN_AT_START,
             false);
-    if (showHidden)
-    {
-      od = new OverviewDimensionsShowHidden(av.getRanges(),
-            (av.isShowAnnotation()
-                    && av.getAlignmentConservationAnnotation() != null));
-    }
-    else
-    {
-      od = new OverviewDimensionsHideHidden(av.getRanges(),
-              (av.isShowAnnotation()
-                      && av.getAlignmentConservationAnnotation() != null));
-    }
-
+    createOverviewDimensions();
     setLayout(new BorderLayout());
     progressPanel = new ProgressPanel(OverviewRenderer.UPDATE,
             MessageManager.getString("label.oview_calc"), getWidth());
-    this.add(progressPanel, BorderLayout.SOUTH);
-    oviewCanvas = new OverviewCanvas(od, av, progressPanel);
-
-    add(oviewCanvas, BorderLayout.CENTER);
+    if (showProgress) // BH 2019
+    {
+      add(progressPanel, BorderLayout.SOUTH);
+    }
+    canvas = new OverviewCanvas(this, od, av,
+            showProgress ? progressPanel : null);
+    canvas.setPreferredSize(canvas.getSize());
+    add(canvas, BorderLayout.CENTER);
 
     av.getRanges().addPropertyChangeListener(this);
 
     // without this the overview window does not size to fit the overview canvas
-    setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
-    
+    // BH - no,no! - This does not include the progressPanel!
+    // BH the problem was that OverviewCanvas.setPreferredSize() had not been set.
+    // setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
+
     addComponentListener(new ComponentAdapter()
     {
       @Override
       public void componentResized(ComponentEvent evt)
       {
+        int ph = (progressPanel.getParent() == null ? 0
+                : progressPanel.getHeight());
         // Resize is called on the initial display of the overview.
         // This code adjusts sizes to account for the progress bar if it has not
         // already been accounted for, which triggers another resize call for
         // the correct sizing, at which point the overview image is updated.
         // (This avoids a double recalculation of the image.)
-        if (getWidth() == od.getWidth() && getHeight() == od.getHeight()
-                + progressPanel.getHeight())
+        if (getWidth() == od.getWidth()
+                && getHeight() == od.getHeight() + ph)
         {
           updateOverviewImage();
         }
         else
         {
-          if ((getWidth() > 0) && (getHeight() > 0))
+          int w = getWidth();
+          int h = getHeight();
+          if ((w > 0) && (h > 0))
           {
-            od.setWidth(getWidth());
-            od.setHeight(getHeight() - progressPanel.getHeight());
+            if (dim != null)
+            {
+              dim.setSize(w, h - ph);
+            }
+            od.setWidth(w);
+            od.setHeight(h - ph);
+            repaint();
           }
-
-          setPreferredSize(new Dimension(od.getWidth(),
-                  od.getHeight() + progressPanel.getHeight()));
+          // BH 2019.07.29 this is unnecessary -- it is what layout managers are
+          // for:
+          // setPreferredSize(new Dimension(od.getWidth(), od.getHeight() +
+          // ph));
         }
       }
 
@@ -195,37 +206,39 @@ public class OverviewPanel extends JPanel
       @Override
       public void mousePressed(MouseEvent evt)
       {
-         
-       if (Platform.isWinRightButton(evt)) {
-               showPopupMenu(evt);
-               return;
-       }
-        if (SwingUtilities.isRightMouseButton(evt)) {
-               return;
+
+        if (Platform.isWinRightButton(evt))
+        {
+          showPopupMenu(evt);
+          return;
         }
-          // don't do anything if the mouse press is in the overview's box
-          // (wait to see if it's a drag instead)
-          // otherwise update the viewport
-          if (!od.isPositionInBox(evt.getX(), evt.getY()))
-          {
-            draggingBox = false;
+        if (SwingUtilities.isRightMouseButton(evt))
+        {
+          return;
+        }
+        // don't do anything if the mouse press is in the overview's box
+        // (wait to see if it's a drag instead)
+        // otherwise update the viewport
+        if (!od.isPositionInBox(evt.getX(), evt.getY()))
+        {
+          draggingBox = false;
 
-            // display drag cursor at mouse position
-            setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+          // display drag cursor at mouse position
+          setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
 
-            od.updateViewportFromMouse(evt.getX(), evt.getY(),
-                    av.getAlignment().getHiddenSequences(),
-                    av.getAlignment().getHiddenColumns());
-            getParent().setCursor(
-                    Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-          }
-          else
-          {
-            draggingBox = true;
-            od.setDragPoint(evt.getX(), evt.getY(),
-                    av.getAlignment().getHiddenSequences(),
-                    av.getAlignment().getHiddenColumns());
-          }
+          od.updateViewportFromMouse(evt.getX(), evt.getY(),
+                  av.getAlignment().getHiddenSequences(),
+                  av.getAlignment().getHiddenColumns());
+          getParent().setCursor(
+                  Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+        }
+        else
+        {
+          draggingBox = true;
+          od.setDragPoint(evt.getX(), evt.getY(),
+                  av.getAlignment().getHiddenSequences(),
+                  av.getAlignment().getHiddenColumns());
+        }
       }
 
       @Override
@@ -255,6 +268,26 @@ public class OverviewPanel extends JPanel
     }
   }
 
+  /**
+   * Create the appropriate type of OverViewDimensions, with the desired size.
+   */
+  private void createOverviewDimensions()
+  {
+    boolean showAnnotation = (av.isShowAnnotation()
+            && av.getAlignmentConservationAnnotation() != null);
+    if (showHidden)
+    {
+      od = new OverviewDimensionsShowHidden(av.getRanges(), showAnnotation,
+              dim);
+    }
+    else
+    {
+      od = new OverviewDimensionsHideHidden(av.getRanges(), showAnnotation,
+              dim);
+    }
+
+  }
+
   /*
    * Displays the popup menu and acts on user input
    */
@@ -285,21 +318,9 @@ public class OverviewPanel extends JPanel
    */
   protected void toggleHiddenColumns()
   {
-    if (showHidden)
-    {
-      showHidden = false;
-      od = new OverviewDimensionsHideHidden(av.getRanges(),
-              (av.isShowAnnotation()
-                      && av.getAlignmentConservationAnnotation() != null));
-    }
-    else
-    {
-      showHidden = true;
-      od = new OverviewDimensionsShowHidden(av.getRanges(),
-              (av.isShowAnnotation()
-                      && av.getAlignmentConservationAnnotation() != null));
-    }
-    oviewCanvas.resetOviewDims(od);
+    showHidden = !showHidden;
+    createOverviewDimensions();
+    canvas.resetOviewDims(od);
     updateOverviewImage();
     setBoxPosition();
   }
@@ -309,7 +330,7 @@ public class OverviewPanel extends JPanel
    */
   public void updateOverviewImage()
   {
-    if (oviewCanvas == null)
+    if (canvas == null)
     {
       /*
        * panel has been disposed
@@ -317,36 +338,35 @@ public class OverviewPanel extends JPanel
       return;
     }
 
+    int ph = (progressPanel.getParent() == null ? 0
+            : progressPanel.getHeight());
+
     if ((getWidth() > 0) && (getHeight() > 0))
     {
       od.setWidth(getWidth());
-      od.setHeight(getHeight() - progressPanel.getHeight());
+      od.setHeight(getHeight() - ph);
     }
-    
-    setPreferredSize(new Dimension(od.getWidth(),
-            od.getHeight() + progressPanel.getHeight()));
 
-    if (oviewCanvas.restartDraw())
+    setPreferredSize(new Dimension(od.getWidth(), od.getHeight() + ph));
+
+    if (canvas.restartDraw())
     {
       return;
     }
 
     Thread thread = new Thread(this);
     thread.start();
-    repaint();
-
-    
   }
 
   @Override
   public void run()
   {
-    if (oviewCanvas != null)
+    if (canvas != null)
     {
-      oviewCanvas.draw(av.isShowSequenceFeatures(),
+      canvas.draw(av.isShowSequenceFeatures(),
               (av.isShowAnnotation()
                       && av.getAlignmentConservationAnnotation() != null),
-              ap.getSeqPanel().seqCanvas.getFeatureRenderer());
+              ap.getFeatureRenderer());
       setBoxPosition();
     }
   }
@@ -360,6 +380,7 @@ public class OverviewPanel extends JPanel
   {
     if (od != null)
     {
+      od.updateBox();
       int oldX = od.getBoxX();
       int oldY = od.getBoxY();
       int oldWidth = od.getBoxWidth();
@@ -400,14 +421,15 @@ public class OverviewPanel extends JPanel
         av.getRanges().removePropertyChangeListener(this);
       }
 
-      oviewCanvas.dispose();
+      canvas.dispose();
 
       /*
        * close the parent frame (which also removes it from the
        * Desktop Windows menu)
        */
-      ((JInternalFrame) SwingUtilities.getAncestorOfClass(
-              JInternalFrame.class, (this))).setClosed(true);
+      ((JInternalFrame) SwingUtilities
+              .getAncestorOfClass(JInternalFrame.class, (this)))
+                      .setClosed(true);
     } catch (PropertyVetoException e)
     {
       // ignore
@@ -415,7 +437,7 @@ public class OverviewPanel extends JPanel
     {
       progressPanel = null;
       av = null;
-      oviewCanvas = null;
+      canvas = null;
       ap = null;
       od = null;
     }
index c9096e2..45cc944 100644 (file)
@@ -22,6 +22,7 @@ package jalview.renderer;
 
 import jalview.api.AlignmentColsCollectionI;
 import jalview.api.AlignmentRowsCollectionI;
+import jalview.api.AlignmentViewPanel;
 import jalview.api.RendererListenerI;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
@@ -30,14 +31,23 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.renderer.seqfeatures.FeatureRenderer;
+import jalview.util.Platform;
 import jalview.viewmodel.OverviewDimensions;
 
 import java.awt.AlphaComposite;
 import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.WritableRaster;
 import java.beans.PropertyChangeSupport;
+import java.util.BitSet;
+import java.util.Iterator;
+
+import javax.swing.Timer;
 
 public class OverviewRenderer
 {
@@ -75,10 +85,25 @@ public class OverviewRenderer
 
   private OverviewResColourFinder resColFinder;
 
-  public OverviewRenderer(FeatureRenderer fr, OverviewDimensions od,
+  private boolean showProgress;
+
+  private AlignmentViewPanel panel;
+
+  public OverviewRenderer(AlignmentViewPanel panel, FeatureRenderer fr,
+          OverviewDimensions od,
           AlignmentI alignment,
           ResidueShaderI resshader, OverviewResColourFinder colFinder)
   {
+    this(panel, fr, od, alignment, resshader, colFinder, true);
+  }
+
+  public OverviewRenderer(AlignmentViewPanel panel,
+          jalview.api.FeatureRenderer fr,
+          OverviewDimensions od,
+          AlignmentI alignment, ResidueShaderI resshader,
+          OverviewResColourFinder colFinder, boolean showProgress)
+  {
+    this.panel = panel;
     finder = new FeatureColourFinder(fr);
     resColFinder = colFinder;
 
@@ -90,108 +115,243 @@ public class OverviewRenderer
     graphHeight = od.getGraphHeight();
     miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
             BufferedImage.TYPE_INT_RGB);
+    this.showProgress = showProgress;
   }
 
-  /**
-   * 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)
+  final static int STATE_INIT = 0;
+  final static int STATE_NEXT = 1;
+  final static int STATE_DONE = 2;
+
+  int state;
+
+  boolean isJS = Platform.isJS();
+
+  Timer timer;
+  int delay = (isJS ? 1 : 0);
+
+  int seqIndex;
+
+  int pixelRow;
+
+  private Integer row;
+
+  void mainLoop()
+  {
+    while (!redraw)
+    {
+      switch (state)
+      {
+      case STATE_INIT:
+        seqIndex = 0;
+        pixelRow = 0;
+        state = STATE_NEXT;
+        continue;
+      case STATE_NEXT:
+        if (iter.hasNext())
+        {
+          nextRow();
+        }
+        else
+        {
+          state = STATE_DONE;
+        }
+        break;
+      case STATE_DONE:
+        done();
+        return;
+      }
+      if (delay > 0)
+      {
+        jsloop();
+        return;
+      }
+    }
+    done();
+  }
+
+  private void jsloop()
+  {
+    if (timer == null)
+    {
+      timer = new Timer(delay, new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          mainLoop();
+        }
+
+      });
+      timer.setRepeats(false);
+      timer.start();
+    }
+    else
+    {
+      timer.restart();
+    }
+  }
+
+  private void nextRow()
   {
-    int rgbcolor = Color.white.getRGB();
-    int seqIndex = 0;
-    int pixelRow = 0;
-    int alignmentHeight = miniMe.getHeight() - graphHeight;
-    int totalPixels = miniMe.getWidth() * alignmentHeight;
+    row = iter.next();
+    // System.out.println("OR row " + r);
+    // get details of this alignment row
+    SequenceI seq = rows.getSequence(row);
 
-    int lastRowUpdate = 0;
-    int lastUpdate = 0;
-    changeSupport.firePropertyChange(UPDATE, -1, 0);
+    // rate limiting step when rendering overview for lots of groups
+    SequenceGroup[] allGroups = al.findAllGroups(seq);
 
-    for (int alignmentRow : rows)
+    // calculate where this row extends to in pixels
+    int endRow = Math.min(Math.round((++seqIndex) * pixelsPerSeq), h);
+
+    for (int pixelCol = 0, colIndex = 0, c = bscol
+            .nextSetBit(0); c >= 0; c = bscol.nextSetBit(c + 1))
     {
       if (redraw)
       {
         break;
       }
-    
-      // get details of this alignment row
-      SequenceI seq = rows.getSequence(alignmentRow);
 
-      // rate limiting step when rendering overview for lots of groups
-      SequenceGroup[] allGroups = al.findAllGroups(seq);
+      // calculate where this column extends to in pixels
+      int endCol = Math.min(Math.round((++colIndex) * pixelsPerCol), w);
 
-      // 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)
+      // 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)
       {
-        if (redraw)
-        {
-          break;
-        }
-    
-        // 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)
+        // System.out.println("OR pc ec " + pixelCol + " " + endCol);
+        int rgb = getColumnColourFromSequence(allGroups, seq, c);
+        // fill in the appropriate number of pixels
+        for (int row = pixelRow; row < endRow; ++row)
         {
-          rgbcolor = getColumnColourFromSequence(allGroups, seq,
-                  alignmentCol);
-    
-          // fill in the appropriate number of pixels
-          for (int row = pixelRow; row <= endRow; ++row)
+          for (int col = pixelCol; col < endCol; ++col)
           {
-            for (int col = pixelCol; col <= endCol; ++col)
-            {
-              miniMe.setRGB(col, row, rgbcolor);
-            }
+            // BH 2019.07.27 was:
+            //
+            // miniMe.setRGB(col, row, rgbcolor);
+            //
+            // but just directly writing to the int[] pixel buffer
+            // is three times faster by my experimentation
+            pixels[row * w + col] = rgb;
+            ndone++;
           }
+        }
+        // }
 
-          // store last update value
-          lastUpdate = sendProgressUpdate(
-                  (pixelCol + 1) * (endRow - pixelRow), totalPixels,
-                  lastRowUpdate, lastUpdate);
-
-          pixelCol = endCol + 1;
+        pixelCol = endCol;
+        // store last update value
+        if (showProgress)
+        {
+          lastUpdate = sendProgressUpdate(endCol * (endRow - 1 - pixelRow),
+                  totalPixels, lastRowUpdate, lastUpdate);
         }
-        colIndex++;
       }
-
-      if (pixelRow != endRow + 1)
+    }
+    if (pixelRow < endRow)
+    {
+      pixelRow = endRow;
+      // store row offset and last update value
+      if (showProgress)
       {
-        // store row offset and last update value
-        lastRowUpdate = sendProgressUpdate(endRow + 1, alignmentHeight, 0,
+        // BH 2019.07.29 was (old) endRow + 1 (now endRow), but should be
+        // pixelRow + 1, surely
+        lastRowUpdate = sendProgressUpdate(endRow, alignmentHeight, 0,
                 lastUpdate);
         lastUpdate = lastRowUpdate;
-        pixelRow = endRow + 1;
       }
-      seqIndex++;
     }
+  }
+
+  private void done()
+  {
+    Platform.timeCheck(
+            "overviewrender " + ndone + " pixels row:" + row + " redraw:"
+                    + redraw,
+            Platform.TIME_MARK);
 
     overlayHiddenRegions(rows, cols);
-    // final update to progress bar if present
-    if (redraw)
+    if (showProgress)
     {
-      sendProgressUpdate(pixelRow - 1, alignmentHeight, 0, 0);
+      // final update to progress bar if present
+      if (redraw)
+      {
+        // aborted in Java
+        // BH was pixelRow - 1, but that could go negative
+        sendProgressUpdate(pixelRow, alignmentHeight, 0, 0);
+      }
+      else
+      {
+        // sendProgressUpdate(alignmentHeight, miniMe.getHeight(), 0, 0);
+        sendProgressUpdate(1, 1, 0, 0);
+      }
     }
-    else
+    panel.overviewDone(miniMe);
+  }
+
+  int ndone = 0;
+
+  private AlignmentRowsCollectionI rows;
+
+  private AlignmentColsCollectionI cols;
+
+  Iterator<Integer> iter;
+
+  int alignmentHeight;
+
+  int totalPixels;
+
+  int lastRowUpdate;
+
+  int lastUpdate;
+
+  int[] pixels;
+
+  BitSet bscol = new BitSet();
+
+  int w, h;
+
+  /**
+   * 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)
+  {
+    this.rows = rows;
+    this.cols = cols;
+    iter = rows.iterator();
+
+    w = miniMe.getWidth();
+    h = miniMe.getHeight();
+    alignmentHeight = h - graphHeight;
+    totalPixels = w * alignmentHeight;
+    lastRowUpdate = 0;
+    lastUpdate = 0;
+
+    if (showProgress)
+    {
+      changeSupport.firePropertyChange(UPDATE, -1, 0);
+    }
+
+    WritableRaster raster = miniMe.getRaster();
+    DataBufferInt db = (DataBufferInt) raster.getDataBuffer();
+    Platform.timeCheck(null, Platform.TIME_MARK);
+    pixels = db.getBankData()[0];
+    bscol.clear();
+    for (int c : cols)
     {
-      sendProgressUpdate(alignmentHeight, miniMe.getHeight(), 0, 0);
+      bscol.set(c);
     }
+    state = STATE_INIT;
+    mainLoop();
+
     return miniMe;
   }
 
@@ -222,18 +382,13 @@ public class OverviewRenderer
    *          column position to get colour for
    * @return colour of sequence at this position, as RGB
    */
-  int getColumnColourFromSequence(SequenceGroup[] allGroups,
-          SequenceI seq, int lastcol)
+  int getColumnColourFromSequence(SequenceGroup[] allGroups, SequenceI seq,
+          int icol)
   {
-    Color color = resColFinder.GAP_COLOUR;
-
-    if ((seq != null) && (seq.getLength() > lastcol))
-    {
-      color = resColFinder.getResidueColour(true, shader, allGroups, seq,
-              lastcol, finder);
-    }
-
-    return color.getRGB();
+    return (seq == null || icol >= seq.getLength()
+            ? resColFinder.GAP_COLOUR
+            : resColFinder.getResidueColour(true, shader, allGroups, seq,
+                    icol, finder)).getRGB();
   }
 
   /**
@@ -256,6 +411,7 @@ public class OverviewRenderer
       g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
               TRANSPARENCY));
       g.drawImage(mask, 0, 0, miniMe.getWidth(), miniMe.getHeight(), null);
+      g.dispose();
     }
   }
 
@@ -280,9 +436,6 @@ public class OverviewRenderer
     BufferedImage hiddenImage = new BufferedImage(width, height,
             BufferedImage.TYPE_INT_ARGB);
 
-    int colIndex = 0;
-    int pixelCol = 0;
-
     Color hidden = resColFinder.getHiddenColour();
 
     Graphics2D g2d = (Graphics2D) hiddenImage.getGraphics();
@@ -294,55 +447,59 @@ public class OverviewRenderer
     // set next colour to opaque
     g2d.setComposite(AlphaComposite.Src);
 
-    for (int alignmentCol : cols)
+    if (cols.hasHidden())
     {
-      if (redraw)
+      int colIndex = 0;
+      int pixelCol = 0;
+      for (int alignmentCol : cols)
       {
-        break;
-      }
+        if (redraw)
+        {
+          break;
+        }
 
-      // calculate where this column extends to in pixels
-      int endCol = Math.min(Math.round((colIndex + 1) * pixelsPerCol) - 1,
-              hiddenImage.getWidth() - 1);
+        // calculate where this column extends to in pixels
+        int endCol = Math.min(Math.round((++colIndex) * pixelsPerCol),
+                width);
 
-      if (pixelCol <= endCol)
-      {
-        // determine the colour based on the sequence and column position
-        if (cols.isHidden(alignmentCol))
+        // endCol is one more than old endCol
+        if (pixelCol < endCol)
         {
-          g2d.setColor(hidden);
-          g2d.fillRect(pixelCol, 0, endCol - pixelCol + 1, height);
+          // determine the colour based on the sequence and column position
+          if (cols.isHidden(alignmentCol))
+          {
+            g2d.setColor(hidden);
+            g2d.fillRect(pixelCol, 0, endCol - pixelCol, height);
+          }
+          pixelCol = endCol;
         }
-
-        pixelCol = endCol + 1;
       }
-      colIndex++;
-
     }
-
-    int seqIndex = 0;
-    int pixelRow = 0;
-    for (int alignmentRow : rows)
+    if (rows.hasHidden())
     {
-      if (redraw)
+      int seqIndex = 0;
+      int pixelRow = 0;
+      for (int alignmentRow : rows)
       {
-        break;
-      }
+        if (redraw)
+        {
+          break;
+        }
 
-      // calculate where this row extends to in pixels
-      int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
-              miniMe.getHeight() - 1);
+        // calculate where this row extends to in pixels
+        int endRow = Math.min(Math.round((++seqIndex) * pixelsPerSeq),
+                height);
 
-      // get details of this alignment row
-      if (rows.isHidden(alignmentRow))
-      {
-        g2d.setColor(hidden);
-        g2d.fillRect(0, pixelRow, width, endRow - pixelRow + 1);
+        // get details of this alignment row
+        if (rows.isHidden(alignmentRow))
+        {
+          g2d.setColor(hidden);
+          g2d.fillRect(0, pixelRow, width, endRow - 1 - pixelRow);
+        }
+        pixelRow = endRow;
       }
-      pixelRow = endRow + 1;
-      seqIndex++;
     }
-
+    g2d.dispose();
     return hiddenImage;
   }
 
@@ -362,56 +519,45 @@ public class OverviewRenderer
           AlignmentColsCollectionI cols)
   {
     Annotation[] annotations = anno.annotations;
+    float max = anno.graphMax;
     g.setColor(Color.white);
-    g.fillRect(0, 0, miniMe.getWidth(), y);
+    int width = miniMe.getWidth();
+    g.fillRect(0, 0, width, y);
 
-    int height;
     int colIndex = 0;
     int pixelCol = 0;
-    for (int alignmentCol : cols)
+    for (int icol : cols)
     {
       if (redraw)
       {
-        changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1, 0);
+        if (showProgress)
+        {
+          changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1, 0);
+        }
         break;
       }
 
-      if (alignmentCol >= annotations.length)
+      if (icol >= annotations.length)
       {
         break; // no more annotations to draw here
       }
-      else
+      int endCol = Math.min(Math.round((++colIndex) * pixelsPerCol), width);
+      Annotation ann = annotations[icol];
+      if (ann != null)
       {
-        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);
-        }
+        Color color = ann.colour;
+        g.setColor(color == null ? Color.black : color);
 
-        pixelCol = endCol + 1;
-        colIndex++;
+        int height = Math.min(y, (int) ((ann.value / max) * y));
+        g.fillRect(pixelCol, y - height, endCol - pixelCol, height);
       }
+      pixelCol = endCol;
+    }
+    if (showProgress)
+    {
+      changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1,
+              MAX_PROGRESS);
     }
-    changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1,
-            MAX_PROGRESS);
   }
 
   /**
index 0235081..3ac236d 100644 (file)
@@ -26,7 +26,9 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.HiddenSequences;
 
+import java.awt.Dimension;
 import java.awt.Graphics;
+import java.awt.Rectangle;
 
 public abstract class OverviewDimensions
 {
@@ -62,6 +64,8 @@ public abstract class OverviewDimensions
 
   protected float heightRatio;
 
+  private Rectangle vpbox = new Rectangle();
+
   /**
    * Create an OverviewDimensions object
    * 
@@ -71,17 +75,23 @@ public abstract class OverviewDimensions
    *          true if the annotation panel is to be shown, false otherwise
    */
   public OverviewDimensions(ViewportRanges ranges,
-          boolean showAnnotationPanel)
+          boolean showAnnotationPanel, Dimension dim)
   {
+    if (!showAnnotationPanel)
+    {
+      graphHeight = 0;
+    }
+
     // scale the initial size of overviewpanel to shape of alignment
     float initialScale = (float) ranges.getAbsoluteAlignmentWidth()
             / (float) ranges.getAbsoluteAlignmentHeight();
 
-    if (!showAnnotationPanel)
+    if (dim != null)
     {
-      graphHeight = 0;
+      width = dim.width;
+      sequencesHeight = dim.height;
+      return;
     }
-
     if (ranges.getAbsoluteAlignmentWidth() > ranges
             .getAbsoluteAlignmentHeight())
     {
@@ -114,6 +124,9 @@ public abstract class OverviewDimensions
    */
   public void drawBox(Graphics g)
   {
+    // System.out.println("OD drawBox " + boxX + " " + boxY + " " + boxWidth
+    // + " " + boxHeight);
+    updateBox();
     g.drawRect(boxX, boxY, boxWidth, boxHeight);
     g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
   }
@@ -178,6 +191,9 @@ public abstract class OverviewDimensions
 
   public void setHeight(int h)
   {
+    // BH 2019 problem was that component.resize() can come
+    // after setBoxPosition().
+    // Solution was to move setting of box dimensions to paint
     sequencesHeight = h - graphHeight;
     heightRatio = (float) alheight / sequencesHeight;
   }
@@ -276,17 +292,22 @@ public abstract class OverviewDimensions
           int vpheight)
   {
     resetAlignmentDims();
+    vpbox = new Rectangle(startRes, startSeq, vpwidth, vpheight);
+    updateBox();
+  }
 
+  public void updateBox()
+  {
     // boxX, boxY is the x,y location equivalent to startRes, startSeq
-    int xPos = Math.min(startRes, alwidth - vpwidth + 1);
+    int xPos = Math.min(vpbox.x, alwidth - vpbox.width + 1);
     boxX = Math.round(xPos / widthRatio);
-    boxY = Math.round(startSeq / heightRatio);
+    boxY = Math.round(vpbox.y / heightRatio);
 
     // boxWidth is the width in residues translated to pixels
-    boxWidth = Math.round(vpwidth / widthRatio);
+    boxWidth = Math.round(vpbox.width / widthRatio);
 
     // boxHeight is the height in sequences translated to pixels
-    boxHeight = Math.round(vpheight / heightRatio);
+    boxHeight = Math.round(vpbox.height / heightRatio);
   }
 
   /**
index de90a21..d2dc607 100644 (file)
@@ -28,6 +28,8 @@ import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.VisibleColsCollection;
 import jalview.datamodel.VisibleRowsCollection;
 
+import java.awt.Dimension;
+
 public class OverviewDimensionsHideHidden extends OverviewDimensions
 {
   private ViewportRanges ranges;
@@ -41,7 +43,13 @@ public class OverviewDimensionsHideHidden extends OverviewDimensions
   public OverviewDimensionsHideHidden(ViewportRanges vpranges,
           boolean showAnnotationPanel)
   {
-    super(vpranges, showAnnotationPanel);
+    this(vpranges, showAnnotationPanel, null);
+  }
+
+  public OverviewDimensionsHideHidden(ViewportRanges vpranges,
+          boolean showAnnotationPanel, Dimension dim)
+  {
+    super(vpranges, showAnnotationPanel, dim);
     ranges = vpranges;
     resetAlignmentDims();
   }
index 3aa6e1b..0752097 100644 (file)
@@ -28,6 +28,8 @@ import jalview.datamodel.AllRowsCollection;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.HiddenSequences;
 
+import java.awt.Dimension;
+
 public class OverviewDimensionsShowHidden extends OverviewDimensions
 {
   private ViewportRanges ranges;
@@ -38,6 +40,12 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
   private int ydiff; // when dragging, difference in alignment units between
                      // start sequence and original mouse click position
 
+  public OverviewDimensionsShowHidden(ViewportRanges vpranges,
+          boolean showAnnotationPanel) 
+  {
+    this(vpranges, showAnnotationPanel, null);
+  }
+
   /**
    * Create an OverviewDimensions object
    * 
@@ -47,9 +55,9 @@ public class OverviewDimensionsShowHidden extends OverviewDimensions
    *          true if the annotation panel is to be shown, false otherwise
    */
   public OverviewDimensionsShowHidden(ViewportRanges vpranges,
-          boolean showAnnotationPanel)
+          boolean showAnnotationPanel, Dimension dim)
   {
-    super(vpranges, showAnnotationPanel);
+    super(vpranges, showAnnotationPanel, dim);
     ranges = vpranges;
     resetAlignmentDims();
   }
index 1d532f7..0a77b65 100644 (file)
@@ -54,7 +54,7 @@ public class OverviewRendererTest
     OverviewDimensions od = new OverviewDimensionsShowHidden(new ViewportRanges(al), false);
     ResidueShaderI rs = new ResidueShader(new ZappoColourScheme());
     FeatureRenderer fr = new FeatureRenderer(av);
-    OverviewRenderer or = new OverviewRenderer(fr, od, al, rs, cf);
+    OverviewRenderer or = new OverviewRenderer(null, fr, od, al, rs, cf);
 
     // P is magenta (see ResidueProperties.zappo)
     assertEquals(or.getColumnColourFromSequence(null, seq1, 0), Color.magenta.getRGB());