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