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