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