2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
23 import java.awt.event.*;
26 import javax.swing.event.*;
28 import net.miginfocom.swing.MigLayout;
30 import jalview.bin.Cache;
31 import jalview.datamodel.*;
32 import jalview.schemes.*;
33 import java.awt.Dimension;
35 public class AnnotationColourChooser extends JPanel
45 Hashtable oldgroupColours;
47 jalview.datamodel.AlignmentAnnotation currentAnnotation;
49 boolean adjusting = false;
51 public AnnotationColourChooser(AlignViewport av, final AlignmentPanel ap)
53 oldcs = av.getGlobalColourScheme();
54 if (av.getAlignment().getGroups() != null)
56 oldgroupColours = new Hashtable();
57 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
61 oldgroupColours.put(sg, sg.cs);
67 frame = new JInternalFrame();
68 frame.setContentPane(this);
69 frame.setLayer(JLayeredPane.PALETTE_LAYER);
70 Desktop.addInternalFrame(frame, "Colour by Annotation", 520, 215);
72 slider.addChangeListener(new ChangeListener()
74 public void stateChanged(ChangeEvent evt)
78 thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
83 slider.addMouseListener(new MouseAdapter()
85 public void mouseReleased(MouseEvent evt)
87 ap.paintAlignment(true);
91 if (av.getAlignment().getAlignmentAnnotation() == null)
96 // Always get default shading from preferences.
99 if (oldcs instanceof AnnotationColourGradient)
101 AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
102 currentColours.setSelected(acg.predefinedColours);
103 if (!acg.predefinedColours)
105 minColour.setBackground(acg.getMinColour());
106 maxColour.setBackground(acg.getMaxColour());
108 seqAssociated.setSelected(acg.isSeqAssociated());
111 annotations = new JComboBox(
112 getAnnotationItems(seqAssociated.isSelected()));
114 threshold.addItem("No Threshold");
115 threshold.addItem("Above Threshold");
116 threshold.addItem("Below Threshold");
118 if (oldcs instanceof AnnotationColourGradient)
120 AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
121 annotations.setSelectedItem(acg.getAnnotation());
122 switch (acg.getAboveThreshold())
124 case AnnotationColourGradient.NO_THRESHOLD:
125 threshold.setSelectedItem("No Threshold");
127 case AnnotationColourGradient.ABOVE_THRESHOLD:
128 threshold.setSelectedItem("Above Threshold");
130 case AnnotationColourGradient.BELOW_THRESHOLD:
131 threshold.setSelectedItem("Below Threshold");
135 "Implementation error: don't know about threshold setting for current AnnotationColourGradient.");
137 thresholdIsMin.setSelected(acg.thresholdIsMinMax);
138 thresholdValue.setText("" + acg.getAnnotationThreshold());
144 } catch (Exception ex)
156 private Vector<String> getAnnotationItems(boolean isSeqAssociated)
158 Vector<String> list = new Vector<String>();
160 int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
161 boolean enableSeqAss = false;
162 for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
164 if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef == null)
175 String label = av.getAlignment().getAlignmentAnnotation()[i].label;
176 if (!list.contains(label))
178 anmap[list.size()] = i;
179 list.addElement(label);
184 if (!isSeqAssociated)
186 anmap[list.size()] = i;
187 list.addElement(label + "_" + (index++));
191 seqAssociated.setEnabled(enableSeqAss);
192 annmap = new int[list.size()];
193 System.arraycopy(anmap, 0, annmap, 0, annmap.length);
197 private void setDefaultMinMax()
199 minColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN",
201 maxColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX",
205 public AnnotationColourChooser()
210 } catch (Exception ex)
212 ex.printStackTrace();
216 private void jbInit() throws Exception
218 minColour.setFont(JvSwingUtils.getLabelFont());
219 minColour.setBorder(BorderFactory.createEtchedBorder());
220 minColour.setPreferredSize(new Dimension(40, 20));
221 minColour.setToolTipText("Minimum Colour");
222 minColour.addMouseListener(new MouseAdapter()
224 public void mousePressed(MouseEvent e)
226 if (minColour.isEnabled())
228 minColour_actionPerformed();
232 maxColour.setFont(JvSwingUtils.getLabelFont());
233 maxColour.setBorder(BorderFactory.createEtchedBorder());
234 maxColour.setPreferredSize(new Dimension(40, 20));
235 maxColour.setToolTipText("Maximum Colour");
236 maxColour.addMouseListener(new MouseAdapter()
238 public void mousePressed(MouseEvent e)
240 if (maxColour.isEnabled())
242 maxColour_actionPerformed();
248 ok.addActionListener(new ActionListener()
250 public void actionPerformed(ActionEvent e)
252 ok_actionPerformed(e);
255 cancel.setOpaque(false);
256 cancel.setText("Cancel");
257 cancel.addActionListener(new ActionListener()
259 public void actionPerformed(ActionEvent e)
261 cancel_actionPerformed(e);
264 defColours.setOpaque(false);
265 defColours.setText("Defaults");
267 .setToolTipText("Reset min and max colours to defaults from user preferences.");
268 defColours.addActionListener(new ActionListener()
272 public void actionPerformed(ActionEvent arg0)
274 resetColours_actionPerformed(arg0);
278 annotations.addActionListener(new ActionListener()
280 public void actionPerformed(ActionEvent e)
282 annotations_actionPerformed(e);
285 threshold.addActionListener(new ActionListener()
287 public void actionPerformed(ActionEvent e)
289 threshold_actionPerformed(e);
292 thresholdValue.addActionListener(new ActionListener()
294 public void actionPerformed(ActionEvent e)
296 thresholdValue_actionPerformed(e);
299 slider.setPaintLabels(false);
300 slider.setPaintTicks(true);
301 slider.setBackground(Color.white);
302 slider.setEnabled(false);
303 slider.setOpaque(false);
304 slider.setPreferredSize(new Dimension(100, 32));
305 thresholdValue.setEnabled(false);
306 thresholdValue.setColumns(7);
307 currentColours.setFont(JvSwingUtils.getLabelFont());
308 currentColours.setOpaque(false);
309 currentColours.setText("Use Original Colours");
310 currentColours.addActionListener(new ActionListener()
312 public void actionPerformed(ActionEvent e)
314 currentColours_actionPerformed(e);
317 thresholdIsMin.setBackground(Color.white);
318 thresholdIsMin.setFont(JvSwingUtils.getLabelFont());
319 thresholdIsMin.setText("Threshold is Min/Max");
320 thresholdIsMin.addActionListener(new ActionListener()
322 public void actionPerformed(ActionEvent actionEvent)
324 thresholdIsMin_actionPerformed(actionEvent);
327 seqAssociated.setBackground(Color.white);
328 seqAssociated.setFont(JvSwingUtils.getLabelFont());
329 seqAssociated.setText("Per-sequence only");
330 seqAssociated.addActionListener(new ActionListener()
334 public void actionPerformed(ActionEvent arg0)
336 seqAssociated_actionPerformed(arg0);
340 this.setLayout(borderLayout1);
341 jPanel2.setLayout(new MigLayout("", "[left][center][right]", "[][][]"));
342 jPanel1.setBackground(Color.white);
343 jPanel2.setBackground(Color.white);
347 jPanel2.add(annotations, "grow, wrap");
348 jPanel2.add(seqAssociated);
349 jPanel2.add(currentColours);
350 JPanel colpanel = new JPanel(new FlowLayout());
351 colpanel.setBackground(Color.white);
352 colpanel.add(minColour);
353 colpanel.add(maxColour);
354 jPanel2.add(colpanel, "wrap");
355 jPanel2.add(threshold);
356 jPanel2.add(defColours, "skip 1, wrap");
357 jPanel2.add(thresholdIsMin);
358 jPanel2.add(slider, "grow");
359 jPanel2.add(thresholdValue, "grow");
360 this.add(jPanel1, java.awt.BorderLayout.SOUTH);
361 this.add(jPanel2, java.awt.BorderLayout.CENTER);
365 protected void seqAssociated_actionPerformed(ActionEvent arg0)
368 String cursel = (String) annotations.getSelectedItem();
369 boolean isvalid = false, isseqs = seqAssociated.isSelected();
370 this.annotations.removeAllItems();
371 for (String anitem : getAnnotationItems(seqAssociated.isSelected()))
373 if (anitem.equals(cursel) || (isseqs && cursel.startsWith(anitem)))
378 this.annotations.addItem(anitem);
383 this.annotations.setSelectedItem(cursel);
387 if (annotations.getItemCount() > 0)
389 annotations.setSelectedIndex(0);
394 protected void resetColours_actionPerformed(ActionEvent arg0)
400 JComboBox annotations;
404 JPanel minColour = new JPanel();
406 JPanel maxColour = new JPanel();
408 JButton defColours = new JButton();
410 JButton ok = new JButton();
412 JButton cancel = new JButton();
414 JPanel jPanel1 = new JPanel();
416 JPanel jPanel2 = new JPanel();
418 BorderLayout borderLayout1 = new BorderLayout();
420 JComboBox threshold = new JComboBox();
422 JSlider slider = new JSlider();
424 JTextField thresholdValue = new JTextField(20);
426 JCheckBox currentColours = new JCheckBox();
428 JCheckBox thresholdIsMin = new JCheckBox();
430 JCheckBox seqAssociated = new JCheckBox();
432 public void minColour_actionPerformed()
434 Color col = JColorChooser.showDialog(this,
435 "Select Colour for Minimum Value", minColour.getBackground());
438 minColour.setBackground(col);
444 public void maxColour_actionPerformed()
446 Color col = JColorChooser.showDialog(this,
447 "Select Colour for Maximum Value", maxColour.getBackground());
450 maxColour.setBackground(col);
458 // Check if combobox is still adjusting
464 currentAnnotation = av.getAlignment().getAlignmentAnnotation()[annmap[annotations
465 .getSelectedIndex()]];
467 int aboveThreshold = -1;
468 if (threshold.getSelectedItem().equals("Above Threshold"))
470 aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
472 else if (threshold.getSelectedItem().equals("Below Threshold"))
474 aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
477 slider.setEnabled(true);
478 thresholdValue.setEnabled(true);
479 thresholdIsMin.setEnabled(true);
481 if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
483 slider.setEnabled(false);
484 thresholdValue.setEnabled(false);
485 thresholdValue.setText("");
486 thresholdIsMin.setEnabled(false);
488 else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
489 && currentAnnotation.threshold == null)
492 .setThreshold(new jalview.datamodel.GraphLine(
493 (currentAnnotation.graphMax - currentAnnotation.graphMin) / 2f,
494 "Threshold", Color.black));
497 if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
500 float range = currentAnnotation.graphMax * 1000
501 - currentAnnotation.graphMin * 1000;
503 slider.setMinimum((int) (currentAnnotation.graphMin * 1000));
504 slider.setMaximum((int) (currentAnnotation.graphMax * 1000));
505 slider.setValue((int) (currentAnnotation.threshold.value * 1000));
506 thresholdValue.setText(currentAnnotation.threshold.value + "");
507 slider.setMajorTickSpacing((int) (range / 10f));
508 slider.setEnabled(true);
509 thresholdValue.setEnabled(true);
513 AnnotationColourGradient acg = null;
514 if (currentColours.isSelected())
516 acg = new AnnotationColourGradient(currentAnnotation,
517 av.getGlobalColourScheme(), aboveThreshold);
521 acg = new AnnotationColourGradient(currentAnnotation,
522 minColour.getBackground(), maxColour.getBackground(),
525 acg.setSeqAssociated(seqAssociated.isSelected());
527 if (currentAnnotation.graphMin == 0f
528 && currentAnnotation.graphMax == 0f)
530 acg.predefinedColours = true;
533 acg.thresholdIsMinMax = thresholdIsMin.isSelected();
535 av.setGlobalColourScheme(acg);
537 if (av.getAlignment().getGroups() != null)
540 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
547 if (currentColours.isSelected())
549 sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
551 ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
557 sg.cs = new AnnotationColourGradient(currentAnnotation,
558 minColour.getBackground(), maxColour.getBackground(),
560 ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
566 ap.alignmentChanged();
567 // ensure all associated views (overviews, structures, etc) are notified of
569 ap.paintAlignment(true);
572 public void ok_actionPerformed(ActionEvent e)
577 frame.setClosed(true);
578 } catch (Exception ex)
583 public void cancel_actionPerformed(ActionEvent e)
586 // ensure all original colouring is propagated to listeners.
587 ap.paintAlignment(true);
590 frame.setClosed(true);
591 } catch (Exception ex)
598 av.setGlobalColourScheme(oldcs);
599 if (av.getAlignment().getGroups() != null)
602 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
604 sg.cs = (ColourSchemeI) oldgroupColours.get(sg);
609 public void thresholdCheck_actionPerformed(ActionEvent e)
614 public void annotations_actionPerformed(ActionEvent e)
619 public void threshold_actionPerformed(ActionEvent e)
624 public void thresholdValue_actionPerformed(ActionEvent e)
628 float f = Float.parseFloat(thresholdValue.getText());
629 slider.setValue((int) (f * 1000));
630 } catch (NumberFormatException ex)
635 public void valueChanged()
637 if (currentColours.isSelected()
638 && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
643 currentAnnotation.threshold.value = (float) slider.getValue() / 1000f;
644 ap.paintAlignment(false);
647 public void currentColours_actionPerformed(ActionEvent e)
649 if (currentColours.isSelected())
654 maxColour.setEnabled(!currentColours.isSelected());
655 minColour.setEnabled(!currentColours.isSelected());
660 public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)