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