JAL-1620 version bump and release notes
[jalview.git] / src / jalview / gui / FeatureRenderer.java
old mode 100755 (executable)
new mode 100644 (file)
index 02ebc34..5a96ff5
@@ -1,23 +1,27 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
- * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2b1)
+ * Copyright (C) 2014 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.
- * 
+ * 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/>.
+ * 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.gui;
 
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -29,6 +33,7 @@ import javax.swing.*;
 
 import jalview.datamodel.*;
 import jalview.schemes.GraduatedColor;
+import jalview.util.MessageManager;
 
 /**
  * DOCUMENT ME!
@@ -53,11 +58,11 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
 
   int charOffset;
 
-  Hashtable featureColours = new Hashtable();
+  Map featureColours = new ConcurrentHashMap();
 
   // A higher level for grouping features of a
   // particular type
-  Hashtable featureGroups = new Hashtable();
+  Map featureGroups = new ConcurrentHashMap();
 
   // This is actually an Integer held in the hashtable,
   // Retrieved using the key feature type
@@ -79,19 +84,24 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
   {
     this.ap = ap;
     this.av = ap.av;
+    if (ap != null && ap.seqPanel != null && ap.seqPanel.seqCanvas != null
+            && ap.seqPanel.seqCanvas.fr != null)
+    {
+      transferSettings(ap.seqPanel.seqCanvas.fr);
+    }
   }
 
   public class FeatureRendererSettings implements Cloneable
   {
     String[] renderOrder;
 
-    Hashtable featureGroups;
+    Map featureGroups;
 
-    Hashtable featureColours;
+    Map featureColours;
 
     float transparency;
 
-    Hashtable featureOrder;
+    Map featureOrder;
 
     public FeatureRendererSettings(String[] renderOrder,
             Hashtable featureGroups, Hashtable featureColours,
@@ -113,27 +123,27 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
     public FeatureRendererSettings(FeatureRenderer fr)
     {
       renderOrder = null;
-      featureGroups = new Hashtable();
-      featureColours = new Hashtable();
-      featureOrder = new Hashtable();
+      featureGroups = new ConcurrentHashMap();
+      featureColours = new ConcurrentHashMap();
+      featureOrder = new ConcurrentHashMap();
       if (fr.renderOrder != null)
       {
         this.renderOrder = new String[fr.renderOrder.length];
         System.arraycopy(fr.renderOrder, 0, renderOrder, 0,
-                renderOrder.length);
+                fr.renderOrder.length);
       }
       if (fr.featureGroups != null)
       {
-        this.featureGroups = new Hashtable(fr.featureGroups);
+        this.featureGroups = new ConcurrentHashMap(fr.featureGroups);
       }
       if (fr.featureColours != null)
       {
-        this.featureColours = new Hashtable(fr.featureColours);
+        this.featureColours = new ConcurrentHashMap(fr.featureColours);
       }
-      Enumeration en = fr.featureColours.keys();
-      while (en.hasMoreElements())
+      Iterator en = fr.featureColours.keySet().iterator();
+      while (en.hasNext())
       {
-        Object next = en.nextElement();
+        Object next = en.next();
         Object val = featureColours.get(next);
         if (val instanceof GraduatedColor)
         {
@@ -144,7 +154,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
       this.transparency = fr.transparency;
       if (fr.featureOrder != null)
       {
-        this.featureOrder = new Hashtable(fr.featureOrder);
+        this.featureOrder = new ConcurrentHashMap(fr.featureOrder);
       }
     }
   }
@@ -163,13 +173,45 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
     this.featureOrder = fr.featureOrder;
   }
 
+  /**
+   * update from another feature renderer
+   * 
+   * @param fr
+   *          settings to copy
+   */
   public void transferSettings(FeatureRenderer fr)
   {
-    this.renderOrder = fr.renderOrder;
-    this.featureGroups = fr.featureGroups;
-    this.featureColours = fr.featureColours;
-    this.transparency = fr.transparency;
-    this.featureOrder = fr.featureOrder;
+    FeatureRendererSettings frs = new FeatureRendererSettings(fr);
+    this.renderOrder = frs.renderOrder;
+    this.featureGroups = frs.featureGroups;
+    this.featureColours = frs.featureColours;
+    this.transparency = frs.transparency;
+    this.featureOrder = frs.featureOrder;
+    if (av != null && av != fr.av)
+    {
+      // copy over the displayed feature settings
+      if (fr.av != null)
+      {
+        if (fr.av.featuresDisplayed != null)
+        {
+          // update display settings
+          if (av.featuresDisplayed == null)
+          {
+            av.featuresDisplayed = new Hashtable(fr.av.featuresDisplayed);
+          }
+          else
+          {
+            av.featuresDisplayed.clear();
+            Enumeration en = fr.av.featuresDisplayed.keys();
+            while (en.hasMoreElements())
+            {
+              av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE);
+            }
+
+          }
+        }
+      }
+    }
   }
 
   BufferedImage offscreenImage;
@@ -185,7 +227,8 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
    * This is used by the Molecule Viewer and Overview to get the accurate
    * colourof the rendered sequence
    */
-  public int findFeatureColour(int initialCol, SequenceI seq, int column)
+  public synchronized int findFeatureColour(int initialCol, SequenceI seq,
+          int column)
   {
     if (!av.showSequenceFeatures)
     {
@@ -229,7 +272,8 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
     }
 
     currentColour = null;
-
+    // TODO: non-threadsafe - each rendering thread needs its own instance of
+    // the feature renderer - or this should be synchronized.
     offscreenRender = true;
 
     if (offscreenImage != null)
@@ -396,16 +440,16 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
         else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
         {
 
-          renderFeature(g, seq, seq
-                  .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
-                  .findIndex(sequenceFeatures[sfindex].begin) - 1,
+          renderFeature(g, seq,
+                  seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
+                  seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
                   getColour(sequenceFeatures[sfindex])
                   // new Color(((Integer) av.featuresDisplayed
                   // .get(sequenceFeatures[sfindex].type)).intValue())
                   , start, end, y1);
-          renderFeature(g, seq, seq
-                  .findIndex(sequenceFeatures[sfindex].end) - 1, seq
-                  .findIndex(sequenceFeatures[sfindex].end) - 1,
+          renderFeature(g, seq,
+                  seq.findIndex(sequenceFeatures[sfindex].end) - 1,
+                  seq.findIndex(sequenceFeatures[sfindex].end) - 1,
                   getColour(sequenceFeatures[sfindex])
                   // new Color(((Integer) av.featuresDisplayed
                   // .get(sequenceFeatures[sfindex].type)).intValue())
@@ -417,17 +461,17 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
           if (av.showSeqFeaturesHeight
                   && sequenceFeatures[sfindex].score != Float.NaN)
           {
-            renderScoreFeature(g, seq, seq
-                    .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
-                    .findIndex(sequenceFeatures[sfindex].end) - 1,
+            renderScoreFeature(g, seq,
+                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
+                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
                     getColour(sequenceFeatures[sfindex]), start, end, y1,
                     normaliseScore(sequenceFeatures[sfindex]));
           }
           else
           {
-            renderFeature(g, seq, seq
-                    .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
-                    .findIndex(sequenceFeatures[sfindex].end) - 1,
+            renderFeature(g, seq,
+                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
+                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
                     getColour(sequenceFeatures[sfindex]), start, end, y1);
           }
         }
@@ -659,9 +703,10 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
     {
       minmax = new Hashtable();
     }
-    for (int i = 0; i < av.alignment.getHeight(); i++)
+    AlignmentI alignment = av.getAlignment();
+    for (int i = 0; i < alignment.getHeight(); i++)
     {
-      SequenceFeature[] features = av.alignment.getSequenceAt(i)
+      SequenceFeature[] features = alignment.getSequenceAt(i)
               .getDatasetSequence().getSequenceFeatures();
 
       if (features == null)
@@ -895,8 +940,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
         return ((GraduatedColor) fc).getMaxColor();
       }
     }
-    throw new Error("Implementation Error: Unrecognised render object "
-            + fc.getClass() + " for features of type " + featureType);
+    throw new Error(MessageManager.formatMessage("error.implementation_error_unrecognised_render_object_for_features_type", new String[]{fc.getClass().toString(),featureType}));
   }
 
   /**
@@ -920,8 +964,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
         return ((GraduatedColor) fc).findColor(feature);
       }
     }
-    throw new Error("Implementation Error: Unrecognised render object "
-            + fc.getClass() + " for features of type " + feature.getType());
+    throw new Error(MessageManager.formatMessage("error.implementation_error_unrecognised_render_object_for_features_type", new String[]{fc.getClass().toString(),feature.getType()}));
   }
 
   private boolean showFeature(SequenceFeature sequenceFeature)
@@ -981,7 +1024,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
         if (fcol instanceof Color)
         {
           Color col = JColorChooser.showDialog(Desktop.desktop,
-                  "Select Feature Colour", ((Color) fcol));
+                  MessageManager.getString("label.select_feature_colour"), ((Color) fcol));
           if (col != null)
           {
             fcol = col;
@@ -1023,7 +1066,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
     {
       panel = new JPanel(new GridLayout(4, 1));
       tmp = new JPanel();
-      tmp.add(new JLabel("Select Feature: "));
+      tmp.add(new JLabel(MessageManager.getString("label.select_feature")));
       overlaps = new JComboBox();
       for (int i = 0; i < features.length; i++)
       {
@@ -1073,17 +1116,19 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
 
     tmp = new JPanel();
     panel.add(tmp);
-    tmp.add(new JLabel("Name: ", JLabel.RIGHT));
+    tmp.add(new JLabel(MessageManager.getString("label.name"), JLabel.RIGHT));
     tmp.add(name);
 
     tmp = new JPanel();
     panel.add(tmp);
-    tmp.add(new JLabel("Group: ", JLabel.RIGHT));
+    tmp.add(new JLabel(MessageManager.getString("label.group") + ":",
+            JLabel.RIGHT));
     tmp.add(source);
 
     tmp = new JPanel();
     panel.add(tmp);
-    tmp.add(new JLabel("Colour: ", JLabel.RIGHT));
+    tmp.add(new JLabel(MessageManager.getString("label.colour"),
+            JLabel.RIGHT));
     tmp.add(colour);
     colour.setPreferredSize(new Dimension(150, 15));
     colour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 9));
@@ -1095,8 +1140,9 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
     bigPanel.add(panel, BorderLayout.NORTH);
 
     panel = new JPanel();
-    panel.add(new JLabel("Description: ", JLabel.RIGHT));
-    description.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    panel.add(new JLabel(MessageManager.getString("label.description"),
+            JLabel.RIGHT));
+    description.setFont(JvSwingUtils.getTextAreaFont());
     description.setLineWrap(true);
     panel.add(new JScrollPane(description));
 
@@ -1105,9 +1151,11 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
       bigPanel.add(panel, BorderLayout.SOUTH);
 
       panel = new JPanel();
-      panel.add(new JLabel(" Start:", JLabel.RIGHT));
+      panel.add(new JLabel(MessageManager.getString("label.start"),
+              JLabel.RIGHT));
       panel.add(start);
-      panel.add(new JLabel("  End:", JLabel.RIGHT));
+      panel.add(new JLabel(MessageManager.getString("label.end"),
+              JLabel.RIGHT));
       panel.add(end);
       bigPanel.add(panel, BorderLayout.CENTER);
     }
@@ -1168,12 +1216,12 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
       { "OK", "Cancel" };
     }
 
-    String title = newFeatures ? "Create New Sequence Feature(s)"
-            : "Amend/Delete Features for " + sequences[0].getName();
+    String title = newFeatures ? MessageManager.getString("label.create_new_sequence_features")
+            : MessageManager.formatMessage("label.amend_delete_features", new String[]{sequences[0].getName()});
 
     int reply = JOptionPane.showInternalOptionDialog(Desktop.desktop,
             bigPanel, title, JOptionPane.YES_NO_CANCEL_OPTION,
-            JOptionPane.QUESTION_MESSAGE, null, options, "OK");
+            JOptionPane.QUESTION_MESSAGE, null, options, MessageManager.getString("action.ok"));
 
     jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
 
@@ -1376,7 +1424,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
 
   }
 
-  Hashtable featureOrder = null;
+  Map featureOrder = null;
 
   /**
    * analogous to colour - store a normalized ordering for all feature types in