993cd2e064ae840486340faef7c49ae8322bd3a4
[jalview.git] / src / jalview / gui / FeatureColourChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 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       cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
91     } else {
92       // promote original color to a graduated color
93       Color bl = Color.black;
94       if (oldcs instanceof Color)
95       {
96         bl = (Color) oldcs;
97       }
98       // original colour becomes the maximum colour
99       cs = new GraduatedColor(Color.white,bl,mm[0],mm[1]);
100     }
101     minColour.setBackground(cs.getMinColor());
102     maxColour.setBackground(cs.getMaxColor());
103     adjusting = true;
104     
105     try
106     {
107       jbInit();
108     } catch (Exception ex)
109     {
110     }
111
112     adjusting = false;
113
114     changeColour();
115
116   }
117
118   public FeatureColourChooser()
119   {
120     try
121     {
122       jbInit();
123     } catch (Exception ex)
124     {
125       ex.printStackTrace();
126     }
127   }
128
129   private void jbInit() throws Exception
130   {
131     minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
132     minColour.setBorder(BorderFactory.createEtchedBorder());
133     minColour.setPreferredSize(new Dimension(40, 20));
134     minColour.setToolTipText("Minimum Colour");
135     minColour.addMouseListener(new MouseAdapter()
136     {
137       public void mousePressed(MouseEvent e)
138       {
139         if (minColour.isEnabled())
140         {
141           minColour_actionPerformed();
142         }
143       }
144     });
145     maxColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
146     maxColour.setBorder(BorderFactory.createEtchedBorder());
147     maxColour.setPreferredSize(new Dimension(40, 20));
148     maxColour.setToolTipText("Maximum Colour");
149     maxColour.addMouseListener(new MouseAdapter()
150     {
151       public void mousePressed(MouseEvent e)
152       {
153         if (maxColour.isEnabled())
154         {
155           maxColour_actionPerformed();
156         }
157       }
158     });
159     ok.setOpaque(false);
160     ok.setText("OK");
161     ok.addActionListener(new ActionListener()
162     {
163       public void actionPerformed(ActionEvent e)
164       {
165         ok_actionPerformed(e);
166       }
167     });
168     cancel.setOpaque(false);
169     cancel.setText("Cancel");
170     cancel.addActionListener(new ActionListener()
171     {
172       public void actionPerformed(ActionEvent e)
173       {
174         cancel_actionPerformed(e);
175       }
176     });
177     this.setLayout(borderLayout1);
178     jPanel2.setLayout(flowLayout1);
179     jPanel1.setBackground(Color.white);
180     jPanel2.setBackground(Color.white);
181     threshold.addActionListener(new ActionListener()
182     {
183       public void actionPerformed(ActionEvent e)
184       {
185         threshold_actionPerformed(e);
186       }
187     });
188     threshold.addItem("No Threshold");
189     threshold.addItem("Above Threshold");
190     threshold.addItem("Below Threshold");
191     jPanel3.setLayout(flowLayout2);
192     thresholdValue.addActionListener(new ActionListener()
193     {
194       public void actionPerformed(ActionEvent e)
195       {
196         thresholdValue_actionPerformed(e);
197       }
198     });
199     slider.setPaintLabels(false);
200     slider.setPaintTicks(true);
201     slider.setBackground(Color.white);
202     slider.setEnabled(false);
203     slider.setOpaque(false);
204     slider.setPreferredSize(new Dimension(100, 32));
205     thresholdValue.setEnabled(false);
206     thresholdValue.setColumns(7);
207     jPanel3.setBackground(Color.white);
208     currentColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
209     currentColours.setOpaque(false);
210     currentColours.setText("Use Original Colours");
211     currentColours.addActionListener(new ActionListener()
212     {
213       public void actionPerformed(ActionEvent e)
214       {
215         currentColours_actionPerformed(e);
216       }
217     });
218     thresholdIsMin.setBackground(Color.white);
219     thresholdIsMin.setText("Threshold is Min/Max");
220     thresholdIsMin.addActionListener(new ActionListener()
221     {
222       public void actionPerformed(ActionEvent actionEvent)
223       {
224         thresholdIsMin_actionPerformed(actionEvent);
225       }
226     });
227     jPanel1.add(ok);
228     jPanel1.add(cancel);
229     // jPanel2.add(currentColours);
230     jPanel2.add(minColour);
231     jPanel2.add(maxColour);
232     this.add(jPanel3, java.awt.BorderLayout.CENTER);
233     jPanel3.add(threshold);
234     jPanel3.add(slider);
235     jPanel3.add(thresholdValue);
236     jPanel3.add(thresholdIsMin);
237     this.add(jPanel1, java.awt.BorderLayout.SOUTH);
238     this.add(jPanel2, java.awt.BorderLayout.NORTH);
239   }
240
241
242   JPanel minColour = new JPanel();
243
244   JPanel maxColour = new JPanel();
245
246   JButton ok = new JButton();
247
248   JButton cancel = new JButton();
249
250   JPanel jPanel1 = new JPanel();
251
252   JPanel jPanel2 = new JPanel();
253
254   BorderLayout borderLayout1 = new BorderLayout();
255
256   JComboBox threshold = new JComboBox();
257
258   FlowLayout flowLayout1 = new FlowLayout();
259
260   JPanel jPanel3 = new JPanel();
261
262   FlowLayout flowLayout2 = new FlowLayout();
263
264   JSlider slider = new JSlider();
265
266   JTextField thresholdValue = new JTextField(20);
267   // TODO refactor to tolower flag
268   JCheckBox currentColours = new JCheckBox();
269
270   JCheckBox thresholdIsMin = new JCheckBox();
271
272   private GraphLine threshline;
273
274   public void minColour_actionPerformed()
275   {
276     Color col = JColorChooser.showDialog(this,
277             "Select Colour for Minimum Value", minColour.getBackground());
278     if (col != null)
279     {
280       minColour.setBackground(col);
281     }
282     minColour.repaint();
283     changeColour();
284   }
285
286   public void maxColour_actionPerformed()
287   {
288     Color col = JColorChooser.showDialog(this,
289             "Select Colour for Maximum Value", maxColour.getBackground());
290     if (col != null)
291     {
292       maxColour.setBackground(col);
293     }
294     maxColour.repaint();
295     changeColour();
296   }
297
298   void changeColour()
299   {
300     // Check if combobox is still adjusting
301     if (adjusting)
302     {
303       return;
304     }
305
306
307     int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD;
308     if (threshold.getSelectedItem().equals("Above Threshold"))
309     {
310       aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
311     }
312     else if (threshold.getSelectedItem().equals("Below Threshold"))
313     {
314       aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
315     } 
316
317     slider.setEnabled(true);
318     thresholdValue.setEnabled(true);
319     GraduatedColor acg = new GraduatedColor(minColour.getBackground(), maxColour.getBackground(), min, max);
320
321     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
322     {
323       slider.setEnabled(false);
324       thresholdValue.setEnabled(false);
325       thresholdValue.setText("");
326     }
327     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
328             && threshline == null)
329     {
330       // todo visual indication of feature threshold
331       threshline = new jalview.datamodel.GraphLine(
332                       (max - min) / 2f,
333                       "Threshold", Color.black);
334     }
335
336     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
337     {
338       adjusting = true;
339       acg.setThresh(threshline.value);
340
341       float range = max * 1000f
342               - min * 1000f;
343
344       slider.setMinimum((int) (min * 1000));
345       slider.setMaximum((int) (max * 1000));
346       slider.setValue((int) (threshline.value * 1000));
347       thresholdValue.setText(threshline.value + "");
348       slider.setMajorTickSpacing((int) (range / 10f));
349       slider.setEnabled(true);
350       thresholdValue.setEnabled(true);
351       adjusting = false;
352     }
353
354     acg.setThreshType(aboveThreshold);
355     if (thresholdIsMin.isSelected() && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
356     {
357       if (aboveThreshold==AnnotationColourGradient.ABOVE_THRESHOLD)
358       { 
359         acg = new GraduatedColor(acg, threshline.value, max);
360       } else { 
361         acg = new GraduatedColor(acg, min,threshline.value);
362       }
363     }
364     
365     fr.featureColours.put(type,acg);
366     cs = acg;
367     ap.paintAlignment(false);
368   }
369
370   public void ok_actionPerformed(ActionEvent e)
371   {
372     changeColour();
373     try
374     {
375       frame.setClosed(true);
376     } catch (Exception ex)
377     {
378     }
379   }
380
381   public void cancel_actionPerformed(ActionEvent e)
382   {
383     reset();
384     try
385     {
386       frame.setClosed(true);
387     } catch (Exception ex)
388     {
389     }
390   }
391
392   void reset()
393   {
394     fr.featureColours.put(type, oldcs);
395   }
396
397   public void thresholdCheck_actionPerformed(ActionEvent e)
398   {
399     changeColour();
400   }
401
402   public void annotations_actionPerformed(ActionEvent e)
403   {
404     changeColour();
405   }
406
407   public void threshold_actionPerformed(ActionEvent e)
408   {
409     changeColour();
410   }
411
412   public void thresholdValue_actionPerformed(ActionEvent e)
413   {
414     try
415     {
416       float f = Float.parseFloat(thresholdValue.getText());
417       slider.setValue((int) (f * 1000));
418       threshline.value = f;
419     } catch (NumberFormatException ex)
420     {
421     }
422   }
423
424   public void valueChanged()
425   {
426     threshline.value = (float) slider.getValue() / 1000f;
427     cs.setThresh(threshline.value);
428     changeColour();
429     ap.paintAlignment(false);
430   }
431
432   public void currentColours_actionPerformed(ActionEvent e)
433   {
434     if (currentColours.isSelected())
435     {
436       reset();
437     }
438
439     maxColour.setEnabled(!currentColours.isSelected());
440     minColour.setEnabled(!currentColours.isSelected());
441
442     changeColour();
443   }
444
445   public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
446   {
447     changeColour();
448   }
449
450 }