basic house keeping
[jalview.git] / src / jalview / gui / AnnotationRowFilter.java
1 package jalview.gui;
2
3 import jalview.api.analysis.AnnotationFilterParameter;
4 import jalview.api.analysis.AnnotationFilterParameter.SearchableAnnotationField;
5 import jalview.datamodel.AlignmentAnnotation;
6 import jalview.datamodel.Annotation;
7 import jalview.datamodel.ColumnSelection;
8 import jalview.datamodel.GraphLine;
9 import jalview.datamodel.SequenceGroup;
10 import jalview.schemes.AnnotationColourGradient;
11 import jalview.util.MessageManager;
12
13 import java.awt.event.ActionEvent;
14 import java.awt.event.MouseAdapter;
15 import java.awt.event.MouseEvent;
16 import java.util.List;
17 import java.util.Vector;
18
19 import javax.swing.JCheckBox;
20 import javax.swing.JComboBox;
21 import javax.swing.JInternalFrame;
22 import javax.swing.JPanel;
23 import javax.swing.JSlider;
24 import javax.swing.JTextField;
25 import javax.swing.event.ChangeEvent;
26 import javax.swing.event.ChangeListener;
27
28 @SuppressWarnings("serial")
29 public abstract class AnnotationRowFilter extends JPanel
30 {
31   protected AlignViewport av;
32
33   protected AlignmentPanel ap;
34
35   protected int[] annmap;
36
37   protected boolean enableSeqAss = false;
38
39   private jalview.datamodel.AlignmentAnnotation currentAnnotation;
40
41   protected boolean adjusting = false;
42
43   protected JCheckBox currentColours = new JCheckBox();
44
45   protected JPanel minColour = new JPanel();
46
47   protected JPanel maxColour = new JPanel();
48
49   protected JCheckBox seqAssociated = new JCheckBox();
50
51   protected JCheckBox thresholdIsMin = new JCheckBox();
52
53   protected JSlider slider = new JSlider();
54
55   protected JTextField thresholdValue = new JTextField(20);
56
57   protected JInternalFrame frame;
58   /**
59    * enabled if the user is dragging the slider - try to keep updates to a
60    * minimun
61    */
62   protected boolean sliderDragging = false;
63
64   protected void addSliderChangeListener()
65   {
66
67     slider.addChangeListener(new ChangeListener()
68     {
69       @Override
70       public void stateChanged(ChangeEvent evt)
71       {
72         if (!adjusting)
73         {
74           thresholdValue.setText((slider.getValue() / 1000f) + "");
75           valueChanged(!sliderDragging);
76         }
77       }
78     });
79   }
80
81   protected void addSliderMouseListeners()
82   {
83
84     slider.addMouseListener(new MouseAdapter()
85     {
86       @Override
87       public void mousePressed(MouseEvent e)
88       {
89         sliderDragging = true;
90         super.mousePressed(e);
91       }
92
93       @Override
94       public void mouseDragged(MouseEvent e)
95       {
96         sliderDragging = true;
97         super.mouseDragged(e);
98       }
99
100       @Override
101       public void mouseReleased(MouseEvent evt)
102       {
103         if (sliderDragging)
104         {
105           sliderDragging = false;
106           valueChanged(true);
107         }
108         ap.paintAlignment(true);
109       }
110     });
111   }
112
113
114   public AnnotationRowFilter(AlignViewport av, final AlignmentPanel ap)
115   {
116     this.av = av;
117     this.ap = ap;
118   }
119
120   public AnnotationRowFilter()
121   {
122
123   }
124
125   public Vector<String> getAnnotationItems(boolean isSeqAssociated)
126   {
127     Vector<String> list = new Vector<String>();
128     int index = 1;
129     int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
130     for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
131     {
132       if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef == null)
133       {
134         if (isSeqAssociated)
135         {
136           continue;
137         }
138       }
139       else
140       {
141         enableSeqAss = true;
142       }
143       String label = av.getAlignment().getAlignmentAnnotation()[i].label;
144       if (!list.contains(label))
145       {
146         anmap[list.size()] = i;
147         list.add(label);
148
149       }
150       else
151       {
152         if (!isSeqAssociated)
153         {
154           anmap[list.size()] = i;
155           list.add(label + "_" + (index++));
156         }
157       }
158     }
159     this.annmap = new int[list.size()];
160     System.arraycopy(anmap, 0, this.annmap, 0, this.annmap.length);
161     return list;
162   }
163
164   protected int getSelectedThresholdItem(int indexValue)
165   {
166     int selectedThresholdItem = -1;
167     if (indexValue == 1)
168     {
169       selectedThresholdItem = AnnotationColourGradient.ABOVE_THRESHOLD;
170     }
171     else if (indexValue == 2)
172     {
173       selectedThresholdItem = AnnotationColourGradient.BELOW_THRESHOLD;
174     }
175     return selectedThresholdItem;
176   }
177
178   public void modelChanged()
179   {
180     seqAssociated.setEnabled(enableSeqAss);
181   }
182
183   public void ok_actionPerformed(ActionEvent e)
184   {
185     updateView();
186     try
187     {
188       frame.setClosed(true);
189     } catch (Exception ex)
190     {
191     }
192   }
193
194   public void cancel_actionPerformed(ActionEvent e)
195   {
196     reset();
197     ap.paintAlignment(true);
198     try
199     {
200       frame.setClosed(true);
201     } catch (Exception ex)
202     {
203     }
204   }
205
206   public void thresholdCheck_actionPerformed(ActionEvent e)
207   {
208     updateView();
209   }
210
211   public void annotations_actionPerformed(ActionEvent e)
212   {
213     updateView();
214   }
215
216   public void threshold_actionPerformed(ActionEvent e)
217   {
218     updateView();
219   }
220
221   public void thresholdValue_actionPerformed(ActionEvent e)
222   {
223     try
224     {
225       float f = Float.parseFloat(thresholdValue.getText());
226       slider.setValue((int) (f * 1000));
227       updateView();
228     } catch (NumberFormatException ex)
229     {
230     }
231   }
232
233   public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
234   {
235     updateView();
236   }
237
238   protected void populateThresholdComboBox(JComboBox<String> threshold)
239   {
240     threshold.addItem(MessageManager
241             .getString("label.threshold_feature_no_thereshold"));
242     threshold.addItem(MessageManager
243             .getString("label.threshold_feature_above_thereshold"));
244     threshold.addItem(MessageManager
245             .getString("label.threshold_feature_below_thereshold"));
246   }
247
248   protected void seqAssociated_actionPerformed(ActionEvent arg0,
249           JComboBox<String> annotations, JCheckBox seqAssociated)
250   {
251     adjusting = true;
252     String cursel = (String) annotations.getSelectedItem();
253     boolean isvalid = false, isseqs = seqAssociated.isSelected();
254     annotations.removeAllItems();
255     for (String anitem : getAnnotationItems(seqAssociated.isSelected()))
256     {
257       if (anitem.equals(cursel) || (isseqs && cursel.startsWith(anitem)))
258       {
259         isvalid = true;
260         cursel = anitem;
261       }
262       annotations.addItem(anitem);
263     }
264     adjusting = false;
265     if (isvalid)
266     {
267       annotations.setSelectedItem(cursel);
268     }
269     else
270     {
271       if (annotations.getItemCount() > 0)
272       {
273         annotations.setSelectedIndex(0);
274       }
275     }
276   }
277
278   protected void propagateSeqAssociatedThreshold(boolean allAnnotation,
279           AlignmentAnnotation annotation)
280   {
281     if (annotation.sequenceRef == null || annotation.threshold == null)
282     {
283       return;
284     }
285
286     float thr = annotation.threshold.value;
287     for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
288     {
289       AlignmentAnnotation aa = av.getAlignment().getAlignmentAnnotation()[i];
290       if (aa.label.equals(annotation.label)
291               && (annotation.getCalcId() == null ? aa.getCalcId() == null
292                       : annotation.getCalcId().equals(aa.getCalcId())))
293       {
294         if (aa.threshold == null)
295         {
296           aa.threshold = new GraphLine(annotation.threshold);
297         }
298         else
299         {
300           aa.threshold.value = thr;
301         }
302       }
303     }
304   }
305
306   protected boolean colorAlignmContaining(
307           AlignmentAnnotation currentAnnotation, int selectedThresholdItem)
308   {
309
310     AnnotationColourGradient acg = null;
311     if (currentColours.isSelected())
312     {
313       acg = new AnnotationColourGradient(currentAnnotation,
314               av.getGlobalColourScheme(), selectedThresholdItem);
315     }
316     else
317     {
318       acg = new AnnotationColourGradient(currentAnnotation,
319               minColour.getBackground(), maxColour.getBackground(),
320               selectedThresholdItem);
321     }
322     acg.setSeqAssociated(seqAssociated.isSelected());
323
324     if (currentAnnotation.graphMin == 0f
325             && currentAnnotation.graphMax == 0f)
326     {
327       acg.setPredefinedColours(true);
328     }
329
330     acg.thresholdIsMinMax = thresholdIsMin.isSelected();
331
332     av.setGlobalColourScheme(acg);
333
334     if (av.getAlignment().getGroups() != null)
335     {
336
337       for (SequenceGroup sg : ap.av.getAlignment().getGroups())
338       {
339         if (sg.cs == null)
340         {
341           continue;
342         }
343
344         if (currentColours.isSelected())
345         {
346           sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
347                   selectedThresholdItem);
348           ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
349                   .isSelected());
350
351         }
352         else
353         {
354           sg.cs = new AnnotationColourGradient(currentAnnotation,
355                   minColour.getBackground(), maxColour.getBackground(),
356                   selectedThresholdItem);
357           ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
358                   .isSelected());
359         }
360
361       }
362     }
363     return false;
364   }
365
366   protected boolean filterAnnotations(Annotation[] annotations,
367           AnnotationFilterParameter filterParams, ColumnSelection cs)
368   {
369     av.showAllHiddenColumns();
370     cs.clear();
371     int count = 0;
372     do
373     {
374       if (annotations[count] != null)
375       {
376
377         boolean itemMatched = false;
378
379         if (filterParams.getThresholdType() == AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD
380                 && annotations[count].value > currentAnnotation.threshold.value)
381         {
382           itemMatched = true;
383         }
384         if (filterParams.getThresholdType() == AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD
385                 && annotations[count].value < currentAnnotation.threshold.value)
386         {
387           itemMatched = true;
388         }
389
390         if (filterParams.isFilterAlphaHelix()
391                 && annotations[count].secondaryStructure == 'H')
392         {
393           itemMatched = true;
394         }
395
396         if (filterParams.isFilterBetaSheet()
397                 && annotations[count].secondaryStructure == 'E')
398         {
399           itemMatched = true;
400         }
401
402         if (filterParams.isFilterTurn()
403                 && annotations[count].secondaryStructure == 'S')
404         {
405           itemMatched = true;
406         }
407
408         String regexSearchString = filterParams.getRegexString();
409         if (regexSearchString != null
410                 && !filterParams.getRegexSearchFields().isEmpty())
411         {
412           List<SearchableAnnotationField> fields = filterParams
413                   .getRegexSearchFields();
414           try
415           {
416             if (fields.contains(SearchableAnnotationField.DISPLAY_STRING)
417                     && annotations[count].displayCharacter
418                             .matches(regexSearchString))
419             {
420               itemMatched = true;
421             }
422           } catch (java.util.regex.PatternSyntaxException pse)
423           {
424             if (annotations[count].displayCharacter
425                     .equals(regexSearchString))
426             {
427               itemMatched = true;
428             }
429           }
430           if (fields.contains(SearchableAnnotationField.DESCRIPTION)
431                   && annotations[count].description != null
432                   && annotations[count].description
433                           .matches(regexSearchString))
434           {
435             itemMatched = true;
436           }
437         }
438
439         if (itemMatched)
440         {
441           cs.addElement(count);
442         }
443       }
444       count++;
445     } while (count < annotations.length);
446     return false;
447   }
448
449   public jalview.datamodel.AlignmentAnnotation getCurrentAnnotation()
450   {
451     return currentAnnotation;
452   }
453
454   public void setCurrentAnnotation(
455           jalview.datamodel.AlignmentAnnotation currentAnnotation)
456   {
457     this.currentAnnotation = currentAnnotation;
458   }
459
460   public abstract void valueChanged(boolean updateAllAnnotation);
461
462   public abstract void updateView();
463
464   public abstract void reset();
465 }