Refactored AnnotationColumnChoser and AnnotationColorChooser to apply the DRY principle
[jalview.git] / src / jalview / gui / AnnotationRowFilter.java
diff --git a/src/jalview/gui/AnnotationRowFilter.java b/src/jalview/gui/AnnotationRowFilter.java
new file mode 100644 (file)
index 0000000..9e205c4
--- /dev/null
@@ -0,0 +1,450 @@
+package jalview.gui;
+
+import jalview.api.AnnotationRowFilterI;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.GraphLine;
+import jalview.datamodel.SequenceGroup;
+import jalview.schemes.AnnotationColourGradient;
+import jalview.util.MessageManager;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Vector;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JInternalFrame;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JTextField;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+@SuppressWarnings("serial")
+public abstract class AnnotationRowFilter extends JPanel implements
+        AnnotationRowFilterI
+{
+  protected AlignViewport av;
+
+  protected AlignmentPanel ap;
+
+  protected int[] annmap;
+
+  protected boolean enableSeqAss = false;
+
+  private jalview.datamodel.AlignmentAnnotation currentAnnotation;
+
+  protected boolean adjusting = false;
+
+  protected JCheckBox currentColours = new JCheckBox();
+
+  protected JPanel minColour = new JPanel();
+
+  protected JPanel maxColour = new JPanel();
+
+  protected JCheckBox seqAssociated = new JCheckBox();
+
+  protected JCheckBox thresholdIsMin = new JCheckBox();
+
+  protected JSlider slider = new JSlider();
+
+  protected JTextField thresholdValue = new JTextField(20);
+
+  protected JInternalFrame frame;
+  /**
+   * enabled if the user is dragging the slider - try to keep updates to a
+   * minimun
+   */
+  protected boolean sliderDragging = false;
+
+  protected void addSliderChangeListener()
+  {
+
+    slider.addChangeListener(new ChangeListener()
+    {
+      @Override
+      public void stateChanged(ChangeEvent evt)
+      {
+        if (!adjusting)
+        {
+          thresholdValue.setText((slider.getValue() / 1000f) + "");
+          valueChanged(!sliderDragging);
+        }
+      }
+    });
+  }
+
+  protected void addSliderMouseListeners()
+  {
+
+    slider.addMouseListener(new MouseAdapter()
+    {
+      @Override
+      public void mousePressed(MouseEvent e)
+      {
+        sliderDragging = true;
+        super.mousePressed(e);
+      }
+
+      @Override
+      public void mouseDragged(MouseEvent e)
+      {
+        sliderDragging = true;
+        super.mouseDragged(e);
+      }
+
+      @Override
+      public void mouseReleased(MouseEvent evt)
+      {
+        if (sliderDragging)
+        {
+          sliderDragging = false;
+          valueChanged(true);
+        }
+        ap.paintAlignment(true);
+      }
+    });
+  }
+
+
+  public AnnotationRowFilter(AlignViewport av, final AlignmentPanel ap)
+  {
+    this.av = av;
+    this.ap = ap;
+  }
+
+  public AnnotationRowFilter()
+  {
+
+  }
+
+  @Override
+  public Vector<String> getAnnotationItems(boolean isSeqAssociated)
+  {
+    Vector<String> list = new Vector<String>();
+    int index = 1;
+    int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
+    for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
+    {
+      if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef == null)
+      {
+        if (isSeqAssociated)
+        {
+          continue;
+        }
+      }
+      else
+      {
+        enableSeqAss = true;
+      }
+      String label = av.getAlignment().getAlignmentAnnotation()[i].label;
+      if (!list.contains(label))
+      {
+        anmap[list.size()] = i;
+        list.add(label);
+
+      }
+      else
+      {
+        if (!isSeqAssociated)
+        {
+          anmap[list.size()] = i;
+          list.add(label + "_" + (index++));
+        }
+      }
+    }
+    // seqAssociated.setEnabled(enableSeqAss);
+    this.annmap = new int[list.size()];
+    System.arraycopy(anmap, 0, this.annmap, 0, this.annmap.length);
+    return list;
+  }
+
+  protected int getSelectedThresholdItem(int indexValue)
+  {
+    int selectedThresholdItem = -1;
+    if (indexValue == 1)
+    {
+      selectedThresholdItem = AnnotationColourGradient.ABOVE_THRESHOLD;
+    }
+    else if (indexValue == 2)
+    {
+      selectedThresholdItem = AnnotationColourGradient.BELOW_THRESHOLD;
+    }
+    return selectedThresholdItem;
+  }
+
+  public void modelChanged()
+  {
+    seqAssociated.setEnabled(enableSeqAss);
+  }
+
+  public void ok_actionPerformed(ActionEvent e)
+  {
+    updateView();
+    try
+    {
+      frame.setClosed(true);
+    } catch (Exception ex)
+    {
+    }
+  }
+
+  public void cancel_actionPerformed(ActionEvent e)
+  {
+    reset();
+    ap.paintAlignment(true);
+    try
+    {
+      frame.setClosed(true);
+    } catch (Exception ex)
+    {
+    }
+  }
+
+  public void thresholdCheck_actionPerformed(ActionEvent e)
+  {
+    updateView();
+  }
+
+  public void annotations_actionPerformed(ActionEvent e)
+  {
+    updateView();
+  }
+
+  public void threshold_actionPerformed(ActionEvent e)
+  {
+    updateView();
+  }
+
+  public void thresholdValue_actionPerformed(ActionEvent e)
+  {
+    try
+    {
+      float f = Float.parseFloat(thresholdValue.getText());
+      slider.setValue((int) (f * 1000));
+      updateView();
+    } catch (NumberFormatException ex)
+    {
+    }
+  }
+
+  public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
+  {
+    updateView();
+  }
+
+  protected void populateThresholdComboBox(JComboBox<String> threshold)
+  {
+    threshold.addItem(MessageManager
+            .getString("label.threshold_feature_no_thereshold"));
+    threshold.addItem(MessageManager
+            .getString("label.threshold_feature_above_thereshold"));
+    threshold.addItem(MessageManager
+            .getString("label.threshold_feature_below_thereshold"));
+  }
+
+  protected void seqAssociated_actionPerformed(ActionEvent arg0,
+          JComboBox<String> annotations, JCheckBox seqAssociated)
+  {
+    adjusting = true;
+    String cursel = (String) annotations.getSelectedItem();
+    boolean isvalid = false, isseqs = seqAssociated.isSelected();
+    annotations.removeAllItems();
+    for (String anitem : getAnnotationItems(seqAssociated.isSelected()))
+    {
+      if (anitem.equals(cursel) || (isseqs && cursel.startsWith(anitem)))
+      {
+        isvalid = true;
+        cursel = anitem;
+      }
+      annotations.addItem(anitem);
+    }
+    adjusting = false;
+    if (isvalid)
+    {
+      annotations.setSelectedItem(cursel);
+    }
+    else
+    {
+      if (annotations.getItemCount() > 0)
+      {
+        annotations.setSelectedIndex(0);
+      }
+    }
+  }
+
+  protected void propagateSeqAssociatedThreshold(boolean allAnnotation,
+          AlignmentAnnotation annotation)
+  {
+    if (annotation.sequenceRef == null || annotation.threshold == null)
+    {
+      return;
+    }
+
+    float thr = annotation.threshold.value;
+    for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
+    {
+      AlignmentAnnotation aa = av.getAlignment().getAlignmentAnnotation()[i];
+      if (aa.label.equals(annotation.label)
+              && (annotation.getCalcId() == null ? aa.getCalcId() == null
+                      : annotation.getCalcId().equals(aa.getCalcId())))
+      {
+        if (aa.threshold == null)
+        {
+          aa.threshold = new GraphLine(annotation.threshold);
+        }
+        else
+        {
+          aa.threshold.value = thr;
+        }
+      }
+    }
+  }
+
+  protected boolean colorAlignmContaining(
+          AlignmentAnnotation currentAnnotation, int selectedThresholdItem)
+  {
+
+    AnnotationColourGradient acg = null;
+    if (currentColours.isSelected())
+    {
+      acg = new AnnotationColourGradient(currentAnnotation,
+              av.getGlobalColourScheme(), selectedThresholdItem);
+    }
+    else
+    {
+      acg = new AnnotationColourGradient(currentAnnotation,
+              minColour.getBackground(), maxColour.getBackground(),
+              selectedThresholdItem);
+    }
+    acg.setSeqAssociated(seqAssociated.isSelected());
+
+    if (currentAnnotation.graphMin == 0f
+            && currentAnnotation.graphMax == 0f)
+    {
+      acg.setPredefinedColours(true);
+    }
+
+    acg.thresholdIsMinMax = thresholdIsMin.isSelected();
+
+    av.setGlobalColourScheme(acg);
+
+    if (av.getAlignment().getGroups() != null)
+    {
+
+      for (SequenceGroup sg : ap.av.getAlignment().getGroups())
+      {
+        if (sg.cs == null)
+        {
+          continue;
+        }
+
+        if (currentColours.isSelected())
+        {
+          sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
+                  selectedThresholdItem);
+          ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
+                  .isSelected());
+
+        }
+        else
+        {
+          sg.cs = new AnnotationColourGradient(currentAnnotation,
+                  minColour.getBackground(), maxColour.getBackground(),
+                  selectedThresholdItem);
+          ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
+                  .isSelected());
+        }
+
+      }
+    }
+    return false;
+  }
+
+  protected boolean markColumnsContaining(
+          AlignmentAnnotation currentAnnotation, int thresholdComparisonType)
+  {
+    try
+    {
+      if (currentAnnotation != null)
+      {
+        Annotation[] annotations = currentAnnotation.annotations;
+        ColumnSelection cs = av.getColumnSelection();
+        cs.clear();
+        if (thresholdComparisonType == AnnotationColourGradient.NO_THRESHOLD)
+        {
+          int count = 0;
+          do
+          {
+            if (annotations[count] != null)
+            {
+              if (currentAnnotation.label.equals("Secondary Structure")
+                      && annotations[count].secondaryStructure != ' ')
+              {
+                cs.addElement(count);
+              }
+              else if (currentAnnotation.label
+                      .equals("Iron Sulphur Contacts"))
+              {
+                cs.addElement(count);
+              }
+              else if (annotations[count].value != 0.0)
+              {
+                cs.addElement(count);
+              }
+
+            }
+            count++;
+          } while (count < annotations.length);
+        }
+        else
+        {
+          int count = 0;
+          do
+          {
+            if (annotations[count] != null)
+            {
+              if (thresholdComparisonType == AnnotationColourGradient.ABOVE_THRESHOLD)
+              {
+                if (annotations[count].value > currentAnnotation.threshold.value)
+                {
+                  cs.addElement(count);
+                }
+              }
+              else if (thresholdComparisonType == AnnotationColourGradient.BELOW_THRESHOLD)
+              {
+                if (annotations[count].value < currentAnnotation.threshold.value)
+                {
+                  cs.addElement(count);
+                }
+              }
+
+            }
+            count++;
+          } while (count < annotations.length);
+        }
+      }
+
+      return true;
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+      return false;
+    }
+  }
+
+  public jalview.datamodel.AlignmentAnnotation getCurrentAnnotation()
+  {
+    return currentAnnotation;
+  }
+
+  public void setCurrentAnnotation(
+          jalview.datamodel.AlignmentAnnotation currentAnnotation)
+  {
+    this.currentAnnotation = currentAnnotation;
+  }
+
+}