JAL-3201 JAL-2386 don't pre-select 'apply to all groups'
[jalview.git] / src / jalview / gui / SliderPanel.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.analysis.Conservation;
24 import jalview.datamodel.SequenceGroup;
25 import jalview.jbgui.GSliderPanel;
26 import jalview.renderer.ResidueShaderI;
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.beans.PropertyVetoException;
33 import java.util.List;
34
35 import javax.swing.JInternalFrame;
36 import javax.swing.JLayeredPane;
37 import javax.swing.event.ChangeEvent;
38 import javax.swing.event.ChangeListener;
39 import javax.swing.event.InternalFrameAdapter;
40 import javax.swing.event.InternalFrameEvent;
41
42 /**
43  * DOCUMENT ME!
44  * 
45  * @author $author$
46  * @version $Revision$
47  */
48 public class SliderPanel extends GSliderPanel
49 {
50   private static final String BACKGROUND = "Background";
51
52   static JInternalFrame conservationSlider;
53
54   static JInternalFrame PIDSlider;
55
56   AlignmentPanel ap;
57
58   boolean forConservation = true;
59
60   ResidueShaderI cs;
61
62   /**
63    * Returns the currently displayed slider panel (or null if none).
64    * 
65    * @return
66    */
67   public static SliderPanel getSliderPanel()
68   {
69     if (conservationSlider != null && conservationSlider.isVisible())
70     {
71       return (SliderPanel) conservationSlider.getContentPane();
72     }
73     if (PIDSlider != null && PIDSlider.isVisible())
74     {
75       return (SliderPanel) PIDSlider.getContentPane();
76     }
77     return null;
78   }
79
80   /**
81    * Creates a new SliderPanel object.
82    * 
83    * @param ap
84    *          DOCUMENT ME!
85    * @param value
86    *          DOCUMENT ME!
87    * @param forConserve
88    *          DOCUMENT ME!
89    * @param scheme
90    *          DOCUMENT ME!
91    */
92   public SliderPanel(final AlignmentPanel ap, int value,
93           boolean forConserve, ResidueShaderI scheme)
94   {
95     this.ap = ap;
96     this.cs = scheme;
97     forConservation = forConserve;
98     undoButton.setVisible(false);
99     applyButton.setVisible(false);
100
101     if (forConservation)
102     {
103       label.setText(MessageManager.getString(
104               "label.enter_value_increase_conservation_visibility"));
105       slider.setMinimum(0);
106       slider.setMaximum(100);
107     }
108     else
109     {
110       label.setText(MessageManager.getString(
111               "label.enter_percentage_identity_above_which_colour_residues"));
112       slider.setMinimum(0);
113       slider.setMaximum(100);
114     }
115
116     slider.addChangeListener(new ChangeListener()
117     {
118       @Override
119       public void stateChanged(ChangeEvent evt)
120       {
121         valueField.setText(slider.getValue() + "");
122         valueChanged(slider.getValue());
123       }
124     });
125
126     slider.addMouseListener(new MouseAdapter()
127     {
128       @Override
129       public void mouseReleased(MouseEvent evt)
130       {
131         ap.paintAlignment(true, true);
132       }
133     });
134
135     slider.setValue(value);
136     valueField.setText(value + "");
137   }
138
139   /**
140    * Method to 'set focus' of the Conservation slider panel
141    * 
142    * @param ap
143    *          the panel to repaint on change of slider
144    * @param rs
145    *          the colour scheme to update on change of slider
146    * @param source
147    *          a text description for the panel's title
148    * 
149    * @return
150    */
151   public static int setConservationSlider(AlignmentPanel ap,
152           ResidueShaderI rs, String source)
153   {
154     SliderPanel sliderPanel = null;
155
156     if (conservationSlider == null)
157     {
158       sliderPanel = new SliderPanel(ap, rs.getConservationInc(), true, rs);
159       conservationSlider = new JInternalFrame();
160       conservationSlider.setContentPane(sliderPanel);
161       conservationSlider.setLayer(JLayeredPane.PALETTE_LAYER);
162     }
163     else
164     {
165       sliderPanel = (SliderPanel) conservationSlider.getContentPane();
166       sliderPanel.valueField
167               .setText(String.valueOf(rs.getConservationInc()));
168       sliderPanel.cs = rs;
169       sliderPanel.ap = ap;
170       sliderPanel.slider.setValue(rs.getConservationInc());
171     }
172
173     conservationSlider.setTitle(MessageManager.formatMessage(
174             "label.conservation_colour_increment", new String[]
175             { source == null ? BACKGROUND : source }));
176
177     List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
178     if (groups != null && !groups.isEmpty())
179     {
180       sliderPanel.setAllGroupsCheckEnabled(true);
181     }
182     else
183     {
184       sliderPanel.setAllGroupsCheckEnabled(false);
185     }
186
187     return sliderPanel.getValue();
188   }
189
190   /**
191    * Hides the PID slider panel if it is shown
192    */
193   public static void hidePIDSlider()
194   {
195     if (PIDSlider != null)
196     {
197       try
198       {
199         PIDSlider.setClosed(true);
200         PIDSlider = null;
201       } catch (PropertyVetoException ex)
202       {
203       }
204     }
205   }
206
207   /**
208    * Hides the conservation slider panel if it is shown
209    */
210   public static void hideConservationSlider()
211   {
212     if (conservationSlider != null)
213     {
214       try
215       {
216         conservationSlider.setClosed(true);
217         conservationSlider = null;
218       } catch (PropertyVetoException ex)
219       {
220       }
221     }
222   }
223
224   /**
225    * DOCUMENT ME!
226    */
227   public static void showConservationSlider()
228   {
229     hidePIDSlider();
230
231     if (!conservationSlider.isVisible())
232     {
233       Desktop.addInternalFrame(conservationSlider,
234               conservationSlider.getTitle(), 420, 90, false);
235       conservationSlider.addInternalFrameListener(new InternalFrameAdapter()
236       {
237         @Override
238         public void internalFrameClosed(InternalFrameEvent e)
239         {
240           conservationSlider = null;
241         }
242       });
243       conservationSlider.setLayer(JLayeredPane.PALETTE_LAYER);
244     }
245   }
246
247   /**
248    * Method to 'set focus' of the PID slider panel
249    * 
250    * @param ap
251    *          the panel to repaint on change of slider
252    * @param rs
253    *          the colour scheme to update on change of slider
254    * @param source
255    *          a text description for the panel's title
256    * 
257    * @return
258    */
259   public static int setPIDSliderSource(AlignmentPanel ap, ResidueShaderI rs,
260           String source)
261   {
262     int threshold = rs.getThreshold();
263
264     SliderPanel sliderPanel = null;
265
266     if (PIDSlider == null)
267     {
268       sliderPanel = new SliderPanel(ap, threshold, false, rs);
269       PIDSlider = new JInternalFrame();
270       PIDSlider.setContentPane(sliderPanel);
271       PIDSlider.setLayer(JLayeredPane.PALETTE_LAYER);
272     }
273     else
274     {
275       sliderPanel = (SliderPanel) PIDSlider.getContentPane();
276       sliderPanel.cs = rs;
277       sliderPanel.ap = ap;
278       sliderPanel.valueField.setText(String.valueOf(rs.getThreshold()));
279       sliderPanel.slider.setValue(rs.getThreshold());
280     }
281
282     PIDSlider.setTitle(MessageManager.formatMessage(
283             "label.percentage_identity_threshold", new String[]
284             { source == null ? BACKGROUND : source }));
285
286     if (ap.av.getAlignment().getGroups() != null)
287     {
288       sliderPanel.setAllGroupsCheckEnabled(true);
289     }
290     else
291     {
292       sliderPanel.setAllGroupsCheckEnabled(false);
293     }
294
295     return sliderPanel.getValue();
296   }
297
298   /**
299    * DOCUMENT ME!
300    * 
301    * @return
302    */
303   public static JInternalFrame showPIDSlider()
304   {
305     hideConservationSlider();
306
307     if (!PIDSlider.isVisible())
308     {
309       Desktop.addInternalFrame(PIDSlider, PIDSlider.getTitle(), 420, 90,
310               false);
311       PIDSlider.setLayer(JLayeredPane.PALETTE_LAYER);
312       PIDSlider.addInternalFrameListener(new InternalFrameAdapter()
313       {
314         @Override
315         public void internalFrameClosed(InternalFrameEvent e)
316         {
317           PIDSlider = null;
318         }
319       });
320       PIDSlider.setLayer(JLayeredPane.PALETTE_LAYER);
321     }
322     return PIDSlider;
323   }
324
325   /**
326    * Updates the colour scheme with the current (identity threshold or
327    * conservation) percentage value. Also updates all groups if 'apply to all
328    * groups' is selected.
329    * 
330    * @param percent
331    */
332   public void valueChanged(int percent)
333   {
334     if (!forConservation)
335     {
336       ap.av.setThreshold(percent);
337     }
338     updateColourScheme(percent, cs, null);
339
340     if (allGroupsCheck.isSelected())
341     {
342       List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
343       for (SequenceGroup sg : groups)
344       {
345         updateColourScheme(percent, sg.getGroupColourScheme(), sg);
346       }
347     }
348
349     ap.getSeqPanel().seqCanvas.repaint();
350   }
351
352   /**
353    * Updates the colour scheme (if not null) with the current (identity
354    * threshold or conservation) percentage value
355    * 
356    * @param percent
357    * @param scheme
358    * @param sg
359    */
360   protected void updateColourScheme(int percent, ResidueShaderI scheme,
361           SequenceGroup sg)
362   {
363     if (scheme == null)
364     {
365       return;
366     }
367     if (forConservation)
368     {
369       if (!scheme.conservationApplied() && sg != null)
370       {
371         /*
372          * first time the colour scheme has had Conservation shading applied
373          * - compute conservation
374          */
375         Conservation c = new Conservation("Group", sg.getSequences(null),
376                 sg.getStartRes(), sg.getEndRes());
377         c.calculate();
378         c.verdict(false, ap.av.getConsPercGaps());
379         sg.cs.setConservation(c);
380
381       }
382       scheme.setConservationApplied(true);
383       scheme.setConservationInc(percent);
384     }
385     else
386     {
387       scheme.setThreshold(percent, ap.av.isIgnoreGapsConsensus());
388     }
389   }
390
391   /**
392    * DOCUMENT ME!
393    * 
394    * @param b
395    *          DOCUMENT ME!
396    */
397   public void setAllGroupsCheckEnabled(boolean b)
398   {
399     allGroupsCheck.setEnabled(b);
400   }
401
402   /**
403    * DOCUMENT ME!
404    * 
405    * @param e
406    *          DOCUMENT ME!
407    */
408   @Override
409   public void valueField_actionPerformed()
410   {
411     try
412     {
413       int i = Integer.parseInt(valueField.getText());
414       slider.setValue(i);
415     } catch (NumberFormatException ex)
416     {
417       valueField.setText(slider.getValue() + "");
418     }
419   }
420
421   /**
422    * DOCUMENT ME!
423    * 
424    * @param value
425    *          DOCUMENT ME!
426    */
427   public void setValue(int value)
428   {
429     slider.setValue(value);
430   }
431
432   /**
433    * DOCUMENT ME!
434    * 
435    * @return DOCUMENT ME!
436    */
437   public int getValue()
438   {
439     return Integer.parseInt(valueField.getText());
440   }
441
442   @Override
443   public void slider_mouseReleased(MouseEvent e)
444   {
445     if (ap.overviewPanel != null)
446     {
447       ap.overviewPanel.updateOverviewImage();
448     }
449   }
450
451   public static int getConservationValue()
452   {
453     return getValue(conservationSlider);
454   }
455
456   static int getValue(JInternalFrame slider)
457   {
458     return slider == null ? 0
459             : ((SliderPanel) slider.getContentPane()).getValue();
460   }
461
462   public static int getPIDValue()
463   {
464     return getValue(PIDSlider);
465   }
466
467   /**
468    * Answers true if the SliderPanel is for Conservation, false if it is for PID
469    * threshold
470    * 
471    * @return
472    */
473   public boolean isForConservation()
474   {
475     return forConservation;
476   }
477
478   /**
479    * Answers the title for the slider panel; this may include 'Background' if
480    * for the alignment, or the group id if for a group
481    * 
482    * @return
483    */
484   public String getTitle()
485   {
486     String title = null;
487     if (isForConservation())
488     {
489       if (conservationSlider != null)
490       {
491         title = conservationSlider.getTitle();
492       }
493     }
494     else if (PIDSlider != null)
495     {
496       title = PIDSlider.getTitle();
497     }
498     return title;
499   }
500
501   @Override
502   protected void allGroupsCheck_actionPerformed(ActionEvent e)
503   {
504     if (allGroupsCheck.isSelected())
505     {
506       valueChanged(slider.getValue());
507     }
508   }
509 }