Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.gui

File UserDefinedColours.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
56% of files have more coverage

Code metrics

114
269
20
1
907
593
84
0.31
13.45
20
4.2

Classes

Class Line # Actions
UserDefinedColours 62 269 84 403
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

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