0a5e96c291e3f2a0060cb937845ef53dcc61e360
[jalview.git] / src / jalview / gui / AnnotationRowFilter.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.gui;
22
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.GraphLine;
25 import jalview.datamodel.SequenceGroup;
26 import jalview.schemes.AnnotationColourGradient;
27 import jalview.util.MessageManager;
28
29 import java.awt.event.ActionEvent;
30 import java.awt.event.MouseAdapter;
31 import java.awt.event.MouseEvent;
32 import java.util.Vector;
33
34 import javax.swing.JButton;
35 import javax.swing.JCheckBox;
36 import javax.swing.JComboBox;
37 import javax.swing.JInternalFrame;
38 import javax.swing.JPanel;
39 import javax.swing.JSlider;
40 import javax.swing.JTextField;
41 import javax.swing.event.ChangeEvent;
42 import javax.swing.event.ChangeListener;
43
44 @SuppressWarnings("serial")
45 public abstract class AnnotationRowFilter extends JPanel
46 {
47   protected AlignViewport av;
48
49   protected AlignmentPanel ap;
50
51   protected int[] annmap;
52
53   protected boolean enableSeqAss = false;
54
55   private jalview.datamodel.AlignmentAnnotation currentAnnotation;
56
57   protected boolean adjusting = false;
58
59   protected JCheckBox currentColours = new JCheckBox();
60
61   protected JPanel minColour = new JPanel();
62
63   protected JPanel maxColour = new JPanel();
64
65   protected JCheckBox seqAssociated = new JCheckBox();
66
67   protected JCheckBox thresholdIsMin = new JCheckBox();
68
69   protected JSlider slider = new JSlider();
70
71   protected JTextField thresholdValue = new JTextField(20);
72
73   protected JInternalFrame frame;
74
75   protected JButton ok = new JButton();
76
77   protected JButton cancel = new JButton();
78
79   /**
80    * enabled if the user is dragging the slider - try to keep updates to a
81    * minimun
82    */
83   protected boolean sliderDragging = false;
84
85   protected void addSliderChangeListener()
86   {
87
88     slider.addChangeListener(new ChangeListener()
89     {
90       @Override
91       public void stateChanged(ChangeEvent evt)
92       {
93         if (!adjusting)
94         {
95           thresholdValue.setText((slider.getValue() / 1000f) + "");
96           valueChanged(!sliderDragging);
97         }
98       }
99     });
100   }
101
102   protected void addSliderMouseListeners()
103   {
104
105     slider.addMouseListener(new MouseAdapter()
106     {
107       @Override
108       public void mousePressed(MouseEvent e)
109       {
110         sliderDragging = true;
111         super.mousePressed(e);
112       }
113
114       @Override
115       public void mouseDragged(MouseEvent e)
116       {
117         sliderDragging = true;
118         super.mouseDragged(e);
119       }
120
121       @Override
122       public void mouseReleased(MouseEvent evt)
123       {
124         if (sliderDragging)
125         {
126           sliderDragging = false;
127           valueChanged(true);
128         }
129         ap.paintAlignment(true);
130       }
131     });
132   }
133
134   public AnnotationRowFilter(AlignViewport av, final AlignmentPanel ap)
135   {
136     this.av = av;
137     this.ap = ap;
138   }
139
140   public AnnotationRowFilter()
141   {
142
143   }
144
145   public Vector<String> getAnnotationItems(boolean isSeqAssociated)
146   {
147     Vector<String> list = new Vector<String>();
148     int index = 1;
149     int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
150     for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
151     {
152       if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef == null)
153       {
154         if (isSeqAssociated)
155         {
156           continue;
157         }
158       }
159       else
160       {
161         enableSeqAss = true;
162       }
163       String label = av.getAlignment().getAlignmentAnnotation()[i].label;
164       // add associated sequence ID if available
165       if (!isSeqAssociated
166               && av.getAlignment().getAlignmentAnnotation()[i].sequenceRef != null)
167       {
168         label = label
169                 + "_"
170                 + av.getAlignment().getAlignmentAnnotation()[i].sequenceRef
171                         .getName();
172       }
173       // make label unique
174       if (!list.contains(label))
175       {
176         anmap[list.size()] = i;
177         list.add(label);
178
179       }
180       else
181       {
182         if (!isSeqAssociated)
183         {
184           anmap[list.size()] = i;
185           list.add(label + "_" + (index++));
186         }
187       }
188     }
189     this.annmap = new int[list.size()];
190     System.arraycopy(anmap, 0, this.annmap, 0, this.annmap.length);
191     return list;
192   }
193
194   protected int getSelectedThresholdItem(int indexValue)
195   {
196     int selectedThresholdItem = -1;
197     if (indexValue == 1)
198     {
199       selectedThresholdItem = AnnotationColourGradient.ABOVE_THRESHOLD;
200     }
201     else if (indexValue == 2)
202     {
203       selectedThresholdItem = AnnotationColourGradient.BELOW_THRESHOLD;
204     }
205     return selectedThresholdItem;
206   }
207
208   public void modelChanged()
209   {
210     seqAssociated.setEnabled(enableSeqAss);
211   }
212
213   public void ok_actionPerformed(ActionEvent e)
214   {
215     try
216     {
217       frame.setClosed(true);
218     } catch (Exception ex)
219     {
220     }
221   }
222
223   public void cancel_actionPerformed(ActionEvent e)
224   {
225     reset();
226     ap.paintAlignment(true);
227     try
228     {
229       frame.setClosed(true);
230     } catch (Exception ex)
231     {
232     }
233   }
234
235   public void thresholdCheck_actionPerformed(ActionEvent e)
236   {
237     updateView();
238   }
239
240   public void annotations_actionPerformed(ActionEvent e)
241   {
242     updateView();
243   }
244
245   public void threshold_actionPerformed(ActionEvent e)
246   {
247     updateView();
248   }
249
250   public void thresholdValue_actionPerformed(ActionEvent e)
251   {
252     try
253     {
254       float f = Float.parseFloat(thresholdValue.getText());
255       slider.setValue((int) (f * 1000));
256       updateView();
257     } catch (NumberFormatException ex)
258     {
259     }
260   }
261
262   public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
263   {
264     updateView();
265   }
266
267   protected void populateThresholdComboBox(JComboBox<String> threshold)
268   {
269     threshold.addItem(MessageManager
270             .getString("label.threshold_feature_no_threshold"));
271     threshold.addItem(MessageManager
272             .getString("label.threshold_feature_above_threshold"));
273     threshold.addItem(MessageManager
274             .getString("label.threshold_feature_below_threshold"));
275   }
276
277   protected void seqAssociated_actionPerformed(ActionEvent arg0,
278           JComboBox<String> annotations, JCheckBox seqAssociated)
279   {
280     adjusting = true;
281     String cursel = (String) annotations.getSelectedItem();
282     boolean isvalid = false, isseqs = seqAssociated.isSelected();
283     annotations.removeAllItems();
284     for (String anitem : getAnnotationItems(seqAssociated.isSelected()))
285     {
286       if (anitem.equals(cursel) || (isseqs && cursel.startsWith(anitem)))
287       {
288         isvalid = true;
289         cursel = anitem;
290       }
291       annotations.addItem(anitem);
292     }
293     adjusting = false;
294     if (isvalid)
295     {
296       annotations.setSelectedItem(cursel);
297     }
298     else
299     {
300       if (annotations.getItemCount() > 0)
301       {
302         annotations.setSelectedIndex(0);
303       }
304     }
305   }
306
307   protected void propagateSeqAssociatedThreshold(boolean allAnnotation,
308           AlignmentAnnotation annotation)
309   {
310     if (annotation.sequenceRef == null || annotation.threshold == null)
311     {
312       return;
313     }
314
315     float thr = annotation.threshold.value;
316     for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
317     {
318       AlignmentAnnotation aa = av.getAlignment().getAlignmentAnnotation()[i];
319       if (aa.label.equals(annotation.label)
320               && (annotation.getCalcId() == null ? aa.getCalcId() == null
321                       : annotation.getCalcId().equals(aa.getCalcId())))
322       {
323         if (aa.threshold == null)
324         {
325           aa.threshold = new GraphLine(annotation.threshold);
326         }
327         else
328         {
329           aa.threshold.value = thr;
330         }
331       }
332     }
333   }
334
335   protected boolean colorAlignmContaining(
336           AlignmentAnnotation currentAnnotation, int selectedThresholdItem)
337   {
338
339     AnnotationColourGradient acg = null;
340     if (currentColours.isSelected())
341     {
342       acg = new AnnotationColourGradient(currentAnnotation,
343               av.getGlobalColourScheme(), selectedThresholdItem);
344     }
345     else
346     {
347       acg = new AnnotationColourGradient(currentAnnotation,
348               minColour.getBackground(), maxColour.getBackground(),
349               selectedThresholdItem);
350     }
351     acg.setSeqAssociated(seqAssociated.isSelected());
352
353     if (currentAnnotation.graphMin == 0f
354             && currentAnnotation.graphMax == 0f)
355     {
356       acg.setPredefinedColours(true);
357     }
358
359     acg.thresholdIsMinMax = thresholdIsMin.isSelected();
360
361     av.setGlobalColourScheme(acg);
362
363     if (av.getAlignment().getGroups() != null)
364     {
365
366       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
367       {
368         if (sg.cs == null)
369         {
370           continue;
371         }
372
373         if (currentColours.isSelected())
374         {
375           sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
376                   selectedThresholdItem);
377           ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
378                   .isSelected());
379
380         }
381         else
382         {
383           sg.cs = new AnnotationColourGradient(currentAnnotation,
384                   minColour.getBackground(), maxColour.getBackground(),
385                   selectedThresholdItem);
386           ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
387                   .isSelected());
388         }
389
390       }
391     }
392     return false;
393   }
394
395   public jalview.datamodel.AlignmentAnnotation getCurrentAnnotation()
396   {
397     return currentAnnotation;
398   }
399
400   public void setCurrentAnnotation(
401           jalview.datamodel.AlignmentAnnotation currentAnnotation)
402   {
403     this.currentAnnotation = currentAnnotation;
404   }
405
406   public abstract void valueChanged(boolean updateAllAnnotation);
407
408   public abstract void updateView();
409
410   public abstract void reset();
411 }