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