JAL-2547 tooltip/AmendFeatures on gap straddled by feature, not for
[jalview.git] / src / jalview / appletgui / FeatureRenderer.java
old mode 100755 (executable)
new mode 100644 (file)
index 4a97e43..3c2715f
-/*\r
- * Jalview - A Sequence Alignment Editor and Viewer\r
- * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
- */\r
-package jalview.appletgui;\r
-\r
-import jalview.datamodel.*;\r
-\r
-import java.awt.*;\r
-\r
-import java.util.*;\r
-\r
-\r
-/**\r
- * DOCUMENT ME!\r
- *\r
- * @author $author$\r
- * @version $Revision$\r
- */\r
-public class FeatureRenderer\r
-{\r
-    AlignViewport av;\r
-    SequenceGroup currentSequenceGroup = null;\r
-    SequenceGroup[] allGroups = null;\r
-    Color resBoxColour;\r
-    Graphics graphics;\r
-    float transparency = .4f;\r
-\r
-    // The following vector holds the features which are\r
-    // to be added, in the correct order or rendering\r
-    Vector featuresDisplayed;\r
-\r
-    /**\r
-     * Creates a new FeatureRenderer object.\r
-     *\r
-     * @param av DOCUMENT ME!\r
-     */\r
-    public FeatureRenderer(AlignViewport av)\r
-    {\r
-        this.av = av;\r
-        initColours();\r
-        String version = System.getProperty("java.version");\r
-        if (version.indexOf("1.1") == 0)\r
-          highlightTransparent = false;\r
-\r
-    }\r
-\r
-boolean highlightTransparent = true;\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param g DOCUMENT ME!\r
-     * @param seq DOCUMENT ME!\r
-     * @param sg DOCUMENT ME!\r
-     * @param start DOCUMENT ME!\r
-     * @param end DOCUMENT ME!\r
-     * @param x1 DOCUMENT ME!\r
-     * @param y1 DOCUMENT ME!\r
-     * @param width DOCUMENT ME!\r
-     * @param height DOCUMENT ME!\r
-     */\r
-    public void drawSequence(Graphics g, SequenceI seq, SequenceGroup[] sg,\r
-        int start, int end, int x1, int y1, int width, int height)\r
-    {\r
-\r
-        if(seq.getSequenceFeatures()==null)\r
-          return;\r
-\r
-        Enumeration e = null, e2;\r
-        String type;\r
-        if(featuresDisplayed!=null)\r
-          e = featuresDisplayed.elements();\r
-        else\r
-         e = seq.getSequenceFeatures().elements();\r
-\r
-       if(highlightTransparent)\r
-        {\r
-        //  MyGraphics.SetTransparency(g, transparency);\r
-        }\r
-\r
-\r
-        while (e.hasMoreElements())\r
-        {\r
-            SequenceFeature sf=null;\r
-            if(featuresDisplayed!=null)\r
-            {\r
-              e2 = seq.getSequenceFeatures().elements();\r
-              type = e.nextElement().toString();\r
-              while(e2.hasMoreElements())\r
-              {\r
-                sf = (SequenceFeature) e2.nextElement();\r
-                if(sf.getType().equals(type))\r
-                  break;\r
-                else\r
-                  sf = null;\r
-              }\r
-            }\r
-            else\r
-            {\r
-              sf = (SequenceFeature) e.nextElement();\r
-              type = sf.getType();\r
-            }\r
-\r
-            if(sf==null)\r
-              continue;\r
-\r
-\r
-            if (sf.getBegin() > seq.getEnd())\r
-            {\r
-                continue;\r
-            }\r
-\r
-            int fstart = seq.findIndex(sf.getBegin()) - 1;\r
-            int fend = seq.findIndex(sf.getEnd()) - 1;\r
-\r
-            if (((fstart <= end) && (fend >= start)))\r
-            {\r
-                if (fstart < start)\r
-                { // fix for if the feature we have starts before the sequence start,\r
-                    fstart = start; // but the feature end is still valid!!\r
-                }\r
-\r
-                if (fend >= end)\r
-                {\r
-                    fend = end;\r
-                }\r
-\r
-                if (fstart == fend)\r
-                {\r
-                    g.setColor(getColour(type));\r
-                    g.fillRoundRect((fstart - start) * width, y1, width,\r
-                        height, 4, 4);\r
-                    g.setColor(Color.white);\r
-\r
-                    char s = seq.getSequence().charAt(fstart);\r
-                    FontMetrics fm = g.getFontMetrics();\r
-                    int charOffset = (width - fm.charWidth(s)) / 2;\r
-                    int pady = height / 5;\r
-                    g.drawString(String.valueOf(s),\r
-                        charOffset + x1 + (width * (fstart - start)),\r
-                        (y1 + height) - pady);\r
-                }\r
-                else\r
-                {\r
-                    for (int i = fstart; i <= fend; i++)\r
-                    {\r
-                        char s = seq.getSequence().charAt(i);\r
-\r
-                        if (jalview.util.Comparison.isGap(s))\r
-                        {\r
-                            continue;\r
-                        }\r
-\r
-                        g.setColor(getColour(type));\r
-                        g.fillRect((i - start) * width, y1, width, height);\r
-\r
-                        g.setColor(Color.white);\r
-\r
-                        FontMetrics fm = g.getFontMetrics();\r
-                        int charOffset = (width - fm.charWidth(s)) / 2;\r
-                        int pady = height / 5;\r
-                        g.drawString(String.valueOf(s),\r
-                            charOffset + x1 + (width * (i - start)),\r
-                            (y1 + height) - pady);\r
-                    }\r
-                }\r
-            }\r
-          }\r
-\r
-          if (highlightTransparent)\r
-          {\r
-        //    MyGraphics.SetTransparency(g, 1.0f);\r
-          }\r
-    }\r
-\r
-    public Color getColour(String featureType)\r
-    {\r
-      return (Color)featureColours.get(featureType);\r
-    }\r
-\r
-    public void setColour(String featureType, Color col)\r
-    {\r
-      featureColours.put(featureType, col);\r
-    }\r
-\r
-    public void setTransparency(float value)\r
-    {\r
-      transparency = value;\r
-    }\r
-\r
-    public float getTransparency()\r
-    {\r
-      return transparency;\r
-    }\r
-\r
-    public void setFeaturePriority(Object [][] data)\r
-    {\r
-      // The feature table will display high priority\r
-      // features at the top, but theses are the ones\r
-      // we need to render last, so invert the data\r
-      featuresDisplayed = new Vector();\r
-      for(int i=data.length-1; i>-1; i--)\r
-      {\r
-       String type = data[i][0].toString();\r
-       setColour(type, (Color)data[i][1]);\r
-       if( ((Boolean)data[i][2]).booleanValue() )\r
-         featuresDisplayed.addElement(type);\r
-      }\r
-    }\r
-\r
-    Hashtable featureColours = new Hashtable();\r
-    void initColours()\r
-    {\r
-      featureColours.put("active site", new Color(255, 75, 0));\r
-      featureColours.put("binding site", new Color(245, 85, 0));\r
-      featureColours.put("calcium-binding region", new Color(235, 95, 0));\r
-      featureColours.put("chain", new Color(225, 105, 0));\r
-      featureColours.put("coiled-coil region", new Color(215, 115, 0));\r
-      featureColours.put("compositionally biased region", new Color(205, 125, 0));\r
-      featureColours.put("cross-link", new Color(195, 135, 0));\r
-      featureColours.put("disulfide bond", new Color(185, 145, 0));\r
-      featureColours.put("DNA-binding region", new Color(175, 155, 0));\r
-      featureColours.put("domain", new Color(165, 165, 0));\r
-      featureColours.put("glycosylation site", new Color(155, 175, 0));\r
-      featureColours.put("helix", new Color(145, 185, 0));\r
-      featureColours.put("initiator methionine", new Color(135, 195, 5));\r
-      featureColours.put("lipid moiety-binding region", new Color(125, 205, 15));\r
-      featureColours.put("metal ion-binding site", new Color(115, 215, 25));\r
-      featureColours.put("modified residue", new Color(105, 225, 35));\r
-      featureColours.put("mutagenesis site", new Color(95, 235, 45));\r
-      featureColours.put("non-consecutive residues", new Color(85, 245, 55));\r
-      featureColours.put("non-terminal residue", new Color(75, 255, 65));\r
-      featureColours.put("nucleotide phosphate-binding region",\r
-                         new Color(65, 245, 75));\r
-      featureColours.put("peptide", new Color(55, 235, 85));\r
-      featureColours.put("propeptide", new Color(45, 225, 95));\r
-      featureColours.put("region of interest", new Color(35, 215, 105));\r
-      featureColours.put("repeat", new Color(25, 205, 115));\r
-      featureColours.put("selenocysteine", new Color(15, 195, 125));\r
-      featureColours.put("sequence conflict", new Color(5, 185, 135));\r
-      featureColours.put("sequence variant", new Color(0, 175, 145));\r
-      featureColours.put("short sequence motif", new Color(0, 165, 155));\r
-      featureColours.put("signal peptide", new Color(0, 155, 165));\r
-      featureColours.put("site", new Color(0, 145, 175));\r
-      featureColours.put("splice variant", new Color(0, 135, 185));\r
-      featureColours.put("strand", new Color(0, 125, 195));\r
-      featureColours.put("topological domain", new Color(0, 115, 205));\r
-      featureColours.put("transit peptide", new Color(0, 105, 215));\r
-      featureColours.put("transmembrane region", new Color(0, 95, 225));\r
-      featureColours.put("turn", new Color(0, 85, 235));\r
-      featureColours.put("unsure residue", new Color(0, 75, 245));\r
-      featureColours.put("zinc finger region", new Color(0, 65, 255));\r
-    }\r
-\r
-}\r
-\r
-\r
-\r
+/*
+ * 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.appletgui;
+
+import jalview.api.FeatureColourI;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.io.FeaturesFile;
+import jalview.schemes.FeatureColour;
+import jalview.util.ColorUtils;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Choice;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.ScrollPane;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
+import java.util.Hashtable;
+import java.util.List;
+
+/**
+ * DOCUMENT ME!
+ * 
+ * @author $author$
+ * @version $Revision$
+ */
+public class FeatureRenderer extends
+        jalview.renderer.seqfeatures.FeatureRenderer
+{
+  /*
+   * creating a new feature defaults to the type and group as
+   * the last one created
+   */
+  static String lastFeatureAdded = "feature_1";
+
+  static String lastFeatureGroupAdded = "Jalview";
+
+  // Holds web links for feature groups and feature types
+  // in the form label|link
+  Hashtable featureLinks = null;
+
+  /**
+   * Creates a new FeatureRenderer object.
+   * 
+   * @param av
+   */
+  public FeatureRenderer(AlignmentViewport av)
+  {
+    super(av);
+
+  }
+
+  int featureIndex = 0;
+
+  boolean deleteFeature = false;
+
+  FeatureColourPanel colourPanel;
+
+  class FeatureColourPanel extends Panel
+  {
+    String label = "";
+
+    private Color maxCol;
+
+    private boolean isColourByLabel, isGcol;
+
+    /**
+     * render a feature style in the amend feature dialog box
+     */
+    public void updateColor(FeatureColourI newcol)
+    {
+      Color bg = null;
+      String vlabel = "";
+      if (newcol.isSimpleColour())
+      {
+        bg = newcol.getColour();
+        setBackground(bg);
+      }
+      else
+      {
+        if (newcol.isAboveThreshold())
+        {
+          vlabel += " (>)";
+        }
+        else if (newcol.isBelowThreshold())
+        {
+          vlabel += " (<)";
+        }
+
+        if (isColourByLabel = newcol.isColourByLabel())
+        {
+          setBackground(bg = Color.white);
+          vlabel += " (by Label)";
+        }
+        else
+        {
+          setBackground(bg = newcol.getMinColour());
+          maxCol = newcol.getMaxColour();
+        }
+      }
+      label = vlabel;
+      setBackground(bg);
+      repaint();
+    }
+
+    FeatureColourPanel()
+    {
+      super(null);
+    }
+
+    @Override
+    public void paint(Graphics g)
+    {
+      Dimension d = getSize();
+      if (isGcol)
+      {
+        if (isColourByLabel)
+        {
+          g.setColor(Color.white);
+          g.fillRect(d.width / 2, 0, d.width / 2, d.height);
+          g.setColor(Color.black);
+          Font f = new Font("Verdana", Font.PLAIN, 10);
+          g.setFont(f);
+          g.drawString(MessageManager.getString("label.label"), 0, 0);
+        }
+        else
+        {
+          g.setColor(maxCol);
+          g.fillRect(d.width / 2, 0, d.width / 2, d.height);
+
+        }
+      }
+    }
+
+  }
+
+  /**
+   * Shows a dialog allowing the user to create, or amend or delete, sequence
+   * features. If null in the supplied feature(s), feature type and group
+   * default to those for the last feature created (with initial defaults of
+   * "feature_1" and "Jalview").
+   * 
+   * @param sequences
+   * @param features
+   * @param create
+   * @param ap
+   * @return
+   */
+  boolean amendFeatures(final List<SequenceI> sequences,
+          final List<SequenceFeature> features, boolean create,
+          final AlignmentPanel ap)
+  {
+    final Panel bigPanel = new Panel(new BorderLayout());
+    final TextField name = new TextField(16);
+    final TextField group = new TextField(16);
+    final TextArea description = new TextArea(3, 35);
+    final TextField start = new TextField(8);
+    final TextField end = new TextField(8);
+    final Choice overlaps;
+    Button deleteButton = new Button("Delete");
+    deleteFeature = false;
+
+    name.addTextListener(new TextListener()
+    {
+      @Override
+      public void textValueChanged(TextEvent e)
+      {
+        warnIfTypeHidden(ap.alignFrame, name.getText());
+      }
+    });
+    group.addTextListener(new TextListener()
+    {
+      @Override
+      public void textValueChanged(TextEvent e)
+      {
+        warnIfGroupHidden(ap.alignFrame, group.getText());
+      }
+    });
+    colourPanel = new FeatureColourPanel();
+    colourPanel.setSize(110, 15);
+    final FeatureRenderer fr = this;
+
+    Panel panel = new Panel(new GridLayout(3, 1));
+
+    featureIndex = 0; // feature to be amended.
+    Panel tmp;
+
+    // /////////////////////////////////////
+    // /MULTIPLE FEATURES AT SELECTED RESIDUE
+    if (!create && features.size() > 1)
+    {
+      panel = new Panel(new GridLayout(4, 1));
+      tmp = new Panel();
+      tmp.add(new Label("Select Feature: "));
+      overlaps = new Choice();
+      for (SequenceFeature sf : features)
+      {
+        String item = sf.getType() + "/" + sf.getBegin() + "-"
+                + sf.getEnd();
+        if (sf.getFeatureGroup() != null)
+        {
+          item += " (" + sf.getFeatureGroup() + ")";
+        }
+        overlaps.addItem(item);
+      }
+
+      tmp.add(overlaps);
+
+      overlaps.addItemListener(new java.awt.event.ItemListener()
+      {
+        @Override
+        public void itemStateChanged(java.awt.event.ItemEvent e)
+        {
+          int index = overlaps.getSelectedIndex();
+          if (index != -1)
+          {
+            featureIndex = index;
+            SequenceFeature sf = features.get(index);
+            name.setText(sf.getType());
+            description.setText(sf.getDescription());
+            group.setText(sf.getFeatureGroup());
+            start.setText(sf.getBegin() + "");
+            end.setText(sf.getEnd() + "");
+
+            SearchResultsI highlight = new SearchResults();
+            highlight.addResult(sequences.get(0), sf.getBegin(),
+                    sf.getEnd());
+
+            ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
+
+          }
+          FeatureColourI col = getFeatureStyle(name.getText());
+          if (col == null)
+          {
+            Color generatedColour = ColorUtils.createColourFromName(name
+                    .getText());
+            col = new FeatureColour(generatedColour);
+          }
+
+          colourPanel.updateColor(col);
+        }
+      });
+
+      panel.add(tmp);
+    }
+    // ////////
+    // ////////////////////////////////////
+
+    tmp = new Panel();
+    panel.add(tmp);
+    tmp.add(new Label(MessageManager.getString("label.name:"), Label.RIGHT));
+    tmp.add(name);
+
+    tmp = new Panel();
+    panel.add(tmp);
+    tmp.add(new Label(MessageManager.getString("label.group:"), Label.RIGHT));
+    tmp.add(group);
+
+    tmp = new Panel();
+    panel.add(tmp);
+    tmp.add(new Label(MessageManager.getString("label.colour"), Label.RIGHT));
+    tmp.add(colourPanel);
+
+    bigPanel.add(panel, BorderLayout.NORTH);
+
+    panel = new Panel();
+    panel.add(new Label(MessageManager.getString("label.description:"),
+            Label.RIGHT));
+    panel.add(new ScrollPane().add(description));
+
+    if (!create)
+    {
+      bigPanel.add(panel, BorderLayout.SOUTH);
+
+      panel = new Panel();
+      panel.add(new Label(MessageManager.getString("label.start"),
+              Label.RIGHT));
+      panel.add(start);
+      panel.add(new Label(MessageManager.getString("label.end"),
+              Label.RIGHT));
+      panel.add(end);
+      bigPanel.add(panel, BorderLayout.CENTER);
+    }
+    else
+    {
+      bigPanel.add(panel, BorderLayout.CENTER);
+    }
+
+    /*
+     * use defaults for type and group (and update them on Confirm) only
+     * if feature type has not been supplied by the caller
+     * (e.g. for Amend, or create features from Find) 
+     */
+    SequenceFeature firstFeature = features.get(0);
+    boolean useLastDefaults = firstFeature.getType() == null;
+    String featureType = useLastDefaults ? lastFeatureAdded : firstFeature
+            .getType();
+    String featureGroup = useLastDefaults ? lastFeatureGroupAdded
+            : firstFeature.getFeatureGroup();
+
+    String title = create ? MessageManager
+            .getString("label.create_new_sequence_features")
+            : MessageManager.formatMessage("label.amend_delete_features",
+                    new String[] { sequences.get(0).getName() });
+
+    final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
+            240);
+
+    dialog.setMainPanel(bigPanel);
+
+    name.setText(featureType);
+    group.setText(featureGroup);
+
+    if (!create)
+    {
+      dialog.ok.setLabel(MessageManager.getString("label.amend"));
+      dialog.buttonPanel.add(deleteButton, 1);
+      deleteButton.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent evt)
+        {
+          deleteFeature = true;
+          dialog.setVisible(false);
+        }
+      });
+    }
+
+    start.setText(firstFeature.getBegin() + "");
+    end.setText(firstFeature.getEnd() + "");
+    description.setText(firstFeature.getDescription());
+    // lookup (or generate) the feature colour
+    FeatureColourI fcol = getFeatureStyle(name.getText());
+    // simply display the feature color in a box
+    colourPanel.updateColor(fcol);
+    dialog.setResizable(true);
+    // TODO: render the graduated color in the box.
+    colourPanel.addMouseListener(new MouseAdapter()
+    {
+      @Override
+      public void mousePressed(MouseEvent evt)
+      {
+        if (!colourPanel.isGcol)
+        {
+          new UserDefinedColours(fr, ap.alignFrame);
+        }
+        else
+        {
+          new FeatureColourChooser(ap.alignFrame, name.getText());
+          dialog.transferFocus();
+        }
+      }
+    });
+    dialog.setVisible(true);
+
+    FeaturesFile ffile = new FeaturesFile();
+
+    /*
+     * only update default type and group if we used defaults
+     */
+    String enteredType = name.getText().trim();
+    if (dialog.accept && useLastDefaults)
+    {
+      lastFeatureAdded = enteredType;
+      lastFeatureGroupAdded = group.getText().trim();
+    }
+
+    if (!create)
+    {
+      SequenceFeature sf = features.get(featureIndex);
+      if (dialog.accept)
+      {
+        sf.type = enteredType;
+        sf.featureGroup = group.getText().trim();
+        if (sf.featureGroup != null && sf.featureGroup.length() < 1)
+        {
+          sf.featureGroup = null;
+        }
+        sf.description = description.getText().replace('\n', ' ');
+        if (!colourPanel.isGcol)
+        {
+          // update colour - otherwise its already done.
+          setColour(sf.type, new FeatureColour(colourPanel.getBackground()));
+        }
+        try
+        {
+          sf.begin = Integer.parseInt(start.getText());
+          sf.end = Integer.parseInt(end.getText());
+        } catch (NumberFormatException ex)
+        {
+          //
+        }
+        boolean typeOrGroupChanged = (!featureType.equals(sf.type) || !featureGroup
+                .equals(sf.featureGroup));
+
+        ffile.parseDescriptionHTML(sf, false);
+        if (typeOrGroupChanged)
+        {
+          featuresAdded();
+        }
+      }
+      if (deleteFeature)
+      {
+        sequences.get(0).deleteFeature(sf);
+        // ensure Feature Settings reflects removal of feature / group
+        featuresAdded();
+      }
+    }
+    else
+    {
+      /*
+       * adding feature(s)
+       */
+      if (dialog.accept && name.getText().length() > 0)
+      {
+        for (int i = 0; i < sequences.size(); i++)
+        {
+          features.get(i).type = enteredType;
+          features.get(i).featureGroup = group.getText().trim();
+          features.get(i).description = description.getText()
+                  .replace('\n', ' ');
+          sequences.get(i).addSequenceFeature(features.get(i));
+          ffile.parseDescriptionHTML(features.get(i), false);
+        }
+
+        Color newColour = colourPanel.getBackground();
+        // setColour(lastFeatureAdded, fcol);
+
+        setColour(enteredType, new FeatureColour(newColour)); // was fcol
+        featuresAdded();
+      }
+      else
+      {
+        // no update to the alignment
+        return false;
+      }
+    }
+    // refresh the alignment and the feature settings dialog
+    if (((jalview.appletgui.AlignViewport) av).featureSettings != null)
+    {
+      ((jalview.appletgui.AlignViewport) av).featureSettings.refreshTable();
+    }
+    // findAllFeatures();
+
+    ap.paintAlignment(true);
+
+    return true;
+  }
+
+  protected void warnIfGroupHidden(Frame frame, String group)
+  {
+    if (featureGroups.containsKey(group) && !featureGroups.get(group))
+    {
+      String msg = MessageManager.formatMessage("label.warning_hidden",
+              MessageManager.getString("label.group"), group);
+      showWarning(frame, msg);
+    }
+  }
+
+  protected void warnIfTypeHidden(Frame frame, String type)
+  {
+    if (getRenderOrder().contains(type))
+    {
+      if (!showFeatureOfType(type))
+      {
+        String msg = MessageManager.formatMessage("label.warning_hidden",
+                MessageManager.getString("label.feature_type"), type);
+        showWarning(frame, msg);
+      }
+    }
+  }
+
+  /**
+   * @param frame
+   * @param msg
+   */
+  protected void showWarning(Frame frame, String msg)
+  {
+    JVDialog d = new JVDialog(frame, "", true, 350, 200);
+    Panel mp = new Panel();
+    d.ok.setLabel(MessageManager.getString("action.ok"));
+    d.cancel.setVisible(false);
+    mp.setLayout(new FlowLayout());
+    mp.add(new Label(msg));
+    d.setMainPanel(mp);
+    d.setVisible(true);
+  }
+}