JAL-1360 Javadoc, Vector replaced with ArrayList, code formatted
[jalview.git] / src / jalview / gui / UserDefinedColours.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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.datamodel.SequenceGroup;
25 import jalview.io.JalviewFileChooser;
26 import jalview.jbgui.GUserDefinedColours;
27 import jalview.schemes.ColourSchemeI;
28 import jalview.schemes.ResidueProperties;
29 import jalview.schemes.UserColourScheme;
30 import jalview.util.ColorUtils;
31 import jalview.util.MessageManager;
32
33 import java.awt.Color;
34 import java.awt.Font;
35 import java.awt.event.ActionEvent;
36 import java.awt.event.MouseEvent;
37 import java.io.File;
38 import java.io.FileInputStream;
39 import java.io.FileOutputStream;
40 import java.io.InputStreamReader;
41 import java.io.OutputStreamWriter;
42 import java.io.PrintWriter;
43 import java.util.ArrayList;
44 import java.util.Hashtable;
45 import java.util.StringTokenizer;
46
47 import javax.swing.JButton;
48 import javax.swing.JInternalFrame;
49 import javax.swing.JOptionPane;
50 import javax.swing.event.ChangeEvent;
51 import javax.swing.event.ChangeListener;
52
53 /**
54  * This panel allows the user to assign colours to Amino Acid residue codes, and
55  * save the colour scheme.
56  * 
57  * @author Andrew Waterhouse
58  * @author Mungo Carstairs
59  */
60 public class UserDefinedColours extends GUserDefinedColours implements
61         ChangeListener
62 {
63   private static final int MY_FRAME_HEIGHT = 420;
64
65   private static final int MY_FRAME_WIDTH = 810;
66
67   private static final int MY_FRAME_WIDTH_CASE_SENSITIVE = 970;
68
69   AlignmentPanel ap;
70
71   SequenceGroup seqGroup;
72
73   ArrayList<JButton> selectedButtons;
74
75   ColourSchemeI oldColourScheme;
76
77   JInternalFrame frame;
78
79   JalviewStructureDisplayI jmol;
80
81   ArrayList<JButton> upperCaseButtons;
82
83   ArrayList<JButton> lowerCaseButtons;
84
85   /**
86    * Creates a new UserDefinedColours object.
87    * 
88    * @param ap
89    *          DOCUMENT ME!
90    * @param sg
91    *          DOCUMENT ME!
92    */
93   public UserDefinedColours(AlignmentPanel ap, SequenceGroup sg)
94   {
95     super();
96
97     lcaseColour.setEnabled(false);
98
99     this.ap = ap;
100     seqGroup = sg;
101
102     if (seqGroup != null)
103     {
104       oldColourScheme = seqGroup.cs;
105     }
106     else
107     {
108       oldColourScheme = ap.av.getGlobalColourScheme();
109     }
110
111     if (oldColourScheme instanceof UserColourScheme)
112     {
113       schemeName.setText(((UserColourScheme) oldColourScheme).getName());
114       if (((UserColourScheme) oldColourScheme).getLowerCaseColours() != null)
115       {
116         caseSensitive.setSelected(true);
117         lcaseColour.setEnabled(true);
118         resetButtonPanel(true);
119       }
120       else
121       {
122         resetButtonPanel(false);
123       }
124     }
125     else
126     {
127       resetButtonPanel(false);
128     }
129
130     showFrame();
131   }
132
133   public UserDefinedColours(JalviewStructureDisplayI jmol,
134           ColourSchemeI oldcs)
135   {
136     super();
137     this.jmol = jmol;
138
139     colorChooser.getSelectionModel().addChangeListener(this);
140
141     oldColourScheme = oldcs;
142
143     if (oldColourScheme instanceof UserColourScheme)
144     {
145       schemeName.setText(((UserColourScheme) oldColourScheme).getName());
146     }
147
148     resetButtonPanel(false);
149
150     showFrame();
151
152   }
153
154   void showFrame()
155   {
156     colorChooser.getSelectionModel().addChangeListener(this);
157     frame = new JInternalFrame();
158     frame.setContentPane(this);
159     Desktop.addInternalFrame(frame,
160             MessageManager.getString("label.user_defined_colours"),
161             MY_FRAME_WIDTH, MY_FRAME_HEIGHT, true);
162
163     if (seqGroup != null)
164     {
165       frame.setTitle(frame.getTitle() + " (" + seqGroup.getName() + ")");
166     }
167   }
168
169   void resetButtonPanel(boolean caseSensitive)
170   {
171     buttonPanel.removeAll();
172
173     if (upperCaseButtons == null)
174     {
175       upperCaseButtons = new ArrayList<JButton>();
176     }
177
178     JButton button;
179     String label;
180     for (int i = 0; i < 20; i++)
181     {
182       if (caseSensitive)
183       {
184         label = ResidueProperties.aa[i];
185       }
186       else
187       {
188         label = ResidueProperties.aa2Triplet.get(ResidueProperties.aa[i])
189                 .toString();
190       }
191
192       button = makeButton(label, ResidueProperties.aa[i], upperCaseButtons,
193               i);
194
195       buttonPanel.add(button);
196     }
197
198     buttonPanel.add(makeButton("B", "B", upperCaseButtons, 20));
199     buttonPanel.add(makeButton("Z", "Z", upperCaseButtons, 21));
200     buttonPanel.add(makeButton("X", "X", upperCaseButtons, 22));
201     buttonPanel.add(makeButton("Gap", "-", upperCaseButtons, 23));
202
203     if (!caseSensitive)
204     {
205       gridLayout.setRows(6);
206       gridLayout.setColumns(4);
207     }
208     else
209     {
210       gridLayout.setRows(7);
211       int cols = 7;
212       gridLayout.setColumns(cols + 1);
213
214       if (lowerCaseButtons == null)
215       {
216         lowerCaseButtons = new ArrayList<JButton>();
217       }
218
219       for (int i = 0; i < 20; i++)
220       {
221         int row = i / cols + 1;
222         int index = (row * cols) + i;
223         button = makeButton(ResidueProperties.aa[i].toLowerCase(),
224                 ResidueProperties.aa[i].toLowerCase(), lowerCaseButtons, i);
225
226         buttonPanel.add(button, index);
227       }
228     }
229
230     if (caseSensitive)
231     {
232       buttonPanel.add(makeButton("b", "b", lowerCaseButtons, 20));
233       buttonPanel.add(makeButton("z", "z", lowerCaseButtons, 21));
234       buttonPanel.add(makeButton("x", "x", lowerCaseButtons, 22));
235     }
236
237     // JAL-1360 widen the frame dynamically to accommodate case-sensitive AA
238     // codes
239     if (this.frame != null)
240     {
241       int newWidth = caseSensitive ? MY_FRAME_WIDTH_CASE_SENSITIVE
242               : MY_FRAME_WIDTH;
243       this.frame.setSize(newWidth, this.frame.getHeight());
244     }
245
246     buttonPanel.validate();
247     validate();
248   }
249
250   /**
251    * DOCUMENT ME!
252    * 
253    * @param evt
254    *          DOCUMENT ME!
255    */
256   @Override
257   public void stateChanged(ChangeEvent evt)
258   {
259     if (selectedButtons != null)
260     {
261       JButton button = null;
262       final Color newColour = colorChooser.getColor();
263       for (int i = 0; i < selectedButtons.size(); i++)
264       {
265         button = selectedButtons.get(i);
266         button.setBackground(newColour);
267         button.setForeground(ColorUtils.brighterThan(newColour));
268       }
269       if (button == lcaseColour)
270       {
271         for (int i = 0; i < lowerCaseButtons.size(); i++)
272         {
273           button = lowerCaseButtons.get(i);
274           button.setBackground(newColour);
275           button.setForeground(ColorUtils.brighterThan(button
276                   .getBackground()));
277         }
278       }
279     }
280   }
281
282   /**
283    * Performs actions when a residue button is clicked. This manages the button
284    * selection set (highlighted by brighter foreground text).
285    * <p>
286    * On select button(s) with Ctrl/click or Shift/click: set button foreground
287    * text to brighter than background.
288    * <p>
289    * On unselect button(s) with Ctrl/click on selected, or click to release
290    * current selection: reset foreground text to darker than background.
291    * <p>
292    * Simple click: clear selection (resetting foreground to darker); set clicked
293    * button foreground to brighter
294    * <p>
295    * Finally, synchronize the colour chooser to the colour of the first button
296    * in the selected set.
297    * 
298    * @param e
299    */
300   public void colourButtonPressed(MouseEvent e)
301   {
302     if (selectedButtons == null)
303     {
304       selectedButtons = new ArrayList<JButton>();
305     }
306
307     JButton pressed = (JButton) e.getSource();
308
309     if (e.isShiftDown())
310     {
311       JButton start, end = (JButton) e.getSource();
312       if (selectedButtons.size() > 0)
313       {
314         start = selectedButtons.get(selectedButtons.size() - 1);
315       }
316       else
317       {
318         start = (JButton) e.getSource();
319       }
320
321       int startIndex = 0, endIndex = 0;
322       for (int b = 0; b < buttonPanel.getComponentCount(); b++)
323       {
324         if (buttonPanel.getComponent(b) == start)
325         {
326           startIndex = b;
327         }
328         if (buttonPanel.getComponent(b) == end)
329         {
330           endIndex = b;
331         }
332       }
333
334       if (startIndex > endIndex)
335       {
336         int temp = startIndex;
337         startIndex = endIndex;
338         endIndex = temp;
339       }
340
341       for (int b = startIndex; b <= endIndex; b++)
342       {
343         JButton button = (JButton) buttonPanel.getComponent(b);
344         if (!selectedButtons.contains(button))
345         {
346           button.setForeground(ColorUtils.brighterThan(button
347                   .getBackground()));
348           selectedButtons.add(button);
349         }
350       }
351     }
352     else if (!e.isControlDown())
353     {
354       for (int b = 0; b < selectedButtons.size(); b++)
355       {
356         JButton button = selectedButtons.get(b);
357         button.setForeground(ColorUtils.darkerThan(button.getBackground()));
358       }
359       selectedButtons.clear();
360       pressed.setForeground(ColorUtils.brighterThan(pressed.getBackground()));
361       selectedButtons.add(pressed);
362
363     }
364     else if (e.isControlDown())
365     {
366       if (selectedButtons.contains(pressed))
367       {
368         pressed.setForeground(ColorUtils.darkerThan(pressed.getBackground()));
369         selectedButtons.remove(pressed);
370       }
371       else
372       {
373         pressed.setForeground(ColorUtils.brighterThan(pressed
374                 .getBackground()));
375         selectedButtons.add(pressed);
376       }
377     }
378
379     if (selectedButtons.size() > 0)
380     {
381       colorChooser.setColor((selectedButtons.get(0)).getBackground());
382     }
383   }
384
385   /**
386    * DOCUMENT ME!
387    * 
388    * @param label
389    *          DOCUMENT ME!
390    * @param aa
391    *          DOCUMENT ME!
392    */
393   JButton makeButton(String label, String aa,
394           ArrayList<JButton> caseSensitiveButtons, int buttonIndex)
395   {
396     final JButton button;
397     Color col;
398
399     if (buttonIndex < caseSensitiveButtons.size())
400     {
401       button = caseSensitiveButtons.get(buttonIndex);
402       col = button.getBackground();
403     }
404     else
405     {
406       button = new JButton();
407       button.addMouseListener(new java.awt.event.MouseAdapter()
408       {
409         @Override
410         public void mouseClicked(MouseEvent e)
411         {
412           colourButtonPressed(e);
413         }
414       });
415
416       caseSensitiveButtons.add(button);
417
418       col = Color.white;
419       if (oldColourScheme != null)
420       {
421         try
422         {
423           col = oldColourScheme.findColour(aa.charAt(0), -1, null);
424         } catch (Exception ex)
425         {
426         }
427       }
428     }
429
430     if (caseSensitive.isSelected())
431     {
432       button.setMargin(new java.awt.Insets(2, 2, 2, 2));
433     }
434     else
435     {
436       button.setMargin(new java.awt.Insets(2, 14, 2, 14));
437     }
438
439     button.setOpaque(true); // required for the next line to have effect
440     button.setBackground(col);
441     button.setText(label);
442     button.setForeground(ColorUtils.darkerThan(col));
443     button.setFont(new java.awt.Font("Verdana", Font.BOLD, 10));
444
445     return button;
446   }
447
448   /**
449    * DOCUMENT ME!
450    * 
451    * @param e
452    *          DOCUMENT ME!
453    */
454   @Override
455   protected void okButton_actionPerformed(ActionEvent e)
456   {
457     applyButton_actionPerformed(null);
458
459     try
460     {
461       frame.setClosed(true);
462     } catch (Exception ex)
463     {
464     }
465   }
466
467   /**
468    * DOCUMENT ME!
469    * 
470    * @param e
471    *          DOCUMENT ME!
472    */
473   @Override
474   protected void applyButton_actionPerformed(ActionEvent e)
475   {
476     UserColourScheme ucs = getSchemeFromButtons();
477     ucs.setName(schemeName.getText());
478
479     if (seqGroup != null)
480     {
481       seqGroup.cs = ucs;
482       ap.paintAlignment(true);
483     }
484     else if (ap != null)
485     {
486       ap.alignFrame.changeColour(ucs);
487     }
488     else if (jmol != null)
489     {
490       jmol.setJalviewColourScheme(ucs);
491     }
492   }
493
494   UserColourScheme getSchemeFromButtons()
495   {
496
497     Color[] newColours = new Color[24];
498
499     for (int i = 0; i < 24; i++)
500     {
501       JButton button = upperCaseButtons.get(i);
502       newColours[i] = button.getBackground();
503     }
504
505     UserColourScheme ucs = new UserColourScheme(newColours);
506
507     if (caseSensitive.isSelected())
508     {
509       newColours = new Color[23];
510       for (int i = 0; i < 23; i++)
511       {
512         JButton button = lowerCaseButtons.get(i);
513         newColours[i] = button.getBackground();
514       }
515       ucs.setLowerCaseColours(newColours);
516     }
517
518     if (ap != null)
519     {
520       ucs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
521     }
522
523     return ucs;
524   }
525
526   /**
527    * DOCUMENT ME!
528    * 
529    * @param e
530    *          DOCUMENT ME!
531    */
532   @Override
533   protected void loadbutton_actionPerformed(ActionEvent e)
534   {
535     upperCaseButtons = new ArrayList<JButton>();
536     lowerCaseButtons = new ArrayList<JButton>();
537
538     JalviewFileChooser chooser = new JalviewFileChooser(
539             jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
540             { "jc" }, new String[]
541             { "Jalview User Colours" }, "Jalview User Colours");
542     chooser.setFileView(new jalview.io.JalviewFileView());
543     chooser.setDialogTitle(MessageManager
544             .getString("label.load_colour_scheme"));
545     chooser.setToolTipText(MessageManager.getString("action.load"));
546
547     int value = chooser.showOpenDialog(this);
548
549     if (value == JalviewFileChooser.APPROVE_OPTION)
550     {
551       File choice = chooser.getSelectedFile();
552       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
553       String defaultColours = jalview.bin.Cache.getDefault(
554               "USER_DEFINED_COLOURS", choice.getPath());
555       if (defaultColours.indexOf(choice.getPath()) == -1)
556       {
557         defaultColours = defaultColours.concat("|")
558                 .concat(choice.getPath());
559       }
560
561       jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", defaultColours);
562
563       UserColourScheme ucs = loadColours(choice.getAbsolutePath());
564       Color[] colors = ucs.getColours();
565       schemeName.setText(ucs.getName());
566
567       if (ucs.getLowerCaseColours() != null)
568       {
569         caseSensitive.setSelected(true);
570         lcaseColour.setEnabled(true);
571         resetButtonPanel(true);
572         for (int i = 0; i < lowerCaseButtons.size(); i++)
573         {
574           JButton button = lowerCaseButtons.get(i);
575           button.setBackground(ucs.getLowerCaseColours()[i]);
576         }
577
578       }
579       else
580       {
581         caseSensitive.setSelected(false);
582         lcaseColour.setEnabled(false);
583         resetButtonPanel(false);
584       }
585
586       for (int i = 0; i < upperCaseButtons.size(); i++)
587       {
588         JButton button = upperCaseButtons.get(i);
589         button.setBackground(colors[i]);
590       }
591
592     }
593   }
594
595   /**
596    * DOCUMENT ME!
597    * 
598    * @return DOCUMENT ME!
599    */
600   public static UserColourScheme loadDefaultColours()
601   {
602     UserColourScheme ret = null;
603
604     String colours = jalview.bin.Cache.getProperty("USER_DEFINED_COLOURS");
605     if (colours != null)
606     {
607       if (colours.indexOf("|") > -1)
608       {
609         colours = colours.substring(0, colours.indexOf("|"));
610       }
611
612       ret = loadColours(colours);
613     }
614
615     if (ret == null)
616     {
617       Color[] newColours = new Color[24];
618       for (int i = 0; i < 24; i++)
619       {
620         newColours[i] = Color.white;
621       }
622       ret = new UserColourScheme(newColours);
623     }
624
625     return ret;
626   }
627
628   /**
629    * DOCUMENT ME!
630    * 
631    * @param file
632    *          DOCUMENT ME!
633    * 
634    * @return DOCUMENT ME!
635    */
636   static UserColourScheme loadColours(String file)
637   {
638     UserColourScheme ucs = null;
639     Color[] newColours = null;
640     try
641     {
642       InputStreamReader in = new InputStreamReader(
643               new FileInputStream(file), "UTF-8");
644
645       jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
646
647       org.exolab.castor.xml.Unmarshaller unmar = new org.exolab.castor.xml.Unmarshaller(
648               jucs);
649       jucs = (jalview.schemabinding.version2.JalviewUserColours) unmar
650               .unmarshal(in);
651
652       newColours = new Color[24];
653
654       Color[] lowerCase = null;
655       boolean caseSensitive = false;
656
657       String name;
658       int index;
659       for (int i = 0; i < jucs.getColourCount(); i++)
660       {
661         name = jucs.getColour(i).getName();
662         if (ResidueProperties.aa3Hash.containsKey(name))
663         {
664           index = ((Integer) ResidueProperties.aa3Hash.get(name))
665                   .intValue();
666         }
667         else
668         {
669           index = ResidueProperties.aaIndex[name.charAt(0)];
670         }
671         if (index == -1)
672         {
673           continue;
674         }
675
676         if (name.toLowerCase().equals(name))
677         {
678           if (lowerCase == null)
679           {
680             lowerCase = new Color[23];
681           }
682           caseSensitive = true;
683           lowerCase[index] = new Color(Integer.parseInt(jucs.getColour(i)
684                   .getRGB(), 16));
685         }
686         else
687         {
688           newColours[index] = new Color(Integer.parseInt(jucs.getColour(i)
689                   .getRGB(), 16));
690         }
691       }
692
693       if (newColours != null)
694       {
695         ucs = new UserColourScheme(newColours);
696         ucs.setName(jucs.getSchemeName());
697         if (caseSensitive)
698         {
699           ucs.setLowerCaseColours(lowerCase);
700         }
701       }
702
703     } catch (Exception ex)
704     {
705       // Could be Archive Jalview format
706       try
707       {
708         InputStreamReader in = new InputStreamReader(new FileInputStream(
709                 file), "UTF-8");
710
711         jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();
712
713         jucs = jucs.unmarshal(in);
714
715         newColours = new Color[jucs.getColourCount()];
716
717         for (int i = 0; i < 24; i++)
718         {
719           newColours[i] = new Color(Integer.parseInt(jucs.getColour(i)
720                   .getRGB(), 16));
721         }
722         if (newColours != null)
723         {
724           ucs = new UserColourScheme(newColours);
725           ucs.setName(jucs.getSchemeName());
726         }
727       } catch (Exception ex2)
728       {
729         ex2.printStackTrace();
730       }
731
732       if (newColours == null)
733       {
734         System.out.println("Error loading User ColourFile\n" + ex);
735       }
736     }
737
738     return ucs;
739   }
740
741   /**
742    * DOCUMENT ME!
743    * 
744    * @param e
745    *          DOCUMENT ME!
746    */
747   @Override
748   protected void savebutton_actionPerformed(ActionEvent e)
749   {
750     if (schemeName.getText().trim().length() < 1)
751     {
752       JOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
753               .getString("label.user_colour_scheme_must_have_name"),
754               MessageManager.getString("label.no_name_colour_scheme"),
755               JOptionPane.WARNING_MESSAGE);
756       return;
757     }
758
759     if (userColourSchemes != null
760             && userColourSchemes.containsKey(schemeName.getText()))
761     {
762       int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
763               MessageManager.formatMessage(
764                       "label.colour_scheme_exists_overwrite", new Object[]
765                       { schemeName.getText(), schemeName.getText() }),
766               MessageManager.getString("label.duplicate_scheme_name"),
767               JOptionPane.YES_NO_OPTION);
768       if (reply != JOptionPane.YES_OPTION)
769       {
770         return;
771       }
772
773       userColourSchemes.remove(schemeName.getText());
774     }
775     JalviewFileChooser chooser = new JalviewFileChooser(
776             jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
777             { "jc" }, new String[]
778             { "Jalview User Colours" }, "Jalview User Colours");
779
780     chooser.setFileView(new jalview.io.JalviewFileView());
781     chooser.setDialogTitle("Save colour scheme");
782     chooser.setToolTipText(MessageManager.getString("action.save"));
783
784     int value = chooser.showSaveDialog(this);
785
786     if (value == JalviewFileChooser.APPROVE_OPTION)
787     {
788       String choice = chooser.getSelectedFile().getPath();
789       String defaultColours = jalview.bin.Cache.getDefault(
790               "USER_DEFINED_COLOURS", choice);
791       if (defaultColours.indexOf(choice) == -1)
792       {
793         if (defaultColours.length() > 0)
794         {
795           defaultColours = defaultColours.concat("|");
796         }
797         defaultColours = defaultColours.concat(choice);
798       }
799
800       userColourSchemes.put(schemeName.getText(), getSchemeFromButtons());
801
802       ap.alignFrame.updateUserColourMenu();
803
804       jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", defaultColours);
805
806       jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
807
808       ucs.setSchemeName(schemeName.getText());
809       try
810       {
811         PrintWriter out = new PrintWriter(new OutputStreamWriter(
812                 new FileOutputStream(choice), "UTF-8"));
813
814         for (int i = 0; i < buttonPanel.getComponentCount(); i++)
815         {
816           JButton button = (JButton) buttonPanel.getComponent(i);
817           jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
818           col.setName(button.getText());
819           col.setRGB(jalview.util.Format.getHexString(button
820                   .getBackground()));
821           ucs.addColour(col);
822         }
823
824         ucs.marshal(out);
825         out.close();
826       } catch (Exception ex)
827       {
828         ex.printStackTrace();
829       }
830     }
831   }
832
833   /**
834    * DOCUMENT ME!
835    * 
836    * @param e
837    *          DOCUMENT ME!
838    */
839   @Override
840   protected void cancelButton_actionPerformed(ActionEvent e)
841   {
842     if (ap != null)
843     {
844       if (seqGroup != null)
845       {
846         seqGroup.cs = oldColourScheme;
847       }
848       else if (ap != null)
849       {
850         ap.av.setGlobalColourScheme(oldColourScheme);
851       }
852       ap.paintAlignment(true);
853     }
854
855     if (jmol != null)
856     {
857       jmol.setJalviewColourScheme(oldColourScheme);
858     }
859
860     try
861     {
862       frame.setClosed(true);
863     } catch (Exception ex)
864     {
865     }
866   }
867
868   static Hashtable userColourSchemes;
869
870   public static Hashtable getUserColourSchemes()
871   {
872     return userColourSchemes;
873   }
874
875   public static void initUserColourSchemes(String files)
876   {
877     userColourSchemes = new Hashtable();
878
879     if (files == null || files.length() == 0)
880     {
881       return;
882     }
883
884     // In case colours can't be loaded, we'll remove them
885     // from the default list here.
886     StringBuffer coloursFound = new StringBuffer();
887     StringTokenizer st = new StringTokenizer(files, "|");
888     while (st.hasMoreElements())
889     {
890       String file = st.nextToken();
891       try
892       {
893         UserColourScheme ucs = loadColours(file);
894         if (ucs != null)
895         {
896           if (coloursFound.length() > 0)
897           {
898             coloursFound.append("|");
899           }
900           coloursFound.append(file);
901           userColourSchemes.put(ucs.getName(), ucs);
902         }
903       } catch (Exception ex)
904       {
905         System.out.println("Error loading User ColourFile\n" + ex);
906       }
907     }
908     if (!files.equals(coloursFound.toString()))
909     {
910       if (coloursFound.toString().length() > 1)
911       {
912         jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS",
913                 coloursFound.toString());
914       }
915       else
916       {
917         jalview.bin.Cache.applicationProperties
918                 .remove("USER_DEFINED_COLOURS");
919       }
920     }
921   }
922
923   public static void removeColourFromDefaults(String target)
924   {
925     // The only way to find colours by name is to load them in
926     // In case colours can't be loaded, we'll remove them
927     // from the default list here.
928
929     userColourSchemes = new Hashtable();
930
931     StringBuffer coloursFound = new StringBuffer();
932     StringTokenizer st = new StringTokenizer(
933             jalview.bin.Cache.getProperty("USER_DEFINED_COLOURS"), "|");
934
935     while (st.hasMoreElements())
936     {
937       String file = st.nextToken();
938       try
939       {
940         UserColourScheme ucs = loadColours(file);
941         if (ucs != null && !ucs.getName().equals(target))
942         {
943           if (coloursFound.length() > 0)
944           {
945             coloursFound.append("|");
946           }
947           coloursFound.append(file);
948           userColourSchemes.put(ucs.getName(), ucs);
949         }
950       } catch (Exception ex)
951       {
952         System.out.println("Error loading User ColourFile\n" + ex);
953       }
954     }
955
956     if (coloursFound.toString().length() > 1)
957     {
958       jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS",
959               coloursFound.toString());
960     }
961     else
962     {
963       jalview.bin.Cache.applicationProperties
964               .remove("USER_DEFINED_COLOURS");
965     }
966
967   }
968
969   @Override
970   public void caseSensitive_actionPerformed(ActionEvent e)
971   {
972     resetButtonPanel(caseSensitive.isSelected());
973     lcaseColour.setEnabled(caseSensitive.isSelected());
974   }
975
976   @Override
977   public void lcaseColour_actionPerformed(ActionEvent e)
978   {
979     if (selectedButtons == null)
980     {
981       selectedButtons = new ArrayList<JButton>();
982     }
983     else
984     {
985       selectedButtons.clear();
986     }
987     selectedButtons.add(lcaseColour);
988   }
989 }