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