2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 The Jalview Authors
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
10 * of the License, or (at your option) any later version.
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.
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.
26 import java.awt.event.*;
29 import javax.swing.event.*;
31 import net.miginfocom.swing.MigLayout;
33 import jalview.bin.Cache;
34 import jalview.datamodel.*;
35 import jalview.schemes.*;
36 import jalview.util.MessageManager;
38 import java.awt.Dimension;
40 public class AnnotationColourChooser extends JPanel
50 Hashtable oldgroupColours;
52 jalview.datamodel.AlignmentAnnotation currentAnnotation;
54 boolean adjusting = false;
57 * enabled if the user is dragging the slider - try to keep updates to a
60 boolean sliderDragging = false;
62 public AnnotationColourChooser(AlignViewport av, final AlignmentPanel ap)
64 oldcs = av.getGlobalColourScheme();
65 if (av.getAlignment().getGroups() != null)
67 oldgroupColours = new Hashtable();
68 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
72 oldgroupColours.put(sg, sg.cs);
78 frame = new JInternalFrame();
79 frame.setContentPane(this);
80 frame.setLayer(JLayeredPane.PALETTE_LAYER);
81 Desktop.addInternalFrame(frame,
82 MessageManager.getString("label.colour_by_annotation"), 520,
85 slider.addChangeListener(new ChangeListener()
87 public void stateChanged(ChangeEvent evt)
91 thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
92 valueChanged(!sliderDragging);
96 slider.addMouseListener(new MouseAdapter()
99 public void mousePressed(MouseEvent e)
101 sliderDragging = true;
102 super.mousePressed(e);
106 public void mouseDragged(MouseEvent e)
108 sliderDragging = true;
109 super.mouseDragged(e);
112 public void mouseReleased(MouseEvent evt)
116 sliderDragging = false;
119 ap.paintAlignment(true);
123 if (av.getAlignment().getAlignmentAnnotation() == null)
128 // Always get default shading from preferences.
132 if (oldcs instanceof AnnotationColourGradient)
134 AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
135 currentColours.setSelected(acg.isPredefinedColours()
136 || acg.getBaseColour() != null);
137 if (!acg.isPredefinedColours() && acg.getBaseColour() == null)
139 minColour.setBackground(acg.getMinColour());
140 maxColour.setBackground(acg.getMaxColour());
142 seqAssociated.setSelected(acg.isSeqAssociated());
145 annotations = new JComboBox(
146 getAnnotationItems(seqAssociated.isSelected()));
148 threshold.addItem(MessageManager
149 .getString("label.threshold_feature_no_thereshold"));
150 threshold.addItem(MessageManager
151 .getString("label.threshold_feature_above_thereshold"));
152 threshold.addItem(MessageManager
153 .getString("label.threshold_feature_below_thereshold"));
155 if (oldcs instanceof AnnotationColourGradient)
157 AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
158 annotations.setSelectedItem(acg.getAnnotation());
159 switch (acg.getAboveThreshold())
161 case AnnotationColourGradient.NO_THRESHOLD:
162 threshold.setSelectedIndex(0);
164 case AnnotationColourGradient.ABOVE_THRESHOLD:
165 threshold.setSelectedIndex(1);
167 case AnnotationColourGradient.BELOW_THRESHOLD:
168 threshold.setSelectedIndex(2);
171 throw new Error(MessageManager.getString("error.implementation_error_dont_know_about_thereshold_setting"));
173 thresholdIsMin.setSelected(acg.thresholdIsMinMax);
174 thresholdValue.setText("" + acg.getAnnotationThreshold());
180 } catch (Exception ex)
192 private Vector<String> getAnnotationItems(boolean isSeqAssociated)
194 Vector<String> list = new Vector<String>();
196 int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
197 boolean enableSeqAss = false;
198 for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
200 if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef == null)
211 String label = av.getAlignment().getAlignmentAnnotation()[i].label;
212 if (!list.contains(label))
214 anmap[list.size()] = i;
215 list.addElement(label);
220 if (!isSeqAssociated)
222 anmap[list.size()] = i;
223 list.addElement(label + "_" + (index++));
227 seqAssociated.setEnabled(enableSeqAss);
228 annmap = new int[list.size()];
229 System.arraycopy(anmap, 0, annmap, 0, annmap.length);
233 private void setDefaultMinMax()
235 minColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN",
237 maxColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX",
241 public AnnotationColourChooser()
246 } catch (Exception ex)
248 ex.printStackTrace();
252 private void jbInit() throws Exception
254 minColour.setFont(JvSwingUtils.getLabelFont());
255 minColour.setBorder(BorderFactory.createEtchedBorder());
256 minColour.setPreferredSize(new Dimension(40, 20));
257 minColour.setToolTipText(MessageManager.getString("label.min_colour"));
258 minColour.addMouseListener(new MouseAdapter()
260 public void mousePressed(MouseEvent e)
262 if (minColour.isEnabled())
264 minColour_actionPerformed();
268 maxColour.setFont(JvSwingUtils.getLabelFont());
269 maxColour.setBorder(BorderFactory.createEtchedBorder());
270 maxColour.setPreferredSize(new Dimension(40, 20));
271 maxColour.setToolTipText(MessageManager.getString("label.max_colour"));
272 maxColour.addMouseListener(new MouseAdapter()
274 public void mousePressed(MouseEvent e)
276 if (maxColour.isEnabled())
278 maxColour_actionPerformed();
283 ok.setText(MessageManager.getString("action.ok"));
284 ok.addActionListener(new ActionListener()
286 public void actionPerformed(ActionEvent e)
288 ok_actionPerformed(e);
291 cancel.setOpaque(false);
292 cancel.setText(MessageManager.getString("action.cancel"));
293 cancel.addActionListener(new ActionListener()
295 public void actionPerformed(ActionEvent e)
297 cancel_actionPerformed(e);
300 defColours.setOpaque(false);
301 defColours.setText(MessageManager.getString("action.set_defaults"));
302 defColours.setToolTipText(MessageManager
303 .getString("label.reset_min_max_colours_to_defaults"));
304 defColours.addActionListener(new ActionListener()
308 public void actionPerformed(ActionEvent arg0)
310 resetColours_actionPerformed(arg0);
314 annotations.addActionListener(new ActionListener()
316 public void actionPerformed(ActionEvent e)
318 annotations_actionPerformed(e);
321 threshold.addActionListener(new ActionListener()
323 public void actionPerformed(ActionEvent e)
325 threshold_actionPerformed(e);
328 thresholdValue.addActionListener(new ActionListener()
330 public void actionPerformed(ActionEvent e)
332 thresholdValue_actionPerformed(e);
335 slider.setPaintLabels(false);
336 slider.setPaintTicks(true);
337 slider.setBackground(Color.white);
338 slider.setEnabled(false);
339 slider.setOpaque(false);
340 slider.setPreferredSize(new Dimension(100, 32));
341 thresholdValue.setEnabled(false);
342 thresholdValue.setColumns(7);
343 currentColours.setFont(JvSwingUtils.getLabelFont());
344 currentColours.setOpaque(false);
345 currentColours.setText(MessageManager
346 .getString("label.use_original_colours"));
347 currentColours.addActionListener(new ActionListener()
349 public void actionPerformed(ActionEvent e)
351 currentColours_actionPerformed(e);
354 thresholdIsMin.setBackground(Color.white);
355 thresholdIsMin.setFont(JvSwingUtils.getLabelFont());
356 thresholdIsMin.setText(MessageManager
357 .getString("label.threshold_minmax"));
358 thresholdIsMin.addActionListener(new ActionListener()
360 public void actionPerformed(ActionEvent actionEvent)
362 thresholdIsMin_actionPerformed(actionEvent);
365 seqAssociated.setBackground(Color.white);
366 seqAssociated.setFont(JvSwingUtils.getLabelFont());
367 seqAssociated.setText(MessageManager
368 .getString("label.per_sequence_only"));
369 seqAssociated.addActionListener(new ActionListener()
373 public void actionPerformed(ActionEvent arg0)
375 seqAssociated_actionPerformed(arg0);
379 this.setLayout(borderLayout1);
380 jPanel2.setLayout(new MigLayout("", "[left][center][right]", "[][][]"));
381 jPanel1.setBackground(Color.white);
382 jPanel2.setBackground(Color.white);
386 jPanel2.add(annotations, "grow, wrap");
387 jPanel2.add(seqAssociated);
388 jPanel2.add(currentColours);
389 JPanel colpanel = new JPanel(new FlowLayout());
390 colpanel.setBackground(Color.white);
391 colpanel.add(minColour);
392 colpanel.add(maxColour);
393 jPanel2.add(colpanel, "wrap");
394 jPanel2.add(threshold);
395 jPanel2.add(defColours, "skip 1, wrap");
396 jPanel2.add(thresholdIsMin);
397 jPanel2.add(slider, "grow");
398 jPanel2.add(thresholdValue, "grow");
399 this.add(jPanel1, java.awt.BorderLayout.SOUTH);
400 this.add(jPanel2, java.awt.BorderLayout.CENTER);
404 protected void seqAssociated_actionPerformed(ActionEvent arg0)
407 String cursel = (String) annotations.getSelectedItem();
408 boolean isvalid = false, isseqs = seqAssociated.isSelected();
409 this.annotations.removeAllItems();
410 for (String anitem : getAnnotationItems(seqAssociated.isSelected()))
412 if (anitem.equals(cursel) || (isseqs && cursel.startsWith(anitem)))
417 this.annotations.addItem(anitem);
422 this.annotations.setSelectedItem(cursel);
426 if (annotations.getItemCount() > 0)
428 annotations.setSelectedIndex(0);
433 protected void resetColours_actionPerformed(ActionEvent arg0)
439 JComboBox annotations;
443 JPanel minColour = new JPanel();
445 JPanel maxColour = new JPanel();
447 JButton defColours = new JButton();
449 JButton ok = new JButton();
451 JButton cancel = new JButton();
453 JPanel jPanel1 = new JPanel();
455 JPanel jPanel2 = new JPanel();
457 BorderLayout borderLayout1 = new BorderLayout();
459 JComboBox threshold = new JComboBox();
461 JSlider slider = new JSlider();
463 JTextField thresholdValue = new JTextField(20);
465 JCheckBox currentColours = new JCheckBox();
467 JCheckBox thresholdIsMin = new JCheckBox();
469 JCheckBox seqAssociated = new JCheckBox();
471 public void minColour_actionPerformed()
473 Color col = JColorChooser.showDialog(this,
474 MessageManager.getString("label.select_colour_minimum_value"), minColour.getBackground());
477 minColour.setBackground(col);
483 public void maxColour_actionPerformed()
485 Color col = JColorChooser.showDialog(this,
486 MessageManager.getString("label.select_colour_maximum_value"), maxColour.getBackground());
489 maxColour.setBackground(col);
497 // Check if combobox is still adjusting
503 currentAnnotation = av.getAlignment().getAlignmentAnnotation()[annmap[annotations
504 .getSelectedIndex()]];
506 int aboveThreshold = -1;
507 if (threshold.getSelectedIndex() == 1)
509 aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
511 else if (threshold.getSelectedIndex() == 2)
513 aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
516 slider.setEnabled(true);
517 thresholdValue.setEnabled(true);
518 thresholdIsMin.setEnabled(true);
520 if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
522 slider.setEnabled(false);
523 thresholdValue.setEnabled(false);
524 thresholdValue.setText("");
525 thresholdIsMin.setEnabled(false);
527 else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
528 && currentAnnotation.threshold == null)
531 .setThreshold(new jalview.datamodel.GraphLine(
532 (currentAnnotation.graphMax - currentAnnotation.graphMin) / 2f,
533 "Threshold", Color.black));
536 if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
539 float range = currentAnnotation.graphMax * 1000
540 - currentAnnotation.graphMin * 1000;
542 slider.setMinimum((int) (currentAnnotation.graphMin * 1000));
543 slider.setMaximum((int) (currentAnnotation.graphMax * 1000));
544 slider.setValue((int) (currentAnnotation.threshold.value * 1000));
545 thresholdValue.setText(currentAnnotation.threshold.value + "");
546 slider.setMajorTickSpacing((int) (range / 10f));
547 slider.setEnabled(true);
548 thresholdValue.setEnabled(true);
552 AnnotationColourGradient acg = null;
553 if (currentColours.isSelected())
555 acg = new AnnotationColourGradient(currentAnnotation,
556 av.getGlobalColourScheme(), aboveThreshold);
560 acg = new AnnotationColourGradient(currentAnnotation,
561 minColour.getBackground(), maxColour.getBackground(),
564 acg.setSeqAssociated(seqAssociated.isSelected());
566 if (currentAnnotation.graphMin == 0f
567 && currentAnnotation.graphMax == 0f)
569 acg.setPredefinedColours(true);
572 acg.thresholdIsMinMax = thresholdIsMin.isSelected();
574 av.setGlobalColourScheme(acg);
576 if (av.getAlignment().getGroups() != null)
579 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
586 if (currentColours.isSelected())
588 sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
590 ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
596 sg.cs = new AnnotationColourGradient(currentAnnotation,
597 minColour.getBackground(), maxColour.getBackground(),
599 ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
605 ap.alignmentChanged();
606 // ensure all associated views (overviews, structures, etc) are notified of
608 ap.paintAlignment(true);
611 public void ok_actionPerformed(ActionEvent e)
616 frame.setClosed(true);
617 } catch (Exception ex)
622 public void cancel_actionPerformed(ActionEvent e)
625 // ensure all original colouring is propagated to listeners.
626 ap.paintAlignment(true);
629 frame.setClosed(true);
630 } catch (Exception ex)
637 av.setGlobalColourScheme(oldcs);
638 if (av.getAlignment().getGroups() != null)
641 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
643 sg.cs = (ColourSchemeI) oldgroupColours.get(sg);
648 public void thresholdCheck_actionPerformed(ActionEvent e)
653 public void annotations_actionPerformed(ActionEvent e)
658 public void threshold_actionPerformed(ActionEvent e)
663 public void thresholdValue_actionPerformed(ActionEvent e)
667 float f = Float.parseFloat(thresholdValue.getText());
668 slider.setValue((int) (f * 1000));
669 } catch (NumberFormatException ex)
674 public void valueChanged(boolean updateAllAnnotation)
676 if (currentColours.isSelected()
677 && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
681 currentAnnotation.threshold.value = (float) slider.getValue() / 1000f;
682 propagateSeqAssociatedThreshold(updateAllAnnotation);
683 ap.paintAlignment(false);
686 private void propagateSeqAssociatedThreshold(boolean allAnnotation)
688 if (currentAnnotation.sequenceRef == null
689 || currentAnnotation.threshold == null)
693 // TODO: JAL-1327 only update visible annotation thresholds if allAnnotation
694 // is false, since we only need to provide a quick visual indicator
696 float thr = currentAnnotation.threshold.value;
697 for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
699 AlignmentAnnotation aa = av.getAlignment().getAlignmentAnnotation()[i];
700 if (aa.label.equals(currentAnnotation.label))
702 aa.threshold.value = thr;
707 public void currentColours_actionPerformed(ActionEvent e)
709 if (currentColours.isSelected())
714 maxColour.setEnabled(!currentColours.isSelected());
715 minColour.setEnabled(!currentColours.isSelected());
720 public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)