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