2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ 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.
23 import java.awt.BorderLayout;
24 import java.awt.Color;
25 import java.awt.Dimension;
26 import java.awt.FlowLayout;
27 import java.awt.event.ActionEvent;
28 import java.awt.event.ActionListener;
29 import java.awt.event.MouseAdapter;
30 import java.awt.event.MouseEvent;
31 import java.util.Hashtable;
32 import java.util.Vector;
34 import javax.swing.BorderFactory;
35 import javax.swing.JButton;
36 import javax.swing.JCheckBox;
37 import javax.swing.JComboBox;
38 import javax.swing.JInternalFrame;
39 import javax.swing.JLayeredPane;
40 import javax.swing.JPanel;
42 import jalview.bin.Cache;
43 import jalview.datamodel.AlignmentAnnotation;
44 import jalview.datamodel.Annotation;
45 import jalview.datamodel.GraphLine;
46 import jalview.datamodel.SequenceGroup;
47 import jalview.gui.JalviewColourChooser.ColourChooserListener;
48 import jalview.schemes.AnnotationColourGradient;
49 import jalview.schemes.ColourSchemeI;
50 import jalview.util.MessageManager;
51 import net.miginfocom.swing.MigLayout;
53 @SuppressWarnings("serial")
54 public class AnnotationColourChooser extends AnnotationRowFilter
56 private ColourSchemeI oldcs;
58 private JButton defColours;
60 private Hashtable<SequenceGroup, ColourSchemeI> oldgroupColours;
62 private JCheckBox useOriginalColours = new JCheckBox();
64 JPanel minColour = new JPanel();
66 JPanel maxColour = new JPanel();
68 private JCheckBox thresholdIsMin = new JCheckBox();
70 protected static final int MIN_WIDTH = 500;
72 protected static final int MIN_HEIGHT = 240;
74 public AnnotationColourChooser(AlignViewport av, final AlignmentPanel ap)
79 public AnnotationColourChooser(AlignViewport av, final AlignmentPanel ap,
80 AnnotationColourGradient initSettings)
83 oldcs = av.getGlobalColourScheme();
84 if (av.getAlignment().getGroups() != null)
86 oldgroupColours = new Hashtable<>();
87 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
89 if (sg.getColourScheme() != null)
91 oldgroupColours.put(sg, sg.getColourScheme());
95 frame = new JInternalFrame();
96 frame.setFrameIcon(null);
97 frame.setContentPane(this);
98 frame.setLayer(JLayeredPane.PALETTE_LAYER);
99 Desktop.addInternalFrame(frame,
100 MessageManager.getString("label.colour_by_annotation"), 520,
102 frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
103 addSliderChangeListener();
104 addSliderMouseListeners();
106 if (av.getAlignment().getAlignmentAnnotation() == null)
111 // Always get default shading from preferences.
115 if (oldcs instanceof AnnotationColourGradient && initSettings == null)
118 initialiseFrom((AnnotationColourGradient) oldcs);
122 // use initial colour gradient - if any..
123 initialiseFrom(initSettings);
134 private void initialiseFrom(AnnotationColourGradient acg)
138 useOriginalColours.setSelected(
139 acg.isPredefinedColours() || acg.getBaseColour() != null);
140 if (!acg.isPredefinedColours() && acg.getBaseColour() == null)
142 minColour.setBackground(acg.getMinColour());
143 maxColour.setBackground(acg.getMaxColour());
145 seqAssociated.setSelected(acg.isSeqAssociated());
148 Vector<String> annotItems = getAnnotationItems(
149 seqAssociated.isSelected());
150 annotations = new JComboBox<>(annotItems);
152 populateThresholdComboBox(threshold);
156 String label = getAnnotationMenuLabel(acg.getAnnotation());
157 // TODO: workaround below shouldn't be necessary - there's a bug in
158 // getAnnotationMenuLabel!
159 if (acg.isSeqAssociated())
161 label = acg.getAnnotation().label;
163 annotations.setSelectedItem(label);
164 switch (acg.getAboveThreshold())
166 case AnnotationColourGradient.NO_THRESHOLD:
167 getThreshold().setSelectedIndex(0);
169 case AnnotationColourGradient.ABOVE_THRESHOLD:
170 getThreshold().setSelectedIndex(1);
172 case AnnotationColourGradient.BELOW_THRESHOLD:
173 getThreshold().setSelectedIndex(2);
176 throw new Error(MessageManager.getString(
177 "error.implementation_error_dont_know_about_threshold_setting"));
179 thresholdIsMin.setSelected(acg.isThresholdIsMinMax());
180 thresholdValue.setText(String.valueOf(acg.getAnnotationThreshold()));
185 protected void jbInit()
189 minColour.setFont(JvSwingUtils.getLabelFont());
190 minColour.setBorder(BorderFactory.createEtchedBorder());
191 minColour.setPreferredSize(new Dimension(40, 20));
192 minColour.setToolTipText(MessageManager.getString("label.min_colour"));
193 minColour.addMouseListener(new MouseAdapter()
196 public void mousePressed(MouseEvent e)
198 if (minColour.isEnabled())
200 showColourChooser(minColour, "label.select_colour_minimum_value");
204 maxColour.setFont(JvSwingUtils.getLabelFont());
205 maxColour.setBorder(BorderFactory.createEtchedBorder());
206 maxColour.setPreferredSize(new Dimension(40, 20));
207 maxColour.setToolTipText(MessageManager.getString("label.max_colour"));
208 maxColour.addMouseListener(new MouseAdapter()
211 public void mousePressed(MouseEvent e)
213 if (maxColour.isEnabled())
215 showColourChooser(maxColour, "label.select_colour_maximum_value");
220 defColours = new JButton();
221 defColours.setOpaque(false);
222 defColours.setText(MessageManager.getString("action.set_defaults"));
223 defColours.setToolTipText(MessageManager
224 .getString("label.reset_min_max_colours_to_defaults"));
225 defColours.addActionListener(new ActionListener()
229 public void actionPerformed(ActionEvent arg0)
231 resetColours_actionPerformed();
235 useOriginalColours.setFont(JvSwingUtils.getLabelFont());
236 useOriginalColours.setOpaque(false);
237 useOriginalColours.setText(
238 MessageManager.getString("label.use_original_colours"));
239 useOriginalColours.addActionListener(new ActionListener()
242 public void actionPerformed(ActionEvent e)
244 originalColours_actionPerformed();
247 thresholdIsMin.setBackground(Color.white);
248 thresholdIsMin.setFont(JvSwingUtils.getLabelFont());
250 .setText(MessageManager.getString("label.threshold_minmax"));
251 thresholdIsMin.addActionListener(new ActionListener()
254 public void actionPerformed(ActionEvent actionEvent)
256 thresholdIsMin_actionPerformed();
259 seqAssociated.setBackground(Color.white);
260 seqAssociated.setFont(JvSwingUtils.getLabelFont());
262 .setText(MessageManager.getString("label.per_sequence_only"));
263 seqAssociated.addActionListener(new ActionListener()
267 public void actionPerformed(ActionEvent arg0)
269 seqAssociated_actionPerformed(annotations);
273 this.setLayout(new BorderLayout());
274 JPanel jPanel1 = new JPanel();
275 JPanel jPanel2 = new JPanel();
276 jPanel2.setLayout(new MigLayout("", "[left][center][right]", "[][][]"));
277 jPanel1.setBackground(Color.white);
278 jPanel2.setBackground(Color.white);
282 jPanel2.add(annotations, "grow, wrap");
283 jPanel2.add(seqAssociated);
284 jPanel2.add(useOriginalColours);
285 JPanel colpanel = new JPanel(new FlowLayout());
286 colpanel.setBackground(Color.white);
287 colpanel.add(minColour);
288 colpanel.add(maxColour);
289 jPanel2.add(colpanel, "wrap");
290 jPanel2.add(getThreshold());
291 jPanel2.add(defColours, "skip 1, wrap");
292 jPanel2.add(thresholdIsMin);
293 jPanel2.add(slider, "grow");
294 jPanel2.add(thresholdValue, "grow");
295 this.add(jPanel1, java.awt.BorderLayout.SOUTH);
296 this.add(jPanel2, java.awt.BorderLayout.CENTER);
300 protected void resetColours_actionPerformed()
306 private void setDefaultMinMax()
308 minColour.setBackground(
309 Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN", Color.orange));
310 maxColour.setBackground(
311 Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX", Color.red));
314 protected void showColourChooser(JPanel colourPanel, String titleKey)
316 String ttl = MessageManager.getString(titleKey);
317 ColourChooserListener listener = new ColourChooserListener()
320 public void colourSelected(Color c)
322 colourPanel.setBackground(c);
323 colourPanel.repaint();
327 JalviewColourChooser.showColourChooser(Desktop.getDesktop(), ttl,
328 colourPanel.getBackground(), listener);
334 this.ap.alignFrame.changeColour(oldcs);
335 if (av.getAlignment().getGroups() != null)
338 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
340 sg.setColourScheme(oldgroupColours.get(sg));
346 public void valueChanged(boolean updateAllAnnotation)
348 if (slider.isEnabled())
350 if (useOriginalColours.isSelected() && !(av
351 .getGlobalColourScheme() instanceof AnnotationColourGradient))
355 getCurrentAnnotation().threshold.value = getSliderValue();
356 propagateSeqAssociatedThreshold(updateAllAnnotation,
357 getCurrentAnnotation());
358 ap.paintAlignment(false, false);
362 public void originalColours_actionPerformed()
364 boolean selected = useOriginalColours.isSelected();
369 maxColour.setEnabled(!selected);
370 minColour.setEnabled(!selected);
371 thresholdIsMin.setEnabled(!selected);
376 public void updateView()
378 // Check if combobox is still adjusting
384 int selIndex = annotations.getSelectedIndex();
385 int annIndex = annmap[selIndex];
386 setCurrentAnnotation(
387 av.getAlignment().getAlignmentAnnotation()[annIndex]);
389 int selectedThresholdItem = getSelectedThresholdItem(
390 getThreshold().getSelectedIndex());
392 slider.setEnabled(true);
393 thresholdValue.setEnabled(true);
394 thresholdIsMin.setEnabled(!useOriginalColours.isSelected());
396 final AlignmentAnnotation currentAnnotation = getCurrentAnnotation();
397 if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD)
399 slider.setEnabled(false);
400 thresholdValue.setEnabled(false);
401 thresholdValue.setText("");
402 thresholdIsMin.setEnabled(false);
404 else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD
405 && currentAnnotation.threshold == null)
407 currentAnnotation.setThreshold(new GraphLine(
408 (currentAnnotation.graphMax - currentAnnotation.graphMin)
410 "Threshold", Color.black));
413 if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD)
416 setSliderModel(currentAnnotation.graphMin, currentAnnotation.graphMax,
417 currentAnnotation.threshold.value);
418 slider.setEnabled(true);
420 setThresholdValueText();
421 thresholdValue.setEnabled(true);
424 colorAlignmentContaining(currentAnnotation, selectedThresholdItem);
426 ap.alignmentChanged();
429 protected void colorAlignmentContaining(AlignmentAnnotation currentAnn,
430 int selectedThresholdOption)
433 AnnotationColourGradient acg = null;
434 if (useOriginalColours.isSelected())
436 acg = new AnnotationColourGradient(currentAnn,
437 av.getGlobalColourScheme(), selectedThresholdOption);
441 acg = new AnnotationColourGradient(currentAnn,
442 minColour.getBackground(), maxColour.getBackground(),
443 selectedThresholdOption);
445 acg.setSeqAssociated(seqAssociated.isSelected());
447 if (currentAnn.graphMin == 0f && currentAnn.graphMax == 0f)
449 acg.setPredefinedColours(true);
452 acg.setThresholdIsMinMax(thresholdIsMin.isSelected());
454 this.ap.alignFrame.changeColour(acg);
456 if (av.getAlignment().getGroups() != null)
459 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
465 sg.setColourScheme(acg.getInstance(av, sg));
471 protected void sliderDragReleased()
473 super.sliderDragReleased();
474 ap.paintAlignment(true, true);
478 * construct and display a colourchooser for a given annotation row
482 * @param alignmentAnnotation
484 * - when true, enable per-sequence if alignment annotation is per
487 public static void displayFor(AlignViewport av, AlignmentPanel ap,
488 AlignmentAnnotation alignmentAnnotation, boolean perSeq)
490 ColourSchemeI global = av.getGlobalColourScheme();
491 AnnotationColourGradient newCS = new AnnotationColourGradient(
492 alignmentAnnotation, global,
493 alignmentAnnotation.threshold != null
494 ? AnnotationColourGradient.ABOVE_THRESHOLD
495 : AnnotationColourGradient.NO_THRESHOLD);
496 if (alignmentAnnotation.sequenceRef != null)
498 newCS.setSeqAssociated(perSeq);
500 for (int i = 0; i < alignmentAnnotation.annotations.length; i++)
502 Annotation ann = alignmentAnnotation.annotations[i];
503 if (ann != null && ann.colour != null
504 && !ann.colour.equals(Color.white))
506 newCS.setPredefinedColours(true);
510 AnnotationColourChooser achooser = new AnnotationColourChooser(av, ap,