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