fedcbc5c3c0b7970a191f8b1b817c88e20e625bc
[jalview.git] / src / jalview / gui / FeatureColourChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3  * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.gui;
20
21 import java.util.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25 import javax.swing.*;
26 import javax.swing.event.*;
27
28 import jalview.datamodel.*;
29 import jalview.schemes.*;
30 import java.awt.Dimension;
31
32 public class FeatureColourChooser extends JPanel
33 {
34   JInternalFrame frame;
35   
36   FeatureRenderer fr;
37
38   FeatureSettings fs;
39
40   GraduatedColor cs;
41   Object oldcs;
42
43   Hashtable oldgroupColours;
44   
45   AlignmentPanel ap;
46   
47
48   boolean adjusting = false;
49
50   private float min;
51
52   private float max;
53   String type = null;
54   public FeatureColourChooser(FeatureSettings fsettings, String type)
55   {
56     this.fs = fsettings;
57     this.type = type;
58     fr = fsettings.fr;
59     ap = fr.ap;
60     frame = new JInternalFrame();
61     frame.setContentPane(this);
62     frame.setLayer(JLayeredPane.PALETTE_LAYER);
63     Desktop.addInternalFrame(frame, "Graduated Feature Colour for "+type, 480, 145);
64
65     slider.addChangeListener(new ChangeListener()
66     {
67       public void stateChanged(ChangeEvent evt)
68       {
69         if (!adjusting)
70         {
71           thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
72           valueChanged();
73         }
74       }
75     });
76     slider.addMouseListener(new MouseAdapter()
77     {
78       public void mouseReleased(MouseEvent evt)
79       {
80         if (fr.ap!=null) { fr.ap.paintAlignment(true); };
81       }
82     });
83
84     float mm[] = ((float[][]) fr.minmax.get(type))[0];
85     min = mm[0];
86     max = mm[1];
87     oldcs = fr.featureColours.get(type);
88     if (oldcs instanceof GraduatedColor)
89     {
90       if (((GraduatedColor)oldcs).isAutoScale())
91       {
92         // update the scale
93         cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
94       } else {
95         cs = new GraduatedColor((GraduatedColor) oldcs);
96       }
97     } else {
98       // promote original color to a graduated color
99       Color bl = Color.black;
100       if (oldcs instanceof Color)
101       {
102         bl = (Color) oldcs;
103       }
104       // original colour becomes the maximum colour
105       cs = new GraduatedColor(Color.white,bl,mm[0],mm[1]);
106       cs.setColourByLabel(false);
107     }
108     minColour.setBackground(cs.getMinColor());
109     maxColour.setBackground(cs.getMaxColor());
110     adjusting = true;
111     
112     try
113     {
114       jbInit();
115     } catch (Exception ex)
116     {
117     }
118     // update the gui from threshold state
119     thresholdIsMin.setSelected(!cs.isAutoScale());
120     colourByLabel.setSelected(cs.isColourByLabel());
121     if (cs.getThreshType()!=AnnotationColourGradient.NO_THRESHOLD)
122     {
123       // initialise threshold slider and selector
124       threshold.setSelectedIndex(cs.getThreshType()==AnnotationColourGradient.ABOVE_THRESHOLD ? 1 : 2);
125             slider.setEnabled(true);
126       thresholdValue.setEnabled(true);
127       threshline = new jalview.datamodel.GraphLine(
128                         (max - min) / 2f,
129                         "Threshold", Color.black);
130       
131     }
132
133     adjusting = false;
134
135     changeColour();
136
137   }
138
139   public FeatureColourChooser()
140   {
141     try
142     {
143       jbInit();
144     } catch (Exception ex)
145     {
146       ex.printStackTrace();
147     }
148   }
149
150   private void jbInit() throws Exception
151   {
152     minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
153     minColour.setBorder(BorderFactory.createEtchedBorder());
154     minColour.setPreferredSize(new Dimension(40, 20));
155     minColour.setToolTipText("Minimum Colour");
156     minColour.addMouseListener(new MouseAdapter()
157     {
158       public void mousePressed(MouseEvent e)
159       {
160         if (minColour.isEnabled())
161         {
162           minColour_actionPerformed();
163         }
164       }
165     });
166     maxColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
167     maxColour.setBorder(BorderFactory.createEtchedBorder());
168     maxColour.setPreferredSize(new Dimension(40, 20));
169     maxColour.setToolTipText("Maximum Colour");
170     maxColour.addMouseListener(new MouseAdapter()
171     {
172       public void mousePressed(MouseEvent e)
173       {
174         if (maxColour.isEnabled())
175         {
176           maxColour_actionPerformed();
177         }
178       }
179     });
180     ok.setOpaque(false);
181     ok.setText("OK");
182     ok.addActionListener(new ActionListener()
183     {
184       public void actionPerformed(ActionEvent e)
185       {
186         ok_actionPerformed(e);
187       }
188     });
189     cancel.setOpaque(false);
190     cancel.setText("Cancel");
191     cancel.addActionListener(new ActionListener()
192     {
193       public void actionPerformed(ActionEvent e)
194       {
195         cancel_actionPerformed(e);
196       }
197     });
198     this.setLayout(borderLayout1);
199     jPanel2.setLayout(flowLayout1);
200     jPanel1.setBackground(Color.white);
201     jPanel2.setBackground(Color.white);
202     threshold.addActionListener(new ActionListener()
203     {
204       public void actionPerformed(ActionEvent e)
205       {
206         threshold_actionPerformed(e);
207       }
208     });
209     threshold.addItem("No Threshold"); // index 0
210     threshold.addItem("Above Threshold"); // index 1
211     threshold.addItem("Below Threshold"); // index 2
212     jPanel3.setLayout(flowLayout2);
213     thresholdValue.addActionListener(new ActionListener()
214     {
215       public void actionPerformed(ActionEvent e)
216       {
217         thresholdValue_actionPerformed(e);
218       }
219     });
220     slider.setPaintLabels(false);
221     slider.setPaintTicks(true);
222     slider.setBackground(Color.white);
223     slider.setEnabled(false);
224     slider.setOpaque(false);
225     slider.setPreferredSize(new Dimension(100, 32));
226     thresholdValue.setEnabled(false);
227     thresholdValue.setColumns(7);
228     jPanel3.setBackground(Color.white);
229     currentColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
230     currentColours.setOpaque(false);
231     currentColours.setText("Use Original Colours");
232     currentColours.addActionListener(new ActionListener()
233     {
234       public void actionPerformed(ActionEvent e)
235       {
236         currentColours_actionPerformed(e);
237       }
238     });
239     thresholdIsMin.setBackground(Color.white);
240     thresholdIsMin.setText("Threshold is Min/Max");
241     thresholdIsMin.addActionListener(new ActionListener()
242     {
243       public void actionPerformed(ActionEvent actionEvent)
244       {
245         thresholdIsMin_actionPerformed(actionEvent);
246       }
247     });
248     colourByLabel.setBackground(Color.white);
249     colourByLabel.setText("Colour by Label");
250     colourByLabel.addActionListener(new ActionListener()
251     {
252       public void actionPerformed(ActionEvent actionEvent)
253       {
254         colourByLabel_actionPerformed(actionEvent);
255       }
256     });
257     jPanel1.add(ok);
258     jPanel1.add(cancel);
259     // jPanel2.add(currentColours);
260     jPanel2.add(minColour);
261     jPanel2.add(maxColour);
262     this.add(jPanel3, java.awt.BorderLayout.CENTER);
263     jPanel3.add(threshold);
264     jPanel3.add(slider);
265     jPanel3.add(thresholdValue);
266     jPanel3.add(thresholdIsMin);
267     jPanel3.add(colourByLabel);
268     this.add(jPanel1, java.awt.BorderLayout.SOUTH);
269     this.add(jPanel2, java.awt.BorderLayout.NORTH);
270   }
271
272
273   JPanel minColour = new JPanel();
274
275   JPanel maxColour = new JPanel();
276
277   JButton ok = new JButton();
278
279   JButton cancel = new JButton();
280
281   JPanel jPanel1 = new JPanel();
282
283   JPanel jPanel2 = new JPanel();
284
285   BorderLayout borderLayout1 = new BorderLayout();
286
287   JComboBox threshold = new JComboBox();
288
289   FlowLayout flowLayout1 = new FlowLayout();
290
291   JPanel jPanel3 = new JPanel();
292
293   FlowLayout flowLayout2 = new FlowLayout();
294
295   JSlider slider = new JSlider();
296
297   JTextField thresholdValue = new JTextField(20);
298   // TODO refactor to tolower flag
299   JCheckBox currentColours = new JCheckBox();
300
301   JCheckBox thresholdIsMin = new JCheckBox();
302   JCheckBox colourByLabel = new JCheckBox();
303
304   private GraphLine threshline;
305
306   public void minColour_actionPerformed()
307   {
308     Color col = JColorChooser.showDialog(this,
309             "Select Colour for Minimum Value", minColour.getBackground());
310     if (col != null)
311     {
312       minColour.setBackground(col);
313     }
314     minColour.repaint();
315     changeColour();
316   }
317
318   public void maxColour_actionPerformed()
319   {
320     Color col = JColorChooser.showDialog(this,
321             "Select Colour for Maximum Value", maxColour.getBackground());
322     if (col != null)
323     {
324       maxColour.setBackground(col);
325     }
326     maxColour.repaint();
327     changeColour();
328   }
329
330   void changeColour()
331   {
332     // Check if combobox is still adjusting
333     if (adjusting)
334     {
335       return;
336     }
337
338
339     int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD;
340     if (threshold.getSelectedItem().equals("Above Threshold"))
341     {
342       aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
343     }
344     else if (threshold.getSelectedItem().equals("Below Threshold"))
345     {
346       aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
347     } 
348
349     slider.setEnabled(true);
350     thresholdValue.setEnabled(true);
351     GraduatedColor acg = new GraduatedColor(minColour.getBackground(), maxColour.getBackground(), min, max);
352
353     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
354     {
355       slider.setEnabled(false);
356       thresholdValue.setEnabled(false);
357       thresholdValue.setText("");
358     }
359     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
360             && threshline == null)
361     {
362       // todo visual indication of feature threshold
363       threshline = new jalview.datamodel.GraphLine(
364                       (max - min) / 2f,
365                       "Threshold", Color.black);
366     }
367
368     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
369     {
370       adjusting = true;
371       acg.setThresh(threshline.value);
372
373       float range = max * 1000f
374               - min * 1000f;
375
376       slider.setMinimum((int) (min * 1000));
377       slider.setMaximum((int) (max * 1000));
378       slider.setValue((int) (threshline.value * 1000));
379       thresholdValue.setText(threshline.value + "");
380       slider.setMajorTickSpacing((int) (range / 10f));
381       slider.setEnabled(true);
382       thresholdValue.setEnabled(true);
383       adjusting = false;
384     }
385
386     acg.setThreshType(aboveThreshold);
387     if (thresholdIsMin.isSelected() && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
388     {
389       acg.setAutoScaled(false);
390       if (aboveThreshold==AnnotationColourGradient.ABOVE_THRESHOLD)
391       { 
392         acg = new GraduatedColor(acg, threshline.value, max);
393       } else { 
394         acg = new GraduatedColor(acg, min,threshline.value);
395       }
396     } else {
397       acg.setAutoScaled(true);
398     }
399     acg.setColourByLabel(colourByLabel.isSelected());
400     fr.featureColours.put(type,acg);
401     cs = acg;
402     ap.paintAlignment(false);
403   }
404
405   public void ok_actionPerformed(ActionEvent e)
406   {
407     changeColour();
408     try
409     {
410       frame.setClosed(true);
411     } catch (Exception ex)
412     {
413     }
414   }
415
416   public void cancel_actionPerformed(ActionEvent e)
417   {
418     reset();
419     try
420     {
421       frame.setClosed(true);
422     } catch (Exception ex)
423     {
424     }
425   }
426
427   void reset()
428   {
429     fr.featureColours.put(type, oldcs);
430   }
431
432   public void thresholdCheck_actionPerformed(ActionEvent e)
433   {
434     changeColour();
435   }
436
437   public void annotations_actionPerformed(ActionEvent e)
438   {
439     changeColour();
440   }
441
442   public void threshold_actionPerformed(ActionEvent e)
443   {
444     changeColour();
445   }
446
447   public void thresholdValue_actionPerformed(ActionEvent e)
448   {
449     try
450     {
451       float f = Float.parseFloat(thresholdValue.getText());
452       slider.setValue((int) (f * 1000));
453       threshline.value = f;
454     } catch (NumberFormatException ex)
455     {
456     }
457   }
458
459   public void valueChanged()
460   {
461     threshline.value = (float) slider.getValue() / 1000f;
462     cs.setThresh(threshline.value);
463     changeColour();
464     ap.paintAlignment(false);
465   }
466
467   public void currentColours_actionPerformed(ActionEvent e)
468   {
469     if (currentColours.isSelected())
470     {
471       reset();
472     }
473
474     maxColour.setEnabled(!currentColours.isSelected());
475     minColour.setEnabled(!currentColours.isSelected());
476
477     changeColour();
478   }
479
480   public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
481   {
482     changeColour();
483   }
484   public void colourByLabel_actionPerformed(ActionEvent actionEvent)
485   {
486     changeColour();
487   }
488
489 }