JAL-2668 fix broken factory method for colour scheme
[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.MouseAdapter;
30 import java.awt.event.MouseEvent;
31 import java.beans.PropertyVetoException;
32 import java.util.List;
33
34 import javax.swing.JInternalFrame;
35 import javax.swing.JLayeredPane;
36 import javax.swing.event.ChangeEvent;
37 import javax.swing.event.ChangeListener;
38 import javax.swing.event.InternalFrameAdapter;
39 import javax.swing.event.InternalFrameEvent;
40
41 /**
42  * DOCUMENT ME!
43  * 
44  * @author $author$
45  * @version $Revision$
46  */
47 public class SliderPanel extends GSliderPanel
48 {
49   private static final String BACKGROUND = "Background";
50
51   static JInternalFrame conservationSlider;
52
53   static JInternalFrame PIDSlider;
54
55   AlignmentPanel ap;
56
57   boolean forConservation = true;
58
59   ResidueShaderI cs;
60
61   /**
62    * Returns the currently displayed slider panel (or null if none).
63    * 
64    * @return
65    */
66   public static SliderPanel getSliderPanel()
67   {
68     if (conservationSlider != null && conservationSlider.isVisible())
69     {
70       return (SliderPanel) conservationSlider.getContentPane();
71     }
72     if (PIDSlider != null && PIDSlider.isVisible())
73     {
74       return (SliderPanel) PIDSlider.getContentPane();
75     }
76     return null;
77   }
78
79   /**
80    * Creates a new SliderPanel object.
81    * 
82    * @param ap
83    *          DOCUMENT ME!
84    * @param value
85    *          DOCUMENT ME!
86    * @param forConserve
87    *          DOCUMENT ME!
88    * @param scheme
89    *          DOCUMENT ME!
90    */
91   public SliderPanel(final AlignmentPanel ap, int value,
92           boolean forConserve, ResidueShaderI scheme)
93   {
94     this.ap = ap;
95     this.cs = scheme;
96     forConservation = forConserve;
97     undoButton.setVisible(false);
98     applyButton.setVisible(false);
99
100     if (forConservation)
101     {
102       label.setText(MessageManager.getString(
103               "label.enter_value_increase_conservation_visibility"));
104       slider.setMinimum(0);
105       slider.setMaximum(100);
106     }
107     else
108     {
109       label.setText(MessageManager.getString(
110               "label.enter_percentage_identity_above_which_colour_residues"));
111       slider.setMinimum(0);
112       slider.setMaximum(100);
113     }
114
115     slider.addChangeListener(new ChangeListener()
116     {
117       @Override
118       public void stateChanged(ChangeEvent evt)
119       {
120         valueField.setText(slider.getValue() + "");
121         valueChanged(slider.getValue());
122       }
123     });
124
125     slider.addMouseListener(new MouseAdapter()
126     {
127       @Override
128       public void mouseReleased(MouseEvent evt)
129       {
130         ap.paintAlignment(true, true);
131       }
132     });
133
134     slider.setValue(value);
135     valueField.setText(value + "");
136   }
137
138   /**
139    * Method to 'set focus' of the Conservation slider panel
140    * 
141    * @param ap
142    *          the panel to repaint on change of slider
143    * @param rs
144    *          the colour scheme to update on change of slider
145    * @param source
146    *          a text description for the panel's title
147    * 
148    * @return
149    */
150   public static int setConservationSlider(AlignmentPanel ap,
151           ResidueShaderI rs, String source)
152   {
153     SliderPanel sliderPanel = null;
154
155     if (conservationSlider == null)
156     {
157       sliderPanel = new SliderPanel(ap, rs.getConservationInc(), true, rs);
158       conservationSlider = new JInternalFrame();
159       conservationSlider.setContentPane(sliderPanel);
160       conservationSlider.setLayer(JLayeredPane.PALETTE_LAYER);
161     }
162     else
163     {
164       sliderPanel = (SliderPanel) conservationSlider.getContentPane();
165       sliderPanel.valueField
166               .setText(String.valueOf(rs.getConservationInc()));
167       sliderPanel.cs = rs;
168       sliderPanel.ap = ap;
169       sliderPanel.slider.setValue(rs.getConservationInc());
170     }
171
172     conservationSlider.setTitle(MessageManager.formatMessage(
173             "label.conservation_colour_increment", new String[]
174             { source == null ? BACKGROUND : source }));
175
176     List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
177     if (groups != null && !groups.isEmpty())
178     {
179       sliderPanel.setAllGroupsCheckEnabled(true);
180     }
181     else
182     {
183       sliderPanel.setAllGroupsCheckEnabled(false);
184     }
185
186     return sliderPanel.getValue();
187   }
188
189   /**
190    * Hides the PID slider panel if it is shown
191    */
192   public static void hidePIDSlider()
193   {
194     if (PIDSlider != null)
195     {
196       try
197       {
198         PIDSlider.setClosed(true);
199         PIDSlider = null;
200       } catch (PropertyVetoException ex)
201       {
202       }
203     }
204   }
205
206   /**
207    * Hides the conservation slider panel if it is shown
208    */
209   public static void hideConservationSlider()
210   {
211     if (conservationSlider != null)
212     {
213       try
214       {
215         conservationSlider.setClosed(true);
216         conservationSlider = null;
217       } catch (PropertyVetoException ex)
218       {
219       }
220     }
221   }
222
223   /**
224    * DOCUMENT ME!
225    */
226   public static void showConservationSlider()
227   {
228     hidePIDSlider();
229
230     if (!conservationSlider.isVisible())
231     {
232       Desktop.addInternalFrame(conservationSlider,
233               conservationSlider.getTitle(), 420, 90, false);
234       conservationSlider.addInternalFrameListener(new InternalFrameAdapter()
235       {
236         @Override
237         public void internalFrameClosed(InternalFrameEvent e)
238         {
239           conservationSlider = null;
240         }
241       });
242       conservationSlider.setLayer(JLayeredPane.PALETTE_LAYER);
243     }
244   }
245
246   /**
247    * Method to 'set focus' of the PID slider panel
248    * 
249    * @param ap
250    *          the panel to repaint on change of slider
251    * @param rs
252    *          the colour scheme to update on change of slider
253    * @param source
254    *          a text description for the panel's title
255    * 
256    * @return
257    */
258   public static int setPIDSliderSource(AlignmentPanel ap, ResidueShaderI rs,
259           String source)
260   {
261     int threshold = rs.getThreshold();
262
263     SliderPanel sliderPanel = null;
264
265     if (PIDSlider == null)
266     {
267       sliderPanel = new SliderPanel(ap, threshold, false, rs);
268       PIDSlider = new JInternalFrame();
269       PIDSlider.setContentPane(sliderPanel);
270       PIDSlider.setLayer(JLayeredPane.PALETTE_LAYER);
271     }
272     else
273     {
274       sliderPanel = (SliderPanel) PIDSlider.getContentPane();
275       sliderPanel.cs = rs;
276       sliderPanel.ap = ap;
277       sliderPanel.valueField.setText(String.valueOf(rs.getThreshold()));
278       sliderPanel.slider.setValue(rs.getThreshold());
279     }
280
281     PIDSlider.setTitle(MessageManager.formatMessage(
282             "label.percentage_identity_threshold", new String[]
283             { source == null ? BACKGROUND : source }));
284
285     if (ap.av.getAlignment().getGroups() != null)
286     {
287       sliderPanel.setAllGroupsCheckEnabled(true);
288     }
289     else
290     {
291       sliderPanel.setAllGroupsCheckEnabled(false);
292     }
293
294     return sliderPanel.getValue();
295   }
296
297   /**
298    * DOCUMENT ME!
299    * 
300    * @return
301    */
302   public static JInternalFrame showPIDSlider()
303   {
304     hideConservationSlider();
305
306     if (!PIDSlider.isVisible())
307     {
308       Desktop.addInternalFrame(PIDSlider, PIDSlider.getTitle(), 420, 90,
309               false);
310       PIDSlider.setLayer(JLayeredPane.PALETTE_LAYER);
311       PIDSlider.addInternalFrameListener(new InternalFrameAdapter()
312       {
313         @Override
314         public void internalFrameClosed(InternalFrameEvent e)
315         {
316           PIDSlider = null;
317         }
318       });
319       PIDSlider.setLayer(JLayeredPane.PALETTE_LAYER);
320     }
321     return PIDSlider;
322   }
323
324   /**
325    * Updates the colour scheme with the current (identity threshold or
326    * conservation) percentage value. Also updates all groups if 'apply to all
327    * groups' is selected.
328    * 
329    * @param percent
330    */
331   public void valueChanged(int percent)
332   {
333     if (!forConservation)
334     {
335       ap.av.setThreshold(percent);
336     }
337     updateColourScheme(percent, cs, null);
338
339     if (allGroupsCheck.isSelected())
340     {
341       List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
342       for (SequenceGroup sg : groups)
343       {
344         updateColourScheme(percent, sg.getGroupColourScheme(), sg);
345       }
346     }
347
348     ap.getSeqPanel().seqCanvas.repaint();
349   }
350
351   /**
352    * Updates the colour scheme (if not null) with the current (identity
353    * threshold or conservation) percentage value
354    * 
355    * @param percent
356    * @param scheme
357    * @param sg
358    */
359   protected void updateColourScheme(int percent, ResidueShaderI scheme,
360           SequenceGroup sg)
361   {
362     if (scheme == null)
363     {
364       return;
365     }
366     if (forConservation)
367     {
368       if (!scheme.conservationApplied() && sg != null)
369       {
370         /*
371          * first time the colour scheme has had Conservation shading applied
372          * - compute conservation
373          */
374         Conservation c = new Conservation("Group", sg.getSequences(null),
375                 sg.getStartRes(), sg.getEndRes());
376         c.calculate();
377         c.verdict(false, ap.av.getConsPercGaps());
378         sg.cs.setConservation(c);
379
380       }
381       scheme.setConservationApplied(true);
382       scheme.setConservationInc(percent);
383     }
384     else
385     {
386       scheme.setThreshold(percent, ap.av.isIgnoreGapsConsensus());
387     }
388   }
389
390   /**
391    * DOCUMENT ME!
392    * 
393    * @param b
394    *          DOCUMENT ME!
395    */
396   public void setAllGroupsCheckEnabled(boolean b)
397   {
398     allGroupsCheck.setEnabled(b);
399     allGroupsCheck.setSelected(ap.av.getColourAppliesToAllGroups());
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 }