JAL-1620 version bump and release notes
[jalview.git] / src / jalview / gui / Preferences.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2b1)
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.analysis.AnnotationSorter.SequenceAnnotationOrder;
24 import jalview.bin.Cache;
25 import jalview.gui.Help.HelpId;
26 import jalview.gui.StructureViewer.Viewer;
27 import jalview.io.JalviewFileChooser;
28 import jalview.io.JalviewFileView;
29 import jalview.jbgui.GPreferences;
30 import jalview.jbgui.GSequenceLink;
31 import jalview.schemes.ColourSchemeProperty;
32 import jalview.util.MessageManager;
33
34 import java.awt.BorderLayout;
35 import java.awt.Color;
36 import java.awt.Dimension;
37 import java.awt.Font;
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.MouseEvent;
41 import java.io.File;
42 import java.util.Collection;
43 import java.util.List;
44 import java.util.StringTokenizer;
45 import java.util.Vector;
46
47 import javax.help.HelpSetException;
48 import javax.swing.JColorChooser;
49 import javax.swing.JFileChooser;
50 import javax.swing.JInternalFrame;
51 import javax.swing.JOptionPane;
52 import javax.swing.JPanel;
53
54 import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
55
56 /**
57  * DOCUMENT ME!
58  * 
59  * @author $author$
60  * @version $Revision$
61  */
62 public class Preferences extends GPreferences
63 {
64
65   public static final String ADD_TEMPFACT_ANN = "ADD_TEMPFACT_ANN";
66
67   public static final String ADD_SS_ANN = "ADD_SS_ANN";
68
69   public static final String USE_RNAVIEW = "USE_RNAVIEW";
70
71   public static final String STRUCT_FROM_PDB = "STRUCT_FROM_PDB";
72
73   public static final String STRUCTURE_DISPLAY = "STRUCTURE_DISPLAY";
74
75   public static final String CHIMERA_PATH = "CHIMERA_PATH";
76
77   public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS";
78
79   public static final String SHOW_AUTOCALC_ABOVE = "SHOW_AUTOCALC_ABOVE";
80
81   private static final int MIN_FONT_SIZE = 1;
82
83   private static final int MAX_FONT_SIZE = 30;
84
85   /**
86    * Holds name and link separated with | character. Sequence ID must be
87    * $SEQUENCE_ID$ or $SEQUENCE_ID=/.possible | chars ./=$
88    */
89   public static Vector sequenceURLLinks;
90
91   /**
92    * Holds name and link separated with | character. Sequence IDS and Sequences
93    * must be $SEQUENCEIDS$ or $SEQUENCEIDS=/.possible | chars ./=$ and
94    * $SEQUENCES$ or $SEQUENCES=/.possible | chars ./=$ and separation character
95    * for first and second token specified after a pipe character at end |,|.
96    * (TODO: proper escape for using | to separate ids or sequences
97    */
98
99   public static Vector groupURLLinks;
100   static
101   {
102     String string = Cache
103             .getDefault(
104                     "SEQUENCE_LINKS",
105                     "EMBL-EBI Search|http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$");
106     sequenceURLLinks = new Vector();
107
108     try
109     {
110       StringTokenizer st = new StringTokenizer(string, "|");
111       while (st.hasMoreElements())
112       {
113         String name = st.nextToken();
114         String url = st.nextToken();
115         // check for '|' within a regex
116         int rxstart = url.indexOf("$SEQUENCE_ID$");
117         while (rxstart == -1 && url.indexOf("/=$") == -1)
118         {
119           url = url + "|" + st.nextToken();
120         }
121         sequenceURLLinks.addElement(name + "|" + url);
122       }
123     } catch (Exception ex)
124     {
125       System.out.println(ex + "\nError parsing sequence links");
126     }
127     {
128       // upgrade old SRS link
129       int srsPos = sequenceURLLinks
130               .indexOf("SRS|http://srs.ebi.ac.uk/srsbin/cgi-bin/wgetz?-newId+(([uniprot-all:$SEQUENCE_ID$]))+-view+SwissEntry");
131       if (srsPos > -1)
132       {
133         sequenceURLLinks
134                 .setElementAt(
135                         "EMBL-EBI Search|http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$",
136                         srsPos);
137       }
138     }
139
140     /**
141      * TODO: reformulate groupURL encoding so two or more can be stored in the
142      * .properties file as '|' separated strings
143      */
144
145     groupURLLinks = new Vector();
146   }
147
148   Vector nameLinks, urlLinks;
149
150   JInternalFrame frame;
151
152   DasSourceBrowser dasSource;
153
154   private WsPreferences wsPrefs;
155
156   /**
157    * Creates a new Preferences object.
158    */
159   public Preferences()
160   {
161     super();
162     frame = new JInternalFrame();
163     frame.setContentPane(this);
164     dasSource = new DasSourceBrowser();
165     dasTab.add(dasSource, BorderLayout.CENTER);
166     wsPrefs = new WsPreferences();
167     wsTab.add(wsPrefs, BorderLayout.CENTER);
168     int width = 500, height = 420;
169     if (new jalview.util.Platform().isAMac())
170     {
171       width = 570;
172       height = 460;
173     }
174
175     Desktop.addInternalFrame(frame,
176             MessageManager.getString("label.preferences"), width, height);
177     frame.setMinimumSize(new Dimension(width, height));
178
179     /*
180      * Set Visual tab defaults
181      */
182     seqLimit.setSelected(Cache.getDefault("SHOW_JVSUFFIX", true));
183     rightAlign.setSelected(Cache.getDefault("RIGHT_ALIGN_IDS", false));
184     fullScreen.setSelected(Cache.getDefault("SHOW_FULLSCREEN", false));
185     annotations.setSelected(Cache.getDefault("SHOW_ANNOTATIONS", true));
186
187     conservation.setSelected(Cache.getDefault("SHOW_CONSERVATION", true));
188     quality.setSelected(Cache.getDefault("SHOW_QUALITY", true));
189     identity.setSelected(Cache.getDefault("SHOW_IDENTITY", true));
190     openoverv.setSelected(Cache.getDefault("SHOW_OVERVIEW", false));
191     showUnconserved
192             .setSelected(Cache.getDefault("SHOW_UNCONSERVED", false));
193     showGroupConsensus.setSelected(Cache.getDefault("SHOW_GROUP_CONSENSUS",
194             false));
195     showGroupConservation.setSelected(Cache.getDefault(
196             "SHOW_GROUP_CONSERVATION", false));
197     showConsensHistogram.setSelected(Cache.getDefault(
198             "SHOW_CONSENSUS_HISTOGRAM", true));
199     showConsensLogo.setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO",
200             false));
201     showNpTooltip.setSelected(Cache
202             .getDefault("SHOW_NPFEATS_TOOLTIP", true));
203     showDbRefTooltip.setSelected(Cache.getDefault("SHOW_DBREFS_TOOLTIP",
204             true));
205
206     String[] fonts = java.awt.GraphicsEnvironment
207             .getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
208     for (int i = 0; i < fonts.length; i++)
209     {
210       fontNameCB.addItem(fonts[i]);
211     }
212
213     for (int i = MIN_FONT_SIZE; i <= MAX_FONT_SIZE; i++)
214     {
215       fontSizeCB.addItem(i + "");
216     }
217
218     fontStyleCB.addItem("plain");
219     fontStyleCB.addItem("bold");
220     fontStyleCB.addItem("italic");
221
222     fontNameCB.setSelectedItem(Cache.getDefault("FONT_NAME", "SansSerif"));
223     fontSizeCB.setSelectedItem(Cache.getDefault("FONT_SIZE", "10"));
224     fontStyleCB.setSelectedItem(Cache.getDefault("FONT_STYLE", Font.PLAIN
225             + ""));
226
227     smoothFont.setSelected(Cache.getDefault("ANTI_ALIAS", false));
228
229     idItalics.setSelected(Cache.getDefault("ID_ITALICS", true));
230
231     wrap.setSelected(Cache.getDefault("WRAP_ALIGNMENT", false));
232
233     gapSymbolCB.addItem("-");
234     gapSymbolCB.addItem(".");
235
236     gapSymbolCB.setSelectedItem(Cache.getDefault("GAP_SYMBOL", "-"));
237
238     sortby.addItem("No sort");
239     sortby.addItem("Id");
240     sortby.addItem("Pairwise Identity");
241     sortby.setSelectedItem(Cache.getDefault("SORT_ALIGNMENT", "No sort"));
242
243     sortAnnBy.addItem(SequenceAnnotationOrder.NONE.toString());
244     sortAnnBy
245             .addItem(SequenceAnnotationOrder.SEQUENCE_AND_LABEL.toString());
246     sortAnnBy
247             .addItem(SequenceAnnotationOrder.LABEL_AND_SEQUENCE.toString());
248     SequenceAnnotationOrder savedSort = SequenceAnnotationOrder
249             .valueOf(Cache.getDefault(SORT_ANNOTATIONS,
250                     SequenceAnnotationOrder.NONE.name()));
251     sortAnnBy.setSelectedItem(savedSort.toString());
252
253     sortAutocalc.addItem("Autocalculated first");
254     sortAutocalc.addItem("Autocalculated last");
255     final boolean showAbove = Cache.getDefault(SHOW_AUTOCALC_ABOVE,
256             true);
257     sortAutocalc.setSelectedItem(showAbove ? sortAutocalc.getItemAt(0)
258             : sortAutocalc.getItemAt(1));
259     startupCheckbox
260             .setSelected(Cache.getDefault("SHOW_STARTUP_FILE", true));
261     startupFileTextfield.setText(Cache.getDefault("STARTUP_FILE",
262             Cache.getDefault("www.jalview.org", "http://www.jalview.org")
263                     + "/examples/exampleFile_2_3.jar"));
264
265     /*
266      * Set Colours tab defaults
267      */
268     for (int i = ColourSchemeProperty.FIRST_COLOUR; i <= ColourSchemeProperty.LAST_COLOUR; i++)
269     {
270       colour.addItem(ColourSchemeProperty.getColourName(i));
271     }
272     String string = Cache.getDefault("DEFAULT_COLOUR", "None");
273     colour.setSelectedItem(string);
274     minColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN",
275             Color.orange));
276     maxColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX",
277             Color.red));
278
279     /*
280      * Set Structure tab defaults.
281      */
282     final boolean structSelected = Cache.getDefault(STRUCT_FROM_PDB, false);
283     structFromPdb.setSelected(structSelected);
284     useRnaView.setSelected(Cache.getDefault(USE_RNAVIEW, false));
285     useRnaView.setEnabled(structSelected);
286     addSecondaryStructure
287             .setSelected(Cache.getDefault(ADD_SS_ANN, false));
288     addSecondaryStructure.setEnabled(structSelected);
289     addTempFactor.setSelected(Cache.getDefault(ADD_TEMPFACT_ANN, false));
290     addTempFactor.setEnabled(structSelected);
291     structViewer.setSelectedItem(Cache.getDefault(STRUCTURE_DISPLAY,
292             Viewer.JMOL.name()));
293     chimeraPath.setText(Cache.getDefault(CHIMERA_PATH, ""));
294     chimeraPath.addActionListener(new ActionListener()
295     {
296       @Override
297       public void actionPerformed(ActionEvent e)
298       {
299         validateChimeraPath();
300       }
301     });
302
303     /*
304      * Set Connections tab defaults
305      */
306     nameLinks = new Vector();
307     urlLinks = new Vector();
308     for (int i = 0; i < sequenceURLLinks.size(); i++)
309     {
310       String link = sequenceURLLinks.elementAt(i).toString();
311       nameLinks.addElement(link.substring(0, link.indexOf("|")));
312       urlLinks.addElement(link.substring(link.indexOf("|") + 1));
313     }
314
315     updateLinkData();
316
317     useProxy.setSelected(Cache.getDefault("USE_PROXY", false));
318     proxyServerTB.setEnabled(useProxy.isSelected());
319     proxyPortTB.setEnabled(useProxy.isSelected());
320     proxyServerTB.setText(Cache.getDefault("PROXY_SERVER", ""));
321     proxyPortTB.setText(Cache.getDefault("PROXY_PORT", ""));
322
323     defaultBrowser.setText(Cache.getDefault("DEFAULT_BROWSER", ""));
324
325     usagestats.setSelected(Cache.getDefault("USAGESTATS", false));
326     // note antisense here: default is true
327     questionnaire
328             .setSelected(Cache.getProperty("NOQUESTIONNAIRES") == null);
329     versioncheck.setSelected(Cache.getDefault("VERSION_CHECK", true));
330
331     /*
332      * Set Output tab defaults
333      */
334     epsRendering
335             .addItem(MessageManager.getString("label.prompt_each_time"));
336     epsRendering.addItem(MessageManager.getString("label.lineart"));
337     epsRendering.addItem(MessageManager.getString("action.text"));
338     epsRendering.setSelectedItem(Cache.getDefault("EPS_RENDERING",
339             "Prompt each time"));
340     autoIdWidth.setSelected(Cache.getDefault("FIGURE_AUTOIDWIDTH", false));
341     userIdWidth.setEnabled(autoIdWidth.isSelected());
342     userIdWidthlabel.setEnabled(autoIdWidth.isSelected());
343     Integer wi = Cache.getIntegerProperty("FIGURE_USERIDWIDTH");
344     userIdWidth.setText(wi == null ? "" : wi.toString());
345     blcjv.setSelected(Cache.getDefault("BLC_JVSUFFIX", true));
346     clustaljv.setSelected(Cache.getDefault("CLUSTAL_JVSUFFIX", true));
347     fastajv.setSelected(Cache.getDefault("FASTA_JVSUFFIX", true));
348     msfjv.setSelected(Cache.getDefault("MSF_JVSUFFIX", true));
349     pfamjv.setSelected(Cache.getDefault("PFAM_JVSUFFIX", true));
350     pileupjv.setSelected(Cache.getDefault("PILEUP_JVSUFFIX", true));
351     pirjv.setSelected(Cache.getDefault("PIR_JVSUFFIX", true));
352     modellerOutput.setSelected(Cache.getDefault("PIR_MODELLER", false));
353
354     /*
355      * Set Editing tab defaults
356      */
357     autoCalculateConsCheck.setSelected(Cache.getDefault(
358             "AUTO_CALC_CONSENSUS", true));
359     padGaps.setSelected(Cache.getDefault("PAD_GAPS", false));
360     sortByTree.setSelected(Cache.getDefault("SORT_BY_TREE", false));
361
362     annotations_actionPerformed(null); // update the display of the annotation
363                                        // settings
364   }
365
366   /**
367    * Save user selections on the Preferences tabs to the Cache and write out to
368    * file.
369    * 
370    * @param e
371    */
372   public void ok_actionPerformed(ActionEvent e)
373   {
374     if (!validateSettings())
375     {
376       return;
377     }
378
379     /*
380      * Save Visual settings
381      */
382     Cache.applicationProperties.setProperty("SHOW_JVSUFFIX",
383             Boolean.toString(seqLimit.isSelected()));
384     Cache.applicationProperties.setProperty("RIGHT_ALIGN_IDS",
385             Boolean.toString(rightAlign.isSelected()));
386     Cache.applicationProperties.setProperty("SHOW_FULLSCREEN",
387             Boolean.toString(fullScreen.isSelected()));
388     Cache.applicationProperties.setProperty("SHOW_OVERVIEW",
389             Boolean.toString(openoverv.isSelected()));
390     Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
391             Boolean.toString(annotations.isSelected()));
392     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
393             Boolean.toString(conservation.isSelected()));
394     Cache.applicationProperties.setProperty("SHOW_QUALITY",
395             Boolean.toString(quality.isSelected()));
396     Cache.applicationProperties.setProperty("SHOW_IDENTITY",
397             Boolean.toString(identity.isSelected()));
398
399     Cache.applicationProperties.setProperty("GAP_SYMBOL", gapSymbolCB
400             .getSelectedItem().toString());
401
402     Cache.applicationProperties.setProperty("FONT_NAME", fontNameCB
403             .getSelectedItem().toString());
404     Cache.applicationProperties.setProperty("FONT_STYLE", fontStyleCB
405             .getSelectedItem().toString());
406     Cache.applicationProperties.setProperty("FONT_SIZE", fontSizeCB
407             .getSelectedItem().toString());
408
409     Cache.applicationProperties.setProperty("ID_ITALICS",
410             Boolean.toString(idItalics.isSelected()));
411     Cache.applicationProperties.setProperty("SHOW_UNCONSERVED",
412             Boolean.toString(showUnconserved.isSelected()));
413     Cache.applicationProperties.setProperty("SHOW_GROUP_CONSENSUS",
414             Boolean.toString(showGroupConsensus.isSelected()));
415     Cache.applicationProperties.setProperty("SHOW_GROUP_CONSERVATION",
416             Boolean.toString(showGroupConservation.isSelected()));
417     Cache.applicationProperties.setProperty("SHOW_CONSENSUS_HISTOGRAM",
418             Boolean.toString(showConsensHistogram.isSelected()));
419     Cache.applicationProperties.setProperty("SHOW_CONSENSUS_LOGO",
420             Boolean.toString(showConsensLogo.isSelected()));
421     Cache.applicationProperties.setProperty("ANTI_ALIAS",
422             Boolean.toString(smoothFont.isSelected()));
423     Cache.applicationProperties.setProperty("SHOW_NPFEATS_TOOLTIP",
424             Boolean.toString(showNpTooltip.isSelected()));
425     Cache.applicationProperties.setProperty("SHOW_DBREFS_TOOLTIP",
426             Boolean.toString(showDbRefTooltip.isSelected()));
427
428     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT",
429             Boolean.toString(wrap.isSelected()));
430
431     Cache.applicationProperties.setProperty("STARTUP_FILE",
432             startupFileTextfield.getText());
433     Cache.applicationProperties.setProperty("SHOW_STARTUP_FILE",
434             Boolean.toString(startupCheckbox.isSelected()));
435
436     Cache.applicationProperties.setProperty("SORT_ALIGNMENT", sortby
437             .getSelectedItem().toString());
438
439     // convert description of sort order to enum name for save
440     SequenceAnnotationOrder annSortOrder = SequenceAnnotationOrder
441             .forDescription(sortAnnBy.getSelectedItem().toString());
442     if (annSortOrder != null)
443     {
444       Cache.applicationProperties.setProperty(SORT_ANNOTATIONS,
445               annSortOrder.name());
446     }
447
448     final boolean showAutocalcFirst = sortAutocalc.getSelectedIndex() == 0;
449     Cache.applicationProperties.setProperty(SHOW_AUTOCALC_ABOVE,
450             Boolean.valueOf(showAutocalcFirst).toString());
451
452     /*
453      * Save Colours settings
454      */
455     Cache.applicationProperties.setProperty("DEFAULT_COLOUR", colour
456             .getSelectedItem().toString());
457     Cache.setColourProperty("ANNOTATIONCOLOUR_MIN",
458             minColour.getBackground());
459     Cache.setColourProperty("ANNOTATIONCOLOUR_MAX",
460             maxColour.getBackground());
461
462     /*
463      * Save Structure settings
464      */
465     Cache.applicationProperties.setProperty(ADD_TEMPFACT_ANN,
466             Boolean.toString(addTempFactor.isSelected()));
467     Cache.applicationProperties.setProperty(ADD_SS_ANN,
468             Boolean.toString(addSecondaryStructure.isSelected()));
469     Cache.applicationProperties.setProperty(USE_RNAVIEW,
470             Boolean.toString(useRnaView.isSelected()));
471     Cache.applicationProperties.setProperty(STRUCT_FROM_PDB,
472             Boolean.toString(structFromPdb.isSelected()));
473     Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY, structViewer
474             .getSelectedItem().toString());
475     Cache.setOrRemove(CHIMERA_PATH, chimeraPath.getText());
476
477     /*
478      * Save Output settings
479      */
480     if (epsRendering.getSelectedItem().equals("Prompt each time"))
481     {
482       Cache.applicationProperties.remove("EPS_RENDERING");
483     }
484     else
485     {
486       Cache.applicationProperties.setProperty("EPS_RENDERING", epsRendering
487               .getSelectedItem().toString());
488     }
489
490     /*
491      * Save Connections settings
492      */
493     Cache.setOrRemove("DEFAULT_BROWSER", defaultBrowser.getText());
494
495     jalview.util.BrowserLauncher.resetBrowser();
496
497     if (nameLinks.size() > 0)
498     {
499       StringBuffer links = new StringBuffer();
500       sequenceURLLinks = new Vector();
501       for (int i = 0; i < nameLinks.size(); i++)
502       {
503         sequenceURLLinks.addElement(nameLinks.elementAt(i) + "|"
504                 + urlLinks.elementAt(i));
505         links.append(sequenceURLLinks.elementAt(i).toString());
506         links.append("|");
507       }
508       // remove last "|"
509       links.setLength(links.length() - 1);
510       Cache.applicationProperties.setProperty("SEQUENCE_LINKS",
511               links.toString());
512     }
513     else
514     {
515       Cache.applicationProperties.remove("SEQUENCE_LINKS");
516     }
517
518     Cache.applicationProperties.setProperty("USE_PROXY",
519             Boolean.toString(useProxy.isSelected()));
520
521     Cache.setOrRemove("PROXY_SERVER", proxyServerTB.getText());
522
523     Cache.setOrRemove("PROXY_PORT", proxyPortTB.getText());
524
525     if (useProxy.isSelected())
526     {
527       System.setProperty("http.proxyHost", proxyServerTB.getText());
528       System.setProperty("http.proxyPort", proxyPortTB.getText());
529     }
530     else
531     {
532       System.setProperty("http.proxyHost", "");
533       System.setProperty("http.proxyPort", "");
534     }
535     Cache.setProperty("VERSION_CHECK",
536             Boolean.toString(versioncheck.isSelected()));
537     if (Cache.getProperty("USAGESTATS") != null || usagestats.isSelected())
538     {
539       // default is false - we only set this if the user has actively agreed
540       Cache.setProperty("USAGESTATS",
541               Boolean.toString(usagestats.isSelected()));
542     }
543     if (!questionnaire.isSelected())
544     {
545       Cache.setProperty("NOQUESTIONNAIRES", "true");
546     }
547     else
548     {
549       // special - made easy to edit a property file to disable questionnaires
550       // by just adding the given line
551       Cache.removeProperty("NOQUESTIONNAIRES");
552     }
553
554     /*
555      * Save Output settings
556      */
557     Cache.applicationProperties.setProperty("BLC_JVSUFFIX",
558             Boolean.toString(blcjv.isSelected()));
559     Cache.applicationProperties.setProperty("CLUSTAL_JVSUFFIX",
560             Boolean.toString(clustaljv.isSelected()));
561     Cache.applicationProperties.setProperty("FASTA_JVSUFFIX",
562             Boolean.toString(fastajv.isSelected()));
563     Cache.applicationProperties.setProperty("MSF_JVSUFFIX",
564             Boolean.toString(msfjv.isSelected()));
565     Cache.applicationProperties.setProperty("PFAM_JVSUFFIX",
566             Boolean.toString(pfamjv.isSelected()));
567     Cache.applicationProperties.setProperty("PILEUP_JVSUFFIX",
568             Boolean.toString(pileupjv.isSelected()));
569     Cache.applicationProperties.setProperty("PIR_JVSUFFIX",
570             Boolean.toString(pirjv.isSelected()));
571     Cache.applicationProperties.setProperty("PIR_MODELLER",
572             Boolean.toString(modellerOutput.isSelected()));
573     jalview.io.PIRFile.useModellerOutput = modellerOutput.isSelected();
574
575     Cache.applicationProperties.setProperty("FIGURE_AUTOIDWIDTH",
576             Boolean.toString(autoIdWidth.isSelected()));
577     userIdWidth_actionPerformed();
578     Cache.applicationProperties.setProperty("FIGURE_USERIDWIDTH",
579             userIdWidth.getText());
580
581     /*
582      * Save Editing settings
583      */
584     Cache.applicationProperties.setProperty("AUTO_CALC_CONSENSUS",
585             Boolean.toString(autoCalculateConsCheck.isSelected()));
586     Cache.applicationProperties.setProperty("SORT_BY_TREE",
587             Boolean.toString(sortByTree.isSelected()));
588     Cache.applicationProperties.setProperty("PAD_GAPS",
589             Boolean.toString(padGaps.isSelected()));
590
591     dasSource.saveProperties(Cache.applicationProperties);
592     wsPrefs.updateAndRefreshWsMenuConfig(false);
593     Cache.saveProperties();
594     Desktop.instance.doConfigureStructurePrefs();
595     try
596     {
597       frame.setClosed(true);
598     } catch (Exception ex)
599     {
600     }
601   }
602
603   /**
604    * Do any necessary validation before saving settings. Return focus to the
605    * first tab which fails validation.
606    * 
607    * @return
608    */
609   private boolean validateSettings()
610   {
611     if (!validateStructure())
612     {
613       structureTab.requestFocusInWindow();
614       return false;
615     }
616     return true;
617   }
618
619   @Override
620   protected boolean validateStructure()
621   {
622     return validateChimeraPath();
623
624   }
625   /**
626    * DOCUMENT ME!
627    */
628   public void startupFileTextfield_mouseClicked()
629   {
630     JalviewFileChooser chooser = new JalviewFileChooser(
631             jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
632             new String[]
633             { "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc", "jar" },
634             new String[]
635             { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview" },
636             jalview.bin.Cache.getProperty("DEFAULT_FILE_FORMAT"));
637     chooser.setFileView(new JalviewFileView());
638     chooser.setDialogTitle(MessageManager.getString("label.select_startup_file"));
639
640     int value = chooser.showOpenDialog(this);
641
642     if (value == JalviewFileChooser.APPROVE_OPTION)
643     {
644       jalview.bin.Cache.applicationProperties.setProperty(
645               "DEFAULT_FILE_FORMAT", chooser.getSelectedFormat());
646       startupFileTextfield.setText(chooser.getSelectedFile()
647               .getAbsolutePath());
648     }
649   }
650
651   /**
652    * DOCUMENT ME!
653    * 
654    * @param e
655    *          DOCUMENT ME!
656    */
657   public void cancel_actionPerformed(ActionEvent e)
658   {
659     try
660     {
661       wsPrefs.updateWsMenuConfig(true);
662       wsPrefs.refreshWs_actionPerformed(e);
663       frame.setClosed(true);
664     } catch (Exception ex)
665     {
666     }
667   }
668
669   /**
670    * DOCUMENT ME!
671    * 
672    * @param e
673    *          DOCUMENT ME!
674    */
675   public void annotations_actionPerformed(ActionEvent e)
676   {
677     conservation.setEnabled(annotations.isSelected());
678     quality.setEnabled(annotations.isSelected());
679     identity.setEnabled(annotations.isSelected());
680     showGroupConsensus.setEnabled(annotations.isSelected());
681     showGroupConservation.setEnabled(annotations.isSelected());
682     showConsensHistogram.setEnabled(annotations.isSelected()
683             && (identity.isSelected() || showGroupConsensus.isSelected()));
684     showConsensLogo.setEnabled(annotations.isSelected()
685             && (identity.isSelected() || showGroupConsensus.isSelected()));
686   }
687
688   public void newLink_actionPerformed(ActionEvent e)
689   {
690
691     GSequenceLink link = new GSequenceLink();
692     boolean valid = false;
693     while (!valid)
694     {
695       if (JOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
696               MessageManager.getString("label.new_sequence_url_link"),
697               JOptionPane.OK_CANCEL_OPTION, -1, null) == JOptionPane.OK_OPTION)
698       {
699         if (link.checkValid())
700         {
701           nameLinks.addElement(link.getName());
702           urlLinks.addElement(link.getURL());
703           updateLinkData();
704           valid = true;
705         }
706       }
707       else
708       {
709         break;
710       }
711     }
712   }
713
714   public void editLink_actionPerformed(ActionEvent e)
715   {
716     GSequenceLink link = new GSequenceLink();
717
718     int index = linkNameList.getSelectedIndex();
719     if (index == -1)
720     {
721       JOptionPane.showInternalMessageDialog(Desktop.desktop,
722               MessageManager.getString("label.no_link_selected"),
723               MessageManager.getString("label.no_link_selected"),
724               JOptionPane.WARNING_MESSAGE);
725       return;
726     }
727
728     link.setName(nameLinks.elementAt(index).toString());
729     link.setURL(urlLinks.elementAt(index).toString());
730
731     boolean valid = false;
732     while (!valid)
733     {
734
735       if (JOptionPane.showInternalConfirmDialog(Desktop.desktop, link,
736               MessageManager.getString("label.new_sequence_url_link"),
737               JOptionPane.OK_CANCEL_OPTION, -1, null) == JOptionPane.OK_OPTION)
738       {
739         if (link.checkValid())
740         {
741           nameLinks.setElementAt(link.getName(), index);
742           urlLinks.setElementAt(link.getURL(), index);
743           updateLinkData();
744           valid = true;
745         }
746       }
747
748       else
749       {
750         break;
751       }
752     }
753   }
754
755   public void deleteLink_actionPerformed(ActionEvent e)
756   {
757     int index = linkNameList.getSelectedIndex();
758     if (index == -1)
759     {
760       JOptionPane.showInternalMessageDialog(Desktop.desktop,
761               MessageManager.getString("label.no_link_selected"),
762               MessageManager.getString("label.no_link_selected"),
763               JOptionPane.WARNING_MESSAGE);
764       return;
765     }
766     nameLinks.removeElementAt(index);
767     urlLinks.removeElementAt(index);
768     updateLinkData();
769   }
770
771   void updateLinkData()
772   {
773     linkNameList.setListData(nameLinks);
774     linkURLList.setListData(urlLinks);
775   }
776
777   public void defaultBrowser_mouseClicked(MouseEvent e)
778   {
779     JFileChooser chooser = new JFileChooser(".");
780     chooser.setDialogTitle(MessageManager.getString("label.select_default_browser"));
781
782     int value = chooser.showOpenDialog(this);
783
784     if (value == JFileChooser.APPROVE_OPTION)
785     {
786       defaultBrowser.setText(chooser.getSelectedFile().getAbsolutePath());
787     }
788
789   }
790
791   /*
792    * (non-Javadoc)
793    * 
794    * @see
795    * jalview.jbgui.GPreferences#showunconserved_actionPerformed(java.awt.event
796    * .ActionEvent)
797    */
798   protected void showunconserved_actionPerformed(ActionEvent e)
799   {
800     // TODO Auto-generated method stub
801     super.showunconserved_actionPerformed(e);
802   }
803
804   public static Collection getGroupURLLinks()
805   {
806     return groupURLLinks;
807   }
808
809   @Override
810   public void minColour_actionPerformed(JPanel panel)
811   {
812     Color col = JColorChooser.showDialog(this,
813             MessageManager.getString("label.select_colour_minimum_value"), minColour.getBackground());
814     if (col != null)
815     {
816       panel.setBackground(col);
817     }
818     panel.repaint();
819   }
820
821   @Override
822   public void maxColour_actionPerformed(JPanel panel)
823   {
824     Color col = JColorChooser.showDialog(this,
825             MessageManager.getString("label.select_colour_maximum_value"), maxColour.getBackground());
826     if (col != null)
827     {
828       panel.setBackground(col);
829     }
830     panel.repaint();
831   }
832
833   @Override
834   protected void userIdWidth_actionPerformed()
835   {
836     try
837     {
838       String val = userIdWidth.getText().trim();
839       if (val.length() > 0)
840       {
841         Integer iw = Integer.parseInt(val);
842         if (iw.intValue() < 12)
843         {
844           throw new NumberFormatException();
845         }
846         userIdWidth.setText(iw.toString());
847       }
848     } catch (NumberFormatException x)
849     {
850       JOptionPane
851               .showInternalMessageDialog(
852                       Desktop.desktop,
853                       MessageManager.getString("warn.user_defined_width_requirements"),
854                       MessageManager.getString("label.invalid_id_column_width"),
855                       JOptionPane.WARNING_MESSAGE);
856       userIdWidth.setText("");
857     }
858   }
859
860   @Override
861   protected void autoIdWidth_actionPerformed()
862   {
863     userIdWidth.setEnabled(!autoIdWidth.isSelected());
864     userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
865   }
866
867   /**
868    * Returns true if chimera path is to a valid executable, else show an error
869    * dialog.
870    */
871   private boolean validateChimeraPath()
872   {
873     if (chimeraPath.getText().trim().length() > 0)
874     {
875       File f = new File(chimeraPath.getText());
876       if (!f.canExecute())
877       {
878         JOptionPane.showInternalMessageDialog(Desktop.desktop,
879                 MessageManager.getString("label.invalid_chimera_path"),
880                 MessageManager.getString("label.invalid_name"),
881                 JOptionPane.ERROR_MESSAGE);
882         return false;
883       }
884     }
885     return true;
886   }
887
888   /**
889    * If Chimera is selected, check it can be found on default or user-specified
890    * path, if not show a warning/help dialog.
891    */
892   @Override
893   protected void structureViewer_actionPerformed(String selectedItem)
894   {
895     if (!selectedItem.equals(Viewer.CHIMERA.name()))
896     {
897       return;
898     }
899     boolean found = false;
900
901     /*
902      * Try user-specified and standard paths for Chimera executable.
903      */
904     List<String> paths = StructureManager.getChimeraPaths();
905     paths.add(0, chimeraPath.getText());
906     for (String path : paths)
907     {
908       if (new File(path.trim()).canExecute())
909       {
910         found = true;
911         break;
912       }
913     }
914     if (!found)
915     {
916       String[] options =
917       { "OK", "Help" };
918       int showHelp = JOptionPane.showInternalOptionDialog(
919               Desktop.desktop,
920               JvSwingUtils.wrapTooltip(true,
921                       MessageManager.getString("label.chimera_missing")),
922               "", JOptionPane.YES_NO_OPTION,
923               JOptionPane.WARNING_MESSAGE, null, options, options[0]);
924       if (showHelp == JOptionPane.NO_OPTION)
925       {
926         try
927         {
928           Help.showHelpWindow(HelpId.StructureViewer);
929         } catch (HelpSetException e)
930         {
931           e.printStackTrace();
932         }
933       }
934     }
935   }
936
937 }