37824fe1688913d7726caaf9837d1544e2ae07b9
[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                 //Check if the user have done any selection
458                 boolean showWarning = (upperCaseButtons==null) ||
459                                         ((upperCaseButtons!=null) && (upperCaseButtons.size()==0)) ||
460                                         (lowerCaseButtons==null) ||
461                                         ((lowerCaseButtons!=null) && (lowerCaseButtons.size()==0));
462                 if (showWarning){
463                 JOptionPane.showMessageDialog(Desktop.desktop,
464                         MessageManager.getString("label.no_colour_selection_in_scheme"),MessageManager.getString("label.no_colour_selection_warn"),
465                         JOptionPane.WARNING_MESSAGE);
466                         
467                 }else{
468                     applyButton_actionPerformed(null);
469                 
470                     try
471                     {
472                       frame.setClosed(true);
473                     } catch (Exception ex)
474                     {
475                     }
476                 }
477   }
478
479   /**
480    * DOCUMENT ME!
481    * 
482    * @param e
483    *          DOCUMENT ME!
484    */
485   @Override
486   protected void applyButton_actionPerformed(ActionEvent e)
487   {
488         //Check if the user have done any selection
489         boolean showWarning = (upperCaseButtons==null) ||
490                                 ((upperCaseButtons!=null) && (upperCaseButtons.size()==0)) ||
491                                 (lowerCaseButtons==null) ||
492                                 ((lowerCaseButtons!=null) && (lowerCaseButtons.size()==0));
493         if (showWarning){
494         JOptionPane.showMessageDialog(Desktop.desktop,
495                 MessageManager.getString("label.no_colour_selection_in_scheme"),MessageManager.getString("label.no_colour_selection_warn"),
496                 JOptionPane.WARNING_MESSAGE);
497                 
498         }
499         UserColourScheme ucs = getSchemeFromButtons();
500     ucs.setName(schemeName.getText());
501
502     if (seqGroup != null)
503     {
504       seqGroup.cs = ucs;
505       ap.paintAlignment(true);
506     }
507     else if (ap != null)
508     {
509       ap.alignFrame.changeColour(ucs);
510     }
511     else if (jmol != null)
512     {
513       jmol.setJalviewColourScheme(ucs);
514     }
515   }
516
517   UserColourScheme getSchemeFromButtons()
518   {
519
520     Color[] newColours = new Color[24];
521
522     int length = upperCaseButtons.size();
523     if (length<24){
524         int i = 0;
525         for (JButton btn:upperCaseButtons){
526                 newColours[i] = btn.getBackground();
527                 i++;
528         }
529     }else{
530         for (int i = 0; i < 24; i++){
531                 JButton button = (JButton) upperCaseButtons.get(i);
532                 newColours[i] = button.getBackground();
533         }
534     }
535
536     UserColourScheme ucs = new UserColourScheme(newColours);
537
538     if (caseSensitive.isSelected())
539     {
540       newColours = new Color[23];
541       length = lowerCaseButtons.size();
542       if (length<23){
543           int i = 0;
544           for (JButton btn:lowerCaseButtons){
545                   newColours[i] = btn.getBackground();
546                   i++;
547           }
548       }else{
549           for (int i = 0; i < 23; i++){
550                   JButton button = (JButton) lowerCaseButtons.get(i);
551                   newColours[i] = button.getBackground();
552           }
553       }
554       ucs.setLowerCaseColours(newColours);
555     }
556
557     if (ap != null)
558     {
559       ucs.setThreshold(0, ap.av.getIgnoreGapsConsensus());
560     }
561
562     return ucs;
563   }
564
565   /**
566    * DOCUMENT ME!
567    * 
568    * @param e
569    *          DOCUMENT ME!
570    */
571   @Override
572   protected void loadbutton_actionPerformed(ActionEvent e)
573   {
574     upperCaseButtons = new ArrayList<JButton>();
575     lowerCaseButtons = new ArrayList<JButton>();
576
577     JalviewFileChooser chooser = new JalviewFileChooser(
578             jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
579             { "jc" }, new String[]
580             { "Jalview User Colours" }, "Jalview User Colours");
581     chooser.setFileView(new jalview.io.JalviewFileView());
582     chooser.setDialogTitle(MessageManager
583             .getString("label.load_colour_scheme"));
584     chooser.setToolTipText(MessageManager.getString("action.load"));
585
586     int value = chooser.showOpenDialog(this);
587
588     if (value == JalviewFileChooser.APPROVE_OPTION)
589     {
590       File choice = chooser.getSelectedFile();
591       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice.getParent());
592       String defaultColours = jalview.bin.Cache.getDefault(
593               "USER_DEFINED_COLOURS", choice.getPath());
594       if (defaultColours.indexOf(choice.getPath()) == -1)
595       {
596         defaultColours = defaultColours.concat("|")
597                 .concat(choice.getPath());
598       }
599
600       jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", defaultColours);
601
602       UserColourScheme ucs = loadColours(choice.getAbsolutePath());
603       Color[] colors = ucs.getColours();
604       schemeName.setText(ucs.getName());
605
606       if (ucs.getLowerCaseColours() != null)
607       {
608         caseSensitive.setSelected(true);
609         lcaseColour.setEnabled(true);
610         resetButtonPanel(true);
611         for (int i = 0; i < lowerCaseButtons.size(); i++)
612         {
613           JButton button = lowerCaseButtons.get(i);
614           button.setBackground(ucs.getLowerCaseColours()[i]);
615         }
616
617       }
618       else
619       {
620         caseSensitive.setSelected(false);
621         lcaseColour.setEnabled(false);
622         resetButtonPanel(false);
623       }
624
625       for (int i = 0; i < upperCaseButtons.size(); i++)
626       {
627         JButton button = upperCaseButtons.get(i);
628         button.setBackground(colors[i]);
629       }
630
631     }
632   }
633
634   /**
635    * DOCUMENT ME!
636    * 
637    * @return DOCUMENT ME!
638    */
639   public static UserColourScheme loadDefaultColours()
640   {
641     UserColourScheme ret = null;
642
643     String colours = jalview.bin.Cache.getProperty("USER_DEFINED_COLOURS");
644     if (colours != null)
645     {
646       if (colours.indexOf("|") > -1)
647       {
648         colours = colours.substring(0, colours.indexOf("|"));
649       }
650
651       ret = loadColours(colours);
652     }
653
654     if (ret == null)
655     {
656       Color[] newColours = new Color[24];
657       for (int i = 0; i < 24; i++)
658       {
659         newColours[i] = Color.white;
660       }
661       ret = new UserColourScheme(newColours);
662     }
663
664     return ret;
665   }
666
667   /**
668    * DOCUMENT ME!
669    * 
670    * @param file
671    *          DOCUMENT ME!
672    * 
673    * @return DOCUMENT ME!
674    */
675   static UserColourScheme loadColours(String file)
676   {
677     UserColourScheme ucs = null;
678     Color[] newColours = null;
679     try
680     {
681       InputStreamReader in = new InputStreamReader(
682               new FileInputStream(file), "UTF-8");
683
684       jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
685
686       org.exolab.castor.xml.Unmarshaller unmar = new org.exolab.castor.xml.Unmarshaller(
687               jucs);
688       jucs = (jalview.schemabinding.version2.JalviewUserColours) unmar
689               .unmarshal(in);
690
691       newColours = new Color[24];
692
693       Color[] lowerCase = null;
694       boolean caseSensitive = false;
695
696       String name;
697       int index;
698       for (int i = 0; i < jucs.getColourCount(); i++)
699       {
700         name = jucs.getColour(i).getName();
701         if (ResidueProperties.aa3Hash.containsKey(name))
702         {
703           index = ((Integer) ResidueProperties.aa3Hash.get(name))
704                   .intValue();
705         }
706         else
707         {
708           index = ResidueProperties.aaIndex[name.charAt(0)];
709         }
710         if (index == -1)
711         {
712           continue;
713         }
714
715         if (name.toLowerCase().equals(name))
716         {
717           if (lowerCase == null)
718           {
719             lowerCase = new Color[23];
720           }
721           caseSensitive = true;
722           lowerCase[index] = new Color(Integer.parseInt(jucs.getColour(i)
723                   .getRGB(), 16));
724         }
725         else
726         {
727           newColours[index] = new Color(Integer.parseInt(jucs.getColour(i)
728                   .getRGB(), 16));
729         }
730       }
731
732       if (newColours != null)
733       {
734         ucs = new UserColourScheme(newColours);
735         ucs.setName(jucs.getSchemeName());
736         if (caseSensitive)
737         {
738           ucs.setLowerCaseColours(lowerCase);
739         }
740       }
741
742     } catch (Exception ex)
743     {
744       // Could be Archive Jalview format
745       try
746       {
747         InputStreamReader in = new InputStreamReader(new FileInputStream(
748                 file), "UTF-8");
749
750         jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();
751
752         jucs = jucs.unmarshal(in);
753
754         newColours = new Color[jucs.getColourCount()];
755
756         for (int i = 0; i < 24; i++)
757         {
758           newColours[i] = new Color(Integer.parseInt(jucs.getColour(i)
759                   .getRGB(), 16));
760         }
761         if (newColours != null)
762         {
763           ucs = new UserColourScheme(newColours);
764           ucs.setName(jucs.getSchemeName());
765         }
766       } catch (Exception ex2)
767       {
768         ex2.printStackTrace();
769       }
770
771       if (newColours == null)
772       {
773         System.out.println("Error loading User ColourFile\n" + ex);
774       }
775     }
776
777     return ucs;
778   }
779
780   /**
781    * DOCUMENT ME!
782    * 
783    * @param e
784    *          DOCUMENT ME!
785    */
786   @Override
787   protected void savebutton_actionPerformed(ActionEvent e)
788   {
789     if (schemeName.getText().trim().length() < 1)
790     {
791       JOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
792               .getString("label.user_colour_scheme_must_have_name"),
793               MessageManager.getString("label.no_name_colour_scheme"),
794               JOptionPane.WARNING_MESSAGE);
795       return;
796     }
797
798     if (userColourSchemes != null
799             && userColourSchemes.containsKey(schemeName.getText()))
800     {
801       int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
802               MessageManager.formatMessage(
803                       "label.colour_scheme_exists_overwrite", new Object[]
804                       { schemeName.getText(), schemeName.getText() }),
805               MessageManager.getString("label.duplicate_scheme_name"),
806               JOptionPane.YES_NO_OPTION);
807       if (reply != JOptionPane.YES_OPTION)
808       {
809         return;
810       }
811
812       userColourSchemes.remove(schemeName.getText());
813     }
814     JalviewFileChooser chooser = new JalviewFileChooser(
815             jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
816             { "jc" }, new String[]
817             { "Jalview User Colours" }, "Jalview User Colours");
818
819     chooser.setFileView(new jalview.io.JalviewFileView());
820     chooser.setDialogTitle(MessageManager.getString("label.save_colour_scheme"));
821     chooser.setToolTipText(MessageManager.getString("action.save"));
822
823     int value = chooser.showSaveDialog(this);
824
825     if (value == JalviewFileChooser.APPROVE_OPTION)
826     {
827       String choice = chooser.getSelectedFile().getPath();
828       String defaultColours = jalview.bin.Cache.getDefault(
829               "USER_DEFINED_COLOURS", choice);
830       if (defaultColours.indexOf(choice) == -1)
831       {
832         if (defaultColours.length() > 0)
833         {
834           defaultColours = defaultColours.concat("|");
835         }
836         defaultColours = defaultColours.concat(choice);
837       }
838
839       userColourSchemes.put(schemeName.getText(), getSchemeFromButtons());
840
841       ap.alignFrame.updateUserColourMenu();
842
843       jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS", defaultColours);
844
845       jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
846
847       ucs.setSchemeName(schemeName.getText());
848       try
849       {
850         PrintWriter out = new PrintWriter(new OutputStreamWriter(
851                 new FileOutputStream(choice), "UTF-8"));
852
853         for (int i = 0; i < buttonPanel.getComponentCount(); i++)
854         {
855           JButton button = (JButton) buttonPanel.getComponent(i);
856           jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
857           col.setName(button.getText());
858           col.setRGB(jalview.util.Format.getHexString(button
859                   .getBackground()));
860           ucs.addColour(col);
861         }
862
863         ucs.marshal(out);
864         out.close();
865       } catch (Exception ex)
866       {
867         ex.printStackTrace();
868       }
869     }
870   }
871
872   /**
873    * DOCUMENT ME!
874    * 
875    * @param e
876    *          DOCUMENT ME!
877    */
878   @Override
879   protected void cancelButton_actionPerformed(ActionEvent e)
880   {
881     if (ap != null)
882     {
883       if (seqGroup != null)
884       {
885         seqGroup.cs = oldColourScheme;
886       }
887       else if (ap != null)
888       {
889         ap.av.setGlobalColourScheme(oldColourScheme);
890       }
891       ap.paintAlignment(true);
892     }
893
894     if (jmol != null)
895     {
896       jmol.setJalviewColourScheme(oldColourScheme);
897     }
898
899     try
900     {
901       frame.setClosed(true);
902     } catch (Exception ex)
903     {
904     }
905   }
906
907   static Hashtable userColourSchemes;
908
909   public static Hashtable getUserColourSchemes()
910   {
911     return userColourSchemes;
912   }
913
914   public static void initUserColourSchemes(String files)
915   {
916     userColourSchemes = new Hashtable();
917
918     if (files == null || files.length() == 0)
919     {
920       return;
921     }
922
923     // In case colours can't be loaded, we'll remove them
924     // from the default list here.
925     StringBuffer coloursFound = new StringBuffer();
926     StringTokenizer st = new StringTokenizer(files, "|");
927     while (st.hasMoreElements())
928     {
929       String file = st.nextToken();
930       try
931       {
932         UserColourScheme ucs = loadColours(file);
933         if (ucs != null)
934         {
935           if (coloursFound.length() > 0)
936           {
937             coloursFound.append("|");
938           }
939           coloursFound.append(file);
940           userColourSchemes.put(ucs.getName(), ucs);
941         }
942       } catch (Exception ex)
943       {
944         System.out.println("Error loading User ColourFile\n" + ex);
945       }
946     }
947     if (!files.equals(coloursFound.toString()))
948     {
949       if (coloursFound.toString().length() > 1)
950       {
951         jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS",
952                 coloursFound.toString());
953       }
954       else
955       {
956         jalview.bin.Cache.applicationProperties
957                 .remove("USER_DEFINED_COLOURS");
958       }
959     }
960   }
961
962   public static void removeColourFromDefaults(String target)
963   {
964     // The only way to find colours by name is to load them in
965     // In case colours can't be loaded, we'll remove them
966     // from the default list here.
967
968     userColourSchemes = new Hashtable();
969
970     StringBuffer coloursFound = new StringBuffer();
971     StringTokenizer st = new StringTokenizer(
972             jalview.bin.Cache.getProperty("USER_DEFINED_COLOURS"), "|");
973
974     while (st.hasMoreElements())
975     {
976       String file = st.nextToken();
977       try
978       {
979         UserColourScheme ucs = loadColours(file);
980         if (ucs != null && !ucs.getName().equals(target))
981         {
982           if (coloursFound.length() > 0)
983           {
984             coloursFound.append("|");
985           }
986           coloursFound.append(file);
987           userColourSchemes.put(ucs.getName(), ucs);
988         }
989       } catch (Exception ex)
990       {
991         System.out.println("Error loading User ColourFile\n" + ex);
992       }
993     }
994
995     if (coloursFound.toString().length() > 1)
996     {
997       jalview.bin.Cache.setProperty("USER_DEFINED_COLOURS",
998               coloursFound.toString());
999     }
1000     else
1001     {
1002       jalview.bin.Cache.applicationProperties
1003               .remove("USER_DEFINED_COLOURS");
1004     }
1005
1006   }
1007
1008   @Override
1009   public void caseSensitive_actionPerformed(ActionEvent e)
1010   {
1011     resetButtonPanel(caseSensitive.isSelected());
1012     lcaseColour.setEnabled(caseSensitive.isSelected());
1013   }
1014
1015   @Override
1016   public void lcaseColour_actionPerformed(ActionEvent e)
1017   {
1018     if (selectedButtons == null)
1019     {
1020       selectedButtons = new ArrayList<JButton>();
1021     }
1022     else
1023     {
1024       selectedButtons.clear();
1025     }
1026     selectedButtons.add(lcaseColour);
1027   }
1028 }