46a67c4bd48a1a0c8b14ac09a27541feab63cab6
[jalview.git] / src / jalview / appletgui / FeatureColourChooser.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.appletgui;
22
23 import jalview.datamodel.GraphLine;
24 import jalview.schemes.AnnotationColourGradient;
25 import jalview.schemes.GraduatedColor;
26 import jalview.util.MessageManager;
27
28 import java.awt.Checkbox;
29 import java.awt.Choice;
30 import java.awt.Color;
31 import java.awt.Dimension;
32 import java.awt.FlowLayout;
33 import java.awt.Font;
34 import java.awt.Frame;
35 import java.awt.GridLayout;
36 import java.awt.Label;
37 import java.awt.Panel;
38 import java.awt.Scrollbar;
39 import java.awt.TextField;
40 import java.awt.event.ActionEvent;
41 import java.awt.event.ActionListener;
42 import java.awt.event.AdjustmentEvent;
43 import java.awt.event.AdjustmentListener;
44 import java.awt.event.ItemEvent;
45 import java.awt.event.ItemListener;
46 import java.awt.event.MouseEvent;
47 import java.awt.event.MouseListener;
48 import java.util.Hashtable;
49
50 public class FeatureColourChooser extends Panel implements ActionListener,
51         AdjustmentListener, ItemListener, MouseListener
52 {
53   JVDialog frame;
54
55   Frame owner;
56
57   FeatureRenderer fr;
58
59   FeatureSettings fs = null;
60
61   // AlignmentPanel ap;
62
63   GraduatedColor cs;
64
65   Object oldcs;
66
67   Hashtable oldgroupColours;
68
69   boolean adjusting = false;
70
71   private float min, max;
72
73   String type = null;
74
75   private AlignFrame af = null;
76
77   public FeatureColourChooser(AlignFrame af, String type)
78   {
79     this.af = af;
80     init(af.getSeqcanvas().getFeatureRenderer(), type);
81   }
82
83   public FeatureColourChooser(FeatureSettings fsettings, String type)
84   {
85     this.fs = fsettings;
86     init(fsettings.fr, type);
87     // this.ap = fsettings.ap;
88   }
89
90   private void init(FeatureRenderer frenderer, String type)
91   {
92     this.type = type;
93     fr = frenderer;
94     float mm[] = ((float[][]) fr.getMinMax().get(type))[0];
95     min = mm[0];
96     max = mm[1];
97     oldcs = fr.getFeatureColours().get(type);
98     if (oldcs instanceof GraduatedColor)
99     {
100       cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
101     }
102     else
103     {
104       // promote original color to a graduated color
105       Color bl = Color.black;
106       if (oldcs instanceof Color)
107       {
108         bl = (Color) oldcs;
109       }
110       // original colour becomes the maximum colour
111       cs = new GraduatedColor(Color.white, bl, mm[0], mm[1]);
112     }
113     minColour.setBackground(cs.getMinColor());
114     maxColour.setBackground(cs.getMaxColor());
115     minColour.setForeground(cs.getMinColor());
116     maxColour.setForeground(cs.getMaxColor());
117     colourFromLabel.setState(cs.isColourByLabel());
118     adjusting = true;
119
120     try
121     {
122       jbInit();
123     } catch (Exception ex)
124     {
125     }
126     threshold
127             .select(cs.getThreshType() == AnnotationColourGradient.NO_THRESHOLD ? 0
128                     : cs.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD ? 1
129                             : 2);
130
131     adjusting = false;
132     changeColour();
133     colourFromLabel.addItemListener(this);
134     slider.addAdjustmentListener(this);
135     slider.addMouseListener(this);
136     owner = (af != null) ? af : fs.frame;
137     frame = new JVDialog(owner, MessageManager.formatMessage(
138             "label.graduated_color_for_params", new String[] { type }),
139             true, 480, 248);
140     frame.setMainPanel(this);
141     validate();
142     frame.setVisible(true);
143     if (frame.accept)
144     {
145       changeColour();
146     }
147     else
148     {
149       // cancel
150       reset();
151       PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
152       frame.setVisible(false);
153     }
154   }
155
156   public FeatureColourChooser()
157   {
158     try
159     {
160       jbInit();
161     } catch (Exception ex)
162     {
163       ex.printStackTrace();
164     }
165   }
166
167   private void jbInit() throws Exception
168   {
169     Label minLabel = new Label(MessageManager.getString("label.min")), maxLabel = new Label(
170             MessageManager.getString("label.max"));
171     minLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
172     maxLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
173     // minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
174     // minColour.setLabel("Min Colour");
175
176     minColour.setBounds(0, 0, 40, 27);
177     maxColour.setBounds(0, 0, 40, 27);
178     minColour.addMouseListener(this);
179
180     maxColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
181     maxColour.addMouseListener(this);
182
183     thresholdIsMin.addItemListener(this);
184
185     this.setLayout(new GridLayout(4, 1));
186     jPanel1.setLayout(new FlowLayout());
187     jPanel2.setLayout(new FlowLayout());
188     jPanel3.setLayout(new GridLayout(1, 1));
189     jPanel4.setLayout(new FlowLayout());
190     jPanel1.setBackground(Color.white);
191     jPanel2.setBackground(Color.white);
192     jPanel4.setBackground(Color.white);
193     threshold.addItemListener(this);
194     threshold.addItem(MessageManager
195             .getString("label.threshold_feature_no_thereshold"));
196     threshold.addItem(MessageManager
197             .getString("label.threshold_feature_above_thereshold"));
198     threshold.addItem(MessageManager
199             .getString("label.threshold_feature_below_thereshold"));
200     thresholdValue.addActionListener(this);
201     slider.setBackground(Color.white);
202     slider.setEnabled(false);
203     slider.setSize(new Dimension(93, 21));
204     thresholdValue.setEnabled(false);
205     thresholdValue.setSize(new Dimension(79, 22)); // setBounds(new
206                                                    // Rectangle(248, 2, 79,
207                                                    // 22));
208     thresholdValue.setColumns(5);
209     jPanel3.setBackground(Color.white);
210
211     colourFromLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
212     colourFromLabel.setLabel(MessageManager
213             .getString("label.colour_by_label"));
214     colourFromLabel.setSize(new Dimension(139, 22));
215     // threshold.setBounds(new Rectangle(11, 3, 139, 22));
216     thresholdIsMin.setBackground(Color.white);
217     thresholdIsMin.setLabel(MessageManager
218             .getString("label.threshold_minmax"));
219     thresholdIsMin.setSize(new Dimension(135, 23));
220     // thresholdIsMin.setBounds(new Rectangle(328, 3, 135, 23));
221     jPanel1.add(minLabel);
222     jPanel1.add(minColour);
223     jPanel1.add(maxLabel);
224     jPanel1.add(maxColour);
225     jPanel1.add(colourFromLabel);
226     jPanel2.add(threshold);
227     jPanel3.add(slider);
228     jPanel4.add(thresholdValue);
229     jPanel4.add(thresholdIsMin);
230     this.add(jPanel1);// , java.awt.BorderLayout.NORTH);
231     this.add(jPanel2);// , java.awt.BorderLayout.NORTH);
232     this.add(jPanel3);// , java.awt.BorderLayout.CENTER);
233     this.add(jPanel4);// , java.awt.BorderLayout.CENTER);
234   }
235
236   Panel minColour = new Panel();
237
238   Panel maxColour = new Panel();
239
240   Panel jPanel1 = new Panel();
241
242   Panel jPanel2 = new Panel();
243
244   Choice threshold = new Choice();
245
246   Panel jPanel3 = new Panel();
247
248   Panel jPanel4 = new Panel();
249
250   Scrollbar slider = new Scrollbar(Scrollbar.HORIZONTAL);
251
252   TextField thresholdValue = new TextField(20);
253
254   // BorderLayout borderLayout1 = new BorderLayout();
255
256   Checkbox thresholdIsMin = new Checkbox();
257
258   Checkbox colourFromLabel = new Checkbox();
259
260   private GraphLine threshline;
261
262   public void actionPerformed(ActionEvent evt)
263   {
264     if (evt.getSource() == thresholdValue)
265     {
266       try
267       {
268         float f = new Float(thresholdValue.getText()).floatValue();
269         slider.setValue((int) (f * 1000));
270         adjustmentValueChanged(null);
271       } catch (NumberFormatException ex)
272       {
273       }
274     }
275     else if (evt.getSource() == minColour)
276     {
277       minColour_actionPerformed(null);
278     }
279     else if (evt.getSource() == maxColour)
280     {
281       maxColour_actionPerformed(null);
282     }
283     else
284     {
285       changeColour();
286     }
287   }
288
289   public void itemStateChanged(ItemEvent evt)
290   {
291     maxColour.setEnabled(!colourFromLabel.getState());
292     minColour.setEnabled(!colourFromLabel.getState());
293     changeColour();
294   }
295
296   public void adjustmentValueChanged(AdjustmentEvent evt)
297   {
298     if (!adjusting)
299     {
300       thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
301       valueChanged();
302     }
303   }
304
305   protected void valueChanged()
306   {
307     threshline.value = (float) slider.getValue() / 1000f;
308     cs.setThresh(threshline.value);
309     changeColour();
310     PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
311     // ap.paintAlignment(false);
312   }
313
314   public void minColour_actionPerformed(Color newCol)
315   {
316     if (newCol == null)
317     {
318       UserDefinedColours udc = new UserDefinedColours(this,
319               minColour.getBackground(), owner,
320               MessageManager.getString("label.select_colour_minimum_value")); // frame.owner,
321     }
322     else
323     {
324       minColour.setBackground(newCol);
325       minColour.setForeground(newCol);
326       minColour.repaint();
327       changeColour();
328     }
329
330   }
331
332   public void maxColour_actionPerformed(Color newCol)
333   {
334     if (newCol == null)
335     {
336
337       // UserDefinedColours udc = new UserDefinedColours(this,
338       // "Select Colour for Maximum Value",maxColour.getBackground(),true);
339       UserDefinedColours udc = new UserDefinedColours(this,
340               maxColour.getBackground(), owner,
341               MessageManager.getString("label.select_colour_maximum_value"));
342     }
343     else
344     {
345       maxColour.setBackground(newCol);
346       maxColour.setForeground(newCol);
347       maxColour.repaint();
348       changeColour();
349     }
350   }
351
352   void changeColour()
353   {
354     // Check if combobox is still adjusting
355     if (adjusting)
356     {
357       return;
358     }
359
360     int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD;
361     if (threshold.getSelectedIndex() == 1)
362     {
363       aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
364     }
365     else if (threshold.getSelectedIndex() == 2)
366     {
367       aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
368     }
369
370     slider.setEnabled(true);
371     thresholdValue.setEnabled(true);
372     GraduatedColor acg = new GraduatedColor(minColour.getBackground(),
373             maxColour.getBackground(), min, max);
374
375     acg.setColourByLabel(colourFromLabel.getState());
376     maxColour.setEnabled(!colourFromLabel.getState());
377     minColour.setEnabled(!colourFromLabel.getState());
378     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
379     {
380       slider.setEnabled(false);
381       thresholdValue.setEnabled(false);
382       thresholdValue.setText("");
383     }
384
385     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
386             && threshline == null)
387     {
388       // todo visual indication of feature threshold
389       threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
390               "Threshold", Color.black);
391     }
392
393     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
394     {
395       adjusting = true;
396       acg.setThresh(threshline.value);
397
398       float range = max * 1000f - min * 1000f;
399
400       slider.setMinimum((int) (min * 1000));
401       slider.setMaximum((int) (max * 1000));
402       slider.setValue((int) (threshline.value * 1000));
403       thresholdValue.setText(threshline.value + "");
404       slider.setEnabled(true);
405       thresholdValue.setEnabled(true);
406       adjusting = false;
407     }
408
409     acg.setThreshType(aboveThreshold);
410     if (thresholdIsMin.getState()
411             && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
412     {
413       if (aboveThreshold == AnnotationColourGradient.ABOVE_THRESHOLD)
414       {
415         acg = new GraduatedColor(acg, threshline.value, max);
416       }
417       else
418       {
419         acg = new GraduatedColor(acg, min, threshline.value);
420       }
421     }
422
423     fr.setColour(type, acg);
424     cs = acg;
425     PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
426     // ap.paintAlignment(false);
427   }
428
429   void reset()
430   {
431     fr.setColour(type, oldcs);
432     PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
433     // ap.paintAlignment(true);
434
435   }
436
437   public void mouseClicked(MouseEvent evt)
438   {
439   }
440
441   public void mousePressed(MouseEvent evt)
442   {
443   }
444
445   public void mouseReleased(MouseEvent evt)
446   {
447     if (evt.getSource() == minColour || evt.getSource() == maxColour)
448     {
449       // relay the event
450       actionPerformed(new ActionEvent(evt.getSource(), 1, "Clicked"));
451     }
452     else
453     {
454       PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
455     }
456     // ap.paintAlignment(true);
457   }
458
459   public void mouseEntered(MouseEvent evt)
460   {
461   }
462
463   public void mouseExited(MouseEvent evt)
464   {
465   }
466
467 }