JAL-2416 allow space in score matrix name
[jalview.git] / src / jalview / gui / UserDefinedColours.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.gui;
22
23 import jalview.api.structures.JalviewStructureDisplayI;
24 import jalview.bin.Cache;
25 import jalview.datamodel.SequenceGroup;
26 import jalview.io.JalviewFileChooser;
27 import jalview.io.JalviewFileView;
28 import jalview.jbgui.GUserDefinedColours;
29 import jalview.schemabinding.version2.Colour;
30 import jalview.schemabinding.version2.JalviewUserColours;
31 import jalview.schemes.ColourSchemeI;
32 import jalview.schemes.ColourSchemes;
33 import jalview.schemes.ResidueProperties;
34 import jalview.schemes.UserColourScheme;
35 import jalview.util.ColorUtils;
36 import jalview.util.Format;
37 import jalview.util.MessageManager;
38
39 import java.awt.Color;
40 import java.awt.Font;
41 import java.awt.Insets;
42 import java.awt.event.ActionEvent;
43 import java.awt.event.MouseAdapter;
44 import java.awt.event.MouseEvent;
45 import java.io.File;
46 import java.io.FileOutputStream;
47 import java.io.OutputStreamWriter;
48 import java.io.PrintWriter;
49 import java.util.ArrayList;
50 import java.util.List;
51
52 import javax.swing.JButton;
53 import javax.swing.JInternalFrame;
54 import javax.swing.event.ChangeEvent;
55 import javax.swing.event.ChangeListener;
56
57 /**
58  * This panel allows the user to assign colours to Amino Acid residue codes, and
59  * save the colour scheme.
60  * 
61  * @author Andrew Waterhouse
62  * @author Mungo Carstairs
63  */
64 public class UserDefinedColours extends GUserDefinedColours implements
65         ChangeListener
66 {
67   private static final Font VERDANA_BOLD_10 = new Font("Verdana",
68           Font.BOLD, 10);
69
70   public static final String USER_DEFINED_COLOURS = "USER_DEFINED_COLOURS";
71
72   private static final String LAST_DIRECTORY = "LAST_DIRECTORY";
73
74   private static final int MY_FRAME_HEIGHT = 420;
75
76   private static final int MY_FRAME_WIDTH = 810;
77
78   private static final int MY_FRAME_WIDTH_CASE_SENSITIVE = 970;
79
80   AlignmentPanel ap;
81
82   SequenceGroup seqGroup;
83
84   List<JButton> selectedButtons;
85
86   ColourSchemeI oldColourScheme;
87
88   JInternalFrame frame;
89
90   JalviewStructureDisplayI structureViewer;
91
92   List<JButton> upperCaseButtons;
93
94   List<JButton> lowerCaseButtons;
95
96   /**
97    * Creates a new UserDefinedColours object.
98    * 
99    * @param ap
100    * @param sg
101    */
102   public UserDefinedColours(AlignmentPanel ap, SequenceGroup sg)
103   {
104     this();
105
106     lcaseColour.setEnabled(false);
107
108     this.ap = ap;
109     seqGroup = sg;
110
111     if (seqGroup != null)
112     {
113       oldColourScheme = seqGroup.getColourScheme();
114     }
115     else
116     {
117       oldColourScheme = ap.av.getGlobalColourScheme();
118     }
119
120     if (oldColourScheme instanceof UserColourScheme)
121     {
122       schemeName.setText(oldColourScheme.getSchemeName());
123       if (((UserColourScheme) oldColourScheme).getLowerCaseColours() != null)
124       {
125         caseSensitive.setSelected(true);
126         lcaseColour.setEnabled(true);
127         resetButtonPanel(true);
128       }
129       else
130       {
131         resetButtonPanel(false);
132       }
133     }
134     else
135     {
136       resetButtonPanel(false);
137     }
138
139     showFrame();
140   }
141
142   public UserDefinedColours(JalviewStructureDisplayI viewer,
143           ColourSchemeI oldcs)
144   {
145     this();
146     this.structureViewer = viewer;
147
148     colorChooser.getSelectionModel().addChangeListener(this);
149
150     oldColourScheme = oldcs;
151
152     if (oldColourScheme instanceof UserColourScheme)
153     {
154       schemeName.setText(((UserColourScheme) oldColourScheme)
155               .getSchemeName());
156     }
157
158     resetButtonPanel(false);
159
160     showFrame();
161
162   }
163
164   public UserDefinedColours()
165   {
166     super();
167     selectedButtons = new ArrayList<JButton>();
168   }
169
170   void showFrame()
171   {
172     colorChooser.getSelectionModel().addChangeListener(this);
173     frame = new JInternalFrame();
174     frame.setContentPane(this);
175     Desktop.addInternalFrame(frame,
176             MessageManager.getString("label.user_defined_colours"),
177             MY_FRAME_WIDTH, MY_FRAME_HEIGHT, true);
178
179     if (seqGroup != null)
180     {
181       frame.setTitle(frame.getTitle() + " (" + seqGroup.getName() + ")");
182     }
183   }
184
185   /**
186    * Rebuilds the panel with coloured buttons for residues. If not case
187    * sensitive colours, show 3-letter amino acid code as button text. If case
188    * sensitive, just show the single letter code, in order to make space for the
189    * additional buttons.
190    * 
191    * @param isCaseSensitive
192    */
193   void resetButtonPanel(boolean isCaseSensitive)
194   {
195     buttonPanel.removeAll();
196
197     if (upperCaseButtons == null)
198     {
199       upperCaseButtons = new ArrayList<JButton>();
200     }
201
202     for (int i = 0; i < 20; i++)
203     {
204       String label = isCaseSensitive ? ResidueProperties.aa[i]
205               : ResidueProperties.aa2Triplet.get(ResidueProperties.aa[i])
206                       .toString();
207       JButton button = makeButton(label, ResidueProperties.aa[i],
208               upperCaseButtons, i);
209       buttonPanel.add(button);
210     }
211
212     buttonPanel.add(makeButton("B", "B", upperCaseButtons, 20));
213     buttonPanel.add(makeButton("Z", "Z", upperCaseButtons, 21));
214     buttonPanel.add(makeButton("X", "X", upperCaseButtons, 22));
215     buttonPanel.add(makeButton("Gap", "-", upperCaseButtons, 23));
216
217     if (!isCaseSensitive)
218     {
219       gridLayout.setRows(6);
220       gridLayout.setColumns(4);
221     }
222     else
223     {
224       gridLayout.setRows(7);
225       int cols = 7;
226       gridLayout.setColumns(cols + 1);
227
228       if (lowerCaseButtons == null)
229       {
230         lowerCaseButtons = new ArrayList<JButton>();
231       }
232
233       for (int i = 0; i < 20; i++)
234       {
235         int row = i / cols + 1;
236         int index = (row * cols) + i;
237         JButton button = makeButton(ResidueProperties.aa[i].toLowerCase(),
238                 ResidueProperties.aa[i].toLowerCase(), lowerCaseButtons, i);
239
240         buttonPanel.add(button, index);
241       }
242     }
243
244     if (isCaseSensitive)
245     {
246       buttonPanel.add(makeButton("b", "b", lowerCaseButtons, 20));
247       buttonPanel.add(makeButton("z", "z", lowerCaseButtons, 21));
248       buttonPanel.add(makeButton("x", "x", lowerCaseButtons, 22));
249     }
250
251     // JAL-1360 widen the frame dynamically to accommodate case-sensitive AA
252     // codes
253     if (this.frame != null)
254     {
255       int newWidth = isCaseSensitive ? MY_FRAME_WIDTH_CASE_SENSITIVE
256               : MY_FRAME_WIDTH;
257       this.frame.setSize(newWidth, this.frame.getHeight());
258     }
259
260     buttonPanel.validate();
261     validate();
262   }
263
264   /**
265    * ChangeListener handler for when a colour is picked in the colour chooser.
266    * The action is to apply the colour to all selected buttons as their
267    * background colour. Foreground colour (text) is set to a lighter shade in
268    * order to highlight which buttons are selected. If 'Lower Case Colour' is
269    * active, then the colour is applied to all lower case buttons (as well as
270    * the Lower Case Colour button itself).
271    * 
272    * @param evt
273    */
274   @Override
275   public void stateChanged(ChangeEvent evt)
276   {
277     JButton button = null;
278     final Color newColour = colorChooser.getColor();
279     for (int i = 0; i < selectedButtons.size(); i++)
280     {
281       button = selectedButtons.get(i);
282       button.setBackground(newColour);
283       button.setForeground(ColorUtils.brighterThan(newColour));
284     }
285     if (lcaseColour.isSelected())
286     {
287       for (int i = 0; i < lowerCaseButtons.size(); i++)
288       {
289         button = lowerCaseButtons.get(i);
290         button.setBackground(newColour);
291         button.setForeground(ColorUtils.brighterThan(button.getBackground()));
292       }
293     }
294   }
295
296   /**
297    * Performs actions when a residue button is clicked. This manages the button
298    * selection set (highlighted by brighter foreground text).
299    * <p>
300    * On select button(s) with Ctrl/click or Shift/click: set button foreground
301    * text to brighter than background.
302    * <p>
303    * On unselect button(s) with Ctrl/click on selected, or click to release
304    * current selection: reset foreground text to darker than background.
305    * <p>
306    * Simple click: clear selection (resetting foreground to darker); set clicked
307    * button foreground to brighter
308    * <p>
309    * Finally, synchronize the colour chooser to the colour of the first button
310    * in the selected set.
311    * 
312    * @param e
313    */
314   public void colourButtonPressed(MouseEvent e)
315   {
316     JButton pressed = (JButton) e.getSource();
317
318     if (e.isShiftDown())
319     {
320       JButton start, end = (JButton) e.getSource();
321       if (selectedButtons.size() > 0)
322       {
323         start = selectedButtons.get(selectedButtons.size() - 1);
324       }
325       else
326       {
327         start = (JButton) e.getSource();
328       }
329
330       int startIndex = 0, endIndex = 0;
331       for (int b = 0; b < buttonPanel.getComponentCount(); b++)
332       {
333         if (buttonPanel.getComponent(b) == start)
334         {
335           startIndex = b;
336         }
337         if (buttonPanel.getComponent(b) == end)
338         {
339           endIndex = b;
340         }
341       }
342
343       if (startIndex > endIndex)
344       {
345         int temp = startIndex;
346         startIndex = endIndex;
347         endIndex = temp;
348       }
349
350       for (int b = startIndex; b <= endIndex; b++)
351       {
352         JButton button = (JButton) buttonPanel.getComponent(b);
353         if (!selectedButtons.contains(button))
354         {
355           button.setForeground(ColorUtils.brighterThan(button
356                   .getBackground()));
357           selectedButtons.add(button);
358         }
359       }
360     }
361     else if (!e.isControlDown())
362     {
363       for (int b = 0; b < selectedButtons.size(); b++)
364       {
365         JButton button = selectedButtons.get(b);
366         button.setForeground(ColorUtils.darkerThan(button.getBackground()));
367       }
368       selectedButtons.clear();
369       pressed.setForeground(ColorUtils.brighterThan(pressed.getBackground()));
370       selectedButtons.add(pressed);
371
372     }
373     else if (e.isControlDown())
374     {
375       if (selectedButtons.contains(pressed))
376       {
377         pressed.setForeground(ColorUtils.darkerThan(pressed.getBackground()));
378         selectedButtons.remove(pressed);
379       }
380       else
381       {
382         pressed.setForeground(ColorUtils.brighterThan(pressed
383                 .getBackground()));
384         selectedButtons.add(pressed);
385       }
386     }
387
388     if (selectedButtons.size() > 0)
389     {
390       colorChooser.setColor((selectedButtons.get(0)).getBackground());
391     }
392   }
393
394   /**
395    * A helper method to update or make a colour button, whose background colour
396    * is the associated colour, and text colour a darker shade of the same. If
397    * the button is already in the list, then its text and margins are updated,
398    * if not then it is created and added. This method supports toggling between
399    * case-sensitive and case-insensitive button panels. The case-sensitive
400    * version has abbreviated button text in order to fit in more buttons.
401    * 
402    * @param label
403    * @param residue
404    * @param the
405    *          list of buttons
406    * @param buttonIndex
407    *          the button's position in the list
408    */
409   JButton makeButton(String label, String residue, List<JButton> buttons,
410           int buttonIndex)
411   {
412     final JButton button;
413     Color col;
414
415     if (buttonIndex < buttons.size())
416     {
417       button = buttons.get(buttonIndex);
418       col = button.getBackground();
419     }
420     else
421     {
422       button = new JButton();
423       button.addMouseListener(new MouseAdapter()
424       {
425         @Override
426         public void mouseClicked(MouseEvent e)
427         {
428           colourButtonPressed(e);
429         }
430       });
431
432       buttons.add(button);
433
434       /*
435        * make initial button colour that of the current colour scheme,
436        * if it is a simple per-residue colouring, else white
437        */
438       col = Color.white;
439       if (oldColourScheme != null && oldColourScheme.isSimple())
440       {
441         col = oldColourScheme.findColour(residue.charAt(0), 0, null, null,
442                 0f);
443       }
444     }
445
446     if (caseSensitive.isSelected())
447     {
448       button.setMargin(new Insets(2, 2, 2, 2));
449     }
450     else
451     {
452       button.setMargin(new Insets(2, 14, 2, 14));
453     }
454
455     button.setOpaque(true); // required for the next line to have effect
456     button.setBackground(col);
457     button.setText(label);
458     button.setForeground(ColorUtils.darkerThan(col));
459     button.setFont(VERDANA_BOLD_10);
460
461     return button;
462   }
463
464   /**
465    * On 'OK', check that at least one colour has been assigned to a residue (and
466    * if not issue a warning), and apply the chosen colour scheme and close the
467    * panel.
468    */
469   @Override
470   protected void okButton_actionPerformed()
471   {
472     if (isNoSelectionMade())
473     {
474       JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
475               .getString("label.no_colour_selection_in_scheme"),
476               MessageManager.getString("label.no_colour_selection_warn"),
477               JvOptionPane.WARNING_MESSAGE);
478     }
479     else
480     {
481       applyButton_actionPerformed();
482
483       try
484       {
485         frame.setClosed(true);
486       } catch (Exception ex)
487       {
488       }
489     }
490   }
491
492   /**
493    * Returns true if the user has not made any colour selection (including if
494    * 'case-sensitive' selected and no lower-case colour chosen).
495    * 
496    * @return
497    */
498   protected boolean isNoSelectionMade()
499   {
500     final boolean noUpperCaseSelected = upperCaseButtons == null
501             || upperCaseButtons.isEmpty();
502     final boolean noLowerCaseSelected = caseSensitive.isSelected()
503             && (lowerCaseButtons == null || lowerCaseButtons.isEmpty());
504     final boolean noSelectionMade = noUpperCaseSelected
505             || noLowerCaseSelected;
506     return noSelectionMade;
507   }
508
509   /**
510    * Applies the current colour scheme to the alignment, sequence group or
511    * structure view.
512    */
513   @Override
514   protected void applyButton_actionPerformed()
515   {
516     if (isNoSelectionMade())
517     {
518       JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
519               .getString("label.no_colour_selection_in_scheme"),
520               MessageManager.getString("label.no_colour_selection_warn"),
521               JvOptionPane.WARNING_MESSAGE);
522
523     }
524     UserColourScheme ucs = getSchemeFromButtons();
525
526     if (seqGroup != null)
527     {
528       seqGroup.setColourScheme(ucs);
529       ap.paintAlignment(true);
530     }
531     else if (ap != null)
532     {
533       ap.alignFrame.changeColour(ucs);
534     }
535     else if (structureViewer != null)
536     {
537       structureViewer.setJalviewColourScheme(ucs);
538     }
539   }
540
541   UserColourScheme getSchemeFromButtons()
542   {
543
544     Color[] newColours = new Color[24];
545
546     int length = upperCaseButtons.size();
547     if (length < 24)
548     {
549       int i = 0;
550       for (JButton btn : upperCaseButtons)
551       {
552         newColours[i] = btn.getBackground();
553         i++;
554       }
555     }
556     else
557     {
558       for (int i = 0; i < 24; i++)
559       {
560         JButton button = upperCaseButtons.get(i);
561         newColours[i] = button.getBackground();
562       }
563     }
564
565     UserColourScheme ucs = new UserColourScheme(newColours);
566     ucs.setName(schemeName.getText());
567
568     if (caseSensitive.isSelected())
569     {
570       newColours = new Color[23];
571       length = lowerCaseButtons.size();
572       if (length < 23)
573       {
574         int i = 0;
575         for (JButton btn : lowerCaseButtons)
576         {
577           newColours[i] = btn.getBackground();
578           i++;
579         }
580       }
581       else
582       {
583         for (int i = 0; i < 23; i++)
584         {
585           JButton button = lowerCaseButtons.get(i);
586           newColours[i] = button.getBackground();
587         }
588       }
589       ucs.setLowerCaseColours(newColours);
590     }
591
592     // if (ap != null)
593     // {
594     // ucs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
595     // }
596
597     return ucs;
598   }
599
600   /**
601    * DOCUMENT ME!
602    * 
603    * @param e
604    *          DOCUMENT ME!
605    */
606   @Override
607   protected void loadbutton_actionPerformed(ActionEvent e)
608   {
609     upperCaseButtons = new ArrayList<JButton>();
610     lowerCaseButtons = new ArrayList<JButton>();
611
612     JalviewFileChooser chooser = new JalviewFileChooser("jc",
613             "Jalview User Colours");
614     chooser.setFileView(new JalviewFileView());
615     chooser.setDialogTitle(MessageManager
616             .getString("label.load_colour_scheme"));
617     chooser.setToolTipText(MessageManager.getString("action.load"));
618
619     int value = chooser.showOpenDialog(this);
620
621     if (value != JalviewFileChooser.APPROVE_OPTION)
622     {
623       return;
624     }
625     File choice = chooser.getSelectedFile();
626     Cache.setProperty(LAST_DIRECTORY, choice.getParent());
627
628     UserColourScheme ucs = ColourSchemes.loadColourScheme(choice
629             .getAbsolutePath());
630     Color[] colors = ucs.getColours();
631     schemeName.setText(ucs.getSchemeName());
632
633     if (ucs.getLowerCaseColours() != null)
634     {
635       caseSensitive.setSelected(true);
636       lcaseColour.setEnabled(true);
637       resetButtonPanel(true);
638       for (int i = 0; i < lowerCaseButtons.size(); i++)
639       {
640         JButton button = lowerCaseButtons.get(i);
641         button.setBackground(ucs.getLowerCaseColours()[i]);
642       }
643     }
644     else
645     {
646       caseSensitive.setSelected(false);
647       lcaseColour.setEnabled(false);
648       resetButtonPanel(false);
649     }
650
651     for (int i = 0; i < upperCaseButtons.size(); i++)
652     {
653       JButton button = upperCaseButtons.get(i);
654       button.setBackground(colors[i]);
655     }
656
657     addNewColourScheme(choice.getPath());
658   }
659
660   /**
661    * Loads the user-defined colour scheme from the first file listed in property
662    * "USER_DEFINED_COLOURS". If this fails, returns an all-white colour scheme.
663    * 
664    * @return
665    */
666   public static UserColourScheme loadDefaultColours()
667   {
668     UserColourScheme ret = null;
669
670     String colours = Cache.getProperty(USER_DEFINED_COLOURS);
671     if (colours != null)
672     {
673       if (colours.indexOf("|") > -1)
674       {
675         colours = colours.substring(0, colours.indexOf("|"));
676       }
677       ret = ColourSchemes.loadColourScheme(colours);
678     }
679
680     if (ret == null)
681     {
682       ret = new UserColourScheme("white");
683     }
684
685     return ret;
686   }
687
688   /**
689    * DOCUMENT ME!
690    * 
691    * @param e
692    *          DOCUMENT ME!
693    */
694   @Override
695   protected void savebutton_actionPerformed(ActionEvent e)
696   {
697     String name = schemeName.getText().trim();
698     if (name.length() < 1)
699     {
700       JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
701               .getString("label.user_colour_scheme_must_have_name"),
702               MessageManager.getString("label.no_name_colour_scheme"),
703               JvOptionPane.WARNING_MESSAGE);
704       return;
705     }
706
707     if (ColourSchemes.getInstance().nameExists(name))
708     {
709       int reply = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
710               MessageManager.formatMessage(
711                       "label.colour_scheme_exists_overwrite", new Object[] {
712                           name, name }),
713               MessageManager.getString("label.duplicate_scheme_name"),
714               JvOptionPane.YES_NO_OPTION);
715       if (reply != JvOptionPane.YES_OPTION)
716       {
717         return;
718       }
719       ColourSchemes.getInstance().removeColourScheme(name);
720     }
721     JalviewFileChooser chooser = new JalviewFileChooser("jc",
722             "Jalview User Colours");
723
724     JalviewFileView fileView = new JalviewFileView();
725     chooser.setFileView(fileView);
726     chooser.setDialogTitle(MessageManager
727             .getString("label.save_colour_scheme"));
728     chooser.setToolTipText(MessageManager.getString("action.save"));
729
730     int value = chooser.showSaveDialog(this);
731
732     if (value == JalviewFileChooser.APPROVE_OPTION)
733     {
734       File file = chooser.getSelectedFile();
735       addNewColourScheme(file.getPath());
736       saveToFile(file);
737     }
738   }
739
740   /**
741    * Adds the current colour scheme to the Jalview properties file so it is
742    * loaded on next startup, and updates the Colour menu in the parent
743    * AlignFrame (if there is one). Note this action does not including applying
744    * the colour scheme.
745    * 
746    * @param filePath
747    */
748   protected void addNewColourScheme(String filePath)
749   {
750     /*
751      * update the delimited list of user defined colour files in
752      * Jalview property USER_DEFINED_COLOURS
753      */
754     String defaultColours = Cache
755             .getDefault(USER_DEFINED_COLOURS, filePath);
756     if (defaultColours.indexOf(filePath) == -1)
757     {
758       if (defaultColours.length() > 0)
759       {
760         defaultColours = defaultColours.concat("|");
761       }
762       defaultColours = defaultColours.concat(filePath);
763     }
764     Cache.setProperty(USER_DEFINED_COLOURS, defaultColours);
765
766     /*
767      * construct and register the colour scheme
768      */
769     UserColourScheme ucs = getSchemeFromButtons();
770     ColourSchemes.getInstance().registerColourScheme(ucs);
771
772     /*
773      * update the Colour menu items
774      */
775     if (ap != null)
776     {
777       ap.alignFrame.buildColourMenu();
778     }
779   }
780
781   /**
782    * Saves the colour scheme to file in XML format
783    * 
784    * @param path
785    */
786   protected void saveToFile(File toFile)
787   {
788     /*
789      * build a Java model of colour scheme as XML, and 
790      * marshal to file
791      */
792     JalviewUserColours ucs = new JalviewUserColours();
793     ucs.setSchemeName(schemeName.getText());
794     try
795     {
796       PrintWriter out = new PrintWriter(new OutputStreamWriter(
797               new FileOutputStream(toFile), "UTF-8"));
798
799       for (int i = 0; i < buttonPanel.getComponentCount(); i++)
800       {
801         JButton button = (JButton) buttonPanel.getComponent(i);
802         Colour col = new Colour();
803         col.setName(button.getText());
804         col.setRGB(Format.getHexString(button.getBackground()));
805         ucs.addColour(col);
806       }
807       ucs.marshal(out);
808       out.close();
809     } catch (Exception ex)
810     {
811       ex.printStackTrace();
812     }
813   }
814
815   /**
816    * On cancel, restores the colour scheme before the dialogue was opened
817    * 
818    * @param e
819    */
820   @Override
821   protected void cancelButton_actionPerformed(ActionEvent e)
822   {
823     if (ap != null)
824     {
825       if (seqGroup != null)
826       {
827         seqGroup.setColourScheme(oldColourScheme);
828       }
829       else
830       {
831         ap.alignFrame.changeColour(oldColourScheme);
832       }
833       ap.paintAlignment(true);
834     }
835
836     if (structureViewer != null)
837     {
838       structureViewer.setJalviewColourScheme(oldColourScheme);
839     }
840
841     try
842     {
843       frame.setClosed(true);
844     } catch (Exception ex)
845     {
846     }
847   }
848
849   @Override
850   public void caseSensitive_actionPerformed(ActionEvent e)
851   {
852     boolean selected = caseSensitive.isSelected();
853     resetButtonPanel(selected);
854     lcaseColour.setEnabled(selected);
855   }
856 }